Пример #1
0
void lock_release(struct lock *lock) {
    assert(lock != NULL);
    int enabled = interrupts_set(0);
    lock->lock_state = 0;
    thread_wakeup(lock->queue, 1);
    interrupts_set(enabled);
}
Пример #2
0
Tid thread_create(void (*fn) (void *), void *parg) {
    int enabled = interrupts_set(0);
    Tid new_id = assign_thread_id();
    if (new_id < 0)
        return THREAD_NOMORE;
    struct thread *new_thread = (struct thread *) malloc(sizeof (struct thread));
    if (new_thread == NULL)
        return THREAD_NOMEMORY;
    getcontext(&(new_thread->thread_context));
    new_thread->tid = new_id;
    thread_id_array[new_id] = 1;
    new_thread->state = NEW_STATE;
    new_thread->next = NULL;
    new_thread->flag = 0;
    void *sp = malloc((THREAD_MIN_STACK + 16) / 16 * 16);
    if (sp == NULL)
        return THREAD_NOMEMORY;
    new_thread->sp = sp;
    new_thread->thread_context.uc_mcontext.gregs[15] = (unsigned long) (sp + THREAD_MIN_STACK - 8);
    new_thread->thread_context.uc_mcontext.gregs[REG_RBP] = (unsigned long) sp;
    new_thread->thread_context.uc_mcontext.gregs[REG_RDI] = (unsigned long) fn;
    new_thread->thread_context.uc_mcontext.gregs[REG_RSI] = (unsigned long) parg;
    new_thread->thread_context.uc_mcontext.gregs[REG_RIP] = (unsigned long) thread_stub;
    insert_thread_to_ready(new_thread);
    interrupts_set(enabled);
    return new_thread->tid;
}
Пример #3
0
int
main(int argc, char **argv)
{
	int enabled;

	thread_init();
	/* show interrupt handler output */
	register_interrupt_handler(1);
	test(1);

	/*  test interrupts_on/off/set */
	enabled = interrupts_off();
	assert(enabled);
	test(0);
	enabled = interrupts_off();
	assert(!enabled);
	test(0);
	enabled = interrupts_set(1);
	assert(!enabled);
	test(1);
	enabled = interrupts_set(1);
	assert(enabled);
	test(1);
	exit(0);
}
Пример #4
0
Tid
thread_create(void (*fn) (void *), void *parg)
{
	int enabled = interrupts_set(0);
	thread *current;
	current=first;
	
	/*int tc=tcounter();
	
	if (tc+1>=THREAD_MAX_THREADS)
		return THREAD_NOMORE;
	*/

	while (current->next != NULL)
	{
		current=current->next;
	}
	current->next=malloc(sizeof(thread));
	if (current->next == NULL)
	{
		interrupts_set(enabled);
		return THREAD_NOMEMORY;
	}
	
	current=current->next;

	current->id=id_calc();
	current->state=READY;
	current->next=NULL;
	current->tcontext=(ucontext_t*)malloc(sizeof(ucontext_t));

	if (current->tcontext == NULL)
	{
		interrupts_set(enabled);
		return THREAD_NOMEMORY;
	}
	

	void *sp=(void*)malloc(THREAD_MIN_STACK);
	if (sp == NULL)
	{
		interrupts_set(enabled);
		return THREAD_NOMEMORY;
	}

	
    getcontext(current->tcontext);


	current->tcontext->uc_mcontext.gregs[REG_RSP]=(unsigned long)(sp+THREAD_MIN_STACK-8);
	current->tcontext->uc_mcontext.gregs[REG_RIP]=(unsigned long)thread_stub;
	current->tcontext->uc_mcontext.gregs[REG_RDI]=(unsigned long)fn;
	current->tcontext->uc_mcontext.gregs[REG_RSI]=(unsigned long)parg;
    //printf("current id is %d\n",current->id);

	interrupts_set(enabled);
	return current->id;	

}
Пример #5
0
void lock_acquire(struct lock *lock) {
    assert(lock != NULL);
    int enabled = interrupts_set(0);
    while(lock->lock_state == 1)
        thread_sleep(lock->queue);
    lock->lock_state = 1;
    interrupts_set(enabled);
}
Пример #6
0
Tid thread_id() {
    int enabled = interrupts_set(0);
    if (RUNNING_THREAD != NULL) {
        Tid id = RUNNING_THREAD->tid;
        interrupts_set(enabled);
        return id;
    }
    interrupts_set(enabled);
    return THREAD_INVALID;
}
Пример #7
0
struct wait_queue *
wait_queue_create()
{
	int enabled = interrupts_set(0);
	struct wait_queue *wq;

	wq = malloc(sizeof(struct wait_queue));
	assert(wq);
	wq->next=NULL;
	wq->dummy=0;

	interrupts_set(enabled);
	return wq;
}
Пример #8
0
static void
test_wakeup_thread(int num)
{
	int i;
	int ret;
	struct timeval start, end, diff;

	for (i = 0; i < LOOPS; i++) {
		int enabled;
		gettimeofday(&start, NULL);

		/* track the number of sleeping threads with interrupts
		 * disabled to avoid wakeup races. */
		enabled = interrupts_off();
		assert(enabled);
		__sync_fetch_and_add(&nr_sleeping, 1);
		ret = thread_sleep(queue);
		assert(thread_ret_ok(ret));
		interrupts_set(enabled);

		gettimeofday(&end, NULL);
		timersub(&end, &start, &diff);

		/* thread_sleep should wait at least 4-5 ms */
		if (diff.tv_sec == 0 && diff.tv_usec < 4000) {
			unintr_printf("%s took %ld us. That's too fast."
				      " You must be busy looping\n",
				      __FUNCTION__, diff.tv_usec);
			goto out;
		}
	}
out:
	__sync_fetch_and_add(&done, 1);
}
Пример #9
0
void thread_stub(void (*thread_main)(void *), void *arg) {
    interrupts_set(1);
    Tid ret;
    thread_main(arg); // call thread_main() function with arg
    ret = thread_exit(THREAD_SELF);
    assert(ret == THREAD_NONE);
    exit(0);
}
Пример #10
0
Tid thread_exit(Tid tid) {
    int enabled = interrupts_set(0);
    if (tid == THREAD_SELF) {
        if (READY_HEAD == NULL)
            return THREAD_NONE;
        interrupts_enabled(0);
        struct thread *temp = RUNNING_THREAD;
        struct thread *new_run = READY_HEAD;
        READY_HEAD = READY_HEAD->next;
        temp->next = NULL;
        thread_id_array[temp->tid] = 0;
        insert_thread_to_delete(temp);
        new_run->next = NULL;
        new_run->state = RECOVER_STATE;
        RUNNING_THREAD = new_run;
        setcontext(&(new_run->thread_context));
    } else if (tid == THREAD_ANY) {
        if (READY_HEAD == NULL)
            return THREAD_NONE;
        struct thread *temp = READY_HEAD;
        Tid returned_tid = temp->tid;
        temp->flag = 1;
        interrupts_set(enabled);
        return returned_tid;
    } else {
        if (tid > THREAD_MAX_THREADS - 1 || tid < THREAD_FAILED || !thread_id_array[tid])
            return THREAD_INVALID;
        if (READY_HEAD == NULL)
            return THREAD_NONE;
        struct thread *temp = READY_HEAD;
        while (temp->tid != tid)
            temp = temp->next;
        Tid returned_tid = temp->tid;
        temp->flag = 1;
        interrupts_set(enabled);
        return returned_tid;
    }
    interrupts_set(enabled);
    return THREAD_FAILED;
}
Пример #11
0
Tid thread_sleep(struct wait_queue *queue) {
    int enabled = interrupts_set(0);
    if (queue == NULL) {
        interrupts_set(enabled);
        return THREAD_INVALID;
    } else if (READY_HEAD == NULL) {
        interrupts_set(enabled);
        return THREAD_NONE;
    } else {
        struct thread *temp = READY_HEAD;
        READY_HEAD = READY_HEAD->next;
        temp->next = NULL;
        Tid returned_tid = temp->tid;
        insert_thread_to_wait(RUNNING_THREAD, queue);
        RUNNING_THREAD->state = NEW_STATE;
        getcontext(&(RUNNING_THREAD->thread_context));
        if (RUNNING_THREAD->flag)
            thread_exit(THREAD_SELF);
        if (TO_DELETE_THREAD)
            delete_threads_list();
        if (!thread_id_array[returned_tid]) {
            interrupts_set(enabled);
            return returned_tid;
        }
        if (temp->state == NEW_STATE && RUNNING_THREAD->state != RECOVER_STATE) {
            temp->state = RECOVER_STATE;
            RUNNING_THREAD = temp;
            setcontext(&(temp->thread_context));
        }
        interrupts_set(enabled);
        return returned_tid;
    }
    interrupts_set(enabled);
    return THREAD_FAILED;
}
Пример #12
0
/* when the 'all' parameter is 1, wakeup all threads waiting in the queue.
 * returns whether a thread was woken up on not. */
int thread_wakeup(struct wait_queue *queue, int all) {
    int enabled = interrupts_set(0);
    if(queue == NULL){
        interrupts_set(enabled);
        return 0;
    } else if(queue->wait_head == NULL){
        interrupts_set(enabled);
        return 0;
    } else{
        if(all == 0){
            if(queue->size == 1){
                insert_thread_to_ready(queue->wait_head);
                queue->wait_head = NULL;
            } else{
                struct thread *temp = queue->wait_head;
                queue->wait_head = temp->next;
                temp->next = NULL;
                insert_thread_to_ready(temp);
            }
            interrupts_set(enabled);
            return 1;
        } else if(all == 1){
            int size = queue->size;
            insert_thread_to_ready(queue->wait_head);
            queue->wait_head = NULL;
            queue->size = 0;
            interrupts_set(enabled);
            return size;
        }
    }
    interrupts_set(enabled);
    return 0;
}
Пример #13
0
/* turn off interrupts while printing */
int
unintr_printf(const char *fmt, ...)
{
	int ret, enabled;
	va_list args;

	enabled = interrupts_off();
	va_start(args, fmt);
	ret = vprintf(fmt, args);
	va_end(args);
	interrupts_set(enabled);
	return ret;
}
Пример #14
0
Tid
thread_exit(Tid tid)
{
	int enabled = interrupts_set(0);
	thread *current;
	//thread *temp;
	current = first;


	if (tid==THREAD_ANY)
	{
		while(current->state != READY)
		{
			current=current->next;
			if (current==NULL)
			{
				interrupts_set(enabled);
				return THREAD_NONE;
			}
		}
		current->state=EXIT;
		int x=current->id;
		aid[x]=0; //make ID available 
		current->id=-99;
		interrupts_set(enabled);
		return x;
	}

	if (first->next==NULL)
	{
		interrupts_set(enabled);
		return THREAD_NONE;
	}


	while ((current->id != tid))
	{
		current=current->next;
		if (current==NULL)
		{
			interrupts_set(enabled);
			return THREAD_INVALID;
		}
		
	}

 	current->state=EXIT;
 	int x=current->id;

	aid[x]=0;
	current->id=-99;

	interrupts_set(enabled);
	return x;

}
Пример #15
0
Tid
thread_yield(Tid want_tid) {
    int enabled = interrupts_set(0);
    if (want_tid == THREAD_ANY) {
        if (READY_HEAD == NULL) {
            interrupts_set(enabled);
            return THREAD_NONE;
        }
        struct thread *temp = READY_HEAD;
        READY_HEAD = READY_HEAD->next;
        temp->next = NULL;
        Tid returned_tid = temp->tid;
        insert_thread_to_ready(RUNNING_THREAD);
        RUNNING_THREAD->state = NEW_STATE;
        getcontext(&(RUNNING_THREAD->thread_context));
        if (RUNNING_THREAD->flag)
            thread_exit(THREAD_SELF);
        if (TO_DELETE_THREAD)
            delete_threads_list();
        if (!thread_id_array[returned_tid]) {
            interrupts_set(enabled);
            return returned_tid;
        }
        if (temp->state == NEW_STATE && RUNNING_THREAD->state != RECOVER_STATE) {
            temp->state = RECOVER_STATE;
            RUNNING_THREAD = temp;
            setcontext(&(temp->thread_context));
        }
        interrupts_set(enabled);
        return returned_tid;
    } else if (want_tid == THREAD_SELF || want_tid == RUNNING_THREAD->tid) {
        RUNNING_THREAD->state = NEW_STATE;
        getcontext(&(RUNNING_THREAD->thread_context));
        if (RUNNING_THREAD->state == NEW_STATE) {
            RUNNING_THREAD->state = RECOVER_STATE;
            setcontext(&(RUNNING_THREAD->thread_context));
        }
        interrupts_set(enabled);
        return RUNNING_THREAD->tid;
    } else if (want_tid > THREAD_MAX_THREADS - 1 || want_tid < THREAD_FAILED || !thread_id_array[want_tid]) {
        interrupts_set(enabled);
        return THREAD_INVALID;
    } else {
        struct thread *temp = READY_HEAD;
        struct thread *prev = READY_HEAD;
        while (temp->tid != want_tid) {
            prev = temp;
            temp = temp->next;
        }
        if (READY_HEAD->tid == want_tid)
            READY_HEAD = READY_HEAD->next;
        else
            prev->next = temp->next;
        temp->next = NULL;
        Tid returned_tid = temp->tid;
        insert_thread_to_ready(RUNNING_THREAD);
        RUNNING_THREAD->state = NEW_STATE;
        getcontext(&(RUNNING_THREAD->thread_context));
        if (RUNNING_THREAD->flag)
            thread_exit(THREAD_SELF);
        if (TO_DELETE_THREAD)
            delete_threads_list();
        if (!thread_id_array[returned_tid]) {
            interrupts_set(enabled);
            return returned_tid;
        }
        if (temp->state == NEW_STATE && RUNNING_THREAD->state != RECOVER_STATE) {
            temp->state = RECOVER_STATE;
            RUNNING_THREAD = temp;
            setcontext(&(temp->thread_context));
        }
        interrupts_set(enabled);
        return returned_tid;
    }
    return THREAD_FAILED;
}
Пример #16
0
/* when the 'all' parameter is 1, wakeup all threads waiting in the queue.
 * returns whether a thread was woken up on not. */
int
thread_wakeup(struct wait_queue *queue, int all)
{
	int enabled = interrupts_set(0);
	thread *current;
	current = first;

	wait_queue *q_current;
	q_current=queue;

	int counter=0;

	if (queue==NULL)
		interrupts_set(enabled);
		return counter;

	// dummy=0 means wait queue has been initialized but nothing has been added to wait queue.
	if (queue->dummy==0)
		interrupts_set(enabled);
		return counter;

	//wake up the the first thread(head) in the sleep queue.
	if (all==0)
	{
		//make current point to the corresponding id in main linked list
		while (current->id != q_current->id)
		{
			current=current->next;
			if (current==NULL)
			{
				interrupts_set(enabled);
				return counter;
			}
		}


		current->state=READY;
		queue=queue->next;
		free(q_current);

		interrupts_set(enabled);
		return 1;
	}

	if (all==1)
	{

		//wake up(put in ready state) for every thread in sleep queue.
		while (q_current != NULL)
		{
		q_current=queue;
		current=first;

			while(q_current->id != current->id)
			{
				current=current->next;
			}
		current->state=READY;
		queue=queue->next;
		free(q_current);
		q_current=queue;

		counter++;
		}

	interrupts_set(enabled);
	return counter;
	}
interrupts_set(enabled);
return 0;
}
Пример #17
0
Tid
thread_sleep(struct wait_queue *queue)
{
	int enabled = interrupts_set(0);
	thread *current;
	current=first;

	wait_queue *q_current;
	q_current=queue;
	

	int context_called = 0;

	if (queue==NULL)
	{
		interrupts_set(enabled);
		return THREAD_INVALID;
	}	

	//find a thread that is ready, if none return THREAD_NONE
	while(current->state != READY)
	{
		current=current->next;
		if (current==NULL)
		{
			interrupts_set(enabled);
			return THREAD_NONE;
		}
	}

	//At this point, current is pointing at ready thread

	//set current running thread's state to sleep.
	curr->state=SLEEP;

	getcontext(curr->tcontext);

	if (context_called==1)
	{
		interrupts_set(enabled);
		return curr->id;
	}
	
	context_called=1;

	//only runs when there is 0 threads in the sleep queue. 
	//malloc not required
	if (queue->dummy == 0)
	{
		queue->dummy=1;
		queue->id=curr->id;
		queue->next=NULL;
	}

	//Add current running thread at the end.
	else
	{
		while(q_current->next != NULL)
		{
			q_current=q_current->next;
		}
	q_current->next=malloc(sizeof(struct wait_queue));
	q_current=q_current->next;
	q_current->id=curr->id;
	q_current->dummy=1;
	q_current->next=NULL;

	}
	
	curr=current;
	curr->state=RUNNING;
	setcontext(curr->tcontext);

	interrupts_set(enabled);
	return curr->id;
}
Пример #18
0
/* enables interrupts. */
int
interrupts_on()
{
	return interrupts_set(1);
}
Пример #19
0
/* disables interrupts */
int
interrupts_off()
{
	return interrupts_set(0);
}
Пример #20
0
Tid
thread_yield(Tid want_tid)
{
	
	int enabled = interrupts_set(0);
	int context_called=0;
	thread *current;
	current=curr;
	//int abc=1;
	//if (current->next==NULL)
	//	current=first;

	//printf("Yielding from %d to %d\n", curr->id, want_tid);

	if ((want_tid > (THREAD_MAX_THREADS-1))||(want_tid<-7))
	{
		interrupts_set(enabled);
		return THREAD_INVALID;
	}
	if (want_tid > tcounter())
	{
		interrupts_set(enabled);
		return THREAD_INVALID;
	}

	if (want_tid==THREAD_SELF) //no-op. return current id and continue the execution.
	{
		interrupts_set(enabled);
		return curr->id;
	}

	if (want_tid==THREAD_ANY)  //run any thread in the ready queue
	{
		//print_rdyq();
		if (first->next==NULL) //if there is only 1 thread running
		{
			interrupts_set(enabled);
			return THREAD_NONE;
		}

	
		while(current->state != READY) //find the first thread that is in ready state
		{
			current=current->next;
			if (current==NULL)
			{
				current=first;
				while(current->state != READY)
				{
					if(current==curr)
					{
						interrupts_set(enabled);
						return THREAD_NONE;	
					}
					current=current->next;
					if(current==curr)
					{
						interrupts_set(enabled);
						return THREAD_NONE;	
					}
				}
				
			}
		}
		//printf("Yielding from %d to %d \n", curr->id, current->id);

		curr->state=READY;

		getcontext(curr->tcontext);

		if (context_called==1)
		{
			interrupts_set(enabled);
			return curr->id;
		}

		context_called=1;
		curr=current;
		curr->state=RUNNING;

		setcontext(curr->tcontext);
		return curr->id;
	}

	current=first;
	while (current->id != want_tid)
	{
		current=current->next;
		if (current==NULL)
		{
			interrupts_set(enabled);
			return THREAD_INVALID;
		}
	}

	if (current->state == READY)
	{
		curr->state=READY;
		getcontext(curr->tcontext);

			if (context_called==1)
			{
				interrupts_set(enabled);
				return want_tid;
			}

		context_called=1;
		curr=current;
		curr->state=RUNNING;
		setcontext(curr->tcontext);
		
		return curr->id;
	}

	else if (current->state == RUNNING)
	{
		interrupts_set(enabled);			
		return current->id;
	}
	
	//printf("HI\n");
	return THREAD_FAILED;
}