Beispiel #1
0
void
test_crt_join_sched(void)
{
	lwt_t chld1, chld2;

	printf("[TEST] thread creation/join/scheduling\n");

	/* functional tests: scheduling */
	lwt_yield(LWT_NULL);

	lwt_chan_t c1 = lwt_chan(0);
	chld1 = lwt_create(fn_sequence, (void*)1, 0, c1);
	lwt_chan_t c2 = lwt_chan(0);
	chld2 = lwt_create(fn_sequence, (void*)2, 0, c2);
	lwt_join(chld2);
	lwt_join(chld1);	
	IS_RESET();

	/* functional tests: join */
	lwt_chan_t c3 = lwt_chan(0);
	chld1 = lwt_create(fn_null, NULL, 0, c3);
	lwt_join(chld1);
	IS_RESET();

	lwt_chan_t c4 = lwt_chan(0);
	chld1 = lwt_create(fn_null, NULL, 0, c4);
	lwt_yield(LWT_NULL);
	lwt_join(chld1);
	IS_RESET();

	lwt_chan_t c5 = lwt_chan(0);
	chld1 = lwt_create(fn_nested_joins, NULL, 0, c5);
	lwt_join(chld1);
	IS_RESET();

	/* functional tests: join only from parents */
	lwt_chan_t c6 = lwt_chan(0);
	chld1 = lwt_create(fn_identity, (void*)0x37337, 0, c6);
	lwt_chan_t c7 = lwt_chan(0);
	chld2 = lwt_create(fn_join, chld1, 0, c7);
	lwt_yield(LWT_NULL);
	lwt_yield(LWT_NULL);
	lwt_join(chld2);
	lwt_join(chld1);
	IS_RESET();

	/* functional tests: passing data between threads */
	lwt_chan_t c8 = lwt_chan(0);
	chld1 = lwt_create(fn_identity, (void*)0x37337, 0, c8);
	assert((void*)0x37337 == lwt_join(chld1));
	IS_RESET();

	/* functional tests: directed yield */
	lwt_chan_t c9 = lwt_chan(0);
	chld1 = lwt_create(fn_null, NULL, 0, c9);
	lwt_yield(chld1);
	assert(lwt_info(LWT_INFO_NTHD_ZOMBIES) == 1);
	lwt_join(chld1);
	IS_RESET();
}
Beispiel #2
0
void test_speed_yield()
{
	lwt_t tid1, tid2;
	tid1 = lwt_create(fn_bounce, (void*)1, 0, 0);
	tid2 = lwt_create(fn_bounce, NULL, 0, 0);
	lwt_yield(LWT_NULL);
	lwt_join(tid1);
	lwt_join(tid2);
	lwt_yield(LWT_NULL);

	IS_RESET();
}
Beispiel #3
0
void test_function_basic()
{
	lwt_t id;
	IS_RESET();
	id = lwt_create(fn_nested_create, 0, 0, 0);
	lwt_yield(LWT_NULL);
	

	printf("join in parent\n");
	lwt_join(id);
	lwt_yield(LWT_NULL);

	IS_RESET();
}
Beispiel #4
0
void *
fn_nested_joins(void *d)
{
	lwt_t chld;

	if (d) {
		lwt_yield(LWT_NULL);
		lwt_yield(LWT_NULL);
		assert(lwt_info(LWT_INFO_NTHD_RUNNABLE) == 1);
		lwt_die(NULL);
	}
	chld = lwt_create(fn_nested_joins, (void*)1);
	lwt_join(chld);
}
Beispiel #5
0
void
test_crt_join_sched(void)
{
	lwt_t chld1, chld2;

	/* functional tests: scheduling */
	lwt_yield(LWT_NULL);

	chld1 = lwt_create(fn_sequence, (void*)1);
	chld2 = lwt_create(fn_sequence, (void*)2);
	lwt_join(chld2);
	lwt_join(chld1);	
	IS_RESET();

	/* functional tests: join */
	chld1 = lwt_create(fn_null, NULL);
	lwt_join(chld1);
	IS_RESET();

	chld1 = lwt_create(fn_null, NULL);
	lwt_yield(LWT_NULL);
	lwt_join(chld1);
	IS_RESET();

	chld1 = lwt_create(fn_nested_joins, NULL);
	lwt_join(chld1);
	IS_RESET();

	/* functional tests: join only from parents */
	chld1 = lwt_create(fn_identity, (void*)0x37337);
	chld2 = lwt_create(fn_join, chld1);
	lwt_yield(LWT_NULL);
	lwt_yield(LWT_NULL);
	lwt_join(chld2);
	lwt_join(chld1);
	IS_RESET();

	/* functional tests: passing data between threads */
	chld1 = lwt_create(fn_identity, (void*)0x37337);
	assert((void*)0x37337 == lwt_join(chld1));
	IS_RESET();

	/* functional tests: directed yield */
	chld1 = lwt_create(fn_null, NULL);
	lwt_yield(chld1);
	assert(lwt_info(LWT_INFO_NTHD_ZOMBIES) == 1);
	lwt_join(chld1);
	IS_RESET();
}
Beispiel #6
0
/**
 * @brief Creates a LWT using the provided function pointer and the data as input for it
 * @param fn The function pointer to use
 * @param data The data to the function
 * @param flags The flags to be associated with the thread
 * @return A pointer to the initialized LWT
 */
lwt_t lwt_create(lwt_fnt_t fn, void * data, lwt_flags_t flags){
	//wait until there's a free thread
	while(!head_ready_pool_threads.lh_first){
		lwt_yield(LWT_NULL);
	}

	//pop the head of the ready pool list
	lwt_t thread = head_ready_pool_threads.lh_first;
	LIST_REMOVE(thread, ready_pool_threads);
	//set thread's parent
	thread->parent = current_thread;
	//insert into parent's siblings
	LIST_INSERT_HEAD(&current_thread->head_children, thread, siblings);
	//set status
	thread->info = LWT_INFO_NTHD_RUNNABLE;

	thread->start_routine = fn;
	thread->args = data;
	thread->flags = flags;

	//associate with kthd
	lwt_kthd_t pthread_kthd = __get_kthd();
	thread->kthd = pthread_kthd;
	LIST_INSERT_HEAD(&pthread_kthd->head_lwts_in_kthd, thread, lwts_in_kthd);

	//insert into runnable list
	__insert_runnable_tail(thread);

	return thread;
}
Beispiel #7
0
void* fn_nested_create(void* data, lwt_chan_t c)
{
	int param = (int)data;
	lwt_t id;
	if(param< 5)
	{
		printf("create: %d\n", param);
		id = lwt_create(fn_nested_create, (void*)(param+1), 0, 0);
		lwt_yield(id);
		printf("join: %d\n", param);
		lwt_join(id);
	}
	lwt_yield(LWT_NULL);

	return NULL;
}
Beispiel #8
0
void *
fn_bounce(void *d) 
{
	int i;
	unsigned long long start, end;

	lwt_yield(LWT_NULL);
	lwt_yield(LWT_NULL);
	rdtscll(start);
	for (i = 0 ; i < ITER ; i++) lwt_yield(LWT_NULL);
	rdtscll(end);
	lwt_yield(LWT_NULL);
	lwt_yield(LWT_NULL);

	if (!d) printf("Overhead of yield is %lld\n", (end-start)/(ITER*2));

	return NULL;
}
Beispiel #9
0
int test_nojoin()
{

	lwt_create(fn, NULL, LWT_FLAG_NOJOIN, NULL);
	assert(num_of_threads == 2);
	lwt_yield(_LWT_NULL);
	assert(num_of_threads == 1);
	return 0;
}
Beispiel #10
0
void* fn_bounce(void* data, lwt_chan_t c)
{
	int i=0;

	unsigned long long int start, end;

	lwt_yield(LWT_NULL);
	rdtscll(start);
	for(i=0 ; i < ITER; i++)
	{
		lwt_yield(LWT_NULL);
	}
	rdtscll(end);

	if((int)data == 1)
		printf("performance of yield: --> %lld\n", (end-start)/(ITER*2));

	return NULL;
}
Beispiel #11
0
/**
 * @brief Prepares the current thread to be cleaned up
 */
void lwt_die(void * value){
	current_thread->return_value = value;
	//check to see if we can return
	while(current_thread->head_children.lh_first){
		current_thread->info = LWT_INFO_NTHD_BLOCKED;
		lwt_yield(LWT_NULL);
	}
	//remove from parent thread
	if(current_thread->parent){
		LIST_REMOVE(current_thread, siblings);

		//check if parent can be unblocked
		if(!current_thread->parent->head_children.lh_first &&
				current_thread->parent->info == LWT_INFO_NTHD_BLOCKED){
			lwt_signal(current_thread->parent);
		}
	}

	//reset thread as ready in the thread pool
	if(current_thread->flags == LWT_NOJOIN){
		__reinit_lwt(current_thread);
	}
	else{
		//change status to zombie
		current_thread->info = LWT_INFO_NTHD_ZOMBIES;
	}

	//remove from kthd
	if(current_thread->kthd){
		LIST_REMOVE(current_thread, lwts_in_kthd);
		//signal the original thread to die if this is the last thread
		if(!current_thread->kthd->head_lwts_in_kthd.lh_first){
			lwt_signal(original_thread);
		}
	}

	//switch to another thread
	lwt_yield(LWT_NULL);
}
Beispiel #12
0
void *
fn_sequence(void *d)
{
	int i, other, val = (int)d;

	for (i = 0 ; i < ITER ; i++) {
		other = curr;
		curr  = (curr + 1) % 2;
		sched[curr] = val;
		assert(sched[other] != val);
		lwt_yield(LWT_NULL);
	}

	return NULL;
}
Beispiel #13
0
int main(int argc, char** argv)
{

//	printf("testing grp_wait...\n");
//	test_grp_wait_with_buffer();

//	test_nojoin();
	test_kthd();
	//test_kthd_iter();

	printf("back to main\n");
	sleep(1);
	lwt_yield(_LWT_NULL);
	return EXIT_SUCCESS;
}
Beispiel #14
0
void *
fn_grpwait(lwt_chan_t c)
{
	int i;

	for (i = 0 ; i < ITER ; i++) {
		if ((i % 7) == 0) {
			int j;

			for (j = 0 ; j < (i % 8) ; j++) lwt_yield(LWT_NULL);
		}
		lwt_snd(c, (void*)lwt_id(lwt_current()));
	}
	lwt_chan_deref(c);
}
Beispiel #15
0
/*
#define IS_RESET()						\
        assert( lwt_info(LWT_INFO_NTHD_RUNNABLE) == 1 &&	\
		lwt_info(LWT_INFO_NTHD_ZOMBIES) == 0 &&		\
		lwt_info(LWT_INFO_NTHD_BLOCKED) == 0)

*/
int
main(void)
{
	lwt_t chld1, chld2;
	int i;
	unsigned long long start, end;


	/* Performance tests */
	rdtscll(start);
	for (i = 0 ; i < ITER ; i++) {
		chld1 = lwt_create(fn_null, NULL);
		lwt_join(chld1);
	}
	rdtscll(end);
	printf("Overhead for fork/join is %lld\n", (end-start)/ITER);
	//IS_RESET();

	chld1 = lwt_create(fn_bounce, NULL);
	chld2 = lwt_create(fn_bounce, NULL);
	lwt_join(chld1);
	lwt_join(chld2);
	//IS_RESET();

	/* functional tests: scheduling */
	lwt_yield(LWT_NULL);

	chld1 = lwt_create(fn_sequence, (void*)1);
	chld2 = lwt_create(fn_sequence, (void*)2);
	lwt_join(chld2);
	lwt_join(chld1);	
	//IS_RESET();

	/* functional tests: join */
	chld1 = lwt_create(fn_null, NULL);
	lwt_join(chld1);
	//IS_RESET();

	chld1 = lwt_create(fn_null, NULL);
	lwt_yield(LWT_NULL);
	lwt_join(chld1);
	//IS_RESET();

	chld1 = lwt_create(fn_nested_joins, NULL);
	lwt_join(chld1);
	//IS_RESET();

	/* functional tests: join only from parents */
	chld1 = lwt_create(fn_identity, (void*)0x37337);
	chld2 = lwt_create(fn_join, chld1);
	lwt_yield(LWT_NULL);
	lwt_yield(LWT_NULL);
	lwt_join(chld2);
	lwt_join(chld1);
	//IS_RESET();

	/* functional tests: passing data between threads */
	chld1 = lwt_create(fn_identity, (void*)0x37337);
	//TODO assert((void*)0x37337 == lwt_join(chld1));
	//IS_RESET();

	/* functional tests: directed yield */
	chld1 = lwt_create(fn_null, NULL);
	lwt_yield(chld1);
	//assert(lwt_info(LWT_INFO_NTHD_ZOMBIES) == 1);
	lwt_join(chld1);
	//IS_RESET();
	
	//TODO assert(thd_cnt == ITER+12);
}
Beispiel #16
0
/**
 * @brief Blocks the current thread
 * @param info The state to set the thread
 */
void lwt_block(lwt_info_t info){
	//ensure info isn't LWT_INFO_NRUNNING
	assert(info != LWT_INFO_NTHD_RUNNABLE);
	current_thread->info = info;
	lwt_yield(LWT_NULL);
}
Beispiel #17
0
/**
 * @brief Cleans up all remaining threads on exit
 */
__attribute__((destructor)) void __destroy__(){
	lwt_kthd_t pthread_kthd = __get_kthd();
	//clean up buffer thread
	if(pthread_kthd->buffer_thread){
		free(pthread_kthd->buffer_thread);
	}
	//free threads
	lwt_t current = head_current.lh_first;
	lwt_t next = NULL;
	lwt_chan_t rcv_channels = NULL;
	lwt_chan_t next_channel = NULL;

	//check for no-joined threads and switch to them to let them die
	while(current){
		next = current->current_threads.le_next;
		if(current->flags == LWT_NOJOIN){
			lwt_yield(current);
		}

		current = next;
	}

	current = head_current.lh_first;
	next = NULL;

	while(current){
		next = current->current_threads.le_next;

		//remove any channels
		rcv_channels = current->head_receiver_channel.lh_first;
		while(rcv_channels){
			next_channel = rcv_channels->receiver_channels.le_next;
			//free buffer
			if(rcv_channels->async_buffer){
				free(rcv_channels->async_buffer);
			}
			//free group
			lwt_cgrp_t group = rcv_channels->channel_group;
			if(group && group->creator_thread == current){
				//free the buffer
				while(group->head_event.tqh_first){
					TAILQ_REMOVE(&group->head_event, group->head_event.tqh_first, events);
				}
				free(group);
			}
			free(rcv_channels);
			rcv_channels = next_channel;
		}


		if(current != original_thread){
			//printf("FREEING STACK!!\n");
			//remove stack
			__lwt_stack_return(current->min_addr_thread_stack);
			free(current);
		}

		current = next;
	}

	//free original thread
	free(original_thread);
	//free kthd
	pthread_cond_destroy(&pthread_kthd->blocked_cv);
	pthread_mutex_destroy(&pthread_kthd->blocked_mutex);
	free(pthread_kthd);

	pthread_exit(0);
}