source: trunk/src/sh_pthread.c@ 142

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

Login watch runs in thread.

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