void MyThreadYield(void) { //printf("MyThreadYield: START ... curr_th = %d , parent_th = %d\n", curr_th->tid, curr_th->pid); /*if(0!=getcontext(&curr_context))l { //printf("MyThreadYield : getcontext error... \n"); }*/ if(front==NULL) { //printf("No pending ready thread, invoking thread = %d , will continue to run \n", curr_th->tid); return; } ucontext_t new_cnxt; struct node * new_th=pop_q(); if(new_th == NULL) { //printf("MyThreadYield: ready queue is empty...continue running this thread... \n"); return; } new_cnxt=new_th->cnxt; //printf("Inserting saved context to the queue : GetContext removed... \n"); struct node * tmp=insert_q(curr_th->cnxt,curr_th->tid,curr_th->pid,curr_th->join_th,curr_th->join_th_rear); int old_th=curr_th->tid; int old_pr=curr_th->pid; ucontext_t old_cnxt=curr_th->cnxt; struct join_list *old_jfront=curr_th->join_th; struct join_list *old_jrear=curr_th->join_th_rear; curr_th->tid=new_th->tid; curr_th->pid=new_th->pid; curr_th->cnxt=new_th->cnxt; curr_th->join_th=new_th->join_th; curr_th->join_th_rear=new_th->join_th_rear; //printf("MyThreadYield: swap context from thread : %d ,to first ready thread : %d ... \n",tmp->tid,curr_th->tid); //printf("MyThreadYield: swap context from =%d , to = %d which is also same as new_cnxt=%d\n ",tmp->cnxt,curr_th->cnxt,new_cnxt); if(swapcontext(&(tmp->cnxt),&(new_th->cnxt))==-1) { curr_th->tid=old_th; curr_th->pid=old_pr; curr_th->cnxt=old_cnxt; curr_th->join_th=old_jfront; curr_th->join_th_rear=old_jrear; removeNode(curr_th->tid); //printf("MyThreadYield: swapcontext error...\n"); } //printf("MyThreadYield: EXIT... \n\n\n"); }
void sem_signal(struct Semaphore *s) { lock_acquire(&s->locksem); if(!empty_q(&s->t_q)) { twakeup(pop_q(&s->t_q)); } else { s->count++; } lock_release(&s->locksem); }
void sem_signal(struct Semaphore *s) { lock_acquire(&s->lock); if (s->count > 0) { s->count++; lock_release(&s->lock); } else { if (empty_q(&s->q) == 1) s->count++; else twakeup(pop_q(&s->q)); lock_release(&s->lock); } }
void MySemaphoreWait(MySemaphore sem) { struct sema *passed_sem=(struct sema *)sem; struct sema *c_sem=get_sem(passed_sem); if(c_sem==NULL) { //printf("MySemaphoreWait : sem is NULL.... returning.... \n"); return; } //printf("MySemaphoreWait : Enter... for sem=%d \n",c_sem->sid); if(c_sem->val>0) { //printf("MySemaphoreWait : resource available for c_sem=%d ...simply decrementing its value , now val=%d\n",c_sem->sid,(c_sem->val-1)); c_sem->val = (c_sem->val)-1; } else if(c_sem->val==0) { //printf(" MySemaphoreWait : c_sem->val is already 0.... add this thread into sem's sblocked list...and then....Move current thread=%d to blocked queue... \n",curr_th->tid); // need to add curr_th into, this semaphore's FIFO blocked thread id list.... struct sb_thread *tmp=(struct sb_thread *)malloc(sizeof(struct sb_thread)); if(tmp==NULL) { //printf(" MySemaphoreWait : Memory not allocated...max limit reached for threads....returning gracefully...\n"); swapcontext(&dmy_cnxt,&init_cnxt); } tmp->sb_id=curr_th->tid; tmp->sb_next=NULL; //printf("MySemaphoreWait : init tmp...\n"); if(c_sem->sb_front == NULL) { c_sem->sb_front=tmp; c_sem->sb_rear=tmp; } else { c_sem->sb_rear->sb_next=tmp; c_sem->sb_rear=tmp; } // Move current thread to blocked queue, run first ready queue, lookup MyThreadJoin for reference.... // POP first ready thread... // todo: code to move current thread to blocked queue... struct node * blocked_th=binsert_q(curr_th->cnxt,curr_th->tid,curr_th->pid,curr_th->join_th,curr_th->join_th_rear); //printf("MySemaphoreWait : current thread:%d entered in BQ , but actual current thread is= %d\n",blocked_th->tid, curr_th->tid); //saving current thread pointers for future failure recovery int old_th=curr_th->tid; int old_pr=curr_th->pid; ucontext_t old_cnxt=curr_th->cnxt; struct join_list *old_jfront=curr_th->join_th; struct join_list *old_jrear=curr_th->join_th_rear; //printf("MySemaphoreWait : popping first RQ thread...\n"); ucontext_t new_cnxt; struct node * new_th=pop_q(); if(new_th == NULL) { //printf(" MySemaphoreWait: ready queue empty ... \n"); swapcontext(&dmy_cnxt,&init_cnxt); } new_cnxt=new_th->cnxt; //updating current thread pointers curr_th->tid=new_th->tid; curr_th->pid=new_th->pid; curr_th->cnxt=new_th->cnxt; curr_th->join_th=new_th->join_th; curr_th->join_th_rear=new_th->join_th_rear; //printf("MySemaphoreWait: swap context from thread : %d to first ready thread : %d ... \n",old_th,curr_th->tid); if(swapcontext(&(blocked_th->cnxt),&new_cnxt)==-1) { //printf("MySemaphoreWait: Blocking swapcontext error... \n"); curr_th->tid=old_th; curr_th->pid=old_pr; curr_th->cnxt=old_cnxt; curr_th->join_th=old_jfront; curr_th->join_th_rear=old_jrear; bremoveNode(curr_th->tid); //printf("MySemaphoreWait: Blocking swapcontext error recovery done...\n"); } // After resuming from ready - queue, //printf(" MySemaphoreWait: Semaphore wait over, for current thread= %d ....\n",curr_th->tid); } //printf(" MySemaphoreWait : EXIT .... \n"); }
/* Terminates the invoking thread. Note: all MyThreads are required to invoke this function. Do not allow functions to “fall out” of the start function. */ void MyThreadExit(void) { //printf("MyThreadExit: START ... for thread =%d \n",curr_th->tid); ucontext_t next_context; //Need to check, if terminating thread's parent is in blocked queue or not ... struct node *parent_th=bgetNode(curr_th->pid); if(parent_th!=NULL) { //printf("Parent thread = %d is in blocked queue, need to check whether it is blocked by this child thread = %d \n" , parent_th->tid,curr_th->tid); struct join_list *jtmp; if(parent_th->join_th !=NULL) { if( (parent_th->join_th == parent_th->join_th_rear) && (parent_th->join_th->ch_tid == curr_th->tid)) { // Only one element in queue, and that's the one we are looking for //printf("Only One element in join_list, and it's a MATCH, deleting it, Queue is empty now ...\n"); jtmp=parent_th->join_th; parent_th->join_th=NULL; parent_th->join_th_rear=NULL; free(jtmp); } else if (parent_th->join_th->ch_tid == curr_th->tid) { // First element needs to be deleted, and Queue have more than one elements... //printf("First element of queue is a MATCH, queue have more than one element, shifting Front pointer of join_list ...\n"); jtmp=parent_th->join_th; parent_th->join_th=parent_th->join_th->link; free(jtmp); } else {// Need to traverse through queue, to check for the element //printf("Need to traverse through, join_list of parent thread = %d , to look for child thread = %d \n",parent_th->tid,curr_th->tid); jtmp=parent_th->join_th; struct join_list *jprev=NULL; while(jtmp!=NULL && (jtmp->ch_tid != curr_th->tid)) { jprev=jtmp; jtmp=jtmp->link; } if(jtmp!=NULL && (jtmp->ch_tid == curr_th->tid)) { //printf("Child thread =%d in join_list of parent thread=%d, removing it from list ...\n",curr_th->tid,parent_th->tid); jprev->link=jtmp->link; free(jtmp); } else if(jtmp==NULL) { //printf("This terminating thread = %d is not blocking its parent thread= %d...\n",curr_th->tid,parent_th->tid); } } //Now, if this parent thread's waiting child thread join_list becomes empty, it is ready to execute and therefore need to insert into ready queue... if(parent_th->join_th ==NULL) { //printf(" Parent thread: %d , join list is empty, It is ready to execute...inserting into ready queue \n",parent_th->tid); struct node *blocked_to_ready=insert_q(parent_th->cnxt,parent_th->tid,parent_th->pid,parent_th->join_th,parent_th->join_th_rear); //printf(" Thread = %d moved to ready Queue \n ",blocked_to_ready->tid); bremoveNode(parent_th->tid); //printf(" Thread = %d removed from blocked Queue \n",blocked_to_ready->tid); } } } if(front==NULL) { //printf("No ready threads pending...\n"); swapcontext(&dmy_cnxt,&init_cnxt); } //printf("MyThreadExit: fetching first ready state ... \n"); struct node * new_th=pop_q(); if(new_th == NULL) { //printf(" MyThreadExit: ready queue empty ... \n"); swapcontext(&dmy_cnxt,&init_cnxt); } next_context=new_th->cnxt; int old_th=curr_th->tid; int old_pr=curr_th->pid; ucontext_t old_cnxt=curr_th->cnxt; struct join_list *old_jfront=curr_th->join_th; struct join_list *old_jrear=curr_th->join_th_rear; curr_th->tid=new_th->tid; curr_th->pid=new_th->pid; curr_th->cnxt=new_th->cnxt; curr_th->join_th=new_th->join_th; curr_th->join_th_rear=new_th->join_th_rear; //printf("MyThreadExit : Terminating invoking thread : %d , and running next thread : %d .... \n",old_th,new_th->tid); //printf("MyThreadExit: Thread=%d set terminated... , New thread=%d , context = %d \n",old_th,new_th->tid, new_th->cnxt); //printf("MyThreadExit: swap context from =%d , to = %d which is also same as next_cnxt=%d\n ",old_cnxt,new_th->cnxt,next_context); if(-1==swapcontext(&(old_cnxt),&(new_th->cnxt))) { //printf("MyThreadExit: setcontext error...\n"); curr_th->tid=old_th; curr_th->pid=old_pr; curr_th->cnxt=old_cnxt; curr_th->join_th=old_jfront; curr_th->join_th_rear=old_jrear; //printf("MyThreadExit: setcontext error RECOVERY done...\n"); } //printf("MyThreadExit: exit for thread=",curr_th->tid); }
/* Waits until all children have terminated. Returns immediately if there are no active children. */ void MyThreadJoinAll(void) { //printf("MyThreadJoinAll: START : for current thread : %d \n", curr_th->tid); //printf("Need to traverse through RQ and BQ and add all children of this thread to its join_list...\n"); //saving join pointers for future failure recovery struct join_list *old_jfront=curr_th->join_th; struct join_list *old_jrear=curr_th->join_th_rear; //Traverse through RQ struct node *tmp=front; while(tmp!=NULL) { if(tmp->pid == curr_th->tid) { //printf("Child found , thread=%d , is a child thread of current thread , need to insert into join_list\n",tmp->tid); struct join_list *jtmp=(struct join_list *)malloc(sizeof(struct join_list)); if(jtmp==NULL) { //printf("No memory allocated... Maximum thread limit reached...returning gracefully...\n"); swapcontext(&dmy_cnxt,&init_cnxt); } jtmp->ch_tid=tmp->tid; jtmp->link=NULL; if((curr_th->join_th)==NULL) { curr_th->join_th=jtmp; curr_th->join_th_rear=curr_th->join_th; } else { curr_th->join_th_rear->link=jtmp; curr_th->join_th_rear=jtmp; } } tmp=tmp->next; } //Need to Traverse through BQ //printf("MyThreadJoinAll: now Traversing BQ... \n"); tmp=bfront; while(tmp!=NULL) { if(tmp->pid == curr_th->tid) { //printf("Child found , thread=%d , is child thread of current thread , need to insert into join_list \n",tmp->tid); struct join_list *jtmp=(struct join_list *)malloc(sizeof(struct join_list)); if(jtmp==NULL) { //printf("No memory allocated... Maximum thread limit reached...returning gracefully...\n"); swapcontext(&dmy_cnxt,&init_cnxt); } jtmp->ch_tid=tmp->tid; jtmp->link=NULL; if((curr_th->join_th)==NULL) { curr_th->join_th=jtmp; curr_th->join_th_rear=curr_th->join_th; } else { curr_th->join_th_rear->link=jtmp; curr_th->join_th_rear=jtmp; } } tmp=tmp->next; } //printf("MyThreadJoinAll : Traversing queues finished... join_list updated... now move thread:%d to blocked queue and run the first ready thread \n",curr_th->tid); //Need to move this thread into blocked Queue and run the first ready state //Fetching first ready state struct node * blocked_th=binsert_q(curr_th->cnxt,curr_th->tid,curr_th->pid,curr_th->join_th,curr_th->join_th_rear); //printf("MyThreadJoinAll : current thread:%d entered in BQ \n",curr_th->tid); int old_th=curr_th->tid; int old_pr=curr_th->pid; ucontext_t old_cnxt=curr_th->cnxt; ucontext_t new_cnxt; struct node * new_th=pop_q(); if(new_th == NULL) { //printf(" MyThreadJoinAll: ready queue empty ... \n"); swapcontext(&dmy_cnxt,&init_cnxt); } new_cnxt=new_th->cnxt; curr_th->tid=new_th->tid; curr_th->pid=new_th->pid; curr_th->cnxt=new_th->cnxt; curr_th->join_th=new_th->join_th; curr_th->join_th_rear=new_th->join_th_rear; //printf("MyThreadJoinAll: swap context from thread : %d to first ready thread : %d... \n",old_th,curr_th->tid); if(swapcontext(&(blocked_th->cnxt),&new_cnxt)==-1) { curr_th->tid=old_th; curr_th->pid=old_pr; curr_th->cnxt=old_cnxt; curr_th->join_th=old_jfront; curr_th->join_th_rear=old_jrear; bremoveNode(curr_th->tid); //printf("MyThreadJoinAll: Blocking swapcontext error... \n"); } }
int MyThreadJoin(MyThread thread) { //printf("MyThreadJoin: START ... \n"); if(thread==NULL) { //printf("NULL thread, returning from MyThreadJoin"); return 0; } struct node *child_th; child_th=(struct node *)thread; //printf("MyThreadJoin: child thread= %d , its parent thread= %d , current invoking thread= %d \n",child_th->tid,child_th->pid,curr_th->tid); if(curr_th->tid != child_th->pid) { //printf("MyThreadJoin: FAILURE : specified thread is not an immediate child of invoking thread...\n"); return -1; } //printf("Search of specified child thread in ready queue...\n"); // If the child has already terminated, do not block. Note: A child may have terminated without the parent having joined with it. int cid=child_th->tid; int child_exist=0; // check for child thread into Ready Queue struct node *tmp=front; while(tmp!=NULL && tmp->tid != cid ) { tmp=tmp->next; } if(tmp!=NULL && tmp->tid ==cid) { child_exist=1; //printf("Specified child thread exists in Ready queue... \n"); } //If child not found in Ready Queue, check in Blocked queue if(child_exist==0) { //printf("Specified child thread not in ready queue...search in blocked queue\n"); tmp=bfront; while(tmp!=NULL && tmp->tid != cid) { tmp=tmp->next; } if(tmp!=NULL && tmp->tid == cid) { child_exist=1; //printf("Specified child thread exists in Blocked queue... \n"); } } if(child_exist==0) { //printf("Specified child thread is already terminated. Not blocking the invoking thread...\n"); return 0; } else if(child_exist == 1) { //printf("Specified child thread exists ... \n"); } //todo: remove this ////printf("MyThreadJoin: RETURN ... \n"); //return 0; //Child thread exists, need to block the invoking thread and move into Blocked queue //After blocking, run the first ready thread //saving join pointers for future failure recovery struct join_list *old_jfront=curr_th->join_th; struct join_list *old_jrear=curr_th->join_th_rear; // Before blocking, need to update join_list of this current thread... //printf("MyThreadJoin : need to update join_list of this current thread:%d \n",curr_th->tid); struct join_list *jtmp=(struct join_list *)malloc(sizeof(struct join_list)); if(jtmp==NULL) { //printf("No memory allocated... Maximum thread limit reached...returning gracefully...\n"); swapcontext(&dmy_cnxt,&init_cnxt); } jtmp->ch_tid=cid; jtmp->link=NULL; if((curr_th->join_th)==NULL) { curr_th->join_th=jtmp; curr_th->join_th_rear=curr_th->join_th; } else { curr_th->join_th_rear->link=jtmp; curr_th->join_th_rear=jtmp; } struct node * blocked_th=binsert_q(curr_th->cnxt,curr_th->tid,curr_th->pid,curr_th->join_th,curr_th->join_th_rear); //printf("MyThreadJoin : current thread:%d entered in BQ , but actual current thread is= %d\n",blocked_th->tid, curr_th->tid); int old_th=curr_th->tid; int old_pr=curr_th->pid; ucontext_t old_cnxt=curr_th->cnxt; ucontext_t new_cnxt; struct node * new_th=pop_q(); if(new_th == NULL) { //printf(" MyThreadJoin: ready queue empty ... \n"); swapcontext(&dmy_cnxt,&init_cnxt); } new_cnxt=new_th->cnxt; curr_th->tid=new_th->tid; curr_th->pid=new_th->pid; curr_th->cnxt=new_th->cnxt; curr_th->join_th=new_th->join_th; curr_th->join_th_rear=new_th->join_th_rear; //printf("MyThreadJoin: swap context from thread : %d to first ready thread : %d ... \n",old_th,curr_th->tid); if(swapcontext(&(blocked_th->cnxt),&new_cnxt)==-1) { curr_th->tid=old_th; curr_th->pid=old_pr; curr_th->cnxt=old_cnxt; curr_th->join_th=old_jfront; curr_th->join_th_rear=old_jrear; bremoveNode(curr_th->tid); //printf("MyThreadJoin: Blocking swapcontext error..."); } //printf("MyThreadJoin: curr_thread= %d , parent_th = %d ,EXIT... \n",curr_th->tid,curr_th->pid); }
/* pre: takes in a void* 'n' which must be a pointer to an integer * post: creates a consumer thread */ void* consumer(void *n) { int number; int i; struct s_product* prod; struct timeval end_time; number = *((int*)n); #ifdef DEBUG printf("[DEBUG]\tStarting consumer [%d]\n", number); fflush(stdout); #endif /* consume products while we have not reached maxProductCount */ while (gl_env.consumptionCount < gl_env.maxProductCount) { #ifdef DEBUG printf("[DEBUG]\tconsumption count %d\n", gl_env.consumptionCount); fflush(stdout); #endif /* lock and check consumptionCount again in case of weird scheduling */ pthread_mutex_lock(&gl_env.consume_prod_lock); if (gl_env.consumptionCount == gl_env.maxProductCount) { pthread_mutex_unlock(&gl_env.consume_prod_lock); break; } pthread_mutex_unlock(&gl_env.consume_prod_lock); if (gl_env.scheduling == FCFS) { /* do a real pop and keep it til' it's gone */ prod = pop_q(); if (prod == NULL) break; gettimeofday(&end_time, NULL); fprintf(stderr, "Product %d waited %lu\n", prod->id, end_time.tv_usec - prod->time_inserted.tv_usec); fflush(stderr); #ifdef DEBUG printf("[DEBUG]\tConsumer [%d] working on product [%d]\n", number, prod->id); fflush(stdout); #endif for (i = 0; i < prod->life; i++) fibonacci(10); /* lock and increment consumptionCount */ pthread_mutex_lock(&gl_env.consume_prod_lock); gl_env.consumptionCount++; pthread_mutex_unlock(&gl_env.consume_prod_lock); printf("Consumer %d has consumed product %d\n", number, prod->id); fflush(stdout); gettimeofday(&end_time, NULL); fprintf(stderr, "Product %d turn-around %lu\n", prod->id, end_time.tv_usec - prod->time_created.tv_usec); fflush(stderr); /* free memory */ free(prod); } else if (gl_env.scheduling == RR) { /* do a "reserved" pop in case we need to put it back */ prod = reserved_pop_q(); if (prod == NULL) break; gettimeofday(&end_time, NULL); fprintf(stderr, "Product %d waited %lu\n", prod->id, end_time.tv_usec - prod->time_inserted.tv_usec); fflush(stderr); #ifdef DEBUG printf("[DEBUG]\tConsumer [%d] working on product [%d]\n", number, prod->id); fflush(stdout); #endif if (prod->life > gl_env.quantum) { for (i = 0; i < gl_env.quantum; i++) fibonacci(10); /* update the product's life */ prod->life = prod->life - gl_env.quantum; /* put the product back */ replace_push_q(prod); } else { for (i = 0; i < prod->life; i++) fibonacci(10); /* "fully" remove product */ decrement_q(); /* lock and increment consumptionCount */ pthread_mutex_lock(&gl_env.consume_prod_lock); ++gl_env.consumptionCount; pthread_mutex_unlock(&gl_env.consume_prod_lock); printf("Consumer %d has consumed product %d\n", number, prod->id); fflush(stdout); gettimeofday(&end_time, NULL); fprintf(stderr, "Product %d turn-around %lu\n", prod->id, end_time.tv_usec - prod->time_created.tv_usec); fflush(stderr); /* free memory */ free(prod); } } /* usleep for 100 milliseconds */ usleep(100000); } #ifdef DEBUG printf("[DEBUG]\tConsumer [%d] exiting\n", number); fflush(stdout); #endif /* return NULL removes compiler warning */ return NULL; }