1 This file describes in little detail the modifications to the 2 Objective-C runtime needed to make it thread safe. 3 4 First off, kudos to Galen Hunt who is the author of this great work. 5 6 If you have an comments or just want to know where to 7 send me money to express your undying gratitude for threading the 8 Objective-C runtime you can reach Galen at: 9 10 gchunt (a] cs.rochester.edu 11 12 Any questions, comments, bug reports, etc. should send email either to the 13 GCC bug account or to: 14 15 Scott Christley <scottc (a] net-community.com> 16 17 * Sarray Threading: 18 19 The most critical component of the Objective-C runtime is the sparse array 20 structure (sarray). Sarrays store object selectors and implementations. 21 Following in the tradition of the Objective-C runtime, my threading 22 support assumes that fast message dispatching is far more important 23 than *ANY* and *ALL* other operations. The message dispatching thus 24 uses *NO* locks on any kind. In fact, if you look in sarray.h, you 25 will notice that the message dispatching has not been modified. 26 Instead, I have modified the sarray management functions so that all 27 updates to the sarray data structure can be made in parallel will 28 message dispatching. 29 30 To support concurrent message dispatching, no dynamically allocated 31 sarray data structures are freed while more than one thread is 32 operational. Sarray data structures that are no longer in use are 33 kept in a linked list of garbage and are released whenever the program 34 is operating with a single thread. The programmer can also flush the 35 garbage list by calling sarray_remove_garbage when the programmer can 36 ensure that no message dispatching is taking place concurrently. The 37 amount of un-reclaimed sarray garbage should normally be extremely 38 small in a real program as sarray structures are freed only when using 39 the "poseAs" functionality and early in program initialization, which 40 normally occurs while the program is single threaded. 41 42 ****************************************************************************** 43 * Static Variables: 44 45 The following variables are either statically or globally defined. This list 46 does not include variables which are internal to implementation dependent 47 versions of thread-*.c. 48 49 The 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 55 Variable 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 73 frwd_sel SAFE2 sendmsg.c 74 idxsize MUTEX sarray.c sendmsg.c sarray.h 75 initialize_sel SAFE2 sendmsg.c 76 narrays MUTEX sarray.c sendmsg.c sarray.h 77 nbuckets MUTEX sarray.c sendmsg.c sarray.h 78 nindices MUTEX sarray.c sarray.h 79 previous_constructors SAFE1 init.c 80 proto_class SAFE1 init.c 81 unclaimed_categories MUTEX init.c 82 unclaimed_proto_list MUTEX init.c 83 uninitialized_statics MUTEX init.c 84 85 Notes: 86 1) Initialized once in unithread mode. 87 2) Initialized value will always be same, guaranteed by lock on selector 88 hash table. 89 90 91 ****************************************************************************** 92 * Frontend/Backend design: 93 94 The design of the Objective-C runtime thread and mutex functions utilizes a 95 frontend/backend implementation. 96 97 The frontend, as characterized by the files thr.h and thr.c, is a set 98 of platform independent structures and functions which represent the 99 user interface. For example, objc_mutex_lock(). Objective-C programs 100 should use these structures and functions for their thread and mutex 101 work if they wish to maintain a high degree of portability across 102 platforms. 103 104 The backend is currently GCC's gthread code (gthr.h and related). For 105 example, __gthread_objc_mutex_lock(). The thread system is 106 automatically configured when GCC is configured. On most platforms 107 this thread backend is able to automatically switch to non-multi-threaded 108 mode if the threading library is not linked in. 109 110 If you want to compile libobjc standalone, then you would need to modify 111 the configure.ac and makefiles for it and you need to import the 112 gthread code from GCC. 113 114 ****************************************************************************** 115 * Threads: 116 117 The thread system attempts to create multiple threads using whatever 118 operating system or library thread support is available. It does 119 assume that all system functions are thread safe. Notably this means 120 that the system implementation of malloc and free must be thread safe. 121 If a system has multiple processors, the threads are configured for 122 full parallel processing. 123 124 * Backend initialization functions 125 126 __objc_init_thread_system(void), int 127 Initialize the thread subsystem. Called once by __objc_exec_class. 128 Return -1 if error otherwise return 0. 129 130 __objc_close_thread_system(void), int 131 Closes the thread subsystem, not currently guaranteed to be called. 132 Return -1 if error otherwise return 0. 133 134 ***** 135 * Frontend thread functions 136 * User programs should use these functions. 137 138 objc_thread_detach(SEL selector, id object, id argument), objc_thread_t 139 Creates and detaches a new thread. The new thread starts by 140 sending the given selector with a single argument to the 141 given object. 142 143 objc_thread_set_priority(int priority), int 144 Sets a thread's relative priority within the program. Valid 145 options are: 146 147 OBJC_THREAD_INTERACTIVE_PRIORITY 148 OBJC_THREAD_BACKGROUND_PRIORITY 149 OBJC_THREAD_LOW_PRIORITY 150 151 objc_thread_get_priority(void), int 152 Query a thread's priority. 153 154 objc_thread_yield(void), void 155 Yields processor to another thread with equal or higher 156 priority. It is up to the system scheduler to determine if 157 the processor is taken or not. 158 159 objc_thread_exit(void), int 160 Terminates a thread. If this is the last thread executing 161 then the program will terminate. 162 163 objc_thread_id(void), int 164 Returns the current thread's id. 165 166 objc_thread_set_data(void *value), int 167 Set a pointer to the thread's local storage. Local storage is 168 thread specific. 169 170 objc_thread_get_data(void), void * 171 Returns the pointer to the thread's local storage. 172 173 ***** 174 * Backend thread functions 175 * User programs should *NOT* directly call these functions. 176 177 __gthr_objc_thread_detach(void (*func)(void *arg), void *arg), objc_thread_t 178 Spawns a new thread executing func, called by objc_thread_detach. 179 Return NULL if error otherwise return thread id. 180 181 __gthr_objc_thread_set_priority(int priority), int 182 Set the thread's priority, called by objc_thread_set_priority. 183 Return -1 if error otherwise return 0. 184 185 __gthr_objc_thread_get_priority(void), int 186 Query a thread's priority, called by objc_thread_get_priority. 187 Return -1 if error otherwise return the priority. 188 189 __gthr_objc_thread_yield(void), void 190 Yields the processor, called by objc_thread_yield. 191 192 __gthr_objc_thread_exit(void), int 193 Terminates the thread, called by objc_thread_exit. 194 Return -1 if error otherwise function does not return. 195 196 __gthr_objc_thread_id(void), objc_thread_t 197 Returns the current thread's id, called by objc_thread_id. 198 Return -1 if error otherwise return thread id. 199 200 __gthr_objc_thread_set_data(void *value), int 201 Set pointer for thread local storage, called by objc_thread_set_data. 202 Returns -1 if error otherwise return 0. 203 204 __gthr_objc_thread_get_data(void), void * 205 Returns the pointer to the thread's local storage. 206 Returns NULL if error, called by objc_thread_get_data. 207 208 209 ****************************************************************************** 210 * Mutexes: 211 212 Mutexes can be locked recursively. Each locked mutex remembers 213 its owner (by thread id) and how many times it has been locked. The 214 last unlock on a mutex removes the system lock and allows other 215 threads to access the mutex. 216 217 ***** 218 * Frontend mutex functions 219 * User programs should use these functions. 220 221 objc_mutex_allocate(void), objc_mutex_t 222 Allocates a new mutex. Mutex is initially unlocked. 223 Return NULL if error otherwise return mutex pointer. 224 225 objc_mutex_deallocate(objc_mutex_t mutex), int 226 Free a mutex. Before freeing the mutex, makes sure that no 227 one else is using it. 228 Return -1 if error otherwise return 0. 229 230 objc_mutex_lock(objc_mutex_t mutex), int 231 Locks a mutex. As mentioned earlier, the same thread may call 232 this routine repeatedly. 233 Return -1 if error otherwise return 0. 234 235 objc_mutex_trylock(objc_mutex_t mutex), int 236 Attempts to lock a mutex. If lock on mutex can be acquired 237 then function operates exactly as objc_mutex_lock. 238 Return -1 if failed to acquire lock otherwise return 0. 239 240 objc_mutex_unlock(objc_mutex_t mutex), int 241 Unlocks the mutex by one level. Other threads may not acquire 242 the mutex until this thread has released all locks on it. 243 Return -1 if error otherwise return 0. 244 245 ***** 246 * Backend mutex functions 247 * User programs should *NOT* directly call these functions. 248 249 __gthr_objc_mutex_allocate(objc_mutex_t mutex), int 250 Allocates a new mutex, called by objc_mutex_allocate. 251 Return -1 if error otherwise return 0. 252 253 __gthr_objc_mutex_deallocate(objc_mutex_t mutex), int 254 Free a mutex, called by objc_mutex_deallocate. 255 Return -1 if error otherwise return 0. 256 257 __gthr_objc_mutex_lock(objc_mutex_t mutex), int 258 Locks a mutex, called by objc_mutex_lock. 259 Return -1 if error otherwise return 0. 260 261 __gthr_objc_mutex_trylock(objc_mutex_t mutex), int 262 Attempts to lock a mutex, called by objc_mutex_trylock. 263 Return -1 if failed to acquire lock or error otherwise return 0. 264 265 __gthr_objc_mutex_unlock(objc_mutex_t mutex), int 266 Unlocks the mutex, called by objc_mutex_unlock. 267 Return -1 if error otherwise return 0. 268 269 ****************************************************************************** 270 * Condition Mutexes: 271 272 Mutexes can be locked recursively. Each locked mutex remembers 273 its owner (by thread id) and how many times it has been locked. The 274 last unlock on a mutex removes the system lock and allows other 275 threads to access the mutex. 276 277 * 278 * Frontend condition mutex functions 279 * User programs should use these functions. 280 * 281 282 objc_condition_allocate(void), objc_condition_t 283 Allocate a condition mutex. 284 Return NULL if error otherwise return condition pointer. 285 286 objc_condition_deallocate(objc_condition_t condition), int 287 Deallocate a condition. Note that this includes an implicit 288 condition_broadcast to insure that waiting threads have the 289 opportunity to wake. It is legal to dealloc a condition only 290 if no other thread is/will be using it. Does NOT check for 291 other threads waiting but just wakes them up. 292 Return -1 if error otherwise return 0. 293 294 objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int 295 Wait on the condition unlocking the mutex until objc_condition_signal() 296 or objc_condition_broadcast() are called for the same condition. The 297 given mutex *must* have the depth 1 so that it can be unlocked 298 here, for someone else can lock it and signal/broadcast the condition. 299 The mutex is used to lock access to the shared data that make up the 300 "condition" predicate. 301 Return -1 if error otherwise return 0. 302 303 objc_condition_broadcast(objc_condition_t condition), int 304 Wake up all threads waiting on this condition. It is recommended that 305 the called would lock the same mutex as the threads in 306 objc_condition_wait before changing the "condition predicate" 307 and make this call and unlock it right away after this call. 308 Return -1 if error otherwise return 0. 309 310 objc_condition_signal(objc_condition_t condition), int 311 Wake up one thread waiting on this condition. 312 Return -1 if error otherwise return 0. 313 314 * 315 * Backend condition mutex functions 316 * User programs should *NOT* directly call these functions. 317 * 318 319 __gthr_objc_condition_allocate(objc_condition_t condition), int 320 Allocate a condition mutex, called by objc_condition_allocate. 321 Return -1 if error otherwise return 0. 322 323 __gthr_objc_condition_deallocate(objc_condition_t condition), int 324 Deallocate a condition, called by objc_condition_deallocate. 325 Return -1 if error otherwise return 0. 326 327 __gthr_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int 328 Wait on the condition, called by objc_condition_wait. 329 Return -1 if error otherwise return 0 when condition is met. 330 331 __gthr_objc_condition_broadcast(objc_condition_t condition), int 332 Wake up all threads waiting on this condition. 333 Called by objc_condition_broadcast. 334 Return -1 if error otherwise return 0. 335 336 __gthr_objc_condition_signal(objc_condition_t condition), int 337 Wake up one thread waiting on this condition. 338 Called by objc_condition_signal. 339 Return -1 if error otherwise return 0. 340