int sthread_mutex_lock(sthread_mutex_t *mutex,int tid) { int ret_val; if(mutex->lock==1){ if(mutex->tid==tid){ printf("Incrementing counter on lock\n"); mutex->counter = mutex->counter + 1; } else if(mutex->tid!=tid){ enqueueWait(mutex); printf("WAIT COUNTER: %d\n",mutex->wcount); printf("Suspending thread %d because mutex is not available\n", tid); sthread_suspend(); //After waking up from suspend assign it the lock and tid. Lock is available at this point. printf("Thread %d obtaining lock after waking up\n", tid); mutex->tid = tid; mutex->lock = 1; ret_val = -1; } } else if (mutex->lock==0){ printf("Thread %d has obtained a mutex\n",tid); mutex->lock = 1; mutex->tid = tid; ret_val = 0; } return ret_val; }
int threadmain(void *arg) { int threadno = (int)arg; for (;;) { printf("thread %d: I'm going to sleep\n", threadno); sthread_suspend(); printf("thread %d: I woke up!\n", threadno); } return 0; }
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 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; }