mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -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)
|
||||
|
||||
/* 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
|
||||
begin_context(ContextFunction *thread_func, void *data) {
|
||||
@ -89,7 +109,42 @@ switch_to_thread_context(struct ThreadContext *context) {
|
||||
|
||||
#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,
|
||||
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 */
|
||||
|
||||
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 */
|
||||
|
@ -30,61 +30,7 @@
|
||||
|
||||
#ifdef THREAD_SIMPLE_IMPL
|
||||
|
||||
#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;
|
||||
#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 */
|
||||
struct ThreadContext;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -112,6 +58,13 @@ void save_thread_context(struct ThreadContext *context,
|
||||
stack (or begin executing thread_func()). */
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
@ -45,6 +45,7 @@ ThreadSimpleImpl(Thread *parent_obj) :
|
||||
_stop_time = 0.0;
|
||||
_wake_time = 0.0;
|
||||
|
||||
_context = alloc_thread_context();
|
||||
_stack = NULL;
|
||||
_stack_size = 0;
|
||||
|
||||
@ -65,6 +66,8 @@ ThreadSimpleImpl::
|
||||
}
|
||||
nassertv(_status != TS_running);
|
||||
|
||||
free_thread_context(_context);
|
||||
|
||||
if (_stack != (void *)NULL) {
|
||||
memory_hook->mmap_free(_stack, _stack_size);
|
||||
}
|
||||
@ -136,7 +139,7 @@ start(ThreadPriority priority, bool joinable) {
|
||||
PyThreadState_Swap(_python_state);
|
||||
#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);
|
||||
return true;
|
||||
|
@ -125,7 +125,7 @@ private:
|
||||
// This records the time at which a sleeping thread should wake up.
|
||||
double _wake_time;
|
||||
|
||||
ThreadContext _context;
|
||||
ThreadContext *_context;
|
||||
unsigned char *_stack;
|
||||
size_t _stack_size;
|
||||
|
||||
|
@ -42,18 +42,6 @@ is_same_system_thread() const {
|
||||
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
|
||||
// Access: Public, Static
|
||||
|
@ -276,7 +276,7 @@ next_context() {
|
||||
}
|
||||
#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
|
||||
// the current thread.
|
||||
|
||||
@ -490,6 +490,18 @@ system_yield() {
|
||||
#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
|
||||
// Access: Private, Static
|
||||
@ -672,7 +684,7 @@ choose_next_context() {
|
||||
<< " blocked, " << _sleeping.size() << " sleeping)\n";
|
||||
}
|
||||
|
||||
switch_to_thread_context(&_current_thread->_context);
|
||||
switch_to_thread_context(_current_thread->_context);
|
||||
|
||||
// Shouldn't get here.
|
||||
nassertv(false);
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
static void system_sleep(double seconds);
|
||||
static void system_yield();
|
||||
|
||||
INLINE double get_current_time() const;
|
||||
double get_current_time() const;
|
||||
INLINE static ThreadSimpleManager *get_global_ptr();
|
||||
|
||||
void write_status(ostream &out) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user