1 This file describes in little detail the modifications to the
2 Objective-C runtime needed to make it thread safe.
4 First off, kudos to Galen Hunt who is the author of this great work.
6 If you have an comments or just want to know where to
7 send me money to express your undying graditude for threading the
8 Objective-C runtime you can reach Galen at:
10 gchunt@cs.rochester.edu
12 Any questions, comments, bug reports, etc. should send email either to the
13 GCC bug account or to:
15 Scott Christley <scottc@net-community.com>
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
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.
42 ******************************************************************************
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.
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.
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
86 1) Initialized once in unithread mode.
87 2) Initialized value will always be same, guaranteed by lock on selector
91 ******************************************************************************
92 * Frontend/Backend design:
94 The design of the Objective-C runtime thread and mutex functions utilizes a
95 frontend/backend implementation.
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. Objective-C programs should use these structures and
100 functions for their thread and mutex work if they wish to maintain a
101 high degree of portability across platforms.
103 The backend is composed of a file with the necessary code to map the ObjC
104 thread and mutex to a platform specific implementation. For example, the
105 file thr-solaris.c contains the implementation for Solaris. When you
106 configure GCC, it attempts to pick an appropriate backend file for the
107 target platform; however, you can override this choice by assign the
108 OBJC_THREAD_FILE make variable to the basename of the backend file. This
109 is especially useful on platforms which have multiple thread libraries.
112 make OBJC_THREAD_FILE=thr-posix
114 would indicate that the generic posix backend file, thr-posix.c, should be
115 compiled with the ObjC runtime library. If your platform does not support
116 threads then you should specify the OBJC_THREAD_FILE=thr-single backend file
117 to compile the ObjC runtime library without thread or mutex support; note
118 that programs which rely upon the ObjC thread and mutex functions will
119 compile and link correctly but attempting to create a thread or mutex will
122 It is questionable whether it is really necessary to have both a
123 frontend and backend function for all available functionality. On the
124 one hand, it provides a clear, consistent differentiation between what
125 is public and what is private with the downside of having the overhead
126 of multiple functions calls. For example, the function to have a thread
127 yield the processor is objc_thread_yield; in the current implementation
128 this produces a function call set:
130 objc_thread_yield() -> __objc_thread_yield() -> system yield function
132 This has two extra function calls over calling the platform specific function
133 explicitly, but the issue is whether only the overhead of a single function
136 objc_thread_yield() -> system yield function
138 This breaks the public/private dichotomy between the frontend/backend
139 for the sake of efficiency. It is possible to just use a preprocessor
140 define so as to eliminate the extra function call:
142 #define objc_thread_yield() __objc_thread_yield()
144 This has the undesirable effect that if objc_thread_yield is actually
145 turned into a function based upon future need; then ObjC programs which
146 access the thread functions would need to be recompiled versus just
149 ******************************************************************************
152 The thread system attempts to create multiple threads using whatever
153 operating system or library thread support is available. It does
154 assume that all system functions are thread safe. Notably this means
155 that the system implementation of malloc and free must be thread safe.
156 If a system has multiple processors, the threads are configured for
157 full parallel processing.
159 * Backend initialization functions
161 __objc_init_thread_system(void), int
162 Initialize the thread subsystem. Called once by __objc_exec_class.
163 Return -1 if error otherwise return 0.
165 __objc_close_thread_system(void), int
166 Closes the thread subsystem, not currently guaranteed to be called.
167 Return -1 if error otherwise return 0.
170 * Frontend thread functions
171 * User programs should use these functions.
173 objc_thread_detach(SEL selector, id object, id argument), objc_thread_t
174 Creates and detaches a new thread. The new thread starts by
175 sending the given selector with a single argument to the
178 objc_thread_set_priority(int priority), int
179 Sets a thread's relative priority within the program. Valid
182 OBJC_THREAD_INTERACTIVE_PRIORITY
183 OBJC_THREAD_BACKGROUND_PRIORITY
184 OBJC_THREAD_LOW_PRIORITY
186 objc_thread_get_priority(void), int
187 Query a thread's priority.
189 objc_thread_yield(void), void
190 Yields processor to another thread with equal or higher
191 priority. It is up to the system scheduler to determine if
192 the processor is taken or not.
194 objc_thread_exit(void), int
195 Terminates a thread. If this is the last thread executing
196 then the program will terminate.
198 objc_thread_id(void), int
199 Returns the current thread's id.
201 objc_thread_set_data(void *value), int
202 Set a pointer to the thread's local storage. Local storage is
205 objc_thread_get_data(void), void *
206 Returns the pointer to the thread's local storage.
209 * Backend thread functions
210 * User programs should *NOT* directly call these functions.
212 __objc_thread_detach(void (*func)(void *arg), void *arg), objc_thread_t
213 Spawns a new thread executing func, called by objc_thread_detach.
214 Return NULL if error otherwise return thread id.
216 __objc_thread_set_priority(int priority), int
217 Set the thread's priority, called by objc_thread_set_priority.
218 Return -1 if error otherwise return 0.
220 __objc_thread_get_priority(void), int
221 Query a thread's priority, called by objc_thread_get_priority.
222 Return -1 if error otherwise return the priority.
224 __objc_thread_yield(void), void
225 Yields the processor, called by objc_thread_yield.
227 __objc_thread_exit(void), int
228 Terminates the thread, called by objc_thread_exit.
229 Return -1 if error otherwise function does not return.
231 __objc_thread_id(void), objc_thread_t
232 Returns the current thread's id, called by objc_thread_id.
233 Return -1 if error otherwise return thread id.
235 __objc_thread_set_data(void *value), int
236 Set pointer for thread local storage, called by objc_thread_set_data.
237 Returns -1 if error otherwise return 0.
239 __objc_thread_get_data(void), void *
240 Returns the pointer to the thread's local storage.
241 Returns NULL if error, called by objc_thread_get_data.
244 ******************************************************************************
247 Mutexs can be locked recursively. Each locked mutex remembers
248 its owner (by thread id) and how many times it has been locked. The
249 last unlock on a mutex removes the system lock and allows other
250 threads to access the mutex.
253 * Frontend mutex functions
254 * User programs should use these functions.
256 objc_mutex_allocate(void), objc_mutex_t
257 Allocates a new mutex. Mutex is initially unlocked.
258 Return NULL if error otherwise return mutex pointer.
260 objc_mutex_deallocate(objc_mutex_t mutex), int
261 Free a mutex. Before freeing the mutex, makes sure that no
262 one else is using it.
263 Return -1 if error otherwise return 0.
265 objc_mutex_lock(objc_mutex_t mutex), int
266 Locks a mutex. As mentioned earlier, the same thread may call
267 this routine repeatedly.
268 Return -1 if error otherwise return 0.
270 objc_mutex_trylock(objc_mutex_t mutex), int
271 Attempts to lock a mutex. If lock on mutex can be acquired
272 then function operates exactly as objc_mutex_lock.
273 Return -1 if failed to acquire lock otherwise return 0.
275 objc_mutex_unlock(objc_mutex_t mutex), int
276 Unlocks the mutex by one level. Other threads may not acquire
277 the mutex until this thread has released all locks on it.
278 Return -1 if error otherwise return 0.
281 * Backend mutex functions
282 * User programs should *NOT* directly call these functions.
284 __objc_mutex_allocate(objc_mutex_t mutex), int
285 Allocates a new mutex, called by objc_mutex_allocate.
286 Return -1 if error otherwise return 0.
288 __objc_mutex_deallocate(objc_mutex_t mutex), int
289 Free a mutex, called by objc_mutex_deallocate.
290 Return -1 if error otherwise return 0.
292 __objc_mutex_lock(objc_mutex_t mutex), int
293 Locks a mutex, called by objc_mutex_lock.
294 Return -1 if error otherwise return 0.
296 __objc_mutex_trylock(objc_mutex_t mutex), int
297 Attempts to lock a mutex, called by objc_mutex_trylock.
298 Return -1 if failed to acquire lock or error otherwise return 0.
300 __objc_mutex_unlock(objc_mutex_t mutex), int
301 Unlocks the mutex, called by objc_mutex_unlock.
302 Return -1 if error otherwise return 0.
304 ******************************************************************************
307 Mutexs can be locked recursively. Each locked mutex remembers
308 its owner (by thread id) and how many times it has been locked. The
309 last unlock on a mutex removes the system lock and allows other
310 threads to access the mutex.
313 * Frontend condition mutex functions
314 * User programs should use these functions.
317 objc_condition_allocate(void), objc_condition_t
318 Allocate a condition mutex.
319 Return NULL if error otherwise return condition pointer.
321 objc_condition_deallocate(objc_condition_t condition), int
322 Deallocate a condition. Note that this includes an implicit
323 condition_broadcast to insure that waiting threads have the
324 opportunity to wake. It is legal to dealloc a condition only
325 if no other thread is/will be using it. Does NOT check for
326 other threads waiting but just wakes them up.
327 Return -1 if error otherwise return 0.
329 objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int
330 Wait on the condition unlocking the mutex until objc_condition_signal()
331 or objc_condition_broadcast() are called for the same condition. The
332 given mutex *must* have the depth 1 so that it can be unlocked
333 here, for someone else can lock it and signal/broadcast the condition.
334 The mutex is used to lock access to the shared data that make up the
335 "condition" predicate.
336 Return -1 if error otherwise return 0.
338 objc_condition_broadcast(objc_condition_t condition), int
339 Wake up all threads waiting on this condition. It is recommended that
340 the called would lock the same mutex as the threads in
341 objc_condition_wait before changing the "condition predicate"
342 and make this call and unlock it right away after this call.
343 Return -1 if error otherwise return 0.
345 objc_condition_signal(objc_condition_t condition), int
346 Wake up one thread waiting on this condition.
347 Return -1 if error otherwise return 0.
350 * Backend condition mutex functions
351 * User programs should *NOT* directly call these functions.
354 __objc_condition_allocate(objc_condition_t condition), int
355 Allocate a condition mutex, called by objc_condition_allocate.
356 Return -1 if error otherwise return 0.
358 __objc_condition_deallocate(objc_condition_t condition), int
359 Deallocate a condition, called by objc_condition_deallocate.
360 Return -1 if error otherwise return 0.
362 __objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex), int
363 Wait on the condition, called by objc_condition_wait.
364 Return -1 if error otherwise return 0 when condition is met.
366 __objc_condition_broadcast(objc_condition_t condition), int
367 Wake up all threads waiting on this condition.
368 Called by objc_condition_broadcast.
369 Return -1 if error otherwise return 0.
371 __objc_condition_signal(objc_condition_t condition), int
372 Wake up one thread waiting on this condition.
373 Called by objc_condition_signal.
374 Return -1 if error otherwise return 0.