2006-10-26 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-sysdeps-pthread.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-sysdeps-pthread.c Implements threads using pthreads (internal to libdbus)
3  * 
4  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-sysdeps.h"
26 #include "dbus-threads.h"
27
28 #include <sys/time.h>
29 #include <pthread.h>
30
31 static DBusMutex*
32 _dbus_pthread_mutex_new (void)
33 {
34   pthread_mutex_t *retval;
35   
36   retval = dbus_new (pthread_mutex_t, 1);
37   if (retval == NULL)
38     return NULL;
39   
40   if (pthread_mutex_init (retval, NULL))
41     {
42       dbus_free (retval);
43       return NULL;
44     }
45
46   return (DBusMutex *) retval;
47 }
48
49 static void
50 _dbus_pthread_mutex_free (DBusMutex *mutex)
51 {
52   pthread_mutex_destroy ((pthread_mutex_t *) mutex);
53   dbus_free (mutex);
54 }
55
56 static dbus_bool_t
57 _dbus_pthread_mutex_lock (DBusMutex *mutex)
58 {
59   return pthread_mutex_lock ((pthread_mutex_t *) mutex) == 0;
60 }
61
62 static dbus_bool_t
63 _dbus_pthread_mutex_unlock (DBusMutex *mutex)
64 {
65   return pthread_mutex_unlock ((pthread_mutex_t *) mutex) == 0;
66 }
67
68 static DBusCondVar *
69 _dbus_pthread_condvar_new (void)
70 {
71   pthread_cond_t *retval;
72   
73   retval = dbus_new (pthread_cond_t, 1);
74   if (retval == NULL)
75     return NULL;
76   
77   if (pthread_cond_init (retval, NULL))
78     {
79       dbus_free (retval);
80       return NULL;
81     }
82   return (DBusCondVar *) retval;
83 }
84
85 static void
86 _dbus_pthread_condvar_free (DBusCondVar *cond)
87 {
88   pthread_cond_destroy ((pthread_cond_t *) cond);
89   dbus_free (cond);
90 }
91
92 static void
93 _dbus_pthread_condvar_wait (DBusCondVar *cond,
94                     DBusMutex   *mutex)
95 {
96   pthread_cond_wait ((pthread_cond_t *)cond,
97                      (pthread_mutex_t *) mutex);
98 }
99
100 static dbus_bool_t
101 _dbus_pthread_condvar_wait_timeout (DBusCondVar               *cond,
102                                      DBusMutex                 *mutex,
103                                      int                        timeout_milliseconds)
104 {
105   struct timeval time_now;
106   struct timespec end_time;
107   int result;
108   
109   gettimeofday (&time_now, NULL);
110   
111   end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000;
112   end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000;
113   if (end_time.tv_nsec > 1000*1000*1000)
114     {
115       end_time.tv_sec += 1;
116       end_time.tv_nsec -= 1000*1000*1000;
117     }
118   
119   result = pthread_cond_timedwait ((pthread_cond_t *) cond,
120                                    (pthread_mutex_t *) mutex,
121                                    &end_time);
122   
123   /* return true if we did not time out */
124   return result != ETIMEDOUT;
125 }
126
127 static void
128 _dbus_pthread_condvar_wake_one (DBusCondVar *cond)
129 {
130   pthread_cond_signal ((pthread_cond_t *)cond);
131 }
132
133 static void
134 _dbus_pthread_condvar_wake_all (DBusCondVar *cond)
135 {
136   pthread_cond_broadcast ((pthread_cond_t *)cond);
137 }
138
139 static const DBusThreadFunctions pthread_functions =
140 {
141   DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
142   DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
143   DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
144   DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
145   DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
146   DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
147   DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
148   DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
149   DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
150   DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
151   _dbus_pthread_mutex_new,
152   _dbus_pthread_mutex_free,
153   _dbus_pthread_mutex_lock,
154   _dbus_pthread_mutex_unlock,
155   _dbus_pthread_condvar_new,
156   _dbus_pthread_condvar_free,
157   _dbus_pthread_condvar_wait,
158   _dbus_pthread_condvar_wait_timeout,
159   _dbus_pthread_condvar_wake_one,
160   _dbus_pthread_condvar_wake_all
161 };
162
163 dbus_bool_t
164 _dbus_threads_init_platform_specific (void)
165 {
166   return dbus_threads_init (&pthread_functions);
167 }