Simple coroutine library / objects in plain C Snapshot
|
00001 #include <sys/mman.h> 00002 #include <unistd.h> 00003 #include "stacks.h" 00004 #include <stdio.h> 00005 00006 STACK_DIR stack_dir( int *ptr ) 00007 { 00008 int a = 0; 00009 if ((size_t) &a < (size_t) ptr ) { 00010 return STACK_DIR_GROWING_DOWN; 00011 } 00012 return STACK_DIR_GROWING_UP; 00013 } 00014 00015 int stack_direction() 00016 { 00017 int a = 0; 00018 00019 return stack_dir( & a ); 00020 } 00021 00022 int STACKS_init( STACKS *stack, int num_stacks, int pages_per_stack ) 00023 { 00024 int page_size; 00025 size_t len, one_stack_size; 00026 STACK_DIR dir; 00027 STACK_ENTRY *entry; 00028 uint8_t *mapping, *stack_start; 00029 uint8_t *guard_page; 00030 int i; 00031 00032 page_size = sysconf( _SC_PAGE_SIZE ); 00033 one_stack_size = page_size * pages_per_stack; 00034 len = num_stacks * one_stack_size; 00035 dir = stack_direction(); 00036 00037 mapping = (uint8_t *) mmap( 0 , len, PROT_READ|PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS 00038 00039 #if 0 00040 #ifdef MAP_STACK 00041 | MAP_STACK 00042 #endif 00043 #endif 00044 , -1, 0 ); 00045 if (!mapping) { 00046 return -1; 00047 } 00048 00049 //fprintf( stderr, "all stacks %p - %p\n", mapping, mapping + len ); 00050 00051 stack->mapping = mapping; 00052 stack->mapping_length = len; 00053 stack->num_stacks = num_stacks; 00054 stack->one_stack_size = one_stack_size - page_size; 00055 00056 DLIST_init( &stack->root ); 00057 00058 for( i = 0; i < num_stacks; i ++ ) { 00059 stack_start = mapping + ( i * one_stack_size); 00060 00061 if (dir == STACK_DIR_GROWING_DOWN) { 00062 //stack_start = mapping + ( (i + 1) * one_stack_size) - 1; 00063 guard_page = mapping + (i * one_stack_size); 00064 } else { 00065 guard_page = mapping + ( i + 1 ) * one_stack_size - page_size; 00066 } 00067 00068 if (mprotect( guard_page , page_size, PROT_NONE )) { 00069 return -1; 00070 } 00071 00072 entry = (STACK_ENTRY *) malloc( sizeof( STACK_ENTRY ) ); 00073 if (!entry) { 00074 return -1; 00075 } 00076 entry->stack_start = stack_start; 00077 entry->stacks = stack; 00078 DLIST_push_back( &stack->root, &entry->entry ); 00079 } 00080 return 0; 00081 } 00082 00083 int STACKS_destroy( STACKS *stack ) 00084 { 00085 if ( DLIST_size( &stack->root) != (size_t) stack->num_stacks ) { 00086 return -1; 00087 } 00088 00089 if (munmap( stack->mapping, stack->mapping_length)) { 00090 return -1; 00091 } 00092 return 0; 00093 } 00094 00095 00096 void *STACKS_get(STACKS *stack, STACK_ENTRY **rentry ) 00097 { 00098 STACK_ENTRY *entry; 00099 if (DLIST_isempty( &stack->root ) ) { 00100 return 0; 00101 } 00102 entry = (STACK_ENTRY *) DLIST_pop_front( &stack->root ); 00103 *rentry = entry; 00104 return entry->stack_start; 00105 } 00106 00107 int STACKS_release(STACK_ENTRY *entry) 00108 { 00109 STACKS *stack = entry->stacks; 00110 DLIST_push_front( &stack->root, &entry->entry ); 00111 return 0; 00112 }