From: Vladimir T. <vtz...@gm...> - 2008-09-12 22:04:53
|
Hi, As the subject says - three items. 1. Signals Basically there are two kind of signals that we may receive - synchronous (notable SIGSEGV) and asynchronous (SIGINT,SIGALRM,SIGWINCH,SIGTERM). (SIGCLD and SIGPIPE does not seem to cause problems - correct me if I am wrong). The SIGSEGV handler is executed in the context of the thread that caused it (only on OSX this is not the case - libsigsegv calls it in it's own dispatching thread). The asynchronous signals may executed in any available of the app threads. In order to prevent this - all newly created threads set their signal mask not to accept these signals. So all asynchronous stuff goes to the main thread (in the same time all other threads continue their execution). Currently (in single thread) "semaphores" -break_sems (simple flags) are used in order to defer the execution of asynchronous signal handlers for "safer" time. In MT I kept these semaphores - but they apply only to the main thread. In this way when we are in signal handler (exception: SIGSEGV) we can be sure that we are in the main thread. The semaphores ensure when it is safe to execute the handler (within the main thread). Does this sound good? (BTW: To what value to set size of the C stack of the newly created threads - since sometimes the default stack size is quite small - for example on OSX - 512 KB?) 2. Streams I went over it and made it full of GC safe blocking/system calls, pin/ unpin heap objects, maygc attributes, and storing/restoring stream and encoding objects. Not sure that I have reached all the cases (especially pipes, keyboard and screen streams). Currently all tests pass (with GCSAFETY as well) but in single thread :). For sure it runs now little bit slower (in single thread as well). That's the reason I thought about defining a new attribute instead of maygc - mt_maygc - which will expand to maygc in multithreaded builds. Also some macros like: #define MT_STORE_STREAM(s) pushSTACK(s) #define MT_GET_STREAM(s) s=STACK_0; #define MT_RESTORE_STREAM(s) s=popSTACK() #define MT_DISCARD_STREAM() skipSTACK(1) And of course in single threaded they will expand to nothing - so no performance slowdown for something that is not used. Unfortunately I was at the end (neat socket stream) when it came to my mind :(. What do you think - is it good to do it? (BTW: what is the best way to check the performance difference of the streams between the versions - some test ?) 3. Pinned objects. During some IO operations I pass pointers inside LISP heap to system calls and "pin" this objects in order not to move during GC. In case of non-local exit (SIGINT and return to REPL) it becomes difficult to keep what have to be "unpinned". I try to ensure that all pinned objects are unpinned (in current implementation) but it will be much easier if this unpinning is integrated in the stack unwinding process somehow. Is it possible - if yes how? (and of course - is it good idea?) BR Vladimir |