<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>ThreadPThread.m3 had the same narrow startup race condition. <div>I fixed it.</div><div>Again I'm not seeing commit mails.</div><div><br></div><div>On the larger matter:</div><div><br></div><div><div>I think there is a solution, in that, if you look at</div><div>ThreadPThread.m3 and how it uses Posix condition variables,</div><div>in that it does a fair amount of the work itself,</div><div>you can term this "condition within condition".</div><div><br></div><div><br></div><div>So I think maybe we can use the counting solution</div><div>and 1) merge the locks and/or 2) take the lock in Signal/Broadcast.</div><div><br></div><div><br></div><div>But I have to look at it more.</div><div><br></div><div><br></div><div><br></div><div>Specifically, in ThreadPThread.m3:</div><div><br></div><div>Broadcast:</div><div>        WITH r = pthread_mutex_lock(t.mutex) DO <*ASSERT r=0*> END;</div><div>        next := t.nextWaiter;</div><div>        t.nextWaiter := NIL;</div><div>        t.waitingOn := NIL;</div><div>        WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END;</div><div><br></div><div>Signal:</div><div>      WITH r = pthread_mutex_lock(t.mutex) DO <*ASSERT r=0*> END;</div><div>      t.nextWaiter := NIL;</div><div>      t.waitingOn := NIL;</div><div>      WITH r = pthread_cond_signal(t.cond) DO <*ASSERT r=0*> END;</div><div><br></div><div><br></div><div>Becaise they signal while locked, we can implement this limited</div><div>form of condition variable, and then use the Modula-3 pthread logic</div><div>using that.</div><div><br></div><div><br></div><div>Make some sense?</div><div><br></div><div><br></div><div>Essentially we will have almost-posix condition variables,</div><div>and exactly-posix mutexes, and then we can use just the pthread code</div><div>on top of that.</div><div><br></div><div><br></div><div>Almost-posix condition variable is a posix condition variable, except</div><div>it is guaranteed you will call pthread_cond_signal with the same</div><div>lock held as when you call pthread_cond_wait.</div><div><br></div><div><br></div><div>On a pthread system, the almost-posix condition variables and exactly-posix</div><div>mutexes are just pass through to the underlying pthreads.</div><div><br></div><div><br></div><div>On a win32 system, an almost-posix condition variable is similar</div><div>to what we have now, except, because we know this lock is held,</div><div>"XWait" can remove some of the leave/enter cycles and remove race conditions.</div><div><br></div><div><br></div><div>Essentially we only need a "monitor", which is one lock and one condition variable.</div><div><br></div><div><br></div><div>OR, we can use "directed notification" where each thread has an event, and threads are linked through a "wait block" i.e. the condition. This should work well too. It depends on us owing CreateThread, which we already do.</div><div><br></div><div> - Jay</div><div><br><br><div><hr id="stopSpelling">From: jay.krell@cornell.edu<br>To: rodney.m.bates@acm.org; m3devel@elegosoft.com<br>Subject: RE: A win32 thread test case<br>Date: Sat, 30 Jul 2016 21:18:08 +0000<br><br>

<style><!--
.ExternalClass .ecxhmmessage P {
padding:0px;
}

.ExternalClass body.ecxhmmessage {
font-size:12pt;
font-family:Calibri;
}

--></style>
<div dir="ltr"><div>I fixed the new_slots problem.</div><div><br></div><div><br></div><div>I agree there are problems here.</div><div>  I think Java got away with a similar implementation</div><div>  because their interface is a bit different.</div><div>  i.e. the lock and condition are merged, and/or notification</div><div>  requires the caller to take the lock. We can't do this.</div><div>  We allow signal/broadcast w/o holding a lock.</div><div>  We'd have to resort to a global lock I guess.</div><div><br></div><div><br></div><div>  I suspect nobody else uses this solution.</div><div><br></div><div><br></div><div>I believe we can solve it better and worse than others.</div><div><br></div><div><br></div><div>Most libraries do not have their own "CreateThread" function.</div><div>That is, most libraries let you call pthread_create or Win32 CreateThread,</div><div>and the library will interoperate with any thread that comes its way.</div><div>And most libraries don't seem to use thread locals in their solution.</div><div>By "most libraries", I mean the pthreads on win32 package and Boost.</div><div><br></div><div><br></div><div>Modula-3 isn't clearly this way. This isn't great, but it is the current</div><div>situation. I believe it is fixable.</div><div>That is, Modula-3 I believe requires using its library to create threads.</div><div>This is not great for interoperation. You want to be able to be used</div><div>by code that isn't away of you, that just creates threads in the "normal" way</div><div>for their platform.</div><div><br></div><div><br></div><div>And then, either the current state, or a fix I have in mind, can be taken</div><div>advantage of to do "directed notify" w/o creating a kernel event</div><div>per wait or notify, like other solutions do.</div><div><br></div><div><br></div><div>As to the fix, to not require threads go through our "CreateThread",</div><div>I believe on Windows (which is all that is relevant here), we should have</div><div>a DllMain that allocates thread locals.</div><div><br></div><div><br></div><div>We can only easily have a DllMain if we are a .dll.</div><div>Or we can use __declspec(thread).</div><div>__declspec(thread) works if the .exe is statically linked to the exe or the dll,</div><div>or on Vista and newer, but not in a .dll loaded by LoadLibrary prior to Vista.</div><div>Perhaps that is good enough.</div><div><br></div><div><br></div><div>If we require Vista then we can just drop a bunch of our code and use</div><div>the Win32 condition variables presumably.</div><div>I remain curious how the condition variables work there, i.e. we can't</div><div>implement them ourselves, but it is possible they either require kernel</div><div>support or are well beyond our abilities.</div><div><br></div><div><br></div><div><br></div><div> - Jay</div><br><br><br><br><div>> Date: Thu, 28 Jul 2016 15:00:45 -0500<br>> From: rodney_bates@lcwb.coop<br>> To: m3devel@elegosoft.com; jay.krell@cornell.edu<br>> Subject: A win32 thread test case<br>> <br>> I have attached a test case program designed to expose one of the bugs<br>> I think I see in ThreadWin32.m3.  It runs correctly on AMD64_LINUX.<br>> I expect it to fail on Windows, but don't have a Windows machine I<br>> can try it on.<br>> <br>> Anybody willing to try it?  It's a self-contained Main module.  Just<br>> compile and run it.  It will announce what it finds.<br>> <br>> <br>> -- <br>> Rodney Bates<br>> rodney.m.bates@acm.org<br></div>                                        </div></div></div></div>                                        </div></body>
</html>