(find_barrier): Set si_limit to 1018 instead of 1020, and
[official-gcc.git] / gcc / objc / thr-win32.c
blobd933999ccb763df1a7eb7332217ce2faca6f537a
1 /* GNU Objective C Runtime Thread Interface - Win32 Implementation
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 Contributed by Galen C. Hunt (gchunt@cs.rochester.edu)
5 This file is part of GNU CC.
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.
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.
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. */
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. */
27 #include <windows.h>
29 /********
30 * This structure represents a single mutual exclusion lock. Lock semantics
31 * are detailed with the subsequent functions. We use whatever lock is
32 * provided by the system. We augment it with depth and current owner id
33 * fields to implement and re-entrant lock.
35 struct _objc_mutex
37 volatile _objc_thread_t owner; /* Id of thread that owns. */
38 volatile int depth; /* # of acquires. */
39 HANDLE handle; /* Win32 mutex HANDLE. */
42 /*****************************************************************************
43 * Static variables.
45 static DWORD __objc_data_tls = (DWORD)-1; /* Win32 Thread Local Index.*/
47 /********
48 * Initialize the threads subsystem. Returns 0 if successful, or -1 if no
49 * thread support is available.
51 int
52 __objc_init_thread_system(void)
54 DEBUG_PRINTF("__objc_init_thread_system\n");
56 if ((__objc_data_tls = TlsAlloc()) != (DWORD)-1)
57 return 0; /* Yes, return success. */
59 return -1; /* Failed. */
62 int
63 __objc_fini_thread_system(void)
65 if (__objc_data_tls != (DWORD)-1) {
66 TlsFree(__objc_data_tls);
67 return 0;
69 return -1;
72 /********
73 * Create a new thread of execution and return its id. Return NULL if fails.
74 * The new thread starts in "func" with the given argument.
76 _objc_thread_t
77 objc_thread_create(void (*func)(void *arg), void *arg)
79 DWORD thread_id = 0; /* Detached thread id. */
80 HANDLE win32_handle; /* Win32 thread handle. */
82 objc_mutex_lock(__objc_runtime_mutex);
84 if ((win32_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func,
85 arg, 0, &thread_id))) {
86 __objc_runtime_threads_alive++;
88 else
89 thread_id = 0;
91 objc_mutex_unlock(__objc_runtime_mutex);
93 return (_objc_thread_t)thread_id;
96 /********
97 * Set the current thread's priority.
99 int
100 objc_thread_set_priority(int priority)
102 int sys_priority = 0;
104 switch (priority) {
105 case OBJC_THREAD_INTERACTIVE_PRIORITY:
106 sys_priority = THREAD_PRIORITY_NORMAL;
107 break;
108 default:
109 case OBJC_THREAD_BACKGROUND_PRIORITY:
110 sys_priority = THREAD_PRIORITY_BELOW_NORMAL;
111 break;
112 case OBJC_THREAD_LOW_PRIORITY:
113 sys_priority = THREAD_PRIORITY_LOWEST;
114 break;
116 if (SetThreadPriority(GetCurrentThread(), sys_priority))
117 return 0; /* Changed priority. End. */
119 return -1; /* Failed. */
122 /********
123 * Return the current thread's priority.
126 objc_thread_get_priority(void)
128 int sys_priority;
130 sys_priority = GetThreadPriority(GetCurrentThread());
132 switch (sys_priority) {
133 case THREAD_PRIORITY_HIGHEST:
134 case THREAD_PRIORITY_TIME_CRITICAL:
135 case THREAD_PRIORITY_ABOVE_NORMAL:
136 case THREAD_PRIORITY_NORMAL:
137 return OBJC_THREAD_INTERACTIVE_PRIORITY;
139 default:
140 case THREAD_PRIORITY_BELOW_NORMAL:
141 return OBJC_THREAD_BACKGROUND_PRIORITY;
143 case THREAD_PRIORITY_IDLE:
144 case THREAD_PRIORITY_LOWEST:
145 return OBJC_THREAD_LOW_PRIORITY;
147 return -1; /* Couldn't get priority. */
150 /********
151 * Yield our process time to another thread. Any BUSY waiting that is done
152 * by a thread should use this function to make sure that other threads can
153 * make progress even on a lazy uniprocessor system.
155 void
156 objc_thread_yield(void)
158 Sleep(0); /* Yield to equal thread. */
161 /********
162 * Terminate the current tread. Doesn't return anything. Doesn't return.
163 * Actually, if it failed returns -1.
166 objc_thread_exit(void)
168 objc_mutex_lock(__objc_runtime_mutex);
169 __objc_runtime_threads_alive--;
170 objc_mutex_unlock(__objc_runtime_mutex);
172 ExitThread(__objc_thread_exit_status); /* Terminate thread. */
173 return -1;
176 /********
177 * Returns an integer value which uniquely describes a thread. Must not be
178 * -1 which is reserved as a marker for "no thread".
180 _objc_thread_t
181 objc_thread_id(void)
183 return (_objc_thread_t)GetCurrentThreadId(); /* Return thread id. */
186 /********
187 * Sets the thread's local storage pointer. Returns 0 if successful or -1
188 * if failed.
191 objc_thread_set_data(void *value)
193 if (TlsSetValue(__objc_data_tls, value))
194 return 0; /* Return thread data. */
195 return -1;
198 /********
199 * Returns the thread's local storage pointer. Returns NULL on failure.
201 void *
202 objc_thread_get_data(void)
204 return TlsGetValue(__objc_data_tls); /* Return thread data. */
207 /********
208 * Allocate a mutex. Return the mutex pointer if successful or NULL if
209 * the allocation fails for any reason.
211 _objc_mutex_t
212 objc_mutex_allocate(void)
214 _objc_mutex_t mutex;
215 int err = 0;
217 if (!(mutex = (_objc_mutex_t)__objc_xmalloc(sizeof(struct _objc_mutex))))
218 return NULL; /* Abort if malloc failed. */
220 if ((mutex->handle = CreateMutex(NULL, 0, NULL)) == NULL) {
221 free(mutex); /* Failed, free memory. */
222 return NULL; /* Abort. */
224 mutex->owner = NULL; /* No owner. */
225 mutex->depth = 0; /* No locks. */
226 return mutex; /* Return mutex handle. */
229 /********
230 * Deallocate a mutex. Note that this includes an implicit mutex_lock to
231 * insure that no one else is using the lock. It is legal to deallocate
232 * a lock if we have a lock on it, but illegal to deallotcate a lock held
233 * by anyone else.
234 * Returns the number of locks on the thread. (1 for deallocate).
237 objc_mutex_deallocate(_objc_mutex_t mutex)
239 int depth; /* # of locks on mutex. */
241 if (!mutex) /* Is argument bad? */
242 return -1; /* Yes, abort. */
243 depth = objc_mutex_lock(mutex); /* Must have lock. */
245 CloseHandle(mutex->handle); /* Close Win32 handle. */
247 free(mutex); /* Free memory. */
248 return depth; /* Return last depth. */
251 /********
252 * Grab a lock on a mutex. If this thread already has a lock on this mutex
253 * then we increment the lock count. If another thread has a lock on the
254 * mutex we block and wait for the thread to release the lock.
255 * Returns the lock count on the mutex held by this thread.
258 objc_mutex_lock(_objc_mutex_t mutex)
260 _objc_thread_t thread_id; /* Cache our thread id. */
261 int status;
263 if (!mutex) /* Is argument bad? */
264 return -1; /* Yes, abort. */
265 thread_id = objc_thread_id(); /* Get this thread's id. */
266 if (mutex->owner == thread_id) /* Already own lock? */
267 return ++mutex->depth; /* Yes, increment depth. */
269 status = WaitForSingleObject(mutex->handle, INFINITE);
270 if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
271 return -1; /* Failed, abort. */
273 mutex->owner = thread_id; /* Mark thread as owner. */
275 return ++mutex->depth; /* Increment depth to end. */
278 /********
279 * Try to grab a lock on a mutex. If this thread already has a lock on
280 * this mutex then we increment the lock count and return it. If another
281 * thread has a lock on the mutex returns -1.
284 objc_mutex_trylock(_objc_mutex_t mutex)
286 _objc_thread_t thread_id; /* Cache our thread id. */
287 DWORD status; /* Return status from Win32.*/
289 if (!mutex) /* Is argument bad? */
290 return -1; /* Yes, abort. */
291 thread_id = objc_thread_id(); /* Get this thread's id. */
292 if (mutex->owner == thread_id) /* Already own lock? */
293 return ++mutex->depth; /* Yes, increment depth. */
295 status = WaitForSingleObject(mutex->handle, 0);
296 if (status != WAIT_OBJECT_0 && status != WAIT_ABANDONED)
297 return -1; /* Failed, abort. */
299 mutex->owner = thread_id; /* Mark thread as owner. */
300 return ++mutex->depth; /* Increment depth to end. */
303 /********
304 * Decrements the lock count on this mutex by one. If the lock count reaches
305 * zero, release the lock on the mutex. Returns the lock count on the mutex.
306 * It is an error to attempt to unlock a mutex which this thread doesn't hold
307 * in which case return -1 and the mutex is unaffected.
308 * Will also return -1 if the mutex free fails.
311 objc_mutex_unlock(_objc_mutex_t mutex)
313 _objc_thread_t thread_id; /* Cache our thread id. */
315 if (!mutex) /* Is argument bad? */
316 return -1; /* Yes, abort. */
317 thread_id = objc_thread_id(); /* Get this thread's id. */
318 if (mutex->owner != thread_id) /* Does some else own lock? */
319 return -1; /* Yes, abort. */
320 if (mutex->depth > 1) /* Released last lock? */
321 return --mutex->depth; /* No, Decrement depth, end.*/
322 mutex->depth = 0; /* Yes, reset depth to 0. */
323 mutex->owner = NULL; /* Set owner to "no thread".*/
325 if (ReleaseMutex(mutex->handle) == 0)
326 return -1; /* Failed, abort. */
328 return 0; /* No, return success. */
331 /* End of File */