source: trunk/src/sh_pthread.c@ 306

Last change on this file since 306 was 259, checked in by katerina, 15 years ago

Use inotify in utmp module (ticket #177).

File size: 6.9 KB
Line 
1#include "config_xor.h"
2
3#include "sh_pthread.h"
4
5#ifdef HAVE_PTHREAD
6
7#include <signal.h>
8#include "sh_calls.h"
9#include "sh_modules.h"
10extern volatile int sh_thread_pause_flag;
11
12SH_MUTEX_INIT(mutex_skey, PTHREAD_MUTEX_INITIALIZER);
13SH_MUTEX_INIT(mutex_resolv, PTHREAD_MUTEX_INITIALIZER);
14SH_MUTEX_INIT(mutex_pwent, PTHREAD_MUTEX_INITIALIZER);
15SH_MUTEX_INIT(mutex_readdir, PTHREAD_MUTEX_INITIALIZER);
16SH_MUTEX_INIT(mutex_thread_nolog, PTHREAD_MUTEX_INITIALIZER);
17
18void sh_pthread_mutex_unlock (void *arg)
19{
20 (void) pthread_mutex_unlock ((pthread_mutex_t *)arg);
21 return;
22}
23
24int sh_pthread_init_threadspecific(void)
25{
26 int rc = 0;
27#ifdef SH_STEALTH
28 extern int sh_g_thread(void);
29
30 rc = sh_g_thread();
31 if (rc != 0)
32 return rc;
33#endif
34
35 return rc;
36}
37
38
39/*
40 * ---- Utilities for modules ----
41 */
42
43/* MODULES: init()
44 *
45 * #ifdef HAVE_PTHREAD
46 * if (arg != NULL)
47 * {
48 * if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
49 * return SH_MOD_THREAD;
50 * else
51 * return SH_MOD_FAILED;
52 * }
53 * #else
54 * return sh_utmp_init_internal();
55 * #endif
56 *
57 *
58 * sh_threaded_module_run(module_struct)
59 * -- calls internal init,
60 * -- polls timer,
61 * -- runs module check,
62 * -- runs sh_pthread_testcancel()
63 * -- returns (return == exit)
64 */
65
66#define SH_NUM_THREADS 16
67static pthread_t threads[SH_NUM_THREADS];
68static int ithread[SH_NUM_THREADS];
69static pthread_mutex_t create_mutex = PTHREAD_MUTEX_INITIALIZER;
70
71int sh_pthread_create(void *(*start_routine)(void*), void *arg)
72{
73 int rc, nthread = 1;
74 sigset_t signal_set;
75 int retval = 0;
76
77 pthread_mutex_lock(&create_mutex);
78
79 /* block all signals
80 */
81 sigfillset( &signal_set );
82 pthread_sigmask( SIG_BLOCK, &signal_set, NULL );
83
84 /* find a free slot in threads[]
85 */
86 while (nthread < SH_NUM_THREADS)
87 {
88 if (ithread[nthread] == 0)
89 break;
90 ++nthread;
91 if (nthread == SH_NUM_THREADS)
92 {
93 retval = -1;
94 goto err_out;
95 }
96 }
97
98 rc = pthread_create(&threads[nthread], NULL, start_routine, arg);
99 if (rc != 0)
100 {
101 retval = -1;
102 goto err_out;
103 }
104
105 ithread[nthread] = 1;
106
107 err_out:
108 pthread_sigmask( SIG_UNBLOCK, &signal_set, NULL );
109 pthread_mutex_unlock(&create_mutex);
110 return retval;
111}
112
113int sh_pthread_cancel_all()
114{
115 int i;
116 int ret = 0;
117
118 SH_MUTEX_LOCK(create_mutex);
119
120 for (i = 1; i < SH_NUM_THREADS; ++i)
121 {
122 if (ithread[i] != 0)
123 if (0 != pthread_cancel(threads[i]))
124 ithread[i] = 0;
125 }
126
127 for (i = 1; i < SH_NUM_THREADS; ++i)
128 {
129 if (ithread[i] != 0)
130 pthread_join(threads[i], NULL);
131 ithread[i] = 0;
132 }
133
134 SH_MUTEX_UNLOCK(create_mutex);
135 return ret;
136}
137
138/* ---- Utility functions for modules ----
139 */
140
141#undef S_TRUE
142#define S_TRUE 1
143#undef S_FALSE
144#define S_FALSE 0
145
146void sh_threaded_module_cleanup(void *arg)
147{
148 sh_mtype * this_module = (sh_mtype *) arg;
149 this_module->mod_cleanup();
150 return;
151}
152
153void * sh_threaded_module_run(void *arg)
154{
155 sh_mtype * this_module = (sh_mtype *) arg;
156
157 /* First we lock the module. This ensures that it cannot be
158 * run twice.
159 */
160 pthread_cleanup_push(sh_pthread_mutex_unlock, (void*) &(this_module->mod_mutex));
161 pthread_mutex_lock(&(this_module->mod_mutex));
162
163 if (0 == sh_pthread_init_threadspecific())
164 {
165
166 if (0 == this_module->mod_init(NULL))
167 {
168 pthread_cleanup_push(sh_threaded_module_cleanup, arg);
169
170 while (1)
171 {
172 if (sh_thread_pause_flag != S_TRUE &&
173 0 != this_module->mod_timer(time(NULL)))
174 {
175 /* If module has been de-activated on reconfigure,
176 * mod_check() must return non-zero.
177 * The mod_cleanup() routine must then enable the
178 * module to be re-activated eventually.
179 */
180 if (0 != this_module->mod_check())
181 break;
182 pthread_testcancel();
183 }
184 if (0 == (SH_MODFL_NOTIMER & this_module->flags))
185 retry_msleep(1,0);
186 }
187
188 pthread_cleanup_pop(1); /* notreached,but required */
189 }
190 }
191
192 pthread_cleanup_pop(1);
193
194 return NULL;
195}
196
197
198/*
199 * ---- Implementation of recursive mutexes from libxml2 ----
200 */
201#if !defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
202/**
203 * libxml2 threads.c: set of generic threading related routines
204 *
205 * Gary Pennington <Gary.Pennington@uk.sun.com>
206 * daniel@veillard.com
207
208 * Except where otherwise noted in the source code (e.g. the files hash.c,
209 * list.c and the trio files, which are covered by a similar licence but
210 * with different Copyright notices) all the files are:
211 *
212 * Copyright (C) 1998-2003 Daniel Veillard. All Rights Reserved.
213 *
214 * Permission is hereby granted, free of charge, to any person obtaining a copy
215 * of this software and associated documentation files (the "Software"), to deal
216 * in the Software without restriction, including without limitation the rights
217 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
218 * copies of the Software, and to permit persons to whom the Software is fur-
219 * nished to do so, subject to the following conditions:
220 *
221 * The above copyright notice and this permission notice shall be included in
222 * all copies or substantial portions of the Software.
223 *
224 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
225 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
226 * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
227 * DANIEL VEILLARD BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
228 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
229 * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
230 *
231 * Except as contained in this notice, the name of Daniel Veillard shall not
232 * be used in advertising or otherwise to promote the sale, use or other deal-
233 * ings in this Software without prior written authorization from him.
234 */
235
236/* Modified NewRMutex -> InitRMutex. We use a static structure, rather than
237 * allocating one. Also dropped code for non-POSIX OSes.
238 */
239void sh_InitRMutex(struct sh_RMutex * tok)
240{
241 pthread_mutex_init(&tok->lock, NULL);
242 tok->held = 0;
243 tok->waiters = 0;
244 pthread_cond_init(&tok->cv, NULL);
245
246 return;
247}
248
249void sh_RMutexLock(struct sh_RMutex * tok)
250{
251 if (tok == NULL)
252 return;
253
254 pthread_mutex_lock(&tok->lock);
255 if (tok->held) {
256 if (pthread_equal(tok->tid, pthread_self())) {
257 tok->held++;
258 pthread_mutex_unlock(&tok->lock);
259 return;
260 } else {
261 tok->waiters++;
262 while (tok->held)
263 pthread_cond_wait(&tok->cv, &tok->lock);
264 tok->waiters--;
265 }
266 }
267 tok->tid = pthread_self();
268 tok->held = 1;
269 pthread_mutex_unlock(&tok->lock);
270}
271
272void sh_RMutexUnlock(void * arg)
273{
274 struct sh_RMutex * tok = (struct sh_RMutex *) arg;
275
276 if (tok == NULL)
277 return;
278
279 pthread_mutex_lock(&tok->lock);
280 tok->held--;
281 if (tok->held == 0) {
282 if (tok->waiters)
283 pthread_cond_signal(&tok->cv);
284 tok->tid = 0;
285 }
286 pthread_mutex_unlock(&tok->lock);
287}
288#endif
289
290
291#endif
Note: See TracBrowser for help on using the repository browser.