Пример #1
0
void condition_wait(struct condition* c, struct mutex* m){
	mutex_unlock(m);
	current_thread->state = BLOCKED;
	thread_enqueue(&c->waiting_threads, current_thread);
	yield();
	mutex_lock(m);
};
Пример #2
0
struct thread* thread_fork(void(*target)(void*), void* arg) {
	// allocate a new thread control block and stack
	struct thread* new_thread = malloc(sizeof(struct thread));
	new_thread->stack_pointer = malloc(STACK_SIZE) + STACK_SIZE;
	// Set the new thread's initial argument and initial function.
	new_thread->initial_function = target;
	new_thread->initial_argument = arg;
	// 	Set the current thread's state to READY and enqueue it on the ready list.
	if(current_thread->state != BLOCKED)
		current_thread->state = READY;
	thread_enqueue(&ready_list, current_thread);
	// Set the new thread's state to RUNNING.
	new_thread->state = RUNNING;
	// allocate mutex lock and condition
	new_thread->mutexLock = malloc(sizeof(struct mutex));
	new_thread->condList = malloc(sizeof(struct condition));
	mutex_init(new_thread->mutexLock);
	condition_init(new_thread->condList);
	// Save a pointer to the current thread in a temporary variable, then set the current thread to the new thread.
	struct thread* temp = current_thread;
	current_thread = new_thread;
	// Call thread_start with the old current thread as old and the new current thread as new.
	thread_start(temp, current_thread);

	return new_thread;
};
Пример #3
0
void condition_signal(struct condition* c){
	struct thread* ready_thread = thread_dequeue(&c->waiting_threads);
	if(ready_thread){
		ready_thread->state = READY;
		thread_enqueue(&ready_list, ready_thread);
	}
};
Пример #4
0
void thread_fork(void(*target)(void*), void *arg)
{
	// Allocate a new thread control block, and allocate its stack.
	thread *new_thread = (thread *) malloc(sizeof(thread));
	new_thread->stack_pointer = malloc(STACK_SIZE) + STACK_SIZE;
//printf("FORK: New Thread allocated\n");

	// Set the new thread's initial argument and initial function.
	new_thread->initial_argument = arg;
	new_thread->initial_function = target;

	// Set the current thread's state to READY and enqueue it on the ready list.
	current_thread->state = READY;
	thread_enqueue(&ready_list, current_thread);
//printf("FORK: Placed current thread onto queue\n");

	// Set the new thread's state to RUNNING.
	new_thread->state = RUNNING;

	/* Save a pointer to the current thread in a temporary variable, 
	then set the current thread to the new thread. */
	thread *temp = current_thread;
	current_thread = new_thread;

	/* Call thread_start with the old current thread as old and the 
	new current thread as new. */
//printf("FORK: New current thread running\n");
	thread_start(temp, current_thread);
}
Пример #5
0
/**
 * \brief Wakeup a thread on a foreign dispatcher while disabled.
 *
 * \param core_id       Core ID to wakeup on
 * \param thread        Pointer to thread to wakeup
 * \param mydisp        Dispatcher this function is running on
 *
 * \return SYS_ERR_OK on success.
 */
static errval_t domain_wakeup_on_coreid_disabled(coreid_t core_id,
                                                 struct thread *thread,
                                                 dispatcher_handle_t mydisp)
{
    struct domain_state *ds = get_domain_state();

    // XXX: Ugly hack to allow waking up on a core id we don't have a
    // dispatcher handler for
    thread->coreid = core_id;

    // Catch this early
    assert_disabled(ds != NULL);
    if (ds->b[core_id] == NULL) {
        return LIB_ERR_NO_SPANNED_DISP;
    }

    thread_enqueue(thread, &ds->remote_wakeup_queue);

    // Signal the inter-disp waitset of this event
    struct event_closure closure = {
        .handler = handle_wakeup_on
    };
    errval_t err =
        waitset_chan_trigger_closure_disabled(&ds->interdisp_ws,
                                              &ds->remote_wakeup_event,
                                              closure,
                                              mydisp);
    assert_disabled(err_is_ok(err) ||
                    err_no(err) == LIB_ERR_CHAN_ALREADY_REGISTERED);

    return SYS_ERR_OK;
}
Пример #6
0
errval_t domain_thread_move_to(struct thread *thread, coreid_t core_id)
{
    assert(thread == thread_self());
    dispatcher_handle_t mydisp = disp_disable();
    struct dispatcher_generic *disp_gen = get_dispatcher_generic(mydisp);
    struct dispatcher_shared_generic *disp =
        get_dispatcher_shared_generic(mydisp);

    struct thread *next = thread->next;
    thread_remove_from_queue(&disp_gen->runq, thread);

    errval_t err = domain_wakeup_on_coreid_disabled(core_id, thread, mydisp);
    if(err_is_fail(err)) {
        thread_enqueue(thread, &disp_gen->runq);
        disp_enable(mydisp);
        return err;
    }

    // run the next thread, if any
    if (next != thread) {
        disp_gen->current = next;
        disp_resume(mydisp, &next->regs);
    } else {
        disp_gen->current = NULL;
        disp->haswork = havework_disabled(mydisp);
        disp_yield_disabled(mydisp);
    }

    USER_PANIC("should never be reached");
}
Пример #7
0
void mutex_lock(struct mutex * m){
	if(m->held == 1){
		current_thread->state = BLOCKED;
		thread_enqueue(&m->waiting_threads, current_thread);
		yield();
	}else
		m->held = 1;
};
Пример #8
0
void condition_broadcast(struct condition* c){
	struct thread* ready_thread = thread_dequeue(&c->waiting_threads);
	while(ready_thread){
		ready_thread->state = READY;
		thread_enqueue(&ready_list, ready_thread);
		ready_thread = thread_dequeue(&c->waiting_threads);
	}
};
Пример #9
0
void thread_relinquish()
/* call this within a thread to allow scheduling of a new thread */
{
	if (_setjmp( current->state ) == 0) {
		thread_enqueue( current, &readylist );
		current = thread_dequeue( &readylist );
		_longjmp( current->state, 1 );
	}
}
Пример #10
0
void thread_signal( struct thread_semaphore * s )
/* call this within a thread to signal a semaphore */
{
	struct thread * t = thread_dequeue( &s->queue );
	if (t == thread_null) {
		s->count++;
	} else {
		thread_enqueue( t, &readylist );
	}
}
Пример #11
0
void mutex_unlock(struct mutex * m){
	if(is_empty(&m->waiting_threads)){
		m->held = 0;
	}else{
		struct thread* temp = thread_dequeue(&m->waiting_threads);
		if(temp){
			temp->state = READY;
			thread_enqueue(&ready_list, temp);
		}
	}
};
Пример #12
0
static void wakeup_thread_request(struct interdisp_binding *b,
                                  genvaddr_t taddr)
{
    coreid_t core_id = disp_get_core_id();
    struct thread *wakeup = (struct thread *)(uintptr_t)taddr;
    dispatcher_handle_t handle = disp_disable();
    struct dispatcher_generic *disp_gen = get_dispatcher_generic(handle);
    /* assert_disabled(wakeup->disp == handle); */
    assert_disabled(wakeup->coreid == core_id);
    wakeup->disp = handle;
    thread_enqueue(wakeup, &disp_gen->runq);
    disp_enable(handle);
}
Пример #13
0
// yield is very similar to thread_fork, with the main difference being that 
// it is pulling the next thread to run off of the ready list instead of creating it. yield should:
void yield(){
	// If the current thread is not DONE, set its state to READY and enqueue it on the ready list.
	if(current_thread->state != DONE && current_thread->state != BLOCKED){
		current_thread->state = READY;
		thread_enqueue(&ready_list, current_thread);
	}
	// Dequeue the next thread from the ready list and set its state to RUNNING.
	struct thread* next_thread = thread_dequeue(&ready_list);
	next_thread->state = RUNNING;
	// Save a pointer to the current thread in a temporary variable, then set the current thread to the next thread.
	struct thread* temp = current_thread;
	current_thread = next_thread;
	// Call thread_switch with the old current thread as old and the new current thread as new.
	thread_switch(temp, current_thread);
};
Пример #14
0
void thread_wait( struct thread_semaphore * s )
/* call this within a thread to block on a semaphore */
{
	if (s->count > 0) {
		s->count--;
        } else {
		if (_setjmp( current->state ) == 0) {
			thread_enqueue( current, &s->queue );
			current = thread_dequeue( &readylist );
			if (current == thread_null) {
				/* crisis */
				thread_error = "possible deadlock";

				_longjmp( thread_death, 1 );
			}
			_longjmp( current->state, 1 );
		}
	}
}
Пример #15
0
void yield()
{
	/* If the current thread is not DONE, set its state to READY and 
	enqueue it on the ready list. */
	if (current_thread->state != DONE) {
		current_thread->state = READY;
		thread_enqueue(&ready_list, current_thread);
//printf("YIELD: current thread not finished, back on queue\n");
	}

	// Dequeue the next thread from the ready list and set its state to RUNNING.
	thread *next_thread = thread_dequeue(&ready_list);

	/* Save a pointer to the current thread in a temporary variable, 
	then set the current thread to the next thread. */
	thread *temp = current_thread;
	current_thread = next_thread;
	
	/* Call thread_switch with the old current thread as old and 
	the new current thread as new. */
	thread_switch(temp, current_thread);
//printf("YIELD: Running dequeued thread\n");
}
Пример #16
0
void thread_launch( int size, void (* proc)(int), int param )
/* call this to launch proc(param) as a thread */
/* may be called from main or from any thread */
{
	struct thread * t;
	t = (struct thread *)malloc( sizeof(struct thread) + size );
	t->size = size;
	t->proc = proc;
	t->param = param;
	if (_setjmp( t->state )) {
		/* comes here only when new thread scheduled first time */
		(*current->proc)(current->param);
		thread_exit();
	}
	/* continue initialization */
	{
		long int * s;
		long int * probe_rec;
		long int local_base = (long int)&t; /* address of local t */
		long int new_base;
		int i;

		/* the following code copies the contents of the
		   activation record, just in case it might prove
		   useful; note that we don't know that this is
		   needed on any machine, but it might, so we do it. */

		if (stack_direction == 1) { /* grows up */
			long int * src;
			long int * dst;
			new_base = (long int)t + sizeof( struct thread )
			 	+ local_offset;
			src = (long int *) (local_base - local_offset);
			dst = (long int *) (new_base - local_offset);
			for (i = 0; i <= local_offset; i += sizeof(long int)) {
				*dst++ = *src++;
			}
		} else { /* grows down */
			long int * src;
			long int * dst;
			new_base = (long int)t + sizeof( struct thread )
			 	+ size - (local_offset + sizeof(long int));
			src = (long int *) (local_base);
			dst = (long int *) (new_base);
			for (i = 0; i <= local_offset; i += sizeof(long int)) {
				*dst++ = *src++;
			}
		}

		/* the following code adjusts the references to the
		   activation record in the saved thread state so that
		   they point to the base of the newly allocated stack */

		s = (long int *)(t->state);
		probe_rec = (long int *)probe_record;
		for (i = 0; i < sizeof(jmp_buf); i += sizeof(long int) ) {
			if (*probe_rec != 0) {
				/* adjust this field of state */
				*s += new_base - local_base;
			}
			s++;
			probe_rec++;
		}
	}
	thread_enqueue( t, &readylist );
}