int mythread_mutex_lock(mythread_mutex_t *mutex) { int lockstatus; mythread_enter_kernel(); mutex->noofwaitingthreads=mutex->noofwaitingthreads+1; mythread_leave_kernel(); if(mutex->lockvariable==-1)// if the lock was already destroyed then return the error code { return 1; // error code } lockstatus=testandtestandset(&(mutex->lockvariable)); // a lockstatus of 0 denotes a successful acquiring of lock while(lockstatus==1) // if the lock acquiring fails after 100 tries , then the thread is blocked and put in a queue until lock becomes available { mythread_enter_kernel(); mutex->noofblockedthreads=mutex->noofblockedthreads+1; mythread_block((mutex->blocked_threads),0);// actual 0 lockstatus=testandtestandset(&(mutex->lockvariable)); // thread that returns from the block state tries to acquire the lock again } mythread_enter_kernel(); mutex->owner_thread=mythread_self(); mythread_leave_kernel(); return lockstatus; }
int mythread_scheduler(){ mythread_t self = mythread_self(); /*Limiting number of priority queues to 10 */ if(self->preemptions < 10){ self->preemptions += 1; } self->attr.attr = pow(2,self->preemptions); /*Since preemptions = invocation -1 */ mythread_block(mythread_readyq(),1); return 0; }
/* * Will block the thread if needed, otherwise will just decrement * the semaphore's value * * @Param - Pointer to the semaphore that will impose waiting */ void mysem_wait(Semaphore* sem){ DISABLE_INTERRUPTS(); sem->value--; tcb* currentThread = get_mythread(); if(sem->value < 0){ mythread_block(currentThread); block_thread(sem, currentThread); mysem_printQueue(sem); } ENABLE_INTERRUPTS(); // Stall the thread until the thread becomes READY while(currentThread->state==BLOCKED){ asm("nop"); } }
int mythread_mutex_lock (mythread_mutex_t *mutex) { // if mutex is not poinitng to anything valid then return EINVAL if (!mutex) return EINVAL; if (mutex->value == -1) return EINVAL; int retry = 0; while (1) { mythread_enter_kernel(); // check if lock is available for atmost 50 times while ((mutex->value == 1) && (retry < RETRY_MAX)) { retry++; } // if we waited for 50 times and lock still not avaialable then break from he loop and block the current thread. if (retry == RETRY_MAX) { break; } // if lock is avaialable, grab it atomically using compare and swap function if (compare_and_swap (&mutex->value, 1, 0)==0) { // update the current owner to mutex to current thread mutex->thread = mythread_self(); mythread_leave_kernel(); return 0; // success } } // end of while loop // if lock is not available after 50 tries, block the current thread. mythread_block (&mutex->queue, BLOCKED); return 0; // success }
int mythread_barrier_wait (mythread_barrier_t *barrier) { // if barrier does not exist or if it was previously destroyed, then return error code. if (!barrier) return EINVAL; if (barrier->init_count == -1) return EINVAL; int i; mythread_enter_kernel(); // A thread called wait, decrement the counter by 1. if (barrier->count > 0) barrier->count--; // if this is the last thread calling the wait if (barrier->count == 0) { // reinitialize the barrier count before unblocking rest of threads, so that the barrier can be reused barrier->count = barrier->init_count; // there should exactly be (init_count - 1) number of threads in the queue at this point. Unblock all of them. for (i = 0; i < barrier->init_count -1; i++) { mythread_unblock (&barrier->queue, 0); mythread_enter_kernel (); } mythread_leave_kernel(); // only the last thread returns MYTHREAD_BARRIER_SERIAL_THREAD while rest of threads return 0. return MYTHREAD_BARRIER_SERIAL_THREAD; // success } // if this is not the last thread calling wait, block the current thread. else mythread_block (&barrier->queue, 1); return 0; // success }