<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div apple-content-edited="true"><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><div style="word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><span class="Apple-style-span" style="border-collapse: separate; border-spacing: 0px 0px; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: auto; -khtml-text-decorations-in-effect: none; text-indent: 0px; -apple-text-size-adjust: auto; text-transform: none; orphans: 2; white-space: normal; widows: 2; word-spacing: 0px; "><div><font class="Apple-style-span" face="GillSans-Light">I am a little concerned about passing REFANY directly to C code as there is no guarantee that REFANY and C pointers will always be compatible. ADDRESS can more safely be assumed compatible.</font></div></span></span></span></span></span></span></span></span></div></span> </div><br><div><div>On 16 Apr 2009, at 00:12, Jay wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div><br>This "rewrites" ThreadPThread.InitMutex and ThreadPThread.InitCondition in C.<br> They are only a few lines either way.<br>Thereby removing all uses of initMu from Modula-3 and enabling removing<br> the "bridging" of it between Modula-3 and C.<br><br><br>Better? I'm not sure.<br>No real difference? Maybe.<br><br><br>Likewise can be done for CreateT's allocation/initialization of cond_t.<br> And then MemAlloc/MemFree would be moved.<br><br><br>Ultimately this is the route toward<br> - writing most/all of ThreadPThread.c in C<br> - removing most/all bridging<br><br><br>I'm aware it should handle out of memory.<br><br><br> - Jay<br><br><br>Index: ThreadPThread.i3<br>===================================================================<br>RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.i3,v<br>retrieving revision 1.14<br>diff -u -r1.14 ThreadPThread.i3<br>--- ThreadPThread.i3 30 Mar 2009 21:52:15 -0000 1.14<br>+++ ThreadPThread.i3 15 Apr 2009 14:03:58 -0000<br>@@ -137,20 +137,10 @@<br> pthread_mutex_t = ADDRESS;<br> pthread_cond_t = ADDRESS;<br><br>-<br>-(*CONST*) VAR sizeof_pthread_mutex_t:int;<br>-<br><br> (*CONST*) VAR sizeof_pthread_cond_t:int;<br><br><br>-PROCEDURE pthread_mutex_init(mutex: pthread_mutex_t; attr:ADDRESS:=NIL):int;<br>-<br>-(* This wrapper has some OS-specific bug workarounds. *)<br>-<br>-PROCEDURE pthread_mutex_destroy(mutex: pthread_mutex_t):int;<br>-<br>-<br> PROCEDURE pthread_mutex_lock(mutex: pthread_mutex_t):int;<br><br><br>@@ -170,4 +160,12 @@<br><br> (*---------------------------------------------------------------------------*)<br><br>+<br>+PROCEDURE InitMutex (MutexRoot: REFANY; VAR pthread_mutex: pthread_mutex_t);<br>+<br>+<br>+PROCEDURE InitCondition (ConditionRoot: REFANY; VAR pthread_mutex: pthread_mutex_t);<br>+<br>+(*---------------------------------------------------------------------------*)<br>+<br> END ThreadPThread.<br>Index: ThreadPThread.m3<br>===================================================================<br>RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/PTHREAD/ThreadPThread.m3,v<br>retrieving revision 1.101<br>diff -u -r1.101 ThreadPThread.m3<br>--- ThreadPThread.m3 30 Mar 2009 21:59:31 -0000 1.101<br>+++ ThreadPThread.m3 15 Apr 2009 14:03:58 -0000<br>@@ -155,35 +155,13 @@<br> m.release ();<br> END Release;<br><br>-PROCEDURE CleanMutex (r: REFANY) =<br>- VAR m := NARROW(r, Mutex);<br>- BEGIN<br>- WITH r = pthread_mutex_destroy (m.mutex) DO END;<br>- MemFree(m.mutex);<br>- END CleanMutex;<br>-<br>-PROCEDURE InitMutex (m: Mutex) =<br>- VAR mutex: pthread_mutex_t;<br>- BEGIN<br>- TRY<br>- WITH r = pthread_mutex_lock_init() DO END;<br>- IF m.mutex # NIL THEN RETURN END;<br>- mutex := MemAlloc(sizeof_pthread_mutex_t);<br>- WITH r = pthread_mutex_init(mutex) DO END;<br>- m.mutex := mutex;<br>- FINALLY<br>- WITH r = pthread_mutex_unlock_init() DO END;<br>- END;<br>- RTHeapRep.RegisterFinalCleanup (m, CleanMutex);<br>- END InitMutex;<br>-<br> PROCEDURE LockMutex (m: Mutex) =<br> VAR self := Self();<br> BEGIN<br> IF self = NIL THEN<br> Die(ThisLine(), "LockMutex called from a non-Modula-3 thread");<br> END;<br>- IF m.mutex = NIL THEN InitMutex(m) END;<br>+ IF m.mutex = NIL THEN InitMutex(m, m.mutex) END;<br> IF perfOn THEN PerfChanged(self.id, State.locking) END;<br> WITH r = pthread_mutex_lock(m.mutex) DO<br> IF r # 0 THEN<br>@@ -211,34 +189,12 @@<br><br> (*---------------------------------------- Condition variables and Alerts ---*)<br><br>-PROCEDURE CleanCondition (r: REFANY) =<br>- VAR c := NARROW(r, Condition);<br>- BEGIN<br>- WITH r = pthread_mutex_destroy (c.mutex) DO END;<br>- MemFree(c.mutex);<br>- END CleanCondition;<br>-<br>-PROCEDURE InitCondition (c: Condition) =<br>- VAR mutex: pthread_mutex_t;<br>- BEGIN<br>- TRY<br>- WITH r = pthread_mutex_lock_init() DO END;<br>- IF c.mutex # NIL THEN RETURN END;<br>- mutex := MemAlloc(sizeof_pthread_mutex_t);<br>- WITH r = pthread_mutex_init(mutex) DO END;<br>- c.mutex := mutex;<br>- FINALLY<br>- WITH r = pthread_mutex_unlock_init() DO END;<br>- END;<br>- RTHeapRep.RegisterFinalCleanup (c, CleanCondition);<br>- END InitCondition;<br>-<br> PROCEDURE XWait (self: T; m: Mutex; c: Condition; alertable: BOOLEAN)<br> RAISES {Alerted} =<br> (* LL = m *)<br> VAR next, prev: T;<br> BEGIN<br>- IF c.mutex = NIL THEN InitCondition(c) END;<br>+ IF c.mutex = NIL THEN InitCondition(c, c.mutex) END;<br> TRY<br><br><br>@@ -325,7 +281,7 @@<br><br> PROCEDURE Signal (c: Condition) =<br> BEGIN<br>- IF c.mutex = NIL THEN InitCondition(c) END;<br>+ IF c.mutex = NIL THEN InitCondition(c, c.mutex) END;<br> WITH r = pthread_mutex_lock(c.mutex) DO END;<br> IF c.waiters # NIL THEN DequeueHead(c) END;<br> WITH r = pthread_mutex_unlock(c.mutex) DO END;<br>@@ -333,7 +289,7 @@<br><br> PROCEDURE Broadcast (c: Condition) =<br> BEGIN<br>- IF c.mutex = NIL THEN InitCondition(c) END;<br>+ IF c.mutex = NIL THEN InitCondition(c, c.mutex) END;<br> WITH r = pthread_mutex_lock(c.mutex) DO END;<br> WHILE c.waiters # NIL DO DequeueHead(c) END;<br> WITH r = pthread_mutex_unlock(c.mutex) DO END;<br>Index: ThreadPThreadC.c<br>===================================================================<br>RCS file: /usr/cvs/cm3/m3-libs/m3core/src/thread/PTHREAD/ThreadPThreadC.c,v<br>retrieving revision 1.19<br>diff -u -r1.19 ThreadPThreadC.c<br>--- ThreadPThreadC.c 30 Mar 2009 21:52:15 -0000 1.19<br>+++ ThreadPThreadC.c 15 Apr 2009 14:03:58 -0000<br>@@ -250,16 +250,12 @@<br><br> MUTEX(active) /* global lock for list of active threads */<br> MUTEX(slot) /* global lock for thread slot table */<br>-MUTEX(init) /* global lock for initializers */<br> MUTEX(perf)<br> MUTEX(heap)<br> CONDITION_VARIABLE(heap)<br> THREAD_LOCAL(activations)<br><br> EXTERN_CONST<br>-int ThreadPThread__sizeof_pthread_mutex_t = sizeof(pthread_mutex_t);<br>-<br>-EXTERN_CONST<br> int ThreadPThread__sizeof_pthread_cond_t = sizeof(pthread_cond_t);<br><br> int<br>@@ -271,17 +267,83 @@<br> pthread_mutex_destroy() intermittently returns<br> EBUSY even when there are no threads accessing the mutex. */<br> int e;<br>- do<br>- {<br>- e = pthread_mutex_destroy(mutex);<br>- }<br>- while (e == EBUSY);<br>+ while ((e = pthread_mutex_destroy(mutex)) == EBUSY) { }<br> return e;<br> #else<br> return pthread_mutex_destroy(mutex);<br> #endif<br> }<br><br>+void RTHeapRep__RegisterFinalCleanup (char* Root, void (*clean)(char*));<br>+<br>+/* This should be known at compile-time, but I don't know the Modula-3 object model. */<br>+size_t M3MutexToPthreadMutex;<br>+size_t M3ConditionToPthreadMutex;<br>+<br>+#define MemAlloc ThreadPThread__MemAlloc<br>+#define MemFree ThreadPThread__MemFree<br>+<br>+void* MemAlloc (size_t size);<br>+void MemFree (void* a);<br>+<br>+static void Common_CleanMutex(char* Root, size_t Offset)<br>+{<br>+ pthread_mutex_t** inout_Mutex = (pthread_mutex_t**)(Root + Offset);<br>+ pthread_mutex_t* Mutex = *inout_Mutex;<br>+ *inout_Mutex = NULL;<br>+ if (Mutex != NULL)<br>+ {<br>+ ThreadPThread__pthread_mutex_destroy(Mutex);<br>+ MemFree(Mutex);<br>+ }<br>+}<br>+<br>+static void CleanCondition(char* Root)<br>+{<br>+ Common_CleanMutex(Root, M3ConditionToPthreadMutex);<br>+}<br>+<br>+static void CleanMutex(char* Root)<br>+{<br>+ Common_CleanMutex(Root, M3MutexToPthreadMutex);<br>+}<br>+<br>+static void Common_InitMutex(char* Root, pthread_mutex_t** inout_Mutex, size_t* inout_Offset, void (*Clean)(char*))<br>+{<br>+ static pthread_mutex_t initMu = PTHREAD_MUTEX_INITIALIZER; /* global lock for initializers */<br>+ size_t Offset = *inout_Offset;<br>+<br>+ if (Offset == 0)<br>+ *inout_Offset = (((char*)inout_Mutex) - Root);<br>+ else<br>+ assert(Offset == (((char*)inout_Mutex) - Root));<br>+ assert((char*)inout_Mutex>= Root);<br>+<br>+ pthread_mutex_lock(&initMu);<br>+ if (*inout_Mutex == NULL)<br>+ {<br>+ pthread_mutex_t* Mutex = (pthread_mutex_t*)calloc(1, sizeof(*Mutex));<br>+ if (Mutex)<br>+ {<br>+ pthread_mutex_init(Mutex, NULL);<br>+ *inout_Mutex = Mutex;<br>+ }<br>+ }<br>+ pthread_mutex_unlock(&initMu);<br>+<br>+ RTHeapRep__RegisterFinalCleanup (Root, Clean);<br>+}<br>+<br>+void ThreadPThread__InitMutex(char* Root, pthread_mutex_t** Mutex)<br>+{<br>+ Common_InitMutex(Root, Mutex, &M3MutexToPthreadMutex, CleanMutex);<br>+}<br>+<br>+void ThreadPThread__InitCondition (char* Root, pthread_mutex_t** Mutex)<br>+{<br>+ Common_InitMutex(Root, Mutex, &M3ConditionToPthreadMutex, CleanCondition);<br>+}<br>+<br> #ifdef __cplusplus<br> } /* extern "C" */<br> #endif<br><span><ThreadPThreadC.c></span><span><ThreadPThread.m3></span><span><diff.txt></span></div></blockquote></div><br></body></html>