From rcolebur at SCIRES.COM Sat Aug 2 03:08:34 2014 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sat, 2 Aug 2014 01:08:34 +0000 Subject: [M3devel] Fwd: Re: Fwd: Fork bug Message-ID: <0BB8FA59C2932741A3A2941A8B9D8BFF9324F0F6@ATLEX04-SRV.SCIRES.LOCAL> Sorry for the delay in responding, but I've been out on travel. In Trestle the authors devised the concept of Locking Levels and used LL pragmas in the code so that proper ordering could be verified. Actually, the problem comes up in other multi-threaded situations and the coder has to take all this into consideration to prevent getting into a deadlock or starvation situation. I've used partial ordering techniques similar to what was done in Trestle to solve this problem. I do NOT favor the proposed change in MUTEX. In addition to locking levels/orders, there are different abstractions that sometimes should be used instead of MUTEX. I have written several such abstractions. For example, ConcurrencyControl.i3: Provide for a mechanism to achieve concurrency control. The abstraction provided is one of readers and writers, where at any instance of time there can be either zero or more readers, or zero or one writer, that is at time t one and only one of the following 3 conditions applies: 1. (numReaders = 0) AND (numWriters = 0). 2. (numReaders > 0) AND (numWriters = 0). 3. (numReaders = 0) AND (numWriters = 1). For example, GateKeeper.i3: Provide an abstraction for controlling concurrency. The abstraction is that of a gatekeeper who can lock/unlock the gate and who regulates entry/exit via the gate, thereby controlling the number of occupants. I can probably arrange to share some of this code if desired. --Randy Coleburn -----Original Message----- From: Rodney M. Bates [mailto:rodney_bates at lcwb.coop] Sent: Tuesday, July 08, 2014 3:20 PM To: m3devel Subject: EXT:[M3devel] Fwd: Re: Fwd: Fork bug Resent after 24 hours: While we are working on MUTEX, I would like to propose making them what I believe is meant by a recursive mutex, that is, one thread can lock multiple times, the mutex being released only when the number of unlocks catches up with the number of locks. I don't remember the details off the top of my head, but there is a place in Trestle where you have to acquire a MUTEX but it is very difficult or impossible to know whether different code on the same thread already has done so. The different code isn't under your control either. Some runtime scheme to figure it out dynamically would be tantamount to, but messier than, just having a recursive MUTEX. I recall there are other places as well where similar problems arise. It would greatly simplify things when needed. The only disadvantage I can think of is there might be a case where runtime detection of a second lock attempt by the same thread would help find a bug. Maybe the RTS could have a way of setting the behavior of a specific MUTEX. On 07/03/2014 02:28 PM, Tony Hosking wrote: > I wonder if we should not move to a surrogate parent model to make this cleaner in general? > Since fork is (or should be) only used in service of creating a new process (i.e., fork + exec) then this technique would save us a lot of grief. > Thoughts? > > In the surrogate parent model, a program forks a child process at initialization time. The sole purpose of the child is to serve as a sort of "surrogate parent" for the original process should it ever need to fork another child. After initialization, the original parent can proceed to create its additional threads. When it wants to /exec/ an image, it communicates this to its child (which has remained single-threaded). The child then performs the /fork/ and /exec/ on behalf of the original process. > > > > Begin forwarded message: > >> *From: *Peter McKinna > > >> *Subject: **Fork bug* >> *Date: *July 2, 2014 at 10:30:24 PM EDT >> *To: *Antony Hosking > > >> >> Hi Tony, >> >> That fork bug on posix doesn't appear to be fixed, so just to recap the problem. In the threadtest program if you have a bunch of threads creating mutexes and having them collected then get a thread that does a few forks what can happen is that the child executes atforkchild as I think the first thing it does which calls initwithstackbase which does an allocation and possible collection. Unfortunately the weaktable from the parent may be non empty and this is the only thread executing. It calls the cleanup of those mutexes of nonexistant threads some of which may be locked. If they are locked then pthread_mutex_destroy returns ebusy. Then the child exits with the abort in pthread_mutex_delete. >> Whether the abort is needed I dont know. In this case the error can be safely ignored. One could try to see if the owner of the mutex is still alive and not abort in that case. Otherwise if one is sure the child is going to do an exec almost immediately then disabling the collector in atforkchild could work. >> In the broader picture anything thats got a weak ref still active could cause problems if one thread does a fork. The weak callback could do anything. >> Anyway I dont know what the fix is. >> >> Peter > -- Rodney Bates rodney.m.bates at acm.org From mika at async.caltech.edu Sat Aug 9 21:16:04 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sat, 09 Aug 2014 12:16:04 -0700 Subject: [M3devel] deadlock in pthreads?? Message-ID: <20140809191604.12DCD1A209C@async.async.caltech.edu> Hi m3devel (mainly Tony), I am finally trying to join the rest of you in using pthreads since you say it works and now I really need it for my next project. I am on AMD64_LINUX, with two compilers installed, source code as of January for those: 1. user threads --- what I normally use with no problems 2. pthreads --- built it but don't use it because it's from before the final fixes that I am told make the thread tester work (144)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>uname -a Linux truffles 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 GNU/Linux (147)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>cm3 -version Critical Mass Modula-3 version d5.9.0 last updated: 2010-07-21 compiled: 2014-01-03 04:15:06 configuration: /home/mika/bsd/cm3-boot2/bin/cm3.cfg host: AMD64_LINUX target: AMD64_LINUX What I did: cvs update -d cm3 (cvs update everything) Then I tried: I. with existing user threads compiler ./upgrade.sh upgraded my compiler "successfully"---see below for results II. with existing pthreads compiler 1. ./upgrade.sh upgraded my compiler "successfully"---see below for results 2. started over and did manual upgrade process per Tony's instructions a while back (attached) upgraded my compiler "successfully"---see below for results RESULTS IN ALL CASES ABOVE: when running finished compiler, it sometimes deadlocks. "Sometimes" = frequently enough that every build breaks. "Sometimes not" seems to only be in gdb. Here is a traceback: (98)truffles:~/bsd/src>gdb cm3 GNU gdb (GDB) 7.4.1-debian Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /big/home/mika/cm3-boot2.pthreads/bin/cm3...done. (gdb) run Starting program: /big/home/mika/cm3-boot2.pthreads/bin/cm3 [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". --- building in ../AMD64_LINUX --- [New Thread 0x2aaaab6f8700 (LWP 29517)] ^C Program received signal SIGINT, Interrupt. __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 136 ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: No such file or directory. (gdb) where #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaaaf59339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaaaf5915b in __pthread_mutex_lock (mutex=0x12d00e0) at pthread_mutex_lock.c:61 #3 0x0000000000720af8 in ThreadPThread__pthread_mutex_lock (mutex=0x12d00e0) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x000000000071ab5f in ThreadPThread__UnlockMutex (M3_AYIbX3_m=) at ../src/thread/PTHREAD/ThreadPThread.m3:151 #5 0x000000000071b018 in ThreadPThread__XWait (M3_DMxDjQ_self=, M3_AYIbX3_m=, M3_Bl0jv4_c=, M3_AicXUJ_alertable=) at ../src/thread/PTHREAD/ThreadPThread.m3:204 #6 0x000000000071d313 in ThreadPThread__XJoin (M3_DMxDjQ_self=, M3_BXP32l_t=, M3_AicXUJ_alertable=) at ../src/thread/PTHREAD/ThreadPThread.m3:557 #7 0x000000000071d462 in Thread__Join (M3_BXP32l_t=) at ../src/thread/PTHREAD/ThreadPThread.m3:569 #8 0x000000000040da95 in Builder__ForceAllPromisesInParallel (M3_C58HwX_promises=, M3_Cwb5VA_parallelism=) at ../src/Builder.m3:1002 #9 0x000000000040e083 in Builder__CompileEverything (M3_DqhcFh_s=, M3_AE6M8L_schedule=) at ../src/Builder.m3:1038 #10 0x0000000000408ce3 in Builder__CompileUnits (M3_Bd56fi_main=, M3_ClaoYw_units=, M3_C1FTrk_sys_libs=, M3_A2QN6Z_info_kind=, M3_An02H2_mach=) at ../src/Builder.m3:337 #11 0x000000000040726b in Builder__BuildPgm (M3_Bd56fi_prog=, M3_ClaoYw_units=, M3_C1FTrk_sys_libs=, M3_AicXUJ_shared=, M3_An02H2_m=) at ../src/Builder.m3:28 #12 0x0000000000425d6f in M3Build__BuildProgram (M3_ABp1Zk_t=, M3_DLS2Hj_nm=) at ../src/M3Build.m3:1515 #13 0x0000000000425bb7 in M3Build__DoProgram (M3_An02H2_m=, M3_AcxOUs_n_args=) at ../src/M3Build.m3:1491 #14 0x00000000004d0cf9 in QMachine__DoCall (M3_An02H2_t=, M3_AcxOUs_n_args=, M3_AicXUJ_isFunc=, M3_AicXUJ_outer=) at ../src/QMachine.m3:546 #15 0x00000000004cf98b in QMachine__Eval (M3_An02H2_t=) at ../src/QMachine.m3:422 #16 0x00000000004cdcb3 in QMachine__Evaluate (M3_An02H2_t=, M3_CYwAos_s=) at ../src/QMachine.m3:165 #17 0x00000000004c4764 in Quake__Run (M3_An02H2_m=, M3_Bd56fi_source_file=) at ../src/Quake.m3:19 #18 0x000000000041f789 in M3Build__Run (M3_ABp1Zk_t=, M3_Bd56fi_makefile=) at ../src/M3Build.m3:242 #19 0x0000000000437b9f in Main__DoIt () at ../src/Main.m3:117 #20 0x0000000000437f23 in Main_M3 (M3_AcxOUs_mode=) at ../src/Main.m3:231 #21 0x000000000070d749 in RTLinker__RunMainBody (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:408 #22 0x000000000070cad4 in RTLinker__AddUnitI (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:115 #23 0x000000000070cb68 in RTLinker__AddUnit (M3_DjPxE5_b=) at ../src/runtime/common/RTLinker.m3:124 #24 0x00000000004061a8 in main (argc=1, argv=0x7fffffffe388, envp=0x7fffffffe398) at _m3main.c:22 (gdb) Below are the instructions I've been using in case II. 2. above. Note that cm3cg doesn't get installed when following the instructions! I'm not sure what does that, I have to copy it manually from the derived dir to the bin dir for the compiler. Date: Sun, 24 Jun 2007 10:38:34 EDT To: Mika Nystrom cc: m3devel at elegosoft.de From: Tony Hosking Subject: Re: [M3devel] strange errors... Return-Path: hosking at cs.purdue.edu Delivery-Date: Sun Jun 24 07:38:38 2007 In-Reply-To: <200706231838.l5NIcRef079333 at camembert.async.caltech.edu> References: <200706231838.l5NIcRef079333 at camembert.async.caltech.edu> Sounds like we really need some work done in this area. I very rarely use the build scripts, since I bootstrap manually from old compilers to new compilers rather than use the scripts. I suggest the following approach, which I hope you will try, and then report back on. Install the bootstrap compiler as you did originally: > rm -rf /usr/local/cm3/* > > cd ~/cm3-cvs > mkdir boot > cd boot > tar xzvf ../cm3-min-POSIX-FreeBSD4-d5.3.1-2005-10-05.tgz > ./cminstall Now you will have some kind of cm3 installed, presumably in /usr/ local/cm3/bin/cm3. Make sure you have a fresh CVS checkout in directory cm3 (let's assume this is in your home directory ~/cm3). Also, make sure you have an up-to-date version of the CM3 backend compiler cm3cg installed by executing the following: STEP 0: export CM3=/usr/local/cm3/bin/cm3 cd ~/cm3/m3-sys/m3cc $CM3 $CM3 -ship You can skip this last step if you know your backend compiler is up to date. Now, let's build the new compiler from scratch (this is the sequence I use regularly to test changes to the run-time system whenever I make them): can replace compilation step with rm -rf && $CM3 && $CM3 -ship STEP 1: (do these LATER if bootstrapping from old compiler!) cd ~/cm3/m3-libs/m3core $CM3 $CM3 -ship cd ~/cm3/m3-libs/libm3 $CM3 $CM3 -ship Now build the compiler: cd ~/cm3/m3-libs/sysutils ; $CM3 etc. cd ~/cm3/m3-sys/m3middle; $CM3 etc. repeat for: m3-sys/m3objfile m3-sys/m3back m3-sys/m3linker m3-sys/m3front m3-sys/m3quake m3-sys/cm3 [ here we may need -DROOT= ] At this point you should have a bootstrapped version of cm3 installed in the directory /usr/local/cm3/pkg/cm3/TARGET/cm3 (where TARGET is the CM3 target platform you are building on -- e.g., LINUXLIBC6, PPC_DARWIN, ...). Note that this did not overwrite your original installed compiler in /usr/local/cm3/bin/cm3. We are now going to test the new compiler, which was built using the old compiler, by bootstrapping it one more time. (If m3core and libm3 were skipped earlier, do them now, and RE-DO all of the above packages before proceeding.) >From here on out, please replace TARGET with your target platform as appropriate. STEP 2: export CM3=/usr/local/cm3/pkg/cm3/TARGET/cm3 cd ~/cm3/scripts ./do-cm3-std.sh realclean REPEAT STEP 1 to rebuild the libraries and the compiler using the STEP 1 bootstrap compiler. Now you have a STEP 2 bootstrap compiler installed in /usr/local/cm3/ pkg/cm3/TARGET/cm3. Let's assume the new compiler now works properly since it successfully bootstrapped itself, but to be sure we can now use it to rebuild the world: cd ~/cm3/scripts ./do-cm3-std.sh realclean ./do-cm3-std.sh buildship Assuming this succeeded then we can be pretty sure /usr/local/cm3/pkg/ cm3/TARGET/cm3 is good, so we can make it our default compiler by replacing the original /usr/local/cm3/bin/cm3: cp $CM3 /usr/local/cm3/bin/cm3 On Jun 23, 2007, at 2:38 PM, Mika Nystrom wrote: > Ok, I'm sorry if I seem a bit dimwitted in the morning like this, > but how exactly does one get started? I wish there were a file called > "GETTING_STARTED" or something like that in scripts... ... From mika at async.caltech.edu Sun Aug 10 01:14:43 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sat, 09 Aug 2014 16:14:43 -0700 Subject: [M3devel] deadlock in pthreads?? In-Reply-To: <20140809191604.12DCD1A209C@async.async.caltech.edu> References: <20140809191604.12DCD1A209C@async.async.caltech.edu> Message-ID: <20140809231443.1045C1A209C@async.async.caltech.edu> Another attempt at making progress. I installed FreeBSD 10 on a new machine. Grabbed the modula3 dist using "pkg" root at rover:/home/mika/cm3-cvs-anon/cm3/scripts # pkg info | grep modula3 modula3-5.8.6_3 Critical Mass Modula-3 compiler root at rover:/home/mika/cm3-cvs-anon/cm3/scripts # uname -a FreeBSD rover 10.0-RELEASE FreeBSD 10.0-RELEASE #0 r260789: Thu Jan 16 22:34:59 UTC 2014 root at snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64 The M3 dist that comes with FreeBSD's pkg seems to work fine, although I suspect it has little pthreads issues, since it is quite old. It's also lacking support for parallel building, which I added a couple of years ago. In short, I'd like to upgrade to something more recent. I take my cvs update as of today (now) and try to upgrade. ./upgrade.sh succeeds (somewhat to my surprise) But the resulting compiler is broken: (69)rover:~/m3hello/src>cm3 --- building in ../AMD64_FREEBSD --- new source -> compiling Main.m3 ERROR: pthread_mutex_lock:11 Abort More detail---ironically, it turns out I wrote the code where it is crashing, but there's "no way it can be wrong"... If I had to guess I'd say there's a race condition between Thread.Fork and Thread.Join: the program forks and probably immediately attempts to join. (74)rover:~/m3hello/src>gdb cm3 GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "amd64-marcel-freebsd"... (gdb) run Starting program: /usr/local/bin/cm3 [New LWP 100914] --- building in ../AMD64_FREEBSD --- missing version stamps -> compiling Main.m3 ERROR: pthread_mutex_lock:11 [New Thread 801806400 (LWP 100914/cm3)] Program received signal SIGABRT, Aborted. [Switching to Thread 801806400 (LWP 100914/cm3)] 0x000000080107626a in thr_kill () from /lib/libc.so.7 (gdb) where #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 #1 0x000000080113dac9 in abort () from /lib/libc.so.7 #2 0x000000000071e206 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ffffc4f8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 #3 0x000000000071837b in ThreadPThread__UnlockMutex (M3_AYIbX3_m=Error accessing memory address 0x8000ffffc528: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:151 #4 0x0000000000718834 in ThreadPThread__XWait (M3_DMxDjQ_self=Error accessing memory address 0x8000ffffc5a8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:204 #5 0x000000000071ab2f in ThreadPThread__XJoin (M3_DMxDjQ_self=Error accessing memory address 0x8000ffffc608: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:557 #6 0x000000000071ac7e in Thread__Join (M3_BXP32l_t=Error accessing memory address 0x8000ffffc6d8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:569 #7 0x000000000040b38d in Builder__ForceAllPromisesInParallel (M3_C58HwX_promises=Error accessing memory address 0x8000ffffc758: Bad address. ) at ../src/Builder.m3:1002 #8 0x000000000040b97b in Builder__CompileEverything (M3_DqhcFh_s=0x0, M3_AE6M8L_schedule=Error accessing memory address 0x8000ffffc7d8: Bad address. ) at ../src/Builder.m3:1038 #9 0x00000000004065db in Builder__CompileUnits (M3_Bd56fi_main=Error accessing memory address 0x8000ffffc8f8: Bad address. ) at ../src/Builder.m3:337 #10 0x0000000000404b63 in Builder__BuildPgm (M3_Bd56fi_prog=Error accessing memory address 0x8000ffffc9a8: Bad address. ) at ../src/Builder.m3:28 #11 0x0000000000423667 in M3Build__BuildProgram (M3_ABp1Zk_t=Error accessing memory address 0x8000ffffc9e8: Bad address. ) at ../src/M3Build.m3:1515 #12 0x00000000004234af in M3Build__DoProgram (M3_An02H2_m=Error accessing memory address 0x8000ffffca28: Bad address. ) at ../src/M3Build.m3:1491 #13 0x00000000004ce5ed in QMachine__DoCall (M3_An02H2_t=Error accessing memory address 0x8000ffffca88: Bad address. ) at ../src/QMachine.m3:546 #14 0x00000000004cd27f in QMachine__Eval (M3_An02H2_t=Error accessing memory address 0x8000ffffcb28: Bad address. ) at ../src/QMachine.m3:422 #15 0x00000000004cb5a7 in QMachine__Evaluate (M3_An02H2_t=Error accessing memory address 0x8000ffffcc78: Bad address. ) at ../src/QMachine.m3:165 #16 0x00000000004c2058 in Quake__Run (M3_An02H2_m=Error accessing memory address 0x8000ffffcca8: Bad address. ) at ../src/Quake.m3:19 #17 0x000000000041d081 in M3Build__Run (M3_ABp1Zk_t=Error accessing memory address 0x8000ffffcce8: Bad address. ) at ../src/M3Build.m3:242 #18 0x0000000000435497 in Main__DoIt () at ../src/Main.m3:117 #19 0x000000000043581b in Main_M3 (M3_AcxOUs_mode=Error accessing memory address 0x8000ffffceb8: Bad address. ) at ../src/Main.m3:231 #20 0x000000000070af59 in RTLinker__RunMainBody (M3_DjPxE3_m=Error accessing memory address 0x8000ffffced8: Bad address. ) at ../src/runtime/common/RTLinker.m3:408 #21 0x000000000070a2e4 in RTLinker__AddUnitI (M3_DjPxE3_m=Error accessing memory address 0x8000ffffcf58: Bad address. ) at ../src/runtime/common/RTLinker.m3:115 #22 0x000000000070a378 in RTLinker__AddUnit (M3_DjPxE5_b=Error accessing memory address 0x8000ffffcf78: Bad address. ) at ../src/runtime/common/RTLinker.m3:124 #23 0x0000000000403aa6 in main (argc=Error accessing memory address 0x8000ffffcfcc: Bad address. ) at _m3main.c:22 (gdb) mika writes: >Hi m3devel (mainly Tony), > >I am finally trying to join the rest of you in using pthreads since you >say it works and now I really need it for my next project. > >I am on AMD64_LINUX, with two compilers installed, source code as of January for those: > >1. user threads --- what I normally use with no problems > >2. pthreads --- built it but don't use it because it's from before the final fixes > that I am told make the thread tester work > >(144)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>uname -a >Linux truffles 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 GNU/Linux > >(147)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>cm3 -version >Critical Mass Modula-3 version d5.9.0 > last updated: 2010-07-21 > compiled: 2014-01-03 04:15:06 > configuration: /home/mika/bsd/cm3-boot2/bin/cm3.cfg > host: AMD64_LINUX > target: AMD64_LINUX > > >What I did: > >cvs update -d cm3 > >(cvs update everything) > >Then I tried: > >I. with existing user threads compiler > > ./upgrade.sh > > upgraded my compiler "successfully"---see below for results > >II. with existing pthreads compiler > > 1. ./upgrade.sh > > upgraded my compiler "successfully"---see below for results > > 2. started over and did manual upgrade process per Tony's instructions a while back (attached) > > upgraded my compiler "successfully"---see below for results > >RESULTS IN ALL CASES ABOVE: > >when running finished compiler, it sometimes deadlocks. "Sometimes" = frequently enough that every >build breaks. "Sometimes not" seems to only be in gdb. > >Here is a traceback: > >(98)truffles:~/bsd/src>gdb cm3 >GNU gdb (GDB) 7.4.1-debian >Copyright (C) 2012 Free Software Foundation, Inc. >License GPLv3+: GNU GPL version 3 or later >This is free software: you are free to change and redistribute it. >There is NO WARRANTY, to the extent permitted by law. Type "show copying" >and "show warranty" for details. >This GDB was configured as "x86_64-linux-gnu". >For bug reporting instructions, please see: >... >Reading symbols from /big/home/mika/cm3-boot2.pthreads/bin/cm3...done. >(gdb) run >Starting program: /big/home/mika/cm3-boot2.pthreads/bin/cm3 >[Thread debugging using libthread_db enabled] >Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". >--- building in ../AMD64_LINUX --- > >[New Thread 0x2aaaab6f8700 (LWP 29517)] >^C >Program received signal SIGINT, Interrupt. >__lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 >136 ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: No such file or directory. >(gdb) where >#0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 >#1 0x00002aaaaaf59339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 >#2 0x00002aaaaaf5915b in __pthread_mutex_lock (mutex=0x12d00e0) at pthread_mutex_lock.c:61 >#3 0x0000000000720af8 in ThreadPThread__pthread_mutex_lock (mutex=0x12d00e0) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >#4 0x000000000071ab5f in ThreadPThread__UnlockMutex (M3_AYIbX3_m=) at ../src/thread/PTHREAD/ThreadPThread.m3:151 >#5 0x000000000071b018 in ThreadPThread__XWait (M3_DMxDjQ_self=, M3_AYIbX3_m=, M3_Bl0jv4_c=, M3_AicXUJ_alertable=iable>) at ../src/thread/PTHREAD/ThreadPThread.m3:204 >#6 0x000000000071d313 in ThreadPThread__XJoin (M3_DMxDjQ_self=, M3_BXP32l_t=, M3_AicXUJ_alertable=) at ../src/thread/PTHREAD/Threa >dPThread.m3:557 >#7 0x000000000071d462 in Thread__Join (M3_BXP32l_t=) at ../src/thread/PTHREAD/ThreadPThread.m3:569 >#8 0x000000000040da95 in Builder__ForceAllPromisesInParallel (M3_C58HwX_promises=, M3_Cwb5VA_parallelism=) at ../src/Builder.m3:1002 >#9 0x000000000040e083 in Builder__CompileEverything (M3_DqhcFh_s=, M3_AE6M8L_schedule=) at ../src/Builder.m3:1038 >#10 0x0000000000408ce3 in Builder__CompileUnits (M3_Bd56fi_main=, M3_ClaoYw_units=, M3_C1FTrk_sys_libs=, M3_A2QN6Z_info_kind= reading variable>, > M3_An02H2_mach=) at ../src/Builder.m3:337 >#11 0x000000000040726b in Builder__BuildPgm (M3_Bd56fi_prog=, M3_ClaoYw_units=, M3_C1FTrk_sys_libs=, M3_AicXUJ_shared=g variable>, M3_An02H2_m=) > at ../src/Builder.m3:28 >#12 0x0000000000425d6f in M3Build__BuildProgram (M3_ABp1Zk_t=, M3_DLS2Hj_nm=) at ../src/M3Build.m3:1515 >#13 0x0000000000425bb7 in M3Build__DoProgram (M3_An02H2_m=, M3_AcxOUs_n_args=) at ../src/M3Build.m3:1491 >#14 0x00000000004d0cf9 in QMachine__DoCall (M3_An02H2_t=, M3_AcxOUs_n_args=, M3_AicXUJ_isFunc=, M3_AicXUJ_outer=able>) at ../src/QMachine.m3:546 >#15 0x00000000004cf98b in QMachine__Eval (M3_An02H2_t=) at ../src/QMachine.m3:422 >#16 0x00000000004cdcb3 in QMachine__Evaluate (M3_An02H2_t=, M3_CYwAos_s=) at ../src/QMachine.m3:165 >#17 0x00000000004c4764 in Quake__Run (M3_An02H2_m=, M3_Bd56fi_source_file=) at ../src/Quake.m3:19 >#18 0x000000000041f789 in M3Build__Run (M3_ABp1Zk_t=, M3_Bd56fi_makefile=) at ../src/M3Build.m3:242 >#19 0x0000000000437b9f in Main__DoIt () at ../src/Main.m3:117 >#20 0x0000000000437f23 in Main_M3 (M3_AcxOUs_mode=) at ../src/Main.m3:231 >#21 0x000000000070d749 in RTLinker__RunMainBody (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:408 >#22 0x000000000070cad4 in RTLinker__AddUnitI (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:115 >#23 0x000000000070cb68 in RTLinker__AddUnit (M3_DjPxE5_b=) at ../src/runtime/common/RTLinker.m3:124 >#24 0x00000000004061a8 in main (argc=1, argv=0x7fffffffe388, envp=0x7fffffffe398) at _m3main.c:22 >(gdb) > >Below are the instructions I've been using in case II. 2. above. > >Note that cm3cg doesn't get installed when following the instructions! I'm not sure what does that, I have to copy it manually from the derived dir to the bin dir for the compiler. > > >Date: Sun, 24 Jun 2007 10:38:34 EDT >To: Mika Nystrom >cc: m3devel at elegosoft.de >From: Tony Hosking >Subject: Re: [M3devel] strange errors... > >Return-Path: hosking at cs.purdue.edu >Delivery-Date: Sun Jun 24 07:38:38 2007 >In-Reply-To: <200706231838.l5NIcRef079333 at camembert.async.caltech.edu> >References: <200706231838.l5NIcRef079333 at camembert.async.caltech.edu> > >Sounds like we really need some work done in this area. I very >rarely use the build scripts, since I bootstrap manually from old >compilers to new compilers rather than use the scripts. I suggest >the following approach, which I hope you will try, and then report >back on. > >Install the bootstrap compiler as you did originally: > >> rm -rf /usr/local/cm3/* >> >> cd ~/cm3-cvs >> mkdir boot >> cd boot >> tar xzvf ../cm3-min-POSIX-FreeBSD4-d5.3.1-2005-10-05.tgz >> ./cminstall > > >Now you will have some kind of cm3 installed, presumably in /usr/ >local/cm3/bin/cm3. > >Make sure you have a fresh CVS checkout in directory cm3 (let's >assume this is in your home directory ~/cm3). Also, make sure you >have an up-to-date version of the CM3 backend compiler cm3cg >installed by executing the following: > >STEP 0: > >export CM3=/usr/local/cm3/bin/cm3 >cd ~/cm3/m3-sys/m3cc >$CM3 >$CM3 -ship > >You can skip this last step if you know your backend compiler is up >to date. > >Now, let's build the new compiler from scratch (this is the sequence >I use regularly to test changes to the run-time system whenever I >make them): > >can replace compilation step with > >rm -rf && $CM3 && $CM3 -ship > > >STEP 1: > >(do these LATER if bootstrapping from old compiler!) >cd ~/cm3/m3-libs/m3core >$CM3 >$CM3 -ship >cd ~/cm3/m3-libs/libm3 >$CM3 >$CM3 -ship > >Now build the compiler: > >cd ~/cm3/m3-libs/sysutils ; $CM3 etc. > >cd ~/cm3/m3-sys/m3middle; $CM3 etc. > >repeat for: > >m3-sys/m3objfile > >m3-sys/m3back > >m3-sys/m3linker > >m3-sys/m3front > >m3-sys/m3quake > >m3-sys/cm3 > >[ here we may need -DROOT= ] > > >At this point you should have a bootstrapped version of cm3 installed >in the directory /usr/local/cm3/pkg/cm3/TARGET/cm3 (where TARGET is >the CM3 target platform you are building on -- e.g., LINUXLIBC6, >PPC_DARWIN, ...). Note that this did not overwrite your original >installed compiler in /usr/local/cm3/bin/cm3. We >are now going to test the new compiler, which was built using the old >compiler, by bootstrapping it one more time. > >(If m3core and libm3 were skipped earlier, do them now, and RE-DO all >of the above packages before proceeding.) > >>From here on out, please replace TARGET with your target platform as >appropriate. > >STEP 2: > >export CM3=/usr/local/cm3/pkg/cm3/TARGET/cm3 >cd ~/cm3/scripts > >./do-cm3-std.sh realclean >REPEAT STEP 1 to rebuild the libraries and the compiler using the >STEP 1 bootstrap compiler. > >Now you have a STEP 2 bootstrap compiler installed in /usr/local/cm3/ >pkg/cm3/TARGET/cm3. Let's assume the new compiler now works properly >since it successfully bootstrapped itself, but to be sure we can now >use it to rebuild the world: > >cd ~/cm3/scripts >./do-cm3-std.sh realclean >./do-cm3-std.sh buildship > >Assuming this succeeded then we can be pretty sure /usr/local/cm3/pkg/ >cm3/TARGET/cm3 is good, so we can make it our default compiler by >replacing the original /usr/local/cm3/bin/cm3: > >cp $CM3 /usr/local/cm3/bin/cm3 > >On Jun 23, 2007, at 2:38 PM, Mika Nystrom wrote: > >> Ok, I'm sorry if I seem a bit dimwitted in the morning like this, >> but how exactly does one get started? I wish there were a file called >> "GETTING_STARTED" or something like that in scripts... >... From mika at async.caltech.edu Tue Aug 12 21:52:02 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 12 Aug 2014 12:52:02 -0700 Subject: [M3devel] Latest pthreads attempt In-Reply-To: <8B27D029-50B0-49B9-B673-34C128B103BB@cs.purdue.edu> References: <8B27D029-50B0-49B9-B673-34C128B103BB@cs.purdue.edu> Message-ID: <20140812195202.25FE51A2094@async.async.caltech.edu> Hi Tony (and others), I instrumented my ThreadPThread.m3 as follows: added an argument "line" to each of mutex_lock, mutex_unlock, and cond_wait called these with Compiler.ThisLine() results are attached... (I only learned yesterday how to do attachments in my Unix mailer!) Is there a document somewhere describing the invariants of ThreadPThread.m3? I can guess at many of them but am not entirely sure of some of the implementation details. In any case it looks to me: l. 194 lock 0x10250a8 self 0x1009400 <---- l. 198 lock 0x1025140 self 0x1009400 l. 202 unlock 0x1025140 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 <---- ERROR: pthread_mutex_lock:11 like we have a problem here somewhere: 188 PROCEDURE XWait (self: Activation; m: Mutex; c: Condition; alertable: BOOLEAN) 189 RAISES {Alerted} = 190 (* LL = m *) 191 VAR next, prev: Activation; 192 BEGIN 193 IF c.mutex = NIL THEN InitMutex(c.mutex, c, CleanCondition) END; 194 WITH r = pthread_mutex_lock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; <======= 195 <*ASSERT self.waitingOn = NIL*> 196 <*ASSERT self.nextWaiter = NIL*> 197 198 WITH r = pthread_mutex_lock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; 199 self.waitingOn := c.mutex; 200 self.nextWaiter := c.waiters; 201 c.waiters := self; 202 WITH r = pthread_mutex_unlock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; 203 204 m.release(); 205 IF perfOn THEN PerfChanged(State.waiting) END; 206 LOOP 207 IF alertable AND self.alerted THEN 208 self.alerted := FALSE; 209 <*ASSERT self.waitingOn = c.mutex*> 210 WITH r = pthread_mutex_lock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; 211 next := c.waiters; prev := NIL; 212 WHILE next # self DO 213 <*ASSERT next # NIL*> 214 prev := next; next := next.nextWaiter; 215 END; 216 IF prev = NIL 217 THEN c.waiters := self.nextWaiter; 218 ELSE prev.nextWaiter := self.nextWaiter; 219 END; 220 WITH r = pthread_mutex_unlock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; 221 self.nextWaiter := NIL; 222 self.waitingOn := NIL; 223 WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; 224 m.acquire(); 225 RAISE Alerted; 226 END; 227 WITH r = pthread_cond_wait(self.cond, self.mutex, ThisLine()) DO <*ASSERT r=0*> END; 228 IF self.waitingOn = NIL THEN 229 <*ASSERT self.nextWaiter = NIL*> 230 WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; 231 m.acquire(); 232 RETURN; 233 END; 234 END; 235 END XWait; The self.mutex is locked at 194, m.release is called with the self.mutex locked in other words. But that winds up here: 144 PROCEDURE UnlockMutex (m: Mutex) = 145 (* LL = m *) 146 VAR 147 self := GetActivation(); 148 t, prev: Activation; 149 BEGIN 150 IF m.mutex = NIL THEN InitMutex(m.mutex, m, CleanMutex) END; 151 WITH r = pthread_mutex_lock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; <======== And the traceback agrees.... ERROR: pthread_mutex_lock:11 [New Thread 801009400 (LWP 101206/cm3)] Program received signal SIGABRT, Aborted. [Switching to Thread 801009400 (LWP 101206/cm3)] thr_kill () at thr_kill.S:3 3 RSYSCALL(thr_kill) Current language: auto; currently asm (gdb) where #0 thr_kill () at thr_kill.S:3 #1 0x0000000000790ea9 in abort () at /usr/src/lib/libc/stdlib/abort.c:65 #2 0x000000000071ad1d in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ffffc4f8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:526 #3 0x0000000000714dad in ThreadPThread__UnlockMutex (M3_AYIbX3_m=Error accessing memory address 0x8000ffffc528: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:151 #4 0x0000000000715298 in ThreadPThread__XWait (M3_DMxDjQ_self=Error accessing memory address 0x8000ffffc5a8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:204 #5 0x0000000000717633 in ThreadPThread__XJoin (M3_DMxDjQ_self=Error accessing memory address 0x8000ffffc608: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:557 #6 0x0000000000717782 in Thread__Join (M3_BXP32l_t=Error accessing memory address 0x8000ffffc6d8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:569 #7 0x0000000000407d8d in Builder__ForceAllPromisesInParallel (M3_C58HwX_promises=Error accessing memory address 0x8000ffffc758: Bad address. ) at ../src/Builder.m3:1002 Mika -------------- next part -------------- /* Copyright (C) 2005, Purdue Research Foundation */ /* All rights reserved. */ /* See the file COPYRIGHT-PURDUE for a full description. */ #include "m3core.h" #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) /* See ThreadApple.c, ThreadFreeBSD.c, ThreadOpenBSD.c. */ #define M3_DIRECT_SUSPEND #endif #define M3MODULE ThreadPThread #if defined(__sparc) || defined(__ia64__) #define M3_REGISTER_WINDOWS #endif #ifdef M3_DIRECT_SUSPEND #define M3_DIRECT_SUSPEND_ASSERT_FALSE do { \ assert(0 && "MacOS X, FreeBSD, OpenBSD should not get here."); \ fprintf(stderr, "MacOS X, FreeBSD, OpenBSD should not get here.\n"); \ abort(); \ } while(0); #endif M3_EXTERNC_BEGIN #define InitC ThreadPThread__InitC #define SignalHandler ThreadPThread__SignalHandler #define sizeof_pthread_mutex_t ThreadPThread__sizeof_pthread_mutex_t #define sizeof_pthread_cond_t ThreadPThread__sizeof_pthread_cond_t #define SIG_SUSPEND ThreadPThread__SIG_SUSPEND void __cdecl SignalHandler(int signo, siginfo_t *info, void *context); #if M3_HAS_VISIBILITY #pragma GCC visibility push(hidden) #endif /* expected values for compat, if compat matters: Solaris: 17 (at least 32bit SPARC?) Cygwin: 19 -- er, but maybe that's wrong Linux: 64 FreeBSD: 31 (not used) OpenBSD: 31 (not used) HPUX: 44 Look at the history of Usignal and RTMachine to find more values. There was RTMachine.SIG_SUSPEND and SIG was aliased to it. Both SIG and SIG_SUSPEND were only defined for systems using pthreads. SIG was shorthand. */ #ifdef M3_DIRECT_SUSPEND EXTERN_CONST int SIG_SUSPEND = 0; #elif defined(__sun) || defined(__CYGWIN__) EXTERN_CONST int SIG_SUSPEND = SIGUSR2; #elif defined(__linux) EXTERN_CONST int SIG_SUSPEND = NSIG - 1; #elif defined(__hpux) EXTERN_CONST int SIG_SUSPEND = _SIGRTMAX; #elif defined(SIGRTMAX) && !defined(__osf__) /* This might be a function call, in which case try _SIGRTMAX or initializing it somewhere. SIGRTMAX is sysconf(132) on OSF. We may be able to use direct suspend/resume on OSF. */ EXTERN_CONST int SIG_SUSPEND = SIGRTMAX; #elif defined(SIGUSR2) EXTERN_CONST int SIG_SUSPEND = SIGUSR2; #else #error Unable to determine SIG_SUSPEND. #endif static int stack_grows_down; #ifndef M3_DIRECT_SUSPEND static sigset_t mask; /* Signal based suspend/resume */ static sem_t ackSem; static void __cdecl SignalHandlerC(int signo, siginfo_t *info, void *context) /* wrapper to workaround on ALPHA_LINUX: /usr/bin/ld: ThreadPThreadC.o: gp-relative relocation against dynamic symbol ThreadPThread__SignalHandler http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46861 */ { SignalHandler(signo, info, context); } int __cdecl ThreadPThread__sem_wait(void) { return sem_wait(&ackSem); } int __cdecl ThreadPThread__sem_post(void) { return sem_post(&ackSem); } int __cdecl ThreadPThread__sem_getvalue(int *value) { return sem_getvalue(&ackSem, value); } void __cdecl ThreadPThread__sigsuspend(void) { struct { sigjmp_buf jb; } s; ZERO_MEMORY(s); if (sigsetjmp(s.jb, 0) == 0) /* save registers to stack */ #ifdef M3_REGISTER_WINDOWS siglongjmp(s.jb, 1); /* flush register windows */ else #endif sigsuspend(&mask); } void __cdecl ThreadPThread__SuspendThread (m3_pthread_t mt) { abort(); } void __cdecl ThreadPThread__RestartThread (m3_pthread_t mt) { abort(); } void __cdecl ThreadPThread__ProcessStopped (m3_pthread_t mt, char *bottom, char *context, void (*p)(void *start, void *limit)) { /* process stack */ if (!bottom) return; if (stack_grows_down) { assert(context < bottom); p(context, bottom); } else { assert(bottom < context); p(bottom, context); } /* process register context */ p(context, context + sizeof(ucontext_t)); } #else /* M3_DIRECT_SUSPEND */ void __cdecl ThreadPThread__sem_wait(void) { M3_DIRECT_SUSPEND_ASSERT_FALSE } void __cdecl ThreadPThread__sem_post(void) { M3_DIRECT_SUSPEND_ASSERT_FALSE } void __cdecl ThreadPThread__sem_getvalue(void) { M3_DIRECT_SUSPEND_ASSERT_FALSE } void __cdecl ThreadPThread__sigsuspend(void) { M3_DIRECT_SUSPEND_ASSERT_FALSE } #endif /* M3_DIRECT_SUSPEND */ void __cdecl ThreadPThread__ProcessLive(char *bottom, void (*p)(void *start, void *limit)) { /* cc: Warning: ThreadPThreadC.c, line 170: In this statement, & before array "jb" is ignored. (addrarray) p(&jb, ((char *)&jb) + sizeof(jb)); ------^ cc: Warning: ThreadPThreadC.c, line 170: In this statement, & before array "jb" is ignored. (addrarray) p(&jb, ((char *)&jb) + sizeof(jb)); --------------------^ jb may or may not be an array, & is necessary, wrap it in struct. */ struct { sigjmp_buf jb; } s; ZERO_MEMORY(s); if (sigsetjmp(s.jb, 0) == 0) /* save registers to stack */ #ifdef M3_REGISTER_WINDOWS siglongjmp(s.jb, 1); /* flush register windows */ else #endif { /* capture top after longjmp because longjmp can clobber non-volatile locals */ char *top = (char*)⊤ assert(bottom); if (stack_grows_down) { assert(top < bottom); p(top, bottom); } else { assert(bottom < top); p(bottom, top); } p(&s, sizeof(s) + (char *)&s); } } #define M3_MAX(x, y) (((x) > (y)) ? (x) : (y)) typedef void *(*start_routine_t)(void *); #define M3_RETRY(expr) \ r = (expr); \ if (r == EAGAIN || r == ENOMEM || r == ENOSPC) \ { \ /* try again right away */ \ r = (expr); \ if (r == EAGAIN || r == ENOMEM || r == ENOSPC) \ { \ /* try again after short delay */ \ sleep(1); \ r = (expr); \ } \ } int __cdecl ThreadPThread__thread_create(WORD_T stackSize, start_routine_t start_routine, void *arg) { int r = { 0 }; WORD_T bytes = { 0 }; pthread_attr_t attr; pthread_t pthread; ZERO_MEMORY(pthread); ZERO_MEMORY(attr); M3_RETRY(pthread_attr_init(&attr)); #ifdef __hpux if (r == ENOSYS) { fprintf(stderr, "You got the nonfunctional pthread stubs on HP-UX. You need to" " adjust your build commands, such as to link to -lpthread or" " use -pthread, and not link explicitly to -lc.\n"); } #endif assert(r == 0); r = pthread_attr_getstacksize(&attr, &bytes); assert(r == 0); bytes = M3_MAX(bytes, stackSize); pthread_attr_setstacksize(&attr, bytes); M3_RETRY(pthread_create(&pthread, &attr, start_routine, arg)); #ifdef __sun if (r == ENOENT) { fprintf(stderr, "You got the nonfunctional pthread stubs on Solaris earlier than 5.10. " "You need to adjust your build commands, such as to link to -lpthread " " ahead of -lc.\n"); } #endif if (r != 0) { fprintf(stderr, "pthread_create(stack_size:0x%X):0x%X errno:0x%X\n", (unsigned)stackSize, (unsigned)r, (unsigned)errno); } pthread_attr_destroy(&attr); return r; } #define MUTEX(name) \ static pthread_mutex_t name##Mu = PTHREAD_MUTEX_INITIALIZER; \ extern pthread_mutex_t * const ThreadPThread__##name##Mu; \ pthread_mutex_t * const ThreadPThread__##name##Mu = &name##Mu; \ #define CONDITION_VARIABLE(name) \ static pthread_cond_t name##Cond = PTHREAD_COND_INITIALIZER; \ extern pthread_cond_t * const ThreadPThread__##name##Cond; \ pthread_cond_t * const ThreadPThread__##name##Cond = &name##Cond; \ /* activeMu slotMu initMu perfMu heapMu heapCond */ MUTEX(active) /* global lock for list of active threads */ MUTEX(slots) /* global lock for thread slots table */ MUTEX(init) /* global lock for initializers */ MUTEX(perf) /* global lock for thread state tracing */ MUTEX(heap) /* global lock for heap atomicity */ CONDITION_VARIABLE(heap) /* CV for heap waiters */ /* NetBSD 5.0.2 compiles __thread, but segfault at runtime. OpenBSD 4.7 compiles __thread, but segfault at runtime. Apple doesn't compile FreeBSD not tested AIX probably works, not tested Solaris: failed to link on Solaris 2.9: http://hudson.modula3.com:8080/job/cm3-current-build-SOLsun-opencsw-current9s/166/console HP-UX? AIX? Linux/arm: /usr/bin/ld: /usr/local/cm3/pkg/m3core/ARMEL_LINUX/libm3core.a(ThreadPThreadC.o)(.stab+0x2e28): R_ARM_ABS32 used with TLS symbol activations */ #if 0 /* defined(__linux) && !defined(__arm__) */ #define M3_COMPILER_THREAD_LOCAL static __thread void* activations; void __cdecl ThreadPThread__SetActivation(void *value) { activations = value; } void* __cdecl ThreadPThread__GetActivation(void) { return activations; } #else static pthread_key_t activations; void __cdecl ThreadPThread__SetActivation(void *value) { int r = { 0 }; M3_RETRY(pthread_setspecific(activations, value)); assert(r == 0); } void * __cdecl ThreadPThread__GetActivation(void) { return pthread_getspecific(activations); } #endif typedef int (*generic_init_t)(void *, const void *); void * __cdecl ThreadPThread_pthread_generic_new(WORD_T size, generic_init_t init) { int r = ENOMEM; void *p = calloc(1, size); if (p == NULL) goto Error; M3_RETRY(init(p, NULL)); if (r == ENOMEM) goto Error; assert(r == 0); if (r != 0) goto Error; return p; Error: if (r) { fprintf(stderr, "ERROR: pthread_generic_new:%d\n", r); abort(); } if (p) free(p); return NULL; } #define THREADPTHREAD__PTHREAD_GENERIC_NEW(type) { \ typedef pthread_##type##_t T; \ typedef pthread_##type##attr_t attr_t; \ typedef int (*init_t)(T *, const attr_t *); \ /* make sure the type matches */ \ init_t init = pthread_##type##_init; \ return ThreadPThread_pthread_generic_new(sizeof(T), \ (generic_init_t)init); \ } void * __cdecl ThreadPThread__pthread_mutex_new(void) { THREADPTHREAD__PTHREAD_GENERIC_NEW(mutex); } void * __cdecl ThreadPThread__pthread_cond_new(void) { THREADPTHREAD__PTHREAD_GENERIC_NEW(cond); } void __cdecl ThreadPThread__pthread_mutex_delete(pthread_mutex_t* p) { int e = { 0 }; if (p == NULL) return; #if defined(__hpux) || defined(__osf) /* workaround Tru64 5.1 and HP-UX bug: pthread_mutex_destroy() intermittently returns EBUSY even when there are no threads accessing the mutex. */ do { e = pthread_mutex_destroy(p); } while (e == EBUSY); #else e = pthread_mutex_destroy(p); #endif if (e) { if (e == EBUSY) fprintf(stderr, "pthread_mutex_destroy:EBUSY\n"); else fprintf(stderr, "pthread_mutex_destroy:%d\n", e); abort(); } free(p); } void __cdecl ThreadPThread__pthread_cond_delete(pthread_cond_t *p) { int r = { 0 }; if (p == NULL) return; r = pthread_cond_destroy(p); assert(r == 0); free(p); } #define BILLION (1000 * 1000 * 1000) void __cdecl ThreadPThread__Nanosleep(INTEGER nanoseconds) { #ifdef __INTERIX assert(nanoseconds >= 0); assert(nanoseconds < BILLION); /* This is only an approximation. We don't try to complete the sleep * if interrupted, because we don't cheaply know how much time has elapsed. */ usleep(nanoseconds / 1000); #else struct timespec wait; struct timespec remaining; assert(nanoseconds >= 0); assert(nanoseconds < BILLION); ZERO_MEMORY(wait); ZERO_MEMORY(remaining); wait.tv_sec = 0; wait.tv_nsec = nanoseconds; while (nanosleep(&wait, &remaining) == -1 && errno == EINTR) wait = remaining; #endif } /*M3WRAP2(int, pthread_cond_wait, pthread_cond_t*, pthread_mutex_t*)*/ M3WRAP1(int, pthread_cond_signal, pthread_cond_t*) M3WRAP1(int, pthread_cond_broadcast, pthread_cond_t*) int __cdecl ThreadPThread__pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, LONGREAL m3timeout) { struct timespec timeout; double n = { 0 }; ZERO_MEMORY(timeout); timeout.tv_nsec = modf(m3timeout, &n) * BILLION; timeout.tv_sec = n; return pthread_cond_timedwait(cond, mutex, &timeout); } int __cdecl ThreadPThread__pthread_detach_self(void) { return pthread_detach(pthread_self()); } m3_pthread_t __cdecl ThreadPThread__pthread_self(void) { pthread_t a = pthread_self(); return PTHREAD_TO_M3(a); } int __cdecl ThreadPThread__pthread_equal(m3_pthread_t t1, m3_pthread_t t2) { return pthread_equal(PTHREAD_FROM_M3(t1), PTHREAD_FROM_M3(t2)); } int __cdecl ThreadPThread__pthread_kill(m3_pthread_t thread, int sig) { return pthread_kill(PTHREAD_FROM_M3(thread), sig); } int __cdecl ThreadPThread__pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m, int line) { fprintf(stderr, "l. %5d wait 0x%x self 0x%x\n",line,m,pthread_self()); return pthread_cond_wait(c,m); } int __cdecl ThreadPThread__pthread_mutex_lock(pthread_mutex_t* mutex, int line) { int a; fprintf(stderr, "l. %5d lock 0x%x self 0x%x\n",line,mutex,pthread_self()); a = pthread_mutex_lock(mutex); if (a) { if (a == EINVAL) fprintf(stderr, "ERROR: pthread_mutex_lock:EINVAL\n"); else fprintf(stderr, "ERROR: pthread_mutex_lock:%d\n", a); abort(); } return a; } int __cdecl ThreadPThread__pthread_mutex_unlock(pthread_mutex_t* mutex, int line) { int a; fprintf(stderr, "l. %5d unlock 0x%x self 0x%x\n",line,mutex,pthread_self()); a = pthread_mutex_unlock(mutex); if (a) { fprintf(stderr, "ERROR: pthread_mutex_unlock:%d\n", a); abort(); } return a; } void __cdecl InitC(int *bottom) { int r = { 0 }; #ifndef M3_DIRECT_SUSPEND struct sigaction act; ZERO_MEMORY(act); #endif stack_grows_down = (bottom > &r); #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__INTERIX) assert(stack_grows_down); /* See ThreadApple.c, ThreadFreeBSD.c */ #endif #ifndef M3_COMPILER_THREAD_LOCAL M3_RETRY(pthread_key_create(&activations, NULL)); assert(r == 0); #endif #ifndef M3_DIRECT_SUSPEND ZERO_MEMORY(act); M3_RETRY(sem_init(&ackSem, 0, 0)); assert(r == 0); r = sigfillset(&mask); assert(r == 0); r = sigdelset(&mask, SIG_SUSPEND); assert(r == 0); r = sigdelset(&mask, SIGINT); assert(r == 0); r = sigdelset(&mask, SIGQUIT); assert(r == 0); r = sigdelset(&mask, SIGABRT); assert(r == 0); r = sigdelset(&mask, SIGTERM); assert(r == 0); act.sa_flags = SA_RESTART | SA_SIGINFO; act.sa_sigaction = SignalHandlerC; r = sigfillset(&act.sa_mask); assert(r == 0); r = sigaction(SIG_SUSPEND, &act, NULL); assert(r == 0); #endif } M3_EXTERNC_END -------------- next part -------------- (* Copyright (C) 2005, Purdue Research Foundation *) (* All rights reserved. *) (* See the file COPYRIGHT-PURDUE for a full description. *) UNSAFE MODULE ThreadPThread EXPORTS Thread, ThreadF, RTThread, Scheduler, SchedulerPosix, RTOS, RTHooks, ThreadPThread; IMPORT Cerrno, FloatMode, MutexRep, RTCollectorSRC, RTError, RTHeapRep, RTIO, RTParams, RTPerfTool, RTProcess, ThreadEvent, Time, Word, Usched, Uerror, Uexec; FROM Compiler IMPORT ThisFile, ThisLine; FROM Ctypes IMPORT int; IMPORT RuntimeError AS RTE; FROM ThreadInternal IMPORT Poll; (*----------------------------------------------------- types and globals ---*) CONST MILLION = 1000 * 1000; WAIT_UNIT = MILLION; (* one million nanoseconds, one thousandth of a second *) RETRY_INTERVAL = 10 * MILLION; (* 10 million nanoseconds, one hundredth of a second *) REVEAL Mutex = MutexRep.Public BRANDED "Mutex Pthread-1.0" OBJECT mutex: pthread_mutex_t := NIL; holder: Activation := NIL; waiters: Activation := NIL; OVERRIDES acquire := LockMutex; release := UnlockMutex; END; Condition = BRANDED "Thread.Condition Pthread-1.0" OBJECT mutex: pthread_mutex_t := NIL; waiters: Activation := NIL; (* LL = mutex *) END; T = BRANDED "Thread.T Pthread-1.6" OBJECT act: Activation := NIL; (* live untraced thread data *) closure: Closure := NIL; (* our work and its result *) result: REFANY := NIL; (* our work and its result *) join: Condition; (* wait here to join; NIL when done *) joined: BOOLEAN := FALSE; (* Is anyone waiting yet? *) END; TYPE ActState = { Starting, Started, Stopping, Stopped }; REVEAL Activation = UNTRACED BRANDED REF RECORD frame: ADDRESS := NIL; (* exception handling support *) mutex: pthread_mutex_t := NIL; (* write-once in CreateT *) cond: pthread_cond_t := NIL; (* write-once in CreateT; a place to park while waiting *) alerted : BOOLEAN := FALSE; (* LL = mutex; the alert flag *) waitingOn: pthread_mutex_t := NIL; (* LL = mutex; The CV's mutex *) nextWaiter: Activation := NIL; (* LL = mutex; waiting thread queue *) next, prev: Activation := NIL; (* LL = activeMu; global doubly-linked, circular list of all active threads *) handle: pthread_t := NIL; (* LL = activeMu; thread handle *) stackbase: ADDRESS := NIL; (* LL = activeMu; stack base for GC *) context: ADDRESS := NIL; (* LL = activeMu *) state := ActState.Started; (* LL = activeMu *) slot: CARDINAL := 0; (* LL = slotMu; index in slots *) floatState : FloatMode.ThreadState; (* per-thread floating point state *) heapState : RTHeapRep.ThreadState; (* per-thread heap state *) END; PROCEDURE SetState (act: Activation; state: ActState) = CONST text = ARRAY ActState OF TEXT { "Starting", "Started", "Stopping", "Stopped" }; BEGIN act.state := state; IF DEBUG THEN RTIO.PutText(text[state]); RTIO.PutText(" act="); RTIO.PutAddr(act); RTIO.PutText("\n"); RTIO.Flush(); END; END SetState; (*----------------------------------------------------------------- Mutex ---*) PROCEDURE Acquire (m: Mutex) = BEGIN m.acquire (); END Acquire; PROCEDURE Release (m: Mutex) = BEGIN m.release (); END Release; PROCEDURE CleanMutex (r: REFANY) = VAR m := NARROW(r, Mutex); BEGIN pthread_mutex_delete(m.mutex); m.mutex := NIL; END CleanMutex; PROCEDURE InitMutex (VAR m: pthread_mutex_t; root: REFANY; Clean: PROCEDURE(root: REFANY)) = VAR mutex := pthread_mutex_new(); BEGIN TRY WITH r = pthread_mutex_lock(initMu,ThisLine()) DO <*ASSERT r=0*> END; (* Did someone else win the race? *) IF m # NIL THEN RETURN END; (* We won the race, but we might have failed to allocate. *) IF mutex = NIL THEN RTE.Raise (RTE.T.OutOfMemory) END; RTHeapRep.RegisterFinalCleanup (root, Clean); m := mutex; mutex := NIL; FINALLY WITH r = pthread_mutex_unlock(initMu,ThisLine()) DO <*ASSERT r=0*> END; pthread_mutex_delete(mutex); END; END InitMutex; PROCEDURE LockMutex (m: Mutex) = VAR self := GetActivation(); BEGIN IF m.mutex = NIL THEN InitMutex(m.mutex, m, CleanMutex) END; WITH r = pthread_mutex_lock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(m.mutex,ThisLine()) DO <*ASSERT r=0*> END; IF m.holder = NIL THEN m.holder := self; WITH r = pthread_mutex_unlock(m.mutex,ThisLine()) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; RETURN; END; <*ASSERT self.waitingOn = NIL*> <*ASSERT self.nextWaiter = NIL*> IF perfOn THEN PerfChanged(State.locking) END; self.waitingOn := m.mutex; self.nextWaiter := m.waiters; m.waiters := self; IF m.holder = self THEN Die(ThisLine(), "impossible acquire") END; WITH r = pthread_mutex_unlock(m.mutex,ThisLine()) DO <*ASSERT r=0*> END; REPEAT WITH r = pthread_cond_wait(self.cond, self.mutex, ThisLine()) DO <*ASSERT r=0*> END; UNTIL self.waitingOn = NIL; (* m.holder = self *) WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; END LockMutex; PROCEDURE UnlockMutex (m: Mutex) = (* LL = m *) VAR self := GetActivation(); t, prev: Activation; BEGIN IF m.mutex = NIL THEN InitMutex(m.mutex, m, CleanMutex) END; WITH r = pthread_mutex_lock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(m.mutex,ThisLine()) DO <*ASSERT r=0*> END; IF m.holder # self THEN Die(ThisLine(), "illegal release") END; t := m.waiters; IF t = NIL THEN m.holder := NIL; WITH r = pthread_mutex_unlock(m.mutex,ThisLine()) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; RETURN; END; prev := NIL; WHILE t.nextWaiter # NIL DO prev := t; t := t.nextWaiter; END; IF prev # NIL THEN prev.nextWaiter := NIL; ELSE m.waiters := NIL; END; m.holder := t; WITH r = pthread_mutex_unlock(m.mutex,ThisLine()) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(t.mutex,ThisLine()) DO <*ASSERT r=0*> END; t.waitingOn := NIL; WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(t.mutex,ThisLine()) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; END UnlockMutex; (*---------------------------------------- Condition variables and Alerts ---*) PROCEDURE CleanCondition (r: REFANY) = VAR c := NARROW(r, Condition); BEGIN pthread_mutex_delete(c.mutex); c.mutex := NIL; END CleanCondition; PROCEDURE XWait (self: Activation; m: Mutex; c: Condition; alertable: BOOLEAN) RAISES {Alerted} = (* LL = m *) VAR next, prev: Activation; BEGIN IF c.mutex = NIL THEN InitMutex(c.mutex, c, CleanCondition) END; WITH r = pthread_mutex_lock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; <*ASSERT self.waitingOn = NIL*> <*ASSERT self.nextWaiter = NIL*> WITH r = pthread_mutex_lock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; self.waitingOn := c.mutex; self.nextWaiter := c.waiters; c.waiters := self; WITH r = pthread_mutex_unlock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; m.release(); IF perfOn THEN PerfChanged(State.waiting) END; LOOP IF alertable AND self.alerted THEN self.alerted := FALSE; <*ASSERT self.waitingOn = c.mutex*> WITH r = pthread_mutex_lock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; next := c.waiters; prev := NIL; WHILE next # self DO <*ASSERT next # NIL*> prev := next; next := next.nextWaiter; END; IF prev = NIL THEN c.waiters := self.nextWaiter; ELSE prev.nextWaiter := self.nextWaiter; END; WITH r = pthread_mutex_unlock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; self.nextWaiter := NIL; self.waitingOn := NIL; WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; m.acquire(); RAISE Alerted; END; WITH r = pthread_cond_wait(self.cond, self.mutex, ThisLine()) DO <*ASSERT r=0*> END; IF self.waitingOn = NIL THEN <*ASSERT self.nextWaiter = NIL*> WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; m.acquire(); RETURN; END; END; END XWait; PROCEDURE AlertWait (m: Mutex; c: Condition) RAISES {Alerted} = (* LL = m *) VAR self := GetActivation(); BEGIN XWait(self, m, c, alertable := TRUE); END AlertWait; PROCEDURE Wait (m: Mutex; c: Condition) = <*FATAL Alerted*> (* LL = m *) VAR self := GetActivation(); BEGIN XWait(self, m, c, alertable := FALSE); END Wait; PROCEDURE DequeueHead(c: Condition) = (* LL = c *) VAR t := c.waiters; BEGIN WITH r = pthread_mutex_lock(t.mutex,ThisLine()) DO <*ASSERT r=0*> END; c.waiters := t.nextWaiter; t.nextWaiter := NIL; t.waitingOn := NIL; WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(t.mutex,ThisLine()) DO <*ASSERT r=0*> END; END DequeueHead; PROCEDURE Signal (c: Condition) = BEGIN IF c.mutex = NIL THEN InitMutex(c.mutex, c, CleanCondition) END; WITH r = pthread_mutex_lock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; IF c.waiters # NIL THEN DequeueHead(c) END; WITH r = pthread_mutex_unlock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; END Signal; PROCEDURE Broadcast (c: Condition) = BEGIN IF c.mutex = NIL THEN InitMutex(c.mutex, c, CleanCondition) END; WITH r = pthread_mutex_lock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; WHILE c.waiters # NIL DO DequeueHead(c) END; WITH r = pthread_mutex_unlock(c.mutex,ThisLine()) DO <*ASSERT r=0*> END; END Broadcast; PROCEDURE Alert (thread: T) = VAR t := thread.act; BEGIN WITH r = pthread_mutex_lock(t.mutex,ThisLine()) DO <*ASSERT r=0*> END; t.alerted := TRUE; WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(t.mutex,ThisLine()) DO <*ASSERT r=0*> END; END Alert; PROCEDURE XTestAlert (self: Activation): BOOLEAN = VAR result: BOOLEAN; BEGIN WITH r = pthread_mutex_lock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; result := self.alerted; self.alerted := FALSE; WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; RETURN result; END XTestAlert; PROCEDURE TestAlert (): BOOLEAN = VAR self := GetActivation(); BEGIN RETURN XTestAlert(self); END TestAlert; (*------------------------------------------------------------------ Self ---*) VAR (* LL = slotMu *) n_slotted: CARDINAL; next_slot: CARDINAL; (* NOTE: we don't use slots[0] *) slots: REF ARRAY OF T; (* NOTE: we don't use slots[0] *) PROCEDURE InitActivations (me: Activation) = BEGIN me.handle := pthread_self(); me.next := me; me.prev := me; SetActivation(me); (* Explicitly (re)initialize to handle fork(). *) next_slot := 1; (* no threads created yet *) slots := NIL; (* no threads created yet *) n_slotted := 0; (* no threads created yet *) allThreads := me; FloatMode.InitThread(me.floatState); END InitActivations; PROCEDURE Self (): T = (* If not the initial thread and not created by Fork, returns NIL *) VAR me := GetActivation(); t: T; BEGIN IF me = NIL THEN Die(ThisLine(), "Thread primitive called from non-Modula-3 thread") END; WITH r = pthread_mutex_lock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; t := slots[me.slot]; WITH r = pthread_mutex_unlock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; IF (t.act # me) THEN Die(ThisLine(), "thread with bad slot!") END; RETURN t; END Self; PROCEDURE AssignSlot (t: T): INTEGER = (* LL = 0, cause we allocate stuff with NEW! *) VAR n: CARDINAL; new_slots: REF ARRAY OF T; slot: CARDINAL; BEGIN WITH r = pthread_mutex_lock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; (* make sure we have room to register this guy *) IF (slots = NIL) THEN WITH r = pthread_mutex_unlock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; slots := NEW (REF ARRAY OF T, 20); WITH r = pthread_mutex_lock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; END; IF (n_slotted >= LAST (slots^)) THEN n := NUMBER (slots^); WITH r = pthread_mutex_unlock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; new_slots := NEW (REF ARRAY OF T, n+n); WITH r = pthread_mutex_lock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; IF (n = NUMBER (slots^)) THEN (* we won any races that may have occurred. *) SUBARRAY (new_slots^, 0, n) := slots^; slots := new_slots; ELSIF (n_slotted < LAST (slots^)) THEN (* we lost a race while allocating a new slot table, and the new table has room for us. *) ELSE (* ouch, the new table is full too! Bail out and retry *) WITH r = pthread_mutex_unlock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; RETURN AssignSlot (t); END; END; (* look for an empty slot *) WHILE (slots [next_slot] # NIL) DO INC (next_slot); IF (next_slot >= NUMBER (slots^)) THEN next_slot := 1; END; END; INC (n_slotted); slot := next_slot; slots [slot] := t; WITH r = pthread_mutex_unlock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; RETURN slot; END AssignSlot; PROCEDURE FreeSlot (self: T) = (* LL = 0 *) BEGIN WITH r = pthread_mutex_lock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; DEC (n_slotted); WITH z = slots [self.act.slot] DO IF z # self THEN Die (ThisLine(), "unslotted thread!"); END; z := NIL; END; self.act.slot := 0; WITH r = pthread_mutex_unlock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; END FreeSlot; PROCEDURE DumpThread (t: Activation) = BEGIN RTIO.PutText("Activation: "); RTIO.PutAddr(t); RTIO.PutChar('\n'); RTIO.PutText(" slot: "); RTIO.PutInt(t.slot); RTIO.PutChar('\n'); RTIO.PutText(" mutex: "); RTIO.PutAddr(t.mutex); RTIO.PutChar('\n'); RTIO.PutText(" cond: "); RTIO.PutAddr(t.cond); RTIO.PutChar('\n'); RTIO.PutText(" alerted: "); RTIO.PutInt(ORD(t.alerted)); RTIO.PutChar('\n'); RTIO.PutText(" waitingOn: "); RTIO.PutAddr(t.waitingOn); RTIO.PutChar('\n'); RTIO.PutText(" nextWaiter: "); RTIO.PutAddr(t.nextWaiter); RTIO.PutChar('\n'); RTIO.PutText(" frame: "); RTIO.PutAddr(t.frame); RTIO.PutChar('\n'); RTIO.PutText(" next: "); RTIO.PutAddr(t.next); RTIO.PutChar('\n'); RTIO.PutText(" prev: "); RTIO.PutAddr(t.prev); RTIO.PutChar('\n'); RTIO.PutText(" handle: "); RTIO.PutAddr(t.handle); RTIO.PutChar('\n'); RTIO.PutText(" stackbase: "); RTIO.PutAddr(t.stackbase); RTIO.PutChar('\n'); RTIO.PutText(" context: "); RTIO.PutAddr(t.context); RTIO.PutChar('\n'); RTIO.PutText(" state: "); CASE t.state OF | ActState.Started => RTIO.PutText("Started\n"); | ActState.Stopped => RTIO.PutText("Stopped\n"); | ActState.Starting => RTIO.PutText("Starting\n"); | ActState.Stopping => RTIO.PutText("Stopping\n"); END; RTIO.Flush(); END DumpThread; PROCEDURE DumpThreads () = VAR t := allThreads; BEGIN REPEAT DumpThread(t); t := t.next UNTIL t = allThreads; END DumpThreads; (*------------------------------------------------------------ Fork, Join ---*) VAR (* LL=activeMu *) allThreads: Activation := NIL; (* global list of active threads *) PROCEDURE CleanThread (r: REFANY) = VAR t := NARROW(r, T); BEGIN pthread_mutex_delete(t.act.mutex); pthread_cond_delete(t.act.cond); DISPOSE(t.act); END CleanThread; (* ThreadBase calls RunThread after finding (approximately) where its stack begins. This dance ensures that all of ThreadMain's traced references are within the stack scanned by the collector. *) PROCEDURE ThreadBase (param: ADDRESS): ADDRESS = VAR me: Activation := param; BEGIN SetActivation(me); me.stackbase := ADR(me); (* enable GC scanning of this stack *) me.handle := pthread_self(); (* add to the list of active threads *) WITH r = pthread_mutex_lock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; me.next := allThreads; me.prev := allThreads.prev; allThreads.prev.next := me; allThreads.prev := me; WITH r = pthread_mutex_unlock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; FloatMode.InitThread (me.floatState); RunThread(me); (* remove from the list of active threads *) WITH r = pthread_mutex_lock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; <*ASSERT allThreads # me*> me.stackbase := NIL; (* disable GC scanning of my stack *) me.next.prev := me.prev; me.prev.next := me.next; WITH r = pthread_detach_self() DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; me.next := NIL; me.prev := NIL; RETURN NIL; END ThreadBase; PROCEDURE RunThread (me: Activation) = VAR self: T; BEGIN IF perfOn THEN PerfChanged(State.alive) END; WITH r = pthread_mutex_lock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; self := slots [me.slot]; WITH r = pthread_mutex_unlock(slotsMu,ThisLine()) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; (*** Run the user-level code. ***) self.result := self.closure.apply(); IF perfOn THEN PerfChanged(State.dying) END; (* Join *) LOCK joinMu DO Broadcast(self.join); self.join := NIL; (* mark me done *) END; IF perfOn THEN PerfChanged(State.dead) END; (* we're dying *) RTHeapRep.FlushThreadState(me.heapState); IF perfOn THEN PerfDeleted() END; FreeSlot(self); (* note: needs self.act ! *) (* Since we're no longer slotted, we cannot touch traced refs. *) END RunThread; VAR joinMu: MUTEX; PROCEDURE Fork (closure: Closure): T = VAR act := NEW(Activation, mutex := pthread_mutex_new(), cond := pthread_cond_new()); size := defaultStackSize; t: T := NIL; BEGIN TRY IF act.mutex = NIL OR act.cond = NIL THEN RTE.Raise(RTE.T.OutOfMemory); END; t := NEW(T, act := act, closure := closure, join := NEW(Condition)); RTHeapRep.RegisterFinalCleanup(t, CleanThread); act.slot := AssignSlot(t); FINALLY IF act.slot = 0 THEN (* we failed, cleanup *) pthread_mutex_delete(act.mutex); pthread_cond_delete(act.cond); DISPOSE(act); END; END; (* determine the initial size of the stack for this thread *) TYPECASE closure OF | SizedClosure (scl) => size := scl.stackSize; ELSE (*skip*) END; WITH r = thread_create(size * ADRSIZE(Word.T), ThreadBase, act) DO IF r # 0 THEN DieI(ThisLine(), r) END; END; RETURN t; END Fork; PROCEDURE XJoin (self: Activation; t: T; alertable: BOOLEAN): REFANY RAISES {Alerted} = BEGIN LOCK joinMu DO IF t.joined THEN Die(ThisLine(), "attempt to join with thread twice") END; TRY t.joined := TRUE; WHILE t.join # NIL DO XWait(self, joinMu, t.join, alertable) END; FINALLY IF t.join # NIL THEN t.joined := FALSE END; END; END; RETURN t.result; END XJoin; PROCEDURE Join (t: T): REFANY = <*FATAL Alerted*> VAR self := GetActivation(); BEGIN RETURN XJoin(self, t, alertable := FALSE); END Join; PROCEDURE AlertJoin (t: T): REFANY RAISES {Alerted} = VAR self := GetActivation(); BEGIN RETURN XJoin(self, t, alertable := TRUE); END AlertJoin; (*---------------------------------------------------- Scheduling support ---*) PROCEDURE XPause (self: Activation; n: LONGREAL; alertable: BOOLEAN) RAISES {Alerted} = VAR until := Time.Now() + n; BEGIN IF perfOn THEN PerfChanged(State.pausing) END; WITH r = pthread_mutex_lock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; <*ASSERT self.waitingOn = NIL*> <*ASSERT self.nextWaiter = NIL*> LOOP IF alertable AND self.alerted THEN self.alerted := FALSE; WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; RAISE Alerted; END; WITH r = pthread_cond_timedwait(self.cond, self.mutex, until) DO IF r = Uerror.ETIMEDOUT THEN WITH r = pthread_mutex_unlock(self.mutex,ThisLine()) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; RETURN; END; <*ASSERT r=0*> END; END; END XPause; PROCEDURE Pause (n: LONGREAL) = <*FATAL Alerted*> VAR self := GetActivation(); BEGIN XPause(self, n, alertable := FALSE); END Pause; PROCEDURE AlertPause (n: LONGREAL) RAISES {Alerted} = VAR self := GetActivation(); BEGIN XPause(self, n, alertable := TRUE); END AlertPause; PROCEDURE Yield () = BEGIN WITH r = Usched.yield() DO IF r # 0 THEN DieI(ThisLine(), Cerrno.GetErrno()) END; END; END Yield; PROCEDURE IOWait (fd: CARDINAL; read: BOOLEAN; timeoutInterval: LONGREAL := -1.0D0): WaitResult = <*FATAL Alerted*> VAR self := GetActivation(); BEGIN TRY IF perfOn THEN PerfChanged(State.blocking) END; RETURN XIOWait(self, fd, read, timeoutInterval, alertable := FALSE); FINALLY IF perfOn THEN PerfRunning() END; END; END IOWait; PROCEDURE IOAlertWait (fd: CARDINAL; read: BOOLEAN; timeoutInterval: LONGREAL := -1.0D0): WaitResult RAISES {Alerted} = VAR self := GetActivation(); BEGIN TRY IF perfOn THEN PerfChanged(State.blocking) END; RETURN XIOWait(self, fd, read, timeoutInterval, alertable := TRUE); FINALLY IF perfOn THEN PerfRunning() END; END; END IOAlertWait; PROCEDURE XIOWait (self: Activation; fd: CARDINAL; read: BOOLEAN; interval: LONGREAL; alertable: BOOLEAN): WaitResult RAISES {Alerted} = VAR res: WaitResult; subInterval: LONGREAL := 1.0d0; err: int := 0; again := FALSE; BEGIN IF NOT alertable THEN subInterval := interval; ELSIF interval < 0.0d0 THEN interval := LAST(LONGREAL); ELSIF interval < subInterval THEN subInterval := interval; END; IF alertable AND XTestAlert(self) THEN RAISE Alerted END; LOOP res := VAL(Poll(fd, ORD(read), subInterval), WaitResult); IF alertable AND XTestAlert(self) THEN RAISE Alerted END; CASE res OF | WaitResult.FDError, WaitResult.Ready => RETURN res; | WaitResult.Error => err := Cerrno.GetErrno(); IF err = Uerror.EINTR THEN (* spurious wakeups are OK *) ELSIF err = Uerror.EAGAIN AND NOT again THEN again := TRUE; (* try just once more *) ELSE RETURN WaitResult.Error; END; | WaitResult.Timeout => interval := interval - subInterval; IF interval <= 0.0d0 THEN RETURN WaitResult.Timeout END; IF interval < subInterval THEN subInterval := interval; END; END; END; END XIOWait; PROCEDURE WaitProcess (pid: int; VAR status: int): int = (* ThreadPThread.m3 and ThreadPosix.m3 are very similar. *) BEGIN LOOP WITH r = Uexec.waitpid(pid, ADR(status), 0) DO <*ASSERT r # 0*> IF r > 0 THEN RETURN r END; IF Cerrno.GetErrno() # Uerror.EINTR THEN RETURN r END; END; END; END WaitProcess; (*--------------------------------------------------- Stack size controls ---*) VAR defaultStackSize := 4096; PROCEDURE GetDefaultStackSize (): CARDINAL = BEGIN RETURN defaultStackSize; END GetDefaultStackSize; PROCEDURE MinDefaultStackSize (size: CARDINAL) = BEGIN defaultStackSize := MAX(defaultStackSize, size); END MinDefaultStackSize; PROCEDURE IncDefaultStackSize (inc: CARDINAL) = BEGIN INC(defaultStackSize, inc); END IncDefaultStackSize; (*--------------------------------------------- Garbage collector support ---*) (* NOTE: These routines are called indirectly by the low-level page fault handler of the garbage collector. So, if they touched traced references, they could trigger indefinite invocations of the fault handler. *) (* In versions of SuspendOthers prior to the addition of the incremental collector, it acquired 'cm' to guarantee that no suspended thread held it. That way when the collector tried to acquire a mutex or signal a condition, it wouldn't deadlock with the suspended thread that held cm. With the VM-synchronized, incremental collector this design is inadequate. Here's a deadlock that occurred: Thread.Broadcast held cm, then it touched its condition argument, the page containing the condition was protected by the collector, another thread started running the page fault handler, the handler called SuspendOthers, SuspendOthers tried to acquire cm. So, SuspendOthers does not grab "cm" before shutting down the other threads. If the collector tries to use any of the thread functions that acquire "cm", it'll be deadlocked. *) VAR suspended: BOOLEAN := FALSE; (* LL=activeMu *) PROCEDURE SuspendOthers () = (* LL=0. Always bracketed with ResumeOthers which releases "activeMu" *) BEGIN WITH r = pthread_mutex_lock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; StopWorld(); <*ASSERT NOT suspended*> suspended := TRUE; END SuspendOthers; PROCEDURE ResumeOthers () = (* LL=activeMu. Always preceded by SuspendOthers. *) BEGIN <*ASSERT suspended*> suspended := FALSE; StartWorld(); WITH r = pthread_mutex_unlock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; END ResumeOthers; PROCEDURE ProcessStacks (p: PROCEDURE (start, limit: ADDRESS)) = (* LL=activeMu. Only called within {SuspendOthers, ResumeOthers} *) VAR me := GetActivation(); act: Activation; BEGIN ProcessMe(me, p); act := me.next; WHILE act # me DO ProcessOther(act, p); act := act.next; END; END ProcessStacks; PROCEDURE ProcessEachStack (p: PROCEDURE (start, limit: ADDRESS)) = (* LL=0 *) VAR me := GetActivation(); act: Activation; acks: int; nLive, nDead, newlySent: INTEGER := 0; wait_nsecs := RETRY_INTERVAL; BEGIN WITH r = pthread_mutex_lock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; ProcessMe(me, p); act := me.next; WHILE act # me DO (* stop *) LOOP <*ASSERT act.state = ActState.Started*> SetState(act, ActState.Stopping); IF SIG_SUSPEND = 0 THEN IF StopThread(act) THEN SetState(act, ActState.Stopped); EXIT; ELSE SetState(act, ActState.Started); END; ELSE SignalThread(act); INC(nLive); EXIT; END; Nanosleep(WAIT_UNIT); END; WHILE nLive > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nLive THEN EXIT END; <*ASSERT acks < nLive*> IF wait_nsecs <= 0 THEN newlySent := 0; <*ASSERT act.state # ActState.Starting*> IF act.state # ActState.Stopped THEN SetState(act, ActState.Stopping); SignalThread(act); INC(newlySent); END; WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF newlySent < nLive - acks THEN (* how did we manage to lose some? *) nLive := acks + newlySent; END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; FOR i := 0 TO nLive - 1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; (* process *) ProcessOther(act, p); (* start *) nDead := 0; LOOP <*ASSERT act.state = ActState.Stopped*> SetState(act, ActState.Starting); IF SIG_SUSPEND = 0 THEN IF StartThread(act) THEN SetState(act, ActState.Started); EXIT; ELSE SetState(act, ActState.Stopped); END; ELSE SignalThread(act); INC(nDead); EXIT; END; Nanosleep(WAIT_UNIT); END; WHILE nDead > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nDead THEN EXIT END; <*ASSERT acks < nDead*> IF wait_nsecs <= 0 THEN newlySent := 0; <*ASSERT act.state # ActState.Stopping*> IF act.state # ActState.Started THEN SignalThread(act); INC(newlySent); END; WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF newlySent < nDead - acks THEN (* how did we manage to lose some? *) nDead := acks + newlySent; END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; FOR i := 0 TO nDead - 1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; END; WITH r = pthread_mutex_unlock(activeMu,ThisLine()) DO <*ASSERT r=0*> END; END ProcessEachStack; PROCEDURE ProcessMe (me: Activation; p: PROCEDURE (start, limit: ADDRESS)) = (* LL=activeMu *) BEGIN <*ASSERT me.state # ActState.Stopped*> IF DEBUG THEN RTIO.PutText("Processing act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); END; RTHeapRep.FlushThreadState(me.heapState); ProcessLive(me.stackbase, p); END ProcessMe; PROCEDURE ProcessOther (act: Activation; p: PROCEDURE (start, stop: ADDRESS)) = (* LL=activeMu *) BEGIN <*ASSERT act.state = ActState.Stopped*> IF DEBUG THEN RTIO.PutText("Processing act="); RTIO.PutAddr(act); RTIO.PutText("\n"); RTIO.Flush(); END; RTHeapRep.FlushThreadState(act.heapState); IF act.stackbase # NIL THEN ProcessStopped(act.handle, act.stackbase, act.context, p); END; END ProcessOther; (* Signal based suspend/resume *) PROCEDURE SignalThread(act: Activation) = (* LL=activeMu *) BEGIN <*ASSERT SIG_SUSPEND # 0*> LOOP WITH z = pthread_kill(act.handle, SIG_SUSPEND) DO IF z = 0 THEN EXIT END; IF z # Uerror.EAGAIN THEN DieI(ThisLine(), z) END; (* try it again... *) END; END; END SignalThread; PROCEDURE StopThread (act: Activation): BOOLEAN = (* LL=activeMu *) BEGIN <*ASSERT act.state = ActState.Stopping*> <*ASSERT SIG_SUSPEND = 0*> IF NOT SuspendThread(act.handle) THEN RETURN FALSE END; IF act.heapState.inCritical # 0 THEN IF NOT RestartThread(act.handle) THEN <*ASSERT FALSE*> END; RETURN FALSE; END; RETURN TRUE; END StopThread; PROCEDURE StartThread (act: Activation): BOOLEAN = (* LL=activeMu *) BEGIN <*ASSERT act.state = ActState.Starting*> <*ASSERT SIG_SUSPEND = 0*> RETURN RestartThread(act.handle); END StartThread; PROCEDURE StopWorld () = (* LL=activeMu *) VAR me := GetActivation(); act: Activation; acks: int; nLive, newlySent: INTEGER; retry: BOOLEAN; wait_nsecs := RETRY_INTERVAL; BEGIN IF DEBUG THEN RTIO.PutText("Stopping from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); END; nLive := 0; LOOP retry := FALSE; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Starting*> IF act.state = ActState.Started THEN SetState(act, ActState.Stopping); IF SIG_SUSPEND = 0 THEN IF StopThread(act) THEN SetState(act, ActState.Stopped); ELSE SetState(act, ActState.Started); retry := TRUE; END; ELSE SignalThread(act); INC(nLive); END; END; act := act.next; END; IF NOT retry THEN EXIT END; Nanosleep(WAIT_UNIT); END; WHILE nLive > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nLive THEN EXIT END; <*ASSERT acks < nLive*> IF wait_nsecs <= 0 THEN newlySent := 0; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Starting*> IF act.state # ActState.Stopped THEN SetState(act, ActState.Stopping); SignalThread(act); INC(newlySent); END; act := act.next; END; WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF newlySent < nLive - acks THEN (* how did we manage to lose some? *) nLive := acks + newlySent; END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; (* drain semaphore *) FOR i := 0 TO nLive-1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; IF DEBUG THEN RTIO.PutText("Stopped from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); DumpThreads(); END; END StopWorld; PROCEDURE StartWorld () = (* LL=activeMu *) VAR me := GetActivation(); act: Activation; acks: int; nDead, newlySent: INTEGER; retry: BOOLEAN; wait_nsecs := RETRY_INTERVAL; BEGIN IF DEBUG THEN RTIO.PutText("Starting from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); END; nDead := 0; LOOP retry := FALSE; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Stopping*> IF act.state # ActState.Started THEN SetState(act, ActState.Starting); IF SIG_SUSPEND = 0 THEN IF StartThread(act) THEN SetState(act, ActState.Started); ELSE SetState(act, ActState.Stopped); retry := TRUE; END; ELSE SignalThread(act); INC(nDead); END; END; act := act.next; END; IF NOT retry THEN EXIT END; Nanosleep(WAIT_UNIT); END; WHILE nDead > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nDead THEN EXIT END; <*ASSERT acks < nDead*> IF wait_nsecs <= 0 THEN newlySent := 0; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Stopping*> IF act.state # ActState.Started THEN SignalThread(act); INC(newlySent); END; act := act.next; END; WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF newlySent < nDead - acks THEN (* how did we manage to lose some? *) nDead := acks + newlySent; END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; (* drain semaphore *) FOR i := 0 TO nDead-1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; IF DEBUG THEN RTIO.PutText("Started from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); DumpThreads(); END; END StartWorld; PROCEDURE SignalHandler (sig: int; <*UNUSED*>info: ADDRESS; context: ADDRESS) = VAR errno := Cerrno.GetErrno(); me := GetActivation(); BEGIN <*ASSERT sig = SIG_SUSPEND*> IF me.state = ActState.Stopping THEN IF me.heapState.inCritical # 0 THEN me.state := ActState.Started; RETURN; END; me.state := ActState.Stopped; <*ASSERT me.context = NIL*> me.context := context; WITH r = sem_post() DO <*ASSERT r=0*> END; REPEAT sigsuspend() UNTIL me.state = ActState.Starting; me.context := NIL; me.state := ActState.Started; WITH r = sem_post() DO <*ASSERT r=0*> END; END; Cerrno.SetErrno(errno); END SignalHandler; (*----------------------------------------------------------- misc. stuff ---*) PROCEDURE MyId (): Id RAISES {} = VAR me := GetActivation(); BEGIN IF me = NIL THEN RETURN 0 ELSE RETURN me.slot; END; END MyId; PROCEDURE MyFPState (): UNTRACED REF FloatMode.ThreadState = VAR me := GetActivation(); BEGIN RETURN ADR(me.floatState); END MyFPState; PROCEDURE MyHeapState (): UNTRACED REF RTHeapRep.ThreadState = VAR me := GetActivation(); BEGIN RETURN ADR(me.heapState); END MyHeapState; PROCEDURE DisableSwitching () = BEGIN (* no user-level thread switching *) END DisableSwitching; PROCEDURE EnableSwitching () = BEGIN (* no user-level thread switching *) END EnableSwitching; (*---------------------------------------------------------------- errors ---*) PROCEDURE Die (lineno: INTEGER; msg: TEXT) = BEGIN RTError.Msg (ThisFile(), lineno, "Thread client error: ", msg); END Die; PROCEDURE DieI (lineno: INTEGER; i: INTEGER) = BEGIN RTError.MsgI (ThisFile(), lineno, "Thread client error: ", i); END DieI; (*------------------------------------------------------ ShowThread hooks ---*) VAR perfW : RTPerfTool.Handle; perfOn: BOOLEAN := FALSE; (* LL = perfMu *) PROCEDURE PerfStart () = BEGIN IF RTPerfTool.Start ("showthread", perfW) THEN perfOn := TRUE; RTProcess.RegisterExitor (PerfStop); END; END PerfStart; PROCEDURE PerfStop () = BEGIN (* UNSAFE, but needed to prevent deadlock if we're crashing! *) RTPerfTool.Close (perfW); END PerfStop; CONST EventSize = (BITSIZE(ThreadEvent.T) + BITSIZE(CHAR) - 1) DIV BITSIZE(CHAR); TYPE TE = ThreadEvent.Kind; PROCEDURE PerfChanged (s: State) = VAR e := ThreadEvent.T {kind := TE.Changed, id := MyId(), state := s}; BEGIN WITH r = pthread_mutex_lock(perfMu,ThisLine()) DO <*ASSERT r=0*> END; perfOn := RTPerfTool.Send (perfW, ADR (e), EventSize); WITH r = pthread_mutex_unlock(perfMu,ThisLine()) DO <*ASSERT r=0*> END; END PerfChanged; PROCEDURE PerfDeleted () = VAR e := ThreadEvent.T {kind := TE.Deleted, id := MyId()}; BEGIN WITH r = pthread_mutex_lock(perfMu,ThisLine()) DO <*ASSERT r=0*> END; perfOn := RTPerfTool.Send (perfW, ADR (e), EventSize); WITH r = pthread_mutex_unlock(perfMu,ThisLine()) DO <*ASSERT r=0*> END; END PerfDeleted; PROCEDURE PerfRunning () = VAR e := ThreadEvent.T {kind := TE.Running, id := MyId()}; BEGIN WITH r = pthread_mutex_lock(perfMu,ThisLine()) DO <*ASSERT r=0*> END; perfOn := RTPerfTool.Send (perfW, ADR (e), EventSize); WITH r = pthread_mutex_unlock(perfMu,ThisLine()) DO <*ASSERT r=0*> END; END PerfRunning; (*-------------------------------------------------------- Initialization ---*) PROCEDURE InitWithStackBase (stackbase: ADDRESS) = VAR self: T; me: Activation; BEGIN InitC(stackbase); me := NEW(Activation, mutex := pthread_mutex_new(), cond := pthread_cond_new()); InitActivations(me); me.stackbase := stackbase; IF me.mutex = NIL OR me.cond = NIL THEN Die(ThisLine(), "Thread initialization failed."); END; self := NEW(T, act := me, closure := NIL, join := NIL); me.slot := AssignSlot(self); joinMu := NEW(MUTEX); PerfStart(); IF perfOn THEN PerfRunning() END; IF RTParams.IsPresent("backgroundgc") THEN RTCollectorSRC.StartBackgroundCollection(); END; IF RTParams.IsPresent("foregroundgc") THEN RTCollectorSRC.StartForegroundCollection(); END; END InitWithStackBase; PROCEDURE Init ()= VAR r: INTEGER; BEGIN r := RTProcess.RegisterForkHandlers(AtForkPrepare, AtForkParent, AtForkChild); IF r # 0 THEN DieI(ThisLine(), r) END; InitWithStackBase(ADR(r)); (* not quite accurate but hopefully ok *) END Init; PROCEDURE PThreadLockMutex(mutex: pthread_mutex_t; line: INTEGER) = BEGIN IF mutex # NIL THEN WITH r = pthread_mutex_lock(mutex,ThisLine()) DO IF r # 0 THEN DieI(line, r) END; END; END; END PThreadLockMutex; PROCEDURE PThreadUnlockMutex(mutex: pthread_mutex_t; line: INTEGER) = BEGIN IF mutex # NIL THEN WITH r = pthread_mutex_unlock(mutex,ThisLine()) DO IF r # 0 THEN DieI(line, r) END; END; END; END PThreadUnlockMutex; PROCEDURE AtForkPrepare() = VAR me := GetActivation(); act: Activation; BEGIN PThreadLockMutex(slotsMu, ThisLine()); PThreadLockMutex(perfMu, ThisLine()); PThreadLockMutex(initMu, ThisLine()); (* InitMutex => RegisterFinalCleanup => LockHeap *) PThreadLockMutex(heapMu, ThisLine()); PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => SuspendOthers => activeMu *) (* Walk activations and lock all threads. * NOTE: We have initMu, activeMu, so slots won't change, conditions and * mutexes won't be initialized on-demand. *) act := me; REPEAT PThreadLockMutex(act.mutex, ThisLine()); act := act.next; UNTIL act = me; END AtForkPrepare; PROCEDURE AtForkParent() = VAR me := GetActivation(); act: Activation; cond: Condition; BEGIN (* Walk activations and unlock all threads, conditions. *) act := me; REPEAT cond := slots[act.slot].join; IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, ThisLine()) END; PThreadUnlockMutex(act.mutex, ThisLine()); act := act.next; UNTIL act = me; PThreadUnlockMutex(activeMu, ThisLine()); PThreadUnlockMutex(heapMu, ThisLine()); PThreadUnlockMutex(initMu, ThisLine()); PThreadUnlockMutex(perfMu, ThisLine()); PThreadUnlockMutex(slotsMu, ThisLine()); END AtForkParent; PROCEDURE AtForkChild() = BEGIN AtForkParent(); InitWithStackBase(GetActivation().stackbase); END AtForkChild; (*------------------------------------------------------------- collector ---*) (* These procedures provide synchronization primitives for the allocator and collector. *) VAR holder: pthread_t; inCritical := 0; PROCEDURE LockHeap () = VAR self := pthread_self(); BEGIN WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; IF inCritical = 0 THEN holder := self; ELSIF pthread_equal(holder, self) = 0 THEN WITH r = pthread_cond_wait(heapCond, heapMu, ThisLine()) DO <*ASSERT r=0*> END; END; INC(inCritical); WITH r = pthread_mutex_unlock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; END LockHeap; PROCEDURE UnlockHeap () = VAR self := pthread_self(); BEGIN WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; <*ASSERT pthread_equal(holder, self) # 0*> DEC(inCritical); IF inCritical = 0 THEN holder := NIL; END; WITH r = pthread_mutex_unlock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; END UnlockHeap; PROCEDURE WaitHeap () = VAR self := pthread_self(); BEGIN WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; <*ASSERT pthread_equal(holder, self) # 0*> DEC(inCritical); <*ASSERT inCritical = 0*> WITH r = pthread_cond_wait(heapCond, heapMu, ThisLine()) DO <*ASSERT r=0*> END; holder := self; <*ASSERT inCritical = 0*> INC(inCritical); WITH r = pthread_mutex_unlock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; END WaitHeap; PROCEDURE BroadcastHeap () = BEGIN WITH r = pthread_cond_broadcast(heapCond) DO <*ASSERT r=0*> END; END BroadcastHeap; (*--------------------------------------------- exception handling support --*) PROCEDURE GetCurrentHandlers (): ADDRESS = VAR me := GetActivation(); BEGIN RETURN me.frame; END GetCurrentHandlers; PROCEDURE SetCurrentHandlers (h: ADDRESS) = VAR me := GetActivation(); BEGIN me.frame := h; END SetCurrentHandlers; (*RTHooks.PushEFrame*) PROCEDURE PushEFrame (frame: ADDRESS) = TYPE Frame = UNTRACED REF RECORD next: ADDRESS END; VAR me := GetActivation(); f: Frame := frame; BEGIN f.next := me.frame; me.frame := f; END PushEFrame; (*RTHooks.PopEFrame*) PROCEDURE PopEFrame (frame: ADDRESS) = VAR me := GetActivation(); BEGIN me.frame := frame; END PopEFrame; VAR DEBUG := RTParams.IsPresent("debugthreads"); BEGIN END ThreadPThread. -------------- next part -------------- (* Copyright (C) 2005, Purdue Research Foundation *) (* All rights reserved. *) (* See the file COPYRIGHT-PURDUE for a full description. *) (*---------------------------------------------------------------------------*) UNSAFE INTERFACE ThreadPThread; FROM Ctypes IMPORT int; FROM Cstddef IMPORT size_t; TYPE (* These are opaque C references (not necessarily UNTRACED REF ADDRESS) *) pthread_t = UNTRACED BRANDED REF ADDRESS; pthread_mutex_t = UNTRACED BRANDED REF ADDRESS; pthread_cond_t = UNTRACED BRANDED REF ADDRESS; Activation <: ADDRESS; (* untraced thread stated stored in thread local *) (*---------------------------------------------------------------------------*) PROCEDURE SignalHandler(sig: int; info, uap: ADDRESS); (*---------------------------------------------------------------------------*) <*EXTERNAL "ThreadPThread__SIG_SUSPEND"*> (*CONST*) VAR SIG_SUSPEND: int; (*---------------------------------------------------------------------------*) <*EXTERNAL "ThreadPThread__InitC"*> PROCEDURE InitC(bottom: ADDRESS); (*---------------------------------------------------------------------------*) (* the semaphore is implied *) <*EXTERNAL "ThreadPThread__sem_wait"*> PROCEDURE sem_wait (): int; <*EXTERNAL "ThreadPThread__sem_post"*> PROCEDURE sem_post (): int; <*EXTERNAL "ThreadPThread__sem_getvalue"*> PROCEDURE sem_getvalue (VAR value: int): int; (*---------------------------------------------------------------------------*) (* the signal set is implied *) <*EXTERNAL "ThreadPThread__sigsuspend"*> PROCEDURE sigsuspend (); (*---------------------------------------------------------------------------*) (* pthread_create but replace attr with stackSize so that attr need not be known to Modula-3 *) <*EXTERNAL "ThreadPThread__thread_create"*> PROCEDURE thread_create(stackSize: size_t; start_routine: PROCEDURE(arg: ADDRESS): ADDRESS; arg: ADDRESS): int; <*EXTERNAL ThreadPThread__pthread_detach_self*> PROCEDURE pthread_detach_self(): int; <*EXTERNAL ThreadPThread__pthread_self*> PROCEDURE pthread_self(): pthread_t; <*EXTERNAL "ThreadPThread__pthread_equal"*> PROCEDURE pthread_equal(t1, t2: pthread_t): int; <*EXTERNAL "ThreadPThread__pthread_kill"*> PROCEDURE pthread_kill(t: pthread_t; sig: int): int; (*---------------------------------------------------------------------------*) (* static mutexes and conditions *) <*EXTERNAL "ThreadPThread__activeMu"*> VAR activeMu: pthread_mutex_t; <*EXTERNAL "ThreadPThread__slotsMu"*> VAR slotsMu: pthread_mutex_t; <*EXTERNAL "ThreadPThread__initMu"*> VAR initMu: pthread_mutex_t; <*EXTERNAL "ThreadPThread__perfMu"*> VAR perfMu: pthread_mutex_t; <*EXTERNAL "ThreadPThread__heapMu"*> VAR heapMu: pthread_mutex_t; <*EXTERNAL "ThreadPThread__heapCond"*> VAR heapCond: pthread_cond_t; (* thread local "activation" *) <*EXTERNAL ThreadPThread__SetActivation*> PROCEDURE SetActivation(value: Activation); <*EXTERNAL ThreadPThread__GetActivation*> PROCEDURE GetActivation(): Activation; (*---------------------------------------------------------------------------*) (* support for dynamically allocated mutexes and condition variables *) <*EXTERNAL "ThreadPThread__pthread_mutex_new"*> PROCEDURE pthread_mutex_new():pthread_mutex_t; <*EXTERNAL "ThreadPThread__pthread_mutex_delete"*> PROCEDURE pthread_mutex_delete(a:pthread_mutex_t); <*EXTERNAL ThreadPThread__pthread_mutex_lock*> PROCEDURE pthread_mutex_lock(mutex: pthread_mutex_t;line :int):int; <*EXTERNAL ThreadPThread__pthread_mutex_unlock*> PROCEDURE pthread_mutex_unlock(mutex: pthread_mutex_t;line :int):int; <*EXTERNAL "ThreadPThread__pthread_cond_new"*> PROCEDURE pthread_cond_new(): pthread_cond_t; <*EXTERNAL "ThreadPThread__pthread_cond_delete"*> PROCEDURE pthread_cond_delete(cond: pthread_cond_t); <*EXTERNAL ThreadPThread__pthread_cond_wait*> PROCEDURE pthread_cond_wait(cond: pthread_cond_t; mutex: pthread_mutex_t; line:int):int; <*EXTERNAL ThreadPThread__pthread_cond_timedwait*> PROCEDURE pthread_cond_timedwait(cond: pthread_cond_t; mutex: pthread_mutex_t; abs: LONGREAL(*Time.T*)):int; <*EXTERNAL ThreadPThread__pthread_cond_signal*> PROCEDURE pthread_cond_signal(cond: pthread_cond_t):int; <*EXTERNAL ThreadPThread__pthread_cond_broadcast*> PROCEDURE pthread_cond_broadcast(cond: pthread_cond_t):int; (*---------------------------------------------------------------------------*) <*EXTERNAL "ThreadPThread__Nanosleep"*> PROCEDURE Nanosleep(nanoseconds: INTEGER); (*---------------------------------------------------------------------------*) <*EXTERNAL "ThreadPThread__SuspendThread"*> PROCEDURE SuspendThread (t: pthread_t): BOOLEAN; <*EXTERNAL "ThreadPThread__RestartThread"*> PROCEDURE RestartThread (t: pthread_t): BOOLEAN; <*EXTERNAL "ThreadPThread__ProcessLive"*> PROCEDURE ProcessLive (bottom: ADDRESS; p: PROCEDURE(start, limit: ADDRESS)); <*EXTERNAL "ThreadPThread__ProcessStopped"*> PROCEDURE ProcessStopped (t: pthread_t; bottom, context: ADDRESS; p: PROCEDURE(start, limit: ADDRESS)); (*---------------------------------------------------------------------------*) END ThreadPThread. -------------- next part -------------- l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 344 lock 0x1383d70 self 0x1009400 l. 348 unlock 0x1383d70 self 0x1009400 l. 350 lock 0x1383d70 self 0x1009400 l. 381 unlock 0x1383d70 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250e0 self 0x1009400 l. 125 unlock 0x10250e0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250e0 self 0x1009400 l. 157 unlock 0x10250e0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250e0 self 0x1009400 l. 125 unlock 0x10250e0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250e0 self 0x1009400 l. 157 unlock 0x10250e0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250e0 self 0x1009400 l. 125 unlock 0x10250e0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250e0 self 0x1009400 l. 157 unlock 0x10250e0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250e0 self 0x1009400 l. 125 unlock 0x10250e0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250e0 self 0x1009400 l. 157 unlock 0x10250e0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250e0 self 0x1009400 l. 125 unlock 0x10250e0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250e0 self 0x1009400 l. 157 unlock 0x10250e0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250e8 self 0x1009400 l. 125 unlock 0x10250e8 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250e8 self 0x1009400 l. 157 unlock 0x10250e8 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f0 self 0x1009400 l. 125 unlock 0x10250f0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f0 self 0x1009400 l. 157 unlock 0x10250f0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 757 lock 0x1383d68 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 769 unlock 0x1383d68 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 757 lock 0x1383d68 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 769 unlock 0x1383d68 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f8 self 0x1009400 l. 125 unlock 0x10250f8 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f8 self 0x1009400 l. 157 unlock 0x10250f8 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f8 self 0x1009400 l. 125 unlock 0x10250f8 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f8 self 0x1009400 l. 157 unlock 0x10250f8 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f8 self 0x1009400 l. 125 unlock 0x10250f8 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f8 self 0x1009400 l. 157 unlock 0x10250f8 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025100 self 0x1009400 l. 125 unlock 0x1025100 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250e0 self 0x1009400 l. 125 unlock 0x10250e0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250e0 self 0x1009400 l. 157 unlock 0x10250e0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025100 self 0x1009400 l. 157 unlock 0x1025100 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 757 lock 0x1383d68 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 769 unlock 0x1383d68 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 757 lock 0x1383d68 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 769 unlock 0x1383d68 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f0 self 0x1009400 l. 125 unlock 0x10250f0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f0 self 0x1009400 l. 157 unlock 0x10250f0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f0 self 0x1009400 l. 125 unlock 0x10250f0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f0 self 0x1009400 l. 157 unlock 0x10250f0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f0 self 0x1009400 l. 125 unlock 0x10250f0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f0 self 0x1009400 l. 157 unlock 0x10250f0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025108 self 0x1009400 l. 125 unlock 0x1025108 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025108 self 0x1009400 l. 157 unlock 0x1025108 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025110 self 0x1009400 l. 125 unlock 0x1025110 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025110 self 0x1009400 l. 157 unlock 0x1025110 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 757 lock 0x1383d68 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 769 unlock 0x1383d68 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025118 self 0x1009400 l. 125 unlock 0x1025118 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025118 self 0x1009400 l. 157 unlock 0x1025118 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025120 self 0x1009400 l. 125 unlock 0x1025120 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025120 self 0x1009400 l. 157 unlock 0x1025120 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f8 self 0x1009400 l. 125 unlock 0x10250f8 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f8 self 0x1009400 l. 157 unlock 0x10250f8 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x10250f0 self 0x1009400 l. 125 unlock 0x10250f0 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x10250f0 self 0x1009400 l. 157 unlock 0x10250f0 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025100 self 0x1009400 l. 125 unlock 0x1025100 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 757 lock 0x1383d68 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 769 unlock 0x1383d68 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 l. 152 lock 0x1025100 self 0x1009400 l. 157 unlock 0x1025100 self 0x1009400 l. 158 unlock 0x10250a8 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 757 lock 0x1383d68 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 769 unlock 0x1383d68 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 344 lock 0x1383d70 self 0x1009400 l. 381 unlock 0x1383d70 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 121 lock 0x10250a8 self 0x1009400 l. 122 lock 0x1025138 self 0x1009400 l. 125 unlock 0x1025138 self 0x1009400 l. 126 unlock 0x10250a8 self 0x1009400 l. 103 lock 0x1383d78 self 0x1009400 l. 1373 lock 0x1383d88 self 0x1009400 l. 1380 unlock 0x1383d88 self 0x1009400 l. 1386 lock 0x1383d88 self 0x1009400 l. 1392 unlock 0x1383d88 self 0x1009400 l. 112 unlock 0x1383d78 self 0x1009400 l. 194 lock 0x10250a8 self 0x1009400 l. 198 lock 0x1025140 self 0x1009400 l. 202 unlock 0x1025140 self 0x1009400 l. 151 lock 0x10250a8 self 0x1009400 ERROR: pthread_mutex_lock:11 From mika at async.caltech.edu Wed Aug 13 00:12:09 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 12 Aug 2014 15:12:09 -0700 Subject: [M3devel] Latest pthreads attempt In-Reply-To: <8B27D029-50B0-49B9-B673-34C128B103BB@cs.purdue.edu> References: <8B27D029-50B0-49B9-B673-34C128B103BB@cs.purdue.edu> Message-ID: <20140812221209.9D5F51A2094@async.async.caltech.edu> Tony, I've been reading a bit of the pthread code and I have a question... What if one were to write a ThreadPThread that is a very thin veneer over pthreads? What goes wrong? That is, simply translate Modula-3 calls Thread.Acquire to pthread_lock(...), Modula-3 condition variables to pthread condition variables, etc. I know Alerted is a bit different but it's cooperative: both the waiter and alerter know they are going to be Alerted (so it could be less efficient and have extra data structures). Would there be issues with the garbage collector? Some inefficiency? I think I am mainly worried about the presence of "GetActivation()" in critical places like LockMutex and UnlockMutex. Maybe it's not a big deal anymore...(it used to be a real drag at least on FreeBSD because it involved a system call). Mika From mika at async.caltech.edu Wed Aug 13 03:47:58 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 12 Aug 2014 18:47:58 -0700 Subject: [M3devel] LockHeap Message-ID: <20140813014758.7CF501A2094@async.async.caltech.edu> The code in LockHeap looks dubious to me: VAR holder: pthread_t; inCritical := 0; PROCEDURE LockHeap () = VAR self := pthread_self(); BEGIN WITH r = pthread_mutex_lock(heapMu) DO <*ASSERT r=0*> END; IF inCritical = 0 THEN holder := self; ELSIF pthread_equal(holder, self) = 0 THEN WITH r = pthread_cond_wait(heapCond, heapMu) DO <*ASSERT r=0*> END; END; INC(inCritical); WITH r = pthread_mutex_unlock(heapMu) DO <*ASSERT r=0*> END; END LockHeap; My understanding is that this code is relatively simple in that there's a single pthread mutex, heapMu, that protects holder and inCritical. All it's trying to do is build a "reentrant" mutex (of the kind Dragisa was asking for a while back). To annotate a bit: PROCEDURE LockHeap () = VAR self := pthread_self(); BEGIN WITH r = pthread_mutex_lock(heapMu) DO <*ASSERT r=0*> END; (* heapMu locked --- only a single thread can be here *) IF inCritical = 0 THEN holder := self; ELSIF pthread_equal(holder, self) = 0 THEN WITH r = pthread_cond_wait(heapCond, heapMu) DO <*ASSERT r=0*> END; (* heapMu locked *) END; INC(inCritical); WITH r = pthread_mutex_unlock(heapMu) DO <*ASSERT r=0*> END; (* heapMu unlocked *) END LockHeap; Based on the assertions in UnlockHeap it seems that the postcondition of LockHeap should be { holder = self AND inCritical > 0 }. So we check if inCritical is 0 -- no one else wants the critical section. OK: mark self as holder and return. Next we check if we already have the critical section (pthread_equal() # 0). If we do, ok, just return, we're done. If neither of those succeeds, we wait for ... what, actually? If neither succeeds, that means another thread is in the critical section. We need to wait for it to release the critical section. Doesn't that mean that we have to wait for the condition { inCritical = 0 OR pthread_equal(holder,self) # 0 }? Since we're a single thread here, we actually need only wait for inCritical = 0.... In any case, my coding of this would be: PROCEDURE LockHeap () = VAR self := pthread_self(); BEGIN WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; LOOP IF inCritical = 0 THEN holder := self; EXIT ELSIF pthread_equal(holder,self) # 0 THEN EXIT ELSE WITH r = pthread_cond_wait(heapCond, heapMu, ThisLine()) DO <*ASSERT r=0*> END; END END; INC(inCritical); <*ASSERT pthread_equal(holder, self) # 0*> WITH r = pthread_mutex_unlock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; END LockHeap; (it makes more logical sense to have the pthread_equal test first, but it is probably much faster to check inCritical so let's check that first). I'm not sure how this could have gotten screwed up? It seems really basic.. unless I'm misunderstanding the code. I note that the documentation in RTOS.i3 also seems slightly incorrect: PROCEDURE WaitHeap (VAR thread: RTHeapRep.ThreadState); Blocks the caller until BroadcastHeap has been called and the allocator/collector critical section is released. The caller must be in the critical section. Shouldn't it say "The calling thread must have entered the critical section exactly once."? (Given that the "LockHeap" is reentrant...) Why is there a reentrant mutex here, anyhow? Mika From mika at async.caltech.edu Wed Aug 13 04:14:01 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 12 Aug 2014 19:14:01 -0700 Subject: [M3devel] Ho hum... AtFork... Message-ID: <20140813021401.238B31A2094@async.async.caltech.edu> Question... is there something odd about my pthreads? Are pthreads normally reentrant? I didn't think so. My compiler is much happier with the following changes I already outlined: 1. a dirty, disgusting hack to keep from locking against myself going from XWait with self.mutex locked to m.release(). 2. the change to LockHeap I described in previous email But now... (gdb) cont Continuing. ERROR: pthread_mutex_lock:11 ERROR: pthread_mutex_lock:11 Program received signal SIGABRT, Aborted. 0x000000080107626a in thr_kill () from /lib/libc.so.7 (gdb) where #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 #1 0x000000080113dac9 in abort () from /lib/libc.so.7 #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ffffb508: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 #3 0x000000000071d48d in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1377 #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=Error accessing memory address 0x8000ffffb568: Bad address. ) at ../src/runtime/common/RTCollector.m3:2234 #5 0x000000000071d284 in ThreadPThread__AtForkParent () at ../src/thread/PTHREAD/ThreadPThread.m3:1348 #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 #7 0x000000000070dd8b in RTProcess__Fork () at ../src/runtime/common/RTProcessC.c:152 #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec (M3_Bd56fi_cmd=Error accessing memory address 0x8000ffffb6f8: Bad address. ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 #9 0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=Error accessing memory address 0x8000ffffb7f8: Bad address. ) at ../src/os/POSIX/ProcessPosix.m3:21 #10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=Error accessing memory address 0x8000ffffb838: Bad address. ) at ../src/QMachine.m3:1666 #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=Error accessing memory address 0x8000ffffb9f8: Bad address. ) at ../src/QMachine.m3:1605 #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=Error accessing memory address 0x8000ffffbee8: Bad address. ) at ../src/QMachine.m3:1476 What am I doing wrong here? The error doesn't look unreasonable! Looking more closely at the code: First, AtForkPrepare has been called: PROCEDURE AtForkPrepare() = VAR me := GetActivation(); act: Activation; BEGIN PThreadLockMutex(slotsMu, ThisLine()); PThreadLockMutex(perfMu, ThisLine()); PThreadLockMutex(initMu, ThisLine()); (* InitMutex => RegisterFinalCleanup => LockHeap *) PThreadLockMutex(heapMu, ThisLine()); PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => SuspendOthers => activeMu *) (* Walk activations and lock all threads. * NOTE: We have initMu, activeMu, so slots won't change, conditions and * mutexes won't be initialized on-demand. *) act := me; REPEAT PThreadLockMutex(act.mutex, ThisLine()); act := act.next; UNTIL act = me; END AtForkPrepare; a postcondition of this routine is that heapMu is locked. now we get into AtForkParent: PROCEDURE AtForkParent() = VAR me := GetActivation(); act: Activation; cond: Condition; BEGIN (* Walk activations and unlock all threads, conditions. *) act := me; REPEAT cond := slots[act.slot].join; IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, ThisLine()) END; PThreadUnlockMutex(act.mutex, ThisLine()); act := act.next; UNTIL act = me; PThreadUnlockMutex(activeMu, ThisLine()); PThreadUnlockMutex(heapMu, ThisLine()); PThreadUnlockMutex(initMu, ThisLine()); PThreadUnlockMutex(perfMu, ThisLine()); PThreadUnlockMutex(slotsMu, ThisLine()); END AtForkParent; We can see by inspecting the code that a necessary precondition for this routine is that heapMu is locked! (Since it's going to unlock it, it had BETTER be locked on entry.) But the cond := ... causes a RTHooks.CheckLoadTracedRef which causes an RTOS.LockHeap the code of which we just saw: PROCEDURE LockHeap () = VAR self := pthread_self(); BEGIN WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; ... we try to lock heapMu. kaboom! No surprise there, really? Am I going about this totally the wrong way? Other people are running Modula-3 with pthreads, right? Right?? Somewhere out there in m3devel-land? Mika From peter.mckinna at gmail.com Wed Aug 13 04:50:53 2014 From: peter.mckinna at gmail.com (Peter McKinna) Date: Wed, 13 Aug 2014 12:50:53 +1000 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: <20140813021401.238B31A2094@async.async.caltech.edu> References: <20140813021401.238B31A2094@async.async.caltech.edu> Message-ID: Mika I think you need to back out Tony's changes to fix the fork bug, at least for now. Need to reload from cvs version 1.262 for ThreadPThread.m3 If you're using git you're on your own. Do a cvs log ThreadPThread.m3 for an explanation for some of the design principles. Also if you use gdb then you need to set lanc c before backtraces so at least you can see address names and values even if they are contorted you can extract the M3 name in the parm lists. Also in gdb thread apply all bt gives all thread backtraces which can be handy to see whose got the locks held. Regards Peter On Wed, Aug 13, 2014 at 12:14 PM, wrote: > > Question... is there something odd about my pthreads? Are pthreads > normally reentrant? I didn't think so. > > My compiler is much happier with the following changes I already outlined: > > 1. a dirty, disgusting hack to keep from locking against myself going from > XWait with self.mutex locked to m.release(). > > 2. the change to LockHeap I described in previous email > > But now... > > (gdb) cont > Continuing. > ERROR: pthread_mutex_lock:11 > ERROR: pthread_mutex_lock:11 > > Program received signal SIGABRT, Aborted. > 0x000000080107626a in thr_kill () from /lib/libc.so.7 > (gdb) where > #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 > #1 0x000000080113dac9 in abort () from /lib/libc.so.7 > #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock (mutex=Error > accessing memory address 0x8000ffffb508: Bad address. > ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 > #3 0x000000000071d48d in RTOS__LockHeap () at > ../src/thread/PTHREAD/ThreadPThread.m3:1377 > #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=Error > accessing memory address 0x8000ffffb568: Bad address. > ) at ../src/runtime/common/RTCollector.m3:2234 > #5 0x000000000071d284 in ThreadPThread__AtForkParent () at > ../src/thread/PTHREAD/ThreadPThread.m3:1348 > #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 > #7 0x000000000070dd8b in RTProcess__Fork () at > ../src/runtime/common/RTProcessC.c:152 > #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec > (M3_Bd56fi_cmd=Error accessing memory address 0x8000ffffb6f8: Bad address. > ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 > #9 0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=Error accessing > memory address 0x8000ffffb7f8: Bad address. > ) at ../src/os/POSIX/ProcessPosix.m3:21 > #10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=Error > accessing memory address 0x8000ffffb838: Bad address. > ) at ../src/QMachine.m3:1666 > #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=Error > accessing memory address 0x8000ffffb9f8: Bad address. > ) at ../src/QMachine.m3:1605 > #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=Error accessing > memory address 0x8000ffffbee8: Bad address. > ) at ../src/QMachine.m3:1476 > > What am I doing wrong here? > > The error doesn't look unreasonable! Looking more closely at the code: > > First, AtForkPrepare has been called: > > PROCEDURE AtForkPrepare() = > VAR me := GetActivation(); > act: Activation; > BEGIN > PThreadLockMutex(slotsMu, ThisLine()); > PThreadLockMutex(perfMu, ThisLine()); > PThreadLockMutex(initMu, ThisLine()); (* InitMutex => > RegisterFinalCleanup => LockHeap *) > PThreadLockMutex(heapMu, ThisLine()); > PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => SuspendOthers > => activeMu *) > (* Walk activations and lock all threads. > * NOTE: We have initMu, activeMu, so slots won't change, conditions > and > * mutexes won't be initialized on-demand. > *) > act := me; > REPEAT > PThreadLockMutex(act.mutex, ThisLine()); > act := act.next; > UNTIL act = me; > END AtForkPrepare; > > a postcondition of this routine is that heapMu is locked. > > now we get into AtForkParent: > > PROCEDURE AtForkParent() = > VAR me := GetActivation(); > act: Activation; > cond: Condition; > BEGIN > (* Walk activations and unlock all threads, conditions. *) > act := me; > REPEAT > cond := slots[act.slot].join; > IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, ThisLine()) END; > PThreadUnlockMutex(act.mutex, ThisLine()); > act := act.next; > UNTIL act = me; > PThreadUnlockMutex(activeMu, ThisLine()); > PThreadUnlockMutex(heapMu, ThisLine()); > PThreadUnlockMutex(initMu, ThisLine()); > PThreadUnlockMutex(perfMu, ThisLine()); > PThreadUnlockMutex(slotsMu, ThisLine()); > END AtForkParent; > > We can see by inspecting the code that a necessary precondition for > this routine is that heapMu is locked! (Since it's going to unlock it, > it had BETTER be locked on entry.) > > But the cond := ... causes a RTHooks.CheckLoadTracedRef > > which causes an RTOS.LockHeap > > the code of which we just saw: > > PROCEDURE LockHeap () = > VAR self := pthread_self(); > BEGIN > WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; > ... > > we try to lock heapMu. kaboom! No surprise there, really? > > Am I going about this totally the wrong way? Other people are running > Modula-3 > with pthreads, right? Right?? Somewhere out there in m3devel-land? > > Mika > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mika at async.caltech.edu Wed Aug 13 06:54:15 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 12 Aug 2014 21:54:15 -0700 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: References: <20140813021401.238B31A2094@async.async.caltech.edu> Message-ID: <20140813045415.C13921A2094@async.async.caltech.edu> Yeah OK 1.262 makes a lot more sense to me but I'm still not getting things to work and now I'm really baffled because I think I understand this code! What I did was I threw away all my changes and reverted ThreadPThread.m3 to 1.262 as you suggested. Rebuilt the compiler with upgrade.sh Then rebuilt the compiler again with itself. Then I realcleaned the world and buildshipped it. (I was afraid that parseparams, also imported by the thread tester, would pollute it somehow.) When I look at the code in 1.262 it looks quite straightforward. heapMu is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. Condition variables are mutexes too, but that's no big deal. So, rebuild thread tester, run it: new source -> compiling Main.m3 -> linking threadtest root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # AMD64_FREEBSD/threadtest Writing file...done Creating read threads...done Creating fork threads...done Creating alloc threads...done Creating lock threads...done running...printing oldest/median age/newest . *** *** runtime error: *** Segmentation violation - possible attempt to dereference NIL.........laziest thread is 1407901189/1407901189/9 (tests: read 1407901189/1407901189/1407901189 fork 1407901189/1407901189/1407901189 alloc 9/9/9 lock 1407901189/1407901189/9) ^C root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb !$ gdb AMD64_FREEBSD/threadtest GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "amd64-marcel-freebsd"... (gdb) run Starting program: /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/threadtest [New LWP 100121] Writing file...done Creating read threads...done Creating fork threads...done Creating alloc threads...done Creating lock threads...done running...printing oldest/median age/newest .[New Thread 801807000 (LWP 100343/threadtest)] [New Thread 801807c00 (LWP 100667/threadtest)] [New Thread 801808800 (LWP 100816/threadtest)] [New Thread 801807400 (LWP 100349/threadtest)] [New Thread 801808400 (LWP 100815/threadtest)] [New Thread 801807800 (LWP 100352/threadtest)] [New Thread 801808c00 (LWP 100817/threadtest)] [New Thread 801809000 (LWP 100818/threadtest)] [New Thread 801809800 (LWP 100820/threadtest)] [New Thread 801808000 (LWP 100678/threadtest)] [New Thread 801806400 (LWP 100121/threadtest)] [New Thread 801806800 (LWP 100341/threadtest)] [New Thread 801806c00 (LWP 100342/threadtest)] .ERROR: pthread_mutex_lock:11 Program received signal SIGABRT, Aborted. [Switching to Thread 801809800 (LWP 100820/threadtest)] 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 (gdb) where #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000fe5f2d98: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 #3 0x000000000044b370 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error accessing memory address 0x8000fe5f2dc8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=Error accessing memory address 0x8000fe5f2df8: Bad address. ) at ../src/Main.m3:319 #5 0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000fe5f2eb8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 #6 0x000000000044cf00 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000fe5f2f68: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 #7 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 #8 0x0000000000000000 in ?? () (gdb) set lang c (gdb) thread apply all bt ... not that interesting ... Segfault is segfault---error 11 is EDEADLK (locking against myself?) ????? the code is very straightforward, as I said. I thought people had the thread tester working with pthreads? Which set of files, then? Anyone on FreeBSD/amd64? Could it be an issue with "volatile"? Not even sure where to look. The code calling the lock is just this: PROCEDURE GetChar (rd: T): CHAR RAISES {EndOfFile, Failure, Alerted} = BEGIN LOCK rd DO RETURN FastGetChar(rd); END END GetChar; No mysteries there... Ah is this the fork bug? Looks like the Init routine is called on a lot of NIL mutexes around the fork. But the subprocesses aren't meant to accesses the mutexes... humm Hmm, and it's not entirely a fork issue. Even with "threadtest -tests STD,-fork,-forktoomuch" it misbehaves. Hangs.... Looks like a deadlock this time. Some stacks... Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): #0 0x00000000004b4e2b in __vdso_gettimeofday () #1 0x00000000004ab8d2 in gettimeofday () #2 0x0000000000452e4b in TimePosix__Now () at ../src/time/POSIX/TimePosixC.c:50 #3 0x0000000000452d72 in Time__Now () at ../src/time/POSIX/TimePosix.m3:14 #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=Error accessing memory address 0x8000fedf6df8: Bad address. ) at ../src/Main.m3:327 #5 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000fedf6eb8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 #6 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000fedf6f68: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 #7 0x000000000047c7d4 in thread_start () #8 0x0000000000000000 in ?? () Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): #0 0x000000000047e53c in _umtx_op_err () #1 0x0000000000475f14 in __thr_umutex_lock () #2 0x0000000000479404 in mutex_lock_common () #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000feff7d98: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004480c0 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error accessing memory address 0x8000feff7dc8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=Error accessing memory address 0x8000feff7df8: Bad address. ) at ../src/Main.m3:319 #6 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000feff7eb8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 #7 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000feff7f68: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 #8 0x000000000047c7d4 in thread_start () #9 0x0000000000000000 in ?? () Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): #0 0x000000000047e53c in _umtx_op_err () #1 0x0000000000475759 in suspend_common () #2 0x00000000004755c1 in pthread_suspend_np () #3 0x000000000044df0c in ThreadPThread__SuspendThread (mt=Error accessing memory address 0x8000ffbfd6f8: Bad address. ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 #4 0x000000000044bade in ThreadPThread__StopThread (M3_DMxDjQ_act=Error accessing memory address 0x8000ffbfd718: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 #5 0x000000000044bc81 in ThreadPThread__StopWorld () at ../src/thread/PTHREAD/ThreadPThread.m3:948 #6 0x000000000044b19e in RTThread__SuspendOthers () at ../src/thread/PTHREAD/ThreadPThread.m3:713 #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero () at ../src/runtime/common/RTCollector.m3:749 #8 0x0000000000433081 in RTCollector__CollectSome () at ../src/runtime/common/RTCollector.m3:723 #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at ../src/runtime/common/RTCollector.m3:657 #10 0x000000000042ff83 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffbfd958: Bad address. ) at ../src/runtime/common/RTAllocator.m3:367 #11 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error accessing memory address 0x8000ffbfda18: Bad address. ) at ../src/runtime/common/RTAllocator.m3:296 #12 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=Error accessing memory address 0x8000ffbfda78: Bad address. ) at ../src/runtime/common/RTAllocator.m3:143 #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=Error accessing memory address 0x8000ffbfdab8: Bad address. ) at ../src/rw/Rd.m3:159 #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=Error accessing memory address 0x8000ffbfdb88: Bad address. ) at ../src/rw/Rd.m3:187 #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=Error accessing memory address 0x8000ffbfdbd8: Bad address. ) at ../src/rw/Rd.m3:176 #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=Error accessing memory address 0x8000ffbfdc58: Bad address. ) at ../src/Main.m3:185 #17 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000ffbfdeb8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 #18 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000ffbfdf68: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 #19 0x000000000047c7d4 in thread_start () #20 0x0000000000000000 in ?? () Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): #0 0x000000000047e53c in _umtx_op_err () #1 0x0000000000475f14 in __thr_umutex_lock () #2 0x0000000000479404 in mutex_lock_common () #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ffffc678: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1337 ---Type to continue, or q to quit--- #5 0x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffffc6e8: Bad address. ) at ../src/runtime/common/RTAllocator.m3:365 #6 0x000000000042f15b in RTAllocator__GetTracedObj (M3_Eic7CK_def=Error accessing memory address 0x8000ffffc7a8: Bad address. ) at ../src/runtime/common/RTAllocator.m3:224 #7 0x000000000042eb23 in RTHooks__AllocateTracedObj (M3_AJWxb1_defn=Error accessing memory address 0x8000ffffc7f8: Bad address. ) at ../src/runtime/common/RTAllocator.m3:122 #8 0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=Error accessing memory address 0x8000ffffc858: Bad address. ) at ../src/text/TextCat.m3:562 #9 0x000000000045ed5d in TextCat__Balance (M3_Bd56fi_LText=0x800c490b0, M3_BUgnwf_LInfo=Error accessing memory address 0x8000ffffc8f8: Bad address. ) at ../src/text/TextCat.m3:488 #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=Error accessing memory address 0x8000ffffcbb8: Bad address. ) at ../src/text/TextCat.m3:40 #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=Error accessing memory address 0x8000ffffcc38: Bad address. ) at ../src/Main.m3:593 #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=Error accessing memory address 0x8000ffffcf88: Bad address. ) at ../src/runtime/common/RTLinker.m3:408 #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=Error accessing memory address 0x8000ffffd008: Bad address. ) at ../src/runtime/common/RTLinker.m3:115 #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=Error accessing memory address 0x8000ffffd028: Bad address. ) at ../src/runtime/common/RTLinker.m3:124 #15 0x00000000004004a6 in main (argc=Error accessing memory address 0x8000ffffd07c: Bad address. ) at _m3main.c:22 Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): #0 0x000000000047e53c in _umtx_op_err () #1 0x0000000000477e8a in check_suspend () #2 0x00000000004780a2 in sigcancel_handler () #3 #4 0x000000000047e53c in _umtx_op_err () #5 0x0000000000475f14 in __thr_umutex_lock () #6 0x0000000000479404 in mutex_lock_common () #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ff5fac18: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #8 0x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1337 #9 0x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ff5fac88: Bad address. ) at ../src/runtime/common/RTAllocator.m3:365 #10 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error accessing memory address 0x8000ff5fad48: Bad address. ) at ../src/runtime/common/RTAllocator.m3:296 #11 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=Error accessing memory address 0x8000ff5fada8: Bad address. ) at ../src/runtime/common/RTAllocator.m3:143 #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=Error accessing memory address 0x8000ff5fade8: Bad address. ) at ../src/Main.m3:283 #13 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000ff5faeb8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 #14 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000ff5faf68: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 #15 0x000000000047c7d4 in thread_start () #16 0x0000000000000000 in ?? () (others are similar) Hmm looks like a FreeBSD issue now. It's here... int __cdecl ThreadPThread__SuspendThread (m3_pthread_t mt) { ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), "pthread_suspend_np"); return 1; } Now this suspend can wait: static int suspend_common(struct pthread *curthread, struct pthread *thread, int waitok) { uint32_t tmp; while (thread->state != PS_DEAD && !(thread->flags & THR_FLAGS_SUSPENDED)) { thread->flags |= THR_FLAGS_NEED_SUSPEND; /* Thread is in creation. */ if (thread->tid == TID_TERMINATED) return (1); tmp = thread->cycle; _thr_send_sig(thread, SIGCANCEL); THR_THREAD_UNLOCK(curthread, thread); if (waitok) { _thr_umtx_wait_uint(&thread->cycle, tmp, NULL, 0); <========== THR_THREAD_LOCK(curthread, thread); } else { THR_THREAD_LOCK(curthread, thread); return (0); } } return (1); } ... but what it can wait for I am not clear on. Do things work better on Linux? What is the status of the fork bug? Can it be worked around by only forking via Process.Create with no mutexes held (outside of all LOCK blocks)? Mika Peter McKinna writes: >--001a11c2ced4471a2e050079db82 >Content-Type: text/plain; charset=UTF-8 > >Mika > > I think you need to back out Tony's changes to fix the fork bug, at least >for now. Need to reload from cvs version 1.262 for ThreadPThread.m3 If >you're using git you're on your own. > Do a cvs log ThreadPThread.m3 for an explanation for some of the design >principles. > Also if you use gdb then you need to set lanc c before backtraces so at >least you can see address names and values even if they are contorted you >can extract the M3 name in the parm lists. Also in gdb thread apply all bt >gives all thread backtraces which can be handy to see whose got the locks >held. > >Regards Peter > > > >On Wed, Aug 13, 2014 at 12:14 PM, wrote: > >> >> Question... is there something odd about my pthreads? Are pthreads >> normally reentrant? I didn't think so. >> >> My compiler is much happier with the following changes I already outlined: >> >> 1. a dirty, disgusting hack to keep from locking against myself going from >> XWait with self.mutex locked to m.release(). >> >> 2. the change to LockHeap I described in previous email >> >> But now... >> >> (gdb) cont >> Continuing. >> ERROR: pthread_mutex_lock:11 >> ERROR: pthread_mutex_lock:11 >> >> Program received signal SIGABRT, Aborted. >> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >> (gdb) where >> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock (mutex=Error >> accessing memory address 0x8000ffffb508: Bad address. >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >> #3 0x000000000071d48d in RTOS__LockHeap () at >> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=Error >> accessing memory address 0x8000ffffb568: Bad address. >> ) at ../src/runtime/common/RTCollector.m3:2234 >> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >> #7 0x000000000070dd8b in RTProcess__Fork () at >> ../src/runtime/common/RTProcessC.c:152 >> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >> (M3_Bd56fi_cmd=Error accessing memory address 0x8000ffffb6f8: Bad address. >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >> #9 0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=Error accessing >> memory address 0x8000ffffb7f8: Bad address. >> ) at ../src/os/POSIX/ProcessPosix.m3:21 >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=Error >> accessing memory address 0x8000ffffb838: Bad address. >> ) at ../src/QMachine.m3:1666 >> #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=Error >> accessing memory address 0x8000ffffb9f8: Bad address. >> ) at ../src/QMachine.m3:1605 >> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=Error accessing >> memory address 0x8000ffffbee8: Bad address. >> ) at ../src/QMachine.m3:1476 >> >> What am I doing wrong here? >> >> The error doesn't look unreasonable! Looking more closely at the code: >> >> First, AtForkPrepare has been called: >> >> PROCEDURE AtForkPrepare() = >> VAR me := GetActivation(); >> act: Activation; >> BEGIN >> PThreadLockMutex(slotsMu, ThisLine()); >> PThreadLockMutex(perfMu, ThisLine()); >> PThreadLockMutex(initMu, ThisLine()); (* InitMutex => >> RegisterFinalCleanup => LockHeap *) >> PThreadLockMutex(heapMu, ThisLine()); >> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => SuspendOthers >> => activeMu *) >> (* Walk activations and lock all threads. >> * NOTE: We have initMu, activeMu, so slots won't change, conditions >> and >> * mutexes won't be initialized on-demand. >> *) >> act := me; >> REPEAT >> PThreadLockMutex(act.mutex, ThisLine()); >> act := act.next; >> UNTIL act = me; >> END AtForkPrepare; >> >> a postcondition of this routine is that heapMu is locked. >> >> now we get into AtForkParent: >> >> PROCEDURE AtForkParent() = >> VAR me := GetActivation(); >> act: Activation; >> cond: Condition; >> BEGIN >> (* Walk activations and unlock all threads, conditions. *) >> act := me; >> REPEAT >> cond := slots[act.slot].join; >> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, ThisLine()) END; >> PThreadUnlockMutex(act.mutex, ThisLine()); >> act := act.next; >> UNTIL act = me; >> PThreadUnlockMutex(activeMu, ThisLine()); >> PThreadUnlockMutex(heapMu, ThisLine()); >> PThreadUnlockMutex(initMu, ThisLine()); >> PThreadUnlockMutex(perfMu, ThisLine()); >> PThreadUnlockMutex(slotsMu, ThisLine()); >> END AtForkParent; >> >> We can see by inspecting the code that a necessary precondition for >> this routine is that heapMu is locked! (Since it's going to unlock it, >> it had BETTER be locked on entry.) >> >> But the cond := ... causes a RTHooks.CheckLoadTracedRef >> >> which causes an RTOS.LockHeap >> >> the code of which we just saw: >> >> PROCEDURE LockHeap () = >> VAR self := pthread_self(); >> BEGIN >> WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> END; >> ... >> >> we try to lock heapMu. kaboom! No surprise there, really? >> >> Am I going about this totally the wrong way? Other people are running >> Modula-3 >> with pthreads, right? Right?? Somewhere out there in m3devel-land? >> >> Mika >> >> > >--001a11c2ced4471a2e050079db82 >Content-Type: text/html; charset=UTF-8 >Content-Transfer-Encoding: quoted-printable > >
Mika

=C2=A0 I think you need to back ou= >t Tony's changes to fix the fork bug, at least for now. Need to reload = >from cvs version 1.262 for ThreadPThread.m3 If you're using git you'= >;re on your own.
> >
=C2=A0 Do a cvs log ThreadPThread.m3 for an explanation for some of th= >e design principles.=C2=A0
=C2=A0 Also if you use gdb then you ne= >ed to set lanc c before backtraces so at least you can see address names an= >d values even if they are contorted you can extract the M3 name in the parm= > lists. Also in gdb thread apply all bt gives all thread backtraces which c= >an be handy to see whose got the locks held.
> >

Regards Peter

xtra">

On Wed, Aug 13, 2014 at 12:14 PM, = > <_blank">mika at async.caltech.edu> wrote:
> >
x #ccc solid;padding-left:1ex">
>Question... is there something odd about my pthreads? =C2=A0Are pthreads no= >rmally reentrant? =C2=A0I didn't think so.
>
>My compiler is much happier with the following changes I already outlined:<= >br> >
>1. a dirty, disgusting hack to keep from locking against myself going from = >XWait with self.mutex locked to m.release().
>
>2. the change to LockHeap I described in previous email
>
>But now...
>
>(gdb) cont
>Continuing.
>ERROR: pthread_mutex_lock:11
>ERROR: pthread_mutex_lock:11
>
>Program received signal SIGABRT, Aborted.
>0x000000080107626a in thr_kill () from /lib/libc.so.7
>(gdb) where
>#0 =C2=A00x000000080107626a in thr_kill () from /lib/libc.so.7
>#1 =C2=A00x000000080113dac9 in abort () from /lib/libc.so.7
>#2 =C2=A00x000000000071e37a in ThreadPThread__pthread_mutex_lock (mutex=3DE= >rror accessing memory address 0x8000ffffb508: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>#3 =C2=A00x000000000071d48d in RTOS__LockHeap () at ../src/thread/PTHREAD/T= >hreadPThread.m3:1377
>#4 =C2=A00x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref= >=3DError accessing memory address 0x8000ffffb568: Bad address.
>) at ../src/runtime/common/RTCollector.m3:2234
>#5 =C2=A00x000000000071d284 in ThreadPThread__AtForkParent () at ../src/thr= >ead/PTHREAD/ThreadPThread.m3:1348
>#6 =C2=A00x0000000800df8733 in fork () from /lib/libthr.so.3
>#7 =C2=A00x000000000070dd8b in RTProcess__Fork () at ../src/runtime/common/= >RTProcessC.c:152
>#8 =C2=A00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec (M3_Bd56= >fi_cmd=3DError accessing memory address 0x8000ffffb6f8: Bad address.
>) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>#9 =C2=A00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DError acces= >sing memory address 0x8000ffffb7f8: Bad address.
>) at ../src/os/POSIX/ProcessPosix.m3:21
>#10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=3DError= > accessing memory address 0x8000ffffb838: Bad address.
>) at ../src/QMachine.m3:1666
>#11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3DError access= >ing memory address 0x8000ffffb9f8: Bad address.
>) at ../src/QMachine.m3:1605
>#12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError accessin= >g memory address 0x8000ffffbee8: Bad address.
>) at ../src/QMachine.m3:1476
>
>What am I doing wrong here?
>
>The error doesn't look unreasonable! =C2=A0Looking more closely at the = >code:
>
>First, AtForkPrepare has been called:
>
>PROCEDURE AtForkPrepare() =3D
>=C2=A0 VAR me :=3D GetActivation();
>=C2=A0 =C2=A0 =C2=A0 act: Activation;
>=C2=A0 BEGIN
>=C2=A0 =C2=A0 PThreadLockMutex(slotsMu, ThisLine());
>=C2=A0 =C2=A0 PThreadLockMutex(perfMu, ThisLine());
>=C2=A0 =C2=A0 PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D> Re= >gisterFinalCleanup =3D> LockHeap *)
>=C2=A0 =C2=A0 PThreadLockMutex(heapMu, ThisLine());
>=C2=A0 =C2=A0 PThreadLockMutex(activeMu, ThisLine()); (* LockHeap =3D> S= >uspendOthers =3D> activeMu *)
>=C2=A0 =C2=A0 (* Walk activations and lock all threads.
>=C2=A0 =C2=A0 =C2=A0* NOTE: We have initMu, activeMu, so slots won't ch= >ange, conditions and
>=C2=A0 =C2=A0 =C2=A0* mutexes won't be initialized on-demand.
>=C2=A0 =C2=A0 =C2=A0*)
>=C2=A0 =C2=A0 act :=3D me;
>=C2=A0 =C2=A0 REPEAT
>=C2=A0 =C2=A0 =C2=A0 PThreadLockMutex(act.mutex, ThisLine());
>=C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>=C2=A0 =C2=A0 UNTIL act =3D me;
>=C2=A0 END AtForkPrepare;
>
>a postcondition of this routine is that heapMu is locked.
>
>now we get into AtForkParent:
>
>PROCEDURE AtForkParent() =3D
>=C2=A0 VAR me :=3D GetActivation();
>=C2=A0 =C2=A0 =C2=A0 act: Activation;
>=C2=A0 =C2=A0 =C2=A0 cond: Condition;
>=C2=A0 BEGIN
>=C2=A0 =C2=A0 (* Walk activations and unlock all threads, conditions. *)> >=C2=A0 =C2=A0 act :=3D me;
>=C2=A0 =C2=A0 REPEAT
>=C2=A0 =C2=A0 =C2=A0 cond :=3D slots[act.slot].join;
>=C2=A0 =C2=A0 =C2=A0 IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, This= >Line()) END;
>=C2=A0 =C2=A0 =C2=A0 PThreadUnlockMutex(act.mutex, ThisLine());
>=C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>=C2=A0 =C2=A0 UNTIL act =3D me;
>=C2=A0 =C2=A0 PThreadUnlockMutex(activeMu, ThisLine());
>=C2=A0 =C2=A0 PThreadUnlockMutex(heapMu, ThisLine());
>=C2=A0 =C2=A0 PThreadUnlockMutex(initMu, ThisLine());
>=C2=A0 =C2=A0 PThreadUnlockMutex(perfMu, ThisLine());
>=C2=A0 =C2=A0 PThreadUnlockMutex(slotsMu, ThisLine());
>=C2=A0 END AtForkParent;
>
>We can see by inspecting the code that a necessary precondition for
>this routine is that heapMu is locked! =C2=A0(Since it's going to unloc= >k it,
>it had BETTER be locked on entry.)
>
>But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef
>
>which causes an RTOS.LockHeap
>
>the code of which we just saw:
>
>PROCEDURE LockHeap () =3D
>=C2=A0 VAR self :=3D pthread_self();
>=C2=A0 BEGIN
>=C2=A0 =C2=A0 WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSE= >RT r=3D0*> END;
>...
>
>we try to lock heapMu. =C2=A0kaboom! =C2=A0No surprise there, really?
>
>Am I going about this totally the wrong way? =C2=A0Other people are running= > Modula-3
>with pthreads, right? =C2=A0Right?? =C2=A0Somewhere out there in m3devel-la= >nd?
>
>=C2=A0 =C2=A0 =C2=A0Mika
>
>

> >--001a11c2ced4471a2e050079db82-- From mika at async.caltech.edu Wed Aug 13 08:30:41 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 12 Aug 2014 23:30:41 -0700 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: References: <20140813021401.238B31A2094@async.async.caltech.edu> <20140813045415.C13921A2094@async.async.caltech.edu> Message-ID: <20140813063041.286EA1A2094@async.async.caltech.edu> OK... deleted all the derived directories and rebuilt. Result on FreeBSD is similar (or identical, hard to tell): I get a partial deadlock: PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU COMMAND 48760 root 98 0 87836K 29104K CPU1 1 12:32 83.89% threadtest{threadtest} 48760 root 94 0 87836K 29104K CPU3 3 11:02 74.66% threadtest{threadtest} 48760 root 94 0 87836K 29104K CPU0 0 11:03 71.97% threadtest{threadtest} 48760 root 32 0 87836K 29104K umtxn 2 0:01 0.00% threadtest{threadtest} 48760 root 20 0 87836K 29104K umtxn 2 0:01 0.00% threadtest{threadtest} 48760 root 35 0 87836K 29104K uwait 2 0:01 0.00% threadtest{threadtest} 48760 root 27 0 87836K 29104K uwait 0 0:01 0.00% threadtest{threadtest} 48760 root 27 0 87836K 29104K umtxn 3 0:01 0.00% threadtest{threadtest} 48760 root 27 0 87836K 29104K umtxn 2 0:01 0.00% threadtest{threadtest} 48760 root 20 0 87836K 29104K umtxn 0 0:00 0.00% threadtest{threadtest} 48759 root 20 0 30276K 11064K wait 0 0:00 0.00% gdb one of the dead threads is the main thread, so now output. But three threads are still alive, interestingly enough. Looks like the same issue as before: Thread 5 (Thread 801807400 (LWP 100751/threadtest)): #0 0x0000000800ae089c in __error () from /lib/libthr.so.3 #1 0x0000000800ad6261 in pthread_suspend_np () from /lib/libthr.so.3 #2 0x00000000004511bc in ThreadPThread__SuspendThread (mt=Error accessing memory address 0x8000ff5faa28: Bad address. ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 #3 0x000000000044ed8e in ThreadPThread__StopThread (M3_DMxDjQ_act=Error accessing memory address 0x8000ff5faa48: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 #4 0x000000000044ef31 in ThreadPThread__StopWorld () at ../src/thread/PTHREAD/ThreadPThread.m3:948 #5 0x000000000044e44e in RTThread__SuspendOthers () at ../src/thread/PTHREAD/ThreadPThread.m3:713 #6 0x0000000000436386 in RTCollector__CollectSomeInStateZero () at ../src/runtime/common/RTCollector.m3:749 #7 0x0000000000436331 in RTCollector__CollectSome () at ../src/runtime/common/RTCollector.m3:723 #8 0x0000000000435ff9 in RTHeapRep__CollectEnough () at ../src/runtime/common/RTCollector.m3:657 #9 0x0000000000433233 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ff5fac88: Bad address. ) at ../src/runtime/common/RTAllocator.m3:367 #10 0x0000000000432b55 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error accessing memory address 0x8000ff5fad48: Bad address. ) at ../src/runtime/common/RTAllocator.m3:296 #11 0x0000000000431e8f in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=Error accessing memory address 0x8000ff5fada8: Bad address. ) at ../src/runtime/common/RTAllocator.m3:143 #12 0x00000000004052ea in Main__AApply (M3_AP7a1g_cl=Error accessing memory address 0x8000ff5fade8: Bad address. ) at ../src/Main.m3:283 #13 0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000ff5faeb8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 #14 0x000000000044cf00 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000ff5faf68: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 #15 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 #16 0x0000000000000000 in ?? () Interestingly the same test seems to work on AMD64_LINUX. That is promising, at least. But of course, software testing never reveals the absence of bugs. Mika Peter McKinna writes: >--089e01183a1813188705007c3498 >Content-Type: text/plain; charset=UTF-8 > >Oh, one other thing that seemed to help me in testing this stuff especially >things to do with m3core and libm3 which seem to get out of whack >sometimes, is to totally remove the target directory of m3core then cm3; >cm3 -ship Same with libm3. I'm not sure that clean actually removes the >targets and I think there are leftover files that stuff things up since I >would get segv in FileRd for no obvious reason. > >Peter > > > >On Wed, Aug 13, 2014 at 3:33 PM, Peter McKinna >wrote: > >> That is weird. The thread tester works fine with the old version of >> ThreadPThread.m3 on linux amd_64 except if you have the fork test in the >> mix of tests you see the pthread_mutex_destroy every now and again, the >> fork bug in fact. >> I was testing the pthread changes Tony has made over the past few days >> using the thread tester program until I stupidly rebuilt the compiler and >> was getting all sorts of hangs as it dragged in the new version of >> pthreads. So I rebuilt everything from a backup to get back where I was >> with a decent compiler, then reintroduced the latest changes to >> ThreadPThread.m3, which yesterday was just hanging in sigsuspend but today >> is giving me an assert failure at line 1387 in UnlockHeap. So its a bit >> unstable to say the least. Maybe there is something else wrong with freebsd. >> >> Peter >> >> >> >> On Wed, Aug 13, 2014 at 2:54 PM, wrote: >> >>> >>> Yeah OK 1.262 makes a lot more sense to me but I'm still not getting >>> things to work and now I'm really baffled because I think I understand >>> this code! >>> >>> What I did was I threw away all my changes and reverted ThreadPThread.m3 >>> to 1.262 as you suggested. >>> >>> Rebuilt the compiler with upgrade.sh >>> >>> Then rebuilt the compiler again with itself. >>> >>> Then I realcleaned the world and buildshipped it. (I was afraid >>> that parseparams, also imported by the thread tester, would pollute >>> it somehow.) >>> >>> When I look at the code in 1.262 it looks quite straightforward. heapMu >>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. >>> Condition >>> variables are mutexes too, but that's no big deal. >>> >>> So, rebuild thread tester, run it: >>> >>> new source -> compiling Main.m3 >>> -> linking threadtest >>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # >>> AMD64_FREEBSD/threadtest >>> Writing file...done >>> Creating read threads...done >>> Creating fork threads...done >>> Creating alloc threads...done >>> Creating lock threads...done >>> running...printing oldest/median age/newest >>> . >>> >>> *** >>> *** runtime error: >>> *** Segmentation violation - possible attempt to dereference >>> NIL.........laziest thread is 1407901189/1407901189/9 (tests: read >>> 1407901189/1407901189/1407901189 fork 1407901189/1407901189/1407901189 >>> alloc 9/9/9 lock 1407901189/1407901189/9) >>> >>> >>> >>> >>> ^C >>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb !$ >>> gdb AMD64_FREEBSD/threadtest >>> GNU gdb 6.1.1 [FreeBSD] >>> Copyright 2004 Free Software Foundation, Inc. >>> GDB is free software, covered by the GNU General Public License, and you >>> are >>> welcome to change it and/or distribute copies of it under certain >>> conditions. >>> Type "show copying" to see the conditions. >>> There is absolutely no warranty for GDB. Type "show warranty" for >>> details. >>> This GDB was configured as "amd64-marcel-freebsd"... >>> (gdb) run >>> Starting program: >>> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/threadtest >>> [New LWP 100121] >>> Writing file...done >>> Creating read threads...done >>> Creating fork threads...done >>> Creating alloc threads...done >>> Creating lock threads...done >>> running...printing oldest/median age/newest >>> .[New Thread 801807000 (LWP 100343/threadtest)] >>> [New Thread 801807c00 (LWP 100667/threadtest)] >>> [New Thread 801808800 (LWP 100816/threadtest)] >>> [New Thread 801807400 (LWP 100349/threadtest)] >>> [New Thread 801808400 (LWP 100815/threadtest)] >>> [New Thread 801807800 (LWP 100352/threadtest)] >>> [New Thread 801808c00 (LWP 100817/threadtest)] >>> [New Thread 801809000 (LWP 100818/threadtest)] >>> [New Thread 801809800 (LWP 100820/threadtest)] >>> [New Thread 801808000 (LWP 100678/threadtest)] >>> [New Thread 801806400 (LWP 100121/threadtest)] >>> [New Thread 801806800 (LWP 100341/threadtest)] >>> [New Thread 801806c00 (LWP 100342/threadtest)] >>> .ERROR: pthread_mutex_lock:11 >>> >>> Program received signal SIGABRT, Aborted. >>> [Switching to Thread 801809800 (LWP 100820/threadtest)] >>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>> (gdb) where >>> #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>> #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 >>> #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock (mutex=Error >>> accessing memory address 0x8000fe5f2d98: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 >>> #3 0x000000000044b370 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error >>> accessing memory address 0x8000fe5f2dc8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>> #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=Error accessing >>> memory address 0x8000fe5f2df8: Bad address. >>> ) at ../src/Main.m3:319 >>> #5 0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>> accessing memory address 0x8000fe5f2eb8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>> #6 0x000000000044cf00 in ThreadPThread__ThreadBase >>> (M3_AJWxb1_param=Error accessing memory address 0x8000fe5f2f68: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>> #7 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>> #8 0x0000000000000000 in ?? () >>> (gdb) set lang c >>> (gdb) thread apply all bt >>> ... not that interesting ... >>> >>> Segfault is segfault---error 11 is EDEADLK (locking against myself?) >>> >>> ????? the code is very straightforward, as I said. >>> >>> I thought people had the thread tester working with pthreads? Which set >>> of files, then? Anyone on FreeBSD/amd64? >>> >>> Could it be an issue with "volatile"? Not even sure where to look. >>> >>> The code calling the lock is just this: >>> >>> PROCEDURE GetChar (rd: T): CHAR >>> RAISES {EndOfFile, Failure, Alerted} = >>> BEGIN >>> LOCK rd DO >>> RETURN FastGetChar(rd); >>> END >>> END GetChar; >>> >>> No mysteries there... >>> >>> Ah is this the fork bug? Looks like the Init routine is called on a >>> lot of NIL mutexes around the fork. But the subprocesses aren't meant >>> to accesses the mutexes... humm >>> >>> Hmm, and it's not entirely a fork issue. Even with "threadtest -tests >>> STD,-fork,-forktoomuch" it misbehaves. Hangs.... >>> >>> Looks like a deadlock this time. >>> >>> Some stacks... >>> >>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): >>> #0 0x00000000004b4e2b in __vdso_gettimeofday () >>> #1 0x00000000004ab8d2 in gettimeofday () >>> #2 0x0000000000452e4b in TimePosix__Now () at >>> ../src/time/POSIX/TimePosixC.c:50 >>> #3 0x0000000000452d72 in Time__Now () at >>> ../src/time/POSIX/TimePosix.m3:14 >>> #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=Error accessing >>> memory address 0x8000fedf6df8: Bad address. >>> ) at ../src/Main.m3:327 >>> #5 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>> accessing memory address 0x8000fedf6eb8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>> #6 0x0000000000449c50 in ThreadPThread__ThreadBase >>> (M3_AJWxb1_param=Error accessing memory address 0x8000fedf6f68: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>> #7 0x000000000047c7d4 in thread_start () >>> #8 0x0000000000000000 in ?? () >>> >>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): >>> #0 0x000000000047e53c in _umtx_op_err () >>> #1 0x0000000000475f14 in __thr_umutex_lock () >>> #2 0x0000000000479404 in mutex_lock_common () >>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error >>> accessing memory address 0x8000feff7d98: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>> #4 0x00000000004480c0 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error >>> accessing memory address 0x8000feff7dc8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>> #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=Error accessing >>> memory address 0x8000feff7df8: Bad address. >>> ) at ../src/Main.m3:319 >>> #6 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>> accessing memory address 0x8000feff7eb8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>> #7 0x0000000000449c50 in ThreadPThread__ThreadBase >>> (M3_AJWxb1_param=Error accessing memory address 0x8000feff7f68: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>> #8 0x000000000047c7d4 in thread_start () >>> #9 0x0000000000000000 in ?? () >>> >>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): >>> #0 0x000000000047e53c in _umtx_op_err () >>> #1 0x0000000000475759 in suspend_common () >>> #2 0x00000000004755c1 in pthread_suspend_np () >>> #3 0x000000000044df0c in ThreadPThread__SuspendThread (mt=Error >>> accessing memory address 0x8000ffbfd6f8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>> #4 0x000000000044bade in ThreadPThread__StopThread (M3_DMxDjQ_act=Error >>> accessing memory address 0x8000ffbfd718: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>> #5 0x000000000044bc81 in ThreadPThread__StopWorld () at >>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>> #6 0x000000000044b19e in RTThread__SuspendOthers () at >>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>> #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero () at >>> ../src/runtime/common/RTCollector.m3:749 >>> #8 0x0000000000433081 in RTCollector__CollectSome () at >>> ../src/runtime/common/RTCollector.m3:723 >>> #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at >>> ../src/runtime/common/RTCollector.m3:657 >>> #10 0x000000000042ff83 in RTAllocator__AllocTraced >>> (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffbfd958: Bad >>> address. >>> ) at ../src/runtime/common/RTAllocator.m3:367 >>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error >>> accessing memory address 0x8000ffbfda18: Bad address. >>> ) at ../src/runtime/common/RTAllocator.m3:296 >>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray >>> (M3_AJWxb1_defn=Error accessing memory address 0x8000ffbfda78: Bad address. >>> ) at ../src/runtime/common/RTAllocator.m3:143 >>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=Error accessing >>> memory address 0x8000ffbfdab8: Bad address. >>> ) at ../src/rw/Rd.m3:159 >>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=Error >>> accessing memory address 0x8000ffbfdb88: Bad address. >>> ) at ../src/rw/Rd.m3:187 >>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=Error accessing >>> memory address 0x8000ffbfdbd8: Bad address. >>> ) at ../src/rw/Rd.m3:176 >>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=Error accessing >>> memory address 0x8000ffbfdc58: Bad address. >>> ) at ../src/Main.m3:185 >>> >>> #17 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>> accessing memory address 0x8000ffbfdeb8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase >>> (M3_AJWxb1_param=Error accessing memory address 0x8000ffbfdf68: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>> #19 0x000000000047c7d4 in thread_start () >>> #20 0x0000000000000000 in ?? () >>> >>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): >>> #0 0x000000000047e53c in _umtx_op_err () >>> #1 0x0000000000475f14 in __thr_umutex_lock () >>> #2 0x0000000000479404 in mutex_lock_common () >>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error >>> accessing memory address 0x8000ffffc678: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>> #4 0x000000000044d039 in RTOS__LockHeap () at >>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>> ---Type to continue, or q to quit--- >>> #5 0x000000000042ff79 in RTAllocator__AllocTraced >>> (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffffc6e8: Bad >>> address. >>> ) at ../src/runtime/common/RTAllocator.m3:365 >>> #6 0x000000000042f15b in RTAllocator__GetTracedObj (M3_Eic7CK_def=Error >>> accessing memory address 0x8000ffffc7a8: Bad address. >>> ) at ../src/runtime/common/RTAllocator.m3:224 >>> #7 0x000000000042eb23 in RTHooks__AllocateTracedObj >>> (M3_AJWxb1_defn=Error accessing memory address 0x8000ffffc7f8: Bad address. >>> ) at ../src/runtime/common/RTAllocator.m3:122 >>> #8 0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=Error accessing >>> memory address 0x8000ffffc858: Bad address. >>> ) at ../src/text/TextCat.m3:562 >>> #9 0x000000000045ed5d in TextCat__Balance (M3_Bd56fi_LText=0x800c490b0, >>> M3_BUgnwf_LInfo=Error accessing memory address 0x8000ffffc8f8: Bad address. >>> ) at ../src/text/TextCat.m3:488 >>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=Error accessing >>> memory address 0x8000ffffcbb8: Bad address. >>> ) at ../src/text/TextCat.m3:40 >>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=Error accessing memory >>> address 0x8000ffffcc38: Bad address. >>> ) at ../src/Main.m3:593 >>> #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=Error >>> accessing memory address 0x8000ffffcf88: Bad address. >>> ) at ../src/runtime/common/RTLinker.m3:408 >>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=Error accessing >>> memory address 0x8000ffffd008: Bad address. >>> ) at ../src/runtime/common/RTLinker.m3:115 >>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=Error accessing >>> memory address 0x8000ffffd028: Bad address. >>> ) at ../src/runtime/common/RTLinker.m3:124 >>> #15 0x00000000004004a6 in main (argc=Error accessing memory address >>> 0x8000ffffd07c: Bad address. >>> ) at _m3main.c:22 >>> >>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): >>> #0 0x000000000047e53c in _umtx_op_err () >>> #1 0x0000000000477e8a in check_suspend () >>> #2 0x00000000004780a2 in sigcancel_handler () >>> #3 >>> #4 0x000000000047e53c in _umtx_op_err () >>> #5 0x0000000000475f14 in __thr_umutex_lock () >>> #6 0x0000000000479404 in mutex_lock_common () >>> #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error >>> accessing memory address 0x8000ff5fac18: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>> #8 0x000000000044d039 in RTOS__LockHeap () at >>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>> #9 0x000000000042ff79 in RTAllocator__AllocTraced >>> (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ff5fac88: Bad >>> address. >>> ) at ../src/runtime/common/RTAllocator.m3:365 >>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error >>> accessing memory address 0x8000ff5fad48: Bad address. >>> ) at ../src/runtime/common/RTAllocator.m3:296 >>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray >>> (M3_AJWxb1_defn=Error accessing memory address 0x8000ff5fada8: Bad address. >>> ) at ../src/runtime/common/RTAllocator.m3:143 >>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=Error accessing >>> memory address 0x8000ff5fade8: Bad address. >>> ) at ../src/Main.m3:283 >>> #13 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>> accessing memory address 0x8000ff5faeb8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase >>> (M3_AJWxb1_param=Error accessing memory address 0x8000ff5faf68: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>> #15 0x000000000047c7d4 in thread_start () >>> #16 0x0000000000000000 in ?? () >>> >>> (others are similar) >>> >>> Hmm looks like a FreeBSD issue now. It's here... >>> >>> int >>> __cdecl >>> ThreadPThread__SuspendThread (m3_pthread_t mt) >>> { >>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), >>> "pthread_suspend_np"); >>> return 1; >>> } >>> >>> Now this suspend can wait: >>> >>> static int >>> suspend_common(struct pthread *curthread, struct pthread *thread, >>> int waitok) >>> { >>> uint32_t tmp; >>> >>> while (thread->state != PS_DEAD && >>> !(thread->flags & THR_FLAGS_SUSPENDED)) { >>> thread->flags |= THR_FLAGS_NEED_SUSPEND; >>> /* Thread is in creation. */ >>> if (thread->tid == TID_TERMINATED) >>> return (1); >>> tmp = thread->cycle; >>> _thr_send_sig(thread, SIGCANCEL); >>> THR_THREAD_UNLOCK(curthread, thread); >>> if (waitok) { >>> _thr_umtx_wait_uint(&thread->cycle, tmp, NULL, >>> 0); <========== >>> THR_THREAD_LOCK(curthread, thread); >>> } else { >>> THR_THREAD_LOCK(curthread, thread); >>> return (0); >>> } >>> } >>> >>> return (1); >>> } >>> >>> ... but what it can wait for I am not clear on. >>> >>> Do things work better on Linux? >>> >>> What is the status of the fork bug? Can it be worked around by only >>> forking via Process.Create with no mutexes held (outside of all LOCK >>> blocks)? >>> >>> Mika >>> >>> >>> >>> Peter McKinna writes: >>> >--001a11c2ced4471a2e050079db82 >>> >Content-Type: text/plain; charset=UTF-8 >>> > >>> >Mika >>> > >>> > I think you need to back out Tony's changes to fix the fork bug, at >>> least >>> >for now. Need to reload from cvs version 1.262 for ThreadPThread.m3 If >>> >you're using git you're on your own. >>> > Do a cvs log ThreadPThread.m3 for an explanation for some of the design >>> >principles. >>> > Also if you use gdb then you need to set lanc c before backtraces so at >>> >least you can see address names and values even if they are contorted you >>> >can extract the M3 name in the parm lists. Also in gdb thread apply all >>> bt >>> >gives all thread backtraces which can be handy to see whose got the locks >>> >held. >>> > >>> >Regards Peter >>> > >>> > >>> > >>> >On Wed, Aug 13, 2014 at 12:14 PM, wrote: >>> > >>> >> >>> >> Question... is there something odd about my pthreads? Are pthreads >>> >> normally reentrant? I didn't think so. >>> >> >>> >> My compiler is much happier with the following changes I already >>> outlined: >>> >> >>> >> 1. a dirty, disgusting hack to keep from locking against myself going >>> from >>> >> XWait with self.mutex locked to m.release(). >>> >> >>> >> 2. the change to LockHeap I described in previous email >>> >> >>> >> But now... >>> >> >>> >> (gdb) cont >>> >> Continuing. >>> >> ERROR: pthread_mutex_lock:11 >>> >> ERROR: pthread_mutex_lock:11 >>> >> >>> >> Program received signal SIGABRT, Aborted. >>> >> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>> >> (gdb) where >>> >> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>> >> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >>> >> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock >>> (mutex=Error >>> >> accessing memory address 0x8000ffffb508: Bad address. >>> >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >>> >> #3 0x000000000071d48d in RTOS__LockHeap () at >>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >>> >> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef >>> (M3_Af40ku_ref=Error >>> >> accessing memory address 0x8000ffffb568: Bad address. >>> >> ) at ../src/runtime/common/RTCollector.m3:2234 >>> >> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >>> >> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >>> >> #7 0x000000000070dd8b in RTProcess__Fork () at >>> >> ../src/runtime/common/RTProcessC.c:152 >>> >> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>> >> (M3_Bd56fi_cmd=Error accessing memory address 0x8000ffffb6f8: Bad >>> address. >>> >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >>> >> #9 0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=Error >>> accessing >>> >> memory address 0x8000ffffb7f8: Bad address. >>> >> ) at ../src/os/POSIX/ProcessPosix.m3:21 >>> >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>> (M3_D6rRrg_ep=Error >>> >> accessing memory address 0x8000ffffb838: Bad address. >>> >> ) at ../src/QMachine.m3:1666 >>> >> #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=Error >>> >> accessing memory address 0x8000ffffb9f8: Bad address. >>> >> ) at ../src/QMachine.m3:1605 >>> >> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=Error >>> accessing >>> >> memory address 0x8000ffffbee8: Bad address. >>> >> ) at ../src/QMachine.m3:1476 >>> >> >>> >> What am I doing wrong here? >>> >> >>> >> The error doesn't look unreasonable! Looking more closely at the code: >>> >> >>> >> First, AtForkPrepare has been called: >>> >> >>> >> PROCEDURE AtForkPrepare() = >>> >> VAR me := GetActivation(); >>> >> act: Activation; >>> >> BEGIN >>> >> PThreadLockMutex(slotsMu, ThisLine()); >>> >> PThreadLockMutex(perfMu, ThisLine()); >>> >> PThreadLockMutex(initMu, ThisLine()); (* InitMutex => >>> >> RegisterFinalCleanup => LockHeap *) >>> >> PThreadLockMutex(heapMu, ThisLine()); >>> >> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => >>> SuspendOthers >>> >> => activeMu *) >>> >> (* Walk activations and lock all threads. >>> >> * NOTE: We have initMu, activeMu, so slots won't change, >>> conditions >>> >> and >>> >> * mutexes won't be initialized on-demand. >>> >> *) >>> >> act := me; >>> >> REPEAT >>> >> PThreadLockMutex(act.mutex, ThisLine()); >>> >> act := act.next; >>> >> UNTIL act = me; >>> >> END AtForkPrepare; >>> >> >>> >> a postcondition of this routine is that heapMu is locked. >>> >> >>> >> now we get into AtForkParent: >>> >> >>> >> PROCEDURE AtForkParent() = >>> >> VAR me := GetActivation(); >>> >> act: Activation; >>> >> cond: Condition; >>> >> BEGIN >>> >> (* Walk activations and unlock all threads, conditions. *) >>> >> act := me; >>> >> REPEAT >>> >> cond := slots[act.slot].join; >>> >> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, ThisLine()) >>> END; >>> >> PThreadUnlockMutex(act.mutex, ThisLine()); >>> >> act := act.next; >>> >> UNTIL act = me; >>> >> PThreadUnlockMutex(activeMu, ThisLine()); >>> >> PThreadUnlockMutex(heapMu, ThisLine()); >>> >> PThreadUnlockMutex(initMu, ThisLine()); >>> >> PThreadUnlockMutex(perfMu, ThisLine()); >>> >> PThreadUnlockMutex(slotsMu, ThisLine()); >>> >> END AtForkParent; >>> >> >>> >> We can see by inspecting the code that a necessary precondition for >>> >> this routine is that heapMu is locked! (Since it's going to unlock it, >>> >> it had BETTER be locked on entry.) >>> >> >>> >> But the cond := ... causes a RTHooks.CheckLoadTracedRef >>> >> >>> >> which causes an RTOS.LockHeap >>> >> >>> >> the code of which we just saw: >>> >> >>> >> PROCEDURE LockHeap () = >>> >> VAR self := pthread_self(); >>> >> BEGIN >>> >> WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> >>> END; >>> >> ... >>> >> >>> >> we try to lock heapMu. kaboom! No surprise there, really? >>> >> >>> >> Am I going about this totally the wrong way? Other people are running >>> >> Modula-3 >>> >> with pthreads, right? Right?? Somewhere out there in m3devel-land? >>> >> >>> >> Mika >>> >> >>> >> >>> > >>> >--001a11c2ced4471a2e050079db82 >>> >Content-Type: text/html; charset=UTF-8 >>> >Content-Transfer-Encoding: quoted-printable >>> > >>> >
Mika

=C2=A0 I think you need to back >>> ou= >>> >t Tony's changes to fix the fork bug, at least for now. Need to >>> reload = >>> >from cvs version 1.262 for ThreadPThread.m3 If you're using git >>> you'= >>> >;re on your own.
>>> > >>> >
=C2=A0 Do a cvs log ThreadPThread.m3 for an explanation for some of >>> th= >>> >e design principles.=C2=A0
=C2=A0 Also if you use gdb then you >>> ne= >>> >ed to set lanc c before backtraces so at least you can see address names >>> an= >>> >d values even if they are contorted you can extract the M3 name in the >>> parm= >>> > lists. Also in gdb thread apply all bt gives all thread backtraces >>> which c= >>> >an be handy to see whose got the locks held.
>>> > >>> >

Regards Peter

>> class=3D"gmail_e= >>> >xtra">

On Wed, Aug 13, 2014 at 12:14 >>> PM, = >>> > <>> target=3D"= >>> >_blank">mika at async.caltech.edu> wrote:
>>> > >>> >
>> .8ex;border-left:1p= >>> >x #ccc solid;padding-left:1ex">
>>> >Question... is there something odd about my pthreads? =C2=A0Are pthreads >>> no= >>> >rmally reentrant? =C2=A0I didn't think so.
>>> >
>>> >My compiler is much happier with the following changes I already >>> outlined:<= >>> >br> >>> >
>>> >1. a dirty, disgusting hack to keep from locking against myself going >>> from = >>> >XWait with self.mutex locked to m.release().
>>> >
>>> >2. the change to LockHeap I described in previous email
>>> >
>>> >But now...
>>> >
>>> >(gdb) cont
>>> >Continuing.
>>> >ERROR: pthread_mutex_lock:11
>>> >ERROR: pthread_mutex_lock:11
>>> >
>>> >Program received signal SIGABRT, Aborted.
>>> >0x000000080107626a in thr_kill () from /lib/libc.so.7
>>> >(gdb) where
>>> >#0 =C2=A00x000000080107626a in thr_kill () from /lib/libc.so.7
>>> >#1 =C2=A00x000000080113dac9 in abort () from /lib/libc.so.7
>>> >#2 =C2=A00x000000000071e37a in ThreadPThread__pthread_mutex_lock >>> (mutex=3DE= >>> >rror accessing memory address 0x8000ffffb508: Bad address.
>>> >) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>> >#3 =C2=A00x000000000071d48d in RTOS__LockHeap () at >>> ../src/thread/PTHREAD/T= >>> >hreadPThread.m3:1377
>>> >#4 =C2=A00x0000000000706b9d in RTHooks__CheckLoadTracedRef >>> (M3_Af40ku_ref= >>> >=3DError accessing memory address 0x8000ffffb568: Bad address.
>>> >) at ../src/runtime/common/RTCollector.m3:2234
>>> >#5 =C2=A00x000000000071d284 in ThreadPThread__AtForkParent () at >>> ../src/thr= >>> >ead/PTHREAD/ThreadPThread.m3:1348
>>> >#6 =C2=A00x0000000800df8733 in fork () from /lib/libthr.so.3
>>> >#7 =C2=A00x000000000070dd8b in RTProcess__Fork () at >>> ../src/runtime/common/= >>> >RTProcessC.c:152
>>> >#8 =C2=A00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>> (M3_Bd56= >>> >fi_cmd=3DError accessing memory address 0x8000ffffb6f8: Bad address.
>>> >) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>> >#9 =C2=A00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DError >>> acces= >>> >sing memory address 0x8000ffffb7f8: Bad address.
>>> >) at ../src/os/POSIX/ProcessPosix.m3:21
>>> >#10 0x00000000004d6826 in QMachine__FulfilExecPromise >>> (M3_D6rRrg_ep=3DError= >>> > accessing memory address 0x8000ffffb838: Bad address.
>>> >) at ../src/QMachine.m3:1666
>>> >#11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3DError >>> access= >>> >ing memory address 0x8000ffffb9f8: Bad address.
>>> >) at ../src/QMachine.m3:1605
>>> >#12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError >>> accessin= >>> >g memory address 0x8000ffffbee8: Bad address.
>>> >) at ../src/QMachine.m3:1476
>>> >
>>> >What am I doing wrong here?
>>> >
>>> >The error doesn't look unreasonable! =C2=A0Looking more closely at >>> the = >>> >code:
>>> >
>>> >First, AtForkPrepare has been called:
>>> >
>>> >PROCEDURE AtForkPrepare() =3D
>>> >=C2=A0 VAR me :=3D GetActivation();
>>> >=C2=A0 =C2=A0 =C2=A0 act: Activation;
>>> >=C2=A0 BEGIN
>>> >=C2=A0 =C2=A0 PThreadLockMutex(slotsMu, ThisLine());
>>> >=C2=A0 =C2=A0 PThreadLockMutex(perfMu, ThisLine());
>>> >=C2=A0 =C2=A0 PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D> >>> Re= >>> >gisterFinalCleanup =3D> LockHeap *)
>>> >=C2=A0 =C2=A0 PThreadLockMutex(heapMu, ThisLine());
>>> >=C2=A0 =C2=A0 PThreadLockMutex(activeMu, ThisLine()); (* LockHeap >>> =3D> S= >>> >uspendOthers =3D> activeMu *)
>>> >=C2=A0 =C2=A0 (* Walk activations and lock all threads.
>>> >=C2=A0 =C2=A0 =C2=A0* NOTE: We have initMu, activeMu, so slots won't >>> ch= >>> >ange, conditions and
>>> >=C2=A0 =C2=A0 =C2=A0* mutexes won't be initialized on-demand.
>>> >=C2=A0 =C2=A0 =C2=A0*)
>>> >=C2=A0 =C2=A0 act :=3D me;
>>> >=C2=A0 =C2=A0 REPEAT
>>> >=C2=A0 =C2=A0 =C2=A0 PThreadLockMutex(act.mutex, ThisLine());
>>> >=C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>>> >=C2=A0 =C2=A0 UNTIL act =3D me;
>>> >=C2=A0 END AtForkPrepare;
>>> >
>>> >a postcondition of this routine is that heapMu is locked.
>>> >
>>> >now we get into AtForkParent:
>>> >
>>> >PROCEDURE AtForkParent() =3D
>>> >=C2=A0 VAR me :=3D GetActivation();
>>> >=C2=A0 =C2=A0 =C2=A0 act: Activation;
>>> >=C2=A0 =C2=A0 =C2=A0 cond: Condition;
>>> >=C2=A0 BEGIN
>>> >=C2=A0 =C2=A0 (* Walk activations and unlock all threads, conditions. >>> *)>> >> >>> >=C2=A0 =C2=A0 act :=3D me;
>>> >=C2=A0 =C2=A0 REPEAT
>>> >=C2=A0 =C2=A0 =C2=A0 cond :=3D slots[act.slot].join;
>>> >=C2=A0 =C2=A0 =C2=A0 IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, >>> This= >>> >Line()) END;
>>> >=C2=A0 =C2=A0 =C2=A0 PThreadUnlockMutex(act.mutex, ThisLine());
>>> >=C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>>> >=C2=A0 =C2=A0 UNTIL act =3D me;
>>> >=C2=A0 =C2=A0 PThreadUnlockMutex(activeMu, ThisLine());
>>> >=C2=A0 =C2=A0 PThreadUnlockMutex(heapMu, ThisLine());
>>> >=C2=A0 =C2=A0 PThreadUnlockMutex(initMu, ThisLine());
>>> >=C2=A0 =C2=A0 PThreadUnlockMutex(perfMu, ThisLine());
>>> >=C2=A0 =C2=A0 PThreadUnlockMutex(slotsMu, ThisLine());
>>> >=C2=A0 END AtForkParent;
>>> >
>>> >We can see by inspecting the code that a necessary precondition for
>>> >this routine is that heapMu is locked! =C2=A0(Since it's going to >>> unloc= >>> >k it,
>>> >it had BETTER be locked on entry.)
>>> >
>>> >But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef
>>> >
>>> >which causes an RTOS.LockHeap
>>> >
>>> >the code of which we just saw:
>>> >
>>> >PROCEDURE LockHeap () =3D
>>> >=C2=A0 VAR self :=3D pthread_self();
>>> >=C2=A0 BEGIN
>>> >=C2=A0 =C2=A0 WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO >>> <*ASSE= >>> >RT r=3D0*> END;
>>> >...
>>> >
>>> >we try to lock heapMu. =C2=A0kaboom! =C2=A0No surprise there, really?
>>> >
>>> >Am I going about this totally the wrong way? =C2=A0Other people are >>> running= >>> > Modula-3
>>> >with pthreads, right? =C2=A0Right?? =C2=A0Somewhere out there in >>> m3devel-la= >>> >nd?
>>> >
>>> >=C2=A0 =C2=A0 =C2=A0Mika
>>> >
>>> >

>>> > >>> >--001a11c2ced4471a2e050079db82-- >>> >> >> > >--089e01183a1813188705007c3498 >Content-Type: text/html; charset=UTF-8 >Content-Transfer-Encoding: quoted-printable > >
Oh, one other thing that seemed to help me in testing this= > stuff especially things to do with m3core and libm3 which seem to get out = >of whack sometimes, is to totally remove the target directory of m3core the= >n cm3; cm3 -ship Same with libm3. I'm not sure that clean actually remo= >ves the targets and I think there are leftover files that stuff things up s= >ince I would get segv in FileRd for no obvious reason.
>
Peter

<= >br>
On Wed, Aug 13, 2014 at 3:33 PM, Peter Mc= >Kinna <et=3D"_blank">peter.mckinna at gmail.com> wrote:
>
x #ccc solid;padding-left:1ex">
That is weird. The thread t= >ester works fine with the old version of ThreadPThread.m3 on linux amd_64 e= >xcept if you have the fork test in the mix of tests you see the pthread_mut= >ex_destroy every now and again, the fork bug in fact.=C2=A0
> >I was testing the pthread changes Tony has made over the past few days usin= >g the thread tester program until I stupidly rebuilt the compiler and was g= >etting all sorts of hangs as it dragged in the new version of pthreads. So = >I rebuilt everything from a backup to get back where I was with a decent co= >mpiler, then reintroduced the latest changes to ThreadPThread.m3, which yes= >terday was just hanging in sigsuspend but today is giving me an assert fail= >ure at line 1387 in UnlockHeap. So its a bit unstable to say the least. May= >be there is something else wrong with freebsd.
> >

Peter

s=3D"HOEnZb">


s=3D"gmail_quote">On Wed, Aug 13, 2014 at 2:54 PM, <<= >a href=3D"mailto:mika at async.caltech.edu" target=3D"_blank">mika at async.calte= >ch.edu> wrote:
> >
x #ccc solid;padding-left:1ex">
>Yeah OK 1.262 makes a lot more sense to me but I'm still not getting> >things to work and now I'm really baffled because I think I understand<= >br> >this code!
>
>What I did was I threw away all my changes and reverted ThreadPThread.m3> >to 1.262 as you suggested.
>
>Rebuilt the compiler with upgrade.sh
>
>Then rebuilt the compiler again with itself.
>
>Then I realcleaned the world and buildshipped it. =C2=A0(I was afraid
>that parseparams, also imported by the thread tester, would pollute
>it somehow.)
>
>When I look at the code in 1.262 it looks quite straightforward. =C2=A0heap= >Mu
>is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. =C2=A0Cond= >ition
>variables are mutexes too, but that's no big deal.
>
>So, rebuild thread tester, run it:
>
>new source -> compiling Main.m3
>=C2=A0-> linking threadtest
>root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # AMD64_FREEB= >SD/threadtest
>Writing file...done
>Creating read threads...done
>Creating fork threads...done
>Creating alloc threads...done
>Creating lock threads...done
>running...printing oldest/median age/newest
>.
>
>***
>*** runtime error:
>*** =C2=A0 =C2=A0Segmentation violation - possible attempt to dereference N= >IL.........laziest thread is 1407901189/e=3D"+14079011899" target=3D"_blank">1407901189/9 (tests: read 14079011= >89/1407901189/1407901189 fork 1407901189/1407901189/1407901189 alloc 9/9/9 = >lock 1407901189/1407901189/9)
> > >
>
>
>
>^C
>root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb !$
>gdb AMD64_FREEBSD/threadtest
>GNU gdb 6.1.1 [FreeBSD]
>Copyright 2004 Free Software Foundation, Inc.
>GDB is free software, covered by the GNU General Public License, and you ar= >e
>welcome to change it and/or distribute copies of it under certain condition= >s.
>Type "show copying" to see the conditions.
>There is absolutely no warranty for GDB. =C2=A0Type "show warranty&quo= >t; for details.
>This GDB was configured as "amd64-marcel-freebsd"...
>(gdb) run
>Starting program: /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread= >/AMD64_FREEBSD/threadtest
>[New LWP 100121]
>Writing file...done
>Creating read threads...done
>Creating fork threads...done
>Creating alloc threads...done
>Creating lock threads...done
>running...printing oldest/median age/newest
>.[New Thread 801807000 (LWP 100343/threadtest)]
>[New Thread 801807c00 (LWP 100667/threadtest)]
>[New Thread 801808800 (LWP 100816/threadtest)]
>[New Thread 801807400 (LWP 100349/threadtest)]
>[New Thread 801808400 (LWP 100815/threadtest)]
>[New Thread 801807800 (LWP 100352/threadtest)]
>[New Thread 801808c00 (LWP 100817/threadtest)]
>[New Thread 801809000 (LWP 100818/threadtest)]
>[New Thread 801809800 (LWP 100820/threadtest)]
>[New Thread 801808000 (LWP 100678/threadtest)]
>[New Thread 801806400 (LWP 100121/threadtest)]
>[New Thread 801806800 (LWP 100341/threadtest)]
>[New Thread 801806c00 (LWP 100342/threadtest)]
>.ERROR: pthread_mutex_lock:11
>

>Program received signal SIGABRT, Aborted.
>
[Switching to Thread 801809800 (LWP 100820/threadtest)]
>0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>(gdb) where
>#0 =C2=A00x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>#1 =C2=A00x0000000800e23ac9 in abort () from /lib/libc.so.7
>#2 =C2=A00x000000000045101f in ThreadPThread__pthread_mutex_lock (mutex=3DE= >rror accessing memory address 0x8000fe5f2d98: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
>#3 =C2=A00x000000000044b370 in ThreadPThread__LockMutex (M3_AYIbX3_m=3DErro= >r accessing memory address 0x8000fe5f2dc8: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>#4 =C2=A00x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3DError accessing= > memory address 0x8000fe5f2df8: Bad address.
>) at ../src/Main.m3:319
>#5 =C2=A00x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DErr= >or accessing memory address 0x8000fe5f2eb8: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>#6 =C2=A00x000000000044cf00 in ThreadPThread__ThreadBase (M3_AJWxb1_param= >=3DError accessing memory address 0x8000fe5f2f68: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>#7 =C2=A00x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3
>#8 =C2=A00x0000000000000000 in ?? ()
>(gdb) set lang c
>(gdb) thread apply all bt
>... not that interesting ...
>
>Segfault is segfault---error 11 is EDEADLK (locking against myself?)
>
>????? the code is very straightforward, as I said.
>
>I thought people had the thread tester working with pthreads? =C2=A0Which s= >et of files, then? =C2=A0Anyone on FreeBSD/amd64?
>
>Could it be an issue with "volatile"? =C2=A0Not even sure where t= >o look.
>
>The code calling the lock is just this:
>
>PROCEDURE GetChar (rd: T): CHAR
>=C2=A0 RAISES {EndOfFile, Failure, Alerted} =3D
>=C2=A0 BEGIN
>=C2=A0 =C2=A0 LOCK rd DO
>=C2=A0 =C2=A0 =C2=A0 RETURN FastGetChar(rd);
>=C2=A0 =C2=A0 END
>=C2=A0 END GetChar;
>
>No mysteries there...
>
>Ah is this the fork bug? =C2=A0Looks like the Init routine is called on ar> >lot of NIL mutexes around the fork. =C2=A0But the subprocesses aren't m= >eant
>to accesses the mutexes... humm
>
>Hmm, and it's not entirely a fork issue. =C2=A0Even with "threadte= >st -tests STD,-fork,-forktoomuch" it misbehaves. =C2=A0Hangs....
>
>Looks like a deadlock this time.
>
>Some stacks...
>
>Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
>#0 =C2=A00x00000000004b4e2b in __vdso_gettimeofday ()
>#1 =C2=A00x00000000004ab8d2 in gettimeofday ()
>#2 =C2=A00x0000000000452e4b in TimePosix__Now () at ../src/time/POSIX/TimeP= >osixC.c:50
>#3 =C2=A00x0000000000452d72 in Time__Now () at ../src/time/POSIX/TimePosix.= >m3:14
>#4 =C2=A00x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3DError accessing= > memory address 0x8000fedf6df8: Bad address.
>) at ../src/Main.m3:327
>#5 =C2=A00x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DErr= >or accessing memory address 0x8000fedf6eb8: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>#6 =C2=A00x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param= >=3DError accessing memory address 0x8000fedf6f68: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>#7 =C2=A00x000000000047c7d4 in thread_start ()
>#8 =C2=A00x0000000000000000 in ?? ()
>
>Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
>#0 =C2=A00x000000000047e53c in _umtx_op_err ()
>#1 =C2=A00x0000000000475f14 in __thr_umutex_lock ()
>#2 =C2=A00x0000000000479404 in mutex_lock_common ()
>#3 =C2=A00x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=3DE= >rror accessing memory address 0x8000feff7d98: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>#4 =C2=A00x00000000004480c0 in ThreadPThread__LockMutex (M3_AYIbX3_m=3DErro= >r accessing memory address 0x8000feff7dc8: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>#5 =C2=A00x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3DError accessing= > memory address 0x8000feff7df8: Bad address.
>) at ../src/Main.m3:319
>#6 =C2=A00x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DErr= >or accessing memory address 0x8000feff7eb8: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>#7 =C2=A00x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param= >=3DError accessing memory address 0x8000feff7f68: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>#8 =C2=A00x000000000047c7d4 in thread_start ()
>#9 =C2=A00x0000000000000000 in ?? ()
>
>Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
>#0 =C2=A00x000000000047e53c in _umtx_op_err ()
>#1 =C2=A00x0000000000475759 in suspend_common ()
>#2 =C2=A00x00000000004755c1 in pthread_suspend_np ()
>#3 =C2=A00x000000000044df0c in ThreadPThread__SuspendThread (mt=3DError acc= >essing memory address 0x8000ffbfd6f8: Bad address.
>) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
>#4 =C2=A00x000000000044bade in ThreadPThread__StopThread (M3_DMxDjQ_act=3DE= >rror accessing memory address 0x8000ffbfd718: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:909
>#5 =C2=A00x000000000044bc81 in ThreadPThread__StopWorld () at ../src/thread= >/PTHREAD/ThreadPThread.m3:948
>#6 =C2=A00x000000000044b19e in RTThread__SuspendOthers () at ../src/thread/= >PTHREAD/ThreadPThread.m3:713
>#7 =C2=A00x00000000004330d6 in RTCollector__CollectSomeInStateZero () at ..= >/src/runtime/common/RTCollector.m3:749
>#8 =C2=A00x0000000000433081 in RTCollector__CollectSome () at ../src/runtim= >e/common/RTCollector.m3:723
>#9 =C2=A00x0000000000432d49 in RTHeapRep__CollectEnough () at ../src/runtim= >e/common/RTCollector.m3:657
>#10 0x000000000042ff83 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=3DEr= >ror accessing memory address 0x8000ffbfd958: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:367
>#11 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=3DError = >accessing memory address 0x8000ffbfda18: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:296
>#12 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=3DErro= >r accessing memory address 0x8000ffbfda78: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:143
>#13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3DError accessing memo= >ry address 0x8000ffbfdab8: Bad address.
>) at ../src/rw/Rd.m3:159
>#14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=3DError acces= >sing memory address 0x8000ffbfdb88: Bad address.
>) at ../src/rw/Rd.m3:187
>#15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3DError accessing memor= >y address 0x8000ffbfdbd8: Bad address.
>) at ../src/rw/Rd.m3:176
>#16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3DError accessing memo= >ry address 0x8000ffbfdc58: Bad address.
>) at ../src/Main.m3:185
>
>#17 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DError ac= >cessing memory address 0x8000ffbfdeb8: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>#18 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=3DErro= >r accessing memory address 0x8000ffbfdf68: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>#19 0x000000000047c7d4 in thread_start ()
>#20 0x0000000000000000 in ?? ()
>
>Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
>#0 =C2=A00x000000000047e53c in _umtx_op_err ()
>#1 =C2=A00x0000000000475f14 in __thr_umutex_lock ()
>#2 =C2=A00x0000000000479404 in mutex_lock_common ()
>#3 =C2=A00x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=3DE= >rror accessing memory address 0x8000ffffc678: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>#4 =C2=A00x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/T= >hreadPThread.m3:1337
>---Type <return> to continue, or q <return> to quit---
>#5 =C2=A00x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize= >=3DError accessing memory address 0x8000ffffc6e8: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:365
>#6 =C2=A00x000000000042f15b in RTAllocator__GetTracedObj (M3_Eic7CK_def=3DE= >rror accessing memory address 0x8000ffffc7a8: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:224
>#7 =C2=A00x000000000042eb23 in RTHooks__AllocateTracedObj (M3_AJWxb1_defn= >=3DError accessing memory address 0x8000ffffc7f8: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:122
>#8 =C2=A00x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=3DError acces= >sing memory address 0x8000ffffc858: Bad address.
>) at ../src/text/TextCat.m3:562
>#9 =C2=A00x000000000045ed5d in TextCat__Balance (M3_Bd56fi_LText=3D0x800c49= >0b0, M3_BUgnwf_LInfo=3DError accessing memory address 0x8000ffffc8f8: Bad a= >ddress.
>) at ../src/text/TextCat.m3:488
>#10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3DError accessing me= >mory address 0x8000ffffcbb8: Bad address.
>) at ../src/text/TextCat.m3:40
>#11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3DError accessing memory = >address 0x8000ffffcc38: Bad address.
>) at ../src/Main.m3:593
>#12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=3DError access= >ing memory address 0x8000ffffcf88: Bad address.
>) at ../src/runtime/common/RTLinker.m3:408
>#13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3DError accessing= > memory address 0x8000ffffd008: Bad address.
>) at ../src/runtime/common/RTLinker.m3:115
>#14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3DError accessing = >memory address 0x8000ffffd028: Bad address.
>) at ../src/runtime/common/RTLinker.m3:124
>#15 0x00000000004004a6 in main (argc=3DError accessing memory address 0x800= >0ffffd07c: Bad address.
>) at _m3main.c:22
>
>Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
>#0 =C2=A00x000000000047e53c in _umtx_op_err ()
>#1 =C2=A00x0000000000477e8a in check_suspend ()
>#2 =C2=A00x00000000004780a2 in sigcancel_handler ()
>#3 =C2=A0<signal handler called>
>#4 =C2=A00x000000000047e53c in _umtx_op_err ()
>#5 =C2=A00x0000000000475f14 in __thr_umutex_lock ()
>#6 =C2=A00x0000000000479404 in mutex_lock_common ()
>#7 =C2=A00x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=3DE= >rror accessing memory address 0x8000ff5fac18: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>#8 =C2=A00x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/T= >hreadPThread.m3:1337
>#9 =C2=A00x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize= >=3DError accessing memory address 0x8000ff5fac88: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:365
>#10 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=3DError = >accessing memory address 0x8000ff5fad48: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:296
>#11 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=3DErro= >r accessing memory address 0x8000ff5fada8: Bad address.
>) at ../src/runtime/common/RTAllocator.m3:143
>#12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3DError accessing memo= >ry address 0x8000ff5fade8: Bad address.
>) at ../src/Main.m3:283
>#13 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DError ac= >cessing memory address 0x8000ff5faeb8: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>#14 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=3DErro= >r accessing memory address 0x8000ff5faf68: Bad address.
>) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>#15 0x000000000047c7d4 in thread_start ()
>#16 0x0000000000000000 in ?? ()
>
>(others are similar)
>
>Hmm looks like a FreeBSD issue now. =C2=A0It's here...
>
>int
>__cdecl
>ThreadPThread__SuspendThread (m3_pthread_t mt)
>{
>=C2=A0 ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), "= >pthread_suspend_np");
>=C2=A0 return 1;
>}
>
>Now this suspend can wait:
>
>static int
>suspend_common(struct pthread *curthread, struct pthread *thread,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 int waitok)
>{
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 uint32_t tmp;
>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 while (thread->state !=3D PS_DEAD &&= >
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 !(thread->flags & T= >HR_FLAGS_SUSPENDED)) {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 thread->flags |= >=3D THR_FLAGS_NEED_SUSPEND;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Thread is in cre= >ation. */
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (thread->tid = >=3D=3D TID_TERMINATED)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >=A0 =C2=A0 return (1);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 tmp =3D thread->= >cycle;
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _thr_send_sig(threa= >d, SIGCANCEL);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 THR_THREAD_UNLOCK(c= >urthread, thread);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (waitok) {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >=A0 =C2=A0 _thr_umtx_wait_uint(&thread->cycle, tmp, NULL, 0); =C2=A0= ><=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >=A0 =C2=A0 THR_THREAD_LOCK(curthread, thread);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >=A0 =C2=A0 THR_THREAD_LOCK(curthread, thread);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >=A0 =C2=A0 return (0);
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (1);
>}
>
>... but what it can wait for I am not clear on.
>
>Do things work better on Linux?
>
>What is the status of the fork bug? =C2=A0Can it be worked around by only f= >orking via Process.Create with no mutexes held (outside of all LOCK blocks)= >?
>
>=C2=A0 =C2=A0 =C2=A0Mika
>
>
>
>Peter McKinna writes:
>>--001a11c2ced4471a2e050079db82
>>Content-Type: text/plain; charset=3DUTF-8
>
>
>>Mika
>>
>> =C2=A0I think you need to back out Tony's changes to fix the fork = >bug, at least
>>for now. Need to reload from cvs version 1.262 for ThreadPThread.m3 If<= >br> >>you're using git you're on your own.
>> =C2=A0Do a cvs log ThreadPThread.m3 for an explanation for some of the= > design
>>principles.
>> =C2=A0Also if you use gdb then you need to set lanc c before backtrace= >s so at
>>least you can see address names and values even if they are contorted y= >ou
>>can extract the M3 name in the parm lists. Also in gdb thread apply all= > bt
>>gives all thread backtraces which can be handy to see whose got the loc= >ks
>>held.
>>
>>Regards Peter
>>
>>
>>
>>On Wed, Aug 13, 2014 at 12:14 PM, <ech.edu" target=3D"_blank">mika at async.caltech.edu> wrote:
>>
>>>
>>> Question... is there something odd about my pthreads? =C2=A0Are pt= >hreads
>>> normally reentrant? =C2=A0I didn't think so.
>>>
>>> My compiler is much happier with the following changes I already o= >utlined:
>>>
>>> 1. a dirty, disgusting hack to keep from locking against myself go= >ing from
>>> XWait with self.mutex locked to m.release().
>>>
>>> 2. the change to LockHeap I described in previous email
>>>
>>> But now...
>>>
>>> (gdb) cont
>>> Continuing.
>>> ERROR: pthread_mutex_lock:11
>>> ERROR: pthread_mutex_lock:11
>>>
>>> Program received signal SIGABRT, Aborted.
>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>> (gdb) where
>>> #0 =C2=A00x000000080107626a in thr_kill () from /lib/libc.so.7
>>> #1 =C2=A00x000000080113dac9 in abort () from /lib/libc.so.7
>>> #2 =C2=A00x000000000071e37a in ThreadPThread__pthread_mutex_lock (= >mutex=3DError
>>> accessing memory address 0x8000ffffb508: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>> #3 =C2=A00x000000000071d48d in RTOS__LockHeap () at
>>> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>>> #4 =C2=A00x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af4= >0ku_ref=3DError
>>> accessing memory address 0x8000ffffb568: Bad address.
>>> ) at ../src/runtime/common/RTCollector.m3:2234
>>> #5 =C2=A00x000000000071d284 in ThreadPThread__AtForkParent () atr> >>> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>>> #6 =C2=A00x0000000800df8733 in fork () from /lib/libthr.so.3
>>> #7 =C2=A00x000000000070dd8b in RTProcess__Fork () at
>>> ../src/runtime/common/RTProcessC.c:152
>>> #8 =C2=A00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec= >
>>> (M3_Bd56fi_cmd=3DError accessing memory address 0x8000ffffb6f8: Ba= >d address.
>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>> #9 =C2=A00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DEr= >ror accessing
>>> memory address 0x8000ffffb7f8: Bad address.
>>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_e= >p=3DError
>>> accessing memory address 0x8000ffffb838: Bad address.
>>> ) at ../src/QMachine.m3:1666
>>> #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3DErr= >or
>>> accessing memory address 0x8000ffffb9f8: Bad address.
>>> ) at ../src/QMachine.m3:1605
>>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError= > accessing
>>> memory address 0x8000ffffbee8: Bad address.
>>> ) at ../src/QMachine.m3:1476
>>>
>>> What am I doing wrong here?
>>>
>>> The error doesn't look unreasonable! =C2=A0Looking more closel= >y at the code:
>>>
>>> First, AtForkPrepare has been called:
>>>
>>> PROCEDURE AtForkPrepare() =3D
>>> =C2=A0 VAR me :=3D GetActivation();
>>> =C2=A0 =C2=A0 =C2=A0 act: Activation;
>>> =C2=A0 BEGIN
>>> =C2=A0 =C2=A0 PThreadLockMutex(slotsMu, ThisLine());
>>> =C2=A0 =C2=A0 PThreadLockMutex(perfMu, ThisLine());
>>> =C2=A0 =C2=A0 PThreadLockMutex(initMu, ThisLine()); (* InitMutex = >=3D>
>>> RegisterFinalCleanup =3D> LockHeap *)
>>> =C2=A0 =C2=A0 PThreadLockMutex(heapMu, ThisLine());
>>> =C2=A0 =C2=A0 PThreadLockMutex(activeMu, ThisLine()); (* LockHeap = >=3D> SuspendOthers
>>> =3D> activeMu *)
>>> =C2=A0 =C2=A0 (* Walk activations and lock all threads.
>>> =C2=A0 =C2=A0 =C2=A0* NOTE: We have initMu, activeMu, so slots won= >'t change, conditions
>>> and
>>> =C2=A0 =C2=A0 =C2=A0* mutexes won't be initialized on-demand.<= >br> >>> =C2=A0 =C2=A0 =C2=A0*)
>>> =C2=A0 =C2=A0 act :=3D me;
>>> =C2=A0 =C2=A0 REPEAT
>>> =C2=A0 =C2=A0 =C2=A0 PThreadLockMutex(act.mutex, ThisLine());
>>> =C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>>> =C2=A0 =C2=A0 UNTIL act =3D me;
>>> =C2=A0 END AtForkPrepare;
>>>
>>> a postcondition of this routine is that heapMu is locked.
>>>
>>> now we get into AtForkParent:
>>>
>>> PROCEDURE AtForkParent() =3D
>>> =C2=A0 VAR me :=3D GetActivation();
>>> =C2=A0 =C2=A0 =C2=A0 act: Activation;
>>> =C2=A0 =C2=A0 =C2=A0 cond: Condition;
>>> =C2=A0 BEGIN
>>> =C2=A0 =C2=A0 (* Walk activations and unlock all threads, conditio= >ns. *)
>>> =C2=A0 =C2=A0 act :=3D me;
>>> =C2=A0 =C2=A0 REPEAT
>>> =C2=A0 =C2=A0 =C2=A0 cond :=3D slots[act.slot].join;
>>> =C2=A0 =C2=A0 =C2=A0 IF cond # NIL THEN PThreadUnlockMutex(cond.mu= >tex, ThisLine()) END;
>>> =C2=A0 =C2=A0 =C2=A0 PThreadUnlockMutex(act.mutex, ThisLine());> >>> =C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>>> =C2=A0 =C2=A0 UNTIL act =3D me;
>>> =C2=A0 =C2=A0 PThreadUnlockMutex(activeMu, ThisLine());
>>> =C2=A0 =C2=A0 PThreadUnlockMutex(heapMu, ThisLine());
>>> =C2=A0 =C2=A0 PThreadUnlockMutex(initMu, ThisLine());
>>> =C2=A0 =C2=A0 PThreadUnlockMutex(perfMu, ThisLine());
>>> =C2=A0 =C2=A0 PThreadUnlockMutex(slotsMu, ThisLine());
>>> =C2=A0 END AtForkParent;
>>>
>>> We can see by inspecting the code that a necessary precondition fo= >r
>>> this routine is that heapMu is locked! =C2=A0(Since it's going= > to unlock it,
>>> it had BETTER be locked on entry.)
>>>
>>> But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef
>>>
>>> which causes an RTOS.LockHeap
>>>
>>> the code of which we just saw:
>>>
>>> PROCEDURE LockHeap () =3D
>>> =C2=A0 VAR self :=3D pthread_self();
>>> =C2=A0 BEGIN
>>> =C2=A0 =C2=A0 WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO = ><*ASSERT r=3D0*> END;
>>> ...
>>>
>>> we try to lock heapMu. =C2=A0kaboom! =C2=A0No surprise there, real= >ly?
>>>
>>> Am I going about this totally the wrong way? =C2=A0Other people ar= >e running
>>> Modula-3
>>> with pthreads, right? =C2=A0Right?? =C2=A0Somewhere out there in m= >3devel-land?
>>>
>>> =C2=A0 =C2=A0 =C2=A0Mika
>>>
>>>
>>
>
>--001a11c2ced4471a2e050079db82
>>Content-Type: text/html; charset=3DUTF-8
>>Content-Transfer-Encoding: quoted-printable
>>
>><div dir=3D3D"ltr">Mika<div><br></div>= >;<div>=3DC2=3DA0 I think you need to back ou=3D
>>t Tony&#39;s changes to fix the fork bug, at least for now. Need to= > reload =3D
>>from cvs version 1.262 for ThreadPThread.m3 If you&#39;re using git= > you&#39=3D
>>;re on your own.</div>
>>
>><div>=3DC2=3DA0 Do a cvs log ThreadPThread.m3 for an explanation = >for some of th=3D
>>e design principles.=3DC2=3DA0</div><div>=3DC2=3DA0 Also if= > you use gdb then you ne=3D
>>ed to set lanc c before backtraces so at least you can see address name= >s an=3D
>>d values even if they are contorted you can extract the M3 name in the = >parm=3D
>> lists. Also in gdb thread apply all bt gives all thread backtraces whi= >ch c=3D
>>an be handy to see whose got the locks held.</div>
>>
>><div><br></div><div>Regards Peter</div>&l= >t;div><br></div><div class=3D3D"gmail_e=3D
>>xtra"><br><br><div class=3D3D"gmail_quote&q= >uot;>On Wed, Aug 13, 2014 at 12:14 PM, =3D
>> <span dir=3D3D"ltr">&lt;<a href=3D3D"mailt= >o:mika at async.ca= >ltech.edu" target=3D3D"=3D
>>_blank">ank">mika at async.caltech.edu</a>&gt;</span> wrote:<br= >>
>>
>><blockquote class=3D3D"gmail_quote" style=3D3D"margin= >:0 0 0 .8ex;border-left:1p=3D
>>x #ccc solid;padding-left:1ex"><br>
>>Question... is there something odd about my pthreads? =3DC2=3DA0Are pth= >reads no=3D
>>rmally reentrant? =3DC2=3DA0I didn&#39;t think so.<br>
>><br>
>>My compiler is much happier with the following changes I already outlin= >ed:<=3D
>>br>
>><br>
>>1. a dirty, disgusting hack to keep from locking against myself going f= >rom =3D
>>XWait with self.mutex locked to m.release().<br>
>><br>
>>2. the change to LockHeap I described in previous email<br>
>><br>
>>But now...<br>
>><br>
>>(gdb) cont<br>
>>Continuing.<br>
>>ERROR: pthread_mutex_lock:11<br>
>>ERROR: pthread_mutex_lock:11<br>
>><br>
>>Program received signal SIGABRT, Aborted.<br>
>>0x000000080107626a in thr_kill () from /lib/libc.so.7<br>
>>(gdb) where<br>
>>#0 =3DC2=3DA00x000000080107626a in thr_kill () from /lib/libc.so.7<b= >r>
>>#1 =3DC2=3DA00x000000080113dac9 in abort () from /lib/libc.so.7<br&g= >t;
>>#2 =3DC2=3DA00x000000000071e37a in ThreadPThread__pthread_mutex_lock (m= >utex=3D3DE=3D
>>rror accessing memory address 0x8000ffffb508: Bad address.<br>> >>) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>>#3 =3DC2=3DA00x000000000071d48d in RTOS__LockHeap () at ../src/thread/P= >THREAD/T=3D
>>hreadPThread.m3:1377<br>
>>#4 =3DC2=3DA00x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40= >ku_ref=3D
>>=3D3DError accessing memory address 0x8000ffffb568: Bad address.<br&= >gt;
>>) at ../src/runtime/common/RTCollector.m3:2234<br>
>>#5 =3DC2=3DA00x000000000071d284 in ThreadPThread__AtForkParent () at ..= >/src/thr=3D
>>ead/PTHREAD/ThreadPThread.m3:1348<br>
>>#6 =3DC2=3DA00x0000000800df8733 in fork () from /lib/libthr.so.3<br&= >gt;
>>#7 =3DC2=3DA00x000000000070dd8b in RTProcess__Fork () at ../src/runtime= >/common/=3D
>>RTProcessC.c:152<br>
>>#8 =3DC2=3DA00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec = >(M3_Bd56=3D
>>fi_cmd=3D3DError accessing memory address 0x8000ffffb6f8: Bad address.&= >lt;br>
>>) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>>#9 =3DC2=3DA00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3D3DE= >rror acces=3D
>>sing memory address 0x8000ffffb7f8: Bad address.<br>
>>) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>>#10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=3D3= >DError=3D
>> accessing memory address 0x8000ffffb838: Bad address.<br>
>>) at ../src/QMachine.m3:1666<br>
>>#11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3D3DError = >access=3D
>>ing memory address 0x8000ffffb9f8: Bad address.<br>
>>) at ../src/QMachine.m3:1605<br>
>>#12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3D3DError ac= >cessin=3D
>>g memory address 0x8000ffffbee8: Bad address.<br>
>>) at ../src/QMachine.m3:1476<br>
>><br>
>>What am I doing wrong here?<br>
>><br>
>>The error doesn&#39;t look unreasonable! =3DC2=3DA0Looking more clo= >sely at the =3D
>>code:<br>
>><br>
>>First, AtForkPrepare has been called:<br>
>><br>
>>PROCEDURE AtForkPrepare() =3D3D<br>
>>=3DC2=3DA0 VAR me :=3D3D GetActivation();<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;<br>
>>=3DC2=3DA0 BEGIN<br>
>>=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(slotsMu, ThisLine());<br><= >br> >>=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(perfMu, ThisLine());<br>r> >>=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(initMu, ThisLine()); (* InitMute= >x =3D3D&gt; Re=3D
>>gisterFinalCleanup =3D3D&gt; LockHeap *)<br>
>>=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(heapMu, ThisLine());<br>r> >>=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(activeMu, ThisLine()); (* LockHe= >ap =3D3D&gt; S=3D
>>uspendOthers =3D3D&gt; activeMu *)<br>
>>=3DC2=3DA0 =3DC2=3DA0 (* Walk activations and lock all threads.<br&g= >t;
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* NOTE: We have initMu, activeMu, so sl= >ots won&#39;t ch=3D
>>ange, conditions and<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* mutexes won&#39;t be initialized = >on-demand.<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0*)<br>
>>=3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;<br>
>>=3DC2=3DA0 =3DC2=3DA0 REPEAT<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(act.mutex, ThisLine()= >);<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;<br>
>>=3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;<br>
>>=3DC2=3DA0 END AtForkPrepare;<br>
>><br>
>>a postcondition of this routine is that heapMu is locked.<br>
>><br>
>>now we get into AtForkParent:<br>
>><br>
>>PROCEDURE AtForkParent() =3D3D<br>
>>=3DC2=3DA0 VAR me :=3D3D GetActivation();<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond: Condition;<br>
>>=3DC2=3DA0 BEGIN<br>
>>=3DC2=3DA0 =3DC2=3DA0 (* Walk activations and unlock all threads, condi= >tions. *)<br=3D
>>>
>>=3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;<br>
>>=3DC2=3DA0 =3DC2=3DA0 REPEAT<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond :=3D3D slots[act.slot].join;<b= >r>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 IF cond # NIL THEN PThreadUnlockMutex(= >cond.mutex, This=3D
>>Line()) END;<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(act.mutex, ThisLine= >());<br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;<br>
>>=3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;<br>
>>=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(activeMu, ThisLine());<br&g= >t;
>>=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(heapMu, ThisLine());<br>= >
>>=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(initMu, ThisLine());<br>= >
>>=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(perfMu, ThisLine());<br>= >
>>=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(slotsMu, ThisLine());<br>= >;
>>=3DC2=3DA0 END AtForkParent;<br>
>><br>
>>We can see by inspecting the code that a necessary precondition for<= >br>
>>this routine is that heapMu is locked! =3DC2=3DA0(Since it&#39;s go= >ing to unloc=3D
>>k it,<br>
>>it had BETTER be locked on entry.)<br>
>><br>
>>But the cond :=3D3D ... causes a RTHooks.CheckLoadTracedRef<br>r> >><br>
>>which causes an RTOS.LockHeap<br>
>><br>
>>the code of which we just saw:<br>
>><br>
>>PROCEDURE LockHeap () =3D3D<br>
>>=3DC2=3DA0 VAR self :=3D3D pthread_self();<br>
>>=3DC2=3DA0 BEGIN<br>
>>=3DC2=3DA0 =3DC2=3DA0 WITH r =3D3D pthread_mutex_lock(heapMu,ThisLine()= >) DO &lt;*ASSE=3D
>>RT r=3D3D0*&gt; END;<br>
>>...<br>
>><br>
>>we try to lock heapMu. =3DC2=3DA0kaboom! =3DC2=3DA0No surprise there, r= >eally?<br>
>><br>
>>Am I going about this totally the wrong way? =3DC2=3DA0Other people are= > running=3D
>> Modula-3<br>
>>with pthreads, right? =3DC2=3DA0Right?? =3DC2=3DA0Somewhere out there i= >n m3devel-la=3D
>>nd?<br>
>><span><font color=3D3D"#888888"><br>
>>=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika<br>
>><br>
>></font></span></blockquote></div><br><= >/div></div>
>>
>>--001a11c2ced4471a2e050079db82--
>

>

> >--089e01183a1813188705007c3498-- From mika at async.caltech.edu Wed Aug 13 09:03:04 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Wed, 13 Aug 2014 00:03:04 -0700 Subject: [M3devel] Another issue... Message-ID: <20140813070304.E798E1A2094@async.async.caltech.edu> There have been problems with this before. libm3 had two interfaces LongrealType and RealType. There are comments to the effect they were moved to m3core. That's fine. But what I see at the head---I think---is that they were removed from the m3makefile for libm3, never moved to m3core/types, and certainly never put in the m3core m3makefile. As a result a lot of my private code is breaking, which uses LongrealType.T in instantiated generics. My fix is to uncomment the include of "types" in libm3. Not sure why it is the way it is at head. Mika From mika at async.caltech.edu Wed Aug 13 18:37:35 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Wed, 13 Aug 2014 09:37:35 -0700 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: <97266593-618F-458D-A975-FE01D9BF19F9@cs.purdue.edu> References: <20140813021401.238B31A2094@async.async.caltech.edu> <20140813045415.C13921A2094@async.async.caltech.edu> <20140813063041.286EA1A2094@async.async.caltech.edu> <97266593-618F-458D-A975-FE01D9BF19F9@cs.purdue.edu> Message-ID: <20140813163735.8D0701A2097@async.async.caltech.edu> 1.262 Short summary: 1.262 seems to work fine on AMD64_LINUX except for the fork issue (a bummer because my parallelization of the backends of cm3 uses fork a lot...and it does speed up the compiler significantly if you have fast disks and lots of cores) It does the attached on AMD64_FREEBSD. I see the intent of what you were doing in later version/s, but it was a bit rough, I think... I think the three issues I reported (1. locking heapMu from AtFork; 2. the try-only-once bug in LockHeap itself; 3. not passing the lock to release from Wait) are all more or less real. Mika Tony Hosking writes: >Which revision of ThreadPThread.m3 is this output from? > >On Aug 13, 2014, at 2:30 AM, mika at async.caltech.edu wrote: > >>=20 >> OK... deleted all the derived directories and rebuilt. Result on = >FreeBSD is similar (or identical, hard to tell): >>=20 >> I get a partial deadlock: >>=20 >> PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU = >COMMAND >> 48760 root 98 0 87836K 29104K CPU1 1 12:32 83.89% = >threadtest{threadtest} >> 48760 root 94 0 87836K 29104K CPU3 3 11:02 74.66% = >threadtest{threadtest} >> 48760 root 94 0 87836K 29104K CPU0 0 11:03 71.97% = >threadtest{threadtest} >> 48760 root 32 0 87836K 29104K umtxn 2 0:01 0.00% = >threadtest{threadtest} >> 48760 root 20 0 87836K 29104K umtxn 2 0:01 0.00% = >threadtest{threadtest} >> 48760 root 35 0 87836K 29104K uwait 2 0:01 0.00% = >threadtest{threadtest} >> 48760 root 27 0 87836K 29104K uwait 0 0:01 0.00% = >threadtest{threadtest} >> 48760 root 27 0 87836K 29104K umtxn 3 0:01 0.00% = >threadtest{threadtest} >> 48760 root 27 0 87836K 29104K umtxn 2 0:01 0.00% = >threadtest{threadtest} >> 48760 root 20 0 87836K 29104K umtxn 0 0:00 0.00% = >threadtest{threadtest} >> 48759 root 20 0 30276K 11064K wait 0 0:00 0.00% gdb >>=20 >> one of the dead threads is the main thread, so now output. But three >> threads are still alive, interestingly enough. >>=20 >> Looks like the same issue as before: >>=20 >> Thread 5 (Thread 801807400 (LWP 100751/threadtest)): >> #0 0x0000000800ae089c in __error () from /lib/libthr.so.3 >> #1 0x0000000800ad6261 in pthread_suspend_np () from /lib/libthr.so.3 >> #2 0x00000000004511bc in ThreadPThread__SuspendThread (mt=3DError = >accessing memory address 0x8000ff5faa28: Bad address. >> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >> #3 0x000000000044ed8e in ThreadPThread__StopThread = >(M3_DMxDjQ_act=3DError accessing memory address 0x8000ff5faa48: Bad = >address. >> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >> #4 0x000000000044ef31 in ThreadPThread__StopWorld () at = >../src/thread/PTHREAD/ThreadPThread.m3:948 >> #5 0x000000000044e44e in RTThread__SuspendOthers () at = >../src/thread/PTHREAD/ThreadPThread.m3:713 >> #6 0x0000000000436386 in RTCollector__CollectSomeInStateZero () at = >../src/runtime/common/RTCollector.m3:749 >> #7 0x0000000000436331 in RTCollector__CollectSome () at = >../src/runtime/common/RTCollector.m3:723 >> #8 0x0000000000435ff9 in RTHeapRep__CollectEnough () at = >../src/runtime/common/RTCollector.m3:657 >> #9 0x0000000000433233 in RTAllocator__AllocTraced = >(M3_Cwb5VA_dataSize=3DError accessing memory address 0x8000ff5fac88: Bad = >address. >> ) at ../src/runtime/common/RTAllocator.m3:367 >> #10 0x0000000000432b55 in RTAllocator__GetOpenArray = >(M3_Eic7CK_def=3DError accessing memory address 0x8000ff5fad48: Bad = >address. >> ) at ../src/runtime/common/RTAllocator.m3:296 >> #11 0x0000000000431e8f in RTHooks__AllocateOpenArray = >(M3_AJWxb1_defn=3DError accessing memory address 0x8000ff5fada8: Bad = >address. >> ) at ../src/runtime/common/RTAllocator.m3:143 >> #12 0x00000000004052ea in Main__AApply (M3_AP7a1g_cl=3DError accessing = >memory address 0x8000ff5fade8: Bad address. >> ) at ../src/Main.m3:283 >> #13 0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DError= > accessing memory address 0x8000ff5faeb8: Bad address. >> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >> #14 0x000000000044cf00 in ThreadPThread__ThreadBase = >(M3_AJWxb1_param=3DError accessing memory address 0x8000ff5faf68: Bad = >address. >> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >> #15 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >> #16 0x0000000000000000 in ?? () >>=20 >> Interestingly the same test seems to work on AMD64_LINUX. That is >> promising, at least. But of course, software testing never reveals = >the >> absence of bugs. >>=20 >> Mika >>=20 >> Peter McKinna writes: >>> --089e01183a1813188705007c3498 >>> Content-Type: text/plain; charset=3DUTF-8 >>>=20 >>> Oh, one other thing that seemed to help me in testing this stuff = >especially >>> things to do with m3core and libm3 which seem to get out of whack >>> sometimes, is to totally remove the target directory of m3core then = >cm3; >>> cm3 -ship Same with libm3. I'm not sure that clean actually removes = >the >>> targets and I think there are leftover files that stuff things up = >since I >>> would get segv in FileRd for no obvious reason. >>>=20 >>> Peter >>>=20 >>>=20 >>>=20 >>> On Wed, Aug 13, 2014 at 3:33 PM, Peter McKinna = > >>> wrote: >>>=20 >>>> That is weird. The thread tester works fine with the old version of >>>> ThreadPThread.m3 on linux amd_64 except if you have the fork test in = >the >>>> mix of tests you see the pthread_mutex_destroy every now and again, = >the >>>> fork bug in fact. >>>> I was testing the pthread changes Tony has made over the past few = >days >>>> using the thread tester program until I stupidly rebuilt the = >compiler and >>>> was getting all sorts of hangs as it dragged in the new version of >>>> pthreads. So I rebuilt everything from a backup to get back where I = >was >>>> with a decent compiler, then reintroduced the latest changes to >>>> ThreadPThread.m3, which yesterday was just hanging in sigsuspend but = >today >>>> is giving me an assert failure at line 1387 in UnlockHeap. So its a = >bit >>>> unstable to say the least. Maybe there is something else wrong with = >freebsd. >>>>=20 >>>> Peter >>>>=20 >>>>=20 >>>>=20 >>>> On Wed, Aug 13, 2014 at 2:54 PM, wrote: >>>>=20 >>>>>=20 >>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not = >getting >>>>> things to work and now I'm really baffled because I think I = >understand >>>>> this code! >>>>>=20 >>>>> What I did was I threw away all my changes and reverted = >ThreadPThread.m3 >>>>> to 1.262 as you suggested. >>>>>=20 >>>>> Rebuilt the compiler with upgrade.sh >>>>>=20 >>>>> Then rebuilt the compiler again with itself. >>>>>=20 >>>>> Then I realcleaned the world and buildshipped it. (I was afraid >>>>> that parseparams, also imported by the thread tester, would pollute >>>>> it somehow.) >>>>>=20 >>>>> When I look at the code in 1.262 it looks quite straightforward. = >heapMu >>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. >>>>> Condition >>>>> variables are mutexes too, but that's no big deal. >>>>>=20 >>>>> So, rebuild thread tester, run it: >>>>>=20 >>>>> new source -> compiling Main.m3 >>>>> -> linking threadtest >>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # >>>>> AMD64_FREEBSD/threadtest >>>>> Writing file...done >>>>> Creating read threads...done >>>>> Creating fork threads...done >>>>> Creating alloc threads...done >>>>> Creating lock threads...done >>>>> running...printing oldest/median age/newest >>>>> . >>>>>=20 >>>>> *** >>>>> *** runtime error: >>>>> *** Segmentation violation - possible attempt to dereference >>>>> NIL.........laziest thread is 1407901189/1407901189/9 (tests: read >>>>> 1407901189/1407901189/1407901189 fork = >1407901189/1407901189/1407901189 >>>>> alloc 9/9/9 lock 1407901189/1407901189/9) >>>>>=20 >>>>>=20 >>>>>=20 >>>>>=20 >>>>> ^C >>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb = >!$ >>>>> gdb AMD64_FREEBSD/threadtest >>>>> GNU gdb 6.1.1 [FreeBSD] >>>>> Copyright 2004 Free Software Foundation, Inc. >>>>> GDB is free software, covered by the GNU General Public License, = >and you >>>>> are >>>>> welcome to change it and/or distribute copies of it under certain >>>>> conditions. >>>>> Type "show copying" to see the conditions. >>>>> There is absolutely no warranty for GDB. Type "show warranty" for >>>>> details. >>>>> This GDB was configured as "amd64-marcel-freebsd"... >>>>> (gdb) run >>>>> Starting program: >>>>> = >/big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/th= >readtest >>>>> [New LWP 100121] >>>>> Writing file...done >>>>> Creating read threads...done >>>>> Creating fork threads...done >>>>> Creating alloc threads...done >>>>> Creating lock threads...done >>>>> running...printing oldest/median age/newest >>>>> .[New Thread 801807000 (LWP 100343/threadtest)] >>>>> [New Thread 801807c00 (LWP 100667/threadtest)] >>>>> [New Thread 801808800 (LWP 100816/threadtest)] >>>>> [New Thread 801807400 (LWP 100349/threadtest)] >>>>> [New Thread 801808400 (LWP 100815/threadtest)] >>>>> [New Thread 801807800 (LWP 100352/threadtest)] >>>>> [New Thread 801808c00 (LWP 100817/threadtest)] >>>>> [New Thread 801809000 (LWP 100818/threadtest)] >>>>> [New Thread 801809800 (LWP 100820/threadtest)] >>>>> [New Thread 801808000 (LWP 100678/threadtest)] >>>>> [New Thread 801806400 (LWP 100121/threadtest)] >>>>> [New Thread 801806800 (LWP 100341/threadtest)] >>>>> [New Thread 801806c00 (LWP 100342/threadtest)] >>>>> .ERROR: pthread_mutex_lock:11 >>>>>=20 >>>>> Program received signal SIGABRT, Aborted. >>>>> [Switching to Thread 801809800 (LWP 100820/threadtest)] >>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>> (gdb) where >>>>> #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>> #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 >>>>> #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock = >(mutex=3DError >>>>> accessing memory address 0x8000fe5f2d98: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 >>>>> #3 0x000000000044b370 in ThreadPThread__LockMutex = >(M3_AYIbX3_m=3DError >>>>> accessing memory address 0x8000fe5f2dc8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>> #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3DError = >accessing >>>>> memory address 0x8000fe5f2df8: Bad address. >>>>> ) at ../src/Main.m3:319 >>>>> #5 0x000000000044d243 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3DError >>>>> accessing memory address 0x8000fe5f2eb8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>> #6 0x000000000044cf00 in ThreadPThread__ThreadBase >>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000fe5f2f68: = >Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>> #7 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>>> #8 0x0000000000000000 in ?? () >>>>> (gdb) set lang c >>>>> (gdb) thread apply all bt >>>>> ... not that interesting ... >>>>>=20 >>>>> Segfault is segfault---error 11 is EDEADLK (locking against = >myself?) >>>>>=20 >>>>> ????? the code is very straightforward, as I said. >>>>>=20 >>>>> I thought people had the thread tester working with pthreads? = >Which set >>>>> of files, then? Anyone on FreeBSD/amd64? >>>>>=20 >>>>> Could it be an issue with "volatile"? Not even sure where to look. >>>>>=20 >>>>> The code calling the lock is just this: >>>>>=20 >>>>> PROCEDURE GetChar (rd: T): CHAR >>>>> RAISES {EndOfFile, Failure, Alerted} =3D >>>>> BEGIN >>>>> LOCK rd DO >>>>> RETURN FastGetChar(rd); >>>>> END >>>>> END GetChar; >>>>>=20 >>>>> No mysteries there... >>>>>=20 >>>>> Ah is this the fork bug? Looks like the Init routine is called on = >a >>>>> lot of NIL mutexes around the fork. But the subprocesses aren't = >meant >>>>> to accesses the mutexes... humm >>>>>=20 >>>>> Hmm, and it's not entirely a fork issue. Even with "threadtest = >-tests >>>>> STD,-fork,-forktoomuch" it misbehaves. Hangs.... >>>>>=20 >>>>> Looks like a deadlock this time. >>>>>=20 >>>>> Some stacks... >>>>>=20 >>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): >>>>> #0 0x00000000004b4e2b in __vdso_gettimeofday () >>>>> #1 0x00000000004ab8d2 in gettimeofday () >>>>> #2 0x0000000000452e4b in TimePosix__Now () at >>>>> ../src/time/POSIX/TimePosixC.c:50 >>>>> #3 0x0000000000452d72 in Time__Now () at >>>>> ../src/time/POSIX/TimePosix.m3:14 >>>>> #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3DError = >accessing >>>>> memory address 0x8000fedf6df8: Bad address. >>>>> ) at ../src/Main.m3:327 >>>>> #5 0x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3DError >>>>> accessing memory address 0x8000fedf6eb8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>> #6 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000fedf6f68: = >Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>> #7 0x000000000047c7d4 in thread_start () >>>>> #8 0x0000000000000000 in ?? () >>>>>=20 >>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): >>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >(mutex=3DError >>>>> accessing memory address 0x8000feff7d98: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>> #4 0x00000000004480c0 in ThreadPThread__LockMutex = >(M3_AYIbX3_m=3DError >>>>> accessing memory address 0x8000feff7dc8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>> #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3DError = >accessing >>>>> memory address 0x8000feff7df8: Bad address. >>>>> ) at ../src/Main.m3:319 >>>>> #6 0x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3DError >>>>> accessing memory address 0x8000feff7eb8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>> #7 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000feff7f68: = >Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>> #8 0x000000000047c7d4 in thread_start () >>>>> #9 0x0000000000000000 in ?? () >>>>>=20 >>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): >>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>> #1 0x0000000000475759 in suspend_common () >>>>> #2 0x00000000004755c1 in pthread_suspend_np () >>>>> #3 0x000000000044df0c in ThreadPThread__SuspendThread (mt=3DError >>>>> accessing memory address 0x8000ffbfd6f8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>>> #4 0x000000000044bade in ThreadPThread__StopThread = >(M3_DMxDjQ_act=3DError >>>>> accessing memory address 0x8000ffbfd718: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>>> #5 0x000000000044bc81 in ThreadPThread__StopWorld () at >>>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>>> #6 0x000000000044b19e in RTThread__SuspendOthers () at >>>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>>> #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero () at >>>>> ../src/runtime/common/RTCollector.m3:749 >>>>> #8 0x0000000000433081 in RTCollector__CollectSome () at >>>>> ../src/runtime/common/RTCollector.m3:723 >>>>> #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at >>>>> ../src/runtime/common/RTCollector.m3:657 >>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced >>>>> (M3_Cwb5VA_dataSize=3DError accessing memory address = >0x8000ffbfd958: Bad >>>>> address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray = >(M3_Eic7CK_def=3DError >>>>> accessing memory address 0x8000ffbfda18: Bad address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>> (M3_AJWxb1_defn=3DError accessing memory address 0x8000ffbfda78: = >Bad address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3DError = >accessing >>>>> memory address 0x8000ffbfdab8: Bad address. >>>>> ) at ../src/rw/Rd.m3:159 >>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=3DError= > >>>>> accessing memory address 0x8000ffbfdb88: Bad address. >>>>> ) at ../src/rw/Rd.m3:187 >>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3DError = >accessing >>>>> memory address 0x8000ffbfdbd8: Bad address. >>>>> ) at ../src/rw/Rd.m3:176 >>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3DError = >accessing >>>>> memory address 0x8000ffbfdc58: Bad address. >>>>> ) at ../src/Main.m3:185 >>>>>=20 >>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3DError >>>>> accessing memory address 0x8000ffbfdeb8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000ffbfdf68: = >Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>> #19 0x000000000047c7d4 in thread_start () >>>>> #20 0x0000000000000000 in ?? () >>>>>=20 >>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): >>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >(mutex=3DError >>>>> accessing memory address 0x8000ffffc678: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>> #4 0x000000000044d039 in RTOS__LockHeap () at >>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>> ---Type to continue, or q to quit--- >>>>> #5 0x000000000042ff79 in RTAllocator__AllocTraced >>>>> (M3_Cwb5VA_dataSize=3DError accessing memory address = >0x8000ffffc6e8: Bad >>>>> address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>> #6 0x000000000042f15b in RTAllocator__GetTracedObj = >(M3_Eic7CK_def=3DError >>>>> accessing memory address 0x8000ffffc7a8: Bad address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:224 >>>>> #7 0x000000000042eb23 in RTHooks__AllocateTracedObj >>>>> (M3_AJWxb1_defn=3DError accessing memory address 0x8000ffffc7f8: = >Bad address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:122 >>>>> #8 0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=3DError = >accessing >>>>> memory address 0x8000ffffc858: Bad address. >>>>> ) at ../src/text/TextCat.m3:562 >>>>> #9 0x000000000045ed5d in TextCat__Balance = >(M3_Bd56fi_LText=3D0x800c490b0, >>>>> M3_BUgnwf_LInfo=3DError accessing memory address 0x8000ffffc8f8: = >Bad address. >>>>> ) at ../src/text/TextCat.m3:488 >>>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3DError = >accessing >>>>> memory address 0x8000ffffcbb8: Bad address. >>>>> ) at ../src/text/TextCat.m3:40 >>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3DError accessing = >memory >>>>> address 0x8000ffffcc38: Bad address. >>>>> ) at ../src/Main.m3:593 >>>>> #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=3DError >>>>> accessing memory address 0x8000ffffcf88: Bad address. >>>>> ) at ../src/runtime/common/RTLinker.m3:408 >>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3DError = >accessing >>>>> memory address 0x8000ffffd008: Bad address. >>>>> ) at ../src/runtime/common/RTLinker.m3:115 >>>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3DError = >accessing >>>>> memory address 0x8000ffffd028: Bad address. >>>>> ) at ../src/runtime/common/RTLinker.m3:124 >>>>> #15 0x00000000004004a6 in main (argc=3DError accessing memory = >address >>>>> 0x8000ffffd07c: Bad address. >>>>> ) at _m3main.c:22 >>>>>=20 >>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): >>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>> #1 0x0000000000477e8a in check_suspend () >>>>> #2 0x00000000004780a2 in sigcancel_handler () >>>>> #3 >>>>> #4 0x000000000047e53c in _umtx_op_err () >>>>> #5 0x0000000000475f14 in __thr_umutex_lock () >>>>> #6 0x0000000000479404 in mutex_lock_common () >>>>> #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >(mutex=3DError >>>>> accessing memory address 0x8000ff5fac18: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>> #8 0x000000000044d039 in RTOS__LockHeap () at >>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>> #9 0x000000000042ff79 in RTAllocator__AllocTraced >>>>> (M3_Cwb5VA_dataSize=3DError accessing memory address = >0x8000ff5fac88: Bad >>>>> address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray = >(M3_Eic7CK_def=3DError >>>>> accessing memory address 0x8000ff5fad48: Bad address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>> (M3_AJWxb1_defn=3DError accessing memory address 0x8000ff5fada8: = >Bad address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3DError = >accessing >>>>> memory address 0x8000ff5fade8: Bad address. >>>>> ) at ../src/Main.m3:283 >>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3DError >>>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000ff5faf68: = >Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>> #15 0x000000000047c7d4 in thread_start () >>>>> #16 0x0000000000000000 in ?? () >>>>>=20 >>>>> (others are similar) >>>>>=20 >>>>> Hmm looks like a FreeBSD issue now. It's here... >>>>>=20 >>>>> int >>>>> __cdecl >>>>> ThreadPThread__SuspendThread (m3_pthread_t mt) >>>>> { >>>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), >>>>> "pthread_suspend_np"); >>>>> return 1; >>>>> } >>>>>=20 >>>>> Now this suspend can wait: >>>>>=20 >>>>> static int >>>>> suspend_common(struct pthread *curthread, struct pthread *thread, >>>>> int waitok) >>>>> { >>>>> uint32_t tmp; >>>>>=20 >>>>> while (thread->state !=3D PS_DEAD && >>>>> !(thread->flags & THR_FLAGS_SUSPENDED)) { >>>>> thread->flags |=3D THR_FLAGS_NEED_SUSPEND; >>>>> /* Thread is in creation. */ >>>>> if (thread->tid =3D=3D TID_TERMINATED) >>>>> return (1); >>>>> tmp =3D thread->cycle; >>>>> _thr_send_sig(thread, SIGCANCEL); >>>>> THR_THREAD_UNLOCK(curthread, thread); >>>>> if (waitok) { >>>>> _thr_umtx_wait_uint(&thread->cycle, tmp, = >NULL, >>>>> 0); <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>>> THR_THREAD_LOCK(curthread, thread); >>>>> } else { >>>>> THR_THREAD_LOCK(curthread, thread); >>>>> return (0); >>>>> } >>>>> } >>>>>=20 >>>>> return (1); >>>>> } >>>>>=20 >>>>> ... but what it can wait for I am not clear on. >>>>>=20 >>>>> Do things work better on Linux? >>>>>=20 >>>>> What is the status of the fork bug? Can it be worked around by = >only >>>>> forking via Process.Create with no mutexes held (outside of all = >LOCK >>>>> blocks)? >>>>>=20 >>>>> Mika >>>>>=20 >>>>>=20 >>>>>=20 >>>>> Peter McKinna writes: >>>>>> --001a11c2ced4471a2e050079db82 >>>>>> Content-Type: text/plain; charset=3DUTF-8 >>>>>>=20 >>>>>> Mika >>>>>>=20 >>>>>> I think you need to back out Tony's changes to fix the fork bug, = >at >>>>> least >>>>>> for now. Need to reload from cvs version 1.262 for = >ThreadPThread.m3 If >>>>>> you're using git you're on your own. >>>>>> Do a cvs log ThreadPThread.m3 for an explanation for some of the = >design >>>>>> principles. >>>>>> Also if you use gdb then you need to set lanc c before backtraces = >so at >>>>>> least you can see address names and values even if they are = >contorted you >>>>>> can extract the M3 name in the parm lists. Also in gdb thread = >apply all >>>>> bt >>>>>> gives all thread backtraces which can be handy to see whose got = >the locks >>>>>> held. >>>>>>=20 >>>>>> Regards Peter >>>>>>=20 >>>>>>=20 >>>>>>=20 >>>>>> On Wed, Aug 13, 2014 at 12:14 PM, wrote: >>>>>>=20 >>>>>>>=20 >>>>>>> Question... is there something odd about my pthreads? Are = >pthreads >>>>>>> normally reentrant? I didn't think so. >>>>>>>=20 >>>>>>> My compiler is much happier with the following changes I already >>>>> outlined: >>>>>>>=20 >>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >going >>>>> from >>>>>>> XWait with self.mutex locked to m.release(). >>>>>>>=20 >>>>>>> 2. the change to LockHeap I described in previous email >>>>>>>=20 >>>>>>> But now... >>>>>>>=20 >>>>>>> (gdb) cont >>>>>>> Continuing. >>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>=20 >>>>>>> Program received signal SIGABRT, Aborted. >>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>> (gdb) where >>>>>>> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >>>>>>> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock >>>>> (mutex=3DError >>>>>>> accessing memory address 0x8000ffffb508: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >>>>>>> #3 0x000000000071d48d in RTOS__LockHeap () at >>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >>>>>>> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>>> (M3_Af40ku_ref=3DError >>>>>>> accessing memory address 0x8000ffffb568: Bad address. >>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234 >>>>>>> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >>>>>>> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >>>>>>> #7 0x000000000070dd8b in RTProcess__Fork () at >>>>>>> ../src/runtime/common/RTProcessC.c:152 >>>>>>> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>>>>>> (M3_Bd56fi_cmd=3DError accessing memory address 0x8000ffffb6f8: = >Bad >>>>> address. >>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >>>>>>> #9 0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DError >>>>> accessing >>>>>>> memory address 0x8000ffffb7f8: Bad address. >>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21 >>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>> (M3_D6rRrg_ep=3DError >>>>>>> accessing memory address 0x8000ffffb838: Bad address. >>>>>>> ) at ../src/QMachine.m3:1666 >>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand = >(M3_An02H2_t=3DError >>>>>>> accessing memory address 0x8000ffffb9f8: Bad address. >>>>>>> ) at ../src/QMachine.m3:1605 >>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError >>>>> accessing >>>>>>> memory address 0x8000ffffbee8: Bad address. >>>>>>> ) at ../src/QMachine.m3:1476 >>>>>>>=20 >>>>>>> What am I doing wrong here? >>>>>>>=20 >>>>>>> The error doesn't look unreasonable! Looking more closely at the = >code: >>>>>>>=20 >>>>>>> First, AtForkPrepare has been called: >>>>>>>=20 >>>>>>> PROCEDURE AtForkPrepare() =3D >>>>>>> VAR me :=3D GetActivation(); >>>>>>> act: Activation; >>>>>>> BEGIN >>>>>>> PThreadLockMutex(slotsMu, ThisLine()); >>>>>>> PThreadLockMutex(perfMu, ThisLine()); >>>>>>> PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D> >>>>>>> RegisterFinalCleanup =3D> LockHeap *) >>>>>>> PThreadLockMutex(heapMu, ThisLine()); >>>>>>> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap =3D> >>>>> SuspendOthers >>>>>>> =3D> activeMu *) >>>>>>> (* Walk activations and lock all threads. >>>>>>> * NOTE: We have initMu, activeMu, so slots won't change, >>>>> conditions >>>>>>> and >>>>>>> * mutexes won't be initialized on-demand. >>>>>>> *) >>>>>>> act :=3D me; >>>>>>> REPEAT >>>>>>> PThreadLockMutex(act.mutex, ThisLine()); >>>>>>> act :=3D act.next; >>>>>>> UNTIL act =3D me; >>>>>>> END AtForkPrepare; >>>>>>>=20 >>>>>>> a postcondition of this routine is that heapMu is locked. >>>>>>>=20 >>>>>>> now we get into AtForkParent: >>>>>>>=20 >>>>>>> PROCEDURE AtForkParent() =3D >>>>>>> VAR me :=3D GetActivation(); >>>>>>> act: Activation; >>>>>>> cond: Condition; >>>>>>> BEGIN >>>>>>> (* Walk activations and unlock all threads, conditions. *) >>>>>>> act :=3D me; >>>>>>> REPEAT >>>>>>> cond :=3D slots[act.slot].join; >>>>>>> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, = >ThisLine()) >>>>> END; >>>>>>> PThreadUnlockMutex(act.mutex, ThisLine()); >>>>>>> act :=3D act.next; >>>>>>> UNTIL act =3D me; >>>>>>> PThreadUnlockMutex(activeMu, ThisLine()); >>>>>>> PThreadUnlockMutex(heapMu, ThisLine()); >>>>>>> PThreadUnlockMutex(initMu, ThisLine()); >>>>>>> PThreadUnlockMutex(perfMu, ThisLine()); >>>>>>> PThreadUnlockMutex(slotsMu, ThisLine()); >>>>>>> END AtForkParent; >>>>>>>=20 >>>>>>> We can see by inspecting the code that a necessary precondition = >for >>>>>>> this routine is that heapMu is locked! (Since it's going to = >unlock it, >>>>>>> it had BETTER be locked on entry.) >>>>>>>=20 >>>>>>> But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef >>>>>>>=20 >>>>>>> which causes an RTOS.LockHeap >>>>>>>=20 >>>>>>> the code of which we just saw: >>>>>>>=20 >>>>>>> PROCEDURE LockHeap () =3D >>>>>>> VAR self :=3D pthread_self(); >>>>>>> BEGIN >>>>>>> WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT = >r=3D0*> >>>>> END; >>>>>>> ... >>>>>>>=20 >>>>>>> we try to lock heapMu. kaboom! No surprise there, really? >>>>>>>=20 >>>>>>> Am I going about this totally the wrong way? Other people are = >running >>>>>>> Modula-3 >>>>>>> with pthreads, right? Right?? Somewhere out there in = >m3devel-land? >>>>>>>=20 >>>>>>> Mika >>>>>>>=20 >>>>>>>=20 >>>>>>=20 >>>>>> --001a11c2ced4471a2e050079db82 >>>>>> Content-Type: text/html; charset=3DUTF-8 >>>>>> Content-Transfer-Encoding: quoted-printable >>>>>>=20 >>>>>>
Mika

=3DC2=3DA0 I think you = >need to back >>>>> ou=3D >>>>>> t Tony's changes to fix the fork bug, at least for now. Need = >to >>>>> reload =3D >>>>>> from cvs version 1.262 for ThreadPThread.m3 If you're using = >git >>>>> you'=3D >>>>>> ;re on your own.
>>>>>>=20 >>>>>>
=3DC2=3DA0 Do a cvs log ThreadPThread.m3 for an explanation = >for some of >>>>> th=3D >>>>>> e design principles.=3DC2=3DA0
=3DC2=3DA0 Also if you = >use gdb then you >>>>> ne=3D >>>>>> ed to set lanc c before backtraces so at least you can see address = >names >>>>> an=3D >>>>>> d values even if they are contorted you can extract the M3 name in = >the >>>>> parm=3D >>>>>> lists. Also in gdb thread apply all bt gives all thread backtraces >>>>> which c=3D >>>>>> an be handy to see whose got the locks held.
>>>>>>=20 >>>>>>

Regards Peter

>>>> class=3D3D"gmail_e=3D >>>>>> xtra">

On Wed, Aug 13, 2014 at = >12:14 >>>>> PM, =3D >>>>>> <>>>> target=3D3D"=3D >>>>>> _blank">mika at async.caltech.edu> wrote:
>>>>>>=20 >>>>>>
>>>> .8ex;border-left:1p=3D >>>>>> x #ccc solid;padding-left:1ex">
>>>>>> Question... is there something odd about my pthreads? =3DC2=3DA0Are = >pthreads >>>>> no=3D >>>>>> rmally reentrant? =3DC2=3DA0I didn't think so.
>>>>>>
>>>>>> My compiler is much happier with the following changes I already >>>>> outlined:<=3D >>>>>> br> >>>>>>
>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >going >>>>> from =3D >>>>>> XWait with self.mutex locked to m.release().
>>>>>>
>>>>>> 2. the change to LockHeap I described in previous email
>>>>>>
>>>>>> But now...
>>>>>>
>>>>>> (gdb) cont
>>>>>> Continuing.
>>>>>> ERROR: pthread_mutex_lock:11
>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>
>>>>>> Program received signal SIGABRT, Aborted.
>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>>> (gdb) where
>>>>>> #0 =3DC2=3DA00x000000080107626a in thr_kill () from = >/lib/libc.so.7
>>>>>> #1 =3DC2=3DA00x000000080113dac9 in abort () from = >/lib/libc.so.7
>>>>>> #2 =3DC2=3DA00x000000000071e37a in = >ThreadPThread__pthread_mutex_lock >>>>> (mutex=3D3DE=3D >>>>>> rror accessing memory address 0x8000ffffb508: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>>> #3 =3DC2=3DA00x000000000071d48d in RTOS__LockHeap () at >>>>> ../src/thread/PTHREAD/T=3D >>>>>> hreadPThread.m3:1377
>>>>>> #4 =3DC2=3DA00x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>>> (M3_Af40ku_ref=3D >>>>>> =3D3DError accessing memory address 0x8000ffffb568: Bad = >address.
>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>>> #5 =3DC2=3DA00x000000000071d284 in ThreadPThread__AtForkParent () = >at >>>>> ../src/thr=3D >>>>>> ead/PTHREAD/ThreadPThread.m3:1348
>>>>>> #6 =3DC2=3DA00x0000000800df8733 in fork () from = >/lib/libthr.so.3
>>>>>> #7 =3DC2=3DA00x000000000070dd8b in RTProcess__Fork () at >>>>> ../src/runtime/common/=3D >>>>>> RTProcessC.c:152
>>>>>> #8 =3DC2=3DA00x00000000006c52f2 in = >ProcessPosixCommon__Create_ForkExec >>>>> (M3_Bd56=3D >>>>>> fi_cmd=3D3DError accessing memory address 0x8000ffffb6f8: Bad = >address.
>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>>> #9 =3DC2=3DA00x00000000006c6c6c in Process__Create = >(M3_Bd56fi_cmd=3D3DError >>>>> acces=3D >>>>>> sing memory address 0x8000ffffb7f8: Bad address.
>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>> (M3_D6rRrg_ep=3D3DError=3D >>>>>> accessing memory address 0x8000ffffb838: Bad address.
>>>>>> ) at ../src/QMachine.m3:1666
>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand = >(M3_An02H2_t=3D3DError >>>>> access=3D >>>>>> ing memory address 0x8000ffffb9f8: Bad address.
>>>>>> ) at ../src/QMachine.m3:1605
>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3D3DError= > >>>>> accessin=3D >>>>>> g memory address 0x8000ffffbee8: Bad address.
>>>>>> ) at ../src/QMachine.m3:1476
>>>>>>
>>>>>> What am I doing wrong here?
>>>>>>
>>>>>> The error doesn't look unreasonable! =3DC2=3DA0Looking more = >closely at >>>>> the =3D >>>>>> code:
>>>>>>
>>>>>> First, AtForkPrepare has been called:
>>>>>>
>>>>>> PROCEDURE AtForkPrepare() =3D3D
>>>>>> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>>>>> =3DC2=3DA0 BEGIN
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(slotsMu, ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(perfMu, ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(initMu, ThisLine()); (* = >InitMutex =3D3D> >>>>> Re=3D >>>>>> gisterFinalCleanup =3D3D> LockHeap *)
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(heapMu, ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(activeMu, ThisLine()); (* = >LockHeap >>>>> =3D3D> S=3D >>>>>> uspendOthers =3D3D> activeMu *)
>>>>>> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and lock all = >threads.
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* NOTE: We have initMu, activeMu, = >so slots won't >>>>> ch=3D >>>>>> ange, conditions and
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* mutexes won't be initialized = >on-demand.
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0*)
>>>>>> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(act.mutex, = >ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>>>>> =3DC2=3DA0 END AtForkPrepare;
>>>>>>
>>>>>> a postcondition of this routine is that heapMu is locked.
>>>>>>
>>>>>> now we get into AtForkParent:
>>>>>>
>>>>>> PROCEDURE AtForkParent() =3D3D
>>>>>> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond: Condition;
>>>>>> =3DC2=3DA0 BEGIN
>>>>>> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and unlock all threads, = >conditions. >>>>> *)>>>>>>=20 >>>>>> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond :=3D3D = >slots[act.slot].join;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 IF cond # NIL THEN = >PThreadUnlockMutex(cond.mutex, >>>>> This=3D >>>>>> Line()) END;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(act.mutex, = >ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(activeMu, = >ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(heapMu, ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(initMu, ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(perfMu, ThisLine());
>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(slotsMu, ThisLine());
>>>>>> =3DC2=3DA0 END AtForkParent;
>>>>>>
>>>>>> We can see by inspecting the code that a necessary precondition = >for
>>>>>> this routine is that heapMu is locked! =3DC2=3DA0(Since it's = >going to >>>>> unloc=3D >>>>>> k it,
>>>>>> it had BETTER be locked on entry.)
>>>>>>
>>>>>> But the cond :=3D3D ... causes a RTHooks.CheckLoadTracedRef
>>>>>>
>>>>>> which causes an RTOS.LockHeap
>>>>>>
>>>>>> the code of which we just saw:
>>>>>>
>>>>>> PROCEDURE LockHeap () =3D3D
>>>>>> =3DC2=3DA0 VAR self :=3D3D pthread_self();
>>>>>> =3DC2=3DA0 BEGIN
>>>>>> =3DC2=3DA0 =3DC2=3DA0 WITH r =3D3D = >pthread_mutex_lock(heapMu,ThisLine()) DO >>>>> <*ASSE=3D >>>>>> RT r=3D3D0*> END;
>>>>>> ...
>>>>>>
>>>>>> we try to lock heapMu. =3DC2=3DA0kaboom! =3DC2=3DA0No surprise = >there, really?
>>>>>>
>>>>>> Am I going about this totally the wrong way? =3DC2=3DA0Other = >people are >>>>> running=3D >>>>>> Modula-3
>>>>>> with pthreads, right? =3DC2=3DA0Right?? =3DC2=3DA0Somewhere out = >there in >>>>> m3devel-la=3D >>>>>> nd?
>>>>>>
>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika
>>>>>>
>>>>>>

>>>>>>=20 >>>>>> --001a11c2ced4471a2e050079db82-- >>>>>=20 >>>>=20 >>>>=20 >>>=20 >>> --089e01183a1813188705007c3498 >>> Content-Type: text/html; charset=3DUTF-8 >>> Content-Transfer-Encoding: quoted-printable >>>=20 >>>
Oh, one other thing that seemed to help me in = >testing this=3D >>> stuff especially things to do with m3core and libm3 which seem to get = >out =3D >>> of whack sometimes, is to totally remove the target directory of = >m3core the=3D >>> n cm3; cm3 -ship Same with libm3. I'm not sure that clean = >actually remo=3D >>> ves the targets and I think there are leftover files that stuff = >things up s=3D >>> ince I would get segv in FileRd for no obvious reason.
>>>
Peter

class=3D3D"gmail_extra"><=3D >>> br>
On Wed, Aug 13, 2014 at 3:33 PM, = >Peter Mc=3D >>> Kinna <href=3D3D"mailto:peter.mckinna at gmail.com" targ=3D >>> et=3D3D"_blank">peter.mckinna at gmail.com> wrote:
>>>
.8ex;border-left:1p=3D >>> x #ccc solid;padding-left:1ex">
That is weird. The = >thread t=3D >>> ester works fine with the old version of ThreadPThread.m3 on linux = >amd_64 e=3D >>> xcept if you have the fork test in the mix of tests you see the = >pthread_mut=3D >>> ex_destroy every now and again, the fork bug in fact.=3DC2=3DA0
>>>=20 >>> I was testing the pthread changes Tony has made over the past few = >days usin=3D >>> g the thread tester program until I stupidly rebuilt the compiler and = >was g=3D >>> etting all sorts of hangs as it dragged in the new version of = >pthreads. So =3D >>> I rebuilt everything from a backup to get back where I was with a = >decent co=3D >>> mpiler, then reintroduced the latest changes to ThreadPThread.m3, = >which yes=3D >>> terday was just hanging in sigsuspend but today is giving me an = >assert fail=3D >>> ure at line 1387 in UnlockHeap. So its a bit unstable to say the = >least. May=3D >>> be there is something else wrong with freebsd.
>>> >>> = >

Peter

clas=3D >>> s=3D3D"HOEnZb">
class=3D3D"gmail_extra">

>> s=3D3D"gmail_quote">On Wed, Aug 13, 2014 at 2:54 PM, dir=3D3D"ltr"><<=3D >>> a href=3D3D"mailto:mika at async.caltech.edu" = >target=3D3D"_blank">mika at async.calte=3D >>> ch.edu> wrote:
>>>=20 >>>
.8ex;border-left:1p=3D >>> x #ccc solid;padding-left:1ex">
>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not = >getting>>>=20 >>> things to work and now I'm really baffled because I think I = >understand<=3D >>> br> >>> this code!
>>>
>>> What I did was I threw away all my changes and reverted = >ThreadPThread.m3>>>=20 >>> to 1.262 as you suggested.
>>>
>>> Rebuilt the compiler with upgrade.sh
>>>
>>> Then rebuilt the compiler again with itself.
>>>
>>> Then I realcleaned the world and buildshipped it. =3DC2=3DA0(I was = >afraid
>>> that parseparams, also imported by the thread tester, would = >pollute
>>> it somehow.)
>>>
>>> When I look at the code in 1.262 it looks quite straightforward. = >=3DC2=3DA0heap=3D >>> Mu
>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. = >=3DC2=3DA0Cond=3D >>> ition
>>> variables are mutexes too, but that's no big deal.
>>>
>>> So, rebuild thread tester, run it:
>>>
>>> new source -> compiling Main.m3
>>> =3DC2=3DA0-> linking threadtest
>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # = >AMD64_FREEB=3D >>> SD/threadtest
>>> Writing file...done
>>> Creating read threads...done
>>> Creating fork threads...done
>>> Creating alloc threads...done
>>> Creating lock threads...done
>>> running...printing oldest/median age/newest
>>> .
>>>
>>> ***
>>> *** runtime error:
>>> *** =3DC2=3DA0 =3DC2=3DA0Segmentation violation - possible attempt to = >dereference N=3D >>> IL.........laziest thread is 1407901189/href=3D3D"tel:1407901189%2F9" valu=3D >>> e=3D3D"+14079011899" target=3D3D"_blank">1407901189/9 (tests: = >read 14079011=3D >>> 89/1407901189/1407901189 fork 1407901189/1407901189/1407901189 alloc = >9/9/9 =3D >>> lock 1407901189/1407901189/9)
>>>=20 >>>=20 >>>
>>>
>>>
>>>
>>> ^C
>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb = >!$
>>> gdb AMD64_FREEBSD/threadtest
>>> GNU gdb 6.1.1 [FreeBSD]
>>> Copyright 2004 Free Software Foundation, Inc.
>>> GDB is free software, covered by the GNU General Public License, and = >you ar=3D >>> e
>>> welcome to change it and/or distribute copies of it under certain = >condition=3D >>> s.
>>> Type "show copying" to see the conditions.
>>> There is absolutely no warranty for GDB. =3DC2=3DA0Type "show = >warranty&quo=3D >>> t; for details.
>>> This GDB was configured as "amd64-marcel-freebsd"...
>>> (gdb) run
>>> Starting program: = >/big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread=3D >>> /AMD64_FREEBSD/threadtest
>>> [New LWP 100121]
>>> Writing file...done
>>> Creating read threads...done
>>> Creating fork threads...done
>>> Creating alloc threads...done
>>> Creating lock threads...done
>>> running...printing oldest/median age/newest
>>> .[New Thread 801807000 (LWP 100343/threadtest)]
>>> [New Thread 801807c00 (LWP 100667/threadtest)]
>>> [New Thread 801808800 (LWP 100816/threadtest)]
>>> [New Thread 801807400 (LWP 100349/threadtest)]
>>> [New Thread 801808400 (LWP 100815/threadtest)]
>>> [New Thread 801807800 (LWP 100352/threadtest)]
>>> [New Thread 801808c00 (LWP 100817/threadtest)]
>>> [New Thread 801809000 (LWP 100818/threadtest)]
>>> [New Thread 801809800 (LWP 100820/threadtest)]
>>> [New Thread 801808000 (LWP 100678/threadtest)]
>>> [New Thread 801806400 (LWP 100121/threadtest)]
>>> [New Thread 801806800 (LWP 100341/threadtest)]
>>> [New Thread 801806c00 (LWP 100342/threadtest)]
>>> .ERROR: pthread_mutex_lock:11
>>>

>>> Program received signal SIGABRT, Aborted.
>>>
[Switching to Thread 801809800 (LWP 100820/threadtest)]
>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>>> (gdb) where
>>> #0 =3DC2=3DA00x0000000800d5c26a in thr_kill () from = >/lib/libc.so.7
>>> #1 =3DC2=3DA00x0000000800e23ac9 in abort () from /lib/libc.so.7
>>> #2 =3DC2=3DA00x000000000045101f in ThreadPThread__pthread_mutex_lock = >(mutex=3D3DE=3D >>> rror accessing memory address 0x8000fe5f2d98: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
>>> #3 =3DC2=3DA00x000000000044b370 in ThreadPThread__LockMutex = >(M3_AYIbX3_m=3D3DErro=3D >>> r accessing memory address 0x8000fe5f2dc8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>> #4 =3DC2=3DA00x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3D3DError= > accessing=3D >>> memory address 0x8000fe5f2df8: Bad address.
>>> ) at ../src/Main.m3:319
>>> #5 =3DC2=3DA00x000000000044d243 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3D3DErr=3D >>> or accessing memory address 0x8000fe5f2eb8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>> #6 =3DC2=3DA00x000000000044cf00 in ThreadPThread__ThreadBase = >(M3_AJWxb1_param=3D >>> =3D3DError accessing memory address 0x8000fe5f2f68: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>> #7 =3DC2=3DA00x0000000800ad54a4 in pthread_create () from = >/lib/libthr.so.3
>>> #8 =3DC2=3DA00x0000000000000000 in ?? ()
>>> (gdb) set lang c
>>> (gdb) thread apply all bt
>>> ... not that interesting ...
>>>
>>> Segfault is segfault---error 11 is EDEADLK (locking against = >myself?)
>>>
>>> ????? the code is very straightforward, as I said.
>>>
>>> I thought people had the thread tester working with pthreads? = >=3DC2=3DA0Which s=3D >>> et of files, then? =3DC2=3DA0Anyone on FreeBSD/amd64?
>>>
>>> Could it be an issue with "volatile"? =3DC2=3DA0Not even = >sure where t=3D >>> o look.
>>>
>>> The code calling the lock is just this:
>>>
>>> PROCEDURE GetChar (rd: T): CHAR
>>> =3DC2=3DA0 RAISES {EndOfFile, Failure, Alerted} =3D3D
>>> =3DC2=3DA0 BEGIN
>>> =3DC2=3DA0 =3DC2=3DA0 LOCK rd DO
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 RETURN FastGetChar(rd);
>>> =3DC2=3DA0 =3DC2=3DA0 END
>>> =3DC2=3DA0 END GetChar;
>>>
>>> No mysteries there...
>>>
>>> Ah is this the fork bug? =3DC2=3DA0Looks like the Init routine is = >called on a>> r> >>> lot of NIL mutexes around the fork. =3DC2=3DA0But the subprocesses = >aren't m=3D >>> eant
>>> to accesses the mutexes... humm
>>>
>>> Hmm, and it's not entirely a fork issue. =3DC2=3DA0Even with = >"threadte=3D >>> st -tests STD,-fork,-forktoomuch" it misbehaves. = >=3DC2=3DA0Hangs....
>>>
>>> Looks like a deadlock this time.
>>>
>>> Some stacks...
>>>
>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
>>> #0 =3DC2=3DA00x00000000004b4e2b in __vdso_gettimeofday ()
>>> #1 =3DC2=3DA00x00000000004ab8d2 in gettimeofday ()
>>> #2 =3DC2=3DA00x0000000000452e4b in TimePosix__Now () at = >../src/time/POSIX/TimeP=3D >>> osixC.c:50
>>> #3 =3DC2=3DA00x0000000000452d72 in Time__Now () at = >../src/time/POSIX/TimePosix.=3D >>> m3:14
>>> #4 =3DC2=3DA00x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3D3DError= > accessing=3D >>> memory address 0x8000fedf6df8: Bad address.
>>> ) at ../src/Main.m3:327
>>> #5 =3DC2=3DA00x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3D3DErr=3D >>> or accessing memory address 0x8000fedf6eb8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>> #6 =3DC2=3DA00x0000000000449c50 in ThreadPThread__ThreadBase = >(M3_AJWxb1_param=3D >>> =3D3DError accessing memory address 0x8000fedf6f68: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>> #7 =3DC2=3DA00x000000000047c7d4 in thread_start ()
>>> #8 =3DC2=3DA00x0000000000000000 in ?? ()
>>>
>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>> #1 =3DC2=3DA00x0000000000475f14 in __thr_umutex_lock ()
>>> #2 =3DC2=3DA00x0000000000479404 in mutex_lock_common ()
>>> #3 =3DC2=3DA00x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >(mutex=3D3DE=3D >>> rror accessing memory address 0x8000feff7d98: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>> #4 =3DC2=3DA00x00000000004480c0 in ThreadPThread__LockMutex = >(M3_AYIbX3_m=3D3DErro=3D >>> r accessing memory address 0x8000feff7dc8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>> #5 =3DC2=3DA00x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3D3DError= > accessing=3D >>> memory address 0x8000feff7df8: Bad address.
>>> ) at ../src/Main.m3:319
>>> #6 =3DC2=3DA00x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3D3DErr=3D >>> or accessing memory address 0x8000feff7eb8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>> #7 =3DC2=3DA00x0000000000449c50 in ThreadPThread__ThreadBase = >(M3_AJWxb1_param=3D >>> =3D3DError accessing memory address 0x8000feff7f68: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>> #8 =3DC2=3DA00x000000000047c7d4 in thread_start ()
>>> #9 =3DC2=3DA00x0000000000000000 in ?? ()
>>>
>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>> #1 =3DC2=3DA00x0000000000475759 in suspend_common ()
>>> #2 =3DC2=3DA00x00000000004755c1 in pthread_suspend_np ()
>>> #3 =3DC2=3DA00x000000000044df0c in ThreadPThread__SuspendThread = >(mt=3D3DError acc=3D >>> essing memory address 0x8000ffbfd6f8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
>>> #4 =3DC2=3DA00x000000000044bade in ThreadPThread__StopThread = >(M3_DMxDjQ_act=3D3DE=3D >>> rror accessing memory address 0x8000ffbfd718: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909
>>> #5 =3DC2=3DA00x000000000044bc81 in ThreadPThread__StopWorld () at = >../src/thread=3D >>> /PTHREAD/ThreadPThread.m3:948
>>> #6 =3DC2=3DA00x000000000044b19e in RTThread__SuspendOthers () at = >../src/thread/=3D >>> PTHREAD/ThreadPThread.m3:713
>>> #7 =3DC2=3DA00x00000000004330d6 in = >RTCollector__CollectSomeInStateZero () at ..=3D >>> /src/runtime/common/RTCollector.m3:749
>>> #8 =3DC2=3DA00x0000000000433081 in RTCollector__CollectSome () at = >../src/runtim=3D >>> e/common/RTCollector.m3:723
>>> #9 =3DC2=3DA00x0000000000432d49 in RTHeapRep__CollectEnough () at = >../src/runtim=3D >>> e/common/RTCollector.m3:657
>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced = >(M3_Cwb5VA_dataSize=3D3DEr=3D >>> ror accessing memory address 0x8000ffbfd958: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:367
>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray = >(M3_Eic7CK_def=3D3DError =3D >>> accessing memory address 0x8000ffbfda18: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray = >(M3_AJWxb1_defn=3D3DErro=3D >>> r accessing memory address 0x8000ffbfda78: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3DError = >accessing memo=3D >>> ry address 0x8000ffbfdab8: Bad address.
>>> ) at ../src/rw/Rd.m3:159
>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=3D3DError= > acces=3D >>> sing memory address 0x8000ffbfdb88: Bad address.
>>> ) at ../src/rw/Rd.m3:187
>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3DError = >accessing memor=3D >>> y address 0x8000ffbfdbd8: Bad address.
>>> ) at ../src/rw/Rd.m3:176
>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3DError = >accessing memo=3D >>> ry address 0x8000ffbfdc58: Bad address.
>>> ) at ../src/Main.m3:185
>>>
>>> #17 0x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3D3DError ac=3D >>> cessing memory address 0x8000ffbfdeb8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase = >(M3_AJWxb1_param=3D3DErro=3D >>> r accessing memory address 0x8000ffbfdf68: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>> #19 0x000000000047c7d4 in thread_start ()
>>> #20 0x0000000000000000 in ?? ()
>>>
>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>> #1 =3DC2=3DA00x0000000000475f14 in __thr_umutex_lock ()
>>> #2 =3DC2=3DA00x0000000000479404 in mutex_lock_common ()
>>> #3 =3DC2=3DA00x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >(mutex=3D3DE=3D >>> rror accessing memory address 0x8000ffffc678: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>> #4 =3DC2=3DA00x000000000044d039 in RTOS__LockHeap () at = >../src/thread/PTHREAD/T=3D >>> hreadPThread.m3:1337
>>> ---Type <return> to continue, or q <return> to = >quit---
>>> #5 =3DC2=3DA00x000000000042ff79 in RTAllocator__AllocTraced = >(M3_Cwb5VA_dataSize=3D >>> =3D3DError accessing memory address 0x8000ffffc6e8: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>> #6 =3DC2=3DA00x000000000042f15b in RTAllocator__GetTracedObj = >(M3_Eic7CK_def=3D3DE=3D >>> rror accessing memory address 0x8000ffffc7a8: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:224
>>> #7 =3DC2=3DA00x000000000042eb23 in RTHooks__AllocateTracedObj = >(M3_AJWxb1_defn=3D >>> =3D3DError accessing memory address 0x8000ffffc7f8: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:122
>>> #8 =3DC2=3DA00x000000000045fbe4 in TextCat__Flat = >(M3_Bd56fi_LText=3D3DError acces=3D >>> sing memory address 0x8000ffffc858: Bad address.
>>> ) at ../src/text/TextCat.m3:562
>>> #9 =3DC2=3DA00x000000000045ed5d in TextCat__Balance = >(M3_Bd56fi_LText=3D3D0x800c49=3D >>> 0b0, M3_BUgnwf_LInfo=3D3DError accessing memory address = >0x8000ffffc8f8: Bad a=3D >>> ddress.
>>> ) at ../src/text/TextCat.m3:488
>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3D3DError = >accessing me=3D >>> mory address 0x8000ffffcbb8: Bad address.
>>> ) at ../src/text/TextCat.m3:40
>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3DError accessing = >memory =3D >>> address 0x8000ffffcc38: Bad address.
>>> ) at ../src/Main.m3:593
>>> #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=3D3DError = >access=3D >>> ing memory address 0x8000ffffcf88: Bad address.
>>> ) at ../src/runtime/common/RTLinker.m3:408
>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3D3DError = >accessing=3D >>> memory address 0x8000ffffd008: Bad address.
>>> ) at ../src/runtime/common/RTLinker.m3:115
>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3D3DError = >accessing =3D >>> memory address 0x8000ffffd028: Bad address.
>>> ) at ../src/runtime/common/RTLinker.m3:124
>>> #15 0x00000000004004a6 in main (argc=3D3DError accessing memory = >address 0x800=3D >>> 0ffffd07c: Bad address.
>>> ) at _m3main.c:22
>>>
>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>> #1 =3DC2=3DA00x0000000000477e8a in check_suspend ()
>>> #2 =3DC2=3DA00x00000000004780a2 in sigcancel_handler ()
>>> #3 =3DC2=3DA0<signal handler called>
>>> #4 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>> #5 =3DC2=3DA00x0000000000475f14 in __thr_umutex_lock ()
>>> #6 =3DC2=3DA00x0000000000479404 in mutex_lock_common ()
>>> #7 =3DC2=3DA00x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >(mutex=3D3DE=3D >>> rror accessing memory address 0x8000ff5fac18: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>> #8 =3DC2=3DA00x000000000044d039 in RTOS__LockHeap () at = >../src/thread/PTHREAD/T=3D >>> hreadPThread.m3:1337
>>> #9 =3DC2=3DA00x000000000042ff79 in RTAllocator__AllocTraced = >(M3_Cwb5VA_dataSize=3D >>> =3D3DError accessing memory address 0x8000ff5fac88: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray = >(M3_Eic7CK_def=3D3DError =3D >>> accessing memory address 0x8000ff5fad48: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray = >(M3_AJWxb1_defn=3D3DErro=3D >>> r accessing memory address 0x8000ff5fada8: Bad address.
>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3DError = >accessing memo=3D >>> ry address 0x8000ff5fade8: Bad address.
>>> ) at ../src/Main.m3:283
>>> #13 0x0000000000449f93 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3D3DError ac=3D >>> cessing memory address 0x8000ff5faeb8: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase = >(M3_AJWxb1_param=3D3DErro=3D >>> r accessing memory address 0x8000ff5faf68: Bad address.
>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>> #15 0x000000000047c7d4 in thread_start ()
>>> #16 0x0000000000000000 in ?? ()
>>>
>>> (others are similar)
>>>
>>> Hmm looks like a FreeBSD issue now. =3DC2=3DA0It's here...
>>>
>>> int
>>> __cdecl
>>> ThreadPThread__SuspendThread (m3_pthread_t mt)
>>> {
>>> =3DC2=3DA0 = >ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), "=3D >>> pthread_suspend_np");
>>> =3DC2=3DA0 return 1;
>>> }
>>>
>>> Now this suspend can wait:
>>>
>>> static int
>>> suspend_common(struct pthread *curthread, struct pthread *thread,
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 int waitok)
>>> {
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 uint32_t tmp;
>>>
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 while (thread->state = >!=3D3D PS_DEAD &&=3D >>>
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 !(thread->flags & T=3D >>> HR_FLAGS_SUSPENDED)) {
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 thread->flags |=3D >>> =3D3D THR_FLAGS_NEED_SUSPEND;
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 /* Thread is in cre=3D >>> ation. */
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 if (thread->tid =3D >>> =3D3D=3D3D TID_TERMINATED)
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>> =3DA0 =3DC2=3DA0 return (1);
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 tmp =3D3D thread->=3D >>> cycle;
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 _thr_send_sig(threa=3D >>> d, SIGCANCEL);
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 THR_THREAD_UNLOCK(c=3D >>> urthread, thread);
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 if (waitok) {
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>> =3DA0 =3DC2=3DA0 _thr_umtx_wait_uint(&thread->cycle, tmp, = >NULL, 0); =3DC2=3DA0=3D >>> <=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>> =3DA0 =3DC2=3DA0 THR_THREAD_LOCK(curthread, thread);
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 } else {
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>> =3DA0 =3DC2=3DA0 THR_THREAD_LOCK(curthread, thread);
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>> =3DA0 =3DC2=3DA0 return (0);
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >=3DC2=3DA0 =3DC2=3DA0 }
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 }
>>>
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 return (1);
>>> }
>>>
>>> ... but what it can wait for I am not clear on.
>>>
>>> Do things work better on Linux?
>>>
>>> What is the status of the fork bug? =3DC2=3DA0Can it be worked around = >by only f=3D >>> orking via Process.Create with no mutexes held (outside of all LOCK = >blocks)=3D >>> ?
>>>
>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika
>>>
>>>
>>>
>>> Peter McKinna writes:
>>> >--001a11c2ced4471a2e050079db82
>>> >Content-Type: text/plain; charset=3D3DUTF-8
>>>
>
>>> >Mika
>>> >
>>> > =3DC2=3DA0I think you need to back out Tony's changes to fix = >the fork =3D >>> bug, at least
>>> >for now. Need to reload from cvs version 1.262 for = >ThreadPThread.m3 If<=3D >>> br> >>> >you're using git you're on your own.
>>> > =3DC2=3DA0Do a cvs log ThreadPThread.m3 for an explanation for = >some of the=3D >>> design
>>> >principles.
>>> > =3DC2=3DA0Also if you use gdb then you need to set lanc c before = >backtrace=3D >>> s so at
>>> >least you can see address names and values even if they are = >contorted y=3D >>> ou
>>> >can extract the M3 name in the parm lists. Also in gdb thread = >apply all=3D >>> bt
>>> >gives all thread backtraces which can be handy to see whose got = >the loc=3D >>> ks
>>> >held.
>>> >
>>> >Regards Peter
>>> >
>>> >
>>> >
>>> >On Wed, Aug 13, 2014 at 12:14 PM, <href=3D3D"mailto:mika at async.calt=3D >>> ech.edu" target=3D3D"_blank">mika at async.caltech.edu> = >wrote:
>>> >
>>> >>
>>> >> Question... is there something odd about my pthreads? = >=3DC2=3DA0Are pt=3D >>> hreads
>>> >> normally reentrant? =3DC2=3DA0I didn't think so.
>>> >>
>>> >> My compiler is much happier with the following changes I = >already o=3D >>> utlined:
>>> >>
>>> >> 1. a dirty, disgusting hack to keep from locking against = >myself go=3D >>> ing from
>>> >> XWait with self.mutex locked to m.release().
>>> >>
>>> >> 2. the change to LockHeap I described in previous email
>>> >>
>>> >> But now...
>>> >>
>>> >> (gdb) cont
>>> >> Continuing.
>>> >> ERROR: pthread_mutex_lock:11
>>> >> ERROR: pthread_mutex_lock:11
>>> >>
>>> >> Program received signal SIGABRT, Aborted.
>>> >> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>> >> (gdb) where
>>> >> #0 =3DC2=3DA00x000000080107626a in thr_kill () from = >/lib/libc.so.7
>>> >> #1 =3DC2=3DA00x000000080113dac9 in abort () from = >/lib/libc.so.7
>>> >> #2 =3DC2=3DA00x000000000071e37a in = >ThreadPThread__pthread_mutex_lock (=3D >>> mutex=3D3DError
>>> >> accessing memory address 0x8000ffffb508: Bad address.
>>> >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>> >> #3 =3DC2=3DA00x000000000071d48d in RTOS__LockHeap () at
>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>>> >> #4 =3DC2=3DA00x0000000000706b9d in = >RTHooks__CheckLoadTracedRef (M3_Af4=3D >>> 0ku_ref=3D3DError
>>> >> accessing memory address 0x8000ffffb568: Bad address.
>>> >> ) at ../src/runtime/common/RTCollector.m3:2234
>>> >> #5 =3DC2=3DA00x000000000071d284 in = >ThreadPThread__AtForkParent () at>> r> >>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>>> >> #6 =3DC2=3DA00x0000000800df8733 in fork () from = >/lib/libthr.so.3
>>> >> #7 =3DC2=3DA00x000000000070dd8b in RTProcess__Fork () at
>>> >> ../src/runtime/common/RTProcessC.c:152
>>> >> #8 =3DC2=3DA00x00000000006c52f2 in = >ProcessPosixCommon__Create_ForkExec=3D >>>
>>> >> (M3_Bd56fi_cmd=3D3DError accessing memory address = >0x8000ffffb6f8: Ba=3D >>> d address.
>>> >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>> >> #9 =3DC2=3DA00x00000000006c6c6c in Process__Create = >(M3_Bd56fi_cmd=3D3DEr=3D >>> ror accessing
>>> >> memory address 0x8000ffffb7f8: Bad address.
>>> >> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>> >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise = >(M3_D6rRrg_e=3D >>> p=3D3DError
>>> >> accessing memory address 0x8000ffffb838: Bad address.
>>> >> ) at ../src/QMachine.m3:1666
>>> >> #11 0x00000000004d6220 in QMachine__ExecCommand = >(M3_An02H2_t=3D3DErr=3D >>> or
>>> >> accessing memory address 0x8000ffffb9f8: Bad address.
>>> >> ) at ../src/QMachine.m3:1605
>>> >> #12 0x00000000004d537e in QMachine__DoTryExec = >(M3_An02H2_t=3D3DError=3D >>> accessing
>>> >> memory address 0x8000ffffbee8: Bad address.
>>> >> ) at ../src/QMachine.m3:1476
>>> >>
>>> >> What am I doing wrong here?
>>> >>
>>> >> The error doesn't look unreasonable! =3DC2=3DA0Looking = >more closel=3D >>> y at the code:
>>> >>
>>> >> First, AtForkPrepare has been called:
>>> >>
>>> >> PROCEDURE AtForkPrepare() =3D3D
>>> >> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>> >> =3DC2=3DA0 BEGIN
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(slotsMu, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(perfMu, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(initMu, ThisLine()); = >(* InitMutex =3D >>> =3D3D>
>>> >> RegisterFinalCleanup =3D3D> LockHeap *)
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(heapMu, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(activeMu, = >ThisLine()); (* LockHeap =3D >>> =3D3D> SuspendOthers
>>> >> =3D3D> activeMu *)
>>> >> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and lock all = >threads.
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* NOTE: We have initMu, = >activeMu, so slots won=3D >>> 't change, conditions
>>> >> and
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* mutexes won't be = >initialized on-demand.<=3D >>> br> >>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0*)
>>> >> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>> >> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(act.mutex, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>> >> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>> >> =3DC2=3DA0 END AtForkPrepare;
>>> >>
>>> >> a postcondition of this routine is that heapMu is = >locked.
>>> >>
>>> >> now we get into AtForkParent:
>>> >>
>>> >> PROCEDURE AtForkParent() =3D3D
>>> >> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond: Condition;
>>> >> =3DC2=3DA0 BEGIN
>>> >> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and unlock all = >threads, conditio=3D >>> ns. *)
>>> >> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>> >> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond :=3D3D = >slots[act.slot].join;
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 IF cond # NIL THEN = >PThreadUnlockMutex(cond.mu=3D >>> tex, ThisLine()) END;
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >PThreadUnlockMutex(act.mutex, ThisLine());>>>=20 >>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>> >> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(activeMu, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(heapMu, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(initMu, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(perfMu, = >ThisLine());
>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(slotsMu, = >ThisLine());
>>> >> =3DC2=3DA0 END AtForkParent;
>>> >>
>>> >> We can see by inspecting the code that a necessary = >precondition fo=3D >>> r
>>> >> this routine is that heapMu is locked! =3DC2=3DA0(Since = >it's going=3D >>> to unlock it,
>>> >> it had BETTER be locked on entry.)
>>> >>
>>> >> But the cond :=3D3D ... causes a = >RTHooks.CheckLoadTracedRef
>>> >>
>>> >> which causes an RTOS.LockHeap
>>> >>
>>> >> the code of which we just saw:
>>> >>
>>> >> PROCEDURE LockHeap () =3D3D
>>> >> =3DC2=3DA0 VAR self :=3D3D pthread_self();
>>> >> =3DC2=3DA0 BEGIN
>>> >> =3DC2=3DA0 =3DC2=3DA0 WITH r =3D3D = >pthread_mutex_lock(heapMu,ThisLine()) DO =3D >>> <*ASSERT r=3D3D0*> END;
>>> >> ...
>>> >>
>>> >> we try to lock heapMu. =3DC2=3DA0kaboom! =3DC2=3DA0No = >surprise there, real=3D >>> ly?
>>> >>
>>> >> Am I going about this totally the wrong way? =3DC2=3DA0Other = >people ar=3D >>> e running
>>> >> Modula-3
>>> >> with pthreads, right? =3DC2=3DA0Right?? =3DC2=3DA0Somewhere = >out there in m=3D >>> 3devel-land?
>>> >>
>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika
>>> >>
>>> >>
>>> >
>>>
>--001a11c2ced4471a2e050079db82
>>> >Content-Type: text/html; charset=3D3DUTF-8
>>> >Content-Transfer-Encoding: quoted-printable
>>> >
>>> ><div = >dir=3D3D3D"ltr">Mika<div><br></div>=3D >>> ;<div>=3D3DC2=3D3DA0 I think you need to back ou=3D3D
>>> >t Tony&#39;s changes to fix the fork bug, at least for now. = >Need to=3D >>> reload =3D3D
>>> >from cvs version 1.262 for ThreadPThread.m3 If you&#39;re = >using git=3D >>> you&#39=3D3D
>>> >;re on your own.</div>
>>> >
>>> ><div>=3D3DC2=3D3DA0 Do a cvs log ThreadPThread.m3 for an = >explanation =3D >>> for some of th=3D3D
>>> >e design principles.=3D3DC2=3D3DA0</div><div>=3D3DC2=3D= >3DA0 Also if=3D >>> you use gdb then you ne=3D3D
>>> >ed to set lanc c before backtraces so at least you can see = >address name=3D >>> s an=3D3D
>>> >d values even if they are contorted you can extract the M3 name = >in the =3D >>> parm=3D3D
>>> > lists. Also in gdb thread apply all bt gives all thread = >backtraces whi=3D >>> ch c=3D3D
>>> >an be handy to see whose got the locks held.</div>
>>> >
>>> ><div><br></div><div>Regards = >Peter</div>&l=3D >>> t;div><br></div><div class=3D3D3D"gmail_e=3D3Dr> >>> >xtra"><br><br><div = >class=3D3D3D"gmail_quote&q=3D >>> uot;>On Wed, Aug 13, 2014 at 12:14 PM, =3D3D
>>> > <span dir=3D3D3D"ltr">&lt;<a = >href=3D3D3D"mailt=3D >>> o:target=3D3D"_blank">mika at async.ca=3D >>> ltech.edu" target=3D3D3D"=3D3D
>>> >_blank">target=3D3D"_bl=3D >>> ank">mika at async.caltech.edu</a>&gt;</span> = >wrote:<br=3D >>> >
>>> >
>>> ><blockquote class=3D3D3D"gmail_quote" = >style=3D3D3D"margin=3D >>> :0 0 0 .8ex;border-left:1p=3D3D
>>> >x #ccc solid;padding-left:1ex"><br>
>>> >Question... is there something odd about my pthreads? = >=3D3DC2=3D3DA0Are pth=3D >>> reads no=3D3D
>>> >rmally reentrant? =3D3DC2=3D3DA0I didn&#39;t think = >so.<br>
>>> ><br>
>>> >My compiler is much happier with the following changes I already = >outlin=3D >>> ed:<=3D3D
>>> >br>
>>> ><br>
>>> >1. a dirty, disgusting hack to keep from locking against myself = >going f=3D >>> rom =3D3D
>>> >XWait with self.mutex locked to m.release().<br>
>>> ><br>
>>> >2. the change to LockHeap I described in previous = >email<br>
>>> ><br>
>>> >But now...<br>
>>> ><br>
>>> >(gdb) cont<br>
>>> >Continuing.<br>
>>> >ERROR: pthread_mutex_lock:11<br>
>>> >ERROR: pthread_mutex_lock:11<br>
>>> ><br>
>>> >Program received signal SIGABRT, Aborted.<br>
>>> >0x000000080107626a in thr_kill () from = >/lib/libc.so.7<br>
>>> >(gdb) where<br>
>>> >#0 =3D3DC2=3D3DA00x000000080107626a in thr_kill () from = >/lib/libc.so.7<b=3D >>> r>
>>> >#1 =3D3DC2=3D3DA00x000000080113dac9 in abort () from = >/lib/libc.so.7<br&g=3D >>> t;
>>> >#2 =3D3DC2=3D3DA00x000000000071e37a in = >ThreadPThread__pthread_mutex_lock (m=3D >>> utex=3D3D3DE=3D3D
>>> >rror accessing memory address 0x8000ffffb508: Bad = >address.<br>>>>=20 >>> >) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>>> >#3 =3D3DC2=3D3DA00x000000000071d48d in RTOS__LockHeap () at = >../src/thread/P=3D >>> THREAD/T=3D3D
>>> >hreadPThread.m3:1377<br>
>>> >#4 =3D3DC2=3D3DA00x0000000000706b9d in = >RTHooks__CheckLoadTracedRef (M3_Af40=3D >>> ku_ref=3D3D
>>> >=3D3D3DError accessing memory address 0x8000ffffb568: Bad = >address.<br&=3D >>> gt;
>>> >) at ../src/runtime/common/RTCollector.m3:2234<br>
>>> >#5 =3D3DC2=3D3DA00x000000000071d284 in = >ThreadPThread__AtForkParent () at ..=3D >>> /src/thr=3D3D
>>> >ead/PTHREAD/ThreadPThread.m3:1348<br>
>>> >#6 =3D3DC2=3D3DA00x0000000800df8733 in fork () from = >/lib/libthr.so.3<br&=3D >>> gt;
>>> >#7 =3D3DC2=3D3DA00x000000000070dd8b in RTProcess__Fork () at = >../src/runtime=3D >>> /common/=3D3D
>>> >RTProcessC.c:152<br>
>>> >#8 =3D3DC2=3D3DA00x00000000006c52f2 in = >ProcessPosixCommon__Create_ForkExec =3D >>> (M3_Bd56=3D3D
>>> >fi_cmd=3D3D3DError accessing memory address 0x8000ffffb6f8: Bad = >address.&=3D >>> lt;br>
>>> >) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>>> >#9 =3D3DC2=3D3DA00x00000000006c6c6c in Process__Create = >(M3_Bd56fi_cmd=3D3D3DE=3D >>> rror acces=3D3D
>>> >sing memory address 0x8000ffffb7f8: Bad address.<br>
>>> >) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>>> >#10 0x00000000004d6826 in QMachine__FulfilExecPromise = >(M3_D6rRrg_ep=3D3D3=3D >>> DError=3D3D
>>> > accessing memory address 0x8000ffffb838: Bad = >address.<br>
>>> >) at ../src/QMachine.m3:1666<br>
>>> >#11 0x00000000004d6220 in QMachine__ExecCommand = >(M3_An02H2_t=3D3D3DError =3D >>> access=3D3D
>>> >ing memory address 0x8000ffffb9f8: Bad address.<br>
>>> >) at ../src/QMachine.m3:1605<br>
>>> >#12 0x00000000004d537e in QMachine__DoTryExec = >(M3_An02H2_t=3D3D3DError ac=3D >>> cessin=3D3D
>>> >g memory address 0x8000ffffbee8: Bad address.<br>
>>> >) at ../src/QMachine.m3:1476<br>
>>> ><br>
>>> >What am I doing wrong here?<br>
>>> ><br>
>>> >The error doesn&#39;t look unreasonable! =3D3DC2=3D3DA0Looking = >more clo=3D >>> sely at the =3D3D
>>> >code:<br>
>>> ><br>
>>> >First, AtForkPrepare has been called:<br>
>>> ><br>
>>> >PROCEDURE AtForkPrepare() =3D3D3D<br>
>>> >=3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >Activation;<br>
>>> >=3D3DC2=3D3DA0 BEGIN<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(slotsMu, = >ThisLine());<br><=3D >>> br> >>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(perfMu, = >ThisLine());<br>>> r> >>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(initMu, = >ThisLine()); (* InitMute=3D >>> x =3D3D3D&gt; Re=3D3D
>>> >gisterFinalCleanup =3D3D3D&gt; LockHeap *)<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(heapMu, = >ThisLine());<br>>> r> >>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(activeMu, = >ThisLine()); (* LockHe=3D >>> ap =3D3D3D&gt; S=3D3D
>>> >uspendOthers =3D3D3D&gt; activeMu *)<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and lock all = >threads.<br&g=3D >>> t;
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* NOTE: We have = >initMu, activeMu, so sl=3D >>> ots won&#39;t ch=3D3D
>>> >ange, conditions and<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* mutexes = >won&#39;t be initialized =3D >>> on-demand.<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0*)<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >PThreadLockMutex(act.mutex, ThisLine()=3D >>> );<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >act.next;<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;<br>
>>> >=3D3DC2=3D3DA0 END AtForkPrepare;<br>
>>> ><br>
>>> >a postcondition of this routine is that heapMu is = >locked.<br>
>>> ><br>
>>> >now we get into AtForkParent:<br>
>>> ><br>
>>> >PROCEDURE AtForkParent() =3D3D3D<br>
>>> >=3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >Activation;<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond: = >Condition;<br>
>>> >=3D3DC2=3D3DA0 BEGIN<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and unlock all = >threads, condi=3D >>> tions. *)<br=3D3D
>>> >>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond :=3D3D3D = >slots[act.slot].join;<b=3D >>> r>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 IF cond # NIL THEN = >PThreadUnlockMutex(=3D >>> cond.mutex, This=3D3D
>>> >Line()) END;<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >PThreadUnlockMutex(act.mutex, ThisLine=3D >>> ());<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >act.next;<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(activeMu, = >ThisLine());<br&g=3D >>> t;
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(heapMu, = >ThisLine());<br>=3D >>>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(initMu, = >ThisLine());<br>=3D >>>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(perfMu, = >ThisLine());<br>=3D >>>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(slotsMu, = >ThisLine());<br>=3D >>> ;
>>> >=3D3DC2=3D3DA0 END AtForkParent;<br>
>>> ><br>
>>> >We can see by inspecting the code that a necessary precondition = >for<=3D >>> br>
>>> >this routine is that heapMu is locked! =3D3DC2=3D3DA0(Since = >it&#39;s go=3D >>> ing to unloc=3D3D
>>> >k it,<br>
>>> >it had BETTER be locked on entry.)<br>
>>> ><br>
>>> >But the cond :=3D3D3D ... causes a = >RTHooks.CheckLoadTracedRef<br>>> r> >>> ><br>
>>> >which causes an RTOS.LockHeap<br>
>>> ><br>
>>> >the code of which we just saw:<br>
>>> ><br>
>>> >PROCEDURE LockHeap () =3D3D3D<br>
>>> >=3D3DC2=3D3DA0 VAR self :=3D3D3D pthread_self();<br>
>>> >=3D3DC2=3D3DA0 BEGIN<br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 WITH r =3D3D3D = >pthread_mutex_lock(heapMu,ThisLine()=3D >>> ) DO &lt;*ASSE=3D3D
>>> >RT r=3D3D3D0*&gt; END;<br>
>>> >...<br>
>>> ><br>
>>> >we try to lock heapMu. =3D3DC2=3D3DA0kaboom! =3D3DC2=3D3DA0No = >surprise there, r=3D >>> eally?<br>
>>> ><br>
>>> >Am I going about this totally the wrong way? =3D3DC2=3D3DA0Other = >people are=3D >>> running=3D3D
>>> > Modula-3<br>
>>> >with pthreads, right? =3D3DC2=3D3DA0Right?? =3D3DC2=3D3DA0Somewhere= > out there i=3D >>> n m3devel-la=3D3D
>>> >nd?<br>
>>> ><span><font = >color=3D3D3D"#888888"><br>
>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika<br>
>>> ><br>
>>> = >></font></span></blockquote></div><br><= >;=3D >>> /div></div>
>>> >
>>> >--001a11c2ced4471a2e050079db82--
>>>

>>>

>>>=20 >>> --089e01183a1813188705007c3498-- From hosking at cs.purdue.edu Wed Aug 13 18:28:50 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Wed, 13 Aug 2014 12:28:50 -0400 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: <20140813063041.286EA1A2094@async.async.caltech.edu> References: <20140813021401.238B31A2094@async.async.caltech.edu> <20140813045415.C13921A2094@async.async.caltech.edu> <20140813063041.286EA1A2094@async.async.caltech.edu> Message-ID: <97266593-618F-458D-A975-FE01D9BF19F9@cs.purdue.edu> Which revision of ThreadPThread.m3 is this output from? On Aug 13, 2014, at 2:30 AM, mika at async.caltech.edu wrote: > > OK... deleted all the derived directories and rebuilt. Result on FreeBSD is similar (or identical, hard to tell): > > I get a partial deadlock: > > PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU COMMAND > 48760 root 98 0 87836K 29104K CPU1 1 12:32 83.89% threadtest{threadtest} > 48760 root 94 0 87836K 29104K CPU3 3 11:02 74.66% threadtest{threadtest} > 48760 root 94 0 87836K 29104K CPU0 0 11:03 71.97% threadtest{threadtest} > 48760 root 32 0 87836K 29104K umtxn 2 0:01 0.00% threadtest{threadtest} > 48760 root 20 0 87836K 29104K umtxn 2 0:01 0.00% threadtest{threadtest} > 48760 root 35 0 87836K 29104K uwait 2 0:01 0.00% threadtest{threadtest} > 48760 root 27 0 87836K 29104K uwait 0 0:01 0.00% threadtest{threadtest} > 48760 root 27 0 87836K 29104K umtxn 3 0:01 0.00% threadtest{threadtest} > 48760 root 27 0 87836K 29104K umtxn 2 0:01 0.00% threadtest{threadtest} > 48760 root 20 0 87836K 29104K umtxn 0 0:00 0.00% threadtest{threadtest} > 48759 root 20 0 30276K 11064K wait 0 0:00 0.00% gdb > > one of the dead threads is the main thread, so now output. But three > threads are still alive, interestingly enough. > > Looks like the same issue as before: > > Thread 5 (Thread 801807400 (LWP 100751/threadtest)): > #0 0x0000000800ae089c in __error () from /lib/libthr.so.3 > #1 0x0000000800ad6261 in pthread_suspend_np () from /lib/libthr.so.3 > #2 0x00000000004511bc in ThreadPThread__SuspendThread (mt=Error accessing memory address 0x8000ff5faa28: Bad address. > ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 > #3 0x000000000044ed8e in ThreadPThread__StopThread (M3_DMxDjQ_act=Error accessing memory address 0x8000ff5faa48: Bad address. > ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 > #4 0x000000000044ef31 in ThreadPThread__StopWorld () at ../src/thread/PTHREAD/ThreadPThread.m3:948 > #5 0x000000000044e44e in RTThread__SuspendOthers () at ../src/thread/PTHREAD/ThreadPThread.m3:713 > #6 0x0000000000436386 in RTCollector__CollectSomeInStateZero () at ../src/runtime/common/RTCollector.m3:749 > #7 0x0000000000436331 in RTCollector__CollectSome () at ../src/runtime/common/RTCollector.m3:723 > #8 0x0000000000435ff9 in RTHeapRep__CollectEnough () at ../src/runtime/common/RTCollector.m3:657 > #9 0x0000000000433233 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ff5fac88: Bad address. > ) at ../src/runtime/common/RTAllocator.m3:367 > #10 0x0000000000432b55 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error accessing memory address 0x8000ff5fad48: Bad address. > ) at ../src/runtime/common/RTAllocator.m3:296 > #11 0x0000000000431e8f in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=Error accessing memory address 0x8000ff5fada8: Bad address. > ) at ../src/runtime/common/RTAllocator.m3:143 > #12 0x00000000004052ea in Main__AApply (M3_AP7a1g_cl=Error accessing memory address 0x8000ff5fade8: Bad address. > ) at ../src/Main.m3:283 > #13 0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error accessing memory address 0x8000ff5faeb8: Bad address. > ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 > #14 0x000000000044cf00 in ThreadPThread__ThreadBase (M3_AJWxb1_param=Error accessing memory address 0x8000ff5faf68: Bad address. > ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 > #15 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 > #16 0x0000000000000000 in ?? () > > Interestingly the same test seems to work on AMD64_LINUX. That is > promising, at least. But of course, software testing never reveals the > absence of bugs. > > Mika > > Peter McKinna writes: >> --089e01183a1813188705007c3498 >> Content-Type: text/plain; charset=UTF-8 >> >> Oh, one other thing that seemed to help me in testing this stuff especially >> things to do with m3core and libm3 which seem to get out of whack >> sometimes, is to totally remove the target directory of m3core then cm3; >> cm3 -ship Same with libm3. I'm not sure that clean actually removes the >> targets and I think there are leftover files that stuff things up since I >> would get segv in FileRd for no obvious reason. >> >> Peter >> >> >> >> On Wed, Aug 13, 2014 at 3:33 PM, Peter McKinna >> wrote: >> >>> That is weird. The thread tester works fine with the old version of >>> ThreadPThread.m3 on linux amd_64 except if you have the fork test in the >>> mix of tests you see the pthread_mutex_destroy every now and again, the >>> fork bug in fact. >>> I was testing the pthread changes Tony has made over the past few days >>> using the thread tester program until I stupidly rebuilt the compiler and >>> was getting all sorts of hangs as it dragged in the new version of >>> pthreads. So I rebuilt everything from a backup to get back where I was >>> with a decent compiler, then reintroduced the latest changes to >>> ThreadPThread.m3, which yesterday was just hanging in sigsuspend but today >>> is giving me an assert failure at line 1387 in UnlockHeap. So its a bit >>> unstable to say the least. Maybe there is something else wrong with freebsd. >>> >>> Peter >>> >>> >>> >>> On Wed, Aug 13, 2014 at 2:54 PM, wrote: >>> >>>> >>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not getting >>>> things to work and now I'm really baffled because I think I understand >>>> this code! >>>> >>>> What I did was I threw away all my changes and reverted ThreadPThread.m3 >>>> to 1.262 as you suggested. >>>> >>>> Rebuilt the compiler with upgrade.sh >>>> >>>> Then rebuilt the compiler again with itself. >>>> >>>> Then I realcleaned the world and buildshipped it. (I was afraid >>>> that parseparams, also imported by the thread tester, would pollute >>>> it somehow.) >>>> >>>> When I look at the code in 1.262 it looks quite straightforward. heapMu >>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. >>>> Condition >>>> variables are mutexes too, but that's no big deal. >>>> >>>> So, rebuild thread tester, run it: >>>> >>>> new source -> compiling Main.m3 >>>> -> linking threadtest >>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # >>>> AMD64_FREEBSD/threadtest >>>> Writing file...done >>>> Creating read threads...done >>>> Creating fork threads...done >>>> Creating alloc threads...done >>>> Creating lock threads...done >>>> running...printing oldest/median age/newest >>>> . >>>> >>>> *** >>>> *** runtime error: >>>> *** Segmentation violation - possible attempt to dereference >>>> NIL.........laziest thread is 1407901189/1407901189/9 (tests: read >>>> 1407901189/1407901189/1407901189 fork 1407901189/1407901189/1407901189 >>>> alloc 9/9/9 lock 1407901189/1407901189/9) >>>> >>>> >>>> >>>> >>>> ^C >>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb !$ >>>> gdb AMD64_FREEBSD/threadtest >>>> GNU gdb 6.1.1 [FreeBSD] >>>> Copyright 2004 Free Software Foundation, Inc. >>>> GDB is free software, covered by the GNU General Public License, and you >>>> are >>>> welcome to change it and/or distribute copies of it under certain >>>> conditions. >>>> Type "show copying" to see the conditions. >>>> There is absolutely no warranty for GDB. Type "show warranty" for >>>> details. >>>> This GDB was configured as "amd64-marcel-freebsd"... >>>> (gdb) run >>>> Starting program: >>>> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/threadtest >>>> [New LWP 100121] >>>> Writing file...done >>>> Creating read threads...done >>>> Creating fork threads...done >>>> Creating alloc threads...done >>>> Creating lock threads...done >>>> running...printing oldest/median age/newest >>>> .[New Thread 801807000 (LWP 100343/threadtest)] >>>> [New Thread 801807c00 (LWP 100667/threadtest)] >>>> [New Thread 801808800 (LWP 100816/threadtest)] >>>> [New Thread 801807400 (LWP 100349/threadtest)] >>>> [New Thread 801808400 (LWP 100815/threadtest)] >>>> [New Thread 801807800 (LWP 100352/threadtest)] >>>> [New Thread 801808c00 (LWP 100817/threadtest)] >>>> [New Thread 801809000 (LWP 100818/threadtest)] >>>> [New Thread 801809800 (LWP 100820/threadtest)] >>>> [New Thread 801808000 (LWP 100678/threadtest)] >>>> [New Thread 801806400 (LWP 100121/threadtest)] >>>> [New Thread 801806800 (LWP 100341/threadtest)] >>>> [New Thread 801806c00 (LWP 100342/threadtest)] >>>> .ERROR: pthread_mutex_lock:11 >>>> >>>> Program received signal SIGABRT, Aborted. >>>> [Switching to Thread 801809800 (LWP 100820/threadtest)] >>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>> (gdb) where >>>> #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>> #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 >>>> #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock (mutex=Error >>>> accessing memory address 0x8000fe5f2d98: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 >>>> #3 0x000000000044b370 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error >>>> accessing memory address 0x8000fe5f2dc8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>> #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=Error accessing >>>> memory address 0x8000fe5f2df8: Bad address. >>>> ) at ../src/Main.m3:319 >>>> #5 0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>>> accessing memory address 0x8000fe5f2eb8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>> #6 0x000000000044cf00 in ThreadPThread__ThreadBase >>>> (M3_AJWxb1_param=Error accessing memory address 0x8000fe5f2f68: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>> #7 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>> #8 0x0000000000000000 in ?? () >>>> (gdb) set lang c >>>> (gdb) thread apply all bt >>>> ... not that interesting ... >>>> >>>> Segfault is segfault---error 11 is EDEADLK (locking against myself?) >>>> >>>> ????? the code is very straightforward, as I said. >>>> >>>> I thought people had the thread tester working with pthreads? Which set >>>> of files, then? Anyone on FreeBSD/amd64? >>>> >>>> Could it be an issue with "volatile"? Not even sure where to look. >>>> >>>> The code calling the lock is just this: >>>> >>>> PROCEDURE GetChar (rd: T): CHAR >>>> RAISES {EndOfFile, Failure, Alerted} = >>>> BEGIN >>>> LOCK rd DO >>>> RETURN FastGetChar(rd); >>>> END >>>> END GetChar; >>>> >>>> No mysteries there... >>>> >>>> Ah is this the fork bug? Looks like the Init routine is called on a >>>> lot of NIL mutexes around the fork. But the subprocesses aren't meant >>>> to accesses the mutexes... humm >>>> >>>> Hmm, and it's not entirely a fork issue. Even with "threadtest -tests >>>> STD,-fork,-forktoomuch" it misbehaves. Hangs.... >>>> >>>> Looks like a deadlock this time. >>>> >>>> Some stacks... >>>> >>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): >>>> #0 0x00000000004b4e2b in __vdso_gettimeofday () >>>> #1 0x00000000004ab8d2 in gettimeofday () >>>> #2 0x0000000000452e4b in TimePosix__Now () at >>>> ../src/time/POSIX/TimePosixC.c:50 >>>> #3 0x0000000000452d72 in Time__Now () at >>>> ../src/time/POSIX/TimePosix.m3:14 >>>> #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=Error accessing >>>> memory address 0x8000fedf6df8: Bad address. >>>> ) at ../src/Main.m3:327 >>>> #5 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>>> accessing memory address 0x8000fedf6eb8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>> #6 0x0000000000449c50 in ThreadPThread__ThreadBase >>>> (M3_AJWxb1_param=Error accessing memory address 0x8000fedf6f68: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>> #7 0x000000000047c7d4 in thread_start () >>>> #8 0x0000000000000000 in ?? () >>>> >>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): >>>> #0 0x000000000047e53c in _umtx_op_err () >>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>> #2 0x0000000000479404 in mutex_lock_common () >>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error >>>> accessing memory address 0x8000feff7d98: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>> #4 0x00000000004480c0 in ThreadPThread__LockMutex (M3_AYIbX3_m=Error >>>> accessing memory address 0x8000feff7dc8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>> #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=Error accessing >>>> memory address 0x8000feff7df8: Bad address. >>>> ) at ../src/Main.m3:319 >>>> #6 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>>> accessing memory address 0x8000feff7eb8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>> #7 0x0000000000449c50 in ThreadPThread__ThreadBase >>>> (M3_AJWxb1_param=Error accessing memory address 0x8000feff7f68: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>> #8 0x000000000047c7d4 in thread_start () >>>> #9 0x0000000000000000 in ?? () >>>> >>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): >>>> #0 0x000000000047e53c in _umtx_op_err () >>>> #1 0x0000000000475759 in suspend_common () >>>> #2 0x00000000004755c1 in pthread_suspend_np () >>>> #3 0x000000000044df0c in ThreadPThread__SuspendThread (mt=Error >>>> accessing memory address 0x8000ffbfd6f8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>> #4 0x000000000044bade in ThreadPThread__StopThread (M3_DMxDjQ_act=Error >>>> accessing memory address 0x8000ffbfd718: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>> #5 0x000000000044bc81 in ThreadPThread__StopWorld () at >>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>> #6 0x000000000044b19e in RTThread__SuspendOthers () at >>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>> #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero () at >>>> ../src/runtime/common/RTCollector.m3:749 >>>> #8 0x0000000000433081 in RTCollector__CollectSome () at >>>> ../src/runtime/common/RTCollector.m3:723 >>>> #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at >>>> ../src/runtime/common/RTCollector.m3:657 >>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced >>>> (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffbfd958: Bad >>>> address. >>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error >>>> accessing memory address 0x8000ffbfda18: Bad address. >>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>> (M3_AJWxb1_defn=Error accessing memory address 0x8000ffbfda78: Bad address. >>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=Error accessing >>>> memory address 0x8000ffbfdab8: Bad address. >>>> ) at ../src/rw/Rd.m3:159 >>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=Error >>>> accessing memory address 0x8000ffbfdb88: Bad address. >>>> ) at ../src/rw/Rd.m3:187 >>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=Error accessing >>>> memory address 0x8000ffbfdbd8: Bad address. >>>> ) at ../src/rw/Rd.m3:176 >>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=Error accessing >>>> memory address 0x8000ffbfdc58: Bad address. >>>> ) at ../src/Main.m3:185 >>>> >>>> #17 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>>> accessing memory address 0x8000ffbfdeb8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase >>>> (M3_AJWxb1_param=Error accessing memory address 0x8000ffbfdf68: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>> #19 0x000000000047c7d4 in thread_start () >>>> #20 0x0000000000000000 in ?? () >>>> >>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): >>>> #0 0x000000000047e53c in _umtx_op_err () >>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>> #2 0x0000000000479404 in mutex_lock_common () >>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error >>>> accessing memory address 0x8000ffffc678: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>> #4 0x000000000044d039 in RTOS__LockHeap () at >>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>> ---Type to continue, or q to quit--- >>>> #5 0x000000000042ff79 in RTAllocator__AllocTraced >>>> (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ffffc6e8: Bad >>>> address. >>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>> #6 0x000000000042f15b in RTAllocator__GetTracedObj (M3_Eic7CK_def=Error >>>> accessing memory address 0x8000ffffc7a8: Bad address. >>>> ) at ../src/runtime/common/RTAllocator.m3:224 >>>> #7 0x000000000042eb23 in RTHooks__AllocateTracedObj >>>> (M3_AJWxb1_defn=Error accessing memory address 0x8000ffffc7f8: Bad address. >>>> ) at ../src/runtime/common/RTAllocator.m3:122 >>>> #8 0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=Error accessing >>>> memory address 0x8000ffffc858: Bad address. >>>> ) at ../src/text/TextCat.m3:562 >>>> #9 0x000000000045ed5d in TextCat__Balance (M3_Bd56fi_LText=0x800c490b0, >>>> M3_BUgnwf_LInfo=Error accessing memory address 0x8000ffffc8f8: Bad address. >>>> ) at ../src/text/TextCat.m3:488 >>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=Error accessing >>>> memory address 0x8000ffffcbb8: Bad address. >>>> ) at ../src/text/TextCat.m3:40 >>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=Error accessing memory >>>> address 0x8000ffffcc38: Bad address. >>>> ) at ../src/Main.m3:593 >>>> #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=Error >>>> accessing memory address 0x8000ffffcf88: Bad address. >>>> ) at ../src/runtime/common/RTLinker.m3:408 >>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=Error accessing >>>> memory address 0x8000ffffd008: Bad address. >>>> ) at ../src/runtime/common/RTLinker.m3:115 >>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=Error accessing >>>> memory address 0x8000ffffd028: Bad address. >>>> ) at ../src/runtime/common/RTLinker.m3:124 >>>> #15 0x00000000004004a6 in main (argc=Error accessing memory address >>>> 0x8000ffffd07c: Bad address. >>>> ) at _m3main.c:22 >>>> >>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): >>>> #0 0x000000000047e53c in _umtx_op_err () >>>> #1 0x0000000000477e8a in check_suspend () >>>> #2 0x00000000004780a2 in sigcancel_handler () >>>> #3 >>>> #4 0x000000000047e53c in _umtx_op_err () >>>> #5 0x0000000000475f14 in __thr_umutex_lock () >>>> #6 0x0000000000479404 in mutex_lock_common () >>>> #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=Error >>>> accessing memory address 0x8000ff5fac18: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>> #8 0x000000000044d039 in RTOS__LockHeap () at >>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>> #9 0x000000000042ff79 in RTAllocator__AllocTraced >>>> (M3_Cwb5VA_dataSize=Error accessing memory address 0x8000ff5fac88: Bad >>>> address. >>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=Error >>>> accessing memory address 0x8000ff5fad48: Bad address. >>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>> (M3_AJWxb1_defn=Error accessing memory address 0x8000ff5fada8: Bad address. >>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=Error accessing >>>> memory address 0x8000ff5fade8: Bad address. >>>> ) at ../src/Main.m3:283 >>>> #13 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=Error >>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase >>>> (M3_AJWxb1_param=Error accessing memory address 0x8000ff5faf68: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>> #15 0x000000000047c7d4 in thread_start () >>>> #16 0x0000000000000000 in ?? () >>>> >>>> (others are similar) >>>> >>>> Hmm looks like a FreeBSD issue now. It's here... >>>> >>>> int >>>> __cdecl >>>> ThreadPThread__SuspendThread (m3_pthread_t mt) >>>> { >>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), >>>> "pthread_suspend_np"); >>>> return 1; >>>> } >>>> >>>> Now this suspend can wait: >>>> >>>> static int >>>> suspend_common(struct pthread *curthread, struct pthread *thread, >>>> int waitok) >>>> { >>>> uint32_t tmp; >>>> >>>> while (thread->state != PS_DEAD && >>>> !(thread->flags & THR_FLAGS_SUSPENDED)) { >>>> thread->flags |= THR_FLAGS_NEED_SUSPEND; >>>> /* Thread is in creation. */ >>>> if (thread->tid == TID_TERMINATED) >>>> return (1); >>>> tmp = thread->cycle; >>>> _thr_send_sig(thread, SIGCANCEL); >>>> THR_THREAD_UNLOCK(curthread, thread); >>>> if (waitok) { >>>> _thr_umtx_wait_uint(&thread->cycle, tmp, NULL, >>>> 0); <========== >>>> THR_THREAD_LOCK(curthread, thread); >>>> } else { >>>> THR_THREAD_LOCK(curthread, thread); >>>> return (0); >>>> } >>>> } >>>> >>>> return (1); >>>> } >>>> >>>> ... but what it can wait for I am not clear on. >>>> >>>> Do things work better on Linux? >>>> >>>> What is the status of the fork bug? Can it be worked around by only >>>> forking via Process.Create with no mutexes held (outside of all LOCK >>>> blocks)? >>>> >>>> Mika >>>> >>>> >>>> >>>> Peter McKinna writes: >>>>> --001a11c2ced4471a2e050079db82 >>>>> Content-Type: text/plain; charset=UTF-8 >>>>> >>>>> Mika >>>>> >>>>> I think you need to back out Tony's changes to fix the fork bug, at >>>> least >>>>> for now. Need to reload from cvs version 1.262 for ThreadPThread.m3 If >>>>> you're using git you're on your own. >>>>> Do a cvs log ThreadPThread.m3 for an explanation for some of the design >>>>> principles. >>>>> Also if you use gdb then you need to set lanc c before backtraces so at >>>>> least you can see address names and values even if they are contorted you >>>>> can extract the M3 name in the parm lists. Also in gdb thread apply all >>>> bt >>>>> gives all thread backtraces which can be handy to see whose got the locks >>>>> held. >>>>> >>>>> Regards Peter >>>>> >>>>> >>>>> >>>>> On Wed, Aug 13, 2014 at 12:14 PM, wrote: >>>>> >>>>>> >>>>>> Question... is there something odd about my pthreads? Are pthreads >>>>>> normally reentrant? I didn't think so. >>>>>> >>>>>> My compiler is much happier with the following changes I already >>>> outlined: >>>>>> >>>>>> 1. a dirty, disgusting hack to keep from locking against myself going >>>> from >>>>>> XWait with self.mutex locked to m.release(). >>>>>> >>>>>> 2. the change to LockHeap I described in previous email >>>>>> >>>>>> But now... >>>>>> >>>>>> (gdb) cont >>>>>> Continuing. >>>>>> ERROR: pthread_mutex_lock:11 >>>>>> ERROR: pthread_mutex_lock:11 >>>>>> >>>>>> Program received signal SIGABRT, Aborted. >>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>> (gdb) where >>>>>> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >>>>>> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock >>>> (mutex=Error >>>>>> accessing memory address 0x8000ffffb508: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >>>>>> #3 0x000000000071d48d in RTOS__LockHeap () at >>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >>>>>> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>> (M3_Af40ku_ref=Error >>>>>> accessing memory address 0x8000ffffb568: Bad address. >>>>>> ) at ../src/runtime/common/RTCollector.m3:2234 >>>>>> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >>>>>> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >>>>>> #7 0x000000000070dd8b in RTProcess__Fork () at >>>>>> ../src/runtime/common/RTProcessC.c:152 >>>>>> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>>>>> (M3_Bd56fi_cmd=Error accessing memory address 0x8000ffffb6f8: Bad >>>> address. >>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >>>>>> #9 0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=Error >>>> accessing >>>>>> memory address 0x8000ffffb7f8: Bad address. >>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21 >>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>> (M3_D6rRrg_ep=Error >>>>>> accessing memory address 0x8000ffffb838: Bad address. >>>>>> ) at ../src/QMachine.m3:1666 >>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=Error >>>>>> accessing memory address 0x8000ffffb9f8: Bad address. >>>>>> ) at ../src/QMachine.m3:1605 >>>>>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=Error >>>> accessing >>>>>> memory address 0x8000ffffbee8: Bad address. >>>>>> ) at ../src/QMachine.m3:1476 >>>>>> >>>>>> What am I doing wrong here? >>>>>> >>>>>> The error doesn't look unreasonable! Looking more closely at the code: >>>>>> >>>>>> First, AtForkPrepare has been called: >>>>>> >>>>>> PROCEDURE AtForkPrepare() = >>>>>> VAR me := GetActivation(); >>>>>> act: Activation; >>>>>> BEGIN >>>>>> PThreadLockMutex(slotsMu, ThisLine()); >>>>>> PThreadLockMutex(perfMu, ThisLine()); >>>>>> PThreadLockMutex(initMu, ThisLine()); (* InitMutex => >>>>>> RegisterFinalCleanup => LockHeap *) >>>>>> PThreadLockMutex(heapMu, ThisLine()); >>>>>> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => >>>> SuspendOthers >>>>>> => activeMu *) >>>>>> (* Walk activations and lock all threads. >>>>>> * NOTE: We have initMu, activeMu, so slots won't change, >>>> conditions >>>>>> and >>>>>> * mutexes won't be initialized on-demand. >>>>>> *) >>>>>> act := me; >>>>>> REPEAT >>>>>> PThreadLockMutex(act.mutex, ThisLine()); >>>>>> act := act.next; >>>>>> UNTIL act = me; >>>>>> END AtForkPrepare; >>>>>> >>>>>> a postcondition of this routine is that heapMu is locked. >>>>>> >>>>>> now we get into AtForkParent: >>>>>> >>>>>> PROCEDURE AtForkParent() = >>>>>> VAR me := GetActivation(); >>>>>> act: Activation; >>>>>> cond: Condition; >>>>>> BEGIN >>>>>> (* Walk activations and unlock all threads, conditions. *) >>>>>> act := me; >>>>>> REPEAT >>>>>> cond := slots[act.slot].join; >>>>>> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, ThisLine()) >>>> END; >>>>>> PThreadUnlockMutex(act.mutex, ThisLine()); >>>>>> act := act.next; >>>>>> UNTIL act = me; >>>>>> PThreadUnlockMutex(activeMu, ThisLine()); >>>>>> PThreadUnlockMutex(heapMu, ThisLine()); >>>>>> PThreadUnlockMutex(initMu, ThisLine()); >>>>>> PThreadUnlockMutex(perfMu, ThisLine()); >>>>>> PThreadUnlockMutex(slotsMu, ThisLine()); >>>>>> END AtForkParent; >>>>>> >>>>>> We can see by inspecting the code that a necessary precondition for >>>>>> this routine is that heapMu is locked! (Since it's going to unlock it, >>>>>> it had BETTER be locked on entry.) >>>>>> >>>>>> But the cond := ... causes a RTHooks.CheckLoadTracedRef >>>>>> >>>>>> which causes an RTOS.LockHeap >>>>>> >>>>>> the code of which we just saw: >>>>>> >>>>>> PROCEDURE LockHeap () = >>>>>> VAR self := pthread_self(); >>>>>> BEGIN >>>>>> WITH r = pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT r=0*> >>>> END; >>>>>> ... >>>>>> >>>>>> we try to lock heapMu. kaboom! No surprise there, really? >>>>>> >>>>>> Am I going about this totally the wrong way? Other people are running >>>>>> Modula-3 >>>>>> with pthreads, right? Right?? Somewhere out there in m3devel-land? >>>>>> >>>>>> Mika >>>>>> >>>>>> >>>>> >>>>> --001a11c2ced4471a2e050079db82 >>>>> Content-Type: text/html; charset=UTF-8 >>>>> Content-Transfer-Encoding: quoted-printable >>>>> >>>>>
Mika

=C2=A0 I think you need to back >>>> ou= >>>>> t Tony's changes to fix the fork bug, at least for now. Need to >>>> reload = >>>>> from cvs version 1.262 for ThreadPThread.m3 If you're using git >>>> you'= >>>>> ;re on your own.
>>>>> >>>>>
=C2=A0 Do a cvs log ThreadPThread.m3 for an explanation for some of >>>> th= >>>>> e design principles.=C2=A0
=C2=A0 Also if you use gdb then you >>>> ne= >>>>> ed to set lanc c before backtraces so at least you can see address names >>>> an= >>>>> d values even if they are contorted you can extract the M3 name in the >>>> parm= >>>>> lists. Also in gdb thread apply all bt gives all thread backtraces >>>> which c= >>>>> an be handy to see whose got the locks held.
>>>>> >>>>>

Regards Peter

>>> class=3D"gmail_e= >>>>> xtra">

On Wed, Aug 13, 2014 at 12:14 >>>> PM, = >>>>> <>>> target=3D"= >>>>> _blank">mika at async.caltech.edu> wrote:
>>>>> >>>>>
>>> .8ex;border-left:1p= >>>>> x #ccc solid;padding-left:1ex">
>>>>> Question... is there something odd about my pthreads? =C2=A0Are pthreads >>>> no= >>>>> rmally reentrant? =C2=A0I didn't think so.
>>>>>
>>>>> My compiler is much happier with the following changes I already >>>> outlined:<= >>>>> br> >>>>>
>>>>> 1. a dirty, disgusting hack to keep from locking against myself going >>>> from = >>>>> XWait with self.mutex locked to m.release().
>>>>>
>>>>> 2. the change to LockHeap I described in previous email
>>>>>
>>>>> But now...
>>>>>
>>>>> (gdb) cont
>>>>> Continuing.
>>>>> ERROR: pthread_mutex_lock:11
>>>>> ERROR: pthread_mutex_lock:11
>>>>>
>>>>> Program received signal SIGABRT, Aborted.
>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>> (gdb) where
>>>>> #0 =C2=A00x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>> #1 =C2=A00x000000080113dac9 in abort () from /lib/libc.so.7
>>>>> #2 =C2=A00x000000000071e37a in ThreadPThread__pthread_mutex_lock >>>> (mutex=3DE= >>>>> rror accessing memory address 0x8000ffffb508: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>> #3 =C2=A00x000000000071d48d in RTOS__LockHeap () at >>>> ../src/thread/PTHREAD/T= >>>>> hreadPThread.m3:1377
>>>>> #4 =C2=A00x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>> (M3_Af40ku_ref= >>>>> =3DError accessing memory address 0x8000ffffb568: Bad address.
>>>>> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>> #5 =C2=A00x000000000071d284 in ThreadPThread__AtForkParent () at >>>> ../src/thr= >>>>> ead/PTHREAD/ThreadPThread.m3:1348
>>>>> #6 =C2=A00x0000000800df8733 in fork () from /lib/libthr.so.3
>>>>> #7 =C2=A00x000000000070dd8b in RTProcess__Fork () at >>>> ../src/runtime/common/= >>>>> RTProcessC.c:152
>>>>> #8 =C2=A00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>>> (M3_Bd56= >>>>> fi_cmd=3DError accessing memory address 0x8000ffffb6f8: Bad address.
>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>> #9 =C2=A00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DError >>>> acces= >>>>> sing memory address 0x8000ffffb7f8: Bad address.
>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>> (M3_D6rRrg_ep=3DError= >>>>> accessing memory address 0x8000ffffb838: Bad address.
>>>>> ) at ../src/QMachine.m3:1666
>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3DError >>>> access= >>>>> ing memory address 0x8000ffffb9f8: Bad address.
>>>>> ) at ../src/QMachine.m3:1605
>>>>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError >>>> accessin= >>>>> g memory address 0x8000ffffbee8: Bad address.
>>>>> ) at ../src/QMachine.m3:1476
>>>>>
>>>>> What am I doing wrong here?
>>>>>
>>>>> The error doesn't look unreasonable! =C2=A0Looking more closely at >>>> the = >>>>> code:
>>>>>
>>>>> First, AtForkPrepare has been called:
>>>>>
>>>>> PROCEDURE AtForkPrepare() =3D
>>>>> =C2=A0 VAR me :=3D GetActivation();
>>>>> =C2=A0 =C2=A0 =C2=A0 act: Activation;
>>>>> =C2=A0 BEGIN
>>>>> =C2=A0 =C2=A0 PThreadLockMutex(slotsMu, ThisLine());
>>>>> =C2=A0 =C2=A0 PThreadLockMutex(perfMu, ThisLine());
>>>>> =C2=A0 =C2=A0 PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D> >>>> Re= >>>>> gisterFinalCleanup =3D> LockHeap *)
>>>>> =C2=A0 =C2=A0 PThreadLockMutex(heapMu, ThisLine());
>>>>> =C2=A0 =C2=A0 PThreadLockMutex(activeMu, ThisLine()); (* LockHeap >>>> =3D> S= >>>>> uspendOthers =3D> activeMu *)
>>>>> =C2=A0 =C2=A0 (* Walk activations and lock all threads.
>>>>> =C2=A0 =C2=A0 =C2=A0* NOTE: We have initMu, activeMu, so slots won't >>>> ch= >>>>> ange, conditions and
>>>>> =C2=A0 =C2=A0 =C2=A0* mutexes won't be initialized on-demand.
>>>>> =C2=A0 =C2=A0 =C2=A0*)
>>>>> =C2=A0 =C2=A0 act :=3D me;
>>>>> =C2=A0 =C2=A0 REPEAT
>>>>> =C2=A0 =C2=A0 =C2=A0 PThreadLockMutex(act.mutex, ThisLine());
>>>>> =C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>>>>> =C2=A0 =C2=A0 UNTIL act =3D me;
>>>>> =C2=A0 END AtForkPrepare;
>>>>>
>>>>> a postcondition of this routine is that heapMu is locked.
>>>>>
>>>>> now we get into AtForkParent:
>>>>>
>>>>> PROCEDURE AtForkParent() =3D
>>>>> =C2=A0 VAR me :=3D GetActivation();
>>>>> =C2=A0 =C2=A0 =C2=A0 act: Activation;
>>>>> =C2=A0 =C2=A0 =C2=A0 cond: Condition;
>>>>> =C2=A0 BEGIN
>>>>> =C2=A0 =C2=A0 (* Walk activations and unlock all threads, conditions. >>>> *)>>>>> >>>>> =C2=A0 =C2=A0 act :=3D me;
>>>>> =C2=A0 =C2=A0 REPEAT
>>>>> =C2=A0 =C2=A0 =C2=A0 cond :=3D slots[act.slot].join;
>>>>> =C2=A0 =C2=A0 =C2=A0 IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, >>>> This= >>>>> Line()) END;
>>>>> =C2=A0 =C2=A0 =C2=A0 PThreadUnlockMutex(act.mutex, ThisLine());
>>>>> =C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>>>>> =C2=A0 =C2=A0 UNTIL act =3D me;
>>>>> =C2=A0 =C2=A0 PThreadUnlockMutex(activeMu, ThisLine());
>>>>> =C2=A0 =C2=A0 PThreadUnlockMutex(heapMu, ThisLine());
>>>>> =C2=A0 =C2=A0 PThreadUnlockMutex(initMu, ThisLine());
>>>>> =C2=A0 =C2=A0 PThreadUnlockMutex(perfMu, ThisLine());
>>>>> =C2=A0 =C2=A0 PThreadUnlockMutex(slotsMu, ThisLine());
>>>>> =C2=A0 END AtForkParent;
>>>>>
>>>>> We can see by inspecting the code that a necessary precondition for
>>>>> this routine is that heapMu is locked! =C2=A0(Since it's going to >>>> unloc= >>>>> k it,
>>>>> it had BETTER be locked on entry.)
>>>>>
>>>>> But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef
>>>>>
>>>>> which causes an RTOS.LockHeap
>>>>>
>>>>> the code of which we just saw:
>>>>>
>>>>> PROCEDURE LockHeap () =3D
>>>>> =C2=A0 VAR self :=3D pthread_self();
>>>>> =C2=A0 BEGIN
>>>>> =C2=A0 =C2=A0 WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO >>>> <*ASSE= >>>>> RT r=3D0*> END;
>>>>> ...
>>>>>
>>>>> we try to lock heapMu. =C2=A0kaboom! =C2=A0No surprise there, really?
>>>>>
>>>>> Am I going about this totally the wrong way? =C2=A0Other people are >>>> running= >>>>> Modula-3
>>>>> with pthreads, right? =C2=A0Right?? =C2=A0Somewhere out there in >>>> m3devel-la= >>>>> nd?
>>>>>
>>>>> =C2=A0 =C2=A0 =C2=A0Mika
>>>>>
>>>>>

>>>>> >>>>> --001a11c2ced4471a2e050079db82-- >>>> >>> >>> >> >> --089e01183a1813188705007c3498 >> Content-Type: text/html; charset=UTF-8 >> Content-Transfer-Encoding: quoted-printable >> >>
Oh, one other thing that seemed to help me in testing this= >> stuff especially things to do with m3core and libm3 which seem to get out = >> of whack sometimes, is to totally remove the target directory of m3core the= >> n cm3; cm3 -ship Same with libm3. I'm not sure that clean actually remo= >> ves the targets and I think there are leftover files that stuff things up s= >> ince I would get segv in FileRd for no obvious reason.
>>
Peter

<= >> br>
On Wed, Aug 13, 2014 at 3:33 PM, Peter Mc= >> Kinna <> et=3D"_blank">peter.mckinna at gmail.com> wrote:
>>
> x #ccc solid;padding-left:1ex">
That is weird. The thread t= >> ester works fine with the old version of ThreadPThread.m3 on linux amd_64 e= >> xcept if you have the fork test in the mix of tests you see the pthread_mut= >> ex_destroy every now and again, the fork bug in fact.=C2=A0
>> >> I was testing the pthread changes Tony has made over the past few days usin= >> g the thread tester program until I stupidly rebuilt the compiler and was g= >> etting all sorts of hangs as it dragged in the new version of pthreads. So = >> I rebuilt everything from a backup to get back where I was with a decent co= >> mpiler, then reintroduced the latest changes to ThreadPThread.m3, which yes= >> terday was just hanging in sigsuspend but today is giving me an assert fail= >> ure at line 1387 in UnlockHeap. So its a bit unstable to say the least. May= >> be there is something else wrong with freebsd.
>> >>

Peter

> s=3D"HOEnZb">


> s=3D"gmail_quote">On Wed, Aug 13, 2014 at 2:54 PM, <<= >> a href=3D"mailto:mika at async.caltech.edu" target=3D"_blank">mika at async.calte= >> ch.edu> wrote:
>> >>
> x #ccc solid;padding-left:1ex">
>> Yeah OK 1.262 makes a lot more sense to me but I'm still not getting>> >> things to work and now I'm really baffled because I think I understand<= >> br> >> this code!
>>
>> What I did was I threw away all my changes and reverted ThreadPThread.m3>> >> to 1.262 as you suggested.
>>
>> Rebuilt the compiler with upgrade.sh
>>
>> Then rebuilt the compiler again with itself.
>>
>> Then I realcleaned the world and buildshipped it. =C2=A0(I was afraid
>> that parseparams, also imported by the thread tester, would pollute
>> it somehow.)
>>
>> When I look at the code in 1.262 it looks quite straightforward. =C2=A0heap= >> Mu
>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. =C2=A0Cond= >> ition
>> variables are mutexes too, but that's no big deal.
>>
>> So, rebuild thread tester, run it:
>>
>> new source -> compiling Main.m3
>> =C2=A0-> linking threadtest
>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # AMD64_FREEB= >> SD/threadtest
>> Writing file...done
>> Creating read threads...done
>> Creating fork threads...done
>> Creating alloc threads...done
>> Creating lock threads...done
>> running...printing oldest/median age/newest
>> .
>>
>> ***
>> *** runtime error:
>> *** =C2=A0 =C2=A0Segmentation violation - possible attempt to dereference N= >> IL.........laziest thread is 1407901189/> e=3D"+14079011899" target=3D"_blank">1407901189/9 (tests: read 14079011= >> 89/1407901189/1407901189 fork 1407901189/1407901189/1407901189 alloc 9/9/9 = >> lock 1407901189/1407901189/9)
>> >> >>
>>
>>
>>
>> ^C
>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb !$
>> gdb AMD64_FREEBSD/threadtest
>> GNU gdb 6.1.1 [FreeBSD]
>> Copyright 2004 Free Software Foundation, Inc.
>> GDB is free software, covered by the GNU General Public License, and you ar= >> e
>> welcome to change it and/or distribute copies of it under certain condition= >> s.
>> Type "show copying" to see the conditions.
>> There is absolutely no warranty for GDB. =C2=A0Type "show warranty&quo= >> t; for details.
>> This GDB was configured as "amd64-marcel-freebsd"...
>> (gdb) run
>> Starting program: /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread= >> /AMD64_FREEBSD/threadtest
>> [New LWP 100121]
>> Writing file...done
>> Creating read threads...done
>> Creating fork threads...done
>> Creating alloc threads...done
>> Creating lock threads...done
>> running...printing oldest/median age/newest
>> .[New Thread 801807000 (LWP 100343/threadtest)]
>> [New Thread 801807c00 (LWP 100667/threadtest)]
>> [New Thread 801808800 (LWP 100816/threadtest)]
>> [New Thread 801807400 (LWP 100349/threadtest)]
>> [New Thread 801808400 (LWP 100815/threadtest)]
>> [New Thread 801807800 (LWP 100352/threadtest)]
>> [New Thread 801808c00 (LWP 100817/threadtest)]
>> [New Thread 801809000 (LWP 100818/threadtest)]
>> [New Thread 801809800 (LWP 100820/threadtest)]
>> [New Thread 801808000 (LWP 100678/threadtest)]
>> [New Thread 801806400 (LWP 100121/threadtest)]
>> [New Thread 801806800 (LWP 100341/threadtest)]
>> [New Thread 801806c00 (LWP 100342/threadtest)]
>> .ERROR: pthread_mutex_lock:11
>>

>> Program received signal SIGABRT, Aborted.
>>
[Switching to Thread 801809800 (LWP 100820/threadtest)]
>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>> (gdb) where
>> #0 =C2=A00x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>> #1 =C2=A00x0000000800e23ac9 in abort () from /lib/libc.so.7
>> #2 =C2=A00x000000000045101f in ThreadPThread__pthread_mutex_lock (mutex=3DE= >> rror accessing memory address 0x8000fe5f2d98: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
>> #3 =C2=A00x000000000044b370 in ThreadPThread__LockMutex (M3_AYIbX3_m=3DErro= >> r accessing memory address 0x8000fe5f2dc8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>> #4 =C2=A00x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3DError accessing= >> memory address 0x8000fe5f2df8: Bad address.
>> ) at ../src/Main.m3:319
>> #5 =C2=A00x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DErr= >> or accessing memory address 0x8000fe5f2eb8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>> #6 =C2=A00x000000000044cf00 in ThreadPThread__ThreadBase (M3_AJWxb1_param= >> =3DError accessing memory address 0x8000fe5f2f68: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>> #7 =C2=A00x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3
>> #8 =C2=A00x0000000000000000 in ?? ()
>> (gdb) set lang c
>> (gdb) thread apply all bt
>> ... not that interesting ...
>>
>> Segfault is segfault---error 11 is EDEADLK (locking against myself?)
>>
>> ????? the code is very straightforward, as I said.
>>
>> I thought people had the thread tester working with pthreads? =C2=A0Which s= >> et of files, then? =C2=A0Anyone on FreeBSD/amd64?
>>
>> Could it be an issue with "volatile"? =C2=A0Not even sure where t= >> o look.
>>
>> The code calling the lock is just this:
>>
>> PROCEDURE GetChar (rd: T): CHAR
>> =C2=A0 RAISES {EndOfFile, Failure, Alerted} =3D
>> =C2=A0 BEGIN
>> =C2=A0 =C2=A0 LOCK rd DO
>> =C2=A0 =C2=A0 =C2=A0 RETURN FastGetChar(rd);
>> =C2=A0 =C2=A0 END
>> =C2=A0 END GetChar;
>>
>> No mysteries there...
>>
>> Ah is this the fork bug? =C2=A0Looks like the Init routine is called on a> r> >> lot of NIL mutexes around the fork. =C2=A0But the subprocesses aren't m= >> eant
>> to accesses the mutexes... humm
>>
>> Hmm, and it's not entirely a fork issue. =C2=A0Even with "threadte= >> st -tests STD,-fork,-forktoomuch" it misbehaves. =C2=A0Hangs....
>>
>> Looks like a deadlock this time.
>>
>> Some stacks...
>>
>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
>> #0 =C2=A00x00000000004b4e2b in __vdso_gettimeofday ()
>> #1 =C2=A00x00000000004ab8d2 in gettimeofday ()
>> #2 =C2=A00x0000000000452e4b in TimePosix__Now () at ../src/time/POSIX/TimeP= >> osixC.c:50
>> #3 =C2=A00x0000000000452d72 in Time__Now () at ../src/time/POSIX/TimePosix.= >> m3:14
>> #4 =C2=A00x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3DError accessing= >> memory address 0x8000fedf6df8: Bad address.
>> ) at ../src/Main.m3:327
>> #5 =C2=A00x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DErr= >> or accessing memory address 0x8000fedf6eb8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>> #6 =C2=A00x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param= >> =3DError accessing memory address 0x8000fedf6f68: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>> #7 =C2=A00x000000000047c7d4 in thread_start ()
>> #8 =C2=A00x0000000000000000 in ?? ()
>>
>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
>> #0 =C2=A00x000000000047e53c in _umtx_op_err ()
>> #1 =C2=A00x0000000000475f14 in __thr_umutex_lock ()
>> #2 =C2=A00x0000000000479404 in mutex_lock_common ()
>> #3 =C2=A00x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=3DE= >> rror accessing memory address 0x8000feff7d98: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>> #4 =C2=A00x00000000004480c0 in ThreadPThread__LockMutex (M3_AYIbX3_m=3DErro= >> r accessing memory address 0x8000feff7dc8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>> #5 =C2=A00x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3DError accessing= >> memory address 0x8000feff7df8: Bad address.
>> ) at ../src/Main.m3:319
>> #6 =C2=A00x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DErr= >> or accessing memory address 0x8000feff7eb8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>> #7 =C2=A00x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param= >> =3DError accessing memory address 0x8000feff7f68: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>> #8 =C2=A00x000000000047c7d4 in thread_start ()
>> #9 =C2=A00x0000000000000000 in ?? ()
>>
>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
>> #0 =C2=A00x000000000047e53c in _umtx_op_err ()
>> #1 =C2=A00x0000000000475759 in suspend_common ()
>> #2 =C2=A00x00000000004755c1 in pthread_suspend_np ()
>> #3 =C2=A00x000000000044df0c in ThreadPThread__SuspendThread (mt=3DError acc= >> essing memory address 0x8000ffbfd6f8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
>> #4 =C2=A00x000000000044bade in ThreadPThread__StopThread (M3_DMxDjQ_act=3DE= >> rror accessing memory address 0x8000ffbfd718: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909
>> #5 =C2=A00x000000000044bc81 in ThreadPThread__StopWorld () at ../src/thread= >> /PTHREAD/ThreadPThread.m3:948
>> #6 =C2=A00x000000000044b19e in RTThread__SuspendOthers () at ../src/thread/= >> PTHREAD/ThreadPThread.m3:713
>> #7 =C2=A00x00000000004330d6 in RTCollector__CollectSomeInStateZero () at ..= >> /src/runtime/common/RTCollector.m3:749
>> #8 =C2=A00x0000000000433081 in RTCollector__CollectSome () at ../src/runtim= >> e/common/RTCollector.m3:723
>> #9 =C2=A00x0000000000432d49 in RTHeapRep__CollectEnough () at ../src/runtim= >> e/common/RTCollector.m3:657
>> #10 0x000000000042ff83 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize=3DEr= >> ror accessing memory address 0x8000ffbfd958: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:367
>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=3DError = >> accessing memory address 0x8000ffbfda18: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:296
>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=3DErro= >> r accessing memory address 0x8000ffbfda78: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:143
>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3DError accessing memo= >> ry address 0x8000ffbfdab8: Bad address.
>> ) at ../src/rw/Rd.m3:159
>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=3DError acces= >> sing memory address 0x8000ffbfdb88: Bad address.
>> ) at ../src/rw/Rd.m3:187
>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3DError accessing memor= >> y address 0x8000ffbfdbd8: Bad address.
>> ) at ../src/rw/Rd.m3:176
>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3DError accessing memo= >> ry address 0x8000ffbfdc58: Bad address.
>> ) at ../src/Main.m3:185
>>
>> #17 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DError ac= >> cessing memory address 0x8000ffbfdeb8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=3DErro= >> r accessing memory address 0x8000ffbfdf68: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>> #19 0x000000000047c7d4 in thread_start ()
>> #20 0x0000000000000000 in ?? ()
>>
>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
>> #0 =C2=A00x000000000047e53c in _umtx_op_err ()
>> #1 =C2=A00x0000000000475f14 in __thr_umutex_lock ()
>> #2 =C2=A00x0000000000479404 in mutex_lock_common ()
>> #3 =C2=A00x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=3DE= >> rror accessing memory address 0x8000ffffc678: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>> #4 =C2=A00x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/T= >> hreadPThread.m3:1337
>> ---Type <return> to continue, or q <return> to quit---
>> #5 =C2=A00x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize= >> =3DError accessing memory address 0x8000ffffc6e8: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:365
>> #6 =C2=A00x000000000042f15b in RTAllocator__GetTracedObj (M3_Eic7CK_def=3DE= >> rror accessing memory address 0x8000ffffc7a8: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:224
>> #7 =C2=A00x000000000042eb23 in RTHooks__AllocateTracedObj (M3_AJWxb1_defn= >> =3DError accessing memory address 0x8000ffffc7f8: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:122
>> #8 =C2=A00x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=3DError acces= >> sing memory address 0x8000ffffc858: Bad address.
>> ) at ../src/text/TextCat.m3:562
>> #9 =C2=A00x000000000045ed5d in TextCat__Balance (M3_Bd56fi_LText=3D0x800c49= >> 0b0, M3_BUgnwf_LInfo=3DError accessing memory address 0x8000ffffc8f8: Bad a= >> ddress.
>> ) at ../src/text/TextCat.m3:488
>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3DError accessing me= >> mory address 0x8000ffffcbb8: Bad address.
>> ) at ../src/text/TextCat.m3:40
>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3DError accessing memory = >> address 0x8000ffffcc38: Bad address.
>> ) at ../src/Main.m3:593
>> #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=3DError access= >> ing memory address 0x8000ffffcf88: Bad address.
>> ) at ../src/runtime/common/RTLinker.m3:408
>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3DError accessing= >> memory address 0x8000ffffd008: Bad address.
>> ) at ../src/runtime/common/RTLinker.m3:115
>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3DError accessing = >> memory address 0x8000ffffd028: Bad address.
>> ) at ../src/runtime/common/RTLinker.m3:124
>> #15 0x00000000004004a6 in main (argc=3DError accessing memory address 0x800= >> 0ffffd07c: Bad address.
>> ) at _m3main.c:22
>>
>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
>> #0 =C2=A00x000000000047e53c in _umtx_op_err ()
>> #1 =C2=A00x0000000000477e8a in check_suspend ()
>> #2 =C2=A00x00000000004780a2 in sigcancel_handler ()
>> #3 =C2=A0<signal handler called>
>> #4 =C2=A00x000000000047e53c in _umtx_op_err ()
>> #5 =C2=A00x0000000000475f14 in __thr_umutex_lock ()
>> #6 =C2=A00x0000000000479404 in mutex_lock_common ()
>> #7 =C2=A00x000000000044dd15 in ThreadPThread__pthread_mutex_lock (mutex=3DE= >> rror accessing memory address 0x8000ff5fac18: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>> #8 =C2=A00x000000000044d039 in RTOS__LockHeap () at ../src/thread/PTHREAD/T= >> hreadPThread.m3:1337
>> #9 =C2=A00x000000000042ff79 in RTAllocator__AllocTraced (M3_Cwb5VA_dataSize= >> =3DError accessing memory address 0x8000ff5fac88: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:365
>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray (M3_Eic7CK_def=3DError = >> accessing memory address 0x8000ff5fad48: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:296
>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray (M3_AJWxb1_defn=3DErro= >> r accessing memory address 0x8000ff5fada8: Bad address.
>> ) at ../src/runtime/common/RTAllocator.m3:143
>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3DError accessing memo= >> ry address 0x8000ff5fade8: Bad address.
>> ) at ../src/Main.m3:283
>> #13 0x0000000000449f93 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DError ac= >> cessing memory address 0x8000ff5faeb8: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase (M3_AJWxb1_param=3DErro= >> r accessing memory address 0x8000ff5faf68: Bad address.
>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>> #15 0x000000000047c7d4 in thread_start ()
>> #16 0x0000000000000000 in ?? ()
>>
>> (others are similar)
>>
>> Hmm looks like a FreeBSD issue now. =C2=A0It's here...
>>
>> int
>> __cdecl
>> ThreadPThread__SuspendThread (m3_pthread_t mt)
>> {
>> =C2=A0 ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), "= >> pthread_suspend_np");
>> =C2=A0 return 1;
>> }
>>
>> Now this suspend can wait:
>>
>> static int
>> suspend_common(struct pthread *curthread, struct pthread *thread,
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 int waitok)
>> {
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 uint32_t tmp;
>>
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 while (thread->state !=3D PS_DEAD &&= >>
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 !(thread->flags & T= >> HR_FLAGS_SUSPENDED)) {
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 thread->flags |= >> =3D THR_FLAGS_NEED_SUSPEND;
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Thread is in cre= >> ation. */
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (thread->tid = >> =3D=3D TID_TERMINATED)
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >> =A0 =C2=A0 return (1);
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 tmp =3D thread->= >> cycle;
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 _thr_send_sig(threa= >> d, SIGCANCEL);
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 THR_THREAD_UNLOCK(c= >> urthread, thread);
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (waitok) {
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >> =A0 =C2=A0 _thr_umtx_wait_uint(&thread->cycle, tmp, NULL, 0); =C2=A0= >> <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >> =A0 =C2=A0 THR_THREAD_LOCK(curthread, thread);
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >> =A0 =C2=A0 THR_THREAD_LOCK(curthread, thread);
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= >> =A0 =C2=A0 return (0);
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>>
>> =C2=A0 =C2=A0 =C2=A0 =C2=A0 return (1);
>> }
>>
>> ... but what it can wait for I am not clear on.
>>
>> Do things work better on Linux?
>>
>> What is the status of the fork bug? =C2=A0Can it be worked around by only f= >> orking via Process.Create with no mutexes held (outside of all LOCK blocks)= >> ?
>>
>> =C2=A0 =C2=A0 =C2=A0Mika
>>
>>
>>
>> Peter McKinna writes:
>> >--001a11c2ced4471a2e050079db82
>> >Content-Type: text/plain; charset=3DUTF-8
>>
>
>> >Mika
>> >
>> > =C2=A0I think you need to back out Tony's changes to fix the fork = >> bug, at least
>> >for now. Need to reload from cvs version 1.262 for ThreadPThread.m3 If<= >> br> >> >you're using git you're on your own.
>> > =C2=A0Do a cvs log ThreadPThread.m3 for an explanation for some of the= >> design
>> >principles.
>> > =C2=A0Also if you use gdb then you need to set lanc c before backtrace= >> s so at
>> >least you can see address names and values even if they are contorted y= >> ou
>> >can extract the M3 name in the parm lists. Also in gdb thread apply all= >> bt
>> >gives all thread backtraces which can be handy to see whose got the loc= >> ks
>> >held.
>> >
>> >Regards Peter
>> >
>> >
>> >
>> >On Wed, Aug 13, 2014 at 12:14 PM, <> ech.edu" target=3D"_blank">mika at async.caltech.edu> wrote:
>> >
>> >>
>> >> Question... is there something odd about my pthreads? =C2=A0Are pt= >> hreads
>> >> normally reentrant? =C2=A0I didn't think so.
>> >>
>> >> My compiler is much happier with the following changes I already o= >> utlined:
>> >>
>> >> 1. a dirty, disgusting hack to keep from locking against myself go= >> ing from
>> >> XWait with self.mutex locked to m.release().
>> >>
>> >> 2. the change to LockHeap I described in previous email
>> >>
>> >> But now...
>> >>
>> >> (gdb) cont
>> >> Continuing.
>> >> ERROR: pthread_mutex_lock:11
>> >> ERROR: pthread_mutex_lock:11
>> >>
>> >> Program received signal SIGABRT, Aborted.
>> >> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>> >> (gdb) where
>> >> #0 =C2=A00x000000080107626a in thr_kill () from /lib/libc.so.7
>> >> #1 =C2=A00x000000080113dac9 in abort () from /lib/libc.so.7
>> >> #2 =C2=A00x000000000071e37a in ThreadPThread__pthread_mutex_lock (= >> mutex=3DError
>> >> accessing memory address 0x8000ffffb508: Bad address.
>> >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>> >> #3 =C2=A00x000000000071d48d in RTOS__LockHeap () at
>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>> >> #4 =C2=A00x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af4= >> 0ku_ref=3DError
>> >> accessing memory address 0x8000ffffb568: Bad address.
>> >> ) at ../src/runtime/common/RTCollector.m3:2234
>> >> #5 =C2=A00x000000000071d284 in ThreadPThread__AtForkParent () at> r> >> >> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>> >> #6 =C2=A00x0000000800df8733 in fork () from /lib/libthr.so.3
>> >> #7 =C2=A00x000000000070dd8b in RTProcess__Fork () at
>> >> ../src/runtime/common/RTProcessC.c:152
>> >> #8 =C2=A00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec= >>
>> >> (M3_Bd56fi_cmd=3DError accessing memory address 0x8000ffffb6f8: Ba= >> d address.
>> >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>> >> #9 =C2=A00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DEr= >> ror accessing
>> >> memory address 0x8000ffffb7f8: Bad address.
>> >> ) at ../src/os/POSIX/ProcessPosix.m3:21
>> >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_e= >> p=3DError
>> >> accessing memory address 0x8000ffffb838: Bad address.
>> >> ) at ../src/QMachine.m3:1666
>> >> #11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3DErr= >> or
>> >> accessing memory address 0x8000ffffb9f8: Bad address.
>> >> ) at ../src/QMachine.m3:1605
>> >> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError= >> accessing
>> >> memory address 0x8000ffffbee8: Bad address.
>> >> ) at ../src/QMachine.m3:1476
>> >>
>> >> What am I doing wrong here?
>> >>
>> >> The error doesn't look unreasonable! =C2=A0Looking more closel= >> y at the code:
>> >>
>> >> First, AtForkPrepare has been called:
>> >>
>> >> PROCEDURE AtForkPrepare() =3D
>> >> =C2=A0 VAR me :=3D GetActivation();
>> >> =C2=A0 =C2=A0 =C2=A0 act: Activation;
>> >> =C2=A0 BEGIN
>> >> =C2=A0 =C2=A0 PThreadLockMutex(slotsMu, ThisLine());
>> >> =C2=A0 =C2=A0 PThreadLockMutex(perfMu, ThisLine());
>> >> =C2=A0 =C2=A0 PThreadLockMutex(initMu, ThisLine()); (* InitMutex = >> =3D>
>> >> RegisterFinalCleanup =3D> LockHeap *)
>> >> =C2=A0 =C2=A0 PThreadLockMutex(heapMu, ThisLine());
>> >> =C2=A0 =C2=A0 PThreadLockMutex(activeMu, ThisLine()); (* LockHeap = >> =3D> SuspendOthers
>> >> =3D> activeMu *)
>> >> =C2=A0 =C2=A0 (* Walk activations and lock all threads.
>> >> =C2=A0 =C2=A0 =C2=A0* NOTE: We have initMu, activeMu, so slots won= >> 't change, conditions
>> >> and
>> >> =C2=A0 =C2=A0 =C2=A0* mutexes won't be initialized on-demand.<= >> br> >> >> =C2=A0 =C2=A0 =C2=A0*)
>> >> =C2=A0 =C2=A0 act :=3D me;
>> >> =C2=A0 =C2=A0 REPEAT
>> >> =C2=A0 =C2=A0 =C2=A0 PThreadLockMutex(act.mutex, ThisLine());
>> >> =C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>> >> =C2=A0 =C2=A0 UNTIL act =3D me;
>> >> =C2=A0 END AtForkPrepare;
>> >>
>> >> a postcondition of this routine is that heapMu is locked.
>> >>
>> >> now we get into AtForkParent:
>> >>
>> >> PROCEDURE AtForkParent() =3D
>> >> =C2=A0 VAR me :=3D GetActivation();
>> >> =C2=A0 =C2=A0 =C2=A0 act: Activation;
>> >> =C2=A0 =C2=A0 =C2=A0 cond: Condition;
>> >> =C2=A0 BEGIN
>> >> =C2=A0 =C2=A0 (* Walk activations and unlock all threads, conditio= >> ns. *)
>> >> =C2=A0 =C2=A0 act :=3D me;
>> >> =C2=A0 =C2=A0 REPEAT
>> >> =C2=A0 =C2=A0 =C2=A0 cond :=3D slots[act.slot].join;
>> >> =C2=A0 =C2=A0 =C2=A0 IF cond # NIL THEN PThreadUnlockMutex(cond.mu= >> tex, ThisLine()) END;
>> >> =C2=A0 =C2=A0 =C2=A0 PThreadUnlockMutex(act.mutex, ThisLine());>> >> >> =C2=A0 =C2=A0 =C2=A0 act :=3D act.next;
>> >> =C2=A0 =C2=A0 UNTIL act =3D me;
>> >> =C2=A0 =C2=A0 PThreadUnlockMutex(activeMu, ThisLine());
>> >> =C2=A0 =C2=A0 PThreadUnlockMutex(heapMu, ThisLine());
>> >> =C2=A0 =C2=A0 PThreadUnlockMutex(initMu, ThisLine());
>> >> =C2=A0 =C2=A0 PThreadUnlockMutex(perfMu, ThisLine());
>> >> =C2=A0 =C2=A0 PThreadUnlockMutex(slotsMu, ThisLine());
>> >> =C2=A0 END AtForkParent;
>> >>
>> >> We can see by inspecting the code that a necessary precondition fo= >> r
>> >> this routine is that heapMu is locked! =C2=A0(Since it's going= >> to unlock it,
>> >> it had BETTER be locked on entry.)
>> >>
>> >> But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef
>> >>
>> >> which causes an RTOS.LockHeap
>> >>
>> >> the code of which we just saw:
>> >>
>> >> PROCEDURE LockHeap () =3D
>> >> =C2=A0 VAR self :=3D pthread_self();
>> >> =C2=A0 BEGIN
>> >> =C2=A0 =C2=A0 WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO = >> <*ASSERT r=3D0*> END;
>> >> ...
>> >>
>> >> we try to lock heapMu. =C2=A0kaboom! =C2=A0No surprise there, real= >> ly?
>> >>
>> >> Am I going about this totally the wrong way? =C2=A0Other people ar= >> e running
>> >> Modula-3
>> >> with pthreads, right? =C2=A0Right?? =C2=A0Somewhere out there in m= >> 3devel-land?
>> >>
>> >> =C2=A0 =C2=A0 =C2=A0Mika
>> >>
>> >>
>> >
>>
>--001a11c2ced4471a2e050079db82
>> >Content-Type: text/html; charset=3DUTF-8
>> >Content-Transfer-Encoding: quoted-printable
>> >
>> ><div dir=3D3D"ltr">Mika<div><br></div>= >> ;<div>=3DC2=3DA0 I think you need to back ou=3D
>> >t Tony&#39;s changes to fix the fork bug, at least for now. Need to= >> reload =3D
>> >from cvs version 1.262 for ThreadPThread.m3 If you&#39;re using git= >> you&#39=3D
>> >;re on your own.</div>
>> >
>> ><div>=3DC2=3DA0 Do a cvs log ThreadPThread.m3 for an explanation = >> for some of th=3D
>> >e design principles.=3DC2=3DA0</div><div>=3DC2=3DA0 Also if= >> you use gdb then you ne=3D
>> >ed to set lanc c before backtraces so at least you can see address name= >> s an=3D
>> >d values even if they are contorted you can extract the M3 name in the = >> parm=3D
>> > lists. Also in gdb thread apply all bt gives all thread backtraces whi= >> ch c=3D
>> >an be handy to see whose got the locks held.</div>
>> >
>> ><div><br></div><div>Regards Peter</div>&l= >> t;div><br></div><div class=3D3D"gmail_e=3D
>> >xtra"><br><br><div class=3D3D"gmail_quote&q= >> uot;>On Wed, Aug 13, 2014 at 12:14 PM, =3D
>> > <span dir=3D3D"ltr">&lt;<a href=3D3D"mailt= >> o:mika at async.ca= >> ltech.edu" target=3D3D"=3D
>> >_blank">> ank">mika at async.caltech.edu</a>&gt;</span> wrote:<br= >> >
>> >
>> ><blockquote class=3D3D"gmail_quote" style=3D3D"margin= >> :0 0 0 .8ex;border-left:1p=3D
>> >x #ccc solid;padding-left:1ex"><br>
>> >Question... is there something odd about my pthreads? =3DC2=3DA0Are pth= >> reads no=3D
>> >rmally reentrant? =3DC2=3DA0I didn&#39;t think so.<br>
>> ><br>
>> >My compiler is much happier with the following changes I already outlin= >> ed:<=3D
>> >br>
>> ><br>
>> >1. a dirty, disgusting hack to keep from locking against myself going f= >> rom =3D
>> >XWait with self.mutex locked to m.release().<br>
>> ><br>
>> >2. the change to LockHeap I described in previous email<br>
>> ><br>
>> >But now...<br>
>> ><br>
>> >(gdb) cont<br>
>> >Continuing.<br>
>> >ERROR: pthread_mutex_lock:11<br>
>> >ERROR: pthread_mutex_lock:11<br>
>> ><br>
>> >Program received signal SIGABRT, Aborted.<br>
>> >0x000000080107626a in thr_kill () from /lib/libc.so.7<br>
>> >(gdb) where<br>
>> >#0 =3DC2=3DA00x000000080107626a in thr_kill () from /lib/libc.so.7<b= >> r>
>> >#1 =3DC2=3DA00x000000080113dac9 in abort () from /lib/libc.so.7<br&g= >> t;
>> >#2 =3DC2=3DA00x000000000071e37a in ThreadPThread__pthread_mutex_lock (m= >> utex=3D3DE=3D
>> >rror accessing memory address 0x8000ffffb508: Bad address.<br>>> >> >) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>> >#3 =3DC2=3DA00x000000000071d48d in RTOS__LockHeap () at ../src/thread/P= >> THREAD/T=3D
>> >hreadPThread.m3:1377<br>
>> >#4 =3DC2=3DA00x0000000000706b9d in RTHooks__CheckLoadTracedRef (M3_Af40= >> ku_ref=3D
>> >=3D3DError accessing memory address 0x8000ffffb568: Bad address.<br&= >> gt;
>> >) at ../src/runtime/common/RTCollector.m3:2234<br>
>> >#5 =3DC2=3DA00x000000000071d284 in ThreadPThread__AtForkParent () at ..= >> /src/thr=3D
>> >ead/PTHREAD/ThreadPThread.m3:1348<br>
>> >#6 =3DC2=3DA00x0000000800df8733 in fork () from /lib/libthr.so.3<br&= >> gt;
>> >#7 =3DC2=3DA00x000000000070dd8b in RTProcess__Fork () at ../src/runtime= >> /common/=3D
>> >RTProcessC.c:152<br>
>> >#8 =3DC2=3DA00x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec = >> (M3_Bd56=3D
>> >fi_cmd=3D3DError accessing memory address 0x8000ffffb6f8: Bad address.&= >> lt;br>
>> >) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>> >#9 =3DC2=3DA00x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3D3DE= >> rror acces=3D
>> >sing memory address 0x8000ffffb7f8: Bad address.<br>
>> >) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>> >#10 0x00000000004d6826 in QMachine__FulfilExecPromise (M3_D6rRrg_ep=3D3= >> DError=3D
>> > accessing memory address 0x8000ffffb838: Bad address.<br>
>> >) at ../src/QMachine.m3:1666<br>
>> >#11 0x00000000004d6220 in QMachine__ExecCommand (M3_An02H2_t=3D3DError = >> access=3D
>> >ing memory address 0x8000ffffb9f8: Bad address.<br>
>> >) at ../src/QMachine.m3:1605<br>
>> >#12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3D3DError ac= >> cessin=3D
>> >g memory address 0x8000ffffbee8: Bad address.<br>
>> >) at ../src/QMachine.m3:1476<br>
>> ><br>
>> >What am I doing wrong here?<br>
>> ><br>
>> >The error doesn&#39;t look unreasonable! =3DC2=3DA0Looking more clo= >> sely at the =3D
>> >code:<br>
>> ><br>
>> >First, AtForkPrepare has been called:<br>
>> ><br>
>> >PROCEDURE AtForkPrepare() =3D3D<br>
>> >=3DC2=3DA0 VAR me :=3D3D GetActivation();<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;<br>
>> >=3DC2=3DA0 BEGIN<br>
>> >=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(slotsMu, ThisLine());<br><= >> br> >> >=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(perfMu, ThisLine());<br>> r> >> >=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(initMu, ThisLine()); (* InitMute= >> x =3D3D&gt; Re=3D
>> >gisterFinalCleanup =3D3D&gt; LockHeap *)<br>
>> >=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(heapMu, ThisLine());<br>> r> >> >=3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(activeMu, ThisLine()); (* LockHe= >> ap =3D3D&gt; S=3D
>> >uspendOthers =3D3D&gt; activeMu *)<br>
>> >=3DC2=3DA0 =3DC2=3DA0 (* Walk activations and lock all threads.<br&g= >> t;
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* NOTE: We have initMu, activeMu, so sl= >> ots won&#39;t ch=3D
>> >ange, conditions and<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* mutexes won&#39;t be initialized = >> on-demand.<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0*)<br>
>> >=3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;<br>
>> >=3DC2=3DA0 =3DC2=3DA0 REPEAT<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(act.mutex, ThisLine()= >> );<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;<br>
>> >=3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;<br>
>> >=3DC2=3DA0 END AtForkPrepare;<br>
>> ><br>
>> >a postcondition of this routine is that heapMu is locked.<br>
>> ><br>
>> >now we get into AtForkParent:<br>
>> ><br>
>> >PROCEDURE AtForkParent() =3D3D<br>
>> >=3DC2=3DA0 VAR me :=3D3D GetActivation();<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond: Condition;<br>
>> >=3DC2=3DA0 BEGIN<br>
>> >=3DC2=3DA0 =3DC2=3DA0 (* Walk activations and unlock all threads, condi= >> tions. *)<br=3D
>> >>
>> >=3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;<br>
>> >=3DC2=3DA0 =3DC2=3DA0 REPEAT<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond :=3D3D slots[act.slot].join;<b= >> r>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 IF cond # NIL THEN PThreadUnlockMutex(= >> cond.mutex, This=3D
>> >Line()) END;<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(act.mutex, ThisLine= >> ());<br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;<br>
>> >=3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;<br>
>> >=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(activeMu, ThisLine());<br&g= >> t;
>> >=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(heapMu, ThisLine());<br>= >>
>> >=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(initMu, ThisLine());<br>= >>
>> >=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(perfMu, ThisLine());<br>= >>
>> >=3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(slotsMu, ThisLine());<br>= >> ;
>> >=3DC2=3DA0 END AtForkParent;<br>
>> ><br>
>> >We can see by inspecting the code that a necessary precondition for<= >> br>
>> >this routine is that heapMu is locked! =3DC2=3DA0(Since it&#39;s go= >> ing to unloc=3D
>> >k it,<br>
>> >it had BETTER be locked on entry.)<br>
>> ><br>
>> >But the cond :=3D3D ... causes a RTHooks.CheckLoadTracedRef<br>> r> >> ><br>
>> >which causes an RTOS.LockHeap<br>
>> ><br>
>> >the code of which we just saw:<br>
>> ><br>
>> >PROCEDURE LockHeap () =3D3D<br>
>> >=3DC2=3DA0 VAR self :=3D3D pthread_self();<br>
>> >=3DC2=3DA0 BEGIN<br>
>> >=3DC2=3DA0 =3DC2=3DA0 WITH r =3D3D pthread_mutex_lock(heapMu,ThisLine()= >> ) DO &lt;*ASSE=3D
>> >RT r=3D3D0*&gt; END;<br>
>> >...<br>
>> ><br>
>> >we try to lock heapMu. =3DC2=3DA0kaboom! =3DC2=3DA0No surprise there, r= >> eally?<br>
>> ><br>
>> >Am I going about this totally the wrong way? =3DC2=3DA0Other people are= >> running=3D
>> > Modula-3<br>
>> >with pthreads, right? =3DC2=3DA0Right?? =3DC2=3DA0Somewhere out there i= >> n m3devel-la=3D
>> >nd?<br>
>> ><span><font color=3D3D"#888888"><br>
>> >=3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika<br>
>> ><br>
>> ></font></span></blockquote></div><br><= >> /div></div>
>> >
>> >--001a11c2ced4471a2e050079db82--
>>

>>

>> >> --089e01183a1813188705007c3498-- From hosking at cs.purdue.edu Wed Aug 13 18:40:22 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Wed, 13 Aug 2014 12:40:22 -0400 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: <20140813163735.8D0701A2097@async.async.caltech.edu> References: <20140813021401.238B31A2094@async.async.caltech.edu> <20140813045415.C13921A2094@async.async.caltech.edu> <20140813063041.286EA1A2094@async.async.caltech.edu> <97266593-618F-458D-A975-FE01D9BF19F9@cs.purdue.edu> <20140813163735.8D0701A2097@async.async.caltech.edu> Message-ID: <7A6EF7C5-9B0F-4FC5-BCB1-C7A0E36BB2D6@cs.purdue.edu> On Aug 13, 2014, at 12:37 PM, mika at async.caltech.edu wrote: > 1.262 > > Short summary: 1.262 seems to work fine on AMD64_LINUX except for the > fork issue (a bummer because my parallelization of the backends of cm3 > uses fork a lot...and it does speed up the compiler significantly if > you have fast disks and lots of cores) It does the attached on AMD64_FREEBSD. Yes, that was the state of things. Subsequent revs were to address fork issues. > > I see the intent of what you were doing in later version/s, but it was > a bit rough, I think... I think the three issues I reported (1. locking > heapMu from AtFork; 2. the try-only-once bug in LockHeap itself; 3. not > passing the lock to release from Wait) are all more or less real. Working on these right now. Sorry for hacked versions ? no time right now to do real testing before push. Getting closer now I think. > > Mika > > Tony Hosking writes: >> Which revision of ThreadPThread.m3 is this output from? >> >> On Aug 13, 2014, at 2:30 AM, mika at async.caltech.edu wrote: >> >>> =20 >>> OK... deleted all the derived directories and rebuilt. Result on = >> FreeBSD is similar (or identical, hard to tell): >>> =20 >>> I get a partial deadlock: >>> =20 >>> PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU = >> COMMAND >>> 48760 root 98 0 87836K 29104K CPU1 1 12:32 83.89% = >> threadtest{threadtest} >>> 48760 root 94 0 87836K 29104K CPU3 3 11:02 74.66% = >> threadtest{threadtest} >>> 48760 root 94 0 87836K 29104K CPU0 0 11:03 71.97% = >> threadtest{threadtest} >>> 48760 root 32 0 87836K 29104K umtxn 2 0:01 0.00% = >> threadtest{threadtest} >>> 48760 root 20 0 87836K 29104K umtxn 2 0:01 0.00% = >> threadtest{threadtest} >>> 48760 root 35 0 87836K 29104K uwait 2 0:01 0.00% = >> threadtest{threadtest} >>> 48760 root 27 0 87836K 29104K uwait 0 0:01 0.00% = >> threadtest{threadtest} >>> 48760 root 27 0 87836K 29104K umtxn 3 0:01 0.00% = >> threadtest{threadtest} >>> 48760 root 27 0 87836K 29104K umtxn 2 0:01 0.00% = >> threadtest{threadtest} >>> 48760 root 20 0 87836K 29104K umtxn 0 0:00 0.00% = >> threadtest{threadtest} >>> 48759 root 20 0 30276K 11064K wait 0 0:00 0.00% gdb >>> =20 >>> one of the dead threads is the main thread, so now output. But three >>> threads are still alive, interestingly enough. >>> =20 >>> Looks like the same issue as before: >>> =20 >>> Thread 5 (Thread 801807400 (LWP 100751/threadtest)): >>> #0 0x0000000800ae089c in __error () from /lib/libthr.so.3 >>> #1 0x0000000800ad6261 in pthread_suspend_np () from /lib/libthr.so.3 >>> #2 0x00000000004511bc in ThreadPThread__SuspendThread (mt=3DError = >> accessing memory address 0x8000ff5faa28: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>> #3 0x000000000044ed8e in ThreadPThread__StopThread = >> (M3_DMxDjQ_act=3DError accessing memory address 0x8000ff5faa48: Bad = >> address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>> #4 0x000000000044ef31 in ThreadPThread__StopWorld () at = >> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>> #5 0x000000000044e44e in RTThread__SuspendOthers () at = >> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>> #6 0x0000000000436386 in RTCollector__CollectSomeInStateZero () at = >> ../src/runtime/common/RTCollector.m3:749 >>> #7 0x0000000000436331 in RTCollector__CollectSome () at = >> ../src/runtime/common/RTCollector.m3:723 >>> #8 0x0000000000435ff9 in RTHeapRep__CollectEnough () at = >> ../src/runtime/common/RTCollector.m3:657 >>> #9 0x0000000000433233 in RTAllocator__AllocTraced = >> (M3_Cwb5VA_dataSize=3DError accessing memory address 0x8000ff5fac88: Bad = >> address. >>> ) at ../src/runtime/common/RTAllocator.m3:367 >>> #10 0x0000000000432b55 in RTAllocator__GetOpenArray = >> (M3_Eic7CK_def=3DError accessing memory address 0x8000ff5fad48: Bad = >> address. >>> ) at ../src/runtime/common/RTAllocator.m3:296 >>> #11 0x0000000000431e8f in RTHooks__AllocateOpenArray = >> (M3_AJWxb1_defn=3DError accessing memory address 0x8000ff5fada8: Bad = >> address. >>> ) at ../src/runtime/common/RTAllocator.m3:143 >>> #12 0x00000000004052ea in Main__AApply (M3_AP7a1g_cl=3DError accessing = >> memory address 0x8000ff5fade8: Bad address. >>> ) at ../src/Main.m3:283 >>> #13 0x000000000044d243 in ThreadPThread__RunThread (M3_DMxDjQ_me=3DError= >> accessing memory address 0x8000ff5faeb8: Bad address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>> #14 0x000000000044cf00 in ThreadPThread__ThreadBase = >> (M3_AJWxb1_param=3DError accessing memory address 0x8000ff5faf68: Bad = >> address. >>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>> #15 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>> #16 0x0000000000000000 in ?? () >>> =20 >>> Interestingly the same test seems to work on AMD64_LINUX. That is >>> promising, at least. But of course, software testing never reveals = >> the >>> absence of bugs. >>> =20 >>> Mika >>> =20 >>> Peter McKinna writes: >>>> --089e01183a1813188705007c3498 >>>> Content-Type: text/plain; charset=3DUTF-8 >>>> =20 >>>> Oh, one other thing that seemed to help me in testing this stuff = >> especially >>>> things to do with m3core and libm3 which seem to get out of whack >>>> sometimes, is to totally remove the target directory of m3core then = >> cm3; >>>> cm3 -ship Same with libm3. I'm not sure that clean actually removes = >> the >>>> targets and I think there are leftover files that stuff things up = >> since I >>>> would get segv in FileRd for no obvious reason. >>>> =20 >>>> Peter >>>> =20 >>>> =20 >>>> =20 >>>> On Wed, Aug 13, 2014 at 3:33 PM, Peter McKinna = >> >>>> wrote: >>>> =20 >>>>> That is weird. The thread tester works fine with the old version of >>>>> ThreadPThread.m3 on linux amd_64 except if you have the fork test in = >> the >>>>> mix of tests you see the pthread_mutex_destroy every now and again, = >> the >>>>> fork bug in fact. >>>>> I was testing the pthread changes Tony has made over the past few = >> days >>>>> using the thread tester program until I stupidly rebuilt the = >> compiler and >>>>> was getting all sorts of hangs as it dragged in the new version of >>>>> pthreads. So I rebuilt everything from a backup to get back where I = >> was >>>>> with a decent compiler, then reintroduced the latest changes to >>>>> ThreadPThread.m3, which yesterday was just hanging in sigsuspend but = >> today >>>>> is giving me an assert failure at line 1387 in UnlockHeap. So its a = >> bit >>>>> unstable to say the least. Maybe there is something else wrong with = >> freebsd. >>>>> =20 >>>>> Peter >>>>> =20 >>>>> =20 >>>>> =20 >>>>> On Wed, Aug 13, 2014 at 2:54 PM, wrote: >>>>> =20 >>>>>> =20 >>>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not = >> getting >>>>>> things to work and now I'm really baffled because I think I = >> understand >>>>>> this code! >>>>>> =20 >>>>>> What I did was I threw away all my changes and reverted = >> ThreadPThread.m3 >>>>>> to 1.262 as you suggested. >>>>>> =20 >>>>>> Rebuilt the compiler with upgrade.sh >>>>>> =20 >>>>>> Then rebuilt the compiler again with itself. >>>>>> =20 >>>>>> Then I realcleaned the world and buildshipped it. (I was afraid >>>>>> that parseparams, also imported by the thread tester, would pollute >>>>>> it somehow.) >>>>>> =20 >>>>>> When I look at the code in 1.262 it looks quite straightforward. = >> heapMu >>>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. >>>>>> Condition >>>>>> variables are mutexes too, but that's no big deal. >>>>>> =20 >>>>>> So, rebuild thread tester, run it: >>>>>> =20 >>>>>> new source -> compiling Main.m3 >>>>>> -> linking threadtest >>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # >>>>>> AMD64_FREEBSD/threadtest >>>>>> Writing file...done >>>>>> Creating read threads...done >>>>>> Creating fork threads...done >>>>>> Creating alloc threads...done >>>>>> Creating lock threads...done >>>>>> running...printing oldest/median age/newest >>>>>> . >>>>>> =20 >>>>>> *** >>>>>> *** runtime error: >>>>>> *** Segmentation violation - possible attempt to dereference >>>>>> NIL.........laziest thread is 1407901189/1407901189/9 (tests: read >>>>>> 1407901189/1407901189/1407901189 fork = >> 1407901189/1407901189/1407901189 >>>>>> alloc 9/9/9 lock 1407901189/1407901189/9) >>>>>> =20 >>>>>> =20 >>>>>> =20 >>>>>> =20 >>>>>> ^C >>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb = >> !$ >>>>>> gdb AMD64_FREEBSD/threadtest >>>>>> GNU gdb 6.1.1 [FreeBSD] >>>>>> Copyright 2004 Free Software Foundation, Inc. >>>>>> GDB is free software, covered by the GNU General Public License, = >> and you >>>>>> are >>>>>> welcome to change it and/or distribute copies of it under certain >>>>>> conditions. >>>>>> Type "show copying" to see the conditions. >>>>>> There is absolutely no warranty for GDB. Type "show warranty" for >>>>>> details. >>>>>> This GDB was configured as "amd64-marcel-freebsd"... >>>>>> (gdb) run >>>>>> Starting program: >>>>>> = >> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/th= >> readtest >>>>>> [New LWP 100121] >>>>>> Writing file...done >>>>>> Creating read threads...done >>>>>> Creating fork threads...done >>>>>> Creating alloc threads...done >>>>>> Creating lock threads...done >>>>>> running...printing oldest/median age/newest >>>>>> .[New Thread 801807000 (LWP 100343/threadtest)] >>>>>> [New Thread 801807c00 (LWP 100667/threadtest)] >>>>>> [New Thread 801808800 (LWP 100816/threadtest)] >>>>>> [New Thread 801807400 (LWP 100349/threadtest)] >>>>>> [New Thread 801808400 (LWP 100815/threadtest)] >>>>>> [New Thread 801807800 (LWP 100352/threadtest)] >>>>>> [New Thread 801808c00 (LWP 100817/threadtest)] >>>>>> [New Thread 801809000 (LWP 100818/threadtest)] >>>>>> [New Thread 801809800 (LWP 100820/threadtest)] >>>>>> [New Thread 801808000 (LWP 100678/threadtest)] >>>>>> [New Thread 801806400 (LWP 100121/threadtest)] >>>>>> [New Thread 801806800 (LWP 100341/threadtest)] >>>>>> [New Thread 801806c00 (LWP 100342/threadtest)] >>>>>> .ERROR: pthread_mutex_lock:11 >>>>>> =20 >>>>>> Program received signal SIGABRT, Aborted. >>>>>> [Switching to Thread 801809800 (LWP 100820/threadtest)] >>>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>> (gdb) where >>>>>> #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>> #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 >>>>>> #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock = >> (mutex=3DError >>>>>> accessing memory address 0x8000fe5f2d98: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 >>>>>> #3 0x000000000044b370 in ThreadPThread__LockMutex = >> (M3_AYIbX3_m=3DError >>>>>> accessing memory address 0x8000fe5f2dc8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>> #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3DError = >> accessing >>>>>> memory address 0x8000fe5f2df8: Bad address. >>>>>> ) at ../src/Main.m3:319 >>>>>> #5 0x000000000044d243 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3DError >>>>>> accessing memory address 0x8000fe5f2eb8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>> #6 0x000000000044cf00 in ThreadPThread__ThreadBase >>>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000fe5f2f68: = >> Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>> #7 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>>>> #8 0x0000000000000000 in ?? () >>>>>> (gdb) set lang c >>>>>> (gdb) thread apply all bt >>>>>> ... not that interesting ... >>>>>> =20 >>>>>> Segfault is segfault---error 11 is EDEADLK (locking against = >> myself?) >>>>>> =20 >>>>>> ????? the code is very straightforward, as I said. >>>>>> =20 >>>>>> I thought people had the thread tester working with pthreads? = >> Which set >>>>>> of files, then? Anyone on FreeBSD/amd64? >>>>>> =20 >>>>>> Could it be an issue with "volatile"? Not even sure where to look. >>>>>> =20 >>>>>> The code calling the lock is just this: >>>>>> =20 >>>>>> PROCEDURE GetChar (rd: T): CHAR >>>>>> RAISES {EndOfFile, Failure, Alerted} =3D >>>>>> BEGIN >>>>>> LOCK rd DO >>>>>> RETURN FastGetChar(rd); >>>>>> END >>>>>> END GetChar; >>>>>> =20 >>>>>> No mysteries there... >>>>>> =20 >>>>>> Ah is this the fork bug? Looks like the Init routine is called on = >> a >>>>>> lot of NIL mutexes around the fork. But the subprocesses aren't = >> meant >>>>>> to accesses the mutexes... humm >>>>>> =20 >>>>>> Hmm, and it's not entirely a fork issue. Even with "threadtest = >> -tests >>>>>> STD,-fork,-forktoomuch" it misbehaves. Hangs.... >>>>>> =20 >>>>>> Looks like a deadlock this time. >>>>>> =20 >>>>>> Some stacks... >>>>>> =20 >>>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): >>>>>> #0 0x00000000004b4e2b in __vdso_gettimeofday () >>>>>> #1 0x00000000004ab8d2 in gettimeofday () >>>>>> #2 0x0000000000452e4b in TimePosix__Now () at >>>>>> ../src/time/POSIX/TimePosixC.c:50 >>>>>> #3 0x0000000000452d72 in Time__Now () at >>>>>> ../src/time/POSIX/TimePosix.m3:14 >>>>>> #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3DError = >> accessing >>>>>> memory address 0x8000fedf6df8: Bad address. >>>>>> ) at ../src/Main.m3:327 >>>>>> #5 0x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3DError >>>>>> accessing memory address 0x8000fedf6eb8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>> #6 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000fedf6f68: = >> Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>> #7 0x000000000047c7d4 in thread_start () >>>>>> #8 0x0000000000000000 in ?? () >>>>>> =20 >>>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): >>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >> (mutex=3DError >>>>>> accessing memory address 0x8000feff7d98: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>> #4 0x00000000004480c0 in ThreadPThread__LockMutex = >> (M3_AYIbX3_m=3DError >>>>>> accessing memory address 0x8000feff7dc8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>> #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3DError = >> accessing >>>>>> memory address 0x8000feff7df8: Bad address. >>>>>> ) at ../src/Main.m3:319 >>>>>> #6 0x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3DError >>>>>> accessing memory address 0x8000feff7eb8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>> #7 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000feff7f68: = >> Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>> #8 0x000000000047c7d4 in thread_start () >>>>>> #9 0x0000000000000000 in ?? () >>>>>> =20 >>>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): >>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>> #1 0x0000000000475759 in suspend_common () >>>>>> #2 0x00000000004755c1 in pthread_suspend_np () >>>>>> #3 0x000000000044df0c in ThreadPThread__SuspendThread (mt=3DError >>>>>> accessing memory address 0x8000ffbfd6f8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>>>> #4 0x000000000044bade in ThreadPThread__StopThread = >> (M3_DMxDjQ_act=3DError >>>>>> accessing memory address 0x8000ffbfd718: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>>>> #5 0x000000000044bc81 in ThreadPThread__StopWorld () at >>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>>>> #6 0x000000000044b19e in RTThread__SuspendOthers () at >>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>>>> #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero () at >>>>>> ../src/runtime/common/RTCollector.m3:749 >>>>>> #8 0x0000000000433081 in RTCollector__CollectSome () at >>>>>> ../src/runtime/common/RTCollector.m3:723 >>>>>> #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at >>>>>> ../src/runtime/common/RTCollector.m3:657 >>>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced >>>>>> (M3_Cwb5VA_dataSize=3DError accessing memory address = >> 0x8000ffbfd958: Bad >>>>>> address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray = >> (M3_Eic7CK_def=3DError >>>>>> accessing memory address 0x8000ffbfda18: Bad address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>> (M3_AJWxb1_defn=3DError accessing memory address 0x8000ffbfda78: = >> Bad address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3DError = >> accessing >>>>>> memory address 0x8000ffbfdab8: Bad address. >>>>>> ) at ../src/rw/Rd.m3:159 >>>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=3DError= >> >>>>>> accessing memory address 0x8000ffbfdb88: Bad address. >>>>>> ) at ../src/rw/Rd.m3:187 >>>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3DError = >> accessing >>>>>> memory address 0x8000ffbfdbd8: Bad address. >>>>>> ) at ../src/rw/Rd.m3:176 >>>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3DError = >> accessing >>>>>> memory address 0x8000ffbfdc58: Bad address. >>>>>> ) at ../src/Main.m3:185 >>>>>> =20 >>>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3DError >>>>>> accessing memory address 0x8000ffbfdeb8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000ffbfdf68: = >> Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>> #19 0x000000000047c7d4 in thread_start () >>>>>> #20 0x0000000000000000 in ?? () >>>>>> =20 >>>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): >>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >> (mutex=3DError >>>>>> accessing memory address 0x8000ffffc678: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>> #4 0x000000000044d039 in RTOS__LockHeap () at >>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>> ---Type to continue, or q to quit--- >>>>>> #5 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>> (M3_Cwb5VA_dataSize=3DError accessing memory address = >> 0x8000ffffc6e8: Bad >>>>>> address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>> #6 0x000000000042f15b in RTAllocator__GetTracedObj = >> (M3_Eic7CK_def=3DError >>>>>> accessing memory address 0x8000ffffc7a8: Bad address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:224 >>>>>> #7 0x000000000042eb23 in RTHooks__AllocateTracedObj >>>>>> (M3_AJWxb1_defn=3DError accessing memory address 0x8000ffffc7f8: = >> Bad address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:122 >>>>>> #8 0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=3DError = >> accessing >>>>>> memory address 0x8000ffffc858: Bad address. >>>>>> ) at ../src/text/TextCat.m3:562 >>>>>> #9 0x000000000045ed5d in TextCat__Balance = >> (M3_Bd56fi_LText=3D0x800c490b0, >>>>>> M3_BUgnwf_LInfo=3DError accessing memory address 0x8000ffffc8f8: = >> Bad address. >>>>>> ) at ../src/text/TextCat.m3:488 >>>>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3DError = >> accessing >>>>>> memory address 0x8000ffffcbb8: Bad address. >>>>>> ) at ../src/text/TextCat.m3:40 >>>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3DError accessing = >> memory >>>>>> address 0x8000ffffcc38: Bad address. >>>>>> ) at ../src/Main.m3:593 >>>>>> #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=3DError >>>>>> accessing memory address 0x8000ffffcf88: Bad address. >>>>>> ) at ../src/runtime/common/RTLinker.m3:408 >>>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3DError = >> accessing >>>>>> memory address 0x8000ffffd008: Bad address. >>>>>> ) at ../src/runtime/common/RTLinker.m3:115 >>>>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3DError = >> accessing >>>>>> memory address 0x8000ffffd028: Bad address. >>>>>> ) at ../src/runtime/common/RTLinker.m3:124 >>>>>> #15 0x00000000004004a6 in main (argc=3DError accessing memory = >> address >>>>>> 0x8000ffffd07c: Bad address. >>>>>> ) at _m3main.c:22 >>>>>> =20 >>>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): >>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>> #1 0x0000000000477e8a in check_suspend () >>>>>> #2 0x00000000004780a2 in sigcancel_handler () >>>>>> #3 >>>>>> #4 0x000000000047e53c in _umtx_op_err () >>>>>> #5 0x0000000000475f14 in __thr_umutex_lock () >>>>>> #6 0x0000000000479404 in mutex_lock_common () >>>>>> #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >> (mutex=3DError >>>>>> accessing memory address 0x8000ff5fac18: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>> #8 0x000000000044d039 in RTOS__LockHeap () at >>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>> #9 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>> (M3_Cwb5VA_dataSize=3DError accessing memory address = >> 0x8000ff5fac88: Bad >>>>>> address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray = >> (M3_Eic7CK_def=3DError >>>>>> accessing memory address 0x8000ff5fad48: Bad address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>> (M3_AJWxb1_defn=3DError accessing memory address 0x8000ff5fada8: = >> Bad address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3DError = >> accessing >>>>>> memory address 0x8000ff5fade8: Bad address. >>>>>> ) at ../src/Main.m3:283 >>>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3DError >>>>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>> (M3_AJWxb1_param=3DError accessing memory address 0x8000ff5faf68: = >> Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>> #15 0x000000000047c7d4 in thread_start () >>>>>> #16 0x0000000000000000 in ?? () >>>>>> =20 >>>>>> (others are similar) >>>>>> =20 >>>>>> Hmm looks like a FreeBSD issue now. It's here... >>>>>> =20 >>>>>> int >>>>>> __cdecl >>>>>> ThreadPThread__SuspendThread (m3_pthread_t mt) >>>>>> { >>>>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), >>>>>> "pthread_suspend_np"); >>>>>> return 1; >>>>>> } >>>>>> =20 >>>>>> Now this suspend can wait: >>>>>> =20 >>>>>> static int >>>>>> suspend_common(struct pthread *curthread, struct pthread *thread, >>>>>> int waitok) >>>>>> { >>>>>> uint32_t tmp; >>>>>> =20 >>>>>> while (thread->state !=3D PS_DEAD && >>>>>> !(thread->flags & THR_FLAGS_SUSPENDED)) { >>>>>> thread->flags |=3D THR_FLAGS_NEED_SUSPEND; >>>>>> /* Thread is in creation. */ >>>>>> if (thread->tid =3D=3D TID_TERMINATED) >>>>>> return (1); >>>>>> tmp =3D thread->cycle; >>>>>> _thr_send_sig(thread, SIGCANCEL); >>>>>> THR_THREAD_UNLOCK(curthread, thread); >>>>>> if (waitok) { >>>>>> _thr_umtx_wait_uint(&thread->cycle, tmp, = >> NULL, >>>>>> 0); <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>> } else { >>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>> return (0); >>>>>> } >>>>>> } >>>>>> =20 >>>>>> return (1); >>>>>> } >>>>>> =20 >>>>>> ... but what it can wait for I am not clear on. >>>>>> =20 >>>>>> Do things work better on Linux? >>>>>> =20 >>>>>> What is the status of the fork bug? Can it be worked around by = >> only >>>>>> forking via Process.Create with no mutexes held (outside of all = >> LOCK >>>>>> blocks)? >>>>>> =20 >>>>>> Mika >>>>>> =20 >>>>>> =20 >>>>>> =20 >>>>>> Peter McKinna writes: >>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>> Content-Type: text/plain; charset=3DUTF-8 >>>>>>> =20 >>>>>>> Mika >>>>>>> =20 >>>>>>> I think you need to back out Tony's changes to fix the fork bug, = >> at >>>>>> least >>>>>>> for now. Need to reload from cvs version 1.262 for = >> ThreadPThread.m3 If >>>>>>> you're using git you're on your own. >>>>>>> Do a cvs log ThreadPThread.m3 for an explanation for some of the = >> design >>>>>>> principles. >>>>>>> Also if you use gdb then you need to set lanc c before backtraces = >> so at >>>>>>> least you can see address names and values even if they are = >> contorted you >>>>>>> can extract the M3 name in the parm lists. Also in gdb thread = >> apply all >>>>>> bt >>>>>>> gives all thread backtraces which can be handy to see whose got = >> the locks >>>>>>> held. >>>>>>> =20 >>>>>>> Regards Peter >>>>>>> =20 >>>>>>> =20 >>>>>>> =20 >>>>>>> On Wed, Aug 13, 2014 at 12:14 PM, wrote: >>>>>>> =20 >>>>>>>> =20 >>>>>>>> Question... is there something odd about my pthreads? Are = >> pthreads >>>>>>>> normally reentrant? I didn't think so. >>>>>>>> =20 >>>>>>>> My compiler is much happier with the following changes I already >>>>>> outlined: >>>>>>>> =20 >>>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >> going >>>>>> from >>>>>>>> XWait with self.mutex locked to m.release(). >>>>>>>> =20 >>>>>>>> 2. the change to LockHeap I described in previous email >>>>>>>> =20 >>>>>>>> But now... >>>>>>>> =20 >>>>>>>> (gdb) cont >>>>>>>> Continuing. >>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>> =20 >>>>>>>> Program received signal SIGABRT, Aborted. >>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>> (gdb) where >>>>>>>> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >>>>>>>> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock >>>>>> (mutex=3DError >>>>>>>> accessing memory address 0x8000ffffb508: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >>>>>>>> #3 0x000000000071d48d in RTOS__LockHeap () at >>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >>>>>>>> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>>>> (M3_Af40ku_ref=3DError >>>>>>>> accessing memory address 0x8000ffffb568: Bad address. >>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234 >>>>>>>> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >>>>>>>> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >>>>>>>> #7 0x000000000070dd8b in RTProcess__Fork () at >>>>>>>> ../src/runtime/common/RTProcessC.c:152 >>>>>>>> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>>>>>>> (M3_Bd56fi_cmd=3DError accessing memory address 0x8000ffffb6f8: = >> Bad >>>>>> address. >>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >>>>>>>> #9 0x00000000006c6c6c in Process__Create (M3_Bd56fi_cmd=3DError >>>>>> accessing >>>>>>>> memory address 0x8000ffffb7f8: Bad address. >>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21 >>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>> (M3_D6rRrg_ep=3DError >>>>>>>> accessing memory address 0x8000ffffb838: Bad address. >>>>>>>> ) at ../src/QMachine.m3:1666 >>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand = >> (M3_An02H2_t=3DError >>>>>>>> accessing memory address 0x8000ffffb9f8: Bad address. >>>>>>>> ) at ../src/QMachine.m3:1605 >>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3DError >>>>>> accessing >>>>>>>> memory address 0x8000ffffbee8: Bad address. >>>>>>>> ) at ../src/QMachine.m3:1476 >>>>>>>> =20 >>>>>>>> What am I doing wrong here? >>>>>>>> =20 >>>>>>>> The error doesn't look unreasonable! Looking more closely at the = >> code: >>>>>>>> =20 >>>>>>>> First, AtForkPrepare has been called: >>>>>>>> =20 >>>>>>>> PROCEDURE AtForkPrepare() =3D >>>>>>>> VAR me :=3D GetActivation(); >>>>>>>> act: Activation; >>>>>>>> BEGIN >>>>>>>> PThreadLockMutex(slotsMu, ThisLine()); >>>>>>>> PThreadLockMutex(perfMu, ThisLine()); >>>>>>>> PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D> >>>>>>>> RegisterFinalCleanup =3D> LockHeap *) >>>>>>>> PThreadLockMutex(heapMu, ThisLine()); >>>>>>>> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap =3D> >>>>>> SuspendOthers >>>>>>>> =3D> activeMu *) >>>>>>>> (* Walk activations and lock all threads. >>>>>>>> * NOTE: We have initMu, activeMu, so slots won't change, >>>>>> conditions >>>>>>>> and >>>>>>>> * mutexes won't be initialized on-demand. >>>>>>>> *) >>>>>>>> act :=3D me; >>>>>>>> REPEAT >>>>>>>> PThreadLockMutex(act.mutex, ThisLine()); >>>>>>>> act :=3D act.next; >>>>>>>> UNTIL act =3D me; >>>>>>>> END AtForkPrepare; >>>>>>>> =20 >>>>>>>> a postcondition of this routine is that heapMu is locked. >>>>>>>> =20 >>>>>>>> now we get into AtForkParent: >>>>>>>> =20 >>>>>>>> PROCEDURE AtForkParent() =3D >>>>>>>> VAR me :=3D GetActivation(); >>>>>>>> act: Activation; >>>>>>>> cond: Condition; >>>>>>>> BEGIN >>>>>>>> (* Walk activations and unlock all threads, conditions. *) >>>>>>>> act :=3D me; >>>>>>>> REPEAT >>>>>>>> cond :=3D slots[act.slot].join; >>>>>>>> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, = >> ThisLine()) >>>>>> END; >>>>>>>> PThreadUnlockMutex(act.mutex, ThisLine()); >>>>>>>> act :=3D act.next; >>>>>>>> UNTIL act =3D me; >>>>>>>> PThreadUnlockMutex(activeMu, ThisLine()); >>>>>>>> PThreadUnlockMutex(heapMu, ThisLine()); >>>>>>>> PThreadUnlockMutex(initMu, ThisLine()); >>>>>>>> PThreadUnlockMutex(perfMu, ThisLine()); >>>>>>>> PThreadUnlockMutex(slotsMu, ThisLine()); >>>>>>>> END AtForkParent; >>>>>>>> =20 >>>>>>>> We can see by inspecting the code that a necessary precondition = >> for >>>>>>>> this routine is that heapMu is locked! (Since it's going to = >> unlock it, >>>>>>>> it had BETTER be locked on entry.) >>>>>>>> =20 >>>>>>>> But the cond :=3D ... causes a RTHooks.CheckLoadTracedRef >>>>>>>> =20 >>>>>>>> which causes an RTOS.LockHeap >>>>>>>> =20 >>>>>>>> the code of which we just saw: >>>>>>>> =20 >>>>>>>> PROCEDURE LockHeap () =3D >>>>>>>> VAR self :=3D pthread_self(); >>>>>>>> BEGIN >>>>>>>> WITH r =3D pthread_mutex_lock(heapMu,ThisLine()) DO <*ASSERT = >> r=3D0*> >>>>>> END; >>>>>>>> ... >>>>>>>> =20 >>>>>>>> we try to lock heapMu. kaboom! No surprise there, really? >>>>>>>> =20 >>>>>>>> Am I going about this totally the wrong way? Other people are = >> running >>>>>>>> Modula-3 >>>>>>>> with pthreads, right? Right?? Somewhere out there in = >> m3devel-land? >>>>>>>> =20 >>>>>>>> Mika >>>>>>>> =20 >>>>>>>> =20 >>>>>>> =20 >>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>> Content-Type: text/html; charset=3DUTF-8 >>>>>>> Content-Transfer-Encoding: quoted-printable >>>>>>> =20 >>>>>>>
Mika

=3DC2=3DA0 I think you = >> need to back >>>>>> ou=3D >>>>>>> t Tony's changes to fix the fork bug, at least for now. Need = >> to >>>>>> reload =3D >>>>>>> from cvs version 1.262 for ThreadPThread.m3 If you're using = >> git >>>>>> you'=3D >>>>>>> ;re on your own.
>>>>>>> =20 >>>>>>>
=3DC2=3DA0 Do a cvs log ThreadPThread.m3 for an explanation = >> for some of >>>>>> th=3D >>>>>>> e design principles.=3DC2=3DA0
=3DC2=3DA0 Also if you = >> use gdb then you >>>>>> ne=3D >>>>>>> ed to set lanc c before backtraces so at least you can see address = >> names >>>>>> an=3D >>>>>>> d values even if they are contorted you can extract the M3 name in = >> the >>>>>> parm=3D >>>>>>> lists. Also in gdb thread apply all bt gives all thread backtraces >>>>>> which c=3D >>>>>>> an be handy to see whose got the locks held.
>>>>>>> =20 >>>>>>>

Regards Peter

>>>>> class=3D3D"gmail_e=3D >>>>>>> xtra">

On Wed, Aug 13, 2014 at = >> 12:14 >>>>>> PM, =3D >>>>>>> <>>>>> target=3D3D"=3D >>>>>>> _blank">mika at async.caltech.edu> wrote:
>>>>>>> =20 >>>>>>>
>>>>> .8ex;border-left:1p=3D >>>>>>> x #ccc solid;padding-left:1ex">
>>>>>>> Question... is there something odd about my pthreads? =3DC2=3DA0Are = >> pthreads >>>>>> no=3D >>>>>>> rmally reentrant? =3DC2=3DA0I didn't think so.
>>>>>>>
>>>>>>> My compiler is much happier with the following changes I already >>>>>> outlined:<=3D >>>>>>> br> >>>>>>>
>>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >> going >>>>>> from =3D >>>>>>> XWait with self.mutex locked to m.release().
>>>>>>>
>>>>>>> 2. the change to LockHeap I described in previous email
>>>>>>>
>>>>>>> But now...
>>>>>>>
>>>>>>> (gdb) cont
>>>>>>> Continuing.
>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>>
>>>>>>> Program received signal SIGABRT, Aborted.
>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>>>> (gdb) where
>>>>>>> #0 =3DC2=3DA00x000000080107626a in thr_kill () from = >> /lib/libc.so.7
>>>>>>> #1 =3DC2=3DA00x000000080113dac9 in abort () from = >> /lib/libc.so.7
>>>>>>> #2 =3DC2=3DA00x000000000071e37a in = >> ThreadPThread__pthread_mutex_lock >>>>>> (mutex=3D3DE=3D >>>>>>> rror accessing memory address 0x8000ffffb508: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>>>> #3 =3DC2=3DA00x000000000071d48d in RTOS__LockHeap () at >>>>>> ../src/thread/PTHREAD/T=3D >>>>>>> hreadPThread.m3:1377
>>>>>>> #4 =3DC2=3DA00x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>>>> (M3_Af40ku_ref=3D >>>>>>> =3D3DError accessing memory address 0x8000ffffb568: Bad = >> address.
>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>>>> #5 =3DC2=3DA00x000000000071d284 in ThreadPThread__AtForkParent () = >> at >>>>>> ../src/thr=3D >>>>>>> ead/PTHREAD/ThreadPThread.m3:1348
>>>>>>> #6 =3DC2=3DA00x0000000800df8733 in fork () from = >> /lib/libthr.so.3
>>>>>>> #7 =3DC2=3DA00x000000000070dd8b in RTProcess__Fork () at >>>>>> ../src/runtime/common/=3D >>>>>>> RTProcessC.c:152
>>>>>>> #8 =3DC2=3DA00x00000000006c52f2 in = >> ProcessPosixCommon__Create_ForkExec >>>>>> (M3_Bd56=3D >>>>>>> fi_cmd=3D3DError accessing memory address 0x8000ffffb6f8: Bad = >> address.
>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>>>> #9 =3DC2=3DA00x00000000006c6c6c in Process__Create = >> (M3_Bd56fi_cmd=3D3DError >>>>>> acces=3D >>>>>>> sing memory address 0x8000ffffb7f8: Bad address.
>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>> (M3_D6rRrg_ep=3D3DError=3D >>>>>>> accessing memory address 0x8000ffffb838: Bad address.
>>>>>>> ) at ../src/QMachine.m3:1666
>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand = >> (M3_An02H2_t=3D3DError >>>>>> access=3D >>>>>>> ing memory address 0x8000ffffb9f8: Bad address.
>>>>>>> ) at ../src/QMachine.m3:1605
>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec (M3_An02H2_t=3D3DError= >> >>>>>> accessin=3D >>>>>>> g memory address 0x8000ffffbee8: Bad address.
>>>>>>> ) at ../src/QMachine.m3:1476
>>>>>>>
>>>>>>> What am I doing wrong here?
>>>>>>>
>>>>>>> The error doesn't look unreasonable! =3DC2=3DA0Looking more = >> closely at >>>>>> the =3D >>>>>>> code:
>>>>>>>
>>>>>>> First, AtForkPrepare has been called:
>>>>>>>
>>>>>>> PROCEDURE AtForkPrepare() =3D3D
>>>>>>> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>>>>>> =3DC2=3DA0 BEGIN
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(slotsMu, ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(perfMu, ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(initMu, ThisLine()); (* = >> InitMutex =3D3D> >>>>>> Re=3D >>>>>>> gisterFinalCleanup =3D3D> LockHeap *)
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(heapMu, ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(activeMu, ThisLine()); (* = >> LockHeap >>>>>> =3D3D> S=3D >>>>>>> uspendOthers =3D3D> activeMu *)
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and lock all = >> threads.
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* NOTE: We have initMu, activeMu, = >> so slots won't >>>>>> ch=3D >>>>>>> ange, conditions and
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* mutexes won't be initialized = >> on-demand.
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0*)
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(act.mutex, = >> ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>>>>>> =3DC2=3DA0 END AtForkPrepare;
>>>>>>>
>>>>>>> a postcondition of this routine is that heapMu is locked.
>>>>>>>
>>>>>>> now we get into AtForkParent:
>>>>>>>
>>>>>>> PROCEDURE AtForkParent() =3D3D
>>>>>>> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond: Condition;
>>>>>>> =3DC2=3DA0 BEGIN
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and unlock all threads, = >> conditions. >>>>>> *)>>>>>>> =20 >>>>>>> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond :=3D3D = >> slots[act.slot].join;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 IF cond # NIL THEN = >> PThreadUnlockMutex(cond.mutex, >>>>>> This=3D >>>>>>> Line()) END;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(act.mutex, = >> ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(activeMu, = >> ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(heapMu, ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(initMu, ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(perfMu, ThisLine());
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(slotsMu, ThisLine());
>>>>>>> =3DC2=3DA0 END AtForkParent;
>>>>>>>
>>>>>>> We can see by inspecting the code that a necessary precondition = >> for
>>>>>>> this routine is that heapMu is locked! =3DC2=3DA0(Since it's = >> going to >>>>>> unloc=3D >>>>>>> k it,
>>>>>>> it had BETTER be locked on entry.)
>>>>>>>
>>>>>>> But the cond :=3D3D ... causes a RTHooks.CheckLoadTracedRef
>>>>>>>
>>>>>>> which causes an RTOS.LockHeap
>>>>>>>
>>>>>>> the code of which we just saw:
>>>>>>>
>>>>>>> PROCEDURE LockHeap () =3D3D
>>>>>>> =3DC2=3DA0 VAR self :=3D3D pthread_self();
>>>>>>> =3DC2=3DA0 BEGIN
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 WITH r =3D3D = >> pthread_mutex_lock(heapMu,ThisLine()) DO >>>>>> <*ASSE=3D >>>>>>> RT r=3D3D0*> END;
>>>>>>> ...
>>>>>>>
>>>>>>> we try to lock heapMu. =3DC2=3DA0kaboom! =3DC2=3DA0No surprise = >> there, really?
>>>>>>>
>>>>>>> Am I going about this totally the wrong way? =3DC2=3DA0Other = >> people are >>>>>> running=3D >>>>>>> Modula-3
>>>>>>> with pthreads, right? =3DC2=3DA0Right?? =3DC2=3DA0Somewhere out = >> there in >>>>>> m3devel-la=3D >>>>>>> nd?
>>>>>>>
>>>>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika
>>>>>>>
>>>>>>>

>>>>>>> =20 >>>>>>> --001a11c2ced4471a2e050079db82-- >>>>>> =20 >>>>> =20 >>>>> =20 >>>> =20 >>>> --089e01183a1813188705007c3498 >>>> Content-Type: text/html; charset=3DUTF-8 >>>> Content-Transfer-Encoding: quoted-printable >>>> =20 >>>>
Oh, one other thing that seemed to help me in = >> testing this=3D >>>> stuff especially things to do with m3core and libm3 which seem to get = >> out =3D >>>> of whack sometimes, is to totally remove the target directory of = >> m3core the=3D >>>> n cm3; cm3 -ship Same with libm3. I'm not sure that clean = >> actually remo=3D >>>> ves the targets and I think there are leftover files that stuff = >> things up s=3D >>>> ince I would get segv in FileRd for no obvious reason.
>>>>
Peter

> class=3D3D"gmail_extra"><=3D >>>> br>
On Wed, Aug 13, 2014 at 3:33 PM, = >> Peter Mc=3D >>>> Kinna <> href=3D3D"mailto:peter.mckinna at gmail.com" targ=3D >>>> et=3D3D"_blank">peter.mckinna at gmail.com> wrote:
>>>>
> .8ex;border-left:1p=3D >>>> x #ccc solid;padding-left:1ex">
That is weird. The = >> thread t=3D >>>> ester works fine with the old version of ThreadPThread.m3 on linux = >> amd_64 e=3D >>>> xcept if you have the fork test in the mix of tests you see the = >> pthread_mut=3D >>>> ex_destroy every now and again, the fork bug in fact.=3DC2=3DA0
>>>> =20 >>>> I was testing the pthread changes Tony has made over the past few = >> days usin=3D >>>> g the thread tester program until I stupidly rebuilt the compiler and = >> was g=3D >>>> etting all sorts of hangs as it dragged in the new version of = >> pthreads. So =3D >>>> I rebuilt everything from a backup to get back where I was with a = >> decent co=3D >>>> mpiler, then reintroduced the latest changes to ThreadPThread.m3, = >> which yes=3D >>>> terday was just hanging in sigsuspend but today is giving me an = >> assert fail=3D >>>> ure at line 1387 in UnlockHeap. So its a bit unstable to say the = >> least. May=3D >>>> be there is something else wrong with freebsd.
>>>> >>>> = >>

Peter

> clas=3D >>>> s=3D3D"HOEnZb">
> class=3D3D"gmail_extra">

>>> s=3D3D"gmail_quote">On Wed, Aug 13, 2014 at 2:54 PM, > dir=3D3D"ltr"><<=3D >>>> a href=3D3D"mailto:mika at async.caltech.edu" = >> target=3D3D"_blank">mika at async.calte=3D >>>> ch.edu> wrote:
>>>> =20 >>>>
> .8ex;border-left:1p=3D >>>> x #ccc solid;padding-left:1ex">
>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not = >> getting>>>> =20 >>>> things to work and now I'm really baffled because I think I = >> understand<=3D >>>> br> >>>> this code!
>>>>
>>>> What I did was I threw away all my changes and reverted = >> ThreadPThread.m3>>>> =20 >>>> to 1.262 as you suggested.
>>>>
>>>> Rebuilt the compiler with upgrade.sh
>>>>
>>>> Then rebuilt the compiler again with itself.
>>>>
>>>> Then I realcleaned the world and buildshipped it. =3DC2=3DA0(I was = >> afraid
>>>> that parseparams, also imported by the thread tester, would = >> pollute
>>>> it somehow.)
>>>>
>>>> When I look at the code in 1.262 it looks quite straightforward. = >> =3DC2=3DA0heap=3D >>>> Mu
>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. = >> =3DC2=3DA0Cond=3D >>>> ition
>>>> variables are mutexes too, but that's no big deal.
>>>>
>>>> So, rebuild thread tester, run it:
>>>>
>>>> new source -> compiling Main.m3
>>>> =3DC2=3DA0-> linking threadtest
>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # = >> AMD64_FREEB=3D >>>> SD/threadtest
>>>> Writing file...done
>>>> Creating read threads...done
>>>> Creating fork threads...done
>>>> Creating alloc threads...done
>>>> Creating lock threads...done
>>>> running...printing oldest/median age/newest
>>>> .
>>>>
>>>> ***
>>>> *** runtime error:
>>>> *** =3DC2=3DA0 =3DC2=3DA0Segmentation violation - possible attempt to = >> dereference N=3D >>>> IL.........laziest thread is 1407901189/> href=3D3D"tel:1407901189%2F9" valu=3D >>>> e=3D3D"+14079011899" target=3D3D"_blank">1407901189/9 (tests: = >> read 14079011=3D >>>> 89/1407901189/1407901189 fork 1407901189/1407901189/1407901189 alloc = >> 9/9/9 =3D >>>> lock 1407901189/1407901189/9)
>>>> =20 >>>> =20 >>>>
>>>>
>>>>
>>>>
>>>> ^C
>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb = >> !$
>>>> gdb AMD64_FREEBSD/threadtest
>>>> GNU gdb 6.1.1 [FreeBSD]
>>>> Copyright 2004 Free Software Foundation, Inc.
>>>> GDB is free software, covered by the GNU General Public License, and = >> you ar=3D >>>> e
>>>> welcome to change it and/or distribute copies of it under certain = >> condition=3D >>>> s.
>>>> Type "show copying" to see the conditions.
>>>> There is absolutely no warranty for GDB. =3DC2=3DA0Type "show = >> warranty&quo=3D >>>> t; for details.
>>>> This GDB was configured as "amd64-marcel-freebsd"...
>>>> (gdb) run
>>>> Starting program: = >> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread=3D >>>> /AMD64_FREEBSD/threadtest
>>>> [New LWP 100121]
>>>> Writing file...done
>>>> Creating read threads...done
>>>> Creating fork threads...done
>>>> Creating alloc threads...done
>>>> Creating lock threads...done
>>>> running...printing oldest/median age/newest
>>>> .[New Thread 801807000 (LWP 100343/threadtest)]
>>>> [New Thread 801807c00 (LWP 100667/threadtest)]
>>>> [New Thread 801808800 (LWP 100816/threadtest)]
>>>> [New Thread 801807400 (LWP 100349/threadtest)]
>>>> [New Thread 801808400 (LWP 100815/threadtest)]
>>>> [New Thread 801807800 (LWP 100352/threadtest)]
>>>> [New Thread 801808c00 (LWP 100817/threadtest)]
>>>> [New Thread 801809000 (LWP 100818/threadtest)]
>>>> [New Thread 801809800 (LWP 100820/threadtest)]
>>>> [New Thread 801808000 (LWP 100678/threadtest)]
>>>> [New Thread 801806400 (LWP 100121/threadtest)]
>>>> [New Thread 801806800 (LWP 100341/threadtest)]
>>>> [New Thread 801806c00 (LWP 100342/threadtest)]
>>>> .ERROR: pthread_mutex_lock:11
>>>>

>>>> Program received signal SIGABRT, Aborted.
>>>>
[Switching to Thread 801809800 (LWP 100820/threadtest)]
>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>>>> (gdb) where
>>>> #0 =3DC2=3DA00x0000000800d5c26a in thr_kill () from = >> /lib/libc.so.7
>>>> #1 =3DC2=3DA00x0000000800e23ac9 in abort () from /lib/libc.so.7
>>>> #2 =3DC2=3DA00x000000000045101f in ThreadPThread__pthread_mutex_lock = >> (mutex=3D3DE=3D >>>> rror accessing memory address 0x8000fe5f2d98: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
>>>> #3 =3DC2=3DA00x000000000044b370 in ThreadPThread__LockMutex = >> (M3_AYIbX3_m=3D3DErro=3D >>>> r accessing memory address 0x8000fe5f2dc8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>> #4 =3DC2=3DA00x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3D3DError= >> accessing=3D >>>> memory address 0x8000fe5f2df8: Bad address.
>>>> ) at ../src/Main.m3:319
>>>> #5 =3DC2=3DA00x000000000044d243 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3D3DErr=3D >>>> or accessing memory address 0x8000fe5f2eb8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>> #6 =3DC2=3DA00x000000000044cf00 in ThreadPThread__ThreadBase = >> (M3_AJWxb1_param=3D >>>> =3D3DError accessing memory address 0x8000fe5f2f68: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>> #7 =3DC2=3DA00x0000000800ad54a4 in pthread_create () from = >> /lib/libthr.so.3
>>>> #8 =3DC2=3DA00x0000000000000000 in ?? ()
>>>> (gdb) set lang c
>>>> (gdb) thread apply all bt
>>>> ... not that interesting ...
>>>>
>>>> Segfault is segfault---error 11 is EDEADLK (locking against = >> myself?)
>>>>
>>>> ????? the code is very straightforward, as I said.
>>>>
>>>> I thought people had the thread tester working with pthreads? = >> =3DC2=3DA0Which s=3D >>>> et of files, then? =3DC2=3DA0Anyone on FreeBSD/amd64?
>>>>
>>>> Could it be an issue with "volatile"? =3DC2=3DA0Not even = >> sure where t=3D >>>> o look.
>>>>
>>>> The code calling the lock is just this:
>>>>
>>>> PROCEDURE GetChar (rd: T): CHAR
>>>> =3DC2=3DA0 RAISES {EndOfFile, Failure, Alerted} =3D3D
>>>> =3DC2=3DA0 BEGIN
>>>> =3DC2=3DA0 =3DC2=3DA0 LOCK rd DO
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 RETURN FastGetChar(rd);
>>>> =3DC2=3DA0 =3DC2=3DA0 END
>>>> =3DC2=3DA0 END GetChar;
>>>>
>>>> No mysteries there...
>>>>
>>>> Ah is this the fork bug? =3DC2=3DA0Looks like the Init routine is = >> called on a>>> r> >>>> lot of NIL mutexes around the fork. =3DC2=3DA0But the subprocesses = >> aren't m=3D >>>> eant
>>>> to accesses the mutexes... humm
>>>>
>>>> Hmm, and it's not entirely a fork issue. =3DC2=3DA0Even with = >> "threadte=3D >>>> st -tests STD,-fork,-forktoomuch" it misbehaves. = >> =3DC2=3DA0Hangs....
>>>>
>>>> Looks like a deadlock this time.
>>>>
>>>> Some stacks...
>>>>
>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
>>>> #0 =3DC2=3DA00x00000000004b4e2b in __vdso_gettimeofday ()
>>>> #1 =3DC2=3DA00x00000000004ab8d2 in gettimeofday ()
>>>> #2 =3DC2=3DA00x0000000000452e4b in TimePosix__Now () at = >> ../src/time/POSIX/TimeP=3D >>>> osixC.c:50
>>>> #3 =3DC2=3DA00x0000000000452d72 in Time__Now () at = >> ../src/time/POSIX/TimePosix.=3D >>>> m3:14
>>>> #4 =3DC2=3DA00x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3D3DError= >> accessing=3D >>>> memory address 0x8000fedf6df8: Bad address.
>>>> ) at ../src/Main.m3:327
>>>> #5 =3DC2=3DA00x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3D3DErr=3D >>>> or accessing memory address 0x8000fedf6eb8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>> #6 =3DC2=3DA00x0000000000449c50 in ThreadPThread__ThreadBase = >> (M3_AJWxb1_param=3D >>>> =3D3DError accessing memory address 0x8000fedf6f68: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>> #7 =3DC2=3DA00x000000000047c7d4 in thread_start ()
>>>> #8 =3DC2=3DA00x0000000000000000 in ?? ()
>>>>
>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
>>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>>> #1 =3DC2=3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>> #2 =3DC2=3DA00x0000000000479404 in mutex_lock_common ()
>>>> #3 =3DC2=3DA00x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >> (mutex=3D3DE=3D >>>> rror accessing memory address 0x8000feff7d98: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>> #4 =3DC2=3DA00x00000000004480c0 in ThreadPThread__LockMutex = >> (M3_AYIbX3_m=3D3DErro=3D >>>> r accessing memory address 0x8000feff7dc8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>> #5 =3DC2=3DA00x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3D3DError= >> accessing=3D >>>> memory address 0x8000feff7df8: Bad address.
>>>> ) at ../src/Main.m3:319
>>>> #6 =3DC2=3DA00x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3D3DErr=3D >>>> or accessing memory address 0x8000feff7eb8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>> #7 =3DC2=3DA00x0000000000449c50 in ThreadPThread__ThreadBase = >> (M3_AJWxb1_param=3D >>>> =3D3DError accessing memory address 0x8000feff7f68: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>> #8 =3DC2=3DA00x000000000047c7d4 in thread_start ()
>>>> #9 =3DC2=3DA00x0000000000000000 in ?? ()
>>>>
>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
>>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>>> #1 =3DC2=3DA00x0000000000475759 in suspend_common ()
>>>> #2 =3DC2=3DA00x00000000004755c1 in pthread_suspend_np ()
>>>> #3 =3DC2=3DA00x000000000044df0c in ThreadPThread__SuspendThread = >> (mt=3D3DError acc=3D >>>> essing memory address 0x8000ffbfd6f8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
>>>> #4 =3DC2=3DA00x000000000044bade in ThreadPThread__StopThread = >> (M3_DMxDjQ_act=3D3DE=3D >>>> rror accessing memory address 0x8000ffbfd718: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909
>>>> #5 =3DC2=3DA00x000000000044bc81 in ThreadPThread__StopWorld () at = >> ../src/thread=3D >>>> /PTHREAD/ThreadPThread.m3:948
>>>> #6 =3DC2=3DA00x000000000044b19e in RTThread__SuspendOthers () at = >> ../src/thread/=3D >>>> PTHREAD/ThreadPThread.m3:713
>>>> #7 =3DC2=3DA00x00000000004330d6 in = >> RTCollector__CollectSomeInStateZero () at ..=3D >>>> /src/runtime/common/RTCollector.m3:749
>>>> #8 =3DC2=3DA00x0000000000433081 in RTCollector__CollectSome () at = >> ../src/runtim=3D >>>> e/common/RTCollector.m3:723
>>>> #9 =3DC2=3DA00x0000000000432d49 in RTHeapRep__CollectEnough () at = >> ../src/runtim=3D >>>> e/common/RTCollector.m3:657
>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced = >> (M3_Cwb5VA_dataSize=3D3DEr=3D >>>> ror accessing memory address 0x8000ffbfd958: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:367
>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray = >> (M3_Eic7CK_def=3D3DError =3D >>>> accessing memory address 0x8000ffbfda18: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray = >> (M3_AJWxb1_defn=3D3DErro=3D >>>> r accessing memory address 0x8000ffbfda78: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3DError = >> accessing memo=3D >>>> ry address 0x8000ffbfdab8: Bad address.
>>>> ) at ../src/rw/Rd.m3:159
>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar (M3_EkTcCb_rd=3D3DError= >> acces=3D >>>> sing memory address 0x8000ffbfdb88: Bad address.
>>>> ) at ../src/rw/Rd.m3:187
>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3DError = >> accessing memor=3D >>>> y address 0x8000ffbfdbd8: Bad address.
>>>> ) at ../src/rw/Rd.m3:176
>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3DError = >> accessing memo=3D >>>> ry address 0x8000ffbfdc58: Bad address.
>>>> ) at ../src/Main.m3:185
>>>>
>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3D3DError ac=3D >>>> cessing memory address 0x8000ffbfdeb8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase = >> (M3_AJWxb1_param=3D3DErro=3D >>>> r accessing memory address 0x8000ffbfdf68: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>> #19 0x000000000047c7d4 in thread_start ()
>>>> #20 0x0000000000000000 in ?? ()
>>>>
>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
>>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>>> #1 =3DC2=3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>> #2 =3DC2=3DA00x0000000000479404 in mutex_lock_common ()
>>>> #3 =3DC2=3DA00x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >> (mutex=3D3DE=3D >>>> rror accessing memory address 0x8000ffffc678: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>> #4 =3DC2=3DA00x000000000044d039 in RTOS__LockHeap () at = >> ../src/thread/PTHREAD/T=3D >>>> hreadPThread.m3:1337
>>>> ---Type <return> to continue, or q <return> to = >> quit---
>>>> #5 =3DC2=3DA00x000000000042ff79 in RTAllocator__AllocTraced = >> (M3_Cwb5VA_dataSize=3D >>>> =3D3DError accessing memory address 0x8000ffffc6e8: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>> #6 =3DC2=3DA00x000000000042f15b in RTAllocator__GetTracedObj = >> (M3_Eic7CK_def=3D3DE=3D >>>> rror accessing memory address 0x8000ffffc7a8: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:224
>>>> #7 =3DC2=3DA00x000000000042eb23 in RTHooks__AllocateTracedObj = >> (M3_AJWxb1_defn=3D >>>> =3D3DError accessing memory address 0x8000ffffc7f8: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:122
>>>> #8 =3DC2=3DA00x000000000045fbe4 in TextCat__Flat = >> (M3_Bd56fi_LText=3D3DError acces=3D >>>> sing memory address 0x8000ffffc858: Bad address.
>>>> ) at ../src/text/TextCat.m3:562
>>>> #9 =3DC2=3DA00x000000000045ed5d in TextCat__Balance = >> (M3_Bd56fi_LText=3D3D0x800c49=3D >>>> 0b0, M3_BUgnwf_LInfo=3D3DError accessing memory address = >> 0x8000ffffc8f8: Bad a=3D >>>> ddress.
>>>> ) at ../src/text/TextCat.m3:488
>>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3D3DError = >> accessing me=3D >>>> mory address 0x8000ffffcbb8: Bad address.
>>>> ) at ../src/text/TextCat.m3:40
>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3DError accessing = >> memory =3D >>>> address 0x8000ffffcc38: Bad address.
>>>> ) at ../src/Main.m3:593
>>>> #12 0x000000000043d55d in RTLinker__RunMainBody (M3_DjPxE3_m=3D3DError = >> access=3D >>>> ing memory address 0x8000ffffcf88: Bad address.
>>>> ) at ../src/runtime/common/RTLinker.m3:408
>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3D3DError = >> accessing=3D >>>> memory address 0x8000ffffd008: Bad address.
>>>> ) at ../src/runtime/common/RTLinker.m3:115
>>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3D3DError = >> accessing =3D >>>> memory address 0x8000ffffd028: Bad address.
>>>> ) at ../src/runtime/common/RTLinker.m3:124
>>>> #15 0x00000000004004a6 in main (argc=3D3DError accessing memory = >> address 0x800=3D >>>> 0ffffd07c: Bad address.
>>>> ) at _m3main.c:22
>>>>
>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
>>>> #0 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>>> #1 =3DC2=3DA00x0000000000477e8a in check_suspend ()
>>>> #2 =3DC2=3DA00x00000000004780a2 in sigcancel_handler ()
>>>> #3 =3DC2=3DA0<signal handler called>
>>>> #4 =3DC2=3DA00x000000000047e53c in _umtx_op_err ()
>>>> #5 =3DC2=3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>> #6 =3DC2=3DA00x0000000000479404 in mutex_lock_common ()
>>>> #7 =3DC2=3DA00x000000000044dd15 in ThreadPThread__pthread_mutex_lock = >> (mutex=3D3DE=3D >>>> rror accessing memory address 0x8000ff5fac18: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>> #8 =3DC2=3DA00x000000000044d039 in RTOS__LockHeap () at = >> ../src/thread/PTHREAD/T=3D >>>> hreadPThread.m3:1337
>>>> #9 =3DC2=3DA00x000000000042ff79 in RTAllocator__AllocTraced = >> (M3_Cwb5VA_dataSize=3D >>>> =3D3DError accessing memory address 0x8000ff5fac88: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray = >> (M3_Eic7CK_def=3D3DError =3D >>>> accessing memory address 0x8000ff5fad48: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray = >> (M3_AJWxb1_defn=3D3DErro=3D >>>> r accessing memory address 0x8000ff5fada8: Bad address.
>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3DError = >> accessing memo=3D >>>> ry address 0x8000ff5fade8: Bad address.
>>>> ) at ../src/Main.m3:283
>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3D3DError ac=3D >>>> cessing memory address 0x8000ff5faeb8: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase = >> (M3_AJWxb1_param=3D3DErro=3D >>>> r accessing memory address 0x8000ff5faf68: Bad address.
>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>> #15 0x000000000047c7d4 in thread_start ()
>>>> #16 0x0000000000000000 in ?? ()
>>>>
>>>> (others are similar)
>>>>
>>>> Hmm looks like a FreeBSD issue now. =3DC2=3DA0It's here...
>>>>
>>>> int
>>>> __cdecl
>>>> ThreadPThread__SuspendThread (m3_pthread_t mt)
>>>> {
>>>> =3DC2=3DA0 = >> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), "=3D >>>> pthread_suspend_np");
>>>> =3DC2=3DA0 return 1;
>>>> }
>>>>
>>>> Now this suspend can wait:
>>>>
>>>> static int
>>>> suspend_common(struct pthread *curthread, struct pthread *thread,
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 int waitok)
>>>> {
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 uint32_t tmp;
>>>>
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 while (thread->state = >> !=3D3D PS_DEAD &&=3D >>>>
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 !(thread->flags & T=3D >>>> HR_FLAGS_SUSPENDED)) {
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 thread->flags |=3D >>>> =3D3D THR_FLAGS_NEED_SUSPEND;
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 /* Thread is in cre=3D >>>> ation. */
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 if (thread->tid =3D >>>> =3D3D=3D3D TID_TERMINATED)
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>>> =3DA0 =3DC2=3DA0 return (1);
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 tmp =3D3D thread->=3D >>>> cycle;
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 _thr_send_sig(threa=3D >>>> d, SIGCANCEL);
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 THR_THREAD_UNLOCK(c=3D >>>> urthread, thread);
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 if (waitok) {
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>>> =3DA0 =3DC2=3DA0 _thr_umtx_wait_uint(&thread->cycle, tmp, = >> NULL, 0); =3DC2=3DA0=3D >>>> <=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>>> =3DA0 =3DC2=3DA0 THR_THREAD_LOCK(curthread, thread);
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 } else {
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>>> =3DA0 =3DC2=3DA0 THR_THREAD_LOCK(curthread, thread);
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3D >>>> =3DA0 =3DC2=3DA0 return (0);
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> =3DC2=3DA0 =3DC2=3DA0 }
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 }
>>>>
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 return (1);
>>>> }
>>>>
>>>> ... but what it can wait for I am not clear on.
>>>>
>>>> Do things work better on Linux?
>>>>
>>>> What is the status of the fork bug? =3DC2=3DA0Can it be worked around = >> by only f=3D >>>> orking via Process.Create with no mutexes held (outside of all LOCK = >> blocks)=3D >>>> ?
>>>>
>>>> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika
>>>>
>>>>
>>>>
>>>> Peter McKinna writes:
>>>> >--001a11c2ced4471a2e050079db82
>>>> >Content-Type: text/plain; charset=3D3DUTF-8
>>>>
>
>>>> >Mika
>>>> >
>>>> > =3DC2=3DA0I think you need to back out Tony's changes to fix = >> the fork =3D >>>> bug, at least
>>>> >for now. Need to reload from cvs version 1.262 for = >> ThreadPThread.m3 If<=3D >>>> br> >>>> >you're using git you're on your own.
>>>> > =3DC2=3DA0Do a cvs log ThreadPThread.m3 for an explanation for = >> some of the=3D >>>> design
>>>> >principles.
>>>> > =3DC2=3DA0Also if you use gdb then you need to set lanc c before = >> backtrace=3D >>>> s so at
>>>> >least you can see address names and values even if they are = >> contorted y=3D >>>> ou
>>>> >can extract the M3 name in the parm lists. Also in gdb thread = >> apply all=3D >>>> bt
>>>> >gives all thread backtraces which can be handy to see whose got = >> the loc=3D >>>> ks
>>>> >held.
>>>> >
>>>> >Regards Peter
>>>> >
>>>> >
>>>> >
>>>> >On Wed, Aug 13, 2014 at 12:14 PM, <> href=3D3D"mailto:mika at async.calt=3D >>>> ech.edu" target=3D3D"_blank">mika at async.caltech.edu> = >> wrote:
>>>> >
>>>> >>
>>>> >> Question... is there something odd about my pthreads? = >> =3DC2=3DA0Are pt=3D >>>> hreads
>>>> >> normally reentrant? =3DC2=3DA0I didn't think so.
>>>> >>
>>>> >> My compiler is much happier with the following changes I = >> already o=3D >>>> utlined:
>>>> >>
>>>> >> 1. a dirty, disgusting hack to keep from locking against = >> myself go=3D >>>> ing from
>>>> >> XWait with self.mutex locked to m.release().
>>>> >>
>>>> >> 2. the change to LockHeap I described in previous email
>>>> >>
>>>> >> But now...
>>>> >>
>>>> >> (gdb) cont
>>>> >> Continuing.
>>>> >> ERROR: pthread_mutex_lock:11
>>>> >> ERROR: pthread_mutex_lock:11
>>>> >>
>>>> >> Program received signal SIGABRT, Aborted.
>>>> >> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>> >> (gdb) where
>>>> >> #0 =3DC2=3DA00x000000080107626a in thr_kill () from = >> /lib/libc.so.7
>>>> >> #1 =3DC2=3DA00x000000080113dac9 in abort () from = >> /lib/libc.so.7
>>>> >> #2 =3DC2=3DA00x000000000071e37a in = >> ThreadPThread__pthread_mutex_lock (=3D >>>> mutex=3D3DError
>>>> >> accessing memory address 0x8000ffffb508: Bad address.
>>>> >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>> >> #3 =3DC2=3DA00x000000000071d48d in RTOS__LockHeap () at
>>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>>>> >> #4 =3DC2=3DA00x0000000000706b9d in = >> RTHooks__CheckLoadTracedRef (M3_Af4=3D >>>> 0ku_ref=3D3DError
>>>> >> accessing memory address 0x8000ffffb568: Bad address.
>>>> >> ) at ../src/runtime/common/RTCollector.m3:2234
>>>> >> #5 =3DC2=3DA00x000000000071d284 in = >> ThreadPThread__AtForkParent () at>>> r> >>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>>>> >> #6 =3DC2=3DA00x0000000800df8733 in fork () from = >> /lib/libthr.so.3
>>>> >> #7 =3DC2=3DA00x000000000070dd8b in RTProcess__Fork () at
>>>> >> ../src/runtime/common/RTProcessC.c:152
>>>> >> #8 =3DC2=3DA00x00000000006c52f2 in = >> ProcessPosixCommon__Create_ForkExec=3D >>>>
>>>> >> (M3_Bd56fi_cmd=3D3DError accessing memory address = >> 0x8000ffffb6f8: Ba=3D >>>> d address.
>>>> >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>> >> #9 =3DC2=3DA00x00000000006c6c6c in Process__Create = >> (M3_Bd56fi_cmd=3D3DEr=3D >>>> ror accessing
>>>> >> memory address 0x8000ffffb7f8: Bad address.
>>>> >> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>> >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise = >> (M3_D6rRrg_e=3D >>>> p=3D3DError
>>>> >> accessing memory address 0x8000ffffb838: Bad address.
>>>> >> ) at ../src/QMachine.m3:1666
>>>> >> #11 0x00000000004d6220 in QMachine__ExecCommand = >> (M3_An02H2_t=3D3DErr=3D >>>> or
>>>> >> accessing memory address 0x8000ffffb9f8: Bad address.
>>>> >> ) at ../src/QMachine.m3:1605
>>>> >> #12 0x00000000004d537e in QMachine__DoTryExec = >> (M3_An02H2_t=3D3DError=3D >>>> accessing
>>>> >> memory address 0x8000ffffbee8: Bad address.
>>>> >> ) at ../src/QMachine.m3:1476
>>>> >>
>>>> >> What am I doing wrong here?
>>>> >>
>>>> >> The error doesn't look unreasonable! =3DC2=3DA0Looking = >> more closel=3D >>>> y at the code:
>>>> >>
>>>> >> First, AtForkPrepare has been called:
>>>> >>
>>>> >> PROCEDURE AtForkPrepare() =3D3D
>>>> >> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>>> >> =3DC2=3DA0 BEGIN
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(slotsMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(perfMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(initMu, ThisLine()); = >> (* InitMutex =3D >>>> =3D3D>
>>>> >> RegisterFinalCleanup =3D3D> LockHeap *)
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(heapMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(activeMu, = >> ThisLine()); (* LockHeap =3D >>>> =3D3D> SuspendOthers
>>>> >> =3D3D> activeMu *)
>>>> >> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and lock all = >> threads.
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* NOTE: We have initMu, = >> activeMu, so slots won=3D >>>> 't change, conditions
>>>> >> and
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0* mutexes won't be = >> initialized on-demand.<=3D >>>> br> >>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0*)
>>>> >> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 PThreadLockMutex(act.mutex, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>>> >> =3DC2=3DA0 END AtForkPrepare;
>>>> >>
>>>> >> a postcondition of this routine is that heapMu is = >> locked.
>>>> >>
>>>> >> now we get into AtForkParent:
>>>> >>
>>>> >> PROCEDURE AtForkParent() =3D3D
>>>> >> =3DC2=3DA0 VAR me :=3D3D GetActivation();
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act: Activation;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond: Condition;
>>>> >> =3DC2=3DA0 BEGIN
>>>> >> =3DC2=3DA0 =3DC2=3DA0 (* Walk activations and unlock all = >> threads, conditio=3D >>>> ns. *)
>>>> >> =3DC2=3DA0 =3DC2=3DA0 act :=3D3D me;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 REPEAT
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 cond :=3D3D = >> slots[act.slot].join;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 IF cond # NIL THEN = >> PThreadUnlockMutex(cond.mu=3D >>>> tex, ThisLine()) END;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 = >> PThreadUnlockMutex(act.mutex, ThisLine());>>>> =20 >>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0 act :=3D3D act.next;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 UNTIL act =3D3D me;
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(activeMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(heapMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(initMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(perfMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 =3DC2=3DA0 PThreadUnlockMutex(slotsMu, = >> ThisLine());
>>>> >> =3DC2=3DA0 END AtForkParent;
>>>> >>
>>>> >> We can see by inspecting the code that a necessary = >> precondition fo=3D >>>> r
>>>> >> this routine is that heapMu is locked! =3DC2=3DA0(Since = >> it's going=3D >>>> to unlock it,
>>>> >> it had BETTER be locked on entry.)
>>>> >>
>>>> >> But the cond :=3D3D ... causes a = >> RTHooks.CheckLoadTracedRef
>>>> >>
>>>> >> which causes an RTOS.LockHeap
>>>> >>
>>>> >> the code of which we just saw:
>>>> >>
>>>> >> PROCEDURE LockHeap () =3D3D
>>>> >> =3DC2=3DA0 VAR self :=3D3D pthread_self();
>>>> >> =3DC2=3DA0 BEGIN
>>>> >> =3DC2=3DA0 =3DC2=3DA0 WITH r =3D3D = >> pthread_mutex_lock(heapMu,ThisLine()) DO =3D >>>> <*ASSERT r=3D3D0*> END;
>>>> >> ...
>>>> >>
>>>> >> we try to lock heapMu. =3DC2=3DA0kaboom! =3DC2=3DA0No = >> surprise there, real=3D >>>> ly?
>>>> >>
>>>> >> Am I going about this totally the wrong way? =3DC2=3DA0Other = >> people ar=3D >>>> e running
>>>> >> Modula-3
>>>> >> with pthreads, right? =3DC2=3DA0Right?? =3DC2=3DA0Somewhere = >> out there in m=3D >>>> 3devel-land?
>>>> >>
>>>> >> =3DC2=3DA0 =3DC2=3DA0 =3DC2=3DA0Mika
>>>> >>
>>>> >>
>>>> >
>>>>
>--001a11c2ced4471a2e050079db82
>>>> >Content-Type: text/html; charset=3D3DUTF-8
>>>> >Content-Transfer-Encoding: quoted-printable
>>>> >
>>>> ><div = >> dir=3D3D3D"ltr">Mika<div><br></div>=3D >>>> ;<div>=3D3DC2=3D3DA0 I think you need to back ou=3D3D
>>>> >t Tony&#39;s changes to fix the fork bug, at least for now. = >> Need to=3D >>>> reload =3D3D
>>>> >from cvs version 1.262 for ThreadPThread.m3 If you&#39;re = >> using git=3D >>>> you&#39=3D3D
>>>> >;re on your own.</div>
>>>> >
>>>> ><div>=3D3DC2=3D3DA0 Do a cvs log ThreadPThread.m3 for an = >> explanation =3D >>>> for some of th=3D3D
>>>> >e design principles.=3D3DC2=3D3DA0</div><div>=3D3DC2=3D= >> 3DA0 Also if=3D >>>> you use gdb then you ne=3D3D
>>>> >ed to set lanc c before backtraces so at least you can see = >> address name=3D >>>> s an=3D3D
>>>> >d values even if they are contorted you can extract the M3 name = >> in the =3D >>>> parm=3D3D
>>>> > lists. Also in gdb thread apply all bt gives all thread = >> backtraces whi=3D >>>> ch c=3D3D
>>>> >an be handy to see whose got the locks held.</div>
>>>> >
>>>> ><div><br></div><div>Regards = >> Peter</div>&l=3D >>>> t;div><br></div><div class=3D3D3D"gmail_e=3D3D> r> >>>> >xtra"><br><br><div = >> class=3D3D3D"gmail_quote&q=3D >>>> uot;>On Wed, Aug 13, 2014 at 12:14 PM, =3D3D
>>>> > <span dir=3D3D3D"ltr">&lt;<a = >> href=3D3D3D"mailt=3D >>>> o:> target=3D3D"_blank">mika at async.ca=3D >>>> ltech.edu" target=3D3D3D"=3D3D
>>>> >_blank">> target=3D3D"_bl=3D >>>> ank">mika at async.caltech.edu</a>&gt;</span> = >> wrote:<br=3D >>>> >
>>>> >
>>>> ><blockquote class=3D3D3D"gmail_quote" = >> style=3D3D3D"margin=3D >>>> :0 0 0 .8ex;border-left:1p=3D3D
>>>> >x #ccc solid;padding-left:1ex"><br>
>>>> >Question... is there something odd about my pthreads? = >> =3D3DC2=3D3DA0Are pth=3D >>>> reads no=3D3D
>>>> >rmally reentrant? =3D3DC2=3D3DA0I didn&#39;t think = >> so.<br>
>>>> ><br>
>>>> >My compiler is much happier with the following changes I already = >> outlin=3D >>>> ed:<=3D3D
>>>> >br>
>>>> ><br>
>>>> >1. a dirty, disgusting hack to keep from locking against myself = >> going f=3D >>>> rom =3D3D
>>>> >XWait with self.mutex locked to m.release().<br>
>>>> ><br>
>>>> >2. the change to LockHeap I described in previous = >> email<br>
>>>> ><br>
>>>> >But now...<br>
>>>> ><br>
>>>> >(gdb) cont<br>
>>>> >Continuing.<br>
>>>> >ERROR: pthread_mutex_lock:11<br>
>>>> >ERROR: pthread_mutex_lock:11<br>
>>>> ><br>
>>>> >Program received signal SIGABRT, Aborted.<br>
>>>> >0x000000080107626a in thr_kill () from = >> /lib/libc.so.7<br>
>>>> >(gdb) where<br>
>>>> >#0 =3D3DC2=3D3DA00x000000080107626a in thr_kill () from = >> /lib/libc.so.7<b=3D >>>> r>
>>>> >#1 =3D3DC2=3D3DA00x000000080113dac9 in abort () from = >> /lib/libc.so.7<br&g=3D >>>> t;
>>>> >#2 =3D3DC2=3D3DA00x000000000071e37a in = >> ThreadPThread__pthread_mutex_lock (m=3D >>>> utex=3D3D3DE=3D3D
>>>> >rror accessing memory address 0x8000ffffb508: Bad = >> address.<br>>>>> =20 >>>> >) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>>>> >#3 =3D3DC2=3D3DA00x000000000071d48d in RTOS__LockHeap () at = >> ../src/thread/P=3D >>>> THREAD/T=3D3D
>>>> >hreadPThread.m3:1377<br>
>>>> >#4 =3D3DC2=3D3DA00x0000000000706b9d in = >> RTHooks__CheckLoadTracedRef (M3_Af40=3D >>>> ku_ref=3D3D
>>>> >=3D3D3DError accessing memory address 0x8000ffffb568: Bad = >> address.<br&=3D >>>> gt;
>>>> >) at ../src/runtime/common/RTCollector.m3:2234<br>
>>>> >#5 =3D3DC2=3D3DA00x000000000071d284 in = >> ThreadPThread__AtForkParent () at ..=3D >>>> /src/thr=3D3D
>>>> >ead/PTHREAD/ThreadPThread.m3:1348<br>
>>>> >#6 =3D3DC2=3D3DA00x0000000800df8733 in fork () from = >> /lib/libthr.so.3<br&=3D >>>> gt;
>>>> >#7 =3D3DC2=3D3DA00x000000000070dd8b in RTProcess__Fork () at = >> ../src/runtime=3D >>>> /common/=3D3D
>>>> >RTProcessC.c:152<br>
>>>> >#8 =3D3DC2=3D3DA00x00000000006c52f2 in = >> ProcessPosixCommon__Create_ForkExec =3D >>>> (M3_Bd56=3D3D
>>>> >fi_cmd=3D3D3DError accessing memory address 0x8000ffffb6f8: Bad = >> address.&=3D >>>> lt;br>
>>>> >) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>>>> >#9 =3D3DC2=3D3DA00x00000000006c6c6c in Process__Create = >> (M3_Bd56fi_cmd=3D3D3DE=3D >>>> rror acces=3D3D
>>>> >sing memory address 0x8000ffffb7f8: Bad address.<br>
>>>> >) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>>>> >#10 0x00000000004d6826 in QMachine__FulfilExecPromise = >> (M3_D6rRrg_ep=3D3D3=3D >>>> DError=3D3D
>>>> > accessing memory address 0x8000ffffb838: Bad = >> address.<br>
>>>> >) at ../src/QMachine.m3:1666<br>
>>>> >#11 0x00000000004d6220 in QMachine__ExecCommand = >> (M3_An02H2_t=3D3D3DError =3D >>>> access=3D3D
>>>> >ing memory address 0x8000ffffb9f8: Bad address.<br>
>>>> >) at ../src/QMachine.m3:1605<br>
>>>> >#12 0x00000000004d537e in QMachine__DoTryExec = >> (M3_An02H2_t=3D3D3DError ac=3D >>>> cessin=3D3D
>>>> >g memory address 0x8000ffffbee8: Bad address.<br>
>>>> >) at ../src/QMachine.m3:1476<br>
>>>> ><br>
>>>> >What am I doing wrong here?<br>
>>>> ><br>
>>>> >The error doesn&#39;t look unreasonable! =3D3DC2=3D3DA0Looking = >> more clo=3D >>>> sely at the =3D3D
>>>> >code:<br>
>>>> ><br>
>>>> >First, AtForkPrepare has been called:<br>
>>>> ><br>
>>>> >PROCEDURE AtForkPrepare() =3D3D3D<br>
>>>> >=3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >> Activation;<br>
>>>> >=3D3DC2=3D3DA0 BEGIN<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(slotsMu, = >> ThisLine());<br><=3D >>>> br> >>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(perfMu, = >> ThisLine());<br>>>> r> >>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(initMu, = >> ThisLine()); (* InitMute=3D >>>> x =3D3D3D&gt; Re=3D3D
>>>> >gisterFinalCleanup =3D3D3D&gt; LockHeap *)<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(heapMu, = >> ThisLine());<br>>>> r> >>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(activeMu, = >> ThisLine()); (* LockHe=3D >>>> ap =3D3D3D&gt; S=3D3D
>>>> >uspendOthers =3D3D3D&gt; activeMu *)<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and lock all = >> threads.<br&g=3D >>>> t;
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* NOTE: We have = >> initMu, activeMu, so sl=3D >>>> ots won&#39;t ch=3D3D
>>>> >ange, conditions and<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* mutexes = >> won&#39;t be initialized =3D >>>> on-demand.<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0*)<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> PThreadLockMutex(act.mutex, ThisLine()=3D >>>> );<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >> act.next;<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;<br>
>>>> >=3D3DC2=3D3DA0 END AtForkPrepare;<br>
>>>> ><br>
>>>> >a postcondition of this routine is that heapMu is = >> locked.<br>
>>>> ><br>
>>>> >now we get into AtForkParent:<br>
>>>> ><br>
>>>> >PROCEDURE AtForkParent() =3D3D3D<br>
>>>> >=3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >> Activation;<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond: = >> Condition;<br>
>>>> >=3D3DC2=3D3DA0 BEGIN<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and unlock all = >> threads, condi=3D >>>> tions. *)<br=3D3D
>>>> >>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond :=3D3D3D = >> slots[act.slot].join;<b=3D >>>> r>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 IF cond # NIL THEN = >> PThreadUnlockMutex(=3D >>>> cond.mutex, This=3D3D
>>>> >Line()) END;<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> PThreadUnlockMutex(act.mutex, ThisLine=3D >>>> ());<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >> act.next;<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(activeMu, = >> ThisLine());<br&g=3D >>>> t;
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(heapMu, = >> ThisLine());<br>=3D >>>>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(initMu, = >> ThisLine());<br>=3D >>>>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(perfMu, = >> ThisLine());<br>=3D >>>>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(slotsMu, = >> ThisLine());<br>=3D >>>> ;
>>>> >=3D3DC2=3D3DA0 END AtForkParent;<br>
>>>> ><br>
>>>> >We can see by inspecting the code that a necessary precondition = >> for<=3D >>>> br>
>>>> >this routine is that heapMu is locked! =3D3DC2=3D3DA0(Since = >> it&#39;s go=3D >>>> ing to unloc=3D3D
>>>> >k it,<br>
>>>> >it had BETTER be locked on entry.)<br>
>>>> ><br>
>>>> >But the cond :=3D3D3D ... causes a = >> RTHooks.CheckLoadTracedRef<br>>>> r> >>>> ><br>
>>>> >which causes an RTOS.LockHeap<br>
>>>> ><br>
>>>> >the code of which we just saw:<br>
>>>> ><br>
>>>> >PROCEDURE LockHeap () =3D3D3D<br>
>>>> >=3D3DC2=3D3DA0 VAR self :=3D3D3D pthread_self();<br>
>>>> >=3D3DC2=3D3DA0 BEGIN<br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 WITH r =3D3D3D = >> pthread_mutex_lock(heapMu,ThisLine()=3D >>>> ) DO &lt;*ASSE=3D3D
>>>> >RT r=3D3D3D0*&gt; END;<br>
>>>> >...<br>
>>>> ><br>
>>>> >we try to lock heapMu. =3D3DC2=3D3DA0kaboom! =3D3DC2=3D3DA0No = >> surprise there, r=3D >>>> eally?<br>
>>>> ><br>
>>>> >Am I going about this totally the wrong way? =3D3DC2=3D3DA0Other = >> people are=3D >>>> running=3D3D
>>>> > Modula-3<br>
>>>> >with pthreads, right? =3D3DC2=3D3DA0Right?? =3D3DC2=3D3DA0Somewhere= >> out there i=3D >>>> n m3devel-la=3D3D
>>>> >nd?<br>
>>>> ><span><font = >> color=3D3D3D"#888888"><br>
>>>> >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika<br>
>>>> ><br>
>>>> = >> ></font></span></blockquote></div><br><= >> ;=3D >>>> /div></div>
>>>> >
>>>> >--001a11c2ced4471a2e050079db82--
>>>>

>>>>

>>>> =20 >>>> --089e01183a1813188705007c3498-- From mika at async.caltech.edu Wed Aug 13 19:04:59 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Wed, 13 Aug 2014 10:04:59 -0700 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: <7A6EF7C5-9B0F-4FC5-BCB1-C7A0E36BB2D6@cs.purdue.edu> References: <20140813021401.238B31A2094@async.async.caltech.edu> <20140813045415.C13921A2094@async.async.caltech.edu> <20140813063041.286EA1A2094@async.async.caltech.edu> <97266593-618F-458D-A975-FE01D9BF19F9@cs.purdue.edu> <20140813163735.8D0701A2097@async.async.caltech.edu> <7A6EF7C5-9B0F-4FC5-BCB1-C7A0E36BB2D6@cs.purdue.edu> Message-ID: <20140813170459.436121A2097@async.async.caltech.edu> Sure, I understand. Just wasn't aware of it yesterday! But I think there are two problems here: fork and FreeBSD. The problems on AMD64_FREEBSD look like something different .. there is custom FreeBSD code that is invoked and seems to screw things up. The attached example doesn't use fork at all. On the other hand, question about fork: what is the precise problem with fork? My understanding was that it was an issue with held mutexes on fork. But what if you don't hold any mutexes on fork? Related question: how many times does fork appear in the cm3 tree? I only ever use Process.Create ... can one build a custom solution for that one routine, maybe with a forker thread somehow? Or do others use more general forking patterns? Mika Tony Hosking writes: > >On Aug 13, 2014, at 12:37 PM, mika at async.caltech.edu wrote: > >> 1.262 >>=20 >> Short summary: 1.262 seems to work fine on AMD64_LINUX except for the >> fork issue (a bummer because my parallelization of the backends of cm3 >> uses fork a lot...and it does speed up the compiler significantly if >> you have fast disks and lots of cores) It does the attached on = >AMD64_FREEBSD. > >Yes, that was the state of things. Subsequent revs were to address fork = >issues. > >>=20 >> I see the intent of what you were doing in later version/s, but it was >> a bit rough, I think... I think the three issues I reported (1. = >locking >> heapMu from AtFork; 2. the try-only-once bug in LockHeap itself; 3. = >not >> passing the lock to release from Wait) are all more or less real. > >Working on these right now. Sorry for hacked versions =97 no time right = >now to do real testing before push. >Getting closer now I think. > >>=20 >> Mika >>=20 >> Tony Hosking writes: >>> Which revision of ThreadPThread.m3 is this output from? >>>=20 >>> On Aug 13, 2014, at 2:30 AM, mika at async.caltech.edu wrote: >>>=20 >>>> =3D20 >>>> OK... deleted all the derived directories and rebuilt. Result on =3D >>> FreeBSD is similar (or identical, hard to tell): >>>> =3D20 >>>> I get a partial deadlock: >>>> =3D20 >>>> PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU =3D >>> COMMAND >>>> 48760 root 98 0 87836K 29104K CPU1 1 12:32 83.89% =3D >>> threadtest{threadtest} >>>> 48760 root 94 0 87836K 29104K CPU3 3 11:02 74.66% =3D >>> threadtest{threadtest} >>>> 48760 root 94 0 87836K 29104K CPU0 0 11:03 71.97% =3D >>> threadtest{threadtest} >>>> 48760 root 32 0 87836K 29104K umtxn 2 0:01 0.00% =3D >>> threadtest{threadtest} >>>> 48760 root 20 0 87836K 29104K umtxn 2 0:01 0.00% =3D >>> threadtest{threadtest} >>>> 48760 root 35 0 87836K 29104K uwait 2 0:01 0.00% =3D >>> threadtest{threadtest} >>>> 48760 root 27 0 87836K 29104K uwait 0 0:01 0.00% =3D >>> threadtest{threadtest} >>>> 48760 root 27 0 87836K 29104K umtxn 3 0:01 0.00% =3D >>> threadtest{threadtest} >>>> 48760 root 27 0 87836K 29104K umtxn 2 0:01 0.00% =3D >>> threadtest{threadtest} >>>> 48760 root 20 0 87836K 29104K umtxn 0 0:00 0.00% =3D >>> threadtest{threadtest} >>>> 48759 root 20 0 30276K 11064K wait 0 0:00 0.00% gdb >>>> =3D20 >>>> one of the dead threads is the main thread, so now output. But = >three >>>> threads are still alive, interestingly enough. >>>> =3D20 >>>> Looks like the same issue as before: >>>> =3D20 >>>> Thread 5 (Thread 801807400 (LWP 100751/threadtest)): >>>> #0 0x0000000800ae089c in __error () from /lib/libthr.so.3 >>>> #1 0x0000000800ad6261 in pthread_suspend_np () from = >/lib/libthr.so.3 >>>> #2 0x00000000004511bc in ThreadPThread__SuspendThread (mt=3D3DError = >=3D >>> accessing memory address 0x8000ff5faa28: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>> #3 0x000000000044ed8e in ThreadPThread__StopThread =3D >>> (M3_DMxDjQ_act=3D3DError accessing memory address 0x8000ff5faa48: Bad = >=3D >>> address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>> #4 0x000000000044ef31 in ThreadPThread__StopWorld () at =3D >>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>> #5 0x000000000044e44e in RTThread__SuspendOthers () at =3D >>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>> #6 0x0000000000436386 in RTCollector__CollectSomeInStateZero () at = >=3D >>> ../src/runtime/common/RTCollector.m3:749 >>>> #7 0x0000000000436331 in RTCollector__CollectSome () at =3D >>> ../src/runtime/common/RTCollector.m3:723 >>>> #8 0x0000000000435ff9 in RTHeapRep__CollectEnough () at =3D >>> ../src/runtime/common/RTCollector.m3:657 >>>> #9 0x0000000000433233 in RTAllocator__AllocTraced =3D >>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address = >0x8000ff5fac88: Bad =3D >>> address. >>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>> #10 0x0000000000432b55 in RTAllocator__GetOpenArray =3D >>> (M3_Eic7CK_def=3D3DError accessing memory address 0x8000ff5fad48: Bad = >=3D >>> address. >>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>> #11 0x0000000000431e8f in RTHooks__AllocateOpenArray =3D >>> (M3_AJWxb1_defn=3D3DError accessing memory address 0x8000ff5fada8: = >Bad =3D >>> address. >>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>> #12 0x00000000004052ea in Main__AApply (M3_AP7a1g_cl=3D3DError = >accessing =3D >>> memory address 0x8000ff5fade8: Bad address. >>>> ) at ../src/Main.m3:283 >>>> #13 0x000000000044d243 in ThreadPThread__RunThread = >(M3_DMxDjQ_me=3D3DError=3D >>> accessing memory address 0x8000ff5faeb8: Bad address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>> #14 0x000000000044cf00 in ThreadPThread__ThreadBase =3D >>> (M3_AJWxb1_param=3D3DError accessing memory address 0x8000ff5faf68: = >Bad =3D >>> address. >>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>> #15 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>> #16 0x0000000000000000 in ?? () >>>> =3D20 >>>> Interestingly the same test seems to work on AMD64_LINUX. That is >>>> promising, at least. But of course, software testing never reveals = >=3D >>> the >>>> absence of bugs. >>>> =3D20 >>>> Mika >>>> =3D20 >>>> Peter McKinna writes: >>>>> --089e01183a1813188705007c3498 >>>>> Content-Type: text/plain; charset=3D3DUTF-8 >>>>> =3D20 >>>>> Oh, one other thing that seemed to help me in testing this stuff =3D >>> especially >>>>> things to do with m3core and libm3 which seem to get out of whack >>>>> sometimes, is to totally remove the target directory of m3core then = >=3D >>> cm3; >>>>> cm3 -ship Same with libm3. I'm not sure that clean actually removes = >=3D >>> the >>>>> targets and I think there are leftover files that stuff things up =3D= > >>> since I >>>>> would get segv in FileRd for no obvious reason. >>>>> =3D20 >>>>> Peter >>>>> =3D20 >>>>> =3D20 >>>>> =3D20 >>>>> On Wed, Aug 13, 2014 at 3:33 PM, Peter McKinna =3D >>> >>>>> wrote: >>>>> =3D20 >>>>>> That is weird. The thread tester works fine with the old version = >of >>>>>> ThreadPThread.m3 on linux amd_64 except if you have the fork test = >in =3D >>> the >>>>>> mix of tests you see the pthread_mutex_destroy every now and = >again, =3D >>> the >>>>>> fork bug in fact. >>>>>> I was testing the pthread changes Tony has made over the past few = >=3D >>> days >>>>>> using the thread tester program until I stupidly rebuilt the =3D >>> compiler and >>>>>> was getting all sorts of hangs as it dragged in the new version of >>>>>> pthreads. So I rebuilt everything from a backup to get back where = >I =3D >>> was >>>>>> with a decent compiler, then reintroduced the latest changes to >>>>>> ThreadPThread.m3, which yesterday was just hanging in sigsuspend = >but =3D >>> today >>>>>> is giving me an assert failure at line 1387 in UnlockHeap. So its = >a =3D >>> bit >>>>>> unstable to say the least. Maybe there is something else wrong = >with =3D >>> freebsd. >>>>>> =3D20 >>>>>> Peter >>>>>> =3D20 >>>>>> =3D20 >>>>>> =3D20 >>>>>> On Wed, Aug 13, 2014 at 2:54 PM, wrote: >>>>>> =3D20 >>>>>>> =3D20 >>>>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not =3D >>> getting >>>>>>> things to work and now I'm really baffled because I think I =3D >>> understand >>>>>>> this code! >>>>>>> =3D20 >>>>>>> What I did was I threw away all my changes and reverted =3D >>> ThreadPThread.m3 >>>>>>> to 1.262 as you suggested. >>>>>>> =3D20 >>>>>>> Rebuilt the compiler with upgrade.sh >>>>>>> =3D20 >>>>>>> Then rebuilt the compiler again with itself. >>>>>>> =3D20 >>>>>>> Then I realcleaned the world and buildshipped it. (I was afraid >>>>>>> that parseparams, also imported by the thread tester, would = >pollute >>>>>>> it somehow.) >>>>>>> =3D20 >>>>>>> When I look at the code in 1.262 it looks quite straightforward. = >=3D >>> heapMu >>>>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. >>>>>>> Condition >>>>>>> variables are mutexes too, but that's no big deal. >>>>>>> =3D20 >>>>>>> So, rebuild thread tester, run it: >>>>>>> =3D20 >>>>>>> new source -> compiling Main.m3 >>>>>>> -> linking threadtest >>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # >>>>>>> AMD64_FREEBSD/threadtest >>>>>>> Writing file...done >>>>>>> Creating read threads...done >>>>>>> Creating fork threads...done >>>>>>> Creating alloc threads...done >>>>>>> Creating lock threads...done >>>>>>> running...printing oldest/median age/newest >>>>>>> . >>>>>>> =3D20 >>>>>>> *** >>>>>>> *** runtime error: >>>>>>> *** Segmentation violation - possible attempt to dereference >>>>>>> NIL.........laziest thread is 1407901189/1407901189/9 (tests: = >read >>>>>>> 1407901189/1407901189/1407901189 fork =3D >>> 1407901189/1407901189/1407901189 >>>>>>> alloc 9/9/9 lock 1407901189/1407901189/9) >>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> ^C >>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # = >gdb =3D >>> !$ >>>>>>> gdb AMD64_FREEBSD/threadtest >>>>>>> GNU gdb 6.1.1 [FreeBSD] >>>>>>> Copyright 2004 Free Software Foundation, Inc. >>>>>>> GDB is free software, covered by the GNU General Public License, = >=3D >>> and you >>>>>>> are >>>>>>> welcome to change it and/or distribute copies of it under certain >>>>>>> conditions. >>>>>>> Type "show copying" to see the conditions. >>>>>>> There is absolutely no warranty for GDB. Type "show warranty" = >for >>>>>>> details. >>>>>>> This GDB was configured as "amd64-marcel-freebsd"... >>>>>>> (gdb) run >>>>>>> Starting program: >>>>>>> =3D >>> = >/big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/th= >=3D >>> readtest >>>>>>> [New LWP 100121] >>>>>>> Writing file...done >>>>>>> Creating read threads...done >>>>>>> Creating fork threads...done >>>>>>> Creating alloc threads...done >>>>>>> Creating lock threads...done >>>>>>> running...printing oldest/median age/newest >>>>>>> .[New Thread 801807000 (LWP 100343/threadtest)] >>>>>>> [New Thread 801807c00 (LWP 100667/threadtest)] >>>>>>> [New Thread 801808800 (LWP 100816/threadtest)] >>>>>>> [New Thread 801807400 (LWP 100349/threadtest)] >>>>>>> [New Thread 801808400 (LWP 100815/threadtest)] >>>>>>> [New Thread 801807800 (LWP 100352/threadtest)] >>>>>>> [New Thread 801808c00 (LWP 100817/threadtest)] >>>>>>> [New Thread 801809000 (LWP 100818/threadtest)] >>>>>>> [New Thread 801809800 (LWP 100820/threadtest)] >>>>>>> [New Thread 801808000 (LWP 100678/threadtest)] >>>>>>> [New Thread 801806400 (LWP 100121/threadtest)] >>>>>>> [New Thread 801806800 (LWP 100341/threadtest)] >>>>>>> [New Thread 801806c00 (LWP 100342/threadtest)] >>>>>>> .ERROR: pthread_mutex_lock:11 >>>>>>> =3D20 >>>>>>> Program received signal SIGABRT, Aborted. >>>>>>> [Switching to Thread 801809800 (LWP 100820/threadtest)] >>>>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>>> (gdb) where >>>>>>> #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>>> #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 >>>>>>> #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3DError >>>>>>> accessing memory address 0x8000fe5f2d98: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 >>>>>>> #3 0x000000000044b370 in ThreadPThread__LockMutex =3D >>> (M3_AYIbX3_m=3D3DError >>>>>>> accessing memory address 0x8000fe5f2dc8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>>> #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3D3DError =3D >>> accessing >>>>>>> memory address 0x8000fe5f2df8: Bad address. >>>>>>> ) at ../src/Main.m3:319 >>>>>>> #5 0x000000000044d243 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3DError >>>>>>> accessing memory address 0x8000fe5f2eb8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>> #6 0x000000000044cf00 in ThreadPThread__ThreadBase >>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >0x8000fe5f2f68: =3D >>> Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>> #7 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>>>>> #8 0x0000000000000000 in ?? () >>>>>>> (gdb) set lang c >>>>>>> (gdb) thread apply all bt >>>>>>> ... not that interesting ... >>>>>>> =3D20 >>>>>>> Segfault is segfault---error 11 is EDEADLK (locking against =3D >>> myself?) >>>>>>> =3D20 >>>>>>> ????? the code is very straightforward, as I said. >>>>>>> =3D20 >>>>>>> I thought people had the thread tester working with pthreads? =3D >>> Which set >>>>>>> of files, then? Anyone on FreeBSD/amd64? >>>>>>> =3D20 >>>>>>> Could it be an issue with "volatile"? Not even sure where to = >look. >>>>>>> =3D20 >>>>>>> The code calling the lock is just this: >>>>>>> =3D20 >>>>>>> PROCEDURE GetChar (rd: T): CHAR >>>>>>> RAISES {EndOfFile, Failure, Alerted} =3D3D >>>>>>> BEGIN >>>>>>> LOCK rd DO >>>>>>> RETURN FastGetChar(rd); >>>>>>> END >>>>>>> END GetChar; >>>>>>> =3D20 >>>>>>> No mysteries there... >>>>>>> =3D20 >>>>>>> Ah is this the fork bug? Looks like the Init routine is called = >on =3D >>> a >>>>>>> lot of NIL mutexes around the fork. But the subprocesses aren't = >=3D >>> meant >>>>>>> to accesses the mutexes... humm >>>>>>> =3D20 >>>>>>> Hmm, and it's not entirely a fork issue. Even with "threadtest =3D= > >>> -tests >>>>>>> STD,-fork,-forktoomuch" it misbehaves. Hangs.... >>>>>>> =3D20 >>>>>>> Looks like a deadlock this time. >>>>>>> =3D20 >>>>>>> Some stacks... >>>>>>> =3D20 >>>>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): >>>>>>> #0 0x00000000004b4e2b in __vdso_gettimeofday () >>>>>>> #1 0x00000000004ab8d2 in gettimeofday () >>>>>>> #2 0x0000000000452e4b in TimePosix__Now () at >>>>>>> ../src/time/POSIX/TimePosixC.c:50 >>>>>>> #3 0x0000000000452d72 in Time__Now () at >>>>>>> ../src/time/POSIX/TimePosix.m3:14 >>>>>>> #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3D3DError =3D >>> accessing >>>>>>> memory address 0x8000fedf6df8: Bad address. >>>>>>> ) at ../src/Main.m3:327 >>>>>>> #5 0x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3DError >>>>>>> accessing memory address 0x8000fedf6eb8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>> #6 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >0x8000fedf6f68: =3D >>> Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>> #7 0x000000000047c7d4 in thread_start () >>>>>>> #8 0x0000000000000000 in ?? () >>>>>>> =3D20 >>>>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): >>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3DError >>>>>>> accessing memory address 0x8000feff7d98: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>> #4 0x00000000004480c0 in ThreadPThread__LockMutex =3D >>> (M3_AYIbX3_m=3D3DError >>>>>>> accessing memory address 0x8000feff7dc8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>>> #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3D3DError =3D >>> accessing >>>>>>> memory address 0x8000feff7df8: Bad address. >>>>>>> ) at ../src/Main.m3:319 >>>>>>> #6 0x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3DError >>>>>>> accessing memory address 0x8000feff7eb8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>> #7 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >0x8000feff7f68: =3D >>> Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>> #8 0x000000000047c7d4 in thread_start () >>>>>>> #9 0x0000000000000000 in ?? () >>>>>>> =3D20 >>>>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): >>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>> #1 0x0000000000475759 in suspend_common () >>>>>>> #2 0x00000000004755c1 in pthread_suspend_np () >>>>>>> #3 0x000000000044df0c in ThreadPThread__SuspendThread = >(mt=3D3DError >>>>>>> accessing memory address 0x8000ffbfd6f8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>>>>> #4 0x000000000044bade in ThreadPThread__StopThread =3D >>> (M3_DMxDjQ_act=3D3DError >>>>>>> accessing memory address 0x8000ffbfd718: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>>>>> #5 0x000000000044bc81 in ThreadPThread__StopWorld () at >>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>>>>> #6 0x000000000044b19e in RTThread__SuspendOthers () at >>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>>>>> #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero () = >at >>>>>>> ../src/runtime/common/RTCollector.m3:749 >>>>>>> #8 0x0000000000433081 in RTCollector__CollectSome () at >>>>>>> ../src/runtime/common/RTCollector.m3:723 >>>>>>> #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at >>>>>>> ../src/runtime/common/RTCollector.m3:657 >>>>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced >>>>>>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address =3D >>> 0x8000ffbfd958: Bad >>>>>>> address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>> (M3_Eic7CK_def=3D3DError >>>>>>> accessing memory address 0x8000ffbfda18: Bad address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>>> (M3_AJWxb1_defn=3D3DError accessing memory address = >0x8000ffbfda78: =3D >>> Bad address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3DError =3D >>> accessing >>>>>>> memory address 0x8000ffbfdab8: Bad address. >>>>>>> ) at ../src/rw/Rd.m3:159 >>>>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar = >(M3_EkTcCb_rd=3D3DError=3D >>>=20 >>>>>>> accessing memory address 0x8000ffbfdb88: Bad address. >>>>>>> ) at ../src/rw/Rd.m3:187 >>>>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3DError =3D >>> accessing >>>>>>> memory address 0x8000ffbfdbd8: Bad address. >>>>>>> ) at ../src/rw/Rd.m3:176 >>>>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3DError =3D >>> accessing >>>>>>> memory address 0x8000ffbfdc58: Bad address. >>>>>>> ) at ../src/Main.m3:185 >>>>>>> =3D20 >>>>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3DError >>>>>>> accessing memory address 0x8000ffbfdeb8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >0x8000ffbfdf68: =3D >>> Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>> #19 0x000000000047c7d4 in thread_start () >>>>>>> #20 0x0000000000000000 in ?? () >>>>>>> =3D20 >>>>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): >>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3DError >>>>>>> accessing memory address 0x8000ffffc678: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>> #4 0x000000000044d039 in RTOS__LockHeap () at >>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>>> ---Type to continue, or q to quit--- >>>>>>> #5 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address =3D >>> 0x8000ffffc6e8: Bad >>>>>>> address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>>> #6 0x000000000042f15b in RTAllocator__GetTracedObj =3D >>> (M3_Eic7CK_def=3D3DError >>>>>>> accessing memory address 0x8000ffffc7a8: Bad address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:224 >>>>>>> #7 0x000000000042eb23 in RTHooks__AllocateTracedObj >>>>>>> (M3_AJWxb1_defn=3D3DError accessing memory address = >0x8000ffffc7f8: =3D >>> Bad address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:122 >>>>>>> #8 0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=3D3DError = >=3D >>> accessing >>>>>>> memory address 0x8000ffffc858: Bad address. >>>>>>> ) at ../src/text/TextCat.m3:562 >>>>>>> #9 0x000000000045ed5d in TextCat__Balance =3D >>> (M3_Bd56fi_LText=3D3D0x800c490b0, >>>>>>> M3_BUgnwf_LInfo=3D3DError accessing memory address = >0x8000ffffc8f8: =3D >>> Bad address. >>>>>>> ) at ../src/text/TextCat.m3:488 >>>>>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3D3DError = >=3D >>> accessing >>>>>>> memory address 0x8000ffffcbb8: Bad address. >>>>>>> ) at ../src/text/TextCat.m3:40 >>>>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3DError = >accessing =3D >>> memory >>>>>>> address 0x8000ffffcc38: Bad address. >>>>>>> ) at ../src/Main.m3:593 >>>>>>> #12 0x000000000043d55d in RTLinker__RunMainBody = >(M3_DjPxE3_m=3D3DError >>>>>>> accessing memory address 0x8000ffffcf88: Bad address. >>>>>>> ) at ../src/runtime/common/RTLinker.m3:408 >>>>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3D3DError= > =3D >>> accessing >>>>>>> memory address 0x8000ffffd008: Bad address. >>>>>>> ) at ../src/runtime/common/RTLinker.m3:115 >>>>>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3D3DError = >=3D >>> accessing >>>>>>> memory address 0x8000ffffd028: Bad address. >>>>>>> ) at ../src/runtime/common/RTLinker.m3:124 >>>>>>> #15 0x00000000004004a6 in main (argc=3D3DError accessing memory =3D= > >>> address >>>>>>> 0x8000ffffd07c: Bad address. >>>>>>> ) at _m3main.c:22 >>>>>>> =3D20 >>>>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): >>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>> #1 0x0000000000477e8a in check_suspend () >>>>>>> #2 0x00000000004780a2 in sigcancel_handler () >>>>>>> #3 >>>>>>> #4 0x000000000047e53c in _umtx_op_err () >>>>>>> #5 0x0000000000475f14 in __thr_umutex_lock () >>>>>>> #6 0x0000000000479404 in mutex_lock_common () >>>>>>> #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3DError >>>>>>> accessing memory address 0x8000ff5fac18: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>> #8 0x000000000044d039 in RTOS__LockHeap () at >>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>>> #9 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address =3D >>> 0x8000ff5fac88: Bad >>>>>>> address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>> (M3_Eic7CK_def=3D3DError >>>>>>> accessing memory address 0x8000ff5fad48: Bad address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>>> (M3_AJWxb1_defn=3D3DError accessing memory address = >0x8000ff5fada8: =3D >>> Bad address. >>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3DError =3D >>> accessing >>>>>>> memory address 0x8000ff5fade8: Bad address. >>>>>>> ) at ../src/Main.m3:283 >>>>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3DError >>>>>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >0x8000ff5faf68: =3D >>> Bad address. >>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>> #15 0x000000000047c7d4 in thread_start () >>>>>>> #16 0x0000000000000000 in ?? () >>>>>>> =3D20 >>>>>>> (others are similar) >>>>>>> =3D20 >>>>>>> Hmm looks like a FreeBSD issue now. It's here... >>>>>>> =3D20 >>>>>>> int >>>>>>> __cdecl >>>>>>> ThreadPThread__SuspendThread (m3_pthread_t mt) >>>>>>> { >>>>>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), >>>>>>> "pthread_suspend_np"); >>>>>>> return 1; >>>>>>> } >>>>>>> =3D20 >>>>>>> Now this suspend can wait: >>>>>>> =3D20 >>>>>>> static int >>>>>>> suspend_common(struct pthread *curthread, struct pthread *thread, >>>>>>> int waitok) >>>>>>> { >>>>>>> uint32_t tmp; >>>>>>> =3D20 >>>>>>> while (thread->state !=3D3D PS_DEAD && >>>>>>> !(thread->flags & THR_FLAGS_SUSPENDED)) { >>>>>>> thread->flags |=3D3D THR_FLAGS_NEED_SUSPEND; >>>>>>> /* Thread is in creation. */ >>>>>>> if (thread->tid =3D3D=3D3D TID_TERMINATED) >>>>>>> return (1); >>>>>>> tmp =3D3D thread->cycle; >>>>>>> _thr_send_sig(thread, SIGCANCEL); >>>>>>> THR_THREAD_UNLOCK(curthread, thread); >>>>>>> if (waitok) { >>>>>>> _thr_umtx_wait_uint(&thread->cycle, tmp, =3D >>> NULL, >>>>>>> 0); <=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D >>>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>>> } else { >>>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>>> return (0); >>>>>>> } >>>>>>> } >>>>>>> =3D20 >>>>>>> return (1); >>>>>>> } >>>>>>> =3D20 >>>>>>> ... but what it can wait for I am not clear on. >>>>>>> =3D20 >>>>>>> Do things work better on Linux? >>>>>>> =3D20 >>>>>>> What is the status of the fork bug? Can it be worked around by =3D= > >>> only >>>>>>> forking via Process.Create with no mutexes held (outside of all =3D= > >>> LOCK >>>>>>> blocks)? >>>>>>> =3D20 >>>>>>> Mika >>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> Peter McKinna writes: >>>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>>> Content-Type: text/plain; charset=3D3DUTF-8 >>>>>>>> =3D20 >>>>>>>> Mika >>>>>>>> =3D20 >>>>>>>> I think you need to back out Tony's changes to fix the fork bug, = >=3D >>> at >>>>>>> least >>>>>>>> for now. Need to reload from cvs version 1.262 for =3D >>> ThreadPThread.m3 If >>>>>>>> you're using git you're on your own. >>>>>>>> Do a cvs log ThreadPThread.m3 for an explanation for some of the = >=3D >>> design >>>>>>>> principles. >>>>>>>> Also if you use gdb then you need to set lanc c before = >backtraces =3D >>> so at >>>>>>>> least you can see address names and values even if they are =3D >>> contorted you >>>>>>>> can extract the M3 name in the parm lists. Also in gdb thread =3D >>> apply all >>>>>>> bt >>>>>>>> gives all thread backtraces which can be handy to see whose got = >=3D >>> the locks >>>>>>>> held. >>>>>>>> =3D20 >>>>>>>> Regards Peter >>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> On Wed, Aug 13, 2014 at 12:14 PM, = >wrote: >>>>>>>> =3D20 >>>>>>>>> =3D20 >>>>>>>>> Question... is there something odd about my pthreads? Are =3D >>> pthreads >>>>>>>>> normally reentrant? I didn't think so. >>>>>>>>> =3D20 >>>>>>>>> My compiler is much happier with the following changes I = >already >>>>>>> outlined: >>>>>>>>> =3D20 >>>>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >=3D >>> going >>>>>>> from >>>>>>>>> XWait with self.mutex locked to m.release(). >>>>>>>>> =3D20 >>>>>>>>> 2. the change to LockHeap I described in previous email >>>>>>>>> =3D20 >>>>>>>>> But now... >>>>>>>>> =3D20 >>>>>>>>> (gdb) cont >>>>>>>>> Continuing. >>>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>>> =3D20 >>>>>>>>> Program received signal SIGABRT, Aborted. >>>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>>> (gdb) where >>>>>>>>> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>>> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >>>>>>>>> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock >>>>>>> (mutex=3D3DError >>>>>>>>> accessing memory address 0x8000ffffb508: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >>>>>>>>> #3 0x000000000071d48d in RTOS__LockHeap () at >>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >>>>>>>>> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>>>>> (M3_Af40ku_ref=3D3DError >>>>>>>>> accessing memory address 0x8000ffffb568: Bad address. >>>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234 >>>>>>>>> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >>>>>>>>> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >>>>>>>>> #7 0x000000000070dd8b in RTProcess__Fork () at >>>>>>>>> ../src/runtime/common/RTProcessC.c:152 >>>>>>>>> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>>>>>>>> (M3_Bd56fi_cmd=3D3DError accessing memory address = >0x8000ffffb6f8: =3D >>> Bad >>>>>>> address. >>>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >>>>>>>>> #9 0x00000000006c6c6c in Process__Create = >(M3_Bd56fi_cmd=3D3DError >>>>>>> accessing >>>>>>>>> memory address 0x8000ffffb7f8: Bad address. >>>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21 >>>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>>> (M3_D6rRrg_ep=3D3DError >>>>>>>>> accessing memory address 0x8000ffffb838: Bad address. >>>>>>>>> ) at ../src/QMachine.m3:1666 >>>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand =3D >>> (M3_An02H2_t=3D3DError >>>>>>>>> accessing memory address 0x8000ffffb9f8: Bad address. >>>>>>>>> ) at ../src/QMachine.m3:1605 >>>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec = >(M3_An02H2_t=3D3DError >>>>>>> accessing >>>>>>>>> memory address 0x8000ffffbee8: Bad address. >>>>>>>>> ) at ../src/QMachine.m3:1476 >>>>>>>>> =3D20 >>>>>>>>> What am I doing wrong here? >>>>>>>>> =3D20 >>>>>>>>> The error doesn't look unreasonable! Looking more closely at = >the =3D >>> code: >>>>>>>>> =3D20 >>>>>>>>> First, AtForkPrepare has been called: >>>>>>>>> =3D20 >>>>>>>>> PROCEDURE AtForkPrepare() =3D3D >>>>>>>>> VAR me :=3D3D GetActivation(); >>>>>>>>> act: Activation; >>>>>>>>> BEGIN >>>>>>>>> PThreadLockMutex(slotsMu, ThisLine()); >>>>>>>>> PThreadLockMutex(perfMu, ThisLine()); >>>>>>>>> PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D3D> >>>>>>>>> RegisterFinalCleanup =3D3D> LockHeap *) >>>>>>>>> PThreadLockMutex(heapMu, ThisLine()); >>>>>>>>> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap =3D3D> >>>>>>> SuspendOthers >>>>>>>>> =3D3D> activeMu *) >>>>>>>>> (* Walk activations and lock all threads. >>>>>>>>> * NOTE: We have initMu, activeMu, so slots won't change, >>>>>>> conditions >>>>>>>>> and >>>>>>>>> * mutexes won't be initialized on-demand. >>>>>>>>> *) >>>>>>>>> act :=3D3D me; >>>>>>>>> REPEAT >>>>>>>>> PThreadLockMutex(act.mutex, ThisLine()); >>>>>>>>> act :=3D3D act.next; >>>>>>>>> UNTIL act =3D3D me; >>>>>>>>> END AtForkPrepare; >>>>>>>>> =3D20 >>>>>>>>> a postcondition of this routine is that heapMu is locked. >>>>>>>>> =3D20 >>>>>>>>> now we get into AtForkParent: >>>>>>>>> =3D20 >>>>>>>>> PROCEDURE AtForkParent() =3D3D >>>>>>>>> VAR me :=3D3D GetActivation(); >>>>>>>>> act: Activation; >>>>>>>>> cond: Condition; >>>>>>>>> BEGIN >>>>>>>>> (* Walk activations and unlock all threads, conditions. *) >>>>>>>>> act :=3D3D me; >>>>>>>>> REPEAT >>>>>>>>> cond :=3D3D slots[act.slot].join; >>>>>>>>> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, =3D >>> ThisLine()) >>>>>>> END; >>>>>>>>> PThreadUnlockMutex(act.mutex, ThisLine()); >>>>>>>>> act :=3D3D act.next; >>>>>>>>> UNTIL act =3D3D me; >>>>>>>>> PThreadUnlockMutex(activeMu, ThisLine()); >>>>>>>>> PThreadUnlockMutex(heapMu, ThisLine()); >>>>>>>>> PThreadUnlockMutex(initMu, ThisLine()); >>>>>>>>> PThreadUnlockMutex(perfMu, ThisLine()); >>>>>>>>> PThreadUnlockMutex(slotsMu, ThisLine()); >>>>>>>>> END AtForkParent; >>>>>>>>> =3D20 >>>>>>>>> We can see by inspecting the code that a necessary precondition = >=3D >>> for >>>>>>>>> this routine is that heapMu is locked! (Since it's going to =3D >>> unlock it, >>>>>>>>> it had BETTER be locked on entry.) >>>>>>>>> =3D20 >>>>>>>>> But the cond :=3D3D ... causes a RTHooks.CheckLoadTracedRef >>>>>>>>> =3D20 >>>>>>>>> which causes an RTOS.LockHeap >>>>>>>>> =3D20 >>>>>>>>> the code of which we just saw: >>>>>>>>> =3D20 >>>>>>>>> PROCEDURE LockHeap () =3D3D >>>>>>>>> VAR self :=3D3D pthread_self(); >>>>>>>>> BEGIN >>>>>>>>> WITH r =3D3D pthread_mutex_lock(heapMu,ThisLine()) DO = ><*ASSERT =3D >>> r=3D3D0*> >>>>>>> END; >>>>>>>>> ... >>>>>>>>> =3D20 >>>>>>>>> we try to lock heapMu. kaboom! No surprise there, really? >>>>>>>>> =3D20 >>>>>>>>> Am I going about this totally the wrong way? Other people are = >=3D >>> running >>>>>>>>> Modula-3 >>>>>>>>> with pthreads, right? Right?? Somewhere out there in =3D >>> m3devel-land? >>>>>>>>> =3D20 >>>>>>>>> Mika >>>>>>>>> =3D20 >>>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>>> Content-Type: text/html; charset=3D3DUTF-8 >>>>>>>> Content-Transfer-Encoding: quoted-printable >>>>>>>> =3D20 >>>>>>>>
Mika

=3D3DC2=3D3DA0 I = >think you =3D >>> need to back >>>>>>> ou=3D3D >>>>>>>> t Tony's changes to fix the fork bug, at least for now. Need = >=3D >>> to >>>>>>> reload =3D3D >>>>>>>> from cvs version 1.262 for ThreadPThread.m3 If you're using = >=3D >>> git >>>>>>> you'=3D3D >>>>>>>> ;re on your own.
>>>>>>>> =3D20 >>>>>>>>
=3D3DC2=3D3DA0 Do a cvs log ThreadPThread.m3 for an = >explanation =3D >>> for some of >>>>>>> th=3D3D >>>>>>>> e design principles.=3D3DC2=3D3DA0
=3D3DC2=3D3DA0 Also = >if you =3D >>> use gdb then you >>>>>>> ne=3D3D >>>>>>>> ed to set lanc c before backtraces so at least you can see = >address =3D >>> names >>>>>>> an=3D3D >>>>>>>> d values even if they are contorted you can extract the M3 name = >in =3D >>> the >>>>>>> parm=3D3D >>>>>>>> lists. Also in gdb thread apply all bt gives all thread = >backtraces >>>>>>> which c=3D3D >>>>>>>> an be handy to see whose got the locks held.
>>>>>>>> =3D20 >>>>>>>>

Regards Peter

>>>>>> class=3D3D3D"gmail_e=3D3D >>>>>>>> xtra">

On Wed, Aug 13, = >2014 at =3D >>> 12:14 >>>>>>> PM, =3D3D >>>>>>>> <href=3D3D3D"mailto:mika at async.caltech.edu" >>>>>>> target=3D3D3D"=3D3D >>>>>>>> _blank">mika at async.caltech.edu> wrote:
>>>>>>>> =3D20 >>>>>>>>
>>>>>> .8ex;border-left:1p=3D3D >>>>>>>> x #ccc solid;padding-left:1ex">
>>>>>>>> Question... is there something odd about my pthreads? = >=3D3DC2=3D3DA0Are =3D >>> pthreads >>>>>>> no=3D3D >>>>>>>> rmally reentrant? =3D3DC2=3D3DA0I didn't think so.
>>>>>>>>
>>>>>>>> My compiler is much happier with the following changes I already >>>>>>> outlined:<=3D3D >>>>>>>> br> >>>>>>>>
>>>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >=3D >>> going >>>>>>> from =3D3D >>>>>>>> XWait with self.mutex locked to m.release().
>>>>>>>>
>>>>>>>> 2. the change to LockHeap I described in previous email
>>>>>>>>
>>>>>>>> But now...
>>>>>>>>
>>>>>>>> (gdb) cont
>>>>>>>> Continuing.
>>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>>>
>>>>>>>> Program received signal SIGABRT, Aborted.
>>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>>>>> (gdb) where
>>>>>>>> #0 =3D3DC2=3D3DA00x000000080107626a in thr_kill () from =3D >>> /lib/libc.so.7
>>>>>>>> #1 =3D3DC2=3D3DA00x000000080113dac9 in abort () from =3D >>> /lib/libc.so.7
>>>>>>>> #2 =3D3DC2=3D3DA00x000000000071e37a in =3D >>> ThreadPThread__pthread_mutex_lock >>>>>>> (mutex=3D3D3DE=3D3D >>>>>>>> rror accessing memory address 0x8000ffffb508: Bad address.
>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>>>>> #3 =3D3DC2=3D3DA00x000000000071d48d in RTOS__LockHeap () at >>>>>>> ../src/thread/PTHREAD/T=3D3D >>>>>>>> hreadPThread.m3:1377
>>>>>>>> #4 =3D3DC2=3D3DA00x0000000000706b9d in = >RTHooks__CheckLoadTracedRef >>>>>>> (M3_Af40ku_ref=3D3D >>>>>>>> =3D3D3DError accessing memory address 0x8000ffffb568: Bad =3D >>> address.
>>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>>>>> #5 =3D3DC2=3D3DA00x000000000071d284 in = >ThreadPThread__AtForkParent () =3D >>> at >>>>>>> ../src/thr=3D3D >>>>>>>> ead/PTHREAD/ThreadPThread.m3:1348
>>>>>>>> #6 =3D3DC2=3D3DA00x0000000800df8733 in fork () from =3D >>> /lib/libthr.so.3
>>>>>>>> #7 =3D3DC2=3D3DA00x000000000070dd8b in RTProcess__Fork () at >>>>>>> ../src/runtime/common/=3D3D >>>>>>>> RTProcessC.c:152
>>>>>>>> #8 =3D3DC2=3D3DA00x00000000006c52f2 in =3D >>> ProcessPosixCommon__Create_ForkExec >>>>>>> (M3_Bd56=3D3D >>>>>>>> fi_cmd=3D3D3DError accessing memory address 0x8000ffffb6f8: Bad = >=3D >>> address.
>>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>>>>> #9 =3D3DC2=3D3DA00x00000000006c6c6c in Process__Create =3D >>> (M3_Bd56fi_cmd=3D3D3DError >>>>>>> acces=3D3D >>>>>>>> sing memory address 0x8000ffffb7f8: Bad address.
>>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>>> (M3_D6rRrg_ep=3D3D3DError=3D3D >>>>>>>> accessing memory address 0x8000ffffb838: Bad address.
>>>>>>>> ) at ../src/QMachine.m3:1666
>>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand =3D >>> (M3_An02H2_t=3D3D3DError >>>>>>> access=3D3D >>>>>>>> ing memory address 0x8000ffffb9f8: Bad address.
>>>>>>>> ) at ../src/QMachine.m3:1605
>>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec = >(M3_An02H2_t=3D3D3DError=3D >>>=20 >>>>>>> accessin=3D3D >>>>>>>> g memory address 0x8000ffffbee8: Bad address.
>>>>>>>> ) at ../src/QMachine.m3:1476
>>>>>>>>
>>>>>>>> What am I doing wrong here?
>>>>>>>>
>>>>>>>> The error doesn't look unreasonable! =3D3DC2=3D3DA0Looking = >more =3D >>> closely at >>>>>>> the =3D3D >>>>>>>> code:
>>>>>>>>
>>>>>>>> First, AtForkPrepare has been called:
>>>>>>>>
>>>>>>>> PROCEDURE AtForkPrepare() =3D3D3D
>>>>>>>> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >Activation;
>>>>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(slotsMu, = >ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(perfMu, = >ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(initMu, = >ThisLine()); (* =3D >>> InitMutex =3D3D3D> >>>>>>> Re=3D3D >>>>>>>> gisterFinalCleanup =3D3D3D> LockHeap *)
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(heapMu, = >ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(activeMu, = >ThisLine()); (* =3D >>> LockHeap >>>>>>> =3D3D3D> S=3D3D >>>>>>>> uspendOthers =3D3D3D> activeMu *)
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and lock all =3D= > >>> threads.
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* NOTE: We have = >initMu, activeMu, =3D >>> so slots won't >>>>>>> ch=3D3D >>>>>>>> ange, conditions and
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* mutexes won't = >be initialized =3D >>> on-demand.
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0*)
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >PThreadLockMutex(act.mutex, =3D >>> ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >act.next;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>>>>> =3D3DC2=3D3DA0 END AtForkPrepare;
>>>>>>>>
>>>>>>>> a postcondition of this routine is that heapMu is locked.
>>>>>>>>
>>>>>>>> now we get into AtForkParent:
>>>>>>>>
>>>>>>>> PROCEDURE AtForkParent() =3D3D3D
>>>>>>>> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >Activation;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond: = >Condition;
>>>>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and unlock all = >threads, =3D >>> conditions. >>>>>>> *)>>>>>>>> =3D20 >>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond :=3D3D3D =3D >>> slots[act.slot].join;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 IF cond # NIL THEN = >=3D >>> PThreadUnlockMutex(cond.mutex, >>>>>>> This=3D3D >>>>>>>> Line()) END;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >PThreadUnlockMutex(act.mutex, =3D >>> ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >act.next;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(activeMu, =3D >>> ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(heapMu, = >ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(initMu, = >ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(perfMu, = >ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(slotsMu, = >ThisLine());
>>>>>>>> =3D3DC2=3D3DA0 END AtForkParent;
>>>>>>>>
>>>>>>>> We can see by inspecting the code that a necessary precondition = >=3D >>> for
>>>>>>>> this routine is that heapMu is locked! =3D3DC2=3D3DA0(Since = >it's =3D >>> going to >>>>>>> unloc=3D3D >>>>>>>> k it,
>>>>>>>> it had BETTER be locked on entry.)
>>>>>>>>
>>>>>>>> But the cond :=3D3D3D ... causes a = >RTHooks.CheckLoadTracedRef
>>>>>>>>
>>>>>>>> which causes an RTOS.LockHeap
>>>>>>>>
>>>>>>>> the code of which we just saw:
>>>>>>>>
>>>>>>>> PROCEDURE LockHeap () =3D3D3D
>>>>>>>> =3D3DC2=3D3DA0 VAR self :=3D3D3D pthread_self();
>>>>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 WITH r =3D3D3D =3D >>> pthread_mutex_lock(heapMu,ThisLine()) DO >>>>>>> <*ASSE=3D3D >>>>>>>> RT r=3D3D3D0*> END;
>>>>>>>> ...
>>>>>>>>
>>>>>>>> we try to lock heapMu. =3D3DC2=3D3DA0kaboom! =3D3DC2=3D3DA0No = >surprise =3D >>> there, really?
>>>>>>>>
>>>>>>>> Am I going about this totally the wrong way? =3D3DC2=3D3DA0Other = >=3D >>> people are >>>>>>> running=3D3D >>>>>>>> Modula-3
>>>>>>>> with pthreads, right? =3D3DC2=3D3DA0Right?? =3D3DC2=3D3DA0Somewher= >e out =3D >>> there in >>>>>>> m3devel-la=3D3D >>>>>>>> nd?
>>>>>>>>
>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika
>>>>>>>>
>>>>>>>>

>>>>>>>> =3D20 >>>>>>>> --001a11c2ced4471a2e050079db82-- >>>>>>> =3D20 >>>>>> =3D20 >>>>>> =3D20 >>>>> =3D20 >>>>> --089e01183a1813188705007c3498 >>>>> Content-Type: text/html; charset=3D3DUTF-8 >>>>> Content-Transfer-Encoding: quoted-printable >>>>> =3D20 >>>>>
Oh, one other thing that seemed to help me in = >=3D >>> testing this=3D3D >>>>> stuff especially things to do with m3core and libm3 which seem to = >get =3D >>> out =3D3D >>>>> of whack sometimes, is to totally remove the target directory of =3D >>> m3core the=3D3D >>>>> n cm3; cm3 -ship Same with libm3. I'm not sure that clean =3D >>> actually remo=3D3D >>>>> ves the targets and I think there are leftover files that stuff =3D >>> things up s=3D3D >>>>> ince I would get segv in FileRd for no obvious reason.
>>>>>
Peter

>> class=3D3D3D"gmail_extra"><=3D3D >>>>> br>
On Wed, Aug 13, 2014 at 3:33 = >PM, =3D >>> Peter Mc=3D3D >>>>> Kinna <>> href=3D3D3D"mailto:peter.mckinna at gmail.com" targ=3D3D >>>>> et=3D3D3D"_blank">peter.mckinna at gmail.com> wrote:
>>>>>
>> .8ex;border-left:1p=3D3D >>>>> x #ccc solid;padding-left:1ex">
That is weird. = >The =3D >>> thread t=3D3D >>>>> ester works fine with the old version of ThreadPThread.m3 on linux = >=3D >>> amd_64 e=3D3D >>>>> xcept if you have the fork test in the mix of tests you see the =3D >>> pthread_mut=3D3D >>>>> ex_destroy every now and again, the fork bug in = >fact.=3D3DC2=3D3DA0
>>>>> =3D20 >>>>> I was testing the pthread changes Tony has made over the past few =3D= > >>> days usin=3D3D >>>>> g the thread tester program until I stupidly rebuilt the compiler = >and =3D >>> was g=3D3D >>>>> etting all sorts of hangs as it dragged in the new version of =3D >>> pthreads. So =3D3D >>>>> I rebuilt everything from a backup to get back where I was with a =3D= > >>> decent co=3D3D >>>>> mpiler, then reintroduced the latest changes to ThreadPThread.m3, =3D= > >>> which yes=3D3D >>>>> terday was just hanging in sigsuspend but today is giving me an =3D >>> assert fail=3D3D >>>>> ure at line 1387 in UnlockHeap. So its a bit unstable to say the =3D >>> least. May=3D3D >>>>> be there is something else wrong with freebsd.
>>>>> >>>>> =3D >>> = >

Peter

>>> clas=3D3D >>>>> s=3D3D3D"HOEnZb">
>> class=3D3D3D"gmail_extra">

>>>> s=3D3D3D"gmail_quote">On Wed, Aug 13, 2014 at 2:54 PM, >> dir=3D3D3D"ltr"><<=3D3D >>>>> a href=3D3D3D"mailto:mika at async.caltech.edu" =3D >>> target=3D3D3D"_blank">mika at async.calte=3D3D >>>>> ch.edu> wrote:
>>>>> =3D20 >>>>>
>> .8ex;border-left:1p=3D3D >>>>> x #ccc solid;padding-left:1ex">
>>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not =3D >>> getting>>>>> =3D20 >>>>> things to work and now I'm really baffled because I think I =3D >>> understand<=3D3D >>>>> br> >>>>> this code!
>>>>>
>>>>> What I did was I threw away all my changes and reverted =3D >>> ThreadPThread.m3>>>>> =3D20 >>>>> to 1.262 as you suggested.
>>>>>
>>>>> Rebuilt the compiler with upgrade.sh
>>>>>
>>>>> Then rebuilt the compiler again with itself.
>>>>>
>>>>> Then I realcleaned the world and buildshipped it. =3D3DC2=3D3DA0(I = >was =3D >>> afraid
>>>>> that parseparams, also imported by the thread tester, would =3D >>> pollute
>>>>> it somehow.)
>>>>>
>>>>> When I look at the code in 1.262 it looks quite straightforward. =3D >>> =3D3DC2=3D3DA0heap=3D3D >>>>> Mu
>>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. =3D >>> =3D3DC2=3D3DA0Cond=3D3D >>>>> ition
>>>>> variables are mutexes too, but that's no big deal.
>>>>>
>>>>> So, rebuild thread tester, run it:
>>>>>
>>>>> new source -> compiling Main.m3
>>>>> =3D3DC2=3D3DA0-> linking threadtest
>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # =3D >>> AMD64_FREEB=3D3D >>>>> SD/threadtest
>>>>> Writing file...done
>>>>> Creating read threads...done
>>>>> Creating fork threads...done
>>>>> Creating alloc threads...done
>>>>> Creating lock threads...done
>>>>> running...printing oldest/median age/newest
>>>>> .
>>>>>
>>>>> ***
>>>>> *** runtime error:
>>>>> *** =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Segmentation violation - possible = >attempt to =3D >>> dereference N=3D3D >>>>> IL.........laziest thread is 1407901189/>> href=3D3D3D"tel:1407901189%2F9" valu=3D3D >>>>> e=3D3D3D"+14079011899" target=3D3D3D"_blank">1407901189/9 = >(tests: =3D >>> read 14079011=3D3D >>>>> 89/1407901189/1407901189 fork 1407901189/1407901189/1407901189 = >alloc =3D >>> 9/9/9 =3D3D >>>>> lock 1407901189/1407901189/9)
>>>>> =3D20 >>>>> =3D20 >>>>>
>>>>>
>>>>>
>>>>>
>>>>> ^C
>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb = >=3D >>> !$
>>>>> gdb AMD64_FREEBSD/threadtest
>>>>> GNU gdb 6.1.1 [FreeBSD]
>>>>> Copyright 2004 Free Software Foundation, Inc.
>>>>> GDB is free software, covered by the GNU General Public License, = >and =3D >>> you ar=3D3D >>>>> e
>>>>> welcome to change it and/or distribute copies of it under certain =3D= > >>> condition=3D3D >>>>> s.
>>>>> Type "show copying" to see the conditions.
>>>>> There is absolutely no warranty for GDB. =3D3DC2=3D3DA0Type = >"show =3D >>> warranty&quo=3D3D >>>>> t; for details.
>>>>> This GDB was configured as "amd64-marcel-freebsd"...
>>>>> (gdb) run
>>>>> Starting program: =3D >>> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread=3D3D >>>>> /AMD64_FREEBSD/threadtest
>>>>> [New LWP 100121]
>>>>> Writing file...done
>>>>> Creating read threads...done
>>>>> Creating fork threads...done
>>>>> Creating alloc threads...done
>>>>> Creating lock threads...done
>>>>> running...printing oldest/median age/newest
>>>>> .[New Thread 801807000 (LWP 100343/threadtest)]
>>>>> [New Thread 801807c00 (LWP 100667/threadtest)]
>>>>> [New Thread 801808800 (LWP 100816/threadtest)]
>>>>> [New Thread 801807400 (LWP 100349/threadtest)]
>>>>> [New Thread 801808400 (LWP 100815/threadtest)]
>>>>> [New Thread 801807800 (LWP 100352/threadtest)]
>>>>> [New Thread 801808c00 (LWP 100817/threadtest)]
>>>>> [New Thread 801809000 (LWP 100818/threadtest)]
>>>>> [New Thread 801809800 (LWP 100820/threadtest)]
>>>>> [New Thread 801808000 (LWP 100678/threadtest)]
>>>>> [New Thread 801806400 (LWP 100121/threadtest)]
>>>>> [New Thread 801806800 (LWP 100341/threadtest)]
>>>>> [New Thread 801806c00 (LWP 100342/threadtest)]
>>>>> .ERROR: pthread_mutex_lock:11
>>>>>

>>>>> Program received signal SIGABRT, Aborted.
>>>>>
[Switching to Thread 801809800 (LWP 100820/threadtest)]
>>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>>>>> (gdb) where
>>>>> #0 =3D3DC2=3D3DA00x0000000800d5c26a in thr_kill () from =3D >>> /lib/libc.so.7
>>>>> #1 =3D3DC2=3D3DA00x0000000800e23ac9 in abort () from = >/lib/libc.so.7
>>>>> #2 =3D3DC2=3D3DA00x000000000045101f in = >ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3D3DE=3D3D >>>>> rror accessing memory address 0x8000fe5f2d98: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
>>>>> #3 =3D3DC2=3D3DA00x000000000044b370 in ThreadPThread__LockMutex =3D >>> (M3_AYIbX3_m=3D3D3DErro=3D3D >>>>> r accessing memory address 0x8000fe5f2dc8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>>> #4 =3D3DC2=3D3DA00x0000000000405b5d in Main__LApply = >(M3_AP7a1g_cl=3D3D3DError=3D >>> accessing=3D3D >>>>> memory address 0x8000fe5f2df8: Bad address.
>>>>> ) at ../src/Main.m3:319
>>>>> #5 =3D3DC2=3D3DA00x000000000044d243 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3D3DErr=3D3D >>>>> or accessing memory address 0x8000fe5f2eb8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>> #6 =3D3DC2=3D3DA00x000000000044cf00 in ThreadPThread__ThreadBase =3D >>> (M3_AJWxb1_param=3D3D >>>>> =3D3D3DError accessing memory address 0x8000fe5f2f68: Bad = >address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>> #7 =3D3DC2=3D3DA00x0000000800ad54a4 in pthread_create () from =3D >>> /lib/libthr.so.3
>>>>> #8 =3D3DC2=3D3DA00x0000000000000000 in ?? ()
>>>>> (gdb) set lang c
>>>>> (gdb) thread apply all bt
>>>>> ... not that interesting ...
>>>>>
>>>>> Segfault is segfault---error 11 is EDEADLK (locking against =3D >>> myself?)
>>>>>
>>>>> ????? the code is very straightforward, as I said.
>>>>>
>>>>> I thought people had the thread tester working with pthreads? =3D >>> =3D3DC2=3D3DA0Which s=3D3D >>>>> et of files, then? =3D3DC2=3D3DA0Anyone on FreeBSD/amd64?
>>>>>
>>>>> Could it be an issue with "volatile"? =3D3DC2=3D3DA0Not = >even =3D >>> sure where t=3D3D >>>>> o look.
>>>>>
>>>>> The code calling the lock is just this:
>>>>>
>>>>> PROCEDURE GetChar (rd: T): CHAR
>>>>> =3D3DC2=3D3DA0 RAISES {EndOfFile, Failure, Alerted} =3D3D3D
>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 LOCK rd DO
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 RETURN = >FastGetChar(rd);
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 END
>>>>> =3D3DC2=3D3DA0 END GetChar;
>>>>>
>>>>> No mysteries there...
>>>>>
>>>>> Ah is this the fork bug? =3D3DC2=3D3DA0Looks like the Init routine = >is =3D >>> called on a>>>> r> >>>>> lot of NIL mutexes around the fork. =3D3DC2=3D3DA0But the = >subprocesses =3D >>> aren't m=3D3D >>>>> eant
>>>>> to accesses the mutexes... humm
>>>>>
>>>>> Hmm, and it's not entirely a fork issue. =3D3DC2=3D3DA0Even = >with =3D >>> "threadte=3D3D >>>>> st -tests STD,-fork,-forktoomuch" it misbehaves. =3D >>> =3D3DC2=3D3DA0Hangs....
>>>>>
>>>>> Looks like a deadlock this time.
>>>>>
>>>>> Some stacks...
>>>>>
>>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
>>>>> #0 =3D3DC2=3D3DA00x00000000004b4e2b in __vdso_gettimeofday ()
>>>>> #1 =3D3DC2=3D3DA00x00000000004ab8d2 in gettimeofday ()
>>>>> #2 =3D3DC2=3D3DA00x0000000000452e4b in TimePosix__Now () at =3D >>> ../src/time/POSIX/TimeP=3D3D >>>>> osixC.c:50
>>>>> #3 =3D3DC2=3D3DA00x0000000000452d72 in Time__Now () at =3D >>> ../src/time/POSIX/TimePosix.=3D3D >>>>> m3:14
>>>>> #4 =3D3DC2=3D3DA00x00000000004029a3 in Main__LApply = >(M3_AP7a1g_cl=3D3D3DError=3D >>> accessing=3D3D >>>>> memory address 0x8000fedf6df8: Bad address.
>>>>> ) at ../src/Main.m3:327
>>>>> #5 =3D3DC2=3D3DA00x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3D3DErr=3D3D >>>>> or accessing memory address 0x8000fedf6eb8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>> #6 =3D3DC2=3D3DA00x0000000000449c50 in ThreadPThread__ThreadBase =3D >>> (M3_AJWxb1_param=3D3D >>>>> =3D3D3DError accessing memory address 0x8000fedf6f68: Bad = >address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>> #7 =3D3DC2=3D3DA00x000000000047c7d4 in thread_start ()
>>>>> #8 =3D3DC2=3D3DA00x0000000000000000 in ?? ()
>>>>>
>>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>> #1 =3D3DC2=3D3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>>> #2 =3D3DC2=3D3DA00x0000000000479404 in mutex_lock_common ()
>>>>> #3 =3D3DC2=3D3DA00x000000000044dd15 in = >ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3D3DE=3D3D >>>>> rror accessing memory address 0x8000feff7d98: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>> #4 =3D3DC2=3D3DA00x00000000004480c0 in ThreadPThread__LockMutex =3D >>> (M3_AYIbX3_m=3D3D3DErro=3D3D >>>>> r accessing memory address 0x8000feff7dc8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>>> #5 =3D3DC2=3D3DA00x00000000004028ad in Main__LApply = >(M3_AP7a1g_cl=3D3D3DError=3D >>> accessing=3D3D >>>>> memory address 0x8000feff7df8: Bad address.
>>>>> ) at ../src/Main.m3:319
>>>>> #6 =3D3DC2=3D3DA00x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3D3DErr=3D3D >>>>> or accessing memory address 0x8000feff7eb8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>> #7 =3D3DC2=3D3DA00x0000000000449c50 in ThreadPThread__ThreadBase =3D >>> (M3_AJWxb1_param=3D3D >>>>> =3D3D3DError accessing memory address 0x8000feff7f68: Bad = >address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>> #8 =3D3DC2=3D3DA00x000000000047c7d4 in thread_start ()
>>>>> #9 =3D3DC2=3D3DA00x0000000000000000 in ?? ()
>>>>>
>>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>> #1 =3D3DC2=3D3DA00x0000000000475759 in suspend_common ()
>>>>> #2 =3D3DC2=3D3DA00x00000000004755c1 in pthread_suspend_np ()
>>>>> #3 =3D3DC2=3D3DA00x000000000044df0c in ThreadPThread__SuspendThread = >=3D >>> (mt=3D3D3DError acc=3D3D >>>>> essing memory address 0x8000ffbfd6f8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
>>>>> #4 =3D3DC2=3D3DA00x000000000044bade in ThreadPThread__StopThread =3D >>> (M3_DMxDjQ_act=3D3D3DE=3D3D >>>>> rror accessing memory address 0x8000ffbfd718: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909
>>>>> #5 =3D3DC2=3D3DA00x000000000044bc81 in ThreadPThread__StopWorld () = >at =3D >>> ../src/thread=3D3D >>>>> /PTHREAD/ThreadPThread.m3:948
>>>>> #6 =3D3DC2=3D3DA00x000000000044b19e in RTThread__SuspendOthers () = >at =3D >>> ../src/thread/=3D3D >>>>> PTHREAD/ThreadPThread.m3:713
>>>>> #7 =3D3DC2=3D3DA00x00000000004330d6 in =3D >>> RTCollector__CollectSomeInStateZero () at ..=3D3D >>>>> /src/runtime/common/RTCollector.m3:749
>>>>> #8 =3D3DC2=3D3DA00x0000000000433081 in RTCollector__CollectSome () = >at =3D >>> ../src/runtim=3D3D >>>>> e/common/RTCollector.m3:723
>>>>> #9 =3D3DC2=3D3DA00x0000000000432d49 in RTHeapRep__CollectEnough () = >at =3D >>> ../src/runtim=3D3D >>>>> e/common/RTCollector.m3:657
>>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced =3D >>> (M3_Cwb5VA_dataSize=3D3D3DEr=3D3D >>>>> ror accessing memory address 0x8000ffbfd958: Bad address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:367
>>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>> (M3_Eic7CK_def=3D3D3DError =3D3D >>>>> accessing memory address 0x8000ffbfda18: Bad address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray =3D >>> (M3_AJWxb1_defn=3D3D3DErro=3D3D >>>>> r accessing memory address 0x8000ffbfda78: Bad address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3D3DError =3D >>> accessing memo=3D3D >>>>> ry address 0x8000ffbfdab8: Bad address.
>>>>> ) at ../src/rw/Rd.m3:159
>>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar = >(M3_EkTcCb_rd=3D3D3DError=3D >>> acces=3D3D >>>>> sing memory address 0x8000ffbfdb88: Bad address.
>>>>> ) at ../src/rw/Rd.m3:187
>>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3D3DError =3D >>> accessing memor=3D3D >>>>> y address 0x8000ffbfdbd8: Bad address.
>>>>> ) at ../src/rw/Rd.m3:176
>>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3D3DError =3D >>> accessing memo=3D3D >>>>> ry address 0x8000ffbfdc58: Bad address.
>>>>> ) at ../src/Main.m3:185
>>>>>
>>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3D3DError ac=3D3D >>>>> cessing memory address 0x8000ffbfdeb8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase =3D >>> (M3_AJWxb1_param=3D3D3DErro=3D3D >>>>> r accessing memory address 0x8000ffbfdf68: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>> #19 0x000000000047c7d4 in thread_start ()
>>>>> #20 0x0000000000000000 in ?? ()
>>>>>
>>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>> #1 =3D3DC2=3D3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>>> #2 =3D3DC2=3D3DA00x0000000000479404 in mutex_lock_common ()
>>>>> #3 =3D3DC2=3D3DA00x000000000044dd15 in = >ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3D3DE=3D3D >>>>> rror accessing memory address 0x8000ffffc678: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>> #4 =3D3DC2=3D3DA00x000000000044d039 in RTOS__LockHeap () at =3D >>> ../src/thread/PTHREAD/T=3D3D >>>>> hreadPThread.m3:1337
>>>>> ---Type <return> to continue, or q <return> to =3D >>> quit---
>>>>> #5 =3D3DC2=3D3DA00x000000000042ff79 in RTAllocator__AllocTraced =3D >>> (M3_Cwb5VA_dataSize=3D3D >>>>> =3D3D3DError accessing memory address 0x8000ffffc6e8: Bad = >address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>>> #6 =3D3DC2=3D3DA00x000000000042f15b in RTAllocator__GetTracedObj =3D >>> (M3_Eic7CK_def=3D3D3DE=3D3D >>>>> rror accessing memory address 0x8000ffffc7a8: Bad address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:224
>>>>> #7 =3D3DC2=3D3DA00x000000000042eb23 in RTHooks__AllocateTracedObj =3D= > >>> (M3_AJWxb1_defn=3D3D >>>>> =3D3D3DError accessing memory address 0x8000ffffc7f8: Bad = >address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:122
>>>>> #8 =3D3DC2=3D3DA00x000000000045fbe4 in TextCat__Flat =3D >>> (M3_Bd56fi_LText=3D3D3DError acces=3D3D >>>>> sing memory address 0x8000ffffc858: Bad address.
>>>>> ) at ../src/text/TextCat.m3:562
>>>>> #9 =3D3DC2=3D3DA00x000000000045ed5d in TextCat__Balance =3D >>> (M3_Bd56fi_LText=3D3D3D0x800c49=3D3D >>>>> 0b0, M3_BUgnwf_LInfo=3D3D3DError accessing memory address =3D >>> 0x8000ffffc8f8: Bad a=3D3D >>>>> ddress.
>>>>> ) at ../src/text/TextCat.m3:488
>>>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3D3D3DError = >=3D >>> accessing me=3D3D >>>>> mory address 0x8000ffffcbb8: Bad address.
>>>>> ) at ../src/text/TextCat.m3:40
>>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3D3DError = >accessing =3D >>> memory =3D3D >>>>> address 0x8000ffffcc38: Bad address.
>>>>> ) at ../src/Main.m3:593
>>>>> #12 0x000000000043d55d in RTLinker__RunMainBody = >(M3_DjPxE3_m=3D3D3DError =3D >>> access=3D3D >>>>> ing memory address 0x8000ffffcf88: Bad address.
>>>>> ) at ../src/runtime/common/RTLinker.m3:408
>>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3D3D3DError= > =3D >>> accessing=3D3D >>>>> memory address 0x8000ffffd008: Bad address.
>>>>> ) at ../src/runtime/common/RTLinker.m3:115
>>>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3D3D3DError = >=3D >>> accessing =3D3D >>>>> memory address 0x8000ffffd028: Bad address.
>>>>> ) at ../src/runtime/common/RTLinker.m3:124
>>>>> #15 0x00000000004004a6 in main (argc=3D3D3DError accessing memory =3D= > >>> address 0x800=3D3D >>>>> 0ffffd07c: Bad address.
>>>>> ) at _m3main.c:22
>>>>>
>>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>> #1 =3D3DC2=3D3DA00x0000000000477e8a in check_suspend ()
>>>>> #2 =3D3DC2=3D3DA00x00000000004780a2 in sigcancel_handler ()
>>>>> #3 =3D3DC2=3D3DA0<signal handler called>
>>>>> #4 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>> #5 =3D3DC2=3D3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>>> #6 =3D3DC2=3D3DA00x0000000000479404 in mutex_lock_common ()
>>>>> #7 =3D3DC2=3D3DA00x000000000044dd15 in = >ThreadPThread__pthread_mutex_lock =3D >>> (mutex=3D3D3DE=3D3D >>>>> rror accessing memory address 0x8000ff5fac18: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>> #8 =3D3DC2=3D3DA00x000000000044d039 in RTOS__LockHeap () at =3D >>> ../src/thread/PTHREAD/T=3D3D >>>>> hreadPThread.m3:1337
>>>>> #9 =3D3DC2=3D3DA00x000000000042ff79 in RTAllocator__AllocTraced =3D >>> (M3_Cwb5VA_dataSize=3D3D >>>>> =3D3D3DError accessing memory address 0x8000ff5fac88: Bad = >address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>> (M3_Eic7CK_def=3D3D3DError =3D3D >>>>> accessing memory address 0x8000ff5fad48: Bad address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray =3D >>> (M3_AJWxb1_defn=3D3D3DErro=3D3D >>>>> r accessing memory address 0x8000ff5fada8: Bad address.
>>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3D3DError =3D >>> accessing memo=3D3D >>>>> ry address 0x8000ff5fade8: Bad address.
>>>>> ) at ../src/Main.m3:283
>>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3D3DError ac=3D3D >>>>> cessing memory address 0x8000ff5faeb8: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase =3D >>> (M3_AJWxb1_param=3D3D3DErro=3D3D >>>>> r accessing memory address 0x8000ff5faf68: Bad address.
>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>> #15 0x000000000047c7d4 in thread_start ()
>>>>> #16 0x0000000000000000 in ?? ()
>>>>>
>>>>> (others are similar)
>>>>>
>>>>> Hmm looks like a FreeBSD issue now. =3D3DC2=3D3DA0It's = >here...
>>>>>
>>>>> int
>>>>> __cdecl
>>>>> ThreadPThread__SuspendThread (m3_pthread_t mt)
>>>>> {
>>>>> =3D3DC2=3D3DA0 =3D >>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), = >"=3D3D >>>>> pthread_suspend_np");
>>>>> =3D3DC2=3D3DA0 return 1;
>>>>> }
>>>>>
>>>>> Now this suspend can wait:
>>>>>
>>>>> static int
>>>>> suspend_common(struct pthread *curthread, struct pthread = >*thread,
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 int = >waitok)
>>>>> {
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >uint32_t tmp;
>>>>>
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 while = >(thread->state =3D >>> !=3D3D3D PS_DEAD &&=3D3D >>>>>
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 !(thread->flags & T=3D3D >>>>> HR_FLAGS_SUSPENDED)) {
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 thread->flags |=3D3D >>>>> =3D3D3D THR_FLAGS_NEED_SUSPEND;
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 /* Thread is in cre=3D3D >>>>> ation. */
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 if (thread->tid =3D3D >>>>> =3D3D3D=3D3D3D TID_TERMINATED)
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >D >>>>> =3D3DA0 =3D3DC2=3D3DA0 return (1);
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 tmp =3D3D3D thread->=3D3D >>>>> cycle;
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 _thr_send_sig(threa=3D3D >>>>> d, SIGCANCEL);
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 THR_THREAD_UNLOCK(c=3D3D >>>>> urthread, thread);
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 if (waitok) {
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >D >>>>> =3D3DA0 =3D3DC2=3D3DA0 _thr_umtx_wait_uint(&thread->cycle, = >tmp, =3D >>> NULL, 0); =3D3DC2=3D3DA0=3D3D >>>>> <=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D= >3D3D
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >D >>>>> =3D3DA0 =3D3DC2=3D3DA0 THR_THREAD_LOCK(curthread, thread);
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 } else {
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >D >>>>> =3D3DA0 =3D3DC2=3D3DA0 THR_THREAD_LOCK(curthread, thread);
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >D >>>>> =3D3DA0 =3D3DC2=3D3DA0 return (0);
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >=3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 }
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 }
>>>>>
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 return = >(1);
>>>>> }
>>>>>
>>>>> ... but what it can wait for I am not clear on.
>>>>>
>>>>> Do things work better on Linux?
>>>>>
>>>>> What is the status of the fork bug? =3D3DC2=3D3DA0Can it be worked = >around =3D >>> by only f=3D3D >>>>> orking via Process.Create with no mutexes held (outside of all LOCK = >=3D >>> blocks)=3D3D >>>>> ?
>>>>>
>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika
>>>>>
>>>>>
>>>>>
>>>>> Peter McKinna writes:
>>>>> >--001a11c2ced4471a2e050079db82
>>>>> >Content-Type: text/plain; charset=3D3D3DUTF-8
>>>>>
>
>>>>> >Mika
>>>>> >
>>>>> > =3D3DC2=3D3DA0I think you need to back out Tony's changes = >to fix =3D >>> the fork =3D3D >>>>> bug, at least
>>>>> >for now. Need to reload from cvs version 1.262 for =3D >>> ThreadPThread.m3 If<=3D3D >>>>> br> >>>>> >you're using git you're on your own.
>>>>> > =3D3DC2=3D3DA0Do a cvs log ThreadPThread.m3 for an explanation = >for =3D >>> some of the=3D3D >>>>> design
>>>>> >principles.
>>>>> > =3D3DC2=3D3DA0Also if you use gdb then you need to set lanc c = >before =3D >>> backtrace=3D3D >>>>> s so at
>>>>> >least you can see address names and values even if they are =3D >>> contorted y=3D3D >>>>> ou
>>>>> >can extract the M3 name in the parm lists. Also in gdb thread =3D= > >>> apply all=3D3D >>>>> bt
>>>>> >gives all thread backtraces which can be handy to see whose got = >=3D >>> the loc=3D3D >>>>> ks
>>>>> >held.
>>>>> >
>>>>> >Regards Peter
>>>>> >
>>>>> >
>>>>> >
>>>>> >On Wed, Aug 13, 2014 at 12:14 PM, <>> href=3D3D3D"mailto:mika at async.calt=3D3D >>>>> ech.edu" target=3D3D3D"_blank">mika at async.caltech.edu> =3D >>> wrote:
>>>>> >
>>>>> >>
>>>>> >> Question... is there something odd about my pthreads? =3D >>> =3D3DC2=3D3DA0Are pt=3D3D >>>>> hreads
>>>>> >> normally reentrant? =3D3DC2=3D3DA0I didn't think = >so.
>>>>> >>
>>>>> >> My compiler is much happier with the following changes I =3D= > >>> already o=3D3D >>>>> utlined:
>>>>> >>
>>>>> >> 1. a dirty, disgusting hack to keep from locking against =3D= > >>> myself go=3D3D >>>>> ing from
>>>>> >> XWait with self.mutex locked to m.release().
>>>>> >>
>>>>> >> 2. the change to LockHeap I described in previous = >email
>>>>> >>
>>>>> >> But now...
>>>>> >>
>>>>> >> (gdb) cont
>>>>> >> Continuing.
>>>>> >> ERROR: pthread_mutex_lock:11
>>>>> >> ERROR: pthread_mutex_lock:11
>>>>> >>
>>>>> >> Program received signal SIGABRT, Aborted.
>>>>> >> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>> >> (gdb) where
>>>>> >> #0 =3D3DC2=3D3DA00x000000080107626a in thr_kill () from =3D >>> /lib/libc.so.7
>>>>> >> #1 =3D3DC2=3D3DA00x000000080113dac9 in abort () from =3D >>> /lib/libc.so.7
>>>>> >> #2 =3D3DC2=3D3DA00x000000000071e37a in =3D >>> ThreadPThread__pthread_mutex_lock (=3D3D >>>>> mutex=3D3D3DError
>>>>> >> accessing memory address 0x8000ffffb508: Bad address.
>>>>> >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>> >> #3 =3D3DC2=3D3DA00x000000000071d48d in RTOS__LockHeap () = >at
>>>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>>>>> >> #4 =3D3DC2=3D3DA00x0000000000706b9d in =3D >>> RTHooks__CheckLoadTracedRef (M3_Af4=3D3D >>>>> 0ku_ref=3D3D3DError
>>>>> >> accessing memory address 0x8000ffffb568: Bad address.
>>>>> >> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>> >> #5 =3D3DC2=3D3DA00x000000000071d284 in =3D >>> ThreadPThread__AtForkParent () at>>>> r> >>>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>>>>> >> #6 =3D3DC2=3D3DA00x0000000800df8733 in fork () from =3D >>> /lib/libthr.so.3
>>>>> >> #7 =3D3DC2=3D3DA00x000000000070dd8b in RTProcess__Fork () = >at
>>>>> >> ../src/runtime/common/RTProcessC.c:152
>>>>> >> #8 =3D3DC2=3D3DA00x00000000006c52f2 in =3D >>> ProcessPosixCommon__Create_ForkExec=3D3D >>>>>
>>>>> >> (M3_Bd56fi_cmd=3D3D3DError accessing memory address =3D >>> 0x8000ffffb6f8: Ba=3D3D >>>>> d address.
>>>>> >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>> >> #9 =3D3DC2=3D3DA00x00000000006c6c6c in Process__Create =3D >>> (M3_Bd56fi_cmd=3D3D3DEr=3D3D >>>>> ror accessing
>>>>> >> memory address 0x8000ffffb7f8: Bad address.
>>>>> >> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>> >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise =3D >>> (M3_D6rRrg_e=3D3D >>>>> p=3D3D3DError
>>>>> >> accessing memory address 0x8000ffffb838: Bad address.
>>>>> >> ) at ../src/QMachine.m3:1666
>>>>> >> #11 0x00000000004d6220 in QMachine__ExecCommand =3D >>> (M3_An02H2_t=3D3D3DErr=3D3D >>>>> or
>>>>> >> accessing memory address 0x8000ffffb9f8: Bad address.
>>>>> >> ) at ../src/QMachine.m3:1605
>>>>> >> #12 0x00000000004d537e in QMachine__DoTryExec =3D >>> (M3_An02H2_t=3D3D3DError=3D3D >>>>> accessing
>>>>> >> memory address 0x8000ffffbee8: Bad address.
>>>>> >> ) at ../src/QMachine.m3:1476
>>>>> >>
>>>>> >> What am I doing wrong here?
>>>>> >>
>>>>> >> The error doesn't look unreasonable! =3D3DC2=3D3DA0Looki= >ng =3D >>> more closel=3D3D >>>>> y at the code:
>>>>> >>
>>>>> >> First, AtForkPrepare has been called:
>>>>> >>
>>>>> >> PROCEDURE AtForkPrepare() =3D3D3D
>>>>> >> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >Activation;
>>>>> >> =3D3DC2=3D3DA0 BEGIN
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(slotsMu, =3D >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(perfMu, =3D >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(initMu, = >ThisLine()); =3D >>> (* InitMutex =3D3D >>>>> =3D3D3D>
>>>>> >> RegisterFinalCleanup =3D3D3D> LockHeap *)
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(heapMu, =3D >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(activeMu, =3D= > >>> ThisLine()); (* LockHeap =3D3D >>>>> =3D3D3D> SuspendOthers
>>>>> >> =3D3D3D> activeMu *)
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and lock = >all =3D >>> threads.
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* NOTE: We = >have initMu, =3D >>> activeMu, so slots won=3D3D >>>>> 't change, conditions
>>>>> >> and
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* mutexes = >won't be =3D >>> initialized on-demand.<=3D3D >>>>> br> >>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0*)
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >PThreadLockMutex(act.mutex, =3D >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >act.next;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>> >> =3D3DC2=3D3DA0 END AtForkPrepare;
>>>>> >>
>>>>> >> a postcondition of this routine is that heapMu is =3D >>> locked.
>>>>> >>
>>>>> >> now we get into AtForkParent:
>>>>> >>
>>>>> >> PROCEDURE AtForkParent() =3D3D3D
>>>>> >> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >Activation;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond: = >Condition;
>>>>> >> =3D3DC2=3D3DA0 BEGIN
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and = >unlock all =3D >>> threads, conditio=3D3D >>>>> ns. *)
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond :=3D3D3D = >=3D >>> slots[act.slot].join;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 IF cond # NIL = >THEN =3D >>> PThreadUnlockMutex(cond.mu=3D3D >>>>> tex, ThisLine()) END;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>> PThreadUnlockMutex(act.mutex, ThisLine());>>>>> =3D20 >>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >act.next;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(activeMu, = >=3D >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(heapMu, =3D= > >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(initMu, =3D= > >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(perfMu, =3D= > >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(slotsMu, = >=3D >>> ThisLine());
>>>>> >> =3D3DC2=3D3DA0 END AtForkParent;
>>>>> >>
>>>>> >> We can see by inspecting the code that a necessary =3D >>> precondition fo=3D3D >>>>> r
>>>>> >> this routine is that heapMu is locked! =3D3DC2=3D3DA0(Since = >=3D >>> it's going=3D3D >>>>> to unlock it,
>>>>> >> it had BETTER be locked on entry.)
>>>>> >>
>>>>> >> But the cond :=3D3D3D ... causes a =3D >>> RTHooks.CheckLoadTracedRef
>>>>> >>
>>>>> >> which causes an RTOS.LockHeap
>>>>> >>
>>>>> >> the code of which we just saw:
>>>>> >>
>>>>> >> PROCEDURE LockHeap () =3D3D3D
>>>>> >> =3D3DC2=3D3DA0 VAR self :=3D3D3D pthread_self();
>>>>> >> =3D3DC2=3D3DA0 BEGIN
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 WITH r =3D3D3D =3D >>> pthread_mutex_lock(heapMu,ThisLine()) DO =3D3D >>>>> <*ASSERT r=3D3D3D0*> END;
>>>>> >> ...
>>>>> >>
>>>>> >> we try to lock heapMu. =3D3DC2=3D3DA0kaboom! =3D3DC2=3D3DA0N= >o =3D >>> surprise there, real=3D3D >>>>> ly?
>>>>> >>
>>>>> >> Am I going about this totally the wrong way? = >=3D3DC2=3D3DA0Other =3D >>> people ar=3D3D >>>>> e running
>>>>> >> Modula-3
>>>>> >> with pthreads, right? =3D3DC2=3D3DA0Right?? = >=3D3DC2=3D3DA0Somewhere =3D >>> out there in m=3D3D >>>>> 3devel-land?
>>>>> >>
>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika
>>>>> >>
>>>>> >>
>>>>> >
>>>>>
>--001a11c2ced4471a2e050079db82
>>>>> >Content-Type: text/html; charset=3D3D3DUTF-8
>>>>> >Content-Transfer-Encoding: quoted-printable
>>>>> >
>>>>> ><div =3D >>> dir=3D3D3D3D"ltr">Mika<div><br></div>=3D3= >D >>>>> ;<div>=3D3D3DC2=3D3D3DA0 I think you need to back ou=3D3D3D
= > >>>>> >t Tony&#39;s changes to fix the fork bug, at least for now. = >=3D >>> Need to=3D3D >>>>> reload =3D3D3D
>>>>> >from cvs version 1.262 for ThreadPThread.m3 If you&#39;re =3D= > >>> using git=3D3D >>>>> you&#39=3D3D3D
>>>>> >;re on your own.</div>
>>>>> >
>>>>> ><div>=3D3D3DC2=3D3D3DA0 Do a cvs log ThreadPThread.m3 for = >an =3D >>> explanation =3D3D >>>>> for some of th=3D3D3D
>>>>> >e design = >principles.=3D3D3DC2=3D3D3DA0</div><div>=3D3D3DC2=3D3D=3D >>> 3DA0 Also if=3D3D >>>>> you use gdb then you ne=3D3D3D
>>>>> >ed to set lanc c before backtraces so at least you can see =3D >>> address name=3D3D >>>>> s an=3D3D3D
>>>>> >d values even if they are contorted you can extract the M3 name = >=3D >>> in the =3D3D >>>>> parm=3D3D3D
>>>>> > lists. Also in gdb thread apply all bt gives all thread =3D >>> backtraces whi=3D3D >>>>> ch c=3D3D3D
>>>>> >an be handy to see whose got the locks held.</div>
>>>>> >
>>>>> ><div><br></div><div>Regards =3D >>> Peter</div>&l=3D3D >>>>> t;div><br></div><div = >class=3D3D3D3D"gmail_e=3D3D3D>> r> >>>>> >xtra"><br><br><div =3D >>> class=3D3D3D3D"gmail_quote&q=3D3D >>>>> uot;>On Wed, Aug 13, 2014 at 12:14 PM, =3D3D3D
>>>>> > <span dir=3D3D3D3D"ltr">&lt;<a =3D >>> href=3D3D3D3D"mailt=3D3D >>>>> o:>> target=3D3D3D"_blank">mika at async.ca=3D3D >>>>> ltech.edu" target=3D3D3D3D"=3D3D3D
>>>>> >_blank"> >>> target=3D3D3D"_bl=3D3D >>>>> ank">mika at async.caltech.edu</a>&gt;</span> =3D >>> wrote:<br=3D3D >>>>> >
>>>>> >
>>>>> ><blockquote class=3D3D3D3D"gmail_quote" =3D >>> style=3D3D3D3D"margin=3D3D >>>>> :0 0 0 .8ex;border-left:1p=3D3D3D
>>>>> >x #ccc solid;padding-left:1ex"><br>
>>>>> >Question... is there something odd about my pthreads? =3D >>> =3D3D3DC2=3D3D3DA0Are pth=3D3D >>>>> reads no=3D3D3D
>>>>> >rmally reentrant? =3D3D3DC2=3D3D3DA0I didn&#39;t think =3D >>> so.<br>
>>>>> ><br>
>>>>> >My compiler is much happier with the following changes I = >already =3D >>> outlin=3D3D >>>>> ed:<=3D3D3D
>>>>> >br>
>>>>> ><br>
>>>>> >1. a dirty, disgusting hack to keep from locking against myself = >=3D >>> going f=3D3D >>>>> rom =3D3D3D
>>>>> >XWait with self.mutex locked to m.release().<br>
>>>>> ><br>
>>>>> >2. the change to LockHeap I described in previous =3D >>> email<br>
>>>>> ><br>
>>>>> >But now...<br>
>>>>> ><br>
>>>>> >(gdb) cont<br>
>>>>> >Continuing.<br>
>>>>> >ERROR: pthread_mutex_lock:11<br>
>>>>> >ERROR: pthread_mutex_lock:11<br>
>>>>> ><br>
>>>>> >Program received signal SIGABRT, Aborted.<br>
>>>>> >0x000000080107626a in thr_kill () from =3D >>> /lib/libc.so.7<br>
>>>>> >(gdb) where<br>
>>>>> >#0 =3D3D3DC2=3D3D3DA00x000000080107626a in thr_kill () from =3D >>> /lib/libc.so.7<b=3D3D >>>>> r>
>>>>> >#1 =3D3D3DC2=3D3D3DA00x000000080113dac9 in abort () from =3D >>> /lib/libc.so.7<br&g=3D3D >>>>> t;
>>>>> >#2 =3D3D3DC2=3D3D3DA00x000000000071e37a in =3D >>> ThreadPThread__pthread_mutex_lock (m=3D3D >>>>> utex=3D3D3D3DE=3D3D3D
>>>>> >rror accessing memory address 0x8000ffffb508: Bad =3D >>> address.<br>>>>>> =3D20 >>>>> >) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>>>>> >#3 =3D3D3DC2=3D3D3DA00x000000000071d48d in RTOS__LockHeap () at = >=3D >>> ../src/thread/P=3D3D >>>>> THREAD/T=3D3D3D
>>>>> >hreadPThread.m3:1377<br>
>>>>> >#4 =3D3D3DC2=3D3D3DA00x0000000000706b9d in =3D >>> RTHooks__CheckLoadTracedRef (M3_Af40=3D3D >>>>> ku_ref=3D3D3D
>>>>> >=3D3D3D3DError accessing memory address 0x8000ffffb568: Bad =3D >>> address.<br&=3D3D >>>>> gt;
>>>>> >) at ../src/runtime/common/RTCollector.m3:2234<br>
>>>>> >#5 =3D3D3DC2=3D3D3DA00x000000000071d284 in =3D >>> ThreadPThread__AtForkParent () at ..=3D3D >>>>> /src/thr=3D3D3D
>>>>> >ead/PTHREAD/ThreadPThread.m3:1348<br>
>>>>> >#6 =3D3D3DC2=3D3D3DA00x0000000800df8733 in fork () from =3D >>> /lib/libthr.so.3<br&=3D3D >>>>> gt;
>>>>> >#7 =3D3D3DC2=3D3D3DA00x000000000070dd8b in RTProcess__Fork () = >at =3D >>> ../src/runtime=3D3D >>>>> /common/=3D3D3D
>>>>> >RTProcessC.c:152<br>
>>>>> >#8 =3D3D3DC2=3D3D3DA00x00000000006c52f2 in =3D >>> ProcessPosixCommon__Create_ForkExec =3D3D >>>>> (M3_Bd56=3D3D3D
>>>>> >fi_cmd=3D3D3D3DError accessing memory address 0x8000ffffb6f8: = >Bad =3D >>> address.&=3D3D >>>>> lt;br>
>>>>> >) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>>>>> >#9 =3D3D3DC2=3D3D3DA00x00000000006c6c6c in Process__Create =3D >>> (M3_Bd56fi_cmd=3D3D3D3DE=3D3D >>>>> rror acces=3D3D3D
>>>>> >sing memory address 0x8000ffffb7f8: Bad address.<br>
>>>>> >) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>>>>> >#10 0x00000000004d6826 in QMachine__FulfilExecPromise =3D >>> (M3_D6rRrg_ep=3D3D3D3=3D3D >>>>> DError=3D3D3D
>>>>> > accessing memory address 0x8000ffffb838: Bad =3D >>> address.<br>
>>>>> >) at ../src/QMachine.m3:1666<br>
>>>>> >#11 0x00000000004d6220 in QMachine__ExecCommand =3D >>> (M3_An02H2_t=3D3D3D3DError =3D3D >>>>> access=3D3D3D
>>>>> >ing memory address 0x8000ffffb9f8: Bad address.<br>
>>>>> >) at ../src/QMachine.m3:1605<br>
>>>>> >#12 0x00000000004d537e in QMachine__DoTryExec =3D >>> (M3_An02H2_t=3D3D3D3DError ac=3D3D >>>>> cessin=3D3D3D
>>>>> >g memory address 0x8000ffffbee8: Bad address.<br>
>>>>> >) at ../src/QMachine.m3:1476<br>
>>>>> ><br>
>>>>> >What am I doing wrong here?<br>
>>>>> ><br>
>>>>> >The error doesn&#39;t look unreasonable! = >=3D3D3DC2=3D3D3DA0Looking =3D >>> more clo=3D3D >>>>> sely at the =3D3D3D
>>>>> >code:<br>
>>>>> ><br>
>>>>> >First, AtForkPrepare has been called:<br>
>>>>> ><br>
>>>>> >PROCEDURE AtForkPrepare() =3D3D3D3D<br>
>>>>> >=3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D = >GetActivation();<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act: =3D= > >>> Activation;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 BEGIN<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(slotsMu, = >=3D >>> ThisLine());<br><=3D3D >>>>> br> >>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(perfMu, = >=3D >>> ThisLine());<br>>>>> r> >>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(initMu, = >=3D >>> ThisLine()); (* InitMute=3D3D >>>>> x =3D3D3D3D&gt; Re=3D3D3D
>>>>> >gisterFinalCleanup =3D3D3D3D&gt; LockHeap *)<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(heapMu, = >=3D >>> ThisLine());<br>>>>> r> >>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(activeMu, =3D >>> ThisLine()); (* LockHe=3D3D >>>>> ap =3D3D3D3D&gt; S=3D3D3D
>>>>> >uspendOthers =3D3D3D3D&gt; activeMu *)<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk activations and = >lock all =3D >>> threads.<br&g=3D3D >>>>> t;
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* NOTE: = >We have =3D >>> initMu, activeMu, so sl=3D3D >>>>> ots won&#39;t ch=3D3D3D
>>>>> >ange, conditions and<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* = >mutexes =3D >>> won&#39;t be initialized =3D3D >>>>> on-demand.<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0*)<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D = >me;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D >>> PThreadLockMutex(act.mutex, ThisLine()=3D3D >>>>> );<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act = >:=3D3D3D3D =3D >>> act.next;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >me;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 END AtForkPrepare;<br>
>>>>> ><br>
>>>>> >a postcondition of this routine is that heapMu is =3D >>> locked.<br>
>>>>> ><br>
>>>>> >now we get into AtForkParent:<br>
>>>>> ><br>
>>>>> >PROCEDURE AtForkParent() =3D3D3D3D<br>
>>>>> >=3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D = >GetActivation();<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act: =3D= > >>> Activation;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 cond: = >=3D >>> Condition;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 BEGIN<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk activations and = >unlock all =3D >>> threads, condi=3D3D >>>>> tions. *)<br=3D3D3D
>>>>> >>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D = >me;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 cond = >:=3D3D3D3D =3D >>> slots[act.slot].join;<b=3D3D >>>>> r>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 IF = >cond # NIL THEN =3D >>> PThreadUnlockMutex(=3D3D >>>>> cond.mutex, This=3D3D3D
>>>>> >Line()) END;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D >>> PThreadUnlockMutex(act.mutex, ThisLine=3D3D >>>>> ());<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act = >:=3D3D3D3D =3D >>> act.next;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >me;<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(activeMu, =3D >>> ThisLine());<br&g=3D3D >>>>> t;
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(heapMu, =3D >>> ThisLine());<br>=3D3D >>>>>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(initMu, =3D >>> ThisLine());<br>=3D3D >>>>>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(perfMu, =3D >>> ThisLine());<br>=3D3D >>>>>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(slotsMu, =3D >>> ThisLine());<br>=3D3D >>>>> ;
>>>>> >=3D3D3DC2=3D3D3DA0 END AtForkParent;<br>
>>>>> ><br>
>>>>> >We can see by inspecting the code that a necessary precondition = >=3D >>> for<=3D3D >>>>> br>
>>>>> >this routine is that heapMu is locked! =3D3D3DC2=3D3D3DA0(Since = >=3D >>> it&#39;s go=3D3D >>>>> ing to unloc=3D3D3D
>>>>> >k it,<br>
>>>>> >it had BETTER be locked on entry.)<br>
>>>>> ><br>
>>>>> >But the cond :=3D3D3D3D ... causes a =3D >>> RTHooks.CheckLoadTracedRef<br>>>>> r> >>>>> ><br>
>>>>> >which causes an RTOS.LockHeap<br>
>>>>> ><br>
>>>>> >the code of which we just saw:<br>
>>>>> ><br>
>>>>> >PROCEDURE LockHeap () =3D3D3D3D<br>
>>>>> >=3D3D3DC2=3D3D3DA0 VAR self :=3D3D3D3D = >pthread_self();<br>
>>>>> >=3D3D3DC2=3D3D3DA0 BEGIN<br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 WITH r =3D3D3D3D =3D >>> pthread_mutex_lock(heapMu,ThisLine()=3D3D >>>>> ) DO &lt;*ASSE=3D3D3D
>>>>> >RT r=3D3D3D3D0*&gt; END;<br>
>>>>> >...<br>
>>>>> ><br>
>>>>> >we try to lock heapMu. =3D3D3DC2=3D3D3DA0kaboom! = >=3D3D3DC2=3D3D3DA0No =3D >>> surprise there, r=3D3D >>>>> eally?<br>
>>>>> ><br>
>>>>> >Am I going about this totally the wrong way? = >=3D3D3DC2=3D3D3DA0Other =3D >>> people are=3D3D >>>>> running=3D3D3D
>>>>> > Modula-3<br>
>>>>> >with pthreads, right? =3D3D3DC2=3D3D3DA0Right?? = >=3D3D3DC2=3D3D3DA0Somewhere=3D >>> out there i=3D3D >>>>> n m3devel-la=3D3D3D
>>>>> >nd?<br>
>>>>> ><span><font =3D >>> color=3D3D3D3D"#888888"><br>
>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0Mika<br>
>>>>> ><br>
>>>>> =3D >>> = >></font></span></blockquote></div><br><= >=3D >>> ;=3D3D >>>>> /div></div>
>>>>> >
>>>>> >--001a11c2ced4471a2e050079db82--
>>>>>

>>>>>

>>>>> =3D20 >>>>> --089e01183a1813188705007c3498-- From hosking at cs.purdue.edu Wed Aug 13 19:49:31 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Wed, 13 Aug 2014 13:49:31 -0400 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: <20140813170459.436121A2097@async.async.caltech.edu> References: <20140813021401.238B31A2094@async.async.caltech.edu> <20140813045415.C13921A2094@async.async.caltech.edu> <20140813063041.286EA1A2094@async.async.caltech.edu> <97266593-618F-458D-A975-FE01D9BF19F9@cs.purdue.edu> <20140813163735.8D0701A2097@async.async.caltech.edu> <7A6EF7C5-9B0F-4FC5-BCB1-C7A0E36BB2D6@cs.purdue.edu> <20140813170459.436121A2097@async.async.caltech.edu> Message-ID: On Aug 13, 2014, at 1:04 PM, mika at async.caltech.edu wrote: > Sure, I understand. Just wasn't aware of it yesterday! > > But I think there are two problems here: fork and FreeBSD. > > The problems on AMD64_FREEBSD look like something different .. > there is custom FreeBSD code that is invoked and seems to screw things > up. The attached example doesn't use fork at all. I?ll take a look at the attached FREEBSD example shortly. > On the other hand, question about fork: what is the precise problem > with fork? My understanding was that it was an issue with held mutexes > on fork. But what if you don't hold any mutexes on fork? The problem is holding pthread mutexes in other threads at fork. If you don?t hold any then all is good. But, other threads may be in the middle of things, holding a mutex, when another thread executes fork. The idea is to prepare for the fork by acquiring all relevant mutexes before forking and releasing them after. The question is how to enumerate the mutexes to be acquired/released. We can enumerate the threads, so if every thread guards all other acquisitions of *other* mutexes by locking itself first, then the prepare to fork code can simply lock all the *threads* before forking and know that no other thread can possibly hold any other mutexes. The difficulty lies in the fact that the current implementation has threads lock both themselves and other mutexes, so you can end up with deadlock. [We used to have a thin veneer for Modula-3 MUTEX over pthread mutex, but then there was no way to know what mutexes were held. I stepped back from that, much as I did way back for Modula-3 condition variables to be able to handle alerting, to be able to enumerate the pthread mutexes (as above).] One approach I am considering is having threads mark themselves as inCritical while they hold any pthread mutexes, and then use thread suspension to bring them all to a safe point before forking (this is similar to GC with respect to allocation ? see RTAllocator.m3). > Related question: how many times does fork appear in the cm3 tree? I > only ever use Process.Create ... can one build a custom solution for that > one routine, maybe with a forker thread somehow? Or do others use more > general forking patterns? Yes, it?s the standard way to create processes on POSIX. A forker thread does not help, because you still need to worry about the other threads. Anyway, I hope to have something soon... > > Mika > > Tony Hosking writes: >> >> On Aug 13, 2014, at 12:37 PM, mika at async.caltech.edu wrote: >> >>> 1.262 >>> =20 >>> Short summary: 1.262 seems to work fine on AMD64_LINUX except for the >>> fork issue (a bummer because my parallelization of the backends of cm3 >>> uses fork a lot...and it does speed up the compiler significantly if >>> you have fast disks and lots of cores) It does the attached on = >> AMD64_FREEBSD. >> >> Yes, that was the state of things. Subsequent revs were to address fork = >> issues. >> >>> =20 >>> I see the intent of what you were doing in later version/s, but it was >>> a bit rough, I think... I think the three issues I reported (1. = >> locking >>> heapMu from AtFork; 2. the try-only-once bug in LockHeap itself; 3. = >> not >>> passing the lock to release from Wait) are all more or less real. >> >> Working on these right now. Sorry for hacked versions =97 no time right = >> now to do real testing before push. >> Getting closer now I think. >> >>> =20 >>> Mika >>> =20 >>> Tony Hosking writes: >>>> Which revision of ThreadPThread.m3 is this output from? >>>> =20 >>>> On Aug 13, 2014, at 2:30 AM, mika at async.caltech.edu wrote: >>>> =20 >>>>> =3D20 >>>>> OK... deleted all the derived directories and rebuilt. Result on =3D >>>> FreeBSD is similar (or identical, hard to tell): >>>>> =3D20 >>>>> I get a partial deadlock: >>>>> =3D20 >>>>> PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU =3D >>>> COMMAND >>>>> 48760 root 98 0 87836K 29104K CPU1 1 12:32 83.89% =3D >>>> threadtest{threadtest} >>>>> 48760 root 94 0 87836K 29104K CPU3 3 11:02 74.66% =3D >>>> threadtest{threadtest} >>>>> 48760 root 94 0 87836K 29104K CPU0 0 11:03 71.97% =3D >>>> threadtest{threadtest} >>>>> 48760 root 32 0 87836K 29104K umtxn 2 0:01 0.00% =3D >>>> threadtest{threadtest} >>>>> 48760 root 20 0 87836K 29104K umtxn 2 0:01 0.00% =3D >>>> threadtest{threadtest} >>>>> 48760 root 35 0 87836K 29104K uwait 2 0:01 0.00% =3D >>>> threadtest{threadtest} >>>>> 48760 root 27 0 87836K 29104K uwait 0 0:01 0.00% =3D >>>> threadtest{threadtest} >>>>> 48760 root 27 0 87836K 29104K umtxn 3 0:01 0.00% =3D >>>> threadtest{threadtest} >>>>> 48760 root 27 0 87836K 29104K umtxn 2 0:01 0.00% =3D >>>> threadtest{threadtest} >>>>> 48760 root 20 0 87836K 29104K umtxn 0 0:00 0.00% =3D >>>> threadtest{threadtest} >>>>> 48759 root 20 0 30276K 11064K wait 0 0:00 0.00% gdb >>>>> =3D20 >>>>> one of the dead threads is the main thread, so now output. But = >> three >>>>> threads are still alive, interestingly enough. >>>>> =3D20 >>>>> Looks like the same issue as before: >>>>> =3D20 >>>>> Thread 5 (Thread 801807400 (LWP 100751/threadtest)): >>>>> #0 0x0000000800ae089c in __error () from /lib/libthr.so.3 >>>>> #1 0x0000000800ad6261 in pthread_suspend_np () from = >> /lib/libthr.so.3 >>>>> #2 0x00000000004511bc in ThreadPThread__SuspendThread (mt=3D3DError = >> =3D >>>> accessing memory address 0x8000ff5faa28: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>>> #3 0x000000000044ed8e in ThreadPThread__StopThread =3D >>>> (M3_DMxDjQ_act=3D3DError accessing memory address 0x8000ff5faa48: Bad = >> =3D >>>> address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>>> #4 0x000000000044ef31 in ThreadPThread__StopWorld () at =3D >>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>>> #5 0x000000000044e44e in RTThread__SuspendOthers () at =3D >>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>>> #6 0x0000000000436386 in RTCollector__CollectSomeInStateZero () at = >> =3D >>>> ../src/runtime/common/RTCollector.m3:749 >>>>> #7 0x0000000000436331 in RTCollector__CollectSome () at =3D >>>> ../src/runtime/common/RTCollector.m3:723 >>>>> #8 0x0000000000435ff9 in RTHeapRep__CollectEnough () at =3D >>>> ../src/runtime/common/RTCollector.m3:657 >>>>> #9 0x0000000000433233 in RTAllocator__AllocTraced =3D >>>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address = >> 0x8000ff5fac88: Bad =3D >>>> address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>>> #10 0x0000000000432b55 in RTAllocator__GetOpenArray =3D >>>> (M3_Eic7CK_def=3D3DError accessing memory address 0x8000ff5fad48: Bad = >> =3D >>>> address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>> #11 0x0000000000431e8f in RTHooks__AllocateOpenArray =3D >>>> (M3_AJWxb1_defn=3D3DError accessing memory address 0x8000ff5fada8: = >> Bad =3D >>>> address. >>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>> #12 0x00000000004052ea in Main__AApply (M3_AP7a1g_cl=3D3DError = >> accessing =3D >>>> memory address 0x8000ff5fade8: Bad address. >>>>> ) at ../src/Main.m3:283 >>>>> #13 0x000000000044d243 in ThreadPThread__RunThread = >> (M3_DMxDjQ_me=3D3DError=3D >>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>> #14 0x000000000044cf00 in ThreadPThread__ThreadBase =3D >>>> (M3_AJWxb1_param=3D3DError accessing memory address 0x8000ff5faf68: = >> Bad =3D >>>> address. >>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>> #15 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>>> #16 0x0000000000000000 in ?? () >>>>> =3D20 >>>>> Interestingly the same test seems to work on AMD64_LINUX. That is >>>>> promising, at least. But of course, software testing never reveals = >> =3D >>>> the >>>>> absence of bugs. >>>>> =3D20 >>>>> Mika >>>>> =3D20 >>>>> Peter McKinna writes: >>>>>> --089e01183a1813188705007c3498 >>>>>> Content-Type: text/plain; charset=3D3DUTF-8 >>>>>> =3D20 >>>>>> Oh, one other thing that seemed to help me in testing this stuff =3D >>>> especially >>>>>> things to do with m3core and libm3 which seem to get out of whack >>>>>> sometimes, is to totally remove the target directory of m3core then = >> =3D >>>> cm3; >>>>>> cm3 -ship Same with libm3. I'm not sure that clean actually removes = >> =3D >>>> the >>>>>> targets and I think there are leftover files that stuff things up =3D= >> >>>> since I >>>>>> would get segv in FileRd for no obvious reason. >>>>>> =3D20 >>>>>> Peter >>>>>> =3D20 >>>>>> =3D20 >>>>>> =3D20 >>>>>> On Wed, Aug 13, 2014 at 3:33 PM, Peter McKinna =3D >>>> >>>>>> wrote: >>>>>> =3D20 >>>>>>> That is weird. The thread tester works fine with the old version = >> of >>>>>>> ThreadPThread.m3 on linux amd_64 except if you have the fork test = >> in =3D >>>> the >>>>>>> mix of tests you see the pthread_mutex_destroy every now and = >> again, =3D >>>> the >>>>>>> fork bug in fact. >>>>>>> I was testing the pthread changes Tony has made over the past few = >> =3D >>>> days >>>>>>> using the thread tester program until I stupidly rebuilt the =3D >>>> compiler and >>>>>>> was getting all sorts of hangs as it dragged in the new version of >>>>>>> pthreads. So I rebuilt everything from a backup to get back where = >> I =3D >>>> was >>>>>>> with a decent compiler, then reintroduced the latest changes to >>>>>>> ThreadPThread.m3, which yesterday was just hanging in sigsuspend = >> but =3D >>>> today >>>>>>> is giving me an assert failure at line 1387 in UnlockHeap. So its = >> a =3D >>>> bit >>>>>>> unstable to say the least. Maybe there is something else wrong = >> with =3D >>>> freebsd. >>>>>>> =3D20 >>>>>>> Peter >>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> On Wed, Aug 13, 2014 at 2:54 PM, wrote: >>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not =3D >>>> getting >>>>>>>> things to work and now I'm really baffled because I think I =3D >>>> understand >>>>>>>> this code! >>>>>>>> =3D20 >>>>>>>> What I did was I threw away all my changes and reverted =3D >>>> ThreadPThread.m3 >>>>>>>> to 1.262 as you suggested. >>>>>>>> =3D20 >>>>>>>> Rebuilt the compiler with upgrade.sh >>>>>>>> =3D20 >>>>>>>> Then rebuilt the compiler again with itself. >>>>>>>> =3D20 >>>>>>>> Then I realcleaned the world and buildshipped it. (I was afraid >>>>>>>> that parseparams, also imported by the thread tester, would = >> pollute >>>>>>>> it somehow.) >>>>>>>> =3D20 >>>>>>>> When I look at the code in 1.262 it looks quite straightforward. = >> =3D >>>> heapMu >>>>>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. >>>>>>>> Condition >>>>>>>> variables are mutexes too, but that's no big deal. >>>>>>>> =3D20 >>>>>>>> So, rebuild thread tester, run it: >>>>>>>> =3D20 >>>>>>>> new source -> compiling Main.m3 >>>>>>>> -> linking threadtest >>>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # >>>>>>>> AMD64_FREEBSD/threadtest >>>>>>>> Writing file...done >>>>>>>> Creating read threads...done >>>>>>>> Creating fork threads...done >>>>>>>> Creating alloc threads...done >>>>>>>> Creating lock threads...done >>>>>>>> running...printing oldest/median age/newest >>>>>>>> . >>>>>>>> =3D20 >>>>>>>> *** >>>>>>>> *** runtime error: >>>>>>>> *** Segmentation violation - possible attempt to dereference >>>>>>>> NIL.........laziest thread is 1407901189/1407901189/9 (tests: = >> read >>>>>>>> 1407901189/1407901189/1407901189 fork =3D >>>> 1407901189/1407901189/1407901189 >>>>>>>> alloc 9/9/9 lock 1407901189/1407901189/9) >>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> ^C >>>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # = >> gdb =3D >>>> !$ >>>>>>>> gdb AMD64_FREEBSD/threadtest >>>>>>>> GNU gdb 6.1.1 [FreeBSD] >>>>>>>> Copyright 2004 Free Software Foundation, Inc. >>>>>>>> GDB is free software, covered by the GNU General Public License, = >> =3D >>>> and you >>>>>>>> are >>>>>>>> welcome to change it and/or distribute copies of it under certain >>>>>>>> conditions. >>>>>>>> Type "show copying" to see the conditions. >>>>>>>> There is absolutely no warranty for GDB. Type "show warranty" = >> for >>>>>>>> details. >>>>>>>> This GDB was configured as "amd64-marcel-freebsd"... >>>>>>>> (gdb) run >>>>>>>> Starting program: >>>>>>>> =3D >>>> = >> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/th= >> =3D >>>> readtest >>>>>>>> [New LWP 100121] >>>>>>>> Writing file...done >>>>>>>> Creating read threads...done >>>>>>>> Creating fork threads...done >>>>>>>> Creating alloc threads...done >>>>>>>> Creating lock threads...done >>>>>>>> running...printing oldest/median age/newest >>>>>>>> .[New Thread 801807000 (LWP 100343/threadtest)] >>>>>>>> [New Thread 801807c00 (LWP 100667/threadtest)] >>>>>>>> [New Thread 801808800 (LWP 100816/threadtest)] >>>>>>>> [New Thread 801807400 (LWP 100349/threadtest)] >>>>>>>> [New Thread 801808400 (LWP 100815/threadtest)] >>>>>>>> [New Thread 801807800 (LWP 100352/threadtest)] >>>>>>>> [New Thread 801808c00 (LWP 100817/threadtest)] >>>>>>>> [New Thread 801809000 (LWP 100818/threadtest)] >>>>>>>> [New Thread 801809800 (LWP 100820/threadtest)] >>>>>>>> [New Thread 801808000 (LWP 100678/threadtest)] >>>>>>>> [New Thread 801806400 (LWP 100121/threadtest)] >>>>>>>> [New Thread 801806800 (LWP 100341/threadtest)] >>>>>>>> [New Thread 801806c00 (LWP 100342/threadtest)] >>>>>>>> .ERROR: pthread_mutex_lock:11 >>>>>>>> =3D20 >>>>>>>> Program received signal SIGABRT, Aborted. >>>>>>>> [Switching to Thread 801809800 (LWP 100820/threadtest)] >>>>>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>>>> (gdb) where >>>>>>>> #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>>>> #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 >>>>>>>> #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3DError >>>>>>>> accessing memory address 0x8000fe5f2d98: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 >>>>>>>> #3 0x000000000044b370 in ThreadPThread__LockMutex =3D >>>> (M3_AYIbX3_m=3D3DError >>>>>>>> accessing memory address 0x8000fe5f2dc8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>>>> #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3D3DError =3D >>>> accessing >>>>>>>> memory address 0x8000fe5f2df8: Bad address. >>>>>>>> ) at ../src/Main.m3:319 >>>>>>>> #5 0x000000000044d243 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3DError >>>>>>>> accessing memory address 0x8000fe5f2eb8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>> #6 0x000000000044cf00 in ThreadPThread__ThreadBase >>>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >> 0x8000fe5f2f68: =3D >>>> Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>> #7 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>>>>>> #8 0x0000000000000000 in ?? () >>>>>>>> (gdb) set lang c >>>>>>>> (gdb) thread apply all bt >>>>>>>> ... not that interesting ... >>>>>>>> =3D20 >>>>>>>> Segfault is segfault---error 11 is EDEADLK (locking against =3D >>>> myself?) >>>>>>>> =3D20 >>>>>>>> ????? the code is very straightforward, as I said. >>>>>>>> =3D20 >>>>>>>> I thought people had the thread tester working with pthreads? =3D >>>> Which set >>>>>>>> of files, then? Anyone on FreeBSD/amd64? >>>>>>>> =3D20 >>>>>>>> Could it be an issue with "volatile"? Not even sure where to = >> look. >>>>>>>> =3D20 >>>>>>>> The code calling the lock is just this: >>>>>>>> =3D20 >>>>>>>> PROCEDURE GetChar (rd: T): CHAR >>>>>>>> RAISES {EndOfFile, Failure, Alerted} =3D3D >>>>>>>> BEGIN >>>>>>>> LOCK rd DO >>>>>>>> RETURN FastGetChar(rd); >>>>>>>> END >>>>>>>> END GetChar; >>>>>>>> =3D20 >>>>>>>> No mysteries there... >>>>>>>> =3D20 >>>>>>>> Ah is this the fork bug? Looks like the Init routine is called = >> on =3D >>>> a >>>>>>>> lot of NIL mutexes around the fork. But the subprocesses aren't = >> =3D >>>> meant >>>>>>>> to accesses the mutexes... humm >>>>>>>> =3D20 >>>>>>>> Hmm, and it's not entirely a fork issue. Even with "threadtest =3D= >> >>>> -tests >>>>>>>> STD,-fork,-forktoomuch" it misbehaves. Hangs.... >>>>>>>> =3D20 >>>>>>>> Looks like a deadlock this time. >>>>>>>> =3D20 >>>>>>>> Some stacks... >>>>>>>> =3D20 >>>>>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): >>>>>>>> #0 0x00000000004b4e2b in __vdso_gettimeofday () >>>>>>>> #1 0x00000000004ab8d2 in gettimeofday () >>>>>>>> #2 0x0000000000452e4b in TimePosix__Now () at >>>>>>>> ../src/time/POSIX/TimePosixC.c:50 >>>>>>>> #3 0x0000000000452d72 in Time__Now () at >>>>>>>> ../src/time/POSIX/TimePosix.m3:14 >>>>>>>> #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3D3DError =3D >>>> accessing >>>>>>>> memory address 0x8000fedf6df8: Bad address. >>>>>>>> ) at ../src/Main.m3:327 >>>>>>>> #5 0x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3DError >>>>>>>> accessing memory address 0x8000fedf6eb8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>> #6 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >> 0x8000fedf6f68: =3D >>>> Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>> #7 0x000000000047c7d4 in thread_start () >>>>>>>> #8 0x0000000000000000 in ?? () >>>>>>>> =3D20 >>>>>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): >>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3DError >>>>>>>> accessing memory address 0x8000feff7d98: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>>> #4 0x00000000004480c0 in ThreadPThread__LockMutex =3D >>>> (M3_AYIbX3_m=3D3DError >>>>>>>> accessing memory address 0x8000feff7dc8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>>>> #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3D3DError =3D >>>> accessing >>>>>>>> memory address 0x8000feff7df8: Bad address. >>>>>>>> ) at ../src/Main.m3:319 >>>>>>>> #6 0x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3DError >>>>>>>> accessing memory address 0x8000feff7eb8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>> #7 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >> 0x8000feff7f68: =3D >>>> Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>> #8 0x000000000047c7d4 in thread_start () >>>>>>>> #9 0x0000000000000000 in ?? () >>>>>>>> =3D20 >>>>>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): >>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>> #1 0x0000000000475759 in suspend_common () >>>>>>>> #2 0x00000000004755c1 in pthread_suspend_np () >>>>>>>> #3 0x000000000044df0c in ThreadPThread__SuspendThread = >> (mt=3D3DError >>>>>>>> accessing memory address 0x8000ffbfd6f8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>>>>>> #4 0x000000000044bade in ThreadPThread__StopThread =3D >>>> (M3_DMxDjQ_act=3D3DError >>>>>>>> accessing memory address 0x8000ffbfd718: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>>>>>> #5 0x000000000044bc81 in ThreadPThread__StopWorld () at >>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>>>>>> #6 0x000000000044b19e in RTThread__SuspendOthers () at >>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>>>>>> #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero () = >> at >>>>>>>> ../src/runtime/common/RTCollector.m3:749 >>>>>>>> #8 0x0000000000433081 in RTCollector__CollectSome () at >>>>>>>> ../src/runtime/common/RTCollector.m3:723 >>>>>>>> #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at >>>>>>>> ../src/runtime/common/RTCollector.m3:657 >>>>>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced >>>>>>>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address =3D >>>> 0x8000ffbfd958: Bad >>>>>>>> address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>>>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>>> (M3_Eic7CK_def=3D3DError >>>>>>>> accessing memory address 0x8000ffbfda18: Bad address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>>>> (M3_AJWxb1_defn=3D3DError accessing memory address = >> 0x8000ffbfda78: =3D >>>> Bad address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3DError =3D >>>> accessing >>>>>>>> memory address 0x8000ffbfdab8: Bad address. >>>>>>>> ) at ../src/rw/Rd.m3:159 >>>>>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar = >> (M3_EkTcCb_rd=3D3DError=3D >>>> =20 >>>>>>>> accessing memory address 0x8000ffbfdb88: Bad address. >>>>>>>> ) at ../src/rw/Rd.m3:187 >>>>>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3DError =3D >>>> accessing >>>>>>>> memory address 0x8000ffbfdbd8: Bad address. >>>>>>>> ) at ../src/rw/Rd.m3:176 >>>>>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3DError =3D >>>> accessing >>>>>>>> memory address 0x8000ffbfdc58: Bad address. >>>>>>>> ) at ../src/Main.m3:185 >>>>>>>> =3D20 >>>>>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3DError >>>>>>>> accessing memory address 0x8000ffbfdeb8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >> 0x8000ffbfdf68: =3D >>>> Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>> #19 0x000000000047c7d4 in thread_start () >>>>>>>> #20 0x0000000000000000 in ?? () >>>>>>>> =3D20 >>>>>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): >>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3DError >>>>>>>> accessing memory address 0x8000ffffc678: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>>> #4 0x000000000044d039 in RTOS__LockHeap () at >>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>>>> ---Type to continue, or q to quit--- >>>>>>>> #5 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>>>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address =3D >>>> 0x8000ffffc6e8: Bad >>>>>>>> address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>>>> #6 0x000000000042f15b in RTAllocator__GetTracedObj =3D >>>> (M3_Eic7CK_def=3D3DError >>>>>>>> accessing memory address 0x8000ffffc7a8: Bad address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:224 >>>>>>>> #7 0x000000000042eb23 in RTHooks__AllocateTracedObj >>>>>>>> (M3_AJWxb1_defn=3D3DError accessing memory address = >> 0x8000ffffc7f8: =3D >>>> Bad address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:122 >>>>>>>> #8 0x000000000045fbe4 in TextCat__Flat (M3_Bd56fi_LText=3D3DError = >> =3D >>>> accessing >>>>>>>> memory address 0x8000ffffc858: Bad address. >>>>>>>> ) at ../src/text/TextCat.m3:562 >>>>>>>> #9 0x000000000045ed5d in TextCat__Balance =3D >>>> (M3_Bd56fi_LText=3D3D0x800c490b0, >>>>>>>> M3_BUgnwf_LInfo=3D3DError accessing memory address = >> 0x8000ffffc8f8: =3D >>>> Bad address. >>>>>>>> ) at ../src/text/TextCat.m3:488 >>>>>>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3D3DError = >> =3D >>>> accessing >>>>>>>> memory address 0x8000ffffcbb8: Bad address. >>>>>>>> ) at ../src/text/TextCat.m3:40 >>>>>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3DError = >> accessing =3D >>>> memory >>>>>>>> address 0x8000ffffcc38: Bad address. >>>>>>>> ) at ../src/Main.m3:593 >>>>>>>> #12 0x000000000043d55d in RTLinker__RunMainBody = >> (M3_DjPxE3_m=3D3DError >>>>>>>> accessing memory address 0x8000ffffcf88: Bad address. >>>>>>>> ) at ../src/runtime/common/RTLinker.m3:408 >>>>>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3D3DError= >> =3D >>>> accessing >>>>>>>> memory address 0x8000ffffd008: Bad address. >>>>>>>> ) at ../src/runtime/common/RTLinker.m3:115 >>>>>>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3D3DError = >> =3D >>>> accessing >>>>>>>> memory address 0x8000ffffd028: Bad address. >>>>>>>> ) at ../src/runtime/common/RTLinker.m3:124 >>>>>>>> #15 0x00000000004004a6 in main (argc=3D3DError accessing memory =3D= >> >>>> address >>>>>>>> 0x8000ffffd07c: Bad address. >>>>>>>> ) at _m3main.c:22 >>>>>>>> =3D20 >>>>>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): >>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>> #1 0x0000000000477e8a in check_suspend () >>>>>>>> #2 0x00000000004780a2 in sigcancel_handler () >>>>>>>> #3 >>>>>>>> #4 0x000000000047e53c in _umtx_op_err () >>>>>>>> #5 0x0000000000475f14 in __thr_umutex_lock () >>>>>>>> #6 0x0000000000479404 in mutex_lock_common () >>>>>>>> #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3DError >>>>>>>> accessing memory address 0x8000ff5fac18: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>>> #8 0x000000000044d039 in RTOS__LockHeap () at >>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>>>> #9 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>>>> (M3_Cwb5VA_dataSize=3D3DError accessing memory address =3D >>>> 0x8000ff5fac88: Bad >>>>>>>> address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>>> (M3_Eic7CK_def=3D3DError >>>>>>>> accessing memory address 0x8000ff5fad48: Bad address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>>>> (M3_AJWxb1_defn=3D3DError accessing memory address = >> 0x8000ff5fada8: =3D >>>> Bad address. >>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3DError =3D >>>> accessing >>>>>>>> memory address 0x8000ff5fade8: Bad address. >>>>>>>> ) at ../src/Main.m3:283 >>>>>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3DError >>>>>>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>> (M3_AJWxb1_param=3D3DError accessing memory address = >> 0x8000ff5faf68: =3D >>>> Bad address. >>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>> #15 0x000000000047c7d4 in thread_start () >>>>>>>> #16 0x0000000000000000 in ?? () >>>>>>>> =3D20 >>>>>>>> (others are similar) >>>>>>>> =3D20 >>>>>>>> Hmm looks like a FreeBSD issue now. It's here... >>>>>>>> =3D20 >>>>>>>> int >>>>>>>> __cdecl >>>>>>>> ThreadPThread__SuspendThread (m3_pthread_t mt) >>>>>>>> { >>>>>>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), >>>>>>>> "pthread_suspend_np"); >>>>>>>> return 1; >>>>>>>> } >>>>>>>> =3D20 >>>>>>>> Now this suspend can wait: >>>>>>>> =3D20 >>>>>>>> static int >>>>>>>> suspend_common(struct pthread *curthread, struct pthread *thread, >>>>>>>> int waitok) >>>>>>>> { >>>>>>>> uint32_t tmp; >>>>>>>> =3D20 >>>>>>>> while (thread->state !=3D3D PS_DEAD && >>>>>>>> !(thread->flags & THR_FLAGS_SUSPENDED)) { >>>>>>>> thread->flags |=3D3D THR_FLAGS_NEED_SUSPEND; >>>>>>>> /* Thread is in creation. */ >>>>>>>> if (thread->tid =3D3D=3D3D TID_TERMINATED) >>>>>>>> return (1); >>>>>>>> tmp =3D3D thread->cycle; >>>>>>>> _thr_send_sig(thread, SIGCANCEL); >>>>>>>> THR_THREAD_UNLOCK(curthread, thread); >>>>>>>> if (waitok) { >>>>>>>> _thr_umtx_wait_uint(&thread->cycle, tmp, =3D >>>> NULL, >>>>>>>> 0); <=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D=3D3D >>>>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>>>> } else { >>>>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>>>> return (0); >>>>>>>> } >>>>>>>> } >>>>>>>> =3D20 >>>>>>>> return (1); >>>>>>>> } >>>>>>>> =3D20 >>>>>>>> ... but what it can wait for I am not clear on. >>>>>>>> =3D20 >>>>>>>> Do things work better on Linux? >>>>>>>> =3D20 >>>>>>>> What is the status of the fork bug? Can it be worked around by =3D= >> >>>> only >>>>>>>> forking via Process.Create with no mutexes held (outside of all =3D= >> >>>> LOCK >>>>>>>> blocks)? >>>>>>>> =3D20 >>>>>>>> Mika >>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> =3D20 >>>>>>>> Peter McKinna writes: >>>>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>>>> Content-Type: text/plain; charset=3D3DUTF-8 >>>>>>>>> =3D20 >>>>>>>>> Mika >>>>>>>>> =3D20 >>>>>>>>> I think you need to back out Tony's changes to fix the fork bug, = >> =3D >>>> at >>>>>>>> least >>>>>>>>> for now. Need to reload from cvs version 1.262 for =3D >>>> ThreadPThread.m3 If >>>>>>>>> you're using git you're on your own. >>>>>>>>> Do a cvs log ThreadPThread.m3 for an explanation for some of the = >> =3D >>>> design >>>>>>>>> principles. >>>>>>>>> Also if you use gdb then you need to set lanc c before = >> backtraces =3D >>>> so at >>>>>>>>> least you can see address names and values even if they are =3D >>>> contorted you >>>>>>>>> can extract the M3 name in the parm lists. Also in gdb thread =3D >>>> apply all >>>>>>>> bt >>>>>>>>> gives all thread backtraces which can be handy to see whose got = >> =3D >>>> the locks >>>>>>>>> held. >>>>>>>>> =3D20 >>>>>>>>> Regards Peter >>>>>>>>> =3D20 >>>>>>>>> =3D20 >>>>>>>>> =3D20 >>>>>>>>> On Wed, Aug 13, 2014 at 12:14 PM, = >> wrote: >>>>>>>>> =3D20 >>>>>>>>>> =3D20 >>>>>>>>>> Question... is there something odd about my pthreads? Are =3D >>>> pthreads >>>>>>>>>> normally reentrant? I didn't think so. >>>>>>>>>> =3D20 >>>>>>>>>> My compiler is much happier with the following changes I = >> already >>>>>>>> outlined: >>>>>>>>>> =3D20 >>>>>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >> =3D >>>> going >>>>>>>> from >>>>>>>>>> XWait with self.mutex locked to m.release(). >>>>>>>>>> =3D20 >>>>>>>>>> 2. the change to LockHeap I described in previous email >>>>>>>>>> =3D20 >>>>>>>>>> But now... >>>>>>>>>> =3D20 >>>>>>>>>> (gdb) cont >>>>>>>>>> Continuing. >>>>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>>>> =3D20 >>>>>>>>>> Program received signal SIGABRT, Aborted. >>>>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>>>> (gdb) where >>>>>>>>>> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>>>> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >>>>>>>>>> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock >>>>>>>> (mutex=3D3DError >>>>>>>>>> accessing memory address 0x8000ffffb508: Bad address. >>>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >>>>>>>>>> #3 0x000000000071d48d in RTOS__LockHeap () at >>>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >>>>>>>>>> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>>>>>> (M3_Af40ku_ref=3D3DError >>>>>>>>>> accessing memory address 0x8000ffffb568: Bad address. >>>>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234 >>>>>>>>>> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >>>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >>>>>>>>>> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >>>>>>>>>> #7 0x000000000070dd8b in RTProcess__Fork () at >>>>>>>>>> ../src/runtime/common/RTProcessC.c:152 >>>>>>>>>> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>>>>>>>>> (M3_Bd56fi_cmd=3D3DError accessing memory address = >> 0x8000ffffb6f8: =3D >>>> Bad >>>>>>>> address. >>>>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >>>>>>>>>> #9 0x00000000006c6c6c in Process__Create = >> (M3_Bd56fi_cmd=3D3DError >>>>>>>> accessing >>>>>>>>>> memory address 0x8000ffffb7f8: Bad address. >>>>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21 >>>>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>>>> (M3_D6rRrg_ep=3D3DError >>>>>>>>>> accessing memory address 0x8000ffffb838: Bad address. >>>>>>>>>> ) at ../src/QMachine.m3:1666 >>>>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand =3D >>>> (M3_An02H2_t=3D3DError >>>>>>>>>> accessing memory address 0x8000ffffb9f8: Bad address. >>>>>>>>>> ) at ../src/QMachine.m3:1605 >>>>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec = >> (M3_An02H2_t=3D3DError >>>>>>>> accessing >>>>>>>>>> memory address 0x8000ffffbee8: Bad address. >>>>>>>>>> ) at ../src/QMachine.m3:1476 >>>>>>>>>> =3D20 >>>>>>>>>> What am I doing wrong here? >>>>>>>>>> =3D20 >>>>>>>>>> The error doesn't look unreasonable! Looking more closely at = >> the =3D >>>> code: >>>>>>>>>> =3D20 >>>>>>>>>> First, AtForkPrepare has been called: >>>>>>>>>> =3D20 >>>>>>>>>> PROCEDURE AtForkPrepare() =3D3D >>>>>>>>>> VAR me :=3D3D GetActivation(); >>>>>>>>>> act: Activation; >>>>>>>>>> BEGIN >>>>>>>>>> PThreadLockMutex(slotsMu, ThisLine()); >>>>>>>>>> PThreadLockMutex(perfMu, ThisLine()); >>>>>>>>>> PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D3D> >>>>>>>>>> RegisterFinalCleanup =3D3D> LockHeap *) >>>>>>>>>> PThreadLockMutex(heapMu, ThisLine()); >>>>>>>>>> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap =3D3D> >>>>>>>> SuspendOthers >>>>>>>>>> =3D3D> activeMu *) >>>>>>>>>> (* Walk activations and lock all threads. >>>>>>>>>> * NOTE: We have initMu, activeMu, so slots won't change, >>>>>>>> conditions >>>>>>>>>> and >>>>>>>>>> * mutexes won't be initialized on-demand. >>>>>>>>>> *) >>>>>>>>>> act :=3D3D me; >>>>>>>>>> REPEAT >>>>>>>>>> PThreadLockMutex(act.mutex, ThisLine()); >>>>>>>>>> act :=3D3D act.next; >>>>>>>>>> UNTIL act =3D3D me; >>>>>>>>>> END AtForkPrepare; >>>>>>>>>> =3D20 >>>>>>>>>> a postcondition of this routine is that heapMu is locked. >>>>>>>>>> =3D20 >>>>>>>>>> now we get into AtForkParent: >>>>>>>>>> =3D20 >>>>>>>>>> PROCEDURE AtForkParent() =3D3D >>>>>>>>>> VAR me :=3D3D GetActivation(); >>>>>>>>>> act: Activation; >>>>>>>>>> cond: Condition; >>>>>>>>>> BEGIN >>>>>>>>>> (* Walk activations and unlock all threads, conditions. *) >>>>>>>>>> act :=3D3D me; >>>>>>>>>> REPEAT >>>>>>>>>> cond :=3D3D slots[act.slot].join; >>>>>>>>>> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, =3D >>>> ThisLine()) >>>>>>>> END; >>>>>>>>>> PThreadUnlockMutex(act.mutex, ThisLine()); >>>>>>>>>> act :=3D3D act.next; >>>>>>>>>> UNTIL act =3D3D me; >>>>>>>>>> PThreadUnlockMutex(activeMu, ThisLine()); >>>>>>>>>> PThreadUnlockMutex(heapMu, ThisLine()); >>>>>>>>>> PThreadUnlockMutex(initMu, ThisLine()); >>>>>>>>>> PThreadUnlockMutex(perfMu, ThisLine()); >>>>>>>>>> PThreadUnlockMutex(slotsMu, ThisLine()); >>>>>>>>>> END AtForkParent; >>>>>>>>>> =3D20 >>>>>>>>>> We can see by inspecting the code that a necessary precondition = >> =3D >>>> for >>>>>>>>>> this routine is that heapMu is locked! (Since it's going to =3D >>>> unlock it, >>>>>>>>>> it had BETTER be locked on entry.) >>>>>>>>>> =3D20 >>>>>>>>>> But the cond :=3D3D ... causes a RTHooks.CheckLoadTracedRef >>>>>>>>>> =3D20 >>>>>>>>>> which causes an RTOS.LockHeap >>>>>>>>>> =3D20 >>>>>>>>>> the code of which we just saw: >>>>>>>>>> =3D20 >>>>>>>>>> PROCEDURE LockHeap () =3D3D >>>>>>>>>> VAR self :=3D3D pthread_self(); >>>>>>>>>> BEGIN >>>>>>>>>> WITH r =3D3D pthread_mutex_lock(heapMu,ThisLine()) DO = >> <*ASSERT =3D >>>> r=3D3D0*> >>>>>>>> END; >>>>>>>>>> ... >>>>>>>>>> =3D20 >>>>>>>>>> we try to lock heapMu. kaboom! No surprise there, really? >>>>>>>>>> =3D20 >>>>>>>>>> Am I going about this totally the wrong way? Other people are = >> =3D >>>> running >>>>>>>>>> Modula-3 >>>>>>>>>> with pthreads, right? Right?? Somewhere out there in =3D >>>> m3devel-land? >>>>>>>>>> =3D20 >>>>>>>>>> Mika >>>>>>>>>> =3D20 >>>>>>>>>> =3D20 >>>>>>>>> =3D20 >>>>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>>>> Content-Type: text/html; charset=3D3DUTF-8 >>>>>>>>> Content-Transfer-Encoding: quoted-printable >>>>>>>>> =3D20 >>>>>>>>>
Mika

=3D3DC2=3D3DA0 I = >> think you =3D >>>> need to back >>>>>>>> ou=3D3D >>>>>>>>> t Tony's changes to fix the fork bug, at least for now. Need = >> =3D >>>> to >>>>>>>> reload =3D3D >>>>>>>>> from cvs version 1.262 for ThreadPThread.m3 If you're using = >> =3D >>>> git >>>>>>>> you'=3D3D >>>>>>>>> ;re on your own.
>>>>>>>>> =3D20 >>>>>>>>>
=3D3DC2=3D3DA0 Do a cvs log ThreadPThread.m3 for an = >> explanation =3D >>>> for some of >>>>>>>> th=3D3D >>>>>>>>> e design principles.=3D3DC2=3D3DA0
=3D3DC2=3D3DA0 Also = >> if you =3D >>>> use gdb then you >>>>>>>> ne=3D3D >>>>>>>>> ed to set lanc c before backtraces so at least you can see = >> address =3D >>>> names >>>>>>>> an=3D3D >>>>>>>>> d values even if they are contorted you can extract the M3 name = >> in =3D >>>> the >>>>>>>> parm=3D3D >>>>>>>>> lists. Also in gdb thread apply all bt gives all thread = >> backtraces >>>>>>>> which c=3D3D >>>>>>>>> an be handy to see whose got the locks held.
>>>>>>>>> =3D20 >>>>>>>>>

Regards Peter

>>>>>>> class=3D3D3D"gmail_e=3D3D >>>>>>>>> xtra">

On Wed, Aug 13, = >> 2014 at =3D >>>> 12:14 >>>>>>>> PM, =3D3D >>>>>>>>> <> href=3D3D3D"mailto:mika at async.caltech.edu" >>>>>>>> target=3D3D3D"=3D3D >>>>>>>>> _blank">mika at async.caltech.edu> wrote:
>>>>>>>>> =3D20 >>>>>>>>>
>>>>>>> .8ex;border-left:1p=3D3D >>>>>>>>> x #ccc solid;padding-left:1ex">
>>>>>>>>> Question... is there something odd about my pthreads? = >> =3D3DC2=3D3DA0Are =3D >>>> pthreads >>>>>>>> no=3D3D >>>>>>>>> rmally reentrant? =3D3DC2=3D3DA0I didn't think so.
>>>>>>>>>
>>>>>>>>> My compiler is much happier with the following changes I already >>>>>>>> outlined:<=3D3D >>>>>>>>> br> >>>>>>>>>
>>>>>>>>> 1. a dirty, disgusting hack to keep from locking against myself = >> =3D >>>> going >>>>>>>> from =3D3D >>>>>>>>> XWait with self.mutex locked to m.release().
>>>>>>>>>
>>>>>>>>> 2. the change to LockHeap I described in previous email
>>>>>>>>>
>>>>>>>>> But now...
>>>>>>>>>
>>>>>>>>> (gdb) cont
>>>>>>>>> Continuing.
>>>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>>>>
>>>>>>>>> Program received signal SIGABRT, Aborted.
>>>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>>>>>> (gdb) where
>>>>>>>>> #0 =3D3DC2=3D3DA00x000000080107626a in thr_kill () from =3D >>>> /lib/libc.so.7
>>>>>>>>> #1 =3D3DC2=3D3DA00x000000080113dac9 in abort () from =3D >>>> /lib/libc.so.7
>>>>>>>>> #2 =3D3DC2=3D3DA00x000000000071e37a in =3D >>>> ThreadPThread__pthread_mutex_lock >>>>>>>> (mutex=3D3D3DE=3D3D >>>>>>>>> rror accessing memory address 0x8000ffffb508: Bad address.
>>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>>>>>> #3 =3D3DC2=3D3DA00x000000000071d48d in RTOS__LockHeap () at >>>>>>>> ../src/thread/PTHREAD/T=3D3D >>>>>>>>> hreadPThread.m3:1377
>>>>>>>>> #4 =3D3DC2=3D3DA00x0000000000706b9d in = >> RTHooks__CheckLoadTracedRef >>>>>>>> (M3_Af40ku_ref=3D3D >>>>>>>>> =3D3D3DError accessing memory address 0x8000ffffb568: Bad =3D >>>> address.
>>>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>>>>>> #5 =3D3DC2=3D3DA00x000000000071d284 in = >> ThreadPThread__AtForkParent () =3D >>>> at >>>>>>>> ../src/thr=3D3D >>>>>>>>> ead/PTHREAD/ThreadPThread.m3:1348
>>>>>>>>> #6 =3D3DC2=3D3DA00x0000000800df8733 in fork () from =3D >>>> /lib/libthr.so.3
>>>>>>>>> #7 =3D3DC2=3D3DA00x000000000070dd8b in RTProcess__Fork () at >>>>>>>> ../src/runtime/common/=3D3D >>>>>>>>> RTProcessC.c:152
>>>>>>>>> #8 =3D3DC2=3D3DA00x00000000006c52f2 in =3D >>>> ProcessPosixCommon__Create_ForkExec >>>>>>>> (M3_Bd56=3D3D >>>>>>>>> fi_cmd=3D3D3DError accessing memory address 0x8000ffffb6f8: Bad = >> =3D >>>> address.
>>>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>>>>>> #9 =3D3DC2=3D3DA00x00000000006c6c6c in Process__Create =3D >>>> (M3_Bd56fi_cmd=3D3D3DError >>>>>>>> acces=3D3D >>>>>>>>> sing memory address 0x8000ffffb7f8: Bad address.
>>>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>>>> (M3_D6rRrg_ep=3D3D3DError=3D3D >>>>>>>>> accessing memory address 0x8000ffffb838: Bad address.
>>>>>>>>> ) at ../src/QMachine.m3:1666
>>>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand =3D >>>> (M3_An02H2_t=3D3D3DError >>>>>>>> access=3D3D >>>>>>>>> ing memory address 0x8000ffffb9f8: Bad address.
>>>>>>>>> ) at ../src/QMachine.m3:1605
>>>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec = >> (M3_An02H2_t=3D3D3DError=3D >>>> =20 >>>>>>>> accessin=3D3D >>>>>>>>> g memory address 0x8000ffffbee8: Bad address.
>>>>>>>>> ) at ../src/QMachine.m3:1476
>>>>>>>>>
>>>>>>>>> What am I doing wrong here?
>>>>>>>>>
>>>>>>>>> The error doesn't look unreasonable! =3D3DC2=3D3DA0Looking = >> more =3D >>>> closely at >>>>>>>> the =3D3D >>>>>>>>> code:
>>>>>>>>>
>>>>>>>>> First, AtForkPrepare has been called:
>>>>>>>>>
>>>>>>>>> PROCEDURE AtForkPrepare() =3D3D3D
>>>>>>>>> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >> Activation;
>>>>>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(slotsMu, = >> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(perfMu, = >> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(initMu, = >> ThisLine()); (* =3D >>>> InitMutex =3D3D3D> >>>>>>>> Re=3D3D >>>>>>>>> gisterFinalCleanup =3D3D3D> LockHeap *)
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(heapMu, = >> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(activeMu, = >> ThisLine()); (* =3D >>>> LockHeap >>>>>>>> =3D3D3D> S=3D3D >>>>>>>>> uspendOthers =3D3D3D> activeMu *)
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and lock all =3D= >> >>>> threads.
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* NOTE: We have = >> initMu, activeMu, =3D >>>> so slots won't >>>>>>>> ch=3D3D >>>>>>>>> ange, conditions and
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* mutexes won't = >> be initialized =3D >>>> on-demand.
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0*)
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> PThreadLockMutex(act.mutex, =3D >>>> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >> act.next;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>>>>>> =3D3DC2=3D3DA0 END AtForkPrepare;
>>>>>>>>>
>>>>>>>>> a postcondition of this routine is that heapMu is locked.
>>>>>>>>>
>>>>>>>>> now we get into AtForkParent:
>>>>>>>>>
>>>>>>>>> PROCEDURE AtForkParent() =3D3D3D
>>>>>>>>> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >> Activation;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond: = >> Condition;
>>>>>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and unlock all = >> threads, =3D >>>> conditions. >>>>>>>> *)>>>>>>>>> =3D20 >>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond :=3D3D3D =3D >>>> slots[act.slot].join;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 IF cond # NIL THEN = >> =3D >>>> PThreadUnlockMutex(cond.mutex, >>>>>>>> This=3D3D >>>>>>>>> Line()) END;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> PThreadUnlockMutex(act.mutex, =3D >>>> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >> act.next;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(activeMu, =3D >>>> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(heapMu, = >> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(initMu, = >> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(perfMu, = >> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(slotsMu, = >> ThisLine());
>>>>>>>>> =3D3DC2=3D3DA0 END AtForkParent;
>>>>>>>>>
>>>>>>>>> We can see by inspecting the code that a necessary precondition = >> =3D >>>> for
>>>>>>>>> this routine is that heapMu is locked! =3D3DC2=3D3DA0(Since = >> it's =3D >>>> going to >>>>>>>> unloc=3D3D >>>>>>>>> k it,
>>>>>>>>> it had BETTER be locked on entry.)
>>>>>>>>>
>>>>>>>>> But the cond :=3D3D3D ... causes a = >> RTHooks.CheckLoadTracedRef
>>>>>>>>>
>>>>>>>>> which causes an RTOS.LockHeap
>>>>>>>>>
>>>>>>>>> the code of which we just saw:
>>>>>>>>>
>>>>>>>>> PROCEDURE LockHeap () =3D3D3D
>>>>>>>>> =3D3DC2=3D3DA0 VAR self :=3D3D3D pthread_self();
>>>>>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 WITH r =3D3D3D =3D >>>> pthread_mutex_lock(heapMu,ThisLine()) DO >>>>>>>> <*ASSE=3D3D >>>>>>>>> RT r=3D3D3D0*> END;
>>>>>>>>> ...
>>>>>>>>>
>>>>>>>>> we try to lock heapMu. =3D3DC2=3D3DA0kaboom! =3D3DC2=3D3DA0No = >> surprise =3D >>>> there, really?
>>>>>>>>>
>>>>>>>>> Am I going about this totally the wrong way? =3D3DC2=3D3DA0Other = >> =3D >>>> people are >>>>>>>> running=3D3D >>>>>>>>> Modula-3
>>>>>>>>> with pthreads, right? =3D3DC2=3D3DA0Right?? =3D3DC2=3D3DA0Somewher= >> e out =3D >>>> there in >>>>>>>> m3devel-la=3D3D >>>>>>>>> nd?
>>>>>>>>>
>>>>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika
>>>>>>>>>
>>>>>>>>>

>>>>>>>>> =3D20 >>>>>>>>> --001a11c2ced4471a2e050079db82-- >>>>>>>> =3D20 >>>>>>> =3D20 >>>>>>> =3D20 >>>>>> =3D20 >>>>>> --089e01183a1813188705007c3498 >>>>>> Content-Type: text/html; charset=3D3DUTF-8 >>>>>> Content-Transfer-Encoding: quoted-printable >>>>>> =3D20 >>>>>>
Oh, one other thing that seemed to help me in = >> =3D >>>> testing this=3D3D >>>>>> stuff especially things to do with m3core and libm3 which seem to = >> get =3D >>>> out =3D3D >>>>>> of whack sometimes, is to totally remove the target directory of =3D >>>> m3core the=3D3D >>>>>> n cm3; cm3 -ship Same with libm3. I'm not sure that clean =3D >>>> actually remo=3D3D >>>>>> ves the targets and I think there are leftover files that stuff =3D >>>> things up s=3D3D >>>>>> ince I would get segv in FileRd for no obvious reason.
>>>>>>
Peter

>>> class=3D3D3D"gmail_extra"><=3D3D >>>>>> br>
On Wed, Aug 13, 2014 at 3:33 = >> PM, =3D >>>> Peter Mc=3D3D >>>>>> Kinna <>>> href=3D3D3D"mailto:peter.mckinna at gmail.com" targ=3D3D >>>>>> et=3D3D3D"_blank">peter.mckinna at gmail.com> wrote:
>>>>>>
>>> .8ex;border-left:1p=3D3D >>>>>> x #ccc solid;padding-left:1ex">
That is weird. = >> The =3D >>>> thread t=3D3D >>>>>> ester works fine with the old version of ThreadPThread.m3 on linux = >> =3D >>>> amd_64 e=3D3D >>>>>> xcept if you have the fork test in the mix of tests you see the =3D >>>> pthread_mut=3D3D >>>>>> ex_destroy every now and again, the fork bug in = >> fact.=3D3DC2=3D3DA0
>>>>>> =3D20 >>>>>> I was testing the pthread changes Tony has made over the past few =3D= >> >>>> days usin=3D3D >>>>>> g the thread tester program until I stupidly rebuilt the compiler = >> and =3D >>>> was g=3D3D >>>>>> etting all sorts of hangs as it dragged in the new version of =3D >>>> pthreads. So =3D3D >>>>>> I rebuilt everything from a backup to get back where I was with a =3D= >> >>>> decent co=3D3D >>>>>> mpiler, then reintroduced the latest changes to ThreadPThread.m3, =3D= >> >>>> which yes=3D3D >>>>>> terday was just hanging in sigsuspend but today is giving me an =3D >>>> assert fail=3D3D >>>>>> ure at line 1387 in UnlockHeap. So its a bit unstable to say the =3D >>>> least. May=3D3D >>>>>> be there is something else wrong with freebsd.
>>>>>> >>>>>> =3D >>>> = >>

Peter

> >>>> clas=3D3D >>>>>> s=3D3D3D"HOEnZb">
>>> class=3D3D3D"gmail_extra">

>>>>> s=3D3D3D"gmail_quote">On Wed, Aug 13, 2014 at 2:54 PM, >>> dir=3D3D3D"ltr"><<=3D3D >>>>>> a href=3D3D3D"mailto:mika at async.caltech.edu" =3D >>>> target=3D3D3D"_blank">mika at async.calte=3D3D >>>>>> ch.edu> wrote:
>>>>>> =3D20 >>>>>>
>>> .8ex;border-left:1p=3D3D >>>>>> x #ccc solid;padding-left:1ex">
>>>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not =3D >>>> getting>>>>>> =3D20 >>>>>> things to work and now I'm really baffled because I think I =3D >>>> understand<=3D3D >>>>>> br> >>>>>> this code!
>>>>>>
>>>>>> What I did was I threw away all my changes and reverted =3D >>>> ThreadPThread.m3>>>>>> =3D20 >>>>>> to 1.262 as you suggested.
>>>>>>
>>>>>> Rebuilt the compiler with upgrade.sh
>>>>>>
>>>>>> Then rebuilt the compiler again with itself.
>>>>>>
>>>>>> Then I realcleaned the world and buildshipped it. =3D3DC2=3D3DA0(I = >> was =3D >>>> afraid
>>>>>> that parseparams, also imported by the thread tester, would =3D >>>> pollute
>>>>>> it somehow.)
>>>>>>
>>>>>> When I look at the code in 1.262 it looks quite straightforward. =3D >>>> =3D3DC2=3D3DA0heap=3D3D >>>>>> Mu
>>>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. =3D >>>> =3D3DC2=3D3DA0Cond=3D3D >>>>>> ition
>>>>>> variables are mutexes too, but that's no big deal.
>>>>>>
>>>>>> So, rebuild thread tester, run it:
>>>>>>
>>>>>> new source -> compiling Main.m3
>>>>>> =3D3DC2=3D3DA0-> linking threadtest
>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # =3D >>>> AMD64_FREEB=3D3D >>>>>> SD/threadtest
>>>>>> Writing file...done
>>>>>> Creating read threads...done
>>>>>> Creating fork threads...done
>>>>>> Creating alloc threads...done
>>>>>> Creating lock threads...done
>>>>>> running...printing oldest/median age/newest
>>>>>> .
>>>>>>
>>>>>> ***
>>>>>> *** runtime error:
>>>>>> *** =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Segmentation violation - possible = >> attempt to =3D >>>> dereference N=3D3D >>>>>> IL.........laziest thread is 1407901189/>>> href=3D3D3D"tel:1407901189%2F9" valu=3D3D >>>>>> e=3D3D3D"+14079011899" target=3D3D3D"_blank">1407901189/9 = >> (tests: =3D >>>> read 14079011=3D3D >>>>>> 89/1407901189/1407901189 fork 1407901189/1407901189/1407901189 = >> alloc =3D >>>> 9/9/9 =3D3D >>>>>> lock 1407901189/1407901189/9)
>>>>>> =3D20 >>>>>> =3D20 >>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> ^C
>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # gdb = >> =3D >>>> !$
>>>>>> gdb AMD64_FREEBSD/threadtest
>>>>>> GNU gdb 6.1.1 [FreeBSD]
>>>>>> Copyright 2004 Free Software Foundation, Inc.
>>>>>> GDB is free software, covered by the GNU General Public License, = >> and =3D >>>> you ar=3D3D >>>>>> e
>>>>>> welcome to change it and/or distribute copies of it under certain =3D= >> >>>> condition=3D3D >>>>>> s.
>>>>>> Type "show copying" to see the conditions.
>>>>>> There is absolutely no warranty for GDB. =3D3DC2=3D3DA0Type = >> "show =3D >>>> warranty&quo=3D3D >>>>>> t; for details.
>>>>>> This GDB was configured as "amd64-marcel-freebsd"...
>>>>>> (gdb) run
>>>>>> Starting program: =3D >>>> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread=3D3D >>>>>> /AMD64_FREEBSD/threadtest
>>>>>> [New LWP 100121]
>>>>>> Writing file...done
>>>>>> Creating read threads...done
>>>>>> Creating fork threads...done
>>>>>> Creating alloc threads...done
>>>>>> Creating lock threads...done
>>>>>> running...printing oldest/median age/newest
>>>>>> .[New Thread 801807000 (LWP 100343/threadtest)]
>>>>>> [New Thread 801807c00 (LWP 100667/threadtest)]
>>>>>> [New Thread 801808800 (LWP 100816/threadtest)]
>>>>>> [New Thread 801807400 (LWP 100349/threadtest)]
>>>>>> [New Thread 801808400 (LWP 100815/threadtest)]
>>>>>> [New Thread 801807800 (LWP 100352/threadtest)]
>>>>>> [New Thread 801808c00 (LWP 100817/threadtest)]
>>>>>> [New Thread 801809000 (LWP 100818/threadtest)]
>>>>>> [New Thread 801809800 (LWP 100820/threadtest)]
>>>>>> [New Thread 801808000 (LWP 100678/threadtest)]
>>>>>> [New Thread 801806400 (LWP 100121/threadtest)]
>>>>>> [New Thread 801806800 (LWP 100341/threadtest)]
>>>>>> [New Thread 801806c00 (LWP 100342/threadtest)]
>>>>>> .ERROR: pthread_mutex_lock:11
>>>>>>

>>>>>> Program received signal SIGABRT, Aborted.
>>>>>>
[Switching to Thread 801809800 (LWP 100820/threadtest)]
>>>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>>>>>> (gdb) where
>>>>>> #0 =3D3DC2=3D3DA00x0000000800d5c26a in thr_kill () from =3D >>>> /lib/libc.so.7
>>>>>> #1 =3D3DC2=3D3DA00x0000000800e23ac9 in abort () from = >> /lib/libc.so.7
>>>>>> #2 =3D3DC2=3D3DA00x000000000045101f in = >> ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3D3DE=3D3D >>>>>> rror accessing memory address 0x8000fe5f2d98: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
>>>>>> #3 =3D3DC2=3D3DA00x000000000044b370 in ThreadPThread__LockMutex =3D >>>> (M3_AYIbX3_m=3D3D3DErro=3D3D >>>>>> r accessing memory address 0x8000fe5f2dc8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>>>> #4 =3D3DC2=3D3DA00x0000000000405b5d in Main__LApply = >> (M3_AP7a1g_cl=3D3D3DError=3D >>>> accessing=3D3D >>>>>> memory address 0x8000fe5f2df8: Bad address.
>>>>>> ) at ../src/Main.m3:319
>>>>>> #5 =3D3DC2=3D3DA00x000000000044d243 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3D3DErr=3D3D >>>>>> or accessing memory address 0x8000fe5f2eb8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>> #6 =3D3DC2=3D3DA00x000000000044cf00 in ThreadPThread__ThreadBase =3D >>>> (M3_AJWxb1_param=3D3D >>>>>> =3D3D3DError accessing memory address 0x8000fe5f2f68: Bad = >> address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>> #7 =3D3DC2=3D3DA00x0000000800ad54a4 in pthread_create () from =3D >>>> /lib/libthr.so.3
>>>>>> #8 =3D3DC2=3D3DA00x0000000000000000 in ?? ()
>>>>>> (gdb) set lang c
>>>>>> (gdb) thread apply all bt
>>>>>> ... not that interesting ...
>>>>>>
>>>>>> Segfault is segfault---error 11 is EDEADLK (locking against =3D >>>> myself?)
>>>>>>
>>>>>> ????? the code is very straightforward, as I said.
>>>>>>
>>>>>> I thought people had the thread tester working with pthreads? =3D >>>> =3D3DC2=3D3DA0Which s=3D3D >>>>>> et of files, then? =3D3DC2=3D3DA0Anyone on FreeBSD/amd64?
>>>>>>
>>>>>> Could it be an issue with "volatile"? =3D3DC2=3D3DA0Not = >> even =3D >>>> sure where t=3D3D >>>>>> o look.
>>>>>>
>>>>>> The code calling the lock is just this:
>>>>>>
>>>>>> PROCEDURE GetChar (rd: T): CHAR
>>>>>> =3D3DC2=3D3DA0 RAISES {EndOfFile, Failure, Alerted} =3D3D3D
>>>>>> =3D3DC2=3D3DA0 BEGIN
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 LOCK rd DO
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 RETURN = >> FastGetChar(rd);
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 END
>>>>>> =3D3DC2=3D3DA0 END GetChar;
>>>>>>
>>>>>> No mysteries there...
>>>>>>
>>>>>> Ah is this the fork bug? =3D3DC2=3D3DA0Looks like the Init routine = >> is =3D >>>> called on a>>>>> r> >>>>>> lot of NIL mutexes around the fork. =3D3DC2=3D3DA0But the = >> subprocesses =3D >>>> aren't m=3D3D >>>>>> eant
>>>>>> to accesses the mutexes... humm
>>>>>>
>>>>>> Hmm, and it's not entirely a fork issue. =3D3DC2=3D3DA0Even = >> with =3D >>>> "threadte=3D3D >>>>>> st -tests STD,-fork,-forktoomuch" it misbehaves. =3D >>>> =3D3DC2=3D3DA0Hangs....
>>>>>>
>>>>>> Looks like a deadlock this time.
>>>>>>
>>>>>> Some stacks...
>>>>>>
>>>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
>>>>>> #0 =3D3DC2=3D3DA00x00000000004b4e2b in __vdso_gettimeofday ()
>>>>>> #1 =3D3DC2=3D3DA00x00000000004ab8d2 in gettimeofday ()
>>>>>> #2 =3D3DC2=3D3DA00x0000000000452e4b in TimePosix__Now () at =3D >>>> ../src/time/POSIX/TimeP=3D3D >>>>>> osixC.c:50
>>>>>> #3 =3D3DC2=3D3DA00x0000000000452d72 in Time__Now () at =3D >>>> ../src/time/POSIX/TimePosix.=3D3D >>>>>> m3:14
>>>>>> #4 =3D3DC2=3D3DA00x00000000004029a3 in Main__LApply = >> (M3_AP7a1g_cl=3D3D3DError=3D >>>> accessing=3D3D >>>>>> memory address 0x8000fedf6df8: Bad address.
>>>>>> ) at ../src/Main.m3:327
>>>>>> #5 =3D3DC2=3D3DA00x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3D3DErr=3D3D >>>>>> or accessing memory address 0x8000fedf6eb8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>> #6 =3D3DC2=3D3DA00x0000000000449c50 in ThreadPThread__ThreadBase =3D >>>> (M3_AJWxb1_param=3D3D >>>>>> =3D3D3DError accessing memory address 0x8000fedf6f68: Bad = >> address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>> #7 =3D3DC2=3D3DA00x000000000047c7d4 in thread_start ()
>>>>>> #8 =3D3DC2=3D3DA00x0000000000000000 in ?? ()
>>>>>>
>>>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
>>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>> #1 =3D3DC2=3D3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>>>> #2 =3D3DC2=3D3DA00x0000000000479404 in mutex_lock_common ()
>>>>>> #3 =3D3DC2=3D3DA00x000000000044dd15 in = >> ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3D3DE=3D3D >>>>>> rror accessing memory address 0x8000feff7d98: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>>> #4 =3D3DC2=3D3DA00x00000000004480c0 in ThreadPThread__LockMutex =3D >>>> (M3_AYIbX3_m=3D3D3DErro=3D3D >>>>>> r accessing memory address 0x8000feff7dc8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>>>> #5 =3D3DC2=3D3DA00x00000000004028ad in Main__LApply = >> (M3_AP7a1g_cl=3D3D3DError=3D >>>> accessing=3D3D >>>>>> memory address 0x8000feff7df8: Bad address.
>>>>>> ) at ../src/Main.m3:319
>>>>>> #6 =3D3DC2=3D3DA00x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3D3DErr=3D3D >>>>>> or accessing memory address 0x8000feff7eb8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>> #7 =3D3DC2=3D3DA00x0000000000449c50 in ThreadPThread__ThreadBase =3D >>>> (M3_AJWxb1_param=3D3D >>>>>> =3D3D3DError accessing memory address 0x8000feff7f68: Bad = >> address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>> #8 =3D3DC2=3D3DA00x000000000047c7d4 in thread_start ()
>>>>>> #9 =3D3DC2=3D3DA00x0000000000000000 in ?? ()
>>>>>>
>>>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
>>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>> #1 =3D3DC2=3D3DA00x0000000000475759 in suspend_common ()
>>>>>> #2 =3D3DC2=3D3DA00x00000000004755c1 in pthread_suspend_np ()
>>>>>> #3 =3D3DC2=3D3DA00x000000000044df0c in ThreadPThread__SuspendThread = >> =3D >>>> (mt=3D3D3DError acc=3D3D >>>>>> essing memory address 0x8000ffbfd6f8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
>>>>>> #4 =3D3DC2=3D3DA00x000000000044bade in ThreadPThread__StopThread =3D >>>> (M3_DMxDjQ_act=3D3D3DE=3D3D >>>>>> rror accessing memory address 0x8000ffbfd718: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909
>>>>>> #5 =3D3DC2=3D3DA00x000000000044bc81 in ThreadPThread__StopWorld () = >> at =3D >>>> ../src/thread=3D3D >>>>>> /PTHREAD/ThreadPThread.m3:948
>>>>>> #6 =3D3DC2=3D3DA00x000000000044b19e in RTThread__SuspendOthers () = >> at =3D >>>> ../src/thread/=3D3D >>>>>> PTHREAD/ThreadPThread.m3:713
>>>>>> #7 =3D3DC2=3D3DA00x00000000004330d6 in =3D >>>> RTCollector__CollectSomeInStateZero () at ..=3D3D >>>>>> /src/runtime/common/RTCollector.m3:749
>>>>>> #8 =3D3DC2=3D3DA00x0000000000433081 in RTCollector__CollectSome () = >> at =3D >>>> ../src/runtim=3D3D >>>>>> e/common/RTCollector.m3:723
>>>>>> #9 =3D3DC2=3D3DA00x0000000000432d49 in RTHeapRep__CollectEnough () = >> at =3D >>>> ../src/runtim=3D3D >>>>>> e/common/RTCollector.m3:657
>>>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced =3D >>>> (M3_Cwb5VA_dataSize=3D3D3DEr=3D3D >>>>>> ror accessing memory address 0x8000ffbfd958: Bad address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:367
>>>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>>> (M3_Eic7CK_def=3D3D3DError =3D3D >>>>>> accessing memory address 0x8000ffbfda18: Bad address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray =3D >>>> (M3_AJWxb1_defn=3D3D3DErro=3D3D >>>>>> r accessing memory address 0x8000ffbfda78: Bad address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3D3DError =3D >>>> accessing memo=3D3D >>>>>> ry address 0x8000ffbfdab8: Bad address.
>>>>>> ) at ../src/rw/Rd.m3:159
>>>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar = >> (M3_EkTcCb_rd=3D3D3DError=3D >>>> acces=3D3D >>>>>> sing memory address 0x8000ffbfdb88: Bad address.
>>>>>> ) at ../src/rw/Rd.m3:187
>>>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3D3DError =3D >>>> accessing memor=3D3D >>>>>> y address 0x8000ffbfdbd8: Bad address.
>>>>>> ) at ../src/rw/Rd.m3:176
>>>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3D3DError =3D >>>> accessing memo=3D3D >>>>>> ry address 0x8000ffbfdc58: Bad address.
>>>>>> ) at ../src/Main.m3:185
>>>>>>
>>>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3D3DError ac=3D3D >>>>>> cessing memory address 0x8000ffbfdeb8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase =3D >>>> (M3_AJWxb1_param=3D3D3DErro=3D3D >>>>>> r accessing memory address 0x8000ffbfdf68: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>> #19 0x000000000047c7d4 in thread_start ()
>>>>>> #20 0x0000000000000000 in ?? ()
>>>>>>
>>>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
>>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>> #1 =3D3DC2=3D3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>>>> #2 =3D3DC2=3D3DA00x0000000000479404 in mutex_lock_common ()
>>>>>> #3 =3D3DC2=3D3DA00x000000000044dd15 in = >> ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3D3DE=3D3D >>>>>> rror accessing memory address 0x8000ffffc678: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>>> #4 =3D3DC2=3D3DA00x000000000044d039 in RTOS__LockHeap () at =3D >>>> ../src/thread/PTHREAD/T=3D3D >>>>>> hreadPThread.m3:1337
>>>>>> ---Type <return> to continue, or q <return> to =3D >>>> quit---
>>>>>> #5 =3D3DC2=3D3DA00x000000000042ff79 in RTAllocator__AllocTraced =3D >>>> (M3_Cwb5VA_dataSize=3D3D >>>>>> =3D3D3DError accessing memory address 0x8000ffffc6e8: Bad = >> address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>>>> #6 =3D3DC2=3D3DA00x000000000042f15b in RTAllocator__GetTracedObj =3D >>>> (M3_Eic7CK_def=3D3D3DE=3D3D >>>>>> rror accessing memory address 0x8000ffffc7a8: Bad address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:224
>>>>>> #7 =3D3DC2=3D3DA00x000000000042eb23 in RTHooks__AllocateTracedObj =3D= >> >>>> (M3_AJWxb1_defn=3D3D >>>>>> =3D3D3DError accessing memory address 0x8000ffffc7f8: Bad = >> address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:122
>>>>>> #8 =3D3DC2=3D3DA00x000000000045fbe4 in TextCat__Flat =3D >>>> (M3_Bd56fi_LText=3D3D3DError acces=3D3D >>>>>> sing memory address 0x8000ffffc858: Bad address.
>>>>>> ) at ../src/text/TextCat.m3:562
>>>>>> #9 =3D3DC2=3D3DA00x000000000045ed5d in TextCat__Balance =3D >>>> (M3_Bd56fi_LText=3D3D3D0x800c49=3D3D >>>>>> 0b0, M3_BUgnwf_LInfo=3D3D3DError accessing memory address =3D >>>> 0x8000ffffc8f8: Bad a=3D3D >>>>>> ddress.
>>>>>> ) at ../src/text/TextCat.m3:488
>>>>>> #10 0x000000000045d64f in RTHooks__Concat (M3_Bd56fi_t=3D3D3DError = >> =3D >>>> accessing me=3D3D >>>>>> mory address 0x8000ffffcbb8: Bad address.
>>>>>> ) at ../src/text/TextCat.m3:40
>>>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3D3DError = >> accessing =3D >>>> memory =3D3D >>>>>> address 0x8000ffffcc38: Bad address.
>>>>>> ) at ../src/Main.m3:593
>>>>>> #12 0x000000000043d55d in RTLinker__RunMainBody = >> (M3_DjPxE3_m=3D3D3DError =3D >>>> access=3D3D >>>>>> ing memory address 0x8000ffffcf88: Bad address.
>>>>>> ) at ../src/runtime/common/RTLinker.m3:408
>>>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI (M3_DjPxE3_m=3D3D3DError= >> =3D >>>> accessing=3D3D >>>>>> memory address 0x8000ffffd008: Bad address.
>>>>>> ) at ../src/runtime/common/RTLinker.m3:115
>>>>>> #14 0x000000000043c97c in RTLinker__AddUnit (M3_DjPxE5_b=3D3D3DError = >> =3D >>>> accessing =3D3D >>>>>> memory address 0x8000ffffd028: Bad address.
>>>>>> ) at ../src/runtime/common/RTLinker.m3:124
>>>>>> #15 0x00000000004004a6 in main (argc=3D3D3DError accessing memory =3D= >> >>>> address 0x800=3D3D >>>>>> 0ffffd07c: Bad address.
>>>>>> ) at _m3main.c:22
>>>>>>
>>>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
>>>>>> #0 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>> #1 =3D3DC2=3D3DA00x0000000000477e8a in check_suspend ()
>>>>>> #2 =3D3DC2=3D3DA00x00000000004780a2 in sigcancel_handler ()
>>>>>> #3 =3D3DC2=3D3DA0<signal handler called>
>>>>>> #4 =3D3DC2=3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>> #5 =3D3DC2=3D3DA00x0000000000475f14 in __thr_umutex_lock ()
>>>>>> #6 =3D3DC2=3D3DA00x0000000000479404 in mutex_lock_common ()
>>>>>> #7 =3D3DC2=3D3DA00x000000000044dd15 in = >> ThreadPThread__pthread_mutex_lock =3D >>>> (mutex=3D3D3DE=3D3D >>>>>> rror accessing memory address 0x8000ff5fac18: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>>> #8 =3D3DC2=3D3DA00x000000000044d039 in RTOS__LockHeap () at =3D >>>> ../src/thread/PTHREAD/T=3D3D >>>>>> hreadPThread.m3:1337
>>>>>> #9 =3D3DC2=3D3DA00x000000000042ff79 in RTAllocator__AllocTraced =3D >>>> (M3_Cwb5VA_dataSize=3D3D >>>>>> =3D3D3DError accessing memory address 0x8000ff5fac88: Bad = >> address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D >>>> (M3_Eic7CK_def=3D3D3DError =3D3D >>>>>> accessing memory address 0x8000ff5fad48: Bad address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray =3D >>>> (M3_AJWxb1_defn=3D3D3DErro=3D3D >>>>>> r accessing memory address 0x8000ff5fada8: Bad address.
>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3D3DError =3D >>>> accessing memo=3D3D >>>>>> ry address 0x8000ff5fade8: Bad address.
>>>>>> ) at ../src/Main.m3:283
>>>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread =3D >>>> (M3_DMxDjQ_me=3D3D3DError ac=3D3D >>>>>> cessing memory address 0x8000ff5faeb8: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase =3D >>>> (M3_AJWxb1_param=3D3D3DErro=3D3D >>>>>> r accessing memory address 0x8000ff5faf68: Bad address.
>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>> #15 0x000000000047c7d4 in thread_start ()
>>>>>> #16 0x0000000000000000 in ?? ()
>>>>>>
>>>>>> (others are similar)
>>>>>>
>>>>>> Hmm looks like a FreeBSD issue now. =3D3DC2=3D3DA0It's = >> here...
>>>>>>
>>>>>> int
>>>>>> __cdecl
>>>>>> ThreadPThread__SuspendThread (m3_pthread_t mt)
>>>>>> {
>>>>>> =3D3DC2=3D3DA0 =3D >>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), = >> "=3D3D >>>>>> pthread_suspend_np");
>>>>>> =3D3DC2=3D3DA0 return 1;
>>>>>> }
>>>>>>
>>>>>> Now this suspend can wait:
>>>>>>
>>>>>> static int
>>>>>> suspend_common(struct pthread *curthread, struct pthread = >> *thread,
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 int = >> waitok)
>>>>>> {
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> uint32_t tmp;
>>>>>>
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 while = >> (thread->state =3D >>>> !=3D3D3D PS_DEAD &&=3D3D >>>>>>
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 !(thread->flags & T=3D3D >>>>>> HR_FLAGS_SUSPENDED)) {
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 thread->flags |=3D3D >>>>>> =3D3D3D THR_FLAGS_NEED_SUSPEND;
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 /* Thread is in cre=3D3D >>>>>> ation. */
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 if (thread->tid =3D3D >>>>>> =3D3D3D=3D3D3D TID_TERMINATED)
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >> D >>>>>> =3D3DA0 =3D3DC2=3D3DA0 return (1);
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 tmp =3D3D3D thread->=3D3D >>>>>> cycle;
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 _thr_send_sig(threa=3D3D >>>>>> d, SIGCANCEL);
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 THR_THREAD_UNLOCK(c=3D3D >>>>>> urthread, thread);
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 if (waitok) {
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >> D >>>>>> =3D3DA0 =3D3DC2=3D3DA0 _thr_umtx_wait_uint(&thread->cycle, = >> tmp, =3D >>>> NULL, 0); =3D3DC2=3D3DA0=3D3D >>>>>> <=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D= >> 3D3D
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >> D >>>>>> =3D3DA0 =3D3DC2=3D3DA0 THR_THREAD_LOCK(curthread, thread);
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 } else {
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >> D >>>>>> =3D3DA0 =3D3DC2=3D3DA0 THR_THREAD_LOCK(curthread, thread);
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3= >> D >>>>>> =3D3DA0 =3D3DC2=3D3DA0 return (0);
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 }
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 }
>>>>>>
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 return = >> (1);
>>>>>> }
>>>>>>
>>>>>> ... but what it can wait for I am not clear on.
>>>>>>
>>>>>> Do things work better on Linux?
>>>>>>
>>>>>> What is the status of the fork bug? =3D3DC2=3D3DA0Can it be worked = >> around =3D >>>> by only f=3D3D >>>>>> orking via Process.Create with no mutexes held (outside of all LOCK = >> =3D >>>> blocks)=3D3D >>>>>> ?
>>>>>>
>>>>>> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika
>>>>>>
>>>>>>
>>>>>>
>>>>>> Peter McKinna writes:
>>>>>> >--001a11c2ced4471a2e050079db82
>>>>>> >Content-Type: text/plain; charset=3D3D3DUTF-8
>>>>>>
>
>>>>>> >Mika
>>>>>> >
>>>>>> > =3D3DC2=3D3DA0I think you need to back out Tony's changes = >> to fix =3D >>>> the fork =3D3D >>>>>> bug, at least
>>>>>> >for now. Need to reload from cvs version 1.262 for =3D >>>> ThreadPThread.m3 If<=3D3D >>>>>> br> >>>>>> >you're using git you're on your own.
>>>>>> > =3D3DC2=3D3DA0Do a cvs log ThreadPThread.m3 for an explanation = >> for =3D >>>> some of the=3D3D >>>>>> design
>>>>>> >principles.
>>>>>> > =3D3DC2=3D3DA0Also if you use gdb then you need to set lanc c = >> before =3D >>>> backtrace=3D3D >>>>>> s so at
>>>>>> >least you can see address names and values even if they are =3D >>>> contorted y=3D3D >>>>>> ou
>>>>>> >can extract the M3 name in the parm lists. Also in gdb thread =3D= >> >>>> apply all=3D3D >>>>>> bt
>>>>>> >gives all thread backtraces which can be handy to see whose got = >> =3D >>>> the loc=3D3D >>>>>> ks
>>>>>> >held.
>>>>>> >
>>>>>> >Regards Peter
>>>>>> >
>>>>>> >
>>>>>> >
>>>>>> >On Wed, Aug 13, 2014 at 12:14 PM, <>>> href=3D3D3D"mailto:mika at async.calt=3D3D >>>>>> ech.edu" target=3D3D3D"_blank">mika at async.caltech.edu> =3D >>>> wrote:
>>>>>> >
>>>>>> >>
>>>>>> >> Question... is there something odd about my pthreads? =3D >>>> =3D3DC2=3D3DA0Are pt=3D3D >>>>>> hreads
>>>>>> >> normally reentrant? =3D3DC2=3D3DA0I didn't think = >> so.
>>>>>> >>
>>>>>> >> My compiler is much happier with the following changes I =3D= >> >>>> already o=3D3D >>>>>> utlined:
>>>>>> >>
>>>>>> >> 1. a dirty, disgusting hack to keep from locking against =3D= >> >>>> myself go=3D3D >>>>>> ing from
>>>>>> >> XWait with self.mutex locked to m.release().
>>>>>> >>
>>>>>> >> 2. the change to LockHeap I described in previous = >> email
>>>>>> >>
>>>>>> >> But now...
>>>>>> >>
>>>>>> >> (gdb) cont
>>>>>> >> Continuing.
>>>>>> >> ERROR: pthread_mutex_lock:11
>>>>>> >> ERROR: pthread_mutex_lock:11
>>>>>> >>
>>>>>> >> Program received signal SIGABRT, Aborted.
>>>>>> >> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>>> >> (gdb) where
>>>>>> >> #0 =3D3DC2=3D3DA00x000000080107626a in thr_kill () from =3D >>>> /lib/libc.so.7
>>>>>> >> #1 =3D3DC2=3D3DA00x000000080113dac9 in abort () from =3D >>>> /lib/libc.so.7
>>>>>> >> #2 =3D3DC2=3D3DA00x000000000071e37a in =3D >>>> ThreadPThread__pthread_mutex_lock (=3D3D >>>>>> mutex=3D3D3DError
>>>>>> >> accessing memory address 0x8000ffffb508: Bad address.
>>>>>> >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>>> >> #3 =3D3DC2=3D3DA00x000000000071d48d in RTOS__LockHeap () = >> at
>>>>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>>>>>> >> #4 =3D3DC2=3D3DA00x0000000000706b9d in =3D >>>> RTHooks__CheckLoadTracedRef (M3_Af4=3D3D >>>>>> 0ku_ref=3D3D3DError
>>>>>> >> accessing memory address 0x8000ffffb568: Bad address.
>>>>>> >> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>>> >> #5 =3D3DC2=3D3DA00x000000000071d284 in =3D >>>> ThreadPThread__AtForkParent () at>>>>> r> >>>>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>>>>>> >> #6 =3D3DC2=3D3DA00x0000000800df8733 in fork () from =3D >>>> /lib/libthr.so.3
>>>>>> >> #7 =3D3DC2=3D3DA00x000000000070dd8b in RTProcess__Fork () = >> at
>>>>>> >> ../src/runtime/common/RTProcessC.c:152
>>>>>> >> #8 =3D3DC2=3D3DA00x00000000006c52f2 in =3D >>>> ProcessPosixCommon__Create_ForkExec=3D3D >>>>>>
>>>>>> >> (M3_Bd56fi_cmd=3D3D3DError accessing memory address =3D >>>> 0x8000ffffb6f8: Ba=3D3D >>>>>> d address.
>>>>>> >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>>> >> #9 =3D3DC2=3D3DA00x00000000006c6c6c in Process__Create =3D >>>> (M3_Bd56fi_cmd=3D3D3DEr=3D3D >>>>>> ror accessing
>>>>>> >> memory address 0x8000ffffb7f8: Bad address.
>>>>>> >> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>>> >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise =3D >>>> (M3_D6rRrg_e=3D3D >>>>>> p=3D3D3DError
>>>>>> >> accessing memory address 0x8000ffffb838: Bad address.
>>>>>> >> ) at ../src/QMachine.m3:1666
>>>>>> >> #11 0x00000000004d6220 in QMachine__ExecCommand =3D >>>> (M3_An02H2_t=3D3D3DErr=3D3D >>>>>> or
>>>>>> >> accessing memory address 0x8000ffffb9f8: Bad address.
>>>>>> >> ) at ../src/QMachine.m3:1605
>>>>>> >> #12 0x00000000004d537e in QMachine__DoTryExec =3D >>>> (M3_An02H2_t=3D3D3DError=3D3D >>>>>> accessing
>>>>>> >> memory address 0x8000ffffbee8: Bad address.
>>>>>> >> ) at ../src/QMachine.m3:1476
>>>>>> >>
>>>>>> >> What am I doing wrong here?
>>>>>> >>
>>>>>> >> The error doesn't look unreasonable! =3D3DC2=3D3DA0Looki= >> ng =3D >>>> more closel=3D3D >>>>>> y at the code:
>>>>>> >>
>>>>>> >> First, AtForkPrepare has been called:
>>>>>> >>
>>>>>> >> PROCEDURE AtForkPrepare() =3D3D3D
>>>>>> >> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >> Activation;
>>>>>> >> =3D3DC2=3D3DA0 BEGIN
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(slotsMu, =3D >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(perfMu, =3D >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(initMu, = >> ThisLine()); =3D >>>> (* InitMutex =3D3D >>>>>> =3D3D3D>
>>>>>> >> RegisterFinalCleanup =3D3D3D> LockHeap *)
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(heapMu, =3D >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadLockMutex(activeMu, =3D= >> >>>> ThisLine()); (* LockHeap =3D3D >>>>>> =3D3D3D> SuspendOthers
>>>>>> >> =3D3D3D> activeMu *)
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and lock = >> all =3D >>>> threads.
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* NOTE: We = >> have initMu, =3D >>>> activeMu, so slots won=3D3D >>>>>> 't change, conditions
>>>>>> >> and
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0* mutexes = >> won't be =3D >>>> initialized on-demand.<=3D3D >>>>>> br> >>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0*)
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 = >> PThreadLockMutex(act.mutex, =3D >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >> act.next;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>>> >> =3D3DC2=3D3DA0 END AtForkPrepare;
>>>>>> >>
>>>>>> >> a postcondition of this routine is that heapMu is =3D >>>> locked.
>>>>>> >>
>>>>>> >> now we get into AtForkParent:
>>>>>> >>
>>>>>> >> PROCEDURE AtForkParent() =3D3D3D
>>>>>> >> =3D3DC2=3D3DA0 VAR me :=3D3D3D GetActivation();
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act: = >> Activation;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond: = >> Condition;
>>>>>> >> =3D3DC2=3D3DA0 BEGIN
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 (* Walk activations and = >> unlock all =3D >>>> threads, conditio=3D3D >>>>>> ns. *)
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D me;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 REPEAT
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 cond :=3D3D3D = >> =3D >>>> slots[act.slot].join;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 IF cond # NIL = >> THEN =3D >>>> PThreadUnlockMutex(cond.mu=3D3D >>>>>> tex, ThisLine()) END;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D >>>> PThreadUnlockMutex(act.mutex, ThisLine());>>>>>> =3D20 >>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 act :=3D3D3D = >> act.next;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 UNTIL act =3D3D3D me;
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(activeMu, = >> =3D >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(heapMu, =3D= >> >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(initMu, =3D= >> >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(perfMu, =3D= >> >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 PThreadUnlockMutex(slotsMu, = >> =3D >>>> ThisLine());
>>>>>> >> =3D3DC2=3D3DA0 END AtForkParent;
>>>>>> >>
>>>>>> >> We can see by inspecting the code that a necessary =3D >>>> precondition fo=3D3D >>>>>> r
>>>>>> >> this routine is that heapMu is locked! =3D3DC2=3D3DA0(Since = >> =3D >>>> it's going=3D3D >>>>>> to unlock it,
>>>>>> >> it had BETTER be locked on entry.)
>>>>>> >>
>>>>>> >> But the cond :=3D3D3D ... causes a =3D >>>> RTHooks.CheckLoadTracedRef
>>>>>> >>
>>>>>> >> which causes an RTOS.LockHeap
>>>>>> >>
>>>>>> >> the code of which we just saw:
>>>>>> >>
>>>>>> >> PROCEDURE LockHeap () =3D3D3D
>>>>>> >> =3D3DC2=3D3DA0 VAR self :=3D3D3D pthread_self();
>>>>>> >> =3D3DC2=3D3DA0 BEGIN
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 WITH r =3D3D3D =3D >>>> pthread_mutex_lock(heapMu,ThisLine()) DO =3D3D >>>>>> <*ASSERT r=3D3D3D0*> END;
>>>>>> >> ...
>>>>>> >>
>>>>>> >> we try to lock heapMu. =3D3DC2=3D3DA0kaboom! =3D3DC2=3D3DA0N= >> o =3D >>>> surprise there, real=3D3D >>>>>> ly?
>>>>>> >>
>>>>>> >> Am I going about this totally the wrong way? = >> =3D3DC2=3D3DA0Other =3D >>>> people ar=3D3D >>>>>> e running
>>>>>> >> Modula-3
>>>>>> >> with pthreads, right? =3D3DC2=3D3DA0Right?? = >> =3D3DC2=3D3DA0Somewhere =3D >>>> out there in m=3D3D >>>>>> 3devel-land?
>>>>>> >>
>>>>>> >> =3D3DC2=3D3DA0 =3D3DC2=3D3DA0 =3D3DC2=3D3DA0Mika
>>>>>> >>
>>>>>> >>
>>>>>> >
>>>>>>
>--001a11c2ced4471a2e050079db82
>>>>>> >Content-Type: text/html; charset=3D3D3DUTF-8
>>>>>> >Content-Transfer-Encoding: quoted-printable
>>>>>> >
>>>>>> ><div =3D >>>> dir=3D3D3D3D"ltr">Mika<div><br></div>=3D3= >> D >>>>>> ;<div>=3D3D3DC2=3D3D3DA0 I think you need to back ou=3D3D3D
= >> >>>>>> >t Tony&#39;s changes to fix the fork bug, at least for now. = >> =3D >>>> Need to=3D3D >>>>>> reload =3D3D3D
>>>>>> >from cvs version 1.262 for ThreadPThread.m3 If you&#39;re =3D= >> >>>> using git=3D3D >>>>>> you&#39=3D3D3D
>>>>>> >;re on your own.</div>
>>>>>> >
>>>>>> ><div>=3D3D3DC2=3D3D3DA0 Do a cvs log ThreadPThread.m3 for = >> an =3D >>>> explanation =3D3D >>>>>> for some of th=3D3D3D
>>>>>> >e design = >> principles.=3D3D3DC2=3D3D3DA0</div><div>=3D3D3DC2=3D3D=3D >>>> 3DA0 Also if=3D3D >>>>>> you use gdb then you ne=3D3D3D
>>>>>> >ed to set lanc c before backtraces so at least you can see =3D >>>> address name=3D3D >>>>>> s an=3D3D3D
>>>>>> >d values even if they are contorted you can extract the M3 name = >> =3D >>>> in the =3D3D >>>>>> parm=3D3D3D
>>>>>> > lists. Also in gdb thread apply all bt gives all thread =3D >>>> backtraces whi=3D3D >>>>>> ch c=3D3D3D
>>>>>> >an be handy to see whose got the locks held.</div>
>>>>>> >
>>>>>> ><div><br></div><div>Regards =3D >>>> Peter</div>&l=3D3D >>>>>> t;div><br></div><div = >> class=3D3D3D3D"gmail_e=3D3D3D>>> r> >>>>>> >xtra"><br><br><div =3D >>>> class=3D3D3D3D"gmail_quote&q=3D3D >>>>>> uot;>On Wed, Aug 13, 2014 at 12:14 PM, =3D3D3D
>>>>>> > <span dir=3D3D3D3D"ltr">&lt;<a =3D >>>> href=3D3D3D3D"mailt=3D3D >>>>>> o:>>> target=3D3D3D"_blank">mika at async.ca=3D3D >>>>>> ltech.edu" target=3D3D3D3D"=3D3D3D
>>>>>> >_blank">> >>>> target=3D3D3D"_bl=3D3D >>>>>> ank">mika at async.caltech.edu</a>&gt;</span> =3D >>>> wrote:<br=3D3D >>>>>> >
>>>>>> >
>>>>>> ><blockquote class=3D3D3D3D"gmail_quote" =3D >>>> style=3D3D3D3D"margin=3D3D >>>>>> :0 0 0 .8ex;border-left:1p=3D3D3D
>>>>>> >x #ccc solid;padding-left:1ex"><br>
>>>>>> >Question... is there something odd about my pthreads? =3D >>>> =3D3D3DC2=3D3D3DA0Are pth=3D3D >>>>>> reads no=3D3D3D
>>>>>> >rmally reentrant? =3D3D3DC2=3D3D3DA0I didn&#39;t think =3D >>>> so.<br>
>>>>>> ><br>
>>>>>> >My compiler is much happier with the following changes I = >> already =3D >>>> outlin=3D3D >>>>>> ed:<=3D3D3D
>>>>>> >br>
>>>>>> ><br>
>>>>>> >1. a dirty, disgusting hack to keep from locking against myself = >> =3D >>>> going f=3D3D >>>>>> rom =3D3D3D
>>>>>> >XWait with self.mutex locked to m.release().<br>
>>>>>> ><br>
>>>>>> >2. the change to LockHeap I described in previous =3D >>>> email<br>
>>>>>> ><br>
>>>>>> >But now...<br>
>>>>>> ><br>
>>>>>> >(gdb) cont<br>
>>>>>> >Continuing.<br>
>>>>>> >ERROR: pthread_mutex_lock:11<br>
>>>>>> >ERROR: pthread_mutex_lock:11<br>
>>>>>> ><br>
>>>>>> >Program received signal SIGABRT, Aborted.<br>
>>>>>> >0x000000080107626a in thr_kill () from =3D >>>> /lib/libc.so.7<br>
>>>>>> >(gdb) where<br>
>>>>>> >#0 =3D3D3DC2=3D3D3DA00x000000080107626a in thr_kill () from =3D >>>> /lib/libc.so.7<b=3D3D >>>>>> r>
>>>>>> >#1 =3D3D3DC2=3D3D3DA00x000000080113dac9 in abort () from =3D >>>> /lib/libc.so.7<br&g=3D3D >>>>>> t;
>>>>>> >#2 =3D3D3DC2=3D3D3DA00x000000000071e37a in =3D >>>> ThreadPThread__pthread_mutex_lock (m=3D3D >>>>>> utex=3D3D3D3DE=3D3D3D
>>>>>> >rror accessing memory address 0x8000ffffb508: Bad =3D >>>> address.<br>>>>>>> =3D20 >>>>>> >) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>>>>>> >#3 =3D3D3DC2=3D3D3DA00x000000000071d48d in RTOS__LockHeap () at = >> =3D >>>> ../src/thread/P=3D3D >>>>>> THREAD/T=3D3D3D
>>>>>> >hreadPThread.m3:1377<br>
>>>>>> >#4 =3D3D3DC2=3D3D3DA00x0000000000706b9d in =3D >>>> RTHooks__CheckLoadTracedRef (M3_Af40=3D3D >>>>>> ku_ref=3D3D3D
>>>>>> >=3D3D3D3DError accessing memory address 0x8000ffffb568: Bad =3D >>>> address.<br&=3D3D >>>>>> gt;
>>>>>> >) at ../src/runtime/common/RTCollector.m3:2234<br>
>>>>>> >#5 =3D3D3DC2=3D3D3DA00x000000000071d284 in =3D >>>> ThreadPThread__AtForkParent () at ..=3D3D >>>>>> /src/thr=3D3D3D
>>>>>> >ead/PTHREAD/ThreadPThread.m3:1348<br>
>>>>>> >#6 =3D3D3DC2=3D3D3DA00x0000000800df8733 in fork () from =3D >>>> /lib/libthr.so.3<br&=3D3D >>>>>> gt;
>>>>>> >#7 =3D3D3DC2=3D3D3DA00x000000000070dd8b in RTProcess__Fork () = >> at =3D >>>> ../src/runtime=3D3D >>>>>> /common/=3D3D3D
>>>>>> >RTProcessC.c:152<br>
>>>>>> >#8 =3D3D3DC2=3D3D3DA00x00000000006c52f2 in =3D >>>> ProcessPosixCommon__Create_ForkExec =3D3D >>>>>> (M3_Bd56=3D3D3D
>>>>>> >fi_cmd=3D3D3D3DError accessing memory address 0x8000ffffb6f8: = >> Bad =3D >>>> address.&=3D3D >>>>>> lt;br>
>>>>>> >) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>>>>>> >#9 =3D3D3DC2=3D3D3DA00x00000000006c6c6c in Process__Create =3D >>>> (M3_Bd56fi_cmd=3D3D3D3DE=3D3D >>>>>> rror acces=3D3D3D
>>>>>> >sing memory address 0x8000ffffb7f8: Bad address.<br>
>>>>>> >) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>>>>>> >#10 0x00000000004d6826 in QMachine__FulfilExecPromise =3D >>>> (M3_D6rRrg_ep=3D3D3D3=3D3D >>>>>> DError=3D3D3D
>>>>>> > accessing memory address 0x8000ffffb838: Bad =3D >>>> address.<br>
>>>>>> >) at ../src/QMachine.m3:1666<br>
>>>>>> >#11 0x00000000004d6220 in QMachine__ExecCommand =3D >>>> (M3_An02H2_t=3D3D3D3DError =3D3D >>>>>> access=3D3D3D
>>>>>> >ing memory address 0x8000ffffb9f8: Bad address.<br>
>>>>>> >) at ../src/QMachine.m3:1605<br>
>>>>>> >#12 0x00000000004d537e in QMachine__DoTryExec =3D >>>> (M3_An02H2_t=3D3D3D3DError ac=3D3D >>>>>> cessin=3D3D3D
>>>>>> >g memory address 0x8000ffffbee8: Bad address.<br>
>>>>>> >) at ../src/QMachine.m3:1476<br>
>>>>>> ><br>
>>>>>> >What am I doing wrong here?<br>
>>>>>> ><br>
>>>>>> >The error doesn&#39;t look unreasonable! = >> =3D3D3DC2=3D3D3DA0Looking =3D >>>> more clo=3D3D >>>>>> sely at the =3D3D3D
>>>>>> >code:<br>
>>>>>> ><br>
>>>>>> >First, AtForkPrepare has been called:<br>
>>>>>> ><br>
>>>>>> >PROCEDURE AtForkPrepare() =3D3D3D3D<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D = >> GetActivation();<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act: =3D= >> >>>> Activation;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 BEGIN<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(slotsMu, = >> =3D >>>> ThisLine());<br><=3D3D >>>>>> br> >>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(perfMu, = >> =3D >>>> ThisLine());<br>>>>>> r> >>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(initMu, = >> =3D >>>> ThisLine()); (* InitMute=3D3D >>>>>> x =3D3D3D3D&gt; Re=3D3D3D
>>>>>> >gisterFinalCleanup =3D3D3D3D&gt; LockHeap *)<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(heapMu, = >> =3D >>>> ThisLine());<br>>>>>> r> >>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> PThreadLockMutex(activeMu, =3D >>>> ThisLine()); (* LockHe=3D3D >>>>>> ap =3D3D3D3D&gt; S=3D3D3D
>>>>>> >uspendOthers =3D3D3D3D&gt; activeMu *)<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk activations and = >> lock all =3D >>>> threads.<br&g=3D3D >>>>>> t;
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* NOTE: = >> We have =3D >>>> initMu, activeMu, so sl=3D3D >>>>>> ots won&#39;t ch=3D3D3D
>>>>>> >ange, conditions and<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* = >> mutexes =3D >>>> won&#39;t be initialized =3D3D >>>>>> on-demand.<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> =3D3D3DC2=3D3D3DA0*)<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D = >> me;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D >>>> PThreadLockMutex(act.mutex, ThisLine()=3D3D >>>>>> );<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act = >> :=3D3D3D3D =3D >>>> act.next;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >> me;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 END AtForkPrepare;<br>
>>>>>> ><br>
>>>>>> >a postcondition of this routine is that heapMu is =3D >>>> locked.<br>
>>>>>> ><br>
>>>>>> >now we get into AtForkParent:<br>
>>>>>> ><br>
>>>>>> >PROCEDURE AtForkParent() =3D3D3D3D<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D = >> GetActivation();<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act: =3D= >> >>>> Activation;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 cond: = >> =3D >>>> Condition;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 BEGIN<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk activations and = >> unlock all =3D >>>> threads, condi=3D3D >>>>>> tions. *)<br=3D3D3D
>>>>>> >>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D = >> me;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 cond = >> :=3D3D3D3D =3D >>>> slots[act.slot].join;<b=3D3D >>>>>> r>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 IF = >> cond # NIL THEN =3D >>>> PThreadUnlockMutex(=3D3D >>>>>> cond.mutex, This=3D3D3D
>>>>>> >Line()) END;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D >>>> PThreadUnlockMutex(act.mutex, ThisLine=3D3D >>>>>> ());<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act = >> :=3D3D3D3D =3D >>>> act.next;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >> me;<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> PThreadUnlockMutex(activeMu, =3D >>>> ThisLine());<br&g=3D3D >>>>>> t;
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> PThreadUnlockMutex(heapMu, =3D >>>> ThisLine());<br>=3D3D >>>>>>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> PThreadUnlockMutex(initMu, =3D >>>> ThisLine());<br>=3D3D >>>>>>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> PThreadUnlockMutex(perfMu, =3D >>>> ThisLine());<br>=3D3D >>>>>>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> PThreadUnlockMutex(slotsMu, =3D >>>> ThisLine());<br>=3D3D >>>>>> ;
>>>>>> >=3D3D3DC2=3D3D3DA0 END AtForkParent;<br>
>>>>>> ><br>
>>>>>> >We can see by inspecting the code that a necessary precondition = >> =3D >>>> for<=3D3D >>>>>> br>
>>>>>> >this routine is that heapMu is locked! =3D3D3DC2=3D3D3DA0(Since = >> =3D >>>> it&#39;s go=3D3D >>>>>> ing to unloc=3D3D3D
>>>>>> >k it,<br>
>>>>>> >it had BETTER be locked on entry.)<br>
>>>>>> ><br>
>>>>>> >But the cond :=3D3D3D3D ... causes a =3D >>>> RTHooks.CheckLoadTracedRef<br>>>>>> r> >>>>>> ><br>
>>>>>> >which causes an RTOS.LockHeap<br>
>>>>>> ><br>
>>>>>> >the code of which we just saw:<br>
>>>>>> ><br>
>>>>>> >PROCEDURE LockHeap () =3D3D3D3D<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 VAR self :=3D3D3D3D = >> pthread_self();<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 BEGIN<br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 WITH r =3D3D3D3D =3D >>>> pthread_mutex_lock(heapMu,ThisLine()=3D3D >>>>>> ) DO &lt;*ASSE=3D3D3D
>>>>>> >RT r=3D3D3D3D0*&gt; END;<br>
>>>>>> >...<br>
>>>>>> ><br>
>>>>>> >we try to lock heapMu. =3D3D3DC2=3D3D3DA0kaboom! = >> =3D3D3DC2=3D3D3DA0No =3D >>>> surprise there, r=3D3D >>>>>> eally?<br>
>>>>>> ><br>
>>>>>> >Am I going about this totally the wrong way? = >> =3D3D3DC2=3D3D3DA0Other =3D >>>> people are=3D3D >>>>>> running=3D3D3D
>>>>>> > Modula-3<br>
>>>>>> >with pthreads, right? =3D3D3DC2=3D3D3DA0Right?? = >> =3D3D3DC2=3D3D3DA0Somewhere=3D >>>> out there i=3D3D >>>>>> n m3devel-la=3D3D3D
>>>>>> >nd?<br>
>>>>>> ><span><font =3D >>>> color=3D3D3D3D"#888888"><br>
>>>>>> >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >> =3D3D3DC2=3D3D3DA0Mika<br>
>>>>>> ><br>
>>>>>> =3D >>>> = >> ></font></span></blockquote></div><br><= >> =3D >>>> ;=3D3D >>>>>> /div></div>
>>>>>> >
>>>>>> >--001a11c2ced4471a2e050079db82--
>>>>>>

>>>>>>

>>>>>> =3D20 >>>>>> --089e01183a1813188705007c3498-- From mika at async.caltech.edu Wed Aug 13 20:58:49 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Wed, 13 Aug 2014 11:58:49 -0700 Subject: [M3devel] Ho hum... AtFork... In-Reply-To: References: <20140813021401.238B31A2094@async.async.caltech.edu> <20140813045415.C13921A2094@async.async.caltech.edu> <20140813063041.286EA1A2094@async.async.caltech.edu> <97266593-618F-458D-A975-FE01D9BF19F9@cs.purdue.edu> <20140813163735.8D0701A2097@async.async.caltech.edu> <7A6EF7C5-9B0F-4FC5-BCB1-C7A0E36BB2D6@cs.purdue.edu> <20140813170459.436121A2097@async.async.caltech.edu> Message-ID: <20140813185849.8A9621A209C@async.async.caltech.edu> Yes I see... hmm, a bit tricky. My point about Process.Create was that Modula-3 doesn't really have to support all of POSIX, does it? Although of course a C library might call fork and then what... As you described it won't your solution imply that if any thread holds a mutex and won't release it, you cannot fork? (Fork locks against all mutexes?) Is that acceptable? If all the child is going to do is exec (as in Process.Create?) does it matter what mutexes are held (in the child), anyhow? My biggest worry is that there is no consistent fully solution for mixing fork and mutexes. In any case I did dig into the assembly output of getting at thread locals on FreeBSD. (I think it is the same on Linux.) It is apparently very fast nowadays. I think the kernel just maps a page at a fixed address per kernel thread (same virtual address across threads, different physical pages). That's good. But anything that gets at thread locals will run very slowly on older FreeBSDs for sure. Maybe nothing to care about anymore... Mika Tony Hosking writes: > >On Aug 13, 2014, at 1:04 PM, mika at async.caltech.edu wrote: > >> Sure, I understand. Just wasn't aware of it yesterday! >>=20 >> But I think there are two problems here: fork and FreeBSD. >>=20 >> The problems on AMD64_FREEBSD look like something different .. >> there is custom FreeBSD code that is invoked and seems to screw things >> up. The attached example doesn't use fork at all. > >I=92ll take a look at the attached FREEBSD example shortly. > >> On the other hand, question about fork: what is the precise problem >> with fork? My understanding was that it was an issue with held = >mutexes >> on fork. But what if you don't hold any mutexes on fork? > >The problem is holding pthread mutexes in other threads at fork. If you = >don=92t hold any then all is good. But, other threads may be in the = >middle of things, holding a mutex, when another thread executes fork. = >The idea is to prepare for the fork by acquiring all relevant mutexes = >before forking and releasing them after. The question is how to = >enumerate the mutexes to be acquired/released. We can enumerate the = >threads, so if every thread guards all other acquisitions of *other* = >mutexes by locking itself first, then the prepare to fork code can = >simply lock all the *threads* before forking and know that no other = >thread can possibly hold any other mutexes. The difficulty lies in the = >fact that the current implementation has threads lock both themselves = >and other mutexes, so you can end up with deadlock. > >[We used to have a thin veneer for Modula-3 MUTEX over pthread mutex, = >but then there was no way to know what mutexes were held. I stepped = >back from that, much as I did way back for Modula-3 condition variables = >to be able to handle alerting, to be able to enumerate the pthread = >mutexes (as above).] > >One approach I am considering is having threads mark themselves as = >inCritical while they hold any pthread mutexes, and then use thread = >suspension to bring them all to a safe point before forking (this is = >similar to GC with respect to allocation =97 see RTAllocator.m3). > >> Related question: how many times does fork appear in the cm3 tree? I >> only ever use Process.Create ... can one build a custom solution for = >that >> one routine, maybe with a forker thread somehow? Or do others use = >more >> general forking patterns? > >Yes, it=92s the standard way to create processes on POSIX. A forker = >thread does not help, because you still need to worry about the other = >threads. =20 > >Anyway, I hope to have something soon... > >>=20 >> Mika >>=20 >> Tony Hosking writes: >>>=20 >>> On Aug 13, 2014, at 12:37 PM, mika at async.caltech.edu wrote: >>>=20 >>>> 1.262 >>>> =3D20 >>>> Short summary: 1.262 seems to work fine on AMD64_LINUX except for = >the >>>> fork issue (a bummer because my parallelization of the backends of = >cm3 >>>> uses fork a lot...and it does speed up the compiler significantly if >>>> you have fast disks and lots of cores) It does the attached on =3D >>> AMD64_FREEBSD. >>>=20 >>> Yes, that was the state of things. Subsequent revs were to address = >fork =3D >>> issues. >>>=20 >>>> =3D20 >>>> I see the intent of what you were doing in later version/s, but it = >was >>>> a bit rough, I think... I think the three issues I reported (1. =3D >>> locking >>>> heapMu from AtFork; 2. the try-only-once bug in LockHeap itself; 3. = >=3D >>> not >>>> passing the lock to release from Wait) are all more or less real. >>>=20 >>> Working on these right now. Sorry for hacked versions =3D97 no time = >right =3D >>> now to do real testing before push. >>> Getting closer now I think. >>>=20 >>>> =3D20 >>>> Mika >>>> =3D20 >>>> Tony Hosking writes: >>>>> Which revision of ThreadPThread.m3 is this output from? >>>>> =3D20 >>>>> On Aug 13, 2014, at 2:30 AM, mika at async.caltech.edu wrote: >>>>> =3D20 >>>>>> =3D3D20 >>>>>> OK... deleted all the derived directories and rebuilt. Result on = >=3D3D >>>>> FreeBSD is similar (or identical, hard to tell): >>>>>> =3D3D20 >>>>>> I get a partial deadlock: >>>>>> =3D3D20 >>>>>> PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU =3D3D= > >>>>> COMMAND >>>>>> 48760 root 98 0 87836K 29104K CPU1 1 12:32 83.89% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 94 0 87836K 29104K CPU3 3 11:02 74.66% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 94 0 87836K 29104K CPU0 0 11:03 71.97% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 32 0 87836K 29104K umtxn 2 0:01 0.00% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 20 0 87836K 29104K umtxn 2 0:01 0.00% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 35 0 87836K 29104K uwait 2 0:01 0.00% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 27 0 87836K 29104K uwait 0 0:01 0.00% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 27 0 87836K 29104K umtxn 3 0:01 0.00% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 27 0 87836K 29104K umtxn 2 0:01 0.00% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48760 root 20 0 87836K 29104K umtxn 0 0:00 0.00% = >=3D3D >>>>> threadtest{threadtest} >>>>>> 48759 root 20 0 30276K 11064K wait 0 0:00 0.00% = >gdb >>>>>> =3D3D20 >>>>>> one of the dead threads is the main thread, so now output. But =3D >>> three >>>>>> threads are still alive, interestingly enough. >>>>>> =3D3D20 >>>>>> Looks like the same issue as before: >>>>>> =3D3D20 >>>>>> Thread 5 (Thread 801807400 (LWP 100751/threadtest)): >>>>>> #0 0x0000000800ae089c in __error () from /lib/libthr.so.3 >>>>>> #1 0x0000000800ad6261 in pthread_suspend_np () from =3D >>> /lib/libthr.so.3 >>>>>> #2 0x00000000004511bc in ThreadPThread__SuspendThread = >(mt=3D3D3DError =3D >>> =3D3D >>>>> accessing memory address 0x8000ff5faa28: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>>>> #3 0x000000000044ed8e in ThreadPThread__StopThread =3D3D >>>>> (M3_DMxDjQ_act=3D3D3DError accessing memory address 0x8000ff5faa48: = >Bad =3D >>> =3D3D >>>>> address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>>>> #4 0x000000000044ef31 in ThreadPThread__StopWorld () at =3D3D >>>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>>>> #5 0x000000000044e44e in RTThread__SuspendOthers () at =3D3D >>>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>>>> #6 0x0000000000436386 in RTCollector__CollectSomeInStateZero () = >at =3D >>> =3D3D >>>>> ../src/runtime/common/RTCollector.m3:749 >>>>>> #7 0x0000000000436331 in RTCollector__CollectSome () at =3D3D >>>>> ../src/runtime/common/RTCollector.m3:723 >>>>>> #8 0x0000000000435ff9 in RTHeapRep__CollectEnough () at =3D3D >>>>> ../src/runtime/common/RTCollector.m3:657 >>>>>> #9 0x0000000000433233 in RTAllocator__AllocTraced =3D3D >>>>> (M3_Cwb5VA_dataSize=3D3D3DError accessing memory address =3D >>> 0x8000ff5fac88: Bad =3D3D >>>>> address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>>>> #10 0x0000000000432b55 in RTAllocator__GetOpenArray =3D3D >>>>> (M3_Eic7CK_def=3D3D3DError accessing memory address 0x8000ff5fad48: = >Bad =3D >>> =3D3D >>>>> address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>> #11 0x0000000000431e8f in RTHooks__AllocateOpenArray =3D3D >>>>> (M3_AJWxb1_defn=3D3D3DError accessing memory address = >0x8000ff5fada8: =3D >>> Bad =3D3D >>>>> address. >>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>> #12 0x00000000004052ea in Main__AApply (M3_AP7a1g_cl=3D3D3DError =3D= > >>> accessing =3D3D >>>>> memory address 0x8000ff5fade8: Bad address. >>>>>> ) at ../src/Main.m3:283 >>>>>> #13 0x000000000044d243 in ThreadPThread__RunThread =3D >>> (M3_DMxDjQ_me=3D3D3DError=3D3D >>>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>> #14 0x000000000044cf00 in ThreadPThread__ThreadBase =3D3D >>>>> (M3_AJWxb1_param=3D3D3DError accessing memory address = >0x8000ff5faf68: =3D >>> Bad =3D3D >>>>> address. >>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>> #15 0x0000000800ad54a4 in pthread_create () from /lib/libthr.so.3 >>>>>> #16 0x0000000000000000 in ?? () >>>>>> =3D3D20 >>>>>> Interestingly the same test seems to work on AMD64_LINUX. That is >>>>>> promising, at least. But of course, software testing never = >reveals =3D >>> =3D3D >>>>> the >>>>>> absence of bugs. >>>>>> =3D3D20 >>>>>> Mika >>>>>> =3D3D20 >>>>>> Peter McKinna writes: >>>>>>> --089e01183a1813188705007c3498 >>>>>>> Content-Type: text/plain; charset=3D3D3DUTF-8 >>>>>>> =3D3D20 >>>>>>> Oh, one other thing that seemed to help me in testing this stuff = >=3D3D >>>>> especially >>>>>>> things to do with m3core and libm3 which seem to get out of whack >>>>>>> sometimes, is to totally remove the target directory of m3core = >then =3D >>> =3D3D >>>>> cm3; >>>>>>> cm3 -ship Same with libm3. I'm not sure that clean actually = >removes =3D >>> =3D3D >>>>> the >>>>>>> targets and I think there are leftover files that stuff things up = >=3D3D=3D >>>=20 >>>>> since I >>>>>>> would get segv in FileRd for no obvious reason. >>>>>>> =3D3D20 >>>>>>> Peter >>>>>>> =3D3D20 >>>>>>> =3D3D20 >>>>>>> =3D3D20 >>>>>>> On Wed, Aug 13, 2014 at 3:33 PM, Peter McKinna =3D3D >>>>> >>>>>>> wrote: >>>>>>> =3D3D20 >>>>>>>> That is weird. The thread tester works fine with the old version = >=3D >>> of >>>>>>>> ThreadPThread.m3 on linux amd_64 except if you have the fork = >test =3D >>> in =3D3D >>>>> the >>>>>>>> mix of tests you see the pthread_mutex_destroy every now and =3D >>> again, =3D3D >>>>> the >>>>>>>> fork bug in fact. >>>>>>>> I was testing the pthread changes Tony has made over the past = >few =3D >>> =3D3D >>>>> days >>>>>>>> using the thread tester program until I stupidly rebuilt the =3D3D= > >>>>> compiler and >>>>>>>> was getting all sorts of hangs as it dragged in the new version = >of >>>>>>>> pthreads. So I rebuilt everything from a backup to get back = >where =3D >>> I =3D3D >>>>> was >>>>>>>> with a decent compiler, then reintroduced the latest changes to >>>>>>>> ThreadPThread.m3, which yesterday was just hanging in sigsuspend = >=3D >>> but =3D3D >>>>> today >>>>>>>> is giving me an assert failure at line 1387 in UnlockHeap. So = >its =3D >>> a =3D3D >>>>> bit >>>>>>>> unstable to say the least. Maybe there is something else wrong =3D= > >>> with =3D3D >>>>> freebsd. >>>>>>>> =3D3D20 >>>>>>>> Peter >>>>>>>> =3D3D20 >>>>>>>> =3D3D20 >>>>>>>> =3D3D20 >>>>>>>> On Wed, Aug 13, 2014 at 2:54 PM, wrote: >>>>>>>> =3D3D20 >>>>>>>>> =3D3D20 >>>>>>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not = >=3D3D >>>>> getting >>>>>>>>> things to work and now I'm really baffled because I think I =3D3D= > >>>>> understand >>>>>>>>> this code! >>>>>>>>> =3D3D20 >>>>>>>>> What I did was I threw away all my changes and reverted =3D3D >>>>> ThreadPThread.m3 >>>>>>>>> to 1.262 as you suggested. >>>>>>>>> =3D3D20 >>>>>>>>> Rebuilt the compiler with upgrade.sh >>>>>>>>> =3D3D20 >>>>>>>>> Then rebuilt the compiler again with itself. >>>>>>>>> =3D3D20 >>>>>>>>> Then I realcleaned the world and buildshipped it. (I was = >afraid >>>>>>>>> that parseparams, also imported by the thread tester, would =3D >>> pollute >>>>>>>>> it somehow.) >>>>>>>>> =3D3D20 >>>>>>>>> When I look at the code in 1.262 it looks quite = >straightforward. =3D >>> =3D3D >>>>> heapMu >>>>>>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) = >mutexes. >>>>>>>>> Condition >>>>>>>>> variables are mutexes too, but that's no big deal. >>>>>>>>> =3D3D20 >>>>>>>>> So, rebuild thread tester, run it: >>>>>>>>> =3D3D20 >>>>>>>>> new source -> compiling Main.m3 >>>>>>>>> -> linking threadtest >>>>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # >>>>>>>>> AMD64_FREEBSD/threadtest >>>>>>>>> Writing file...done >>>>>>>>> Creating read threads...done >>>>>>>>> Creating fork threads...done >>>>>>>>> Creating alloc threads...done >>>>>>>>> Creating lock threads...done >>>>>>>>> running...printing oldest/median age/newest >>>>>>>>> . >>>>>>>>> =3D3D20 >>>>>>>>> *** >>>>>>>>> *** runtime error: >>>>>>>>> *** Segmentation violation - possible attempt to dereference >>>>>>>>> NIL.........laziest thread is 1407901189/1407901189/9 (tests: =3D= > >>> read >>>>>>>>> 1407901189/1407901189/1407901189 fork =3D3D >>>>> 1407901189/1407901189/1407901189 >>>>>>>>> alloc 9/9/9 lock 1407901189/1407901189/9) >>>>>>>>> =3D3D20 >>>>>>>>> =3D3D20 >>>>>>>>> =3D3D20 >>>>>>>>> =3D3D20 >>>>>>>>> ^C >>>>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # = >=3D >>> gdb =3D3D >>>>> !$ >>>>>>>>> gdb AMD64_FREEBSD/threadtest >>>>>>>>> GNU gdb 6.1.1 [FreeBSD] >>>>>>>>> Copyright 2004 Free Software Foundation, Inc. >>>>>>>>> GDB is free software, covered by the GNU General Public = >License, =3D >>> =3D3D >>>>> and you >>>>>>>>> are >>>>>>>>> welcome to change it and/or distribute copies of it under = >certain >>>>>>>>> conditions. >>>>>>>>> Type "show copying" to see the conditions. >>>>>>>>> There is absolutely no warranty for GDB. Type "show warranty" = >=3D >>> for >>>>>>>>> details. >>>>>>>>> This GDB was configured as "amd64-marcel-freebsd"... >>>>>>>>> (gdb) run >>>>>>>>> Starting program: >>>>>>>>> =3D3D >>>>> =3D >>> = >/big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread/AMD64_FREEBSD/th= >=3D >>> =3D3D >>>>> readtest >>>>>>>>> [New LWP 100121] >>>>>>>>> Writing file...done >>>>>>>>> Creating read threads...done >>>>>>>>> Creating fork threads...done >>>>>>>>> Creating alloc threads...done >>>>>>>>> Creating lock threads...done >>>>>>>>> running...printing oldest/median age/newest >>>>>>>>> .[New Thread 801807000 (LWP 100343/threadtest)] >>>>>>>>> [New Thread 801807c00 (LWP 100667/threadtest)] >>>>>>>>> [New Thread 801808800 (LWP 100816/threadtest)] >>>>>>>>> [New Thread 801807400 (LWP 100349/threadtest)] >>>>>>>>> [New Thread 801808400 (LWP 100815/threadtest)] >>>>>>>>> [New Thread 801807800 (LWP 100352/threadtest)] >>>>>>>>> [New Thread 801808c00 (LWP 100817/threadtest)] >>>>>>>>> [New Thread 801809000 (LWP 100818/threadtest)] >>>>>>>>> [New Thread 801809800 (LWP 100820/threadtest)] >>>>>>>>> [New Thread 801808000 (LWP 100678/threadtest)] >>>>>>>>> [New Thread 801806400 (LWP 100121/threadtest)] >>>>>>>>> [New Thread 801806800 (LWP 100341/threadtest)] >>>>>>>>> [New Thread 801806c00 (LWP 100342/threadtest)] >>>>>>>>> .ERROR: pthread_mutex_lock:11 >>>>>>>>> =3D3D20 >>>>>>>>> Program received signal SIGABRT, Aborted. >>>>>>>>> [Switching to Thread 801809800 (LWP 100820/threadtest)] >>>>>>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>>>>> (gdb) where >>>>>>>>> #0 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7 >>>>>>>>> #1 0x0000000800e23ac9 in abort () from /lib/libc.so.7 >>>>>>>>> #2 0x000000000045101f in ThreadPThread__pthread_mutex_lock =3D3D= > >>>>> (mutex=3D3D3DError >>>>>>>>> accessing memory address 0x8000fe5f2d98: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 >>>>>>>>> #3 0x000000000044b370 in ThreadPThread__LockMutex =3D3D >>>>> (M3_AYIbX3_m=3D3D3DError >>>>>>>>> accessing memory address 0x8000fe5f2dc8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>>>>> #4 0x0000000000405b5d in Main__LApply (M3_AP7a1g_cl=3D3D3DError = >=3D3D >>>>> accessing >>>>>>>>> memory address 0x8000fe5f2df8: Bad address. >>>>>>>>> ) at ../src/Main.m3:319 >>>>>>>>> #5 0x000000000044d243 in ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3DError >>>>>>>>> accessing memory address 0x8000fe5f2eb8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>>> #6 0x000000000044cf00 in ThreadPThread__ThreadBase >>>>>>>>> (M3_AJWxb1_param=3D3D3DError accessing memory address =3D >>> 0x8000fe5f2f68: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>>> #7 0x0000000800ad54a4 in pthread_create () from = >/lib/libthr.so.3 >>>>>>>>> #8 0x0000000000000000 in ?? () >>>>>>>>> (gdb) set lang c >>>>>>>>> (gdb) thread apply all bt >>>>>>>>> ... not that interesting ... >>>>>>>>> =3D3D20 >>>>>>>>> Segfault is segfault---error 11 is EDEADLK (locking against =3D3D= > >>>>> myself?) >>>>>>>>> =3D3D20 >>>>>>>>> ????? the code is very straightforward, as I said. >>>>>>>>> =3D3D20 >>>>>>>>> I thought people had the thread tester working with pthreads? = >=3D3D >>>>> Which set >>>>>>>>> of files, then? Anyone on FreeBSD/amd64? >>>>>>>>> =3D3D20 >>>>>>>>> Could it be an issue with "volatile"? Not even sure where to =3D= > >>> look. >>>>>>>>> =3D3D20 >>>>>>>>> The code calling the lock is just this: >>>>>>>>> =3D3D20 >>>>>>>>> PROCEDURE GetChar (rd: T): CHAR >>>>>>>>> RAISES {EndOfFile, Failure, Alerted} =3D3D3D >>>>>>>>> BEGIN >>>>>>>>> LOCK rd DO >>>>>>>>> RETURN FastGetChar(rd); >>>>>>>>> END >>>>>>>>> END GetChar; >>>>>>>>> =3D3D20 >>>>>>>>> No mysteries there... >>>>>>>>> =3D3D20 >>>>>>>>> Ah is this the fork bug? Looks like the Init routine is called = >=3D >>> on =3D3D >>>>> a >>>>>>>>> lot of NIL mutexes around the fork. But the subprocesses = >aren't =3D >>> =3D3D >>>>> meant >>>>>>>>> to accesses the mutexes... humm >>>>>>>>> =3D3D20 >>>>>>>>> Hmm, and it's not entirely a fork issue. Even with "threadtest = >=3D3D=3D >>>=20 >>>>> -tests >>>>>>>>> STD,-fork,-forktoomuch" it misbehaves. Hangs.... >>>>>>>>> =3D3D20 >>>>>>>>> Looks like a deadlock this time. >>>>>>>>> =3D3D20 >>>>>>>>> Some stacks... >>>>>>>>> =3D3D20 >>>>>>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)): >>>>>>>>> #0 0x00000000004b4e2b in __vdso_gettimeofday () >>>>>>>>> #1 0x00000000004ab8d2 in gettimeofday () >>>>>>>>> #2 0x0000000000452e4b in TimePosix__Now () at >>>>>>>>> ../src/time/POSIX/TimePosixC.c:50 >>>>>>>>> #3 0x0000000000452d72 in Time__Now () at >>>>>>>>> ../src/time/POSIX/TimePosix.m3:14 >>>>>>>>> #4 0x00000000004029a3 in Main__LApply (M3_AP7a1g_cl=3D3D3DError = >=3D3D >>>>> accessing >>>>>>>>> memory address 0x8000fedf6df8: Bad address. >>>>>>>>> ) at ../src/Main.m3:327 >>>>>>>>> #5 0x0000000000449f93 in ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3DError >>>>>>>>> accessing memory address 0x8000fedf6eb8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>>> #6 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>>> (M3_AJWxb1_param=3D3D3DError accessing memory address =3D >>> 0x8000fedf6f68: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>>> #7 0x000000000047c7d4 in thread_start () >>>>>>>>> #8 0x0000000000000000 in ?? () >>>>>>>>> =3D3D20 >>>>>>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)): >>>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D3D= > >>>>> (mutex=3D3D3DError >>>>>>>>> accessing memory address 0x8000feff7d98: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>>>> #4 0x00000000004480c0 in ThreadPThread__LockMutex =3D3D >>>>> (M3_AYIbX3_m=3D3D3DError >>>>>>>>> accessing memory address 0x8000feff7dc8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119 >>>>>>>>> #5 0x00000000004028ad in Main__LApply (M3_AP7a1g_cl=3D3D3DError = >=3D3D >>>>> accessing >>>>>>>>> memory address 0x8000feff7df8: Bad address. >>>>>>>>> ) at ../src/Main.m3:319 >>>>>>>>> #6 0x0000000000449f93 in ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3DError >>>>>>>>> accessing memory address 0x8000feff7eb8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>>> #7 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>>> (M3_AJWxb1_param=3D3D3DError accessing memory address =3D >>> 0x8000feff7f68: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>>> #8 0x000000000047c7d4 in thread_start () >>>>>>>>> #9 0x0000000000000000 in ?? () >>>>>>>>> =3D3D20 >>>>>>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)): >>>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>>> #1 0x0000000000475759 in suspend_common () >>>>>>>>> #2 0x00000000004755c1 in pthread_suspend_np () >>>>>>>>> #3 0x000000000044df0c in ThreadPThread__SuspendThread =3D >>> (mt=3D3D3DError >>>>>>>>> accessing memory address 0x8000ffbfd6f8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33 >>>>>>>>> #4 0x000000000044bade in ThreadPThread__StopThread =3D3D >>>>> (M3_DMxDjQ_act=3D3D3DError >>>>>>>>> accessing memory address 0x8000ffbfd718: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909 >>>>>>>>> #5 0x000000000044bc81 in ThreadPThread__StopWorld () at >>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:948 >>>>>>>>> #6 0x000000000044b19e in RTThread__SuspendOthers () at >>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:713 >>>>>>>>> #7 0x00000000004330d6 in RTCollector__CollectSomeInStateZero = >() =3D >>> at >>>>>>>>> ../src/runtime/common/RTCollector.m3:749 >>>>>>>>> #8 0x0000000000433081 in RTCollector__CollectSome () at >>>>>>>>> ../src/runtime/common/RTCollector.m3:723 >>>>>>>>> #9 0x0000000000432d49 in RTHeapRep__CollectEnough () at >>>>>>>>> ../src/runtime/common/RTCollector.m3:657 >>>>>>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced >>>>>>>>> (M3_Cwb5VA_dataSize=3D3D3DError accessing memory address =3D3D >>>>> 0x8000ffbfd958: Bad >>>>>>>>> address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:367 >>>>>>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D3D >>>>> (M3_Eic7CK_def=3D3D3DError >>>>>>>>> accessing memory address 0x8000ffbfda18: Bad address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>>>>> (M3_AJWxb1_defn=3D3D3DError accessing memory address =3D >>> 0x8000ffbfda78: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3D3DError = >=3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ffbfdab8: Bad address. >>>>>>>>> ) at ../src/rw/Rd.m3:159 >>>>>>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar =3D >>> (M3_EkTcCb_rd=3D3D3DError=3D3D >>>>> =3D20 >>>>>>>>> accessing memory address 0x8000ffbfdb88: Bad address. >>>>>>>>> ) at ../src/rw/Rd.m3:187 >>>>>>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3D3DError = >=3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ffbfdbd8: Bad address. >>>>>>>>> ) at ../src/rw/Rd.m3:176 >>>>>>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3D3DError = >=3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ffbfdc58: Bad address. >>>>>>>>> ) at ../src/Main.m3:185 >>>>>>>>> =3D3D20 >>>>>>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3DError >>>>>>>>> accessing memory address 0x8000ffbfdeb8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>>> (M3_AJWxb1_param=3D3D3DError accessing memory address =3D >>> 0x8000ffbfdf68: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>>> #19 0x000000000047c7d4 in thread_start () >>>>>>>>> #20 0x0000000000000000 in ?? () >>>>>>>>> =3D3D20 >>>>>>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)): >>>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>>> #1 0x0000000000475f14 in __thr_umutex_lock () >>>>>>>>> #2 0x0000000000479404 in mutex_lock_common () >>>>>>>>> #3 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D3D= > >>>>> (mutex=3D3D3DError >>>>>>>>> accessing memory address 0x8000ffffc678: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>>>> #4 0x000000000044d039 in RTOS__LockHeap () at >>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>>>>> ---Type to continue, or q to quit--- >>>>>>>>> #5 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>>>>> (M3_Cwb5VA_dataSize=3D3D3DError accessing memory address =3D3D >>>>> 0x8000ffffc6e8: Bad >>>>>>>>> address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>>>>> #6 0x000000000042f15b in RTAllocator__GetTracedObj =3D3D >>>>> (M3_Eic7CK_def=3D3D3DError >>>>>>>>> accessing memory address 0x8000ffffc7a8: Bad address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:224 >>>>>>>>> #7 0x000000000042eb23 in RTHooks__AllocateTracedObj >>>>>>>>> (M3_AJWxb1_defn=3D3D3DError accessing memory address =3D >>> 0x8000ffffc7f8: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:122 >>>>>>>>> #8 0x000000000045fbe4 in TextCat__Flat = >(M3_Bd56fi_LText=3D3D3DError =3D >>> =3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ffffc858: Bad address. >>>>>>>>> ) at ../src/text/TextCat.m3:562 >>>>>>>>> #9 0x000000000045ed5d in TextCat__Balance =3D3D >>>>> (M3_Bd56fi_LText=3D3D3D0x800c490b0, >>>>>>>>> M3_BUgnwf_LInfo=3D3D3DError accessing memory address =3D >>> 0x8000ffffc8f8: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/text/TextCat.m3:488 >>>>>>>>> #10 0x000000000045d64f in RTHooks__Concat = >(M3_Bd56fi_t=3D3D3DError =3D >>> =3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ffffcbb8: Bad address. >>>>>>>>> ) at ../src/text/TextCat.m3:40 >>>>>>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3D3DError =3D= > >>> accessing =3D3D >>>>> memory >>>>>>>>> address 0x8000ffffcc38: Bad address. >>>>>>>>> ) at ../src/Main.m3:593 >>>>>>>>> #12 0x000000000043d55d in RTLinker__RunMainBody =3D >>> (M3_DjPxE3_m=3D3D3DError >>>>>>>>> accessing memory address 0x8000ffffcf88: Bad address. >>>>>>>>> ) at ../src/runtime/common/RTLinker.m3:408 >>>>>>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI = >(M3_DjPxE3_m=3D3D3DError=3D >>> =3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ffffd008: Bad address. >>>>>>>>> ) at ../src/runtime/common/RTLinker.m3:115 >>>>>>>>> #14 0x000000000043c97c in RTLinker__AddUnit = >(M3_DjPxE5_b=3D3D3DError =3D >>> =3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ffffd028: Bad address. >>>>>>>>> ) at ../src/runtime/common/RTLinker.m3:124 >>>>>>>>> #15 0x00000000004004a6 in main (argc=3D3D3DError accessing = >memory =3D3D=3D >>>=20 >>>>> address >>>>>>>>> 0x8000ffffd07c: Bad address. >>>>>>>>> ) at _m3main.c:22 >>>>>>>>> =3D3D20 >>>>>>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)): >>>>>>>>> #0 0x000000000047e53c in _umtx_op_err () >>>>>>>>> #1 0x0000000000477e8a in check_suspend () >>>>>>>>> #2 0x00000000004780a2 in sigcancel_handler () >>>>>>>>> #3 >>>>>>>>> #4 0x000000000047e53c in _umtx_op_err () >>>>>>>>> #5 0x0000000000475f14 in __thr_umutex_lock () >>>>>>>>> #6 0x0000000000479404 in mutex_lock_common () >>>>>>>>> #7 0x000000000044dd15 in ThreadPThread__pthread_mutex_lock =3D3D= > >>>>> (mutex=3D3D3DError >>>>>>>>> accessing memory address 0x8000ff5fac18: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >>>>>>>>> #8 0x000000000044d039 in RTOS__LockHeap () at >>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1337 >>>>>>>>> #9 0x000000000042ff79 in RTAllocator__AllocTraced >>>>>>>>> (M3_Cwb5VA_dataSize=3D3D3DError accessing memory address =3D3D >>>>> 0x8000ff5fac88: Bad >>>>>>>>> address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365 >>>>>>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D3D >>>>> (M3_Eic7CK_def=3D3D3DError >>>>>>>>> accessing memory address 0x8000ff5fad48: Bad address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296 >>>>>>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray >>>>>>>>> (M3_AJWxb1_defn=3D3D3DError accessing memory address =3D >>> 0x8000ff5fada8: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143 >>>>>>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3D3DError = >=3D3D >>>>> accessing >>>>>>>>> memory address 0x8000ff5fade8: Bad address. >>>>>>>>> ) at ../src/Main.m3:283 >>>>>>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3DError >>>>>>>>> accessing memory address 0x8000ff5faeb8: Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449 >>>>>>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase >>>>>>>>> (M3_AJWxb1_param=3D3D3DError accessing memory address =3D >>> 0x8000ff5faf68: =3D3D >>>>> Bad address. >>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422 >>>>>>>>> #15 0x000000000047c7d4 in thread_start () >>>>>>>>> #16 0x0000000000000000 in ?? () >>>>>>>>> =3D3D20 >>>>>>>>> (others are similar) >>>>>>>>> =3D3D20 >>>>>>>>> Hmm looks like a FreeBSD issue now. It's here... >>>>>>>>> =3D3D20 >>>>>>>>> int >>>>>>>>> __cdecl >>>>>>>>> ThreadPThread__SuspendThread (m3_pthread_t mt) >>>>>>>>> { >>>>>>>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), >>>>>>>>> "pthread_suspend_np"); >>>>>>>>> return 1; >>>>>>>>> } >>>>>>>>> =3D3D20 >>>>>>>>> Now this suspend can wait: >>>>>>>>> =3D3D20 >>>>>>>>> static int >>>>>>>>> suspend_common(struct pthread *curthread, struct pthread = >*thread, >>>>>>>>> int waitok) >>>>>>>>> { >>>>>>>>> uint32_t tmp; >>>>>>>>> =3D3D20 >>>>>>>>> while (thread->state !=3D3D3D PS_DEAD && >>>>>>>>> !(thread->flags & THR_FLAGS_SUSPENDED)) { >>>>>>>>> thread->flags |=3D3D3D THR_FLAGS_NEED_SUSPEND; >>>>>>>>> /* Thread is in creation. */ >>>>>>>>> if (thread->tid =3D3D3D=3D3D3D TID_TERMINATED) >>>>>>>>> return (1); >>>>>>>>> tmp =3D3D3D thread->cycle; >>>>>>>>> _thr_send_sig(thread, SIGCANCEL); >>>>>>>>> THR_THREAD_UNLOCK(curthread, thread); >>>>>>>>> if (waitok) { >>>>>>>>> _thr_umtx_wait_uint(&thread->cycle, tmp, = >=3D3D >>>>> NULL, >>>>>>>>> 0); <=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D= >3D3D=3D3D3D >>>>>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>>>>> } else { >>>>>>>>> THR_THREAD_LOCK(curthread, thread); >>>>>>>>> return (0); >>>>>>>>> } >>>>>>>>> } >>>>>>>>> =3D3D20 >>>>>>>>> return (1); >>>>>>>>> } >>>>>>>>> =3D3D20 >>>>>>>>> ... but what it can wait for I am not clear on. >>>>>>>>> =3D3D20 >>>>>>>>> Do things work better on Linux? >>>>>>>>> =3D3D20 >>>>>>>>> What is the status of the fork bug? Can it be worked around by = >=3D3D=3D >>>=20 >>>>> only >>>>>>>>> forking via Process.Create with no mutexes held (outside of all = >=3D3D=3D >>>=20 >>>>> LOCK >>>>>>>>> blocks)? >>>>>>>>> =3D3D20 >>>>>>>>> Mika >>>>>>>>> =3D3D20 >>>>>>>>> =3D3D20 >>>>>>>>> =3D3D20 >>>>>>>>> Peter McKinna writes: >>>>>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>>>>> Content-Type: text/plain; charset=3D3D3DUTF-8 >>>>>>>>>> =3D3D20 >>>>>>>>>> Mika >>>>>>>>>> =3D3D20 >>>>>>>>>> I think you need to back out Tony's changes to fix the fork = >bug, =3D >>> =3D3D >>>>> at >>>>>>>>> least >>>>>>>>>> for now. Need to reload from cvs version 1.262 for =3D3D >>>>> ThreadPThread.m3 If >>>>>>>>>> you're using git you're on your own. >>>>>>>>>> Do a cvs log ThreadPThread.m3 for an explanation for some of = >the =3D >>> =3D3D >>>>> design >>>>>>>>>> principles. >>>>>>>>>> Also if you use gdb then you need to set lanc c before =3D >>> backtraces =3D3D >>>>> so at >>>>>>>>>> least you can see address names and values even if they are = >=3D3D >>>>> contorted you >>>>>>>>>> can extract the M3 name in the parm lists. Also in gdb thread = >=3D3D >>>>> apply all >>>>>>>>> bt >>>>>>>>>> gives all thread backtraces which can be handy to see whose = >got =3D >>> =3D3D >>>>> the locks >>>>>>>>>> held. >>>>>>>>>> =3D3D20 >>>>>>>>>> Regards Peter >>>>>>>>>> =3D3D20 >>>>>>>>>> =3D3D20 >>>>>>>>>> =3D3D20 >>>>>>>>>> On Wed, Aug 13, 2014 at 12:14 PM, =3D >>> wrote: >>>>>>>>>> =3D3D20 >>>>>>>>>>> =3D3D20 >>>>>>>>>>> Question... is there something odd about my pthreads? Are = >=3D3D >>>>> pthreads >>>>>>>>>>> normally reentrant? I didn't think so. >>>>>>>>>>> =3D3D20 >>>>>>>>>>> My compiler is much happier with the following changes I =3D >>> already >>>>>>>>> outlined: >>>>>>>>>>> =3D3D20 >>>>>>>>>>> 1. a dirty, disgusting hack to keep from locking against = >myself =3D >>> =3D3D >>>>> going >>>>>>>>> from >>>>>>>>>>> XWait with self.mutex locked to m.release(). >>>>>>>>>>> =3D3D20 >>>>>>>>>>> 2. the change to LockHeap I described in previous email >>>>>>>>>>> =3D3D20 >>>>>>>>>>> But now... >>>>>>>>>>> =3D3D20 >>>>>>>>>>> (gdb) cont >>>>>>>>>>> Continuing. >>>>>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>>>>> ERROR: pthread_mutex_lock:11 >>>>>>>>>>> =3D3D20 >>>>>>>>>>> Program received signal SIGABRT, Aborted. >>>>>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>>>>> (gdb) where >>>>>>>>>>> #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 >>>>>>>>>>> #1 0x000000080113dac9 in abort () from /lib/libc.so.7 >>>>>>>>>>> #2 0x000000000071e37a in ThreadPThread__pthread_mutex_lock >>>>>>>>> (mutex=3D3D3DError >>>>>>>>>>> accessing memory address 0x8000ffffb508: Bad address. >>>>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543 >>>>>>>>>>> #3 0x000000000071d48d in RTOS__LockHeap () at >>>>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1377 >>>>>>>>>>> #4 0x0000000000706b9d in RTHooks__CheckLoadTracedRef >>>>>>>>> (M3_Af40ku_ref=3D3D3DError >>>>>>>>>>> accessing memory address 0x8000ffffb568: Bad address. >>>>>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234 >>>>>>>>>>> #5 0x000000000071d284 in ThreadPThread__AtForkParent () at >>>>>>>>>>> ../src/thread/PTHREAD/ThreadPThread.m3:1348 >>>>>>>>>>> #6 0x0000000800df8733 in fork () from /lib/libthr.so.3 >>>>>>>>>>> #7 0x000000000070dd8b in RTProcess__Fork () at >>>>>>>>>>> ../src/runtime/common/RTProcessC.c:152 >>>>>>>>>>> #8 0x00000000006c52f2 in ProcessPosixCommon__Create_ForkExec >>>>>>>>>>> (M3_Bd56fi_cmd=3D3D3DError accessing memory address =3D >>> 0x8000ffffb6f8: =3D3D >>>>> Bad >>>>>>>>> address. >>>>>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75 >>>>>>>>>>> #9 0x00000000006c6c6c in Process__Create =3D >>> (M3_Bd56fi_cmd=3D3D3DError >>>>>>>>> accessing >>>>>>>>>>> memory address 0x8000ffffb7f8: Bad address. >>>>>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21 >>>>>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>>>>> (M3_D6rRrg_ep=3D3D3DError >>>>>>>>>>> accessing memory address 0x8000ffffb838: Bad address. >>>>>>>>>>> ) at ../src/QMachine.m3:1666 >>>>>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand =3D3D >>>>> (M3_An02H2_t=3D3D3DError >>>>>>>>>>> accessing memory address 0x8000ffffb9f8: Bad address. >>>>>>>>>>> ) at ../src/QMachine.m3:1605 >>>>>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec =3D >>> (M3_An02H2_t=3D3D3DError >>>>>>>>> accessing >>>>>>>>>>> memory address 0x8000ffffbee8: Bad address. >>>>>>>>>>> ) at ../src/QMachine.m3:1476 >>>>>>>>>>> =3D3D20 >>>>>>>>>>> What am I doing wrong here? >>>>>>>>>>> =3D3D20 >>>>>>>>>>> The error doesn't look unreasonable! Looking more closely at = >=3D >>> the =3D3D >>>>> code: >>>>>>>>>>> =3D3D20 >>>>>>>>>>> First, AtForkPrepare has been called: >>>>>>>>>>> =3D3D20 >>>>>>>>>>> PROCEDURE AtForkPrepare() =3D3D3D >>>>>>>>>>> VAR me :=3D3D3D GetActivation(); >>>>>>>>>>> act: Activation; >>>>>>>>>>> BEGIN >>>>>>>>>>> PThreadLockMutex(slotsMu, ThisLine()); >>>>>>>>>>> PThreadLockMutex(perfMu, ThisLine()); >>>>>>>>>>> PThreadLockMutex(initMu, ThisLine()); (* InitMutex =3D3D3D> >>>>>>>>>>> RegisterFinalCleanup =3D3D3D> LockHeap *) >>>>>>>>>>> PThreadLockMutex(heapMu, ThisLine()); >>>>>>>>>>> PThreadLockMutex(activeMu, ThisLine()); (* LockHeap =3D3D3D> >>>>>>>>> SuspendOthers >>>>>>>>>>> =3D3D3D> activeMu *) >>>>>>>>>>> (* Walk activations and lock all threads. >>>>>>>>>>> * NOTE: We have initMu, activeMu, so slots won't change, >>>>>>>>> conditions >>>>>>>>>>> and >>>>>>>>>>> * mutexes won't be initialized on-demand. >>>>>>>>>>> *) >>>>>>>>>>> act :=3D3D3D me; >>>>>>>>>>> REPEAT >>>>>>>>>>> PThreadLockMutex(act.mutex, ThisLine()); >>>>>>>>>>> act :=3D3D3D act.next; >>>>>>>>>>> UNTIL act =3D3D3D me; >>>>>>>>>>> END AtForkPrepare; >>>>>>>>>>> =3D3D20 >>>>>>>>>>> a postcondition of this routine is that heapMu is locked. >>>>>>>>>>> =3D3D20 >>>>>>>>>>> now we get into AtForkParent: >>>>>>>>>>> =3D3D20 >>>>>>>>>>> PROCEDURE AtForkParent() =3D3D3D >>>>>>>>>>> VAR me :=3D3D3D GetActivation(); >>>>>>>>>>> act: Activation; >>>>>>>>>>> cond: Condition; >>>>>>>>>>> BEGIN >>>>>>>>>>> (* Walk activations and unlock all threads, conditions. *) >>>>>>>>>>> act :=3D3D3D me; >>>>>>>>>>> REPEAT >>>>>>>>>>> cond :=3D3D3D slots[act.slot].join; >>>>>>>>>>> IF cond # NIL THEN PThreadUnlockMutex(cond.mutex, =3D3D >>>>> ThisLine()) >>>>>>>>> END; >>>>>>>>>>> PThreadUnlockMutex(act.mutex, ThisLine()); >>>>>>>>>>> act :=3D3D3D act.next; >>>>>>>>>>> UNTIL act =3D3D3D me; >>>>>>>>>>> PThreadUnlockMutex(activeMu, ThisLine()); >>>>>>>>>>> PThreadUnlockMutex(heapMu, ThisLine()); >>>>>>>>>>> PThreadUnlockMutex(initMu, ThisLine()); >>>>>>>>>>> PThreadUnlockMutex(perfMu, ThisLine()); >>>>>>>>>>> PThreadUnlockMutex(slotsMu, ThisLine()); >>>>>>>>>>> END AtForkParent; >>>>>>>>>>> =3D3D20 >>>>>>>>>>> We can see by inspecting the code that a necessary = >precondition =3D >>> =3D3D >>>>> for >>>>>>>>>>> this routine is that heapMu is locked! (Since it's going to = >=3D3D >>>>> unlock it, >>>>>>>>>>> it had BETTER be locked on entry.) >>>>>>>>>>> =3D3D20 >>>>>>>>>>> But the cond :=3D3D3D ... causes a RTHooks.CheckLoadTracedRef >>>>>>>>>>> =3D3D20 >>>>>>>>>>> which causes an RTOS.LockHeap >>>>>>>>>>> =3D3D20 >>>>>>>>>>> the code of which we just saw: >>>>>>>>>>> =3D3D20 >>>>>>>>>>> PROCEDURE LockHeap () =3D3D3D >>>>>>>>>>> VAR self :=3D3D3D pthread_self(); >>>>>>>>>>> BEGIN >>>>>>>>>>> WITH r =3D3D3D pthread_mutex_lock(heapMu,ThisLine()) DO =3D >>> <*ASSERT =3D3D >>>>> r=3D3D3D0*> >>>>>>>>> END; >>>>>>>>>>> ... >>>>>>>>>>> =3D3D20 >>>>>>>>>>> we try to lock heapMu. kaboom! No surprise there, really? >>>>>>>>>>> =3D3D20 >>>>>>>>>>> Am I going about this totally the wrong way? Other people = >are =3D >>> =3D3D >>>>> running >>>>>>>>>>> Modula-3 >>>>>>>>>>> with pthreads, right? Right?? Somewhere out there in =3D3D >>>>> m3devel-land? >>>>>>>>>>> =3D3D20 >>>>>>>>>>> Mika >>>>>>>>>>> =3D3D20 >>>>>>>>>>> =3D3D20 >>>>>>>>>> =3D3D20 >>>>>>>>>> --001a11c2ced4471a2e050079db82 >>>>>>>>>> Content-Type: text/html; charset=3D3D3DUTF-8 >>>>>>>>>> Content-Transfer-Encoding: quoted-printable >>>>>>>>>> =3D3D20 >>>>>>>>>>
Mika

=3D3D3DC2=3D3D3DA= >0 I =3D >>> think you =3D3D >>>>> need to back >>>>>>>>> ou=3D3D3D >>>>>>>>>> t Tony's changes to fix the fork bug, at least for now. = >Need =3D >>> =3D3D >>>>> to >>>>>>>>> reload =3D3D3D >>>>>>>>>> from cvs version 1.262 for ThreadPThread.m3 If you're = >using =3D >>> =3D3D >>>>> git >>>>>>>>> you'=3D3D3D >>>>>>>>>> ;re on your own.
>>>>>>>>>> =3D3D20 >>>>>>>>>>
=3D3D3DC2=3D3D3DA0 Do a cvs log ThreadPThread.m3 for an =3D= > >>> explanation =3D3D >>>>> for some of >>>>>>>>> th=3D3D3D >>>>>>>>>> e design principles.=3D3D3DC2=3D3D3DA0
=3D3D3DC2=3D3D3= >DA0 Also =3D >>> if you =3D3D >>>>> use gdb then you >>>>>>>>> ne=3D3D3D >>>>>>>>>> ed to set lanc c before backtraces so at least you can see =3D >>> address =3D3D >>>>> names >>>>>>>>> an=3D3D3D >>>>>>>>>> d values even if they are contorted you can extract the M3 = >name =3D >>> in =3D3D >>>>> the >>>>>>>>> parm=3D3D3D >>>>>>>>>> lists. Also in gdb thread apply all bt gives all thread =3D >>> backtraces >>>>>>>>> which c=3D3D3D >>>>>>>>>> an be handy to see whose got the locks held.
>>>>>>>>>> =3D3D20 >>>>>>>>>>

Regards Peter

>>>>>>>> class=3D3D3D3D"gmail_e=3D3D3D >>>>>>>>>> xtra">

On Wed, Aug 13, = >=3D >>> 2014 at =3D3D >>>>> 12:14 >>>>>>>>> PM, =3D3D3D >>>>>>>>>> <>> href=3D3D3D3D"mailto:mika at async.caltech.edu" >>>>>>>>> target=3D3D3D3D"=3D3D3D >>>>>>>>>> _blank">mika at async.caltech.edu> wrote:
>>>>>>>>>> =3D3D20 >>>>>>>>>>
0 0 >>>>>>>>> .8ex;border-left:1p=3D3D3D >>>>>>>>>> x #ccc solid;padding-left:1ex">
>>>>>>>>>> Question... is there something odd about my pthreads? =3D >>> =3D3D3DC2=3D3D3DA0Are =3D3D >>>>> pthreads >>>>>>>>> no=3D3D3D >>>>>>>>>> rmally reentrant? =3D3D3DC2=3D3D3DA0I didn't think so.
>>>>>>>>>>
>>>>>>>>>> My compiler is much happier with the following changes I = >already >>>>>>>>> outlined:<=3D3D3D >>>>>>>>>> br> >>>>>>>>>>
>>>>>>>>>> 1. a dirty, disgusting hack to keep from locking against = >myself =3D >>> =3D3D >>>>> going >>>>>>>>> from =3D3D3D >>>>>>>>>> XWait with self.mutex locked to m.release().
>>>>>>>>>>
>>>>>>>>>> 2. the change to LockHeap I described in previous email
>>>>>>>>>>
>>>>>>>>>> But now...
>>>>>>>>>>
>>>>>>>>>> (gdb) cont
>>>>>>>>>> Continuing.
>>>>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>>>>> ERROR: pthread_mutex_lock:11
>>>>>>>>>>
>>>>>>>>>> Program received signal SIGABRT, Aborted.
>>>>>>>>>> 0x000000080107626a in thr_kill () from /lib/libc.so.7
>>>>>>>>>> (gdb) where
>>>>>>>>>> #0 =3D3D3DC2=3D3D3DA00x000000080107626a in thr_kill () from = >=3D3D >>>>> /lib/libc.so.7
>>>>>>>>>> #1 =3D3D3DC2=3D3D3DA00x000000080113dac9 in abort () from =3D3D >>>>> /lib/libc.so.7
>>>>>>>>>> #2 =3D3D3DC2=3D3D3DA00x000000000071e37a in =3D3D >>>>> ThreadPThread__pthread_mutex_lock >>>>>>>>> (mutex=3D3D3D3DE=3D3D3D >>>>>>>>>> rror accessing memory address 0x8000ffffb508: Bad address.
>>>>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>>>>>>> #3 =3D3D3DC2=3D3D3DA00x000000000071d48d in RTOS__LockHeap () = >at >>>>>>>>> ../src/thread/PTHREAD/T=3D3D3D >>>>>>>>>> hreadPThread.m3:1377
>>>>>>>>>> #4 =3D3D3DC2=3D3D3DA00x0000000000706b9d in =3D >>> RTHooks__CheckLoadTracedRef >>>>>>>>> (M3_Af40ku_ref=3D3D3D >>>>>>>>>> =3D3D3D3DError accessing memory address 0x8000ffffb568: Bad = >=3D3D >>>>> address.
>>>>>>>>>> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>>>>>>> #5 =3D3D3DC2=3D3D3DA00x000000000071d284 in =3D >>> ThreadPThread__AtForkParent () =3D3D >>>>> at >>>>>>>>> ../src/thr=3D3D3D >>>>>>>>>> ead/PTHREAD/ThreadPThread.m3:1348
>>>>>>>>>> #6 =3D3D3DC2=3D3D3DA00x0000000800df8733 in fork () from =3D3D >>>>> /lib/libthr.so.3
>>>>>>>>>> #7 =3D3D3DC2=3D3D3DA00x000000000070dd8b in RTProcess__Fork () = >at >>>>>>>>> ../src/runtime/common/=3D3D3D >>>>>>>>>> RTProcessC.c:152
>>>>>>>>>> #8 =3D3D3DC2=3D3D3DA00x00000000006c52f2 in =3D3D >>>>> ProcessPosixCommon__Create_ForkExec >>>>>>>>> (M3_Bd56=3D3D3D >>>>>>>>>> fi_cmd=3D3D3D3DError accessing memory address 0x8000ffffb6f8: = >Bad =3D >>> =3D3D >>>>> address.
>>>>>>>>>> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>>>>>>> #9 =3D3D3DC2=3D3D3DA00x00000000006c6c6c in Process__Create =3D3D= > >>>>> (M3_Bd56fi_cmd=3D3D3D3DError >>>>>>>>> acces=3D3D3D >>>>>>>>>> sing memory address 0x8000ffffb7f8: Bad address.
>>>>>>>>>> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>>>>>>> #10 0x00000000004d6826 in QMachine__FulfilExecPromise >>>>>>>>> (M3_D6rRrg_ep=3D3D3D3DError=3D3D3D >>>>>>>>>> accessing memory address 0x8000ffffb838: Bad address.
>>>>>>>>>> ) at ../src/QMachine.m3:1666
>>>>>>>>>> #11 0x00000000004d6220 in QMachine__ExecCommand =3D3D >>>>> (M3_An02H2_t=3D3D3D3DError >>>>>>>>> access=3D3D3D >>>>>>>>>> ing memory address 0x8000ffffb9f8: Bad address.
>>>>>>>>>> ) at ../src/QMachine.m3:1605
>>>>>>>>>> #12 0x00000000004d537e in QMachine__DoTryExec =3D >>> (M3_An02H2_t=3D3D3D3DError=3D3D >>>>> =3D20 >>>>>>>>> accessin=3D3D3D >>>>>>>>>> g memory address 0x8000ffffbee8: Bad address.
>>>>>>>>>> ) at ../src/QMachine.m3:1476
>>>>>>>>>>
>>>>>>>>>> What am I doing wrong here?
>>>>>>>>>>
>>>>>>>>>> The error doesn't look unreasonable! =3D3D3DC2=3D3D3DA0Looki= >ng =3D >>> more =3D3D >>>>> closely at >>>>>>>>> the =3D3D3D >>>>>>>>>> code:
>>>>>>>>>>
>>>>>>>>>> First, AtForkPrepare has been called:
>>>>>>>>>>
>>>>>>>>>> PROCEDURE AtForkPrepare() =3D3D3D3D
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D GetActivation();
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act: = >=3D >>> Activation;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 BEGIN
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(slotsMu, =3D >>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(perfMu, = >=3D >>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(initMu, = >=3D >>> ThisLine()); (* =3D3D >>>>> InitMutex =3D3D3D3D> >>>>>>>>> Re=3D3D3D >>>>>>>>>> gisterFinalCleanup =3D3D3D3D> LockHeap *)
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 PThreadLockMutex(heapMu, = >=3D >>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(activeMu, =3D >>> ThisLine()); (* =3D3D >>>>> LockHeap >>>>>>>>> =3D3D3D3D> S=3D3D3D >>>>>>>>>> uspendOthers =3D3D3D3D> activeMu *)
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk activations and = >lock all =3D3D=3D >>>=20 >>>>> threads.
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* = >NOTE: We have =3D >>> initMu, activeMu, =3D3D >>>>> so slots won't >>>>>>>>> ch=3D3D3D >>>>>>>>>> ange, conditions and
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* = >mutexes won't =3D >>> be initialized =3D3D >>>>> on-demand.
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0*)
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D me;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D >>> PThreadLockMutex(act.mutex, =3D3D >>>>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act = >:=3D3D3D3D =3D >>> act.next;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >me;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 END AtForkPrepare;
>>>>>>>>>>
>>>>>>>>>> a postcondition of this routine is that heapMu is locked.
>>>>>>>>>>
>>>>>>>>>> now we get into AtForkParent:
>>>>>>>>>>
>>>>>>>>>> PROCEDURE AtForkParent() =3D3D3D3D
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D GetActivation();
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act: = >=3D >>> Activation;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 cond: = >=3D >>> Condition;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 BEGIN
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk activations and = >unlock all =3D >>> threads, =3D3D >>>>> conditions. >>>>>>>>> *)>>>>>>>>>> =3D3D20 >>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D me;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 cond = >:=3D3D3D3D =3D3D >>>>> slots[act.slot].join;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 IF = >cond # NIL THEN =3D >>> =3D3D >>>>> PThreadUnlockMutex(cond.mutex, >>>>>>>>> This=3D3D3D >>>>>>>>>> Line()) END;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D >>> PThreadUnlockMutex(act.mutex, =3D3D >>>>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act = >:=3D3D3D3D =3D >>> act.next;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >me;
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(activeMu, =3D3D >>>>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(heapMu, =3D >>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(initMu, =3D >>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(perfMu, =3D >>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(slotsMu, =3D >>> ThisLine());
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 END AtForkParent;
>>>>>>>>>>
>>>>>>>>>> We can see by inspecting the code that a necessary = >precondition =3D >>> =3D3D >>>>> for
>>>>>>>>>> this routine is that heapMu is locked! =3D3D3DC2=3D3D3DA0(Since = >=3D >>> it's =3D3D >>>>> going to >>>>>>>>> unloc=3D3D3D >>>>>>>>>> k it,
>>>>>>>>>> it had BETTER be locked on entry.)
>>>>>>>>>>
>>>>>>>>>> But the cond :=3D3D3D3D ... causes a =3D >>> RTHooks.CheckLoadTracedRef
>>>>>>>>>>
>>>>>>>>>> which causes an RTOS.LockHeap
>>>>>>>>>>
>>>>>>>>>> the code of which we just saw:
>>>>>>>>>>
>>>>>>>>>> PROCEDURE LockHeap () =3D3D3D3D
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 VAR self :=3D3D3D3D pthread_self();
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 BEGIN
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 WITH r =3D3D3D3D =3D3D >>>>> pthread_mutex_lock(heapMu,ThisLine()) DO >>>>>>>>> <*ASSE=3D3D3D >>>>>>>>>> RT r=3D3D3D3D0*> END;
>>>>>>>>>> ...
>>>>>>>>>>
>>>>>>>>>> we try to lock heapMu. =3D3D3DC2=3D3D3DA0kaboom! = >=3D3D3DC2=3D3D3DA0No =3D >>> surprise =3D3D >>>>> there, really?
>>>>>>>>>>
>>>>>>>>>> Am I going about this totally the wrong way? = >=3D3D3DC2=3D3D3DA0Other =3D >>> =3D3D >>>>> people are >>>>>>>>> running=3D3D3D >>>>>>>>>> Modula-3
>>>>>>>>>> with pthreads, right? =3D3D3DC2=3D3D3DA0Right?? = >=3D3D3DC2=3D3D3DA0Somewher=3D >>> e out =3D3D >>>>> there in >>>>>>>>> m3devel-la=3D3D3D >>>>>>>>>> nd?
>>>>>>>>>>
>>>>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0Mika
= > >>>>>>>>>>
>>>>>>>>>>

>>>>>>>>>> =3D3D20 >>>>>>>>>> --001a11c2ced4471a2e050079db82-- >>>>>>>>> =3D3D20 >>>>>>>> =3D3D20 >>>>>>>> =3D3D20 >>>>>>> =3D3D20 >>>>>>> --089e01183a1813188705007c3498 >>>>>>> Content-Type: text/html; charset=3D3D3DUTF-8 >>>>>>> Content-Transfer-Encoding: quoted-printable >>>>>>> =3D3D20 >>>>>>>
Oh, one other thing that seemed to help me = >in =3D >>> =3D3D >>>>> testing this=3D3D3D >>>>>>> stuff especially things to do with m3core and libm3 which seem to = >=3D >>> get =3D3D >>>>> out =3D3D3D >>>>>>> of whack sometimes, is to totally remove the target directory of = >=3D3D >>>>> m3core the=3D3D3D >>>>>>> n cm3; cm3 -ship Same with libm3. I'm not sure that clean =3D3D= > >>>>> actually remo=3D3D3D >>>>>>> ves the targets and I think there are leftover files that stuff = >=3D3D >>>>> things up s=3D3D3D >>>>>>> ince I would get segv in FileRd for no obvious reason.
>>>>>>>
Peter

>>>> class=3D3D3D3D"gmail_extra"><=3D3D3D >>>>>>> br>
On Wed, Aug 13, 2014 at = >3:33 =3D >>> PM, =3D3D >>>>> Peter Mc=3D3D3D >>>>>>> Kinna <>>>> href=3D3D3D3D"mailto:peter.mckinna at gmail.com" targ=3D3D3D >>>>>>> et=3D3D3D3D"_blank">peter.mckinna at gmail.com> = >wrote:
>>>>>>>
0 =3D3D >>>>> .8ex;border-left:1p=3D3D3D >>>>>>> x #ccc solid;padding-left:1ex">
That is = >weird. =3D >>> The =3D3D >>>>> thread t=3D3D3D >>>>>>> ester works fine with the old version of ThreadPThread.m3 on = >linux =3D >>> =3D3D >>>>> amd_64 e=3D3D3D >>>>>>> xcept if you have the fork test in the mix of tests you see the = >=3D3D >>>>> pthread_mut=3D3D3D >>>>>>> ex_destroy every now and again, the fork bug in =3D >>> fact.=3D3D3DC2=3D3D3DA0
>>>>>>> =3D3D20 >>>>>>> I was testing the pthread changes Tony has made over the past few = >=3D3D=3D >>>=20 >>>>> days usin=3D3D3D >>>>>>> g the thread tester program until I stupidly rebuilt the compiler = >=3D >>> and =3D3D >>>>> was g=3D3D3D >>>>>>> etting all sorts of hangs as it dragged in the new version of =3D3D= > >>>>> pthreads. So =3D3D3D >>>>>>> I rebuilt everything from a backup to get back where I was with a = >=3D3D=3D >>>=20 >>>>> decent co=3D3D3D >>>>>>> mpiler, then reintroduced the latest changes to ThreadPThread.m3, = >=3D3D=3D >>>=20 >>>>> which yes=3D3D3D >>>>>>> terday was just hanging in sigsuspend but today is giving me an = >=3D3D >>>>> assert fail=3D3D3D >>>>>>> ure at line 1387 in UnlockHeap. So its a bit unstable to say the = >=3D3D >>>>> least. May=3D3D3D >>>>>>> be there is something else wrong with freebsd.
>>>>>>> >>>>>>> =3D3D >>>>> =3D >>> = >

Peter

=3D3D=3D >>>=20 >>>>> clas=3D3D3D >>>>>>> s=3D3D3D3D"HOEnZb">
>>>> class=3D3D3D3D"gmail_extra">

>>>>>> s=3D3D3D3D"gmail_quote">On Wed, Aug 13, 2014 at 2:54 PM, =3D3D >>>>> dir=3D3D3D3D"ltr"><<=3D3D3D >>>>>>> a href=3D3D3D3D"mailto:mika at async.caltech.edu" =3D3D >>>>> target=3D3D3D3D"_blank">mika at async.calte=3D3D3D >>>>>>> ch.edu> wrote:
>>>>>>> =3D3D20 >>>>>>>
0 =3D3D >>>>> .8ex;border-left:1p=3D3D3D >>>>>>> x #ccc solid;padding-left:1ex">
>>>>>>> Yeah OK 1.262 makes a lot more sense to me but I'm still not = >=3D3D >>>>> getting>>>>>>> =3D3D20 >>>>>>> things to work and now I'm really baffled because I think I = >=3D3D >>>>> understand<=3D3D3D >>>>>>> br> >>>>>>> this code!
>>>>>>>
>>>>>>> What I did was I threw away all my changes and reverted =3D3D >>>>> ThreadPThread.m3>>>>>>> =3D3D20 >>>>>>> to 1.262 as you suggested.
>>>>>>>
>>>>>>> Rebuilt the compiler with upgrade.sh
>>>>>>>
>>>>>>> Then rebuilt the compiler again with itself.
>>>>>>>
>>>>>>> Then I realcleaned the world and buildshipped it. = >=3D3D3DC2=3D3D3DA0(I =3D >>> was =3D3D >>>>> afraid
>>>>>>> that parseparams, also imported by the thread tester, would =3D3D >>>>> pollute
>>>>>>> it somehow.)
>>>>>>>
>>>>>>> When I look at the code in 1.262 it looks quite straightforward. = >=3D3D >>>>> =3D3D3DC2=3D3D3DA0heap=3D3D3D >>>>>>> Mu
>>>>>>> is just a mutex, (Modula-3) mutexes are just (pthreads) mutexes. = >=3D3D >>>>> =3D3D3DC2=3D3D3DA0Cond=3D3D3D >>>>>>> ition
>>>>>>> variables are mutexes too, but that's no big deal.
>>>>>>>
>>>>>>> So, rebuild thread tester, run it:
>>>>>>>
>>>>>>> new source -> compiling Main.m3
>>>>>>> =3D3D3DC2=3D3D3DA0-> linking threadtest
>>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # = >=3D3D >>>>> AMD64_FREEB=3D3D3D >>>>>>> SD/threadtest
>>>>>>> Writing file...done
>>>>>>> Creating read threads...done
>>>>>>> Creating fork threads...done
>>>>>>> Creating alloc threads...done
>>>>>>> Creating lock threads...done
>>>>>>> running...printing oldest/median age/newest
>>>>>>> .
>>>>>>>
>>>>>>> ***
>>>>>>> *** runtime error:
>>>>>>> *** =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0Segmentation violation - = >possible =3D >>> attempt to =3D3D >>>>> dereference N=3D3D3D >>>>>>> IL.........laziest thread is 1407901189/>>>> href=3D3D3D3D"tel:1407901189%2F9" valu=3D3D3D >>>>>>> e=3D3D3D3D"+14079011899" target=3D3D3D3D"_blank">1407901189/9 = >=3D >>> (tests: =3D3D >>>>> read 14079011=3D3D3D >>>>>>> 89/1407901189/1407901189 fork 1407901189/1407901189/1407901189 =3D >>> alloc =3D3D >>>>> 9/9/9 =3D3D3D >>>>>>> lock 1407901189/1407901189/9)
>>>>>>> =3D3D20 >>>>>>> =3D3D20 >>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ^C
>>>>>>> root at rover:~mika/cm3-cvs-anon/cm3/m3-libs/m3core/tests/thread # = >gdb =3D >>> =3D3D >>>>> !$
>>>>>>> gdb AMD64_FREEBSD/threadtest
>>>>>>> GNU gdb 6.1.1 [FreeBSD]
>>>>>>> Copyright 2004 Free Software Foundation, Inc.
>>>>>>> GDB is free software, covered by the GNU General Public License, = >=3D >>> and =3D3D >>>>> you ar=3D3D3D >>>>>>> e
>>>>>>> welcome to change it and/or distribute copies of it under certain = >=3D3D=3D >>>=20 >>>>> condition=3D3D3D >>>>>>> s.
>>>>>>> Type "show copying" to see the conditions.
>>>>>>> There is absolutely no warranty for GDB. =3D3D3DC2=3D3D3DA0Type =3D= > >>> "show =3D3D >>>>> warranty&quo=3D3D3D >>>>>>> t; for details.
>>>>>>> This GDB was configured as = >"amd64-marcel-freebsd"...
>>>>>>> (gdb) run
>>>>>>> Starting program: =3D3D >>>>> /big/home2/mika/2/cm3-cvs/cm3/m3-libs/m3core/tests/thread=3D3D3D >>>>>>> /AMD64_FREEBSD/threadtest
>>>>>>> [New LWP 100121]
>>>>>>> Writing file...done
>>>>>>> Creating read threads...done
>>>>>>> Creating fork threads...done
>>>>>>> Creating alloc threads...done
>>>>>>> Creating lock threads...done
>>>>>>> running...printing oldest/median age/newest
>>>>>>> .[New Thread 801807000 (LWP 100343/threadtest)]
>>>>>>> [New Thread 801807c00 (LWP 100667/threadtest)]
>>>>>>> [New Thread 801808800 (LWP 100816/threadtest)]
>>>>>>> [New Thread 801807400 (LWP 100349/threadtest)]
>>>>>>> [New Thread 801808400 (LWP 100815/threadtest)]
>>>>>>> [New Thread 801807800 (LWP 100352/threadtest)]
>>>>>>> [New Thread 801808c00 (LWP 100817/threadtest)]
>>>>>>> [New Thread 801809000 (LWP 100818/threadtest)]
>>>>>>> [New Thread 801809800 (LWP 100820/threadtest)]
>>>>>>> [New Thread 801808000 (LWP 100678/threadtest)]
>>>>>>> [New Thread 801806400 (LWP 100121/threadtest)]
>>>>>>> [New Thread 801806800 (LWP 100341/threadtest)]
>>>>>>> [New Thread 801806c00 (LWP 100342/threadtest)]
>>>>>>> .ERROR: pthread_mutex_lock:11
>>>>>>>

>>>>>>> Program received signal SIGABRT, Aborted.
>>>>>>>
[Switching to Thread 801809800 (LWP 100820/threadtest)]
>>>>>>> 0x0000000800d5c26a in thr_kill () from /lib/libc.so.7
>>>>>>> (gdb) where
>>>>>>> #0 =3D3D3DC2=3D3D3DA00x0000000800d5c26a in thr_kill () from =3D3D >>>>> /lib/libc.so.7
>>>>>>> #1 =3D3D3DC2=3D3D3DA00x0000000800e23ac9 in abort () from =3D >>> /lib/libc.so.7
>>>>>>> #2 =3D3D3DC2=3D3D3DA00x000000000045101f in =3D >>> ThreadPThread__pthread_mutex_lock =3D3D >>>>> (mutex=3D3D3D3DE=3D3D3D >>>>>>> rror accessing memory address 0x8000fe5f2d98: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513
>>>>>>> #3 =3D3D3DC2=3D3D3DA00x000000000044b370 in = >ThreadPThread__LockMutex =3D3D >>>>> (M3_AYIbX3_m=3D3D3D3DErro=3D3D3D >>>>>>> r accessing memory address 0x8000fe5f2dc8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>>>>> #4 =3D3D3DC2=3D3D3DA00x0000000000405b5d in Main__LApply =3D >>> (M3_AP7a1g_cl=3D3D3D3DError=3D3D >>>>> accessing=3D3D3D >>>>>>> memory address 0x8000fe5f2df8: Bad address.
>>>>>>> ) at ../src/Main.m3:319
>>>>>>> #5 =3D3D3DC2=3D3D3DA00x000000000044d243 in = >ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3D3DErr=3D3D3D >>>>>>> or accessing memory address 0x8000fe5f2eb8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>>> #6 =3D3D3DC2=3D3D3DA00x000000000044cf00 in = >ThreadPThread__ThreadBase =3D3D >>>>> (M3_AJWxb1_param=3D3D3D >>>>>>> =3D3D3D3DError accessing memory address 0x8000fe5f2f68: Bad =3D >>> address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>>> #7 =3D3D3DC2=3D3D3DA00x0000000800ad54a4 in pthread_create () from = >=3D3D >>>>> /lib/libthr.so.3
>>>>>>> #8 =3D3D3DC2=3D3D3DA00x0000000000000000 in ?? ()
>>>>>>> (gdb) set lang c
>>>>>>> (gdb) thread apply all bt
>>>>>>> ... not that interesting ...
>>>>>>>
>>>>>>> Segfault is segfault---error 11 is EDEADLK (locking against =3D3D >>>>> myself?)
>>>>>>>
>>>>>>> ????? the code is very straightforward, as I said.
>>>>>>>
>>>>>>> I thought people had the thread tester working with pthreads? =3D3D= > >>>>> =3D3D3DC2=3D3D3DA0Which s=3D3D3D >>>>>>> et of files, then? =3D3D3DC2=3D3D3DA0Anyone on FreeBSD/amd64?
>>>>>>>
>>>>>>> Could it be an issue with "volatile"? =3D3D3DC2=3D3D3DA0N= >ot =3D >>> even =3D3D >>>>> sure where t=3D3D3D >>>>>>> o look.
>>>>>>>
>>>>>>> The code calling the lock is just this:
>>>>>>>
>>>>>>> PROCEDURE GetChar (rd: T): CHAR
>>>>>>> =3D3D3DC2=3D3D3DA0 RAISES {EndOfFile, Failure, Alerted} = >=3D3D3D3D
>>>>>>> =3D3D3DC2=3D3D3DA0 BEGIN
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 LOCK rd DO
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 RETURN =3D= > >>> FastGetChar(rd);
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 END
>>>>>>> =3D3D3DC2=3D3D3DA0 END GetChar;
>>>>>>>
>>>>>>> No mysteries there...
>>>>>>>
>>>>>>> Ah is this the fork bug? =3D3D3DC2=3D3D3DA0Looks like the Init = >routine =3D >>> is =3D3D >>>>> called on a>>>>>> r> >>>>>>> lot of NIL mutexes around the fork. =3D3D3DC2=3D3D3DA0But the =3D >>> subprocesses =3D3D >>>>> aren't m=3D3D3D >>>>>>> eant
>>>>>>> to accesses the mutexes... humm
>>>>>>>
>>>>>>> Hmm, and it's not entirely a fork issue. =3D3D3DC2=3D3D3DA0Even= > =3D >>> with =3D3D >>>>> "threadte=3D3D3D >>>>>>> st -tests STD,-fork,-forktoomuch" it misbehaves. =3D3D >>>>> =3D3D3DC2=3D3D3DA0Hangs....
>>>>>>>
>>>>>>> Looks like a deadlock this time.
>>>>>>>
>>>>>>> Some stacks...
>>>>>>>
>>>>>>> Thread 4 (Thread 800c0b400 (LWP 100477/threadtest)):
>>>>>>> #0 =3D3D3DC2=3D3D3DA00x00000000004b4e2b in __vdso_gettimeofday = >()
>>>>>>> #1 =3D3D3DC2=3D3D3DA00x00000000004ab8d2 in gettimeofday ()
>>>>>>> #2 =3D3D3DC2=3D3D3DA00x0000000000452e4b in TimePosix__Now () at = >=3D3D >>>>> ../src/time/POSIX/TimeP=3D3D3D >>>>>>> osixC.c:50
>>>>>>> #3 =3D3D3DC2=3D3D3DA00x0000000000452d72 in Time__Now () at =3D3D >>>>> ../src/time/POSIX/TimePosix.=3D3D3D >>>>>>> m3:14
>>>>>>> #4 =3D3D3DC2=3D3D3DA00x00000000004029a3 in Main__LApply =3D >>> (M3_AP7a1g_cl=3D3D3D3DError=3D3D >>>>> accessing=3D3D3D >>>>>>> memory address 0x8000fedf6df8: Bad address.
>>>>>>> ) at ../src/Main.m3:327
>>>>>>> #5 =3D3D3DC2=3D3D3DA00x0000000000449f93 in = >ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3D3DErr=3D3D3D >>>>>>> or accessing memory address 0x8000fedf6eb8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>>> #6 =3D3D3DC2=3D3D3DA00x0000000000449c50 in = >ThreadPThread__ThreadBase =3D3D >>>>> (M3_AJWxb1_param=3D3D3D >>>>>>> =3D3D3D3DError accessing memory address 0x8000fedf6f68: Bad =3D >>> address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>>> #7 =3D3D3DC2=3D3D3DA00x000000000047c7d4 in thread_start ()
>>>>>>> #8 =3D3D3DC2=3D3D3DA00x0000000000000000 in ?? ()
>>>>>>>
>>>>>>> Thread 3 (Thread 800c0b000 (LWP 100476/threadtest)):
>>>>>>> #0 =3D3D3DC2=3D3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>>> #1 =3D3D3DC2=3D3D3DA00x0000000000475f14 in __thr_umutex_lock = >()
>>>>>>> #2 =3D3D3DC2=3D3D3DA00x0000000000479404 in mutex_lock_common = >()
>>>>>>> #3 =3D3D3DC2=3D3D3DA00x000000000044dd15 in =3D >>> ThreadPThread__pthread_mutex_lock =3D3D >>>>> (mutex=3D3D3D3DE=3D3D3D >>>>>>> rror accessing memory address 0x8000feff7d98: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>>>> #4 =3D3D3DC2=3D3D3DA00x00000000004480c0 in = >ThreadPThread__LockMutex =3D3D >>>>> (M3_AYIbX3_m=3D3D3D3DErro=3D3D3D >>>>>>> r accessing memory address 0x8000feff7dc8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:119
>>>>>>> #5 =3D3D3DC2=3D3D3DA00x00000000004028ad in Main__LApply =3D >>> (M3_AP7a1g_cl=3D3D3D3DError=3D3D >>>>> accessing=3D3D3D >>>>>>> memory address 0x8000feff7df8: Bad address.
>>>>>>> ) at ../src/Main.m3:319
>>>>>>> #6 =3D3D3DC2=3D3D3DA00x0000000000449f93 in = >ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3D3DErr=3D3D3D >>>>>>> or accessing memory address 0x8000feff7eb8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>>> #7 =3D3D3DC2=3D3D3DA00x0000000000449c50 in = >ThreadPThread__ThreadBase =3D3D >>>>> (M3_AJWxb1_param=3D3D3D >>>>>>> =3D3D3D3DError accessing memory address 0x8000feff7f68: Bad =3D >>> address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>>> #8 =3D3D3DC2=3D3D3DA00x000000000047c7d4 in thread_start ()
>>>>>>> #9 =3D3D3DC2=3D3D3DA00x0000000000000000 in ?? ()
>>>>>>>
>>>>>>> Thread 6 (Thread 800c09800 (LWP 100470/threadtest)):
>>>>>>> #0 =3D3D3DC2=3D3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>>> #1 =3D3D3DC2=3D3D3DA00x0000000000475759 in suspend_common ()
>>>>>>> #2 =3D3D3DC2=3D3D3DA00x00000000004755c1 in pthread_suspend_np = >()
>>>>>>> #3 =3D3D3DC2=3D3D3DA00x000000000044df0c in = >ThreadPThread__SuspendThread =3D >>> =3D3D >>>>> (mt=3D3D3D3DError acc=3D3D3D >>>>>>> essing memory address 0x8000ffbfd6f8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadFreeBSD.c:33
>>>>>>> #4 =3D3D3DC2=3D3D3DA00x000000000044bade in = >ThreadPThread__StopThread =3D3D >>>>> (M3_DMxDjQ_act=3D3D3D3DE=3D3D3D >>>>>>> rror accessing memory address 0x8000ffbfd718: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:909
>>>>>>> #5 =3D3D3DC2=3D3D3DA00x000000000044bc81 in = >ThreadPThread__StopWorld () =3D >>> at =3D3D >>>>> ../src/thread=3D3D3D >>>>>>> /PTHREAD/ThreadPThread.m3:948
>>>>>>> #6 =3D3D3DC2=3D3D3DA00x000000000044b19e in = >RTThread__SuspendOthers () =3D >>> at =3D3D >>>>> ../src/thread/=3D3D3D >>>>>>> PTHREAD/ThreadPThread.m3:713
>>>>>>> #7 =3D3D3DC2=3D3D3DA00x00000000004330d6 in =3D3D >>>>> RTCollector__CollectSomeInStateZero () at ..=3D3D3D >>>>>>> /src/runtime/common/RTCollector.m3:749
>>>>>>> #8 =3D3D3DC2=3D3D3DA00x0000000000433081 in = >RTCollector__CollectSome () =3D >>> at =3D3D >>>>> ../src/runtim=3D3D3D >>>>>>> e/common/RTCollector.m3:723
>>>>>>> #9 =3D3D3DC2=3D3D3DA00x0000000000432d49 in = >RTHeapRep__CollectEnough () =3D >>> at =3D3D >>>>> ../src/runtim=3D3D3D >>>>>>> e/common/RTCollector.m3:657
>>>>>>> #10 0x000000000042ff83 in RTAllocator__AllocTraced =3D3D >>>>> (M3_Cwb5VA_dataSize=3D3D3D3DEr=3D3D3D >>>>>>> ror accessing memory address 0x8000ffbfd958: Bad address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:367
>>>>>>> #11 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D3D >>>>> (M3_Eic7CK_def=3D3D3D3DError =3D3D3D >>>>>>> accessing memory address 0x8000ffbfda18: Bad address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>>>>> #12 0x000000000042ebdf in RTHooks__AllocateOpenArray =3D3D >>>>> (M3_AJWxb1_defn=3D3D3D3DErro=3D3D3D >>>>>>> r accessing memory address 0x8000ffbfda78: Bad address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>>>>> #13 0x000000000040ca4e in Rd__NextBuff (M3_EkTcCb_rd=3D3D3D3DError = >=3D3D >>>>> accessing memo=3D3D3D >>>>>>> ry address 0x8000ffbfdab8: Bad address.
>>>>>>> ) at ../src/rw/Rd.m3:159
>>>>>>> #14 0x000000000040cd43 in UnsafeRd__FastGetChar =3D >>> (M3_EkTcCb_rd=3D3D3D3DError=3D3D >>>>> acces=3D3D3D >>>>>>> sing memory address 0x8000ffbfdb88: Bad address.
>>>>>>> ) at ../src/rw/Rd.m3:187
>>>>>>> #15 0x000000000040cc4a in Rd__GetChar (M3_EkTcCb_rd=3D3D3D3DError = >=3D3D >>>>> accessing memor=3D3D3D >>>>>>> y address 0x8000ffbfdbd8: Bad address.
>>>>>>> ) at ../src/rw/Rd.m3:176
>>>>>>> #16 0x000000000040095c in Main__RApply (M3_AP7a1g_cl=3D3D3D3DError = >=3D3D >>>>> accessing memo=3D3D3D >>>>>>> ry address 0x8000ffbfdc58: Bad address.
>>>>>>> ) at ../src/Main.m3:185
>>>>>>>
>>>>>>> #17 0x0000000000449f93 in ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3D3DError ac=3D3D3D >>>>>>> cessing memory address 0x8000ffbfdeb8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>>> #18 0x0000000000449c50 in ThreadPThread__ThreadBase =3D3D >>>>> (M3_AJWxb1_param=3D3D3D3DErro=3D3D3D >>>>>>> r accessing memory address 0x8000ffbfdf68: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>>> #19 0x000000000047c7d4 in thread_start ()
>>>>>>> #20 0x0000000000000000 in ?? ()
>>>>>>>
>>>>>>> Thread 5 (Thread 800c09400 (LWP 101035/threadtest)):
>>>>>>> #0 =3D3D3DC2=3D3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>>> #1 =3D3D3DC2=3D3D3DA00x0000000000475f14 in __thr_umutex_lock = >()
>>>>>>> #2 =3D3D3DC2=3D3D3DA00x0000000000479404 in mutex_lock_common = >()
>>>>>>> #3 =3D3D3DC2=3D3D3DA00x000000000044dd15 in =3D >>> ThreadPThread__pthread_mutex_lock =3D3D >>>>> (mutex=3D3D3D3DE=3D3D3D >>>>>>> rror accessing memory address 0x8000ffffc678: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>>>> #4 =3D3D3DC2=3D3D3DA00x000000000044d039 in RTOS__LockHeap () at = >=3D3D >>>>> ../src/thread/PTHREAD/T=3D3D3D >>>>>>> hreadPThread.m3:1337
>>>>>>> ---Type <return> to continue, or q <return> to =3D3D >>>>> quit---
>>>>>>> #5 =3D3D3DC2=3D3D3DA00x000000000042ff79 in = >RTAllocator__AllocTraced =3D3D >>>>> (M3_Cwb5VA_dataSize=3D3D3D >>>>>>> =3D3D3D3DError accessing memory address 0x8000ffffc6e8: Bad =3D >>> address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>>>>> #6 =3D3D3DC2=3D3D3DA00x000000000042f15b in = >RTAllocator__GetTracedObj =3D3D >>>>> (M3_Eic7CK_def=3D3D3D3DE=3D3D3D >>>>>>> rror accessing memory address 0x8000ffffc7a8: Bad address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:224
>>>>>>> #7 =3D3D3DC2=3D3D3DA00x000000000042eb23 in = >RTHooks__AllocateTracedObj =3D3D=3D >>>=20 >>>>> (M3_AJWxb1_defn=3D3D3D >>>>>>> =3D3D3D3DError accessing memory address 0x8000ffffc7f8: Bad =3D >>> address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:122
>>>>>>> #8 =3D3D3DC2=3D3D3DA00x000000000045fbe4 in TextCat__Flat =3D3D >>>>> (M3_Bd56fi_LText=3D3D3D3DError acces=3D3D3D >>>>>>> sing memory address 0x8000ffffc858: Bad address.
>>>>>>> ) at ../src/text/TextCat.m3:562
>>>>>>> #9 =3D3D3DC2=3D3D3DA00x000000000045ed5d in TextCat__Balance =3D3D >>>>> (M3_Bd56fi_LText=3D3D3D3D0x800c49=3D3D3D >>>>>>> 0b0, M3_BUgnwf_LInfo=3D3D3D3DError accessing memory address =3D3D >>>>> 0x8000ffffc8f8: Bad a=3D3D3D >>>>>>> ddress.
>>>>>>> ) at ../src/text/TextCat.m3:488
>>>>>>> #10 0x000000000045d64f in RTHooks__Concat = >(M3_Bd56fi_t=3D3D3D3DError =3D >>> =3D3D >>>>> accessing me=3D3D3D >>>>>>> mory address 0x8000ffffcbb8: Bad address.
>>>>>>> ) at ../src/text/TextCat.m3:40
>>>>>>> #11 0x000000000040639e in Main_M3 (M3_AcxOUs_mode=3D3D3D3DError =3D= > >>> accessing =3D3D >>>>> memory =3D3D3D >>>>>>> address 0x8000ffffcc38: Bad address.
>>>>>>> ) at ../src/Main.m3:593
>>>>>>> #12 0x000000000043d55d in RTLinker__RunMainBody =3D >>> (M3_DjPxE3_m=3D3D3D3DError =3D3D >>>>> access=3D3D3D >>>>>>> ing memory address 0x8000ffffcf88: Bad address.
>>>>>>> ) at ../src/runtime/common/RTLinker.m3:408
>>>>>>> #13 0x000000000043c8e8 in RTLinker__AddUnitI = >(M3_DjPxE3_m=3D3D3D3DError=3D >>> =3D3D >>>>> accessing=3D3D3D >>>>>>> memory address 0x8000ffffd008: Bad address.
>>>>>>> ) at ../src/runtime/common/RTLinker.m3:115
>>>>>>> #14 0x000000000043c97c in RTLinker__AddUnit = >(M3_DjPxE5_b=3D3D3D3DError =3D >>> =3D3D >>>>> accessing =3D3D3D >>>>>>> memory address 0x8000ffffd028: Bad address.
>>>>>>> ) at ../src/runtime/common/RTLinker.m3:124
>>>>>>> #15 0x00000000004004a6 in main (argc=3D3D3D3DError accessing = >memory =3D3D=3D >>>=20 >>>>> address 0x800=3D3D3D >>>>>>> 0ffffd07c: Bad address.
>>>>>>> ) at _m3main.c:22
>>>>>>>
>>>>>>> Thread 9 (Thread 800c0a400 (LWP 100473/threadtest)):
>>>>>>> #0 =3D3D3DC2=3D3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>>> #1 =3D3D3DC2=3D3D3DA00x0000000000477e8a in check_suspend ()
>>>>>>> #2 =3D3D3DC2=3D3D3DA00x00000000004780a2 in sigcancel_handler = >()
>>>>>>> #3 =3D3D3DC2=3D3D3DA0<signal handler called>
>>>>>>> #4 =3D3D3DC2=3D3D3DA00x000000000047e53c in _umtx_op_err ()
>>>>>>> #5 =3D3D3DC2=3D3D3DA00x0000000000475f14 in __thr_umutex_lock = >()
>>>>>>> #6 =3D3D3DC2=3D3D3DA00x0000000000479404 in mutex_lock_common = >()
>>>>>>> #7 =3D3D3DC2=3D3D3DA00x000000000044dd15 in =3D >>> ThreadPThread__pthread_mutex_lock =3D3D >>>>> (mutex=3D3D3D3DE=3D3D3D >>>>>>> rror accessing memory address 0x8000ff5fac18: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:506
>>>>>>> #8 =3D3D3DC2=3D3D3DA00x000000000044d039 in RTOS__LockHeap () at = >=3D3D >>>>> ../src/thread/PTHREAD/T=3D3D3D >>>>>>> hreadPThread.m3:1337
>>>>>>> #9 =3D3D3DC2=3D3D3DA00x000000000042ff79 in = >RTAllocator__AllocTraced =3D3D >>>>> (M3_Cwb5VA_dataSize=3D3D3D >>>>>>> =3D3D3D3DError accessing memory address 0x8000ff5fac88: Bad =3D >>> address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:365
>>>>>>> #10 0x000000000042f8a5 in RTAllocator__GetOpenArray =3D3D >>>>> (M3_Eic7CK_def=3D3D3D3DError =3D3D3D >>>>>>> accessing memory address 0x8000ff5fad48: Bad address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:296
>>>>>>> #11 0x000000000042ebdf in RTHooks__AllocateOpenArray =3D3D >>>>> (M3_AJWxb1_defn=3D3D3D3DErro=3D3D3D >>>>>>> r accessing memory address 0x8000ff5fada8: Bad address.
>>>>>>> ) at ../src/runtime/common/RTAllocator.m3:143
>>>>>>> #12 0x000000000040203a in Main__AApply (M3_AP7a1g_cl=3D3D3D3DError = >=3D3D >>>>> accessing memo=3D3D3D >>>>>>> ry address 0x8000ff5fade8: Bad address.
>>>>>>> ) at ../src/Main.m3:283
>>>>>>> #13 0x0000000000449f93 in ThreadPThread__RunThread =3D3D >>>>> (M3_DMxDjQ_me=3D3D3D3DError ac=3D3D3D >>>>>>> cessing memory address 0x8000ff5faeb8: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:449
>>>>>>> #14 0x0000000000449c50 in ThreadPThread__ThreadBase =3D3D >>>>> (M3_AJWxb1_param=3D3D3D3DErro=3D3D3D >>>>>>> r accessing memory address 0x8000ff5faf68: Bad address.
>>>>>>> ) at ../src/thread/PTHREAD/ThreadPThread.m3:422
>>>>>>> #15 0x000000000047c7d4 in thread_start ()
>>>>>>> #16 0x0000000000000000 in ?? ()
>>>>>>>
>>>>>>> (others are similar)
>>>>>>>
>>>>>>> Hmm looks like a FreeBSD issue now. =3D3D3DC2=3D3D3DA0It's =3D >>> here...
>>>>>>>
>>>>>>> int
>>>>>>> __cdecl
>>>>>>> ThreadPThread__SuspendThread (m3_pthread_t mt)
>>>>>>> {
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D >>>>> ThreadFreeBSD__Fatal(pthread_suspend_np(PTHREAD_FROM_M3(mt)), =3D >>> "=3D3D3D >>>>>>> pthread_suspend_np");
>>>>>>> =3D3D3DC2=3D3D3DA0 return 1;
>>>>>>> }
>>>>>>>
>>>>>>> Now this suspend can wait:
>>>>>>>
>>>>>>> static int
>>>>>>> suspend_common(struct pthread *curthread, struct pthread =3D >>> *thread,
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 int =3D >>> waitok)
>>>>>>> {
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> uint32_t tmp;
>>>>>>>
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 while =3D >>> (thread->state =3D3D >>>>> !=3D3D3D3D PS_DEAD &&=3D3D3D >>>>>>>
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 !(thread->flags & T=3D3D3D >>>>>>> HR_FLAGS_SUSPENDED)) {
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 thread->flags |=3D3D3D >>>>>>> =3D3D3D3D THR_FLAGS_NEED_SUSPEND;
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 /* Thread is in cre=3D3D3D >>>>>>> ation. */
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 if (thread->tid =3D3D3D >>>>>>> =3D3D3D3D=3D3D3D3D TID_TERMINATED)
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3=3D >>> D >>>>>>> =3D3D3DA0 =3D3D3DC2=3D3D3DA0 return (1);
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 tmp =3D3D3D3D = >thread->=3D3D3D >>>>>>> cycle;
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 _thr_send_sig(threa=3D3D3D >>>>>>> d, SIGCANCEL);
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 THR_THREAD_UNLOCK(c=3D3D3D >>>>>>> urthread, thread);
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 if (waitok) {
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3=3D >>> D >>>>>>> =3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >_thr_umtx_wait_uint(&thread->cycle, =3D >>> tmp, =3D3D >>>>> NULL, 0); =3D3D3DC2=3D3D3DA0=3D3D3D >>>>>>> = ><=3D3D3D3D=3D3D3D3D=3D3D3D3D=3D3D3D3D=3D3D3D3D=3D3D3D3D=3D3D3D3D=3D3D3D= >3D=3D3D3D3D=3D3D=3D >>> 3D3D
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3=3D >>> D >>>>>>> =3D3D3DA0 =3D3D3DC2=3D3D3DA0 THR_THREAD_LOCK(curthread, = >thread);
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 } else {
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3=3D >>> D >>>>>>> =3D3D3DA0 =3D3D3DC2=3D3D3DA0 THR_THREAD_LOCK(curthread, = >thread);
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3=3D >>> D >>>>>>> =3D3D3DA0 =3D3D3DC2=3D3D3DA0 return (0);
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 =3D >>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D >>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 }
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 }
>>>>>>>
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0 return =3D >>> (1);
>>>>>>> }
>>>>>>>
>>>>>>> ... but what it can wait for I am not clear on.
>>>>>>>
>>>>>>> Do things work better on Linux?
>>>>>>>
>>>>>>> What is the status of the fork bug? =3D3D3DC2=3D3D3DA0Can it be = >worked =3D >>> around =3D3D >>>>> by only f=3D3D3D >>>>>>> orking via Process.Create with no mutexes held (outside of all = >LOCK =3D >>> =3D3D >>>>> blocks)=3D3D3D >>>>>>> ?
>>>>>>>
>>>>>>> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0Mika
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Peter McKinna writes:
>>>>>>> >--001a11c2ced4471a2e050079db82
>>>>>>> >Content-Type: text/plain; charset=3D3D3D3DUTF-8
>>>>>>>
>
>>>>>>> >Mika
>>>>>>> >
>>>>>>> > =3D3D3DC2=3D3D3DA0I think you need to back out Tony's = >changes =3D >>> to fix =3D3D >>>>> the fork =3D3D3D >>>>>>> bug, at least
>>>>>>> >for now. Need to reload from cvs version 1.262 for =3D3D >>>>> ThreadPThread.m3 If<=3D3D3D >>>>>>> br> >>>>>>> >you're using git you're on your own.
>>>>>>> > =3D3D3DC2=3D3D3DA0Do a cvs log ThreadPThread.m3 for an = >explanation =3D >>> for =3D3D >>>>> some of the=3D3D3D >>>>>>> design
>>>>>>> >principles.
>>>>>>> > =3D3D3DC2=3D3D3DA0Also if you use gdb then you need to set = >lanc c =3D >>> before =3D3D >>>>> backtrace=3D3D3D >>>>>>> s so at
>>>>>>> >least you can see address names and values even if they are = >=3D3D >>>>> contorted y=3D3D3D >>>>>>> ou
>>>>>>> >can extract the M3 name in the parm lists. Also in gdb thread = >=3D3D=3D >>>=20 >>>>> apply all=3D3D3D >>>>>>> bt
>>>>>>> >gives all thread backtraces which can be handy to see whose = >got =3D >>> =3D3D >>>>> the loc=3D3D3D >>>>>>> ks
>>>>>>> >held.
>>>>>>> >
>>>>>>> >Regards Peter
>>>>>>> >
>>>>>>> >
>>>>>>> >
>>>>>>> >On Wed, Aug 13, 2014 at 12:14 PM, <>>>> href=3D3D3D3D"mailto:mika at async.calt=3D3D3D >>>>>>> ech.edu" target=3D3D3D3D"_blank">mika at async.caltech.edu> = >=3D3D >>>>> wrote:
>>>>>>> >
>>>>>>> >>
>>>>>>> >> Question... is there something odd about my pthreads? = >=3D3D >>>>> =3D3D3DC2=3D3D3DA0Are pt=3D3D3D >>>>>>> hreads
>>>>>>> >> normally reentrant? =3D3D3DC2=3D3D3DA0I didn't think = >=3D >>> so.
>>>>>>> >>
>>>>>>> >> My compiler is much happier with the following changes I = >=3D3D=3D >>>=20 >>>>> already o=3D3D3D >>>>>>> utlined:
>>>>>>> >>
>>>>>>> >> 1. a dirty, disgusting hack to keep from locking against = >=3D3D=3D >>>=20 >>>>> myself go=3D3D3D >>>>>>> ing from
>>>>>>> >> XWait with self.mutex locked to m.release().
>>>>>>> >>
>>>>>>> >> 2. the change to LockHeap I described in previous =3D >>> email
>>>>>>> >>
>>>>>>> >> But now...
>>>>>>> >>
>>>>>>> >> (gdb) cont
>>>>>>> >> Continuing.
>>>>>>> >> ERROR: pthread_mutex_lock:11
>>>>>>> >> ERROR: pthread_mutex_lock:11
>>>>>>> >>
>>>>>>> >> Program received signal SIGABRT, Aborted.
>>>>>>> >> 0x000000080107626a in thr_kill () from = >/lib/libc.so.7
>>>>>>> >> (gdb) where
>>>>>>> >> #0 =3D3D3DC2=3D3D3DA00x000000080107626a in thr_kill () = >from =3D3D >>>>> /lib/libc.so.7
>>>>>>> >> #1 =3D3D3DC2=3D3D3DA00x000000080113dac9 in abort () from = >=3D3D >>>>> /lib/libc.so.7
>>>>>>> >> #2 =3D3D3DC2=3D3D3DA00x000000000071e37a in =3D3D >>>>> ThreadPThread__pthread_mutex_lock (=3D3D3D >>>>>>> mutex=3D3D3D3DError
>>>>>>> >> accessing memory address 0x8000ffffb508: Bad = >address.
>>>>>>> >> ) at ../src/thread/PTHREAD/ThreadPThreadC.c:543
>>>>>>> >> #3 =3D3D3DC2=3D3D3DA00x000000000071d48d in = >RTOS__LockHeap () =3D >>> at
>>>>>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1377
>>>>>>> >> #4 =3D3D3DC2=3D3D3DA00x0000000000706b9d in =3D3D >>>>> RTHooks__CheckLoadTracedRef (M3_Af4=3D3D3D >>>>>>> 0ku_ref=3D3D3D3DError
>>>>>>> >> accessing memory address 0x8000ffffb568: Bad = >address.
>>>>>>> >> ) at ../src/runtime/common/RTCollector.m3:2234
>>>>>>> >> #5 =3D3D3DC2=3D3D3DA00x000000000071d284 in =3D3D >>>>> ThreadPThread__AtForkParent () at>>>>>> r> >>>>>>> >> ../src/thread/PTHREAD/ThreadPThread.m3:1348
>>>>>>> >> #6 =3D3D3DC2=3D3D3DA00x0000000800df8733 in fork () from = >=3D3D >>>>> /lib/libthr.so.3
>>>>>>> >> #7 =3D3D3DC2=3D3D3DA00x000000000070dd8b in = >RTProcess__Fork () =3D >>> at
>>>>>>> >> ../src/runtime/common/RTProcessC.c:152
>>>>>>> >> #8 =3D3D3DC2=3D3D3DA00x00000000006c52f2 in =3D3D >>>>> ProcessPosixCommon__Create_ForkExec=3D3D3D >>>>>>>
>>>>>>> >> (M3_Bd56fi_cmd=3D3D3D3DError accessing memory address = >=3D3D >>>>> 0x8000ffffb6f8: Ba=3D3D3D >>>>>>> d address.
>>>>>>> >> ) at ../src/os/POSIX/ProcessPosixCommon.m3:75
>>>>>>> >> #9 =3D3D3DC2=3D3D3DA00x00000000006c6c6c in = >Process__Create =3D3D >>>>> (M3_Bd56fi_cmd=3D3D3D3DEr=3D3D3D >>>>>>> ror accessing
>>>>>>> >> memory address 0x8000ffffb7f8: Bad address.
>>>>>>> >> ) at ../src/os/POSIX/ProcessPosix.m3:21
>>>>>>> >> #10 0x00000000004d6826 in QMachine__FulfilExecPromise = >=3D3D >>>>> (M3_D6rRrg_e=3D3D3D >>>>>>> p=3D3D3D3DError
>>>>>>> >> accessing memory address 0x8000ffffb838: Bad = >address.
>>>>>>> >> ) at ../src/QMachine.m3:1666
>>>>>>> >> #11 0x00000000004d6220 in QMachine__ExecCommand =3D3D >>>>> (M3_An02H2_t=3D3D3D3DErr=3D3D3D >>>>>>> or
>>>>>>> >> accessing memory address 0x8000ffffb9f8: Bad = >address.
>>>>>>> >> ) at ../src/QMachine.m3:1605
>>>>>>> >> #12 0x00000000004d537e in QMachine__DoTryExec =3D3D >>>>> (M3_An02H2_t=3D3D3D3DError=3D3D3D >>>>>>> accessing
>>>>>>> >> memory address 0x8000ffffbee8: Bad address.
>>>>>>> >> ) at ../src/QMachine.m3:1476
>>>>>>> >>
>>>>>>> >> What am I doing wrong here?
>>>>>>> >>
>>>>>>> >> The error doesn't look unreasonable! = >=3D3D3DC2=3D3D3DA0Looki=3D >>> ng =3D3D >>>>> more closel=3D3D3D >>>>>>> y at the code:
>>>>>>> >>
>>>>>>> >> First, AtForkPrepare has been called:
>>>>>>> >>
>>>>>>> >> PROCEDURE AtForkPrepare() =3D3D3D3D
>>>>>>> >> =3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D = >GetActivation();
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >act: =3D >>> Activation;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 BEGIN
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(slotsMu, =3D3D >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(perfMu, =3D3D >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(initMu, =3D >>> ThisLine()); =3D3D >>>>> (* InitMutex =3D3D3D >>>>>>> =3D3D3D3D>
>>>>>>> >> RegisterFinalCleanup =3D3D3D3D> LockHeap *)
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(heapMu, =3D3D >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadLockMutex(activeMu, =3D3D=3D >>>=20 >>>>> ThisLine()); (* LockHeap =3D3D3D >>>>>>> =3D3D3D3D> SuspendOthers
>>>>>>> >> =3D3D3D3D> activeMu *)
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk = >activations and lock =3D >>> all =3D3D >>>>> threads.
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* = >NOTE: We =3D >>> have initMu, =3D3D >>>>> activeMu, so slots won=3D3D3D >>>>>>> 't change, conditions
>>>>>>> >> and
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0* = >mutexes =3D >>> won't be =3D3D >>>>> initialized on-demand.<=3D3D3D >>>>>>> br> >>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0*)
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D = >me;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D >>> PThreadLockMutex(act.mutex, =3D3D >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >act :=3D3D3D3D =3D >>> act.next;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >me;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 END AtForkPrepare;
>>>>>>> >>
>>>>>>> >> a postcondition of this routine is that heapMu is =3D3D >>>>> locked.
>>>>>>> >>
>>>>>>> >> now we get into AtForkParent:
>>>>>>> >>
>>>>>>> >> PROCEDURE AtForkParent() =3D3D3D3D
>>>>>>> >> =3D3D3DC2=3D3D3DA0 VAR me :=3D3D3D3D = >GetActivation();
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >act: =3D >>> Activation;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >cond: =3D >>> Condition;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 BEGIN
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 (* Walk = >activations and =3D >>> unlock all =3D3D >>>>> threads, conditio=3D3D3D >>>>>>> ns. *)
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 act :=3D3D3D3D = >me;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 REPEAT
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >cond :=3D3D3D3D =3D >>> =3D3D >>>>> slots[act.slot].join;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >IF cond # NIL =3D >>> THEN =3D3D >>>>> PThreadUnlockMutex(cond.mu=3D3D3D >>>>>>> tex, ThisLine()) END;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D >>>>> PThreadUnlockMutex(act.mutex, ThisLine());>>>>>>> =3D3D20 >>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >act :=3D3D3D3D =3D >>> act.next;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 UNTIL act =3D3D3D3D = >me;
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(activeMu, =3D >>> =3D3D >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(heapMu, =3D3D=3D >>>=20 >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(initMu, =3D3D=3D >>>=20 >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(perfMu, =3D3D=3D >>>=20 >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >PThreadUnlockMutex(slotsMu, =3D >>> =3D3D >>>>> ThisLine());
>>>>>>> >> =3D3D3DC2=3D3D3DA0 END AtForkParent;
>>>>>>> >>
>>>>>>> >> We can see by inspecting the code that a necessary =3D3D >>>>> precondition fo=3D3D3D >>>>>>> r
>>>>>>> >> this routine is that heapMu is locked! = >=3D3D3DC2=3D3D3DA0(Since =3D >>> =3D3D >>>>> it's going=3D3D3D >>>>>>> to unlock it,
>>>>>>> >> it had BETTER be locked on entry.)
>>>>>>> >>
>>>>>>> >> But the cond :=3D3D3D3D ... causes a =3D3D >>>>> RTHooks.CheckLoadTracedRef
>>>>>>> >>
>>>>>>> >> which causes an RTOS.LockHeap
>>>>>>> >>
>>>>>>> >> the code of which we just saw:
>>>>>>> >>
>>>>>>> >> PROCEDURE LockHeap () =3D3D3D3D
>>>>>>> >> =3D3D3DC2=3D3D3DA0 VAR self :=3D3D3D3D = >pthread_self();
>>>>>>> >> =3D3D3DC2=3D3D3DA0 BEGIN
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 WITH r =3D3D3D3D = >=3D3D >>>>> pthread_mutex_lock(heapMu,ThisLine()) DO =3D3D3D >>>>>>> <*ASSERT r=3D3D3D3D0*> END;
>>>>>>> >> ...
>>>>>>> >>
>>>>>>> >> we try to lock heapMu. =3D3D3DC2=3D3D3DA0kaboom! = >=3D3D3DC2=3D3D3DA0N=3D >>> o =3D3D >>>>> surprise there, real=3D3D3D >>>>>>> ly?
>>>>>>> >>
>>>>>>> >> Am I going about this totally the wrong way? =3D >>> =3D3D3DC2=3D3D3DA0Other =3D3D >>>>> people ar=3D3D3D >>>>>>> e running
>>>>>>> >> Modula-3
>>>>>>> >> with pthreads, right? =3D3D3DC2=3D3D3DA0Right?? =3D >>> =3D3D3DC2=3D3D3DA0Somewhere =3D3D >>>>> out there in m=3D3D3D >>>>>>> 3devel-land?
>>>>>>> >>
>>>>>>> >> =3D3D3DC2=3D3D3DA0 =3D3D3DC2=3D3D3DA0 = >=3D3D3DC2=3D3D3DA0Mika
>>>>>>> >>
>>>>>>> >>
>>>>>>> >
>>>>>>>
>--001a11c2ced4471a2e050079db82
>>>>>>> >Content-Type: text/html; charset=3D3D3D3DUTF-8
>>>>>>> >Content-Transfer-Encoding: quoted-printable
>>>>>>> >
>>>>>>> ><div =3D3D >>>>> = >dir=3D3D3D3D3D"ltr">Mika<div><br></div>=3D3D= >3=3D >>> D >>>>>>> ;<div>=3D3D3D3DC2=3D3D3D3DA0 I think you need to back = >ou=3D3D3D3D
=3D >>>=20 >>>>>>> >t Tony&#39;s changes to fix the fork bug, at least for = >now. =3D >>> =3D3D >>>>> Need to=3D3D3D >>>>>>> reload =3D3D3D3D
>>>>>>> >from cvs version 1.262 for ThreadPThread.m3 If you&#39;re = >=3D3D=3D >>>=20 >>>>> using git=3D3D3D >>>>>>> you&#39=3D3D3D3D
>>>>>>> >;re on your own.</div>
>>>>>>> >
>>>>>>> ><div>=3D3D3D3DC2=3D3D3D3DA0 Do a cvs log = >ThreadPThread.m3 for =3D >>> an =3D3D >>>>> explanation =3D3D3D >>>>>>> for some of th=3D3D3D3D
>>>>>>> >e design =3D >>> principles.=3D3D3D3DC2=3D3D3D3DA0</div><div>=3D3D3D3DC2=3D3= >D3D=3D3D >>>>> 3DA0 Also if=3D3D3D >>>>>>> you use gdb then you ne=3D3D3D3D
>>>>>>> >ed to set lanc c before backtraces so at least you can see = >=3D3D >>>>> address name=3D3D3D >>>>>>> s an=3D3D3D3D
>>>>>>> >d values even if they are contorted you can extract the M3 = >name =3D >>> =3D3D >>>>> in the =3D3D3D >>>>>>> parm=3D3D3D3D
>>>>>>> > lists. Also in gdb thread apply all bt gives all thread =3D3D >>>>> backtraces whi=3D3D3D >>>>>>> ch c=3D3D3D3D
>>>>>>> >an be handy to see whose got the locks held.</div>
>>>>>>> >
>>>>>>> ><div><br></div><div>Regards =3D3D >>>>> Peter</div>&l=3D3D3D >>>>>>> t;div><br></div><div =3D >>> class=3D3D3D3D3D"gmail_e=3D3D3D3D>>>> r> >>>>>>> >xtra"><br><br><div =3D3D >>>>> class=3D3D3D3D3D"gmail_quote&q=3D3D3D >>>>>>> uot;>On Wed, Aug 13, 2014 at 12:14 PM, =3D3D3D3D
>>>>>>> > <span dir=3D3D3D3D3D"ltr">&lt;<a =3D3D >>>>> href=3D3D3D3D3D"mailt=3D3D3D >>>>>>> o:>>>> target=3D3D3D3D"_blank">mika at async.ca=3D3D3D >>>>>>> ltech.edu" target=3D3D3D3D3D"=3D3D3D3D
>>>>>>> >_blank"> =3D3D=3D >>>=20 >>>>> target=3D3D3D3D"_bl=3D3D3D >>>>>>> ank">mika at async.caltech.edu</a>&gt;</span> = >=3D3D >>>>> wrote:<br=3D3D3D >>>>>>> >
>>>>>>> >
>>>>>>> ><blockquote class=3D3D3D3D3D"gmail_quote" =3D3D >>>>> style=3D3D3D3D3D"margin=3D3D3D >>>>>>> :0 0 0 .8ex;border-left:1p=3D3D3D3D
>>>>>>> >x #ccc solid;padding-left:1ex"><br>
>>>>>>> >Question... is there something odd about my pthreads? =3D3D >>>>> =3D3D3D3DC2=3D3D3D3DA0Are pth=3D3D3D >>>>>>> reads no=3D3D3D3D
>>>>>>> >rmally reentrant? =3D3D3D3DC2=3D3D3D3DA0I didn&#39;t = >think =3D3D >>>>> so.<br>
>>>>>>> ><br>
>>>>>>> >My compiler is much happier with the following changes I =3D >>> already =3D3D >>>>> outlin=3D3D3D >>>>>>> ed:<=3D3D3D3D
>>>>>>> >br>
>>>>>>> ><br>
>>>>>>> >1. a dirty, disgusting hack to keep from locking against = >myself =3D >>> =3D3D >>>>> going f=3D3D3D >>>>>>> rom =3D3D3D3D
>>>>>>> >XWait with self.mutex locked to m.release().<br>
>>>>>>> ><br>
>>>>>>> >2. the change to LockHeap I described in previous =3D3D >>>>> email<br>
>>>>>>> ><br>
>>>>>>> >But now...<br>
>>>>>>> ><br>
>>>>>>> >(gdb) cont<br>
>>>>>>> >Continuing.<br>
>>>>>>> >ERROR: pthread_mutex_lock:11<br>
>>>>>>> >ERROR: pthread_mutex_lock:11<br>
>>>>>>> ><br>
>>>>>>> >Program received signal SIGABRT, Aborted.<br>
>>>>>>> >0x000000080107626a in thr_kill () from =3D3D >>>>> /lib/libc.so.7<br>
>>>>>>> >(gdb) where<br>
>>>>>>> >#0 =3D3D3D3DC2=3D3D3D3DA00x000000080107626a in thr_kill () = >from =3D3D >>>>> /lib/libc.so.7<b=3D3D3D >>>>>>> r>
>>>>>>> >#1 =3D3D3D3DC2=3D3D3D3DA00x000000080113dac9 in abort () from = >=3D3D >>>>> /lib/libc.so.7<br&g=3D3D3D >>>>>>> t;
>>>>>>> >#2 =3D3D3D3DC2=3D3D3D3DA00x000000000071e37a in =3D3D >>>>> ThreadPThread__pthread_mutex_lock (m=3D3D3D >>>>>>> utex=3D3D3D3D3DE=3D3D3D3D
>>>>>>> >rror accessing memory address 0x8000ffffb508: Bad =3D3D >>>>> address.<br>>>>>>>> =3D3D20 >>>>>>> >) at ../src/thread/PTHREAD/ThreadPThreadC.c:543<br>
>>>>>>> >#3 =3D3D3D3DC2=3D3D3D3DA00x000000000071d48d in RTOS__LockHeap = >() at =3D >>> =3D3D >>>>> ../src/thread/P=3D3D3D >>>>>>> THREAD/T=3D3D3D3D
>>>>>>> >hreadPThread.m3:1377<br>
>>>>>>> >#4 =3D3D3D3DC2=3D3D3D3DA00x0000000000706b9d in =3D3D >>>>> RTHooks__CheckLoadTracedRef (M3_Af40=3D3D3D >>>>>>> ku_ref=3D3D3D3D
>>>>>>> >=3D3D3D3D3DError accessing memory address 0x8000ffffb568: Bad = >=3D3D >>>>> address.<br&=3D3D3D >>>>>>> gt;
>>>>>>> >) at ../src/runtime/common/RTCollector.m3:2234<br>
>>>>>>> >#5 =3D3D3D3DC2=3D3D3D3DA00x000000000071d284 in =3D3D >>>>> ThreadPThread__AtForkParent () at ..=3D3D3D >>>>>>> /src/thr=3D3D3D3D
>>>>>>> >ead/PTHREAD/ThreadPThread.m3:1348<br>
>>>>>>> >#6 =3D3D3D3DC2=3D3D3D3DA00x0000000800df8733 in fork () from = >=3D3D >>>>> /lib/libthr.so.3<br&=3D3D3D >>>>>>> gt;
>>>>>>> >#7 =3D3D3D3DC2=3D3D3D3DA00x000000000070dd8b in = >RTProcess__Fork () =3D >>> at =3D3D >>>>> ../src/runtime=3D3D3D >>>>>>> /common/=3D3D3D3D
>>>>>>> >RTProcessC.c:152<br>
>>>>>>> >#8 =3D3D3D3DC2=3D3D3D3DA00x00000000006c52f2 in =3D3D >>>>> ProcessPosixCommon__Create_ForkExec =3D3D3D >>>>>>> (M3_Bd56=3D3D3D3D
>>>>>>> >fi_cmd=3D3D3D3D3DError accessing memory address = >0x8000ffffb6f8: =3D >>> Bad =3D3D >>>>> address.&=3D3D3D >>>>>>> lt;br>
>>>>>>> >) at ../src/os/POSIX/ProcessPosixCommon.m3:75<br>
>>>>>>> >#9 =3D3D3D3DC2=3D3D3D3DA00x00000000006c6c6c in = >Process__Create =3D3D >>>>> (M3_Bd56fi_cmd=3D3D3D3D3DE=3D3D3D >>>>>>> rror acces=3D3D3D3D
>>>>>>> >sing memory address 0x8000ffffb7f8: Bad = >address.<br>
>>>>>>> >) at ../src/os/POSIX/ProcessPosix.m3:21<br>
>>>>>>> >#10 0x00000000004d6826 in QMachine__FulfilExecPromise =3D3D >>>>> (M3_D6rRrg_ep=3D3D3D3D3=3D3D3D >>>>>>> DError=3D3D3D3D
>>>>>>> > accessing memory address 0x8000ffffb838: Bad =3D3D >>>>> address.<br>
>>>>>>> >) at ../src/QMachine.m3:1666<br>
>>>>>>> >#11 0x00000000004d6220 in QMachine__ExecCommand =3D3D >>>>> (M3_An02H2_t=3D3D3D3D3DError =3D3D3D >>>>>>> access=3D3D3D3D
>>>>>>> >ing memory address 0x8000ffffb9f8: Bad address.<br>
>>>>>>> >) at ../src/QMachine.m3:1605<br>
>>>>>>> >#12 0x00000000004d537e in QMachine__DoTryExec =3D3D >>>>> (M3_An02H2_t=3D3D3D3D3DError ac=3D3D3D >>>>>>> cessin=3D3D3D3D
>>>>>>> >g memory address 0x8000ffffbee8: Bad address.<br>
>>>>>>> >) at ../src/QMachine.m3:1476<br>
>>>>>>> ><br>
>>>>>>> >What am I doing wrong here?<br>
>>>>>>> ><br>
>>>>>>> >The error doesn&#39;t look unreasonable! =3D >>> =3D3D3D3DC2=3D3D3D3DA0Looking =3D3D >>>>> more clo=3D3D3D >>>>>>> sely at the =3D3D3D3D
>>>>>>> >code:<br>
>>>>>>> ><br>
>>>>>>> >First, AtForkPrepare has been called:<br>
>>>>>>> ><br>
>>>>>>> >PROCEDURE AtForkPrepare() =3D3D3D3D3D<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 VAR me :=3D3D3D3D3D =3D >>> GetActivation();<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 act: =3D3D=3D >>>=20 >>>>> Activation;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 BEGIN<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >PThreadLockMutex(slotsMu, =3D >>> =3D3D >>>>> ThisLine());<br><=3D3D3D >>>>>>> br> >>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >PThreadLockMutex(perfMu, =3D >>> =3D3D >>>>> ThisLine());<br>>>>>>> r> >>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >PThreadLockMutex(initMu, =3D >>> =3D3D >>>>> ThisLine()); (* InitMute=3D3D3D >>>>>>> x =3D3D3D3D3D&gt; Re=3D3D3D3D
>>>>>>> >gisterFinalCleanup =3D3D3D3D3D&gt; LockHeap = >*)<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >PThreadLockMutex(heapMu, =3D >>> =3D3D >>>>> ThisLine());<br>>>>>>> r> >>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> PThreadLockMutex(activeMu, =3D3D >>>>> ThisLine()); (* LockHe=3D3D3D >>>>>>> ap =3D3D3D3D3D&gt; S=3D3D3D3D
>>>>>>> >uspendOthers =3D3D3D3D3D&gt; activeMu *)<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 (* Walk = >activations and =3D >>> lock all =3D3D >>>>> threads.<br&g=3D3D3D >>>>>>> t;
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0* NOTE: =3D >>> We have =3D3D >>>>> initMu, activeMu, so sl=3D3D3D >>>>>>> ots won&#39;t ch=3D3D3D3D
>>>>>>> >ange, conditions and<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0* =3D >>> mutexes =3D3D >>>>> won&#39;t be initialized =3D3D3D >>>>>>> on-demand.<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> =3D3D3D3DC2=3D3D3D3DA0*)<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 act :=3D3D3D3D3D = >=3D >>> me;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >REPEAT<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 =3D3D >>>>> PThreadLockMutex(act.mutex, ThisLine()=3D3D3D >>>>>>> );<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 act =3D >>> :=3D3D3D3D3D =3D3D >>>>> act.next;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 UNTIL act = >=3D3D3D3D3D =3D >>> me;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 END AtForkPrepare;<br>
>>>>>>> ><br>
>>>>>>> >a postcondition of this routine is that heapMu is =3D3D >>>>> locked.<br>
>>>>>>> ><br>
>>>>>>> >now we get into AtForkParent:<br>
>>>>>>> ><br>
>>>>>>> >PROCEDURE AtForkParent() =3D3D3D3D3D<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 VAR me :=3D3D3D3D3D =3D >>> GetActivation();<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 act: =3D3D=3D >>>=20 >>>>> Activation;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 cond: =3D >>> =3D3D >>>>> Condition;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 BEGIN<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 (* Walk = >activations and =3D >>> unlock all =3D3D >>>>> threads, condi=3D3D3D >>>>>>> tions. *)<br=3D3D3D3D
>>>>>>> >>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 act :=3D3D3D3D3D = >=3D >>> me;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >REPEAT<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 cond =3D >>> :=3D3D3D3D3D =3D3D >>>>> slots[act.slot].join;<b=3D3D3D >>>>>>> r>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 IF =3D >>> cond # NIL THEN =3D3D >>>>> PThreadUnlockMutex(=3D3D3D >>>>>>> cond.mutex, This=3D3D3D3D
>>>>>>> >Line()) END;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 =3D3D >>>>> PThreadUnlockMutex(act.mutex, ThisLine=3D3D3D >>>>>>> ());<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 = >=3D3D3D3DC2=3D3D3D3DA0 act =3D >>> :=3D3D3D3D3D =3D3D >>>>> act.next;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 UNTIL act = >=3D3D3D3D3D =3D >>> me;<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> PThreadUnlockMutex(activeMu, =3D3D >>>>> ThisLine());<br&g=3D3D3D >>>>>>> t;
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> PThreadUnlockMutex(heapMu, =3D3D >>>>> ThisLine());<br>=3D3D3D >>>>>>>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> PThreadUnlockMutex(initMu, =3D3D >>>>> ThisLine());<br>=3D3D3D >>>>>>>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> PThreadUnlockMutex(perfMu, =3D3D >>>>> ThisLine());<br>=3D3D3D >>>>>>>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> PThreadUnlockMutex(slotsMu, =3D3D >>>>> ThisLine());<br>=3D3D3D >>>>>>> ;
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 END AtForkParent;<br>
>>>>>>> ><br>
>>>>>>> >We can see by inspecting the code that a necessary = >precondition =3D >>> =3D3D >>>>> for<=3D3D3D >>>>>>> br>
>>>>>>> >this routine is that heapMu is locked! = >=3D3D3D3DC2=3D3D3D3DA0(Since =3D >>> =3D3D >>>>> it&#39;s go=3D3D3D >>>>>>> ing to unloc=3D3D3D3D
>>>>>>> >k it,<br>
>>>>>>> >it had BETTER be locked on entry.)<br>
>>>>>>> ><br>
>>>>>>> >But the cond :=3D3D3D3D3D ... causes a =3D3D >>>>> RTHooks.CheckLoadTracedRef<br>>>>>>> r> >>>>>>> ><br>
>>>>>>> >which causes an RTOS.LockHeap<br>
>>>>>>> ><br>
>>>>>>> >the code of which we just saw:<br>
>>>>>>> ><br>
>>>>>>> >PROCEDURE LockHeap () =3D3D3D3D3D<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 VAR self :=3D3D3D3D3D =3D >>> pthread_self();<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 BEGIN<br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 WITH r = >=3D3D3D3D3D =3D3D >>>>> pthread_mutex_lock(heapMu,ThisLine()=3D3D3D >>>>>>> ) DO &lt;*ASSE=3D3D3D3D
>>>>>>> >RT r=3D3D3D3D3D0*&gt; END;<br>
>>>>>>> >...<br>
>>>>>>> ><br>
>>>>>>> >we try to lock heapMu. =3D3D3D3DC2=3D3D3D3DA0kaboom! =3D >>> =3D3D3D3DC2=3D3D3D3DA0No =3D3D >>>>> surprise there, r=3D3D3D >>>>>>> eally?<br>
>>>>>>> ><br>
>>>>>>> >Am I going about this totally the wrong way? =3D >>> =3D3D3D3DC2=3D3D3D3DA0Other =3D3D >>>>> people are=3D3D3D >>>>>>> running=3D3D3D3D
>>>>>>> > Modula-3<br>
>>>>>>> >with pthreads, right? =3D3D3D3DC2=3D3D3D3DA0Right?? =3D >>> =3D3D3D3DC2=3D3D3D3DA0Somewhere=3D3D >>>>> out there i=3D3D3D >>>>>>> n m3devel-la=3D3D3D3D
>>>>>>> >nd?<br>
>>>>>>> ><span><font =3D3D >>>>> color=3D3D3D3D3D"#888888"><br>
>>>>>>> >=3D3D3D3DC2=3D3D3D3DA0 =3D3D3D3DC2=3D3D3D3DA0 =3D >>> =3D3D3D3DC2=3D3D3D3DA0Mika<br>
>>>>>>> ><br>
>>>>>>> =3D3D >>>>> =3D >>> = >></font></span></blockquote></div><br><= >=3D >>> =3D3D >>>>> ;=3D3D3D >>>>>>> /div></div>
>>>>>>> >
>>>>>>> >--001a11c2ced4471a2e050079db82--
>>>>>>>

>>>>>>>

>>>>>>> =3D3D20 >>>>>>> --089e01183a1813188705007c3498-- From hosking at cs.purdue.edu Wed Aug 13 21:23:49 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Wed, 13 Aug 2014 15:23:49 -0400 Subject: [M3devel] LockHeap In-Reply-To: <20140813014758.7CF501A2094@async.async.caltech.edu> References: <20140813014758.7CF501A2094@async.async.caltech.edu> Message-ID: <9FF45484-840B-43AE-B2C2-47E66DD734DF@cs.purdue.edu> On Aug 12, 2014, at 9:47 PM, mika at async.caltech.edu wrote: > > The code in LockHeap looks dubious to me: Yes, it was a broken and incomplete attempt. I?ve reverted to what we used to have that actually works. > I note that the documentation in RTOS.i3 also seems slightly incorrect: > > PROCEDURE WaitHeap (VAR thread: RTHeapRep.ThreadState); > > Blocks the caller until BroadcastHeap has been called and the allocator/collector critical section is released. The caller must be in the critical section. > > Shouldn't it say "The calling thread must have entered the critical > section exactly once."? (Given that the "LockHeap" is reentrant?) Yes, true. > Why is there a reentrant mutex here, anyhow? Reentrant because it is possible for the collector thread to try to re-enter the collector when performing allocation. It would be possible to carry a flag down through the recursion, but this is the way it has always been (since DEC SRC days). From hosking at cs.purdue.edu Wed Aug 13 21:40:32 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Wed, 13 Aug 2014 15:40:32 -0400 Subject: [M3devel] Latest pthreads attempt In-Reply-To: <20140812221209.9D5F51A2094@async.async.caltech.edu> References: <8B27D029-50B0-49B9-B673-34C128B103BB@cs.purdue.edu> <20140812221209.9D5F51A2094@async.async.caltech.edu> Message-ID: <390F3ADB-C1EC-4C2B-BEC0-2630D6721470@cs.purdue.edu> On Aug 12, 2014, at 6:12 PM, mika at async.caltech.edu wrote: > Tony, > > I've been reading a bit of the pthread code and I have a question... > > What if one were to write a ThreadPThread that is a very thin veneer > over pthreads? What goes wrong? That is, simply translate Modula-3 > calls Thread.Acquire to pthread_lock(...), Modula-3 condition variables > to pthread condition variables, etc. Way back in the dim dark days of early pthreads for Modula-3 this is exactly what we had. But it turned out to make a lot of the Modula-3 thread semantics difficult/impossible to implement. I?d have to trawl through the logs to recall the specifics. But it would still make fork impossible to implement because threads could have an arbitrary set of locks locked at the fork. > I know Alerted is a bit different but it's cooperative: both the waiter > and alerter know they are going to be Alerted (so it could be less > efficient and have extra data structures). I seem to recall that was one of the issues. > Would there be issues with the garbage collector? Some inefficiency? Hmm. Not sure. The GC is fairly agnostic so long as allocation is not interruptible (hence the inCritical flag in the heapState field). > I think I am mainly worried about the presence of "GetActivation()" > in critical places like LockMutex and UnlockMutex. Maybe it's not a > big deal anymore...(it used to be a real drag at least on FreeBSD > because it involved a system call). Tough to get away with that if we wrap pthread mutexes like we do. But yes, much cheaper on modern thread implementations. And wrapping allows us to go to a thin-lock implementation using CAS (acquire of an uncontended mutex is simply CAS(ADR(m.holder), NIL, self). A contended mutex can be detected by setting a low bit in the holder field. And even better, we can implement biased locking, wherein an uncontended lock is biased towards one particular thread which can lock it without CAS. Revoking the bias requires stopping the thread holding the bias, clearing it, and resuming. Need more time... > > Mika > From dragisha at m3w.org Wed Aug 13 21:47:45 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 13 Aug 2014 21:47:45 +0200 Subject: [M3devel] Latest pthreads attempt In-Reply-To: <390F3ADB-C1EC-4C2B-BEC0-2630D6721470@cs.purdue.edu> References: <8B27D029-50B0-49B9-B673-34C128B103BB@cs.purdue.edu> <20140812221209.9D5F51A2094@async.async.caltech.edu> <390F3ADB-C1EC-4C2B-BEC0-2630D6721470@cs.purdue.edu> Message-ID: <7969380F-47F8-40D3-A7DD-789DC2D548FA@m3w.org> CAS locking is exactly what is used in futexes so we have that kind of being-thin functionality at least in Linuxes. Futexes are around for more than 10yrs now so I believe it is pretty common already. On 13 Aug 2014, at 21:40, Tony Hosking wrote: > Tough to get away with that if we wrap pthread mutexes like we do. But yes, much cheaper on modern thread implementations. And wrapping allows us to go to a thin-lock implementation using CAS (acquire of an uncontended mutex is simply CAS(ADR(m.holder), NIL, self). A contended mutex can be detected by setting a low bit in the holder field. And even better, we can implement biased locking, wherein an uncontended lock is biased towards one particular thread which can lock it without CAS. Revoking the bias requires stopping the thread holding the bias, clearing it, and resuming. > > Need more time... -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hosking at cs.purdue.edu Wed Aug 13 23:47:08 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Wed, 13 Aug 2014 17:47:08 -0400 Subject: [M3devel] Latest pthreads attempt In-Reply-To: <7969380F-47F8-40D3-A7DD-789DC2D548FA@m3w.org> References: <8B27D029-50B0-49B9-B673-34C128B103BB@cs.purdue.edu> <20140812221209.9D5F51A2094@async.async.caltech.edu> <390F3ADB-C1EC-4C2B-BEC0-2630D6721470@cs.purdue.edu> <7969380F-47F8-40D3-A7DD-789DC2D548FA@m3w.org> Message-ID: <9E32AA9C-A95D-4AE9-8F8B-183DD348A5EB@cs.purdue.edu> Yes, indeed. Unfortunately, only on Linux... On Aug 13, 2014, at 3:47 PM, Dragi?a Duri? wrote: > CAS locking is exactly what is used in futexes so we have that kind of being-thin functionality at least in Linuxes. Futexes are around for more than 10yrs now so I believe it is pretty common already. > > On 13 Aug 2014, at 21:40, Tony Hosking wrote: > >> Tough to get away with that if we wrap pthread mutexes like we do. But yes, much cheaper on modern thread implementations. And wrapping allows us to go to a thin-lock implementation using CAS (acquire of an uncontended mutex is simply CAS(ADR(m.holder), NIL, self). A contended mutex can be detected by setting a low bit in the holder field. And even better, we can implement biased locking, wherein an uncontended lock is biased towards one particular thread which can lock it without CAS. Revoking the bias requires stopping the thread holding the bias, clearing it, and resuming. >> >> Need more time... > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Sun Aug 17 11:40:50 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 17 Aug 2014 11:40:50 +0200 Subject: [M3devel] --> Git Message-ID: <31B6D683-1B33-47EA-A93C-2846EF76E0DE@m3w.org> You probably all know differences between theory and practice. In theory, there are none. In practice - a lot of them! :) I have identified three main ways to convert CVS to Git. One looked most promising as it is bidirectional (and incremental) - using git cvsimport. I did this one, and its result is at github right now. But - it is not good. Some files show wrong version in HEAD. git cvsimport depends on old version of cvsps, and those cvsps people probably released newer version for some reason(s)? As long as I don?t want to dive into cvsps / git cvsimport source codes, no solution there. And I really do not have that kind of interest and/or time. Ok, no incremental? This is where I tried cvs2git. It works well but it does not map authors (svn2git does, but although cvs2git comes from same team, features are not in concert). There is some arcane way proposed, but I lost trust when I saw svn2git from same team supports authors file, but cvs2git does not. Not big issue, but I had that in first try so I tried third way. Third way is cvs2svn, and then git svn clone. Results look good, esp. after applying some after processing proposed bu Git people. One proposal there is to not convert whole repository history. My idea is to convert from just before 5.8.6 was released (July 2010). Does anybody have something against this? I will still keep original CVS repo, and SVN conversion results (where all history is accessible). If there is oposition, I will spend some more CPU time and make full history available through Git. There are around 10000 svn revisions before July 2010, and total of 12752 as of today. Please advise :) TIA, dd -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Sun Aug 17 19:03:08 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 17 Aug 2014 19:03:08 +0200 Subject: [M3devel] --> Git In-Reply-To: <3220E55D-72BE-4C5B-902A-962707564ED0@purdue.edu> References: <31B6D683-1B33-47EA-A93C-2846EF76E0DE@m3w.org> <3220E55D-72BE-4C5B-902A-962707564ED0@purdue.edu> Message-ID: <2E5C7A76-845D-4F04-8325-DFF798523D31@m3w.org> Thanks for info, it will be so. Now, on boxes I am using it takes about 6 hours to do whole conversion and I cannot do it incrementally. It would be great if we arrange few tests and then turn CVS read-only and switch to using Git. I will push current CVS converted to github in few minutes. On 17 Aug 2014, at 18:19, Antony Hosking wrote: > I would dearly like to preserve the entire history. It has significant value. > > Sent from my iPhone > >> On Aug 17, 2014, at 5:40 AM, Dragi?a Duri? wrote: >> >> You probably all know differences between theory and practice. In theory, there are none. In practice - a lot of them! :) >> >> I have identified three main ways to convert CVS to Git. >> >> One looked most promising as it is bidirectional (and incremental) - using git cvsimport. I did this one, and its result is at github right now. But - it is not good. Some files show wrong version in HEAD. git cvsimport depends on old version of cvsps, and those cvsps people probably released newer version for some reason(s)? As long as I don?t want to dive into cvsps / git cvsimport source codes, no solution there. And I really do not have that kind of interest and/or time. >> >> Ok, no incremental? This is where I tried cvs2git. It works well but it does not map authors (svn2git does, but although cvs2git comes from same team, features are not in concert). There is some arcane way proposed, but I lost trust when I saw svn2git from same team supports authors file, but cvs2git does not. Not big issue, but I had that in first try so I tried third way. >> >> Third way is cvs2svn, and then git svn clone. Results look good, esp. after applying some after processing proposed bu Git people. >> >> One proposal there is to not convert whole repository history. My idea is to convert from just before 5.8.6 was released (July 2010). Does anybody have something against this? I will still keep original CVS repo, and SVN conversion results (where all history is accessible). If there is oposition, I will spend some more CPU time and make full history available through Git. There are around 10000 svn revisions before July 2010, and total of 12752 as of today. >> >> Please advise :) >> >> TIA, >> dd >> -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Sun Aug 17 20:20:33 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Sun, 17 Aug 2014 20:20:33 +0200 Subject: [M3devel] --> Git In-Reply-To: <2E5C7A76-845D-4F04-8325-DFF798523D31@m3w.org> References: <31B6D683-1B33-47EA-A93C-2846EF76E0DE@m3w.org> <3220E55D-72BE-4C5B-902A-962707564ED0@purdue.edu> <2E5C7A76-845D-4F04-8325-DFF798523D31@m3w.org> Message-ID: # git push --all --force Counting objects: 134952, done. Delta compression using up to 4 threads. Compressing objects: 100% (59339/59339), done. Writing objects: 100% (134952/134952), 166.60 MiB | 827.00 KiB/s, done. Total 134952 (delta 92451), reused 114795 (delta 73863) remote: warning: GH001: Large files detected. remote: warning: See http://git.io/iEPt8g for more information. remote: warning: File m3-sys/m3tests/src/p2/p227/stdout.pgm is 52.44 MB; this is larger than GitHub's recommended maximum file size of 50 MB remote: warning: File m3-sys/m3tests/src/p2/p227/stdout.pgm-little_endian32 is 52.44 MB; this is larger than GitHub's recommended maximum file size of 50 MB To https://github.com/dragisha/cm3.git + 0b54fd3...6216c2d master -> master (forced update) + 24a4428...56a30c3 release_branch_cm3_5_8 -> release_branch_cm3_5_8 (forced update) * [new branch] FSF_GCC_4_5 -> FSF_GCC_4_5 * [new branch] FSF_GCC_4_7 -> FSF_GCC_4_7 * [new branch] branch_feature_longint_offset -> branch_feature_longint_offset * [new branch] devel_m3core_text_newtext_branch -> devel_m3core_text_newtext_branch * [new branch] devel_unicode -> devel_unicode * [new branch] gcc -> gcc * [new branch] trunk -> trunk Here we are. Please test this HEAD at least, I will do the same today and tomorrow. Also - let?s make this final, if possible. I can speed this conversion up but it would be the best to make this final if tests pass - so we can free CVS repo and start to reap Git benefits. TIA, dd On 17 Aug 2014, at 19:03, Dragi?a Duri? wrote: > Thanks for info, it will be so. > > Now, on boxes I am using it takes about 6 hours to do whole conversion and I cannot do it incrementally. > > It would be great if we arrange few tests and then turn CVS read-only and switch to using Git. I will push current CVS converted to github in few minutes. > > > > On 17 Aug 2014, at 18:19, Antony Hosking wrote: > >> I would dearly like to preserve the entire history. It has significant value. >> >> Sent from my iPhone >> >>> On Aug 17, 2014, at 5:40 AM, Dragi?a Duri? wrote: >>> >>> You probably all know differences between theory and practice. In theory, there are none. In practice - a lot of them! :) >>> >>> I have identified three main ways to convert CVS to Git. >>> >>> One looked most promising as it is bidirectional (and incremental) - using git cvsimport. I did this one, and its result is at github right now. But - it is not good. Some files show wrong version in HEAD. git cvsimport depends on old version of cvsps, and those cvsps people probably released newer version for some reason(s)? As long as I don?t want to dive into cvsps / git cvsimport source codes, no solution there. And I really do not have that kind of interest and/or time. >>> >>> Ok, no incremental? This is where I tried cvs2git. It works well but it does not map authors (svn2git does, but although cvs2git comes from same team, features are not in concert). There is some arcane way proposed, but I lost trust when I saw svn2git from same team supports authors file, but cvs2git does not. Not big issue, but I had that in first try so I tried third way. >>> >>> Third way is cvs2svn, and then git svn clone. Results look good, esp. after applying some after processing proposed bu Git people. >>> >>> One proposal there is to not convert whole repository history. My idea is to convert from just before 5.8.6 was released (July 2010). Does anybody have something against this? I will still keep original CVS repo, and SVN conversion results (where all history is accessible). If there is oposition, I will spend some more CPU time and make full history available through Git. There are around 10000 svn revisions before July 2010, and total of 12752 as of today. >>> >>> Please advise :) >>> >>> TIA, >>> dd >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From rodney_bates at lcwb.coop Mon Aug 18 23:29:28 2014 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Mon, 18 Aug 2014 16:29:28 -0500 Subject: [M3devel] --> Git In-Reply-To: References: <31B6D683-1B33-47EA-A93C-2846EF76E0DE@m3w.org> <3220E55D-72BE-4C5B-902A-962707564ED0@purdue.edu> <2E5C7A76-845D-4F04-8325-DFF798523D31@m3w.org> Message-ID: <53F27038.3080909@lcwb.coop> On 08/17/2014 01:20 PM, Dragi?a Duri? wrote: > # git push --all --force > Counting objects: 134952, done. > Delta compression using up to 4 threads. > Compressing objects: 100% (59339/59339), done. > Writing objects: 100% (134952/134952), 166.60 MiB | 827.00 KiB/s, done. > Total 134952 (delta 92451), reused 114795 (delta 73863) > remote: warning: GH001: Large files detected. > remote: warning: See http://git.io/iEPt8g for more information. > remote: warning: File m3-sys/m3tests/src/p2/p227/stdout.pgm is 52.44 MB; this is larger than GitHub's recommended maximum file size of 50 MB > remote: warning: File m3-sys/m3tests/src/p2/p227/stdout.pgm-little_endian32 is 52.44 MB; this is larger than GitHub's recommended maximum file size of 50 MB > To https://github.com/dragisha/cm3.git > + 0b54fd3...6216c2d master -> master (forced update) > + 24a4428...56a30c3 release_branch_cm3_5_8 -> release_branch_cm3_5_8 (forced update) > * [new branch] FSF_GCC_4_5 -> FSF_GCC_4_5 > * [new branch] FSF_GCC_4_7 -> FSF_GCC_4_7 > * [new branch] branch_feature_longint_offset -> branch_feature_longint_offset > * [new branch] devel_m3core_text_newtext_branch -> devel_m3core_text_newtext_branch > * [new branch] devel_unicode -> devel_unicode > * [new branch] gcc -> gcc > * [new branch] trunk -> trunk > > Here we are. > > Please test this HEAD at least, I will do the same today and tomorrow. Also - let?s make this final, if possible. I can speed this conversion up but it would be the best to make this final if tests pass - so we can free CVS repo and start to reap Git benefits. > > TIA, > dd I was able to git-clone cm3 and pm3 on two machines and, on LINUXLIBC6, build, install, and rebuild the "front" group from the sources in the git checkout, then build as much else as I expect to also build in the cvs checkout. A diff between the cvs and git checkouts was less than conclusive, because of overwhelming irrelevant differences, especially .mx & .m3x files. Still, it looks like the only differences I see in relevant files are changes of \r\n to \n, in a few files, e.g. m3-www/http/src/App.i3 > > On 17 Aug 2014, at 19:03, Dragi?a Duri? > wrote: > >> Thanks for info, it will be so. >> >> Now, on boxes I am using it takes about 6 hours to do whole conversion and I cannot do it incrementally. >> >> It would be great if we arrange few tests and then turn CVS read-only and switch to using Git. I will push current CVS converted to github in few minutes. >> >> >> >> On 17 Aug 2014, at 18:19, Antony Hosking > wrote: >> >>> I would dearly like to preserve the entire history. It has significant value. >>> >>> Sent from my iPhone >>> >>>> On Aug 17, 2014, at 5:40 AM, Dragi?a Duri? > wrote: >>>> >>>> You probably all know differences between theory and practice. In theory, there are none. In practice - a lot of them! :) >>>> >>>> I have identified three main ways to convert CVS to Git. >>>> >>>> One looked most promising as it is bidirectional (and incremental) - using git cvsimport. I did this one, and its result is at github right now. But - it is not good. Some files show wrong version in HEAD. git cvsimport depends on old version of cvsps, and those cvsps people probably released newer version for some reason(s)? As long as I don?t want to dive into cvsps / git cvsimport source codes, no solution there. And I really do not have that kind of interest and/or time. >>>> >>>> Ok, no incremental? This is where I tried cvs2git. It works well but it does not map authors (svn2git does, but although cvs2git comes from same team, features are not in concert). There is some arcane way proposed, but I lost trust when I saw svn2git from same team supports authors file, but cvs2git does not. Not big issue, but I had that in first try so I tried third way. >>>> >>>> Third way is cvs2svn, and then git svn clone. Results look good, esp. after applying some after processing proposed bu Git people. >>>> >>>> One proposal there is to not convert whole repository history. My idea is to convert from just before 5.8.6 was released (July 2010). Does anybody have something against this? I will still keep original CVS repo, and SVN conversion results (where all history is accessible). If there is oposition, I will spend some more CPU time and make full history available through Git. There are around 10000 svn revisions before July 2010, and total of 12752 as of today. >>>> >>>> Please advise :) >>>> >>>> TIA, >>>> dd >>>> >> > -- Rodney Bates rodney.m.bates at acm.org From dragisha at m3w.org Tue Aug 19 08:14:24 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 08:14:24 +0200 Subject: [M3devel] --> Git In-Reply-To: <53F27038.3080909@lcwb.coop> References: <31B6D683-1B33-47EA-A93C-2846EF76E0DE@m3w.org> <3220E55D-72BE-4C5B-902A-962707564ED0@purdue.edu> <2E5C7A76-845D-4F04-8325-DFF798523D31@m3w.org> <53F27038.3080909@lcwb.coop> Message-ID: Thanks Rodney! I have run SVN -> Git step once over because (as Darko pointed it out for me) a version from SVN rev 3300+ was used mistakenly. It is corrected now. From SVN to Git - diff shows _zero_ differences. From CVS to Git - a lot - but all I saw while looking through were CVS keyword replacements. dd On 18 Aug 2014, at 23:29, Rodney M. Bates wrote: > > > On 08/17/2014 01:20 PM, Dragi?a Duri? wrote: >> # git push --all --force >> Counting objects: 134952, done. >> Delta compression using up to 4 threads. >> Compressing objects: 100% (59339/59339), done. >> Writing objects: 100% (134952/134952), 166.60 MiB | 827.00 KiB/s, done. >> Total 134952 (delta 92451), reused 114795 (delta 73863) >> remote: warning: GH001: Large files detected. >> remote: warning: See http://git.io/iEPt8g for more information. >> remote: warning: File m3-sys/m3tests/src/p2/p227/stdout.pgm is 52.44 MB; this is larger than GitHub's recommended maximum file size of 50 MB >> remote: warning: File m3-sys/m3tests/src/p2/p227/stdout.pgm-little_endian32 is 52.44 MB; this is larger than GitHub's recommended maximum file size of 50 MB >> To https://github.com/dragisha/cm3.git >> + 0b54fd3...6216c2d master -> master (forced update) >> + 24a4428...56a30c3 release_branch_cm3_5_8 -> release_branch_cm3_5_8 (forced update) >> * [new branch] FSF_GCC_4_5 -> FSF_GCC_4_5 >> * [new branch] FSF_GCC_4_7 -> FSF_GCC_4_7 >> * [new branch] branch_feature_longint_offset -> branch_feature_longint_offset >> * [new branch] devel_m3core_text_newtext_branch -> devel_m3core_text_newtext_branch >> * [new branch] devel_unicode -> devel_unicode >> * [new branch] gcc -> gcc >> * [new branch] trunk -> trunk >> >> Here we are. >> >> Please test this HEAD at least, I will do the same today and tomorrow. Also - let?s make this final, if possible. I can speed this conversion up but it would be the best to make this final if tests pass - so we can free CVS repo and start to reap Git benefits. >> >> TIA, >> dd > > I was able to git-clone cm3 and pm3 on two machines and, on LINUXLIBC6, build, install, > and rebuild the "front" group from the sources in the git checkout, then build as much > else as I expect to also build in the cvs checkout. > > A diff between the cvs and git checkouts was less than conclusive, because of overwhelming > irrelevant differences, especially .mx & .m3x files. Still, it looks like the only differences > I see in relevant files are changes of \r\n to \n, in a few files, e.g. m3-www/http/src/App.i3 > >> >> On 17 Aug 2014, at 19:03, Dragi?a Duri? > wrote: >> >>> Thanks for info, it will be so. >>> >>> Now, on boxes I am using it takes about 6 hours to do whole conversion and I cannot do it incrementally. >>> >>> It would be great if we arrange few tests and then turn CVS read-only and switch to using Git. I will push current CVS converted to github in few minutes. >>> >>> >>> >>> On 17 Aug 2014, at 18:19, Antony Hosking > wrote: >>> >>>> I would dearly like to preserve the entire history. It has significant value. >>>> >>>> Sent from my iPhone >>>> >>>>> On Aug 17, 2014, at 5:40 AM, Dragi?a Duri? > wrote: >>>>> >>>>> You probably all know differences between theory and practice. In theory, there are none. In practice - a lot of them! :) >>>>> >>>>> I have identified three main ways to convert CVS to Git. >>>>> >>>>> One looked most promising as it is bidirectional (and incremental) - using git cvsimport. I did this one, and its result is at github right now. But - it is not good. Some files show wrong version in HEAD. git cvsimport depends on old version of cvsps, and those cvsps people probably released newer version for some reason(s)? As long as I don?t want to dive into cvsps / git cvsimport source codes, no solution there. And I really do not have that kind of interest and/or time. >>>>> >>>>> Ok, no incremental? This is where I tried cvs2git. It works well but it does not map authors (svn2git does, but although cvs2git comes from same team, features are not in concert). There is some arcane way proposed, but I lost trust when I saw svn2git from same team supports authors file, but cvs2git does not. Not big issue, but I had that in first try so I tried third way. >>>>> >>>>> Third way is cvs2svn, and then git svn clone. Results look good, esp. after applying some after processing proposed bu Git people. >>>>> >>>>> One proposal there is to not convert whole repository history. My idea is to convert from just before 5.8.6 was released (July 2010). Does anybody have something against this? I will still keep original CVS repo, and SVN conversion results (where all history is accessible). If there is oposition, I will spend some more CPU time and make full history available through Git. There are around 10000 svn revisions before July 2010, and total of 12752 as of today. >>>>> >>>>> Please advise :) >>>>> >>>>> TIA, >>>>> dd >>>>> >>> >> > > -- > Rodney Bates > rodney.m.bates at acm.org -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From mika at async.caltech.edu Tue Aug 19 10:13:09 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 19 Aug 2014 01:13:09 -0700 Subject: [M3devel] m3gdb status? Message-ID: <20140819081309.3D9251A2095@async.async.caltech.edu> What is the status of m3gdb? I am on AMD64_LINUX here...head from CVS. The error looks pedantic but the fact that things aren't building makes me think maybe this code is pretty dusty...? /bin/sh ../../gdb/bfd/../move-if-change bfd-tmp.h bfd.h rm -f bfd-tmp.h touch stmp-bfd-h /bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c -o archive.lo ../../gdb/bfd/archive.c gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c ../../gdb/bfd/archive.c -o archive.o ../../gdb/bfd/archive.c: In function 'bfd_generic_archive_p': ../../gdb/bfd/archive.c:669:16: error: variable 'fail' set but not used [-Werror=unused-but-set-variable] cc1: all warnings being treated as errors make[4]: *** [archive.lo] Error 1 make[4]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' make[3]: *** [all-recursive] Error 1 make[3]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' make[2]: *** [all] Error 2 make[2]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' make[1]: *** [all-bfd] Error 2 make[1]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX' make: *** [all] Error 2 "/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile", line 40: quake runtime error: exit 2: make MAKE=make MAKEINFO=: --procedure-- -line- -file--- exec -- m3gdb_Run 40 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile include_dir 85 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile 4 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/m3make.args Fatal Error: package build failed (326)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/m3gdb> From rodney_bates at lcwb.coop Tue Aug 19 18:14:13 2014 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 19 Aug 2014 11:14:13 -0500 Subject: [M3devel] m3gdb status? In-Reply-To: <20140819081309.3D9251A2095@async.async.caltech.edu> References: <20140819081309.3D9251A2095@async.async.caltech.edu> Message-ID: <53F377D5.8060505@lcwb.coop> It's very dusty: looks unchanged since brought into the M3 repository from gdb 6.4, in 2006. However, I have built m3gdb many times since then, with neither build failures nor bugs that are likely to have anything to do with bfd/archive.c. It looks like a harmless warning, from the original gdb, turned into an error by the -Werror flag to gcc. I last successfully compiled archive.c on 2013-10-21 for AMD64_LINUX and on 2014-6-23 for LINUXLIBC6. Perhaps the -Werror flag has became a default in gcc since. In a quick scan using grep, I didn't see anywhere in the M3 distribution or installation that would have set it. Changing -Werror to -Wno-error in variable WARN_CFLAGS in AMD64_LINUX/bfd/Makefile and AMD64_LINUX/opcodes/Makefile got me through all the compile problems (hit unrelated link problems). But that's the wrong solution, as these Makefiles are, I am sure, mechanically generated from somewhere else, no doubt configure. I haven't figured out where it comes from originally. On 08/19/2014 03:13 AM, mika at async.caltech.edu wrote: > What is the status of m3gdb? > > I am on AMD64_LINUX here...head from CVS. > > The error looks pedantic but the fact that things aren't building makes me think maybe this code is pretty dusty...? > > /bin/sh ../../gdb/bfd/../move-if-change bfd-tmp.h bfd.h > rm -f bfd-tmp.h > touch stmp-bfd-h > /bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c -o archive.lo ../../gdb/bfd/archive.c > gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c ../../gdb/bfd/archive.c -o archive.o > ../../gdb/bfd/archive.c: In function 'bfd_generic_archive_p': > ../../gdb/bfd/archive.c:669:16: error: variable 'fail' set but not used [-Werror=unused-but-set-variable] > cc1: all warnings being treated as errors > make[4]: *** [archive.lo] Error 1 > make[4]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' > make[3]: *** [all-recursive] Error 1 > make[3]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' > make[2]: *** [all] Error 2 > make[2]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' > make[1]: *** [all-bfd] Error 2 > make[1]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX' > make: *** [all] Error 2 > "/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile", line 40: quake runtime error: exit 2: make MAKE=make MAKEINFO=: > > --procedure-- -line- -file--- > exec -- > m3gdb_Run 40 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile > include_dir 85 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile > 4 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/m3make.args > > Fatal Error: package build failed > (326)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/m3gdb> > > > > -- Rodney Bates rodney.m.bates at acm.org From dragisha at m3w.org Tue Aug 19 18:26:14 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 18:26:14 +0200 Subject: [M3devel] cm3 @ OSX Mavericks Message-ID: Anybody has working cm3 on 10.9.4 OSX? Care to upload cm3-bin-core-AMD64_LINUX..? TIA, dd -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Tue Aug 19 18:35:07 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 18:35:07 +0200 Subject: [M3devel] cm3 @ OSX Mavericks In-Reply-To: References: Message-ID: It would be great to have latest from other platforms too. I am just trying to make mine for LINUXLIBC6, and earlier today I have failed to do it for AMD64_LINUX and AMD64_DARWIN. While I am sure it is solvable, it would be better to not solve things other people already did :). TIA, dd On 19 Aug 2014, at 18:26, Dragi?a Duri? wrote: > Anybody has working cm3 on 10.9.4 OSX? Care to upload cm3-bin-core-AMD64_LINUX..? > > TIA, > dd > > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Tue Aug 19 18:54:27 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 18:54:27 +0200 Subject: [M3devel] cm3 @ OSX Mavericks In-Reply-To: <604BEF67-A967-41ED-BECF-4776244EEC3B@purdue.edu> References: <604BEF67-A967-41ED-BECF-4776244EEC3B@purdue.edu> Message-ID: <8BA92447-1451-443A-AAEF-2B6FC163AA04@m3w.org> I did: cd scripts ./makebin-dist-min.sh Got a lot of output and:?. creating distribution archive /var/tmp/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz -rw-rw-r--. 1 root root 21636241 Aug 19 18:38 /var/tmp/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz cleaning up Copied this file to birch.elegosoft.com:/var/www/modula3.elegosoft.com/cm3/uploaded-archives Ran Jay?s update... /var/www/modula3.elegosoft.com/cm3/uploaded-archives/update-download-index.sh Last time I tried this, index file was rewritten. But, nevertheless - uploaded file remained where I put it. Right now, LINUXLIBC6 from Git HEAD is at: http://opencm3.net/uploaded-archives/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz Please upload your archives there! TIA, dd On 19 Aug 2014, at 18:30, Antony Hosking wrote: > I do. One small fix needed to head to fix a change in OSX pthread library. Should have it done this week. > I?ll upload AMD64_DARWIN then. Remind me. How do I package it? It has been a long time since I built/bootstrapped using the scripts. Usually I do by hand. In fact, I am still using an old cm3cg and old cm3.cfg. > > What are the latest instructions for installing fresh? I took a quick look and things looked pretty daunting? too many scripts that I don?t understand. > > On Aug 19, 2014, at 12:26 PM, Dragi?a Duri? wrote: > >> Anybody has working cm3 on 10.9.4 OSX? Care to upload cm3-bin-core-AMD64_LINUX..? >> >> TIA, >> dd >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From rodney_bates at lcwb.coop Tue Aug 19 18:54:44 2014 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 19 Aug 2014 11:54:44 -0500 Subject: [M3devel] m3gdb status? In-Reply-To: <53F377D5.8060505@lcwb.coop> References: <20140819081309.3D9251A2095@async.async.caltech.edu> <53F377D5.8060505@lcwb.coop> Message-ID: <53F38154.6020204@lcwb.coop> The change I just checked in to m3-sys/m3gdb/src/m3makefile gets it back to building while tolerating warnings. There are many compile warnings in this dusty code, a lot of them from original gdb 64. You have to reconfigure, so do a realclean, before building. On 08/19/2014 11:14 AM, Rodney M. Bates wrote: > It's very dusty: looks unchanged since brought into the M3 repository from > gdb 6.4, in 2006. However, I have built m3gdb many times since then, with > neither build failures nor bugs that are likely to have anything to do with > bfd/archive.c. It looks like a harmless warning, from the original gdb, > turned into an error by the -Werror flag to gcc. > > I last successfully compiled archive.c on 2013-10-21 for AMD64_LINUX and on > 2014-6-23 for LINUXLIBC6. Perhaps the -Werror flag has became a default > in gcc since. In a quick scan using grep, I didn't see anywhere in the M3 > distribution or installation that would have set it. > > Changing -Werror to -Wno-error in variable WARN_CFLAGS in AMD64_LINUX/bfd/Makefile > and AMD64_LINUX/opcodes/Makefile got me through all the compile problems (hit > unrelated link problems). But that's the wrong solution, as these Makefiles > are, I am sure, mechanically generated from somewhere else, no doubt configure. > I haven't figured out where it comes from originally. > > On 08/19/2014 03:13 AM, mika at async.caltech.edu wrote: >> What is the status of m3gdb? >> >> I am on AMD64_LINUX here...head from CVS. >> >> The error looks pedantic but the fact that things aren't building makes me think maybe this code is pretty dusty...? >> >> /bin/sh ../../gdb/bfd/../move-if-change bfd-tmp.h bfd.h >> rm -f bfd-tmp.h >> touch stmp-bfd-h >> /bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c -o archive.lo ../../gdb/bfd/archive.c >> gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c ../../gdb/bfd/archive.c -o archive.o >> ../../gdb/bfd/archive.c: In function 'bfd_generic_archive_p': >> ../../gdb/bfd/archive.c:669:16: error: variable 'fail' set but not used [-Werror=unused-but-set-variable] >> cc1: all warnings being treated as errors >> make[4]: *** [archive.lo] Error 1 >> make[4]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >> make[3]: *** [all-recursive] Error 1 >> make[3]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >> make[2]: *** [all] Error 2 >> make[2]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >> make[1]: *** [all-bfd] Error 2 >> make[1]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX' >> make: *** [all] Error 2 >> "/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile", line 40: quake runtime error: exit 2: make MAKE=make MAKEINFO=: >> >> --procedure-- -line- -file--- >> exec -- >> m3gdb_Run 40 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile >> include_dir 85 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile >> 4 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/m3make.args >> >> Fatal Error: package build failed >> (326)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/m3gdb> >> >> >> >> > -- Rodney Bates rodney.m.bates at acm.org From dragisha at m3w.org Tue Aug 19 19:03:43 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 19:03:43 +0200 Subject: [M3devel] m3gdb status? In-Reply-To: <53F38154.6020204@lcwb.coop> References: <20140819081309.3D9251A2095@async.async.caltech.edu> <53F377D5.8060505@lcwb.coop> <53F38154.6020204@lcwb.coop> Message-ID: <5D3D021A-5A97-411A-8CB3-8DDF6CE20780@m3w.org> Rodney, It would be great if you can commit same change to Git as conversion I had to do in end is not incremental. Thanks! dd On 19 Aug 2014, at 18:54, Rodney M. Bates wrote: > The change I just checked in to m3-sys/m3gdb/src/m3makefile gets it back to > building while tolerating warnings. There are many compile warnings in this > dusty code, a lot of them from original gdb 64. > > You have to reconfigure, so do a realclean, before building. > > On 08/19/2014 11:14 AM, Rodney M. Bates wrote: >> It's very dusty: looks unchanged since brought into the M3 repository from >> gdb 6.4, in 2006. However, I have built m3gdb many times since then, with >> neither build failures nor bugs that are likely to have anything to do with >> bfd/archive.c. It looks like a harmless warning, from the original gdb, >> turned into an error by the -Werror flag to gcc. >> >> I last successfully compiled archive.c on 2013-10-21 for AMD64_LINUX and on >> 2014-6-23 for LINUXLIBC6. Perhaps the -Werror flag has became a default >> in gcc since. In a quick scan using grep, I didn't see anywhere in the M3 >> distribution or installation that would have set it. >> >> Changing -Werror to -Wno-error in variable WARN_CFLAGS in AMD64_LINUX/bfd/Makefile >> and AMD64_LINUX/opcodes/Makefile got me through all the compile problems (hit >> unrelated link problems). But that's the wrong solution, as these Makefiles >> are, I am sure, mechanically generated from somewhere else, no doubt configure. >> I haven't figured out where it comes from originally. >> >> On 08/19/2014 03:13 AM, mika at async.caltech.edu wrote: >>> What is the status of m3gdb? >>> >>> I am on AMD64_LINUX here...head from CVS. >>> >>> The error looks pedantic but the fact that things aren't building makes me think maybe this code is pretty dusty...? >>> >>> /bin/sh ../../gdb/bfd/../move-if-change bfd-tmp.h bfd.h >>> rm -f bfd-tmp.h >>> touch stmp-bfd-h >>> /bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c -o archive.lo ../../gdb/bfd/archive.c >>> gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c ../../gdb/bfd/archive.c -o archive.o >>> ../../gdb/bfd/archive.c: In function 'bfd_generic_archive_p': >>> ../../gdb/bfd/archive.c:669:16: error: variable 'fail' set but not used [-Werror=unused-but-set-variable] >>> cc1: all warnings being treated as errors >>> make[4]: *** [archive.lo] Error 1 >>> make[4]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >>> make[3]: *** [all-recursive] Error 1 >>> make[3]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >>> make[2]: *** [all] Error 2 >>> make[2]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >>> make[1]: *** [all-bfd] Error 2 >>> make[1]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX' >>> make: *** [all] Error 2 >>> "/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile", line 40: quake runtime error: exit 2: make MAKE=make MAKEINFO=: >>> >>> --procedure-- -line- -file--- >>> exec -- >>> m3gdb_Run 40 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile >>> include_dir 85 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile >>> 4 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/m3make.args >>> >>> Fatal Error: package build failed >>> (326)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/m3gdb> >>> >>> >>> >>> >> > > -- > Rodney Bates > rodney.m.bates at acm.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Tue Aug 19 20:29:10 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 20:29:10 +0200 Subject: [M3devel] Another! This time AMD64_LINUX (was Re: cm3 @ OSX Mavericks) In-Reply-To: <8BA92447-1451-443A-AAEF-2B6FC163AA04@m3w.org> References: <604BEF67-A967-41ED-BECF-4776244EEC3B@purdue.edu> <8BA92447-1451-443A-AAEF-2B6FC163AA04@m3w.org> Message-ID: <3E83F12F-B557-4B3D-BED5-2747934FA05E@m3w.org> http://opencm3.net/uploaded-archives/cm3-bin-core-AMD64_LINUX-d5.9.0-x86_64-unknown-linux-gnu-2014-08-19-18-12-25.tgz Please test! This is also from Git HEAD. On 19 Aug 2014, at 18:54, Dragi?a Duri? wrote: > I did: > > cd scripts > ./makebin-dist-min.sh > > Got a lot of output and:?. > creating distribution archive /var/tmp/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz > -rw-rw-r--. 1 root root 21636241 Aug 19 18:38 /var/tmp/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz > cleaning up > > Copied this file to birch.elegosoft.com:/var/www/modula3.elegosoft.com/cm3/uploaded-archives > > Ran Jay?s update... > /var/www/modula3.elegosoft.com/cm3/uploaded-archives/update-download-index.sh > > Last time I tried this, index file was rewritten. But, nevertheless - uploaded file remained where I put it. > > Right now, LINUXLIBC6 from Git HEAD is at: > > http://opencm3.net/uploaded-archives/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz > > Please upload your archives there! > > TIA, > dd > > On 19 Aug 2014, at 18:30, Antony Hosking wrote: > >> I do. One small fix needed to head to fix a change in OSX pthread library. Should have it done this week. >> I?ll upload AMD64_DARWIN then. Remind me. How do I package it? It has been a long time since I built/bootstrapped using the scripts. Usually I do by hand. In fact, I am still using an old cm3cg and old cm3.cfg. >> >> What are the latest instructions for installing fresh? I took a quick look and things looked pretty daunting? too many scripts that I don?t understand. >> >> On Aug 19, 2014, at 12:26 PM, Dragi?a Duri? wrote: >> >>> Anybody has working cm3 on 10.9.4 OSX? Care to upload cm3-bin-core-AMD64_LINUX..? >>> >>> TIA, >>> dd >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Tue Aug 19 20:32:17 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 20:32:17 +0200 Subject: [M3devel] Another! This time AMD64_LINUX (was Re: cm3 @ OSX Mavericks) In-Reply-To: <3E83F12F-B557-4B3D-BED5-2747934FA05E@m3w.org> References: <604BEF67-A967-41ED-BECF-4776244EEC3B@purdue.edu> <8BA92447-1451-443A-AAEF-2B6FC163AA04@m3w.org> <3E83F12F-B557-4B3D-BED5-2747934FA05E@m3w.org> Message-ID: <9A9971C6-99B2-4734-B7C1-84DEBDC61231@m3w.org> make-bin-dist-min.sh @ HEAD is a bit Windows biased so I had to comment lines 85-87 before these two builds. I will fix this later on when I confirm everything else is ok and works. dd On 19 Aug 2014, at 20:29, Dragi?a Duri? wrote: > http://opencm3.net/uploaded-archives/cm3-bin-core-AMD64_LINUX-d5.9.0-x86_64-unknown-linux-gnu-2014-08-19-18-12-25.tgz > > Please test! This is also from Git HEAD. > > On 19 Aug 2014, at 18:54, Dragi?a Duri? wrote: > >> I did: >> >> cd scripts >> ./makebin-dist-min.sh >> >> Got a lot of output and:?. >> creating distribution archive /var/tmp/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz >> -rw-rw-r--. 1 root root 21636241 Aug 19 18:38 /var/tmp/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz >> cleaning up >> >> Copied this file to birch.elegosoft.com:/var/www/modula3.elegosoft.com/cm3/uploaded-archives >> >> Ran Jay?s update... >> /var/www/modula3.elegosoft.com/cm3/uploaded-archives/update-download-index.sh >> >> Last time I tried this, index file was rewritten. But, nevertheless - uploaded file remained where I put it. >> >> Right now, LINUXLIBC6 from Git HEAD is at: >> >> http://opencm3.net/uploaded-archives/cm3-bin-core-LINUXLIBC6-d5.9.0-i686-pc-linux-gnu-2014-08-19-16-33-42.tgz >> >> Please upload your archives there! >> >> TIA, >> dd >> >> On 19 Aug 2014, at 18:30, Antony Hosking wrote: >> >>> I do. One small fix needed to head to fix a change in OSX pthread library. Should have it done this week. >>> I?ll upload AMD64_DARWIN then. Remind me. How do I package it? It has been a long time since I built/bootstrapped using the scripts. Usually I do by hand. In fact, I am still using an old cm3cg and old cm3.cfg. >>> >>> What are the latest instructions for installing fresh? I took a quick look and things looked pretty daunting? too many scripts that I don?t understand. >>> >>> On Aug 19, 2014, at 12:26 PM, Dragi?a Duri? wrote: >>> >>>> Anybody has working cm3 on 10.9.4 OSX? Care to upload cm3-bin-core-AMD64_LINUX..? >>>> >>>> TIA, >>>> dd >>>> >>>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Tue Aug 19 21:30:26 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 19 Aug 2014 21:30:26 +0200 Subject: [M3devel] Someone please check these Message-ID: https://github.com/dragisha/cm3/releases/tag/verification-release-x86_64 https://github.com/dragisha/cm3/releases/tag/verification-release Same archives as I have uploaded on birch, but it looks like github also has very nice mechanism for binary releases. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From rodney_bates at lcwb.coop Tue Aug 19 22:21:48 2014 From: rodney_bates at lcwb.coop (Rodney M. Bates) Date: Tue, 19 Aug 2014 15:21:48 -0500 Subject: [M3devel] m3gdb status? In-Reply-To: <5D3D021A-5A97-411A-8CB3-8DDF6CE20780@m3w.org> References: <20140819081309.3D9251A2095@async.async.caltech.edu> <53F377D5.8060505@lcwb.coop> <53F38154.6020204@lcwb.coop> <5D3D021A-5A97-411A-8CB3-8DDF6CE20780@m3w.org> Message-ID: <53F3B1DC.3050104@lcwb.coop> Yes, I plan to. It might take me a day or so. On 08/19/2014 12:03 PM, Dragi?a Duri? wrote: > Rodney, > > It would be great if you can commit same change to Git as conversion I had to do in end is not incremental. > > Thanks! > > dd > > On 19 Aug 2014, at 18:54, Rodney M. Bates wrote: > >> The change I just checked in to m3-sys/m3gdb/src/m3makefile gets it back to >> building while tolerating warnings. There are many compile warnings in this >> dusty code, a lot of them from original gdb 64. >> >> You have to reconfigure, so do a realclean, before building. >> >> On 08/19/2014 11:14 AM, Rodney M. Bates wrote: >>> It's very dusty: looks unchanged since brought into the M3 repository from >>> gdb 6.4, in 2006. However, I have built m3gdb many times since then, with >>> neither build failures nor bugs that are likely to have anything to do with >>> bfd/archive.c. It looks like a harmless warning, from the original gdb, >>> turned into an error by the -Werror flag to gcc. >>> >>> I last successfully compiled archive.c on 2013-10-21 for AMD64_LINUX and on >>> 2014-6-23 for LINUXLIBC6. Perhaps the -Werror flag has became a default >>> in gcc since. In a quick scan using grep, I didn't see anywhere in the M3 >>> distribution or installation that would have set it. >>> >>> Changing -Werror to -Wno-error in variable WARN_CFLAGS in AMD64_LINUX/bfd/Makefile >>> and AMD64_LINUX/opcodes/Makefile got me through all the compile problems (hit >>> unrelated link problems). But that's the wrong solution, as these Makefiles >>> are, I am sure, mechanically generated from somewhere else, no doubt configure. >>> I haven't figured out where it comes from originally. >>> >>> On 08/19/2014 03:13 AM, mika at async.caltech.edu wrote: >>>> What is the status of m3gdb? >>>> >>>> I am on AMD64_LINUX here...head from CVS. >>>> >>>> The error looks pedantic but the fact that things aren't building makes me think maybe this code is pretty dusty...? >>>> >>>> /bin/sh ../../gdb/bfd/../move-if-change bfd-tmp.h bfd.h >>>> rm -f bfd-tmp.h >>>> touch stmp-bfd-h >>>> /bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c -o archive.lo ../../gdb/bfd/archive.c >>>> gcc -DHAVE_CONFIG_H -I. -I../../gdb/bfd -I. -I. -I../../gdb/bfd -I../../gdb/bfd/../include -I../../gdb/bfd/../intl -I../intl -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c ../../gdb/bfd/archive.c -o archive.o >>>> ../../gdb/bfd/archive.c: In function 'bfd_generic_archive_p': >>>> ../../gdb/bfd/archive.c:669:16: error: variable 'fail' set but not used [-Werror=unused-but-set-variable] >>>> cc1: all warnings being treated as errors >>>> make[4]: *** [archive.lo] Error 1 >>>> make[4]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >>>> make[3]: *** [all-recursive] Error 1 >>>> make[3]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >>>> make[2]: *** [all] Error 2 >>>> make[2]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/bfd' >>>> make[1]: *** [all-bfd] Error 2 >>>> make[1]: Leaving directory `/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX' >>>> make: *** [all] Error 2 >>>> "/big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile", line 40: quake runtime error: exit 2: make MAKE=make MAKEINFO=: >>>> >>>> --procedure-- -line- -file--- >>>> exec -- >>>> m3gdb_Run 40 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile >>>> include_dir 85 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/src/m3makefile >>>> 4 /big/home2/mika/2/cm3-cvs/cm3/m3-sys/m3gdb/AMD64_LINUX/m3make.args >>>> >>>> Fatal Error: package build failed >>>> (326)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/m3gdb> >>>> >>>> >>>> >>>> >>> >> >> -- >> Rodney Bates >> rodney.m.bates at acm.org > -- Rodney Bates rodney.m.bates at acm.org From mika at async.caltech.edu Mon Aug 25 07:49:21 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sun, 24 Aug 2014 22:49:21 -0700 Subject: [M3devel] pthreads status Message-ID: <20140825054921.B14421A20AC@async.async.caltech.edu> Hi m3devel, I hope this email finds you well and you had a good weekend. I spent mine with a debugger, as will become clear. I have a programming problem I chose to solve as I choose to solve most programming problems, by writing a program in Modula-3. The particular programming problem is one in (electronic) design automation and requires lots of memory (200 GB of RAM maybe) and has lots of FINE-grained parallelism. In other words, it's a prime candidate for multiprocessing via pthreads in Modula-3. One of the reasons I even chose to approach the problem this way is that I saw some noises on this mailing list suggesting that the pthreads threading library "now works". I've tried the pthreads many times over the years and things have always been so broken that I found the code to be unusable so I was really happy to hear that the pthreads were now working. Well, of course the pthreads library wasn't working. That's not a criticism, really. I understand from reading the code and communicating with Tony that many of the problems stem from issues in understanding the underlying POSIX facilities, which are not always documented properly (in particular issues with interactions between threading and signals). In any case there was a blatant race condition in the code. But now, after lots of invaluable assistance from Tony and countless gigabytes of log files and beating on code... I am reasonably confident that we have a version of the threading library, over pthreads, that is actually correct! For now it is on one architecture only, namely AMD64_LINUX. It crashes and burns on AMD64_FREEBSD. Don't ask me why---the code on FreeBSD uses less "tricky stuff" and ought to be monotonically easier to get working than the Linux code. I've run the thread tester in its grumpiest modes for several CPU weeks against the new library, as well as my CAD application, all without evident problems. I don't know the precise procedure for submitting things anymore, with the git migration. Tony has a copy of the code I'm also attaching to this email, which is the correctly functioning ThreadPThread.m3 for AMD64_LINUX. Not everything is roses with this, but I'll leave the bad news for another email (I need some advice, too). Best regards, Mika -------------- next part -------------- (* Copyright (C) 2005, Purdue Research Foundation *) (* All rights reserved. *) (* See the file COPYRIGHT-PURDUE for a full description. *) UNSAFE MODULE ThreadPThread EXPORTS Thread, ThreadF, RTThread, Scheduler, SchedulerPosix, RTOS, RTHooks, ThreadPThread; IMPORT Cerrno, FloatMode, MutexRep, RTCollectorSRC, RTError, RTHeapRep, RTIO, RTParams, RTPerfTool, RTProcess, ThreadEvent, Time, Word, Usched, Uerror, Uexec; FROM Compiler IMPORT ThisFile, ThisLine; FROM Ctypes IMPORT int; IMPORT RuntimeError AS RTE; FROM ThreadInternal IMPORT Poll; (*----------------------------------------------------- types and globals ---*) CONST MILLION = 1000 * 1000; WAIT_UNIT = MILLION; (* one million nanoseconds, one thousandth of a second *) RETRY_INTERVAL = 10 * MILLION; (* 10 million nanoseconds, one hundredth of a second *) REVEAL Mutex = MutexRep.Public BRANDED "Mutex Pthread-1.0" OBJECT mutex: pthread_mutex_t := NIL; holder: Activation := NIL; waiters: Activation := NIL; OVERRIDES acquire := LockMutex; release := UnlockMutex; END; Condition = BRANDED "Thread.Condition Pthread-1.0" OBJECT mutex: pthread_mutex_t := NIL; waiters: Activation := NIL; (* LL = mutex *) END; T = BRANDED "Thread.T Pthread-1.6" OBJECT act: Activation := NIL; (* live untraced thread data *) closure: Closure := NIL; (* our work and its result *) result: REFANY := NIL; (* our work and its result *) join: Condition; (* wait here to join; NIL when done *) joined: BOOLEAN := FALSE; (* Is anyone waiting yet? *) END; TYPE ActState = { Starting, Started, Stopping, Stopped }; REVEAL Activation = UNTRACED BRANDED REF RECORD frame: ADDRESS := NIL; (* exception handling support *) mutex: pthread_mutex_t := NIL; (* write-once in CreateT *) cond: pthread_cond_t := NIL; (* write-once in CreateT; a place to park while waiting *) alerted : BOOLEAN := FALSE; (* LL = mutex; the alert flag *) waitingOn: pthread_mutex_t := NIL; (* LL = mutex; The CV's mutex *) nextWaiter: Activation := NIL; (* LL = mutex; waiting thread queue *) next, prev: Activation := NIL; (* LL = activeMu; global doubly-linked, circular list of all active threads *) handle: pthread_t := NIL; (* LL = activeMu; thread handle *) stackbase: ADDRESS := NIL; (* LL = activeMu; stack base for GC *) context: ADDRESS := NIL; (* LL = activeMu *) state := ActState.Started; (* LL = activeMu *) slot: CARDINAL := 0; (* LL = slotMu; index in slots *) floatState : FloatMode.ThreadState; (* per-thread floating point state *) heapState : RTHeapRep.ThreadState; (* per-thread heap state *) END; PROCEDURE SetState (act: Activation; state: ActState) = CONST text = ARRAY ActState OF TEXT { "Starting", "Started", "Stopping", "Stopped" }; BEGIN act.state := state; IF DEBUG THEN RTIO.PutText(text[state]); RTIO.PutText(" act="); RTIO.PutAddr(act); RTIO.PutText("\n"); RTIO.Flush(); END; END SetState; (*----------------------------------------------------------------- Mutex ---*) PROCEDURE Acquire (m: Mutex) = BEGIN m.acquire (); END Acquire; PROCEDURE Release (m: Mutex) = BEGIN m.release (); END Release; PROCEDURE CleanMutex (r: REFANY) = VAR m := NARROW(r, Mutex); BEGIN pthread_mutex_delete(m.mutex); m.mutex := NIL; END CleanMutex; PROCEDURE InitMutex (VAR m: pthread_mutex_t; root: REFANY; Clean: PROCEDURE(root: REFANY)) = VAR mutex := pthread_mutex_new(); BEGIN TRY WITH r = pthread_mutex_lock(initMu) DO <*ASSERT r=0*> END; (* Did someone else win the race? *) IF m # NIL THEN RETURN END; (* We won the race, but we might have failed to allocate. *) IF mutex = NIL THEN RTE.Raise (RTE.T.OutOfMemory) END; RTHeapRep.RegisterFinalCleanup (root, Clean); m := mutex; mutex := NIL; FINALLY WITH r = pthread_mutex_unlock(initMu) DO <*ASSERT r=0*> END; pthread_mutex_delete(mutex); END; END InitMutex; PROCEDURE LockMutex (m: Mutex) = VAR self := GetActivation(); BEGIN IF perfOn THEN PerfChanged(State.locking) END; IF m.mutex = NIL THEN InitMutex(m.mutex, m, CleanMutex) END; WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(m.mutex) DO <*ASSERT r=0*> END; IF m.holder = NIL THEN m.holder := self; WITH r = pthread_mutex_unlock(m.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; RETURN; END; <*ASSERT self.waitingOn = NIL*> <*ASSERT self.nextWaiter = NIL*> self.waitingOn := m.mutex; self.nextWaiter := m.waiters; m.waiters := self; IF m.holder = self THEN Die(ThisLine(), "impossible acquire") END; WITH r = pthread_mutex_unlock(m.mutex) DO <*ASSERT r=0*> END; REPEAT WITH r = pthread_cond_wait(self.cond, self.mutex) DO <*ASSERT r=0*> END; UNTIL self.waitingOn = NIL; (* m.holder = self *) <*ASSERT m.holder = self*> <*ASSERT self.nextWaiter = NIL*> WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; END LockMutex; PROCEDURE UnlockMutex (m: Mutex) = VAR self := GetActivation(); t, prev: Activation; BEGIN IF m.mutex = NIL THEN InitMutex(m.mutex, m, CleanMutex) END; WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(m.mutex) DO <*ASSERT r=0*> END; IF m.holder # self THEN Die(ThisLine(), "illegal release") END; t := m.waiters; IF t = NIL THEN m.holder := NIL; WITH r = pthread_mutex_unlock(m.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; RETURN; END; prev := NIL; WHILE t.nextWaiter # NIL DO prev := t; t := t.nextWaiter; END; IF prev # NIL THEN prev.nextWaiter := NIL; ELSE m.waiters := NIL; END; m.holder := t; WITH r = pthread_mutex_unlock(m.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(t.mutex) DO <*ASSERT r=0*> END; <*ASSERT t.waitingOn = m.mutex*> t.nextWaiter := NIL; t.waitingOn := NIL; WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(t.mutex) DO <*ASSERT r=0*> END; END UnlockMutex; (*---------------------------------------- Condition variables and Alerts ---*) PROCEDURE CleanCondition (r: REFANY) = VAR c := NARROW(r, Condition); BEGIN pthread_mutex_delete(c.mutex); c.mutex := NIL; END CleanCondition; PROCEDURE XWait (self: Activation; m: Mutex; c: Condition; alertable: BOOLEAN) RAISES {Alerted} = (* LL = m *) VAR next, prev: Activation; BEGIN IF perfOn THEN PerfChanged(State.waiting) END; IF c.mutex = NIL THEN InitMutex(c.mutex, c, CleanCondition) END; WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; <*ASSERT self.waitingOn = NIL*> <*ASSERT self.nextWaiter = NIL*> WITH r = pthread_mutex_lock(c.mutex) DO <*ASSERT r=0*> END; self.waitingOn := c.mutex; self.nextWaiter := c.waiters; c.waiters := self; WITH r = pthread_mutex_unlock(c.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; m.release(); WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; LOOP IF alertable AND self.alerted THEN self.alerted := FALSE; <*ASSERT self.waitingOn = c.mutex*> WITH r = pthread_mutex_lock(c.mutex) DO <*ASSERT r=0*> END; next := c.waiters; prev := NIL; WHILE next # self DO <*ASSERT next # NIL*> prev := next; next := next.nextWaiter; END; IF prev = NIL THEN c.waiters := self.nextWaiter; ELSE prev.nextWaiter := self.nextWaiter; END; WITH r = pthread_mutex_unlock(c.mutex) DO <*ASSERT r=0*> END; self.nextWaiter := NIL; self.waitingOn := NIL; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; m.acquire(); RAISE Alerted; ELSIF self.waitingOn = NIL THEN <*ASSERT self.nextWaiter = NIL*> WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; m.acquire(); RETURN; END; WITH r = pthread_cond_wait(self.cond, self.mutex) DO <*ASSERT r=0*> END; END; END XWait; PROCEDURE AlertWait (m: Mutex; c: Condition) RAISES {Alerted} = (* LL = m *) VAR self := GetActivation(); BEGIN XWait(self, m, c, alertable := TRUE); END AlertWait; PROCEDURE Wait (m: Mutex; c: Condition) = <*FATAL Alerted*> (* LL = m *) VAR self := GetActivation(); BEGIN XWait(self, m, c, alertable := FALSE); END Wait; PROCEDURE Signal (c: Condition) = VAR self := GetActivation(); t: Activation; BEGIN IF c.mutex = NIL THEN InitMutex(c.mutex, c, CleanCondition) END; WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(c.mutex) DO <*ASSERT r=0*> END; t := c.waiters; IF t # NIL THEN c.waiters := t.nextWaiter; END; WITH r = pthread_mutex_unlock(c.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; IF t # NIL THEN WITH r = pthread_mutex_lock(t.mutex) DO <*ASSERT r=0*> END; t.nextWaiter := NIL; t.waitingOn := NIL; WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(t.mutex) DO <*ASSERT r=0*> END; END; END Signal; PROCEDURE Broadcast (c: Condition) = VAR self := GetActivation(); t, next: Activation; BEGIN IF c.mutex = NIL THEN InitMutex(c.mutex, c, CleanCondition) END; WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_lock(c.mutex) DO <*ASSERT r=0*> END; t := c.waiters; c.waiters := NIL; WITH r = pthread_mutex_unlock(c.mutex) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; WHILE t # NIL DO WITH r = pthread_mutex_lock(t.mutex) DO <*ASSERT r=0*> END; next := t.nextWaiter; t.nextWaiter := NIL; t.waitingOn := NIL; WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(t.mutex) DO <*ASSERT r=0*> END; t := next; END; END Broadcast; PROCEDURE Alert (thread: T) = VAR t := thread.act; BEGIN WITH r = pthread_mutex_lock(t.mutex) DO <*ASSERT r=0*> END; t.alerted := TRUE; WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(t.mutex) DO <*ASSERT r=0*> END; END Alert; PROCEDURE XTestAlert (self: Activation): BOOLEAN = VAR result: BOOLEAN; BEGIN WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; result := self.alerted; self.alerted := FALSE; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; RETURN result; END XTestAlert; PROCEDURE TestAlert (): BOOLEAN = VAR self := GetActivation(); BEGIN RETURN XTestAlert(self); END TestAlert; (*------------------------------------------------------------------ Self ---*) VAR (* LL = slotMu *) n_slotted: CARDINAL; next_slot: CARDINAL; (* NOTE: we don't use slots[0] *) slots: REF ARRAY OF T; (* NOTE: we don't use slots[0] *) PROCEDURE InitActivations (me: Activation) = BEGIN me.handle := pthread_self(); me.next := me; me.prev := me; SetActivation(me); (* Explicitly (re)initialize to handle fork(). *) next_slot := 1; (* no threads created yet *) slots := NIL; (* no threads created yet *) n_slotted := 0; (* no threads created yet *) allThreads := me; FloatMode.InitThread(me.floatState); END InitActivations; PROCEDURE Self (): T = (* If not the initial thread and not created by Fork, returns NIL *) VAR me := GetActivation(); t: T; BEGIN IF me = NIL THEN Die(ThisLine(), "Thread primitive called from non-Modula-3 thread") END; WITH r = pthread_mutex_lock(slotsMu) DO <*ASSERT r=0*> END; t := slots[me.slot]; WITH r = pthread_mutex_unlock(slotsMu) DO <*ASSERT r=0*> END; IF (t.act # me) THEN Die(ThisLine(), "thread with bad slot!") END; RETURN t; END Self; PROCEDURE AssignSlot (t: T): INTEGER = (* LL = 0, cause we allocate stuff with NEW! *) VAR n: CARDINAL; new_slots: REF ARRAY OF T; slot: CARDINAL; BEGIN WITH r = pthread_mutex_lock(slotsMu) DO <*ASSERT r=0*> END; (* make sure we have room to register this guy *) IF (slots = NIL) THEN WITH r = pthread_mutex_unlock(slotsMu) DO <*ASSERT r=0*> END; slots := NEW (REF ARRAY OF T, 20); WITH r = pthread_mutex_lock(slotsMu) DO <*ASSERT r=0*> END; END; IF (n_slotted >= LAST (slots^)) THEN n := NUMBER (slots^); WITH r = pthread_mutex_unlock(slotsMu) DO <*ASSERT r=0*> END; new_slots := NEW (REF ARRAY OF T, n+n); WITH r = pthread_mutex_lock(slotsMu) DO <*ASSERT r=0*> END; IF (n = NUMBER (slots^)) THEN (* we won any races that may have occurred. *) SUBARRAY (new_slots^, 0, n) := slots^; slots := new_slots; ELSIF (n_slotted < LAST (slots^)) THEN (* we lost a race while allocating a new slot table, and the new table has room for us. *) ELSE (* ouch, the new table is full too! Bail out and retry *) WITH r = pthread_mutex_unlock(slotsMu) DO <*ASSERT r=0*> END; RETURN AssignSlot (t); END; END; (* look for an empty slot *) WHILE (slots [next_slot] # NIL) DO INC (next_slot); IF (next_slot >= NUMBER (slots^)) THEN next_slot := 1; END; END; INC (n_slotted); slot := next_slot; slots [slot] := t; WITH r = pthread_mutex_unlock(slotsMu) DO <*ASSERT r=0*> END; RETURN slot; END AssignSlot; PROCEDURE FreeSlot (self: T) = (* LL = 0 *) BEGIN WITH r = pthread_mutex_lock(slotsMu) DO <*ASSERT r=0*> END; DEC (n_slotted); WITH z = slots [self.act.slot] DO IF z # self THEN Die (ThisLine(), "unslotted thread!"); END; z := NIL; END; self.act.slot := 0; WITH r = pthread_mutex_unlock(slotsMu) DO <*ASSERT r=0*> END; END FreeSlot; PROCEDURE DumpThread (t: Activation) = BEGIN RTIO.PutText("Activation: "); RTIO.PutAddr(t); RTIO.PutChar('\n'); RTIO.PutText(" slot: "); RTIO.PutInt(t.slot); RTIO.PutChar('\n'); RTIO.PutText(" mutex: "); RTIO.PutAddr(t.mutex); RTIO.PutChar('\n'); RTIO.PutText(" cond: "); RTIO.PutAddr(t.cond); RTIO.PutChar('\n'); RTIO.PutText(" alerted: "); RTIO.PutInt(ORD(t.alerted)); RTIO.PutChar('\n'); RTIO.PutText(" waitingOn: "); RTIO.PutAddr(t.waitingOn); RTIO.PutChar('\n'); RTIO.PutText(" nextWaiter: "); RTIO.PutAddr(t.nextWaiter); RTIO.PutChar('\n'); RTIO.PutText(" frame: "); RTIO.PutAddr(t.frame); RTIO.PutChar('\n'); RTIO.PutText(" next: "); RTIO.PutAddr(t.next); RTIO.PutChar('\n'); RTIO.PutText(" prev: "); RTIO.PutAddr(t.prev); RTIO.PutChar('\n'); RTIO.PutText(" handle: "); RTIO.PutAddr(t.handle); RTIO.PutChar('\n'); RTIO.PutText(" stackbase: "); RTIO.PutAddr(t.stackbase); RTIO.PutChar('\n'); RTIO.PutText(" context: "); RTIO.PutAddr(t.context); RTIO.PutChar('\n'); RTIO.PutText(" state: "); CASE t.state OF | ActState.Started => RTIO.PutText("Started\n"); | ActState.Stopped => RTIO.PutText("Stopped\n"); | ActState.Starting => RTIO.PutText("Starting\n"); | ActState.Stopping => RTIO.PutText("Stopping\n"); END; RTIO.Flush(); END DumpThread; PROCEDURE DumpThreads () = VAR t := allThreads; BEGIN REPEAT DumpThread(t); t := t.next UNTIL t = allThreads; END DumpThreads; (*------------------------------------------------------------ Fork, Join ---*) VAR (* LL=activeMu *) allThreads: Activation := NIL; (* global list of active threads *) PROCEDURE CleanThread (r: REFANY) = VAR t := NARROW(r, T); BEGIN pthread_mutex_delete(t.act.mutex); pthread_cond_delete(t.act.cond); DISPOSE(t.act); END CleanThread; (* ThreadBase calls RunThread after finding (approximately) where its stack begins. This dance ensures that all of ThreadMain's traced references are within the stack scanned by the collector. *) PROCEDURE ThreadBase (param: ADDRESS): ADDRESS = VAR me: Activation := param; BEGIN SetActivation(me); me.stackbase := ADR(me); (* enable GC scanning of this stack *) me.handle := pthread_self(); (* add to the list of active threads *) WITH r = pthread_mutex_lock(activeMu) DO <*ASSERT r=0*> END; me.next := allThreads; me.prev := allThreads.prev; allThreads.prev.next := me; allThreads.prev := me; WITH r = pthread_mutex_unlock(activeMu) DO <*ASSERT r=0*> END; FloatMode.InitThread (me.floatState); RunThread(me); (* remove from the list of active threads *) WITH r = pthread_mutex_lock(activeMu) DO <*ASSERT r=0*> END; <*ASSERT allThreads # me*> me.stackbase := NIL; (* disable GC scanning of my stack *) me.next.prev := me.prev; me.prev.next := me.next; WITH r = pthread_detach_self() DO <*ASSERT r=0*> END; WITH r = pthread_mutex_unlock(activeMu) DO <*ASSERT r=0*> END; me.next := NIL; me.prev := NIL; RETURN NIL; END ThreadBase; PROCEDURE RunThread (me: Activation) = VAR self: T; BEGIN IF perfOn THEN PerfChanged(State.alive) END; WITH r = pthread_mutex_lock(slotsMu) DO <*ASSERT r=0*> END; self := slots [me.slot]; WITH r = pthread_mutex_unlock(slotsMu) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; (*** Run the user-level code. ***) self.result := self.closure.apply(); IF perfOn THEN PerfChanged(State.dying) END; (* Join *) LOCK joinMu DO Broadcast(self.join); self.join := NIL; (* mark me done *) END; IF perfOn THEN PerfChanged(State.dead) END; (* we're dying *) RTHeapRep.FlushThreadState(me.heapState); IF perfOn THEN PerfDeleted() END; FreeSlot(self); (* note: needs self.act ! *) (* Since we're no longer slotted, we cannot touch traced refs. *) END RunThread; VAR joinMu: MUTEX; PROCEDURE Fork (closure: Closure): T = VAR act := NEW(Activation, mutex := pthread_mutex_new(), cond := pthread_cond_new()); size := defaultStackSize; t: T := NIL; BEGIN TRY IF act.mutex = NIL OR act.cond = NIL THEN RTE.Raise(RTE.T.OutOfMemory); END; t := NEW(T, act := act, closure := closure, join := NEW(Condition)); RTHeapRep.RegisterFinalCleanup(t, CleanThread); act.slot := AssignSlot(t); FINALLY IF act.slot = 0 THEN (* we failed, cleanup *) pthread_mutex_delete(act.mutex); pthread_cond_delete(act.cond); DISPOSE(act); END; END; (* determine the initial size of the stack for this thread *) TYPECASE closure OF | SizedClosure (scl) => size := scl.stackSize; ELSE (*skip*) END; WITH r = thread_create(size * ADRSIZE(Word.T), ThreadBase, act) DO IF r # 0 THEN DieI(ThisLine(), r) END; END; RETURN t; END Fork; PROCEDURE XJoin (self: Activation; t: T; alertable: BOOLEAN): REFANY RAISES {Alerted} = BEGIN LOCK joinMu DO IF t.joined THEN Die(ThisLine(), "attempt to join with thread twice") END; TRY t.joined := TRUE; WHILE t.join # NIL DO XWait(self, joinMu, t.join, alertable) END; FINALLY IF t.join # NIL THEN t.joined := FALSE END; END; END; RETURN t.result; END XJoin; PROCEDURE Join (t: T): REFANY = <*FATAL Alerted*> VAR self := GetActivation(); BEGIN RETURN XJoin(self, t, alertable := FALSE); END Join; PROCEDURE AlertJoin (t: T): REFANY RAISES {Alerted} = VAR self := GetActivation(); BEGIN RETURN XJoin(self, t, alertable := TRUE); END AlertJoin; (*---------------------------------------------------- Scheduling support ---*) PROCEDURE XPause (self: Activation; n: LONGREAL; alertable: BOOLEAN) RAISES {Alerted} = VAR until := Time.Now() + n; BEGIN IF perfOn THEN PerfChanged(State.pausing) END; WITH r = pthread_mutex_lock(self.mutex) DO <*ASSERT r=0*> END; <*ASSERT self.waitingOn = NIL*> <*ASSERT self.nextWaiter = NIL*> LOOP IF alertable AND self.alerted THEN self.alerted := FALSE; WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; RAISE Alerted; END; WITH r = pthread_cond_timedwait(self.cond, self.mutex, until) DO IF r = Uerror.ETIMEDOUT THEN WITH r = pthread_mutex_unlock(self.mutex) DO <*ASSERT r=0*> END; IF perfOn THEN PerfRunning() END; RETURN; END; <*ASSERT r=0*> END; END; END XPause; PROCEDURE Pause (n: LONGREAL) = <*FATAL Alerted*> VAR self := GetActivation(); BEGIN XPause(self, n, alertable := FALSE); END Pause; PROCEDURE AlertPause (n: LONGREAL) RAISES {Alerted} = VAR self := GetActivation(); BEGIN XPause(self, n, alertable := TRUE); END AlertPause; PROCEDURE Yield () = BEGIN WITH r = Usched.yield() DO IF r # 0 THEN DieI(ThisLine(), Cerrno.GetErrno()) END; END; END Yield; PROCEDURE IOWait (fd: CARDINAL; read: BOOLEAN; timeoutInterval: LONGREAL := -1.0D0): WaitResult = <*FATAL Alerted*> VAR self := GetActivation(); BEGIN TRY IF perfOn THEN PerfChanged(State.blocking) END; RETURN XIOWait(self, fd, read, timeoutInterval, alertable := FALSE); FINALLY IF perfOn THEN PerfRunning() END; END; END IOWait; PROCEDURE IOAlertWait (fd: CARDINAL; read: BOOLEAN; timeoutInterval: LONGREAL := -1.0D0): WaitResult RAISES {Alerted} = VAR self := GetActivation(); BEGIN TRY IF perfOn THEN PerfChanged(State.blocking) END; RETURN XIOWait(self, fd, read, timeoutInterval, alertable := TRUE); FINALLY IF perfOn THEN PerfRunning() END; END; END IOAlertWait; PROCEDURE XIOWait (self: Activation; fd: CARDINAL; read: BOOLEAN; interval: LONGREAL; alertable: BOOLEAN): WaitResult RAISES {Alerted} = VAR res: WaitResult; subInterval: LONGREAL := 1.0d0; err: int := 0; again := FALSE; BEGIN IF NOT alertable THEN subInterval := interval; ELSIF interval < 0.0d0 THEN interval := LAST(LONGREAL); ELSIF interval < subInterval THEN subInterval := interval; END; IF alertable AND XTestAlert(self) THEN RAISE Alerted END; LOOP res := VAL(Poll(fd, ORD(read), subInterval), WaitResult); IF alertable AND XTestAlert(self) THEN RAISE Alerted END; CASE res OF | WaitResult.FDError, WaitResult.Ready => RETURN res; | WaitResult.Error => err := Cerrno.GetErrno(); IF err = Uerror.EINTR THEN (* spurious wakeups are OK *) ELSIF err = Uerror.EAGAIN AND NOT again THEN again := TRUE; (* try just once more *) ELSE RETURN WaitResult.Error; END; | WaitResult.Timeout => interval := interval - subInterval; IF interval <= 0.0d0 THEN RETURN WaitResult.Timeout END; IF interval < subInterval THEN subInterval := interval; END; END; END; END XIOWait; PROCEDURE WaitProcess (pid: int; VAR status: int): int = (* ThreadPThread.m3 and ThreadPosix.m3 are very similar. *) BEGIN LOOP WITH r = Uexec.waitpid(pid, ADR(status), 0) DO <*ASSERT r # 0*> IF r > 0 THEN RETURN r END; IF Cerrno.GetErrno() # Uerror.EINTR THEN RETURN r END; END; END; END WaitProcess; (*--------------------------------------------------- Stack size controls ---*) VAR defaultStackSize := 4096; PROCEDURE GetDefaultStackSize (): CARDINAL = BEGIN RETURN defaultStackSize; END GetDefaultStackSize; PROCEDURE MinDefaultStackSize (size: CARDINAL) = BEGIN defaultStackSize := MAX(defaultStackSize, size); END MinDefaultStackSize; PROCEDURE IncDefaultStackSize (inc: CARDINAL) = BEGIN INC(defaultStackSize, inc); END IncDefaultStackSize; (*--------------------------------------------- Garbage collector support ---*) (* NOTE: These routines are called indirectly by the low-level page fault handler of the garbage collector. So, if they touched traced references, they could trigger indefinite invocations of the fault handler. *) (* In versions of SuspendOthers prior to the addition of the incremental collector, it acquired 'cm' to guarantee that no suspended thread held it. That way when the collector tried to acquire a mutex or signal a condition, it wouldn't deadlock with the suspended thread that held cm. With the VM-synchronized, incremental collector this design is inadequate. Here's a deadlock that occurred: Thread.Broadcast held cm, then it touched its condition argument, the page containing the condition was protected by the collector, another thread started running the page fault handler, the handler called SuspendOthers, SuspendOthers tried to acquire cm. So, SuspendOthers does not grab "cm" before shutting down the other threads. If the collector tries to use any of the thread functions that acquire "cm", it'll be deadlocked. *) VAR suspended: BOOLEAN := FALSE; (* LL=activeMu *) PROCEDURE SuspendOthers () = (* LL=0. Always bracketed with ResumeOthers which releases "activeMu" *) BEGIN WITH r = pthread_mutex_lock(activeMu) DO <*ASSERT r=0*> END; StopWorld(); <*ASSERT NOT suspended*> suspended := TRUE; END SuspendOthers; PROCEDURE ResumeOthers () = (* LL=activeMu. Always preceded by SuspendOthers. *) BEGIN <*ASSERT suspended*> suspended := FALSE; StartWorld(); WITH r = pthread_mutex_unlock(activeMu) DO <*ASSERT r=0*> END; END ResumeOthers; PROCEDURE ProcessStacks (p: PROCEDURE (start, limit: ADDRESS)) = (* LL=activeMu. Only called within {SuspendOthers, ResumeOthers} *) VAR me := GetActivation(); act: Activation; BEGIN ProcessMe(me, p); act := me.next; WHILE act # me DO ProcessOther(act, p); act := act.next; END; END ProcessStacks; PROCEDURE ProcessEachStack (p: PROCEDURE (start, limit: ADDRESS)) = (* LL=0 *) VAR me := GetActivation(); act: Activation; acks: int; nLive, nDead, newlySent: INTEGER := 0; wait_nsecs := RETRY_INTERVAL; BEGIN WITH r = pthread_mutex_lock(activeMu) DO <*ASSERT r=0*> END; ProcessMe(me, p); act := me.next; WHILE act # me DO (* stop *) LOOP <*ASSERT act.state = ActState.Started*> SetState(act, ActState.Stopping); IF SIG_SUSPEND = 0 THEN IF StopThread(act) THEN SetState(act, ActState.Stopped); EXIT; ELSE SetState(act, ActState.Started); END; ELSE SignalThread(act); INC(nLive); EXIT; END; Nanosleep(WAIT_UNIT); END; WHILE nLive > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nLive THEN EXIT END; <*ASSERT acks < nLive*> IF wait_nsecs <= 0 THEN newlySent := 0; <*ASSERT act.state # ActState.Starting*> IF act.state # ActState.Stopped THEN SetState(act, ActState.Stopping); SignalThread(act); INC(newlySent); END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; FOR i := 0 TO nLive - 1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; (* process *) ProcessOther(act, p); (* start *) nDead := 0; LOOP <*ASSERT act.state = ActState.Stopped*> SetState(act, ActState.Starting); IF SIG_SUSPEND = 0 THEN IF StartThread(act) THEN SetState(act, ActState.Started); EXIT; ELSE SetState(act, ActState.Stopped); END; ELSE SignalThread(act); INC(nDead); EXIT; END; Nanosleep(WAIT_UNIT); END; WHILE nDead > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nDead THEN EXIT END; <*ASSERT acks < nDead*> IF wait_nsecs <= 0 THEN newlySent := 0; <*ASSERT act.state # ActState.Stopping*> IF act.state # ActState.Started THEN SignalThread(act); INC(newlySent); END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; FOR i := 0 TO nDead - 1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; END; WITH r = pthread_mutex_unlock(activeMu) DO <*ASSERT r=0*> END; END ProcessEachStack; PROCEDURE ProcessMe (me: Activation; p: PROCEDURE (start, limit: ADDRESS)) = (* LL=activeMu *) BEGIN <*ASSERT me.state # ActState.Stopped*> IF DEBUG THEN RTIO.PutText("Processing act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); END; RTHeapRep.FlushThreadState(me.heapState); ProcessLive(me.stackbase, p); END ProcessMe; PROCEDURE ProcessOther (act: Activation; p: PROCEDURE (start, stop: ADDRESS)) = (* LL=activeMu *) BEGIN <*ASSERT act.state = ActState.Stopped*> IF DEBUG THEN RTIO.PutText("Processing act="); RTIO.PutAddr(act); RTIO.PutText("\n"); RTIO.Flush(); END; RTHeapRep.FlushThreadState(act.heapState); IF act.stackbase # NIL THEN ProcessStopped(act.handle, act.stackbase, act.context, p); END; END ProcessOther; (* Signal based suspend/resume *) PROCEDURE SignalThread(act: Activation) = (* LL=activeMu *) BEGIN <*ASSERT SIG_SUSPEND # 0*> LOOP WITH z = pthread_kill(act.handle, SIG_SUSPEND) DO IF z = 0 THEN EXIT END; IF z # Uerror.EAGAIN THEN DieI(ThisLine(), z) END; (* try it again... *) END; END; END SignalThread; PROCEDURE StopThread (act: Activation): BOOLEAN = (* LL=activeMu *) BEGIN <*ASSERT act.state = ActState.Stopping*> <*ASSERT SIG_SUSPEND = 0*> IF NOT SuspendThread(act.handle) THEN RETURN FALSE END; IF act.heapState.inCritical # 0 THEN IF NOT RestartThread(act.handle) THEN <*ASSERT FALSE*> END; RETURN FALSE; END; RETURN TRUE; END StopThread; PROCEDURE StartThread (act: Activation): BOOLEAN = (* LL=activeMu *) BEGIN <*ASSERT act.state = ActState.Starting*> <*ASSERT SIG_SUSPEND = 0*> RETURN RestartThread(act.handle); END StartThread; PROCEDURE StopWorld () = (* LL=activeMu *) VAR me := GetActivation(); act: Activation; acks: int; nLive, newlySent: INTEGER; retry: BOOLEAN; wait_nsecs := RETRY_INTERVAL; BEGIN IF DEBUG THEN RTIO.PutText("Stopping from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); END; nLive := 0; LOOP retry := FALSE; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Starting*> IF act.state = ActState.Started THEN SetState(act, ActState.Stopping); IF SIG_SUSPEND = 0 THEN IF StopThread(act) THEN SetState(act, ActState.Stopped); ELSE SetState(act, ActState.Started); retry := TRUE; END; ELSE SignalThread(act); INC(nLive); END; END; act := act.next; END; IF NOT retry THEN EXIT END; Nanosleep(WAIT_UNIT); END; WHILE nLive > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nLive THEN EXIT END; <*ASSERT acks < nLive*> IF wait_nsecs <= 0 THEN newlySent := 0; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Starting*> IF act.state # ActState.Stopped THEN SetState(act, ActState.Stopping); SignalThread(act); INC(newlySent); END; act := act.next; END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; (* drain semaphore *) FOR i := 0 TO nLive-1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; IF DEBUG THEN RTIO.PutText("Stopped from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); DumpThreads(); END; END StopWorld; PROCEDURE StartWorld () = (* LL=activeMu *) VAR me := GetActivation(); act: Activation; acks: int; nDead, newlySent: INTEGER; retry: BOOLEAN; wait_nsecs := RETRY_INTERVAL; BEGIN IF DEBUG THEN RTIO.PutText("Starting from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); END; nDead := 0; LOOP retry := FALSE; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Stopping*> IF act.state # ActState.Started THEN SetState(act, ActState.Starting); IF SIG_SUSPEND = 0 THEN IF StartThread(act) THEN SetState(act, ActState.Started); ELSE SetState(act, ActState.Stopped); retry := TRUE; END; ELSE SignalThread(act); INC(nDead); END; END; act := act.next; END; IF NOT retry THEN EXIT END; Nanosleep(WAIT_UNIT); END; WHILE nDead > 0 DO <*ASSERT SIG_SUSPEND # 0*> WITH r = sem_getvalue(acks) DO <*ASSERT r=0*> END; IF acks = nDead THEN EXIT END; <*ASSERT acks < nDead*> IF wait_nsecs <= 0 THEN newlySent := 0; act := me.next; WHILE act # me DO <*ASSERT act.state # ActState.Stopping*> IF act.state # ActState.Started THEN SignalThread(act); INC(newlySent); END; act := act.next; END; wait_nsecs := RETRY_INTERVAL; ELSE Nanosleep(WAIT_UNIT); DEC(wait_nsecs, WAIT_UNIT); END; END; (* drain semaphore *) FOR i := 0 TO nDead-1 DO WHILE sem_wait() # 0 DO WITH r = Cerrno.GetErrno() DO IF r # Uerror.EINTR THEN DieI(ThisLine(), r) END; END; (*retry*) END; END; IF DEBUG THEN RTIO.PutText("Started from act="); RTIO.PutAddr(me); RTIO.PutText("\n"); RTIO.Flush(); DumpThreads(); END; END StartWorld; PROCEDURE SignalHandler (sig: int; <*UNUSED*>info: ADDRESS; context: ADDRESS) = VAR errno := Cerrno.GetErrno(); me := GetActivation(); BEGIN <*ASSERT sig = SIG_SUSPEND*> IF me.state = ActState.Stopping THEN IF me.heapState.inCritical # 0 THEN me.state := ActState.Started; RETURN; END; me.state := ActState.Stopped; <*ASSERT me.context = NIL*> me.context := context; WITH r = sem_post() DO <*ASSERT r=0*> END; REPEAT sigsuspend() UNTIL me.state = ActState.Starting; me.context := NIL; me.state := ActState.Started; WITH r = sem_post() DO <*ASSERT r=0*> END; END; Cerrno.SetErrno(errno); END SignalHandler; (*----------------------------------------------------------- misc. stuff ---*) PROCEDURE MyId (): Id RAISES {} = VAR me := GetActivation(); BEGIN IF me = NIL THEN RETURN 0 ELSE RETURN me.slot; END; END MyId; PROCEDURE MyFPState (): UNTRACED REF FloatMode.ThreadState = VAR me := GetActivation(); BEGIN RETURN ADR(me.floatState); END MyFPState; PROCEDURE MyHeapState (): UNTRACED REF RTHeapRep.ThreadState = VAR me := GetActivation(); BEGIN RETURN ADR(me.heapState); END MyHeapState; PROCEDURE DisableSwitching () = BEGIN (* no user-level thread switching *) END DisableSwitching; PROCEDURE EnableSwitching () = BEGIN (* no user-level thread switching *) END EnableSwitching; (*---------------------------------------------------------------- errors ---*) PROCEDURE Die (lineno: INTEGER; msg: TEXT) = BEGIN RTError.Msg (ThisFile(), lineno, "Thread client error: ", msg); END Die; PROCEDURE DieI (lineno: INTEGER; i: INTEGER) = BEGIN RTError.MsgI (ThisFile(), lineno, "Thread client error: ", i); END DieI; (*------------------------------------------------------ ShowThread hooks ---*) VAR perfW : RTPerfTool.Handle; perfOn: BOOLEAN := FALSE; (* LL = perfMu *) PROCEDURE PerfStart () = BEGIN IF RTPerfTool.Start ("showthread", perfW) THEN perfOn := TRUE; RTProcess.RegisterExitor (PerfStop); END; END PerfStart; PROCEDURE PerfStop () = BEGIN (* UNSAFE, but needed to prevent deadlock if we're crashing! *) RTPerfTool.Close (perfW); END PerfStop; CONST EventSize = (BITSIZE(ThreadEvent.T) + BITSIZE(CHAR) - 1) DIV BITSIZE(CHAR); TYPE TE = ThreadEvent.Kind; PROCEDURE PerfChanged (s: State) = VAR e := ThreadEvent.T {kind := TE.Changed, id := MyId(), state := s}; BEGIN WITH r = pthread_mutex_lock(perfMu) DO <*ASSERT r=0*> END; perfOn := RTPerfTool.Send (perfW, ADR (e), EventSize); WITH r = pthread_mutex_unlock(perfMu) DO <*ASSERT r=0*> END; END PerfChanged; PROCEDURE PerfDeleted () = VAR e := ThreadEvent.T {kind := TE.Deleted, id := MyId()}; BEGIN WITH r = pthread_mutex_lock(perfMu) DO <*ASSERT r=0*> END; perfOn := RTPerfTool.Send (perfW, ADR (e), EventSize); WITH r = pthread_mutex_unlock(perfMu) DO <*ASSERT r=0*> END; END PerfDeleted; PROCEDURE PerfRunning () = VAR e := ThreadEvent.T {kind := TE.Running, id := MyId()}; BEGIN WITH r = pthread_mutex_lock(perfMu) DO <*ASSERT r=0*> END; perfOn := RTPerfTool.Send (perfW, ADR (e), EventSize); WITH r = pthread_mutex_unlock(perfMu) DO <*ASSERT r=0*> END; END PerfRunning; (*-------------------------------------------------------- Initialization ---*) PROCEDURE InitWithStackBase (stackbase: ADDRESS) = VAR self: T; me: Activation; BEGIN InitC(stackbase); me := NEW(Activation, mutex := pthread_mutex_new(), cond := pthread_cond_new()); InitActivations(me); me.stackbase := stackbase; IF me.mutex = NIL OR me.cond = NIL THEN Die(ThisLine(), "Thread initialization failed."); END; self := NEW(T, act := me, closure := NIL, join := NIL); me.slot := AssignSlot(self); joinMu := NEW(MUTEX); PerfStart(); IF perfOn THEN PerfRunning() END; IF RTParams.IsPresent("backgroundgc") THEN RTCollectorSRC.StartBackgroundCollection(); END; IF RTParams.IsPresent("foregroundgc") THEN RTCollectorSRC.StartForegroundCollection(); END; END InitWithStackBase; PROCEDURE Init ()= VAR r: INTEGER; BEGIN r := RTProcess.RegisterForkHandlers(AtForkPrepare, AtForkParent, AtForkChild); IF r # 0 THEN DieI(ThisLine(), r) END; InitWithStackBase(ADR(r)); (* not quite accurate but hopefully ok *) END Init; PROCEDURE PThreadLockMutex(mutex: pthread_mutex_t; line: INTEGER) = BEGIN IF mutex # NIL THEN WITH r = pthread_mutex_lock(mutex) DO IF r # 0 THEN DieI(line, r) END; END; END; END PThreadLockMutex; PROCEDURE PThreadUnlockMutex(mutex: pthread_mutex_t; line: INTEGER) = BEGIN IF mutex # NIL THEN WITH r = pthread_mutex_unlock(mutex) DO IF r # 0 THEN DieI(line, r) END; END; END; END PThreadUnlockMutex; PROCEDURE AtForkPrepare() = VAR me := GetActivation(); act: Activation; BEGIN PThreadLockMutex(slotsMu, ThisLine()); PThreadLockMutex(perfMu, ThisLine()); PThreadLockMutex(initMu, ThisLine()); (* InitMutex => RegisterFinalCleanup => LockHeap *) LockHeap(); PThreadLockMutex(activeMu, ThisLine()); (* LockHeap => SuspendOthers => activeMu *) (* Walk activations and lock all threads. * NOTE: We have initMu, activeMu, so slots won't change, conditions and * mutexes won't be initialized on-demand. *) act := me; REPEAT PThreadLockMutex(act.mutex, ThisLine()); act := act.next; UNTIL act = me; END AtForkPrepare; PROCEDURE AtForkParent() = VAR me := GetActivation(); act: Activation; BEGIN (* Walk activations and unlock all threads, conditions. *) act := me; REPEAT PThreadUnlockMutex(act.mutex, ThisLine()); act := act.next; UNTIL act = me; PThreadUnlockMutex(activeMu, ThisLine()); UnlockHeap(); PThreadUnlockMutex(initMu, ThisLine()); PThreadUnlockMutex(perfMu, ThisLine()); PThreadUnlockMutex(slotsMu, ThisLine()); END AtForkParent; PROCEDURE AtForkChild() = BEGIN AtForkParent(); InitWithStackBase(GetActivation().stackbase); END AtForkChild; (*------------------------------------------------------------- collector ---*) (* These procedures provide synchronization primitives for the allocator and collector. *) VAR holder: pthread_t; inCritical := 0; PROCEDURE LockHeap () = VAR self := pthread_self(); BEGIN IF pthread_equal(holder, self) = 0 THEN WITH r = pthread_mutex_lock(heapMu) DO <*ASSERT r=0*> END; holder := self; END; INC(inCritical); END LockHeap; PROCEDURE UnlockHeap () = BEGIN <*ASSERT pthread_equal(holder, pthread_self()) # 0*> DEC(inCritical); IF inCritical = 0 THEN holder := NIL; WITH r = pthread_mutex_unlock(heapMu) DO <*ASSERT r=0*> END; END; END UnlockHeap; PROCEDURE WaitHeap () = VAR self := pthread_self(); BEGIN <*ASSERT pthread_equal(holder, self) # 0*> DEC(inCritical); <*ASSERT inCritical = 0*> WITH r = pthread_cond_wait(heapCond, heapMu) DO <*ASSERT r=0*> END; holder := self; <*ASSERT inCritical = 0*> INC(inCritical); END WaitHeap; PROCEDURE BroadcastHeap () = BEGIN WITH r = pthread_cond_broadcast(heapCond) DO <*ASSERT r=0*> END; END BroadcastHeap; (*--------------------------------------------- exception handling support --*) PROCEDURE GetCurrentHandlers (): ADDRESS = VAR me := GetActivation(); BEGIN RETURN me.frame; END GetCurrentHandlers; PROCEDURE SetCurrentHandlers (h: ADDRESS) = VAR me := GetActivation(); BEGIN me.frame := h; END SetCurrentHandlers; (*RTHooks.PushEFrame*) PROCEDURE PushEFrame (frame: ADDRESS) = TYPE Frame = UNTRACED REF RECORD next: ADDRESS END; VAR me := GetActivation(); f: Frame := frame; BEGIN f.next := me.frame; me.frame := f; END PushEFrame; (*RTHooks.PopEFrame*) PROCEDURE PopEFrame (frame: ADDRESS) = VAR me := GetActivation(); BEGIN me.frame := frame; END PopEFrame; VAR DEBUG := RTParams.IsPresent("debugthreads"); BEGIN END ThreadPThread. From mika at async.caltech.edu Mon Aug 25 08:13:35 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sun, 24 Aug 2014 23:13:35 -0700 Subject: [M3devel] pthreads efficiency Message-ID: <20140825061336.09DEC1A20AC@async.async.caltech.edu> Hi again m3devel, This is my promised email about "issues" with the pthreads library. My application is an optimization program that operates basically as follows: it simulates an electronic circuit until it finds a problem, then it aborts the simulation, makes an adjustment to the circuit, and re-simulate. The adjustment and simulation loop is inherently sequential. But Einstein teaches that physics is parallel. That means that any physical simulation, at the limit, can be parallelized. Although the size of the system that is being simulated can put limits on how much parallelism you can extract. My chosen architecture for the simulation (mentioned in previous email) is a master thread that acts as a "conductor" for N "worker" threads (well call them musicians if you want to). The code is structured as a little bit of computation (workers running, mater waiting for them), followed by a barrier synchronization (all workers stopped, master performing some status computations). Each of the N+1 threads is a Modula-3 thread, thus in practice a pthread. I fairly quickly realized that one of the problems with my implementation was that the pthreads synchronization primitives and the Modula-3 primitives built on top of them are not a perfect match. I wound up using POSIX semaphores instead (sem_wait, sem_post). Not a big deal but will require work if I ever want to port back to user threads (hope not, let's get pthreads working everywhere???) So my code now uses semaphores and runs fairly well. I get about 600% CPU at best (on a 12-core machine---well maybe it's just 6 cores but they are hyperthreaded up to 12 and in C you can get 1200%). I think the performance issue now is with the garbage collector, and I'd like some advice on how to proceed. I'm attaching a backtrace from a run of my program. Noteworthy is that my program generates VERY little garbage. I have coded it very carefully to recycle all its memory. The program has noticeable hangs while running. The backtrace was captured during one of these hangs. We see a lot of this stuff: #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca120 in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=) at ../src/runtime/common/RTCollector.m3:2234 #6 0x000000000041b78a in PllERS__DoOneTimestep (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:712 #7 0x000000000041c81e in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:653 #8 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #9 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #10 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #11 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #12 0x0000000000000000 in ?? () This is not really acceptable for my application. I anticipate I have 100-fold parallelism in it. I can get a machine with 50 cores, I should be able to get 5,000% CPU out of it no problem. I think I am limited to about threefold speedup with the garbage collector mutex locking as above. But at the same time I realize that if your application is performing arbitrary memory references and you are in a garbage-collected environment, there is an implicit dependency on the garbage collector for heap references. I'm not asking for the impossible. Here's what I'd like to propose and I'd like to hear (from Tony or anyone else) whether what I'm proposing is sensible at all: My application is structed as worker threads-barrier synchronization-worker threads-etc. This is a common pattern in physical simulations in high-performance computing. Can I turn off the garbage collector while the worker threads are running and somehow dispense with the "CheckLoadTracedRef", or at least with the mutex lock? I will do whatever is necessry to ensure that the system doesn't need to lock while the workers are running. I don't care if it locks when they are stopped... Worst case maybe we can push updates from the worker threads on to a queue to be sorted out during the barrier interval. Or something. The locks do need to be avoided somehow. And yes I have looked at what it is that is being loaded by my program. It is an almost entirely static structure that changes very slowly---it is only updated BETWEEN runs of the simulation, not during simulation itself. And it never shrinks, so it never garbage collected. Does that help somehow? Mika P.S. I'm also attaching the Semaphore code if anyone finds that interesting. -------------- next part -------------- Thread 20 (Thread 0x2aaab118e700 (LWP 5191)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 19 (Thread 0x2aaab0f8d700 (LWP 5190)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 18 (Thread 0x2aaab0d8c700 (LWP 5189)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 17 (Thread 0x2aaab0b8b700 (LWP 5188)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 16 (Thread 0x2aaab098a700 (LWP 5187)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 15 (Thread 0x2aaab0789700 (LWP 5186)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 14 (Thread 0x2aaab0588700 (LWP 5185)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 13 (Thread 0x2aaab0387700 (LWP 5184)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 12 (Thread 0x2aaab0186700 (LWP 5183)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfaf4c0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c7fa in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:649 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 11 (Thread 0x2aaaaff85700 (LWP 5182)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca27f in RTHooks__CheckStoreTraced (M3_Af40ku_dst=) at ../src/runtime/common/RTCollector.m3:2255 #6 0x000000000041c55f in PllERS__HandleFanout (M3_De1Q5p_cl=, M3_BZemAb_f=...) at ../src/PllERS.m3:403 #7 0x000000000041c78d in PllERS__FlushFanouts (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:438 #8 0x000000000041c810 in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:652 #9 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #10 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #11 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #12 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #13 0x0000000000000000 in ?? () Thread 10 (Thread 0x2aaaafd84700 (LWP 5181)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca120 in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=) at ../src/runtime/common/RTCollector.m3:2234 #6 0x000000000041b48a in PllERS__DoOneTimestep (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:701 #7 0x000000000041c81e in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:653 #8 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #9 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #10 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #11 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #12 0x0000000000000000 in ?? () Thread 9 (Thread 0x2aaaafb83700 (LWP 5180)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca120 in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=) at ../src/runtime/common/RTCollector.m3:2234 #6 0x000000000041b78a in PllERS__DoOneTimestep (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:712 #7 0x000000000041c81e in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:653 #8 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #9 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #10 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #11 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #12 0x0000000000000000 in ?? () Thread 8 (Thread 0x2aaaaf982700 (LWP 5179)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfadaf0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c846 in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:660 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 7 (Thread 0x2aaaaf781700 (LWP 5178)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca27f in RTHooks__CheckStoreTraced (M3_Af40ku_dst=) at ../src/runtime/common/RTCollector.m3:2255 #6 0x000000000041c55f in PllERS__HandleFanout (M3_De1Q5p_cl=, M3_BZemAb_f=...) at ../src/PllERS.m3:403 #7 0x000000000041c78d in PllERS__FlushFanouts (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:438 #8 0x000000000041c810 in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:652 #9 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #10 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #11 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #12 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #13 0x0000000000000000 in ?? () Thread 6 (Thread 0x2aaaaf580700 (LWP 5177)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca27f in RTHooks__CheckStoreTraced (M3_Af40ku_dst=) at ../src/runtime/common/RTCollector.m3:2255 #6 0x000000000041c55f in PllERS__HandleFanout (M3_De1Q5p_cl=, M3_BZemAb_f=...) at ../src/PllERS.m3:403 #7 0x000000000041c78d in PllERS__FlushFanouts (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:438 #8 0x000000000041c810 in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:652 #9 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #10 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #11 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #12 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #13 0x0000000000000000 in ?? () Thread 5 (Thread 0x2aaaaf37f700 (LWP 5176)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca120 in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=) at ../src/runtime/common/RTCollector.m3:2234 #6 0x000000000041b78a in PllERS__DoOneTimestep (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:712 #7 0x000000000041c81e in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:653 #8 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #9 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #10 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #11 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #12 0x0000000000000000 in ?? () Thread 4 (Thread 0x2aaaaf17e700 (LWP 5175)): #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaac1b9339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaac1b915b in __pthread_mutex_lock (mutex=0xf96880) at pthread_mutex_lock.c:61 #3 0x00000000004df034 in ThreadPThread__pthread_mutex_lock (mutex=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x00000000004de22a in RTOS__LockHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1375 #5 0x00000000004ca120 in RTHooks__CheckLoadTracedRef (M3_Af40ku_ref=) at ../src/runtime/common/RTCollector.m3:2234 #6 0x000000000041b48a in PllERS__DoOneTimestep (M3_De1Q5p_cl=, M3_CiABk7_fi=) at ../src/PllERS.m3:701 #7 0x000000000041c81e in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:653 #8 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #9 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #10 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #11 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #12 0x0000000000000000 in ?? () Thread 3 (Thread 0x2aaaaef7d700 (LWP 5174)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfadaf0) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041c846 in PllERS__CApply (M3_De1Q5p_cl=) at ../src/PllERS.m3:660 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 2 (Thread 0x2aaaaed7c700 (LWP 5173)): #0 pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:162 #1 0x00000000004deeda in ThreadPThread__pthread_cond_wait (i=0xf968c0, j=0xf96880) at ../src/thread/PTHREAD/ThreadPThreadC.c:454 #2 0x00000000004de3ce in RTOS__WaitHeap () at ../src/thread/PTHREAD/ThreadPThread.m3:1397 #3 0x00000000004c9d54 in RTCollector__WeakCleaner (M3_EMTrVz_closure=) at ../src/runtime/common/RTCollector.m3:2185 #4 0x00000000004db633 in ThreadPThread__RunThread (M3_DMxDjQ_me=) at ../src/thread/PTHREAD/ThreadPThread.m3:518 #5 0x00000000004db2f0 in ThreadPThread__ThreadBase (M3_AJWxb1_param=) at ../src/thread/PTHREAD/ThreadPThread.m3:491 #6 0x00002aaaac1b6b50 in start_thread (arg=) at pthread_create.c:304 #7 0x00002aaaac4a6a7d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 #8 0x0000000000000000 in ?? () Thread 1 (Thread 0x2aaaaeb7a2a0 (LWP 5163)): #0 sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86 #1 0x0000000000420a30 in SemaphoreC__sem_wait (sem=0xfadb50) at ../src/SemaphoreC.c:16 #2 0x0000000000420bac in Semaphore (M3_Cfdzoy_t=) at ../src/Semaphore.m3:34 #3 0x000000000041a998 in PllERS__WaitForWorkers (M3_Cfdzoy_s=) at ../src/PllERS.m3:522 #4 0x000000000041c238 in PllERS__DoVisits (M3_De1Q5o_iter=) at ../src/PllERS.m3:545 #5 0x000000000041223c in Main__DoDumpAll (M3_CIrmEi_dMode=) at ../src/Main.m3:147 #6 0x0000000000419fb9 in Main_M3 (M3_AcxOUs_mode=) at ../src/Main.m3:1244 #7 0x00000000004ce4d9 in RTLinker__RunMainBody (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:408 #8 0x00000000004cd864 in RTLinker__AddUnitI (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:115 #9 0x00000000004cd8f8 in RTLinker__AddUnit (M3_DjPxE5_b=) at ../src/runtime/common/RTLinker.m3:124 #10 0x0000000000406278 in main (argc=5, argv=0x7fffffffe308, envp=0x7fffffffe338) at _m3main.c:22 -------------- next part -------------- (* $Id: Semaphore.m3,v 1.3 2014/08/23 05:50:51 mika Exp $ *) UNSAFE MODULE Semaphore; FROM SemaphoreC IMPORT sem_init, sem_destroy, sem_post, sem_wait, sem_getvalue, sem_alloc; IMPORT WeakRef; FROM Ctypes IMPORT int; REVEAL T = BRANDED Brand REF RECORD sem : ADDRESS; END; PROCEDURE New() : T = BEGIN WITH q = sem_alloc(), r = sem_init(q), n = NEW(T, sem := q) DO <*ASSERT r = 0*> EVAL WeakRef.FromRef(n, Cleanup); RETURN n END END New; PROCEDURE Cleanup(<*UNUSED*>READONLY self : WeakRef.T; ref : REFANY) = VAR d : T := ref; BEGIN WITH r = sem_destroy(d.sem) DO <*ASSERT r = 0*> END END Cleanup; PROCEDURE P(t : T) = BEGIN WITH r = sem_wait(t.sem) DO <*ASSERT r=0*> END END P; PROCEDURE V(t : T) = VAR r : INTEGER; BEGIN REPEAT r := sem_post(t.sem) UNTIL r = 0 END V; PROCEDURE Value(t : T) : INTEGER = VAR res : int; BEGIN WITH r = sem_getvalue(t.sem, res) DO <*ASSERT r=0*> END; RETURN res END Value; BEGIN END Semaphore. -------------- next part -------------- (* $Id: Semaphore.i3,v 1.1 2014/08/23 02:50:54 mika Exp $ *) INTERFACE Semaphore; TYPE T <: REFANY; PROCEDURE New() : T; PROCEDURE P(t : T); PROCEDURE V(t : T); PROCEDURE Value(t : T) : INTEGER; CONST Brand = "Semaphore"; END Semaphore. -------------- next part -------------- (* $Id: SemaphoreC.i3,v 1.1 2014/08/23 02:50:54 mika Exp $ *) INTERFACE SemaphoreC; FROM Ctypes IMPORT int; <*EXTERNAL "SemaphoreC__sem_alloc"*> PROCEDURE sem_alloc() : ADDRESS; <*EXTERNAL "SemaphoreC__sem_init"*> PROCEDURE sem_init(sem : ADDRESS) : int; <*EXTERNAL "SemaphoreC__sem_destroy"*> PROCEDURE sem_destroy(sem : ADDRESS) : int; <*EXTERNAL "SemaphoreC__sem_post"*> PROCEDURE sem_post(sem : ADDRESS) : int; <*EXTERNAL "SemaphoreC__sem_wait"*> PROCEDURE sem_wait(sem : ADDRESS) : int; <*EXTERNAL "SemaphoreC__sem_getvalue"*> PROCEDURE sem_getvalue(sem : ADDRESS; VAR value : int) : int; END SemaphoreC. -------------- next part -------------- #include #include #include #include /* $Id: SemaphoreC.c,v 1.2 2014/08/23 05:50:51 mika Exp $ */ /* Author : Mika Nystrom */ #define DEBUG 0 int SemaphoreC__sem_wait(void *sem) { int r; if(DEBUG)fprintf(stderr, "sem_wait(0x%x)--->\n", sem); r = sem_wait(sem); if(DEBUG)fprintf(stderr, "<---sem_wait(0x%x)\n", sem); return r; } int SemaphoreC__sem_post(void * sem) { int r; if(DEBUG)fprintf(stderr, "sem_post(0x%x)\n", sem); r = sem_post(sem); return r; } int SemaphoreC__sem_getvalue(void *sem, int *value) { int r = sem_getvalue(sem, value); return r; } void * SemaphoreC__sem_alloc(void) { void *a=malloc(sizeof(sem_t)); assert(a); return a; } int SemaphoreC__sem_init(void *sem) { return sem_init(sem, 0, 0); } int SemaphoreC__sem_destroy(void *sem) { int r = sem_destroy(sem); free(sem); return r; } From wagner at elego.de Mon Aug 25 10:04:51 2014 From: wagner at elego.de (Olaf Wagner) Date: Mon, 25 Aug 2014 10:04:51 +0200 Subject: [M3devel] pthreads status In-Reply-To: <20140825054921.B14421A20AC@async.async.caltech.edu> References: <20140825054921.B14421A20AC@async.async.caltech.edu> Message-ID: <20140825100451.9f459db1d90518072bb21577@elego.de> On Sun, 24 Aug 2014 22:49:21 -0700 mika at async.caltech.edu wrote: > I don't know the precise procedure for submitting things anymore, with the > git migration. Tony has a copy of the code I'm also attaching to this email, > which is the correctly functioning ThreadPThread.m3 for AMD64_LINUX. It would be great if someone could document the migration to git and the new access procedures in the existing HTML pages. A news item would also be appropritate. All the documentation is contained in the www subdirectory of the cm3 repository. I know that the existing web pages aren't very fancy, but I think it would be better to keep them until they have been replaced by someting new and better. So if somebody can produce some updates I'll install them on the web server. Olaf -- Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 95 Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 From hosking at cs.purdue.edu Mon Aug 25 18:01:51 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Mon, 25 Aug 2014 12:01:51 -0400 Subject: [M3devel] Git repository Message-ID: Does anyone on this mailing list own the opencm3 user id on github? Antony Hosking | Associate Professor | Computer Science | Purdue University 305 N. University Street | West Lafayette | IN 47907 | USA Mobile +1 765 427 5484 -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Mon Aug 25 19:21:50 2014 From: dragisha at m3w.org (dragisha at m3w.org) Date: Mon, 25 Aug 2014 19:21:50 +0200 Subject: [M3devel] Git repository In-Reply-To: References: Message-ID: <8d73154d787adf2f028a9ce3cb4998d7@m3w.org> AFAIK, no. OpenCM3-NET is ours. dd On 25.08.2014 18:01, Tony Hosking wrote: > Does anyone on this mailing list own the opencm3 user id on github? > > Antony Hosking | Associate Professor | Computer Science | Purdue > University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 From dragisha at m3w.org Mon Aug 25 20:41:50 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Mon, 25 Aug 2014 20:41:50 +0200 Subject: [M3devel] Git repository In-Reply-To: References: <8d73154d787adf2f028a9ce3cb4998d7@m3w.org> Message-ID: <3FE0052C-1270-496C-AA52-BB448293D170@m3w.org> Argh :) Good thing my notes have getter recollection than me. Yes - opencm3 is also registered by me. So yes, it is ours too :) dd On 25 Aug 2014, at 20:06, Darko Volaric wrote: > Are you sure you didn't create it accidently? It has the same creation date as OpenCM3-NET. Seems like an incredible coincidence. > > > On Mon, Aug 25, 2014 at 10:21 AM, wrote: > AFAIK, no. > > OpenCM3-NET is ours. > > dd > > On 25.08.2014 18:01, Tony Hosking wrote: > Does anyone on this mailing list own the opencm3 user id on github? > > Antony Hosking | Associate Professor | Computer Science | Purdue > University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Mon Aug 25 20:54:10 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Mon, 25 Aug 2014 20:54:10 +0200 Subject: [M3devel] Git repository In-Reply-To: <5DC431EE-1DA9-4C87-AD8A-953DD7A3268A@purdue.edu> References: <8d73154d787adf2f028a9ce3cb4998d7@m3w.org> <3FE0052C-1270-496C-AA52-BB448293D170@m3w.org> <5DC431EE-1DA9-4C87-AD8A-953DD7A3268A@purdue.edu> Message-ID: <2546DD56-FC7B-436B-BB57-4B24DBE814C6@m3w.org> opencm3 is user, and OpenCM3-NET is an organization. Modula3/cm3 is good idea. I have already transferred both repos there. pm3 is not fully verified, but I will do it later on from CVS. dd On 25 Aug 2014, at 20:45, Antony Hosking wrote: > Is opencm3 an organization or what? Let?s leave it there for now. > I suggest we use the (renamed) modula3 organization and put everything M3 related there. This will include both the pm3 and cm3 repos, as converted by you. I sent instructions on how you can move them to the organization from your current ownership. I?m being pretty liberal on adding owners of the organization right now. Ultimately we will probably want to restrict org ownership to a small group while assigning commit privileges on different repos to different teams. > > On Aug 25, 2014, at 2:41 PM, Dragi?a Duri? wrote: > >> Argh :) >> >> Good thing my notes have getter recollection than me. >> >> Yes - opencm3 is also registered by me. So yes, it is ours too :) >> >> dd >> >> On 25 Aug 2014, at 20:06, Darko Volaric wrote: >> >>> Are you sure you didn't create it accidently? It has the same creation date as OpenCM3-NET. Seems like an incredible coincidence. >>> >>> >>> On Mon, Aug 25, 2014 at 10:21 AM, wrote: >>> AFAIK, no. >>> >>> OpenCM3-NET is ours. >>> >>> dd >>> >>> On 25.08.2014 18:01, Tony Hosking wrote: >>> Does anyone on this mailing list own the opencm3 user id on github? >>> >>> Antony Hosking | Associate Professor | Computer Science | Purdue >>> University >>> 305 N. University Street | West Lafayette | IN 47907 | USA >>> Mobile +1 765 427 5484 >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From lists at darko.org Mon Aug 25 20:57:16 2014 From: lists at darko.org (Darko Volaric) Date: Mon, 25 Aug 2014 11:57:16 -0700 Subject: [M3devel] Git repository In-Reply-To: <2546DD56-FC7B-436B-BB57-4B24DBE814C6@m3w.org> References: <8d73154d787adf2f028a9ce3cb4998d7@m3w.org> <3FE0052C-1270-496C-AA52-BB448293D170@m3w.org> <5DC431EE-1DA9-4C87-AD8A-953DD7A3268A@purdue.edu> <2546DD56-FC7B-436B-BB57-4B24DBE814C6@m3w.org> Message-ID: I think that user would be useful for performing administrative tasks, so it's clear that it's not the contributions of a particular user. On Mon, Aug 25, 2014 at 11:54 AM, Dragi?a Duri? wrote: > opencm3 is user, and OpenCM3-NET is an organization. > > Modula3/cm3 is good idea. I have already transferred both repos there. pm3 > is not fully verified, but I will do it later on from CVS. > > dd > > On 25 Aug 2014, at 20:45, Antony Hosking wrote: > > Is opencm3 an organization or what? Let?s leave it there for now. > I suggest we use the (renamed) modula3 organization and put everything M3 > related there. This will include both the pm3 and cm3 repos, as converted > by you. I sent instructions on how you can move them to the organization > from your current ownership. I?m being pretty liberal on adding owners of > the organization right now. Ultimately we will probably want to restrict > org ownership to a small group while assigning commit privileges on > different repos to different teams. > > On Aug 25, 2014, at 2:41 PM, Dragi?a Duri? wrote: > > Argh :) > > Good thing my notes have getter recollection than me. > > Yes - opencm3 is also registered by me. So yes, it is ours too :) > > dd > > On 25 Aug 2014, at 20:06, Darko Volaric wrote: > > Are you sure you didn't create it accidently? It has the same creation > date as OpenCM3-NET. Seems like an incredible coincidence. > > > On Mon, Aug 25, 2014 at 10:21 AM, wrote: > >> AFAIK, no. >> >> OpenCM3-NET is ours. >> >> dd >> >> On 25.08.2014 18:01, Tony Hosking wrote: >> >>> Does anyone on this mailing list own the opencm3 user id on github? >>> >>> Antony Hosking | Associate Professor | Computer Science | Purdue >>> University >>> 305 N. University Street | West Lafayette | IN 47907 | USA >>> Mobile +1 765 427 5484 >>> >> > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From wagner at elegosoft.com Tue Aug 26 07:51:01 2014 From: wagner at elegosoft.com (Olaf Wagner) Date: Tue, 26 Aug 2014 07:51:01 +0200 Subject: [M3devel] pthreads status In-Reply-To: References: <20140825054921.B14421A20AC@async.async.caltech.edu> <20140825100451.9f459db1d90518072bb21577@elego.de> Message-ID: <20140826075101.ff0c83e564c3bf768d6d2c7b@elegosoft.com> On Mon, 25 Aug 2014 16:12:16 -0400 Antony Hosking wrote: > Who owns/maintains the modula3.org domain? I think this is actually owned by elego -- yes, whois confirms that. Would you like it to be transferred? For the short term, we can add and modify entries as the m3 developers wish. Olaf > On Aug 25, 2014, at 4:04 AM, Olaf Wagner wrote: > > > On Sun, 24 Aug 2014 22:49:21 -0700 > > mika at async.caltech.edu wrote: > > > >> I don't know the precise procedure for submitting things anymore, with the > >> git migration. Tony has a copy of the code I'm also attaching to this email, > >> which is the correctly functioning ThreadPThread.m3 for AMD64_LINUX. > > > > It would be great if someone could document the migration to git > > and the new access procedures in the existing HTML pages. A news > > item would also be appropritate. > > > > All the documentation is contained in the www subdirectory of the > > cm3 repository. > > > > I know that the existing web pages aren't very fancy, but I think it > > would be better to keep them until they have been replaced by someting > > new and better. > > > > So if somebody can produce some updates I'll install them on the > > web server. > > > > Olaf > > -- > > Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com > > Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany > > phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 95 > > Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin > > Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 > -- Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 95 Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 From mika at async.caltech.edu Tue Aug 26 09:52:05 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Tue, 26 Aug 2014 00:52:05 -0700 Subject: [M3devel] pthreads committed to git Message-ID: <20140826075205.AAA8A1A20A3@async.async.caltech.edu> Hi m3devel, I just pushed---I think---the fixed version of ThreadPThread.m3 to github. There is no m3commit email from this? I (and I'm sure Tony too) am very curious to hear if this makes things worse on any OS. (E.g., if it causes the pthreads to freeze.) It works perfectly on my AMD64_LINUX system: fork, memory allocation, everything. Now to figure out whether the garbage collector bits can be sped up a bit. Mika From dragisha at m3w.org Tue Aug 26 11:01:49 2014 From: dragisha at m3w.org (dragisha at m3w.org) Date: Tue, 26 Aug 2014 11:01:49 +0200 Subject: [M3devel] pthreads committed to git In-Reply-To: <20140826075205.AAA8A1A20A3@async.async.caltech.edu> References: <20140826075205.AAA8A1A20A3@async.async.caltech.edu> Message-ID: <88e4d9c11631b31588a16b0f95f8d4ef@m3w.org> You can see on github what went through. There are some RSS feed to be used for notification automation, no emails as far as I can see. To ensure changes are commited, you need to "git add" changed files, and then "git commit" added files. After that "git push" will finish this. You can first "git add" all changed files, of course, and this way all will go through as single commit. There can be a conflict at "git push" in case someone did something conflicting with your changes remotely. Not right now, most probably, and you just need to do a "git pull" before "git push" to do merge locally. As I said, right now this will most probably be without conflict - not many people are changing. I will try to explain workflows as soon as I get some time. dd On 26.08.2014 09:52, mika at async.caltech.edu wrote: > Hi m3devel, > > I just pushed---I think---the fixed version of ThreadPThread.m3 to > github. > There is no m3commit email from this? > > I (and I'm sure Tony too) am very curious to hear if this makes things > worse on any OS. (E.g., if it causes the pthreads to freeze.) It > works > perfectly on my AMD64_LINUX system: fork, memory allocation, > everything. > > Now to figure out whether the garbage collector bits can be sped up a > bit. > > Mika From lists at darko.org Tue Aug 26 13:22:59 2014 From: lists at darko.org (Darko Volaric) Date: Tue, 26 Aug 2014 04:22:59 -0700 Subject: [M3devel] pthreads status In-Reply-To: <20140826075101.ff0c83e564c3bf768d6d2c7b@elegosoft.com> References: <20140825054921.B14421A20AC@async.async.caltech.edu> <20140825100451.9f459db1d90518072bb21577@elego.de> <20140826075101.ff0c83e564c3bf768d6d2c7b@elegosoft.com> Message-ID: Could we perhaps have the domain just redirect to the github project's wiki? The best chance of up to date documentation, news, etc is if anyone can quickly and easily update the info, since everyone is short of time. On Mon, Aug 25, 2014 at 10:51 PM, Olaf Wagner wrote: > On Mon, 25 Aug 2014 16:12:16 -0400 > Antony Hosking wrote: > > > Who owns/maintains the modula3.org domain? > > I think this is actually owned by elego -- yes, > whois confirms that. > > Would you like it to be transferred? > For the short term, we can add and modify entries > as the m3 developers wish. > > Olaf > > > On Aug 25, 2014, at 4:04 AM, Olaf Wagner wrote: > > > > > On Sun, 24 Aug 2014 22:49:21 -0700 > > > mika at async.caltech.edu wrote: > > > > > >> I don't know the precise procedure for submitting things anymore, > with the > > >> git migration. Tony has a copy of the code I'm also attaching to > this email, > > >> which is the correctly functioning ThreadPThread.m3 for AMD64_LINUX. > > > > > > It would be great if someone could document the migration to git > > > and the new access procedures in the existing HTML pages. A news > > > item would also be appropritate. > > > > > > All the documentation is contained in the www subdirectory of the > > > cm3 repository. > > > > > > I know that the existing web pages aren't very fancy, but I think it > > > would be better to keep them until they have been replaced by someting > > > new and better. > > > > > > So if somebody can produce some updates I'll install them on the > > > web server. > > > > > > Olaf > > > -- > > > Olaf Wagner -- elego Software Solutions GmbH -- > http://www.elegosoft.com > > > Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany > > > phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 > 45 86 95 > > > Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin > > > Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: > DE163214194 > > > > > -- > Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com > Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany > phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 > 95 > Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin > Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: > DE163214194 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From michael.anderson at elego.de Tue Aug 26 15:34:35 2014 From: michael.anderson at elego.de (Michael Anderson) Date: Tue, 26 Aug 2014 15:34:35 +0200 Subject: [M3devel] pthreads status In-Reply-To: References: <20140825054921.B14421A20AC@async.async.caltech.edu> <20140825100451.9f459db1d90518072bb21577@elego.de> Message-ID: <53FC8CEB.8010201@elego.de> Hi Antony, elego owns and manages the following Modula3 domains/DNS Zones: modula3.com modula3.org opencm3.com opencm3.de opencm3.net We would be glad to transfer the domains or set up redirects as needed - let me know what you'd like to do. Considering the remaining Modula3 infrastructure at elego: * Hudson The Hudson installation at http://hudson.modula3.com:8080 has not been actively maintained for some time. The hudson installation itself is outdated and, many (most?) of the build jobs and scripts are fairly broken and need work. Also, the jobs/scripts need to be modified to use Git instead of CVS. elego doesn't presently have resources to do this, and unless someone from the community take this upon themselves, I'd like to decommission the present Hudson instance at some point. If someone is interested in taking over the continuous integration side of things, please let me know. We would be glad to set up and host a fresh Jenkins installation on a new virtual server. * WWW & package download We can continue to host the websites at opencm3.* and modula3.* if desired. If I recall correctly, all of the HTML is in the cm3 repo, as well as a script to deploy changes to the website. Your account on birch.elego.de should have the necessary rights to run the deployment script. If anybody else would like to maintain the web presence, I can set up the appropriate account permissions. Perhaps the existing package archives should be moved to GitHub? * CVS I've chmodded the cvs repositories read-only. We can host them as long as desired. * Trac (cm3-bugs.elegosoft.com) I suppose you'll be using GitHub for issue tracking and wiki? Shall we keep the trac site going - perhaps read-only, with a link to the GitHub site? * birch.elego.de (linux-amd64 server) At some point in October/November I'll be migrating services from birch to new hardware. If we still have modula3 services running, I'll move them to a dedicated VM. Please let me know if you have any questions/problems. I can be contacted for at michael.anderson at elego.de. Regards, Michael Anderson On 25.08.2014 22:12, Antony Hosking wrote: > Who owns/maintains the modula3.org domain? > > > On Aug 25, 2014, at 4:04 AM, Olaf Wagner wrote: > >> On Sun, 24 Aug 2014 22:49:21 -0700 >> mika at async.caltech.edu wrote: >> >>> I don't know the precise procedure for submitting things anymore, with the >>> git migration. Tony has a copy of the code I'm also attaching to this email, >>> which is the correctly functioning ThreadPThread.m3 for AMD64_LINUX. >> It would be great if someone could document the migration to git >> and the new access procedures in the existing HTML pages. A news >> item would also be appropritate. >> >> All the documentation is contained in the www subdirectory of the >> cm3 repository. >> >> I know that the existing web pages aren't very fancy, but I think it >> would be better to keep them until they have been replaced by someting >> new and better. >> >> So if somebody can produce some updates I'll install them on the >> web server. >> >> Olaf >> -- >> Olaf Wagner -- elego Software Solutions GmbH -- http://www.elegosoft.com >> Gustav-Meyer-Allee 25 / Geb?ude 12, 13355 Berlin, Germany >> phone: +49 30 23 45 86 96 mobile: +49 177 2345 869 fax: +49 30 23 45 86 95 >> Gesch?ftsf?hrer: Michael Diers, Olaf Wagner | Sitz: Berlin >> Handelregister: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194 -- Michael Anderson IT Services & Support elego Software Solutions GmbH Gustav-Meyer-Allee 25 Building 12.3 (BIG) room 227 13355 Berlin, Germany phone +49 30 23 45 86 96 michael.anderson at elegosoft.com fax +49 30 23 45 86 95 http://www.elegosoft.com Geschaeftsfuehrer: Olaf Wagner, Michael Diers, Sitz Berlin Amtsgericht Berlin-Charlottenburg, HRB 77719, USt-IdNr: DE163214194 From dragisha at m3w.org Tue Aug 26 18:52:25 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Tue, 26 Aug 2014 18:52:25 +0200 Subject: [M3devel] pthreads committed to git In-Reply-To: <88e4d9c11631b31588a16b0f95f8d4ef@m3w.org> References: <20140826075205.AAA8A1A20A3@async.async.caltech.edu> <88e4d9c11631b31588a16b0f95f8d4ef@m3w.org> Message-ID: There is also some webhooks mechanism. We can work on webhook -> e-mail later on. dd On 26 Aug 2014, at 11:01, dragisha at m3w.org wrote: > You can see on github what went through. There are some RSS feed to be used for notification automation, no emails as far as I can see. > > To ensure changes are commited, you need to "git add" changed files, and then "git commit" added files. After that "git push" will finish this. You can first "git add" all changed files, of course, and this way all will go through as single commit. > > There can be a conflict at "git push" in case someone did something conflicting with your changes remotely. Not right now, most probably, and you just need to do a "git pull" before "git push" to do merge locally. As I said, right now this will most probably be without conflict - not many people are changing. > > I will try to explain workflows as soon as I get some time. > > dd > > On 26.08.2014 09:52, mika at async.caltech.edu wrote: >> Hi m3devel, >> I just pushed---I think---the fixed version of ThreadPThread.m3 to github. >> There is no m3commit email from this? >> I (and I'm sure Tony too) am very curious to hear if this makes things >> worse on any OS. (E.g., if it causes the pthreads to freeze.) It works >> perfectly on my AMD64_LINUX system: fork, memory allocation, everything. >> Now to figure out whether the garbage collector bits can be sped up a bit. >> Mika -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From lists at darko.org Tue Aug 26 20:48:22 2014 From: lists at darko.org (Darko Volaric) Date: Tue, 26 Aug 2014 11:48:22 -0700 Subject: [M3devel] How to Commit Wiki Page Message-ID: I've started the nub of a page on how to commit to git. It's very basic right now. If you have anything to add please update the page directly: https://github.com/modula3/cm3/wiki/How-to-Commit -------------- next part -------------- An HTML attachment was scrubbed... URL: From hosking at cs.purdue.edu Tue Aug 26 23:12:21 2014 From: hosking at cs.purdue.edu (Tony Hosking) Date: Tue, 26 Aug 2014 17:12:21 -0400 Subject: [M3devel] github Message-ID: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> Something weird happened on my recent git commit. Why did I end up committing thousands of files? Antony Hosking | Associate Professor | Computer Science | Purdue University 305 N. University Street | West Lafayette | IN 47907 | USA Mobile +1 765 427 5484 -------------- next part -------------- An HTML attachment was scrubbed... URL: From lists at darko.org Tue Aug 26 23:26:52 2014 From: lists at darko.org (Darko Volaric) Date: Tue, 26 Aug 2014 14:26:52 -0700 Subject: [M3devel] github In-Reply-To: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> References: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> Message-ID: Did you do 'git pull origin master' before your add's? Apparently that's important. On Tue, Aug 26, 2014 at 2:12 PM, Tony Hosking wrote: > Something weird happened on my recent git commit. > Why did I end up committing thousands of files? > > Antony Hosking | Associate Professor | Computer Science | Purdue > University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Wed Aug 27 08:04:49 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 27 Aug 2014 08:04:49 +0200 Subject: [M3devel] github In-Reply-To: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> References: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> Message-ID: <43ADA110-F52B-4F90-ADDB-8DADFE82FAC2@m3w.org> It is a merge operation. You can study "git status? output at any time, but after you ?git pull? two operations are done implicitly. One is ?git fetch? and this operation updates your local copy of origin/master branch. Second is "git merge? and this operation merges origin/master to your master. Files changed by other people can show in your commit, but that is how DAG of Git commits synchronizes. All looks well in repo. On 26 Aug 2014, at 23:12, Tony Hosking wrote: > Something weird happened on my recent git commit. > Why did I end up committing thousands of files? > > Antony Hosking | Associate Professor | Computer Science | Purdue University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From lists at darko.org Wed Aug 27 17:47:27 2014 From: lists at darko.org (Darko Volaric) Date: Wed, 27 Aug 2014 08:47:27 -0700 Subject: [M3devel] github In-Reply-To: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> References: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> Message-ID: Apparently this is because of the name change of the repository, or its owner. You'll need to do a clone of the new repository before commits to avoid the problem. Dragisha is fixing it up... On Tue, Aug 26, 2014 at 2:12 PM, Tony Hosking wrote: > Something weird happened on my recent git commit. > Why did I end up committing thousands of files? > > Antony Hosking | Associate Professor | Computer Science | Purdue > University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From dragisha at m3w.org Wed Aug 27 20:37:01 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 27 Aug 2014 20:37:01 +0200 Subject: [M3devel] github In-Reply-To: References: <7CC5CB49-D9E9-4511-82D6-7F3E59B0FBB4@cs.purdue.edu> Message-ID: <3361C17B-D932-4646-9F44-737760EFA5A5@m3w.org> Problem really looks like that. It did not happen to me, but I was using strict workflow. Git is like that - a sharp knife. But it gives a lot back, I believe we will all reap benefits from it RSN. Good news 2 - build problems on AMD64_DARWIN I had just went away with few fixes - one I am sure of is one already commited. I am trying few other gcc variants now to see what OSX Mavericks gcc options are good for cm3 build. One thing I know already - C backend has a problem, some ASSERT fails. As it is my first priority to have cm3 running I only changed backend mode from C to 3. More coming. On 27 Aug 2014, at 17:47, Darko Volaric wrote: > Apparently this is because of the name change of the repository, or its owner. You'll need to do a clone of the new repository before commits to avoid the problem. > > Dragisha is fixing it up... > > > > > On Tue, Aug 26, 2014 at 2:12 PM, Tony Hosking wrote: > Something weird happened on my recent git commit. > Why did I end up committing thousands of files? > > Antony Hosking | Associate Professor | Computer Science | Purdue University > 305 N. University Street | West Lafayette | IN 47907 | USA > Mobile +1 765 427 5484 > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From dragisha at m3w.org Wed Aug 27 20:40:40 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 27 Aug 2014 20:40:40 +0200 Subject: [M3devel] problems on FreeBSD 10.0-RELEASE In-Reply-To: <20140526192247.0A2D71A209C@async.async.caltech.edu> References: <20140526192247.0A2D71A209C@async.async.caltech.edu> Message-ID: <16855160-1383-4121-B1F3-7737653D53D3@m3w.org> Mika, If you did not fix this already - last commit on origin/master probably will do it for you. dd On 26 May 2014, at 21:22, mika at async.caltech.edu wrote: > Hi m3devel, > > The usual story.. new computer, new OS, trying to set up CM3. > > I installed the binary snapshot > > cm3-bin-core-AMD64_FREEBSD-d5.9.0-x86_64-unknown-freebsd8.3-2013-10-15-17-59-51.tgz > > cvs synced against current as of today > > ran ./upgrade.sh and got various errors. (See below.) Versions... > > root at pluto:/home/mika/cm3/cm3/scripts # uname -a > FreeBSD pluto 10.0-RELEASE-p3 FreeBSD 10.0-RELEASE-p3 #0: Tue May 13 18:31:10 UTC 2014 root at amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 > > root at pluto:/home/mika/cm3/cm3/scripts # gcc -v > Using built-in specs. > COLLECT_GCC=gcc > COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc47/gcc/x86_64-portbld-freebsd10.0/4.7.3/lto-wrapper > Target: x86_64-portbld-freebsd10.0 > Configured with: ./../gcc-4.7.3/configure --disable-bootstrap --disable-nls --enable-gnu-indirect-function --libdir=/usr/local/lib/gcc47 --libexecdir=/usr/local/libexec/gcc47 --program-suffix=47 --with-as=/usr/local/bin/as --with-gmp=/usr/local --with-gxx-include-dir=/usr/local/lib/gcc47/include/c++/ --with-ld=/usr/local/bin/ld --with-pkgversion='FreeBSD Ports Collection' --with-system-zlib --with-ecj-jar=/usr/local/share/java/ecj-4.5.jar --enable-languages=c,c++,objc,fortran,java --prefix=/usr/local --mandir=/usr/local/man --infodir=/usr/local/info/gcc47 --build=x86_64-portbld-freebsd10.0 > Thread model: posix > gcc version 4.7.3 (FreeBSD Ports Collection) > root at pluto:/home/mika/cm3/cm3/scripts # > > Any ideas? It looks like gcc is having trouble compiling gcc? > > Mika > > > build/gcov-iov '4.7.1' '' \ >> tmp-gcov-iov.h > /bin/sh ../../gcc-4.7/gcc/../move-if-change tmp-gcov-iov.h gcov-iov.h > echo timestamp > s-iov > gcc -c -DIN_GCC_FRONTEND -g -O2 -DIN_GCC -Wno-missing-field-initializers -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.7/gcc -I../../gcc-4.7/gcc/. -I../../gcc-4.7/gcc/../include -I../../gcc-4.7/gcc/../libcpp/include -I/usr/local/include ../../gcc-4.7/gcc/attribs.c -o attribs.o > gcc -c -g -O2 -DIN_GCC -Wno-missing-field-initializers -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.7/gcc -I../../gcc-4.7/gcc/. -I../../gcc-4.7/gcc/../include -I../../gcc-4.7/gcc/../libcpp/include -I/usr/local/include ../../gcc-4.7/gcc/main.c -o main.o > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:46: > In file included from ../../gcc-4.7/gcc/tree.h:30: > ../../gcc-4.7/gcc/statistics.h:48:46: error: reference to 'function' is ambiguous > extern void statistics_counter_event (struct function *, const char *, int); > ^ > ../../gcc-4.7/gcc/statistics.h:41:8: note: candidate found by name lookup is 'function' > struct function; > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:46: > In file included from ../../gcc-4.7/gcc/tree.h:30: > ../../gcc-4.7/gcc/statistics.h:49:48: error: reference to 'function' is ambiguous > extern void statistics_histogram_event (struct function *, const char *, int); > ^ > ../../gcc-4.7/gcc/statistics.h:41:8: note: candidate found by name lookup is 'function' > struct function; > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > gcc -c -g -O2 -DIN_GCC -Wno-missing-field-initializers -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wc++-compat -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.7/gcc -I../../gcc-4.7/gcc/. -I../../gcc-4.7/gcc/../include -I../../gcc-4.7/gcc/../libcpp/include -I/usr/local/include ../../gcc-4.7/gcc/tree-browser.c -o tree-browser.o > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:46: > ../../gcc-4.7/gcc/tree.h:3547:10: error: reference to 'function' is ambiguous > struct function *f; > ^ > ../../gcc-4.7/gcc/tree.h:2653:8: note: candidate found by name lookup is 'function' > struct function; > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:643:24: error: reference to 'function' is ambiguous > add_local_decl (struct function *fun, tree d) > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:657:23: error: reference to 'function' is ambiguous > extern GTY(()) struct function *cfun; > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:693:30: error: reference to 'function' is ambiguous > extern void set_cfun (struct function *new_cfun); > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:694:31: error: reference to 'function' is ambiguous > extern void push_cfun (struct function *new_cfun); > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:732:40: error: reference to 'function' is ambiguous > extern void free_after_parsing (struct function *); > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:733:44: error: reference to 'function' is ambiguous > extern void free_after_compilation (struct function *); > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:764:50: error: reference to 'function' is ambiguous > extern bool optimize_function_for_size_p (struct function *); > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > In file included from ../../gcc-4.7/gcc/basic-block.h:26: > ../../gcc-4.7/gcc/function.h:765:51: error: reference to 'function' is ambiguous > extern bool optimize_function_for_speed_p (struct function *); > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: > In file included from ../../gcc-4.7/gcc/gimple.h:32: > ../../gcc-4.7/gcc/basic-block.h:779:31: error: reference to 'function' is ambiguous > extern void init_flow (struct function *); > ^../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:59: > ../../gcc-4.7/gcc/output.h:137:6: warning: 'format' attribute argument not supported: __asm_fprintf__ [-Wignored-attributes] > ATTRIBUTE_ASM_FPRINTF(2, 3); > ^ > ../../gcc-4.7/gcc/output.h:123:53: note: expanded from macro 'ATTRIBUTE_ASM_FPRINTF' > #define ATTRIBUTE_ASM_FPRINTF(m, n) __attribute__ ((__format__ (__asm_fprintf__, m, n))) ATTRIBUTE_NONNULL(m) > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:63: > ../../gcc-4.7/gcc/langhooks-def.h:40:38: error: reference to 'function' is ambiguous > extern void lhd_do_nothing_f (struct function *); > ^ > ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name lookup is 'function' > struct GTY(()) function { > ^ > /usr/include/c++/v1/__functional_03:206:44: note: candidate found by name lookup is 'std::__1::function' > template class _LIBCPP_TYPE_VIS function; // undefined > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:69: > In file included from ../../gcc-4.7/gcc/expr.h:28: > In file included from ../../gcc-4.7/gcc/rtl.h:2244: > ./genrtl.h:385:3: warning: array index 1 is past the end of the array (which contains 1 element) [-Warray-bounds] > XWINT (rt, 1) = arg1; > ^ ~ > ../../gcc-4.7/gcc/rtl.h:633:29: note: expanded from macro 'XWINT' > #define XWINT(RTX, N) ((RTX)->u.hwint[N]) > ^ > ../../gcc-4.7/gcc/rtl.h:344:5: note: array 'hwint' declared here > HOST_WIDE_INT hwint[1]; > ^ > ../../gcc-4.7/gcc/hwint.h:64:26: note: expanded from macro 'HOST_WIDE_INT' > # define HOST_WIDE_INT long > ^ > In file included from ../../gcc-4.7/gcc/m3cg/parse.c:69: > In file included from ../../gcc-4.7/gcc/expr.h:28: > In file included from ../../gcc-4.7/gcc/rtl.h:2244: > ./genrtl.h:386:3: warning: array index 2 is past the end of the array (which contains 1 element) [-Warray-bounds] > XWINT (rt, 2) = arg2; > ^ ~ > ../../gcc-4.7/gcc/rtl.h:633:29: note: expanded from macro 'XWINT' > #define XWINT(RTX, N) ((RTX)->u.hwint[N]) > ^ > ../../gcc-4.7/gcc/rtl.h:344:5: note: array 'hwint' declared here > HOST_WIDE_INT hwint[1]; > ^../../gcc-4.7/gcc/hwint.h:64:26: note: expanded from macro 'HOST_WIDE_INT' > # define HOST_WIDE_INT long > ^ > 3 warnings and 13 errors generated. > gmake: *** [m3cg/parse.o] Error 1 > gmake: *** Waiting for unfinished jobs.... > /bin/sh ../../gcc-4.7/gcc/../move-if-change tmp-attrtab.c insn-attrtab.c > echo timestamp > s-attrtab > /bin/sh ../../gcc-4.7/gcc/../move-if-change tmp-automata.c insn-automata.c > echo timestamp > s-automata > "/usr/home/mika/cm3/cm3/m3-sys/m3cc/src/m3makefile", line 327: quake runtime error: exit 2: cd ../AMD64_FREEBSD && cd gcc && gmake MAKE="gmake -j4 " AUTOCONF=: AUTOMAKE=: LEX='touch lex.yy.c' MAKEINFO=: -j4 s-modes insn-config.h m3cg > > --procedure-- -line- -file--- > exec -- > m3cc_Run 327 /usr/home/mika/cm3/cm3/m3-sys/m3cc/src/m3makefile > include_dir 577 /usr/home/mika/cm3/cm3/m3-sys/m3cc/src/m3makefile > 6 /usr/home/mika/cm3/cm3/m3-sys/m3cc/AMD64_FREEBSD/m3make.args > > Fatal Error: package build failed > ==> /home/mika/cm3/cm3/m3-sys/m3cc done > > Critical Mass Modula-3 version d5.9.0 > last updated: 2010-07-21 > compiled: 2014-05-26 19:11:28 > configuration: /usr/local/cm3/bin/cm3.cfg > host: AMD64_FREEBSD > quake runtime error: "/usr/local/cm3/bin/cm3.cfg", line 2: quake runtime error: undefined variable: SL > > --procedure-- -line- -file--- > 2 /usr/local/cm3/bin/cm3.cfg > target: > > ./upgrade.sh: /home/mika/cm3/cm3/m3-sys/m3cc/AMD64_FREEBSD/cm3cg: not found > root at pluto:/home/mika/cm3/cm3/scripts # > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From mika at async.caltech.edu Wed Aug 27 20:54:59 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Wed, 27 Aug 2014 11:54:59 -0700 Subject: [M3devel] problems on FreeBSD 10.0-RELEASE In-Reply-To: <16855160-1383-4121-B1F3-7737653D53D3@m3w.org> References: <20140526192247.0A2D71A209C@async.async.caltech.edu> <16855160-1383-4121-B1F3-7737653D53D3@m3w.org> Message-ID: <20140827185459.27E211A20B9@async.async.caltech.edu> I think last time I tried on FreeBSD (AMD64_FREEBSD) it was working again. But of course pthreads are still broken on that system. Haven't had time to look at that. Mika =?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?= writes: > >--Apple-Mail=_CFCEC712-B5CE-4266-A433-4CACD1B61CFA >Content-Transfer-Encoding: quoted-printable >Content-Type: text/plain; > charset=us-ascii > >Mika, > >If you did not fix this already - last commit on origin/master probably = >will do it for you. > >dd > >On 26 May 2014, at 21:22, mika at async.caltech.edu wrote: > >> Hi m3devel, >>=20 >> The usual story.. new computer, new OS, trying to set up CM3. >>=20 >> I installed the binary snapshot=20 >>=20 >> = >cm3-bin-core-AMD64_FREEBSD-d5.9.0-x86_64-unknown-freebsd8.3-2013-10-15-17-= >59-51.tgz >>=20 >> cvs synced against current as of today >>=20 >> ran ./upgrade.sh and got various errors. (See below.) Versions... >>=20 >> root at pluto:/home/mika/cm3/cm3/scripts # uname -a >> FreeBSD pluto 10.0-RELEASE-p3 FreeBSD 10.0-RELEASE-p3 #0: Tue May 13 = >18:31:10 UTC 2014 = >root at amd64-builder.daemonology.net:/usr/obj/usr/src/sys/GENERIC amd64 >>=20 >> root at pluto:/home/mika/cm3/cm3/scripts # gcc -v >> Using built-in specs. >> COLLECT_GCC=3Dgcc >> = >COLLECT_LTO_WRAPPER=3D/usr/local/libexec/gcc47/gcc/x86_64-portbld-freebsd1= >0.0/4.7.3/lto-wrapper >> Target: x86_64-portbld-freebsd10.0 >> Configured with: ./../gcc-4.7.3/configure --disable-bootstrap = >--disable-nls --enable-gnu-indirect-function = >--libdir=3D/usr/local/lib/gcc47 --libexecdir=3D/usr/local/libexec/gcc47 = >--program-suffix=3D47 --with-as=3D/usr/local/bin/as = >--with-gmp=3D/usr/local = >--with-gxx-include-dir=3D/usr/local/lib/gcc47/include/c++/ = >--with-ld=3D/usr/local/bin/ld --with-pkgversion=3D'FreeBSD Ports = >Collection' --with-system-zlib = >--with-ecj-jar=3D/usr/local/share/java/ecj-4.5.jar = >--enable-languages=3Dc,c++,objc,fortran,java --prefix=3D/usr/local = >--mandir=3D/usr/local/man --infodir=3D/usr/local/info/gcc47 = >--build=3Dx86_64-portbld-freebsd10.0 >> Thread model: posix >> gcc version 4.7.3 (FreeBSD Ports Collection)=20 >> root at pluto:/home/mika/cm3/cm3/scripts #=20 >>=20 >> Any ideas? It looks like gcc is having trouble compiling gcc? >>=20 >> Mika >>=20 >>=20 >> build/gcov-iov '4.7.1' '' \ >>> tmp-gcov-iov.h >> /bin/sh ../../gcc-4.7/gcc/../move-if-change tmp-gcov-iov.h gcov-iov.h >> echo timestamp > s-iov >> gcc -c -DIN_GCC_FRONTEND -g -O2 -DIN_GCC = >-Wno-missing-field-initializers -W -Wall -Wno-narrowing -Wwrite-strings = >-Wcast-qual -Wstrict-prototypes -Wmissing-prototypes = >-Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros = >-Wno-overlength-strings -Wold-style-definition -Wc++-compat = >-DHAVE_CONFIG_H -I. -I. -I../../gcc-4.7/gcc -I../../gcc-4.7/gcc/. = >-I../../gcc-4.7/gcc/../include -I../../gcc-4.7/gcc/../libcpp/include = >-I/usr/local/include ../../gcc-4.7/gcc/attribs.c -o attribs.o >> gcc -c -g -O2 -DIN_GCC -Wno-missing-field-initializers -W -Wall = >-Wno-narrowing -Wwrite-strings -Wcast-qual -Wstrict-prototypes = >-Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long = >-Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition = >-Wc++-compat -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.7/gcc = >-I../../gcc-4.7/gcc/. -I../../gcc-4.7/gcc/../include = >-I../../gcc-4.7/gcc/../libcpp/include -I/usr/local/include = >../../gcc-4.7/gcc/main.c -o main.o >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:46: >> In file included from ../../gcc-4.7/gcc/tree.h:30: >> ../../gcc-4.7/gcc/statistics.h:48:46: error: reference to 'function' = >is ambiguous >> extern void statistics_counter_event (struct function *, const char *, = >int); >> ^ >> ../../gcc-4.7/gcc/statistics.h:41:8: note: candidate found by name = >lookup is 'function' >> struct function; >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:46: >> In file included from ../../gcc-4.7/gcc/tree.h:30: >> ../../gcc-4.7/gcc/statistics.h:49:48: error: reference to 'function' = >is ambiguous >> extern void statistics_histogram_event (struct function *, const char = >*, int); >> ^ >> ../../gcc-4.7/gcc/statistics.h:41:8: note: candidate found by name = >lookup is 'function' >> struct function; >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> gcc -c -g -O2 -DIN_GCC -Wno-missing-field-initializers -W -Wall = >-Wno-narrowing -Wwrite-strings -Wcast-qual -Wstrict-prototypes = >-Wmissing-prototypes -Wmissing-format-attribute -pedantic -Wno-long-long = >-Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition = >-Wc++-compat -DHAVE_CONFIG_H -I. -I. -I../../gcc-4.7/gcc = >-I../../gcc-4.7/gcc/. -I../../gcc-4.7/gcc/../include = >-I../../gcc-4.7/gcc/../libcpp/include -I/usr/local/include = >../../gcc-4.7/gcc/tree-browser.c -o tree-browser.o >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:46: >> ../../gcc-4.7/gcc/tree.h:3547:10: error: reference to 'function' is = >ambiguous >> struct function *f; >> ^ >> ../../gcc-4.7/gcc/tree.h:2653:8: note: candidate found by name lookup = >is 'function' >> struct function; >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:643:24: error: reference to 'function' is = >ambiguous >> add_local_decl (struct function *fun, tree d) >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:657:23: error: reference to 'function' is = >ambiguous >> extern GTY(()) struct function *cfun; >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:693:30: error: reference to 'function' is = >ambiguous >> extern void set_cfun (struct function *new_cfun); >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:694:31: error: reference to 'function' is = >ambiguous >> extern void push_cfun (struct function *new_cfun); >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:732:40: error: reference to 'function' is = >ambiguous >> extern void free_after_parsing (struct function *); >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:733:44: error: reference to 'function' is = >ambiguous >> extern void free_after_compilation (struct function *); >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:764:50: error: reference to 'function' is = >ambiguous >> extern bool optimize_function_for_size_p (struct function *); >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> In file included from ../../gcc-4.7/gcc/basic-block.h:26: >> ../../gcc-4.7/gcc/function.h:765:51: error: reference to 'function' is = >ambiguous >> extern bool optimize_function_for_speed_p (struct function *); >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:53: >> In file included from ../../gcc-4.7/gcc/gimple.h:32: >> ../../gcc-4.7/gcc/basic-block.h:779:31: error: reference to 'function' = >is ambiguous >> extern void init_flow (struct function *); >> ^../../gcc-4.7/gcc/function.h:503:16: = >note: candidate found by name lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:59: >> ../../gcc-4.7/gcc/output.h:137:6: warning: 'format' attribute argument = >not supported: __asm_fprintf__ [-Wignored-attributes] >> ATTRIBUTE_ASM_FPRINTF(2, 3); >> ^ >> ../../gcc-4.7/gcc/output.h:123:53: note: expanded from macro = >'ATTRIBUTE_ASM_FPRINTF' >> #define ATTRIBUTE_ASM_FPRINTF(m, n) __attribute__ ((__format__ = >(__asm_fprintf__, m, n))) ATTRIBUTE_NONNULL(m) >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:63: >> ../../gcc-4.7/gcc/langhooks-def.h:40:38: error: reference to = >'function' is ambiguous >> extern void lhd_do_nothing_f (struct function *); >> ^ >> ../../gcc-4.7/gcc/function.h:503:16: note: candidate found by name = >lookup is 'function' >> struct GTY(()) function { >> ^ >> /usr/include/c++/v1/__functional_03:206:44: note: candidate found by = >name lookup is 'std::__1::function' >> template class _LIBCPP_TYPE_VIS function; // undefined >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:69: >> In file included from ../../gcc-4.7/gcc/expr.h:28: >> In file included from ../../gcc-4.7/gcc/rtl.h:2244: >> ./genrtl.h:385:3: warning: array index 1 is past the end of the array = >(which contains 1 element) [-Warray-bounds] >> XWINT (rt, 1) =3D arg1; >> ^ ~ >> ../../gcc-4.7/gcc/rtl.h:633:29: note: expanded from macro 'XWINT' >> #define XWINT(RTX, N) ((RTX)->u.hwint[N]) >> ^ >> ../../gcc-4.7/gcc/rtl.h:344:5: note: array 'hwint' declared here >> HOST_WIDE_INT hwint[1]; >> ^ >> ../../gcc-4.7/gcc/hwint.h:64:26: note: expanded from macro = >'HOST_WIDE_INT' >> # define HOST_WIDE_INT long >> ^ >> In file included from ../../gcc-4.7/gcc/m3cg/parse.c:69: >> In file included from ../../gcc-4.7/gcc/expr.h:28: >> In file included from ../../gcc-4.7/gcc/rtl.h:2244: >> ./genrtl.h:386:3: warning: array index 2 is past the end of the array = >(which contains 1 element) [-Warray-bounds] >> XWINT (rt, 2) =3D arg2; >> ^ ~ >> ../../gcc-4.7/gcc/rtl.h:633:29: note: expanded from macro 'XWINT' >> #define XWINT(RTX, N) ((RTX)->u.hwint[N]) >> ^ >> ../../gcc-4.7/gcc/rtl.h:344:5: note: array 'hwint' declared here >> HOST_WIDE_INT hwint[1]; >> ^../../gcc-4.7/gcc/hwint.h:64:26: note: expanded from macro = >'HOST_WIDE_INT' >> # define HOST_WIDE_INT long >> ^ >> 3 warnings and 13 errors generated. >> gmake: *** [m3cg/parse.o] Error 1 >> gmake: *** Waiting for unfinished jobs.... >> /bin/sh ../../gcc-4.7/gcc/../move-if-change tmp-attrtab.c = >insn-attrtab.c >> echo timestamp > s-attrtab >> /bin/sh ../../gcc-4.7/gcc/../move-if-change tmp-automata.c = >insn-automata.c >> echo timestamp > s-automata >> "/usr/home/mika/cm3/cm3/m3-sys/m3cc/src/m3makefile", line 327: quake = >runtime error: exit 2: cd ../AMD64_FREEBSD && cd gcc && gmake = >MAKE=3D"gmake -j4 " AUTOCONF=3D: AUTOMAKE=3D: LEX=3D'touch lex.yy.c' = >MAKEINFO=3D: -j4 s-modes insn-config.h m3cg >>=20 >> --procedure-- -line- -file--- >> exec -- >> m3cc_Run 327 = >/usr/home/mika/cm3/cm3/m3-sys/m3cc/src/m3makefile >> include_dir 577 = >/usr/home/mika/cm3/cm3/m3-sys/m3cc/src/m3makefile >> 6 = >/usr/home/mika/cm3/cm3/m3-sys/m3cc/AMD64_FREEBSD/m3make.args >>=20 >> Fatal Error: package build failed >> =3D=3D> /home/mika/cm3/cm3/m3-sys/m3cc done >>=20 >> Critical Mass Modula-3 version d5.9.0 >> last updated: 2010-07-21 >> compiled: 2014-05-26 19:11:28 >> configuration: /usr/local/cm3/bin/cm3.cfg >> host: AMD64_FREEBSD >> quake runtime error: "/usr/local/cm3/bin/cm3.cfg", line 2: quake = >runtime error: undefined variable: SL >>=20 >> --procedure-- -line- -file--- >> 2 /usr/local/cm3/bin/cm3.cfg >> target:=20 >>=20 >> ./upgrade.sh: /home/mika/cm3/cm3/m3-sys/m3cc/AMD64_FREEBSD/cm3cg: not = >found >> root at pluto:/home/mika/cm3/cm3/scripts #=20 >>=20 > > >--Apple-Mail=_CFCEC712-B5CE-4266-A433-4CACD1B61CFA >Content-Transfer-Encoding: 7bit >Content-Disposition: attachment; > filename=signature.asc >Content-Type: application/pgp-signature; > name=signature.asc >Content-Description: Message signed with OpenPGP using GPGMail > >-----BEGIN PGP SIGNATURE----- >Comment: GPGTools - http://gpgtools.org > >iQEcBAEBAgAGBQJT/iYoAAoJEJtljYXUJo8xYuYIAJLvrSpyyxo3vfbZCBNB6ZrB >FCuFUQSoro+s/mxDBH1xGFd403ZfZTGZfrSOJLr/4ydZqdMJHokdAtUrgA12E6C+ >oR874yVlEPHw1LXBaiSAuBi3C/RrlGbop5DDzSx5dsyFtD6Zta8Dg28vJrbpAUbJ >iPZuoW17jXnHw91DdHtN4OiEm8Z2GUZyUrF5W3bbRc8NVYYwd7i81eEAwQajxXqU >nu5l57GjgeQKwf2GRQm0V4rVJl5qjeQm/awH/np+d4gwgN1Zau7QQGaBftZgkp0O >FII3NXJGPAqzNlUF/yC2lhhomAGs8FFU2wNTxWcQFLgbp1ZXkcSkx1q9q2EvlnI= >=HjrH >-----END PGP SIGNATURE----- > >--Apple-Mail=_CFCEC712-B5CE-4266-A433-4CACD1B61CFA-- From dragisha at m3w.org Wed Aug 27 21:47:53 2014 From: dragisha at m3w.org (=?utf-8?Q?Dragi=C5=A1a_Duri=C4=87?=) Date: Wed, 27 Aug 2014 21:47:53 +0200 Subject: [M3devel] "pre-releases" for few Linux platforms and for OSX Mavericks Message-ID: <24640F73-4FCA-4B99-A858-0091C9D60F0C@m3w.org> https://github.com/modula3/cm3/releases Here are three pretty current cm3-bin-core build for LINUXLIBC6, AMD64_LINUX and AMD64_DARWIN (Mavericks build). These archives are all you need (usually) to bootstrap system from Git HEAD on your respective machine. dd -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 495 bytes Desc: Message signed with OpenPGP using GPGMail URL: From hendrik at topoi.pooq.com Thu Aug 28 01:49:47 2014 From: hendrik at topoi.pooq.com (Hendrik Boom) Date: Wed, 27 Aug 2014 19:49:47 -0400 Subject: [M3devel] "pre-releases" for few Linux platforms and for OSX Mavericks In-Reply-To: <24640F73-4FCA-4B99-A858-0091C9D60F0C@m3w.org> References: <24640F73-4FCA-4B99-A858-0091C9D60F0C@m3w.org> Message-ID: <20140827234947.GA686@topoi.pooq.com> On Wed, Aug 27, 2014 at 09:47:53PM +0200, Dragi?a Duri? wrote: > https://github.com/modula3/cm3/releases > > Here are three pretty current cm3-bin-core build for LINUXLIBC6, AMD64_LINUX and AMD64_DARWIN (Mavericks build). These archives are all you need (usually) to bootstrap system from Git HEAD on your respective machine. Wasn't LINUXLIBC6 supposed to have another name by now? -- hendrik From jay.krell at cornell.edu Thu Aug 28 12:30:39 2014 From: jay.krell at cornell.edu (Jay K) Date: Thu, 28 Aug 2014 10:30:39 +0000 Subject: [M3devel] "pre-releases" for few Linux platforms and for OSX Mavericks In-Reply-To: <20140827234947.GA686@topoi.pooq.com> References: <24640F73-4FCA-4B99-A858-0091C9D60F0C@m3w.org>, <20140827234947.GA686@topoi.pooq.com> Message-ID: It is also called I386_LINUX.Whenever I propose dropping the old names, people say they want them to remain supported.It takes very little in the system to do so. The extra names do confuse people and make us talk much about little. - Jay > Date: Wed, 27 Aug 2014 19:49:47 -0400 > From: hendrik at topoi.pooq.com > To: m3devel at elegosoft.com > Subject: Re: [M3devel] "pre-releases" for few Linux platforms and for OSX Mavericks > > On Wed, Aug 27, 2014 at 09:47:53PM +0200, Dragi?a Duri? wrote: > > https://github.com/modula3/cm3/releases > > > > Here are three pretty current cm3-bin-core build for LINUXLIBC6, AMD64_LINUX and AMD64_DARWIN (Mavericks build). These archives are all you need (usually) to bootstrap system from Git HEAD on your respective machine. > > Wasn't LINUXLIBC6 supposed to have another name by now? > > -- hendrik -------------- next part -------------- An HTML attachment was scrubbed... URL: From rcolebur at SCIRES.COM Sat Aug 2 03:08:34 2014 From: rcolebur at SCIRES.COM (Coleburn, Randy) Date: Sat, 2 Aug 2014 01:08:34 +0000 Subject: [M3devel] Fwd: Re: Fwd: Fork bug Message-ID: <0BB8FA59C2932741A3A2941A8B9D8BFF9324F0F6@ATLEX04-SRV.SCIRES.LOCAL> Sorry for the delay in responding, but I've been out on travel. In Trestle the authors devised the concept of Locking Levels and used LL pragmas in the code so that proper ordering could be verified. Actually, the problem comes up in other multi-threaded situations and the coder has to take all this into consideration to prevent getting into a deadlock or starvation situation. I've used partial ordering techniques similar to what was done in Trestle to solve this problem. I do NOT favor the proposed change in MUTEX. In addition to locking levels/orders, there are different abstractions that sometimes should be used instead of MUTEX. I have written several such abstractions. For example, ConcurrencyControl.i3: Provide for a mechanism to achieve concurrency control. The abstraction provided is one of readers and writers, where at any instance of time there can be either zero or more readers, or zero or one writer, that is at time t one and only one of the following 3 conditions applies: 1. (numReaders = 0) AND (numWriters = 0). 2. (numReaders > 0) AND (numWriters = 0). 3. (numReaders = 0) AND (numWriters = 1). For example, GateKeeper.i3: Provide an abstraction for controlling concurrency. The abstraction is that of a gatekeeper who can lock/unlock the gate and who regulates entry/exit via the gate, thereby controlling the number of occupants. I can probably arrange to share some of this code if desired. --Randy Coleburn -----Original Message----- From: Rodney M. Bates [mailto:rodney_bates at lcwb.coop] Sent: Tuesday, July 08, 2014 3:20 PM To: m3devel Subject: EXT:[M3devel] Fwd: Re: Fwd: Fork bug Resent after 24 hours: While we are working on MUTEX, I would like to propose making them what I believe is meant by a recursive mutex, that is, one thread can lock multiple times, the mutex being released only when the number of unlocks catches up with the number of locks. I don't remember the details off the top of my head, but there is a place in Trestle where you have to acquire a MUTEX but it is very difficult or impossible to know whether different code on the same thread already has done so. The different code isn't under your control either. Some runtime scheme to figure it out dynamically would be tantamount to, but messier than, just having a recursive MUTEX. I recall there are other places as well where similar problems arise. It would greatly simplify things when needed. The only disadvantage I can think of is there might be a case where runtime detection of a second lock attempt by the same thread would help find a bug. Maybe the RTS could have a way of setting the behavior of a specific MUTEX. On 07/03/2014 02:28 PM, Tony Hosking wrote: > I wonder if we should not move to a surrogate parent model to make this cleaner in general? > Since fork is (or should be) only used in service of creating a new process (i.e., fork + exec) then this technique would save us a lot of grief. > Thoughts? > > In the surrogate parent model, a program forks a child process at initialization time. The sole purpose of the child is to serve as a sort of "surrogate parent" for the original process should it ever need to fork another child. After initialization, the original parent can proceed to create its additional threads. When it wants to /exec/ an image, it communicates this to its child (which has remained single-threaded). The child then performs the /fork/ and /exec/ on behalf of the original process. > > > > Begin forwarded message: > >> *From: *Peter McKinna > > >> *Subject: **Fork bug* >> *Date: *July 2, 2014 at 10:30:24 PM EDT >> *To: *Antony Hosking > > >> >> Hi Tony, >> >> That fork bug on posix doesn't appear to be fixed, so just to recap the problem. In the threadtest program if you have a bunch of threads creating mutexes and having them collected then get a thread that does a few forks what can happen is that the child executes atforkchild as I think the first thing it does which calls initwithstackbase which does an allocation and possible collection. Unfortunately the weaktable from the parent may be non empty and this is the only thread executing. It calls the cleanup of those mutexes of nonexistant threads some of which may be locked. If they are locked then pthread_mutex_destroy returns ebusy. Then the child exits with the abort in pthread_mutex_delete. >> Whether the abort is needed I dont know. In this case the error can be safely ignored. One could try to see if the owner of the mutex is still alive and not abort in that case. Otherwise if one is sure the child is going to do an exec almost immediately then disabling the collector in atforkchild could work. >> In the broader picture anything thats got a weak ref still active could cause problems if one thread does a fork. The weak callback could do anything. >> Anyway I dont know what the fix is. >> >> Peter > -- Rodney Bates rodney.m.bates at acm.org From mika at async.caltech.edu Sat Aug 9 21:16:04 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sat, 09 Aug 2014 12:16:04 -0700 Subject: [M3devel] deadlock in pthreads?? Message-ID: <20140809191604.12DCD1A209C@async.async.caltech.edu> Hi m3devel (mainly Tony), I am finally trying to join the rest of you in using pthreads since you say it works and now I really need it for my next project. I am on AMD64_LINUX, with two compilers installed, source code as of January for those: 1. user threads --- what I normally use with no problems 2. pthreads --- built it but don't use it because it's from before the final fixes that I am told make the thread tester work (144)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>uname -a Linux truffles 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 GNU/Linux (147)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>cm3 -version Critical Mass Modula-3 version d5.9.0 last updated: 2010-07-21 compiled: 2014-01-03 04:15:06 configuration: /home/mika/bsd/cm3-boot2/bin/cm3.cfg host: AMD64_LINUX target: AMD64_LINUX What I did: cvs update -d cm3 (cvs update everything) Then I tried: I. with existing user threads compiler ./upgrade.sh upgraded my compiler "successfully"---see below for results II. with existing pthreads compiler 1. ./upgrade.sh upgraded my compiler "successfully"---see below for results 2. started over and did manual upgrade process per Tony's instructions a while back (attached) upgraded my compiler "successfully"---see below for results RESULTS IN ALL CASES ABOVE: when running finished compiler, it sometimes deadlocks. "Sometimes" = frequently enough that every build breaks. "Sometimes not" seems to only be in gdb. Here is a traceback: (98)truffles:~/bsd/src>gdb cm3 GNU gdb (GDB) 7.4.1-debian Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /big/home/mika/cm3-boot2.pthreads/bin/cm3...done. (gdb) run Starting program: /big/home/mika/cm3-boot2.pthreads/bin/cm3 [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". --- building in ../AMD64_LINUX --- [New Thread 0x2aaaab6f8700 (LWP 29517)] ^C Program received signal SIGINT, Interrupt. __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 136 ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: No such file or directory. (gdb) where #0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 #1 0x00002aaaaaf59339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 #2 0x00002aaaaaf5915b in __pthread_mutex_lock (mutex=0x12d00e0) at pthread_mutex_lock.c:61 #3 0x0000000000720af8 in ThreadPThread__pthread_mutex_lock (mutex=0x12d00e0) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 #4 0x000000000071ab5f in ThreadPThread__UnlockMutex (M3_AYIbX3_m=) at ../src/thread/PTHREAD/ThreadPThread.m3:151 #5 0x000000000071b018 in ThreadPThread__XWait (M3_DMxDjQ_self=, M3_AYIbX3_m=, M3_Bl0jv4_c=, M3_AicXUJ_alertable=) at ../src/thread/PTHREAD/ThreadPThread.m3:204 #6 0x000000000071d313 in ThreadPThread__XJoin (M3_DMxDjQ_self=, M3_BXP32l_t=, M3_AicXUJ_alertable=) at ../src/thread/PTHREAD/ThreadPThread.m3:557 #7 0x000000000071d462 in Thread__Join (M3_BXP32l_t=) at ../src/thread/PTHREAD/ThreadPThread.m3:569 #8 0x000000000040da95 in Builder__ForceAllPromisesInParallel (M3_C58HwX_promises=, M3_Cwb5VA_parallelism=) at ../src/Builder.m3:1002 #9 0x000000000040e083 in Builder__CompileEverything (M3_DqhcFh_s=, M3_AE6M8L_schedule=) at ../src/Builder.m3:1038 #10 0x0000000000408ce3 in Builder__CompileUnits (M3_Bd56fi_main=, M3_ClaoYw_units=, M3_C1FTrk_sys_libs=, M3_A2QN6Z_info_kind=, M3_An02H2_mach=) at ../src/Builder.m3:337 #11 0x000000000040726b in Builder__BuildPgm (M3_Bd56fi_prog=, M3_ClaoYw_units=, M3_C1FTrk_sys_libs=, M3_AicXUJ_shared=, M3_An02H2_m=) at ../src/Builder.m3:28 #12 0x0000000000425d6f in M3Build__BuildProgram (M3_ABp1Zk_t=, M3_DLS2Hj_nm=) at ../src/M3Build.m3:1515 #13 0x0000000000425bb7 in M3Build__DoProgram (M3_An02H2_m=, M3_AcxOUs_n_args=) at ../src/M3Build.m3:1491 #14 0x00000000004d0cf9 in QMachine__DoCall (M3_An02H2_t=, M3_AcxOUs_n_args=, M3_AicXUJ_isFunc=, M3_AicXUJ_outer=) at ../src/QMachine.m3:546 #15 0x00000000004cf98b in QMachine__Eval (M3_An02H2_t=) at ../src/QMachine.m3:422 #16 0x00000000004cdcb3 in QMachine__Evaluate (M3_An02H2_t=, M3_CYwAos_s=) at ../src/QMachine.m3:165 #17 0x00000000004c4764 in Quake__Run (M3_An02H2_m=, M3_Bd56fi_source_file=) at ../src/Quake.m3:19 #18 0x000000000041f789 in M3Build__Run (M3_ABp1Zk_t=, M3_Bd56fi_makefile=) at ../src/M3Build.m3:242 #19 0x0000000000437b9f in Main__DoIt () at ../src/Main.m3:117 #20 0x0000000000437f23 in Main_M3 (M3_AcxOUs_mode=) at ../src/Main.m3:231 #21 0x000000000070d749 in RTLinker__RunMainBody (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:408 #22 0x000000000070cad4 in RTLinker__AddUnitI (M3_DjPxE3_m=) at ../src/runtime/common/RTLinker.m3:115 #23 0x000000000070cb68 in RTLinker__AddUnit (M3_DjPxE5_b=) at ../src/runtime/common/RTLinker.m3:124 #24 0x00000000004061a8 in main (argc=1, argv=0x7fffffffe388, envp=0x7fffffffe398) at _m3main.c:22 (gdb) Below are the instructions I've been using in case II. 2. above. Note that cm3cg doesn't get installed when following the instructions! I'm not sure what does that, I have to copy it manually from the derived dir to the bin dir for the compiler. Date: Sun, 24 Jun 2007 10:38:34 EDT To: Mika Nystrom cc: m3devel at elegosoft.de From: Tony Hosking Subject: Re: [M3devel] strange errors... Return-Path: hosking at cs.purdue.edu Delivery-Date: Sun Jun 24 07:38:38 2007 In-Reply-To: <200706231838.l5NIcRef079333 at camembert.async.caltech.edu> References: <200706231838.l5NIcRef079333 at camembert.async.caltech.edu> Sounds like we really need some work done in this area. I very rarely use the build scripts, since I bootstrap manually from old compilers to new compilers rather than use the scripts. I suggest the following approach, which I hope you will try, and then report back on. Install the bootstrap compiler as you did originally: > rm -rf /usr/local/cm3/* > > cd ~/cm3-cvs > mkdir boot > cd boot > tar xzvf ../cm3-min-POSIX-FreeBSD4-d5.3.1-2005-10-05.tgz > ./cminstall Now you will have some kind of cm3 installed, presumably in /usr/ local/cm3/bin/cm3. Make sure you have a fresh CVS checkout in directory cm3 (let's assume this is in your home directory ~/cm3). Also, make sure you have an up-to-date version of the CM3 backend compiler cm3cg installed by executing the following: STEP 0: export CM3=/usr/local/cm3/bin/cm3 cd ~/cm3/m3-sys/m3cc $CM3 $CM3 -ship You can skip this last step if you know your backend compiler is up to date. Now, let's build the new compiler from scratch (this is the sequence I use regularly to test changes to the run-time system whenever I make them): can replace compilation step with rm -rf && $CM3 && $CM3 -ship STEP 1: (do these LATER if bootstrapping from old compiler!) cd ~/cm3/m3-libs/m3core $CM3 $CM3 -ship cd ~/cm3/m3-libs/libm3 $CM3 $CM3 -ship Now build the compiler: cd ~/cm3/m3-libs/sysutils ; $CM3 etc. cd ~/cm3/m3-sys/m3middle; $CM3 etc. repeat for: m3-sys/m3objfile m3-sys/m3back m3-sys/m3linker m3-sys/m3front m3-sys/m3quake m3-sys/cm3 [ here we may need -DROOT= ] At this point you should have a bootstrapped version of cm3 installed in the directory /usr/local/cm3/pkg/cm3/TARGET/cm3 (where TARGET is the CM3 target platform you are building on -- e.g., LINUXLIBC6, PPC_DARWIN, ...). Note that this did not overwrite your original installed compiler in /usr/local/cm3/bin/cm3. We are now going to test the new compiler, which was built using the old compiler, by bootstrapping it one more time. (If m3core and libm3 were skipped earlier, do them now, and RE-DO all of the above packages before proceeding.) >From here on out, please replace TARGET with your target platform as appropriate. STEP 2: export CM3=/usr/local/cm3/pkg/cm3/TARGET/cm3 cd ~/cm3/scripts ./do-cm3-std.sh realclean REPEAT STEP 1 to rebuild the libraries and the compiler using the STEP 1 bootstrap compiler. Now you have a STEP 2 bootstrap compiler installed in /usr/local/cm3/ pkg/cm3/TARGET/cm3. Let's assume the new compiler now works properly since it successfully bootstrapped itself, but to be sure we can now use it to rebuild the world: cd ~/cm3/scripts ./do-cm3-std.sh realclean ./do-cm3-std.sh buildship Assuming this succeeded then we can be pretty sure /usr/local/cm3/pkg/ cm3/TARGET/cm3 is good, so we can make it our default compiler by replacing the original /usr/local/cm3/bin/cm3: cp $CM3 /usr/local/cm3/bin/cm3 On Jun 23, 2007, at 2:38 PM, Mika Nystrom wrote: > Ok, I'm sorry if I seem a bit dimwitted in the morning like this, > but how exactly does one get started? I wish there were a file called > "GETTING_STARTED" or something like that in scripts... ... From mika at async.caltech.edu Sun Aug 10 01:14:43 2014 From: mika at async.caltech.edu (mika at async.caltech.edu) Date: Sat, 09 Aug 2014 16:14:43 -0700 Subject: [M3devel] deadlock in pthreads?? In-Reply-To: <20140809191604.12DCD1A209C@async.async.caltech.edu> References: <20140809191604.12DCD1A209C@async.async.caltech.edu> Message-ID: <20140809231443.1045C1A209C@async.async.caltech.edu> Another attempt at making progress. I installed FreeBSD 10 on a new machine. Grabbed the modula3 dist using "pkg" root at rover:/home/mika/cm3-cvs-anon/cm3/scripts # pkg info | grep modula3 modula3-5.8.6_3 Critical Mass Modula-3 compiler root at rover:/home/mika/cm3-cvs-anon/cm3/scripts # uname -a FreeBSD rover 10.0-RELEASE FreeBSD 10.0-RELEASE #0 r260789: Thu Jan 16 22:34:59 UTC 2014 root at snap.freebsd.org:/usr/obj/usr/src/sys/GENERIC amd64 The M3 dist that comes with FreeBSD's pkg seems to work fine, although I suspect it has little pthreads issues, since it is quite old. It's also lacking support for parallel building, which I added a couple of years ago. In short, I'd like to upgrade to something more recent. I take my cvs update as of today (now) and try to upgrade. ./upgrade.sh succeeds (somewhat to my surprise) But the resulting compiler is broken: (69)rover:~/m3hello/src>cm3 --- building in ../AMD64_FREEBSD --- new source -> compiling Main.m3 ERROR: pthread_mutex_lock:11 Abort More detail---ironically, it turns out I wrote the code where it is crashing, but there's "no way it can be wrong"... If I had to guess I'd say there's a race condition between Thread.Fork and Thread.Join: the program forks and probably immediately attempts to join. (74)rover:~/m3hello/src>gdb cm3 GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "amd64-marcel-freebsd"... (gdb) run Starting program: /usr/local/bin/cm3 [New LWP 100914] --- building in ../AMD64_FREEBSD --- missing version stamps -> compiling Main.m3 ERROR: pthread_mutex_lock:11 [New Thread 801806400 (LWP 100914/cm3)] Program received signal SIGABRT, Aborted. [Switching to Thread 801806400 (LWP 100914/cm3)] 0x000000080107626a in thr_kill () from /lib/libc.so.7 (gdb) where #0 0x000000080107626a in thr_kill () from /lib/libc.so.7 #1 0x000000080113dac9 in abort () from /lib/libc.so.7 #2 0x000000000071e206 in ThreadPThread__pthread_mutex_lock (mutex=Error accessing memory address 0x8000ffffc4f8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThreadC.c:513 #3 0x000000000071837b in ThreadPThread__UnlockMutex (M3_AYIbX3_m=Error accessing memory address 0x8000ffffc528: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:151 #4 0x0000000000718834 in ThreadPThread__XWait (M3_DMxDjQ_self=Error accessing memory address 0x8000ffffc5a8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:204 #5 0x000000000071ab2f in ThreadPThread__XJoin (M3_DMxDjQ_self=Error accessing memory address 0x8000ffffc608: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:557 #6 0x000000000071ac7e in Thread__Join (M3_BXP32l_t=Error accessing memory address 0x8000ffffc6d8: Bad address. ) at ../src/thread/PTHREAD/ThreadPThread.m3:569 #7 0x000000000040b38d in Builder__ForceAllPromisesInParallel (M3_C58HwX_promises=Error accessing memory address 0x8000ffffc758: Bad address. ) at ../src/Builder.m3:1002 #8 0x000000000040b97b in Builder__CompileEverything (M3_DqhcFh_s=0x0, M3_AE6M8L_schedule=Error accessing memory address 0x8000ffffc7d8: Bad address. ) at ../src/Builder.m3:1038 #9 0x00000000004065db in Builder__CompileUnits (M3_Bd56fi_main=Error accessing memory address 0x8000ffffc8f8: Bad address. ) at ../src/Builder.m3:337 #10 0x0000000000404b63 in Builder__BuildPgm (M3_Bd56fi_prog=Error accessing memory address 0x8000ffffc9a8: Bad address. ) at ../src/Builder.m3:28 #11 0x0000000000423667 in M3Build__BuildProgram (M3_ABp1Zk_t=Error accessing memory address 0x8000ffffc9e8: Bad address. ) at ../src/M3Build.m3:1515 #12 0x00000000004234af in M3Build__DoProgram (M3_An02H2_m=Error accessing memory address 0x8000ffffca28: Bad address. ) at ../src/M3Build.m3:1491 #13 0x00000000004ce5ed in QMachine__DoCall (M3_An02H2_t=Error accessing memory address 0x8000ffffca88: Bad address. ) at ../src/QMachine.m3:546 #14 0x00000000004cd27f in QMachine__Eval (M3_An02H2_t=Error accessing memory address 0x8000ffffcb28: Bad address. ) at ../src/QMachine.m3:422 #15 0x00000000004cb5a7 in QMachine__Evaluate (M3_An02H2_t=Error accessing memory address 0x8000ffffcc78: Bad address. ) at ../src/QMachine.m3:165 #16 0x00000000004c2058 in Quake__Run (M3_An02H2_m=Error accessing memory address 0x8000ffffcca8: Bad address. ) at ../src/Quake.m3:19 #17 0x000000000041d081 in M3Build__Run (M3_ABp1Zk_t=Error accessing memory address 0x8000ffffcce8: Bad address. ) at ../src/M3Build.m3:242 #18 0x0000000000435497 in Main__DoIt () at ../src/Main.m3:117 #19 0x000000000043581b in Main_M3 (M3_AcxOUs_mode=Error accessing memory address 0x8000ffffceb8: Bad address. ) at ../src/Main.m3:231 #20 0x000000000070af59 in RTLinker__RunMainBody (M3_DjPxE3_m=Error accessing memory address 0x8000ffffced8: Bad address. ) at ../src/runtime/common/RTLinker.m3:408 #21 0x000000000070a2e4 in RTLinker__AddUnitI (M3_DjPxE3_m=Error accessing memory address 0x8000ffffcf58: Bad address. ) at ../src/runtime/common/RTLinker.m3:115 #22 0x000000000070a378 in RTLinker__AddUnit (M3_DjPxE5_b=Error accessing memory address 0x8000ffffcf78: Bad address. ) at ../src/runtime/common/RTLinker.m3:124 #23 0x0000000000403aa6 in main (argc=Error accessing memory address 0x8000ffffcfcc: Bad address. ) at _m3main.c:22 (gdb) mika writes: >Hi m3devel (mainly Tony), > >I am finally trying to join the rest of you in using pthreads since you >say it works and now I really need it for my next project. > >I am on AMD64_LINUX, with two compilers installed, source code as of January for those: > >1. user threads --- what I normally use with no problems > >2. pthreads --- built it but don't use it because it's from before the final fixes > that I am told make the thread tester work > >(144)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>uname -a >Linux truffles 3.2.0-4-amd64 #1 SMP Debian 3.2.51-1 x86_64 GNU/Linux > >(147)truffles:~/bsd/cm3-cvs-anon/cm3/m3-sys/cm3>cm3 -version >Critical Mass Modula-3 version d5.9.0 > last updated: 2010-07-21 > compiled: 2014-01-03 04:15:06 > configuration: /home/mika/bsd/cm3-boot2/bin/cm3.cfg > host: AMD64_LINUX > target: AMD64_LINUX > > >What I did: > >cvs update -d cm3 > >(cvs update everything) > >Then I tried: > >I. with existing user threads compiler > > ./upgrade.sh > > upgraded my compiler "successfully"---see below for results > >II. with existing pthreads compiler > > 1. ./upgrade.sh > > upgraded my compiler "successfully"---see below for results > > 2. started over and did manual upgrade process per Tony's instructions a while back (attached) > > upgraded my compiler "successfully"---see below for results > >RESULTS IN ALL CASES ABOVE: > >when running finished compiler, it sometimes deadlocks. "Sometimes" = frequently enough that every >build breaks. "Sometimes not" seems to only be in gdb. > >Here is a traceback: > >(98)truffles:~/bsd/src>gdb cm3 >GNU gdb (GDB) 7.4.1-debian >Copyright (C) 2012 Free Software Foundation, Inc. >License GPLv3+: GNU GPL version 3 or later >This is free software: you are free to change and redistribute it. >There is NO WARRANTY, to the extent permitted by law. Type "show copying" >and "show warranty" for details. >This GDB was configured as "x86_64-linux-gnu". >For bug reporting instructions, please see: >... >Reading symbols from /big/home/mika/cm3-boot2.pthreads/bin/cm3...done. >(gdb) run >Starting program: /big/home/mika/cm3-boot2.pthreads/bin/cm3 >[Thread debugging using libthread_db enabled] >Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". >--- building in ../AMD64_LINUX --- > >[New Thread 0x2aaaab6f8700 (LWP 29517)] >^C >Program received signal SIGINT, Interrupt. >__lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 >136 ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: No such file or directory. >(gdb) where >#0 __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:136 >#1 0x00002aaaaaf59339 in _L_lock_926 () from /lib/x86_64-linux-gnu/libpthread.so.0 >#2 0x00002aaaaaf5915b in __pthread_mutex_lock (mutex=0x12d00e0) at pthread_mutex_lock.c:61 >#3 0x0000000000720af8 in ThreadPThread__pthread_mutex_lock (mutex=0x12d00e0) at ../src/thread/PTHREAD/ThreadPThreadC.c:506 >#4 0x000000000071ab5f in ThreadPThread__UnlockMutex (M3_AYIbX3_m=) at ../src/thread/PTHREAD/ThreadPThread.m3:151 >#5 0x000000000071b018 in ThreadPThread__XWait (M3_DMxDjQ_self=, M3_AYIbX3_m=, M3_Bl0jv4_c=, M3_AicXUJ_alertable=iable>) at ../src/thread/P