int sthread_mutex_lock(sthread_mutex_t *mutex) { sthread_t ptr_this_thread = sthread_self(); //fighting for the right to modify Q while(test_and_set(&mutex->M)){} //after this I am now the only one //to modify the passed in mutex //therefore I should go ahead and //modify the lock and Q if needed //check if I should go into critical //section struct queue *pQ = &mutex->Q; if(Q_empty(pQ)) { //lock available Q_push(pQ, ptr_this_thread); mutex->M = 0; // I am done with Q; others can come and look / change Q. return 0; //this_thread will go into critical section } else { //lock not available //there are someone or myself before me in the Q //if it is myself in criticle section //I shoud not wait for myself to wake myself up //I will increment counter and keep running in criticle seciton //else //someone else is before me in the Q //either he is sleeping (he is not the 1st) //or he is in the critical section now (he is the 1st and //I am the 2nd in Q) //either way I should go to bed and wait for him to wake me up if(Q_first(pQ)->ptr_thread == ptr_this_thread) { Q_first(pQ)->count++; //Trying to acquire the lock own by myself //take down this attempt and keep myself in //criticle section mutex->M = 0; //I am done with lock; others can now check / modify lock. } else { Q_push(pQ, ptr_this_thread); mutex->M = 0; sthread_suspend(); //Other thread is in criticle section //I should go to bed and sleep return 0; //the moment I am woken up will //return 0 to caller } } }
int enqueueWait(sthread_mutex_t *mutex){ if(mutex->wcount == MAX_THREADS){ printf("Queue is full when callling enqueueWait()\n"); return -1; } else{ mutex->back = (mutex->back+1) % MAX_THREADS; mutex->waiting[mutex->back] = sthread_self(); mutex->wcount = mutex->wcount + 1; return 0; } }
int sthread_sem_down(sthread_sem_t *sem)//will decrement the semaphore by 1 if the value of which is greater than 0 (these two steps must be atomic), or it will block until another thread releases the semaphore and wakes it up. { while (test_and_set(sem->mutex)) sched_yield(); if(sem->count == 0){ push(sem->sem_queue, sthread_self()); *(sem->mutex) = 0; sthread_suspend(); } else { sem->count--; *(sem->mutex) = 0; } return 0; }
/* down() - It checks if sem-> > 0 , If true then decreases the count and gives the semaphore else adds the thread to the waiting queue and suspends it. */ int sthread_sem_down(sthread_sem_t *sem) { lock(); int ret; if (sem->count > 0) { sem->count--; ret = 0; unlock(); } else { insertNode(sem, sthread_self()); ret = -1; unlock(); sthread_suspend(); } return ret; }
int sthread_mutex_trylock(sthread_mutex_t *mutex) { sthread_t ptr_this_thread = sthread_self(); //fighting for the right to modify Q while(test_and_set(&mutex->M)){} //after this I am now the only one //to modify the passed in mutex //therefore I should go ahead and //modify the lock and Q if needed //check if I should go into critical //section struct queue *pQ = &mutex->Q; if(Q_empty(pQ)) { //lock available Q_push(pQ, ptr_this_thread); mutex->M = 0; // I am done with Q; others can come and look / change Q. //this_thread will go into critical section return 0; } else { //lock not available if(Q_first(pQ)->ptr_thread == ptr_this_thread) { Q_first(pQ)->count++;//Trying to acquire the lock own by myself //take down this attempt and keep myself in //criticle section mutex->M = 0; //I am done with lock; others can now check / modify lock. } //do not block caller //return non-zero indication lock not available return -1; } }