mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
osx ucontext issues popping up again. This should fix them for good.
This commit is contained in:
parent
90f0c9d671
commit
7bc69b76ed
@ -21,7 +21,27 @@
|
|||||||
|
|
||||||
#if defined(PHAVE_UCONTEXT_H)
|
#if defined(PHAVE_UCONTEXT_H)
|
||||||
|
|
||||||
/* The getcontext() / setcontext() implementation. Easy-peasy. */
|
#else /* PHAVE_UCONTEXT_H */
|
||||||
|
|
||||||
|
#endif /* PHAVE_UCONTEXT_H */
|
||||||
|
|
||||||
|
#if defined(PHAVE_UCONTEXT_H)
|
||||||
|
|
||||||
|
/* We'd prefer to use getcontext() / setcontext() to portably change
|
||||||
|
execution contexts within C code. That's what these library
|
||||||
|
functions are designed for. */
|
||||||
|
#include <ucontext.h>
|
||||||
|
|
||||||
|
struct ThreadContext {
|
||||||
|
ucontext_t _ucontext;
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// Due to a bug in OSX 10.5, the system ucontext_t declaration
|
||||||
|
// doesn't reserve enough space, and we need to reserve some
|
||||||
|
// additional space to make room.
|
||||||
|
#define EXTRA_PADDING_SIZE 4096
|
||||||
|
char _extra_padding[EXTRA_PADDING_SIZE];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
begin_context(ContextFunction *thread_func, void *data) {
|
begin_context(ContextFunction *thread_func, void *data) {
|
||||||
@ -89,7 +109,42 @@ switch_to_thread_context(struct ThreadContext *context) {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* The setjmp() / longjmp() implementation. A bit hackier. */
|
/* Unfortunately, setcontext() is not defined everywhere (even though
|
||||||
|
it claims to be adopted by Posix). So we have to fall back to
|
||||||
|
setjmp() / longjmp() in its absence. This is a hackier solution. */
|
||||||
|
|
||||||
|
#if defined(_M_IX86) || defined(__i386__)
|
||||||
|
/* Maybe we can implement our own setjmp/longjmp in assembly code.
|
||||||
|
This will be safer than the system version, since who knows what
|
||||||
|
that one's really doing? */
|
||||||
|
|
||||||
|
typedef int cs_jmp_buf[33];
|
||||||
|
|
||||||
|
#define CS_JB_SP 4
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Fall back to the system implmentation of setjmp/longjmp. */
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
typedef jmp_buf cs_jmp_buf;
|
||||||
|
#define cs_setjmp setjmp
|
||||||
|
#define cs_longjmp(buf) longjmp(buf, 1)
|
||||||
|
|
||||||
|
#ifdef JB_SP
|
||||||
|
#define CS_JB_SP JB_SP
|
||||||
|
|
||||||
|
#elif defined(__ppc__)
|
||||||
|
/* This was determined experimentally through test_setjmp. */
|
||||||
|
#define CS_JB_SP 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __i386__ */
|
||||||
|
|
||||||
|
struct ThreadContext {
|
||||||
|
cs_jmp_buf _jmp_context;
|
||||||
|
};
|
||||||
|
|
||||||
/* The approach is: hack our way onto the new stack pointer right now,
|
/* The approach is: hack our way onto the new stack pointer right now,
|
||||||
then call setjmp() to record that stack pointer in the
|
then call setjmp() to record that stack pointer in the
|
||||||
@ -333,4 +388,43 @@ switch_to_thread_context(struct ThreadContext *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* PHAVE_UCONTEXT_H */
|
#endif /* PHAVE_UCONTEXT_H */
|
||||||
|
|
||||||
|
struct ThreadContext *
|
||||||
|
alloc_thread_context() {
|
||||||
|
struct ThreadContext *context =
|
||||||
|
(struct ThreadContext *)malloc(sizeof(struct ThreadContext));
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(_DEBUG)
|
||||||
|
{
|
||||||
|
int p;
|
||||||
|
// Pre-fill the extra_padding with bytes that we can recognize
|
||||||
|
// later.
|
||||||
|
for (p = 0; p < EXTRA_PADDING_SIZE; ++p) {
|
||||||
|
context->_extra_padding[p] = (p & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // __APPLE__
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_thread_context(struct ThreadContext *context) {
|
||||||
|
#if defined(__APPLE__) && defined(_DEBUG)
|
||||||
|
{
|
||||||
|
// Because of the OSX 10.5 bug, we anticipate that the extra_padding
|
||||||
|
// may have been filled in with junk. Confirm this.
|
||||||
|
int p = EXTRA_PADDING_SIZE;
|
||||||
|
while (p > 0) {
|
||||||
|
--p;
|
||||||
|
if (context->_extra_padding[p] != (char)(p & 0xff)) {
|
||||||
|
fprintf(stderr, "Context was mangled at byte %d: %d!\n", p, context->_extra_padding[p]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // __APPLE__
|
||||||
|
free(context);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* THREAD_SIMPLE_IMPL */
|
#endif /* THREAD_SIMPLE_IMPL */
|
||||||
|
@ -30,61 +30,7 @@
|
|||||||
|
|
||||||
#ifdef THREAD_SIMPLE_IMPL
|
#ifdef THREAD_SIMPLE_IMPL
|
||||||
|
|
||||||
#if defined(PHAVE_UCONTEXT_H)
|
struct ThreadContext;
|
||||||
/* We'd prefer to use getcontext() / setcontext() to portably change
|
|
||||||
execution contexts within C code. That's what these library
|
|
||||||
functions are designed for. */
|
|
||||||
#include <ucontext.h>
|
|
||||||
|
|
||||||
struct ThreadContext {
|
|
||||||
ucontext_t _ucontext;
|
|
||||||
#if defined(__APPLE__) && defined(_STRUCT_MCONTEXT)
|
|
||||||
// Due to a bug in OSX 10.5, the system ucontext_t declaration
|
|
||||||
// doesn't reserve enough space, and we need to reserve some
|
|
||||||
// additional space to make room.
|
|
||||||
_STRUCT_MCONTEXT _extra_padding;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#else /* PHAVE_UCONTEXT_H */
|
|
||||||
/* Unfortunately, setcontext() is not defined everywhere (even though
|
|
||||||
it claims to be adopted by Posix). So we have to fall back to
|
|
||||||
setjmp() / longjmp() in its absence. This is a hackier solution. */
|
|
||||||
|
|
||||||
#if defined(_M_IX86) || defined(__i386__)
|
|
||||||
/* Maybe we can implement our own setjmp/longjmp in assembly code.
|
|
||||||
This will be safer than the system version, since who knows what
|
|
||||||
that one's really doing? */
|
|
||||||
|
|
||||||
typedef int cs_jmp_buf[33];
|
|
||||||
|
|
||||||
#define CS_JB_SP 4
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Fall back to the system implmentation of setjmp/longjmp. */
|
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
typedef jmp_buf cs_jmp_buf;
|
|
||||||
#define cs_setjmp setjmp
|
|
||||||
#define cs_longjmp(buf) longjmp(buf, 1)
|
|
||||||
|
|
||||||
#ifdef JB_SP
|
|
||||||
#define CS_JB_SP JB_SP
|
|
||||||
|
|
||||||
#elif defined(__ppc__)
|
|
||||||
/* This was determined experimentally through test_setjmp. */
|
|
||||||
#define CS_JB_SP 0
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* __i386__ */
|
|
||||||
|
|
||||||
struct ThreadContext {
|
|
||||||
cs_jmp_buf _jmp_context;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* PHAVE_UCONTEXT_H */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -112,6 +58,13 @@ void save_thread_context(struct ThreadContext *context,
|
|||||||
stack (or begin executing thread_func()). */
|
stack (or begin executing thread_func()). */
|
||||||
void switch_to_thread_context(struct ThreadContext *context);
|
void switch_to_thread_context(struct ThreadContext *context);
|
||||||
|
|
||||||
|
/* Use this pair of functions to transparently allocate and destroy an
|
||||||
|
opaque ThreadContext object of the appropriate size. These
|
||||||
|
functions only allocate memory; they do not initialize the values
|
||||||
|
of the context (see init_thread_context(), above, for that). */
|
||||||
|
struct ThreadContext *alloc_thread_context();
|
||||||
|
void free_thread_context(struct ThreadContext *context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +45,7 @@ ThreadSimpleImpl(Thread *parent_obj) :
|
|||||||
_stop_time = 0.0;
|
_stop_time = 0.0;
|
||||||
_wake_time = 0.0;
|
_wake_time = 0.0;
|
||||||
|
|
||||||
|
_context = alloc_thread_context();
|
||||||
_stack = NULL;
|
_stack = NULL;
|
||||||
_stack_size = 0;
|
_stack_size = 0;
|
||||||
|
|
||||||
@ -65,6 +66,8 @@ ThreadSimpleImpl::
|
|||||||
}
|
}
|
||||||
nassertv(_status != TS_running);
|
nassertv(_status != TS_running);
|
||||||
|
|
||||||
|
free_thread_context(_context);
|
||||||
|
|
||||||
if (_stack != (void *)NULL) {
|
if (_stack != (void *)NULL) {
|
||||||
memory_hook->mmap_free(_stack, _stack_size);
|
memory_hook->mmap_free(_stack, _stack_size);
|
||||||
}
|
}
|
||||||
@ -136,7 +139,7 @@ start(ThreadPriority priority, bool joinable) {
|
|||||||
PyThreadState_Swap(_python_state);
|
PyThreadState_Swap(_python_state);
|
||||||
#endif // HAVE_PYTHON
|
#endif // HAVE_PYTHON
|
||||||
|
|
||||||
init_thread_context(&_context, _stack, _stack_size, st_begin_thread, this);
|
init_thread_context(_context, _stack, _stack_size, st_begin_thread, this);
|
||||||
|
|
||||||
_manager->enqueue_ready(this, false);
|
_manager->enqueue_ready(this, false);
|
||||||
return true;
|
return true;
|
||||||
|
@ -125,7 +125,7 @@ private:
|
|||||||
// This records the time at which a sleeping thread should wake up.
|
// This records the time at which a sleeping thread should wake up.
|
||||||
double _wake_time;
|
double _wake_time;
|
||||||
|
|
||||||
ThreadContext _context;
|
ThreadContext *_context;
|
||||||
unsigned char *_stack;
|
unsigned char *_stack;
|
||||||
size_t _stack_size;
|
size_t _stack_size;
|
||||||
|
|
||||||
|
@ -42,18 +42,6 @@ is_same_system_thread() const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: ThreadSimpleManager::get_current_time
|
|
||||||
// Access: Public
|
|
||||||
// Description: Returns elapsed time in seconds from some undefined
|
|
||||||
// epoch, via whatever clock the manager is using for
|
|
||||||
// all thread timing.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE double ThreadSimpleManager::
|
|
||||||
get_current_time() const {
|
|
||||||
return _clock->get_short_raw_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: ThreadSimpleManager::get_global_ptr
|
// Function: ThreadSimpleManager::get_global_ptr
|
||||||
// Access: Public, Static
|
// Access: Public, Static
|
||||||
|
@ -276,7 +276,7 @@ next_context() {
|
|||||||
}
|
}
|
||||||
#endif // DO_PSTATS
|
#endif // DO_PSTATS
|
||||||
|
|
||||||
save_thread_context(&_current_thread->_context, st_choose_next_context, this);
|
save_thread_context(_current_thread->_context, st_choose_next_context, this);
|
||||||
// Pass 2: we have returned into the context, and are now resuming
|
// Pass 2: we have returned into the context, and are now resuming
|
||||||
// the current thread.
|
// the current thread.
|
||||||
|
|
||||||
@ -490,6 +490,18 @@ system_yield() {
|
|||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: ThreadSimpleManager::get_current_time
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns elapsed time in seconds from some undefined
|
||||||
|
// epoch, via whatever clock the manager is using for
|
||||||
|
// all thread timing.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
double ThreadSimpleManager::
|
||||||
|
get_current_time() const {
|
||||||
|
return _clock->get_short_raw_time();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: ThreadSimpleManager::init_pointers
|
// Function: ThreadSimpleManager::init_pointers
|
||||||
// Access: Private, Static
|
// Access: Private, Static
|
||||||
@ -672,7 +684,7 @@ choose_next_context() {
|
|||||||
<< " blocked, " << _sleeping.size() << " sleeping)\n";
|
<< " blocked, " << _sleeping.size() << " sleeping)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_to_thread_context(&_current_thread->_context);
|
switch_to_thread_context(_current_thread->_context);
|
||||||
|
|
||||||
// Shouldn't get here.
|
// Shouldn't get here.
|
||||||
nassertv(false);
|
nassertv(false);
|
||||||
|
@ -76,7 +76,7 @@ public:
|
|||||||
static void system_sleep(double seconds);
|
static void system_sleep(double seconds);
|
||||||
static void system_yield();
|
static void system_yield();
|
||||||
|
|
||||||
INLINE double get_current_time() const;
|
double get_current_time() const;
|
||||||
INLINE static ThreadSimpleManager *get_global_ptr();
|
INLINE static ThreadSimpleManager *get_global_ptr();
|
||||||
|
|
||||||
void write_status(ostream &out) const;
|
void write_status(ostream &out) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user