From: <don...@is...> - 2009-01-26 18:34:24
|
I've been watching with great interest the recent progress in clisp threads and I find that I could really use a (with-timeout ...) facility. Is this thought to be working well enough to be worth trying to use? Where can I find instructions for building with threads and doing something with a time limit? multithread.txt says In the Makefile, define in the CFLAGS the symbol MULTITHREAD and one of the symbols POSIX_THREADS, POSIXOLD_THREADS, SOLARIS_THREADS, C_THREADS, WIN32_THREADS. (See xthread.d about their meaning.) I'm guessing that means something like this? CFLAGS = ... -DMULTITHREAD -DPOSIX_THREADS Given this: Currently only POSIX_THREADS are tested and all development is done with them. I guess I should use POSIX_THREADS, which I hope will work in a recent linux. The usable function from MT currently are: MAKE-THREAD, CURRENT-THREAD, LIST-THREADS, THREADP, THREAD-ACTIVE-P, THREAD-INTERRUPT, THREAD-KILL, THREAD-YIELD, THREAD-NAME, SYMBOL-VALUE-THREAD Some docs on them will be helpful (and will come shortly :)) I don't see a timeout macro. Should I be trying to write my own? Is it likely to work? What I'd like to do is something like this: (let (results) (with-timeout 15 (loop ... do (push (nextresult) results)))) where the loop is interrupted after 15 sec and with-timeout then returns. Possibly a little better would be for with-timeout to return a value indicating whether the execution was terminated by the timeout. |
From: <don...@is...> - 2009-01-26 22:46:47
|
Vladimir Tzankov writes: > I would say - yes. When built with POSIX_THREADS (linux, osx, may be > solaris) it works well. Ok, good. > >Where can I find instructions for building with threads and doing something with a time limit? > > ./configure --with-threads=POSIX_THREADS This takes care of the -D stuff in CFLAGS ? > If you are building 32 bit version and your compiler does not support > per thread storage qualifier (gcc __thread) than you may consider How can I tell whether this is the case? I'm using gcc. > adding to CFLAGS: -DUSE_CUSTOM_TLS=3 (or 2). This will give you much > better performance (with some increased memory usage).There is brief > description for this flag at the beginning of lispbibl.d. Definitely > more docs are needed. Ah, an interesting point. Do you think 64bit would be more likely to work or work better? Usually it's the opposite. I'm prepared to try either or both, but would prefer to first try the one more likely to work. What's this custom tls stuff about? (Thread local storage?) What do the different values mean and how do I choose? How do I find my page size? Maybe I'll just hope for gcc support... > > multithread.txt says > It is not updated recently so here I'll summarize what is the current > status. The tested threads flavours are POSIX_THREADS and > WIN32_THREADS. Currently I am struggling with implementing "proper" > THREAD-INTERRUPT on Win32 - but still not good and nothing in the cvs. No problem - I plan to use posix. > With POSIX-THREADS all exported thread functions are implemented with > exception of: THREAD-WAIT and THREAD-STATE. The first should do some > polling when the predicate is not a lock. For the latter - I am not > sure that it is needed at all. Sounds like these are not needed for timeout. > With WIN32_THREADS also THREAD-INTERRUPT is not implemented - so no > THREAD-KILL and CALL-WITH-TIMEOUT (and nice CTRL-C behavior). I am > almost lost in implementing this. I'm glad I'm using linux. Call-with-timeout sounds interesting. > There are several things that have to be changed in the runtime. ... all seem non-issues for the present purpose - I hope, we'll see. > > I don't see a timeout macro. Should I be trying to write my own? > There is with-timeout (in threads.lisp) and it is exported: > (defmacro with-timeout ((seconds &body timeout-forms) &body body) > "Execute BODY; if execution takes more than SECONDS seconds, > terminate and evaluate TIMEOUT-FORMS." > `(call-with-timeout ,seconds (lambda () ,@timeout-forms) (lambda () ,@body))) Very good. |
From: Vladimir T. <vtz...@gm...> - 2009-01-26 23:03:13
|
On Tue, Jan 27, 2009 at 12:46 AM, Don Cohen <don...@is...> wrote: > > ./configure --with-threads=POSIX_THREADS > This takes care of the -D stuff in CFLAGS ? yes > > If you are building 32 bit version and your compiler does not support > > per thread storage qualifier (gcc __thread) than you may consider > How can I tell whether this is the case? > I'm using gcc. It will be good configure to check this. Currently if you build on linux - it is considered that it is available (all recent versions of gcc on linux support it). If you get a lot of weird errors during the build - probably this is not the case -DUSE_CUSTOM_TLS is needed. On any other platform - by default USE_CUSTOM_TLS=1 wil be used. > > adding to CFLAGS: -DUSE_CUSTOM_TLS=3 (or 2). This will give you much > > better performance (with some increased memory usage).There is brief > > description for this flag at the beginning of lispbibl.d. Definitely > > more docs are needed. > Ah, an interesting point. Do you think 64bit would be more likely to > work or work better? I am doing most of the development/testing on 32 bit - so I assume it is "more stable". > What's this custom tls stuff about? (Thread local storage?) What do > the different values mean and how do I choose? > How do I find my page size? Maybe I'll just hope for gcc support... Yes it is thread local storage. In case there is no compiler support for TLS we have following options (pasted from lispbibl.d): USE_CUSTOM_TLS={1,2,3} 1 - using xthread_key_get/set - slowest one (and probably safest) 2 - using slightly modified version of TLS found in Boehm GC for C/C++. 3 - using full page map of address space (4 MB). Basically it is trade-off between performance/memory usage: {1} - xthread_key_get/set is 200-500% slower then native compiler TLS. {2} is about 50-100% slower than compiler TLS support and uses just 8 KB. {3} is almost as fast as single threaded and compiler TLS but uses 4 MB. {2} and {3} work only on 32 bit builds. In both the thread stack pointer is used to determine the TLS. {2} is using hashtable and {3} lookup array indexed with [ESP >> 12] (12 since on 32 bit 4K page size is assumed - anything else will cause problems). {1} is supposed to work always and is the default choice (if no -DUSE_CUSTOM_TLS in CFLAGs). Vladimir |
From: Vladimir T. <vtz...@gm...> - 2009-01-26 22:49:34
|
Hi, On 1/26/09, Don Cohen <don...@is...> wrote: > I've been watching with great interest the recent progress in clisp > threads and I find that I could really use a (with-timeout ...) > facility. Is this thought to be working well enough to be worth > trying to use? I would say - yes. When built with POSIX_THREADS (linux, osx, may be solaris) it works well. >Where can I find instructions for building with threads and doing something with a time limit? ./configure --with-threads=POSIX_THREADS If you are building 32 bit version and your compiler does not support per thread storage qualifier (gcc __thread) than you may consider adding to CFLAGS: -DUSE_CUSTOM_TLS=3 (or 2). This will give you much better performance (with some increased memory usage).There is brief description for this flag at the beginning of lispbibl.d. Definitely more docs are needed. > multithread.txt says It is not updated recently so here I'll summarize what is the current status. The tested threads flavours are POSIX_THREADS and WIN32_THREADS. Currently I am struggling with implementing "proper" THREAD-INTERRUPT on Win32 - but still not good and nothing in the cvs. With POSIX-THREADS all exported thread functions are implemented with exception of: THREAD-WAIT and THREAD-STATE. The first should do some polling when the predicate is not a lock. For the latter - I am not sure that it is needed at all. With WIN32_THREADS also THREAD-INTERRUPT is not implemented - so no THREAD-KILL and CALL-WITH-TIMEOUT (and nice CTRL-C behavior). I am almost lost in implementing this. There are several things that have to be changed in the runtime. 1. Not all package functions are thread safe. For example USE-PACKAGE while the package itself is being modified may bring some surprising results. INTERN does not cause deadlocks anymore but simultaneous symbol lookup (while the internal hashtable is rehashed) may return wrong values. This is a major issue. 2. CLOS is not thread safe (adding/redefining classes, generic functions, structures). 3. I think some hashtable functions may go in infinite loops if modified from multiple threads simultaneously without any synchronization. This is not to say that I want to add internal synchronization to them (may be just as an option) but at least we should prevent this. 4. The printer/reader are slow when they check for circularities (currently use lisp hashtable and conses a lot). 5. Documentation and tests > I don't see a timeout macro. Should I be trying to write my own? There is with-timeout (in threads.lisp) and it is exported: (defmacro with-timeout ((seconds &body timeout-forms) &body body) "Execute BODY; if execution takes more than SECONDS seconds, terminate and evaluate TIMEOUT-FORMS." `(call-with-timeout ,seconds (lambda () ,@timeout-forms) (lambda () ,@body))) seconds can be just part of the second i.e. 0.2. Vladimir |
From: Sam S. <sd...@gn...> - 2009-01-26 23:33:53
|
Hi, Vladimir Tzankov wrote: > > With POSIX-THREADS all exported thread functions are implemented with > exception of: THREAD-WAIT and THREAD-STATE. The first should do some > polling when the predicate is not a lock. For the latter - I am not > sure that it is needed at all. I think it is useful to be able to find out whether a thread is sleeping or running. > There are several things that have to be changed in the runtime. > 1. Not all package functions are thread safe. For example USE-PACKAGE > while the package itself is being modified may bring some surprising > results. INTERN does not cause deadlocks anymore but simultaneous > symbol lookup (while the internal hashtable is rehashed) may return > wrong values. This is a major issue. > 2. CLOS is not thread safe (adding/redefining classes, generic > functions, structures). I think we need a global "language" mutex, which would be acquired by LOAD. If re-acquiring an already held mutex costs nothing, we can also re-acquire it for make-package et al (in that case we might even have separate locks for CLOS and each package, as well as O(package_list)). if not - tough luck, the user would have to take care. alas, this, essentially removes packages from the realm of user data structures and into the domain of "system programming". also, using read-from-string as a cheap general-purpose parses would all of a sudden require getting a mutex... > 3. I think some hashtable functions may go in infinite loops if > modified from multiple threads simultaneously without any > synchronization. This is not to say that I want to add internal > synchronization to them (may be just as an option) but at least we > should prevent this. I think this is one of the cases where they user can shoot himself in the foot, and we can do little to help. I don't think mutexing every HT operation is viable. The user would have to be careful. > 4. The printer/reader are slow when they check for circularities > (currently use lisp hashtable and conses a lot). yes, this is a major issue. > 5. Documentation and tests Sam. |
From: Vladimir T. <vtz...@gm...> - 2009-01-27 15:59:29
|
On Jan 27, 2009, at 1:33 AM, Sam Steingold wrote: > Hi, >> There are several things that have to be changed in the runtime. >> 1. Not all package functions are thread safe. For example USE-PACKAGE >> while the package itself is being modified may bring some surprising >> results. INTERN does not cause deadlocks anymore but simultaneous >> symbol lookup (while the internal hashtable is rehashed) may return >> wrong values. This is a major issue. >> 2. CLOS is not thread safe (adding/redefining classes, generic >> functions, structures). > > I think we need a global "language" mutex, which would be acquired > by LOAD. > If re-acquiring an already held mutex costs nothing, we can also re- > acquire it for make-package et al (in that case we might even have > separate locks for CLOS and each package, as well as O(package_list)). > if not - tough luck, the user would have to take care. This is not going to solve all concurrency issues. I've added a mutex to every package so we can guard against concurrent modifications. However when "single" operation modifies/ accesses 2 or more packages - it is not safe to acquire all the package mutexes (order of acquisition is important in order to prevent deadlocks) (USE-PACKAGE is example). O(all_packages) is guarded by it's own mutex. If a thread is in INTERN rehashing the internal hashtable (INTERN is guarded by the package lock now) and another thread look-ups symbols from this package (this is not guarded - there will be performance issues if we do) - wrong results are possible. Solution to this is to implement lock-free hashtable. For this we need to implement/find portable atomic operations library (at least for the architectures on which threads will run). > >> 3. I think some hashtable functions may go in infinite loops if >> modified from multiple threads simultaneously without any >> synchronization. This is not to say that I want to add internal >> synchronization to them (may be just as an option) but at least we >> should prevent this. > > I think this is one of the cases where they user can shoot himself > in the foot, and we can do little to help. > I don't think mutexing every HT operation is viable. > The user would have to be careful. I agree that the user should be careful - in above scenario he will definitely not get what he expects. But I would like to prevent infinite loops. >> 4. The printer/reader are slow when they check for circularities >> (currently use lisp hashtable and conses a lot). > > yes, this is a major issue. I think simple hashtable (not a lisp one and not allocated on lisp heap) based on the object address will do much better. Will experiment with it. Vladimir |
From: Kaz K. <kky...@gm...> - 2009-01-28 03:17:18
|
On Mon, Jan 26, 2009 at 3:33 PM, Sam Steingold <sd...@gn...> wrote: > Hi, > > Vladimir Tzankov wrote: >> >> With POSIX-THREADS all exported thread functions are implemented with >> exception of: THREAD-WAIT and THREAD-STATE. The first should do some >> polling when the predicate is not a lock. For the latter - I am not >> sure that it is needed at all. > > I think it is useful to be able to find out whether a thread is sleeping or > running. I do not agree. This kind of operation, though seemingly useful on the surface, is not useful in robust multithreaded programming. Why it seems useful is obvious. A thread is an object, right? And it has states like running and sleeping. So why not have accessors for the state? The question is, what are you going to do with them. Their use is fraught with race conditions. By the time you make any decision based on whether a thread is sleeping or not, that state could have changed. Suppose that a thread is one instruction away from making a blocking system trap into the kernel. Do you regard that thread as sleeping? Why or why not? Do you try to use the information to try to manage the thread? E.g. ``if thread is not sleeping, put it to sleep?'' Isn't that trying to do the scheduler's job, only without having access to the kernel data structures to do it properly? You can use threads to write active objects (i.e. higher level abstractions over threads) which exhibit such states, and do exactly what you want according to some sane concurrency rules. I.e. some multithreaded object can have an "active" and "inactive" state, along with thread-safe mechanisms to request a transition from one to the other, and be notified of its completion. To implement things like that, you don't need to peek at low level thread states. |
From: <don...@is...> - 2009-01-28 02:36:31
|
Vladimir Tzankov writes: > ./configure --with-threads=POSIX_THREADS Below is the transcript on a 64 bit machine running linux. Let me know what I'm doing wrong or how to proceed. In the mean while perhaps I'll try a 32 bit machine. [2009-01-27 18:21:12 root@number11 ~/clisp] $ ./configure CC='gcc -m64' --with-libsigsegv-prefix=/usr/local --disable-maintainer-mode --with-module=rawsock all above is what I've used to build non-MT I now just add the with-threads and change the directory. --with-threads=POSIX_THREADS build-mt ... To continue building CLISP, the following commands are recommended (cf. unix/INSTALL step 4 ff): cd build-mt vi config.lisp # The default stack size on your platform is insufficient # and must be increased to at least 16384. You must do either # 'ulimit -s 16384' (for Bourne shell derivatives, e.g., bash and zsh) # or 'limit stacksize 16384' (for C shell derivarives, e.g., tcsh) make make check [2009-01-27 18:22:43 root@number11 ~/clisp] $ ulimit -s 16384 [2009-01-27 18:23:06 root@number11 ~/clisp] $ cd build-mt [2009-01-27 18:23:18 root@number11 ~/clisp/build-mt] $ make ... ;; Loading file ../src/type.lisp ... ;; Loading file ../src/subtypep.lisp ... *** - handle_fault error2 ! address = 0xc00000006 not in [0x334308000,0x334370d38) ! SIGSEGV cannot be cured. Fault address = 0xc00000006. GC count: 12 Space collected by GC: 4333520 Run time: 1 30842 Real time: 1 374546 GC time: 0 34996 Permanently allocated: 176136 bytes. Currently in use: 1937208 bytes. Free space: 0 bytes. make: *** [interpreted.mem] Segmentation fault [2009-01-27 18:24:23 root@number11 ~/clisp/build-mt] $ |
From: <don...@is...> - 2009-01-28 02:59:35
|
Don Cohen writes: > In the mean while perhaps I'll try a 32 bit machine. This gives a result similar to that reported by Jose A. Ortega Ruiz: [2009-01-27 18:37:22 root@don-eve /tmp/clisp] $ ./configure --disable-maintainer-mode --with-module=rawsock --with-threads=POSIX_THREADS build-mt ... [2009-01-27 18:39:19 root@don-eve /tmp/clisp] $ cd build-mt [2009-01-27 18:39:58 root@don-eve /tmp/clisp/build-mt] $ ulimit -s 16384 [2009-01-27 18:40:00 root@don-eve /tmp/clisp/build-mt] $ make ... MODPREP: wrote gettext.m.c (121,270 bytes) gcc -Igllib -g -O2 -W -Wswitch -Wcomment -Wpointer-arith -Wimplicit -Wreturn-type -Wmissing-declarations -Wno-sign-compare -Wno-format-nonliteral -O2 -fexpensive-optimizations -falign-functions=4 -pthread -DUNICODE -DMULTITHREAD -DPOSIX_THREADS -I. -I$(/tmp/clisp/build-mt/clisp -K boot -B /tmp/clisp/build-mt -N /tmp/clisp/build-mt/locale -E UTF-8 -Epathname 1:1 -Emisc 1:1 -norc -q -b)/linkkit -c gettext.m.c -o gettext.o In file included from gettext.c:13: /tmp/clisp/build-mt/linkkit/clisp.h:4305:21: error: xthread.c: No such file or directory In file included from gettext.c:13: /tmp/clisp/build-mt/linkkit/clisp.h:4316: error: syntax error before 'spinlock_t' /tmp/clisp/build-mt/linkkit/clisp.h:4316: warning: no semicolon at end of struct or union ... |
From: Vladimir T. <vtz...@gm...> - 2009-01-28 07:16:54
|
There is a problem in building the full and base linking sets (xthread.c is included from clisp.h and cannot be found). If you make a symbolic link to xthread.c in your linkkit/ folder it should build build fine (not sure when this problem apeared). cd linkkit ln -s ../xthread.c . cd .. make Vladimir On Wed, Jan 28, 2009 at 4:59 AM, Don Cohen <don...@is...> wrote: > Don Cohen writes: > > In the mean while perhaps I'll try a 32 bit machine. > > This gives a result similar to that reported by Jose A. Ortega Ruiz: > [2009-01-27 18:37:22 root@don-eve /tmp/clisp] > $ ./configure --disable-maintainer-mode --with-module=rawsock > --with-threads=POSIX_THREADS build-mt > ... > [2009-01-27 18:39:19 root@don-eve /tmp/clisp] > $ cd build-mt > [2009-01-27 18:39:58 root@don-eve /tmp/clisp/build-mt] > $ ulimit -s 16384 > [2009-01-27 18:40:00 root@don-eve /tmp/clisp/build-mt] > $ make > ... > MODPREP: wrote gettext.m.c (121,270 bytes) > gcc -Igllib -g -O2 -W -Wswitch -Wcomment -Wpointer-arith -Wimplicit > -Wreturn-type -Wmissing-declarations -Wno-sign-compare -Wno-format-nonliteral -O2 > -fexpensive-optimizations -falign-functions=4 -pthread -DUNICODE -DMULTITHREAD > -DPOSIX_THREADS -I. -I$(/tmp/clisp/build-mt/clisp -K boot -B > /tmp/clisp/build-mt -N /tmp/clisp/build-mt/locale -E UTF-8 -Epathname 1:1 -Emisc 1:1 -norc -q > -b)/linkkit -c gettext.m.c -o gettext.o > In file included from gettext.c:13: > /tmp/clisp/build-mt/linkkit/clisp.h:4305:21: error: xthread.c: No such > file or directory > In file included from gettext.c:13: > /tmp/clisp/build-mt/linkkit/clisp.h:4316: error: syntax error before > 'spinlock_t' > /tmp/clisp/build-mt/linkkit/clisp.h:4316: warning: no semicolon at end > of struct or union > ... > |
From: <don...@is...> - 2009-01-28 08:51:48
|
Vladimir Tzankov writes: > There is a problem in building the full and base linking sets > (xthread.c is included from clisp.h and cannot be found). > If you make a symbolic link to xthread.c in your linkkit/ folder it > should build build fine (not sure when this problem apeared). > > cd linkkit > ln -s ../xthread.c . > cd .. > make This works for me (in the 32 bit case). I suggest that something be added to *features* for MT. I find that when I do saveinitmem with :executable t from the resulting build, I cannot run the result: $ ./save2 module 'syscalls' requires package OS. |
From: Jose A. O. R. <ja...@gn...> - 2009-01-28 09:08:27
|
Vladimir Tzankov <vtz...@gm...> writes: > There is a problem in building the full and base linking sets > (xthread.c is included from clisp.h and cannot be found). > If you make a symbolic link to xthread.c in your linkkit/ folder it > should build build fine (not sure when this problem apeared). > > cd linkkit > ln -s ../xthread.c . > cd .. > make > Thank you, that worked: the compilation succeeds. But 'make check' ends with the following error: --8<---------------cut here---------------start------------->8--- ./foo -x "(setq zz 10) (saveinitmem \"foo\")" i i i i i i i ooooo o ooooooo ooooo ooooo I I I I I I I 8 8 8 8 8 o 8 8 I \ `+' / I 8 8 8 8 8 8 \ `-+-' / 8 8 8 ooooo 8oooo `-__|__-' 8 8 8 8 8 | 8 o 8 8 o 8 8 ------+------ ooooo 8oooooo ooo8ooo ooooo 8 Welcome to GNU CLISP 2.47+ (2008-10-24) <http://clisp.cons.org/> Copyright (c) Bruno Haible, Michael Stoll 1992, 1993 Copyright (c) Bruno Haible, Marcus Daniels 1994-1997 Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998 Copyright (c) Bruno Haible, Sam Steingold 1999-2000 Copyright (c) Sam Steingold, Bruno Haible 2001-2008 Type :h and hit Enter for context help. WARNING: No installation directory specified. Please try: ./foo -B /usr/local/lib/clisp 10 *** - EVAL: undefined function SAVEINITMEM Bye. --8<---------------cut here---------------end--------------->8--- Cheers, jao |
From: Sam S. <sd...@gn...> - 2009-01-28 15:29:11
|
Jose A. Ortega Ruiz wrote: > > --8<---------------cut here---------------start------------->8--- > ./foo -x "(setq zz 10) (saveinitmem \"foo\")" > > WARNING: No installation directory specified. > Please try: ./foo -B /usr/local/lib/clisp > 10 > *** - EVAL: undefined function SAVEINITMEM > Bye. > --8<---------------cut here---------------end--------------->8--- Vladimir, does saveinitmem work in MT builds? PS. this discussion belongs in clisp-devel, not clisp-list. follow-ups set. PPS. reminder: please do NOT cross-port to both lists. http://clisp.cons.org/impnotes/faq.html#faq-mailing-lists |
From: Sam S. <sd...@gn...> - 2009-01-28 15:27:35
|
Vladimir Tzankov wrote: > There is a problem in building the full and base linking sets > (xthread.c is included from clisp.h and cannot be found). > If you make a symbolic link to xthread.c in your linkkit/ folder it > should build build fine (not sure when this problem apeared). > > cd linkkit > ln -s ../xthread.c . > cd .. > make this is OK as a temp workaround, but no good long term. the necessary definitions should be exported the same was as in lispbibl.d, i.e., using "%%". we do NOT want any "#if"s in clisp.h. PS. this discussion belongs in clisp-devel, not clisp-list. follow-ups set. PPS. reminder: please do NOT cross-port to both lists. http://clisp.cons.org/impnotes/faq.html#faq-mailing-lists |
From: Jose A. O. R. <ja...@gn...> - 2009-01-27 23:08:23
|
Hi, Vladimir Tzankov <vtz...@gm...> writes: > Hi, > On 1/26/09, Don Cohen <don...@is...> wrote: >> I've been watching with great interest the recent progress in clisp >> threads and I find that I could really use a (with-timeout ...) >> facility. Is this thought to be working well enough to be worth >> trying to use? > > I would say - yes. When built with POSIX_THREADS (linux, osx, may be > solaris) it works well. > >>Where can I find instructions for building with threads and doing >>something with a time limit? > > ./configure --with-threads=POSIX_THREADS > Trying to build on Linux, with a fresh checkout of the CVS HEAD tree, i've got this error: In file included from gettext.c:13: /home/jao/usr/share/lisp/src/clisp/build-mt/linkkit/clisp.h:4400:21: error: xthread.c: No such file or directory In file included from gettext.c:13: /home/jao/usr/share/lisp/src/clisp/build-mt/linkkit/clisp.h:4411: error: expected specifier-qualifier-list before âspinlock_tâ followed by many linkage errors in gettext.c. Do i need to get any other branch of the CVS tree? Thanks for any hints. Cheers, jao |
From: Sam S. <sd...@gn...> - 2009-01-28 15:35:57
|
Kaz Kylheku wrote: > On Mon, Jan 26, 2009 at 3:33 PM, Sam Steingold <sd...@gn...> wrote: > This kind of operation, though seemingly useful on the surface, is not > useful in robust multithreaded programming. > > The question is, what are you going to do with them. Their use is > fraught with race conditions. By the time you make any decision based > on whether a thread is sleeping or not, that state could have changed. why do other cl implementations offer this function? some even make it SETFable! http://www.scieneer.com/scl/doc/function/mp/process-whostate.html http://www.franz.com/support/documentation/6.0/doc/pages/operators/mp/process-whostate.htm http://www.lispworks.com/documentation/lw51/LWRM/html/lwref-449.htm |
From: Stelian I. <ste...@po...> - 2009-01-28 15:50:50
|
On Wed, 2009-01-28 at 10:35 -0500, Sam Steingold wrote: > Kaz Kylheku wrote: > > On Mon, Jan 26, 2009 at 3:33 PM, Sam Steingold <sd...@gn...> wrote: > > This kind of operation, though seemingly useful on the surface, is not > > useful in robust multithreaded programming. > > > > The question is, what are you going to do with them. Their use is > > fraught with race conditions. By the time you make any decision based > > on whether a thread is sleeping or not, that state could have changed. > > why do other cl implementations offer this function? The adventurous world of commercial software: you need to give the customers what they ask, even if it doesn't make sense. > some even make it SETFable! It can only be safely SETFable if the host implementation is running green threads - like Allegro and LW. -- Stelian Ionescu a.k.a. fe[nl]ix Quidquid latine dictum sit, altum videtur. |
From: Kaz K. <kky...@gm...> - 2009-02-03 23:39:56
|
[ This has been sitting forgotten in my Drafts folder ] On Wed, Jan 28, 2009 at 7:35 AM, Sam Steingold <sd...@gn...> wrote: > Kaz Kylheku wrote: >> >> On Mon, Jan 26, 2009 at 3:33 PM, Sam Steingold <sd...@gn...> wrote: >> This kind of operation, though seemingly useful on the surface, is not >> useful in robust multithreaded programming. >> >> The question is, what are you going to do with them. Their use is >> fraught with race conditions. By the time you make any decision based >> on whether a thread is sleeping or not, that state could have changed. > > why do other cl implementations offer this function? > some even make it SETFable! I would say that it's because their designs and implementations are heavily outdated, going back to the dark ages before there was more wide spread awareness about good system designs for multithreading, and good practices at the application level. Come on, the threading models in some Lisps are just ridiculous and primitive. Where in POSIX or Win32 can you call to find out these thread states? On Linux, this function would have to open virtual files under /proc/<pid>. > http://www.scieneer.com/scl/doc/function/mp/process-whostate.html > http://www.franz.com/support/documentation/6.0/doc/pages/operators/mp/process-whostate.htm > http://www.lispworks.com/documentation/lw51/LWRM/html/lwref-449.htm This is all bad, outdated multithreading that tries to maintain compability between two threading models (the real OS threads and fake ones) by building silly cruft on top of the OS threads that does not make sense. For instance, take a look at the process-wait function supported in these Lisps. The purpose is to suspend a thread until some predicate becomes true. Anyone who knows anything about sane multithreading will immediately recognize this kind of interface being out of place under preemptive multitasking or multiprocessing. It's a throwback to cooperative multitasking. There is no correct way to use this function if threads are preemptive, or truly concurrent on multiple processors, because the calling thread does not hold any lock that can preserve the truth value of the predicate, or ensure that the wakeup from another thread is not lost. It is like a condition variable wait, but without the mutex to resolve races. C. A. R. Hoare invented the concept of waiting until a condition happens, i.e. the same thing as process-wait. He described it in a 1974 paper called _Monitors: an operating system structuring concept_ To do the equivalent of process-wait, you have to be in a monitor, which is implicitly given up during the wait. These guys didn't read the paper. Or maybe their implementations even pre-date 1974. LispWorks does implement the monitor erquirement. How? By not allowing any real concurrency. Come on, the 1970's are calling and want their multithreading back. Housewives now have multi-core laptop computers that they use for sharing recipes. :) Please, don't copy any of this braindamage in CLISP. If a compatibility layer is desireable for porting applications that depend on the threading models in these Lisps, that can be done as a separate API project. All of the threads using such an API can be made cooperative relative to just each other each other (by locking a big mutex). |