sessionmgr: fix deadlock with multiple waiters (fix #556)

This commit is contained in:
fincs 2021-06-20 12:39:42 +02:00
parent b17873d071
commit 982aef9ea5
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
2 changed files with 4 additions and 5 deletions

View File

@ -12,7 +12,7 @@ typedef struct SessionMgr
u32 free_mask; u32 free_mask;
Mutex mutex; Mutex mutex;
CondVar condvar; CondVar condvar;
bool is_waiting; u32 num_waiters;
} SessionMgr; } SessionMgr;
Result sessionmgrCreate(SessionMgr* mgr, Handle root_session, u32 num_sessions); Result sessionmgrCreate(SessionMgr* mgr, Handle root_session, u32 num_sessions);

View File

@ -43,8 +43,9 @@ int sessionmgrAttachClient(SessionMgr* mgr) {
for (;;) { for (;;) {
slot = __builtin_ffs(mgr->free_mask)-1; slot = __builtin_ffs(mgr->free_mask)-1;
if (slot >= 0) break; if (slot >= 0) break;
mgr->is_waiting = true; mgr->num_waiters ++;
condvarWait(&mgr->condvar, &mgr->mutex); condvarWait(&mgr->condvar, &mgr->mutex);
mgr->num_waiters --;
} }
mgr->free_mask &= ~(1U << slot); mgr->free_mask &= ~(1U << slot);
mutexUnlock(&mgr->mutex); mutexUnlock(&mgr->mutex);
@ -54,9 +55,7 @@ int sessionmgrAttachClient(SessionMgr* mgr) {
void sessionmgrDetachClient(SessionMgr* mgr, int slot) { void sessionmgrDetachClient(SessionMgr* mgr, int slot) {
mutexLock(&mgr->mutex); mutexLock(&mgr->mutex);
mgr->free_mask |= 1U << slot; mgr->free_mask |= 1U << slot;
if (mgr->is_waiting) { if (mgr->num_waiters)
mgr->is_waiting = false;
condvarWakeOne(&mgr->condvar); condvarWakeOne(&mgr->condvar);
}
mutexUnlock(&mgr->mutex); mutexUnlock(&mgr->mutex);
} }