OSDN Git Service

* doc/tm.texi.in (Cond. Exec. Macros): Rename node from this ...
[pf3gnuchains/gcc-fork.git] / libobjc / thr.c
1 /* GNU Objective C Runtime Thread Interface
2    Copyright (C) 1996, 1997, 2009, 2010 Free Software Foundation, Inc.
3    Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 3, or (at your option) any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14 details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 <http://www.gnu.org/licenses/>.  */
24
25 #include "objc-private/common.h"
26 #include "objc-private/error.h"
27 #define _LIBOBJC
28 /* The line below is needed for declarations of functions such as
29    pthread_mutexattr_settype, without which gthr-posix.h may fail to
30    compile within libobjc.  Unfortunately, this breaks compilation on
31    Tru64 UNIX V4.0F, so disable it there.  */
32 #ifndef __osf__
33 #define _XOPEN_SOURCE 500
34 #endif
35 #include "config.h"
36 #include "tconfig.h"
37 #include "coretypes.h"
38 #include "tm.h"
39 #include "defaults.h"
40 #include "objc/thr.h"
41 #include "objc/runtime.h"
42 #include "objc-private/runtime.h"
43 #include <gthr.h>
44
45 #include <stdlib.h>
46
47 /* Global exit status. */
48 int __objc_thread_exit_status = 0;
49
50 /* Flag which lets us know if we ever became multi threaded */
51 int __objc_is_multi_threaded = 0;
52
53 /* The hook function called when the runtime becomes multi threaded */
54 objc_thread_callback _objc_became_multi_threaded = NULL;
55
56 /*
57   Use this to set the hook function that will be called when the 
58   runtime initially becomes multi threaded.
59   The hook function is only called once, meaning only when the 
60   2nd thread is spawned, not for each and every thread.
61
62   It returns the previous hook function or NULL if there is none.
63
64   A program outside of the runtime could set this to some function so
65   it can be informed; for example, the GNUstep Base Library sets it 
66   so it can implement the NSBecomingMultiThreaded notification.
67   */
68 objc_thread_callback objc_set_thread_callback (objc_thread_callback func)
69 {
70   objc_thread_callback temp = _objc_became_multi_threaded;
71   _objc_became_multi_threaded = func;
72   return temp;
73 }
74
75 /*
76   Private functions
77
78   These functions are utilized by the frontend, but they are not
79   considered part of the public interface.
80   */
81
82 /* Initialize the threads subsystem. */
83 int
84 __objc_init_thread_system(void)
85 {
86   return __gthread_objc_init_thread_system ();
87 }
88
89 /*
90   First function called in a thread, starts everything else.
91
92   This function is passed to the backend by objc_thread_detach
93   as the starting function for a new thread.
94  */
95 struct __objc_thread_start_state
96 {
97   SEL selector;
98   id object;
99   id argument;
100 };
101
102 static void __attribute__((noreturn))
103 __objc_thread_detach_function (struct __objc_thread_start_state *istate) 
104 {
105   /* Valid state? */
106   if (istate) {
107     id (*imp) (id, SEL, id);
108     SEL selector = istate->selector;
109     id object   = istate->object;
110     id argument = istate->argument;
111
112     /* Don't need anymore so free it */
113     objc_free (istate);
114
115     /* Clear out the thread local storage */
116     objc_thread_set_data (NULL);
117
118     /* Check to see if we just became multi threaded */
119     if (! __objc_is_multi_threaded)
120       {
121         __objc_is_multi_threaded = 1;
122
123         /* Call the hook function */
124         if (_objc_became_multi_threaded != NULL)
125           (*_objc_became_multi_threaded) ();
126       }
127
128     /* Call the method */
129     if ((imp = (id (*) (id, SEL, id))objc_msg_lookup (object, selector)))
130         (*imp) (object, selector, argument);
131     else
132       {
133         /* FIXME: Should we abort here ? */
134         _objc_abort ("objc_thread_detach called with bad selector.\n");
135       }
136   }
137   else
138     {
139       /* FIXME: Should we abort here ? */
140       _objc_abort ("objc_thread_detach called with NULL state.\n");
141     }
142
143   /* Exit the thread */
144   objc_thread_exit ();
145   
146   /* Make sure compiler detects no return.  */
147   __builtin_trap ();
148 }
149
150 /*
151   Frontend functions
152
153   These functions constitute the public interface to the Objective-C thread
154   and mutex functionality.
155   */
156
157 /* Frontend thread functions */
158
159 /*
160   Detach a new thread of execution and return its id.  Returns NULL if fails.
161   Thread is started by sending message with selector to object.  Message
162   takes a single argument.
163   */
164 objc_thread_t
165 objc_thread_detach (SEL selector, id object, id argument)
166 {
167   struct __objc_thread_start_state *istate;
168   objc_thread_t        thread_id = NULL;
169
170   /* Allocate the state structure */
171   if (! (istate = (struct __objc_thread_start_state *)
172          objc_malloc (sizeof (*istate))))
173     return NULL;
174
175   /* Initialize the state structure */
176   istate->selector = selector;
177   istate->object = object;
178   istate->argument = argument;
179
180   /* lock access */
181   objc_mutex_lock (__objc_runtime_mutex);
182
183   /* Call the backend to spawn the thread */
184   if ((thread_id = __gthread_objc_thread_detach ((void *)__objc_thread_detach_function,
185                                                  istate)) == NULL)
186     {
187       /* failed! */
188       objc_mutex_unlock (__objc_runtime_mutex);
189       objc_free (istate);
190       return NULL;
191     }
192
193   /* Increment our thread counter */
194   __objc_runtime_threads_alive++;
195   objc_mutex_unlock (__objc_runtime_mutex);
196
197   return thread_id;
198 }
199
200 /* Set the current thread's priority. */
201 int
202 objc_thread_set_priority (int priority)
203 {
204   /* Call the backend */
205   return __gthread_objc_thread_set_priority (priority);
206 }
207
208 /* Return the current thread's priority. */
209 int
210 objc_thread_get_priority (void)
211 {
212   /* Call the backend */
213   return __gthread_objc_thread_get_priority ();
214 }
215
216 /*
217   Yield our process time to another thread.  Any BUSY waiting that is done
218   by a thread should use this function to make sure that other threads can
219   make progress even on a lazy uniprocessor system.
220   */
221 void
222 objc_thread_yield (void)
223 {
224   /* Call the backend */
225   __gthread_objc_thread_yield ();
226 }
227
228 /*
229   Terminate the current tread.  Doesn't return.
230   Actually, if it failed returns -1.
231   */
232 int
233 objc_thread_exit (void)
234 {
235   /* Decrement our counter of the number of threads alive */
236   objc_mutex_lock (__objc_runtime_mutex);
237   __objc_runtime_threads_alive--;
238   objc_mutex_unlock (__objc_runtime_mutex);
239
240   /* Call the backend to terminate the thread */
241   return __gthread_objc_thread_exit ();
242 }
243
244 /*
245   Returns an integer value which uniquely describes a thread.  Must not be
246   NULL which is reserved as a marker for "no thread".
247   */
248 objc_thread_t
249 objc_thread_id (void)
250 {
251   /* Call the backend */
252   return __gthread_objc_thread_id ();
253 }
254
255 /*
256   Sets the thread's local storage pointer. 
257   Returns 0 if successful or -1 if failed.
258   */
259 int
260 objc_thread_set_data (void *value)
261 {
262   /* Call the backend */
263   return __gthread_objc_thread_set_data (value);
264 }
265
266 /*
267   Returns the thread's local storage pointer.  Returns NULL on failure.
268   */
269 void *
270 objc_thread_get_data (void)
271 {
272   /* Call the backend */
273   return __gthread_objc_thread_get_data ();
274 }
275
276 /* Frontend mutex functions */
277
278 /*
279   Allocate a mutex.  Return the mutex pointer if successful or NULL if the
280   allocation failed for any reason.
281   */
282 objc_mutex_t
283 objc_mutex_allocate (void)
284 {
285   objc_mutex_t mutex;
286
287   /* Allocate the mutex structure */
288   if (! (mutex = (objc_mutex_t)objc_malloc (sizeof (struct objc_mutex))))
289     return NULL;
290
291   /* Call backend to create the mutex */
292   if (__gthread_objc_mutex_allocate (mutex))
293     {
294       /* failed! */
295       objc_free (mutex);
296       return NULL;
297     }
298
299   /* Initialize mutex */
300   mutex->owner = NULL;
301   mutex->depth = 0;
302   return mutex;
303 }
304
305 /*
306   Deallocate a mutex.  Note that this includes an implicit mutex_lock to
307   insure that no one else is using the lock.  It is legal to deallocate
308   a lock if we have a lock on it, but illegal to deallocate a lock held
309   by anyone else.
310   Returns the number of locks on the thread.  (1 for deallocate).
311   */
312 int
313 objc_mutex_deallocate (objc_mutex_t mutex)
314 {
315   int depth;
316
317   /* Valid mutex? */
318   if (! mutex)
319     return -1;
320
321   /* Acquire lock on mutex */
322   depth = objc_mutex_lock (mutex);
323
324   /* Call backend to destroy mutex */
325   if (__gthread_objc_mutex_deallocate (mutex))
326     return -1;
327
328   /* Free the mutex structure */
329   objc_free (mutex);
330
331   /* Return last depth */
332   return depth;
333 }
334
335 /*
336   Grab a lock on a mutex.  If this thread already has a lock on this mutex
337   then we increment the lock count.  If another thread has a lock on the 
338   mutex we block and wait for the thread to release the lock.
339   Returns the lock count on the mutex held by this thread.
340   */
341 int
342 objc_mutex_lock (objc_mutex_t mutex)
343 {
344   objc_thread_t thread_id;
345   int status;
346
347   /* Valid mutex? */
348   if (! mutex)
349     return -1;
350
351   /* If we already own the lock then increment depth */
352   thread_id = __gthread_objc_thread_id ();
353   if (mutex->owner == thread_id)
354     return ++mutex->depth;
355
356   /* Call the backend to lock the mutex */
357   status = __gthread_objc_mutex_lock (mutex);
358
359   /* Failed? */
360   if (status)
361     return status;
362
363   /* Successfully locked the thread */
364   mutex->owner = thread_id;
365   return mutex->depth = 1;
366 }
367
368 /*
369   Try to grab a lock on a mutex.  If this thread already has a lock on
370   this mutex then we increment the lock count and return it.  If another
371   thread has a lock on the mutex returns -1.
372   */
373 int
374 objc_mutex_trylock (objc_mutex_t mutex)
375 {
376   objc_thread_t thread_id;
377   int status;
378
379   /* Valid mutex? */
380   if (! mutex)
381     return -1;
382
383   /* If we already own the lock then increment depth */ 
384   thread_id = __gthread_objc_thread_id ();
385   if (mutex->owner == thread_id)
386     return ++mutex->depth;
387     
388   /* Call the backend to try to lock the mutex */
389   status = __gthread_objc_mutex_trylock (mutex);
390
391   /* Failed? */
392   if (status)
393     return status;
394
395   /* Successfully locked the thread */
396   mutex->owner = thread_id;
397   return mutex->depth = 1;
398 }
399
400 /* 
401   Unlocks the mutex by one level.
402   Decrements the lock count on this mutex by one.
403   If the lock count reaches zero, release the lock on the mutex.
404   Returns the lock count on the mutex.
405   It is an error to attempt to unlock a mutex which this thread 
406   doesn't hold in which case return -1 and the mutex is unaffected.
407   */
408 int
409 objc_mutex_unlock (objc_mutex_t mutex)
410 {
411   objc_thread_t thread_id;
412   int status;
413
414   /* Valid mutex? */
415   if (! mutex)
416     return -1;
417
418   /* If another thread owns the lock then abort */
419   thread_id = __gthread_objc_thread_id ();
420   if (mutex->owner != thread_id)
421     return -1;
422
423   /* Decrement depth and return */
424   if (mutex->depth > 1)
425     return --mutex->depth;
426
427   /* Depth down to zero so we are no longer the owner */
428   mutex->depth = 0;
429   mutex->owner = NULL;
430
431   /* Have the backend unlock the mutex */
432   status = __gthread_objc_mutex_unlock (mutex);
433
434   /* Failed? */
435   if (status)
436     return status;
437
438   return 0;
439 }
440
441 /* Frontend condition mutex functions */
442
443 /*
444   Allocate a condition.  Return the condition pointer if successful or NULL
445   if the allocation failed for any reason.
446   */
447 objc_condition_t 
448 objc_condition_allocate (void)
449 {
450   objc_condition_t condition;
451     
452   /* Allocate the condition mutex structure */
453   if (! (condition = 
454          (objc_condition_t) objc_malloc (sizeof (struct objc_condition))))
455     return NULL;
456
457   /* Call the backend to create the condition mutex */
458   if (__gthread_objc_condition_allocate (condition))
459     {
460       /* failed! */
461       objc_free (condition);
462       return NULL;
463     }
464
465   /* Success! */
466   return condition;
467 }
468
469 /*
470   Deallocate a condition. Note that this includes an implicit 
471   condition_broadcast to insure that waiting threads have the opportunity
472   to wake.  It is legal to dealloc a condition only if no other
473   thread is/will be using it. Here we do NOT check for other threads
474   waiting but just wake them up.
475   */
476 int
477 objc_condition_deallocate (objc_condition_t condition)
478 {
479   /* Broadcast the condition */
480   if (objc_condition_broadcast (condition))
481     return -1;
482
483   /* Call the backend to destroy */
484   if (__gthread_objc_condition_deallocate (condition))
485     return -1;
486
487   /* Free the condition mutex structure */
488   objc_free (condition);
489
490   return 0;
491 }
492
493 /*
494   Wait on the condition unlocking the mutex until objc_condition_signal ()
495   or objc_condition_broadcast () are called for the same condition. The
496   given mutex *must* have the depth set to 1 so that it can be unlocked
497   here, so that someone else can lock it and signal/broadcast the condition.
498   The mutex is used to lock access to the shared data that make up the
499   "condition" predicate.
500   */
501 int
502 objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
503 {
504   objc_thread_t thread_id;
505
506   /* Valid arguments? */
507   if (! mutex || ! condition)
508     return -1;
509
510   /* Make sure we are owner of mutex */
511   thread_id = __gthread_objc_thread_id ();
512   if (mutex->owner != thread_id)
513     return -1;
514
515   /* Cannot be locked more than once */
516   if (mutex->depth > 1)
517     return -1;
518
519   /* Virtually unlock the mutex */
520   mutex->depth = 0;
521   mutex->owner = (objc_thread_t)NULL;
522
523   /* Call the backend to wait */
524   __gthread_objc_condition_wait (condition, mutex);
525
526   /* Make ourselves owner of the mutex */
527   mutex->owner = thread_id;
528   mutex->depth = 1;
529
530   return 0;
531 }
532
533 /*
534   Wake up all threads waiting on this condition. It is recommended that 
535   the called would lock the same mutex as the threads in objc_condition_wait
536   before changing the "condition predicate" and make this call and unlock it
537   right away after this call.
538   */
539 int
540 objc_condition_broadcast (objc_condition_t condition)
541 {
542   /* Valid condition mutex? */
543   if (! condition)
544     return -1;
545
546   return __gthread_objc_condition_broadcast (condition);
547 }
548
549 /*
550   Wake up one thread waiting on this condition. It is recommended that 
551   the called would lock the same mutex as the threads in objc_condition_wait
552   before changing the "condition predicate" and make this call and unlock it
553   right away after this call.
554   */
555 int
556 objc_condition_signal (objc_condition_t condition)
557 {
558   /* Valid condition mutex? */
559   if (! condition)
560     return -1;
561
562   return __gthread_objc_condition_signal (condition);
563 }
564
565 /* Make the objc thread system aware that a thread which is managed
566    (started, stopped) by external code could access objc facilities
567    from now on.  This is used when you are interfacing with some
568    external non-objc-based environment/system - you must call
569    objc_thread_add () before an alien thread makes any calls to
570    Objective-C.  Do not cause the _objc_became_multi_threaded hook to
571    be executed. */
572 void 
573 objc_thread_add (void)
574 {
575   objc_mutex_lock (__objc_runtime_mutex);
576   __objc_is_multi_threaded = 1;
577   __objc_runtime_threads_alive++;
578   objc_mutex_unlock (__objc_runtime_mutex);  
579 }
580
581 /* Make the objc thread system aware that a thread managed (started,
582    stopped) by some external code will no longer access objc and thus
583    can be forgotten by the objc thread system.  Call
584    objc_thread_remove () when your alien thread is done with making
585    calls to Objective-C. */
586 void
587 objc_thread_remove (void)
588 {
589   objc_mutex_lock (__objc_runtime_mutex);
590   __objc_runtime_threads_alive--;
591   objc_mutex_unlock (__objc_runtime_mutex);  
592 }
593
594 /* End of File */