source: trunk/src/sh_pthread.c@ 140

Last change on this file since 140 was 140, checked in by rainer, 17 years ago

Utility function for threaded modules.

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