Author: Robert Hyatt
Date: 21:57:44 04/28/00
Go up one level in this thread
On April 29, 2000 at 00:48:24, KarinsDad wrote: >On April 28, 2000 at 20:45:37, Robert Hyatt wrote: > >>On April 28, 2000 at 13:28:22, KarinsDad wrote: >> >>>I read an interesting article by John M. Dlugosz titled "An Atomic Counter for >>>Guaranteed Thread Safety" and was wondering if anyone was using this technique >>>in their x86 SMP chess program. The article can be found in MSDN under >>>Periodicals 1998/Visual C++ Developer/August. >>> >>>Since these techniques only appear to work for certain data types, I would >>>assume that other techniques must also be used. What other techniques are being >>>used? >>> >>>Also, this article implies that this works with multiple processors, but did not >>>come right out and say it. >>> >>>This article also allows you to download source examples. And, some information >>>can be found at: >>> >>>http://www.dlugosz.com/Repertoire/ >>> >>>KarinsDad :) >> >> >>I use pure spinlocks everywhere. Simple and easy. And very high performance. > >I'm not familiar with that term (and am too lazy at the moment to look it up). >What is it and where would I find it in the Crafty source? > >KarinsDad :) The Macros for Lock() and Unlock() are in lock.h. They look like this: #define Lock(volatile int lockvar) while (Exchange(lockvar,1)) while (lockvar) #define UnLock(volatile int lockvar) Exchange(lockvar,0) Lock works like this: (assume lockvar is initialized to 0). The Exchange() macro is actually inline assembly to use the intel exchange(a,b) instruction, which is an atomic instruction. IE it reads the old value for A, and then sets A=B, all in one bus transaction, guaranteeing that if multiple cpus do this at the same time, one will get a value of zero, the rest will get a value of one. If the lock is set, rather than looping on the exchange(), which would lock the bus frequently and smother other processors trying to get to memory, I then do a normal spin loop in the second while. So long as the lockvar is 1, it will continue to spin. However, lockvar gets loaded into L2 and then L1 cache so that the spin uses no memory cycles at all. When another cpu zeros lockvar, the buss snooping cache controller will notice that a memory location has been modified, while it has a local copy in its cache. It marks it invalid, which causes a new memory read to get the new value of zero. To prevent race conditions, I then drop out of that while, and go back to the original which again does an Exchange(), hoping that this time it gets a zero, while simultaneously setting the lock to 1. Very simple, very efficient, and easy to use. Before modifying any shared data structure, its lock variable is acquired with the above. A process can't acquire the lock if another has already done so. This implements critical sections quite nicely. If you want more details, feel free to ask...
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.