Annotation of embedaddon/strongswan/src/libstrongswan/threading/semaphore.c, revision 1.1.1.1

1.1       misho       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>