simple_threads for win32

This commit is contained in:
David Rose 2007-06-22 18:15:51 +00:00
parent bebefc5563
commit 9ad516cea2
3 changed files with 89 additions and 26 deletions

View File

@ -89,18 +89,62 @@ switch_to_thread_context(struct ThreadContext *context) {
_jmp_context. Then restore back to the original stack pointer. */ _jmp_context. Then restore back to the original stack pointer. */
#if defined(_M_IX86) #if defined(_M_IX86)
/* Here is own own implementation of setjmp and longjmp for I386, via /* Here is our own implementation of setjmp and longjmp for I386, via
Windows syntax. */ Windows syntax. */
int cs_setjmp(cs_jmp_buf env); /* warning C4731: frame pointer register 'ebp' modified by inline assembly code */
void cs_longjmp(cs_jmp_buf env); #pragma warning(disable:4731)
int
cs_setjmp(cs_jmp_buf env) {
__asm {
pop ebp; /* Restore the frame pointer that the compiler pushed */
pop edx; /* edx = return address */
pop eax; /* eax = &env */
push eax; /* keep &env on the stack; the caller will remove it */
mov [eax + 0], ebx;
mov [eax + 4], edi;
mov [eax + 8], esi;
mov [eax + 12], ebp;
mov [eax + 16], esp;
mov [eax + 20], edx;
fnsave [eax + 24]; /* save floating-point state */
xor eax,eax; /* return 0: pass 1 return */
jmp edx; /* this works like ret */
}
}
void
cs_longjmp(cs_jmp_buf env) {
_asm {
mov eax, env;
mov ebx, [eax + 0];
mov edi, [eax + 4];
mov esi, [eax + 8];
mov ebp, [eax + 12];
mov esp, [eax + 16];
mov edx, [eax + 20];
frstor [eax + 24]; /* restore floating-point state */
mov eax, 1; /* return 1 from setjmp: pass 2 return */
jmp edx; /* return from above setjmp call */
}
}
#elif defined(__i386__) #elif defined(__i386__)
/* Here is own own implementation of setjmp and longjmp for I386, via /* Here is our own implementation of setjmp and longjmp for I386, via
GNU syntax. */ GNU syntax. */
#if defined(IS_LINUX) #if defined(IS_LINUX)
/* On Linux, the underscores are not implicit. */ /* On Linux, the leading underscores are not implicitly added for C
function names. */
#define cs_setjmp _cs_setjmp #define cs_setjmp _cs_setjmp
#define cs_longjmp _cs_longjmp #define cs_longjmp _cs_longjmp
#endif #endif
@ -113,27 +157,33 @@ __asm__
"popl %edx\n" "popl %edx\n"
"popl %eax\n" "popl %eax\n"
"pushl %eax\n" "pushl %eax\n"
"movl %ebx,0(%eax)\n"
"movl %edi,4(%eax)\n" "movl %ebx, 0(%eax)\n"
"movl %esi,8(%eax)\n" "movl %edi, 4(%eax)\n"
"movl %ebp,12(%eax)\n" "movl %esi, 8(%eax)\n"
"movl %esp,16(%eax)\n" "movl %ebp, 12(%eax)\n"
"movl %edx,20(%eax)\n" "movl %esp, 16(%eax)\n"
"movl %edx, 20(%eax)\n"
"fnsave 24(%eax)\n" "fnsave 24(%eax)\n"
"xorl %eax,%eax\n"
"xorl %eax, %eax\n"
"jmp *%edx\n"); "jmp *%edx\n");
__asm__ __asm__
("_cs_longjmp:\n" ("_cs_longjmp:\n"
"popl %edx\n" "popl %edx\n"
"popl %eax\n" "popl %eax\n"
"movl 0(%eax),%ebx\n"
"movl 4(%eax),%edi\n" "movl 0(%eax), %ebx\n"
"movl 8(%eax),%esi\n" "movl 4(%eax), %edi\n"
"movl 12(%eax),%ebp\n" "movl 8(%eax), %esi\n"
"movl 16(%eax),%esp\n" "movl 12(%eax), %ebp\n"
"movl 20(%eax),%edx\n" "movl 16(%eax), %esp\n"
"movl 20(%eax), %edx\n"
"frstor 24(%eax)\n" "frstor 24(%eax)\n"
"mov $1,%eax\n" "mov $1,%eax\n"
"jmp *%edx\n"); "jmp *%edx\n");
@ -149,11 +199,6 @@ __asm__
this directory. */ this directory. */
#define CS_JB_SP 9 #define CS_JB_SP 9
#elif defined(WIN32)
/* We have determined this value empirically, via test_setjmp.cxx in
this directory. */
#define CS_JB_SP 4
#endif #endif
#endif /* CS_JB_SP */ #endif /* CS_JB_SP */

View File

@ -49,7 +49,7 @@ struct ThreadContext {
it claims to be adopted by Posix). So we have to fall back to it claims to be adopted by Posix). So we have to fall back to
setjmp() / longjmp() in its absence. This is a hackier solution. */ setjmp() / longjmp() in its absence. This is a hackier solution. */
#if defined(__i386__) #if defined(_M_IX86) || defined(__i386__)
/* Maybe we can implement our own setjmp/longjmp in assembly code. /* Maybe we can implement our own setjmp/longjmp in assembly code.
This will be safe than the system version, since who knows what This will be safe than the system version, since who knows what
that one's really doing? */ that one's really doing? */

View File

@ -24,6 +24,11 @@
#include "threadSimpleManager.h" #include "threadSimpleManager.h"
#include "thread.h" #include "thread.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
ThreadSimpleImpl *volatile ThreadSimpleImpl::_st_this; ThreadSimpleImpl *volatile ThreadSimpleImpl::_st_this;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -45,7 +50,14 @@ ThreadSimpleImpl(Thread *parent_obj) :
// We allocate the requested stack size, plus an additional tiny // We allocate the requested stack size, plus an additional tiny
// buffer to allow room for the code to access values on the // buffer to allow room for the code to access values on the
// currently executing stack frame at the time we switch the stack. // currently executing stack frame at the time we switch the stack.
_stack = (unsigned char *)malloc(_stack_size + 0x100); size_t alloc_size = _stack_size + 0x100;
#ifdef WIN32
_stack = (unsigned char *)VirtualAlloc(NULL, alloc_size, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
#else
_stack = (unsigned char *)malloc(alloc_size);
#endif
// Save this pointer for convenience. // Save this pointer for convenience.
_manager = ThreadSimpleManager::get_global_ptr(); _manager = ThreadSimpleManager::get_global_ptr();
@ -64,7 +76,13 @@ ThreadSimpleImpl::
} }
nassertv(_status != S_running); nassertv(_status != S_running);
free(_stack); if (_stack != (void *)NULL) {
#ifdef WIN32
VirtualFree(_stack, 0, MEM_RELEASE);
#else
free(_stack);
#endif
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////