summaryrefslogtreecommitdiff
path: root/pr/src/md/os2/os2thred.c
diff options
context:
space:
mode:
Diffstat (limited to 'pr/src/md/os2/os2thred.c')
-rw-r--r--pr/src/md/os2/os2thred.c152
1 files changed, 138 insertions, 14 deletions
diff --git a/pr/src/md/os2/os2thred.c b/pr/src/md/os2/os2thred.c
index d64ae0b9..45613573 100644
--- a/pr/src/md/os2/os2thred.c
+++ b/pr/src/md/os2/os2thred.c
@@ -43,6 +43,8 @@
#include <signal.h>
#endif
+#include <float.h>
+
/* --- globals ------------------------------------------------ */
_NSPR_TLS* pThreadLocalStorage = 0;
_PRInterruptTable _pr_interruptTable[] = { { 0 } };
@@ -88,19 +90,92 @@ _pr_SetThreadMDHandle(PRThread *thread)
thread->md.handle = ptib->tib_ptib2->tib2_ultid;
}
+/* On OS/2, some system function calls seem to change the FPU control word,
+ * such that we crash with a floating underflow exception. The FIX_FPU() call
+ * in jsnum.c does not always work, as sometimes FIX_FPU() is called BEFORE the
+ * OS/2 system call that horks the FPU control word. So, we set an exception
+ * handler that covers any floating point exceptions and resets the FPU CW to
+ * the required value.
+ */
+static ULONG
+_System OS2_FloatExcpHandler(PEXCEPTIONREPORTRECORD p1,
+ PEXCEPTIONREGISTRATIONRECORD p2,
+ PCONTEXTRECORD p3,
+ PVOID pv)
+{
+#ifdef DEBUG_pedemonte
+ printf("Entering exception handler; ExceptionNum = %x\n", p1->ExceptionNum);
+ switch(p1->ExceptionNum) {
+ case XCPT_FLOAT_DENORMAL_OPERAND:
+ printf("got XCPT_FLOAT_DENORMAL_OPERAND\n");
+ break;
+ case XCPT_FLOAT_DIVIDE_BY_ZERO:
+ printf("got XCPT_FLOAT_DIVIDE_BY_ZERO\n");
+ break;
+ case XCPT_FLOAT_INEXACT_RESULT:
+ printf("got XCPT_FLOAT_INEXACT_RESULT\n");
+ break;
+ case XCPT_FLOAT_INVALID_OPERATION:
+ printf("got XCPT_FLOAT_INVALID_OPERATION\n");
+ break;
+ case XCPT_FLOAT_OVERFLOW:
+ printf("got XCPT_FLOAT_OVERFLOW\n");
+ break;
+ case XCPT_FLOAT_STACK_CHECK:
+ printf("got XCPT_FLOAT_STACK_CHECK\n");
+ break;
+ case XCPT_FLOAT_UNDERFLOW:
+ printf("got XCPT_FLOAT_UNDERFLOW\n");
+ break;
+ }
+#endif
+
+ switch(p1->ExceptionNum) {
+ case XCPT_FLOAT_DENORMAL_OPERAND:
+ case XCPT_FLOAT_DIVIDE_BY_ZERO:
+ case XCPT_FLOAT_INEXACT_RESULT:
+ case XCPT_FLOAT_INVALID_OPERATION:
+ case XCPT_FLOAT_OVERFLOW:
+ case XCPT_FLOAT_STACK_CHECK:
+ case XCPT_FLOAT_UNDERFLOW:
+ {
+ unsigned cw = p3->ctx_env[0];
+ if ((cw & MCW_EM) != MCW_EM) {
+ /* Mask out all floating point exceptions */
+ p3->ctx_env[0] |= MCW_EM;
+ /* Following two lines set precision to 53 bit mantissa. See jsnum.c */
+ p3->ctx_env[0] &= ~MCW_PC;
+ p3->ctx_env[0] |= PC_53;
+ return XCPT_CONTINUE_EXECUTION;
+ }
+ }
+ }
+ return XCPT_CONTINUE_SEARCH;
+}
+
+PR_IMPLEMENT(void)
+PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg)
+{
+ /* setup the exception handler for the thread */
+ APIRET rv;
+ excpreg->ExceptionHandler = OS2_FloatExcpHandler;
+ excpreg->prev_structure = NULL;
+ rv = DosSetExceptionHandler(excpreg);
+ PR_ASSERT(rv == NO_ERROR);
+}
+
+PR_IMPLEMENT(void)
+PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg)
+{
+ /* unset exception handler */
+ APIRET rv = DosUnsetExceptionHandler(excpreg);
+ PR_ASSERT(rv == NO_ERROR);
+}
PRStatus
_PR_MD_INIT_THREAD(PRThread *thread)
{
APIRET rv;
-#ifdef XP_OS2_EMX
- /* disable SIGPIPE */
- struct sigaction sa;
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = 0;
- sigemptyset( &sa.sa_mask);
- sigaction( SIGPIPE, &sa, NULL);
-#endif
if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) {
_pr_SetThreadMDHandle(thread);
@@ -111,6 +186,29 @@ _PR_MD_INIT_THREAD(PRThread *thread)
return (rv == NO_ERROR) ? PR_SUCCESS : PR_FAILURE;
}
+typedef struct param_store
+{
+ void (*start)(void *);
+ PRThread* thread;
+} PARAMSTORE;
+
+/* This is a small intermediate function that sets/unsets the exception
+ handler before calling the initial thread function */
+static void
+ExcpStartFunc(void* arg)
+{
+ EXCEPTIONREGISTRATIONRECORD excpreg;
+ PARAMSTORE params, *pParams = arg;
+
+ PR_OS2_SetFloatExcpHandler(&excpreg);
+
+ params = *pParams;
+ PR_Free(pParams);
+ params.start(params.thread);
+
+ PR_OS2_UnsetFloatExcpHandler(&excpreg);
+}
+
PRStatus
_PR_MD_CREATE_THREAD(PRThread *thread,
void (*start)(void *),
@@ -119,15 +217,25 @@ _PR_MD_CREATE_THREAD(PRThread *thread,
PRThreadState state,
PRUint32 stackSize)
{
- thread->md.handle = thread->id = (TID) _beginthread(
- (void(* _Optlink)(void*))start,
- NULL,
- thread->stack->stackSize,
- thread);
+ PARAMSTORE* params = PR_Malloc(sizeof(PARAMSTORE));
+ params->start = start;
+ params->thread = thread;
+ thread->md.handle = thread->id = (TID) _beginthread(ExcpStartFunc,
+ NULL,
+ thread->stack->stackSize,
+ params);
if(thread->md.handle == -1) {
return PR_FAILURE;
}
- _PR_MD_SET_PRIORITY(&(thread->md), priority);
+
+ /*
+ * On OS/2, a thread is created with a thread priority of
+ * THREAD_PRIORITY_NORMAL
+ */
+
+ if (priority != PR_PRIORITY_NORMAL) {
+ _PR_MD_SET_PRIORITY(&(thread->md), priority);
+ }
return PR_SUCCESS;
}
@@ -270,3 +378,19 @@ _PR_MD_RESUME_THREAD(PRThread *thread)
}
}
+
+PRThread*
+_MD_CURRENT_THREAD(void)
+{
+ PRThread *thread;
+
+ thread = _MD_GET_ATTACHED_THREAD();
+
+ if (NULL == thread) {
+ thread = _PRI_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0);
+ }
+
+ PR_ASSERT(thread != NULL);
+ return thread;
+}
+