2010-01-15 Jing Yu <jingyu@google.com>
[official-gcc.git] / libobjc / thr-posix.c
blob6e6061457ec1a7c6534ef613a564f1daeb57e821
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)
7 This file is part of GCC.
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.
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.
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.
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/>. */
28 #include "objc/thr.h"
29 #include "objc/runtime.h"
30 #include <pthread.h>
32 /* Key structure for maintaining thread specific storage */
33 static pthread_key_t _objc_thread_storage;
34 static pthread_attr_t _objc_thread_attribs;
36 /* Backend initialization functions */
38 /* Initialize the threads subsystem. */
39 int
40 __objc_init_thread_system(void)
42 /* Initialize the thread storage key */
43 if (pthread_key_create(&_objc_thread_storage, NULL) == 0)
46 * The normal default detach state for threads is PTHREAD_CREATE_JOINABLE
47 * which causes threads to not die when you think they should.
49 if (pthread_attr_init(&_objc_thread_attribs) == 0)
51 if (pthread_attr_setdetachstate(&_objc_thread_attribs,
52 PTHREAD_CREATE_DETACHED) == 0)
53 return 0;
57 return -1;
60 /* Close the threads subsystem. */
61 int
62 __objc_close_thread_system(void)
64 if (pthread_key_delete(_objc_thread_storage) == 0)
66 if (pthread_attr_destroy(&_objc_thread_attribs) == 0)
67 return 0;
70 return -1;
73 /* Backend thread functions */
75 /* Create a new thread of execution. */
76 objc_thread_t
77 __objc_thread_detach(void (*func)(void *arg), void *arg)
79 objc_thread_t thread_id;
80 pthread_t new_thread_handle;
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;
88 return thread_id;
91 /* Set the current thread's priority.
93 * Be aware that the default schedpolicy often disallows thread priorities.
95 int
96 __objc_thread_set_priority(int priority)
98 pthread_t thread_id = pthread_self();
99 int policy;
100 struct sched_param params;
101 int priority_min, priority_max;
103 if (pthread_getschedparam(thread_id, &policy, &params) == 0)
105 if ((priority_max = sched_get_priority_max(policy)) != 0)
106 return -1;
108 if ((priority_min = sched_get_priority_min(policy)) != 0)
109 return -1;
111 if (priority > priority_max)
112 priority = priority_max;
113 else if (priority < priority_min)
114 priority = priority_min;
115 params.sched_priority = priority;
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.
122 if (pthread_setschedparam(thread_id, policy, &params) == 0)
123 return 0;
125 return -1;
128 /* Return the current thread's priority. */
130 __objc_thread_get_priority(void)
132 int policy;
133 struct sched_param params;
135 if (pthread_getschedparam(pthread_self(), &policy, &params) == 0)
136 return params.sched_priority;
137 else
138 return -1;
141 /* Yield our process time to another thread. */
142 void
143 __objc_thread_yield(void)
145 sched_yield();
148 /* Terminate the current thread. */
150 __objc_thread_exit(void)
152 /* exit the thread */
153 pthread_exit(&__objc_thread_exit_status);
155 /* Failed if we reached here */
156 return -1;
159 /* Returns an integer value which uniquely describes a thread. */
160 objc_thread_t
161 __objc_thread_id(void)
163 pthread_t self = pthread_self();
165 return *(objc_thread_t *)&self;
168 /* Sets the thread's local storage pointer. */
170 __objc_thread_set_data(void *value)
172 if (pthread_setspecific(_objc_thread_storage, value) == 0)
173 return 0;
174 else
175 return -1;
178 /* Returns the thread's local storage pointer. */
179 void *
180 __objc_thread_get_data(void)
182 return pthread_getspecific(_objc_thread_storage);
185 /* Backend mutex functions */
187 /* Allocate a mutex. */
189 __objc_mutex_allocate(objc_mutex_t mutex)
191 mutex->backend = objc_malloc(sizeof(pthread_mutex_t));
193 if (pthread_mutex_init((pthread_mutex_t *)mutex->backend, NULL))
195 objc_free(mutex->backend);
196 mutex->backend = NULL;
197 return -1;
200 return 0;
203 /* Deallocate a mutex. */
205 __objc_mutex_deallocate(objc_mutex_t mutex)
207 int count = 1;
210 * Posix Threads specifically require that the thread be unlocked for
211 * pthread_mutex_destroy to work.
214 while (count)
216 if ((count = pthread_mutex_unlock((pthread_mutex_t*)mutex->backend)) < 0)
217 return -1;
220 if (pthread_mutex_destroy((pthread_mutex_t *)mutex->backend))
221 return -1;
223 objc_free(mutex->backend);
224 mutex->backend = NULL;
225 return 0;
228 /* Grab a lock on a mutex. */
230 __objc_mutex_lock(objc_mutex_t mutex)
232 if (pthread_mutex_lock((pthread_mutex_t *)mutex->backend) == 0)
233 return 0;
234 else
235 return -1;
238 /* Try to grab a lock on a mutex. */
240 __objc_mutex_trylock(objc_mutex_t mutex)
242 if (pthread_mutex_trylock((pthread_mutex_t *)mutex->backend) == 0)
243 return 0;
244 else
245 return -1;
248 /* Unlock the mutex */
250 __objc_mutex_unlock(objc_mutex_t mutex)
252 if (pthread_mutex_unlock((pthread_mutex_t *)mutex->backend) == 0)
253 return 0;
254 else
255 return -1;
258 /* Backend condition mutex functions */
260 /* Allocate a condition. */
262 __objc_condition_allocate(objc_condition_t condition)
264 condition->backend = objc_malloc(sizeof(pthread_cond_t));
266 if (pthread_cond_init((pthread_cond_t *)condition->backend, NULL))
268 objc_free(condition->backend);
269 condition->backend = NULL;
270 return -1;
273 return 0;
276 /* Deallocate a condition. */
278 __objc_condition_deallocate(objc_condition_t condition)
280 if (pthread_cond_destroy((pthread_cond_t *)condition->backend))
281 return -1;
283 objc_free(condition->backend);
284 condition->backend = NULL;
285 return 0;
288 /* Wait on the condition */
290 __objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
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;
299 /* Wake up all threads waiting on this condition. */
301 __objc_condition_broadcast(objc_condition_t condition)
303 if (pthread_cond_broadcast((pthread_cond_t *)condition->backend) == 0)
304 return 0;
305 else
306 return -1;
309 /* Wake up one thread waiting on this condition. */
311 __objc_condition_signal(objc_condition_t condition)
313 if (pthread_cond_signal((pthread_cond_t *)condition->backend) == 0)
314 return 0;
315 else
316 return -1;