[M3commit] CVS Update: cm3
Jay Krell
jkrell at elego.de
Mon May 4 13:19:07 CEST 2009
CVSROOT: /usr/cvs
Changes by: jkrell at birch. 09/05/04 13:19:07
Modified files:
cm3/m3-libs/m3core/src/thread/PTHREAD/: ThreadPThread.m3
Log message:
move expensive calloc+pthread_mutex_init outside lock, using a double
check pattern:
if it appears work is needed (but with taking lock to be sure)
do the work, into temp
take lock
if work not actually needed, ok
release lock
free the temp (don't care if it succeeded)
else
if attempt to do the work failed
release lock
raise exception
else
commit the work
release lock
end
end
end
It is ugly perhaps to repeat "release lock" three times instead
of once, but time holding the lock is minimized.
As long as "temp" is a pointer, which it is here,
this can use InterlockedCompareExchangePointer and not a full blown lock.
Something like:
if pointer == null
temp = new ...
if InterlockedCompareExchange(&pointer, NULL, temp) != NULL)
delete temp (* lost the race, ok *)
else
if temp == NULL (* won the race but failed *)
raise exception
end
end
end
This pattern is bad if the temp work is particularly expensive or
must not be executed more than once. That leaves
many instances in which it is ok.
Also here eliminate PushFrame, but the point is more to eliminate
calloc from inside a lock. Therefore, if calloc is well tuned for
multiprocessor systems, and many locks are used for the first
time at about the same time on multiple threads, scale better.
("hold locks for minimal time, even at the risk of doing more work
in the event of a race" is a good scalability principle; as well as "replace lock
with interlocked/atomic/cas/etc., also at the risk of doing
more work when there is a race")
Factor InitMutex and InitCondition into one function InitMutexHelper.
It is tempting to rewrite InitMutexHelper in C, thereby removing
the exposure of the init lock, however as I understand this is a
bad move due to interior gc pointers or such.
More information about the M3commit
mailing list