diff options
Diffstat (limited to 'contrib/libobjc/thr.c')
-rw-r--r-- | contrib/libobjc/thr.c | 534 |
1 files changed, 0 insertions, 534 deletions
diff --git a/contrib/libobjc/thr.c b/contrib/libobjc/thr.c deleted file mode 100644 index f1c957aaa15c7..0000000000000 --- a/contrib/libobjc/thr.c +++ /dev/null @@ -1,534 +0,0 @@ -/* GNU Objective C Runtime Thread Interface - Copyright (C) 1996, 1997 Free Software Foundation, Inc. - Contributed by Galen C. Hunt (gchunt@cs.rochester.edu) - -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 <stdlib.h> -#include "runtime.h" - -/* 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; - -/* - Use this to set the hook function that will be called when the - runtime initially becomes multi threaded. - The hook function is only called once, meaning only when the - 2nd thread is spawned, not for each and every thread. - - It returns the previous hook function or NULL if there is none. - - A program outside of the runtime could set this to some function so - it can be informed; for example, the GNUstep Base Library sets it - so it can implement the NSBecomingMultiThreaded notification. - */ -objc_thread_callback objc_set_thread_callback(objc_thread_callback func) -{ - objc_thread_callback temp = _objc_became_multi_threaded; - _objc_became_multi_threaded = func; - return temp; -} - -/* - 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; -}; - -static volatile void -__objc_thread_detach_function(struct __objc_thread_start_state *istate) -{ - /* Valid state? */ - if (istate) { - id (*imp)(id,SEL,id); - SEL selector = istate->selector; - id object = istate->object; - id argument = istate->argument; - - /* Don't need anymore so free it */ - objc_free(istate); - - /* 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; - - /* Call the hook function */ - if (_objc_became_multi_threaded != NULL) - (*_objc_became_multi_threaded)(); - } - - /* 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(); -} - -/* - 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; - objc_thread_t thread_id = NULL; - - /* Allocate the state structure */ - if (!(istate = (struct __objc_thread_start_state *) - objc_malloc(sizeof(*istate)))) - return NULL; - - /* Initialize the state structure */ - istate->selector = selector; - istate->object = object; - istate->argument = argument; - - /* 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; -} - -/* 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_thread_get_priority(void) -{ - /* 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_thread_exit(void) -{ - /* 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 */ |