OSDN Git Service

fix broken checkin, test should be link not assemble
[pf3gnuchains/gcc-fork.git] / libobjc / thr-posix.c
1 /* GNU Objective C Runtime Thread Interface for POSIX compliant threads
2    Copyright (C) 1996, 1997, 2009 Free Software Foundation, Inc.
3    Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
4    Modified for Linux/Pthreads by Kai-Uwe Sattler (kus@iti.cs.uni-magdeburg.de)
5    Modified for posix compliance by Chris Ball (cball@fmco.com)
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation; either version 3, or (at your option) any later version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
16 details.
17
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
21
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 <http://www.gnu.org/licenses/>.  */
26
27
28 #include "objc/thr.h"
29 #include "objc/runtime.h"
30 #include <pthread.h>
31
32 /* Key structure for maintaining thread specific storage */
33 static pthread_key_t _objc_thread_storage;
34 static pthread_attr_t _objc_thread_attribs;
35
36 /* Backend initialization functions */
37
38 /* Initialize the threads subsystem. */
39 int
40 __objc_init_thread_system(void)
41 {
42   /* Initialize the thread storage key */
43   if (pthread_key_create(&_objc_thread_storage, NULL) == 0)
44     {
45       /*
46        * The normal default detach state for threads is PTHREAD_CREATE_JOINABLE
47        * which causes threads to not die when you think they should.
48            */
49       if (pthread_attr_init(&_objc_thread_attribs) == 0)
50         {
51           if (pthread_attr_setdetachstate(&_objc_thread_attribs, 
52                                           PTHREAD_CREATE_DETACHED) == 0)
53             return 0;
54         }
55     }
56
57   return -1;
58 }
59
60 /* Close the threads subsystem. */
61 int
62 __objc_close_thread_system(void)
63 {
64   if (pthread_key_delete(_objc_thread_storage) == 0)
65     {
66       if (pthread_attr_destroy(&_objc_thread_attribs) == 0)
67         return 0;
68     }
69
70   return -1;
71 }
72
73 /* Backend thread functions */
74
75 /* Create a new thread of execution. */
76 objc_thread_t
77 __objc_thread_detach(void (*func)(void *arg), void *arg)
78 {
79   objc_thread_t thread_id;
80   pthread_t new_thread_handle;
81   
82   if (!(pthread_create(&new_thread_handle, &_objc_thread_attribs, 
83                        (void *)func, arg)))
84     thread_id = *(objc_thread_t *)&new_thread_handle;
85   else
86     thread_id = NULL;
87   
88   return thread_id;
89 }
90
91 /* Set the current thread's priority.
92  *
93  * Be aware that the default schedpolicy often disallows thread priorities.
94  */
95 int
96 __objc_thread_set_priority(int priority)
97 {
98   pthread_t thread_id = pthread_self();
99   int policy;
100   struct sched_param params;
101   int priority_min, priority_max;
102
103   if (pthread_getschedparam(thread_id, &policy, &params) == 0)
104     {
105       if ((priority_max = sched_get_priority_max(policy)) != 0)
106         return -1;
107
108       if ((priority_min = sched_get_priority_min(policy)) != 0)
109         return -1;
110
111       if (priority > priority_max)
112         priority = priority_max;
113       else if (priority < priority_min)
114         priority = priority_min;
115       params.sched_priority = priority;
116
117       /*
118        * The solaris 7 and several other man pages incorrectly state that
119        * this should be a pointer to policy but pthread.h is universally
120        * at odds with this.
121        */
122       if (pthread_setschedparam(thread_id, policy, &params) == 0)
123         return 0;
124     }
125   return -1;
126 }
127
128 /* Return the current thread's priority. */
129 int
130 __objc_thread_get_priority(void)
131 {
132   int policy;
133   struct sched_param params;
134
135   if (pthread_getschedparam(pthread_self(), &policy, &params) == 0)
136     return params.sched_priority;
137   else
138     return -1;
139 }
140
141 /* Yield our process time to another thread. */
142 void
143 __objc_thread_yield(void)
144 {
145   sched_yield();
146 }
147
148 /* Terminate the current thread. */
149 int
150 __objc_thread_exit(void)
151 {
152   /* exit the thread */
153   pthread_exit(&__objc_thread_exit_status);
154
155   /* Failed if we reached here */
156   return -1;
157 }
158
159 /* Returns an integer value which uniquely describes a thread. */
160 objc_thread_t
161 __objc_thread_id(void)
162 {
163   pthread_t self = pthread_self();
164
165   return *(objc_thread_t *)&self;
166 }
167
168 /* Sets the thread's local storage pointer. */
169 int
170 __objc_thread_set_data(void *value)
171 {
172   if (pthread_setspecific(_objc_thread_storage, value) == 0)
173     return 0;
174   else
175     return -1;
176 }
177
178 /* Returns the thread's local storage pointer. */
179 void *
180 __objc_thread_get_data(void)
181 {
182   return pthread_getspecific(_objc_thread_storage);
183 }
184
185 /* Backend mutex functions */
186
187 /* Allocate a mutex. */
188 int
189 __objc_mutex_allocate(objc_mutex_t mutex)
190 {
191   mutex->backend = objc_malloc(sizeof(pthread_mutex_t));
192
193   if (pthread_mutex_init((pthread_mutex_t *)mutex->backend, NULL))
194     {
195       objc_free(mutex->backend);
196       mutex->backend = NULL;
197       return -1;
198     }
199
200   return 0;
201 }
202
203 /* Deallocate a mutex. */
204 int
205 __objc_mutex_deallocate(objc_mutex_t mutex)
206 {
207   int count = 1;
208
209   /*
210    * Posix Threads specifically require that the thread be unlocked for
211    * pthread_mutex_destroy to work.
212    */
213
214   while (count)
215     {
216       if ((count = pthread_mutex_unlock((pthread_mutex_t*)mutex->backend)) < 0)
217         return -1;
218     }
219
220   if (pthread_mutex_destroy((pthread_mutex_t *)mutex->backend))
221     return -1;
222
223   objc_free(mutex->backend);
224   mutex->backend = NULL;
225   return 0;
226 }
227
228 /* Grab a lock on a mutex. */
229 int
230 __objc_mutex_lock(objc_mutex_t mutex)
231 {
232   if (pthread_mutex_lock((pthread_mutex_t *)mutex->backend) == 0)
233     return 0;
234   else
235     return -1;
236 }
237
238 /* Try to grab a lock on a mutex. */
239 int
240 __objc_mutex_trylock(objc_mutex_t mutex)
241 {
242   if (pthread_mutex_trylock((pthread_mutex_t *)mutex->backend) == 0)
243     return 0;
244   else
245     return -1;
246 }
247
248 /* Unlock the mutex */
249 int
250 __objc_mutex_unlock(objc_mutex_t mutex)
251 {
252   if (pthread_mutex_unlock((pthread_mutex_t *)mutex->backend) == 0)
253     return 0;
254   else
255     return -1;
256 }
257
258 /* Backend condition mutex functions */
259
260 /* Allocate a condition. */
261 int
262 __objc_condition_allocate(objc_condition_t condition)
263 {
264   condition->backend = objc_malloc(sizeof(pthread_cond_t));
265
266   if (pthread_cond_init((pthread_cond_t *)condition->backend, NULL))
267     {
268       objc_free(condition->backend);
269       condition->backend = NULL;
270       return -1;
271     }
272
273   return 0;
274 }
275
276 /* Deallocate a condition. */
277 int
278 __objc_condition_deallocate(objc_condition_t condition)
279 {
280   if (pthread_cond_destroy((pthread_cond_t *)condition->backend))
281     return -1;
282
283   objc_free(condition->backend);
284   condition->backend = NULL;
285   return 0;
286 }
287
288 /* Wait on the condition */
289 int
290 __objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
291 {
292   if (pthread_cond_wait((pthread_cond_t *)condition->backend,
293                         (pthread_mutex_t *)mutex->backend) == 0)
294     return 0;
295   else
296     return -1;
297 }
298
299 /* Wake up all threads waiting on this condition. */
300 int
301 __objc_condition_broadcast(objc_condition_t condition)
302 {
303   if (pthread_cond_broadcast((pthread_cond_t *)condition->backend) == 0)
304     return 0;
305   else
306     return -1;
307 }
308
309 /* Wake up one thread waiting on this condition. */
310 int
311 __objc_condition_signal(objc_condition_t condition)
312 {
313   if (pthread_cond_signal((pthread_cond_t *)condition->backend) == 0)
314     return 0;
315   else
316     return -1;
317 }