From a8a3a4846f65003e651426f2c847e0ce25570da5 Mon Sep 17 00:00:00 2001 From: mccallum Date: Mon, 2 Sep 1996 15:55:52 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1679 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 4 +- objc.patch | 4040 ---------------------------------------------------- 2 files changed, 2 insertions(+), 4042 deletions(-) delete mode 100644 objc.patch diff --git a/ChangeLog b/ChangeLog index fbb826a6c..295887bb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ Mon Sep 2 10:00:05 1996 Andrew McCallum + * Version (SUBMINOR_VERSION): Version 0.2.7. + * src/NSString.m ([NSString -substringFromRange:]): Fix bug in references to string length. @@ -8,8 +10,6 @@ Mon Sep 2 10:00:05 1996 Andrew McCallum * src/NSCharacterSet.m ([NSCharacterSet +_bitmapForSet:number:]): Add an abort() after raising the exception, to avoid gcc warning. - * Version (SUBMINOR_VERSION): Version 0.2.7. - * Makefile.in (clean): Fix dependancies so we actually clean-top, not mostlyclean-top. (distclean): Analogously. diff --git a/objc.patch b/objc.patch deleted file mode 100644 index d203f113d..000000000 --- a/objc.patch +++ /dev/null @@ -1,4040 +0,0 @@ -diff -rc2P objc/Makefile objc-threaded/Makefile -*** objc/Makefile Sat Jan 20 21:09:37 1996 ---- objc-threaded/Makefile Fri Jan 26 14:39:17 1996 -*************** -*** 57,61 **** - - OBJC_O = hash.o sarray.o class.o sendmsg.o init.o archive.o encoding.o \ -! selector.o objects.o misc.o NXConstStr.o Object.o Protocol.o - - libobjc.a: $(OBJC_O) ---- 57,61 ---- - - OBJC_O = hash.o sarray.o class.o sendmsg.o init.o archive.o encoding.o \ -! selector.o objects.o misc.o NXConstStr.o Object.o Protocol.o thread.o - - libobjc.a: $(OBJC_O) -*************** -*** 64,70 **** - # ranlib is run in the parent directory's makefile. - -! OBJC_H = hash.h list.h sarray.h objc.h \ - objc-api.h \ -! NXConstStr.h Object.h Protocol.h encoding.h typedstream.h - - # copy objc headers to installation include directory ---- 64,70 ---- - # ranlib is run in the parent directory's makefile. - -! OBJC_H = hash.h objc-list.h sarray.h objc.h \ - objc-api.h \ -! NXConstStr.h Object.h Protocol.h encoding.h typedstream.h thread.h - - # copy objc headers to installation include directory -*************** -*** 99,100 **** ---- 99,102 ---- - Object.o: Object.m - Protocol.o: Protocol.m -+ thread.o: thread.c thread-solaris.c thread-irix.c thread-win32.c thread-single.c -+ -diff -rc2P objc/README.threads objc-threaded/README.threads -*** objc/README.threads Wed Dec 31 19:00:00 1969 ---- objc-threaded/README.threads Sun Jan 21 21:28:14 1996 -*************** -*** 0 **** ---- 1,52 ---- -+ ============================================================================== -+ README - Wed Nov 29 15:16:24 EST 1995 -+ ------------------------------------------------------------------------------ -+ -+ Limited documentation is available in the THREADS file. -+ -+ A simple multiple threaded test program is available in thread-test/. -+ -+ This version has been tested on Sun Solaris, SGI Irix, and Windows NT. -+ It should also work on any single threaded system. -+ -+ Thanks go to the following people for help test and debug the library: -+ -+ Scott Christley, scottc@ocbi.com -+ Andrew McCallum, mccallum@cs.rochester.edu -+ -+ galen -+ gchunt@cs.rochester.edu -+ -+ Any questions, bug reports, etc should be directed to: -+ -+ Scott Christley, scottc@ocbi.com -+ -+ Please do not bug Galen with email as he no longer supports the code. -+ -+ ============================================================================== -+ Changes from prior releases (in revered chronological order): -+ ------------------------------------------------------------------------------ -+ -+ * Fixed bug in copy part of sarray_realloc. I had an < which should -+ have been <=. (Bug report from Scott). -+ -+ ------------------------------------------------------------------------------ -+ -+ * Support for DEC OSF/1 is definitely broken. My programs always -+ seg-fault when I link with libpthreads.a. -+ -+ * Thread id's are no longer int's, but are instead of type -+ _objc_thread_t which is typedef'ed from a void *. An invalid thread -+ id is denoted by NULL and not -1 as before. -+ -+ ------------------------------------------------------------------------------ -+ -+ * Renamed thread-winnt.c to thread-win32.c to better reflect support -+ for the API on both Windows NT and Windows 95 platforms. -+ (Who knows, maybe even Win32s :-). -+ -+ * Fixed bugs in Win32 support as per report from Scott Christley. -+ -+ * Fixed bug in sarray_get as per report from Scott Christley. -+ -+ -diff -rc2P objc/THREADS objc-threaded/THREADS -*** objc/THREADS Wed Dec 31 19:00:00 1969 ---- objc-threaded/THREADS Sun Jan 21 21:34:30 1996 -*************** -*** 0 **** ---- 1,206 ---- -+ This file describes in little detail the modifications to the -+ Objective-C runtime needed to make it thread safe. -+ -+ First off, kudos to Galen Hunt who is the author of this great work. -+ -+ If you have an comments or just want to know where to -+ send me money to express your undying graditude for threading the -+ Objective-C runtime you can reach Galen at: -+ -+ gchunt@cs.rochester.edu -+ -+ Any questions, comments, bug reports, etc. should send email either to the -+ GCC bug account or to: -+ -+ Scott Christley -+ -+ ****************************************************************************** -+ * Simple test program: -+ -+ A simple test program can be found in the thread-test directory. -+ -+ ****************************************************************************** -+ * Sarray Threading: -+ -+ The most critical component of the Objective-C runtime is the sparse array -+ structure (sarray). Sarrays store object selectors and implementations. -+ Following in the tradition of the Objective-C runtime, my threading -+ support assumes that fast message dispatching is far more important -+ than *ANY* and *ALL* other operations. The message dispatching thus -+ uses *NO* locks on any kind. In fact, if you look in sarray.h, you -+ will notice that the message dispatching has not been modified. -+ Instead, I have modified the sarray management functions so that all -+ updates to the sarray data structure can be made in parallel will -+ message dispatching. -+ -+ To support concurrent message dispatching, no dynamically allocated -+ sarray data structures are freed while more than one thread is -+ operational. Sarray data structures that are no longer in use are -+ kept in a linked list of garbage and are released whenever the program -+ is operating with a single thread. The programmer can also flush the -+ garbage list by calling sarray_remove_garbage when the programmer can -+ ensure that no message dispatching is taking place concurrently. The -+ amount of un-reclaimed sarray garbage should normally be extremely -+ small in a real program as sarray structures are freed only when using -+ the "poseAs" functionality and early in program initialization, which -+ normally occurs while the program is single threaded. -+ -+ ****************************************************************************** -+ * Static Variables: -+ -+ The following variables are either statically or globally defined. This list -+ does not include variables which are internal to implementation dependent -+ versions of thread-*.c. -+ -+ The following threading designations are used: -+ SAFE : Implicitly thread safe. -+ SINGLE : Must only be used in single thread mode. -+ MUTEX : Protected by single global mutex objc_runtime_mutex. -+ UNUSED : Not used in the runtime. -+ -+ Variable Name: Usage: Defined: Also used in: -+ =========================== ====== ============ ===================== -+ __objc_class_hash MUTEX class.c -+ __objc_class_links_resolved UNUSED class.c runtime.h -+ __objc_class_number MUTEX class.c -+ __objc_dangling_categories UNUSED init.c -+ __objc_module_list MUTEX init.c -+ __objc_selector_array MUTEX selector.c -+ __objc_selector_hash MUTEX selector.c -+ __objc_selector_max_index MUTEX selector.c sendmsg.c runtime.h -+ __objc_selector_names MUTEX selector.c -+ __objc_thread_exit_status SAFE thread.c -+ __objc_uninstalled_dtable MUTEX sendmsg.c selector.c -+ _objc_load_callback SAFE init.c objc-api.h -+ _objc_lookup_class SAFE class.c objc-api.h -+ _objc_object_alloc SINGLE objects.c objc-api.h -+ _objc_object_copy SINGLE objects.c objc-api.h -+ _objc_object_dispose SINGLE objects.c objc-api.h -+ frwd_sel SAFE2 sendmsg.c -+ idxsize MUTEX sarray.c sendmsg.c sarray.h -+ initialize_sel SAFE2 sendmsg.c -+ narrays MUTEX sarray.c sendmsg.c sarray.h -+ nbuckets MUTEX sarray.c sendmsg.c sarray.h -+ nindices MUTEX sarray.c sarray.h -+ previous_constructors SAFE1 init.c -+ proto_class SAFE1 init.c -+ unclaimed_categories MUTEX init.c -+ unclaimed_proto_list MUTEX init.c -+ uninitialized_statics MUTEX init.c -+ -+ Notes: -+ 1) Initialized once in unithread mode. -+ 2) Initialized value will always be same, guaranteed by lock on selector -+ hash table. -+ -+ ****************************************************************************** -+ * Linking: -+ -+ On Solaris, you must link with -lthread to include the system -+ thread library. We use its low level thread and mutex implementations. -+ -+ On OSF/1, you must link with -lpthreads to include the pthreads library. -+ -+ On WIN32, thread support is built-in to the WIN32 API; refer to your -+ compiler documentation for the appropriate library. -+ -+ ****************************************************************************** -+ * Threads: -+ -+ The thread system attempts to create multiple threads using whatever -+ operating system or library thread support is available. It does -+ assume that all system functions are thread safe. Notably this means -+ that the system implementation of malloc and free must be thread safe. -+ If a system has multiple processors, the threads are configured for -+ full parallel processing. -+ -+ __objc_init_thread_system(void), int -+ Initialize the thread subsystem. Call once by __objc_exec_class. -+ -+ __objc_fini_thread_system(void), int -+ Closes the thread subsystem. -+ -+ objc_thread_detach(SEL selector, id object, id argument), int -+ Creates and detaches a new thread. The new thread starts by -+ sending the given selector with a single argument to the -+ given object. -+ -+ objc_thread_set_priority(int priority), int -+ Sets a threads relative priority within the program. Valid -+ options are: -+ -+ OBJC_THREAD_INTERACTIVE_PRIORITY -+ OBJC_THREAD_BACKGROUND_PRIORITY -+ OBJC_THREAD_LOW_PRIORITY -+ -+ objc_thread_get_priority(void), int -+ Query a threads priority. -+ -+ objc_thread_yield(void), void -+ Yields processor to another thread with equal or higher -+ priority. It is up to the system scheduler to determine if -+ the processor is taken or not. -+ -+ objc_thread_exit(void), int -+ Terminates a thread. If this is the last thread executing -+ then the program will terminate. -+ -+ objc_thread_id(void), int -+ Returns the current thread's id. -+ -+ objc_thread_set_data(void *value), int -+ Set a pointer to the thread's local storage. Local storage is -+ thread specific. -+ -+ objc_thread_get_data(void), void * -+ Returns the pointer to the thread's local storage. -+ -+ ****************************************************************************** -+ * Mutexs: -+ -+ Mutexs can be locked recursively. Each mutex locked mutex remembers -+ its owner (by thread id) and how many times it has been locked. The -+ last unlock on a mutex removes the system lock and allows other -+ threads to access the mutex. -+ -+ objc_mutex_allocate(void), Mutex_t -+ Allocates a new mutex. Mutex is initially unlocked. -+ -+ objc_mutex_deallocate(Mutex_t mutex), int -+ Free a mutex. Before freeing the mutex, makes sure that no -+ one else is using it. -+ -+ objc_mutex_lock(Mutex_t mutex), int -+ Locks a mutex. As mentioned earlier, the same thread may call -+ this routine repeatedly. -+ -+ objc_mutex_trylock(Mutex_t mutex), int -+ Attempts to lock a mutex. Returns -1 if failed. If lock on -+ mutex can be acquired then function operates exactly as -+ objc_mutex_lock. -+ -+ objc_mutex_unlock(Mutex_t mutex), int -+ Unlocks the mutex by one level. Other threads may not acquire -+ the mutex until this thread has released all locks on it. -+ -+ ****************************************************************************** -+ * Sample run of thread-test/checks/test01.m -+ -+ << program started >> -- Program started -+ __objc_exec_class(Object.m) -- Initialize once -+ __objc_init_mutex_system -+ __objc_init_thread_system -+ __objc_init_selector_tables() -+ __objc_init_class_tables() -+ __objc_init_dispatch_tables() -+ __objc_exec_class(Protocol.m) -- Called repeatedly -+ __objc_init_protocols(0x000746d4) -- Called repeatedly -+ class_add_method_list(0x74718, 0x74208) -- Called repeatedly -+ << main called >> -- Main called -+ __objc_init_install_dtable(0x6d980, 0x6d5c0) -- Called repeatedly -+ << delegatePool filled, count=10 >> -- Code in secondary function -+ __objc_init_install_dtable(0x76268, 0x70614) -- Called repeatedly -+ Array: count=1 -- More secondary code. -+ EltNodeCollector: count=1 -+ << end of program >> -- End of program -+ -diff -rc2P objc/class.c objc-threaded/class.c -*** objc/class.c Sat Jan 20 21:09:37 1996 ---- objc-threaded/class.c Fri Jan 26 14:41:59 1996 -*************** -*** 28,41 **** - - /* The table of classname->class. Used for objc_lookup_class and friends */ -! static cache_ptr __objc_class_hash = 0; - - /* This is a hook which is called by objc_get_class and - objc_lookup_class if the runtime is not able to find the class. - This may e.g. try to load in the class using dynamic loading */ -! Class (*_objc_lookup_class)(const char* name) = 0; - - - /* True when class links has been resolved */ -! BOOL __objc_class_links_resolved = NO; - - ---- 28,41 ---- - - /* The table of classname->class. Used for objc_lookup_class and friends */ -! static cache_ptr __objc_class_hash = 0; /* !T:MUTEX */ - - /* This is a hook which is called by objc_get_class and - objc_lookup_class if the runtime is not able to find the class. - This may e.g. try to load in the class using dynamic loading */ -! Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */ - - - /* True when class links has been resolved */ -! BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */ - - -*************** -*** 50,57 **** ---- 50,61 ---- - return; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - __objc_class_hash - = hash_new (CLASS_HASH_SIZE, - (hash_func_type) hash_string, - (compare_func_type) compare_strings); -+ -+ objc_mutex_unlock(__objc_runtime_mutex); - } - -*************** -*** 63,66 **** ---- 67,72 ---- - Class h_class; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - /* make sure the table is there */ - assert(__objc_class_hash); -*************** -*** 83,86 **** ---- 89,94 ---- - hash_add (&__objc_class_hash, class->name, class); - } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); - } - -*************** -*** 92,95 **** ---- 100,105 ---- - Class class; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - /* Make sure the class hash table exists. */ - assert (__objc_class_hash); -*************** -*** 97,100 **** ---- 107,112 ---- - class = hash_value_for_key (__objc_class_hash, name); - -+ objc_mutex_unlock(__objc_runtime_mutex); -+ - if (class) - return class; -*************** -*** 114,117 **** ---- 126,131 ---- - Class class; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - /* Make sure the class hash table exists. */ - assert (__objc_class_hash); -*************** -*** 119,122 **** ---- 133,138 ---- - class = hash_value_for_key (__objc_class_hash, name); - -+ objc_mutex_unlock(__objc_runtime_mutex); -+ - if (class) - return class; -*************** -*** 150,153 **** ---- 166,171 ---- - objc_next_class(void **enum_state) - { -+ objc_mutex_lock(__objc_runtime_mutex); -+ - /* make sure the table is there */ - assert(__objc_class_hash); -*************** -*** 155,158 **** ---- 173,179 ---- - *(node_ptr*)enum_state = - hash_next(__objc_class_hash, *(node_ptr*)enum_state); -+ -+ objc_mutex_unlock(__objc_runtime_mutex); -+ - if (*(node_ptr*)enum_state) - return (*(node_ptr*)enum_state)->value; -*************** -*** 170,173 **** ---- 191,196 ---- - assert(object_class); - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - /* Assign subclass links */ - for (node = hash_next (__objc_class_hash, NULL); node; -*************** -*** 235,238 **** ---- 258,263 ---- - } - } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); - } - -*************** -*** 308,311 **** ---- 333,338 ---- - superclass into impostor. */ - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - for (node = hash_next (__objc_class_hash, NULL); node; - node = hash_next (__objc_class_hash, node)) -*************** -*** 317,320 **** ---- 344,349 ---- - } - } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); - - /* next, we update the dispatch tables... */ -diff -rc2P objc/init.c objc-threaded/init.c -*** objc/init.c Sat Jan 20 21:09:37 1996 ---- objc-threaded/init.c Fri Jan 26 14:43:19 1996 -*************** -*** 32,42 **** - - /* This list contains all modules currently loaded into the runtime */ -! static struct objc_list* __objc_module_list = 0; - - /* This list contains all proto_list's not yet assigned class links */ -! static struct objc_list* unclaimed_proto_list = 0; - - /* List of unresolved static instances. */ -! static struct objc_list *uninitialized_statics; - - /* Check compiler vs runtime version */ ---- 32,48 ---- - - /* This list contains all modules currently loaded into the runtime */ -! static struct objc_list* __objc_module_list = 0; /* !T:MUTEX */ - - /* This list contains all proto_list's not yet assigned class links */ -! static struct objc_list* unclaimed_proto_list = 0; /* !T:MUTEX */ - - /* List of unresolved static instances. */ -! static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */ -! -! /* Global runtime "write" mutex. */ -! _objc_mutex_t __objc_runtime_mutex; -! -! /* Number of threads that are alive. */ -! int __objc_runtime_threads_alive = 1; /* !T:MUTEX */ - - /* Check compiler vs runtime version */ -*************** -*** 53,60 **** - dynamic loader determine the classes that have been loaded when - an object file is dynamically linked in */ -! void (*_objc_load_callback)(Class class, Category* category) = 0; - - /* Is all categories/classes resolved? */ -! BOOL __objc_dangling_categories = NO; - - extern SEL ---- 59,66 ---- - dynamic loader determine the classes that have been loaded when - an object file is dynamically linked in */ -! void (*_objc_load_callback)(Class class, Category* category) = 0; /* !T:SAFE */ - - /* Is all categories/classes resolved? */ -! BOOL __objc_dangling_categories = NO; /* !T:UNUSED */ - - extern SEL -*************** -*** 70,73 **** ---- 76,81 ---- - struct objc_static_instances **statics_in_module; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - while (*cell) - { -*************** -*** 115,118 **** ---- 123,128 ---- - cell = &(*cell)->tail; - } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); - } /* objc_init_statics */ - -*************** -*** 151,154 **** ---- 161,169 ---- - if (!previous_constructors) - { -+ /* Initialize thread-safe system */ -+ __objc_init_thread_system(); -+ __objc_runtime_threads_alive = 1; -+ __objc_runtime_mutex = objc_mutex_allocate(); -+ - __objc_init_selector_tables(); - __objc_init_class_tables(); -*************** -*** 158,161 **** ---- 173,177 ---- - - /* Save the module pointer for later processing. (not currently used) */ -+ objc_mutex_lock(__objc_runtime_mutex); - __objc_module_list = list_cons(module, __objc_module_list); - -*************** -*** 288,291 **** ---- 304,308 ---- - } - -+ objc_mutex_unlock(__objc_runtime_mutex); - } - -*************** -*** 316,319 **** ---- 333,338 ---- - return; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - if (!proto_class) - proto_class = objc_lookup_class("Protocol"); -*************** -*** 349,352 **** ---- 368,373 ---- - } - } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); - } - -Only in objc: list.h -diff -rc2P objc/makefile.dos objc-threaded/makefile.dos -*** objc/makefile.dos Sat Jan 20 21:09:38 1996 ---- objc-threaded/makefile.dos Sat Jan 20 22:13:18 1996 -*************** -*** 38,42 **** - - OBJC_O = hash.o sarray.o class.o sendmsg.o init.o archive.o \ -! selector.o objects.o misc.o object.o protocol.o encoding.o - - libobjc.a: $(OBJC_O) ---- 38,42 ---- - - OBJC_O = hash.o sarray.o class.o sendmsg.o init.o archive.o \ -! selector.o objects.o misc.o object.o protocol.o encoding.o thread.o - - libobjc.a: $(OBJC_O) -*************** -*** 45,52 **** - ranlib libobjc.a - -! OBJC_H = hash.h list.h sarray.h objc.h \ - objc-api.h \ - object.h protocol.h mutex.h \ -! typedstream.h - - mostlyclean: ---- 45,52 ---- - ranlib libobjc.a - -! OBJC_H = hash.h objc-list.h sarray.h objc.h \ - objc-api.h \ - object.h protocol.h mutex.h \ -! typedstream.h thread.h - - mostlyclean: -diff -rc2P objc/objc-api.h objc-threaded/objc-api.h -*** objc/objc-api.h Sat Jan 20 21:09:38 1996 ---- objc-threaded/objc-api.h Fri Jan 26 14:44:31 1996 -*************** -*** 30,33 **** ---- 30,34 ---- - #include "objc/objc.h" - #include "objc/hash.h" -+ #include "objc/thread.h" - #include - -diff -rc2P objc/objc-list.h objc-threaded/objc-list.h -*** objc/objc-list.h Wed Dec 31 19:00:00 1969 ---- objc-threaded/objc-list.h Thu Jun 15 08:40:27 1995 -*************** -*** 0 **** ---- 1,150 ---- -+ /* Generic single linked list to keep various information -+ Copyright (C) 1993, 1994 Free Software Foundation, Inc. -+ -+ Author: Kresten Krab Thorup -+ -+ 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. */ -+ -+ #ifndef __GNU_OBJC_LIST_H -+ #define __GNU_OBJC_LIST_H -+ void * __objc_xrealloc (void *optr, size_t size); -+ void * __objc_xmalloc (size_t size); -+ -+ struct objc_list { -+ void *head; -+ struct objc_list *tail; -+ }; -+ -+ /* Return a cons cell produced from (head . tail) */ -+ -+ static inline struct objc_list* -+ list_cons(void* head, struct objc_list* tail) -+ { -+ struct objc_list* cell; -+ -+ cell = (struct objc_list*)__objc_xmalloc(sizeof(struct objc_list)); -+ cell->head = head; -+ cell->tail = tail; -+ return cell; -+ } -+ -+ /* Return the length of a list, list_length(NULL) returns zero */ -+ -+ static inline int -+ list_length(struct objc_list* list) -+ { -+ int i = 0; -+ while(list) -+ { -+ i += 1; -+ list = list->tail; -+ } -+ return i; -+ } -+ -+ /* Return the Nth element of LIST, where N count from zero. If N -+ larger than the list length, NULL is returned */ -+ -+ static inline void* -+ list_nth(int index, struct objc_list* list) -+ { -+ while(index-- != 0) -+ { -+ if(list->tail) -+ list = list->tail; -+ else -+ return 0; -+ } -+ return list->head; -+ } -+ -+ /* Remove the element at the head by replacing it by its successor */ -+ -+ static inline void -+ list_remove_head(struct objc_list** list) -+ { -+ if ((*list)->tail) -+ { -+ struct objc_list* tail = (*list)->tail; /* fetch next */ -+ *(*list) = *tail; /* copy next to list head */ -+ free(tail); /* free next */ -+ } -+ else /* only one element in list */ -+ { -+ free (*list); -+ (*list) = 0; -+ } -+ } -+ -+ -+ /* Remove the element with `car' set to ELEMENT */ -+ -+ static inline void -+ list_remove_elem(struct objc_list** list, void* elem) -+ { -+ while (*list) { -+ if ((*list)->head == elem) -+ list_remove_head(list); -+ list = &((*list)->tail); -+ } -+ } -+ -+ /* Map FUNCTION over all elements in LIST */ -+ -+ static inline void -+ list_mapcar(struct objc_list* list, void(*function)(void*)) -+ { -+ while(list) -+ { -+ (*function)(list->head); -+ list = list->tail; -+ } -+ } -+ -+ /* Return element that has ELEM as car */ -+ -+ static inline struct objc_list** -+ list_find(struct objc_list** list, void* elem) -+ { -+ while(*list) -+ { -+ if ((*list)->head == elem) -+ return list; -+ list = &((*list)->tail); -+ } -+ return NULL; -+ } -+ -+ /* Free list (backwards recursive) */ -+ -+ static void -+ list_free(struct objc_list* list) -+ { -+ if(list) -+ { -+ list_free(list->tail); -+ free(list); -+ } -+ } -+ #endif __GNU_OBJC_LIST_H -diff -rc2P objc/objects.c objc-threaded/objects.c -*** objc/objects.c Sat Jan 20 21:09:38 1996 ---- objc-threaded/objects.c Sun Jan 21 16:46:14 1996 -*************** -*** 32,38 **** - id __objc_object_copy(id); - -! id (*_objc_object_alloc)(Class) = __objc_object_alloc; -! id (*_objc_object_dispose)(id) = __objc_object_dispose; -! id (*_objc_object_copy)(id) = __objc_object_copy; - - id ---- 32,38 ---- - id __objc_object_copy(id); - -! id (*_objc_object_alloc)(Class) = __objc_object_alloc; /* !T:SINGLE */ -! id (*_objc_object_dispose)(id) = __objc_object_dispose; /* !T:SINGLE */ -! id (*_objc_object_copy)(id) = __objc_object_copy; /* !T:SINGLE */ - - id -diff -rc2P objc/runtime.h objc-threaded/runtime.h -*** objc/runtime.h Sat Jan 20 21:09:38 1996 ---- objc-threaded/runtime.h Fri Jan 26 14:46:27 1996 -*************** -*** 38,43 **** - #include "objc/objc-api.h" /* runtime api functions */ - - #include "objc/hash.h" /* hash structures */ -! #include "objc/list.h" /* linear lists */ - - extern void __objc_add_class_to_hash(Class); /* (objc-class.c) */ ---- 38,45 ---- - #include "objc/objc-api.h" /* runtime api functions */ - -+ #include "objc/thread.h" /* thread and mutex support */ -+ - #include "objc/hash.h" /* hash structures */ -! #include "objc/objc-list.h" /* linear lists */ - - extern void __objc_add_class_to_hash(Class); /* (objc-class.c) */ -*************** -*** 49,52 **** ---- 51,58 ---- - extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */ - extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */ -+ -+ extern int __objc_init_thread_system(void); /* thread.c */ -+ extern int __objc_fini_thread_system(void); /* thread.c */ -+ - extern void class_add_method_list(Class, MethodList_t); - -*************** -*** 59,62 **** ---- 65,74 ---- - /* Number of selectors stored in each of the selector tables */ - extern int __objc_selector_max_index; -+ -+ /* Mutex locking __objc_selector_max_index and its arrays. */ -+ extern _objc_mutex_t __objc_runtime_mutex; -+ -+ /* Number of threads which are alive. */ -+ extern int __objc_runtime_threads_alive; - - #ifdef DEBUG -diff -rc2P objc/sarray.c objc-threaded/sarray.c -*** objc/sarray.c Sat Jan 20 21:09:38 1996 ---- objc-threaded/sarray.c Fri Jan 26 14:52:16 1996 -*************** -*** 26,36 **** - - #include "objc/sarray.h" - #include - #include "assert.h" - -! int nbuckets = 0; -! int nindices = 0; -! int narrays = 0; -! int idxsize = 0; - - #ifdef OBJC_SPARSE2 ---- 26,39 ---- - - #include "objc/sarray.h" -+ #include "objc/runtime.h" - #include - #include "assert.h" - -! int nbuckets = 0; /* !T:MUTEX */ -! int nindices = 0; /* !T:MUTEX */ -! int narrays = 0; /* !T:MUTEX */ -! int idxsize = 0; /* !T:MUTEX */ -! -! static void * first_free_data = NULL; /* !T:MUTEX */ - - #ifdef OBJC_SPARSE2 -*************** -*** 47,50 **** ---- 50,98 ---- - #endif - -+ /* This function removes any structures left over from free operations -+ that were not safe in a multi-threaded environment. */ -+ void -+ sarray_remove_garbage(void) -+ { -+ void **vp; -+ void *np; -+ -+ objc_mutex_lock(__objc_runtime_mutex); -+ -+ vp = first_free_data; -+ first_free_data = NULL; -+ -+ while (vp) { -+ np = *vp; -+ free(vp); -+ vp = np; -+ } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); -+ } -+ -+ /* Free a block of dynamically allocated memory. If we are in multi-threaded -+ mode, it is ok to free it. If not, we add it to the garbage heap to be -+ freed later. */ -+ -+ static void -+ sarray_free_garbage(void *vp) -+ { -+ objc_mutex_lock(__objc_runtime_mutex); -+ -+ if (__objc_runtime_threads_alive == 1) { -+ free(vp); -+ if (first_free_data) -+ sarray_remove_garbage(); -+ } -+ else { -+ *(void **)vp = first_free_data; -+ first_free_data = vp; -+ } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); -+ } -+ -+ /* sarray_at_put : copies data in such a way as to be thread reader safe. */ - void - sarray_at_put(struct sarray* array, sidx index, void* element) -*************** -*** 52,57 **** ---- 100,107 ---- - #ifdef OBJC_SPARSE3 - struct sindex** the_index; -+ struct sindex* new_index; - #endif - struct sbucket** the_bucket; -+ struct sbucket* new_bucket; - #ifdef OBJC_SPARSE3 - size_t ioffset; -*************** -*** 97,116 **** - - /* The index was previously empty, allocate a new */ -! *the_index = (struct sindex*)__objc_xmalloc(sizeof(struct sindex)); -! memcpy(*the_index, array->empty_index, sizeof(struct sindex)); -! (*the_index)->version = array->version; - the_bucket = &((*the_index)->buckets[boffset]); -- nindices += 1; - -! } else if ((*the_index)->version != array->version) { - - /* This index must be lazy copied */ - struct sindex* old_index = *the_index; -! *the_index = (struct sindex*)__objc_xmalloc(sizeof(struct sindex)); -! memcpy( *the_index,old_index, sizeof(struct sindex)); -! (*the_index)->version = array->version; - the_bucket = &((*the_index)->buckets[boffset]); -- nindices += 1; - - } - ---- 147,168 ---- - - /* The index was previously empty, allocate a new */ -! new_index = (struct sindex*)__objc_xmalloc(sizeof(struct sindex)); -! memcpy(new_index, array->empty_index, sizeof(struct sindex)); -! new_index->version.version = array->version.version; -! *the_index = new_index; /* Prepared for install. */ - the_bucket = &((*the_index)->buckets[boffset]); - -! nindices += 1; -! } else if ((*the_index)->version.version != array->version.version) { - - /* This index must be lazy copied */ - struct sindex* old_index = *the_index; -! new_index = (struct sindex*)__objc_xmalloc(sizeof(struct sindex)); -! memcpy( new_index, old_index, sizeof(struct sindex)); -! new_index->version.version = array->version.version; -! *the_index = new_index; /* Prepared for install. */ - the_bucket = &((*the_index)->buckets[boffset]); - -+ nindices += 1; - } - -*************** -*** 123,138 **** - /* The bucket was previously empty (or something like that), */ - /* allocate a new. This is the effect of `lazy' allocation */ -! *the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket)); -! memcpy((void *) *the_bucket, (const void*)array->empty_bucket, sizeof(struct sbucket)); -! (*the_bucket)->version = array->version; - nbuckets += 1; - -! } else if ((*the_bucket)->version != array->version) { - - /* Perform lazy copy. */ - struct sbucket* old_bucket = *the_bucket; -! *the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket)); -! memcpy( *the_bucket,old_bucket, sizeof(struct sbucket)); -! (*the_bucket)->version = array->version; - nbuckets += 1; - ---- 175,194 ---- - /* The bucket was previously empty (or something like that), */ - /* allocate a new. This is the effect of `lazy' allocation */ -! new_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket)); -! memcpy((void *) new_bucket, (const void*)array->empty_bucket, sizeof(struct sbucket)); -! new_bucket->version.version = array->version.version; -! *the_bucket = new_bucket; /* Prepared for install. */ -! - nbuckets += 1; - -! } else if ((*the_bucket)->version.version != array->version.version) { - - /* Perform lazy copy. */ - struct sbucket* old_bucket = *the_bucket; -! new_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket)); -! memcpy( new_bucket, old_bucket, sizeof(struct sbucket)); -! new_bucket->version.version = array->version.version; -! *the_bucket = new_bucket; /* Prepared for install. */ -! - nbuckets += 1; - -*************** -*** 152,162 **** - sarray_new (int size, void* default_element) - { - #ifdef OBJC_SPARSE3 - size_t num_indices = ((size-1)/(INDEX_CAPACITY))+1; - #else /* OBJC_SPARSE2 */ - size_t num_indices = ((size-1)/BUCKET_SIZE)+1; - #endif - int counter; -- struct sarray* arr; - - assert(size > 0); ---- 208,220 ---- - sarray_new (int size, void* default_element) - { -+ struct sarray* arr; - #ifdef OBJC_SPARSE3 - size_t num_indices = ((size-1)/(INDEX_CAPACITY))+1; -+ struct sindex ** new_indices; - #else /* OBJC_SPARSE2 */ - size_t num_indices = ((size-1)/BUCKET_SIZE)+1; -+ struct sbucket ** new_buckets; - #endif - int counter; - - assert(size > 0); -*************** -*** 164,185 **** - /* Allocate core array */ - arr = (struct sarray*) __objc_xmalloc(sizeof(struct sarray)); -! arr->version = 0; -! narrays += 1; - - /* Initialize members */ - #ifdef OBJC_SPARSE3 - arr->capacity = num_indices*INDEX_CAPACITY; -! arr->indices = (struct sindex**) - __objc_xmalloc(sizeof(struct sindex*)*num_indices); -- idxsize += num_indices; - - arr->empty_index = (struct sindex*) __objc_xmalloc(sizeof(struct sindex)); -! arr->empty_index->version = 0; - nindices += 1; - - #else /* OBJC_SPARSE2 */ - arr->capacity = num_indices*BUCKET_SIZE; -! arr->buckets = (struct sbucket**) - __objc_xmalloc(sizeof(struct sbucket*)*num_indices); - idxsize += num_indices; - ---- 222,246 ---- - /* Allocate core array */ - arr = (struct sarray*) __objc_xmalloc(sizeof(struct sarray)); -! arr->version.version = 0; - - /* Initialize members */ - #ifdef OBJC_SPARSE3 - arr->capacity = num_indices*INDEX_CAPACITY; -! new_indices = (struct sindex**) - __objc_xmalloc(sizeof(struct sindex*)*num_indices); - - arr->empty_index = (struct sindex*) __objc_xmalloc(sizeof(struct sindex)); -! arr->empty_index->version.version = 0; -! -! narrays += 1; -! idxsize += num_indices; - nindices += 1; - - #else /* OBJC_SPARSE2 */ - arr->capacity = num_indices*BUCKET_SIZE; -! new_buckets = (struct sbucket**) - __objc_xmalloc(sizeof(struct sbucket*)*num_indices); -+ -+ narrays += 1; - idxsize += num_indices; - -*************** -*** 187,191 **** - - arr->empty_bucket = (struct sbucket*) __objc_xmalloc(sizeof(struct sbucket)); -! arr->empty_bucket->version = 0; - nbuckets += 1; - ---- 248,253 ---- - - arr->empty_bucket = (struct sbucket*) __objc_xmalloc(sizeof(struct sbucket)); -! arr->empty_bucket->version.version = 0; -! - nbuckets += 1; - -*************** -*** 201,218 **** - - for (counter=0; counterindices[counter] = arr->empty_index; - - #else /* OBJC_SPARSE2 */ - - for (counter=0; counterbuckets[counter] = arr->empty_bucket; - - #endif -! - return arr; - } - - -! /* Reallocate the sparse array to hold `newsize' entries */ - - void ---- 263,288 ---- - - for (counter=0; counterempty_index; - - #else /* OBJC_SPARSE2 */ - - for (counter=0; counterempty_bucket; - - #endif -! -! #ifdef OBJC_SPARSE3 -! arr->indices = new_indices; -! #else /* OBJC_SPARSE2 */ -! arr->buckets = new_buckets; -! #endif -! - return arr; - } - - -! /* Reallocate the sparse array to hold `newsize' entries -! Note: We really allocate and then free. We have to do this to ensure that -! any concurrent readers notice the update. */ - - void -*************** -*** 224,227 **** ---- 294,300 ---- - size_t rounded_size = (new_max_index+1)*INDEX_CAPACITY; - -+ struct sindex ** new_indices; -+ struct sindex ** old_indices; -+ - #else /* OBJC_SPARSE2 */ - size_t old_max_index = (array->capacity-1)/BUCKET_SIZE; -*************** -*** 229,232 **** ---- 302,308 ---- - size_t rounded_size = (new_max_index+1)*BUCKET_SIZE; - -+ struct sbucket ** new_buckets; -+ struct sbucket ** old_buckets; -+ - #endif - -*************** -*** 236,320 **** - - /* The size is the same, just ignore the request */ -! if(rounded_size == array->capacity) - return; - - assert(array->ref_count == 1); /* stop if lazy copied... */ - -! if(rounded_size < array->capacity) - { -- /* update capacity */ -- array->capacity = rounded_size; - -- /* free buckets above new_max_index */ -- for(counter = old_max_index; counter > new_max_index; counter-- ) { - #ifdef OBJC_SPARSE3 -! struct sindex* idx = array->indices[counter]; -! if((idx != array->empty_index) && (idx->version == array->version)) { -! int c2; -! for(c2=0; c2buckets[c2]; -! if((bkt != array->empty_bucket) && (bkt->version == array->version)) -! { -! free(bkt); -! nbuckets -= 1; -! } -! } -! free(idx); -! nindices -= 1; -! } - #else /* OBJC_SPARSE2 */ -! struct sbucket* bkt = array->buckets[counter]; -! if ((bkt != array->empty_bucket) && (bkt->version == array->version)) -! { -! free(bkt); -! nbuckets -= 1; -! } - #endif -! } -! -! #ifdef OBJC_SPARSE3 -! /* realloc to free the space above new_max_index */ -! array->indices = (struct sindex**) -! __objc_xrealloc(array->indices, -! (new_max_index+1)*sizeof(struct sindex*)); -! #else /* OBJC_SPARSE2 */ -! array->buckets = (struct sbucket**) -! __objc_xrealloc(array->buckets, -! (new_max_index+1)*sizeof(struct sbucket*)); -! #endif -! idxsize -= (old_max_index-new_max_index); -! -! return; -! } -! -! /* We are asked to extend the array -- reallocate the bucket table, */ -! /* and insert empty_bucket in newly allocated places. */ -! if(rounded_size > array->capacity) -! { - /* update capacity */ - array->capacity = rounded_size; - - #ifdef OBJC_SPARSE3 -! /* realloc to make room in table above old_max_index */ -! array->indices = (struct sindex**) -! __objc_xrealloc(array->indices, -! (new_max_index+1)*sizeof(struct sindex*)); - - /* reset entries above old_max_index to empty_bucket */ - for(counter = old_max_index+1; counter <= new_max_index; counter++) -! array->indices[counter] = array->empty_index; -! - #else /* OBJC_SPARSE2 */ -- -- /* realloc to make room in table above old_max_index */ -- array->buckets = (struct sbucket**) -- __objc_xrealloc(array->buckets, -- (new_max_index+1)*sizeof(struct sbucket*)); -- - /* reset entries above old_max_index to empty_bucket */ - for(counter = old_max_index+1; counter <= new_max_index; counter++) -! array->buckets[counter] = array->empty_bucket; - - #endif - idxsize += (new_max_index-old_max_index); - return; ---- 312,381 ---- - - /* The size is the same, just ignore the request */ -! if(rounded_size <= array->capacity) - return; - - assert(array->ref_count == 1); /* stop if lazy copied... */ - -! /* We are asked to extend the array -- allocate new bucket table, */ -! /* and insert empty_bucket in newly allocated places. */ -! if(rounded_size > array->capacity) - { - - #ifdef OBJC_SPARSE3 -! new_max_index += 4; -! rounded_size = (new_max_index+1)*INDEX_CAPACITY; -! - #else /* OBJC_SPARSE2 */ -! new_max_index += 4; -! rounded_size = (new_max_index+1)*BUCKET_SIZE; - #endif -! - /* update capacity */ - array->capacity = rounded_size; - - #ifdef OBJC_SPARSE3 -! /* alloc to force re-read by any concurrent readers. */ -! old_indices = array->indices; -! new_indices = (struct sindex**) -! __objc_xmalloc((new_max_index+1)*sizeof(struct sindex*)); -! #else /* OBJC_SPARSE2 */ -! old_buckets = array->buckets; -! new_buckets = (struct sbucket**) -! __objc_xmalloc((new_max_index+1)*sizeof(struct sbucket*)); -! #endif - -+ /* copy buckets below old_max_index (they are still valid) */ -+ for(counter = 0; counter <= old_max_index; counter++ ) { -+ #ifdef OBJC_SPARSE3 -+ new_indices[counter] = old_indices[counter]; -+ #else /* OBJC_SPARSE2 */ -+ new_buckets[counter] = old_buckets[counter]; -+ #endif -+ } -+ -+ #ifdef OBJC_SPARSE3 - /* reset entries above old_max_index to empty_bucket */ - for(counter = old_max_index+1; counter <= new_max_index; counter++) -! new_indices[counter] = array->empty_index; - #else /* OBJC_SPARSE2 */ - /* reset entries above old_max_index to empty_bucket */ - for(counter = old_max_index+1; counter <= new_max_index; counter++) -! new_buckets[counter] = array->empty_bucket; -! #endif -! -! #ifdef OBJC_SPARSE3 -! /* install the new indices */ -! array->indices = new_indices; -! #else /* OBJC_SPARSE2 */ -! array->buckets = new_buckets; -! #endif - -+ #ifdef OBJC_SPARSE3 -+ /* free the old indices */ -+ sarray_free_garbage(old_indices); -+ #else /* OBJC_SPARSE2 */ -+ sarray_free_garbage(old_buckets); - #endif -+ - idxsize += (new_max_index-old_max_index); - return; -*************** -*** 327,334 **** ---- 388,398 ---- - void - sarray_free(struct sarray* array) { -+ - #ifdef OBJC_SPARSE3 - size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY; -+ struct sindex ** old_indices; - #else - size_t old_max_index = (array->capacity-1)/BUCKET_SIZE; -+ struct sbucket ** old_buckets; - #endif - int counter = 0; -*************** -*** 339,342 **** ---- 403,412 ---- - return; - -+ #ifdef OBJC_SPARSE3 -+ old_indices = array->indices; -+ #else -+ old_buckets = array->buckets; -+ #endif -+ - if((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0)) - sarray_free(array->is_copy_of); -*************** -*** 345,367 **** - for(counter = 0; counter <= old_max_index; counter++ ) { - #ifdef OBJC_SPARSE3 -! struct sindex* idx = array->indices[counter]; -! if((idx != array->empty_index) && (idx->version == array->version)) { - int c2; - for(c2=0; c2buckets[c2]; -! if((bkt != array->empty_bucket) && (bkt->version == array->version)) - { -! free(bkt); - nbuckets -= 1; - } - } -! free(idx); - nindices -= 1; - } - #else /* OBJC_SPARSE2 */ - struct sbucket* bkt = array->buckets[counter]; -! if ((bkt != array->empty_bucket) && (bkt->version == array->version)) - { -! free(bkt); - nbuckets -= 1; - } ---- 415,440 ---- - for(counter = 0; counter <= old_max_index; counter++ ) { - #ifdef OBJC_SPARSE3 -! struct sindex* idx = old_indices[counter]; -! if((idx != array->empty_index) && -! (idx->version.version == array->version.version)) { - int c2; - for(c2=0; c2buckets[c2]; -! if((bkt != array->empty_bucket) && -! (bkt->version.version == array->version.version)) - { -! sarray_free_garbage(bkt); - nbuckets -= 1; - } - } -! sarray_free_garbage(idx); - nindices -= 1; - } - #else /* OBJC_SPARSE2 */ - struct sbucket* bkt = array->buckets[counter]; -! if ((bkt != array->empty_bucket) && -! (bkt->version.version == array->version.version)) - { -! sarray_free_garbage(bkt); - nbuckets -= 1; - } -*************** -*** 371,376 **** - #ifdef OBJC_SPARSE3 - /* free empty_index */ -! if(array->empty_index->version == array->version) { -! free(array->empty_index); - nindices -= 1; - } ---- 444,449 ---- - #ifdef OBJC_SPARSE3 - /* free empty_index */ -! if(array->empty_index->version.version == array->version.version) { -! sarray_free_garbage(array->empty_index); - nindices -= 1; - } -*************** -*** 378,401 **** - - /* free empty_bucket */ -! if(array->empty_bucket->version == array->version) { -! free(array->empty_bucket); - nbuckets -= 1; - } - - #ifdef OBJC_SPARSE3 - /* free bucket table */ -! free(array->indices); -! idxsize -= (old_max_index+1); - - #else - /* free bucket table */ -! free(array->buckets); -! idxsize -= (old_max_index+1); - - #endif -! - /* free array */ -! free(array); -! narrays -= 1; - } - ---- 451,473 ---- - - /* free empty_bucket */ -! if(array->empty_bucket->version.version == array->version.version) { -! sarray_free_garbage(array->empty_bucket); - nbuckets -= 1; - } -+ idxsize -= (old_max_index+1); -+ narrays -= 1; - - #ifdef OBJC_SPARSE3 - /* free bucket table */ -! sarray_free_garbage(array->indices); - - #else - /* free bucket table */ -! sarray_free_garbage(array->buckets); - - #endif -! - /* free array */ -! sarray_free_garbage(array); - } - -*************** -*** 406,441 **** - sarray_lazy_copy(struct sarray* oarr) - { - #ifdef OBJC_SPARSE3 - size_t num_indices = ((oarr->capacity-1)/INDEX_CAPACITY)+1; - #else /* OBJC_SPARSE2 */ - size_t num_indices = ((oarr->capacity-1)/BUCKET_SIZE)+1; - #endif -- struct sarray* arr; - - /* Allocate core array */ -! arr = (struct sarray*) __objc_xmalloc(sizeof(struct sarray)); -! memcpy( arr,oarr, sizeof(struct sarray)); -! arr->version = oarr->version + 1; -! arr->is_copy_of = oarr; -! oarr->ref_count += 1; - arr->ref_count = 1; - - #ifdef OBJC_SPARSE3 - /* Copy bucket table */ -! arr->indices = (struct sindex**) - __objc_xmalloc(sizeof(struct sindex*)*num_indices); -! memcpy( arr->indices,oarr->indices, - sizeof(struct sindex*)*num_indices); - #else - /* Copy bucket table */ -! arr->buckets = (struct sbucket**) - __objc_xmalloc(sizeof(struct sbucket*)*num_indices); -! memcpy( arr->buckets,oarr->buckets, - sizeof(struct sbucket*)*num_indices); - #endif - - idxsize += num_indices; - narrays += 1; -! - return arr; - } ---- 478,522 ---- - sarray_lazy_copy(struct sarray* oarr) - { -+ struct sarray* arr; -+ - #ifdef OBJC_SPARSE3 - size_t num_indices = ((oarr->capacity-1)/INDEX_CAPACITY)+1; -+ struct sindex ** new_indices; - #else /* OBJC_SPARSE2 */ - size_t num_indices = ((oarr->capacity-1)/BUCKET_SIZE)+1; -+ struct sbucket ** new_buckets; - #endif - - /* Allocate core array */ -! arr = (struct sarray*) __objc_xmalloc(sizeof(struct sarray)); /* !!! */ -! arr->version.version = oarr->version.version + 1; -! #ifdef OBJC_SPARSE3 -! arr->empty_index = oarr->empty_index; -! #endif -! arr->empty_bucket = oarr->empty_bucket; - arr->ref_count = 1; -+ oarr->ref_count += 1; -+ arr->is_copy_of = oarr; -+ arr->capacity = oarr->capacity; - - #ifdef OBJC_SPARSE3 - /* Copy bucket table */ -! new_indices = (struct sindex**) - __objc_xmalloc(sizeof(struct sindex*)*num_indices); -! memcpy( new_indices,oarr->indices, - sizeof(struct sindex*)*num_indices); -+ arr->indices = new_indices; - #else - /* Copy bucket table */ -! new_buckets = (struct sbucket**) - __objc_xmalloc(sizeof(struct sbucket*)*num_indices); -! memcpy( new_buckets,oarr->buckets, - sizeof(struct sbucket*)*num_indices); -+ arr->buckets = new_buckets; - #endif - - idxsize += num_indices; - narrays += 1; -! - return arr; - } -diff -rc2P objc/sarray.h objc-threaded/sarray.h -*** objc/sarray.h Sat Jan 20 21:09:38 1996 ---- objc-threaded/sarray.h Fri Jan 26 14:50:39 1996 -*************** -*** 43,46 **** ---- 43,48 ---- - #include - -+ #include "objc/thread.h" -+ - extern int nbuckets; /* for stats */ - extern int nindices; -*************** -*** 112,118 **** - void * __objc_xmalloc (size_t size); - - struct sbucket { - void* elems[BUCKET_SIZE]; /* elements stored in array */ -! short version; /* used for copy-on-write */ - }; - ---- 114,125 ---- - void * __objc_xmalloc (size_t size); - -+ union sversion { -+ int version; -+ void *next_free; -+ }; -+ - struct sbucket { - void* elems[BUCKET_SIZE]; /* elements stored in array */ -! union sversion version; /* used for copy-on-write */ - }; - -*************** -*** 121,125 **** - struct sindex { - struct sbucket* buckets[INDEX_SIZE]; -! short version; - }; - ---- 128,132 ---- - struct sindex { - struct sbucket* buckets[INDEX_SIZE]; -! union sversion version; /* used for copy-on-write */ - }; - -*************** -*** 134,138 **** - #endif /* OBJC_SPARSE2 */ - struct sbucket* empty_bucket; -! short version; - short ref_count; - struct sarray* is_copy_of; ---- 141,145 ---- - #endif /* OBJC_SPARSE2 */ - struct sbucket* empty_bucket; -! union sversion version; /* used for copy-on-write */ - short ref_count; - struct sarray* is_copy_of; -*************** -*** 143,150 **** - void sarray_free(struct sarray*); - struct sarray* sarray_lazy_copy(struct sarray*); -- struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */ - void sarray_realloc(struct sarray*, int new_size); - void sarray_at_put(struct sarray*, sidx index, void* elem); - void sarray_at_put_safe(struct sarray*, sidx index, void* elem); - - ---- 150,159 ---- - void sarray_free(struct sarray*); - struct sarray* sarray_lazy_copy(struct sarray*); - void sarray_realloc(struct sarray*, int new_size); - void sarray_at_put(struct sarray*, sidx index, void* elem); - void sarray_at_put_safe(struct sarray*, sidx index, void* elem); -+ -+ struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */ -+ void sarray_remove_garbage(void); - - -diff -rc2P objc/selector.c objc-threaded/selector.c -*** objc/selector.c Sat Jan 20 21:09:38 1996 ---- objc-threaded/selector.c Fri Jan 26 14:49:35 1996 -*************** -*** 32,43 **** - - /* Tables mapping selector names to uid and opposite */ -! static struct sarray* __objc_selector_array = 0; /* uid -> sel */ -! static struct sarray* __objc_selector_names = 0; /* uid -> name */ -! static cache_ptr __objc_selector_hash = 0; /* name -> uid */ - - static void register_selectors_from_list(MethodList_t); - - /* Number of selectors stored in each of the above tables */ -! int __objc_selector_max_index = 0; - - void __objc_init_selector_tables() ---- 32,43 ---- - - /* Tables mapping selector names to uid and opposite */ -! static struct sarray* __objc_selector_array = 0; /* uid -> sel !T:MUTEX */ -! static struct sarray* __objc_selector_names = 0; /* uid -> name !T:MUTEX */ -! static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */ - - static void register_selectors_from_list(MethodList_t); - - /* Number of selectors stored in each of the above tables */ -! int __objc_selector_max_index = 0; /* !T:MUTEX */ - - void __objc_init_selector_tables() -*************** -*** 123,129 **** - sidx i; - - i = (sidx) hash_value_for_key (__objc_selector_hash, name); - if (i == 0) -! return 0; - - for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); ---- 123,134 ---- - sidx i; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - i = (sidx) hash_value_for_key (__objc_selector_hash, name); - if (i == 0) -! { -! objc_mutex_unlock(__objc_runtime_mutex); -! return 0; -! } - - for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); -*************** -*** 135,138 **** ---- 140,144 ---- - if (s->sel_types == types) - { -+ objc_mutex_unlock(__objc_runtime_mutex); - return s; - } -*************** -*** 140,147 **** ---- 146,155 ---- - else if (sel_types_match (s->sel_types, types)) - { -+ objc_mutex_unlock(__objc_runtime_mutex); - return s; - } - } - -+ objc_mutex_unlock(__objc_runtime_mutex); - return 0; - } -*************** -*** 155,161 **** - SEL s; - - i = (sidx) hash_value_for_key (__objc_selector_hash, name); - if (i == 0) -! return 0; - - for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); ---- 163,174 ---- - SEL s; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - i = (sidx) hash_value_for_key (__objc_selector_hash, name); - if (i == 0) -! { -! objc_mutex_unlock(__objc_runtime_mutex); -! return 0; -! } - - for (l = (struct objc_list*)sarray_get (__objc_selector_array, i); -*************** -*** 164,170 **** - s = (SEL) l->head; - if (s->sel_types) -! return s; - } - - return s; - } ---- 177,187 ---- - s = (SEL) l->head; - if (s->sel_types) -! { -! objc_mutex_unlock(__objc_runtime_mutex); -! return s; -! } - } - -+ objc_mutex_unlock(__objc_runtime_mutex); - return s; - } -*************** -*** 177,185 **** - sidx i; - - i = (sidx) hash_value_for_key (__objc_selector_hash, name); - if (soffset_decode (i) == 0) -! return 0; - - l = (struct objc_list*)sarray_get (__objc_selector_array, i); - if (l == 0) - return 0; ---- 194,209 ---- - sidx i; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - i = (sidx) hash_value_for_key (__objc_selector_hash, name); - if (soffset_decode (i) == 0) -! { -! objc_mutex_unlock(__objc_runtime_mutex); -! return 0; -! } - - l = (struct objc_list*)sarray_get (__objc_selector_array, i); -+ objc_mutex_unlock(__objc_runtime_mutex); -+ - if (l == 0) - return 0; -*************** -*** 200,208 **** - sel_get_name (SEL selector) - { - if ((soffset_decode((sidx)selector->sel_id) > 0) - && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index)) -! return sarray_get (__objc_selector_names, (sidx) selector->sel_id); - else -! return 0; - } - ---- 224,237 ---- - sel_get_name (SEL selector) - { -+ const char *ret; -+ -+ objc_mutex_lock(__objc_runtime_mutex); - if ((soffset_decode((sidx)selector->sel_id) > 0) - && (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index)) -! ret = sarray_get (__objc_selector_names, (sidx) selector->sel_id); - else -! ret = 0; -! objc_mutex_unlock(__objc_runtime_mutex); -! return ret; - } - -*************** -*** 228,232 **** - - /* Store the passed selector name in the selector record and return its -! selector value (value returned by sel_get_uid). */ - SEL - __sel_register_typed_name (const char *name, const char *types, ---- 257,262 ---- - - /* Store the passed selector name in the selector record and return its -! selector value (value returned by sel_get_uid). -! Assumes that the calling function has locked down __objc_runtime_mutex. */ - SEL - __sel_register_typed_name (const char *name, const char *types, -*************** -*** 311,315 **** - sel_register_name (const char *name) - { -! return __sel_register_typed_name (name, 0, 0); - } - ---- 341,351 ---- - sel_register_name (const char *name) - { -! SEL ret; -! -! objc_mutex_lock(__objc_runtime_mutex); -! ret = __sel_register_typed_name (name, 0, 0); -! objc_mutex_unlock(__objc_runtime_mutex); -! -! return ret; - } - -*************** -*** 317,321 **** - sel_register_typed_name (const char *name, const char *type) - { -! return __sel_register_typed_name (name, type, 0); - } - ---- 353,363 ---- - sel_register_typed_name (const char *name, const char *type) - { -! SEL ret; -! -! objc_mutex_lock(__objc_runtime_mutex); -! ret = __sel_register_typed_name (name, type, 0); -! objc_mutex_unlock(__objc_runtime_mutex); -! -! return ret; - } - -diff -rc2P objc/sendmsg.c objc-threaded/sendmsg.c -*** objc/sendmsg.c Sat Jan 20 21:09:38 1996 ---- objc-threaded/sendmsg.c Fri Jan 26 15:09:21 1996 -*************** -*** 41,45 **** - - /* The uninstalled dispatch table */ -! struct sarray* __objc_uninstalled_dtable = 0; - - /* Send +initialize to class */ ---- 41,45 ---- - - /* The uninstalled dispatch table */ -! struct sarray* __objc_uninstalled_dtable = 0; /* !T:MUTEX */ - - /* Send +initialize to class */ -*************** -*** 77,81 **** ---- 77,83 ---- - if(res == __objc_init_install_dtable) - { -+ objc_mutex_lock(__objc_runtime_mutex); - __objc_install_dispatch_table_for_class (class); -+ objc_mutex_unlock(__objc_runtime_mutex); - res = sarray_get (class->dtable, (size_t) sel->sel_id); - } -*************** -*** 97,101 **** ---- 99,105 ---- - if(res == __objc_init_install_dtable) - { -+ objc_mutex_lock(__objc_runtime_mutex); - __objc_install_dispatch_table_for_class (object->class_pointer); -+ objc_mutex_unlock(__objc_runtime_mutex); - res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id); - } -*************** -*** 173,176 **** ---- 177,182 ---- - goto already_initialized; - -+ objc_mutex_lock(__objc_runtime_mutex); -+ - if(CLS_ISCLASS(receiver->class_pointer)) - { -*************** -*** 199,202 **** ---- 205,209 ---- - CLS_SETINITIALIZED((Class)receiver); - } -+ objc_mutex_unlock(__objc_runtime_mutex); - - already_initialized: -*************** -*** 270,273 **** ---- 277,281 ---- - } - -+ /* Assumes that __objc_runtime_mutex is locked down. */ - static void - __objc_install_dispatch_table_for_class (Class class) -*************** -*** 290,294 **** ---- 298,304 ---- - if (super == 0) - { -+ objc_mutex_lock(__objc_runtime_mutex); - class->dtable = sarray_new (__objc_selector_max_index, 0); -+ objc_mutex_unlock(__objc_runtime_mutex); - } - else -*************** -*** 312,315 **** ---- 322,326 ---- - { - Class next; -+ struct sarray *arr; - - /* not yet installed -- skip it */ -*************** -*** 317,322 **** - return; - -! sarray_free (class->dtable); /* release memory */ - __objc_install_premature_dtable (class); /* someone might require it... */ - __objc_install_dispatch_table_for_class (class); /* could have been lazy... */ - ---- 328,337 ---- - return; - -! objc_mutex_lock(__objc_runtime_mutex); -! -! arr = class->dtable; - __objc_install_premature_dtable (class); /* someone might require it... */ -+ sarray_free (arr); /* release memory */ -+ - __objc_install_dispatch_table_for_class (class); /* could have been lazy... */ - -*************** -*** 325,328 **** ---- 340,344 ---- - __objc_update_dispatch_table_for_class (next); - -+ objc_mutex_unlock(__objc_runtime_mutex); - } - -*************** -*** 330,334 **** - /* This function adds a method list to a class. This function is - typically called by another function specific to the run-time. As -! such this function does not worry about thread safe issued. - - This one is only called for categories. Class objects have their ---- 346,350 ---- - /* This function adds a method list to a class. This function is - typically called by another function specific to the run-time. As -! such this function does not worry about thread safe issues. - - This one is only called for categories. Class objects have their -*************** -*** 339,343 **** - { - int i; -! static SEL initialize_sel = 0; - if (!initialize_sel) - initialize_sel = sel_register_name ("initialize"); ---- 355,360 ---- - { - int i; -! static SEL initialize_sel = 0; /* !T:SAFE2 */ -! - if (!initialize_sel) - initialize_sel = sel_register_name ("initialize"); -*************** -*** 483,487 **** - { - IMP imp; -! static SEL frwd_sel = 0; - SEL err_sel; - ---- 500,504 ---- - { - IMP imp; -! static SEL frwd_sel = 0; /* !T:SAFE2 */ - SEL err_sel; - -*************** -*** 535,538 **** ---- 552,558 ---- - { - int total = 0; -+ -+ objc_mutex_lock(__objc_runtime_mutex); -+ - printf("memory usage: (%s)\n", - #ifdef OBJC_SPARSE2 -*************** -*** 553,556 **** ---- 573,578 ---- - printf("total: %d bytes\n", total); - printf("===================================\n"); -+ -+ objc_mutex_unlock(__objc_runtime_mutex); - } - -diff -rc2P objc/thread-decosf1.c objc-threaded/thread-decosf1.c -*** objc/thread-decosf1.c Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread-decosf1.c Sun Jan 21 19:36:27 1996 -*************** -*** 0 **** ---- 1,325 ---- -+ /* GNU Objective C Runtime Thread Interface -+ Copyright (C) 1995 Free Software Foundation, Inc. -+ -+ Author: Galen C. Hunt (gchunt@cs.rochester.edu) -+ -+ 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, 675 Mass Ave, Cambridge, MA 02139, 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 -+ -+ /******** -+ * 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) -+ { -+ printf("__objc_init_thread_system\n"); -+ -+ if (pthread_keycreate(&__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, pthread_attr_default, -+ (void *)func, arg) == 0) { -+ thread_id = *(_objc_thread_t *)&new_thread_handle; /* ??? May not work! (64bit)*/ -+ 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) -+ { -+ 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. */ -+ -+ return -1; /* Failed. */ -+ } -+ -+ /******** -+ * Return the current thread's priority. -+ */ -+ int -+ objc_thread_get_priority(void) -+ { -+ 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; -+ } -+ 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". -+ */ -+ int -+ objc_thread_id(void) -+ { -+ pthread_t self = pthread_self(); -+ -+ return *(int *)&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) -+ { -+ void * value = NULL; -+ -+ if (pthread_getspecific(__objc_thread_data_key, (void *)&value) == 0) -+ return value; /* Return thread data. */ -+ -+ 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) -+ { -+ _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, pthread_mutexattr_default); -+ -+ if (err != 0) { /* System init failed? */ -+ free(mutex); /* Yes, free local memory. */ -+ return NULL; /* Abort. */ -+ } -+ mutex->owner = -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 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) -+ { -+ int 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) -+ { -+ int 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) -+ { -+ int 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 = -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. */ -+ } -+ -+ /* End of File */ -diff -rc2P objc/thread-irix.c objc-threaded/thread-irix.c -*** objc/thread-irix.c Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread-irix.c Sun Jan 21 19:36:27 1996 -*************** -*** 0 **** ---- 1,314 ---- -+ /* GNU Objective C Runtime Thread Interface - SGI IRIX Implementation -+ Copyright (C) 1995 Free Software Foundation, Inc. -+ -+ Author: Galen C. Hunt (gchunt@cs.rochester.edu) -+ -+ 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, 675 Mass Ave, Cambridge, MA 02139, 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 -+ #include -+ #include -+ -+ /******** -+ * 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. -+ */ -+ 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; -+ } -+ -+ 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; -+ 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; -+ } -+ -+ /******** -+ * Set the current thread's priority. -+ */ -+ int -+ 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. */ -+ } -+ -+ /******** -+ * Return the current thread's priority. -+ */ -+ int -+ objc_thread_get_priority(void) -+ { -+ 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) -+ { -+ sginap(0); /* Yield to equal process. */ -+ } -+ -+ /******** -+ * 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); -+ -+ exit(__objc_thread_exit_status); /* IRIX only has exit. */ -+ 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) -+ { -+ return (_objc_thread_t)get_pid(); /* Threads are processes. */ -+ } -+ -+ /******** -+ * Sets the thread's local storage pointer. Returns 0 if successful or -1 -+ * if failed. -+ */ -+ int -+ objc_thread_set_data(void *value) -+ { -+ *((void **)&PRDA->usr_prda) = value; /* Set thread data ptr. */ -+ return 0; -+ } -+ -+ /******** -+ * Returns the thread's local storage pointer. Returns NULL on failure. -+ */ -+ void * -+ objc_thread_get_data(void) -+ { -+ return *((void **)&PRDA->usr_prda); /* Return thread data ptr. */ -+ } -+ -+ /******** -+ * 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. */ -+ -+ if (!(mutex->lock = usnewlock(__objc_shared_arena_handle))) -+ err = -1; -+ -+ 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. */ -+ -+ usfreelock(mutex->lock, __objc_shared_arena_handle); /* Free IRIX lock. */ -+ -+ 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? */ -+ 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. */ -+ } -+ -+ /******** -+ * 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 (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. */ -+ } -+ -+ /******** -+ * 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. */ -+ -+ 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. */ -+ } -+ -+ /* End of File */ -diff -rc2P objc/thread-single.c objc-threaded/thread-single.c -*** objc/thread-single.c Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread-single.c Sun Jan 21 19:36:27 1996 -*************** -*** 0 **** ---- 1,239 ---- -+ /* GNU Objective C Runtime Thread Implementation -+ Copyright (C) 1995 Free Software Foundation, Inc. -+ -+ Author: Galen C. Hunt (gchunt@cs.rochester.edu) -+ -+ 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, 675 Mass Ave, Cambridge, MA 02139, 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. */ -+ -+ /******** -+ * 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. -+ */ -+ int -+ __objc_init_thread_system(void) -+ { -+ DEBUG_PRINTF("__objc_init_thread_system\n"); -+ return -1; /* Failed. */ -+ } -+ -+ /******** -+ * 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) -+ { -+ return NULL; /* We can't start threads. */ -+ } -+ -+ /******** -+ * Set the current thread's priority. -+ */ -+ int -+ objc_thread_set_priority(int priority) -+ { -+ return -1; /* Failed. */ -+ } -+ -+ /******** -+ * Return the current thread's priority. -+ */ -+ int -+ objc_thread_get_priority(void) -+ { -+ 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) -+ { -+ return; -+ } -+ -+ /******** -+ * Terminate the current tread. Doesn't return anything. Doesn't return. -+ * Actually, if it failed returns -1. -+ */ -+ int -+ objc_thread_exit(void) -+ { -+ 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". -+ */ -+ _objc_thread_t -+ objc_thread_id(void) -+ { -+ return (_objc_thread_t)1; /* No thread support, use 1.*/ -+ } -+ -+ /******** -+ * Sets the thread's local storage pointer. Returns 0 if successful or -1 -+ * if failed. -+ */ -+ -+ static void *thread_local_storage = NULL; -+ -+ int -+ objc_thread_set_data(void *value) -+ { -+ thread_local_storage = value; -+ return 0; -+ } -+ -+ /******** -+ * Returns the thread's local storage pointer. Returns NULL on failure. -+ */ -+ 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_xmalloc(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. */ -+ -+ 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) -+ { -+ int 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. */ -+ } -+ -+ /* End of File */ -diff -rc2P objc/thread-solaris.c objc-threaded/thread-solaris.c -*** objc/thread-solaris.c Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread-solaris.c Sun Jan 21 19:36:27 1996 -*************** -*** 0 **** ---- 1,328 ---- -+ /* GNU Objective C Runtime Thread Interface -+ Copyright (C) 1995 Free Software Foundation, Inc. -+ -+ Author: Galen C. Hunt (gchunt@cs.rochester.edu) -+ -+ 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, 675 Mass Ave, Cambridge, MA 02139, 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 "runtime.h" -+ -+ #include -+ #include -+ #include -+ -+ /******** -+ * 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. */ -+ }; -+ -+ /***************************************************************************** -+ * 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. -+ */ -+ 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. */ -+ } -+ -+ int -+ __objc_fini_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. -+ */ -+ _objc_thread_t -+ objc_thread_create(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); -+ -+ 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++; -+ } -+ -+ objc_mutex_unlock(__objc_runtime_mutex); -+ -+ return thread_id; -+ } -+ -+ /******** -+ * Set the current thread's priority. -+ */ -+ int -+ objc_thread_set_priority(int priority) -+ { -+ int sys_priority = 0; -+ -+ switch (priority) { -+ case OBJC_THREAD_INTERACTIVE_PRIORITY: -+ sys_priority = 300; -+ break; -+ default: -+ case OBJC_THREAD_BACKGROUND_PRIORITY: -+ sys_priority = 200; -+ break; -+ case OBJC_THREAD_LOW_PRIORITY: -+ sys_priority = 1000; -+ break; -+ } -+ -+ if (thr_setprio(thr_self(), sys_priority) == 0) -+ return 0; /* Changed priority. End. */ -+ -+ return -1; /* Failed. */ -+ } -+ -+ /******** -+ * Return the current thread's priority. -+ */ -+ int -+ objc_thread_get_priority(void) -+ { -+ int sys_priority; /* Solaris thread 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. */ -+ } -+ -+ /******** -+ * 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) -+ { -+ thr_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); -+ -+ thr_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) -+ { -+ return (_objc_thread_t)thr_self(); -+ } -+ -+ /******** -+ * Sets the thread's local storage pointer. Returns 0 if successful or -1 -+ * if failed. -+ */ -+ int -+ objc_thread_set_data(void *value) -+ { -+ if (thr_setspecific(__objc_thread_data_key, value) == 0) -+ return 0; -+ return -1; -+ } -+ -+ /******** -+ * Returns the thread's local storage pointer. Returns NULL on failure. -+ */ -+ 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; -+ } -+ -+ /******** -+ * 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_xmalloc(sizeof(struct _objc_mutex)))) -+ return NULL; /* Abort if malloc failed. */ -+ -+ err = mutex_init(&mutex->lock, USYNC_THREAD, 0); -+ -+ 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. */ -+ -+ mutex_destroy(&mutex->lock); /* System deallocate. */ -+ -+ 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 (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. */ -+ } -+ -+ /******** -+ * 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_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. */ -+ } -+ -+ /******** -+ * 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 (mutex_unlock(&mutex->lock) != 0) /* Did lock release fail? */ -+ return -1; /* Yes, return error value. */ -+ -+ return 0; /* No, return success. */ -+ } -+ -+ /* End of File */ -diff -rc2P objc/thread-test/Makefile objc-threaded/thread-test/Makefile -*** objc/thread-test/Makefile Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread-test/Makefile Sun Jan 21 20:06:00 1996 -*************** -*** 0 **** ---- 1,45 ---- -+ ############################################################################## -+ # -+ # -+ # -+ -+ all: test1 -+ -+ ######## -+ # Solaris: -+ # -+ # test1 : test1.o ../libobjc-thread.a -+ # gcc -g -o test1 test1.o ../libobjc-thread.a -lthread -+ -+ ######## -+ # Linux: -+ # -+ # test1 : test1.o ../libobjc-thread.a -+ # gcc -g -o test1 test1.o ../libobjc-thread.a -lieee -+ -+ ######## -+ # Others: -+ # -+ test1 : test1.o ../libobjc-thread.a -+ gcc -g -o test1 test1.o ../libobjc-thread.a -+ -+ test1.o : test1.m -+ gcc -DOBJC_THREAD_SAFE -g -I../.. -o test1.o -c test1.m -+ -+ ######## -+ -+ clean: -+ rm -f *.o test1 -+ -+ test: test1 -+ time test1 -+ # -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff -rc2P objc/thread-test/test1.m objc-threaded/thread-test/test1.m -*** objc/thread-test/test1.m Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread-test/test1.m Sun Jan 21 19:46:28 1996 -*************** -*** 0 **** ---- 1,160 ---- -+ // -+ -+ #include -+ #include -+ #include -+ #include -+ -+ ////////////////////////////////////////////////////////////////////////////// -+ -+ @interface NSLocking : Object -+ { -+ _objc_mutex_t mutex; -+ } -+ -+ - init; -+ - free; -+ - (void)lock; -+ - (void)unlock; -+ -+ @end -+ -+ @implementation NSLocking -+ -+ - init -+ { -+ [super init]; -+ -+ mutex = objc_mutex_allocate(); -+ return self; -+ } -+ -+ - free -+ { -+ objc_mutex_deallocate(mutex); -+ return [super free]; -+ } -+ -+ - (void)lock -+ { -+ objc_mutex_lock(mutex); -+ } -+ -+ - (void)unlock -+ { -+ objc_mutex_lock(mutex); -+ } -+ -+ @end -+ -+ ////////////////////////////////////////////////////////////////////////////// -+ -+ @interface Fruit : Object -+ { -+ int m_refs; -+ const char *m_name; -+ volatile int m_done; -+ } -+ -+ /* Obtaining attributes intrinsic to the protocol */ -+ -+ - init; -+ - free; -+ - (const char *)name; -+ - set_name: (const char *)name; -+ - loop: (void *)arg; -+ - (int)bogus: (int)n; -+ - wait; -+ -+ -+ @end -+ -+ @implementation Fruit -+ -+ - init -+ { -+ [super init]; -+ m_refs = 1; -+ m_name = ""; -+ m_done = 0; -+ return self; -+ } -+ -+ - free -+ { -+ printf("[%s free, refs: %d]\n", m_name, m_refs); -+ return [super free]; -+ } -+ -+ - (const char *)name -+ { -+ return m_name; -+ } -+ -+ - set_name: (const char *)name -+ { -+ m_name = name; -+ return self; -+ } -+ -+ - loop: (void *)arg -+ { -+ int i; -+ -+ printf("%s loop start\n", m_name); -+ fflush(stdout); -+ for (i = 0; i < 100000;) { -+ i = [self bogus: i]; -+ if (i % 10000 == 1) -+ printf("%s loop: %d\n", m_name, i); -+ } -+ printf("%s loop done\n", m_name); -+ m_done = 1; -+ -+ return self; -+ } -+ -+ - (int)bogus: (int)n -+ { -+ return n + 1; -+ } -+ -+ - wait -+ { -+ while (!m_done) -+ ; -+ -+ return self; -+ } -+ -+ @end -+ -+ -+ int main(int argc, char **argv) -+ { -+ id f1, f2, f3; -+ id (*imp)(id,SEL,id); -+ -+ printf("Main:\n"); -+ -+ f1 = [[Fruit new] set_name: "f1"]; -+ f2 = [[Fruit new] set_name: "f2"]; -+ f3 = [[Fruit new] set_name: "f3"]; -+ -+ printf("Inside the main body.\n"); -+ objc_thread_detach(@selector(loop:), f1, NULL); -+ objc_thread_detach(@selector(loop:), f2, NULL); -+ -+ [f3 loop: NULL]; -+ -+ [f1 wait]; -+ [f2 wait]; -+ -+ [f1 free]; -+ [f2 free]; -+ [f3 free]; -+ -+ printf("Done:\n"); -+ -+ return 0; -+ } -diff -rc2P objc/thread-win32.c objc-threaded/thread-win32.c -*** objc/thread-win32.c Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread-win32.c Mon Jan 22 11:55:50 1996 -*************** -*** 0 **** ---- 1,333 ---- -+ /* GNU Objective C Runtime Thread Interface - Win32 Implementation -+ Copyright (C) 1995 Free Software Foundation, Inc. -+ -+ Author: Galen C. Hunt (gchunt@cs.rochester.edu) -+ -+ 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, 675 Mass Ave, Cambridge, MA 02139, 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 -+ -+ /******** -+ * 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. -+ */ -+ int -+ __objc_init_thread_system(void) -+ { -+ DEBUG_PRINTF("__objc_init_thread_system\n"); -+ -+ if ((__objc_data_tls = TlsAlloc()) != (DWORD)-1) -+ return 0; /* Yes, return success. */ -+ -+ return -1; /* Failed. */ -+ } -+ -+ int -+ __objc_fini_thread_system(void) -+ { -+ if (__objc_data_tls != (DWORD)-1) { -+ TlsFree(__objc_data_tls); -+ return 0; -+ } -+ 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. -+ */ -+ _objc_thread_t -+ objc_thread_create(void (*func)(void *arg), void *arg) -+ { -+ DWORD thread_id = 0; /* Detached thread id. */ -+ HANDLE win32_handle; /* Win32 thread 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); -+ -+ return (_objc_thread_t)thread_id; -+ } -+ -+ /******** -+ * Set the current thread's priority. -+ */ -+ int -+ 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; -+ } -+ if (SetThreadPriority(GetCurrentThread(), sys_priority)) -+ return 0; /* Changed priority. End. */ -+ -+ return -1; /* Failed. */ -+ } -+ -+ /******** -+ * Return the current thread's priority. -+ */ -+ int -+ objc_thread_get_priority(void) -+ { -+ 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; -+ -+ case THREAD_PRIORITY_IDLE: -+ case THREAD_PRIORITY_LOWEST: -+ return OBJC_THREAD_LOW_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) -+ { -+ Sleep(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); -+ -+ ExitThread(__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) -+ { -+ return (_objc_thread_t)GetCurrentThreadId(); /* 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) -+ { -+ if (TlsSetValue(__objc_data_tls, value)) -+ 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 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) -+ { -+ _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 ((mutex->handle = CreateMutex(NULL, 0, NULL)) == NULL) { -+ free(mutex); /* Failed, free 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. */ -+ -+ CloseHandle(mutex->handle); /* Close Win32 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. */ -+ 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. */ -+ -+ 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. */ -+ 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. */ -+ } -+ -+ /******** -+ * 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 (ReleaseMutex(mutex->handle) == 0) -+ return -1; /* Failed, abort. */ -+ -+ return 0; /* No, return success. */ -+ } -+ -+ /* End of File */ -diff -rc2P objc/thread.c objc-threaded/thread.c -*** objc/thread.c Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread.c Fri Jan 26 14:40:09 1996 -*************** -*** 0 **** ---- 1,132 ---- -+ /* GNU Objective C Runtime Thread Interface -+ Copyright (C) 1995 Free Software Foundation, Inc. -+ -+ Author: 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, 675 Mass Ave, Cambridge, MA 02139, 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 "runtime.h" -+ -+ /***************************************************************************** -+ * Universal static variables: -+ */ -+ int __objc_thread_exit_status = 0; /* Global exit status. */ -+ -+ /***************************************************************************** -+ * Universal Functionality -+ */ -+ -+ /******** -+ * First function called in a thread, starts everything else. -+ */ -+ struct __objc_thread_start_state -+ { -+ 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; -+ -+ free(istate); -+ -+ 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(); -+ } -+ -+ /******** -+ * 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. */ -+ -+ if (!(istate = (struct __objc_thread_start_state *) -+ __objc_xmalloc(sizeof(*istate)))) /* Can we allocate state? */ -+ return NULL; /* No, abort. */ -+ -+ istate->selector = selector; /* Initialize the thread's */ -+ istate->object = object; /* state structure. */ -+ istate->argument = argument; -+ -+ if ((thread_id = objc_thread_create((void *)__objc_thread_detach_function, -+ istate)) == NULL) { -+ free(istate); /* Release state if failed. */ -+ return thread_id; -+ } -+ return thread_id; -+ } -+ -+ #undef objc_mutex_lock() -+ #undef objc_mutex_unlock() -+ -+ int -+ objc_mutex_unlock_x(_objc_mutex_t mutex, const char *f, int l) -+ { -+ printf("%16.16s#%4d < unlock", f, l); -+ return objc_mutex_unlock(mutex); -+ } -+ -+ int -+ objc_mutex_lock_x(_objc_mutex_t mutex, const char *f, int l) -+ { -+ printf("%16.16s#%4d < lock", f, l); -+ return objc_mutex_lock(mutex); -+ } -+ -+ /***************************************************************************** -+ * Implementation specific functionality: -+ */ -+ -+ #if defined(__sparc__) && defined(__svr4__) /* Solaris only code. */ -+ #include "thread-solaris.c" -+ #elif defined(__sgi__) && defined(__mips__) /* IRIX only code. */ -+ #include "thread-irix.c" -+ #elif defined(__alpha__) && defined(__osf__) /* Alpha OSF/1 only code. */ -+ #include "thread-decosf1.c" -+ #elif defined(__WIN32__) -+ #include "thread-win32.c" -+ #else /* Single threaded code. */ -+ #include "thread-single.c" -+ #endif -+ -+ /* End of File */ -diff -rc2P objc/thread.h objc-threaded/thread.h -*** objc/thread.h Wed Dec 31 19:00:00 1969 ---- objc-threaded/thread.h Sun Jan 21 19:37:01 1996 -*************** -*** 0 **** ---- 1,68 ---- -+ /* Thread and mutex controls for Objective C. -+ Copyright (C) 1993 Free Software Foundation, Inc. -+ -+ AUTHOR: 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, 675 Mass Ave, Cambridge, MA 02139, 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. */ -+ -+ -+ #ifndef __thread_INCLUDE_GNU -+ #define __thread_INCLUDE_GNU -+ -+ #include "objc/objc.h" -+ -+ /******** -+ * Thread safe implementation types and functions. -+ */ -+ -+ #define OBJC_THREAD_INTERACTIVE_PRIORITY 2 -+ #define OBJC_THREAD_BACKGROUND_PRIORITY 1 -+ #define OBJC_THREAD_LOW_PRIORITY 0 -+ -+ typedef struct _objc_mutex *_objc_mutex_t; -+ typedef void * _objc_thread_t; -+ -+ _objc_mutex_t objc_mutex_allocate(void); -+ int objc_mutex_deallocate(_objc_mutex_t mutex); -+ int objc_mutex_lock(_objc_mutex_t mutex); -+ int objc_mutex_unlock(_objc_mutex_t mutex); -+ int objc_mutex_trylock(_objc_mutex_t mutex); -+ -+ _objc_thread_t objc_thread_create(void (*func)(void *arg), void *arg); -+ void objc_thread_yield(void); -+ int objc_thread_exit(void); -+ int objc_thread_set_priority(int priority); -+ int objc_thread_get_priority(void); -+ void * objc_thread_get_data(void); -+ int objc_thread_set_data(void *value); -+ _objc_thread_t objc_thread_id(void); -+ -+ _objc_thread_t objc_thread_detach(SEL selector, id object, id argument); -+ int objc_mutex_lock_x(_objc_mutex_t mutex, const char *f, int l); -+ int objc_mutex_unlock_x(_objc_mutex_t mutex, const char *f, int l); -+ -+ /* For debugging of locks, uncomment these two macros: */ -+ /* #define objc_mutex_lock(x) objc_mutex_lock_x(x, __FILE__, __LINE__) */ -+ /* #define objc_mutex_unlock(x) objc_mutex_unlock_x(x, __FILE__, __LINE__)*/ -+ -+ #endif /* not __thread_INCLUDE_GNU */