diff options
author | Richard Kenner <kenner@gcc.gnu.org> | 1997-06-25 16:25:24 -0400 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 1997-06-25 16:25:24 -0400 |
commit | 2024f9e4dc4746fc1f87a82ccd998d0c24f75d8c (patch) | |
tree | 938bbdc79bc8962b1b6cd7bb530731700295bc79 /gcc/objc | |
parent | f15e9e7ef22cffbdff2f1792dfc0d539fdd26a01 (diff) | |
download | gcc-2024f9e4dc4746fc1f87a82ccd998d0c24f75d8c.zip gcc-2024f9e4dc4746fc1f87a82ccd998d0c24f75d8c.tar.gz gcc-2024f9e4dc4746fc1f87a82ccd998d0c24f75d8c.tar.bz2 |
Completely rework according to new interface.
From-SVN: r14310
Diffstat (limited to 'gcc/objc')
-rw-r--r-- | gcc/objc/thr-decosf1.c | 385 | ||||
-rw-r--r-- | gcc/objc/thr-irix.c | 353 | ||||
-rw-r--r-- | gcc/objc/thr-mach.c | 492 | ||||
-rw-r--r-- | gcc/objc/thr-os2.c | 306 | ||||
-rw-r--r-- | gcc/objc/thr-posix.c | 340 | ||||
-rw-r--r-- | gcc/objc/thr-pthreads.c | 354 | ||||
-rw-r--r-- | gcc/objc/thr-single.c | 284 | ||||
-rw-r--r-- | gcc/objc/thr-solaris.c | 428 | ||||
-rw-r--r-- | gcc/objc/thr-win32.c | 383 | ||||
-rw-r--r-- | gcc/objc/thr.c | 505 |
10 files changed, 1632 insertions, 2198 deletions
diff --git a/gcc/objc/thr-decosf1.c b/gcc/objc/thr-decosf1.c index fa432aa..0c611b8 100644 --- a/gcc/objc/thr-decosf1.c +++ b/gcc/objc/thr-decosf1.c @@ -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 */ diff --git a/gcc/objc/thr-irix.c b/gcc/objc/thr-irix.c index 6ea883e..4203254 100644 --- a/gcc/objc/thr-irix.c +++ b/gcc/objc/thr-irix.c @@ -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 */ diff --git a/gcc/objc/thr-mach.c b/gcc/objc/thr-mach.c index 1f43fc5..6f54ada 100644 --- a/gcc/objc/thr-mach.c +++ b/gcc/objc/thr-mach.c @@ -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 */ diff --git a/gcc/objc/thr-os2.c b/gcc/objc/thr-os2.c index 422d53e..d546060 100644 --- a/gcc/objc/thr-os2.c +++ b/gcc/objc/thr-os2.c @@ -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 */ diff --git a/gcc/objc/thr-posix.c b/gcc/objc/thr-posix.c index 987f8a8..1b9a9e5 100644 --- a/gcc/objc/thr-posix.c +++ b/gcc/objc/thr-posix.c @@ -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 */ diff --git a/gcc/objc/thr-pthreads.c b/gcc/objc/thr-pthreads.c index 3e73fe0..4c4c245 100644 --- a/gcc/objc/thr-pthreads.c +++ b/gcc/objc/thr-pthreads.c @@ -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 */ diff --git a/gcc/objc/thr-single.c b/gcc/objc/thr-single.c index 45b7b73..b196677 100644 --- a/gcc/objc/thr-single.c +++ b/gcc/objc/thr-single.c @@ -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 */ diff --git a/gcc/objc/thr-solaris.c b/gcc/objc/thr-solaris.c index f1084bc..0b5227a 100644 --- a/gcc/objc/thr-solaris.c +++ b/gcc/objc/thr-solaris.c @@ -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 */ diff --git a/gcc/objc/thr-win32.c b/gcc/objc/thr-win32.c index 520a91d..159e3e3 100644 --- a/gcc/objc/thr-win32.c +++ b/gcc/objc/thr-win32.c @@ -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 */ diff --git a/gcc/objc/thr.c b/gcc/objc/thr.c index 2770b7d..f1c957a 100644 --- a/gcc/objc/thr.c +++ b/gcc/objc/thr.c @@ -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 */ |