111
|
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@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@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.
|