[Openmcl-devel] http servers and threads under heavy load; was: Good Video

R. Matthew Emerson rme at clozure.com
Sat Oct 17 23:32:37 UTC 2009


On Oct 17, 2009, at 4:45 PM, Daniel Pezely wrote:

>
> Sometimes, however, OS-native threads are required for your particular
> needs.  In those cases, try lock-free, spin-free message lists within
> the pipeline.  It's no magic bullet, of course...  You'll want atomic-
> push and -pop operations (and ideally, atomic-rotatef-1), which in
> SBCL can be built upon #'sb-ext:compare-and-swap function.  Since CCL
> internally has #'ccl::atomic-incf and -decf, I'm sure that the other
> functions will follow soon or already exist by some other name.  I
> couldn't find any with a quick check of latest source in svn; anyone
> know?

There was a discussion on the #ccl irc channel on Freenode a couple of  
days ago about this.

The upshot of it is that there are several building blocks of this  
nature in ccl, but they're all undocumented and all somewhat  
idiosyncratic.

http://ccl.clozure.com/irc-logs/ccl/2009-10/ccl-2009.10.15.txt

01:52:37 <chandler> Is there an exposed CAS-style operation? (Forgive  
me if I'm missing something in the documentation.)
01:54:03 <gbyers> There are several, all funky and none (AFAIK)  
documented.  CLX wants a CONDITIONAL-STORE, and there's something  
that's slightly exposed for its benefit.
01:55:24 <sellout> chandler: Adlai was playing with a CAS earlier  
today, I think ...
01:55:48 <sellout> (for CCL)
01:56:16 <sykopomp> sellout: he's been working on it for a while. I  
don't know if he's gotten around to writing that latest version after  
he figured out what was wrong...
01:56:22 <chandler> Ah, I just found that in the logs.
01:56:42 <gbyers> The general case of CAS is weird for a few reasons  
(having to do with the GC, threads, and interrupts.)
01:56:58 <rme> Without special lisp runtime support, I don't think  
it's possible to do a CAS for lisp objects.
01:58:02 <chandler> Can you elucidate some of the reasoning behind that?
02:00:54 <gbyers> on x8664, "cmpxchg" uses %rax as an implicit  
operand: you generally load the contents of a memory location into  
%rax, then try to store a new value there, and the conditional store  
works if the location still contains the value in %rax.  If the GC  
runs between the load and the cmpxchg, the memory location's value may  
change but the value in %rax (presumed to be a non-lisp value) won't  
change.
02:01:24 <rme> In CCL, a gc can happen at any instruction boundary.   
CCL's gc thinks it always knows if a register contains a lisp  
object ... what he said.
02:04:44 <chandler> Ah. Having only dealt with this at a C level, I  
never noticed.
02:07:05 <chandler> Presumably some sort of thread state could be  
updated around the instruction, with a worst case that the old value  
is incorrectly marked as alive. (Or I suppose the GC could look back  
an instruction and handle cmpxchg cases specially.)
02:07:20 <gbyers> rme and I walk around saying "... but if a GC  
happens here, we're screwed."  It may be a curse.
02:07:32 <chandler> Heh.
02:07:34 <rme> For a good time (not) read pc_luser_xp() in ccl:lisp- 
kernel;x86-exceptions.c
02:10:34 <chandler> I'll have a look when I'm not IRCing from my phone.
02:11:00 <gbyers> We do the problematic cmpxchg's in a few known  
locations in the lisp kernel, and that function recognizes when a  
thread gets stopped in the middle of one of those sequences and backs  
up/moves forward as appropriate.
02:15:21 <gbyers> We also do the generational write-barrier stuff in  
software, so if a cmpxchg succeeds, it may have just stored a pointer  
to a young object in an old object.  We need to set a bit to indicate  
a possible intergenerational reference, and the store and the bit- 
setting have to appear to be atomic.






More information about the Openmcl-devel mailing list