<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>