以下是我对SleepConditionVariableCS
,WakeAllConditionVariable
和线程创建函数的实现。问题是,有时当我尝试创建线程时,创建线程会卡WaitForSingleObject( cv->mut, INFINITE );
在SleepConditionVariableCS
. 我无法弄清楚这里的比赛条件是什么。
typedef struct
{
int waiters_count;
HANDLE sema_;
HANDLE mut;
} CONDITION_VARIABLE;
void SleepConditionVariableCS(CONDITION_VARIABLE *cv, CRITICAL_SECTION *cs, int32_t dwMilliseconds){
WaitForSingleObject( cv->mut, INFINITE ); //Acuire object lock
cv->waiters_count++;
LeaveCriticalSection (cs);
if (SignalObjectAndWait(cv->mut, cv->sema_, dwMilliseconds, FALSE) == WAIT_TIMEOUT){ //SignalObjectAndWait releases the lock
cv->waiters_count--;
}
EnterCriticalSection(cs);
}
void WakeAllConditionVariable(CONDITION_VARIABLE *cv){
WaitForSingleObject( cv->mut, INFINITE );
while (cv->waiters_count > 0){
cv->waiters_count = cv->waiters_count - 1;
ReleaseSemaphore (cv->sema_, 1, 0);
}
ReleaseMutex(cv->mut);
}
void KernelThread_CreationWait(void *kthread){
KernelThread *thread = (KernelThread *) kthread;
EnterCriticalSection(thread->lock);
thread->state = Thread_CREATED;
WakeAllConditionVariable(thread->condition_variable);
LeaveCriticalSection(thread->lock);
KernelThread_main(kthread);
}
KernelThread* createKernelThread(){
EventHandler_getHandler();
unsigned long threadid;
int t;
void *hand;
KernelThread *thread = KernelThread_malloc();
EnterCriticalSection(thread->lock);
thread->state = Thread_WAITINGFORCREATION;
hand = CreateThread(NULL,
0, // security, stack size
(LPTHREAD_START_ROUTINE)&KernelThread_CreationWait, // start
(void *)thread,
0,
&threadid); // param, creation flags, id
if (hand == NULL){
printf("ERROR: return handle from CreateThread() is NULL\n");
exit(-1);
}
thread->thread = hand;
thread->thread_id = threadid;
SleepConditionVariableCS(thread->condition_variable,thread->lock,INFINITE);
LeaveCriticalSection(thread->lock);
return thread;
}
void InitializeConditionVariable (CONDITION_VARIABLE *cv){
cv->waiters_count = 0;
cv->sema_ = CreateSemaphore (NULL, // no security
0, // initially 0
0x7fffffff, // max count
NULL); // unnamed
cv->mut = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
}