Completely rework according to new interface.
authorRichard Kenner <kenner@gcc.gnu.org>
Wed, 25 Jun 1997 20:25:24 +0000 (16:25 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Wed, 25 Jun 1997 20:25:24 +0000 (16:25 -0400)
From-SVN: r14310

gcc/objc/thr-decosf1.c
gcc/objc/thr-irix.c
gcc/objc/thr-mach.c
gcc/objc/thr-os2.c
gcc/objc/thr-posix.c
gcc/objc/thr-pthreads.c
gcc/objc/thr-single.c
gcc/objc/thr-solaris.c
gcc/objc/thr-win32.c
gcc/objc/thr.c

index fa432aa28cb5c2cd47175992b5a9535a3436d194..0c611b89afb4a2e1baad3b51940e3252066979f4 100644 (file)
@@ -28,299 +28,254 @@ Boston, MA 02111-1307, USA.  */
 #include <objc/thr.h>
 #include "runtime.h"
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-    volatile objc_thread_t      owner;          /* Id of thread that owns.  */
-    volatile int                depth;          /* # of acquires.           */
-    pthread_mutex_t             lock;           /* pthread mutex.           */
-};
-
-/*****************************************************************************
- *  Static variables.
- */
-static pthread_key_t    __objc_thread_data_key; /* Data key for thread data.*/
+/* Key structure for maintiain thread specific storage */
+static pthread_key_t _objc_thread_storage;
 
+/* Backend initialization functions */
 
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-    printf("__objc_init_thread_system\n");
-    
-    if (pthread_keycreate(&__objc_thread_data_key, NULL) == 0)
-        return 0;                               /* Yes, return success.     */
-    
-    return -1;                                  /* Failed.                  */
+  /* Initialize the thread storage key */
+  return pthread_keycreate(&_objc_thread_storage, NULL);
 }
 
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
+  /* Destroy the thread storage key */
+  /* Not implemented yet */
+  /* return pthread_key_delete(&_objc_thread_storage); */
   return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-    objc_thread_t      thread_id = NULL;       /* Detached thread id.      */
-    pthread_t           new_thread_handle;      /* DCE thread handle.       */
-
-    objc_mutex_lock(__objc_runtime_mutex);
-    
-    if (pthread_create(&new_thread_handle, pthread_attr_default,
-                       (void *)func, arg) == 0) {
-      /* ??? May not work! (64bit)*/
-        thread_id = *(objc_thread_t *)&new_thread_handle; 
-        pthread_detach(&new_thread_handle);     /* Fully detach thread.     */
-       __objc_runtime_threads_alive++;
+  objc_thread_t thread_id;
+  pthread_t new_thread_handle;
+
+  if (pthread_create(&new_thread_handle, pthread_attr_default,
+                    (void *)func, arg) == 0)
+    {
+      /* ??? May not work! (64bit) */
+      thread_id = *(objc_thread_t *)&new_thread_handle; 
+      pthread_detach(&new_thread_handle);     /* Fully detach thread.     */
     }
-    
-    objc_mutex_unlock(__objc_runtime_mutex);
-    return thread_id;
+  else
+    thread_id = NULL;
+  
+  return thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
-    int         sys_priority = 0;
+  int sys_priority = 0;
 
-    switch (priority) {
+  switch (priority)
+    {
     case OBJC_THREAD_INTERACTIVE_PRIORITY:
-        sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2;
-        break;
+      sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2;
+      break;
     default:
     case OBJC_THREAD_BACKGROUND_PRIORITY:
-        sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
-        break;
+      sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
+      break;
     case OBJC_THREAD_LOW_PRIORITY:
-        sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
-        break;
+      sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
+      break;
     }
     
-    if (pthread_setprio(pthread_self(), sys_priority) >= 0)
-        return 0;                               /* Changed priority. End.   */
-    
-    return -1;                                  /* Failed.                  */
+  /* Change the priority. */
+  if (pthread_setprio(pthread_self(), sys_priority) >= 0)
+    return 0;
+  else
+    /* Failed */
+    return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
-    int         sys_priority;                   /* DCE thread priority.     */
+  int sys_priority;
     
-    if ((sys_priority = pthread_getprio(pthread_self())) >= 0) {
-        if (sys_priority >= PRI_FG_MIN_NP && sys_priority <= PRI_FG_MAX_NP)
-            return OBJC_THREAD_INTERACTIVE_PRIORITY;
-        if (sys_priority >= PRI_BG_MIN_NP && sys_priority <= PRI_BG_MAX_NP)
-            return OBJC_THREAD_BACKGROUND_PRIORITY;
-        return OBJC_THREAD_LOW_PRIORITY;
-    }
-    return -1;                                  /* Couldn't get priority.   */
+  if ((sys_priority = pthread_getprio(pthread_self())) >= 0) {
+    if (sys_priority >= PRI_FG_MIN_NP && sys_priority <= PRI_FG_MAX_NP)
+      return OBJC_THREAD_INTERACTIVE_PRIORITY;
+    if (sys_priority >= PRI_BG_MIN_NP && sys_priority <= PRI_BG_MAX_NP)
+      return OBJC_THREAD_BACKGROUND_PRIORITY;
+    return OBJC_THREAD_LOW_PRIORITY;
+  }
+
+  /* Failed */
+  return -1;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
-    pthread_yield();                            /* Yield to equal thread.   */
+  pthread_yield();
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  objc_mutex_lock(__objc_runtime_mutex);
-  __objc_runtime_threads_alive--;
-  objc_mutex_unlock(__objc_runtime_mutex);
-      
-  pthread_exit(&__objc_thread_exit_status);     /* Terminate thread.        */
+  /* exit the thread */
+  pthread_exit(&__objc_thread_exit_status);
+
+  /* Failed if we reached here */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  -1 which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
   pthread_t self = pthread_self();
 
   return (objc_thread_t) pthread_getuniqe_np (&self);
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
-    if (pthread_setspecific(__objc_thread_data_key, (void *)value) == 0)
-        return 0;                              /* Return thread data.      */
-    return -1;
+  return pthread_setspecific(_objc_thread_storage, value);
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
 {
-    void *      value = NULL;
-    
-    if (pthread_getspecific(__objc_thread_data_key, (void *)&value) == 0)
-        return value;                           /* Return thread data.      */
-    
-    return NULL;
+  void *value = NULL;
+
+  if ( !(pthread_getspecific(_objc_thread_storage, &value)) )
+    return value;
+
+  return NULL;
 }
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if
- *  the allocation fails for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
 {
-    objc_mutex_t mutex;
-    int         err = 0;
-    
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
-    
-    err = pthread_mutex_init(&mutex->lock, pthread_mutexattr_default);
-    
-    if (err != 0) {                             /* System init failed?      */
-        objc_free(mutex);                       /* Yes, free local memory.  */
-        return NULL;                            /* Abort.                   */
-    }
-    mutex->owner = (objc_thread_t) -1;         /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
+  if (pthread_mutex_init((pthread_mutex_t *)(&(mutex->backend)), 
+                        pthread_mutexattr_default))
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallotcate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Deallocate a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-    int         depth;                          /* # of locks on mutex.     */
+  if (pthread_mutex_destroy((pthread_mutex_t *)(&(mutex->backend))))
+    return -1;
+  else
+    return 0;
+}
 
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-    
-    pthread_mutex_unlock(&mutex->lock);         /* Must unlock system mutex.*/
-    pthread_mutex_destroy(&mutex->lock);        /* Free system mutex.       */
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
+/* Grab a lock on a mutex. */
+int
+__objc_mutex_lock(objc_mutex_t mutex)
+{
+  return pthread_mutex_lock((pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+/* Try to grab a lock on a mutex. */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_mutex_trylock(objc_mutex_t mutex)
 {
-    objc_thread_t thread_id;                   /* Cache our thread id.     */
+  if (pthread_mutex_trylock((pthread_mutex_t *)(&(mutex->backend))) != 1)
+    return -1;
+  else
+    return 0;
+}
+
+/* Unlock the mutex */
+int
+__objc_mutex_unlock(objc_mutex_t mutex)
+{
+  return pthread_mutex_unlock((pthread_mutex_t *)(&(mutex->backend)));
+}
 
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
+/* Backend condition mutex functions */
 
-    if (pthread_mutex_lock(&mutex->lock) != 0)  /* Lock DCE system mutex.   */
-        return -1;                              /* Failed, abort.           */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+/* Allocate a condition. */
+int
+__objc_condition_allocate(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
+
+  /*
+  if (pthread_cond_init((pthread_cond_t *)(&(condition->backend)), NULL))
+    return -1;
+  else
+    return 0;
+    */
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Deallocate a condition. */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_condition_deallocate(objc_condition_t condition)
 {
-    objc_thread_t thread_id;                   /* Cache our thread id.     */
+  /* Unimplemented. */
+  return -1;
 
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-    
-    if (pthread_mutex_trylock(&mutex->lock) != 1) /* Lock DCE system mutex. */
-        return -1;                              /* Failed, abort.           */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  /*
+  return pthread_cond_destroy((pthread_cond_t *)(&(condition->backend)));
+  */
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Wait on the condition */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
 {
-    objc_thread_t thread_id;                   /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = (objc_thread_t) -1;         /* Set owner to "no thread".*/
-    
-    if (pthread_mutex_unlock(&mutex->lock) != 0)  /* Unlock system mutex.   */
-        return -1;                              /* Failed, abort.           */
-    
-    return 0;                                   /* No, return success.      */
+  /* Unimplemented. */
+  return -1;
+
+  /*
+  return pthread_cond_wait((pthread_cond_t *)(&(condition->backend)),
+                          (pthread_mutex_t *)(&(mutex->backend)));
+                          */
+}
+
+/* Wake up all threads waiting on this condition. */
+int
+__objc_condition_broadcast(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
+
+  /*
+  return pthread_cond_broadcast((pthread_cond_t *)(&(condition->backend)));
+  */
+}
+
+/* Wake up one thread waiting on this condition. */
+int
+__objc_condition_signal(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
+
+  /*
+  return pthread_cond_signal((pthread_cond_t *)(&(condition->backend)));
+  */
 }
 
 /* End of File */
index 6ea883e257c8edccc1fe074fa8f19fff7d6fbc63..42032542b8017d794d25d7d2bdfeda5ef34b5ce7 100644 (file)
@@ -32,283 +32,204 @@ Boston, MA 02111-1307, USA.  */
 #include <objc/thr.h>
 #include "runtime.h"
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-    volatile objc_thread_t     owner;          /* Id of thread that owns.  */
-    volatile int                depth;          /* # of acquires.           */
-    ulock_t                     lock;           /* Irix lock.               */
-};
-
-/*****************************************************************************
- *  Static variables.
- */
-static void *  __objc_shared_arena_handle = NULL; /* Storage arena locks.   */
-
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Key structure for maintiain thread specific storage */
+static void * __objc_shared_arena_handle = NULL;
+
+/* Backend initialization functions */
+
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-    char        arena_name[64];                 /* Name of IRIX arena.      */
-
-    DEBUG_PRINTF("__objc_init_thread_system\n");
-    sprintf(arena_name, "/usr/tmp/objc_%05u", (unsigned)getpid());
-    usconfig(CONF_INITUSERS, 256);              /* Up to 256 threads.       */
-    usconfig(CONF_ARENATYPE, US_SHAREDONLY);    /* Arena only for threads.  */
-    if (!(__objc_shared_arena_handle = usinit(arena_name))) /* Init Failed? */ 
-        return -1;                              /* Yes, return error code.  */
-    
-    return 0;
+  /* Name of IRIX arena. */
+  char arena_name[64];
+
+  DEBUG_PRINTF("__objc_init_thread_system\n");
+
+  /* Construct a temporary name for arena. */
+  sprintf(arena_name, "/usr/tmp/objc_%05u", (unsigned)getpid());
+
+  /* Up to 256 threads.  Arena only for threads. */
+  usconfig(CONF_INITUSERS, 256);
+  usconfig(CONF_ARENATYPE, US_SHAREDONLY);
+
+  /* Initialize the arena */
+  if (!(__objc_shared_arena_handle = usinit(arena_name)))
+    /* Failed */
+    return -1;
+
+  return 0;
 }
 
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
   return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-    objc_thread_t      thread_id = NULL;
-    int                 sys_id;
-    
-    objc_mutex_lock(__objc_runtime_mutex);
-    if ((sys_id = sproc((void *)func, PR_SALL, arg)) >= 0) {
-        thread_id = (objc_thread_t)sys_id;
-        __objc_runtime_threads_alive++;
-    }
-    objc_mutex_unlock(__objc_runtime_mutex);
-
-    return thread_id;
+  objc_thread_t thread_id;
+  int sys_id;
+
+  if ((sys_id = sproc((void *)func, PR_SALL, arg)) >= 0)
+    thread_id = (objc_thread_t)sys_id;
+  else
+    thread_id = NULL;
+  
+  return thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
-    int         sys_priority = 0;
-
-    switch (priority) {
-    case OBJC_THREAD_INTERACTIVE_PRIORITY:
-        break;
-    default:
-    case OBJC_THREAD_BACKGROUND_PRIORITY:
-        break;
-    case OBJC_THREAD_LOW_PRIORITY:
-        break;
-    }
-    return -1;                                  /* Failed.                  */
+  /* Not implemented yet */
+  return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
-    return -1;                                  /* Couldn't get priority.   */
+  /* Not implemented yet */
+  return OBJC_THREAD_INTERACTIVE_PRIORITY;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
-    sginap(0);                                  /* Yield to equal process.  */
+  sginap(0);
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-    objc_mutex_lock(__objc_runtime_mutex);
-    __objc_runtime_threads_alive--;
-    objc_mutex_unlock(__objc_runtime_mutex);
+  /* IRIX only has exit. */
+  exit(__objc_thread_exit_status);
 
-    exit(__objc_thread_exit_status);            /* IRIX only has exit.      */
-    return -1;
+  /* Failed if we reached here */
+  return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  NULL which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
-    return (objc_thread_t)get_pid();           /* Threads are processes.   */
+  /* Threads are processes. */
+  return (objc_thread_t)get_pid();
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
-    *((void **)&PRDA->usr_prda) = value;        /* Set thread data ptr.     */
-    return 0;
+  *((void **)&PRDA->usr_prda) = value;
+  return 0;
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
+{
+  return *((void **)&PRDA->usr_prda);
+}
+
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
+{
+  if (!( (ulock_t)(mutex->backend) = usnewlock(__objc_shared_arena_handle) ))
+    return -1;
+  else
+    return 0;
+}
+
+/* Deallocate a mutex. */
+int
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-    return *((void **)&PRDA->usr_prda);         /* Return thread data ptr.  */
+  usfreelock((ulock_t)(mutex->backend), __objc_shared_arena_handle);
+  return 0;
 }
 
-/********
- *  Allocate a mutex.
- *  Return the mutex pointer if successful or NULL if the allocation failed
- *  for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
+/* Grab a lock on a mutex. */
+int
+__objc_mutex_lock(objc_mutex_t mutex)
 {
-    objc_mutex_t       mutex;
-    int                 err = 0;
-    
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
-    
-    if (!(mutex->lock = usnewlock(__objc_shared_arena_handle)))
-        err = -1;
-    
-    if (err != 0) {                             /* System init failed?      */
-        objc_free(mutex);                       /* Yes, free local memory.  */
-        return NULL;                            /* Abort.                   */
-    }
-    mutex->owner = NULL;                        /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
+  if (ussetlock((ulock_t)(mutex->backend)) == 0)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallotcate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Try to grab a lock on a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_trylock(objc_mutex_t mutex)
 {
-    int         depth;                          /* # of locks on mutex.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-    
-    usfreelock(mutex->lock, __objc_shared_arena_handle); /* Free IRIX lock. */
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
+  if (ustestlock((ulock_t)(mutex->backend)) == 0)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+/* Unlock the mutex */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_mutex_unlock(objc_mutex_t mutex)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id) {            /* Already own lock?        */
-        DEBUG_PRINTF("lock owned by: %d:%d\n", mutex->owner, mutex->depth);
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-    }
-    
-    DEBUG_PRINTF("lock owned by: %d:%d (attempt by %d)\n",
-                 mutex->owner, mutex->depth, thread_id);
-
-    if (ussetlock(mutex->lock) == 0)            /* Did lock acquire fail?   */
-        return -1;                              /* Yes, abort.              */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  usunsetlock((ulock_t)(mutex->backend));
+  return 0;
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Backend condition mutex functions */
+
+/* Allocate a condition. */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_condition_allocate(objc_condition_t condition)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-    
-    if (ustestlock(mutex->lock) == 0)           /* Did lock acquire fail?   */
-        return -1;                              /* Yes, abort.              */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  /* Unimplemented. */
+  return -1;
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Deallocate a condition. */
+int
+__objc_condition_deallocate(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
+}
+
+/* Wait on the condition */
+int
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+{
+  /* Unimplemented. */
+  return -1;
+}
+
+/* Wake up all threads waiting on this condition. */
+int
+__objc_condition_broadcast(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
+}
 
+/* Wake up one thread waiting on this condition. */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_condition_signal(objc_condition_t condition)
 {
-    objc_thread_t     thread_id;               /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-
-    DEBUG_PRINTF("unlock by: %d:%d\n", mutex->owner, mutex->depth - 1);
-    
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = NULL;                        /* Set owner to "no thread".*/
-    
-    usunsetlock(mutex->lock);                   /* Free lock.               */
-    
-    return 0;                                   /* No, return success.      */
+  /* Unimplemented. */
+  return -1;
 }
 
 /* End of File */
index 1f43fc56f2407e8ada5c1c95fe0f4a2f39a9a697..6f54ada61082298a8fd248270936d5413274603c 100644 (file)
@@ -31,434 +31,282 @@ Boston, MA 02111-1307, USA.  */
 #include <objc/thr.h>
 #include "runtime.h"
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
*  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
+/*
+  Obtain the maximum thread priority that can set for t.  Under the
+  mach threading model, it is possible for the developer to adjust the
+  maximum priority downward only-- cannot be raised without superuser
 priviledges.  Once lowered, it cannot be raised.
 */
+static int __mach_get_max_thread_priority(cthread_t t, int *base)
 {
-    volatile objc_thread_t     owner;          /* Id of thread that owns.  */
-    volatile int                depth;          /* # of acquires.           */
-    struct mutex                lock;           /* cthread mutex            */
-};
-
-struct objc_condition 
-{
-    struct condition            condition;      /* cthread condition        */
-};
-
-/********
- * obtain the maximum thread priority that can set for t.  Under the
- * mach threading model, it is possible for the developer to adjust the
- * maximum priority downward only-- cannot be raised without superuser
- * priviledges.  Once lowered, it cannot be raised.
- */
-static int __mach_get_max_thread_priority(cthread_t t, int *base) {
-    thread_t                         threadP;
-    kern_return_t             error;
-    struct thread_sched_info  info;
-    unsigned int              info_count=THREAD_SCHED_INFO_COUNT;
+  thread_t threadP;
+  kern_return_t error;
+  struct thread_sched_info info;
+  unsigned int info_count=THREAD_SCHED_INFO_COUNT;
     
-    if (t == NULL)
-       return -1;
+  if (t == NULL)
+    return -1;
 
-    threadP  = cthread_thread(t);      /* get thread underlying */
+  threadP  = cthread_thread(t);        /* get thread underlying */
 
-    error=thread_info(threadP, THREAD_SCHED_INFO, 
-                     (thread_info_t)&info, &info_count);
+  error=thread_info(threadP, THREAD_SCHED_INFO, 
+                   (thread_info_t)&info, &info_count);
 
-    if (error != KERN_SUCCESS)
-       return -1;
+  if (error != KERN_SUCCESS)
+    return -1;
 
-    if (base != NULL)
-       *base = info.base_priority;
+  if (base != NULL)
+    *base = info.base_priority;
 
-    return info.max_priority;
+  return info.max_priority;
 }
        
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Backend initialization functions */
+
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-    DEBUG_PRINTF("__objc_init_thread_system\n");
-    return 0;                                    /* Succeeded.       */
+  return 0;
 }
 
-
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
   return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-    objc_thread_t      thread_id = NULL;       /* Detached thread id.      */
-    cthread_t           new_thread_handle;      /* cthread handle.          */
+  objc_thread_t thread_id;
+  cthread_t new_thread_handle;
 
-    objc_mutex_lock(__objc_runtime_mutex);
-    
-    /* create thread */
-    new_thread_handle = cthread_fork((cthread_fn_t)func, arg);
+  /* create thread */
+  new_thread_handle = cthread_fork((cthread_fn_t)func, arg);
 
-    if(new_thread_handle) {
+  if(new_thread_handle)
+    {
       /* this is not terribly portable */
-        thread_id = *(objc_thread_t *)&new_thread_handle; 
-        cthread_detach(new_thread_handle);      /* fully detach thread */
-        __objc_runtime_threads_alive++;         /* increment thread count */
+      thread_id = *(objc_thread_t *)&new_thread_handle; 
+      cthread_detach(new_thread_handle);
     }
-    
-    objc_mutex_unlock(__objc_runtime_mutex);
-    return thread_id;
+  else
+    thread_id = NULL;
+  
+  return thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
-    objc_thread_t   *t      = objc_thread_id();
-    cthread_t        cT             = (cthread_t) t; 
-    int             maxPriority  = __mach_get_max_thread_priority(cT, NULL);
-    int              sys_priority = 0;
+  objc_thread_t *t = objc_thread_id();
+  cthread_t cT = (cthread_t) t; 
+  int maxPriority = __mach_get_max_thread_priority(cT, NULL);
+  int sys_priority = 0;
 
-    if (maxPriority == -1)
-       return -1;
+  if (maxPriority == -1)
+    return -1;
 
-    switch (priority) {
+  switch (priority)
+    {
     case OBJC_THREAD_INTERACTIVE_PRIORITY:
-        sys_priority = maxPriority;
-        break;
+      sys_priority = maxPriority;
+      break;
     case OBJC_THREAD_BACKGROUND_PRIORITY:
-        sys_priority = (maxPriority * 2) / 3;
-        break;
+      sys_priority = (maxPriority * 2) / 3;
+      break;
     case OBJC_THREAD_LOW_PRIORITY:
-        sys_priority = maxPriority / 3;
-        break;
+      sys_priority = maxPriority / 3;
+      break;
     default:
-       return -1;
+      return -1;
     }
 
-    if (sys_priority == 0)
-       return -1;
-    
-    if (cthread_priority(cT, sys_priority, 0) == KERN_SUCCESS)
-        return 0;                               /* Changed priority. End.   */
-    
-    return -1;                                  /* Failed.                  */
+  if (sys_priority == 0)
+    return -1;
+
+  /* Change the priority */
+  if (cthread_priority(cT, sys_priority, 0) == KERN_SUCCESS)
+    return 0;
+  else
+    return -1;
 }
 
-/********
- *  Return the current thread's priority [well, whatever it is closest to].
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
-    objc_thread_t *t           = objc_thread_id();
-    cthread_t      cT          = (cthread_t) t; /* see objc_thread_id() */
-    int           basePriority;
-    int           maxPriority;
-    int            sys_priority = 0;
-
-    int interactiveT, backgroundT, lowT; /* threasholds */
-
-    maxPriority = __mach_get_max_thread_priority(cT, &basePriority);
-
-    if(maxPriority == -1)
-       return -1;
-
-    if (basePriority > ( (maxPriority * 2) / 3))
-       return OBJC_THREAD_INTERACTIVE_PRIORITY; /* interactive priority
-                                                */
-    if (basePriority > ( maxPriority / 3))
-       return OBJC_THREAD_BACKGROUND_PRIORITY; /* background priority
-                                                */
-    return OBJC_THREAD_LOW_PRIORITY; /* everything else is low */
+  objc_thread_t *t = objc_thread_id();
+  cthread_t cT = (cthread_t) t; /* see objc_thread_id() */
+  int basePriority;
+  int maxPriority;
+  int sys_priority = 0;
+
+  int interactiveT, backgroundT, lowT; /* threasholds */
+
+  maxPriority = __mach_get_max_thread_priority(cT, &basePriority);
+
+  if(maxPriority == -1)
+    return -1;
+
+  if (basePriority > ( (maxPriority * 2) / 3))
+    return OBJC_THREAD_INTERACTIVE_PRIORITY;
+
+  if (basePriority > ( maxPriority / 3))
+    return OBJC_THREAD_BACKGROUND_PRIORITY;
+
+  return OBJC_THREAD_LOW_PRIORITY;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
-    cthread_yield();                            /* Yield to equal thread.   */
+  cthread_yield();
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  objc_mutex_lock(__objc_runtime_mutex);
-  __objc_runtime_threads_alive--;
-  objc_mutex_unlock(__objc_runtime_mutex);
-      
-  cthread_exit(&__objc_thread_exit_status);     /* Terminate thread.        */
+  /* exit the thread */
+  cthread_exit(&__objc_thread_exit_status);
+
+  /* Failed if we reached here */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  NULL which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
   cthread_t self = cthread_self();
-  return (objc_thread_t)self;
-}
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+  return *(objc_thread_t *)&self;
+}
 
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
   cthread_set_data(cthread_self(), (any_t) value);
   return 0;
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
 {
   return (void *) cthread_data(cthread_self());
 }
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if the
- *  allocation failed for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
 {
-    objc_mutex_t mutex;
-    int         err = 0;
-    
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
+  int err = 0;
+  mutex->backend = objc_malloc(sizeof(struct mutex));
 
-    err = mutex_init(&(mutex->lock));
-    
-    if (err != 0) {                             /* System init failed?      */
-        objc_free(mutex);                       /* Yes, free local memory.  */
-        return NULL;                            /* Abort.                   */
+  err = mutex_init((mutex_t)(mutex->backend));
+
+  if (err != 0)
+    {
+      objc_free(mutex->backend);
+      return -1;
     }
-    mutex->owner = (objc_thread_t) -1;         /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallocate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Deallocate a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-    int         depth;                          /* # of locks on mutex.     */
+  mutex_clear((mutex_t)(mutex->backend));
 
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-    
-    mutex_unlock(&(mutex->lock));               /* Must unlock system mutex.*/
-    mutex_clear(&(mutex->lock));                /* Free system mutex.       */
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
+  objc_free(mutex->backend);
+  mutex->backend = NULL;
+  return 0;
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+/* Grab a lock on a mutex. */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_mutex_lock(objc_mutex_t mutex)
 {
-    objc_thread_t thread_id;                  /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-
-    mutex_lock(&(mutex->lock));                 /* Lock cthread mutex.      */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  mutex_lock((mutex_t)(mutex->backend));
+  return 0;
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Try to grab a lock on a mutex. */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_mutex_trylock(objc_mutex_t mutex)
 {
-    objc_thread_t         thread_id;           /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-    
-    if (mutex_try_lock(&(mutex->lock)) == 0)    /* Lock cthread mutex.      */
-        return -1;                              /* Failed, abort.           */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  if (mutex_try_lock((mutex_t)(mutex->backend)) == 0)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Unlock the mutex */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_mutex_unlock(objc_mutex_t mutex)
 {
-    objc_thread_t    thread_id;                /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = (objc_thread_t) -1;         /* Set owner to "no thread".*/
-    
-    mutex_unlock(&(mutex->lock));               /* unlock cthread mutex.    */
-    
-    return 0;                                   /* No, return success.      */
+  mutex_unlock((mutex_t)(mutex->backend));
+  return 0;
 }
 
-/********
- *  Allocate a condition.  Return the condition pointer if successful or NULL
- * if the allocation failed for any reason.
- */
-objc_condition_t 
-objc_condition_allocate(void)
-{
-    objc_condition_t condition;
-    
-    if (!(condition = (objc_condition_t)objc_malloc(
-                        sizeof(struct objc_condition))))
-        return NULL;                            /* Abort if malloc failed.  */
+/* Backend condition mutex functions */
 
-    condition_init(&(condition->condition));
-    
-    return condition;                           /* Return mutex handle.     */
+/* Allocate a condition. */
+int
+__objc_condition_allocate(objc_condition_t condition)
+{
+  condition->backend = objc_malloc(sizeof(struct condition));
+  condition_init((condition_t)(condition->backend));
+  return 0;
 }
 
-/********
- *  Deallocate a condition. Note that this includes an implicit 
- *  condition_broadcast to insure that waiting threads have the opportunity
- *  to wake.  It is legal to dealloc a condition only if no other
- *  thread is/will be using it. Here we do NOT check for other threads
- *  waiting but just wake them up.
- */
+/* Deallocate a condition. */
 int
-objc_condition_deallocate(objc_condition_t condition)
+__objc_condition_deallocate(objc_condition_t condition)
 {
-       condition_broadcast(&(condition->condition));
-       condition_clear(&(condition->condition));
-       objc_free(condition);
-       return 0;
+  condition_clear((condition_t)(condition->backend));
+  objc_free(condition->backend);
+  condition->backend = NULL;
+  return 0;
 }
 
-/********
- *  Wait on the condition unlocking the mutex until objc_condition_signal()
- *  or objc_condition_broadcast() are called for the same condition. The
- *  given mutex *must* have the depth set to 1 so that it can be unlocked
- *  here, so that someone else can lock it and signal/broadcast the condition.
- *  The mutex is used to lock access to the shared data that make up the
- *  "condition" predicate.
- */
+/* Wait on the condition */
 int
-objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
 {
-    objc_thread_t    thread_id;                /* Cache our thread id.     */
-    
-    if (!mutex || !condition)                   /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Locked more than once ?  */
-        return -1;                              /* YES, return error        */
-                                                /* mutex will be unlocked   */
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = (objc_thread_t) -1;         /* Set owner to "no thread".*/
-    
-    condition_wait(&(condition->condition),
-               &(mutex->lock));                        /* unlock, wait ..., lock   */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    mutex->depth = 1;                           /* Increment depth to end.  */
-    return 0;                                   /* Return success.          */
+  condition_wait((condition_t)(condition->backend),
+                (mutex_t)(mutex->backend));
+  return 0;
 }
 
-/********
- *  Wake up all threads waiting on this condition. It is recommended that 
- *  the called would lock the same mutex as the threads in objc_condition_wait
- *  before changing the "condition predicate" and make this call and unlock it
- *  right away after this call.
- */
+/* Wake up all threads waiting on this condition. */
 int
-objc_condition_broadcast(objc_condition_t condition)
+__objc_condition_broadcast(objc_condition_t condition)
 {
-    if (!condition)
-               return -1;
-       condition_broadcast(&(condition->condition));
-       return 0;
+  condition_broadcast((condition_t)(condition->backend));
+  return 0;
 }
 
-/********
- *  Wake up one thread waiting on this condition. It is recommended that 
- *  the called would lock the same mutex as the threads in objc_condition_wait
- *  before changing the "condition predicate" and make this call and unlock it
- *  right away after this call.
- */
+/* Wake up one thread waiting on this condition. */
 int
-objc_condition_signal(objc_condition_t condition)
+__objc_condition_signal(objc_condition_t condition)
 {
-    if (!condition)
-               return -1;
-       condition_signal(&(condition->condition));
-       return 0;
+  condition_signal((condition_t)(condition->backend));
+  return 0;
 }
 
+/* End of File */
index 422d53ec3c190c05ba3fdb8927dae925411d79c4..d54606052d0054d5d645868afe5cd19b2e3220d4 100644 (file)
@@ -44,71 +44,39 @@ Boston, MA 02111-1307, USA.  */
 
 #include <stdlib.h>
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-  volatile objc_thread_t owner;          /* Id of thread that owns.  */
-  volatile int            depth;          /* # of acquires.           */
-  HMTX                    handle;         /* OS/2 mutex HANDLE.      */
-};
+/* Backend initialization functions */
 
-/*****************************************************************************
- *  Static variables.
- */
-/* none needed for OS/2 */
-
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-  DEBUG_PRINTF("__objc_init_thread_system (os2-emx)\n");
-
-  /* no initialization of thread subsystem */
-  return 0;                                    /* Yes, return success.     */
+  return 0;
 }
 
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
-  /* no termination code for thread subsystem */
   return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-  int thread_id = 0;  /* id of the newly created thread */
+  int thread_id = 0;
 
-  objc_mutex_lock(__objc_runtime_mutex);
-
-  /* create a thread calling "func", args "arg", stack size 32768 bytes */
   if ((thread_id = _beginthread (func,NULL,32768,arg)) < 0)
     thread_id = 0;
-  else
-    __objc_runtime_threads_alive++;
-  
-  objc_mutex_unlock(__objc_runtime_mutex);
   
   return (objc_thread_t)thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
   ULONG sys_class = 0;
   ULONG sys_priority = 0;
@@ -132,210 +100,168 @@ objc_thread_set_priority(int priority)
     sys_priority = 0;
     break;
   }
+
+  /* Change priority */
   if (!DosSetPriority (PRTYS_THREAD,sys_class,sys_priority,*_threadid))
-    return 0;                                          /* Changed priority. End.   */
-    
-  return -1;                                   /* Failed.                  */
+    return 0;
+  else
+    return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
   PTIB ptib;
   PPIB ppib;
 
-  DosGetInfoBlocks (&ptib,&ppib); /* get information about current thread */
+  /* get information about current thread */
+  DosGetInfoBlocks (&ptib,&ppib);
+
+  switch (ptib->tib_ptib2->tib2_ulpri)
+    {
+    case PRTYC_IDLETIME:
+    case PRTYC_REGULAR:
+    case PRTYC_TIMECRITICAL:
+    case PRTYC_FOREGROUNDSERVER:
+    default:
+      return OBJC_THREAD_INTERACTIVE_PRIORITY;
+    }
 
-  switch (ptib->tib_ptib2->tib2_ulpri) {
-  case PRTYC_IDLETIME:
-  case PRTYC_REGULAR:
-  case PRTYC_TIMECRITICAL:
-  case PRTYC_FOREGROUNDSERVER:
-  default:
-    return OBJC_THREAD_INTERACTIVE_PRIORITY;
-  }
-  return -1;                                   /* Couldn't get priority.   */
+  return -1;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
-  DosSleep (0);                                        /* Yield to equal thread.   */
+  DosSleep (0);
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  objc_mutex_lock(__objc_runtime_mutex);
-  __objc_runtime_threads_alive--;
-  objc_mutex_unlock(__objc_runtime_mutex);
-
-  _endthread (); /* terminate the thread, NEVER use DosExit () */
+  /* terminate the thread, NEVER use DosExit () */
+  _endthread ();
 
+  /* Failed if we reached here */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  -1 which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
-  return (objc_thread_t) *_threadid;  /* Return thread id.        */
+  return (objc_thread_t) *_threadid;
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
   *_threadstore () = value;
 
   return 0;
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
 {
   return *_threadstore ();
 }
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if
- *  the allocation fails for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
-{
-    objc_mutex_t mutex;
-    int         err = 0;
-
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
-
-    if (DosCreateMutexSem (NULL,&(mutex->handle),0L,0) > 0) {
-      objc_free(mutex);
-      return NULL;
-    }
+/* Backend mutex functions */
 
-    mutex->owner = NULL;                        /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
+{
+  if (DosCreateMutexSem (NULL, (HMTX)(&(mutex->backend)),0L,0) > 0)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallotcate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Deallocate a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-    int         depth;                          /* # of locks on mutex.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-
-    DosCloseMutexSem (mutex->handle);
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
+  DosCloseMutexSem ((HMTX)(mutex->backend));
+  return 0;
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+/* Grab a lock on a mutex. */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_mutex_lock(objc_mutex_t mutex)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
+  if (DosRequestMutexSem ((HMTX)(mutex->backend),-1L) != 0)
+    return -1;
+  else
+    return 0;
+}
 
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
+/* Try to grab a lock on a mutex. */
+int
+__objc_mutex_trylock(objc_mutex_t mutex)
+{
+  if (DosRequestMutexSem ((HMTX)(mutex->backend),0L) != 0)
+    return -1;
+  else
+    return 0;
+}
 
-    if (DosRequestMutexSem (mutex->handle,-1L) != 0)
-      return -1;
+/* Unlock the mutex */
+int
+__objc_mutex_unlock(objc_mutex_t mutex)
+{
+  if (DosReleaseMutexSem((HMTX)(mutex->backend)) != 0)
+    return -1;
+  else
+    return 0;
+}
 
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
+/* Backend condition mutex functions */
 
-    return ++mutex->depth;                      /* Increment depth to end.  */
+/* Allocate a condition. */
+int
+__objc_condition_allocate(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Deallocate a condition. */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_condition_deallocate(objc_condition_t condition)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
+  /* Unimplemented. */
+  return -1;
+}
 
-    if (DosRequestMutexSem (mutex->handle,0L) != 0)
-      return -1;
+/* Wait on the condition */
+int
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+{
+  /* Unimplemented. */
+  return -1;
+}
 
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return ++mutex->depth;                      /* Increment depth to end.  */
+/* Wake up all threads waiting on this condition. */
+int
+__objc_condition_broadcast(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Wake up one thread waiting on this condition. */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_condition_signal(objc_condition_t condition)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = NULL;                        /* Set owner to "no thread".*/
-    
-    if (DosReleaseMutexSem(mutex->handle) != 0)
-        return -1;                              /* Failed, abort.           */
-    
-    return 0;                                   /* No, return success.      */
+  /* Unimplemented. */
+  return -1;
 }
+
+/* End of File */
index 987f8a81b01010cfb3251fd75b5358acee7d9455..1b9a9e50049ccf72bf8bf15dc58607896730c8bd 100644 (file)
@@ -29,294 +29,182 @@ Boston, MA 02111-1307, USA.  */
 #include "runtime.h"
 #include <pthread.h>
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-    volatile objc_thread_t     owner;          /* Id of thread that owns.  */
-    volatile int                depth;          /* # of acquires.           */
-    pthread_mutex_t             lock;           /* pthread mutex.           */
-};
-
-/*****************************************************************************
- *  Static variables.
- */
-static pthread_key_t    __objc_thread_data_key; /* Data key for thread data.*/
+/* Key structure for maintiain thread specific storage */
+static pthread_key_t _objc_thread_storage;
 
+/* Backend initialization functions */
 
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-    if (pthread_key_create(&__objc_thread_data_key, NULL) == 0)
-        return 0;                               /* Yes, return success.     */
-    
-    return -1;                                  /* Failed.                  */
+  /* Initialize the thread storage key */
+  return pthread_key_create(&_objc_thread_storage, NULL);
 }
 
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
   return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-    objc_thread_t      thread_id = NULL;       /* Detached thread id.      */
-    pthread_t           new_thread_handle;      /* DCE thread handle.       */
-
-    objc_mutex_lock(__objc_runtime_mutex);
-
-    if (pthread_create(&new_thread_handle, NULL,
-                       (void *)func, arg) == 0) {
-        thread_id = (objc_thread_t) new_thread_handle;
-        pthread_detach(new_thread_handle);     /* Fully detach thread.     */
-       __objc_runtime_threads_alive++;
-    }
-    
-    objc_mutex_unlock(__objc_runtime_mutex);
-    return thread_id;
+  objc_thread_t thread_id;
+  pthread_t new_thread_handle;
+
+  if ( !(pthread_create(&new_thread_handle, NULL, (void *)func, arg)) )
+      thread_id = *(objc_thread_t *)&new_thread_handle;
+  else
+    thread_id = NULL;
+  
+  return thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
-#if 0 /* no get/set priority in Linux pthreads */
-
-    int         sys_priority = 0;
-
-    switch (priority) {
-    case OBJC_THREAD_INTERACTIVE_PRIORITY:
-        sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2;
-        break;
-    default:
-    case OBJC_THREAD_BACKGROUND_PRIORITY:
-        sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
-        break;
-    case OBJC_THREAD_LOW_PRIORITY:
-        sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
-        break;
-    }
-    
-    if (pthread_setprio(pthread_self(), sys_priority) >= 0)
-        return 0;                               /* Changed priority. End.   */
-    
-#endif
-    return -1;                                  /* Failed.                  */
+  /* Not implemented yet */
+  return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
-#if 0 /* no get/set priority in Linux pthreads */
-    int         sys_priority;                   /* DCE thread priority.     */
-    
-    if ((sys_priority = pthread_getprio(pthread_self())) >= 0) {
-        if (sys_priority >= PRI_FG_MIN_NP && sys_priority <= PRI_FG_MAX_NP)
-            return OBJC_THREAD_INTERACTIVE_PRIORITY;
-        if (sys_priority >= PRI_BG_MIN_NP && sys_priority <= PRI_BG_MAX_NP)
-            return OBJC_THREAD_BACKGROUND_PRIORITY;
-        return OBJC_THREAD_LOW_PRIORITY;
-    }
-#endif
-    return -1;                                  /* Couldn't get priority.   */
+  /* Not implemented yet */
+  return -1;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
-    pthread_yield();                            /* Yield to equal thread.   */
+  pthread_yield();
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  objc_mutex_lock(__objc_runtime_mutex);
-  __objc_runtime_threads_alive--;
-  objc_mutex_unlock(__objc_runtime_mutex);
-      
-  pthread_exit(&__objc_thread_exit_status);     /* Terminate thread.        */
+  /* exit the thread */
+  pthread_exit(&__objc_thread_exit_status);
+
+  /* Failed if we reached here */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  -1 which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
   pthread_t self = pthread_self();
 
-  return (objc_thread_t) self;               /* Return thread handle.    */
+  return *(objc_thread_t *)&self;
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
-    if (pthread_setspecific(__objc_thread_data_key, (void *)value) == 0)
-        return 0;                              /* Return thread data.      */
-    return -1;
+  return pthread_setspecific(_objc_thread_storage, value);
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
+{
+  return pthread_getspecific(_objc_thread_storage);
+}
+
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
 {
-    return pthread_getspecific(__objc_thread_data_key);
+  if (pthread_mutex_init((pthread_mutex_t *)(&(mutex->backend)), NULL))
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if
- *  the allocation fails for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
+/* Deallocate a mutex. */
+int
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-    objc_mutex_t mutex;
-    int         err = 0;
-    
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
-
-    err = pthread_mutex_init(&mutex->lock, NULL);
-    
-    if (err != 0) {                             /* System init failed?      */
-        objc_free(mutex);                       /* Yes, free local memory.  */
-        return NULL;                            /* Abort.                   */
-    }
-    mutex->owner = NULL;                        /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
+  if (pthread_mutex_destroy((pthread_mutex_t *)(&(mutex->backend))))
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallotcate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Grab a lock on a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_lock(objc_mutex_t mutex)
 {
-    int         depth;                          /* # of locks on mutex.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-    
-    pthread_mutex_unlock(&mutex->lock);         /* Must unlock system mutex.*/
-    pthread_mutex_destroy(&mutex->lock);        /* Free system mutex.       */
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
+  return pthread_mutex_lock((pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+/* Try to grab a lock on a mutex. */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_mutex_trylock(objc_mutex_t mutex)
 {
-    objc_thread_t     thread_id;                /* Cache our thread id. */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-
-    if (pthread_mutex_lock(&mutex->lock) != 0)  /* Lock DCE system mutex.   */
-        return -1;                              /* Failed, abort.           */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  return pthread_mutex_trylock((pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Unlock the mutex */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_mutex_unlock(objc_mutex_t mutex)
 {
-    objc_thread_t    thread_id;                 /* Cache our thread id. */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-    
-    if (pthread_mutex_trylock(&mutex->lock) != 1) /* Lock DCE system mutex. */
-        return -1;                              /* Failed, abort.           */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  return pthread_mutex_unlock((pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Backend condition mutex functions */
+
+/* Allocate a condition. */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_condition_allocate(objc_condition_t condition)
 {
-    objc_thread_t   thread_id;                 /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = NULL;                        /* Set owner to "no thread".*/
-    
-    if (pthread_mutex_unlock(&mutex->lock) != 0)  /* Unlock system mutex.   */
-        return -1;                              /* Failed, abort.           */
-    
-    return 0;                                   /* No, return success.      */
+  if (pthread_cond_init((pthread_cond_t *)(&(condition->backend)), NULL))
+    return -1;
+  else
+    return 0;
 }
+
+/* Deallocate a condition. */
+int
+__objc_condition_deallocate(objc_condition_t condition)
+{
+  return pthread_cond_destroy((pthread_cond_t *)(&(condition->backend)));
+}
+
+/* Wait on the condition */
+int
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+{
+  return pthread_cond_wait((pthread_cond_t *)(&(condition->backend)),
+                          (pthread_mutex_t *)(&(mutex->backend)));
+}
+
+/* Wake up all threads waiting on this condition. */
+int
+__objc_condition_broadcast(objc_condition_t condition)
+{
+  return pthread_cond_broadcast((pthread_cond_t *)(&(condition->backend)));
+}
+
+/* Wake up one thread waiting on this condition. */
+int
+__objc_condition_signal(objc_condition_t condition)
+{
+  return pthread_cond_signal((pthread_cond_t *)(&(condition->backend)));
+}
+
+/* End of File */
index 3e73fe07eb121f47bb8f9648c7e983cd626f258c..4c4c2450aac43fbeb04ce40b870f5f9595ff9a8a 100644 (file)
@@ -1,6 +1,7 @@
 /* GNU Objective C Runtime Thread Implementation for PCThreads under Linux.
    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    Contributed by Scott Christley <scottc@net-community.com>
+   Condition functions added by: Mircea Oancea <mircea@first.elcom.pub.ro>
 
 This file is part of GNU CC.
 
@@ -24,35 +25,16 @@ Boston, MA 02111-1307, USA.  */
    however invalidate any other reasons why the executable file might be
    covered by the GNU General Public License.  */
 
-#include <pthread.h>
+#include <pcthread.h>
 #include <objc/thr.h>
 #include "runtime.h"
 
 /* Key structure for maintiain thread specific storage */
 static pthread_key_t _objc_thread_storage;
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-  volatile objc_thread_t     owner;          /* Id of thread that owns.  */
-  volatile int                depth;          /* # of acquires.           */
-  pthread_mutex_t             mutex;          /* PCThread mutex           */
-};
-
-struct objc_condition 
-{
-  pthread_cond_t              condition;      /* cthread condition        */
-};
+/* Backend initialization functions */
 
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
@@ -60,11 +42,9 @@ __objc_init_thread_system(void)
   return pthread_key_create(&_objc_thread_storage, NULL);
 }
 
-/********
- *  Finalize the threads subsystem.  Returns 0 if successful, or -1 if not
- */
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
   /* Destroy the thread storage key */
   /* Not implemented yet */
@@ -72,104 +52,76 @@ __objc_fini_thread_system(void)
   return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
   objc_thread_t thread_id;
   pthread_t new_thread_handle;
 
-  objc_mutex_lock(__objc_runtime_mutex);
-  
   if ( !(pthread_create(&new_thread_handle, NULL, (void *)func, arg)) )
-    {
       thread_id = *(objc_thread_t *)&new_thread_handle;
-      __objc_runtime_threads_alive++;
-    }
   else
     thread_id = NULL;
   
-  objc_mutex_unlock(__objc_runtime_mutex);
-  
   return thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
   /* Not implemented yet */
-  return -1;                                           /* Failed.                  */
+  return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
   /* Not implemented yet */
-  return OBJC_THREAD_INTERACTIVE_PRIORITY;      /* Highest priority.        */
+  return OBJC_THREAD_INTERACTIVE_PRIORITY;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
   pthread_yield(NULL);
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  objc_mutex_lock(__objc_runtime_mutex);
-  __objc_runtime_threads_alive--;
-  objc_mutex_unlock(__objc_runtime_mutex);
-      
-  pthread_exit(&__objc_thread_exit_status);     /* Terminate thread.        */
+  /* exit the thread */
+  pthread_exit(&__objc_thread_exit_status);
+
+  /* Failed if we reached here */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  NULL which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
   pthread_t self = pthread_self();
 
-  return *(objc_thread_t *)&self;            /* Return thread handle.    */
+  return *(objc_thread_t *)&self;
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
   return pthread_setspecific(_objc_thread_storage, value);
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
 {
   void *value = NULL;
 
@@ -179,240 +131,88 @@ objc_thread_get_data(void)
   return NULL;
 }
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if the
- *  allocation failed for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
 {
-  objc_mutex_t mutex;
-    
-  if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-    return NULL;                            /* Abort if malloc failed.  */
-
-  /* Create PCThread mutex */
-  if ( pthread_mutex_init(&(mutex->mutex), NULL) )
-    {
-      /* Failed */
-      objc_free(mutex);
-      return NULL;
-    }
-
-  mutex->owner = NULL;                        /* No owner.                */
-  mutex->depth = 0;                           /* No locks.                */
-  return mutex;                               /* Return mutex handle.     */
+  if (pthread_mutex_init((pthread_mutex_t *)(&(mutex->backend)), NULL))
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallocate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Deallocate a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-  int         depth;                          /* # of locks on mutex.     */
-
-  if (!mutex)                                 /* Is argument bad?         */
-    return -1;                              /* Yes, abort.              */
-  depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-
-  /* Destroy PCThread mutex */
-  pthread_mutex_destroy(&(mutex->mutex));
-
-  objc_free(mutex);                           /* Free memory.             */
-  return depth;                               /* Return last depth.       */
+  if (pthread_mutex_destroy((pthread_mutex_t *)(&(mutex->backend))))
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+/* Grab a lock on a mutex. */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_mutex_lock(objc_mutex_t mutex)
 {
-  objc_thread_t      thread_id;              /* Cache our thread id.     */
-  int status;
-
-  if (!mutex)                                 /* Is argument bad?         */
-    return -1;                              /* Yes, abort.              */
-  thread_id = objc_thread_id();               /* Get this thread's id.    */
-  if (mutex->owner == thread_id)              /* Already own lock?        */
-    {
-      return ++mutex->depth;                  /* Yes, increment depth.    */
-    }
-
-  /* Lock the PCThread mutex */
-  status = pthread_mutex_lock(&(mutex->mutex));
-  if (status)
-    {
-      return status;                            /* Failed */
-    }
-
-  mutex->owner = thread_id;                   /* Mark thread as owner.    */
-  return mutex->depth = 1;                    /* Increment depth to end.  */
+  return pthread_mutex_lock((pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Try to grab a lock on a mutex. */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_mutex_trylock(objc_mutex_t mutex)
 {
-  objc_thread_t      thread_id;              /* Cache our thread id.     */
-  int status;
-
-  if (!mutex)                                 /* Is argument bad?         */
-    return -1;                              /* Yes, abort.              */
-  thread_id = objc_thread_id();               /* Get this thread's id.    */
-  if (mutex->owner == thread_id)              /* Already own lock?        */
-    return ++mutex->depth;                  /* Yes, increment depth.    */
-    
-  /* Lock the PCThread mutex */
-  status = pthread_mutex_trylock(&(mutex->mutex));
-  if (status)
-    return status;                            /* Failed */
-
-  mutex->owner = thread_id;                   /* Mark thread as owner.    */
-  return mutex->depth = 1;                    /* Increment depth to end.  */
+  return pthread_mutex_trylock((pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Unlock the mutex */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_mutex_unlock(objc_mutex_t mutex)
 {
-  objc_thread_t thread_id;                   /* Cache our thread id.     */
-  int status;
-    
-  if (!mutex)                                 /* Is argument bad?         */
-    return -1;                              /* Yes, abort.              */
-  thread_id = objc_thread_id();               /* Get this thread's id.    */
-  if (mutex->owner != thread_id)              /* Does some else own lock? */
-    return -1;                              /* Yes, abort.              */
-  if (mutex->depth > 1)                       /* Released last lock?      */
-    return --mutex->depth;                  /* No, Decrement depth, end.*/
-  mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-  mutex->owner = NULL;                        /* Set owner to "no thread".*/
-
-  /* Unlock the PCThread mutex */
-  status = pthread_mutex_unlock(&(mutex->mutex));
-  if (status)
-    return status;                            /* Failed */
-
-  return 0;                                   /* No, return success.      */
+  return pthread_mutex_unlock((pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Allocate a condition.  Return the condition pointer if successful or NULL
- * if the allocation failed for any reason.
- */
-objc_condition_t 
-objc_condition_allocate(void)
+/* Backend condition mutex functions */
+
+/* Allocate a condition. */
+int
+__objc_condition_allocate(objc_condition_t condition)
 {
-    objc_condition_t condition;
-    
-    if (!(condition = (objc_condition_t)objc_malloc(
-                        sizeof(struct objc_condition))))
-        return NULL;                            /* Abort if malloc failed.  */
-
-       if ( pthread_cond_init(&(condition->condition), NULL) ) {
-               objc_free(condition);
-               return NULL;
-       }
-    
-    return condition;                           /* Return condition handle. */
+  if (pthread_cond_init((pthread_cond_t *)(&(condition->backend)), NULL))
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a condition. Note that this includes an implicit 
- *  condition_broadcast to insure that waiting threads have the opportunity
- *  to wake.  It is legal to dealloc a condition only if no other
- *  thread is/will be using it. Here we do NOT check for other threads
- *  waiting but just wake them up.
- */
+/* Deallocate a condition. */
 int
-objc_condition_deallocate(objc_condition_t condition)
+__objc_condition_deallocate(objc_condition_t condition)
 {
-       pthread_cond_broadcast(&(condition->condition));
-       pthread_cond_destroy(&(condition->condition));
-       objc_free(condition);
-       return 0;
+  return pthread_cond_destroy((pthread_cond_t *)(&(condition->backend)));
 }
 
-/********
- *  Wait on the condition unlocking the mutex until objc_condition_signal()
- *  or objc_condition_broadcast() are called for the same condition. The
- *  given mutex *must* have the depth set to 1 so that it can be unlocked
- *  here, so that someone else can lock it and signal/broadcast the condition.
- *  The mutex is used to lock access to the shared data that make up the
- *  "condition" predicate.
- */
+/* Wait on the condition */
 int
-objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
 {
-    objc_thread_t    thread_id;                /* Cache our thread id.     */
-    
-    if (!mutex || !condition)                   /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Locked more than once ?  */
-        return -1;                              /* YES, return error        */
-                                                /* mutex will be unlocked   */
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = (objc_thread_t) -1;         /* Set owner to "no thread".*/
-    
-    pthread_cond_wait(&(condition->condition),
-               &(mutex->mutex));               /* unlock, wait ..., lock   */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    mutex->depth = 1;                           /* Increment depth to end.  */
-    return 0;                                   /* Return success.          */
+  return pthread_cond_wait((pthread_cond_t *)(&(condition->backend)),
+                          (pthread_mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Wake up all threads waiting on this condition. It is recommended that 
- *  the called would lock the same mutex as the threads in objc_condition_wait
- *  before changing the "condition predicate" and make this call and unlock it
- *  right away after this call.
- */
+/* Wake up all threads waiting on this condition. */
 int
-objc_condition_broadcast(objc_condition_t condition)
+__objc_condition_broadcast(objc_condition_t condition)
 {
-    if (!condition)
-               return -1;
-       pthread_cond_broadcast(&(condition->condition));
-       return 0;
+  return pthread_cond_broadcast((pthread_cond_t *)(&(condition->backend)));
 }
 
-/********
- *  Wake up one thread waiting on this condition. It is recommended that 
- *  the called would lock the same mutex as the threads in objc_condition_wait
- *  before changing the "condition predicate" and make this call and unlock it
- *  right away after this call.
- */
+/* Wake up one thread waiting on this condition. */
 int
-objc_condition_signal(objc_condition_t condition)
+__objc_condition_signal(objc_condition_t condition)
 {
-    if (!condition)
-               return -1;
-       pthread_cond_signal(&(condition->condition));
-       return 0;
+  return pthread_cond_signal((pthread_cond_t *)(&(condition->backend)));
 }
 
 /* End of File */
index 45b7b73fe2a540ef14f61673ec9b41d0bae167f4..b196677c6b696d79e4fe7f98018d7d79bee4c75e 100644 (file)
@@ -27,214 +27,166 @@ Boston, MA 02111-1307, USA.  */
 #include <objc/thr.h>
 #include "runtime.h"
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-    volatile objc_thread_t     owner;          /* Id of thread that owns.  */
-    volatile int                depth;          /* # of acquires.           */
-};
-
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Thread local storage for a single thread */
+static void *thread_local_storage = NULL;
+
+/* Backend initialization functions */
+
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-  DEBUG_PRINTF("__objc_init_thread_system\n");
-  return -1;                                   /* Failed.                  */
+  /* No thread support available */
+  return -1;
+}
+
+/* Close the threads subsystem. */
+int
+__objc_close_thread_system(void)
+{
+  /* No thread support available */
+  return -1;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-  return NULL;                                 /* We can't start threads.  */
+  /* No thread support available */
+  return NULL;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
-  return -1;                                           /* Failed.                  */
+  /* No thread support available */
+  return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
-  return OBJC_THREAD_INTERACTIVE_PRIORITY;      /* Highest priority.        */
+  return OBJC_THREAD_INTERACTIVE_PRIORITY;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
   return;
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  exit(__objc_thread_exit_status);
+  /* No thread support available */
+  /* Should we really exit the program */
+  /* exit(&__objc_thread_exit_status); */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  NULL which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
-  return (objc_thread_t)1;                     /* No thread support, use 1.*/
+  /* No thread support, use 1. */
+  return (objc_thread_t)1;
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
-
-static void *thread_local_storage = NULL;
-
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
   thread_local_storage = value;
   return 0;
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
 {
   return thread_local_storage;
 }
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if the
- *  allocation failed for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
-{
-    objc_mutex_t mutex;
-    
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
-    
-    mutex->owner = NULL;                        /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
-}
-
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallocate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
-int
-objc_mutex_deallocate(objc_mutex_t mutex)
-{
-    int         depth;                          /* # of locks on mutex.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
-}
-
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
-int
-objc_mutex_lock(objc_mutex_t mutex)
-{
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-
-    return mutex->depth = 1;                    /* Increment depth to end.  */
-}
-
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
-int
-objc_mutex_trylock(objc_mutex_t mutex)
-{
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
-}
-
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
-int
-objc_mutex_unlock(objc_mutex_t mutex)
-{
-    objc_thread_t  thread_id;                  /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = NULL;                        /* Set owner to "no thread".*/
-    
-    return 0;                                   /* No, return success.      */
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
+{
+  return 0;
+}
+
+/* Deallocate a mutex. */
+int
+__objc_mutex_deallocate(objc_mutex_t mutex)
+{
+  return 0;
+}
+
+/* Grab a lock on a mutex. */
+int
+__objc_mutex_lock(objc_mutex_t mutex)
+{
+  /* There can only be one thread, so we always get the lock */
+  return 0;
+}
+
+/* Try to grab a lock on a mutex. */
+int
+__objc_mutex_trylock(objc_mutex_t mutex)
+{
+  /* There can only be one thread, so we always get the lock */
+  return 0;
+}
+
+/* Unlock the mutex */
+int
+__objc_mutex_unlock(objc_mutex_t mutex)
+{
+  return 0;
+}
+
+/* Backend condition mutex functions */
+
+/* Allocate a condition. */
+int
+__objc_condition_allocate(objc_condition_t condition)
+{
+  return 0;
+}
+
+/* Deallocate a condition. */
+int
+__objc_condition_deallocate(objc_condition_t condition)
+{
+  return 0;
+}
+
+/* Wait on the condition */
+int
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+{
+  return 0;
+}
+
+/* Wake up all threads waiting on this condition. */
+int
+__objc_condition_broadcast(objc_condition_t condition)
+{
+  return 0;
+}
+
+/* Wake up one thread waiting on this condition. */
+int
+__objc_condition_signal(objc_condition_t condition)
+{
+  return 0;
 }
 
 /* End of File */
index f1084bc79138e62f1e3c02c0f8f20bfc70a0cabb..0b5227a8e89b02358c114dd7c126e9a66c84f52b 100644 (file)
@@ -32,400 +32,228 @@ Boston, MA 02111-1307, USA.  */
 #include <synch.h>
 #include <errno.h>
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-    volatile objc_thread_t     owner;          /* Id of thread that owns.  */
-    volatile int                depth;          /* # of acquires.           */
-    mutex_t                     lock;           /* System mutex.            */
-};
+/* Key structure for maintiain thread specific storage */
+static thread_key_t     __objc_thread_data_key;
 
-struct objc_condition
-{
-    cond_t                     condition;      /* solaris condition        */
-};
-
-/*****************************************************************************
- *  Static variables.
- */
-static thread_key_t     __objc_thread_data_key; /* Data key for thread data.*/
-
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Backend initialization functions */
+
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-    DEBUG_PRINTF("__objc_init_thread_system\n");
-
-    if (thr_keycreate(&__objc_thread_data_key, NULL) == 0)
-        return 0;                               /* Yes, return success.     */
-    
-    return -1;                                  /* Failed.                  */
+  /* Initialize the thread storage key */
+  if (thr_keycreate(&__objc_thread_data_key, NULL) == 0)
+    return 0;
+  else
+    return -1;
 }
 
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
   return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return -1 if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-  objc_thread_t        thread_id = NULL;       /* Detached thread id.      */
-  thread_t              new_thread_id = 0;      /* Solaris thread id type.  */
-  int                   errn;
-
-  objc_mutex_lock(__objc_runtime_mutex);
+  objc_thread_t thread_id;
+  thread_t new_thread_id = 0;
 
   if (thr_create(NULL, 0, (void *)func, arg,
                  THR_DETACHED | THR_NEW_LWP,
-                 &new_thread_id) == 0) {       /* Created new thread?      */
-    thread_id = (objc_thread_t)new_thread_id;  /* Yes, remember its id.    */
-    __objc_runtime_threads_alive++;
-  }
+                 &new_thread_id) == 0)
+    thread_id = *(objc_thread_t *)&new_thread_id;
+  else
+    thread_id = NULL;
   
-  objc_mutex_unlock(__objc_runtime_mutex);
-    
   return thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
-    int         sys_priority = 0;
+  int sys_priority = 0;
 
-    switch (priority) {
+  switch (priority)
+    {
     case OBJC_THREAD_INTERACTIVE_PRIORITY:
-        sys_priority = 300;
-        break;
+      sys_priority = 300;
+      break;
     default:
     case OBJC_THREAD_BACKGROUND_PRIORITY:
-        sys_priority = 200;
-        break;
+      sys_priority = 200;
+      break;
     case OBJC_THREAD_LOW_PRIORITY:
-        sys_priority = 1000;
-        break;
+      sys_priority = 1000;
+      break;
     }
-    
-    if (thr_setprio(thr_self(), sys_priority) == 0)
-        return 0;                               /* Changed priority. End.   */
-    
-    return -1;                                  /* Failed.                  */
+
+  /* Change priority */
+  if (thr_setprio(thr_self(), sys_priority) == 0)
+    return 0;
+  else
+    return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
-    int         sys_priority;                   /* Solaris thread priority. */
+  int sys_priority;
                                                    
-    if (thr_getprio(thr_self(), &sys_priority) == 0) {
-        if (sys_priority >= 250)
-            return OBJC_THREAD_INTERACTIVE_PRIORITY;
-        else if (sys_priority >= 150)
-            return OBJC_THREAD_BACKGROUND_PRIORITY;
-        return OBJC_THREAD_LOW_PRIORITY;
+  if (thr_getprio(thr_self(), &sys_priority) == 0)
+    {
+      if (sys_priority >= 250)
+       return OBJC_THREAD_INTERACTIVE_PRIORITY;
+      else if (sys_priority >= 150)
+       return OBJC_THREAD_BACKGROUND_PRIORITY;
+      return OBJC_THREAD_LOW_PRIORITY;
     }
-    
-    return -1;                                  /* Couldn't get priority.   */
+
+  /* Couldn't get priority. */
+  return -1;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
-    thr_yield();                                /* Yield to equal thread.   */
+  thr_yield();
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  objc_mutex_lock(__objc_runtime_mutex);
-  __objc_runtime_threads_alive++;
-  objc_mutex_unlock(__objc_runtime_mutex);
-  
-  thr_exit(&__objc_thread_exit_status);         /* Terminate thread.        */
+  /* exit the thread */
+  thr_exit(&__objc_thread_exit_status);
+
+  /* Failed if we reached here */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  NULL which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
-    return (objc_thread_t)thr_self();
+  return (objc_thread_t)thr_self();
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
-    if (thr_setspecific(__objc_thread_data_key, value) == 0)
-        return 0;
+  if (thr_setspecific(__objc_thread_data_key, value) == 0)
+    return 0;
+  else
     return -1;
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
 {
-    void *      value = NULL;
-    
-    if (thr_getspecific(__objc_thread_data_key, &value) == 0)
-        return value;                           /* Return thread data.      */
-    
-    return NULL;
-}
+  void *value = NULL;
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if
- *  the allocation fails for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
-{
-    struct objc_mutex *mutex;
-    int         err = 0;
-    
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
-    
-    err = mutex_init(&mutex->lock, USYNC_THREAD, 0);
-    
-    if (err != 0) {                             /* System init failed?      */
-        objc_free(mutex);                       /* Yes, free local memory.  */
-        return NULL;                            /* Abort.                   */
-    }
-    mutex->owner = NULL;                        /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
+  if (thr_getspecific(__objc_thread_data_key, &value) == 0)
+    return value;
+
+  return NULL;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallotcate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_allocate(objc_mutex_t mutex)
 {
-    int         depth;                          /* # of locks on mutex.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
-    
-    mutex_destroy(&mutex->lock);                /* System deallocate.       */
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
+  if (mutex_init( (mutex_t *)(&(mutex->backend)), USYNC_THREAD, 0))
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+
+/* Deallocate a mutex. */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-
-    if (mutex_lock(&mutex->lock) != 0)          /* Did lock acquire fail?   */
-        return -1;                              /* Yes, abort.              */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  mutex_destroy((mutex_t *)(&(mutex->backend)));
+  return 0;
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Grab a lock on a mutex. */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_mutex_lock(objc_mutex_t mutex)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-    
-    if (mutex_trylock(&mutex->lock) != 0)       /* Did lock acquire fail?   */
-        return -1;                              /* Yes, abort.              */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return mutex->depth = 1;                    /* Increment depth to end.  */
+  if (mutex_lock((mutex_t *)(&(mutex->backend))) != 0)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Try to grab a lock on a mutex. */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_mutex_trylock(objc_mutex_t mutex)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = NULL;                        /* Set owner to "no thread".*/
-    
-    if (mutex_unlock(&mutex->lock) != 0)        /* Did lock release fail?   */
-        return -1;                              /* Yes, return error value. */
-    
-    return 0;                                   /* No, return success.      */
+  if (mutex_trylock((mutex_t *)(&(mutex->backend))) != 0)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Allocate a condition.  Return the condition pointer if successful or NULL
- * if the allocation failed for any reason.
- */
-objc_condition_t
-objc_condition_allocate(void)
+/* Unlock the mutex */
+int
+__objc_mutex_unlock(objc_mutex_t mutex)
 {
-    objc_condition_t condition;
-
-    if (!(condition = (objc_condition_t)objc_malloc(
-                        sizeof(struct objc_condition))))
-        return NULL;                            /* Abort if malloc failed.  */
+  if (mutex_unlock((mutex_t *)(&(mutex->backend))) != 0)
+    return -1;
+  else
+    return 0;
+}
 
-    cond_init(&(condition->condition), USYNC_THREAD, NULL);
+/* Backend condition mutex functions */
 
-    return condition;                           /* Return new condition     */
+/* Allocate a condition. */
+int
+__objc_condition_allocate(objc_condition_t condition)
+{
+  return cond_init((cond_t *)(&(condition->backend)), USYNC_THREAD, NULL);
 }
 
-/********
- *  Deallocate a condition. Note that this includes an implicit
- *  condition_broadcast to insure that waiting threads have the opportunity
- *  to wake.  It is legal to dealloc a condition only if no other
- *  thread is/will be using it. Here we do NOT check for other threads
- *  waiting but just wake them up.
- */
+/* Deallocate a condition. */
 int
-objc_condition_deallocate(objc_condition_t condition)
+__objc_condition_deallocate(objc_condition_t condition)
 {
-    cond_broadcast(&(condition->condition));    /* Wakeup waiting threads   */
-    cond_destroy(&(condition->condition));      /* Kill condition           */
-    objc_free(condition);                       /* Release struct memory    */
-    return 0;
+  return cond_destroy((cond_t *)(&(condition->backend)));
 }
 
-/********
- *  Wait on the condition unlocking the mutex until objc_condition_signal()
- *  or objc_condition_broadcast() are called for the same condition. The
- *  given mutex *must* have the depth set to 1 so that it can be unlocked
- *  here, so that someone else can lock it and signal/broadcast the condition.
- *  The mutex is used to lock access to the shared data that make up the
- *  "condition" predicate.
- */
+/* Wait on the condition */
 int
-objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
 {
-    objc_thread_t    thread_id;                /* Cache our thread id.     */
-
-    if (!mutex || !condition)                   /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Locked more than once ?  */
-        return -1;                              /* YES, return error        */
-                                                /* mutex will be unlocked   */
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = (objc_thread_t) -1;         /* Set owner to "no thread".*/
-
-    cond_wait(&(condition->condition),
-        &(mutex->lock));                        /* unlock, wait ..., lock   */
-
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    mutex->depth = 1;                           /* Must be here !           */
-
-    return 0;                                   /* Return success.          */
+  return cond_wait((cond_t *)(&(condition->backend)),
+                  (mutex_t *)(&(mutex->backend)));
 }
 
-/********
- *  Wake up all threads waiting on this condition. It is recommended that
- *  the called would lock the same mutex as the threads in objc_condition_wait
- *  before changing the "condition predicate" and make this call and unlock it
- *  right away after this call.
- */
+/* Wake up all threads waiting on this condition. */
 int
-objc_condition_broadcast(objc_condition_t condition)
+__objc_condition_broadcast(objc_condition_t condition)
 {
-    if (!condition)
-        return -1;
-    cond_broadcast(&(condition->condition));
-    return 0;
+  return cond_broadcast((cond_t *)(&(condition->backend)));
 }
 
-/********
- *  Wake up one thread waiting on this condition. It is recommended that
- *  the called would lock the same mutex as the threads in objc_condition_wait
- *  before changing the "condition predicate" and make this call and unlock it
- *  right away after this call.
- */
+/* Wake up one thread waiting on this condition. */
 int
-objc_condition_signal(objc_condition_t condition)
+__objc_condition_signal(objc_condition_t condition)
 {
-    if (!condition)
-        return -1;
-    cond_signal(&(condition->condition));
-    return 0;
+  return cond_signal((cond_t *)(&(condition->backend)));
 }
 
 /* End of File */
index 520a91d6ced70284c0fb5e5aca44dedda9e7fbff..159e3e37665f35f7b5e80e7cdd325df73cb8e7e6 100644 (file)
@@ -32,306 +32,241 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #include <windows.h>
 
-/********
- *  This structure represents a single mutual exclusion lock.  Lock semantics
- *  are detailed with the subsequent functions.  We use whatever lock is
- *  provided by the system.  We augment it with depth and current owner id
- *  fields to implement and re-entrant lock.
- */
-struct objc_mutex 
-{
-  volatile objc_thread_t       owner;          /* Id of thread that owns.  */
-  volatile int                  depth;          /* # of acquires.           */
-  HANDLE                        handle;         /* Win32 mutex HANDLE.      */
-};
-
-/*****************************************************************************
- *  Static variables.
- */
-static DWORD   __objc_data_tls = (DWORD)-1;    /* Win32 Thread Local Index.*/
-
-/********
- *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
- *  thread support is available.
- */
+/* Key structure for maintiain thread specific storage */
+static DWORD   __objc_data_tls = (DWORD)-1;
+
+/* Backend initialization functions */
+
+/* Initialize the threads subsystem. */
 int
 __objc_init_thread_system(void)
 {
-  DEBUG_PRINTF("__objc_init_thread_system\n");
-
+  /* Initialize the thread storage key */
   if ((__objc_data_tls = TlsAlloc()) != (DWORD)-1)
-    return 0;                                  /* Yes, return success.     */
-    
-  return -1;                                   /* Failed.                  */
+    return 0;
+  else
+    return -1;
 }
 
+/* Close the threads subsystem. */
 int
-__objc_fini_thread_system(void)
+__objc_close_thread_system(void)
 {
-  if (__objc_data_tls != (DWORD)-1) {
+  if (__objc_data_tls != (DWORD)-1)
     TlsFree(__objc_data_tls);
-    return 0;
-  }
-  return -1;
+  return 0;
 }
 
-/********
- *  Create a new thread of execution and return its id.  Return NULL if fails.
- *  The new thread starts in "func" with the given argument.
- */
+/* Backend thread functions */
+
+/* Create a new thread of execution. */
 objc_thread_t
-objc_thread_create(void (*func)(void *arg), void *arg)
+__objc_thread_detach(void (*func)(void *arg), void *arg)
 {
-  DWORD                thread_id = 0;                  /* Detached thread id.      */
-  HANDLE       win32_handle;                   /* Win32 thread handle.     */
+  DWORD        thread_id = 0;
+  HANDLE win32_handle;
 
-  objc_mutex_lock(__objc_runtime_mutex);
-  
-  if ((win32_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func,
-                                   arg, 0, &thread_id))) {
-      __objc_runtime_threads_alive++;
-  }
-  else
-      thread_id = 0;
-  
-  objc_mutex_unlock(__objc_runtime_mutex);
+  if (!(win32_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func,
+                                   arg, 0, &thread_id)))
+    thread_id = 0;
   
   return (objc_thread_t)thread_id;
 }
 
-/********
- *  Set the current thread's priority.
- */
+/* Set the current thread's priority. */
 int
-objc_thread_set_priority(int priority)
+__objc_thread_set_priority(int priority)
 {
-  int          sys_priority = 0;
-
-  switch (priority) {
-  case OBJC_THREAD_INTERACTIVE_PRIORITY:
-    sys_priority = THREAD_PRIORITY_NORMAL;
-    break;
-  default:
-  case OBJC_THREAD_BACKGROUND_PRIORITY:
-    sys_priority = THREAD_PRIORITY_BELOW_NORMAL;
-    break;
-  case OBJC_THREAD_LOW_PRIORITY:
-    sys_priority = THREAD_PRIORITY_LOWEST;
-    break;
-  }
+  int sys_priority = 0;
+
+  switch (priority)
+    {
+    case OBJC_THREAD_INTERACTIVE_PRIORITY:
+      sys_priority = THREAD_PRIORITY_NORMAL;
+      break;
+    default:
+    case OBJC_THREAD_BACKGROUND_PRIORITY:
+      sys_priority = THREAD_PRIORITY_BELOW_NORMAL;
+      break;
+    case OBJC_THREAD_LOW_PRIORITY:
+      sys_priority = THREAD_PRIORITY_LOWEST;
+      break;
+    }
+
+  /* Change priority */
   if (SetThreadPriority(GetCurrentThread(), sys_priority))
-    return 0;                                          /* Changed priority. End.   */
-    
-  return -1;                                   /* Failed.                  */
+    return 0;
+  else
+    return -1;
 }
 
-/********
- *  Return the current thread's priority.
- */
+/* Return the current thread's priority. */
 int
-objc_thread_get_priority(void)
+__objc_thread_get_priority(void)
 {
-  int          sys_priority;
+  int sys_priority;
 
   sys_priority = GetThreadPriority(GetCurrentThread());
   
-  switch (sys_priority) {
-  case THREAD_PRIORITY_HIGHEST:
-  case THREAD_PRIORITY_TIME_CRITICAL:
-  case THREAD_PRIORITY_ABOVE_NORMAL:
-  case THREAD_PRIORITY_NORMAL:
-    return OBJC_THREAD_INTERACTIVE_PRIORITY;
-
-  default:
-  case THREAD_PRIORITY_BELOW_NORMAL:
-    return OBJC_THREAD_BACKGROUND_PRIORITY;
+  switch (sys_priority)
+    {
+    case THREAD_PRIORITY_HIGHEST:
+    case THREAD_PRIORITY_TIME_CRITICAL:
+    case THREAD_PRIORITY_ABOVE_NORMAL:
+    case THREAD_PRIORITY_NORMAL:
+      return OBJC_THREAD_INTERACTIVE_PRIORITY;
+
+    default:
+    case THREAD_PRIORITY_BELOW_NORMAL:
+      return OBJC_THREAD_BACKGROUND_PRIORITY;
     
-  case THREAD_PRIORITY_IDLE:
-  case THREAD_PRIORITY_LOWEST:
-    return OBJC_THREAD_LOW_PRIORITY;
-  }
-  return -1;                                   /* Couldn't get priority.   */
+    case THREAD_PRIORITY_IDLE:
+    case THREAD_PRIORITY_LOWEST:
+      return OBJC_THREAD_LOW_PRIORITY;
+    }
+
+  /* Couldn't get priority. */
+  return -1;
 }
 
-/********
- *  Yield our process time to another thread.  Any BUSY waiting that is done
- *  by a thread should use this function to make sure that other threads can
- *  make progress even on a lazy uniprocessor system.
- */
+/* Yield our process time to another thread. */
 void
-objc_thread_yield(void)
+__objc_thread_yield(void)
 {
-  Sleep(0);                                    /* Yield to equal thread.   */
+  Sleep(0);
 }
 
-/********
- *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
- *  Actually, if it failed returns -1.
- */
+/* Terminate the current thread. */
 int
-objc_thread_exit(void)
+__objc_thread_exit(void)
 {
-  objc_mutex_lock(__objc_runtime_mutex);
-  __objc_runtime_threads_alive--;
-  objc_mutex_unlock(__objc_runtime_mutex);
-  
-  ExitThread(__objc_thread_exit_status);       /* Terminate thread.        */
+  /* exit the thread */
+  ExitThread(__objc_thread_exit_status);
+
+  /* Failed if we reached here */
   return -1;
 }
 
-/********
- *  Returns an integer value which uniquely describes a thread.  Must not be
- *  -1 which is reserved as a marker for "no thread".
- */
+/* Returns an integer value which uniquely describes a thread. */
 objc_thread_t
-objc_thread_id(void)
+__objc_thread_id(void)
 {
-  return (objc_thread_t)GetCurrentThreadId();  /* Return thread id.        */
+  return (objc_thread_t)GetCurrentThreadId();
 }
 
-/********
- *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
- *  if failed.
- */
+/* Sets the thread's local storage pointer. */
 int
-objc_thread_set_data(void *value)
+__objc_thread_set_data(void *value)
 {
   if (TlsSetValue(__objc_data_tls, value))
-    return 0;                                  /* Return thread data.      */
-  return -1;
+    return 0;
+  else
+    return -1;
 }
 
-/********
- *  Returns the thread's local storage pointer.  Returns NULL on failure.
- */
+/* Returns the thread's local storage pointer. */
 void *
-objc_thread_get_data(void)
+__objc_thread_get_data(void)
 {
   return TlsGetValue(__objc_data_tls);          /* Return thread data.      */
 }
 
-/********
- *  Allocate a mutex.  Return the mutex pointer if successful or NULL if
- *  the allocation fails for any reason.
- */
-objc_mutex_t
-objc_mutex_allocate(void)
+/* Backend mutex functions */
+
+/* Allocate a mutex. */
+int
+__objc_mutex_allocate(objc_mutex_t mutex)
+{
+  if ((mutex->backend = (void *)CreateMutex(NULL, 0, NULL)) == NULL)
+    return -1;
+  else
+    return 0;
+}
+
+/* Deallocate a mutex. */
+int
+__objc_mutex_deallocate(objc_mutex_t mutex)
 {
-    objc_mutex_t mutex;
-    int         err = 0;
+  CloseHandle((HANDLE)(mutex->backend));
+  return 0;
+}
 
-    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
-        return NULL;                            /* Abort if malloc failed.  */
+/* Grab a lock on a mutex. */
+int
+__objc_mutex_lock(objc_mutex_t mutex)
+{
+  int status;
 
-    if ((mutex->handle = CreateMutex(NULL, 0, NULL)) == NULL) {
-        objc_free(mutex);                       /* Failed, free memory.     */
-        return NULL;                            /* Abort.                   */
-    }
-    mutex->owner = NULL;                        /* No owner.                */
-    mutex->depth = 0;                           /* No locks.                */
-    return mutex;                               /* Return mutex handle.     */
+  status = WaitForSingleObject((HANDLE)(mutex->backend), INFINITE);
+  if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
- *  insure that no one else is using the lock.  It is legal to deallocate
- *  a lock if we have a lock on it, but illegal to deallotcate a lock held
- *  by anyone else.
- *  Returns the number of locks on the thread.  (1 for deallocate).
- */
+/* Try to grab a lock on a mutex. */
 int
-objc_mutex_deallocate(objc_mutex_t mutex)
+__objc_mutex_trylock(objc_mutex_t mutex)
 {
-    int         depth;                          /* # of locks on mutex.     */
+  int status;
 
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
+  status = WaitForSingleObject((HANDLE)(mutex->backend), 0);
+  if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
+    return -1;
+  else
+    return 0;
+}
 
-    CloseHandle(mutex->handle);                        /* Close Win32 handle.      */
-    
-    objc_free(mutex);                           /* Free memory.             */
-    return depth;                               /* Return last depth.       */
+/* Unlock the mutex */
+int
+__objc_mutex_unlock(objc_mutex_t mutex)
+{
+  if (ReleaseMutex((HANDLE)(mutex->backend)) == 0)
+    return -1;
+  else
+    return 0;
 }
 
-/********
- *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
- *  then we increment the lock count.  If another thread has a lock on the 
- *  mutex we block and wait for the thread to release the lock.
- *  Returns the lock count on the mutex held by this thread.
- */
+/* Backend condition mutex functions */
+
+/* Allocate a condition. */
 int
-objc_mutex_lock(objc_mutex_t mutex)
+__objc_condition_allocate(objc_condition_t condition)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-    int                 status;
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-
-    status = WaitForSingleObject(mutex->handle, INFINITE);
-    if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
-        return -1;                              /* Failed, abort.           */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
+  /* Unimplemented. */
+  return -1;
+}
 
-    return ++mutex->depth;                      /* Increment depth to end.  */
+/* Deallocate a condition. */
+int
+__objc_condition_deallocate(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
 }
 
-/********
- *  Try to grab a lock on a mutex.  If this thread already has a lock on
- *  this mutex then we increment the lock count and return it.  If another
- *  thread has a lock on the mutex returns -1.
- */
+/* Wait on the condition */
 int
-objc_mutex_trylock(objc_mutex_t mutex)
+__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-    DWORD               status;                 /* Return status from Win32.*/
-
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner == thread_id)              /* Already own lock?        */
-        return ++mutex->depth;                  /* Yes, increment depth.    */
-
-    status = WaitForSingleObject(mutex->handle, 0);
-    if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
-        return -1;                              /* Failed, abort.           */
-    
-    mutex->owner = thread_id;                   /* Mark thread as owner.    */
-    return ++mutex->depth;                      /* Increment depth to end.  */
+  /* Unimplemented. */
+  return -1;
 }
 
-/********
- *  Decrements the lock count on this mutex by one.  If the lock count reaches
- *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
- *  It is an error to attempt to unlock a mutex which this thread doesn't hold
- *  in which case return -1 and the mutex is unaffected.
- *  Will also return -1 if the mutex free fails.
- */
+/* Wake up all threads waiting on this condition. */
 int
-objc_mutex_unlock(objc_mutex_t mutex)
+__objc_condition_broadcast(objc_condition_t condition)
 {
-    objc_thread_t      thread_id;              /* Cache our thread id.     */
-    
-    if (!mutex)                                 /* Is argument bad?         */
-        return -1;                              /* Yes, abort.              */
-    thread_id = objc_thread_id();               /* Get this thread's id.    */
-    if (mutex->owner != thread_id)              /* Does some else own lock? */
-        return -1;                              /* Yes, abort.              */
-    if (mutex->depth > 1)                       /* Released last lock?      */
-        return --mutex->depth;                  /* No, Decrement depth, end.*/
-    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
-    mutex->owner = NULL;                        /* Set owner to "no thread".*/
-    
-    if (ReleaseMutex(mutex->handle) == 0)
-        return -1;                              /* Failed, abort.           */
-    
-    return 0;                                   /* No, return success.      */
+  /* Unimplemented. */
+  return -1;
+}
+
+/* Wake up one thread waiting on this condition. */
+int
+__objc_condition_signal(objc_condition_t condition)
+{
+  /* Unimplemented. */
+  return -1;
 }
 
 /* End of File */
index 2770b7de1abd35796078b8e257539f5ceb42158c..f1c957aaa15c79a784e7926483d32ce6d25790e6 100644 (file)
@@ -27,20 +27,15 @@ Boston, MA 02111-1307, USA.  */
 #include <stdlib.h>
 #include "runtime.h"
 
-/*************************************************************************
- *  Universal static variables:
- */
-int __objc_thread_exit_status = 0;      /* Global exit status.   */
+/* Global exit status. */
+int __objc_thread_exit_status = 0;
 
 /* Flag which lets us know if we ever became multi threaded */
 int __objc_is_multi_threaded = 0;
+
 /* The hook function called when the runtime becomes multi threaded */
 objc_thread_callback _objc_became_multi_threaded = NULL;
 
-/*****************************************************************************
- *  Universal Functionality
- */
-
 /*
   Use this to set the hook function that will be called when the 
   runtime initially becomes multi threaded.
@@ -60,94 +55,480 @@ objc_thread_callback objc_set_thread_callback(objc_thread_callback func)
   return temp;
 }
 
-/********
- *  First function called in a thread, starts everything else.
+/*
+  Private functions
+
+  These functions are utilized by the frontend, but they are not
+  considered part of the public interface.
+  */
+
+/*
+  First function called in a thread, starts everything else.
+
+  This function is passed to the backend by objc_thread_detach
+  as the starting function for a new thread.
  */
 struct __objc_thread_start_state
 {
-    SEL         selector;
-    id          object;
-    id          argument;
+  SEL selector;
+  id object;
+  id argument;
 };
 
 static volatile void
 __objc_thread_detach_function(struct __objc_thread_start_state *istate)
 {
-    if (istate) {                               /* Is state valid?          */
-        id      (*imp)(id,SEL,id);
-        SEL     selector = istate->selector;
-        id      object   = istate->object;
-        id      argument = istate->argument;
+  /* Valid state? */
+  if (istate) {
+    id (*imp)(id,SEL,id);
+    SEL selector = istate->selector;
+    id object   = istate->object;
+    id argument = istate->argument;
 
-        objc_free(istate);
+    /* Don't need anymore so free it */
+    objc_free(istate);
 
-       /* Clear out the thread local storage */
-       objc_thread_set_data(NULL);
+    /* Clear out the thread local storage */
+    objc_thread_set_data(NULL);
 
-       /* Check to see if we just became multi threaded */
-       if (!__objc_is_multi_threaded) {
-         __objc_is_multi_threaded = 1;
+    /* Check to see if we just became multi threaded */
+    if (!__objc_is_multi_threaded)
+      {
+       __objc_is_multi_threaded = 1;
 
-         /* Call the hook function */
-         if (_objc_became_multi_threaded != NULL)
-           (*_objc_became_multi_threaded)();
-       }
+       /* Call the hook function */
+       if (_objc_became_multi_threaded != NULL)
+         (*_objc_became_multi_threaded)();
+      }
 
-        if ((imp = (id(*)(id, SEL, id))objc_msg_lookup(object, selector))) {
-            (*imp)(object, selector, argument);
-        }
-        else
-            fprintf(stderr, "__objc_thread_start called with bad selector.\n");
-    }
-    else {
-        fprintf(stderr, "__objc_thread_start called with NULL state.\n");
-    }
-    objc_thread_exit();
+    /* Call the method */
+    if ((imp = (id(*)(id, SEL, id))objc_msg_lookup(object, selector)))
+       (*imp)(object, selector, argument);
+    else
+      objc_error(object, OBJC_ERR_UNIMPLEMENTED,
+                "objc_thread_detach called with bad selector.\n");
+  }
+  else
+    objc_error(nil, OBJC_ERR_BAD_STATE,
+              "objc_thread_detach called with NULL state.\n");
+
+  /* Exit the thread */
+  objc_thread_exit();
 }
 
-/********
- *  Detach a new thread of execution and return its id.  Returns NULL if fails.
- *  Thread is started by sending message with selector to object.  Message
- *  takes a single argument.
- */
+/*
+  Frontend functions
+
+  These functions constitute the public interface to the Objective-C thread
+  and mutex functionality.
+  */
+
+/* Frontend thread functions */
+
+/*
+  Detach a new thread of execution and return its id.  Returns NULL if fails.
+  Thread is started by sending message with selector to object.  Message
+  takes a single argument.
+  */
 objc_thread_t
 objc_thread_detach(SEL selector, id object, id argument)
 {
-  struct __objc_thread_start_state *istate;   /* Initialial thread state. */
-  objc_thread_t        thread_id = NULL;     /* Detached thread id.      */
+  struct __objc_thread_start_state *istate;
+  objc_thread_t        thread_id = NULL;
 
+  /* Allocate the state structure */
   if (!(istate = (struct __objc_thread_start_state *)
-       objc_malloc(sizeof(*istate))))     /* Can we allocate state?   */
-    return NULL;                              /* No, abort.               */
+       objc_malloc(sizeof(*istate))))
+    return NULL;
 
-  istate->selector = selector;                /* Initialize the thread's  */
-  istate->object = object;                    /*   state structure.       */
+  /* Initialize the state structure */
+  istate->selector = selector;
+  istate->object = object;
   istate->argument = argument;
 
-  if ((thread_id = objc_thread_create((void *)__objc_thread_detach_function,
-                                      istate)) == NULL) {
-    objc_free(istate);                       /* Release state if failed.   */
-    return thread_id;
-  }
+  /* lock access */
+  objc_mutex_lock(__objc_runtime_mutex);
+
+  /* Call the backend to spawn the thread */
+  if ((thread_id = __objc_thread_detach((void *)__objc_thread_detach_function,
+                                       istate)) == NULL)
+    {
+      /* failed! */
+      objc_mutex_unlock(__objc_runtime_mutex);
+      objc_free(istate);
+      return NULL;
+    }
+
+  /* Increment our thread counter */
+  __objc_runtime_threads_alive++;
+  objc_mutex_unlock(__objc_runtime_mutex);
 
   return thread_id;
 }
 
-#undef objc_mutex_lock()
-#undef objc_mutex_unlock()
+/* Set the current thread's priority. */
+int
+objc_thread_set_priority(int priority)
+{
+  /* Call the backend */
+  return __objc_thread_set_priority(priority);
+}
 
+/* Return the current thread's priority. */
 int
-objc_mutex_unlock_x(objc_mutex_t mutex, const char *f, int l)
+objc_thread_get_priority(void)
 {
-    printf("%16.16s#%4d < unlock", f, l);
-    return objc_mutex_unlock(mutex);
+  /* Call the backend */
+  return __objc_thread_get_priority();
 }
 
+/*
+  Yield our process time to another thread.  Any BUSY waiting that is done
+  by a thread should use this function to make sure that other threads can
+  make progress even on a lazy uniprocessor system.
+  */
+void
+objc_thread_yield(void)
+{
+  /* Call the backend */
+  __objc_thread_yield();
+}
+
+/*
+  Terminate the current tread.  Doesn't return.
+  Actually, if it failed returns -1.
+  */
 int
-objc_mutex_lock_x(objc_mutex_t mutex, const char *f, int l)
+objc_thread_exit(void)
 {
-    printf("%16.16s#%4d < lock", f, l);
-    return objc_mutex_lock(mutex);
+  /* Decrement our counter of the number of threads alive */
+  objc_mutex_lock(__objc_runtime_mutex);
+  __objc_runtime_threads_alive--;
+  objc_mutex_unlock(__objc_runtime_mutex);
+
+  /* Call the backend to terminate the thread */
+  return __objc_thread_exit();
+}
+
+/*
+  Returns an integer value which uniquely describes a thread.  Must not be
+  NULL which is reserved as a marker for "no thread".
+  */
+objc_thread_t
+objc_thread_id(void)
+{
+  /* Call the backend */
+  return __objc_thread_id();
+}
+
+/*
+  Sets the thread's local storage pointer. 
+  Returns 0 if successful or -1 if failed.
+  */
+int
+objc_thread_set_data(void *value)
+{
+  /* Call the backend */
+  return __objc_thread_set_data(value);
+}
+
+/*
+  Returns the thread's local storage pointer.  Returns NULL on failure.
+  */
+void *
+objc_thread_get_data(void)
+{
+  /* Call the backend */
+  return __objc_thread_get_data();
+}
+
+/* Frontend mutex functions */
+
+/*
+  Allocate a mutex.  Return the mutex pointer if successful or NULL if the
+  allocation failed for any reason.
+  */
+objc_mutex_t
+objc_mutex_allocate(void)
+{
+  objc_mutex_t mutex;
+
+  /* Allocate the mutex structure */
+  if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
+    return NULL;
+
+  /* Call backend to create the mutex */
+  if (__objc_mutex_allocate(mutex))
+    {
+      /* failed! */
+      objc_free(mutex);
+      return NULL;
+    }
+
+  /* Initialize mutex */
+  mutex->owner = NULL;
+  mutex->depth = 0;
+  return mutex;
+}
+
+/*
+  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
+  insure that no one else is using the lock.  It is legal to deallocate
+  a lock if we have a lock on it, but illegal to deallocate a lock held
+  by anyone else.
+  Returns the number of locks on the thread.  (1 for deallocate).
+  */
+int
+objc_mutex_deallocate(objc_mutex_t mutex)
+{
+  int depth;
+
+  /* Valid mutex? */
+  if (!mutex)
+    return -1;
+
+  /* Acquire lock on mutex */
+  depth = objc_mutex_lock(mutex);
+
+  /* Call backend to destroy mutex */
+  if (__objc_mutex_deallocate(mutex))
+    return -1;
+
+  /* Free the mutex structure */
+  objc_free(mutex);
+
+  /* Return last depth */
+  return depth;
+}
+
+/*
+  Grab a lock on a mutex.  If this thread already has a lock on this mutex
+  then we increment the lock count.  If another thread has a lock on the 
+  mutex we block and wait for the thread to release the lock.
+  Returns the lock count on the mutex held by this thread.
+  */
+int
+objc_mutex_lock(objc_mutex_t mutex)
+{
+  objc_thread_t thread_id;
+  int status;
+
+  /* Valid mutex? */
+  if (!mutex)
+    return -1;
+
+  /* If we already own the lock then increment depth */
+  thread_id = objc_thread_id();
+  if (mutex->owner == thread_id)
+    return ++mutex->depth;
+
+  /* Call the backend to lock the mutex */
+  status = __objc_mutex_lock(mutex);
+
+  /* Failed? */
+  if (status)
+    return status;
+
+  /* Successfully locked the thread */
+  mutex->owner = thread_id;
+  return mutex->depth = 1;
+}
+
+/*
+  Try to grab a lock on a mutex.  If this thread already has a lock on
+  this mutex then we increment the lock count and return it.  If another
+  thread has a lock on the mutex returns -1.
+  */
+int
+objc_mutex_trylock(objc_mutex_t mutex)
+{
+  objc_thread_t thread_id;
+  int status;
+
+  /* Valid mutex? */
+  if (!mutex)
+    return -1;
+
+  /* If we already own the lock then increment depth */ 
+  thread_id = objc_thread_id();
+  if (mutex->owner == thread_id)
+    return ++mutex->depth;
+    
+  /* Call the backend to try to lock the mutex */
+  status = __objc_mutex_trylock(mutex);
+
+  /* Failed? */
+  if (status)
+    return status;
+
+  /* Successfully locked the thread */
+  mutex->owner = thread_id;
+  return mutex->depth = 1;
+}
+
+/* 
+  Unlocks the mutex by one level.
+  Decrements the lock count on this mutex by one.
+  If the lock count reaches zero, release the lock on the mutex.
+  Returns the lock count on the mutex.
+  It is an error to attempt to unlock a mutex which this thread 
+  doesn't hold in which case return -1 and the mutex is unaffected.
+  */
+int
+objc_mutex_unlock(objc_mutex_t mutex)
+{
+  objc_thread_t thread_id;
+  int status;
+
+  /* Valid mutex? */
+  if (!mutex)
+    return -1;
+
+  /* If another thread owns the lock then abort */
+  thread_id = objc_thread_id();
+  if (mutex->owner != thread_id)
+    return -1;
+
+  /* Decrement depth and return */
+  if (mutex->depth > 1)
+    return --mutex->depth;
+
+  /* Depth down to zero so we are no longer the owner */
+  mutex->depth = 0;
+  mutex->owner = NULL;
+
+  /* Have the backend unlock the mutex */
+  status = __objc_mutex_unlock(mutex);
+
+  /* Failed? */
+  if (status)
+    return status;
+
+  return 0;
+}
+
+/* Frontend condition mutex functions */
+
+/*
+  Allocate a condition.  Return the condition pointer if successful or NULL
+  if the allocation failed for any reason.
+  */
+objc_condition_t 
+objc_condition_allocate(void)
+{
+  objc_condition_t condition;
+    
+  /* Allocate the condition mutex structure */
+  if (!(condition = 
+       (objc_condition_t)objc_malloc(sizeof(struct objc_condition))))
+    return NULL;
+
+  /* Call the backend to create the condition mutex */
+  if (__objc_condition_allocate(condition))
+    {
+      /* failed! */
+      objc_free(condition);
+      return NULL;
+    }
+
+  /* Success! */
+  return condition;
+}
+
+/*
+  Deallocate a condition. Note that this includes an implicit 
+  condition_broadcast to insure that waiting threads have the opportunity
+  to wake.  It is legal to dealloc a condition only if no other
+  thread is/will be using it. Here we do NOT check for other threads
+  waiting but just wake them up.
+  */
+int
+objc_condition_deallocate(objc_condition_t condition)
+{
+  /* Broadcast the condition */
+  if (objc_condition_broadcast(condition))
+    return -1;
+
+  /* Call the backend to destroy */
+  if (__objc_condition_deallocate(condition))
+    return -1;
+
+  /* Free the condition mutex structure */
+  objc_free(condition);
+
+  return 0;
+}
+
+/*
+  Wait on the condition unlocking the mutex until objc_condition_signal()
+  or objc_condition_broadcast() are called for the same condition. The
+  given mutex *must* have the depth set to 1 so that it can be unlocked
+  here, so that someone else can lock it and signal/broadcast the condition.
+  The mutex is used to lock access to the shared data that make up the
+  "condition" predicate.
+  */
+int
+objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+{
+  objc_thread_t thread_id;
+
+  /* Valid arguments? */
+  if (!mutex || !condition)
+    return -1;
+
+  /* Make sure we are owner of mutex */
+  thread_id = objc_thread_id();
+  if (mutex->owner != thread_id)
+    return -1;
+
+  /* Cannot be locked more than once */
+  if (mutex->depth > 1)
+    return -1;
+
+  /* Virtually unlock the mutex */
+  mutex->depth = 0;
+  mutex->owner = (objc_thread_t)NULL;
+
+  /* Call the backend to wait */
+  __objc_condition_wait(condition, mutex);
+
+  /* Make ourselves owner of the mutex */
+  mutex->owner = thread_id;
+  mutex->depth = 1;
+
+  return 0;
+}
+
+/*
+  Wake up all threads waiting on this condition. It is recommended that 
+  the called would lock the same mutex as the threads in objc_condition_wait
+  before changing the "condition predicate" and make this call and unlock it
+  right away after this call.
+  */
+int
+objc_condition_broadcast(objc_condition_t condition)
+{
+  /* Valid condition mutex? */
+  if (!condition)
+    return -1;
+
+  return __objc_condition_broadcast(condition);
+}
+
+/*
+  Wake up one thread waiting on this condition. It is recommended that 
+  the called would lock the same mutex as the threads in objc_condition_wait
+  before changing the "condition predicate" and make this call and unlock it
+  right away after this call.
+  */
+int
+objc_condition_signal(objc_condition_t condition)
+{
+  /* Valid condition mutex? */
+  if (!condition)
+    return -1;
+
+  return __objc_condition_signal(condition);
 }
 
 /* End of File */