Simple coroutine library / objects in plain C Snapshot
stacks.c
Go to the documentation of this file.
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 }