1This file describes in little detail the modifications to the 2Objective-C runtime needed to make it thread safe. 3 4First off, kudos to Galen Hunt who is the author of this great work. 5 6If you have an comments or just want to know where to 7send me money to express your undying gratitude for threading the 8Objective-C runtime you can reach Galen at: 9 10 gchunt@cs.rochester.edu 11 12Any questions, comments, bug reports, etc. should send email either to the 13GCC bug account or to: 14 15 Scott Christley <scottc@net-community.com> 16 17* Sarray Threading: 18 19The most critical component of the Objective-C runtime is the sparse array 20structure (sarray). Sarrays store object selectors and implementations. 21Following in the tradition of the Objective-C runtime, my threading 22support assumes that fast message dispatching is far more important 23than *ANY* and *ALL* other operations. The message dispatching thus 24uses *NO* locks on any kind. In fact, if you look in sarray.h, you 25will notice that the message dispatching has not been modified. 26Instead, I have modified the sarray management functions so that all 27updates to the sarray data structure can be made in parallel will 28message dispatching. 29 30To support concurrent message dispatching, no dynamically allocated 31sarray data structures are freed while more than one thread is 32operational. Sarray data structures that are no longer in use are 33kept in a linked list of garbage and are released whenever the program 34is operating with a single thread. The programmer can also flush the 35garbage list by calling sarray_remove_garbage when the programmer can 36ensure that no message dispatching is taking place concurrently. The 37amount of un-reclaimed sarray garbage should normally be extremely 38small in a real program as sarray structures are freed only when using 39the "poseAs" functionality and early in program initialization, which 40normally occurs while the program is single threaded. 41 42****************************************************************************** 43* Static Variables: 44 45The following variables are either statically or globally defined. This list 46does not include variables which are internal to implementation dependent 47versions of thread-*.c. 48 49The following threading designations are used: 50 SAFE : Implicitly thread safe. 51 SINGLE : Must only be used in single thread mode. 52 MUTEX : Protected by single global mutex objc_runtime_mutex. 53 UNUSED : Not used in the runtime. 54 55Variable Name: Usage: Defined: Also used in: 56=========================== ====== ============ ===================== 57__objc_class_hash MUTEX class.c 58__objc_class_links_resolved UNUSED class.c runtime.h 59__objc_class_number MUTEX class.c 60__objc_dangling_categories UNUSED init.c 61__objc_module_list MUTEX init.c 62__objc_selector_array MUTEX selector.c 63__objc_selector_hash MUTEX selector.c 64__objc_selector_max_index MUTEX selector.c sendmsg.c runtime.h 65__objc_selector_names MUTEX selector.c 66__objc_thread_exit_status SAFE thread.c 67__objc_uninstalled_dtable MUTEX sendmsg.c selector.c 68_objc_load_callback SAFE init.c objc-api.h 69_objc_lookup_class SAFE class.c objc-api.h 70_objc_object_alloc SINGLE objects.c objc-api.h 71_objc_object_copy SINGLE objects.c objc-api.h 72_objc_object_dispose SINGLE objects.c objc-api.h 73frwd_sel SAFE2 sendmsg.c 74idxsize MUTEX sarray.c sendmsg.c sarray.h 75initialize_sel SAFE2 sendmsg.c 76narrays MUTEX sarray.c sendmsg.c sarray.h 77nbuckets MUTEX sarray.c sendmsg.c sarray.h 78nindices MUTEX sarray.c sarray.h 79previous_constructors SAFE1 init.c 80proto_class SAFE1 init.c 81unclaimed_categories MUTEX init.c 82unclaimed_proto_list MUTEX init.c 83uninitialized_statics MUTEX init.c 84 85Notes: 861) Initialized once in unithread mode. 872) Initialized value will always be same, guaranteed by lock on selector 88 hash table. 89 90 91****************************************************************************** 92* Frontend/Backend design: 93 94The design of the Objective-C runtime thread and mutex functions utilizes a 95frontend/backend implementation. 96 97The frontend, as characterized by the files thr.h and thr.c, is a set 98of platform independent structures and functions which represent the 99user interface. Objective-C programs should use these structures and 100functions for their thread and mutex work if they wish to maintain a 101high degree of portability across platforms. 102 103The backend is composed of a file with the necessary code to map the ObjC 104thread and mutex to a platform specific implementation. For example, the 105file thr-solaris.c contains the implementation for Solaris. 106 107If you are compiling libobjc as part of GCC, the thr-objc.c backend is 108always used; this backend uses GCC's gthread code. The thread system 109is automatically configured when GCC is configured. Important: make 110sure you configure GCC using `--enable-threads' if you want threads ! 111 112If you want to compile libobjc standalone, then you would need to 113modify the configure.in and makefiles for it; and you need to pick an 114appropriate backend file for the target platform; you make this choice 115by assigning the OBJC_THREAD_FILE make variable to the basename of the 116backend file. For example, OBJC_THREAD_FILE=thr-posix would indicate 117that the generic posix backend file, thr-posix.c, should be compiled 118with the ObjC runtime library. If your platform does not support 119threads then you should specify the OBJC_THREAD_FILE=thr-single 120backend file to compile the ObjC runtime library without thread or 121mutex support; note that programs which rely upon the ObjC thread and 122mutex functions will compile and link correctly but attempting to 123create a thread or mutex will result in an error. 124 125It is questionable whether it is really necessary to have both a 126frontend and backend function for all available functionality. On the 127one hand, it provides a clear, consistent differentiation between what 128is public and what is private with the downside of having the overhead 129of multiple functions calls. For example, the function to have a 130thread yield the processor is objc_thread_yield; in the current 131implementation this produces a function call set: 132 133objc_thread_yield() -> __objc_thread_yield() -> system yield function 134 135This has two extra function calls over calling the platform specific function 136explicitly, but the issue is whether only the overhead of a single function 137is necessary. 138 139objc_thread_yield() -> system yield function 140 141This breaks the public/private dichotomy between the frontend/backend 142for the sake of efficiency. It is possible to just use a preprocessor 143define so as to eliminate the extra function call: 144 145#define objc_thread_yield() __objc_thread_yield() 146 147This has the undesirable effect that if objc_thread_yield is actually 148turned into a function based upon future need; then ObjC programs which 149access the thread functions would need to be recompiled versus just 150being relinked. 151 152****************************************************************************** 153* Threads: 154 155The thread system attempts to create multiple threads using whatever 156operating system or library thread support is available. It does 157assume that all system functions are thread safe. Notably this means 158that the system implementation of malloc and free must be thread safe. 159If a system has multiple processors, the threads are configured for 160full parallel processing. 161 162* Backend initialization functions 163 164__objc_init_thread_system(void), int 165 Initialize the thread subsystem. Called once by __objc_exec_class. 166 Return -1 if error otherwise return 0. 167 168__objc_close_thread_system(void), int 169 Closes the thread subsystem, not currently guaranteed to be called. 170 Return -1 if error otherwise return 0. 171 172***** 173* Frontend thread functions 174* User programs should use these functions. 175 176objc_thread_detach(SEL selector, id object, id argument), objc_thread_t 177 Creates and detaches a new thread. The new thread starts by 178 sending the given selector with a single argument to the 179 given object. 180 181objc_thread_set_priority(int priority), int 182 Sets a thread's relative priority within the program. Valid 183 options are: 184 185 OBJC_THREAD_INTERACTIVE_PRIORITY 186 OBJC_THREAD_BACKGROUND_PRIORITY 187 OBJC_THREAD_LOW_PRIORITY 188 189objc_thread_get_priority(void), int 190 Query a thread's priority. 191 192objc_thread_yield(void), void 193 Yields processor to another thread with equal or higher 194 priority. It is up to the system scheduler to determine if 195 the processor is taken or not. 196 197objc_thread_exit(void), int 198 Terminates a thread. If this is the last thread executing 199 then the program will terminate. 200 201objc_thread_id(void), int 202 Returns the current thread's id. 203 204objc_thread_set_data(void *value), int 205 Set a pointer to the thread's local storage. Local storage is 206 thread specific. 207 208objc_thread_get_data(void), void * 209 Returns the pointer to the thread's local storage. 210 211***** 212* Backend thread functions 213* User programs should *NOT* directly call these functions. 214 215__objc_thread_detach(void (*func)(void *arg), void *arg), objc_thread_t 216 Spawns a new thread executing func, called by objc_thread_detach. 217 Return NULL if error otherwise return thread id. 218 219__objc_thread_set_priority(int priority), int 220 Set the thread's priority, called by objc_thread_set_priority. 221 Return -1 if error otherwise return 0. 222 223__objc_thread_get_priority(void), int 224 Query a thread's priority, called by objc_thread_get_priority. 225 Return -1 if error otherwise return the priority. 226 227__objc_thread_yield(void), void 228 Yields the processor, called by objc_thread_yield. 229 230__objc_thread_exit(void), int 231 Terminates the thread, called by objc_thread_exit. 232 Return -1 if error otherwise function does not return. 233 234__objc_thread_id(void), objc_thread_t 235 Returns the current thread's id, called by objc_thread_id. 236 Return -1 if error otherwise return thread id. 237 238__objc_thread_set_data(void *value), int 239 Set pointer for thread local storage, called by objc_thread_set_data. 240 Returns -1 if error otherwise return 0. 241 242__objc_thread_get_data(void), void * 243 Returns the pointer to the thread's local storage. 244 Returns NULL if error, called by objc_thread_get_data. 245 246 247****************************************************************************** 248* Mutexes: 249 250Mutexes can be locked recursively. Each locked mutex remembers 251its owner (by thread id) and how many times it has been locked. The 252last unlock on a mutex removes the system lock and allows other 253threads to access the mutex. 254 255***** 256* Frontend mutex functions 257* User programs should use these functions. 258 259objc_mutex_allocate(void), objc_mutex_t 260 Allocates a new mutex. Mutex is initially unlocked. 261 Return NULL if error otherwise return mutex pointer. 262 263objc_mutex_deallocate(objc_mutex_t mutex), int 264 Free a mutex. Before freeing the mutex, makes sure that no 265 one else is using it. 266 Return -1 if error otherwise return 0. 267 268objc_mutex_lock(objc_mutex_t mutex), int 269 Locks a mutex. As mentioned earlier, the same thread may call 270 this routine repeatedly. 271 Return -1 if error otherwise return 0. 272 273objc_mutex_trylock(objc_mutex_t mutex), int 274 Attempts to lock a mutex. If lock on mutex can be acquired 275 then function operates exactly as objc_mutex_lock. 276 Return -1 if failed to acquire lock otherwise return 0. 277 278objc_mutex_unlock(objc_mutex_t mutex), int 279 Unlocks the mutex by one level. Other threads may not acquire 280 the mutex until this thread has released all locks on it. 281 Return -1 if error otherwise return 0. 282 283***** 284* Backend mutex functions 285* User programs should *NOT* directly call these functions. 286 287__objc_mutex_allocate(objc_mutex_t mutex), int 288 Allocates a new mutex, called by objc_mutex_allocate. 289 Return -1 if error otherwise return 0. 290 291__objc_mutex_deallocate(objc_mutex_t mutex), int 292 Free a mutex, called by objc_mutex_deallocate. 293 Return -1 if error otherwise return 0. 294 295__objc_mutex_lock(objc_mutex_t mutex), int 296 Locks a mutex, called by objc_mutex_lock. 297 Return -1 if error otherwise return 0. 298 299__objc_mutex_trylock(objc_mutex_t mutex), int 300 Attempts to lock a mutex, called by objc_mutex_trylock. 301 Return -1 if failed to acquire lock or error otherwise return 0. 302 303__objc_mutex_unlock(objc_mutex_t mutex), int 304 Unlocks the mutex, called by objc_mutex_unlock. 305 Return -1 if error otherwise return 0. 306 307****************************************************************************** 308* Condition Mutexes: 309 310Mutexes can be locked recursively. Each locked mutex remembers 311its owner (by thread id) and how many times it has been locked. The 312last unlock on a mutex removes the system lock and allows other 313threads to access the mutex. 314 315* 316* Frontend condition mutex functions 317* User programs should use these functions. 318* 319 320objc_condition_allocate(void), objc_condition_t 321 Allocate a condition mutex. 322 Return NULL if error otherwise return condition pointer. 323 324objc_condition_deallocate(objc_condition_t condition), int 325 Deallocate a condition. Note that this includes an implicit 326 condition_broadcast to insure that waiting threads have the 327 opportunity to wake. It is legal to dealloc a condition only 328 if no other thread is/will be using it. Does NOT check for 329 other threads waiting but just wakes them up. 330 Return -1 if error otherwise return 0. 331 332objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int 333 Wait on the condition unlocking the mutex until objc_condition_signal() 334 or objc_condition_broadcast() are called for the same condition. The 335 given mutex *must* have the depth 1 so that it can be unlocked 336 here, for someone else can lock it and signal/broadcast the condition. 337 The mutex is used to lock access to the shared data that make up the 338 "condition" predicate. 339 Return -1 if error otherwise return 0. 340 341objc_condition_broadcast(objc_condition_t condition), int 342 Wake up all threads waiting on this condition. It is recommended that 343 the called would lock the same mutex as the threads in 344 objc_condition_wait before changing the "condition predicate" 345 and make this call and unlock it right away after this call. 346 Return -1 if error otherwise return 0. 347 348objc_condition_signal(objc_condition_t condition), int 349 Wake up one thread waiting on this condition. 350 Return -1 if error otherwise return 0. 351 352* 353* Backend condition mutex functions 354* User programs should *NOT* directly call these functions. 355* 356 357__objc_condition_allocate(objc_condition_t condition), int 358 Allocate a condition mutex, called by objc_condition_allocate. 359 Return -1 if error otherwise return 0. 360 361__objc_condition_deallocate(objc_condition_t condition), int 362 Deallocate a condition, called by objc_condition_deallocate. 363 Return -1 if error otherwise return 0. 364 365__objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int 366 Wait on the condition, called by objc_condition_wait. 367 Return -1 if error otherwise return 0 when condition is met. 368 369__objc_condition_broadcast(objc_condition_t condition), int 370 Wake up all threads waiting on this condition. 371 Called by objc_condition_broadcast. 372 Return -1 if error otherwise return 0. 373 374__objc_condition_signal(objc_condition_t condition), int 375 Wake up one thread waiting on this condition. 376 Called by objc_condition_signal. 377 Return -1 if error otherwise return 0. 378