OSDN Git Service

* configure.ac: Determine Sun ld version numbers.
[pf3gnuchains/gcc-fork.git] / libobjc / thr-mach.c
1 /* GNU Objective C Runtime Thread Implementation
2    Copyright (C) 1996, 1997, 2002, 2009 Free Software Foundation, Inc.
3    Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
4    Modified for Mach threads by Bill Bumgarner <bbum@friday.com>
5    Condition functions added by Mircea Oancea <mircea@first.elcom.pub.ro>
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 <mach/mach.h>
29 #include <mach/cthreads.h>
30 #include "objc/thr.h"
31 #include "objc/runtime.h"
32
33 /*
34   Obtain the maximum thread priority that can set for t.  Under the
35   mach threading model, it is possible for the developer to adjust the
36   maximum priority downward only-- cannot be raised without superuser
37   privileges.  Once lowered, it cannot be raised.
38   */
39 static int
40 __mach_get_max_thread_priority (cthread_t t, int *base)
41 {
42   thread_t threadP;
43   kern_return_t error;
44   struct thread_sched_info info;
45   unsigned int info_count=THREAD_SCHED_INFO_COUNT;
46     
47   if (t == NULL)
48     return -1;
49
50   threadP  = cthread_thread (t);        /* get thread underlying */
51
52   error = thread_info (threadP, THREAD_SCHED_INFO, 
53                        (thread_info_t) &info, &info_count);
54
55   if (error != KERN_SUCCESS)
56     return -1;
57
58   if (base != NULL)
59     *base = info.base_priority;
60
61   return info.max_priority;
62 }
63         
64 /* Backend initialization functions */
65
66 /* Initialize the threads subsystem. */
67 int
68 __objc_init_thread_system (void)
69 {
70   return 0;
71 }
72
73 /* Close the threads subsystem. */
74 int
75 __objc_close_thread_system (void)
76 {
77   return 0;
78 }
79
80 /* Backend thread functions */
81
82 /* Create a new thread of execution. */
83 objc_thread_t
84 __objc_thread_detach (void (*func) (void *arg), void *arg)
85 {
86   objc_thread_t thread_id;
87   cthread_t new_thread_handle;
88
89   /* create thread */
90   new_thread_handle = cthread_fork ((cthread_fn_t) func, arg);
91
92   if (new_thread_handle)
93     {
94       /* this is not terribly portable */
95       thread_id = *(objc_thread_t *) &new_thread_handle; 
96       cthread_detach (new_thread_handle);
97     }
98   else
99     thread_id = NULL;
100   
101   return thread_id;
102 }
103
104 /* Set the current thread's priority. */
105 int
106 __objc_thread_set_priority (int priority)
107 {
108   objc_thread_t *t = objc_thread_id ();
109   cthread_t cT = (cthread_t) t; 
110   int maxPriority = __mach_get_max_thread_priority (cT, NULL);
111   int sys_priority = 0;
112
113   if (maxPriority == -1)
114     return -1;
115
116   switch (priority)
117     {
118     case OBJC_THREAD_INTERACTIVE_PRIORITY:
119       sys_priority = maxPriority;
120       break;
121     case OBJC_THREAD_BACKGROUND_PRIORITY:
122       sys_priority = (maxPriority * 2) / 3;
123       break;
124     case OBJC_THREAD_LOW_PRIORITY:
125       sys_priority = maxPriority / 3;
126       break;
127     default:
128       return -1;
129     }
130
131   if (sys_priority == 0)
132     return -1;
133
134   /* Change the priority */
135   if (cthread_priority (cT, sys_priority, 0) == KERN_SUCCESS)
136     return 0;
137   else
138     return -1;
139 }
140
141 /* Return the current thread's priority. */
142 int
143 __objc_thread_get_priority (void)
144 {
145   objc_thread_t *t = objc_thread_id ();
146   cthread_t cT = (cthread_t) t; /* see objc_thread_id () */
147   int basePriority;
148   int maxPriority;
149   int sys_priority = 0;
150
151   int interactiveT, backgroundT, lowT; /* thresholds */
152
153   maxPriority = __mach_get_max_thread_priority (cT, &basePriority);
154
155   if (maxPriority == -1)
156     return -1;
157
158   if (basePriority > ( (maxPriority * 2) / 3))
159     return OBJC_THREAD_INTERACTIVE_PRIORITY;
160
161   if (basePriority > ( maxPriority / 3))
162     return OBJC_THREAD_BACKGROUND_PRIORITY;
163
164   return OBJC_THREAD_LOW_PRIORITY;
165 }
166
167 /* Yield our process time to another thread. */
168 void
169 __objc_thread_yield (void)
170 {
171   cthread_yield ();
172 }
173
174 /* Terminate the current thread. */
175 int
176 __objc_thread_exit (void)
177 {
178   /* exit the thread */
179   cthread_exit (&__objc_thread_exit_status);
180
181   /* Failed if we reached here */
182   return -1;
183 }
184
185 /* Returns an integer value which uniquely describes a thread. */
186 objc_thread_t
187 __objc_thread_id (void)
188 {
189   cthread_t self = cthread_self ();
190
191   return *(objc_thread_t *) &self;
192 }
193
194 /* Sets the thread's local storage pointer. */
195 int
196 __objc_thread_set_data (void *value)
197 {
198   cthread_set_data (cthread_self (), (any_t) value);
199   return 0;
200 }
201
202 /* Returns the thread's local storage pointer. */
203 void *
204 __objc_thread_get_data (void)
205 {
206   return (void *) cthread_data (cthread_self ());
207 }
208
209 /* Backend mutex functions */
210
211 /* Allocate a mutex. */
212 int
213 __objc_mutex_allocate (objc_mutex_t mutex)
214 {
215   int err = 0;
216   mutex->backend = objc_malloc (sizeof (struct mutex));
217
218   err = mutex_init ((mutex_t) (mutex->backend));
219
220   if (err != 0)
221     {
222       objc_free (mutex->backend);
223       return -1;
224     }
225   else
226     return 0;
227 }
228
229 /* Deallocate a mutex. */
230 int
231 __objc_mutex_deallocate (objc_mutex_t mutex)
232 {
233   mutex_clear ((mutex_t) (mutex->backend));
234
235   objc_free (mutex->backend);
236   mutex->backend = NULL;
237   return 0;
238 }
239
240 /* Grab a lock on a mutex. */
241 int
242 __objc_mutex_lock (objc_mutex_t mutex)
243 {
244   mutex_lock ((mutex_t) (mutex->backend));
245   return 0;
246 }
247
248 /* Try to grab a lock on a mutex. */
249 int
250 __objc_mutex_trylock (objc_mutex_t mutex)
251 {
252   if (mutex_try_lock ((mutex_t) (mutex->backend)) == 0)
253     return -1;
254   else
255     return 0;
256 }
257
258 /* Unlock the mutex */
259 int
260 __objc_mutex_unlock (objc_mutex_t mutex)
261 {
262   mutex_unlock ((mutex_t) (mutex->backend));
263   return 0;
264 }
265
266 /* Backend condition mutex functions */
267
268 /* Allocate a condition. */
269 int
270 __objc_condition_allocate (objc_condition_t condition)
271 {
272   condition->backend = objc_malloc (sizeof (struct condition));
273   condition_init ((condition_t) (condition->backend));
274   return 0;
275 }
276
277 /* Deallocate a condition. */
278 int
279 __objc_condition_deallocate (objc_condition_t condition)
280 {
281   condition_clear ((condition_t) (condition->backend));
282   objc_free (condition->backend);
283   condition->backend = NULL;
284   return 0;
285 }
286
287 /* Wait on the condition */
288 int
289 __objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
290 {
291   condition_wait ((condition_t) (condition->backend),
292                   (mutex_t) (mutex->backend));
293   return 0;
294 }
295
296 /* Wake up all threads waiting on this condition. */
297 int
298 __objc_condition_broadcast (objc_condition_t condition)
299 {
300   condition_broadcast ((condition_t) (condition->backend));
301   return 0;
302 }
303
304 /* Wake up one thread waiting on this condition. */
305 int
306 __objc_condition_signal (objc_condition_t condition)
307 {
308   condition_signal ((condition_t) (condition->backend));
309   return 0;
310 }
311
312 /* End of File */