Guest User

microthread.cpp

a guest
Jul 29th, 2013
121
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // written by Aidan Dodds (c) 2013
  2. // based on the micro threading article in Game Programming Gems 2
  3. //
  4. //
  5. #include <stdio.h>
  6.  
  7. // number of full integers that can fit on the stack
  8. const int c_shared_stack_size = 1024 * 128; // 128k
  9. const int c_thread_stack_size = 1024;       // 1k
  10.  
  11. //
  12. #define NULL 0
  13.  
  14. // here we allocate a large stack, that is shared amongst the running
  15. // micro code.  
  16. static void *_sharedStack = NULL;
  17. static int   _esp_save    = 0;
  18.  
  19. // offset X by Y bytes
  20. #define offset( X, Y ) ((char*)(X) + (Y))
  21.  
  22. // our yield function
  23. static void __declspec( naked ) _yield( void )
  24. {
  25.     __asm
  26.     {
  27.         push ebx;
  28.         push ebp;
  29.         push esi;
  30.         push edi;
  31.         //
  32.         mov eax, esp;
  33.         mov esp, _esp_save;
  34.         mov _esp_save, eax;
  35.         //
  36.         pop edi;
  37.         pop esi;
  38.         pop ebp;
  39.         pop ebx;
  40.         //
  41.         ret;
  42.     };
  43. }
  44.  
  45. // basic mem clear
  46. static void _clearMem( void *src, int size )
  47. {
  48.     char *mem = (char*)src;
  49.     for ( int i=0; i<size; i++ )
  50.     {
  51.         mem[i] = 0x13;
  52.     }
  53. }
  54.  
  55. // basic mem copy
  56. static void _copy( void *src, void *dst, int size )
  57. {
  58.     //
  59.     char *a = (char*)src;
  60.     char *b = (char*)dst;
  61.     //
  62.     for ( int i=0; i<size; i++ )
  63.     {
  64.         //
  65.         b[i] = a[i];
  66.     }
  67. }
  68.  
  69. //
  70. struct sMicroThread
  71. {
  72.     int   id;
  73.     void *stack;
  74.     int   esp;
  75. };
  76.  
  77. //
  78. bool uThread_create( sMicroThread *thread, void (*func)(void) )
  79. {
  80.     // create the shared stack if it doesnt exist
  81.     if ( _sharedStack == NULL )
  82.     {
  83.         _sharedStack = new char[ c_shared_stack_size ];
  84.         _clearMem( _sharedStack, c_shared_stack_size );
  85.     }
  86.     // create the private thread stack
  87.     thread->stack = new char[ c_thread_stack_size ];
  88.     _clearMem( thread->stack, c_thread_stack_size );
  89.     //
  90.     int *a = (int*) offset( thread->stack, c_thread_stack_size );
  91.     // make room for the default stack
  92.     a -= 5;
  93.     a[0] = (int ) 0;
  94.     a[1] = (int ) 0;
  95.     a[2] = (int ) 0;
  96.     a[3] = (int ) 0;
  97.     // the return address is our microthread function
  98.     a[4] = (int ) func;
  99.     // prepare our default stack pointer location
  100.     thread->esp = (int)_sharedStack + c_shared_stack_size - (5 * 4);
  101.     //
  102.     return true;
  103. }
  104.  
  105. //
  106. void uThread_run( sMicroThread *thread )
  107. {
  108.     // find the starting copy point for the thread stack
  109.     void *copy_loc = offset( _sharedStack, c_shared_stack_size - c_thread_stack_size );
  110.     _copy( thread->stack, copy_loc, c_thread_stack_size );
  111.     // prep the stack pointer for the switch
  112.     _esp_save = thread->esp;
  113.     // switch over our stacks
  114.     _yield( );
  115.     //
  116.     thread->esp = _esp_save;
  117.     //
  118.     _copy( copy_loc, thread->stack, c_thread_stack_size );
  119. }
  120.  
  121. //
  122. void uThread_free( sMicroThread *thread )
  123. {
  124.     //
  125.     if ( thread->stack != NULL )
  126.     {
  127.         delete [] thread->stack;
  128.         thread->stack = NULL;
  129.     }
  130.     //
  131.     thread->esp = 0;
  132. }
  133.  
  134. //
  135. void _mthreadFunc( void )
  136. {
  137.     while ( true )
  138.     {
  139.         printf( "test" );
  140.         _yield( );
  141.     }
  142. }
  143.  
  144. //
  145. void dumpstack( sMicroThread *thread )
  146. {
  147.     //
  148.     printf( "stack dump\n{\n" );
  149.     //
  150.     unsigned char *data = (unsigned char*)thread->stack;
  151.     //
  152.     for ( int i=0; i<c_thread_stack_size; i++ )
  153.     {
  154.         //
  155.         if ( (i%16 == 0) && (i>0) )
  156.             putchar( '\n' );
  157.         //
  158.         int a = (data[i]) &  0xF;
  159.         int b = (data[i]) >> 4;
  160.         //
  161.         if ( b <  10 ) putchar( b + '0' );
  162.         if ( b >= 10 ) putchar( b + 'a' - 10 );
  163.         if ( a <  10 ) putchar( a + '0' );
  164.         if ( a >= 10 ) putchar( a + 'a' - 10 );
  165.         putchar( ' ' );
  166.     }
  167.     putchar( '\n' );
  168.     //
  169.     printf( "};\n" );
  170. }
  171.  
  172. //
  173. int main( void )
  174. {
  175.     //
  176.     sMicroThread thread = { 0, 0 };
  177.     uThread_create( &thread, _mthreadFunc );
  178.     //
  179.     dumpstack( &thread );
  180.     //
  181.     for ( int i=0; i<4; i++ )
  182.     {
  183.         uThread_run( &thread );
  184.     }
  185.     //
  186.     return 1;
  187. }
RAW Paste Data