aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1996-05-17 08:28:54 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1996-05-17 08:28:54 -0400
commitfc94a55b9221b13ebe9ac1c01a096d18c5d92594 (patch)
tree3fe8f6c2cde777ce58d62f3fd96a198b014b03b0 /gcc
parentb8abf72abbb7370d88a16fb7e2600f386fb41985 (diff)
downloadgcc-fc94a55b9221b13ebe9ac1c01a096d18c5d92594.zip
gcc-fc94a55b9221b13ebe9ac1c01a096d18c5d92594.tar.gz
gcc-fc94a55b9221b13ebe9ac1c01a096d18c5d92594.tar.bz2
Initial revision
From-SVN: r11985
Diffstat (limited to 'gcc')
-rw-r--r--gcc/objc/thr-mach.c359
-rw-r--r--gcc/objc/thr-os2.c341
-rw-r--r--gcc/objc/thr-posix.c321
3 files changed, 1021 insertions, 0 deletions
diff --git a/gcc/objc/thr-mach.c b/gcc/objc/thr-mach.c
new file mode 100644
index 0000000..22743d2
--- /dev/null
+++ b/gcc/objc/thr-mach.c
@@ -0,0 +1,359 @@
+/* GNU Objective C Runtime Thread Implementation
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+Author: Galen C. Hunt (gchunt@cs.rochester.edu)
+Modified for Mach threads by: Bill Bumgarner <bbum@friday.com>
+
+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 <mach/mach.h>
+#include <mach/cthreads.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. */
+ struct mutex lock; /* cthread 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) {
+ 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;
+
+ threadP = cthread_thread(t); /* get thread underlying */
+
+ error=thread_info(threadP, THREAD_SCHED_INFO,
+ (thread_info_t)&info, &info_count);
+
+ if (error != KERN_SUCCESS)
+ return -1;
+
+ if (base != NULL)
+ *base = info.base_priority;
+
+ return info.max_priority;
+}
+
+/********
+ * Initialize the threads subsystem. Returns 0 if successful, or -1 if no
+ * thread support is available.
+ */
+int
+__objc_init_thread_system(void)
+{
+ DEBUG_PRINTF("__objc_init_thread_system\n");
+ return 0; /* Succeeded. */
+}
+
+
+int
+__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.
+ */
+_objc_thread_t
+objc_thread_create(void (*func)(void *arg), void *arg)
+{
+ _objc_thread_t thread_id = NULL; /* Detached thread id. */
+ cthread_t new_thread_handle; /* cthread handle. */
+
+ objc_mutex_lock(__objc_runtime_mutex);
+
+ /* create thread */
+ new_thread_handle = cthread_fork((cthread_fn_t)func, arg);
+
+ if(new_thread_handle) {
+ thread_id = *(_objc_thread_t *)&new_thread_handle; /* this is not terribly portable */
+ cthread_detach(new_thread_handle); /* fully detach thread */
+ __objc_runtime_threads_alive++; /* increment thread count */
+ }
+
+ objc_mutex_unlock(__objc_runtime_mutex);
+ return thread_id;
+}
+
+/********
+ * Set the current thread's priority.
+ */
+int
+objc_thread_set_priority(int priority)
+{
+ _objc_thread_t *t = objc_thread_id();
+ cthread_t cT = (cthread_t) t; /* see objc_thread_id() */
+ int maxPriority = __mach_get_max_thread_priority(cT, NULL);
+ int sys_priority = 0;
+
+ if (maxPriority == -1)
+ return -1;
+
+ switch (priority) {
+ case OBJC_THREAD_INTERACTIVE_PRIORITY:
+ sys_priority = maxPriority;
+ break;
+ case OBJC_THREAD_BACKGROUND_PRIORITY:
+ sys_priority = (maxPriority * 2) / 3;
+ break;
+ case OBJC_THREAD_LOW_PRIORITY:
+ sys_priority = maxPriority / 3;
+ break;
+ default:
+ 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. */
+}
+
+/********
+ * Return the current thread's priority [well, whatever it is closest to].
+ */
+int
+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 */
+}
+
+/********
+ * 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)
+{
+ cthread_yield(); /* Yield to equal thread. */
+}
+
+/********
+ * 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);
+
+ cthread_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)
+{
+ 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.
+ */
+
+int
+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.
+ */
+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)
+{
+ _objc_mutex_t mutex;
+ int err = 0;
+
+ if (!(mutex = (_objc_mutex_t)__objc_xmalloc(sizeof(struct _objc_mutex))))
+ return NULL; /* Abort if malloc failed. */
+
+ err = mutex_init(&(mutex->lock));
+
+ if (err != 0) { /* System init failed? */
+ 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. */
+}
+
+/********
+ * 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. */
+
+ mutex_unlock(&(mutex->lock)); /* Must unlock system mutex.*/
+ mutex_clear(&(mutex->lock)); /* Free system 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. */
+
+ 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. */
+}
+
+/********
+ * 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. */
+
+ 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. */
+}
+
+/********
+ * 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 = (_objc_thread_t) -1; /* Set owner to "no thread".*/
+
+ mutex_unlock(&(mutex->lock)); /* unlock cthread mutex. */
+
+ return 0; /* No, return success. */
+}
diff --git a/gcc/objc/thr-os2.c b/gcc/objc/thr-os2.c
new file mode 100644
index 0000000..0db006b
--- /dev/null
+++ b/gcc/objc/thr-os2.c
@@ -0,0 +1,341 @@
+/* GNU Objective C Runtime Thread Interface - OS/2 emx Implementation
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+Author: Thomas Baier (baier@ci.tuwien.ac.at)
+
+This file is included into thread.c
+
+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. */
+
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSPROCESS
+
+/*
+ * conflicts with objc.h: SEL, BOOL, id
+ * solution: prefixing those with _OS2_ before including <os2.h>
+ */
+#define SEL _OS2_SEL
+#define BOOL _OS2_BOOL
+#define id _OS2_id
+#include <os2.h>
+#undef id
+#undef SEL
+#undef BOOL
+
+#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. */
+};
+
+/*****************************************************************************
+ * Static variables.
+ */
+/* none needed for OS/2 */
+
+/********
+ * Initialize the threads subsystem. Returns 0 if successful, or -1 if no
+ * thread support is available.
+ */
+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. */
+}
+
+int
+__objc_fini_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.
+ */
+_objc_thread_t
+objc_thread_create(void (*func)(void *arg), void *arg)
+{
+ int thread_id = 0; /* id of the newly created thread */
+
+ 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.
+ */
+int
+objc_thread_set_priority(int priority)
+{
+ ULONG sys_class = 0;
+ ULONG sys_priority = 0;
+
+ /* OBJC_THREAD_INTERACTIVE_PRIORITY -> PRTYC_FOREGROUNDSERVER
+ * OBJC_THREAD_BACKGROUND_PRIORITY -> PRTYC_REGULSR
+ * OBJC_THREAD_LOW_PRIORITY -> PRTYC_IDLETIME */
+
+ switch (priority) {
+ case OBJC_THREAD_INTERACTIVE_PRIORITY:
+ sys_class = PRTYC_REGULAR;
+ sys_priority = 10;
+ break;
+ default:
+ case OBJC_THREAD_BACKGROUND_PRIORITY:
+ sys_class = PRTYC_IDLETIME;
+ sys_priority = 25;
+ break;
+ case OBJC_THREAD_LOW_PRIORITY:
+ sys_class = PRTYC_IDLETIME;
+ sys_priority = 0;
+ break;
+ }
+ if (!DosSetPriority (PRTYS_THREAD,sys_class,sys_priority,*_threadid))
+ return 0; /* Changed priority. End. */
+
+ return -1; /* Failed. */
+}
+
+/********
+ * Return the current thread's priority.
+ */
+int
+objc_thread_get_priority(void)
+{
+ PTIB ptib;
+ PPIB ppib;
+
+ DosGetInfoBlocks (&ptib,&ppib); /* get information about current thread */
+
+ 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. */
+}
+
+/********
+ * 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)
+{
+ DosSleep (0); /* Yield to equal thread. */
+}
+
+/********
+ * 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);
+
+ _endthread (); /* terminate the thread, NEVER use DosExit () */
+
+ return -1;
+}
+
+/********
+ * Returns an integer value which uniquely describes a thread. Must not be
+ * -1 which is reserved as a marker for "no thread".
+ */
+_objc_thread_t
+objc_thread_id(void)
+{
+ return (_objc_thread_t) *_threadid; /* Return thread id. */
+}
+
+/********
+ * Sets the thread's local storage pointer. Returns 0 if successful or -1
+ * if failed.
+ */
+int
+objc_thread_set_data(void *value)
+{
+ *_threadstore () = value;
+
+ return 0;
+}
+
+/********
+ * Returns the thread's local storage pointer. Returns NULL on failure.
+ */
+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_xmalloc(sizeof(struct _objc_mutex))))
+ return NULL; /* Abort if malloc failed. */
+
+ if (DosCreateMutexSem (NULL,&(mutex->handle),0L,0) > 0) {
+ 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 deallotcate 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. */
+
+ DosCloseMutexSem (mutex->handle);
+
+ 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. */
+
+ if (DosRequestMutexSem (mutex->handle,-1L) != 0)
+ return -1;
+
+ mutex->owner = thread_id; /* Mark thread as owner. */
+
+ return ++mutex->depth; /* 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. */
+
+ if (DosRequestMutexSem (mutex->handle,0L) != 0)
+ return -1;
+
+ mutex->owner = thread_id; /* Mark thread as owner. */
+ return ++mutex->depth; /* 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".*/
+
+ if (DosReleaseMutexSem(mutex->handle) != 0)
+ return -1; /* Failed, abort. */
+
+ return 0; /* No, return success. */
+}
diff --git a/gcc/objc/thr-posix.c b/gcc/objc/thr-posix.c
new file mode 100644
index 0000000..fd9be1b
--- /dev/null
+++ b/gcc/objc/thr-posix.c
@@ -0,0 +1,321 @@
+/* GNU Objective C Runtime Thread Interface for POSIX compliant threads
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+Author: Galen C. Hunt (gchunt@cs.rochester.edu)
+Modified for Linux & Pthreads: Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
+
+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 <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.*/
+
+
+/********
+ * Initialize the threads subsystem. Returns 0 if successful, or -1 if no
+ * thread support is available.
+ */
+int
+__objc_init_thread_system(void)
+{
+ if (pthread_key_create(&__objc_thread_data_key, NULL) == 0)
+ return 0; /* Yes, return success. */
+
+ return -1; /* Failed. */
+}
+
+int
+__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.
+ */
+_objc_thread_t
+objc_thread_create(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;
+}
+
+/********
+ * Set the current thread's priority.
+ */
+int
+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. */
+}
+
+/********
+ * Return the current thread's priority.
+ */
+int
+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. */
+}
+
+/********
+ * 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(); /* Yield to equal thread. */
+}
+
+/********
+ * 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
+ * -1 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)
+{
+ if (pthread_setspecific(__objc_thread_data_key, (void *)value) == 0)
+ return 0; /* Return thread data. */
+ return -1;
+}
+
+/********
+ * Returns the thread's local storage pointer. Returns NULL on failure.
+ */
+void *
+objc_thread_get_data(void)
+{
+ return pthread_getspecific(__objc_thread_data_key);
+}
+
+/********
+ * 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_xmalloc(sizeof(struct _objc_mutex))))
+ return NULL; /* Abort if malloc failed. */
+
+ err = pthread_mutex_init(&mutex->lock, NULL);
+
+ if (err != 0) { /* System init failed? */
+ free(mutex); /* Yes, free local memory. */
+ return NULL; /* Abort. */
+ }
+ 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 deallotcate 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. */
+
+ pthread_mutex_unlock(&mutex->lock); /* Must unlock system mutex.*/
+ pthread_mutex_destroy(&mutex->lock); /* Free system 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. */
+
+ 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. */
+}
+
+/********
+ * 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. */
+
+ 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. */
+}
+
+/********
+ * 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".*/
+
+ if (pthread_mutex_unlock(&mutex->lock) != 0) /* Unlock system mutex. */
+ return -1; /* Failed, abort. */
+
+ return 0; /* No, return success. */
+}