<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Reader-writer Lock in Intel® Moderncode for Parallel Architectures</title>
    <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863257#M2546</link>
    <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/438844"&gt;matt.j&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;BR /&gt;&lt;EM&gt;
&lt;/EM&gt;&lt;PRE&gt;&lt;EM&gt;[cpp]NAKED Void FASTCALL RWLock::AquireRead()&lt;BR /&gt;{&lt;BR /&gt;	__asm&lt;BR /&gt;	{&lt;BR /&gt;		// Aquire lock.&lt;BR /&gt;		mov edx, 1&lt;BR /&gt;&lt;BR /&gt;		ALIGN 16&lt;BR /&gt;		SPIN:&lt;BR /&gt;			xor eax, eax&lt;BR /&gt;			pause&lt;BR /&gt;			lock cmpxchg word ptr [ecx], dx&lt;BR /&gt;&lt;BR /&gt;[/cpp]&lt;/EM&gt;&lt;/PRE&gt;
&lt;BR /&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;BR /&gt;Doesn't it have to be lock cmpxchg word ptr [ecx + 1], dx?&lt;BR /&gt;&lt;BR /&gt;</description>
    <pubDate>Mon, 14 Dec 2009 20:33:09 GMT</pubDate>
    <dc:creator>Dmitry_Vyukov</dc:creator>
    <dc:date>2009-12-14T20:33:09Z</dc:date>
    <item>
      <title>Reader-writer Lock</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863256#M2545</link>
      <description>Hello,&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;I've written a simple reader-writer lock for my own needs and am just after another pair of eyes to identify any issues I may have missed.&lt;BR /&gt;&lt;BR /&gt;The domain this will be used in involves the vast majority being reads with the workload between each read-request being quite significant (ie., there will be little thread-contention)&lt;BR /&gt;&lt;BR /&gt;A few things to note that may or may not be obvious:&lt;BR /&gt;#1: A basic lock needs to be aquired for any request (read/write)&lt;BR /&gt;#2: Writers are given priority, the "Writers" variable is about pending-writers, not current writers.&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;
&lt;PRE&gt;[cpp]struct RWLock
{
	// Attributes
	Byte Writers;
	Byte Lock;
	Byte Readers;
	Byte Unused;

	// Methods
	Void FASTCALL AquireWrite();
	Void FASTCALL AquireRead();
	Void FASTCALL ReleaseWrite();
	Void FASTCALL ReleaseRead();
};


NAKED Void FASTCALL RWLock::AquireWrite()
{
	__asm
	{
		// Signal readers to wait.
		add byte ptr [ecx], 1

		// Aquire lock, no readers.
		mov edx, 1

		ALIGN 16
		SPIN:
			xor eax, eax
			pause
			lock cmpxchg word ptr [ecx+1], dx
			jnz short SPIN

		// Decrement writer-pending count.
		sub byte ptr [ecx], 1

		// Aquired.
		ret
	}
}




NAKED Void FASTCALL RWLock::AquireRead()
{
	__asm
	{
		// Aquire lock.
		mov edx, 1

		ALIGN 16
		SPIN:
			xor eax, eax
			pause
			lock cmpxchg word ptr [ecx], dx
			jnz short SPIN

		// Increment reader count.
		lock add byte ptr [ecx+2], 1

		// Free lock.
		mov byte ptr [ecx+1], 0

		// Aquired.
		ret
	}
}


FORCEINLINE Void FASTCALL RWLock::ReleaseRead()
{
	// Decrement reader count.
	this-&amp;gt;Readers--;
}


FORCEINLINE Void FASTCALL RWLock::ReleaseWrite()
{
	// Free lock.
	this-&amp;gt;Lock = 0;
}[/cpp]&lt;/PRE&gt;
&lt;BR /&gt;For C-style ('this' omitted for clarity)&lt;BR /&gt;&lt;BR /&gt;
&lt;PRE&gt;[cpp]/*
 * AquireWrite()
 */

// Signal readers to wait.
Writers++;

// Aquire lock when no writers or readers are present.
while(Lock != 0 &amp;amp;&amp;amp; Readers != 0);
Lock=1;

// Decrement writer-pending count.
Writers--;


/*
 * AquireRead()
 */

// Aquire lock when no writers are either present or pending.
while(Writers != 0 &amp;amp;&amp;amp; Lock != 0);
Lock=1;

// Increment reader count.
Readers++;

// Free lock
Lock=0;
[/cpp]&lt;/PRE&gt;
&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;Cheers,&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;Matt.&lt;BR /&gt;</description>
      <pubDate>Sat, 12 Dec 2009 02:54:19 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863256#M2545</guid>
      <dc:creator>matt_j</dc:creator>
      <dc:date>2009-12-12T02:54:19Z</dc:date>
    </item>
    <item>
      <title>Re: Reader-writer Lock</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863257#M2546</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/438844"&gt;matt.j&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;BR /&gt;&lt;EM&gt;
&lt;/EM&gt;&lt;PRE&gt;&lt;EM&gt;[cpp]NAKED Void FASTCALL RWLock::AquireRead()&lt;BR /&gt;{&lt;BR /&gt;	__asm&lt;BR /&gt;	{&lt;BR /&gt;		// Aquire lock.&lt;BR /&gt;		mov edx, 1&lt;BR /&gt;&lt;BR /&gt;		ALIGN 16&lt;BR /&gt;		SPIN:&lt;BR /&gt;			xor eax, eax&lt;BR /&gt;			pause&lt;BR /&gt;			lock cmpxchg word ptr [ecx], dx&lt;BR /&gt;&lt;BR /&gt;[/cpp]&lt;/EM&gt;&lt;/PRE&gt;
&lt;BR /&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;BR /&gt;Doesn't it have to be lock cmpxchg word ptr [ecx + 1], dx?&lt;BR /&gt;&lt;BR /&gt;</description>
      <pubDate>Mon, 14 Dec 2009 20:33:09 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863257#M2546</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2009-12-14T20:33:09Z</dc:date>
    </item>
    <item>
      <title>Re: Reader-writer Lock</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863258#M2547</link>
      <description>You must use the same address and the same operand size in all atomic RMW operations.&lt;BR /&gt;
&lt;PRE&gt;Intel 64 and IA-32 Architectures Software Developer's Manual Volume&lt;BR /&gt;3A: System Programming Guide, Part 1&lt;BR /&gt;&lt;BR /&gt;7.1.2.2 Software Controlled Bus Locking&lt;BR /&gt;&lt;BR /&gt;Software should access semaphores (shared memory used for signalling&lt;BR /&gt;between multiple processors) using identical addresses *and operand lengths*.&lt;BR /&gt;For example, if one processor accesses a semaphore using a word access, other&lt;BR /&gt;processors should not access the semaphore using a byte access.&lt;/PRE&gt;
&lt;BR /&gt;</description>
      <pubDate>Mon, 14 Dec 2009 20:35:38 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863258#M2547</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2009-12-14T20:35:38Z</dc:date>
    </item>
    <item>
      <title>Re: Reader-writer Lock</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863259#M2548</link>
      <description>You better align your mutex variable on 4-byte boundary. If it happens to cross cache line boundary it will run very slowly on Intel QPI based system, system-wide quiescence is *very* unpleasant thing.&lt;BR /&gt;</description>
      <pubDate>Mon, 14 Dec 2009 20:39:54 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863259#M2548</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2009-12-14T20:39:54Z</dc:date>
    </item>
    <item>
      <title>Re: Reader-writer Lock</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863260#M2549</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/438844"&gt;matt.j&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;BR /&gt;&lt;EM&gt;
&lt;/EM&gt;&lt;PRE&gt;&lt;EM&gt;[cpp]NAKED Void FASTCALL RWLock::AquireWrite()&lt;BR /&gt;{&lt;BR /&gt;	__asm&lt;BR /&gt;	{&lt;BR /&gt;		// Signal readers to wait.&lt;BR /&gt;		add byte ptr [ecx], 1&lt;BR /&gt;&lt;BR /&gt;		// Aquire lock, no readers.&lt;BR /&gt;		mov edx, 1&lt;BR /&gt;&lt;BR /&gt;		ALIGN 16&lt;BR /&gt;		SPIN:&lt;BR /&gt;			xor eax, eax&lt;BR /&gt;			pause&lt;BR /&gt;			lock cmpxchg word ptr [ecx+1], dx&lt;BR /&gt;			jnz short SPIN&lt;BR /&gt;&lt;BR /&gt;		// Decrement writer-pending count.&lt;BR /&gt;		sub byte ptr [ecx], 1&lt;BR /&gt;&lt;BR /&gt;		// Aquired.&lt;BR /&gt;		ret&lt;BR /&gt;	}&lt;BR /&gt;}&lt;BR /&gt;[/cpp]&lt;/EM&gt;&lt;/PRE&gt;
&lt;BR /&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;BR /&gt;Here is a race on [ecx], you use non-atomic operations 'add byte ptr [ecx]' and 'sub byte ptr [ecx]'. Two concurrent writer can damage [ecx], so that it will never become zero again.&lt;BR /&gt;&lt;BR /&gt;</description>
      <pubDate>Mon, 14 Dec 2009 20:43:07 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863260#M2549</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2009-12-14T20:43:07Z</dc:date>
    </item>
    <item>
      <title>Re: Reader-writer Lock</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863261#M2550</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/438844"&gt;matt.j&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;
&lt;/EM&gt;&lt;PRE&gt;&lt;EM&gt;[cpp]&lt;BR /&gt;FORCEINLINE Void FASTCALL RWLock::ReleaseRead()&lt;BR /&gt;{&lt;BR /&gt;	// Decrement reader count.&lt;BR /&gt;	this-&amp;gt;Readers--;&lt;BR /&gt;}&lt;BR /&gt;[/cpp]&lt;/EM&gt;&lt;/PRE&gt;
&lt;BR /&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;BR /&gt;ReleaseReed() is not atomic wrt 'Readers', you need to use 'lock sub' in ReleaseRead(). Otherwise concurrent readers will corrupt 'Readers'.&lt;BR /&gt;</description>
      <pubDate>Mon, 14 Dec 2009 20:44:50 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863261#M2550</guid>
      <dc:creator>Dmitry_Vyukov</dc:creator>
      <dc:date>2009-12-14T20:44:50Z</dc:date>
    </item>
    <item>
      <title>Re: Reader-writer Lock</title>
      <link>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863262#M2551</link>
      <description>&lt;DIV style="margin:0px;"&gt;
&lt;DIV id="quote_reply" style="width: 100%; margin-top: 5px;"&gt;
&lt;DIV style="margin-left:2px;margin-right:2px;"&gt;Quoting - &lt;A href="https://community.intel.com/en-us/profile/438844"&gt;matt.j&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV style="background-color:#E5E5E5; padding:5px;border: 1px; border-style: inset;margin-left:2px;margin-right:2px;"&gt;&lt;EM&gt;Hello,&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;I've written a simple reader-writer lock for my own needs and am just after another pair of eyes to identify any issues I may have missed.&lt;BR /&gt;&lt;BR /&gt;[...]&lt;/EM&gt;&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;/DIV&gt;
&lt;BR /&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;Read this whole thread:&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://software.intel.com/en-us/forums/showthread.php?t=65822"&gt;http://software.intel.com/en-us/forums/showthread.php?t=65822&lt;/A&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;Also, here is the best FIFO rw-spinlock out there:&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://groups.google.com/group/comp.programming.threads/browse_frm/thread/be3871ad661efa73/ac0c61ee539625de"&gt;http://groups.google.com/group/comp.programming.threads/browse_frm/thread/be3871ad661efa73/ac0c61ee539625de&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;I modified it to block, however you can easily change it back to a spinlock if you simply remove the eventcount logic and add a backoff/yield in the wait loops.&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;BR /&gt;&lt;/DIV&gt;
&lt;DIV&gt;Any thoughts?&lt;/DIV&gt;</description>
      <pubDate>Wed, 16 Dec 2009 00:39:31 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Moderncode-for-Parallel/Reader-writer-Lock/m-p/863262#M2551</guid>
      <dc:creator>Chris_M__Thomasson</dc:creator>
      <dc:date>2009-12-16T00:39:31Z</dc:date>
    </item>
  </channel>
</rss>

