Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanups for mutex utilities #3912

Merged
merged 12 commits into from
Aug 11, 2023
2 changes: 0 additions & 2 deletions stl/inc/xthreads.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,8 @@ _CRTIMP2_PURE void __cdecl _Mtx_destroy_in_situ(_Mtx_t);
_CRTIMP2_PURE int __cdecl _Mtx_current_owns(_Mtx_t);
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_lock(_Mtx_t);
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_trylock(_Mtx_t);
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_timedlock(_Mtx_t, const _timespec64*);
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
_CRTIMP2_PURE _Thrd_result __cdecl _Mtx_unlock(_Mtx_t); // TRANSITION, ABI: Always succeeds
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

_CRTIMP2_PURE void* __cdecl _Mtx_getconcrtcs(_Mtx_t);
_CRTIMP2_PURE void __cdecl _Mtx_clear_owner(_Mtx_t);
_CRTIMP2_PURE void __cdecl _Mtx_reset_owner(_Mtx_t);

Expand Down
29 changes: 14 additions & 15 deletions stl/src/mutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,28 @@ void _Mtx_destroy(_Mtx_t mtx) { // destroy mutex
}

static _Thrd_result mtx_do_lock(_Mtx_t mtx, const _timespec64* target) { // lock mutex
// TRANSITION, ABI: the use of `const _timespec64*` is preserved for `_Mtx_timedlock`
const long current_thread_id = static_cast<long>(GetCurrentThreadId());
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
if ((mtx->_Type & ~_Mtx_recursive) == _Mtx_plain) { // set the lock
if (mtx->_Thread_id != static_cast<long>(GetCurrentThreadId())) { // not current thread, do lock
if (mtx->_Thread_id != current_thread_id) { // not current thread, do lock
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
AcquireSRWLockExclusive(get_srw_lock(mtx));
mtx->_Thread_id = static_cast<long>(GetCurrentThreadId());
mtx->_Thread_id = current_thread_id;
}
++mtx->_Count;

return _Thrd_result::_Success;
} else { // handle timed or recursive mutex
int res = WAIT_TIMEOUT;
if (target == nullptr) { // no target --> plain wait (i.e. infinite timeout)
if (mtx->_Thread_id != static_cast<long>(GetCurrentThreadId())) {
if (mtx->_Thread_id != current_thread_id) {
AcquireSRWLockExclusive(get_srw_lock(mtx));
}

res = WAIT_OBJECT_0;

} else if (target->tv_sec < 0 || target->tv_sec == 0 && target->tv_nsec <= 0) {
// target time <= 0 --> plain trylock or timed wait for time that has passed; try to lock with 0 timeout
if (mtx->_Thread_id != static_cast<long>(GetCurrentThreadId())) { // not this thread, lock it
if (mtx->_Thread_id != current_thread_id) { // not this thread, lock it
if (TryAcquireSRWLockExclusive(get_srw_lock(mtx)) != 0) {
res = WAIT_OBJECT_0;
} else {
Expand All @@ -107,11 +109,12 @@ static _Thrd_result mtx_do_lock(_Mtx_t mtx, const _timespec64* target) { // lock
}

} else { // check timeout
// TRANSITION, ABI: this branch is preserved for `_Mtx_timedlock`
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
_timespec64 now;
_Timespec64_get_sys(&now);
while (now.tv_sec < target->tv_sec || now.tv_sec == target->tv_sec && now.tv_nsec < target->tv_nsec) {
// time has not expired
if (mtx->_Thread_id == static_cast<long>(GetCurrentThreadId())
if (mtx->_Thread_id == current_thread_id
|| TryAcquireSRWLockExclusive(get_srw_lock(mtx)) != 0) { // stop waiting
res = WAIT_OBJECT_0;
break;
Expand All @@ -123,31 +126,25 @@ static _Thrd_result mtx_do_lock(_Mtx_t mtx, const _timespec64* target) { // lock
}
}

if (res == WAIT_OBJECT_0 || res == WAIT_ABANDONED) {
if (res == WAIT_OBJECT_0) {
if (1 < ++mtx->_Count) { // check count
if ((mtx->_Type & _Mtx_recursive) != _Mtx_recursive) { // not recursive, fixup count
--mtx->_Count;
res = WAIT_TIMEOUT;
}
} else {
mtx->_Thread_id = static_cast<long>(GetCurrentThreadId());
mtx->_Thread_id = current_thread_id;
}
}

switch (res) {
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
if (res == WAIT_OBJECT_0) {
return _Thrd_result::_Success;

case WAIT_TIMEOUT:
} else { // WAIT_TIMEOUT
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
if (target == nullptr || (target->tv_sec == 0 && target->tv_nsec == 0)) {
return _Thrd_result::_Busy;
} else {
return _Thrd_result::_Timedout;
}

default:
return _Thrd_result::_Error;
}
}
}
Expand Down Expand Up @@ -178,6 +175,7 @@ _Thrd_result _Mtx_trylock(_Mtx_t mtx) { // attempt to lock try_mutex
return mtx_do_lock(mtx, &xt);
}

// TRANSITION, ABI: preserved for binary compatibility
_Thrd_result _Mtx_timedlock(_Mtx_t mtx, const _timespec64* xt) { // attempt to lock timed mutex
_Thrd_result res;

Expand All @@ -190,6 +188,7 @@ int _Mtx_current_owns(_Mtx_t mtx) { // test if current thread owns mutex
return mtx->_Count != 0 && mtx->_Thread_id == static_cast<long>(GetCurrentThreadId());
}

// TRANSITION, ABI: preserved for binary compatibility
void* _Mtx_getconcrtcs(_Mtx_t mtx) { // get internal cs impl
return &mtx->_Critical_section;
}
Expand Down