diff --git a/src/libsodium/sodium/core.c b/src/libsodium/sodium/core.c index ad48bd20..dcfd8ff7 100644 --- a/src/libsodium/sodium/core.c +++ b/src/libsodium/sodium/core.c @@ -76,33 +76,44 @@ _sodium_crit_leave(void) #elif defined(_WIN32) -static CRITICAL_SECTION *_sodium_lock; +static CRITICAL_SECTION _sodium_lock; static volatile LONG _sodium_lock_initialized; +static int +_sodium_crit_init(void) +{ + LONG status = 0L; + + while ((status = InterlockedCompareExchange(&_sodium_lock_initialized, + 1L, 0L)) == 1L) { + Sleep(0); + } + + switch(status) { + case 0L: + InitializeCriticalSection(&_sodium_lock); + return InterlockedExchange(&_sodium_lock_initialized, 2L) == 1L ? 0 : -1; + case 2L: + return 0; + default: /* should never be reached */ + return -1; + } +} + static int _sodium_crit_enter(void) { - if (InterlockedCompareExchange(&_sodium_lock_initialized, - 1L, 0L) == 0L) { - InitializeCriticalSection(_sodium_lock); - InterlockedIncrement(&_sodium_lock_initialized); - } else { - while (InterlockedCompareExchange(&_sodium_lock_initialized, - 2L, 2L) != 2L) { - Sleep(0); - } + if(_sodium_crit_init() != 0) { + return -1; } + EnterCriticalSection(&_sodium_lock); return 0; } static int _sodium_crit_leave(void) { - if (_sodium_lock == NULL) { - return -1; - } - LeaveCriticalSection(_sodium_lock); - + LeaveCriticalSection(&_sodium_lock); return 0; }