Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // written by Aidan Dodds (c) 2013
- // based on the micro threading article in Game Programming Gems 2
- //
- //
- #include <stdio.h>
- // number of full integers that can fit on the stack
- const int c_shared_stack_size = 1024 * 128; // 128k
- const int c_thread_stack_size = 1024; // 1k
- //
- #define NULL 0
- // here we allocate a large stack, that is shared amongst the running
- // micro code.
- static void *_sharedStack = NULL;
- static int _esp_save = 0;
- // offset X by Y bytes
- #define offset( X, Y ) ((char*)(X) + (Y))
- // our yield function
- static void __declspec( naked ) _yield( void )
- {
- __asm
- {
- push ebx;
- push ebp;
- push esi;
- push edi;
- //
- mov eax, esp;
- mov esp, _esp_save;
- mov _esp_save, eax;
- //
- pop edi;
- pop esi;
- pop ebp;
- pop ebx;
- //
- ret;
- };
- }
- // basic mem clear
- static void _clearMem( void *src, int size )
- {
- char *mem = (char*)src;
- for ( int i=0; i<size; i++ )
- {
- mem[i] = 0x13;
- }
- }
- // basic mem copy
- static void _copy( void *src, void *dst, int size )
- {
- //
- char *a = (char*)src;
- char *b = (char*)dst;
- //
- for ( int i=0; i<size; i++ )
- {
- //
- b[i] = a[i];
- }
- }
- //
- struct sMicroThread
- {
- int id;
- void *stack;
- int esp;
- };
- //
- bool uThread_create( sMicroThread *thread, void (*func)(void) )
- {
- // create the shared stack if it doesnt exist
- if ( _sharedStack == NULL )
- {
- _sharedStack = new char[ c_shared_stack_size ];
- _clearMem( _sharedStack, c_shared_stack_size );
- }
- // create the private thread stack
- thread->stack = new char[ c_thread_stack_size ];
- _clearMem( thread->stack, c_thread_stack_size );
- //
- int *a = (int*) offset( thread->stack, c_thread_stack_size );
- // make room for the default stack
- a -= 5;
- a[0] = (int ) 0;
- a[1] = (int ) 0;
- a[2] = (int ) 0;
- a[3] = (int ) 0;
- // the return address is our microthread function
- a[4] = (int ) func;
- // prepare our default stack pointer location
- thread->esp = (int)_sharedStack + c_shared_stack_size - (5 * 4);
- //
- return true;
- }
- //
- void uThread_run( sMicroThread *thread )
- {
- // find the starting copy point for the thread stack
- void *copy_loc = offset( _sharedStack, c_shared_stack_size - c_thread_stack_size );
- _copy( thread->stack, copy_loc, c_thread_stack_size );
- // prep the stack pointer for the switch
- _esp_save = thread->esp;
- // switch over our stacks
- _yield( );
- //
- thread->esp = _esp_save;
- //
- _copy( copy_loc, thread->stack, c_thread_stack_size );
- }
- //
- void uThread_free( sMicroThread *thread )
- {
- //
- if ( thread->stack != NULL )
- {
- delete [] thread->stack;
- thread->stack = NULL;
- }
- //
- thread->esp = 0;
- }
- //
- void _mthreadFunc( void )
- {
- while ( true )
- {
- printf( "test" );
- _yield( );
- }
- }
- //
- void dumpstack( sMicroThread *thread )
- {
- //
- printf( "stack dump\n{\n" );
- //
- unsigned char *data = (unsigned char*)thread->stack;
- //
- for ( int i=0; i<c_thread_stack_size; i++ )
- {
- //
- if ( (i%16 == 0) && (i>0) )
- putchar( '\n' );
- //
- int a = (data[i]) & 0xF;
- int b = (data[i]) >> 4;
- //
- if ( b < 10 ) putchar( b + '0' );
- if ( b >= 10 ) putchar( b + 'a' - 10 );
- if ( a < 10 ) putchar( a + '0' );
- if ( a >= 10 ) putchar( a + 'a' - 10 );
- putchar( ' ' );
- }
- putchar( '\n' );
- //
- printf( "};\n" );
- }
- //
- int main( void )
- {
- //
- sMicroThread thread = { 0, 0 };
- uThread_create( &thread, _mthreadFunc );
- //
- dumpstack( &thread );
- //
- for ( int i=0; i<4; i++ )
- {
- uThread_run( &thread );
- }
- //
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement