1*36ac495dSmrgThis file describes in little detail the modifications to the 2*36ac495dSmrgObjective-C runtime needed to make it thread safe. 3*36ac495dSmrg 4*36ac495dSmrgFirst off, kudos to Galen Hunt who is the author of this great work. 5*36ac495dSmrg 6*36ac495dSmrgIf you have an comments or just want to know where to 7*36ac495dSmrgsend me money to express your undying gratitude for threading the 8*36ac495dSmrgObjective-C runtime you can reach Galen at: 9*36ac495dSmrg 10*36ac495dSmrg gchunt@cs.rochester.edu 11*36ac495dSmrg 12*36ac495dSmrgAny questions, comments, bug reports, etc. should send email either to the 13*36ac495dSmrgGCC bug account or to: 14*36ac495dSmrg 15*36ac495dSmrg Scott Christley <scottc@net-community.com> 16*36ac495dSmrg 17*36ac495dSmrg* Sarray Threading: 18*36ac495dSmrg 19*36ac495dSmrgThe most critical component of the Objective-C runtime is the sparse array 20*36ac495dSmrgstructure (sarray). Sarrays store object selectors and implementations. 21*36ac495dSmrgFollowing in the tradition of the Objective-C runtime, my threading 22*36ac495dSmrgsupport assumes that fast message dispatching is far more important 23*36ac495dSmrgthan *ANY* and *ALL* other operations. The message dispatching thus 24*36ac495dSmrguses *NO* locks on any kind. In fact, if you look in sarray.h, you 25*36ac495dSmrgwill notice that the message dispatching has not been modified. 26*36ac495dSmrgInstead, I have modified the sarray management functions so that all 27*36ac495dSmrgupdates to the sarray data structure can be made in parallel will 28*36ac495dSmrgmessage dispatching. 29*36ac495dSmrg 30*36ac495dSmrgTo support concurrent message dispatching, no dynamically allocated 31*36ac495dSmrgsarray data structures are freed while more than one thread is 32*36ac495dSmrgoperational. Sarray data structures that are no longer in use are 33*36ac495dSmrgkept in a linked list of garbage and are released whenever the program 34*36ac495dSmrgis operating with a single thread. The programmer can also flush the 35*36ac495dSmrggarbage list by calling sarray_remove_garbage when the programmer can 36*36ac495dSmrgensure that no message dispatching is taking place concurrently. The 37*36ac495dSmrgamount of un-reclaimed sarray garbage should normally be extremely 38*36ac495dSmrgsmall in a real program as sarray structures are freed only when using 39*36ac495dSmrgthe "poseAs" functionality and early in program initialization, which 40*36ac495dSmrgnormally occurs while the program is single threaded. 41*36ac495dSmrg 42*36ac495dSmrg****************************************************************************** 43*36ac495dSmrg* Static Variables: 44*36ac495dSmrg 45*36ac495dSmrgThe following variables are either statically or globally defined. This list 46*36ac495dSmrgdoes not include variables which are internal to implementation dependent 47*36ac495dSmrgversions of thread-*.c. 48*36ac495dSmrg 49*36ac495dSmrgThe following threading designations are used: 50*36ac495dSmrg SAFE : Implicitly thread safe. 51*36ac495dSmrg SINGLE : Must only be used in single thread mode. 52*36ac495dSmrg MUTEX : Protected by single global mutex objc_runtime_mutex. 53*36ac495dSmrg UNUSED : Not used in the runtime. 54*36ac495dSmrg 55*36ac495dSmrgVariable Name: Usage: Defined: Also used in: 56*36ac495dSmrg=========================== ====== ============ ===================== 57*36ac495dSmrg__objc_class_hash MUTEX class.c 58*36ac495dSmrg__objc_class_links_resolved UNUSED class.c runtime.h 59*36ac495dSmrg__objc_class_number MUTEX class.c 60*36ac495dSmrg__objc_dangling_categories UNUSED init.c 61*36ac495dSmrg__objc_module_list MUTEX init.c 62*36ac495dSmrg__objc_selector_array MUTEX selector.c 63*36ac495dSmrg__objc_selector_hash MUTEX selector.c 64*36ac495dSmrg__objc_selector_max_index MUTEX selector.c sendmsg.c runtime.h 65*36ac495dSmrg__objc_selector_names MUTEX selector.c 66*36ac495dSmrg__objc_thread_exit_status SAFE thread.c 67*36ac495dSmrg__objc_uninstalled_dtable MUTEX sendmsg.c selector.c 68*36ac495dSmrg_objc_load_callback SAFE init.c objc-api.h 69*36ac495dSmrg_objc_lookup_class SAFE class.c objc-api.h 70*36ac495dSmrg_objc_object_alloc SINGLE objects.c objc-api.h 71*36ac495dSmrg_objc_object_copy SINGLE objects.c objc-api.h 72*36ac495dSmrg_objc_object_dispose SINGLE objects.c objc-api.h 73*36ac495dSmrgfrwd_sel SAFE2 sendmsg.c 74*36ac495dSmrgidxsize MUTEX sarray.c sendmsg.c sarray.h 75*36ac495dSmrginitialize_sel SAFE2 sendmsg.c 76*36ac495dSmrgnarrays MUTEX sarray.c sendmsg.c sarray.h 77*36ac495dSmrgnbuckets MUTEX sarray.c sendmsg.c sarray.h 78*36ac495dSmrgnindices MUTEX sarray.c sarray.h 79*36ac495dSmrgprevious_constructors SAFE1 init.c 80*36ac495dSmrgproto_class SAFE1 init.c 81*36ac495dSmrgunclaimed_categories MUTEX init.c 82*36ac495dSmrgunclaimed_proto_list MUTEX init.c 83*36ac495dSmrguninitialized_statics MUTEX init.c 84*36ac495dSmrg 85*36ac495dSmrgNotes: 86*36ac495dSmrg1) Initialized once in unithread mode. 87*36ac495dSmrg2) Initialized value will always be same, guaranteed by lock on selector 88*36ac495dSmrg hash table. 89*36ac495dSmrg 90*36ac495dSmrg 91*36ac495dSmrg****************************************************************************** 92*36ac495dSmrg* Frontend/Backend design: 93*36ac495dSmrg 94*36ac495dSmrgThe design of the Objective-C runtime thread and mutex functions utilizes a 95*36ac495dSmrgfrontend/backend implementation. 96*36ac495dSmrg 97*36ac495dSmrgThe frontend, as characterized by the files thr.h and thr.c, is a set 98*36ac495dSmrgof platform independent structures and functions which represent the 99*36ac495dSmrguser interface. For example, objc_mutex_lock(). Objective-C programs 100*36ac495dSmrgshould use these structures and functions for their thread and mutex 101*36ac495dSmrgwork if they wish to maintain a high degree of portability across 102*36ac495dSmrgplatforms. 103*36ac495dSmrg 104*36ac495dSmrgThe backend is currently GCC's gthread code (gthr.h and related). For 105*36ac495dSmrgexample, __gthread_objc_mutex_lock(). The thread system is 106*36ac495dSmrgautomatically configured when GCC is configured. On most platforms 107*36ac495dSmrgthis thread backend is able to automatically switch to non-multi-threaded 108*36ac495dSmrgmode if the threading library is not linked in. 109*36ac495dSmrg 110*36ac495dSmrgIf you want to compile libobjc standalone, then you would need to modify 111*36ac495dSmrgthe configure.ac and makefiles for it and you need to import the 112*36ac495dSmrggthread code from GCC. 113*36ac495dSmrg 114*36ac495dSmrg****************************************************************************** 115*36ac495dSmrg* Threads: 116*36ac495dSmrg 117*36ac495dSmrgThe thread system attempts to create multiple threads using whatever 118*36ac495dSmrgoperating system or library thread support is available. It does 119*36ac495dSmrgassume that all system functions are thread safe. Notably this means 120*36ac495dSmrgthat the system implementation of malloc and free must be thread safe. 121*36ac495dSmrgIf a system has multiple processors, the threads are configured for 122*36ac495dSmrgfull parallel processing. 123*36ac495dSmrg 124*36ac495dSmrg* Backend initialization functions 125*36ac495dSmrg 126*36ac495dSmrg__objc_init_thread_system(void), int 127*36ac495dSmrg Initialize the thread subsystem. Called once by __objc_exec_class. 128*36ac495dSmrg Return -1 if error otherwise return 0. 129*36ac495dSmrg 130*36ac495dSmrg__objc_close_thread_system(void), int 131*36ac495dSmrg Closes the thread subsystem, not currently guaranteed to be called. 132*36ac495dSmrg Return -1 if error otherwise return 0. 133*36ac495dSmrg 134*36ac495dSmrg***** 135*36ac495dSmrg* Frontend thread functions 136*36ac495dSmrg* User programs should use these functions. 137*36ac495dSmrg 138*36ac495dSmrgobjc_thread_detach(SEL selector, id object, id argument), objc_thread_t 139*36ac495dSmrg Creates and detaches a new thread. The new thread starts by 140*36ac495dSmrg sending the given selector with a single argument to the 141*36ac495dSmrg given object. 142*36ac495dSmrg 143*36ac495dSmrgobjc_thread_set_priority(int priority), int 144*36ac495dSmrg Sets a thread's relative priority within the program. Valid 145*36ac495dSmrg options are: 146*36ac495dSmrg 147*36ac495dSmrg OBJC_THREAD_INTERACTIVE_PRIORITY 148*36ac495dSmrg OBJC_THREAD_BACKGROUND_PRIORITY 149*36ac495dSmrg OBJC_THREAD_LOW_PRIORITY 150*36ac495dSmrg 151*36ac495dSmrgobjc_thread_get_priority(void), int 152*36ac495dSmrg Query a thread's priority. 153*36ac495dSmrg 154*36ac495dSmrgobjc_thread_yield(void), void 155*36ac495dSmrg Yields processor to another thread with equal or higher 156*36ac495dSmrg priority. It is up to the system scheduler to determine if 157*36ac495dSmrg the processor is taken or not. 158*36ac495dSmrg 159*36ac495dSmrgobjc_thread_exit(void), int 160*36ac495dSmrg Terminates a thread. If this is the last thread executing 161*36ac495dSmrg then the program will terminate. 162*36ac495dSmrg 163*36ac495dSmrgobjc_thread_id(void), int 164*36ac495dSmrg Returns the current thread's id. 165*36ac495dSmrg 166*36ac495dSmrgobjc_thread_set_data(void *value), int 167*36ac495dSmrg Set a pointer to the thread's local storage. Local storage is 168*36ac495dSmrg thread specific. 169*36ac495dSmrg 170*36ac495dSmrgobjc_thread_get_data(void), void * 171*36ac495dSmrg Returns the pointer to the thread's local storage. 172*36ac495dSmrg 173*36ac495dSmrg***** 174*36ac495dSmrg* Backend thread functions 175*36ac495dSmrg* User programs should *NOT* directly call these functions. 176*36ac495dSmrg 177*36ac495dSmrg__gthr_objc_thread_detach(void (*func)(void *arg), void *arg), objc_thread_t 178*36ac495dSmrg Spawns a new thread executing func, called by objc_thread_detach. 179*36ac495dSmrg Return NULL if error otherwise return thread id. 180*36ac495dSmrg 181*36ac495dSmrg__gthr_objc_thread_set_priority(int priority), int 182*36ac495dSmrg Set the thread's priority, called by objc_thread_set_priority. 183*36ac495dSmrg Return -1 if error otherwise return 0. 184*36ac495dSmrg 185*36ac495dSmrg__gthr_objc_thread_get_priority(void), int 186*36ac495dSmrg Query a thread's priority, called by objc_thread_get_priority. 187*36ac495dSmrg Return -1 if error otherwise return the priority. 188*36ac495dSmrg 189*36ac495dSmrg__gthr_objc_thread_yield(void), void 190*36ac495dSmrg Yields the processor, called by objc_thread_yield. 191*36ac495dSmrg 192*36ac495dSmrg__gthr_objc_thread_exit(void), int 193*36ac495dSmrg Terminates the thread, called by objc_thread_exit. 194*36ac495dSmrg Return -1 if error otherwise function does not return. 195*36ac495dSmrg 196*36ac495dSmrg__gthr_objc_thread_id(void), objc_thread_t 197*36ac495dSmrg Returns the current thread's id, called by objc_thread_id. 198*36ac495dSmrg Return -1 if error otherwise return thread id. 199*36ac495dSmrg 200*36ac495dSmrg__gthr_objc_thread_set_data(void *value), int 201*36ac495dSmrg Set pointer for thread local storage, called by objc_thread_set_data. 202*36ac495dSmrg Returns -1 if error otherwise return 0. 203*36ac495dSmrg 204*36ac495dSmrg__gthr_objc_thread_get_data(void), void * 205*36ac495dSmrg Returns the pointer to the thread's local storage. 206*36ac495dSmrg Returns NULL if error, called by objc_thread_get_data. 207*36ac495dSmrg 208*36ac495dSmrg 209*36ac495dSmrg****************************************************************************** 210*36ac495dSmrg* Mutexes: 211*36ac495dSmrg 212*36ac495dSmrgMutexes can be locked recursively. Each locked mutex remembers 213*36ac495dSmrgits owner (by thread id) and how many times it has been locked. The 214*36ac495dSmrglast unlock on a mutex removes the system lock and allows other 215*36ac495dSmrgthreads to access the mutex. 216*36ac495dSmrg 217*36ac495dSmrg***** 218*36ac495dSmrg* Frontend mutex functions 219*36ac495dSmrg* User programs should use these functions. 220*36ac495dSmrg 221*36ac495dSmrgobjc_mutex_allocate(void), objc_mutex_t 222*36ac495dSmrg Allocates a new mutex. Mutex is initially unlocked. 223*36ac495dSmrg Return NULL if error otherwise return mutex pointer. 224*36ac495dSmrg 225*36ac495dSmrgobjc_mutex_deallocate(objc_mutex_t mutex), int 226*36ac495dSmrg Free a mutex. Before freeing the mutex, makes sure that no 227*36ac495dSmrg one else is using it. 228*36ac495dSmrg Return -1 if error otherwise return 0. 229*36ac495dSmrg 230*36ac495dSmrgobjc_mutex_lock(objc_mutex_t mutex), int 231*36ac495dSmrg Locks a mutex. As mentioned earlier, the same thread may call 232*36ac495dSmrg this routine repeatedly. 233*36ac495dSmrg Return -1 if error otherwise return 0. 234*36ac495dSmrg 235*36ac495dSmrgobjc_mutex_trylock(objc_mutex_t mutex), int 236*36ac495dSmrg Attempts to lock a mutex. If lock on mutex can be acquired 237*36ac495dSmrg then function operates exactly as objc_mutex_lock. 238*36ac495dSmrg Return -1 if failed to acquire lock otherwise return 0. 239*36ac495dSmrg 240*36ac495dSmrgobjc_mutex_unlock(objc_mutex_t mutex), int 241*36ac495dSmrg Unlocks the mutex by one level. Other threads may not acquire 242*36ac495dSmrg the mutex until this thread has released all locks on it. 243*36ac495dSmrg Return -1 if error otherwise return 0. 244*36ac495dSmrg 245*36ac495dSmrg***** 246*36ac495dSmrg* Backend mutex functions 247*36ac495dSmrg* User programs should *NOT* directly call these functions. 248*36ac495dSmrg 249*36ac495dSmrg__gthr_objc_mutex_allocate(objc_mutex_t mutex), int 250*36ac495dSmrg Allocates a new mutex, called by objc_mutex_allocate. 251*36ac495dSmrg Return -1 if error otherwise return 0. 252*36ac495dSmrg 253*36ac495dSmrg__gthr_objc_mutex_deallocate(objc_mutex_t mutex), int 254*36ac495dSmrg Free a mutex, called by objc_mutex_deallocate. 255*36ac495dSmrg Return -1 if error otherwise return 0. 256*36ac495dSmrg 257*36ac495dSmrg__gthr_objc_mutex_lock(objc_mutex_t mutex), int 258*36ac495dSmrg Locks a mutex, called by objc_mutex_lock. 259*36ac495dSmrg Return -1 if error otherwise return 0. 260*36ac495dSmrg 261*36ac495dSmrg__gthr_objc_mutex_trylock(objc_mutex_t mutex), int 262*36ac495dSmrg Attempts to lock a mutex, called by objc_mutex_trylock. 263*36ac495dSmrg Return -1 if failed to acquire lock or error otherwise return 0. 264*36ac495dSmrg 265*36ac495dSmrg__gthr_objc_mutex_unlock(objc_mutex_t mutex), int 266*36ac495dSmrg Unlocks the mutex, called by objc_mutex_unlock. 267*36ac495dSmrg Return -1 if error otherwise return 0. 268*36ac495dSmrg 269*36ac495dSmrg****************************************************************************** 270*36ac495dSmrg* Condition Mutexes: 271*36ac495dSmrg 272*36ac495dSmrgMutexes can be locked recursively. Each locked mutex remembers 273*36ac495dSmrgits owner (by thread id) and how many times it has been locked. The 274*36ac495dSmrglast unlock on a mutex removes the system lock and allows other 275*36ac495dSmrgthreads to access the mutex. 276*36ac495dSmrg 277*36ac495dSmrg* 278*36ac495dSmrg* Frontend condition mutex functions 279*36ac495dSmrg* User programs should use these functions. 280*36ac495dSmrg* 281*36ac495dSmrg 282*36ac495dSmrgobjc_condition_allocate(void), objc_condition_t 283*36ac495dSmrg Allocate a condition mutex. 284*36ac495dSmrg Return NULL if error otherwise return condition pointer. 285*36ac495dSmrg 286*36ac495dSmrgobjc_condition_deallocate(objc_condition_t condition), int 287*36ac495dSmrg Deallocate a condition. Note that this includes an implicit 288*36ac495dSmrg condition_broadcast to insure that waiting threads have the 289*36ac495dSmrg opportunity to wake. It is legal to dealloc a condition only 290*36ac495dSmrg if no other thread is/will be using it. Does NOT check for 291*36ac495dSmrg other threads waiting but just wakes them up. 292*36ac495dSmrg Return -1 if error otherwise return 0. 293*36ac495dSmrg 294*36ac495dSmrgobjc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int 295*36ac495dSmrg Wait on the condition unlocking the mutex until objc_condition_signal() 296*36ac495dSmrg or objc_condition_broadcast() are called for the same condition. The 297*36ac495dSmrg given mutex *must* have the depth 1 so that it can be unlocked 298*36ac495dSmrg here, for someone else can lock it and signal/broadcast the condition. 299*36ac495dSmrg The mutex is used to lock access to the shared data that make up the 300*36ac495dSmrg "condition" predicate. 301*36ac495dSmrg Return -1 if error otherwise return 0. 302*36ac495dSmrg 303*36ac495dSmrgobjc_condition_broadcast(objc_condition_t condition), int 304*36ac495dSmrg Wake up all threads waiting on this condition. It is recommended that 305*36ac495dSmrg the called would lock the same mutex as the threads in 306*36ac495dSmrg objc_condition_wait before changing the "condition predicate" 307*36ac495dSmrg and make this call and unlock it right away after this call. 308*36ac495dSmrg Return -1 if error otherwise return 0. 309*36ac495dSmrg 310*36ac495dSmrgobjc_condition_signal(objc_condition_t condition), int 311*36ac495dSmrg Wake up one thread waiting on this condition. 312*36ac495dSmrg Return -1 if error otherwise return 0. 313*36ac495dSmrg 314*36ac495dSmrg* 315*36ac495dSmrg* Backend condition mutex functions 316*36ac495dSmrg* User programs should *NOT* directly call these functions. 317*36ac495dSmrg* 318*36ac495dSmrg 319*36ac495dSmrg__gthr_objc_condition_allocate(objc_condition_t condition), int 320*36ac495dSmrg Allocate a condition mutex, called by objc_condition_allocate. 321*36ac495dSmrg Return -1 if error otherwise return 0. 322*36ac495dSmrg 323*36ac495dSmrg__gthr_objc_condition_deallocate(objc_condition_t condition), int 324*36ac495dSmrg Deallocate a condition, called by objc_condition_deallocate. 325*36ac495dSmrg Return -1 if error otherwise return 0. 326*36ac495dSmrg 327*36ac495dSmrg__gthr_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int 328*36ac495dSmrg Wait on the condition, called by objc_condition_wait. 329*36ac495dSmrg Return -1 if error otherwise return 0 when condition is met. 330*36ac495dSmrg 331*36ac495dSmrg__gthr_objc_condition_broadcast(objc_condition_t condition), int 332*36ac495dSmrg Wake up all threads waiting on this condition. 333*36ac495dSmrg Called by objc_condition_broadcast. 334*36ac495dSmrg Return -1 if error otherwise return 0. 335*36ac495dSmrg 336*36ac495dSmrg__gthr_objc_condition_signal(objc_condition_t condition), int 337*36ac495dSmrg Wake up one thread waiting on this condition. 338*36ac495dSmrg Called by objc_condition_signal. 339*36ac495dSmrg Return -1 if error otherwise return 0. 340