<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.geekhold.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;DkQHQ3w_fip7ImA9Wx5RGUQ.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401</id><updated>2010-08-28T04:18:52.246-07:00</updated><title>Coding Relic</title><subtitle type="html">Random musings on software in an embedded world.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://codingrelic.geekhold.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>138</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.geekhold.com/CodingRelic" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="codingrelic" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0MCQX85fCp7ImA9Wx5RGE8.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-8163416332846676343</id><published>2010-08-26T06:31:00.000-07:00</published><updated>2010-08-26T06:31:00.124-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-26T06:31:00.124-07:00</app:edited><title>Code Test Haiku</title><content type="html">&lt;pre style="font-style: italic;"&gt;Function works first time
Briefly feel elation...
Did it really work?&lt;/pre&gt;

&lt;br/&gt;

&lt;p style="width: 50%;"&gt;Having code work the first time is &lt;b&gt;more&lt;/b&gt; annoying than having it fail.&lt;/p&gt;

&lt;p style="width: 50%;"&gt;If it doesn't work I go poke around to fix the failing tests, and when it finally passes I feel confident that it really works.&lt;/p&gt;

&lt;p style="width: 50%;"&gt;When code works the first time I still go poke around in the unit tests, only this time I have no idea what I'm looking for. Did it really get tested? Does it really test what I think its testing? Surely there is &lt;i&gt;something&lt;/i&gt; wrong &lt;i&gt;somewhere.&lt;/i&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-8163416332846676343?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/Ngd2C144XLI" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=8163416332846676343" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8163416332846676343?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8163416332846676343?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/code-test-haiku.html" title="Code Test Haiku" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DEMCQXw5eip7ImA9Wx5REU4.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-3118550972016133270</id><published>2010-08-18T06:01:00.000-07:00</published><updated>2010-08-18T06:01:00.222-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-18T06:01:00.222-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mobile" /><category scheme="http://www.blogger.com/atom/ns#" term="CPU" /><title>x86 vs ARM Mobile CPUs</title><content type="html">&lt;p&gt;The &lt;a href="http://www.arm.com/"&gt;ARM architecture&lt;/a&gt; dominates mobile computing. It is used in all popular mobile phones and in a huge percentage of battery powered devices generally. This is due partly to its good overall performance, but especially due to its performance per watt expended. ARM chips consume very little power when compared to x86, and ARM's power consumption still excels even when compared to other RISC chips. At one time even &lt;a href="http://www.intel.com/design/intelxscale/"&gt;Intel manufactured ARM&lt;/a&gt; chips, the result of its purchase of the DEC semiconductor business and its excellent StrongARM design. In 2006 Intel sold its ARM products to &lt;a href="http://www.marvell.com/"&gt;Marvell Semiconductor&lt;/a&gt;, committing to x86 for every segment of the computing market.&lt;/p&gt;

&lt;p&gt;Its easy to assume that this state of affairs will continue, and that Intel will never successfully compete in the mobile market. I suspect that is too simplistic an assumption. There are two main sources of power dissipation in modern microprocessors: the power consumed by transistors actively switching, and the power lost to leakage current.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" width="310" height="148"  src="http://3.bp.blogspot.com/_WibILqsOlLg/TGgPyZ1FW_I/AAAAAAAAAvw/j8sRJuM_F8A/s320/transistor.png" style="border: none; margin: 1px 1em 1px 0;" alt="active current, leakage current into substrate" title="Sometimes, its amazing this stuff works at all" /&gt;&lt;/center&gt;


&lt;span style="font-size: 120%; font-weight: bold;"&gt;x86 vs ARM: Active Power&lt;/span&gt;
&lt;p&gt;It requires power to switch a CMOS transistor 0-&amp;gt;1 or 1-&amp;gt;0, so one way to reduce power consumption is to have fewer transistors and to switch them at a lower frequency. x86 is at a disadvantage here compared to ARM, which Intel and AMD's design teams have to cover with extra work and cleverness. The vagaries of the x86 instruction set burdens it with hardware logic which ARM does not require.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Since the &lt;a href="http://en.wikipedia.org/wiki/Pentium_Pro"&gt;Pentium Pro&lt;/a&gt;, Intel has decoded complex x86 instructions down to simpler micro-ops for execution. AMD uses a similar technique. This instruction decode logic is active whenever new opcodes are fetched from RAM. ARM has no need for this logic, as even its alternate Thumb encoding is a relatively straightforward mapping to regular ARM instructions.&lt;/li&gt;
 &lt;li&gt;x86_32 exposes only a few registers to the compiler. To achieve good performance, x86 CPUs implement a much larger number of hardware registers which are &lt;a href="http://en.wikipedia.org/wiki/Register_renaming"&gt;dynamically renamed&lt;/a&gt; as needed. ARM does not require such extensive register renaming logic.&lt;/li&gt;
 &lt;li&gt;Every ARM instruction is conditional, and simple if-then-else constructs can be handled without branches. x86 relies much more heavily on branches, but frequent branches can &lt;a href="http://en.wikipedia.org/wiki/Branch_predictor"&gt;stall the pipeline&lt;/a&gt; on a processor. Good performance in x86 requires extensive branch prediction hardware, where ARM is served with a far simpler implementation.&lt;/li&gt;
&lt;/ul&gt;


&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;x86 vs ARM: Leakage Current&lt;/span&gt;
&lt;p&gt;&lt;img border="0" width="347" height="239" align="right" src="http://4.bp.blogspot.com/_WibILqsOlLg/TGgP8s1igDI/AAAAAAAAAv0/18O_vX5EmB8/s640/Nehalem.jpg" style="border: none; margin: 2px;" alt="Intel Nehalem processor die" /&gt;Leakage current became a significant contributor to power consumption in 2003 with the move from 0.18 to 0.13 micron feature sizes, and has become more significant in each subsequent generation. The industry is now moving into 0.032 micron technologies.&lt;/p&gt;
&lt;p&gt;A capacitor is formed when two conductive materials are separated by an insulator, called the dielectric. The capacitance is determined by the quality of the insulating material, quantified by the dielectric constant &lt;i&gt;k.&lt;/i&gt; Higher &lt;i&gt;k&lt;/i&gt; means more capacitance. &amp;quot;Leakage&amp;quot; is current which is able to flow out of the ASIC transistors and into the silicon substrate. To reduce the current leaking out, one needs to make a better dielectric between the transistor and the bulk of the silicon. This is generically referred to as &lt;i&gt;high-k silicon technology.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;As we're now talking about silicon fabrication techniques, we have to start talking about Intel specifically rather than the x86 architecture in general. Intel began using a high-k dielectric in production in 2007, during the 45 nm generation of parts. The rest of the industry has been experimenting with such materials, but is only now rolling it into the 32 nm generation. Intel hasn't stopped working on the technique, their 32 nm process benefits from the last several years of experience.&lt;/p&gt;


&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;x86 vs ARM: Predicting The Future&lt;/span&gt;
&lt;p&gt;Leakage current becomes more significant with each generation of process technology. The power consumed by actively switching transistors has been radically reduced over the last few years, leaving leakage as the more significant source of current consumption. It is difficult to estimate how serious the effect is, but &lt;a href="http://asic-soc.blogspot.com/2008/03/leakage-power-trends.html"&gt;this article&lt;/a&gt; from March 2008 shows leakage current starting out relatively insignificant in 180 nm silicon but growing to nearly 40% of total power consumption in a 50 nm process.&lt;/p&gt;
&lt;p&gt;So far as I can see, this trend will continue. Leakage current will soon become the dominant factor in CPU power consumption. In fact, in 32 nm processes it might already &lt;u&gt;be&lt;/u&gt; the primary factor. This is where the game changes: the advantage for total power consumption shifts away from the efficiency of the CPU architecture and design, and to the process technology of the fab. Presumably, this trend informed Intel's decision to sell their ARM assets to Marvell: there is little reason to enrich a competitor if the advantages of doing so will diminish over time.&lt;/p&gt;

&lt;br/&gt;
&lt;p&gt;There is still room for clever design, of course. To reduce active power consumption, processor designs have long stopped the clock to unused portion of the CPU. To reduce leakage current, AMD is taking the next step to actually remove the power supply to those portions of the CPU. For ARM, that design choice makes even more sense. ARM has no control over the fab, their designs have to minimize assumptions about the underlying silicon technology.&lt;/p&gt;

&lt;p&gt;Right now ARM reigns supreme in the mobile space, but the strengths which gave it an advantage over x86 are rapidly becoming less compelling. Having to compete directly on silicon process sophistication moves the game onto Intel's turf, which Intel is happy to capitalize on with its &lt;a href="http://www.infoworld.com/d/hardware/details-about-intels-upcoming-medfield-smartphone-chip-emerge-772"&gt;Medfield&lt;/a&gt; platform. Its a great time to be in the mobile space.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-3118550972016133270?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/MjllngyHXOE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=3118550972016133270" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3118550972016133270?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3118550972016133270?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/x86-vs-arm-mobile-cpus.html" title="x86 vs ARM Mobile CPUs" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_WibILqsOlLg/TGgPyZ1FW_I/AAAAAAAAAvw/j8sRJuM_F8A/s72-c/transistor.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CUECQX8-fyp7ImA9Wx5SGUs.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-4719711784100504266</id><published>2010-08-16T06:01:00.000-07:00</published><updated>2010-08-16T06:01:00.157-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-16T06:01:00.157-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>A Scene from the Near Future</title><content type="html">&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;FURNITURE LICENSE AGREEMENT&lt;/span&gt;
&lt;p&gt;THIS FURNITURE IS LICENSED, NOT SOLD. By using the furniture you signify that you have read and agree to all the terms of this license  agreement.&lt;/p&gt;

&lt;p&gt;THIS IS A LEGAL AND BINDING AGREEMENT BETWEEN YOU, HEREINAFTER ALSO REFERRED TO AS "USER", AND THE FURNITURE RETAILER, HEREINAFTER ALSO REFERRED TO AS THE "STORE". BY SITTING ON, LYING ON, OR OTHERWISE MAKING USE OF THE FURNITURE, HERINAFTER REFERRED AS THE "PRODUCT", (OR AUTHORIZING ANY OTHER PERSON TO DO SO), YOU INDICATE YOUR COMPLETE AND UNCONDITIONAL ACCEPTANCE OF ALL THE TERMS AND CONDITIONS OF THIS LICENSE AGREEMENT. THIS LICENSE AGREEMENT CONSTITUTES THE COMPLETE  AGREEMENT BETWEEN YOU AND THE STORE. IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE AGREEMENT, YOU MUST DESTROY THE ITEM OF FURNITURE (WITH ALL ACCOMPANYING MATERIALS).&lt;/p&gt;

&lt;p&gt;IMPORTANT: CAREFULLY READ THIS LICENSE BEFORE USING THIS PRODUCT. SITTING ON, LYING ON, OR OTHERWISE USING THIS PRODUCT INDICATES YOUR ACKNOWLEDGMENT THAT YOU HAVE READ THIS LICENSE AND AGREE TO BE BOUND BY AND COMPLY WITH ITS TERMS. IF YOU DO NOT AGREE, RETURN THE COMPLETE  PRODUCT TO THE STORE WITHIN 30 DAYS OF THE DATE YOU PURCHASED IT FOR A FULL REFUND. THIS LICENSE AGREEMENT IS YOUR PROOF OF LICENSE. PLEASE TREAT IT AS VALUABLE PROPERTY.&lt;/p&gt;

&lt;br/&gt;
&lt;p&gt;A. LICENSE:&lt;/p&gt;
&lt;p&gt;The STORE provides the user with the furniture and separate cushions  (together called the "PRODUCT") and we grant the user a license to use the PRODUCT in accordance with the terms of this License. Any supplemental materials provided to the user as part of support services provided by the STORE for the PRODUCT shall be considered part of the PRODUCT and subject to the terms and conditions of this License. The copyright and all other rights to the PRODUCT shall remain with the STORE or its licensors.&lt;/p&gt;

&lt;br/&gt;
&lt;p&gt;B. THE USER MAY:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;transfer the PRODUCT to the USER's primary residence, and place it within a single room therein.&lt;/li&gt;
&lt;li&gt;move the PROUCT to a different room within the same structure. The user must acquire and dedicate a supplementary license for each separate room in which the PRODUCT may be used. A license for the PRODUCT may not be shared or used concurrently in different rooms.&lt;/li&gt;&lt;/ol&gt;

&lt;br/&gt;
&lt;p&gt;&lt;b&gt;C. THE USER MAY NOT:&lt;/b&gt;&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;&lt;b&gt;use the PRODUCT or make copies of it except as permitted in this License.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;use the PRODUCT within a structure which is not the USER's primary residence. A separate commercial license applies to these cases.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;use the PRODUCT outside a structure, i.e. outdoors. A separate public performance license applies to these cases.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;reupholster, except within the initial TEN (10) days of a license term. Outside of the initial ten days, reupholstery will require an early renewal.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;deconstruct, reverse engineer, or disassemble the PRODUCT except to the extent 
the foregoing restriction is expressly prohibited by applicable law. The PRODUCT may not be used as a template from which to build additional furniture.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;rent, lease, assign, sell, or transfer the PRODUCT.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;modify the PRODUCT or merge all or any part of the PRODUCT with another item of furniture.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;separate the component parts of the PRODUCT for use in more than one room.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;br/&gt;
&lt;p&gt;D. TERM:&lt;/p&gt;
&lt;p&gt;This license shall remain in effect only for so long as the user is in compliance with the terms and conditions of this agreement. This license will terminate if the user fails to comply with any of its terms or conditions. The user agrees, upon termination, to destroy the PRODUCT.&lt;/p&gt;

&lt;br/&gt;
&lt;p&gt;E. U.S. GOVERNMENT RIGHTS:&lt;/p&gt;
&lt;p&gt;With respect to any acquisition of the PRODUCT by or for any unit or agency of the United States Government (the "Government"), the Product shall be classiﬁed as "commercial furniture", as that term is deﬁned in the applicable provisions of the Federal acquisition Regulation (the "FAR") and supplements thereto, including the Department of Defense (DoD) FAR Supplement (the "DFARS"). The Product was developed entirely at private expense, and no part of the Product was first produced in the performance of a Government contract. If the Product is supplied for use by DoD, the Product is delivered subject to the terms of this Agreement and either (i) in accordance with DFARS 3.1415-9 (a) and 2.71(a), or (ii) with restricted rights in accordance with DFARS 012-345-6789 (c)(1)(ii)(JUN 1970), as applicable. If the Product is supplied for use by a Federal agency other than DoD, the Product is commercial furniture delivered subject to the terms of this Agreement and (i) FAR 6.66(a); (ii) FAR 57.57-57; or (iii) FAR 12.345-67(ALT VIII), as applicable.&lt;/p&gt;

&lt;br/&gt;
&lt;p&gt;F. GENERAL:&lt;/p&gt;
&lt;p&gt;This License is the entire agreement between the STORE and the USER, superseding any other agreement or discussions, oral or written, and may not be changed except by a signed agreement. This License shall be governed by and construed in accordance with the laws of the state of Delaware, USA, excluding that body of law applicable to choice of law and excluding the United Nations Convention on Contracts for the International Sale of Goods and any legislation implementing such Convention, if otherwise applicable. If any provision of this License is declared by a Court of competent jurisdiction to be invalid, illegal, or unenforceable, such a provision shall be severed from the License and the other provisions shall remain in full force and effect.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-4719711784100504266?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/ZXH0kx0Ahr0" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=4719711784100504266" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4719711784100504266?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4719711784100504266?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/scene-from-near-future.html" title="A Scene from the Near Future" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkcCQXo4eSp7ImA9Wx5SF00.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-2492378086077980536</id><published>2010-08-13T07:01:00.000-07:00</published><updated>2010-08-13T07:01:00.431-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-13T07:01:00.431-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="social" /><title>Bury Brigades as the Future of Media?</title><content type="html">&lt;p&gt;&lt;a href="http://www.flickr.com/photos/beger/2336486182/in/photostream/"&gt;&lt;img border="0" width="108" height="240" align="right" src="http://3.bp.blogspot.com/_WibILqsOlLg/TGVNibSw2VI/AAAAAAAAAvs/Iqm6vReOmiY/s1600/broadcasttower.jpg" style="border: none; margin: 2px;" alt="Broadcast transmission tower" title="Image by Steve Beger Photography, licensed under creative commons" /&gt;&lt;/a&gt;I'm currently reading &lt;i&gt;Cognitive Surplus&lt;/i&gt;, by &lt;a href="http://www.shirky.com/"&gt;Clay Shirky&lt;/a&gt;. It builds upon his earlier &lt;a href="http://www.herecomeseverybody.org/"&gt;&lt;i&gt;Here Comes Everybody&lt;/i&gt;&lt;/a&gt;, detailing how the Internet fundamentally changes the media landscape to an extent not seen since Gutenberg. Before the Internet, when the cost of distribution was non-trivial, you ended up with publishers, producers, TV networks, and a whole host of powerful institutions built upon managing the production. When the cost of distributing media drops to essentially nothing, when everybody who wants to can become a publisher without having to ask permission or convince anybody of the value of their work, it completely disrupts the models which evolved in the prior era. A &lt;u&gt;lot&lt;/u&gt; more material will be produced. Much of it will be trash, as we've moved the filtering function away from an editor before publication and onto the audience after publication.&lt;/p&gt;

&lt;p&gt;Something will evolve to fill an institutional role in the New Media. The current period of creative chaos is unlikely to continue forever. A portion of the population is willing to wade through the trash in order to surface the truly great, but only a small portion. The rest of us need some filtering, or &lt;a href="http://scobleizer.com/2010/03/27/the-seven-needs-of-real-time-curators/"&gt;curation&lt;/a&gt; as the cool kids seem to call it.&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;Warning: Speculation Ahead&lt;/span&gt;
&lt;p&gt;Are &lt;a href="http://blogs.alternet.org/oleoleolson/2010/08/05/massive-censorship-of-digg-uncovered/"&gt;Digg Bury Brigades&lt;/a&gt; early precursors to a form of New Media institution? Organized groups, loosely connected by shared interests but not centrally funded or managed, they influence the spread of material online and therefore gain some control over media distribution. Bury Brigades are negative filters, suppressing material they don't agree with rather than surfacing material they want to promote. There will be equally a role for positive filters, entities which seek out and promote material. Motivation for groups to organize as positive filters is less clear, as simple altruism and a desire for recognition only go so far.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-2492378086077980536?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/HZLa7Uw6PYE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=2492378086077980536" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2492378086077980536?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2492378086077980536?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/bury-brigades-as-future-of-media.html" title="Bury Brigades as the Future of Media?" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_WibILqsOlLg/TGVNibSw2VI/AAAAAAAAAvs/Iqm6vReOmiY/s72-c/broadcasttower.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0UCQXw7fCp7ImA9Wx5SFEk.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5848480384073130853</id><published>2010-08-10T06:01:00.000-07:00</published><updated>2010-08-10T06:01:00.204-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-10T06:01:00.204-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mobile" /><title>A Barrrgain Indeed</title><content type="html">&lt;p&gt;&lt;img border="0" width="403" height="241" align="right" src="http://3.bp.blogspot.com/_WibILqsOlLg/TGCfnHTkUJI/AAAAAAAAAvI/c4M387Hi8MY/s640/barrr.jpg" style="border: none; margin: 2px;" alt="Barrr screenshot" title="The pirates look young. I doubt they are checking IDs." /&gt;If you have an Android phone, Barrr is a wonderful game by &lt;a href="http://www.firedroid.net/"&gt;FireDroid&lt;/a&gt;. It is available in the Android Market or direct from their site via a QR barcode. It was developed by two Dutch students as part of their degree program in Multimedia: &lt;a href="http://nl.linkedin.com/in/kouwenberg"&gt;Mariecke Kouwenberg&lt;/a&gt; and &lt;a href="http://nl.linkedin.com/in/rvdveen"&gt;Roy van der Veen.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Barrr is a lighthearted simulation of a pirate bar complete with tattoo station, video games, karaoke, and a dart board. Each scenario takes a couple minutes to complete, making it a great diversion for short interludes.&lt;/p&gt;

&lt;p&gt;Price: free.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5848480384073130853?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/IkPkyFxvfsE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=5848480384073130853" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5848480384073130853?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5848480384073130853?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/barrrgain-indeed.html" title="A Barrrgain Indeed" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_WibILqsOlLg/TGCfnHTkUJI/AAAAAAAAAvI/c4M387Hi8MY/s72-c/barrr.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEEBQHY_fyp7ImA9Wx5SE0s.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-3032989872772340446</id><published>2010-08-09T07:01:00.000-07:00</published><updated>2010-08-09T07:04:11.847-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-09T07:04:11.847-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Mispsleled Words in Code</title><content type="html">&lt;p&gt;I ran into an interesting variation on the brain being able to &lt;a href="http://simplebits.com/notebook/2004/01/16/mipellssed-wdors/"&gt;recnogzie mispsleled wrods&lt;/a&gt; so long as the first and last letters are correct.&lt;/p&gt;

&lt;pre style="font-family: Courier New, monospace; font-size: small; line-height: 1.2em; margin-left: 4em;"&gt;
char *filename = "XXXXXX"; 
mkstemp(filename); 
&lt;/pre&gt;

&lt;p&gt;One of the resulting runs produced:&lt;/p&gt;
&lt;pre style="font-family: Courier New, monospace; font-size: small; line-height: 1.2em; margin-left: 4em;"&gt;
-rwx------ 2 dgentry eng 4096 Jul 8 10:41 ufseuL
&lt;/pre&gt;

&lt;p&gt;Why yes, it was useful. Thank you for your efforts, computer.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-3032989872772340446?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/Z9xTM_yjGBE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=3032989872772340446" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3032989872772340446?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3032989872772340446?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/mispsleled-words-in-code.html" title="Mispsleled Words in Code" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DE8CQXo-eSp7ImA9Wx5TGU8.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-4586548453049839317</id><published>2010-08-04T06:01:00.000-07:00</published><updated>2010-08-04T06:01:00.451-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-04T06:01:00.451-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="architecture" /><title>node.js from 30,000 feet</title><content type="html">&lt;p&gt;I attended a tech talk last week on &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt; by &lt;a href="http://tinyclouds.org/"&gt;Ryah Dahl&lt;/a&gt;. The video of the talk is up on YouTube.&lt;/p&gt;

&lt;div style="margin: 2em 0 1em 0;"&gt;&lt;object width="640" height="505"&gt;&lt;param name="movie" value="http://www.youtube-nocookie.com/v/F6k8lTrAE2g&amp;amp;hl=en_US&amp;amp;fs=1?rel=0"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube-nocookie.com/v/F6k8lTrAE2g&amp;amp;hl=en_US&amp;amp;fs=1?rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;

&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;Node.js Overall Structure&lt;/span&gt;
&lt;p&gt;&lt;img border="0" width="256" height="206" align="right" src="http://2.bp.blogspot.com/_WibILqsOlLg/TFlc-83p25I/AAAAAAAAAvE/8ohNw2L6kOc/s320/nodejsarch.png" style="border: none; margin: 1px 1em 1px 0;" alt="V8+libev+libeio+libcares at the bottom, node bindings in the middle, top layer node.js standard library in JavaScript" title="Adapted from one of Ryah Dahls slides" /&gt;The JavaScript implementation in node.js is &lt;a href="http://code.google.com/p/v8/"&gt;Google's V8&lt;/a&gt;. As &lt;a href="http://codingrelic.geekhold.com/2010/07/virtual-instruction-sets-opcode.html#v8"&gt;mentioned&lt;/a&gt; in an earlier article, V8 compiles the source JavaScript directly to machine code the first time it is executed. There is no intermediate bytecode format and no JS interpreter. In addition to V8, node.js relies on &lt;a href="http://software.schmorp.de/pkg/libev"&gt;libev&lt;/a&gt; for its event loop, &lt;a href="http://lists.schmorp.de/pipermail/libev/2008q2/000293.html"&gt;libeio&lt;/a&gt; for asynchronous I/O, and &lt;a href="http://c-ares.haxx.se/"&gt;c-ares&lt;/a&gt; for asynchronous DNS support. Like everything else in the known universe, it relies on &lt;a href="http://openssl.org"&gt;OpenSSL&lt;/a&gt; for cryptography and SSL/TLS support.&lt;/p&gt;

&lt;p&gt;A standard library in JavaScript is supplied. This provides access to the underlying C++ implementation, and also has helpful bits like a URL parser and a &lt;a href="http://en.wikipedia.org/wiki/Read-eval-print_loop"&gt;REPL&lt;/a&gt; shell for easy experimentation. One thing it does &lt;i&gt;not&lt;/i&gt; provide is the &lt;a href="http://en.wikipedia.org/wiki/Document_Object_Model"&gt;DOM&lt;/a&gt;. Node.js is not a browser, there is no HTML document to interact with.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;Node.js Implementation&lt;/span&gt;
&lt;p&gt;Entry points to the C++ code appear as a JavaScript variable named &lt;i&gt;process.&lt;/i&gt; For example, here is an excerpt from dns.js:&lt;/p&gt;


&lt;pre style="margin: 3em 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;var dns = process.binding('cares');&lt;/pre&gt;

&lt;p&gt;'cares' refers to the &lt;a href="http://c-ares.haxx.se/"&gt;c-ares&lt;/a&gt; DNS support library. The dns variable allows JavaScript code to make calls to c-areas.&lt;/p&gt;


&lt;pre style="margin: 3em 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;// Easy DNS A/AAAA look up
exports.lookup = function (domain, callback) {&lt;/pre&gt;

&lt;p&gt;Notice the signature of the function: input arguments and a callback when finished. There are never blocking operations in node, everything which might not complete immediately is a callback.&lt;/p&gt;


&lt;pre style="margin: 3em 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;  var addressType = dns.isIP(domain);
  if (addressType) {
    process.nextTick(function () {
      callback(null, domain, addressType);
    });&lt;/pre&gt;

&lt;p&gt;dns.isIP() calls into C++ code, which makes a series of inet_pton(AF_INET*) calls to figure out if the argument is a valid numeric IP address. I've omitted the C++ code here, we dive into a more interesting example below.&lt;/p&gt;


&lt;pre style="margin: 3em 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;  } else {
    if (/\w\.local\.?$/.test(domain) ) {
      // ANNOYING: In the case of mDNS domains use NSS in the thread pool.
      // I wish c-ares had better support.
      process.binding('net').getaddrinfo(domain, 4, function (err, domains4) {
        callback(err, domains4[0], 4);
      });&lt;/pre&gt;

&lt;p&gt;Node.js has two ways to implement support routines in C++. If the C++ code is structured to be asynchronous with a callback, it can be launched from the main thread using libev. Node.js makes heavy use of async I/O for this reason. Blocking C++ calls are handled by a pool of worker threads, which send an event to the main when their operation completes. In this code snippet the 'local' domain is handled by the thread pool as a special case, because c-ares doesn't handle mDNS.&lt;/p&gt;

&lt;p&gt;We'll come back to the thread pool code path later, after examining the common case.&lt;/p&gt;

&lt;pre style="margin: 3em 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;    } else {
      channel.getHostByName(domain, dns.AF_INET, function (err, domains4) {
        if (domains4 &amp;amp;&amp;amp; domains4.length) {
          callback(null, domains4[0], 4);
        } else {
          channel.getHostByName(domain, dns.AF_INET6, function (err, domains6) {
            if (domains6 &amp;amp;&amp;amp; domains6.length) {
              callback(null, domains6[0], 6);
            } else {
              callback(err, []);
            }
          });
        }
      });
      ... etc ...
&lt;/pre&gt;

&lt;p&gt;&amp;quot;channel&amp;quot; is a JavaScript variable which links to a context in the c-ares library. The JS code to create channel is omitted for brevity. Now we'll peel back one layer to look at the C++ implementation.&lt;/p&gt;


&lt;pre style="margin: 3em 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;Handle&lt;Value&gt; Channel::GetHostByName(const Arguments&amp;amp; args) {
  HandleScope scope;
  Channel *c = ObjectWrap::Unwrap&lt;Channel&gt;(args.Holder());
  assert(c);

  if (!args[0]-&amp;gt;IsString()) {
    return ThrowException(Exception::Error(
          String::New("First argument must be a name")));
  }

  if (!args[1]-&amp;gt;IsInt32()) {
    return ThrowException(Exception::Error(
          String::New("Second argument must be a family")));
  }

  if (!args[2]-&amp;gt;IsFunction()) {
    return ThrowException(Exception::Error(
          String::New("Third argument must be a callback")));
  }

  int family = args[1]-&amp;gt;Int32Value();
  if (family != AF_INET6 &amp;amp;&amp;amp; family != AF_INET) {
    return ThrowException(Exception::Error(
          String::New("Unsupported address family")));
  }&lt;/pre&gt;

&lt;p&gt;Argument unwrapping and validity checks when traversing the interface from one programming language are always tedious. You can never predict when someone will copy the channel.getHostByName invocation out of the standard library and mess with it, and you'd like the framework to do something sane no matter what they do.&lt;/p&gt;


&lt;pre style="margin: 3em 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;  String::Utf8Value name(args[0]-&gt;ToString());

  ares_gethostbyname(c-&amp;gt;channel, *name, family, HostByNameCb, cb_persist(args[2]));

  return Undefined();
}&lt;/pre&gt;

&lt;p&gt;Thats it. ares_gethostbyname() is in the C-ARES library, which we won't delve into here. HostByNameCb is the C++ callback function when resolution is done. HostByNameCb injects an event to the JavaScript code, to call the callback function passed in to the original call.&lt;/p&gt;

&lt;p&gt;The JavaScript has an alternate code path for mDNS requests, using the getaddrinfo() method on process.binding('net'). Most of that code path consists of the same sort of argument unwrapping and checking as GetHostByName, which we will omit. The mDNS code path uses a blocking DNS request, serviced by the thread pool. The code to send work to the pool and arrange a callback later is pleasingly simple:&lt;/p&gt;

&lt;pre style="margin: 0 1em 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;  eio_custom(Resolve, EIO_PRI_DEFAULT, AfterResolve, rreq);&lt;/pre&gt;

&lt;p&gt;Resolve is the function the worker thread is supposed to call. AfterResolve is the callback function in the main loop which the worker thread should trigger when done.&lt;/p&gt;

&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;Final Thoughts&lt;/span&gt;
&lt;p&gt;Node.js makes it easy to develop high performance applications by not offering APIs which would drastically lower performance. Everything is a callback, there are no blocking calls in the API (except for initialization calls such as module loading). Where the underlying C++ implementation is also based on callbacks, this is straightforward. Where the underlying C++ code would block, the implementation becomes a somewhat more difficult exercise in thread management.&lt;/p&gt;

&lt;p&gt;The JavaScript API in node.js &amp;quot;feels&amp;quot; very much like JavaScript. I believe a main factor making this possible is the relatively small number of entry points required from the JavaScript down into the C++ code: sockets, DNS resolution, the http parsing library, etc. It was feasible for each interface to be lovingly crafted by hand, baking JavaScriptiness into the API.&lt;/p&gt;
 
&lt;p&gt;Attempting this technique for software like GUIs, where the number of C/C++ APIs to bind to is enormous, would likely require a more automated linkage between JavaScript and C++. This is the world of things like &lt;a href="http://www.swig.org/"&gt;SWIG&lt;/a&gt; to generate interfaces or &lt;a href="http://sourceware.org/libffi/"&gt;libffi&lt;/a&gt; to make direct calls. SWIG and libffiare extremely useful in their niches, but definitely have the feel of a foreign intruder in the host language. I don't know that a node.js for GUIs would be as pleasant a thing to look upon, but we need a way to do so. Software needs to advance without having to continually reinvent and reimplement what has come before, and without requiring drastic amounts of manual effort.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-4586548453049839317?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/hSFhwtXridU" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=4586548453049839317" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4586548453049839317?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4586548453049839317?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/nodejs-from-30000-feet.html" title="node.js from 30,000 feet" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_WibILqsOlLg/TFlc-83p25I/AAAAAAAAAvE/8ohNw2L6kOc/s72-c/nodejsarch.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkINQn49cCp7ImA9Wx5TF0g.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5524011614575150411</id><published>2010-08-02T06:01:00.000-07:00</published><updated>2010-08-02T06:09:53.068-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-02T06:09:53.068-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Zeus SCM</title><content type="html">&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/File:Jupiter_Smyrna_Louvre_Ma13.jpg"&gt;&lt;img border="0" width="249" height="213" align="right" src="http://3.bp.blogspot.com/_WibILqsOlLg/TFV8YW7szzI/AAAAAAAAAvA/xizMvQmxAk8/s320/ZeusSCM.jpg" style="border: none; margin: 2px;" alt="Closeup of face from statue of Zeus" title="Image from Wikipedia, licensed under creative commons" /&gt;&lt;/a&gt;The last few years have seen much innovation in source code management systems. Personally I find these systems to be needlessly complex, and have long wished for a simpler option. Therefore it is with great pride that I announce a new source code management system: Zeus. Its name comes from a particular event in Greek mythology where Pallas Athena bursts forth, fully grown, from the forehead of Zeus. The guiding principle of Zeus is that source code should appear in its final form, and thus dispenses with such outmoded concepts as file versions and history. Source files simply spring forth from the repository, in all their glory.&lt;/p&gt;

&lt;p&gt;Zeus relies on a single environment variable for all of its settings: ${REPO}. This is the central source repository where all files will reside. Zeus supports both local and remote filesystems such as NFS. The Zeus command structure is designed to leverage a developer's familiarity with existing shell commands. For example, checking code out from the repository is deliberately very similar to a copy command:&lt;/p&gt;

&lt;pre style="margin: 0 0 0.5em 1em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;zeus cp ${REPO}/file.cc client/&lt;/pre&gt;

&lt;p&gt;Other available Zeus commands include, but are not limited to:&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;&lt;span style="font-family: Courier New, monospace; font-size: small;"&gt;zeus ls ${REPO}&lt;/span&gt; : list files in the repository&lt;/li&gt;
 &lt;li&gt;&lt;span style="font-family: Courier New, monospace; font-size: small;"&gt;zeus ls -l ${REPO}&lt;/span&gt; : detailed information about files in the repository&lt;/li&gt;
 &lt;li&gt;&lt;span style="font-family: Courier New, monospace; font-size: small;"&gt;zeus echo "note" &gt;&gt; ${REPO}/notes.txt&lt;/span&gt; : maintain a feature request list in the repository&lt;/li&gt;
 &lt;li&gt;&lt;span style="font-family: Courier New, monospace; font-size: small;"&gt;zeus cat ${REPO}/file.cc&lt;/span&gt; : print file.cc to the console, without checking it out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another great thing about Zeus is its simple, straightforward implementation. Any developer can understand its workings, and implement changes to meet their needs.&lt;/p&gt;

&lt;pre style="border-width: 1px; border-color: #999999; border-style: solid; background-color: #f7f7f7; padding: 6px; margin: 1em 2em 1em 2em; font-family: Courier New, monospace; font-size: small; line-height: 1.3;"&gt;#!/bin/sh

# Zeus source code management system
# Copyright 8/2010, Denton Gentry

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.

&lt;b&gt;exec $*&lt;/b&gt;&lt;/pre&gt;

&lt;p&gt;I hope you enjoy using Zeus as much as I do. Many thanks to &lt;a href="http://www.victusspiritus.com/"&gt;Mark Essel&lt;/a&gt; for his contribution of ideas.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5524011614575150411?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/IWZ7ganRqS8" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=5524011614575150411" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5524011614575150411?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5524011614575150411?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/08/zeus-scm.html" title="Zeus SCM" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_WibILqsOlLg/TFV8YW7szzI/AAAAAAAAAvA/xizMvQmxAk8/s72-c/ZeusSCM.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CU8CQXs6eSp7ImA9Wx5TE08.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-8834023469746797959</id><published>2010-07-28T06:31:00.000-07:00</published><updated>2010-07-28T06:31:00.511-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-28T06:31:00.511-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Virtual Machines" /><title>Exploring libjit</title><content type="html">&lt;p&gt;Continuing investigation into JIT compilation for &lt;a href="http://codingrelic.geekhold.com/2010/07/virtual-instruction-sets-opcode.html"&gt;virtual machines&lt;/a&gt;, today we will delve into some of the plumbing. &lt;a href="http://www.gnu.org/software/dotgnu/libjit-doc/libjit.html#Top"&gt;libjit&lt;/a&gt; is a library for implementing JIT compilers in a platform independent way. A virtual machine calls functions within libjit to emit abstract, low level operations such as arithmetic computation or branches. libjit will handle translation to the native opcodes of the platform on which it is running. x86 and ARM are currently supported, with other CPU architectures falling back to a slower interpreted path. The main thrust of libjit development is to support the &lt;a href="http://www.mono-project.com/Main_Page"&gt;Mono project&lt;/a&gt;, an open source effort to implement the .NET CLR.&lt;/p&gt;

&lt;p&gt;To investigate libjit we'll turn to the &lt;a href="http://progopedia.com/example/fibonacci/"&gt;Official Subroutine for Programming Language Evaluation on the Internet&lt;/a&gt;, Fibonacci numbers. We'll start with an iterative C implementation:&lt;/p&gt;

&lt;pre style="margin: 0 3em 1em 5em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;
unsigned long long fib (unsigned int n) {
  if (n &amp;lt;= 2) return 1;
  unsigned long long a = 1, b = 1, c;
  do {
    c = a + b;
    b = a;
    a = c;
    n--;
  } while (n &amp;gt; 2);
  return c;
}
&lt;/pre&gt;

&lt;p&gt;libjit is designed to be driven from an Abstract Syntax Tree description of an algorithm. By descending through the AST outputting JIT operations at each node, you can construct native instructions for that algorithm. Had we written fib() in an interpreted language, we'd start with the AST within the interpreter. For the purposes of this example I've skipped the AST, manually constructing a fibonacci number routine by translating each line of C source code into JIT calls. The code is below, for your edification and bemusement.&lt;/p&gt;

&lt;pre style="margin: 0 3em 1em 5em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;
jit_function_t create_fib_jit (jit_context_t *context) {
  jit_type_t param;
  jit_type_t signature;
  jit_function_t function;
  jit_value_t n, a, b, c;
  jit_value_t constant, compare, n_minus_1, a_plus_b;
  jit_label_t label1 = jit_label_undefined;
  jit_label_t label2 = jit_label_undefined;

  jit_init();
  *context = jit_context_create();
  jit_context_build_start(*context);

  /* Build the function signature, fib(unsigned int) */
  param = jit_type_uint;
  signature = jit_type_create_signature(jit_abi_cdecl, jit_type_ulong,
                                        &amp;amp;param, 1, 1);
  function = jit_function_create(*context, signature);

  /* Begin emitting instructions */

  /* &lt;b&gt;"if (n &amp;lt;= 2)"&lt;/b&gt; */
  n = jit_value_create(function, jit_type_uint);
  n = jit_value_get_param(function, 0);
  constant = jit_value_create_nint_constant(function, jit_type_uint, 2);
  compare = jit_insn_le(function, n, constant);
  jit_insn_branch_if_not(function, compare, &amp;amp;label1);

  /* &lt;b&gt;"return 1;"&lt;/b&gt; */
  constant = jit_value_create_nint_constant(function, jit_type_ulong, 1);
  jit_insn_return(function, constant);

  /* &lt;b&gt;"if (n &amp;lt;= 2)" else branches here&lt;/b&gt; */
  jit_insn_label(function, &amp;amp;label1);

  /* &lt;b&gt;"unsigned long long a = 1, b = 1, c;"&lt;/b&gt; */
  constant = jit_value_create_nint_constant(function, jit_type_ulong, 1);
  a = jit_value_create(function, jit_type_ulong);
  jit_insn_store(function, a, constant);
  b = jit_value_create(function, jit_type_ulong);
  jit_insn_store(function, b, constant);
  c = jit_value_create(function, jit_type_ulong);

  /* &lt;b&gt;"do {"&lt;/b&gt; */
  jit_insn_label(function, &amp;amp;label2);

  /* &lt;b&gt;"c = a + b;&lt;/b&gt;
   *  &lt;b&gt;b = a;&lt;/b&gt;
   *  &lt;b&gt;a = c;"&lt;/b&gt; */
  a_plus_b = jit_insn_add(function, a, b);
  jit_insn_store(function, c, a_plus_b);
  jit_insn_store(function, b, a);
  jit_insn_store(function, a, c);

  /* &lt;b&gt;"n--;"&lt;/b&gt; */
  constant = jit_value_create_nint_constant(function, jit_type_uint, 1);
  n_minus_1 = jit_insn_sub(function, n, constant);
  jit_insn_store(function, n, n_minus_1);

  /* &lt;b&gt;"} while (n &gt; 2);"&lt;/b&gt; */
  constant = jit_value_create_nint_constant(function, jit_type_uint, 2);
  compare = jit_insn_gt(function, n, constant);
  jit_insn_branch_if(function, compare, &amp;amp;label2);

  /* &lt;b&gt;"return c;"&lt;/b&gt; */
  jit_insn_return(function, c);

  if (jit_function_compile(function) == 0) {
    printf("compilation error occurred\n");
  }
  jit_context_build_end(*context);
  return function;
}
&lt;/pre&gt;

&lt;p&gt;libjit compiles this function to native opcodes. Running on x86, the resulting assembly looks a great deal like the series of jit_insn_* calls which generated it.&lt;/p&gt;

&lt;pre style="margin: 0 3em 1em 5em; font-family: Courier New, monospace; font-size: small; line-height: 1.4;"&gt;
   push   %rbp
   mov    %rsp,%rbp
   sub    $0x20,%rsp
   mov    %r12,(%rsp)
   mov    %r13,0x8(%rsp)
   mov    %r14,0x10(%rsp)
   mov    %r15,0x18(%rsp)
   mov    %rdi,%r15
   cmp    $0x2,%edi
   ja     A
   mov    $0x1,%eax
   jmpq   C
A: mov    $0x1,%r14d
   mov    $0x1,%r13d
B: mov    %r14,%r12
   add    %r13,%r12
   mov    %r14,%r13
   mov    %r12,%r14
   dec    %r15d
   cmp    $0x2,%r15d
   ja     B
   mov    %r12,%rax
C: mov    (%rsp),%r12
   mov    0x8(%rsp),%r13
   mov    0x10(%rsp),%r14
   mov    0x18(%rsp),%r15
   mov    %rbp,%rsp
   pop    %rbp
   retq   
&lt;/pre&gt;

&lt;p&gt;How does it perform compared to the C version? I ran each in a loop of 1,000,000 iterations computing fib(75). The function was run once outside the timing loop, to avoid cache miss effects. The C code was compiled with -O0 and -O2, which made a huge difference in the results. Invoking gcc -O3 resulted slower code due to overly aggressive loop unrolling. Similarly, libjit can set an optimization level, though it made no measurable difference in the results.&lt;/p&gt;

&lt;table border="0" style="margin: 0 2em 1em 2em;"&gt;
&lt;tr&gt;&lt;td&gt;C -O0:&lt;/td&gt;&lt;td&gt;&amp;nbsp;367.2 nsecs/iteration&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;libjit:&lt;/td&gt;&lt;td&gt;&amp;nbsp;344.8 nsecs/iteration&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;C -O2:&lt;/td&gt;&lt;td&gt;&amp;nbsp;110.1 nsecs/iteration&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;In this example libjit achieved the speed of a naive C compilation. This makes sense, it is the result of a naive programmer translating C code.&lt;/p&gt;

&lt;p&gt;The point of this series of articles is the promise, not necessarily the current reality. The great promise of JIT compilation as compared to static is the ability to make optimizations based on profiling, even specializing routines for specific input values. The routine can sanity check its inputs, and escape back into the interpreter if the input does not match expectations. This would be of great benefit in large code bases, where we frequently have variables which are essentially constant. For example in a web application the language setting is a variable, though any individual user essentially never changes their language setting in the middle of a session. We'll explore this idea more in the future.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-8834023469746797959?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/KXCxUX6Mc_I" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=8834023469746797959" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8834023469746797959?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8834023469746797959?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/exploring-libjit.html" title="Exploring libjit" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CEQHQXw6eyp7ImA9Wx5TEUg.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5575376323413482120</id><published>2010-07-26T06:01:00.001-07:00</published><updated>2010-07-26T06:52:10.213-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-26T06:52:10.213-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Victorian Arduino</title><content type="html">&lt;p&gt;You might think this is a painting of an espresso machine, but that is incorrect. Its actually an early Victorian prototype of the &lt;a href="http://www.arduino.cc/"&gt;Arduino&lt;/a&gt;, and an espresso machine is just one of the projects it can be used for.&lt;/p&gt;
&lt;p&gt;As this first Arduino shipped before the invention of semiconductors, it is steam powered.&lt;/p&gt;

&lt;br/&gt;
&lt;center&gt;&lt;img src="http://4.bp.blogspot.com/_WibILqsOlLg/TDHfwYNXm1I/AAAAAAAAAuk/QquGj4QqBxg/s640/arduino.jpg" width="446" height="567"&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5575376323413482120?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/WUsmxBXdmUU" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=5575376323413482120" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5575376323413482120?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5575376323413482120?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/victorian-arduino.html" title="Victorian Arduino" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_WibILqsOlLg/TDHfwYNXm1I/AAAAAAAAAuk/QquGj4QqBxg/s72-c/arduino.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0IAQHY5cCp7ImA9WxFaGUU.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-1342090499293179285</id><published>2010-07-24T08:30:00.000-07:00</published><updated>2010-07-24T08:32:21.828-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-24T08:32:21.828-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CPU" /><title>WWMD?</title><content type="html">&lt;p&gt;When Apple announced its A4 ARM CPU, I &lt;a href="http://codingrelic.geekhold.com/2010/02/apple-plus-four-more-letters.html"&gt;speculated&lt;/a&gt;  about what would be in it. This speculation turned out to be completely wrong, but it was fun to write and engendered some good conversations about the possibilities. Now that &lt;a href="http://www.theregister.co.uk/2010/07/23/microsoft_arm/"&gt;Microsoft has signed an architecture license&lt;/a&gt; for ARM, I'm going to do it again. This article is complete speculation, and therefore rubbish. I am reliant on the same public sources of information as everyone else. Here we go.&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;What Will Microsoft Do?&lt;/span&gt;
&lt;p&gt;Many companies license core designs from ARM, building them into chips with peripherals to add functionality. The various levels of ARM license offer both synthesized gate-level netlists and encrypted synthesizable RTL. An architectural license is much more extensive, allowing development of entirely new implementations of the ARM instruction set. Only the architectural license conveys the unencrypted, modifiable source code for the processor design. According to news reports, three other companies currently have an architectural license: &lt;a href="http://www.qualcomm.com/"&gt;Qualcomm&lt;/a&gt;, &lt;a href="http://www.marvell.com/"&gt;Marvell Semiconductor&lt;/a&gt; and &lt;a href="http://www.infineon.com"&gt;Infineon Technologies&lt;/a&gt;.   Qualcomm develops the &lt;a href="http://www.qualcomm.com/products_services/chipsets/snapdragon.html"&gt;Snapdragon,&lt;/a&gt; a line of ARM CPUs with integrated DSP and various mobile-related features. Marvell now owns the license originally used by DEC for development of the &lt;a href="http://en.wikipedia.org/wiki/StrongARM"&gt;StrongARM&lt;/a&gt;, and under which Intel later produced the &lt;a href="http://en.wikipedia.org/wiki/XScale"&gt;XScale&lt;/a&gt;. Infineon entered into the licensing agreement &lt;a href="http://www.infineon.com/cms/en/corporate/press/news/releases/2009/INFCCS200911-009.html"&gt;in late 2009,&lt;/a&gt; and will focus on security applications. Infineon is one of the few companies which embeds DRAM cells into the same die as the logic, and presumably will use this capability for HD SIM cards and other applications.&lt;/p&gt;

&lt;p&gt;More notable than the list of architecture licensees is the list of companies which do &lt;i&gt;not&lt;/i&gt; license the architecture. &lt;a href="http://www.samsung.com/global/business/semiconductor/productList.do?fmly_id=834&amp;xFmly_id=229"&gt;Samsung&lt;/a&gt;, which produces vast numbers of ARM CPUs, is content to work with ARM cores. Apple uses a Cortex A8 core in &lt;a href="http://codingrelic.geekhold.com/2010/02/apple-plus-four-more-letters.html"&gt;the A4&lt;/a&gt;, and does not have an architectural license either. Neither do &lt;a href="http://www.ti.com/ww/en/embedded/arm/index.html"&gt;TI&lt;/a&gt;, &lt;a href="http://www.cirrus.com/en/products/pro/techs/T7.html"&gt;Cirrus Logic&lt;/a&gt;, or &lt;a href="http://www.atmel.com/products/at91/"&gt;Atmel&lt;/a&gt;. Most companies use ARM core designs, and spend their efforts on the logic surrounding the CPU.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/File:KL_Microsoft_XBOX_380_CPU_ES.jpg"&gt;&lt;img border="0" width="144" height="145" align="right" src="http://4.bp.blogspot.com/_WibILqsOlLg/TEr3J6l_NNI/AAAAAAAAAu4/kPOhvm6EtkQ/s160/xcpu.jpg" style="border: none; margin: 1px;" alt="XCU from XBox360-S" title="Image courtesy Wikipedia" /&gt;&lt;/a&gt;I tend to agree with &lt;a href="http://www.theregister.co.uk/2010/07/23/microsoft_arm/"&gt;The Register's take&lt;/a&gt; on it: Microsoft's ARM license is all about the XBox. Windows Mobile phones and the Zune use ARM, but there is little justification in producing their own chip for these markets. The XBox is the one hardware product which Microsoft produces itself, which can gain a competitive advantage via a unique CPU design, and which sells in large enough volume to be worth it. Microsoft already employs a great deal of custom silicon from suppliers in the product, such as the &lt;a href="http://www.pcper.com/article.php?aid=940&amp;type=expert&amp;pid=3"&gt;XCGPU&lt;/a&gt; used in the XBox 360-S. This chip combines the main PowerPC CPU and the ATI GPU onto a single die, with a second DRAM die incorporated into the package.&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;Its the Architecture, Stupid&lt;/span&gt;
&lt;p&gt;So what might Microsoft do? I'll speculate that they won't design their own entirely new  pipeline, the return on investment seems slim compared to other things they could spend time on. Its more likely they'd start from an existing ARM core and begin making changes. Microsoft will certainly integrate a powerful GPU onto the processor die, not doing so would be a step backwards from the existing XBox 360-S. I'll speculate they will tightly couple the GPU, allowing very low latency access to it as an ARM coprocessor in addition to the more straightforward memory mapped device. This is not unique: some of the on-chip XScale functional units can be accessed both as coprocessors for low latency and as memory mapped registers to get to the complete functionality of the unit. Having very low latency access to the GPU would allow efficient offloading of even small chunks of processing to GPU threads.&lt;/p&gt;

&lt;p&gt;Yet even ARM coprocessors can be designed without needing an architectural license. TI implements its &lt;a href="http://en.wikipedia.org/wiki/Texas_Instruments_DaVinci"&gt;DaVinci DSP&lt;/a&gt; as a coprocessor, and Cirrus Logic had its own &lt;a href="http://wiki.debian.org/ArmEabiMaverickCrunch"&gt;Maverick Crunch FPU&lt;/a&gt;. Neither company is an architectural licensee. So why would Microsoft feel it needs one?&lt;/p&gt;

&lt;p&gt;One possibility is to let the GPU directly access the ARM processor cache and registers. This would allow GPU offloading to work almost exactly like a function call, putting arguments into registers or onto the stack with a coprocessor instruction to dispatch the GPU. When the GPU finishes, the ARM returns from the function call. For operations where the GPU is dramatically better suited, the ARM CPU would spend less time stalled than it would take to compute the result itself. If the ARM CPU supported &lt;a href="http://en.wikipedia.org/wiki/Simultaneous_multithreading"&gt;hardware threads&lt;/a&gt;, it could switch to a different register file and run some other task while the GPU is crunching.&lt;/p&gt;

&lt;p&gt;Part of the success of the XBox is due to its straightforward programming model compared to the Sony PS3. XBox has a fast SMP CPU paired with a GPU, where PS3 has an unruly gaggle of  Cell processors to be managed explicitly. XBox cannot rely on the individual cores getting faster, as single core performance has leveled off due to power dissipation constraints. XBox has to make it easy for game developers to take advantage of more cores. Tightly coupling the GPU threads so they can function more like one big SMP system is one avenue to do this.&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 120%; font-weight: bold;"&gt;Wrapping up&lt;/span&gt;
&lt;p&gt;I'll say it again: I made this all up. I have no insight into the specifics of Microsoft's intentions, just speculation. In the unlikely event that anyone reads this, don't copy it into Wikipedia as though it were verified information.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-1342090499293179285?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/XyEYULBQDjo" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=1342090499293179285" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1342090499293179285?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1342090499293179285?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/wwmd.html" title="WWMD?" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_WibILqsOlLg/TEr3J6l_NNI/AAAAAAAAAu4/kPOhvm6EtkQ/s72-c/xcpu.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CE8BSHk5eyp7ImA9WxFaFUg.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-679324973573773062</id><published>2010-07-19T06:01:00.000-07:00</published><updated>2010-07-19T08:20:59.723-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-19T08:20:59.723-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Fibre Channel over Token Ring</title><content type="html">&lt;p&gt;&lt;img border="0" width="140" height="158" align="right" src="http://1.bp.blogspot.com/_WibILqsOlLg/TERCVsQsw0I/AAAAAAAAAu0/3Keynxh6YMU/s320/tokenring.jpg" style="border: none; margin: 1px;" alt="Token Ring connector" title="If you squint just right, you can see the token just emerging from the upper right pin" /&gt;Monday morning posts on this site are normally jokes, funny observations, and amusing bits of fluff. Today I have to tip my hat to something far more elaborate: &lt;a href="http://fcotr.org/"&gt;Fibre Channel over Token Ring&lt;/a&gt;. I can only stand in awe of the work of true masters.&lt;/p&gt;

&lt;p&gt;The Fibre Channel link technology is lossless, with extensive flow control and data integrity mechanisms to ensure all data is delivered. Running &lt;a href="http://en.wikipedia.org/wiki/Fibre_Channel_over_Ethernet"&gt;Fibre Channel over Ethernet&lt;/a&gt; is saddled with significant complexity. Had Token Ring won the LAN battle instead of Ethernet, running Fibre Channel over it would be simpler. Therefore, FCoTR aims to resurrect Token Ring and make it the new dominant networking technology. Sounds simple and logical, right?&lt;/p&gt;

&lt;p&gt;The amount of work put into this hoax is impressive.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is an industry trade group, the &lt;a href="http://fcotr.org/"&gt;Fibre Channel over Token Ring Alliance&lt;/a&gt;. In a nice touch, all of the links on the site are broken including the press release announcing its formation.&lt;/li&gt;
&lt;li&gt;There is a &lt;a href="http://fctr.blogspot.com/"&gt;FCoTR User Group&lt;/a&gt;, complete with &lt;a href="http://twitter.com/FCoTRUserGroup/"&gt;twitter account&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The obligatory &lt;a href="http://www.wikipedia.com/wiki/FCoTR"&gt;Wikipedia page&lt;/a&gt; is sadly already flagged for deletion.&lt;/li&gt;
&lt;li&gt;There is a &lt;a href="http://fcotr.org/wp-content/uploads/2010/07/802.5qZ-DRAFT-20100716.pdf"&gt;White Paper&lt;/a&gt; which was clearly created by a Markov chainer seeded with computer science and storage terminology, possibly &lt;a href="http://pdos.csail.mit.edu/scigen/"&gt;SCIgen&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Dozens of tweets carry the hashtag &lt;a href="http://twitter.com/#search?q=%23FCoTR"&gt;#FCoTR&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Stephen Foskett wrote a long &lt;a href="http://blog.fosketts.net/2010/07/16/fibre-channel-token-ring-fcotr/"&gt;blog post&lt;/a&gt; about the idea. It starts off subtle, but becomes increasingly outrageous. As many people will only skim the first paragraph, they won't notice the claims at the end: Intel building a &lt;a href="http://en.wikipedia.org/wiki/Micro_Channel_architecture"&gt;Micro Channel&lt;/a&gt; to PCI Express bridge to ease the introduction of token ring products, and Proteon making a comeback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Greg Ferro has &lt;a href="http://etherealmind.com/myth-fibrechannel-over-token-ring/"&gt;an excellent writeup&lt;/a&gt; about FCoTR and its motivations. In order to make a large network appear to be completely lossless, Fibre Channel has always relied on extremely complex designs. This leads to very expensive gear. Fibre Channel networks also run at relatively low utilization, because full buffers lead to packet loss. FC over Ethernet disrupts all of that. For vendors and storage mavens who feel threatened by a converged network, the solution is to push for a solution which will once again let them run a separate, single purpose, and thoroughly overengineered network. Token Ring meets these requirements.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-679324973573773062?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/4hAuu4Fz2JE" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=679324973573773062" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/679324973573773062?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/679324973573773062?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/fiber-channel-over-token-ring.html" title="Fibre Channel over Token Ring" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_WibILqsOlLg/TERCVsQsw0I/AAAAAAAAAu0/3Keynxh6YMU/s72-c/tokenring.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0UCQX4zeip7ImA9WxFaEkU.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-1352667774154635861</id><published>2010-07-16T06:01:00.000-07:00</published><updated>2010-07-16T06:01:00.082-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-16T06:01:00.082-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mobile" /><title>Alternate Phone B</title><content type="html">&lt;div style="float: right;"&gt;
&lt;center&gt;&lt;img border="0" width="166" height="326" src="http://1.bp.blogspot.com/_WibILqsOlLg/TEBSD_JZPuI/AAAAAAAAAuw/FeQKE8VzryU/s640/iphone4.jpg" style="border: none; margin: 1px;" alt="iPhone 4" title="Image Courtesy of Apple." /&gt;&lt;br/&gt;&lt;p style="font-size: 9px; color: #777;"&gt;Image courtesy of Apple&lt;/p&gt;&lt;/center&gt;
&lt;/div&gt;
&lt;p&gt;When Gizmodo &lt;a href="http://gizmodo.com/5520164/this-is-apples-next-iphone"&gt;acquired an iPhone 4 prototype&lt;/a&gt;, I recall a mention that Apple execs were especially annoyed because there had been &lt;i&gt;two&lt;/i&gt; versions of the iPhone 4. The one Gizmodo recovered was the more aggressive of the two designs, with the other version prepared as a backup. When Gizmodo showed the prototype to the world, it became impossible to go with the alternate design.&lt;/p&gt;

&lt;p&gt;When developing a backup release for any product, software or hardware, you want to minimize the resources spent on it. You spend most of the effort on the primary design, the more aggressive version. The primary &lt;i&gt;will&lt;/i&gt; ship, its just a question of when, so the resources spent on it will not go to waste. The backup, in contrast, will ideally never see the light of day. You'd prefer to only spend resources on it which can also benefit the primary effort, and minimize the amount of throw-away work.&lt;/p&gt;

&lt;p&gt;So what might the &amp;quot;Alternate Plan B&amp;quot; version of the iPhone 4 have been? Using the &lt;a href="http://codingrelic.geekhold.com/2010/02/apple-plus-four-more-letters.html"&gt;A4 CPU&lt;/a&gt; seems assured, as &lt;i&gt;not&lt;/i&gt; using it would have led to uncomfortable questions. It presumably would also have incorporated the current versions of the baseband radio circuitry, and possibly the new gyroscope as well. If the gyro didn't work out, it could be marked no-stuff in assembly and the software support disabled. I'd speculate that the Alternate Plan B for iPhone 4 was a new board with A4 CPU and gyro sized to fit in a minimally modified 3GS housing.&lt;/p&gt;

&lt;p&gt;I wonder which version would Apple have gone with, had they a choice?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-1352667774154635861?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/BLyUX1twuRc" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=1352667774154635861" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1352667774154635861?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1352667774154635861?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/alternate-phone-b.html" title="Alternate Phone B" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_WibILqsOlLg/TEBSD_JZPuI/AAAAAAAAAuw/FeQKE8VzryU/s72-c/iphone4.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0MMQ30_fip7ImA9WxFbGEg.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-3883689188532957624</id><published>2010-07-08T06:01:00.000-07:00</published><updated>2010-07-11T07:44:42.346-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-11T07:44:42.346-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Virtual Machines" /><category scheme="http://www.blogger.com/atom/ns#" term="CPU" /><category scheme="http://www.blogger.com/atom/ns#" term="bestof" /><title>Virtual Instruction Sets: Opcode Arguments</title><content type="html">&lt;p&gt;&lt;img border="0" width="128" height="128" align="right" src="http://1.bp.blogspot.com/_WibILqsOlLg/TDXALF9yBhI/AAAAAAAAAus/CJ_qCsx0_zU/s160/CPUfan.png" style="border: none; margin: 5px;" alt="Its a virtual CPU fan, get it?" title="CPU fan" /&gt;Virtual Machine architectures are a fascinating topic, and one that I plan to &lt;a href="http://codingrelic.geekhold.com/2009/01/blogroll-january-2009.html"&gt;occasionally explore&lt;/a&gt; in this space. Not virtual machines in the sense of &lt;a href="http://www.vmware.com/"&gt;VMWare&lt;/a&gt; or &lt;a href="http://www.xen.org/"&gt;Xen&lt;/a&gt;, rather the runtime environment for a programming language like Java or Python. This time we'll focus on the structure of the instruction set, in particular on how operands are passed and stored. Why are these low level details important?&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;Traditional compilers emit instruction sequences without knowing anything about the specific CPU model, system configuration, or input data to be processed.&lt;/li&gt;
 &lt;li&gt;The compiler can optimize for a specific CPU pipeline, and maybe even produce multiple binaries for different CPUs. As a practical matter you cannot produce a large number of variations due to the sheer size of the final binary image.&lt;/li&gt;
 &lt;li&gt;Profile-driven compilation can optimize for representative data you supply during the build phase, but representative data is always a guess and a compromise. Also as a practical matter, its difficult to use profile-driven optimization for many applications, such as GUIs.&lt;/li&gt;
 &lt;li&gt;Only a &lt;a href="http://en.wikipedia.org/wiki/Just-in-time_compilation"&gt;JIT&lt;/a&gt; for a virtual machine has the luxury of knowing the specific CPU, system configuration, and has profiling information &lt;i&gt;from the current input data.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hardware CPU architectures we use now have evolved in lockstep with compiler technology, and mostly C/C++ compilers at that. They have enormous I$ and D$ because the compiler cannot predict very much about what it will execute next. The hardware has extensive branch prediction logic and history tracking because compilers emit an average of one branch every 7 instructions.&lt;/p&gt;

&lt;p&gt;Virtual Machines change everything: by profiling the running code they can produce instructions for this specific workload, resulting in long sequences of very predictable opcodes without branches or conditionals. It has the potential to change hardware architectures, once we pass a tipping point where most of the workload runs within a VM. I suspect this tipping point will be reached in mobile devices well before it impacts workstations, laptops, or servers.&lt;/p&gt;

&lt;p&gt;This rosy prediction is by no means certain. The JIT for most current VMs will compile a function the first time it is used. They can optimize for the CPU and possibly even take memory size into account, but they don't use any profiling information. Thus the JIT can potentially get the benefit of compiling for the specific CPU pipeline on which it runs, though in practice even this isn't typically done. So far as I know of the VMs discussed here only Mozilla's Spidermonkey makes use of tracing to produce specifically optimized routines according to the input data being processed.&lt;/p&gt;

&lt;p&gt;We're going to examine seven virtual machines, focussing on how operands are passed: the JVM, CLR, Spidermonkey, LLVM, Parrot, V8, and Dalvik.&lt;/p&gt;

&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 125%; font-weight: bold;"&gt;JVM &amp;amp; CLR&lt;/span&gt;
&lt;p&gt;&lt;img border="0" width="238" height="112" align="right" src="http://1.bp.blogspot.com/_WibILqsOlLg/TC4nT5H6eSI/AAAAAAAAAuc/L_ObWPWkAFw/s320/jvm.png" style="border: none; margin: 1px;" alt="JVM argument stack" title="Very clever, young man, very clever, but its operands all the way down." /&gt;The &lt;a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions.doc.html"&gt;Java Virtual Machine&lt;/a&gt; and the &lt;a href="http://en.wikipedia.org/wiki/Common_Language_Runtime"&gt;Common Language Runtime&lt;/a&gt; used by .Net are certainly very different, but as virtual machines go they have a lot in common. Both are stack based: operands to an instruction are popped from the stack, and the result is pushed.&lt;/p&gt;

&lt;p&gt;Stack based virtual machines are relatively common, because they are conceptually very simple. Indeed many early microprocessors and microcontollers were stack based, because the silicon technology of the day wouldn't allow a CPU with a generous number of registers on the die. In that sense virtual CPUs are following the same evolutionary path as hardware CPUs did several decades ago, starting with stack based machines and adding registers later.&lt;p&gt;

&lt;p&gt;Stack-based instruction sets tend to have a very high code density, because their opcodes don't need to encode source and destination register numbers. When the JVM was developed in the early 1990s, processor caches were measured in the tens of kilobytes. A densely packed bytecode was a big advantage, far more bytecode could be stored in the hardware CPU's data cache.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 125%; font-weight: bold;"&gt;Spidermonkey (Firefox)&lt;/span&gt;
&lt;p&gt;&lt;a href="http://www.mozilla.org/js/spidermonkey/"&gt;SpiderMonkey&lt;/a&gt; is the Javascript engine in &lt;a href="http://www.mozilla.org/firefox/"&gt;Firefox&lt;/a&gt;, and is a stack-based machine like the JVM and CLR. What I find most interesting about SpiderMonkey is that it tackled profile-driven JIT optimization &lt;i&gt;first,&lt;/i&gt; via &lt;a href="https://wiki.mozilla.org/JavaScript:TraceMonkey"&gt;TraceMonkey&lt;/a&gt; in the latter part of 2008. A more conventional method-compiling JIT came later, via &lt;a href="https://wiki.mozilla.org/JaegerMonkey"&gt;JaegerMonkey&lt;/a&gt; in &lt;a href="http://www.bailopan.net/blog/?p=683"&gt;early 2010&lt;/a&gt;. The virtue of doing things in this order is pretty compelling: tracing, when it works, can deliver spectacular gains. However tracing really only helps with loops, leaving lots of low hanging fruit for a method-based JIT. Doing the method-based JIT first makes it more difficult to get the profiling information which tracing needs. By doing TraceMonkey first, its instrumentation needs became part of the requirements for JaegerMonkey.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 125%; font-weight: bold;"&gt;LLVM&lt;/span&gt;
&lt;p&gt;The primary design point of the &lt;a href="http://www.llvm.org/"&gt;LLVM&lt;/a&gt; project is a compiler toolchain, and the LLVM instruction set was designed to be the intermediate representation between the language-specific frontend and more generic backend. The LLVM instruction set defines a register based virtual machine with an interesting twist: it has an infinite number of registers. In keeping with its design point as a compiler intermediate representation, LLVM registers enable &lt;a href="http://en.wikipedia.org/wiki/Static_single_assignment_form"&gt;static single assignment form&lt;/a&gt;. A register is used for exactly one value and never reassigned, making it easy for subsequent processing to determine whether values are live or can be eliminated.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 125%; font-weight: bold;"&gt;Parrot&lt;/span&gt;
&lt;p&gt;&lt;a href="http://www.parrot.org/"&gt;Parrot&lt;/a&gt; is also a register based virtual machine. It defines four types of registers:&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;Integers&lt;/li&gt;
 &lt;li&gt;Numbers (i.e. floating point)&lt;/li&gt;
 &lt;li&gt;Strings&lt;/li&gt;
 &lt;li&gt;Polymorphic Containers (PMCs), which reference complex types and structures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Like LLVM, Parrot does not define a maximum number of registers: each function uses as many registers as it needs. Functions do not re-use registers for different purposes by storing their values to memory, they specify a new register number instead. The Parrot runtime will handle assignment of virtual machine registers to CPU registers.&lt;/p&gt;

&lt;p&gt;So far as I can tell, integer registers are the width of the host CPU on which the VM is running. A Parrot bytecode might find itself using either 32 or 64 bit integer registers, determined at runtime and not compile time. This is fascinating if correct, though it seems like &lt;a href="http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic"&gt;BigNum&lt;/a&gt; handling would be somewhat complicated by this.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 125%; font-weight: bold;"&gt;V8 (Chrome)&lt;/span&gt;
&lt;p&gt;&lt;a href="http://code.google.com/p/v8/"&gt;V8&lt;/a&gt; is the JavaScript engine in the &lt;a href="http://www.google.com/chrome"&gt;Chrome&lt;/a&gt; browser from Google. Its a bit of a misnomer to call V8 a virtual machine: it compiles the Javascript source for a method directly to machine code the first time it is executed. There is no intermediate bytecode, and no interpreter. This is an interesting design choice, but for the purposes of this article there isn't much to say about V8.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 125%; font-weight: bold;"&gt;Dalvik (Android)&lt;/span&gt;
&lt;p&gt;&lt;img border="0" width="227" height="274" align="right" src="http://1.bp.blogspot.com/_WibILqsOlLg/TC4ni_UJtjI/AAAAAAAAAug/s-oTvd80MUU/s320/dalvik.png" style="border: none; margin: 1px;" alt="Dalvik virtual machine registers" title="Mondrian, look out!" /&gt;Dalvik is the virtual machine for Android application code. The Dalvik instruction set implements an interesting compromise: it is register based, but there are a finite number of them as opposed to the theoretically infinite registers of LLVM or Parrot. Dalvik supports 65,536 registers, a vast number compared to hardware CPUs and presumably sufficient to implement SSA (if desired) in reasonably large functions.&lt;/p&gt;

&lt;p&gt;Even more interestingly, not all Dalvik instructions can access all registers. Many &lt;a href="http://www.netmite.com/android/mydroid/dalvik/docs/dalvik-bytecode.html"&gt;Dalvik instructions&lt;/a&gt; dedicate 4 bits to the register number, requiring their operands to be stored in the first 16 registers. A few more instructions have an 8 bit instruction number, to access the first 256. There are also instructions to copy the value to or from any of the 65,536 registers to a low register, for a subsequent instruction to access.&lt;/p&gt;

&lt;p&gt;It took a while to understand the rationale for this choice, and I'm still not confident I fully get it. Clearly the Dalvik designers believe that keeping data in one of the high registers will be faster than explicitly storing it to memory, even if the vast number of registers end up mostly residing in RAM. Addressing data as register numbers instead of memory addresses should make it easier for the VM to dynamically remap Dalvik registers to the real hardware registers. For example, if it can predict that virtual register 257 will likely be used in the near future it can be kept in a CPU register instead of being immediately stored to memory.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;span style="font-size: 125%; font-weight: bold;"&gt;Other VMs&lt;/span&gt;
&lt;p&gt;There are many, many more virtual machine implementations beyond the ones implemented here. The &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;, &lt;a href="http://www.smalltalk.org/"&gt;Smalltalk&lt;/a&gt;, and &lt;a href="http://www.lua.org/"&gt;Lua&lt;/a&gt; programming languages each have their own VM instruction set and implementation. &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt; started with a VM called JAM, and later reimplemented the underpinnings in a new virtual machine called BEAM. &lt;a href="http://www.adobe.com/"&gt;Adobe&lt;/a&gt; &lt;a href="http://www.adobe.com/products/flashplayer/"&gt;Flash&lt;/a&gt; has a VM which has been open sourced and donated to the Mozilla project as &lt;a href="http://www.mozilla.org/projects/tamarin/"&gt;Tamarin&lt;/a&gt;. Wikipedia &lt;a href="http://en.wikipedia.org/wiki/Comparison_of_application_virtual_machines"&gt;lists brief descriptions&lt;/a&gt; of a number of current VMs.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-3883689188532957624?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/pNxKhNcEu98" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=3883689188532957624" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3883689188532957624?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3883689188532957624?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/virtual-instruction-sets-opcode.html" title="Virtual Instruction Sets: Opcode Arguments" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_WibILqsOlLg/TDXALF9yBhI/AAAAAAAAAus/CJ_qCsx0_zU/s72-c/CPUfan.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0cCRHo9eCp7ImA9WxFbGEg.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-9121937666404314932</id><published>2010-07-06T11:13:00.000-07:00</published><updated>2010-07-11T07:37:45.460-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-11T07:37:45.460-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="social" /><category scheme="http://www.blogger.com/atom/ns#" term="bestof" /><title>The New Intelligence Agency: All of Us</title><content type="html">&lt;p&gt;Yesterday &lt;a href="http://blog.louisgray.com/"&gt;Louis Gray&lt;/a&gt; pieced together vague snippets of information from tweets made by the founders and investors of &lt;a href="http://foursquare.com/"&gt;Foursquare&lt;/a&gt; and &lt;a href="http://brizzly.com/"&gt;Brizzly&lt;/a&gt; to speculate that Foursquare was &lt;a href="http://blog.louisgray.com/2010/07/independence-day-speculation-is.html"&gt;negotiating to buy Brizzly&lt;/a&gt;. Later that day the speculation was denied by all parties involved. To (loosely) quote &lt;a href="http://en.wikipedia.org/wiki/Mandy_Rice-Davies"&gt;Mandy Rice-Davies&lt;/a&gt;: &amp;quot;They would deny it, wouldn't they?&amp;quot; &amp;nbsp;&amp;nbsp;... I don't think this story is over.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://commons.wikimedia.org/wiki/File:Lockheed's_%22Blue_Cube%22.jpg"&gt;&lt;img src="http://4.bp.blogspot.com/_WibILqsOlLg/TDNxxQCZbDI/AAAAAAAAAuo/ttgZEYFuwPc/s320/satellite.jpg" width="232" height="243" style="border: none; margin-left: 2em;" align="right"&gt;&lt;/a&gt;Nonetheless the details of the speculated transaction are not our topic today. Instead, I'd like to consider the process which led to it. For decades government (and sometimes corporate) intelligence operations have had access to reams of communications data from which to make inferences. They could see who was calling whom, where letters and packages were being delivered, and know people's movements to some extent via airline manifests.  Intelligence agencies are famous for collecting massive amounts of information and using algorithms to look for patterns, to be followed up by a human analyst.&lt;/p&gt;

&lt;p&gt;We're rapidly moving into a world where a significant amount of that information is available to anyone who cares to look for it. We're using social networks which broadcast our updates publicly, either deliberately or because we don't understand the privacy settings. We're rapidly integrating location data into online applications, which people willingly share if they see a benefit from it. As the tweets Louis quoted show, people also love making coy hints about their dealings, secure in the knowledge that nobody will figure out such a vague hint. Yet given enough vague data, particularly if one is aware of existing connections between the participants, correlations can be found. Certainly there will be false positives, but there will also be some real gems.&lt;/p&gt;

&lt;p&gt;Systematic data mining of social networks, both their contents and the metadata they contain, in order to gain competitive advantage has enormous implications. It apparently is already happening: military raids have been &lt;a href="http://seattletimes.nwsource.com/html/nationworld/2011249564_isfacebook04.html"&gt;cancelled&lt;/a&gt; due to leaks on social networks, showing that government agencies are concerned about the possibility. For the most part it won't be reported on, and will become just another part of the Internet underpinnings.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-9121937666404314932?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/2kbYmTS2mKg" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=9121937666404314932" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/9121937666404314932?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/9121937666404314932?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/new-intelligence-agency-all-of-us.html" title="The New Intelligence Agency: All of Us" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_WibILqsOlLg/TDNxxQCZbDI/AAAAAAAAAuo/ttgZEYFuwPc/s72-c/satellite.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;A0UCSHY7fSp7ImA9WxFbGEg.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-8806670260064937332</id><published>2010-07-01T06:01:00.000-07:00</published><updated>2010-07-11T07:41:09.805-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-11T07:41:09.805-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="astrostuff" /><category scheme="http://www.blogger.com/atom/ns#" term="CPU" /><title>Voyager 2 Soft Error</title><content type="html">&lt;p&gt;&lt;a href="http://voyager.jpl.nasa.gov/"&gt;&lt;img border="0" width="400" height="297" align="right" src="http://1.bp.blogspot.com/_WibILqsOlLg/TB9lJ9QW3UI/AAAAAAAAAuQ/ZumpUpVQR-I/s640/voyager2.jpg" style="border: none; margin: 1px;" alt="Voyager 2" title="Image courtesy NASA JPL" /&gt;&lt;/a&gt;&lt;a href="http://voyager.jpl.nasa.gov/"&gt;Voyager 2&lt;/a&gt; is currently traversing the &lt;a href="http://en.wikipedia.org/wiki/Heliosphere"&gt;heliosphere&lt;/a&gt;, the shockwave where the solar wind and particles of the interstellar medium meet. Decades after launch the Voyager probes are still transmitting data back to Earth, at 160 bits per second. Starting April 22, 2010, the checksums in the Voyager 2 datastream indicated problems in every frame. Something bad had happened to the spacecraft.&lt;/p&gt;

&lt;p&gt;After several weeks of testing, JPL &lt;a href="http://www.jpl.nasa.gov/news/news.cfm?release=2010-151"&gt;determined the root cause&lt;/a&gt; to be a flipped bit in the computer's memory. A bit had spontaneously changed from zero to one. JPL duplicated the incorrect checksum symptom by deliberately flipping that bit on a terrestrial copy of the Voyager computer system. On May 19, 2010 a command was sent to reset the bit to zero, and the next day (after 13 hour propagation delay each way) Voyager 2's datastream returned to normal.&lt;/p&gt;

&lt;p&gt;It appears to have been a &lt;a href="http://codingrelic.geekhold.com/2009/09/soft-errors-are-hard-problems.html"&gt;soft error&lt;/a&gt;. What is most interesting about this is the technology involved: the Voyager computer systems use magnetic core memory. On Earth, soft errors in core memory of this vintage are essentially impossible. The amount of energy required to flip the bit is so large that any particle with sufficient charge would have been deflected by the Earth's magnetic field. Out at the heliosphere, particles carrying sufficient energy to affect the core memory are apparently present.&lt;/p&gt;

&lt;p&gt;Software engineers at JPL are currently working on a software patch to stop using that bit in the core. It is possible that the problem wasn't purely random, that instead this particular bit of hardware is degrading and no longer holding its state reliably.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-8806670260064937332?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/0ouOFtUt8To" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=8806670260064937332" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8806670260064937332?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8806670260064937332?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/07/voyager-2-soft-error.html" title="Voyager 2 Soft Error" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_WibILqsOlLg/TB9lJ9QW3UI/AAAAAAAAAuQ/ZumpUpVQR-I/s72-c/voyager2.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkcCQXg-eip7ImA9WxFUF04.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5618859477501094874</id><published>2010-06-28T06:01:00.000-07:00</published><updated>2010-06-28T06:01:00.652-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-28T06:01:00.652-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Toxoplasmowhosit?</title><content type="html">&lt;p&gt;&lt;a href="http://www.flickr.com/photos/pulmonary_pathology/3785989291/"&gt;&lt;img border="0" width="250" height="169" align="right" src="http://4.bp.blogspot.com/_WibILqsOlLg/TB9rkKGdNrI/AAAAAAAAAuU/PTD_ZHh1xTw/s320/toxoplasmosis.jpg" style="border: none; margin: 1px;" alt="Toxoplasmosis" title="Image courtesy pulmonary_pathology on flikr, licensed under Creative Commons" /&gt;&lt;/a&gt;&lt;a href="https://health.google.com/health/ref/Toxoplasmosis"&gt;Toxoplasmosis&lt;/a&gt; has long been known to &lt;a href="http://www.economist.com/node/16271339?story_id=16271339"&gt;modify the behavior&lt;/a&gt; of its host mice, influencing them in ways which make it more likely they will be eaten by a cat. The microbe reproduces in the intestines of felines. The chemicals it produces to effect this appear to also have an impact in other mammals, including humans. As cats do not normally eat humans, effects on humans are just an accident.&lt;/p&gt;

&lt;p&gt;Natural selection will eventually produce a toxoplasmosis microbe which forces humans to take felines into their homes and care for them, producing a much larger population of suitable environments for their reproduction. When this happens, when large numbers of humans willingly share their homes with cats, then we will know that the microbes have taken over.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5618859477501094874?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/WBtfsD1dunY" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=5618859477501094874" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5618859477501094874?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5618859477501094874?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/06/toxoplasmowhosit.html" title="Toxoplasmowhosit?" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_WibILqsOlLg/TB9rkKGdNrI/AAAAAAAAAuU/PTD_ZHh1xTw/s72-c/toxoplasmosis.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;DkINRH09eip7ImA9WxFUE0U.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-3248510942063764202</id><published>2010-06-24T06:01:00.000-07:00</published><updated>2010-06-24T06:03:15.362-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-24T06:03:15.362-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C Programming" /><title>Virtual Trouble</title><content type="html">&lt;p&gt;After many years of working in plain C, I'm back to writing C++. I feel like an unfrozen caveman, confused by the flashing lights of the big city. Here is something I ran into recently.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: small; line-height: 1.2em; margin-left: 4em;"&gt;
#include &amp;lt;stdio.h&amp;gt;

class BaseClass {
 public:
  BaseClass() { InitName(); }
  virtual void InitName() { name_ = "BaseClass"; }
  char *name_;
};

class SubClass : public BaseClass {
 public:
  virtual void InitName() { name_ = "SubClass"; }
};

int main(int argc, char** argv) {
  BaseClass base;
  SubClass sub;

  printf("BaseClass name_ = %s\n", base.name_);
  printf("SubClass  name_ = %s\n", sub.name_);
}
&lt;/pre&gt;

&lt;p&gt;A base class provides a virtual InitName() method, and calls it from the constructor. A subclass overrides InitName(), yet the overridden method is not called during  construction. The BaseClass InitName() is used instead.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: small; line-height: 1.2em; margin-left: 4em;"&gt;
$ ./a.out
BaseClass name_ = BaseClass
SubClass  name_ = BaseClass
&lt;/pre&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 115%; font-weight: bold;"&gt;A Maze of Twisty Little Passages&lt;/span&gt;
&lt;p&gt;Objects are constructed from the most basic class first. When the BaseClass() constructor runs, the SubClass methods and member variables have not yet been initialized. The object &lt;i&gt;is&lt;/i&gt; a BaseClass object at that point. When BaseClass::BaseClass() returns, the object will be remarked as a SubClass object, and only then will its overridden methods actually do anything. Destructors work similarly. The outermost derived class is destroyed first, and by the time BaseClass::~BaseClass() runs the object will be of BaseClass type. Any virtual methods called from ~BaseClass() will call the BaseClass definition.&lt;/p&gt;

&lt;p&gt;Scott Meyers' &lt;a  href="http://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876?ie=UTF8&amp;tag=codin-20&amp;link_code=btl&amp;camp=213689&amp;creative=392969"&gt;Effective C++, 3rd Edition&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=codin-20&amp;l=btl&amp;camp=213689&amp;creative=392969&amp;o=1&amp;a=0321334876" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important; padding: 0px !important" /&gt; (*) devotes a chapter to this topic, with considerably more detail. That chapter happens to be available online &lt;a href="http://www.artima.com/cppsource/nevercall.html"&gt;in an excerpt&lt;/a&gt; by the publisher.&lt;/p&gt;

&lt;p&gt;For my specific issue, my object already had an Init() method to be called after object construction. It was straightforward to move the functionality from the constructor to Init(), with some checks to make it do something sensible if the caller neglects to call Init().&lt;/p&gt;

&lt;p style="color: #888;"&gt;(*) - affiliate link&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-3248510942063764202?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/Ed8WGvb29a0" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=3248510942063764202" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3248510942063764202?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3248510942063764202?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/06/virtual-trouble.html" title="Virtual Trouble" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0UCQX07eip7ImA9WxFUEU8.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-4064776442186466052</id><published>2010-06-21T06:01:00.000-07:00</published><updated>2010-06-21T06:01:00.302-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-21T06:01:00.302-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Stackoverflow Maintenance Page</title><content type="html">&lt;p&gt;I love how the &lt;a href="http://stackoverflow.com"&gt;stackoverflow.com&lt;/a&gt; maintenance page show a binary dump of a Windows process where the stack overflow error is defined. Clever.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" width="555" height="755" src="http://4.bp.blogspot.com/_WibILqsOlLg/TAua1ctBvaI/AAAAAAAAAuE/KgEzww9fdA8/s1600/stackoverflowdown.png" style="border: solid black 1px; margin: 0px;" alt="Stackoverflow is down for maintenance." /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-4064776442186466052?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/MMQeGZ5KLkY" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=4064776442186466052" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4064776442186466052?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4064776442186466052?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/06/stackoverflow-maintenance-page.html" title="Stackoverflow Maintenance Page" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_WibILqsOlLg/TAua1ctBvaI/AAAAAAAAAuE/KgEzww9fdA8/s72-c/stackoverflowdown.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0EBRH07eip7ImA9WxFbGEg.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-6337087111399633386</id><published>2010-06-17T06:01:00.000-07:00</published><updated>2010-07-11T06:40:55.302-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-11T06:40:55.302-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="astrostuff" /><title>A Moon of Endor</title><content type="html">&lt;p&gt;At the time of this writing 455 planets outside of Earth's own solar system have been discovered. Nearly all are gas giants like Jupiter and Saturn, and even the smallest are several times the mass of Earth. This doesn't mean smaller planets are uncommon, it means our current techniques using optical occlusion and gravitational deflection are far better at detecting massive planets.&lt;/p&gt;

&lt;p&gt;When I read reports on these discoveries they have already been &amp;quot;dumbed down&amp;quot; for a  mainstream audience. Invariably the lack of Earth-like planets is mentioned, followed by a reference to extraterrestrial life on those Earth-like planets. Yet I suspect that if we're really interested in finding planets where life is likely to have evolved, gas giants are what we should be looking for.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://commons.wikimedia.org/wiki/File:Mars_Hubble.jpg"&gt;&lt;img border="0" width="250" height="250" align="right" src="http://2.bp.blogspot.com/_WibILqsOlLg/TBI1oUcIc0I/AAAAAAAAAuI/x5U6fkzgKr4/s320/mars.jpg" style="border: none; margin: 1px;" alt="Mars as seen by the Hubble space telescope." /&gt;&lt;/a&gt;In our own solar system there are three &amp;quot;Earth like&amp;quot; planets: Venus, Earth, and Mars. Of the three, only Earth is tectonically active with a strong magnetic field. Tectonics and vulcanism leads to temperature variation in the environment, which on Earth appears to spur evolution. A strong magnetic field protects the planet's surface from solar flares.&lt;/p&gt;

&lt;p&gt;Something about Earth is different, resulting in it having a highly dynamic molten core where Mars and Venus are far more settled. One possibility is the Moon: Earth has a relatively enormous moon compared to Mars. The force of lunar gravity exerts considerable strain on the planet, and perhaps that keeps the inner dynamo from settling. Another possibility is related to the formation of the moon: if indeed it formed due to a massive asteroid strike on the Earth ejecting a huge volume of material into space, then perhaps the planet simply hasn't settled down yet.&lt;/p&gt;

&lt;p&gt;The moons of a gas giant have some of the same properties as Earth. The massive gravity of their neighbor exerts considerable  force, making a dynamic molten core more likely. If their orbit is close enough they also sit inside their host's magnetic field, protecting them from solar wind and flares. There is a considerable amount of radiation near a gas giant, but its a constant level which becomes part of the environment. On Earth life seems able to evolve in &lt;a href="http://www.technologyreview.com/blog/arxiv/25051/"&gt;extremely harsh environments&lt;/a&gt;, so perhaps life can evolve on a gas giant moon in spite of the radiation. In our own solar system it is possible that &lt;a href="http://www.time.com/time/health/article/0,8599,1995828,00.html?xid=rss-topstories"&gt;life exists on Titan,&lt;/a&gt; which would be incredibly exciting.&lt;/p&gt;

&lt;p&gt;Advancements in our ability to detect Earth-like exoplanets is interesting, but to me it will be far more interesting when we can detect moons orbiting gas giants.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-6337087111399633386?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/6PBswJIhj_E" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=6337087111399633386" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6337087111399633386?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6337087111399633386?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/06/moon-of-endor.html" title="A Moon of Endor" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_WibILqsOlLg/TBI1oUcIc0I/AAAAAAAAAuI/x5U6fkzgKr4/s72-c/mars.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;CkMCQX87fip7ImA9WxFVFU8.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-8272762069456474330</id><published>2010-06-14T06:01:00.000-07:00</published><updated>2010-06-14T06:01:00.106-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-14T06:01:00.106-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Expect the Unexpected Error</title><content type="html">&lt;center&gt;&lt;img border="0" width="536" height="217" src="http://1.bp.blogspot.com/_WibILqsOlLg/S5TWoseYN0I/AAAAAAAAAqE/8wHmpssO9f0/s640/sonos.png" style="border: solid black 1px; margin: 0px;" alt="Sonos.com Unexpected error occurred." /&gt;&lt;/center&gt;

&lt;br/&gt;
&lt;p&gt;Well, sure. If were it an expected error you would have done something more useful.&lt;/p&gt;
&lt;br/&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-8272762069456474330?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/HxO0zAJJNcc" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=8272762069456474330" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8272762069456474330?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8272762069456474330?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/06/expect-unexpected-error.html" title="Expect the Unexpected Error" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_WibILqsOlLg/S5TWoseYN0I/AAAAAAAAAqE/8wHmpssO9f0/s72-c/sonos.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;AkMCQX4-fCp7ImA9WxFVEEU.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-1368833688419446803</id><published>2010-06-09T06:01:00.000-07:00</published><updated>2010-06-09T06:01:00.054-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-09T06:01:00.054-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="embedded" /><title>4k Sectors Approacheth</title><content type="html">&lt;p&gt;&lt;a href="http://www.flickr.com/photos/kubina/326629230/"&gt;&lt;img border="0" height="75" width="75" align="right" alt="hard drive magnetic head" title="Photo by Jeff Kubina, licensed under Creative Commons" style="padding:3px; border:0px;" src="http://3.bp.blogspot.com/_WibILqsOlLg/TAPM66rubMI/AAAAAAAAAtw/gE41tS87pE4/s160/drivehead.jpg" /&gt;&lt;/a&gt;Its amazing that hard drives work at all. A tiny little drive head flies just above a metallic tundra, manipulating miniscule dots of magnetism flying by at high speed. The dots have gotten small enough that advances in materials science are required to reliably detect the field.&lt;/p&gt;

&lt;p&gt;As an industry, drive manufacturers have done a remarkable job in advancing the technology without breaking compatibility. For example when drives added &lt;a href="http://www.48bitlba.com/"&gt;LBA48&lt;/a&gt; to support larger than 128 Gigabytes, the older LBA28 commands were retained without modification. New drives could be put into existing LBA28 controllers without trouble in the common cases. No more than 128 GB would be used, but older controllers did not stop working the instant LBA48 came out. It allowed an orderly transition to newer designs.&lt;/p&gt;

&lt;p&gt;We're on the verge of the next big transition: 4k sectors. For 30 years hard disk drives have used a 512 byte sector. I'm not sure of the original motivation for that specific size, though I suspect the VAX page size of 512 bytes was a factor. The drive industry begin preparing for a transition to 4 Kilobyte pages nearly ten years ago, and the first products are now on the market.&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 115%; font-weight: bold;"&gt;Anatomy of a Disk Sector&lt;/span&gt;
&lt;p&gt;&lt;img border="0" height="46" width="369" align="right" style="padding:3px; border:0px;" src="http://3.bp.blogspot.com/_WibILqsOlLg/TAPNH2f6_4I/AAAAAAAAAt0/8L7z1j6vmQU/s640/sector.png" /&gt;Disks with 512b sectors currently allocate about 40 bytes of additional space for ECC. Thus the error correction occupies ~8% of the raw capacity of the disk. The density of bits on the platter continues to increase, while imperfections in the drive media tend to remain the same size. As more bits are packed into the same area a media flaw will affect a larger span, and require more ECC to recover. If drives stick with 512 sectors, one can see the day coming when ECC will consume unacceptable fractions of the disk: 20%, 30%, etc. Therefore the drive industry is moving to 4 kilobyte sectors, which amortize the ECC across larger swaths of data. Where a 512 byte sector  uses 40 bytes of ECC, a 4096 byte sector requires about 100 bytes. Eight times more data is covered with only 2.5x more ECC.&lt;/p&gt;

&lt;p&gt;There are several other sources of overhead for each sector, including a synchronization region at the beginning (to prepare the read head to deserialize the data) and a gap between sectors. I do not know the size of these, but they should remain the same even as they amortize over 8x more data. These are a smaller win, but worth mentioning.&lt;/p&gt;

&lt;p&gt;As with previous technology transitions the drive will continue to accept the older commands for 512 byte sector accesses, transparently performing a read-modify-write to the enclosing 4096 byte sector. The first time such a sector is accessed will be relatively expensive: the drive head cannot read and write simultaneously, it must first read in the full 4096 bytes and then allow a complete rotation of the platter before it can write the modification back. All modern drives contain 32 or 64 MBytes of cache, subsequent sub-sector writes can merge from cache to write directly to the platter.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" height="94" width="435" style="padding:3px; border:0px;" src="http://3.bp.blogspot.com/_WibILqsOlLg/TAPNQqAfApI/AAAAAAAAAt4/DA-2rTY1I2Q/s640/subsectors.png" /&gt;&lt;/center&gt;

&lt;p&gt;Most processor architectures and OS implementations use a page size of 4K or larger, and almost always write full pages to disk. No read+modify is needed if the entire 4K sector is being written. There is a caveat to this happy outcome: the OS page needs to start at the 4K sector boundary, which really means the disk partition needs to start at a 4K aligned boundary. If it doesn't, then even 4k writes will still turn into read-modify-write cycles.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" height="94" width="435" style="padding:3px; border:0px;" src="http://3.bp.blogspot.com/_WibILqsOlLg/TAPNYesxW6I/AAAAAAAAAt8/LbIqSO3-1cw/s640/offbyone.png" /&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="http://www.anandtech.com/show/2888/2"&gt;According to Western Digital&lt;/a&gt;, Windows versions starting with Vista and all recent versions of MacOS X and Linux align their partitions to a multiple of 4K Bytes. Windows XP and earlier generally did not: the Master Boot Record ended at sector 63, and all subsequent partitions would be laid out one sector off from 4K alignment. If a subsequent partition was itself not a multiple of 4K, it would throw off the alignment of the partitions which follow it.&lt;/p&gt;

&lt;p&gt;Embedded systems should also be on the list of potential problem areas for the 4k sector size: DVRs, security camera monitoring systems, various consumer electronics, etc. Its quite common to design a product, use existing tools like fdisk.exe to create a &amp;quot;golden software image,&amp;quot; and bit-copy that image to the hard drive. If the fdisk of the day did not align its partitions, then the image won't have them aligned. Periodically as components are discontinued new substitutes have to be qualified. Qualification of new commodity components is often left to the contract manufacturer, the engineering team may not be involved at all. As hard drive models come and go relatively frequently, a design will see several different drive models through its production lifetime.&lt;/p&gt;

&lt;p&gt;In this particular case, its worthwhile for the engineering team to be proactive and not leave it up to the CM. A 4K sector drive will &lt;i&gt;work:&lt;/i&gt; the software will boot and operate. Only the performance is impacted. Its quite conceivable for the CM to finish a change order for a new drive and ship a significant amount of product before the performance issues are noticed, if the problem is subtle.&lt;/p&gt;

&lt;p&gt;WD has two solutions if unaligned writes are a problem:&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;A jumper on the drive can add one to all 512B sector numbers.&lt;/li&gt;
 &lt;li&gt;WDAlign.exe can re-image an existing installation to align the partitions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your existing product happens to have its partitions all off by one sector, presumably because an older Windows fdisk.exe was used to create it, the jumper is a potential solution. There is no telling how long drive manufacturers will keep the jumper in their products, of course. If the existing golden image has misaligned partitions, its time to start working on a new image. This should be a matter of changing the partition table without having to touch the binaries. A QA cycle would be needed, checking for regression.&lt;/p&gt;

&lt;p&gt;If the partitions are misaligned, the product accesses the raw disk devices, and it avoids using a partition table to &amp;quot;improve performance&amp;quot; or some other reason... you're screwed. Start a project to update the design, and don't hard-code sector numbers next time. Native 512b drives will be available for a while, which may provide enough time to re-engineer.&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 115%; font-weight: bold;"&gt;Random Postscript&lt;/span&gt;
&lt;p&gt;This kind of change in block size has happened once before, by my recollection. Many very early CD-ROM drives used a 512 byte sector size, matching that of hard drives. Sometime in the early 1990s CD drives changed to a 2048 byte sector, which they still use today. A number of drives had jumpers to switch between the two sizes, and I recall Sun workstations of the time being unable to boot from a 2048 byte sector.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-1368833688419446803?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/0MDZ9yrdv-w" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=1368833688419446803" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1368833688419446803?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1368833688419446803?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/06/4k-sectors-approacheth.html" title="4k Sectors Approacheth" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_WibILqsOlLg/TAPM66rubMI/AAAAAAAAAtw/gE41tS87pE4/s72-c/drivehead.jpg" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;D0ECQXk_fCp7ImA9WxFWGUw.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-2874458580888546390</id><published>2010-06-07T06:01:00.000-07:00</published><updated>2010-06-07T06:01:00.744-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-07T06:01:00.744-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>We Still Have Unlimited SMS</title><content type="html">&lt;p&gt;AT&amp;amp;T recently &lt;a href="http://gizmodo.com/5553135/att-iphone-tethering-an-extra-20month"&gt;announced&lt;/a&gt; changes to their data plans, eliminating the unlimited data plans and replacing them with tiered plans offering up to 2GB of data per month. Yet AT&amp;amp;T still offers &lt;a href="http://www.wireless.att.com/cell-phone-service/services/serviceDetails.jsp?skuId=sku1160055"&gt;unlimited messaging,&lt;/a&gt; including SMS and MMS. Thus, there is a mechanism to game the system.&lt;/p&gt;

&lt;br/&gt;
&lt;span style="font-size: 115%; font-weight: bold;"&gt;IP via SMS&lt;/span&gt;
&lt;p&gt;SMS relies on the &lt;a href="http://www.csoft.co.uk/sms/character_sets/gsm.htm"&gt;GSM 03.38 character set&lt;/a&gt;, which is 7 bits but using an escape code for additional characters. UTF-16 is used for non-Latin alphabets, and an 8 bit clean data alphabet is also supported (but not required).&lt;/p&gt;

&lt;p&gt;For widest support we should rely on GSM 03.38, the only character encoding which handsets are required to implement. TCP/IP packets can be encoded into at most 160 characters of 7 bits each, for a total of 1120 bits or 140 bytes. An &amp;lt;ESC&amp;gt; can be followed by only a few valid characters, so an &amp;lt;ESC&amp;gt; followed by any arbitrary character might be rejected at some point through the delivery path. An HDLC character-stuffing technique can be used to eliminate &amp;lt;ESC&amp;gt; from the data stream, details to be worked out later.&lt;/p&gt;

&lt;p&gt;SMS does define a &lt;a href="http://en.wikipedia.org/wiki/Concatenated_SMS"&gt;concatenated  option&lt;/a&gt; to support longer messages, but it occupies 7 characters in the payload. As a compressed IP header would be smaller than 7 characters, it is recommended that SMS concatenation not be used. A 140 byte packet MTU will pack more efficiently than a larger MTU plus concatenation overheads.&lt;/p&gt;

&lt;p&gt;With such a small MTU, header compression is a must. &lt;a href="http://tools.ietf.org/html/rfc5225"&gt;Robust Header Compression&lt;/a&gt; defines profiles for &lt;a href="http://tools.ietf.org/html/rfc4996"&gt;TCP+IP&lt;/a&gt;, UDP+IP, and RTP+UDP+IP compression, which can reduce the typical header stack down to about 3 bytes. For deployment use we'll need to define a new ROHC profile for IP Fragments, an RFC will be drafted later.&lt;/p&gt;


&lt;br/&gt;
&lt;span style="font-size: 115%; font-weight: bold;"&gt;IP via MMS&lt;/span&gt;
&lt;img border="0" height="188" width="188" align="right" alt="QR code" title="No, its not really a packet in there..." style="padding:3px; border:0px;" src="http://3.bp.blogspot.com/_WibILqsOlLg/TAuZxa6VnEI/AAAAAAAAAuA/qqqAcTO380M/s320/IPPacketQR.png" /&gt;
&lt;p&gt;MMS can be used to send small pictures and movies. Initially this seemed very promising: wrap the IP packet inside a JPG header and send it. Unfortunately to save cost, most mobile operators re-sample and re-encode any images sent via MMS to reduce their size. Straight data inside an image payload would be destroyed.&lt;/p&gt;

&lt;p&gt;Instead the IP packet should be encoded as an image of a &lt;a href="http://en.wikipedia.org/wiki/QR_Code"&gt;QR code&lt;/a&gt;, which can be  robustly decoded even if the image is resampled. QR Code also includes error correction, helpful in this application.&lt;/p&gt;

&lt;p&gt;QR Code can handle over 2 KBytes of data in a single barcode, easily enough to handle the maximum 1.5K ethernet frame size. ROHC header compression is not required.&lt;/p&gt;


&lt;br/&gt;
&lt;span style="font-size: 115%; font-weight: bold;"&gt;Closing Notes&lt;/span&gt;
&lt;p&gt;Yes, this is a joke. Material posted on Mondays is not intended to be taken seriously. After all, nothing productive happens on &lt;i&gt;Monday.&lt;/i&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-2874458580888546390?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/qigbe1GeIQc" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=2874458580888546390" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2874458580888546390?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2874458580888546390?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/06/we-still-have-unlimited-sms.html" title="We Still Have Unlimited SMS" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_WibILqsOlLg/TAuZxa6VnEI/AAAAAAAAAuA/qqqAcTO380M/s72-c/IPPacketQR.png" height="72" width="72" /><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0QER3w9fip7ImA9WxFXFEk.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-751425434861964365</id><published>2010-05-21T04:28:00.000-07:00</published><updated>2010-05-21T04:28:26.266-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-21T04:28:26.266-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Administrivia" /><title>Hiatus</title><content type="html">&lt;p&gt;For the next month or so expect postings here to be infrequent. I'm more likely to post short snippets on &lt;a href="http://twitter.com/dgentry"&gt;Twitter&lt;/a&gt; or &lt;a href="http://www.google.com/profiles/denton.gentry"&gt;Google Buzz&lt;/a&gt; during this time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-751425434861964365?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/k077MOtFP6Y" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=751425434861964365" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/751425434861964365?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/751425434861964365?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/05/hiatus.html" title="Hiatus" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><thr:total>0</thr:total></entry><entry gd:etag="W/&quot;C0UCQXw-eSp7ImA9WxFXEU0.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-4079403516227081918</id><published>2010-05-17T06:01:00.000-07:00</published><updated>2010-05-17T06:01:00.251-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-17T06:01:00.251-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>/dev/tty</title><content type="html">&lt;table style="padding: 4px; border-collapse: collapse; width: 99%; margin-bottom: 1em;" columns="3" cellspacing="0"&gt;&lt;tr&gt;

&lt;td style="text-align=left; font-size: 40px; font-family: monospace; font-weight: bold;" width="40%"&gt;/dev/tty&lt;/td&gt;

&lt;td style="text-align=center; font-size: 32px;" width="20%"&gt;==&lt;/td&gt;

&lt;td style="text-align=right;" width="40%"&gt;&lt;div xmlns:cc="http://creativecommons.org/ns#" about="http://www.flickr.com/photos/dancentury/3916969051/"&gt;&lt;a rel="cc:attributionURL" href="http://www.flickr.com/photos/dancentury/3916969051/"&gt;&lt;img border="0" width="300" height="225" src="http://4.bp.blogspot.com/_WibILqsOlLg/S7CWokuz5FI/AAAAAAAAArE/k53SB_G9-Ag/s640/teletype.jpg" style="border: 0px;" alt="TTC TeleType machine" title="Note the paper tape punch machine." /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;

&lt;tr style="margin-top: 3em; margin-bottom: 1em;"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Any questions?&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-4079403516227081918?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/d_zxxXW1tWg" height="1" width="1"/&gt;</content><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=9151880169490356401&amp;postID=4079403516227081918" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4079403516227081918?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4079403516227081918?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2010/05/devtty.html" title="/dev/tty" /><author><name>Denton Gentry</name><uri>http://www.blogger.com/profile/11782508603268183191</uri><email>denny@geekhold.com</email><gd:extendedProperty name="OpenSocialUserId" value="05410638791985846968" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_WibILqsOlLg/S7CWokuz5FI/AAAAAAAAArE/k53SB_G9-Ag/s72-c/teletype.jpg" height="72" width="72" /><thr:total>0</thr:total></entry></feed>
