Annotation of embedaddon/strongswan/src/libstrongswan/threading/thread.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2009-2012 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #define _GNU_SOURCE
17: #include <pthread.h>
18: #include <signal.h>
19:
20: #ifdef HAVE_GETTID
21: #include <sys/types.h>
22: #include <unistd.h>
23: #endif
24:
25: #ifdef HAVE_SYS_GETTID
26: #include <sys/syscall.h>
27: static inline pid_t gettid()
28: {
29: return syscall(SYS_gettid);
30: }
31: #endif
32:
33: #include <library.h>
34: #include <utils/debug.h>
35:
36: #include <threading/thread_value.h>
37: #include <threading/mutex.h>
38: #include <collections/linked_list.h>
39:
40: #include "thread.h"
41:
42: typedef struct private_thread_t private_thread_t;
43:
44: struct private_thread_t {
45: /**
46: * Public interface.
47: */
48: thread_t public;
49:
50: /**
51: * Identifier of this thread (human-readable/thread ID).
52: */
53: u_int id;
54:
55: /**
56: * ID of the underlying thread.
57: */
58: pthread_t thread_id;
59:
60: /**
61: * Main function of this thread (NULL for the main thread).
62: */
63: thread_main_t main;
64:
65: /**
66: * Argument for the main function.
67: */
68: void *arg;
69:
70: /**
71: * Stack of cleanup handlers.
72: */
73: linked_list_t *cleanup_handlers;
74:
75: /**
76: * Mutex to make modifying thread properties safe.
77: */
78: mutex_t *mutex;
79:
80: /**
81: * TRUE if this thread has been detached or joined, i.e. can be cleaned
82: * up after terminating.
83: */
84: bool detached_or_joined;
85:
86: /**
87: * TRUE if the threads has terminated (cancelled, via thread_exit or
88: * returned from the main function)
89: */
90: bool terminated;
91:
92: };
93:
94: typedef struct {
95: /**
96: * Cleanup callback function.
97: */
98: thread_cleanup_t cleanup;
99:
100: /**
101: * Argument provided to the cleanup function.
102: */
103: void *arg;
104:
105: } cleanup_handler_t;
106:
107:
108: /**
109: * Next thread ID.
110: */
111: static u_int next_id;
112:
113: /**
114: * Mutex to safely access the next thread ID.
115: */
116: static mutex_t *id_mutex;
117:
118: /**
119: * Store the thread object in a thread-specific value.
120: */
121: static thread_value_t *current_thread;
122:
123:
124: #ifndef HAVE_PTHREAD_CANCEL
125: /* if pthread_cancel is not available, we emulate it using a signal */
126: #ifdef ANDROID
127: #define SIG_CANCEL SIGUSR2
128: #else
129: #define SIG_CANCEL (SIGRTMIN+7)
130: #endif
131:
132: /* the signal handler for SIG_CANCEL uses pthread_exit to terminate the
133: * "cancelled" thread */
134: static void cancel_signal_handler(int sig)
135: {
136: pthread_exit(NULL);
137: }
138: #endif
139:
140:
141: /**
142: * Destroy an internal thread object.
143: *
144: * @note The mutex of this thread object has to be locked, it gets unlocked
145: * automatically.
146: */
147: static void thread_destroy(private_thread_t *this)
148: {
149: if (!this->terminated || !this->detached_or_joined)
150: {
151: this->mutex->unlock(this->mutex);
152: return;
153: }
154: this->cleanup_handlers->destroy(this->cleanup_handlers);
155: this->mutex->unlock(this->mutex);
156: this->mutex->destroy(this->mutex);
157: free(this);
158: }
159:
160: /**
161: * Determine the ID of the current thread
162: */
163: static u_int get_thread_id()
164: {
165: u_int id;
166:
167: #if defined(USE_THREAD_IDS) && defined(HAVE_GETTID)
168: id = gettid();
169: #else
170: id_mutex->lock(id_mutex);
171: id = next_id++;
172: id_mutex->unlock(id_mutex);
173: #endif
174: return id;
175: }
176:
177: METHOD(thread_t, cancel, void,
178: private_thread_t *this)
179: {
180: this->mutex->lock(this->mutex);
181: if (pthread_equal(this->thread_id, pthread_self()))
182: {
183: this->mutex->unlock(this->mutex);
184: DBG1(DBG_LIB, "!!! CANNOT CANCEL CURRENT THREAD !!!");
185: return;
186: }
187: #ifdef HAVE_PTHREAD_CANCEL
188: pthread_cancel(this->thread_id);
189: #else
190: pthread_kill(this->thread_id, SIG_CANCEL);
191: #endif /* HAVE_PTHREAD_CANCEL */
192: this->mutex->unlock(this->mutex);
193: }
194:
195: METHOD(thread_t, kill_, void,
196: private_thread_t *this, int sig)
197: {
198: this->mutex->lock(this->mutex);
199: if (pthread_equal(this->thread_id, pthread_self()))
200: {
201: /* it might actually be possible to send a signal to pthread_self (there
202: * is an example in raise(3) describing that), the problem is though,
203: * that the thread only returns here after the signal handler has
204: * returned, so depending on the signal, the lock might not get
205: * unlocked. */
206: this->mutex->unlock(this->mutex);
207: DBG1(DBG_LIB, "!!! CANNOT SEND SIGNAL TO CURRENT THREAD !!!");
208: return;
209: }
210: pthread_kill(this->thread_id, sig);
211: this->mutex->unlock(this->mutex);
212: }
213:
214: METHOD(thread_t, detach, void,
215: private_thread_t *this)
216: {
217: this->mutex->lock(this->mutex);
218: pthread_detach(this->thread_id);
219: this->detached_or_joined = TRUE;
220: thread_destroy(this);
221: }
222:
223: METHOD(thread_t, join, void*,
224: private_thread_t *this)
225: {
226: pthread_t thread_id;
227: void *val;
228:
229: this->mutex->lock(this->mutex);
230: if (pthread_equal(this->thread_id, pthread_self()))
231: {
232: this->mutex->unlock(this->mutex);
233: DBG1(DBG_LIB, "!!! CANNOT JOIN CURRENT THREAD !!!");
234: return NULL;
235: }
236: if (this->detached_or_joined)
237: {
238: this->mutex->unlock(this->mutex);
239: DBG1(DBG_LIB, "!!! CANNOT JOIN DETACHED THREAD !!!");
240: return NULL;
241: }
242: thread_id = this->thread_id;
243: this->detached_or_joined = TRUE;
244: if (this->terminated)
245: {
246: /* thread has terminated before the call to join */
247: thread_destroy(this);
248: }
249: else
250: {
251: /* thread_destroy is called when the thread terminates normally */
252: this->mutex->unlock(this->mutex);
253: }
254: pthread_join(thread_id, &val);
255:
256: return val;
257: }
258:
259: /**
260: * Create an internal thread object.
261: */
262: static private_thread_t *thread_create_internal()
263: {
264: private_thread_t *this;
265:
266: INIT(this,
267: .public = {
268: .cancel = _cancel,
269: .kill = _kill_,
270: .detach = _detach,
271: .join = _join,
272: },
273: .cleanup_handlers = linked_list_create(),
274: .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
275: );
276:
277: return this;
278: }
279:
280: /**
281: * Remove and run all cleanup handlers in reverse order.
282: */
283: static void thread_cleanup_popall_internal(private_thread_t *this)
284: {
285: cleanup_handler_t *handler;
286:
287: while (this->cleanup_handlers->remove_last(this->cleanup_handlers,
288: (void**)&handler) == SUCCESS)
289: {
290: handler->cleanup(handler->arg);
291: free(handler);
292: }
293: }
294:
295: /**
296: * Main cleanup function for threads.
297: */
298: static void thread_cleanup(private_thread_t *this)
299: {
300: thread_cleanup_popall_internal(this);
301: this->mutex->lock(this->mutex);
302: this->terminated = TRUE;
303: thread_destroy(this);
304: }
305:
306: /**
307: * Main function wrapper for threads.
308: */
309: static void *thread_main(private_thread_t *this)
310: {
311: void *res;
312:
313: this->id = get_thread_id();
314:
315: current_thread->set(current_thread, this);
316: pthread_cleanup_push((thread_cleanup_t)thread_cleanup, this);
317:
318: /* TODO: this is not 100% portable as pthread_t is an opaque type (i.e.
319: * could be of any size, or even a struct) */
320: #ifdef HAVE_GETTID
321: DBG2(DBG_LIB, "created thread %.2d [%u]",
322: this->id, gettid());
323: #elif defined(WIN32)
324: DBG2(DBG_LIB, "created thread %.2d [%p]",
325: this->id, this->thread_id.p);
326: #else
327: DBG2(DBG_LIB, "created thread %.2d [%lx]",
328: this->id, (u_long)this->thread_id);
329: #endif
330:
331: res = this->main(this->arg);
332: pthread_cleanup_pop(TRUE);
333:
334: return res;
335: }
336:
337: /**
338: * Described in header.
339: */
340: thread_t *thread_create(thread_main_t main, void *arg)
341: {
342: private_thread_t *this = thread_create_internal();
343:
344: this->main = main;
345: this->arg = arg;
346:
347: if (pthread_create(&this->thread_id, NULL, (void*)thread_main, this) != 0)
348: {
349: DBG1(DBG_LIB, "failed to create thread!");
350: this->mutex->lock(this->mutex);
351: this->terminated = TRUE;
352: this->detached_or_joined = TRUE;
353: thread_destroy(this);
354: return NULL;
355: }
356:
357: return &this->public;
358: }
359:
360: /**
361: * Described in header.
362: */
363: thread_t *thread_current()
364: {
365: private_thread_t *this;
366:
367: this = (private_thread_t*)current_thread->get(current_thread);
368: if (!this)
369: {
370: this = thread_create_internal();
371: this->id = get_thread_id();
372: current_thread->set(current_thread, (void*)this);
373: }
374: return &this->public;
375: }
376:
377: /**
378: * Described in header.
379: */
380: u_int thread_current_id()
381: {
382: private_thread_t *this = (private_thread_t*)thread_current();
383:
384: return this ? this->id : 0;
385: }
386:
387: /**
388: * Described in header.
389: */
390: void thread_cleanup_push(thread_cleanup_t cleanup, void *arg)
391: {
392: private_thread_t *this = (private_thread_t*)thread_current();
393: cleanup_handler_t *handler;
394:
395: INIT(handler,
396: .cleanup = cleanup,
397: .arg = arg,
398: );
399:
400: this->cleanup_handlers->insert_last(this->cleanup_handlers, handler);
401: }
402:
403: /**
404: * Described in header.
405: */
406: void thread_cleanup_pop(bool execute)
407: {
408: private_thread_t *this = (private_thread_t*)thread_current();
409: cleanup_handler_t *handler;
410:
411: if (this->cleanup_handlers->remove_last(this->cleanup_handlers,
412: (void**)&handler) != SUCCESS)
413: {
414: DBG1(DBG_LIB, "!!! THREAD CLEANUP ERROR !!!");
415: return;
416: }
417:
418: if (execute)
419: {
420: handler->cleanup(handler->arg);
421: }
422: free(handler);
423: }
424:
425: /**
426: * Described in header.
427: */
428: void thread_cleanup_popall()
429: {
430: private_thread_t *this = (private_thread_t*)thread_current();
431:
432: thread_cleanup_popall_internal(this);
433: }
434:
435: /**
436: * Described in header.
437: */
438: bool thread_cancelability(bool enable)
439: {
440: #ifdef HAVE_PTHREAD_CANCEL
441: int old;
442:
443: pthread_setcancelstate(enable ? PTHREAD_CANCEL_ENABLE
444: : PTHREAD_CANCEL_DISABLE, &old);
445:
446: return old == PTHREAD_CANCEL_ENABLE;
447: #else
448: sigset_t new, old;
449:
450: sigemptyset(&new);
451: sigaddset(&new, SIG_CANCEL);
452: pthread_sigmask(enable ? SIG_UNBLOCK : SIG_BLOCK, &new, &old);
453:
454: return sigismember(&old, SIG_CANCEL) == 0;
455: #endif /* HAVE_PTHREAD_CANCEL */
456: }
457:
458: /**
459: * Described in header.
460: */
461: void thread_cancellation_point()
462: {
463: bool old = thread_cancelability(TRUE);
464:
465: #ifdef HAVE_PTHREAD_CANCEL
466: pthread_testcancel();
467: #endif /* HAVE_PTHREAD_CANCEL */
468: thread_cancelability(old);
469: }
470:
471: /**
472: * Described in header.
473: */
474: void thread_exit(void *val)
475: {
476: pthread_exit(val);
477: }
478:
479: /**
480: * A dummy thread value that reserved pthread_key_t value "0". A buggy PKCS#11
481: * library mangles this key, without owning it, so we allocate it for them.
482: */
483: static thread_value_t *dummy1;
484:
485: /**
486: * Described in header.
487: */
488: void threads_init()
489: {
490: private_thread_t *main_thread = thread_create_internal();
491:
492: dummy1 = thread_value_create(NULL);
493:
494: next_id = 0;
495: main_thread->thread_id = pthread_self();
496: current_thread = thread_value_create(NULL);
497: current_thread->set(current_thread, (void*)main_thread);
498: id_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
499: main_thread->id = get_thread_id();
500:
501: #ifndef HAVE_PTHREAD_CANCEL
502: { /* install a signal handler for our custom SIG_CANCEL */
503: struct sigaction action = {
504: .sa_handler = cancel_signal_handler
505: };
506: sigaction(SIG_CANCEL, &action, NULL);
507: }
508: #endif /* HAVE_PTHREAD_CANCEL */
509: }
510:
511: /**
512: * Described in header.
513: */
514: void threads_deinit()
515: {
516: private_thread_t *main_thread = (private_thread_t*)thread_current();
517:
518: dummy1->destroy(dummy1);
519:
520: main_thread->mutex->lock(main_thread->mutex);
521: main_thread->terminated = TRUE;
522: main_thread->detached_or_joined = TRUE;
523: thread_destroy(main_thread);
524: current_thread->destroy(current_thread);
525: id_mutex->destroy(id_mutex);
526: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>