OSDN Git Service

(OBJC_VERSION): Increment version as recent changes have made old
[pf3gnuchains/gcc-fork.git] / gcc / objc / thr.c
1 /* GNU Objective C Runtime Thread Interface
2    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
3    Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
4
5 This file is part of GNU CC.
6
7 GNU CC 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 2, or (at your option) any later version.
10
11 GNU CC 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 You should have received a copy of the GNU General Public License along with
17 GNU CC; see the file COPYING.  If not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* As a special exception, if you link this library with files compiled with
22    GCC to produce an executable, this does not cause the resulting executable
23    to be covered by the GNU General Public License. This exception does not
24    however invalidate any other reasons why the executable file might be
25    covered by the GNU General Public License.  */
26
27 #include <stdlib.h>
28 #include "runtime.h"
29
30 /*************************************************************************
31  *  Universal static variables:
32  */
33 int __objc_thread_exit_status = 0;      /* Global exit status.   */
34
35 /* Flag which lets us know if we ever became multi threaded */
36 int __objc_is_multi_threaded = 0;
37 /* The hook function called when the runtime becomes multi threaded */
38 objc_thread_callback _objc_became_multi_threaded = NULL;
39
40 /*****************************************************************************
41  *  Universal Functionality
42  */
43
44 /*
45   Use this to set the hook function that will be called when the 
46   runtime initially becomes multi threaded.
47   The hook function is only called once, meaning only when the 
48   2nd thread is spawned, not for each and every thread.
49
50   It returns the previous hook function or NULL if there is none.
51
52   A program outside of the runtime could set this to some function so
53   it can be informed; for example, the GNUstep Base Library sets it 
54   so it can implement the NSBecomingMultiThreaded notification.
55   */
56 objc_thread_callback objc_set_thread_callback(objc_thread_callback func)
57 {
58   objc_thread_callback temp = _objc_became_multi_threaded;
59   _objc_became_multi_threaded = func;
60   return temp;
61 }
62
63 /********
64  *  First function called in a thread, starts everything else.
65  */
66 struct __objc_thread_start_state
67 {
68     SEL         selector;
69     id          object;
70     id          argument;
71 };
72
73 static volatile void
74 __objc_thread_detach_function(struct __objc_thread_start_state *istate)
75 {
76     if (istate) {                               /* Is state valid?          */
77         id      (*imp)(id,SEL,id);
78         SEL     selector = istate->selector;
79         id      object   = istate->object;
80         id      argument = istate->argument;
81
82         objc_free(istate);
83
84         /* Clear out the thread local storage */
85         objc_thread_set_data(NULL);
86
87         /* Check to see if we just became multi threaded */
88         if (!__objc_is_multi_threaded) {
89           __objc_is_multi_threaded = 1;
90
91           /* Call the hook function */
92           if (_objc_became_multi_threaded != NULL)
93             (*_objc_became_multi_threaded)();
94         }
95
96         if ((imp = (id(*)(id, SEL, id))objc_msg_lookup(object, selector))) {
97             (*imp)(object, selector, argument);
98         }
99         else
100             fprintf(stderr, "__objc_thread_start called with bad selector.\n");
101     }
102     else {
103         fprintf(stderr, "__objc_thread_start called with NULL state.\n");
104     }
105     objc_thread_exit();
106 }
107
108 /********
109  *  Detach a new thread of execution and return its id.  Returns NULL if fails.
110  *  Thread is started by sending message with selector to object.  Message
111  *  takes a single argument.
112  */
113 objc_thread_t
114 objc_thread_detach(SEL selector, id object, id argument)
115 {
116   struct __objc_thread_start_state *istate;   /* Initialial thread state. */
117   objc_thread_t        thread_id = NULL;     /* Detached thread id.      */
118
119   if (!(istate = (struct __objc_thread_start_state *)
120         objc_malloc(sizeof(*istate))))     /* Can we allocate state?   */
121     return NULL;                              /* No, abort.               */
122
123   istate->selector = selector;                /* Initialize the thread's  */
124   istate->object = object;                    /*   state structure.       */
125   istate->argument = argument;
126
127   if ((thread_id = objc_thread_create((void *)__objc_thread_detach_function,
128                                       istate)) == NULL) {
129     objc_free(istate);                       /* Release state if failed.   */
130     return thread_id;
131   }
132
133   return thread_id;
134 }
135
136 #undef objc_mutex_lock()
137 #undef objc_mutex_unlock()
138
139 int
140 objc_mutex_unlock_x(objc_mutex_t mutex, const char *f, int l)
141 {
142     printf("%16.16s#%4d < unlock", f, l);
143     return objc_mutex_unlock(mutex);
144 }
145
146 int
147 objc_mutex_lock_x(objc_mutex_t mutex, const char *f, int l)
148 {
149     printf("%16.16s#%4d < lock", f, l);
150     return objc_mutex_lock(mutex);
151 }
152
153 /* End of File */