File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / threading / thread.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 3 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    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>