I have uploaded a set of changes that covers various things, including some recent bug reports and the implementation of locks and condition variables. I will focus on the locks here.
The code has been tested using Matthew Mondor's web server (http://article.gmane.org/gmane.lisp.ecl.general/8965
) with a varying number of connections and threads. I have witnessed some glitches but only when recompiling and using a new executable. Will continue testing, though.
The current philosophy is as follows:
* The lock is a word-sized field in a structure, atomically updated by the locking thread.
* The no-wait locking amounts to trying to reset the field atomically (using libatomics), and returning NIL if the field is already set.
* The wait mechanism consits on three phases
++ try to acquire the lock once
++ enter ecl_wait_on() which will
+++ first perform a brief spin lock
+++ then enter a look with increasing wait times
* The unlocking routine is now designed to awake at least one thread. This is done by issuing an interrupt that will disrupt the waiting loop from ecl_wait_on().
As discussed earlier, the advantage of this user space implementation is that we have full control of the status of the lock even when interrupts occur.
Time-wise, it seems to be slower than the pthreads implementation, reaching 400 connections / second or 2.5 ms / connection in Matthew's tests, vs. 1.5 ms / connection for pthreads (ECL 12.1.1). On the other hand, I have not seen any segfaults and it still puzzles me the difference: using a profiler I do not see any more time being spent in the waiting loop (it is 0.4% of the total time)
The code is not yet extremely mature and I believe it has to be possible to improve the speed or at least learn how to do a more efficient wait loop.