From: Richard Kenner Date: Fri, 7 Jun 1996 23:22:01 +0000 (-0400) Subject: Initial revision X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2361ec2a842b6e7048a9e0498bb56795c063142a;p=gcc.git Initial revision From-SVN: r12220 --- diff --git a/gcc/objc/thr-pthreads.c b/gcc/objc/thr-pthreads.c new file mode 100644 index 00000000000..27ecbb63690 --- /dev/null +++ b/gcc/objc/thr-pthreads.c @@ -0,0 +1,313 @@ +/* GNU Objective C Runtime Thread Implementation for PCThreads under Linux. + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Scott Christley + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation; either version 2, or (at your option) any later version. + +GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files compiled with + GCC to produce an executable, this does not cause the resulting executable + to be covered by the GNU General Public License. This exception does not + however invalidate any other reasons why the executable file might be + covered by the GNU General Public License. */ + +#include +#include +#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 */ +}; + +/******** + * Initialize the threads subsystem. Returns 0 if successful, or -1 if no + * thread support is available. + */ +int +__objc_init_thread_system(void) +{ + /* Initialize the thread storage key */ + return pthread_key_create(&_objc_thread_storage, NULL); +} + +/******** + * Finalize the threads subsystem. Returns 0 if successful, or -1 if not + */ +int +__objc_fini_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. + */ +_objc_thread_t +objc_thread_create(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. + */ +int +objc_thread_set_priority(int priority) +{ + /* Not implemented yet */ + return -1; /* Failed. */ +} + +/******** + * Return the current thread's priority. + */ +int +objc_thread_get_priority(void) +{ + /* Not implemented yet */ + return OBJC_THREAD_INTERACTIVE_PRIORITY; /* Highest 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) +{ + pthread_yield(NULL); +} + +/******** + * Terminate the current tread. Doesn't return anything. Doesn't return. + * Actually, if it failed returns -1. + */ +int +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. */ + return -1; +} + +/******** + * 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) +{ + pthread_t self = pthread_self(); + + return *(_objc_thread_t *)&self; /* Return thread handle. */ +} + +/******** + * Sets the thread's local storage pointer. Returns 0 if successful or -1 + * if failed. + */ +int +objc_thread_set_data(void *value) +{ + return pthread_setspecific(_objc_thread_storage, value); +} + +/******** + * Returns the thread's local storage pointer. Returns NULL on failure. + */ +void * +objc_thread_get_data(void) +{ + 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 failed for any reason. + */ +_objc_mutex_t +objc_mutex_allocate(void) +{ + _objc_mutex_t mutex; + + if (!(mutex = (_objc_mutex_t)__objc_xmalloc(sizeof(struct _objc_mutex)))) + return NULL; /* Abort if malloc failed. */ + + /* Create PCThread mutex */ + if ( pthread_mutex_init(&(mutex->mutex), NULL) ) + { + /* Failed */ + free(mutex); + return NULL; + } + + 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. */ + + /* Destroy PCThread mutex */ + pthread_mutex_destroy(&(mutex->mutex)); + + 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. */ + 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. */ +} + +/******** + * 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. */ + 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. */ +} + +/******** + * 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. */ + 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. */ +} + +/* End of File */