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

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Martin Willi
                      3:  * Copyright (C) 2013 revosec AG
                      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 "thread.h"
                     17: 
                     18: #include <utils/debug.h>
                     19: #include <threading/mutex.h>
                     20: #include <threading/condvar.h>
                     21: 
                     22: typedef struct private_mutex_t private_mutex_t;
                     23: typedef struct private_condvar_t private_condvar_t;
                     24: 
                     25: /**
                     26:  * private data of mutex
                     27:  */
                     28: struct private_mutex_t {
                     29: 
                     30:        /**
                     31:         * public functions
                     32:         */
                     33:        mutex_t public;
                     34: 
                     35:        /**
                     36:         * wrapped critical section
                     37:         */
                     38:        CRITICAL_SECTION cs;
                     39: 
                     40:        /**
                     41:         * Recursive lock count
                     42:         */
                     43:        u_int times;
                     44: };
                     45: 
                     46: /**
                     47:  * private data of condvar
                     48:  */
                     49: struct private_condvar_t {
                     50: 
                     51:        /**
                     52:         * public functions
                     53:         */
                     54:        condvar_t public;
                     55: 
                     56:        /**
                     57:         * wrapped condition variable
                     58:         */
                     59:        CONDITION_VARIABLE cv;
                     60: };
                     61: 
                     62: 
                     63: METHOD(mutex_t, lock, void,
                     64:        private_mutex_t *this)
                     65: {
                     66:        EnterCriticalSection(&this->cs);
                     67:        this->times++;
                     68: }
                     69: 
                     70: METHOD(mutex_t, unlock, void,
                     71:        private_mutex_t *this)
                     72: {
                     73:        this->times--;
                     74:        LeaveCriticalSection(&this->cs);
                     75: }
                     76: 
                     77: METHOD(mutex_t, mutex_destroy, void,
                     78:        private_mutex_t *this)
                     79: {
                     80:        DeleteCriticalSection(&this->cs);
                     81:        free(this);
                     82: }
                     83: 
                     84: /*
                     85:  * see header file
                     86:  */
                     87: mutex_t *mutex_create(mutex_type_t type)
                     88: {
                     89:        private_mutex_t *this;
                     90: 
                     91:        INIT(this,
                     92:                .public = {
                     93:                        .lock = _lock,
                     94:                        .unlock = _unlock,
                     95:                        .destroy = _mutex_destroy,
                     96:                },
                     97:        );
                     98: 
                     99:        /* CriticalSections are recursive, we use it for all mutex types. */
                    100:        InitializeCriticalSection(&this->cs);
                    101: 
                    102:        return &this->public;
                    103: }
                    104: 
                    105: METHOD(condvar_t, timed_wait, bool,
                    106:        private_condvar_t *this, mutex_t *pubmutex, u_int timeout)
                    107: {
                    108:        private_mutex_t *mutex = (private_mutex_t*)pubmutex;
                    109:        u_int times;
                    110:        bool ret;
                    111: 
                    112:        thread_set_active_condvar(&this->cv);
                    113: 
                    114:        /* while a CriticalSection is recursive, waiting in a condvar releases
                    115:         * only one mutex. So release (and reacquire) all locks except the last. */
                    116:        times = mutex->times;
                    117:        while (mutex->times-- > 1)
                    118:        {
                    119:                LeaveCriticalSection(&mutex->cs);
                    120:        }
                    121: 
                    122:        ret = SleepConditionVariableCS(&this->cv, &mutex->cs, timeout);
                    123: 
                    124:        while (++mutex->times < times)
                    125:        {
                    126:                EnterCriticalSection(&mutex->cs);
                    127:        }
                    128: 
                    129:        thread_set_active_condvar(NULL);
                    130: 
                    131:        return ret == 0;
                    132: }
                    133: 
                    134: METHOD(condvar_t, wait_, void,
                    135:        private_condvar_t *this, mutex_t *mutex)
                    136: {
                    137:        timed_wait(this, mutex, INFINITE);
                    138: }
                    139: 
                    140: METHOD(condvar_t, timed_wait_abs, bool,
                    141:        private_condvar_t *this, mutex_t *mutex, timeval_t tv)
                    142: {
                    143:        DWORD timeout;
                    144:        timeval_t now, diff;
                    145: 
                    146:        time_monotonic(&now);
                    147:        if (timercmp(&now, &tv, >))
                    148:        {
                    149:                return TRUE;
                    150:        }
                    151:        timersub(&tv, &now, &diff);
                    152:        timeout = diff.tv_sec * 1000 + diff.tv_usec / 1000;
                    153: 
                    154:        return timed_wait(this, mutex, timeout);
                    155: }
                    156: 
                    157: METHOD(condvar_t, signal_, void,
                    158:        private_condvar_t *this)
                    159: {
                    160:        WakeConditionVariable(&this->cv);
                    161: }
                    162: 
                    163: METHOD(condvar_t, broadcast, void,
                    164:        private_condvar_t *this)
                    165: {
                    166:        WakeAllConditionVariable(&this->cv);
                    167: }
                    168: 
                    169: METHOD(condvar_t, condvar_destroy, void,
                    170:        private_condvar_t *this)
                    171: {
                    172:        free(this);
                    173: }
                    174: 
                    175: /*
                    176:  * see header file
                    177:  */
                    178: condvar_t *condvar_create(condvar_type_t type)
                    179: {
                    180:        private_condvar_t *this;
                    181: 
                    182:        INIT(this,
                    183:                .public = {
                    184:                        .wait = _wait_,
                    185:                        .timed_wait = _timed_wait,
                    186:                        .timed_wait_abs = _timed_wait_abs,
                    187:                        .signal = _signal_,
                    188:                        .broadcast = _broadcast,
                    189:                        .destroy = _condvar_destroy,
                    190:                }
                    191:        );
                    192: 
                    193:        InitializeConditionVariable(&this->cv);
                    194: 
                    195:        return &this->public;
                    196: }

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