int mypthread_join(mypthread_t thread, void **retval)
{
    kargs *tempargs;
    tempargs = (kargs *)malloc(sizeof(kargs));
    tempargs->thread = thread;
    tempargs->kmode = 2;

    mythread_scheduler((void *)tempargs);
    /*
    //sem_wait(&sem_main);
    int target_thread_id = thread.pthread->thread_id;
    mypthread_t *current_thread = search_thread(mythread_q,cur_thread_id);
    mypthread_t *target_thread = search_thread(mythread_q,target_thread_id);
    if (target_thread->pthread->thread_state != PS_ACTIVE)
    {
       //sem_post(&sem_main);
       return 0;
    }
    else
    {
       current_thread->pthread->thread_state = PS_BLOCKED;
       target_thread->pthread->joined_from_th = cur_thread_id;
       cur_thread_id = target_thread_id;
       //sem_post(&sem_main);       
       swapcontext(current_thread->pthread->ucontext, target_thread->pthread->ucontext);  
    }
    */
    return 0;
}
int mypthread_yield(void)
{

    mypthread_t thread;

    kargs *tempargs;
    tempargs = (kargs *)malloc(sizeof(kargs));
    tempargs->thread = thread;
    tempargs->kmode = 3;

    mythread_scheduler((void *)tempargs);
 
    /*
    //sem_wait(&sem_main);
    printf("Inside thread yield\n");
    mypthread_t *current_thread = search_thread(mythread_q, cur_thread_id);
    mypthread_t *next_thread = next_active_thread(mythread_q);
    printf("Current thread id = %d , next thread id = %d\n", cur_thread_id, next_thread->pthread->thread_id);
    if (cur_thread_id == next_thread->pthread->thread_id)
    {
        //sem_post(&sem_main);
        return 0;
    }
    printf("Thread %d Yielding\n",cur_thread_id);
    cur_thread_id = next_thread->pthread->thread_id;
   // sem_post(&sem_main);
    swapcontext(current_thread->pthread->ucontext, next_thread->pthread->ucontext);    
    */

    return 0; 
}
Ejemplo n.º 3
0
int mythread_leave_kernel(){
	
	mythread_t self = mythread_self();

repeat:	
	
		if(self->reschedule == 1){ 
			self->reschedule = 0;
			/* Reschedule here*/
			if(mythread_readyq()!=NULL && self->attr.attr == 0){
				/*The threads time is up and since there's some thread waiting in readyq, it needs to
				preempt itself */
				mythread_scheduler();
			}
			else{
				/*If  Ready queue is empty or time is not up, continue executing
				*/
				mythread_leave_kernel_nonpreemptive();
			}
		}
		else{
			mythread_leave_kernel_nonpreemptive();
		}
	/* Check again in case of a rescheduling since leaving kernel */
	if(self->reschedule == 1){
		mythread_enter_kernel();
		goto repeat;
	}
	return 0;
}
void mypthread_exit(void *retval)
{
    mypthread_t thread;
    
    kargs *tempargs;

    tempargs = (kargs *)malloc(sizeof(kargs));
    tempargs->thread = thread;
    tempargs->kmode = 1;

    mythread_scheduler((void *)tempargs);

    /*
  //sem_wait(&sem_main);
    mypthread_t* cur_thread = search_thread(mythread_q, cur_thread_id);

    cur_thread->pthread->thread_state = PS_DEAD;
    free(cur_thread->pthread->ucontext);

    if (cur_thread->pthread->joined_from_th != 0)
    {
        mypthread_t *join_thread = search_thread(mythread_q,cur_thread->pthread->joined_from_th);
        join_thread->pthread->thread_state = PS_ACTIVE;
         
    }
    mypthread_t* next_thread = return_head(mythread_q);
    cur_thread_id = next_thread->pthread->thread_id; 
    //sem_post(&sem_main);
    setcontext(next_thread->pthread->ucontext);
   */
    return;
}
int ksched(void *args)
{
   while (next_active_thread(mythread_q) != NULL)
   {
       sem_wait(&sem_kern);
       mythread_scheduler(args);
       sem_post(&sem_kern);   
   }

}
/*
 * Helper function that creates mykthread_t node and executes next active user thread from runnable queue
 */
int schedule_kthread() {
	mykthread_t *k_th = (mykthread_t *) malloc(sizeof(mykthread_t));
	k_th->kth_id = gettid();
	//This value will be populated by mythread_scheduler
	k_th->th = NULL;
	//Add to the kthread list
	mykthread_add(k_th);
	mythread_scheduler(k_th, 0);
	return 0;
}
/*
 *	Functionality for pthread_join()
 */
int mypthread_join(mypthread_t thread, void **retval) {
	//Search for target thread
	sem_wait(&mypthread_sem);
	mypthread_t* target_thread = mypthread_get(thread.th_id);
	sem_wait(&kthread_sem);
	mykthread_t* current_kthread = mykthread_get(gettid());
	sem_post(&kthread_sem);
	sem_post(&mypthread_sem);
	if (target_thread == NULL) {
		if (mykthread_is_running(thread.th_id)) {
			// Thread is currently running by some other kthread
			//Change status of the current thread and run next active thread
			current_kthread->th->state = PS_WAITING;
			current_kthread->th->dependent_th = thread.th_id;
			sem_wait(&mypthread_sem);
			mypthread_enqueue(current_kthread->th);
			sem_post(&mypthread_sem);
			//Swap context to the next active thread
			mythread_scheduler(current_kthread, 1);
			return 0;
		} else {
			//Immediately return if no thread is waiting
			return 0;
		}
	} else {
		if (target_thread->state != PS_DEAD) {
			//Current thread is currently waiting due to other thread
			//Change status of the current thread and run next active thread
			current_kthread->th->state = PS_WAITING;
			current_kthread->th->dependent_th = thread.th_id;
			sem_wait(&mypthread_sem);
			mypthread_enqueue(current_kthread->th);
			sem_post(&mypthread_sem);
			//Swap context to the next active thread
			mythread_scheduler(current_kthread, 1);
			return 0;
		} else {
			//No need to wait. Immediately return
			return 0;
		}
	}
}
/*
 *	Functionality for pthread_yield()
 */
int mypthread_yield(void) {
	//get current thread and change the status to PS_ACTIVE
	mykthread_t* current_kthread = mykthread_get(gettid());
	current_kthread->th->state = PS_ACTIVE;
	sem_wait(&mypthread_sem);
	mypthread_enqueue(current_kthread->th);
	sem_post(&mypthread_sem);
	//Swap context to next runnable thread
	mythread_scheduler(current_kthread, 1);
	return 0;
}
/*
 *	Functionality for pthread_exit()
 */
void mypthread_exit(void *retval) {
	//First get the current executing kthread
	mykthread_t* current_kthread = mykthread_get(gettid());
	//First make all other waiting threads active
	sem_wait(&mypthread_sem);
	mypthread_count--;
	current_kthread->th->state = PS_DEAD;
	mypthread_update_waiting_threads(current_kthread->th->th_id);
	sem_post(&mypthread_sem);
	//Free pthread
	free(current_kthread->th->ctx);
	//Just destroy the mypthread node and run the next active thread
	mythread_scheduler(current_kthread, 0);
}
/*
 *	Functionality for pthread_cond_wait()
 */
int mypthread_cond_wait(mypthread_cond_t *cond, mypthread_mutex_t *mutex) {
	sem_wait(&cond_sem);
	//Unblock all threads locked by mutex
	mypthread_mutex_unlock(mutex);
	//Make the current thread wait for the signal
	mykthread_t* current_kthread = mykthread_get(gettid());
	current_kthread->th->state = PS_BLOCKED;
	ll_add(current_kthread->th, &(cond->cond_q_head), &(cond->cond_q_tail));
	sem_wait(&mypthread_sem);
	mypthread_enqueue(current_kthread->th);
	sem_post(&mypthread_sem);
	sem_post(&cond_sem);
	mythread_scheduler(current_kthread, 1);
	mypthread_mutex_lock(mutex);
	return 0;
}
/*
 *	Functionality for pthread_mutex_lock()
 */
int mypthread_mutex_lock(mypthread_mutex_t *mutex) {
	sem_wait(&mutex_sem);
	if (!(mutex->lock)) {
		mutex->lock = true;
		sem_post(&mutex_sem);
	} else {
		mykthread_t* current_kthread = mykthread_get(gettid());
		//No need to acquire mypthread_lock as the mypthread_t are not in the run queue
		current_kthread->th->state = PS_BLOCKED;
		ll_add(current_kthread->th, &(mutex->blocked_q_head),
				&(mutex->blocked_q_tail));
		//This will ensure that when the blocked thread becomes runnable, it executes the mutex lock logic again
		makecontext(current_kthread->th->ctx, (void (*)()) mypthread_mutex_lock,
				1, mutex);
		sem_wait(&mypthread_sem);
		mypthread_enqueue(current_kthread->th);
		sem_post(&mypthread_sem);
		sem_post(&mutex_sem);
		//Set context to the next active thread
		mythread_scheduler(current_kthread, 0);
	}
	return 0;
}