Beispiel #1
0
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");
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
	}
}
Beispiel #4
0
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");
}
Beispiel #5
0
/*
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);
}
Beispiel #6
0
/*
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");
	}
	
}
Beispiel #7
0
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);
}
Beispiel #8
0
/* 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;
}