gthread-posix.c revision 77ccad4d2fe1dde7927a194fc53fa520cb20d059
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 Library 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 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library 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 * MT safe 25 */ 26 27#include <pthread.h> 28#include <errno.h> 29#include <stdlib.h> 30#include <sys/time.h> 31 32#define posix_print_error( name, num ) \ 33 g_error( "file %s: line %d (%s): error %s during %s", \ 34 __FILE__, __LINE__, G_GNUC_PRETTY_FUNCTION, \ 35 g_strerror((num)), #name ) 36 37#define posix_check_for_error( what ) G_STMT_START{ \ 38 int error = (what); \ 39 if( error ) { posix_print_error( what, error ); } \ 40 }G_STMT_END 41 42static GMutex * 43g_mutex_new_posix_impl (void) 44{ 45 GMutex *result = (GMutex *) g_new (pthread_mutex_t, 1); 46 posix_check_for_error (pthread_mutex_init ((pthread_mutex_t *) result, NULL)); 47 return result; 48} 49 50static void 51g_mutex_free_posix_impl (GMutex * mutex) 52{ 53 posix_check_for_error (pthread_mutex_destroy ((pthread_mutex_t *) mutex)); 54 g_free (mutex); 55} 56 57/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use 58 functions from gmem.c and gmessages.c; */ 59 60/* pthread_mutex_lock, pthread_mutex_unlock can be taken directly, as 61 signature and semantic are right, but without error check then!!!!, 62 we might want to change this therefore. */ 63 64static gboolean 65g_mutex_trylock_posix_impl (GMutex * mutex) 66{ 67 int result; 68 69 result = pthread_mutex_trylock ((pthread_mutex_t *) mutex); 70 if (result != EBUSY) 71 return FALSE; 72 73 posix_check_for_error (result); 74 return TRUE; 75} 76 77static GCond * 78g_cond_new_posix_impl (void) 79{ 80 GCond *result = (GCond *) g_new (pthread_cond_t, 1); 81 posix_check_for_error (pthread_cond_init ((pthread_cond_t *) result, NULL)); 82 return result; 83} 84 85/* pthread_cond_signal, pthread_cond_broadcast and pthread_cond_wait 86 can be taken directly, as signature and semantic are right, but 87 without error check then!!!!, we might want to change this 88 therfore. */ 89 90#define G_MICROSEC 1000000 91#define G_NANOSEC 1000000000 92 93static gboolean 94g_cond_timed_wait_posix_impl (GCond * cond, 95 GMutex * entered_mutex, 96 GTimeVal * abs_time) 97{ 98 int result; 99 struct timespec end_time; 100 gboolean timed_out; 101 102 g_return_val_if_fail (cond != NULL, FALSE); 103 g_return_val_if_fail (entered_mutex != NULL, FALSE); 104 105 if (!abs_time) 106 { 107 g_cond_wait (cond, entered_mutex); 108 return TRUE; 109 } 110 111 end_time.tv_sec = abs_time->tv_sec; 112 end_time.tv_nsec = abs_time->tv_usec * (G_NANOSEC / G_MICROSEC); 113 g_assert (end_time.tv_nsec < G_NANOSEC); 114 result = pthread_cond_timedwait ((pthread_cond_t *) cond, 115 (pthread_mutex_t *) entered_mutex, 116 &end_time); 117 timed_out = (result == ETIMEDOUT); 118 if (!timed_out) 119 posix_check_for_error (result); 120 return !timed_out; 121} 122 123static void 124g_cond_free_posix_impl (GCond * cond) 125{ 126 posix_check_for_error (pthread_cond_destroy ((pthread_cond_t *) cond)); 127 g_free (cond); 128} 129 130static GPrivate * 131g_private_new_posix_impl (GDestroyNotify destructor) 132{ 133 GPrivate *result = (GPrivate *) g_new (pthread_key_t, 1); 134 posix_check_for_error (pthread_key_create ((pthread_key_t *) result, 135 destructor)); 136 return result; 137} 138 139/* NOTE: the functions g_private_get and g_private_set may not use 140 functions from gmem.c and gmessages.c */ 141 142static void 143g_private_set_posix_impl (GPrivate * private_key, gpointer value) 144{ 145 if (!private_key) 146 return; 147 148 pthread_setspecific (*(pthread_key_t *) private_key, value); 149} 150 151static gpointer 152g_private_get_posix_impl (GPrivate * private_key) 153{ 154 if (!private_key) 155 return NULL; 156 157 return pthread_getspecific (*(pthread_key_t *) private_key); 158} 159 160static GThreadFunctions g_thread_functions_for_glib_use_default = 161{ 162 g_mutex_new_posix_impl, 163 (void (*)(GMutex *)) pthread_mutex_lock, 164 g_mutex_trylock_posix_impl, 165 (void (*)(GMutex *)) pthread_mutex_unlock, 166 g_mutex_free_posix_impl, 167 g_cond_new_posix_impl, 168 (void (*)(GCond *)) pthread_cond_signal, 169 (void (*)(GCond *)) pthread_cond_broadcast, 170 (void (*)(GCond *, GMutex *)) pthread_cond_wait, 171 g_cond_timed_wait_posix_impl, 172 g_cond_free_posix_impl, 173 g_private_new_posix_impl, 174 g_private_get_posix_impl, 175 g_private_set_posix_impl 176}; 177