<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alex on Linux&#187; Blog</title>
	<atom:link href="http://www.alexonlinux.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.alexonlinux.com</link>
	<description></description>
	<lastBuildDate>Tue, 02 Mar 2010 11:51:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>I got a new job, take 3</title>
		<link>http://www.alexonlinux.com/i-got-a-new-job-take-3</link>
		<comments>http://www.alexonlinux.com/i-got-a-new-job-take-3#comments</comments>
		<pubDate>Tue, 02 Mar 2010 11:51:36 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1740</guid>
		<description><![CDATA[I got a new job, again. Dell decided to obtain what have left of Exanet LTD, a company I worked for in the past. They kindly decided to offer a job to majority of ex-Exanet engineers, me included.
So, I decided to leave Fabrix and as of last week I am software engineer and senior consultant [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/resume' rel='bookmark' title='Permanent Link: Resume'>Resume</a></li>
<li><a href='http://www.alexonlinux.com/i-am-looking-for-a-new-job' rel='bookmark' title='Permanent Link: I am looking for a new job'>I am looking for a new job</a></li>
<li><a href='http://www.alexonlinux.com/what-it-takes-to-be-a-qa-engineer' rel='bookmark' title='Permanent Link: What it takes to be a QA engineer'>What it takes to be a QA engineer</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I got a new job, again. Dell decided to obtain what have left of Exanet LTD, <a href="i-got-a-new-job">a company I worked for in the past</a>. They kindly decided to offer a job to majority of ex-Exanet engineers, me included.</p>
<p>So, I decided to leave Fabrix and as of last week I am software engineer and senior consultant at Dell IDC (Israel Developer Center).</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/resume' rel='bookmark' title='Permanent Link: Resume'>Resume</a></li>
<li><a href='http://www.alexonlinux.com/i-am-looking-for-a-new-job' rel='bookmark' title='Permanent Link: I am looking for a new job'>I am looking for a new job</a></li>
<li><a href='http://www.alexonlinux.com/what-it-takes-to-be-a-qa-engineer' rel='bookmark' title='Permanent Link: What it takes to be a QA engineer'>What it takes to be a QA engineer</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/i-got-a-new-job-take-3/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>What&#8217;s is direct I/O anyway?</title>
		<link>http://www.alexonlinux.com/whats-is-direct-io-anyway</link>
		<comments>http://www.alexonlinux.com/whats-is-direct-io-anyway#comments</comments>
		<pubDate>Mon, 15 Feb 2010 10:03:57 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[direct]]></category>
		<category><![CDATA[direct I/O]]></category>
		<category><![CDATA[io]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[page cache]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1713</guid>
		<description><![CDATA[Few days ago I&#8217;ve written a post explaining how to do a direct I/O in Python. But then I thought that it might be a good idea to explain what direct I/O is. So, here we go.
As surprising as it is, when you write some information to the disk, it doesn&#8217;t get there immediately. In [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/swap-vs-no-swap' rel='bookmark' title='Permanent Link: Swap vs. no swap'>Swap vs. no swap</a></li>
<li><a href='http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux' rel='bookmark' title='Permanent Link: SMP affinity and proper interrupt handling in Linux'>SMP affinity and proper interrupt handling in Linux</a></li>
<li><a href='http://www.alexonlinux.com/aligned-vs-unaligned-memory-access' rel='bookmark' title='Permanent Link: Aligned vs. unaligned memory access'>Aligned vs. unaligned memory access</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Few days ago I&#8217;ve written <a href="http://www.alexonlinux.com/direct-io-in-python" onclick="return TrackClick('http%3A%2F%2Fwww.alexonlinux.com%2Fdirect-io-in-python','a+post+explaining+how+to+do+a+direct+I%2FO+in+Python')">a post explaining how to do a direct I/O in Python</a>. But then I thought that it might be a good idea to explain what direct I/O is. So, here we go.</p>
<p>As surprising as it is, when you write some information to the disk, it doesn&#8217;t get there immediately. In Linux especially, the kernel tries to cache write requests in memory as much as it can. This means that in addition to writing the data to the disk, kernel keeps it in memory. Consecutive read request to the same place on the disk will be much faster because there&#8217;s no need to read the information from slow disk &#8211; it is already in memory. On the other hand, the information goes to the hard-disk only after some period of time (short though) or when the system runs out of memory. In the meantime, Linux reports that data has been written, despite it is not yet on the disk.<span id="more-1713"></span></p>
<p>This causes several interesting phenomena that you may have noticed. For example Linux machines with little memory, even though not all memory is in use, do use disk much more than machines with more memory. There are several reasons for it. One of them is because kernel doesn&#8217;t have enough memory to cache information from the disks and as a result read requests rarely hit the cache and more often go to the disk.</p>
<blockquote><p>Want to see exactly how Linux reports successful write requests before data actually lands on the disk? Try writing some information to floppy disk and see how fast it is in Linux. The truth is that it&#8217;s still frustratingly slow. Linux just makes it look like a fast device.</p></blockquote>
<p>Sheer thought that Linux doesn&#8217;t write the data to the disk, despite it says it did, may be pretty scary. But it shouldn&#8217;t really. First of all, if its not very busy it does write the data to the disk as soon as possible. Second, Linux does excellent job avoiding various problems and even if something bad happens, it is pretty good at recovering lost data. The way Linux works is excellent for 99% of users. This approach improves performance in various ways and makes the system more healthy and stable.</p>
<p>However, some folks out there are not happy with this situation. Some software systems cannot work the way Linux works. One of the examples are so called clustered file-systems &#8211; file-systems that are spread among multiple servers for redundancy purposes. Such systems need a way to know that data has been written to the disk for real, not just being cached. Also, such systems want to make sure that reads hit disk and not OS cache.</p>
<p>This is where direct I/O becomes handy. Direct I/O is a way to avoid entire caching layer in the kernel and send the I/O directly to the disk. Overall, this makes I/O slower and does not let Linux do various optimizations that it usually does. Also, it introduces some constraints on memory buffer that being used for the I/O. Yet sometimes it is inevitable.</p>
<p>Want to try it yourself? <em>dd</em>, I/O Swiss army knife, has an option called <em>direct</em>. It tells <em>dd</em> to do direct I/O instead of regular I/O. Another option for doing direct I/O is writing your own program that opens files with O_DIRECT flag (see <em>open</em>(2) for details).</p>
<p><em>Update Feb. 12: Thanks to Ivan for noting the difference between synchronous I/O and direct I/O. I updated the post to reflect the difference.<br />
</em></p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/swap-vs-no-swap' rel='bookmark' title='Permanent Link: Swap vs. no swap'>Swap vs. no swap</a></li>
<li><a href='http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux' rel='bookmark' title='Permanent Link: SMP affinity and proper interrupt handling in Linux'>SMP affinity and proper interrupt handling in Linux</a></li>
<li><a href='http://www.alexonlinux.com/aligned-vs-unaligned-memory-access' rel='bookmark' title='Permanent Link: Aligned vs. unaligned memory access'>Aligned vs. unaligned memory access</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/whats-is-direct-io-anyway/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Recursively deleting symbolic link and what it points to</title>
		<link>http://www.alexonlinux.com/recursively-deleting-symbolic-link-and-what-it-points-to</link>
		<comments>http://www.alexonlinux.com/recursively-deleting-symbolic-link-and-what-it-points-to#comments</comments>
		<pubDate>Mon, 01 Feb 2010 08:52:59 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Code library]]></category>
		<category><![CDATA[Programming Articles]]></category>
		<category><![CDATA[Short articles]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1703</guid>
		<description><![CDATA[Recently I looked for a solution to this little problem. how do you, programmatically, delete a symbolic link and a file that it points to?
One problem that you should take care of when tackling this problem, is that symbolic link can point to a symbolic link. Then symbolic link should also point to symbolic link. [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/hex-dump-functions' rel='bookmark' title='Permanent Link: Hex dump functions'>Hex dump functions</a></li>
<li><a href='http://www.alexonlinux.com/direct-io-in-python' rel='bookmark' title='Permanent Link: Direct IO in Python'>Direct IO in Python</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Recently I looked for a solution to this little problem. how do you, programmatically, delete a symbolic link and a file that it points to?</p>
<p>One problem that you should take care of when tackling this problem, is that symbolic link can point to a symbolic link. Then symbolic link should also point to symbolic link. And once again, and again and again&#8230;</p>
<p><span id="more-1703"></span>So what can we do about it? First, lets start with <em>lstat</em>() system all. It will tell us is the file we&#8217;re interested in, is actually a symbolic link. To be more precise, <em>st_mode</em> field in <em>struct stat</em> will have flag S_IFLNK if specified file is a symbolic link. Note that it should be <em>lstat</em>() and not <em>stat</em>() &#8211; the later will return information about file the link points to and not about the link.</p>
<p>Next step is to call <em>readlink</em>(). This system call returns name of the file pointed to by specified symbolic link.</p>
<p>Finally, you should repeat the process recursively, for the pointed to file. Here is the code that does it:</p>
<pre class="brush:cpp">int recursive_deleter(const char* filename)
{
  struct stat st;
  char buffer[1024];

  if (lstat(filename, &amp;st)) {
    perror("stat");
    return -1;
  }     

  if (st.st_mode &amp; S_IFLNK == S_IFLNK) {
    memset(buffer, 0, sizeof(buffer));
    if (readlink(filename, buffer, sizeof(buffer)) &lt; 0) {
      perror("readlink");
      return -1;
    }           

    printf("File %s is a symbolic link to %s\n", filename, buffer);

    if (recursive_deleter(buffer))
      return 0;
  }     

  printf("Deleting %s\n", filename);

  if (unlink(filename)) {
    perror("unlink");
    return -1;
  }     

  return 0;
}
</pre>
<p>Have fun!</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/hex-dump-functions' rel='bookmark' title='Permanent Link: Hex dump functions'>Hex dump functions</a></li>
<li><a href='http://www.alexonlinux.com/direct-io-in-python' rel='bookmark' title='Permanent Link: Direct IO in Python'>Direct IO in Python</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/recursively-deleting-symbolic-link-and-what-it-points-to/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Direct IO in Python</title>
		<link>http://www.alexonlinux.com/direct-io-in-python</link>
		<comments>http://www.alexonlinux.com/direct-io-in-python#comments</comments>
		<pubDate>Tue, 12 Jan 2010 07:50:06 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Programming Articles]]></category>
		<category><![CDATA[Short articles]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1684</guid>
		<description><![CDATA[Doing file I/O of any kind in Python is really easy. You can start with plain open() and friends, working with Python&#8217;s file objects. by the way, Python&#8217;s open() resembles C&#8217;s fopen() so closely that I can&#8217;t stop thinking that open() may be based on fopen().
When its not enough, you can always upgrade to open() [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/whats-is-direct-io-anyway' rel='bookmark' title='Permanent Link: What&#8217;s is direct I/O anyway?'>What&#8217;s is direct I/O anyway?</a></li>
<li><a href='http://www.alexonlinux.com/recursively-deleting-symbolic-link-and-what-it-points-to' rel='bookmark' title='Permanent Link: Recursively deleting symbolic link and what it points to'>Recursively deleting symbolic link and what it points to</a></li>
<li><a href='http://www.alexonlinux.com/how-to-send-sms-message-with-python' rel='bookmark' title='Permanent Link: How to send SMS message with Python'>How to send SMS message with Python</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Doing file I/O of any kind in Python is really easy. You can start with plain <em>open()</em> and friends, working with Python&#8217;s file objects. by the way, Python&#8217;s <em>open()</em> resembles <em>C</em>&#8217;s <em>fopen()</em> so closely that I can&#8217;t stop thinking that <em>open()</em> may be based on <em>fopen()</em>.</p>
<p>When its not enough, you can always upgrade to <em>open()</em> and <em>close()</em> from <em>os</em> module. Opening man page on <em>open()</em> (the system call &#8211; open(2)) reveals all those O_something options that you can pass to <em>os.open()</em>. But not all of them can be used in Python. For example, if you open a file with <em>O_DIRECT</em> and then try to write to it, you will end up with some strange error message.</p>
<p><span id="more-1684"></span></p>
<pre class="brush:py">&gt;&gt;&gt; import os
&gt;&gt;&gt; f = os.open('file', os.O_CREAT | os.O_TRUNC | os.O_DIRECT | os.O_RDWR)
&gt;&gt;&gt; s = ' ' * 1024
&gt;&gt;&gt; os.write(f, s)
Traceback (most recent call last):
  File "", line 1, in
OSError: [Errno 22] Invalid argument
&gt;&gt;&gt;
</pre>
<p>Invalid argument?. What invalid argument? Hey there&#8217;s nothing wrong with those arguments&#8230;</p>
<p>Reading open(2) man page further reveals that working with <em>O_DIRECT</em> requires that all buffers used for I/O should be aligned to 512 byte boundary. But how can you have a memory buffer aligned to 512 bytes in Python?</p>
<p>Apparently, there&#8217;s a way. Python comes with a module called <em>mmap</em>. <em>mmap()</em> is a system call that allows one to map portion of file into memory. All writes to memory mapped file, go directly to file despite it looks like you&#8217;re working with plain memory buffer. Same with reads.</p>
<p>There&#8217;s one interesting thing about<em> mmap</em>. It works with granularity of one memory page &#8211; 4kb that is. So every memory mapped buffer is naturally memory aligned to 4kb, thus to 512 byte boundary too. But hey, shouldn&#8217;t <em>mmap</em> map files?</p>
<p>Well, apparently <em>mmap</em> can be used for memory allocations. I.e. specifying -1 as file descriptor does just that &#8211; allocates RAM, as much as you tell it. So, this is what we do:</p>
<pre class="brush:py">&gt;&gt;&gt; import os
&gt;&gt;&gt; import mmap
&gt;&gt;&gt;
&gt;&gt;&gt; f = os.open('file', os.O_CREAT | os.O_DIRECT | os.O_TRUNC | os.O_RDWR)
&gt;&gt;&gt; m = mmap.mmap(-1, 1024 * 1024)
&gt;&gt;&gt; s = ' ' * 1024 * 1024
&gt;&gt;&gt;
&gt;&gt;&gt; m.write(s)
&gt;&gt;&gt; os.write(f, m)
1048576
&gt;&gt;&gt; os.close(f)
&gt;&gt;&gt;</pre>
<p>Note that <em>mmap </em>memory buffer object behaves like a file. I.e. you can write into the buffer and read from it &#8211; like I do in line 8. More on it in <a href="http://docs.python.org/library/mmap.html" onclick="return TrackClick('http%3A%2F%2Fdocs.python.org%2Flibrary%2Fmmap.html','official+documentation')">official documentation</a>.</p>
<p>Have fun! <img src='http://www.alexonlinux.com/wp-content/plugins/smilies-themer/modern/smile.gif' alt=':-)' class='wp-smiley' /> </p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/whats-is-direct-io-anyway' rel='bookmark' title='Permanent Link: What&#8217;s is direct I/O anyway?'>What&#8217;s is direct I/O anyway?</a></li>
<li><a href='http://www.alexonlinux.com/recursively-deleting-symbolic-link-and-what-it-points-to' rel='bookmark' title='Permanent Link: Recursively deleting symbolic link and what it points to'>Recursively deleting symbolic link and what it points to</a></li>
<li><a href='http://www.alexonlinux.com/how-to-send-sms-message-with-python' rel='bookmark' title='Permanent Link: How to send SMS message with Python'>How to send SMS message with Python</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/direct-io-in-python/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>I got a new job, take 2</title>
		<link>http://www.alexonlinux.com/i-got-a-new-job-take-2</link>
		<comments>http://www.alexonlinux.com/i-got-a-new-job-take-2#comments</comments>
		<pubDate>Mon, 21 Dec 2009 13:59:54 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1677</guid>
		<description><![CDATA[I got a new job, again  Today I signed a contract with a company named Fabrix.TV. Fabrix is developing a new generation of video content delivery platform.
I am joining as a chief video content consumer senior software engineer.


Related posts:Resume



Related posts:<ol><li><a href='http://www.alexonlinux.com/resume' rel='bookmark' title='Permanent Link: Resume'>Resume</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I got a new job, again <img src='http://www.alexonlinux.com/wp-content/plugins/smilies-themer/modern/smile.gif' alt=':-)' class='wp-smiley' /> Today I signed a contract with a company named <a title="Link to Fabrix.TV" href="http://www.fabrix.tv" onclick="return TrackClick('http%3A%2F%2Fwww.fabrix.tv','Link+to+Fabrix.TV')">Fabrix.TV</a>. Fabrix is developing a new generation of video content delivery platform.</p>
<p>I am joining as a <span style="text-decoration: line-through;">chief video content consumer</span> senior software engineer.</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/resume' rel='bookmark' title='Permanent Link: Resume'>Resume</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/i-got-a-new-job-take-2/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Rethinking linked list insertion</title>
		<link>http://www.alexonlinux.com/rethinking-linked-list-insertion</link>
		<comments>http://www.alexonlinux.com/rethinking-linked-list-insertion#comments</comments>
		<pubDate>Sat, 19 Dec 2009 12:24:36 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code library]]></category>
		<category><![CDATA[Short articles]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1658</guid>
		<description><![CDATA[There is one nice thing in looking for a new job. That is, you meet lots of new people and have a chance to learn from them. For example in one of the companies I was asked about something called anti-debugging. I didn&#8217;t have a clue what that is and had to ask for an [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/pthread-mutex-vs-pthread-spinlock' rel='bookmark' title='Permanent Link: pthread mutex vs pthread spinlock'>pthread mutex vs pthread spinlock</a></li>
<li><a href='http://www.alexonlinux.com/todo-list' rel='bookmark' title='Permanent Link: Todo list'>Todo list</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>There is one nice thing in looking for a new job. That is, you meet lots of new people and have a chance to learn from them. For example in one of the companies I was asked about something called anti-debugging. I didn&#8217;t have a clue what that is and had to ask for an explanation. Apparently, this is a set of techniques used to fool a debugger and make the code undebuggable.</p>
<p>Anyway, here&#8217;s something else that I learned during one of the interviews.</p>
<p><span id="more-1658"></span>I was asked to implement insertion into a linked list in <em>C</em>. Each list node has a number (<em>num</em>). Numbers in the list should be sorted in ascending order &#8211; node with lowest number should be first. Here is my naive implementation.</p>
<pre class="brush:cpp">void list_insert(int num)
{
        list_node_t *n, *tmp, *prev;

        n = allocate_node();
        n-&gt;num = num;

        if (!head) {
                head = n;
                n-&gt;next = NULL;
        } else {
                tmp = head;
                prev = NULL;
                while (tmp) {
                        if (tmp-&gt;num &gt;= n-&gt;num) {
                                if (prev == NULL) {
                                        head-&gt;next = n;
                                        n-&gt;next = NULL;
                                } else {
                                        n-&gt;next = tmp;
                                        prev-&gt;next = n;
                                }

                                break;
                        }

                        prev = tmp;
                        tmp = tmp-&gt;next;
                }

                if (!tmp) {
                        n-&gt;next = NULL;
                        prev-&gt;next = n;
                }
        }
}</pre>
<p>Yeah, well it is pretty long, but that&#8217;s how you do it, right? You have to make sure that the list is not empty (line 8 ) &#8211; if it is empty, then new node should be placed at the head of the list. Then we have to find right place for the new node and insert it into its position (lines 14-29). Finally, if we didn&#8217;t find a good position for the new node, we should put the node at the end of the list (lines 31-34).</p>
<p>When I showed this to the examiner he asked me to rethink the routine. In particular he didn&#8217;t like number of <em>if</em> statements. After an hour of discussing various optimizations, this is what we came up with.</p>
<pre class="brush:cpp">void list_insert(int num)
{
        list_node_t **tmp, *n;

        n = allocate_node();
        n-&gt;num = num;

        tmp = &amp;head;
        while (*tmp) {
                if ((*tmp)-&gt;num &gt;= n-&gt;num)
                        break;
                tmp = &amp;(*tmp)-&gt;next;
        }

/*
        (*tmp) = n;
       n-&gt;next = (*tmp)-&gt;next;
*/

/*
        The code in the comment above is broken. Thanks to jagan
        for pointing this out. Here's the right code.
*/
        n->next = *tmp;
        *tmp = n;
}</pre>
<p>There are several things that make this version better.</p>
<p>First of all, instead of having a pointer to current node (<em>tmp</em>) and previous node (<em>prev</em>), we have one pointer that corresponds to pointer to previous node. This way we can always get to the current node via <em>next</em> field in the previous node. Thus we don&#8217;t need two pointers anymore.</p>
<p>Also, this version uses pointer to pointer to node to traverse through the list. We don&#8217;t insert the node in the while loop anymore. Purpose of the while loop is to find right place for the new node. This spares <em>if</em> statement that tests if the list is empty and <em>if </em>statement in the loop.</p>
<p>Finally, once <em>tmp</em> points to the right place, we insert the node.</p>
<p>Second version runs faster too. I did a small program that tests both versions and it appears that the later version is something like 5% faster.</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/pthread-mutex-vs-pthread-spinlock' rel='bookmark' title='Permanent Link: pthread mutex vs pthread spinlock'>pthread mutex vs pthread spinlock</a></li>
<li><a href='http://www.alexonlinux.com/todo-list' rel='bookmark' title='Permanent Link: Todo list'>Todo list</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/rethinking-linked-list-insertion/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>I am looking for a new job</title>
		<link>http://www.alexonlinux.com/i-am-looking-for-a-new-job</link>
		<comments>http://www.alexonlinux.com/i-am-looking-for-a-new-job#comments</comments>
		<pubDate>Mon, 07 Dec 2009 13:52:03 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1651</guid>
		<description><![CDATA[I am sorry to say that, but Exanet, a company that I joined less than a month ago, has been closed.
This means that I am looking for a new job. The good thing is that now your or your friend&#8217;s company has  a chance to hire a programmer with ten years of experience in writing [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/i-got-a-new-job-take-3' rel='bookmark' title='Permanent Link: I got a new job, take 3'>I got a new job, take 3</a></li>
<li><a href='http://www.alexonlinux.com/resume' rel='bookmark' title='Permanent Link: Resume'>Resume</a></li>
<li><a href='http://www.alexonlinux.com/new-lkml-daily-podcast' rel='bookmark' title='Permanent Link: New LKML daily podcast'>New LKML daily podcast</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I am sorry to say that, but Exanet, a company that I joined less than a month ago, has been closed.</p>
<p>This means that I am looking for a new job. The good thing is that now your or your friend&#8217;s company has  a chance to hire a programmer with ten years of experience in writing application for Linux and Linux kernel. So, if you can help, please pass my resume. <a title="Link to my resume" href="http://www.alexonlinux.com/resume" onclick="return TrackClick('http%3A%2F%2Fwww.alexonlinux.com%2Fresume','Link+to+my+resume')">You can find it here.</a></p>
<p>Thanks.</p>
<p>Alex.</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/i-got-a-new-job-take-3' rel='bookmark' title='Permanent Link: I got a new job, take 3'>I got a new job, take 3</a></li>
<li><a href='http://www.alexonlinux.com/resume' rel='bookmark' title='Permanent Link: Resume'>Resume</a></li>
<li><a href='http://www.alexonlinux.com/new-lkml-daily-podcast' rel='bookmark' title='Permanent Link: New LKML daily podcast'>New LKML daily podcast</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/i-am-looking-for-a-new-job/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>I got a new job</title>
		<link>http://www.alexonlinux.com/i-got-a-new-job</link>
		<comments>http://www.alexonlinux.com/i-got-a-new-job#comments</comments>
		<pubDate>Wed, 18 Nov 2009 07:51:09 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1647</guid>
		<description><![CDATA[You probably noticed that I didn&#8217;t write anything new for awhile. Well, I was looking for a new job and didn&#8217;t have much time to write. Luckily, this is over. I am now a senior software engineer at Exanet LTD.
Exanet is developing storage solutions for large organisations. ExaStore, main product of the company, is a [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/i-am-looking-for-a-new-job' rel='bookmark' title='Permanent Link: I am looking for a new job'>I am looking for a new job</a></li>
<li><a href='http://www.alexonlinux.com/a-new-kind-of-virtualization' rel='bookmark' title='Permanent Link: A new kind of virtualization'>A new kind of virtualization</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>You probably noticed that I didn&#8217;t write anything new for awhile. Well, I was looking for a new job and didn&#8217;t have much time to write. Luckily, this is over. I am now a senior software engineer at <a href="http://www.exanet.com" onclick="return TrackClick('http%3A%2F%2Fwww.exanet.com','Exanet+LTD')">Exanet LTD</a>.</p>
<p>Exanet is developing storage solutions for large organisations. ExaStore, main product of the company, is a clustered NAS gateway solution providing highly available and distributed data storage.</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/i-am-looking-for-a-new-job' rel='bookmark' title='Permanent Link: I am looking for a new job'>I am looking for a new job</a></li>
<li><a href='http://www.alexonlinux.com/a-new-kind-of-virtualization' rel='bookmark' title='Permanent Link: A new kind of virtualization'>A new kind of virtualization</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/i-got-a-new-job/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MSI-X &#8211; the right way to spread interrupt load</title>
		<link>http://www.alexonlinux.com/msi-x-the-right-way-to-spread-interrupt-load</link>
		<comments>http://www.alexonlinux.com/msi-x-the-right-way-to-spread-interrupt-load#comments</comments>
		<pubDate>Wed, 18 Nov 2009 07:46:11 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programming Articles]]></category>
		<category><![CDATA[System Administrator Articles]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1632</guid>
		<description><![CDATA[When considering ways to spread interrupts from one device among multiple cores, I can&#8217;t not to mention MSI-X. The thing is that MSI-X is actually the right way to do the job.
Interrupt affinity, which I discussed here and here, has a fundamental problem. That is inevitable CPU cache misses. To emphasise this, think about what [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/why-interrupt-affinity-with-multiple-cores-is-not-such-a-good-thing' rel='bookmark' title='Permanent Link: Why interrupt affinity with multiple cores is not such a good thing'>Why interrupt affinity with multiple cores is not such a good thing</a></li>
<li><a href='http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux' rel='bookmark' title='Permanent Link: SMP affinity and proper interrupt handling in Linux'>SMP affinity and proper interrupt handling in Linux</a></li>
<li><a href='http://www.alexonlinux.com/a-new-kind-of-virtualization' rel='bookmark' title='Permanent Link: A new kind of virtualization'>A new kind of virtualization</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>When considering ways to spread interrupts from one device among multiple cores, I can&#8217;t not to mention MSI-X. The thing is that MSI-X is actually the right way to do the job.</p>
<p>Interrupt affinity, which I discussed <a href="why-interrupt-affinity-with-multiple-cores-is-not-such-a-good-thing">here</a> and <a href="smp-affinity-and-proper-interrupt-handling-in-linux">here</a>, has a fundamental problem. That is inevitable CPU cache misses. To emphasise this, think about what happens when your computer receives a packet from the network. Packet belongs to some connection. With interrupt affinity the packet would land on core X, while the chances are that previous packet on the same TCP connection has landed on core Y (X ≠ Y).</p>
<p>Handing the packet would require kernel to load TCP connection object into X&#8217;s cache. But, this is so ineffective. After all, the TCP connection object is already in Y&#8217;s cache. Wouldn&#8217;t it be better to handle second packet on core Y as well?</p>
<p><span id="more-1632"></span>This is the  problem with interrupt affinity. From one point of view we want to spread interrupts to even the load on cores. From another point of view, doing simple round robin isn&#8217;t enough. The little fella that decides where each interrupt goes, should be able to look into the packet and depending on what TCP connection it belongs to, send the interrupt to core that handles all packets that belong to this connection.</p>
<p>Ideally, NICs should be able to:</p>
<ol>
<li>Look into packets and identify connections.</li>
<li>Direct interrupt to core that handles the connection.</li>
</ol>
<p>Apparently, this functionality already here. Devices that support MSI-X do exactly this.</p>
<h2>Meet MSI-X</h2>
<p>MSI-X is an extension to MSI. MSI replaces good old pin based interrupt delivery mechanism.</p>
<blockquote><p>Each IO-APIC chip (x86 permits up to 5) has 24 legs, each connected to one or more devices. When IO-APIC receives an interrupt, it redirects the interrupt to one of the local-APICs. Each local-APIC connected to a core that receives an interrupt.</p></blockquote>
<p>MSI provides a kind of protocol for interrupt delivery. Instead of raising signal on pins, PCI cards send a message over MSI and IO-APIC translates the message into right interrupt. Theoretically this means that each device can have number of interrupt vectors. In reality, plain MSI does not support this, but MSI-X does.</p>
<p>Modern high-end network cards that support MSI-X, implement multiple tx-rx queues. Each queue tied up to an interrupt vector and each NIC has plenty of them. I checked Intel&#8217;s 82575 chipset. With igb driver compiled properly, it has up to eight queues, four rx and four tx. Broadcom&#8217;s 5709 chipset provides eight queues (and eight interrupt vectors), each handling both rx and tx.</p>
<p>In kernel 2.6.24, kernel developers introduced new member of struct sk_buff called queue_mapping. This member tells incoming NIC driver what queue to use when transmitting the packet.</p>
<p>Before transmitting the packet, kernel decides what queue to use for this packet (net/core/dev.c:dev_queue_xmit()). It uses two techniques to do so. First, kernel can ask NIC driver to provide a queue number for the packet. This functionality, however, is optional in NIC drivers and at the moment both Intel and Broadcom drivers don&#8217;t provide it. Otherwise, kernel uses a simple hashing algorithm that produces 16 bit number from two ip addresses and (in case of TCP or UDP) two port numbers. All this happens in function named simple_tx_hash() in net/core/dev.c.</p>
<p>When receiving packets, things are even easier because NIC firmware and the driver decide what queue to use to introduce the packet to the kernel.</p>
<p>Using this simple technique kernel and modern NIC&#8217;s can verify that packets that belong to certain connection land on certain queue. Using interrupt affinity binding techniques you can bind certain interrupt vector to certain core (writing to smp_affinity, etc). Thus you can spread interrupts among multiple cores and yet make sure there are no cache misses.</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/why-interrupt-affinity-with-multiple-cores-is-not-such-a-good-thing' rel='bookmark' title='Permanent Link: Why interrupt affinity with multiple cores is not such a good thing'>Why interrupt affinity with multiple cores is not such a good thing</a></li>
<li><a href='http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux' rel='bookmark' title='Permanent Link: SMP affinity and proper interrupt handling in Linux'>SMP affinity and proper interrupt handling in Linux</a></li>
<li><a href='http://www.alexonlinux.com/a-new-kind-of-virtualization' rel='bookmark' title='Permanent Link: A new kind of virtualization'>A new kind of virtualization</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/msi-x-the-right-way-to-spread-interrupt-load/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why interrupt affinity with multiple cores is not such a good thing</title>
		<link>http://www.alexonlinux.com/why-interrupt-affinity-with-multiple-cores-is-not-such-a-good-thing</link>
		<comments>http://www.alexonlinux.com/why-interrupt-affinity-with-multiple-cores-is-not-such-a-good-thing#comments</comments>
		<pubDate>Thu, 17 Sep 2009 12:44:23 +0000</pubDate>
		<dc:creator>Alexander Sandler</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[System Administrator Articles]]></category>
		<category><![CDATA[affinity]]></category>
		<category><![CDATA[core]]></category>
		<category><![CDATA[CPU]]></category>
		<category><![CDATA[interrupt]]></category>
		<category><![CDATA[motherboard]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[tcp]]></category>

		<guid isPermaLink="false">http://www.alexonlinux.com/?p=1613</guid>
		<description><![CDATA[One of the features of x86 architecture is ability to spread interrupts evenly among multiple cores. Benefits of such configuration seems to be obvious. Interrupts consume CPU time and by spreading them on all cores we avoid bottle-necks.
I&#8217;ve written an article explaining this mechanism in greater detail. Yet let me remind you how it works [...]


Related posts:<ol><li><a href='http://www.alexonlinux.com/msi-x-the-right-way-to-spread-interrupt-load' rel='bookmark' title='Permanent Link: MSI-X &#8211; the right way to spread interrupt load'>MSI-X &#8211; the right way to spread interrupt load</a></li>
<li><a href='http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux' rel='bookmark' title='Permanent Link: SMP affinity and proper interrupt handling in Linux'>SMP affinity and proper interrupt handling in Linux</a></li>
<li><a href='http://www.alexonlinux.com/a-new-kind-of-virtualization' rel='bookmark' title='Permanent Link: A new kind of virtualization'>A new kind of virtualization</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>One of the features of x86 architecture is ability to spread interrupts evenly among multiple cores. Benefits of such configuration seems to be obvious. Interrupts consume CPU time and by spreading them on all cores we avoid bottle-necks.</p>
<p>I&#8217;ve written an <a title="SMP affinity and proper interrupt handling" href="http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux" onclick="return TrackClick('http%3A%2F%2Fwww.alexonlinux.com%2Fsmp-affinity-and-proper-interrupt-handling-in-linux','SMP+affinity+and+proper+interrupt+handling')">article explaining this mechanism in greater detail</a>. Yet let me remind you how it works in two words.</p>
<p><span id="more-1613"></span>Every x86 motherboard has a chip called IO-APIC. This is a device that controls interrupt delivery within your system. It knows how many CPUs are in your system and can direct various interrupts to various CPUs. It uses so called local APIC-ID as an identifier of the processor.</p>
<p>It has two modes of operation. In one mode it sends interrupts from certain device to single, predefined core. This mode of operation called fixed/physical mode. In another mode, it can deliver interrupts from certain device to multiple cores. The later mode called logical/low priority interrupt delivery mode.</p>
<p>When in logical mode, IO-APIC can deliver interrupts to up to eight cores. Source of this limitation is the size of the bitmask register that tells what CPUs should receive the interrupts. The bitmask is only eight bits long.</p>
<p>When considering the round robin-type of interrupt delivery mode (the logical mode), I cannot stop thinking about how it degrades performance.</p>
<p>You see, having burden of interrupt handling spread among multiple cores may solve some bottle-necks, but it creates a problem.</p>
<p>Consider network interface card for example. Lets say we have a TCP connection to some host out there. When packet arrives, the network card issues an interrupt and IO-APIC directs it to one of the cores. Next, the core handing the packet should fetch the TCP connection objects from the memory to its cache.</p>
<p>IO-APIC does not guarantee that next packet that belongs to the connection will be handled by the same core. So, it is likely that two cores will have to work with TCP connection object. Both of them will have to fetch its content into their cache. This will cause <a title="Link to cache coherency on Wikipedia" href="http://en.wikipedia.org/wiki/Cache_coherence" onclick="return TrackClick('http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FCache_coherence','Link+to+cache+coherency+on+Wikipedia')">cache coherency</a> problems (cache misses). And as you can learn from the <a title="Link to aligned vs unaligned memory access article" href="aligned-vs-unaligned-memory-access">article I&#8217;ve written on misaligned memory accesses</a>, accessing memory that is not in cache can take up to 30 times more time than accessing cached RAM.</p>
<p>Moreover, assuming TCP connection object is properly protected using synchronization techniques, one of the cores will inevitably have to wait for the other, adding unnecessary delay to packet processing.</p>
<p>My point is that round-robin style interrupt delivery can be quiet nasty on performance. It is much better to deliver interrupts from certain device to given core.</p>
<p>Luckily, <em>smp_affinity</em> interface, that I mentioned in my <a title="Link to smp affinity and proper interrupt handling article" href="smp-affinity-and-proper-interrupt-handling-in-linux">old article</a>, allows you to bind interrupts from certain device to certain (single) core.</p>
<p>On some computers IO-APIC does not support logical delivery mode. This can be because of buggy BIOS or too many CPUs. On such computers physical interrupt delivery mode is the only thing that works, so binding single interrupt to single core is the only choice and the only thing you can do is switch the core from one to another.</p>
<p>My point is that round-robin style interrupt delivery can:</p>
<ol>
<li>Malfunction</li>
<li>Cause performance degradation.</li>
</ol>
<p>So, when it still might become useful, you may ask? It depends on what you do with your computer. Usually, you don&#8217;t need round-robin style interrupt delivery. You only need it if you know that your computer receives lots of interrupts and you have real-time applications.</p>
<p>In this case, scheduler (which has no idea about interrupts) can schedule thread that requires lots of CPU time to run on core that serves interrupts. Since interrupts has higher priority, the thread will receive less CPU time. In case of real-time application it may result in reduced responsiveness.</p>
<p>Even so, you can still assign all interrupts to one core and use thread affinity techniques to make sure that your application doesn&#8217;t use that core.</p>


<p>Related posts:<ol><li><a href='http://www.alexonlinux.com/msi-x-the-right-way-to-spread-interrupt-load' rel='bookmark' title='Permanent Link: MSI-X &#8211; the right way to spread interrupt load'>MSI-X &#8211; the right way to spread interrupt load</a></li>
<li><a href='http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux' rel='bookmark' title='Permanent Link: SMP affinity and proper interrupt handling in Linux'>SMP affinity and proper interrupt handling in Linux</a></li>
<li><a href='http://www.alexonlinux.com/a-new-kind-of-virtualization' rel='bookmark' title='Permanent Link: A new kind of virtualization'>A new kind of virtualization</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexonlinux.com/why-interrupt-affinity-with-multiple-cores-is-not-such-a-good-thing/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
