void OSTakeMutex(OSMutex *mutex) { OSMakeAtomic(); if(!mutex->val) { procEnq(_running, _tasks, &mutex->blocked); _tasks[_running].status |= _OS_BLOCKED; OSExitAtomic(); OSSwap(); } else mutex->val=0; OSExitAtomic(); }
// Can only be used by one process. void OSWait(OSCond *cond, OSMutex *mutex) { OSMakeAtomic(); if(!cond->pendingWake) { cond->blockedProcess=_running; _tasks[_running].status |= _OS_BLOCKED; OSGiveMutex(mutex); OSMakeAtomic(); // If val is 1 it means no swap took place. if(mutex->val) OSSwap(); // Retake the mutex when we resume OSTakeMutex(mutex); } else cond->pendingWake=0; OSExitAtomic(); }
void OSTakeSema(TOSSema *sema) { unsigned char sreg; OSMakeAtomic(&sreg); if(sema->semaval>0) sema->semaval--; else { // Block current process _tasks[_running].status |= _OS_BLOCKED; // Enqueue this task prioEnq(_running, _tasks, &sema->taskQ); OSExitAtomic(sreg); // Call scheduler. OSSwap(); } OSExitAtomic(sreg); }