Don't use the thread vtable for g_thread_yield()
[platform/upstream/glib.git] / glib / gthread-posix.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * gthread.c: posix thread system implementation
5  * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
25  * file for a list of people on the GLib Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GLib at ftp://ftp.gtk.org/pub/gtk/.
28  */
29
30 /* The GMutex, GCond and GPrivate implementations in this file are some
31  * of the lowest-level code in GLib.  All other parts of GLib (messages,
32  * memory, slices, etc) assume that they can freely use these facilities
33  * without risking recursion.
34  *
35  * As such, these functions are NOT permitted to call any other part of
36  * GLib.
37  *
38  * The thread manipulation functions (create, exit, join, etc.) have
39  * more freedom -- they can do as they please.
40  */
41
42 #include "config.h"
43
44 #include "gthread.h"
45 #include "gthreadprivate.h"
46
47 #include <pthread.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <errno.h>
51 #include <stdio.h>
52
53 static void
54 g_thread_abort (gint         status,
55                 const gchar *function)
56 {
57   fprintf (stderr, "GLib (gthread-posix.c): Unexpected error from C library during '%s': %s.  Aborting.\n",
58            strerror (status), function);
59   abort ();
60 }
61
62 /* {{{1 GMutex */
63
64 /**
65  * g_mutex_init:
66  * @mutex: an uninitialized #GMutex
67  *
68  * Initializes a #GMutex so that it can be used.
69  *
70  * This function is useful to initialize a mutex that has been
71  * allocated on the stack, or as part of a larger structure.
72  * It is not necessary to initialize a mutex that has been
73  * created with g_mutex_new(). Also see #G_MUTEX_INITIALIZER
74  * for an alternative way to initialize statically allocated mutexes.
75  *
76  * |[
77  *   typedef struct {
78  *     GMutex m;
79  *     /&ast; ... &ast;/
80  *   } Blob;
81  *
82  * Blob *b;
83  *
84  * b = g_new (Blob, 1);
85  * g_mutex_init (&b->m);
86  * /&ast; ... &ast;/
87  * ]|
88  *
89  * To undo the effect of g_mutex_init() when a mutex is no longer
90  * needed, use g_mutex_clear().
91  *
92  * Since: 2.32
93  */
94 void
95 g_mutex_init (GMutex *mutex)
96 {
97   gint status;
98
99   if G_UNLIKELY ((status = pthread_mutex_init (&mutex->impl, NULL)) != 0)
100     g_thread_abort (status, "pthread_mutex_init");
101 }
102
103 /**
104  * g_mutex_clear:
105  * @mutex: an initialized #GMutex
106  *
107  * Frees the resources allocated to a mutex with g_mutex_init().
108  *
109  * #GMutexes that have have been created with g_mutex_new() should
110  * be freed with g_mutex_free() instead.
111  *
112  * Sine: 2.32
113  */
114 void
115 g_mutex_clear (GMutex *mutex)
116 {
117   gint status;
118
119   if G_UNLIKELY ((status = pthread_mutex_destroy (&mutex->impl)) != 0)
120     g_thread_abort (status, "pthread_mutex_destroy");
121 }
122
123 /**
124  * g_mutex_lock:
125  * @mutex: a #GMutex
126  *
127  * Locks @mutex. If @mutex is already locked by another thread, the
128  * current thread will block until @mutex is unlocked by the other
129  * thread.
130  *
131  * This function can be used even if g_thread_init() has not yet been
132  * called, and, in that case, will do nothing.
133  *
134  * <note>#GMutex is neither guaranteed to be recursive nor to be
135  * non-recursive, i.e. a thread could deadlock while calling
136  * g_mutex_lock(), if it already has locked @mutex. Use
137  * #GStaticRecMutex, if you need recursive mutexes.</note>
138  */
139 void
140 g_mutex_lock (GMutex *mutex)
141 {
142   gint status;
143
144   if G_UNLIKELY ((status = pthread_mutex_lock (&mutex->impl)) != 0)
145     g_thread_abort (status, "pthread_mutex_lock");
146 }
147
148 /**
149  * g_mutex_unlock:
150  * @mutex: a #GMutex
151  *
152  * Unlocks @mutex. If another thread is blocked in a g_mutex_lock()
153  * call for @mutex, it will be woken and can lock @mutex itself.
154  *
155  * This function can be used even if g_thread_init() has not yet been
156  * called, and, in that case, will do nothing.
157  */
158 void
159 g_mutex_unlock (GMutex *mutex)
160 {
161   gint status;
162
163   if G_UNLIKELY ((status = pthread_mutex_unlock (&mutex->impl)) != 0)
164     g_thread_abort (status, "pthread_mutex_lock");
165 }
166
167 /**
168  * g_mutex_trylock:
169  * @mutex: a #GMutex
170  *
171  * Tries to lock @mutex. If @mutex is already locked by another thread,
172  * it immediately returns %FALSE. Otherwise it locks @mutex and returns
173  * %TRUE.
174  *
175  * This function can be used even if g_thread_init() has not yet been
176  * called, and, in that case, will immediately return %TRUE.
177  *
178  * <note>#GMutex is neither guaranteed to be recursive nor to be
179  * non-recursive, i.e. the return value of g_mutex_trylock() could be
180  * both %FALSE or %TRUE, if the current thread already has locked
181  * @mutex. Use #GStaticRecMutex, if you need recursive
182  * mutexes.</note>
183
184  * Returns: %TRUE, if @mutex could be locked
185  */
186 gboolean
187 g_mutex_trylock (GMutex *mutex)
188 {
189   gint status;
190
191   if G_LIKELY ((status = pthread_mutex_trylock (&mutex->impl)) == 0)
192     return TRUE;
193
194   if G_UNLIKELY (status != EBUSY)
195     g_thread_abort (status, "pthread_mutex_trylock");
196
197   return FALSE;
198 }
199
200 /* {{{1 GCond */
201
202 /**
203  * g_cond_init:
204  * @cond: an uninitialized #GCond
205  *
206  * Initialized a #GCond so that it can be used.
207  *
208  * This function is useful to initialize a #GCond that has been
209  * allocated on the stack, or as part of a larger structure.
210  * It is not necessary to initialize a #GCond that has been
211  * created with g_cond_new(). Also see #G_COND_INITIALIZER
212  * for an alternative way to initialize statically allocated
213  * #GConds.
214  *
215  * Since: 2.32
216  */
217 void
218 g_cond_init (GCond *cond)
219 {
220   gint status;
221
222   if G_UNLIKELY ((status = pthread_cond_init (&cond->impl, NULL)) != 0)
223     g_thread_abort (status, "pthread_cond_init");
224 }
225
226 /**
227  * g_cond_clear:
228  * @cond: an initialized #GCond
229  *
230  * Frees the resources allocated ot a #GCond with g_cond_init().
231  *
232  * #GConds that have been created with g_cond_new() should
233  * be freed with g_cond_free() instead.
234  *
235  * Since: 2.32
236  */
237 void
238 g_cond_clear (GCond *cond)
239 {
240   gint status;
241
242   if G_UNLIKELY ((status = pthread_cond_destroy (&cond->impl)) != 0)
243     g_thread_abort (status, "pthread_cond_destroy");
244 }
245
246 /**
247  * g_cond_wait:
248  * @cond: a #GCond
249  * @mutex: a #GMutex that is currently locked
250  *
251  * Waits until this thread is woken up on @cond.
252  * The @mutex is unlocked before falling asleep
253  * and locked again before resuming.
254  *
255  * This function can be used even if g_thread_init() has not yet been
256  * called, and, in that case, will immediately return.
257  */
258 void
259 g_cond_wait (GCond  *cond,
260              GMutex *mutex)
261 {
262   gint status;
263
264   if G_UNLIKELY ((status = pthread_cond_wait (&cond->impl, &mutex->impl)) != 0)
265     g_thread_abort (status, "pthread_cond_wait");
266 }
267
268 /**
269  * g_cond_signal:
270  * @cond: a #GCond
271  *
272  * If threads are waiting for @cond, exactly one of them is woken up.
273  * It is good practice to hold the same lock as the waiting thread
274  * while calling this function, though not required.
275  *
276  * This function can be used even if g_thread_init() has not yet been
277  * called, and, in that case, will do nothing.
278  */
279 void
280 g_cond_signal (GCond *cond)
281 {
282   gint status;
283
284   if G_UNLIKELY ((status = pthread_cond_signal (&cond->impl)) != 0)
285     g_thread_abort (status, "pthread_cond_signal");
286 }
287
288 /**
289  * g_cond_broadcast:
290  * @cond: a #GCond
291  *
292  * If threads are waiting for @cond, all of them are woken up.
293  * It is good practice to lock the same mutex as the waiting threads
294  * while calling this function, though not required.
295  *
296  * This function can be used even if g_thread_init() has not yet been
297  * called, and, in that case, will do nothing.
298  */
299 void
300 g_cond_broadcast (GCond *cond)
301 {
302   gint status;
303
304   if G_UNLIKELY ((status = pthread_cond_broadcast (&cond->impl)) != 0)
305     g_thread_abort (status, "pthread_cond_broadcast");
306 }
307
308 /**
309  * g_cond_timed_wait:
310  * @cond: a #GCond
311  * @mutex: a #GMutex that is currently locked
312  * @abs_time: a #GTimeVal, determining the final time
313  *
314  * Waits until this thread is woken up on @cond, but not longer than
315  * until the time specified by @abs_time. The @mutex is unlocked before
316  * falling asleep and locked again before resuming.
317  *
318  * If @abs_time is %NULL, g_cond_timed_wait() acts like g_cond_wait().
319  *
320  * This function can be used even if g_thread_init() has not yet been
321  * called, and, in that case, will immediately return %TRUE.
322  *
323  * To easily calculate @abs_time a combination of g_get_current_time()
324  * and g_time_val_add() can be used.
325  *
326  * Returns: %TRUE if @cond was signalled, or %FALSE on timeout
327  */
328 gboolean
329 g_cond_timed_wait (GCond    *cond,
330                    GMutex   *mutex,
331                    GTimeVal *abs_time)
332 {
333   struct timespec end_time;
334   gint status;
335
336   if (abs_time == NULL)
337     {
338       g_cond_wait (cond, mutex);
339       return TRUE;
340     }
341
342   end_time.tv_sec = abs_time->tv_sec;
343   end_time.tv_nsec = abs_time->tv_usec * 1000;
344
345   if ((status = pthread_cond_timedwait (&cond->impl, &mutex->impl, &end_time)) == 0)
346     return TRUE;
347
348   if G_UNLIKELY (status != ETIMEDOUT)
349     g_thread_abort (status, "pthread_cond_timedwait");
350
351   return FALSE;
352 }
353
354 /**
355  * g_cond_timedwait:
356  * @cond: a #GCond
357  * @mutex: a #GMutex that is currently locked
358  * @abs_time: the final time, in microseconds
359  *
360  * A variant of g_cond_timed_wait() that takes @abs_time
361  * as a #gint64 instead of a #GTimeVal.
362  * See g_cond_timed_wait() for details.
363  *
364  * Returns: %TRUE if @cond was signalled, or %FALSE on timeout
365  *
366  * Since: 2.32
367  */
368 gboolean
369 g_cond_timedwait (GCond  *cond,
370                   GMutex *mutex,
371                   gint64  abs_time)
372 {
373   struct timespec end_time;
374   gint status;
375
376   end_time.tv_sec = abs_time / 1000000;
377   end_time.tv_nsec = (abs_time % 1000000) * 1000;
378
379   if ((status = pthread_cond_timedwait (&cond->impl, &mutex->impl, &end_time)) == 0)
380     return TRUE;
381
382   if G_UNLIKELY (status != ETIMEDOUT)
383     g_thread_abort (status, "pthread_cond_timedwait");
384
385   return FALSE;
386 }
387
388 /* {{{1 GPrivate */
389
390 void
391 g_private_init (GPrivate       *key,
392                 GDestroyNotify  notify)
393 {
394   pthread_key_create (&key->key, notify);
395   key->ready = TRUE;
396 }
397
398 /**
399  * g_private_get:
400  * @private_key: a #GPrivate
401  *
402  * Returns the pointer keyed to @private_key for the current thread. If
403  * g_private_set() hasn't been called for the current @private_key and
404  * thread yet, this pointer will be %NULL.
405  *
406  * This function can be used even if g_thread_init() has not yet been
407  * called, and, in that case, will return the value of @private_key
408  * casted to #gpointer. Note however, that private data set
409  * <emphasis>before</emphasis> g_thread_init() will
410  * <emphasis>not</emphasis> be retained <emphasis>after</emphasis> the
411  * call. Instead, %NULL will be returned in all threads directly after
412  * g_thread_init(), regardless of any g_private_set() calls issued
413  * before threading system initialization.
414  *
415  * Returns: the corresponding pointer
416  */
417 gpointer
418 g_private_get (GPrivate *key)
419 {
420   if (!key->ready)
421     return key->single_value;
422
423   /* quote POSIX: No errors are returned from pthread_getspecific(). */
424   return pthread_getspecific (key->key);
425 }
426
427 /**
428  * g_private_set:
429  * @private_key: a #GPrivate
430  * @data: the new pointer
431  *
432  * Sets the pointer keyed to @private_key for the current thread.
433  *
434  * This function can be used even if g_thread_init() has not yet been
435  * called, and, in that case, will set @private_key to @data casted to
436  * #GPrivate*. See g_private_get() for resulting caveats.
437  */
438 void
439 g_private_set (GPrivate *key,
440                gpointer  value)
441 {
442   gint status;
443
444   if (!key->ready)
445     {
446       key->single_value = value;
447       return;
448     }
449
450   if G_UNLIKELY ((status = pthread_setspecific (key->key, value)) != 0)
451     g_thread_abort (status, "pthread_setspecific");
452 }
453
454 /* {{{1 GThread */
455
456 #include "glib.h"
457 #include "gthreadprivate.h"
458
459 #include <pthread.h>
460 #include <errno.h>
461 #include <stdlib.h>
462 #ifdef HAVE_SYS_TIME_H
463 # include <sys/time.h>
464 #endif
465 #ifdef HAVE_UNISTD_H
466 # include <unistd.h>
467 #endif
468
469 #ifdef HAVE_SCHED_H
470 #include <sched.h>
471 #endif
472
473 #define posix_check_err(err, name) G_STMT_START{                        \
474   int error = (err);                                                    \
475   if (error)                                                            \
476     g_error ("file %s: line %d (%s): error '%s' during '%s'",           \
477            __FILE__, __LINE__, G_STRFUNC,                               \
478            g_strerror (error), name);                                   \
479   }G_STMT_END
480
481 #define posix_check_cmd(cmd) posix_check_err (cmd, #cmd)
482
483 #ifdef G_ENABLE_DEBUG
484 static gboolean posix_check_cmd_prio_warned = FALSE;
485 # define posix_check_cmd_prio(cmd) G_STMT_START{                        \
486     int err = (cmd);                                                    \
487     if (err == EPERM)                                                   \
488       {                                                                 \
489         if (!posix_check_cmd_prio_warned)                               \
490           {                                                             \
491             posix_check_cmd_prio_warned = TRUE;                         \
492             g_warning ("Priorities can only be changed "                \
493                         "(resp. increased) by root.");                  \
494           }                                                             \
495       }                                                                 \
496     else                                                                \
497       posix_check_err (err, #cmd);                                      \
498      }G_STMT_END
499 #else /* G_ENABLE_DEBUG */
500 # define posix_check_cmd_prio(cmd) G_STMT_START{                        \
501     int err = (cmd);                                                    \
502     if (err != EPERM)                                                   \
503       posix_check_err (err, #cmd);                                      \
504      }G_STMT_END
505 #endif /* G_ENABLE_DEBUG */
506
507 #if defined (POSIX_MIN_PRIORITY) && defined (POSIX_MAX_PRIORITY)
508 # define HAVE_PRIORITIES 1
509 static gint priority_normal_value;
510 # ifdef __FreeBSD__
511    /* FreeBSD threads use different priority values from the POSIX_
512     * defines so we just set them here. The corresponding macros
513     * PTHREAD_MIN_PRIORITY and PTHREAD_MAX_PRIORITY are implied to be
514     * exported by the docs, but they aren't.
515     */
516 #  define PRIORITY_LOW_VALUE      0
517 #  define PRIORITY_URGENT_VALUE   31
518 # else /* !__FreeBSD__ */
519 #  define PRIORITY_LOW_VALUE      POSIX_MIN_PRIORITY
520 #  define PRIORITY_URGENT_VALUE   POSIX_MAX_PRIORITY
521 # endif /* !__FreeBSD__ */
522 # define PRIORITY_NORMAL_VALUE    priority_normal_value
523
524 # define PRIORITY_HIGH_VALUE \
525     ((PRIORITY_NORMAL_VALUE + PRIORITY_URGENT_VALUE * 2) / 3)
526
527 static gint
528 g_thread_priority_map (GThreadPriority priority)
529 {
530   switch (priority)
531     {
532     case G_THREAD_PRIORITY_LOW:
533       return PRIORITY_LOW_VALUE;
534
535     case G_THREAD_PRIORITY_NORMAL:
536       return PRIORITY_NORMAL_VALUE;
537
538     case G_THREAD_PRIORITY_HIGH:
539       return PRIORITY_HIGH_VALUE;
540
541     case G_THREAD_PRIORITY_URGENT:
542       return PRIORITY_URGENT_VALUE;
543
544     default:
545       g_assert_not_reached ();
546     }
547 }
548
549 #endif /* POSIX_MIN_PRIORITY && POSIX_MAX_PRIORITY */
550
551 static gulong g_thread_min_stack_size = 0;
552
553 #define G_MUTEX_SIZE (sizeof (pthread_mutex_t))
554
555 void
556 _g_thread_impl_init(void)
557 {
558 #ifdef _SC_THREAD_STACK_MIN
559   g_thread_min_stack_size = MAX (sysconf (_SC_THREAD_STACK_MIN), 0);
560 #endif /* _SC_THREAD_STACK_MIN */
561 #ifdef HAVE_PRIORITIES
562   {
563     struct sched_param sched;
564     int policy;
565     posix_check_cmd (pthread_getschedparam (pthread_self(), &policy, &sched));
566     priority_normal_value = sched.sched_priority;
567   }
568 #endif /* HAVE_PRIORITIES */
569 }
570
571 static void
572 g_thread_create_posix_impl (GThreadFunc thread_func,
573                             gpointer arg,
574                             gulong stack_size,
575                             gboolean joinable,
576                             gboolean bound,
577                             GThreadPriority priority,
578                             gpointer thread,
579                             GError **error)
580 {
581   pthread_attr_t attr;
582   gint ret;
583
584   g_return_if_fail (thread_func);
585   g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
586   g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
587
588   posix_check_cmd (pthread_attr_init (&attr));
589
590 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
591   if (stack_size)
592     {
593       stack_size = MAX (g_thread_min_stack_size, stack_size);
594       /* No error check here, because some systems can't do it and
595        * we simply don't want threads to fail because of that. */
596       pthread_attr_setstacksize (&attr, stack_size);
597     }
598 #endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
599
600 #ifdef PTHREAD_SCOPE_SYSTEM
601   if (bound)
602     /* No error check here, because some systems can't do it and we
603      * simply don't want threads to fail because of that. */
604     pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
605 #endif /* PTHREAD_SCOPE_SYSTEM */
606
607   posix_check_cmd (pthread_attr_setdetachstate (&attr,
608           joinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED));
609
610 #ifdef HAVE_PRIORITIES
611   {
612     struct sched_param sched;
613     posix_check_cmd (pthread_attr_getschedparam (&attr, &sched));
614     sched.sched_priority = g_thread_priority_map (priority);
615     posix_check_cmd_prio (pthread_attr_setschedparam (&attr, &sched));
616   }
617 #endif /* HAVE_PRIORITIES */
618   ret = pthread_create (thread, &attr, (void* (*)(void*))thread_func, arg);
619
620   posix_check_cmd (pthread_attr_destroy (&attr));
621
622   if (ret == EAGAIN)
623     {
624       g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, 
625                    "Error creating thread: %s", g_strerror (ret));
626       return;
627     }
628
629   posix_check_err (ret, "pthread_create");
630 }
631
632 void
633 g_thread_yield (void)
634 {
635   sched_yield ();
636 }
637
638 static void
639 g_thread_join_posix_impl (gpointer thread)
640 {
641   gpointer ignore;
642   posix_check_cmd (pthread_join (*(pthread_t*)thread, &ignore));
643 }
644
645 static void
646 g_thread_exit_posix_impl (void)
647 {
648   pthread_exit (NULL);
649 }
650
651 static void
652 g_thread_set_priority_posix_impl (gpointer thread, GThreadPriority priority)
653 {
654   g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
655   g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
656 #ifdef HAVE_PRIORITIES
657   {
658     struct sched_param sched;
659     int policy;
660     posix_check_cmd (pthread_getschedparam (*(pthread_t*)thread, &policy,
661                                             &sched));
662     sched.sched_priority = g_thread_priority_map (priority);
663     posix_check_cmd_prio (pthread_setschedparam (*(pthread_t*)thread, policy,
664                                                  &sched));
665   }
666 #endif /* HAVE_PRIORITIES */
667 }
668
669 static void
670 g_thread_self_posix_impl (gpointer thread)
671 {
672   *(pthread_t*)thread = pthread_self();
673 }
674
675 static gboolean
676 g_thread_equal_posix_impl (gpointer thread1, gpointer thread2)
677 {
678   return (pthread_equal (*(pthread_t*)thread1, *(pthread_t*)thread2) != 0);
679 }
680
681 /* {{{1 Epilogue */
682 GThreadFunctions g_thread_functions_for_glib_use =
683 {
684   g_mutex_new,
685   g_mutex_lock,
686   g_mutex_trylock,
687   g_mutex_unlock,
688   g_mutex_free,
689   g_cond_new,
690   g_cond_signal,
691   g_cond_broadcast,
692   g_cond_wait,
693   g_cond_timed_wait,
694   g_cond_free,
695   g_private_new,
696   g_private_get,
697   g_private_set,
698   g_thread_create_posix_impl,
699   g_thread_yield,
700   g_thread_join_posix_impl,
701   g_thread_exit_posix_impl,
702   g_thread_set_priority_posix_impl,
703   g_thread_self_posix_impl,
704   g_thread_equal_posix_impl
705 };
706
707 /* vim:set foldmethod=marker: */