File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / threading / semaphore.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) 2011 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: #include <library.h>
   17: 
   18: #if defined(HAVE_CLOCK_GETTIME) && \
   19: 	(defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
   20: 	 defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
   21: /* if we use MONOTONIC times, we can't use POSIX_SEMAPHORES since they use
   22:  * times based on CLOCK_REALTIME */
   23: #undef HAVE_SEM_TIMEDWAIT
   24: #endif /* HAVE_CLOCK_GETTIME && ... */
   25: 
   26: #ifdef HAVE_SEM_TIMEDWAIT
   27: #include <semaphore.h>
   28: #else /* !HAVE_SEM_TIMEDWAIT */
   29: #include <threading/thread.h>
   30: #include <threading/condvar.h>
   31: #endif /* HAVE_SEM_TIMEDWAIT */
   32: 
   33: #include "semaphore.h"
   34: 
   35: typedef struct private_semaphore_t private_semaphore_t;
   36: 
   37: /**
   38:  * private data of a semaphore
   39:  */
   40: struct private_semaphore_t {
   41: 	/**
   42: 	 * public interface
   43: 	 */
   44: 	semaphore_t public;
   45: 
   46: #ifdef HAVE_SEM_TIMEDWAIT
   47: 	/**
   48: 	 * wrapped POSIX semaphore object
   49: 	 */
   50: 	sem_t sem;
   51: #else /* !HAVE_SEM_TIMEDWAIT */
   52: 
   53: 	/**
   54: 	 * Mutex to lock count variable
   55: 	 */
   56: 	mutex_t *mutex;
   57: 
   58: 	/**
   59: 	 * Condvar to signal count increase
   60: 	 */
   61: 	condvar_t *cond;
   62: 
   63: 	/**
   64: 	 * Semaphore count value
   65: 	 */
   66: 	u_int count;
   67: #endif /* HAVE_SEM_TIMEDWAIT */
   68: };
   69: 
   70: METHOD(semaphore_t, wait_, void,
   71: 	private_semaphore_t *this)
   72: {
   73: #ifdef HAVE_SEM_TIMEDWAIT
   74: 	sem_wait(&this->sem);
   75: #else /* !HAVE_SEM_TIMEDWAIT */
   76: 	this->mutex->lock(this->mutex);
   77: 	thread_cleanup_push((void*)this->mutex->unlock, this->mutex);
   78: 	while (this->count == 0)
   79: 	{
   80: 		this->cond->wait(this->cond, this->mutex);
   81: 	}
   82: 	this->count--;
   83: 	thread_cleanup_pop(TRUE);
   84: #endif /* HAVE_SEM_TIMEDWAIT */
   85: }
   86: 
   87: METHOD(semaphore_t, timed_wait_abs, bool,
   88: 	private_semaphore_t *this, timeval_t tv)
   89: {
   90: #ifdef HAVE_SEM_TIMEDWAIT
   91: 	timespec_t ts;
   92: 
   93: 	ts.tv_sec = tv.tv_sec;
   94: 	ts.tv_nsec = tv.tv_usec * 1000;
   95: 
   96: 	/* there are errors other than ETIMEDOUT possible, but we consider them
   97: 	 * all as timeout */
   98: 	return sem_timedwait(&this->sem, &ts) == -1;
   99: #else /* !HAVE_SEM_TIMEDWAIT */
  100: 	this->mutex->lock(this->mutex);
  101: 	thread_cleanup_push((void*)this->mutex->unlock, this->mutex);
  102: 	while (this->count == 0)
  103: 	{
  104: 		if (this->cond->timed_wait_abs(this->cond, this->mutex, tv))
  105: 		{
  106: 			thread_cleanup_pop(TRUE);
  107: 			return TRUE;
  108: 		}
  109: 	}
  110: 	this->count--;
  111: 	thread_cleanup_pop(TRUE);
  112: 	return FALSE;
  113: #endif /* HAVE_SEM_TIMEDWAIT */
  114: }
  115: 
  116: METHOD(semaphore_t, timed_wait, bool,
  117: 	private_semaphore_t *this, u_int timeout)
  118: {
  119: 	timeval_t tv, add;
  120: 
  121: 	add.tv_sec = timeout / 1000;
  122: 	add.tv_usec = (timeout % 1000) * 1000;
  123: 
  124: 	time_monotonic(&tv);
  125: 	timeradd(&tv, &add, &tv);
  126: 
  127: 	return timed_wait_abs(this, tv);
  128: }
  129: 
  130: METHOD(semaphore_t, post, void,
  131: 	private_semaphore_t *this)
  132: {
  133: #ifdef HAVE_SEM_TIMEDWAIT
  134: 	sem_post(&this->sem);
  135: #else /* !HAVE_SEM_TIMEDWAIT */
  136: 	this->mutex->lock(this->mutex);
  137: 	this->count++;
  138: 	this->mutex->unlock(this->mutex);
  139: 	this->cond->signal(this->cond);
  140: #endif /* HAVE_SEM_TIMEDWAIT */
  141: }
  142: 
  143: METHOD(semaphore_t, destroy, void,
  144: 	private_semaphore_t *this)
  145: {
  146: #ifdef HAVE_SEM_TIMEDWAIT
  147: 	sem_destroy(&this->sem);
  148: #else /* !HAVE_SEM_TIMEDWAIT */
  149: 	this->cond->destroy(this->cond);
  150: 	this->mutex->destroy(this->mutex);
  151: #endif /* HAVE_SEM_TIMEDWAIT */
  152: 	free(this);
  153: }
  154: 
  155: /*
  156:  * Described in header
  157:  */
  158: semaphore_t *semaphore_create(u_int value)
  159: {
  160: 	private_semaphore_t *this;
  161: 
  162: 	INIT(this,
  163: 		.public = {
  164: 			.wait = _wait_,
  165: 			.timed_wait = _timed_wait,
  166: 			.timed_wait_abs = _timed_wait_abs,
  167: 			.post = _post,
  168: 			.destroy = _destroy,
  169: 		},
  170: 	);
  171: 
  172: #ifdef HAVE_SEM_TIMEDWAIT
  173: 	sem_init(&this->sem, 0, value);
  174: #else /* !HAVE_SEM_TIMEDWAIT */
  175: 	this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
  176: 	this->cond = condvar_create(CONDVAR_TYPE_DEFAULT);
  177: 	this->count = value;
  178: #endif /* HAVE_SEM_TIMEDWAIT */
  179: 
  180: 	return &this->public;
  181: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>