int mythread_mutex_unlock(mythread_mutex_t *mutex) { int status; if(mutex->lockvariable==-1) // if the lock was already destroyed, return an error code { return 1; // return the error code } status=compare_and_swap(&mutex->lockvariable,0,1); // changing the state of the lockvariable to unlocked atomically while(status==0) { status=compare_and_swap(&mutex->lockvariable,0,1); } mythread_enter_kernel(); mutex->noofwaitingthreads-=1; // decrementing the number of threads waiting on the mutex by one mutex->owner_thread=NULL; // Chech if there are any threads that are blocked in the queue due to exceeding the threshold if(mutex->noofwaitingthreads==mutex->noofblockedthreads && mutex->noofwaitingthreads > 0) { mutex->noofblockedthreads-=1; mythread_unblock(mutex->blocked_threads,1); } else { mythread_leave_kernel(); } return 0; }
/* * This function unblocks one of the threads blocked on a conditional variable * The scheduling policy uses FIFO * Pre:A conditional variable on which threads are blocked * Post:One thread which was blocked on the conditional variable is unblocked * Returns: 1 on failure * 0 on success */ int mythread_cond_signal(mythread_cond_t * cond) { /* * Wait if there is any thread is executing conditional wait * This is used to ensure no signal is lost * while any thread is executing condtional wait code. */ if (futex_down(&ccb_table[*cond]->mutex)) { perror("failed to do futex_down"); return 1; } /* * Dequeue and resume the thread from blocked queue */ mythread_enter_kernel(); if(ccb_table[*cond]->q != NULL) { mythread_unblock(&ccb_table[*cond]->q, 0); } else { mythread_leave_kernel(); } /* * Resume any thread about to execute conditional wait */ if (futex_up(&ccb_table[*cond]->mutex)) { perror("failed to do futex up\n"); return 1; } return 0; }
/* * Will release a thread if needed, otherwise will just increment * the semaphore's value * * @Param - Pointer to the semaphore that is being signaled */ void mysem_signal(Semaphore* sem){ DISABLE_INTERRUPTS(); sem->value++; if(sem->value <= 0){ mythread_unblock(release_thread(sem)); mysem_printQueue(sem); } ENABLE_INTERRUPTS(); }
int mythread_mutex_unlock (mythread_mutex_t *mutex) { // if mutex is not pointing to anything valid then return EINVAL if (!mutex) return EINVAL; if (mutex->value == -1) return EINVAL; mythread_enter_kernel (); // set the mutex value to zero to indicate that mutex is available. mutex->value = 0; // unblock the next thread from the mutex queue waiting for the lock. mythread_unblock (&mutex->queue, RUNNING); 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 }
/* * This function unblocks all the threads which are blocked on the conditional variable referenced by cond * Pre:A conditional variable on which threads are blocked * Post: All threads which are blocked on the conditional variable are unblocked * Returns: 1 on failure * 0 on success */ int mythread_cond_broadcast(mythread_cond_t * cond) { if (futex_down(&ccb_table[*cond]->mutex)) { perror("failed to do futex_down\n"); return 1; } /* * Remove each thread from head of the queue and wake up all the blocked threads. */ mythread_enter_kernel(); while (ccb_table[*cond]->q != NULL) { mythread_unblock(&ccb_table[*cond]->q, 0); mythread_enter_kernel(); } mythread_leave_kernel(); /* * Resume any thread that is about to execute conditional wait */ if (futex_up(&ccb_table[*cond]->mutex)) { perror("failed to do futex_up\n"); return 1; } return 0; }