source: trunk/src/sh_pthread.c@ 402

Last change on this file since 402 was 335, checked in by katerina, 13 years ago

Module cleanup/thread restart at configuration reload.

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