Created
November 12, 2009 06:09
-
-
Save cchandler/232643 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Play with context | |
#define _XOPEN_SOURCE | |
#include<stdlib.h> | |
#include<stdio.h> | |
#include<string.h> | |
#include<ucontext.h> | |
typedef struct{ | |
int ctx_pos; | |
int cleanup; | |
ucontext_t *ctx; | |
char *stack_space; | |
} ChrisThread; | |
ChrisThread *current_thread; | |
ucontext_t *thread_start; | |
char *stack_space; | |
ChrisThread *ctx_list; | |
int current_pos = 0; | |
int current_ctx_pos = 0; | |
#define LIST_SIZE 50 | |
void yield(); | |
int _init_ctx_list() | |
{ | |
if(!ctx_list) | |
{ | |
printf("Initialize context list\n"); | |
ctx_list = malloc(sizeof(ChrisThread)*LIST_SIZE); | |
} | |
return 0; | |
} | |
void _increment_current_ctx_pos() | |
{ | |
// printf("Incrementing %d %d \n", current_ctx_pos, current_pos); | |
current_ctx_pos++; | |
if(current_ctx_pos >= current_pos) | |
{ | |
current_ctx_pos = 0; | |
} | |
} | |
int _get_current_ctx_pos() | |
{ | |
if(current_ctx_pos > current_pos) | |
{ | |
current_ctx_pos = 0; | |
} | |
return current_ctx_pos; | |
} | |
void _remove_from_ctx_list() | |
{ | |
// printf("Execution concluded, freeing thread %d current thread %d\n", (*thread_ref).ctx_pos, (*current_thread).ctx_pos); | |
(*current_thread).cleanup = 1; | |
// printf("Cleanup of ref %d current %d\n", (*thread_ref).cleanup, (*current_thread).cleanup); | |
// printf("Memory addresses %d %d \n", thread_ref, current_thread); | |
} | |
void _cleanup_thread(ChrisThread *thread_ref) | |
{ | |
printf("Cleaning thread\n"); | |
current_pos--; | |
free( (*thread_ref).stack_space ); | |
free( (*thread_ref).ctx ); | |
// free( thread_ref ); | |
int pos = (*thread_ref).ctx_pos; | |
while(pos < current_pos) | |
{ | |
ctx_list[pos] = ctx_list[pos+1]; | |
pos++; | |
} | |
} | |
void _thread_life_cycle(void(*entry_point)(), ChrisThread *thread_ref ) | |
{ | |
// printf("Init thread lifecycle %d\n", (*thread_ref).ctx_pos); | |
(*entry_point)(); | |
_remove_from_ctx_list(); | |
yield(); | |
} | |
int create_thread( void(*func_point)() ) | |
{ | |
_init_ctx_list(); | |
ChrisThread *thread = (ChrisThread *) malloc(sizeof(ChrisThread)); | |
ucontext_t *newctx = (ucontext_t *) malloc(sizeof(ucontext_t)); | |
(*thread).ctx = newctx; | |
(*thread).ctx_pos = current_pos; | |
getcontext(newctx); | |
stack_space = (char *) malloc(sizeof(char)*SIGSTKSZ); | |
(*newctx).uc_stack.ss_sp = stack_space; | |
(*newctx).uc_stack.ss_size = sizeof(char)*SIGSTKSZ; | |
(*thread).stack_space = stack_space; | |
ctx_list[current_pos] = *thread; | |
int old_pos = current_pos++; | |
makecontext(newctx, &_thread_life_cycle, 2, func_point, &ctx_list[old_pos]); | |
return old_pos; | |
} | |
void run_threads() | |
{ | |
thread_start = (ucontext_t *) malloc(sizeof(ucontext_t)); | |
getcontext(thread_start); | |
char iterator_stack[SIGSTKSZ]; | |
(*thread_start).uc_stack.ss_sp = iterator_stack; | |
(*thread_start).uc_stack.ss_size = sizeof(iterator_stack); | |
int _current_ctx_pos = current_ctx_pos; | |
_increment_current_ctx_pos(); | |
current_thread = &ctx_list[_current_ctx_pos]; | |
swapcontext(thread_start,((*current_thread).ctx)); | |
} | |
void yield() | |
{ | |
// printf("Current thread ID %d\n", (*current_thread).ctx_pos); | |
ChrisThread *old_thread = current_thread; | |
_increment_current_ctx_pos(); | |
current_thread = &ctx_list[_get_current_ctx_pos()]; | |
if((*old_thread).cleanup) | |
{ | |
if((*old_thread).ctx_pos == (*current_thread).ctx_pos) | |
{ | |
//The old thread that we're cleaning up is also | |
//the new thread. No more work :-). | |
printf("Exiting from threads\n"); | |
return; | |
} | |
_cleanup_thread(old_thread); | |
setcontext((*current_thread).ctx); | |
} | |
else | |
{ | |
swapcontext((*old_thread).ctx,(*current_thread).ctx); | |
} | |
} | |
void some_function(int a) | |
{ | |
a = 25; | |
int i = 0; | |
while(a > 0) | |
{ | |
printf("Hello %d\n", a); | |
i++; | |
if(i == 25) | |
{ | |
break; | |
} | |
yield(); | |
// a = 0; | |
} | |
} | |
void some_other_function() | |
{ | |
// while(1) | |
// { | |
printf("The other function\n"); | |
yield(); | |
// } | |
} | |
void third_function() | |
{ | |
int a = 25; | |
int i = 0; | |
while(a > 0) | |
{ | |
printf("Third \n"); | |
i++; | |
if(i == 15) | |
{ | |
break; | |
} | |
yield(); | |
// a = 0; | |
} | |
} | |
int main() | |
{ | |
create_thread(&some_function); | |
create_thread(&some_other_function); | |
create_thread(&third_function); | |
run_threads(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment