michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "primpl.h" michael@0: #include michael@0: michael@0: #if defined(HPUX_LW_TIMER) michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: int __lw_get_thread_times(int which, int64_t *sample, int64_t *time); michael@0: michael@0: static double msecond_per_itick; michael@0: michael@0: void _PR_HPUX_LW_IntervalInit(void) michael@0: { michael@0: struct pst_processor psp; michael@0: int iticksperclktick, clk_tck; michael@0: int rv; michael@0: michael@0: rv = pstat_getprocessor(&psp, sizeof(psp), 1, 0); michael@0: PR_ASSERT(rv != -1); michael@0: michael@0: iticksperclktick = psp.psp_iticksperclktick; michael@0: clk_tck = sysconf(_SC_CLK_TCK); michael@0: msecond_per_itick = (1000.0)/(double)(iticksperclktick * clk_tck); michael@0: } michael@0: michael@0: PRIntervalTime _PR_HPUX_LW_GetInterval(void) michael@0: { michael@0: int64_t time, sample; michael@0: michael@0: __lw_get_thread_times(1, &sample, &time); michael@0: /* michael@0: * Division is slower than float multiplication. michael@0: * return (time / iticks_per_msecond); michael@0: */ michael@0: return (time * msecond_per_itick); michael@0: } michael@0: #endif /* HPUX_LW_TIMER */ michael@0: michael@0: #if !defined(PTHREADS_USER) michael@0: michael@0: void _MD_EarlyInit(void) michael@0: { michael@0: #ifndef _PR_PTHREADS michael@0: /* michael@0: * The following piece of code is taken from ns/nspr/src/md_HP-UX.c. michael@0: * In the comment for revision 1.6, dated 1995/09/11 23:33:34, michael@0: * robm says: michael@0: * This version has some problems which need to be addressed. michael@0: * First, intercept all system calls and prevent them from michael@0: * executing the library code which performs stack switches michael@0: * before normal system call invocation. In order for library michael@0: * calls which make system calls to work (like stdio), however, michael@0: * we must also allocate our own stack and switch the primordial michael@0: * stack to use it. This isn't so bad, except that I fudged the michael@0: * backtrace length when copying the old stack to the new one. michael@0: * michael@0: * This is the original comment of robm in the code: michael@0: * XXXrobm Horrific. To avoid a problem with HP's system call michael@0: * code, we allocate a new stack for the primordial thread and michael@0: * use it. However, we don't know how far back the original stack michael@0: * goes. We should create a routine that performs a backtrace and michael@0: * finds out just how much we need to copy. As a temporary measure, michael@0: * I just copy an arbitrary guess. michael@0: * michael@0: * In an email to servereng dated 2 Jan 1997, Mike Patnode (mikep) michael@0: * suggests that this only needs to be done for HP-UX 9. michael@0: */ michael@0: #ifdef HPUX9 michael@0: #define PIDOOMA_STACK_SIZE 524288 michael@0: #define BACKTRACE_SIZE 8192 michael@0: { michael@0: jmp_buf jb; michael@0: char *newstack; michael@0: char *oldstack; michael@0: michael@0: if(!setjmp(jb)) { michael@0: newstack = (char *) PR_MALLOC(PIDOOMA_STACK_SIZE); michael@0: oldstack = (char *) (*(((int *) jb) + 1) - BACKTRACE_SIZE); michael@0: memcpy(newstack, oldstack, BACKTRACE_SIZE); michael@0: *(((int *) jb) + 1) = (int) (newstack + BACKTRACE_SIZE); michael@0: longjmp(jb, 1); michael@0: } michael@0: } michael@0: #endif /* HPUX9 */ michael@0: #endif /* !_PR_PTHREADS */ michael@0: } michael@0: michael@0: PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) michael@0: { michael@0: #ifndef _PR_PTHREADS michael@0: if (isCurrent) { michael@0: (void) setjmp(CONTEXT(t)); michael@0: } michael@0: *np = sizeof(CONTEXT(t)) / sizeof(PRWord); michael@0: return (PRWord *) CONTEXT(t); michael@0: #else michael@0: *np = 0; michael@0: return NULL; michael@0: #endif michael@0: } michael@0: michael@0: #ifndef _PR_PTHREADS michael@0: void michael@0: _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) michael@0: { michael@0: return; michael@0: } michael@0: michael@0: PRStatus michael@0: _MD_InitializeThread(PRThread *thread) michael@0: { michael@0: return PR_SUCCESS; michael@0: } michael@0: michael@0: PRStatus michael@0: _MD_WAIT(PRThread *thread, PRIntervalTime ticks) michael@0: { michael@0: PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); michael@0: _PR_MD_SWITCH_CONTEXT(thread); michael@0: return PR_SUCCESS; michael@0: } michael@0: michael@0: PRStatus michael@0: _MD_WAKEUP_WAITER(PRThread *thread) michael@0: { michael@0: if (thread) { michael@0: PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); michael@0: } michael@0: return PR_SUCCESS; michael@0: } michael@0: michael@0: /* These functions should not be called for HP-UX */ michael@0: void michael@0: _MD_YIELD(void) michael@0: { michael@0: PR_NOT_REACHED("_MD_YIELD should not be called for HP-UX."); michael@0: } michael@0: michael@0: PRStatus michael@0: _MD_CREATE_THREAD( michael@0: PRThread *thread, michael@0: void (*start) (void *), michael@0: PRThreadPriority priority, michael@0: PRThreadScope scope, michael@0: PRThreadState state, michael@0: PRUint32 stackSize) michael@0: { michael@0: PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for HP-UX."); michael@0: } michael@0: #endif /* _PR_PTHREADS */ michael@0: michael@0: void michael@0: _MD_suspend_thread(PRThread *thread) michael@0: { michael@0: #ifdef _PR_PTHREADS michael@0: #endif michael@0: } michael@0: michael@0: void michael@0: _MD_resume_thread(PRThread *thread) michael@0: { michael@0: #ifdef _PR_PTHREADS michael@0: #endif michael@0: } michael@0: #endif /* PTHREADS_USER */ michael@0: michael@0: /* michael@0: * The HP version of strchr is buggy. It looks past the end of the michael@0: * string and causes a segmentation fault when our (NSPR) version michael@0: * of malloc is used. michael@0: * michael@0: * A better solution might be to put a cushion in our malloc just in michael@0: * case HP's version of strchr somehow gets used instead of this one. michael@0: */ michael@0: char * michael@0: strchr(const char *s, int c) michael@0: { michael@0: char ch; michael@0: michael@0: if (!s) { michael@0: return NULL; michael@0: } michael@0: michael@0: ch = (char) c; michael@0: michael@0: while ((*s) && ((*s) != ch)) { michael@0: s++; michael@0: } michael@0: michael@0: if ((*s) == ch) { michael@0: return (char *) s; michael@0: } michael@0: michael@0: return NULL; michael@0: } michael@0: michael@0: /* michael@0: * Implemementation of memcmp in HP-UX (verified on releases A.09.03, michael@0: * A.09.07, and B.10.10) dumps core if called with: michael@0: * 1. First operand with address = 1(mod 4). michael@0: * 2. Size = 1(mod 4) michael@0: * 3. Last byte of the second operand is the last byte of the page and michael@0: * next page is not accessible(not mapped or protected) michael@0: * Thus, using the following naive version (tons of optimizations are michael@0: * possible;^) michael@0: */ michael@0: michael@0: int memcmp(const void *s1, const void *s2, size_t n) michael@0: { michael@0: register unsigned char *p1 = (unsigned char *) s1, michael@0: *p2 = (unsigned char *) s2; michael@0: michael@0: while (n-- > 0) { michael@0: register int r = ((int) ((unsigned int) *p1)) michael@0: - ((int) ((unsigned int) *p2)); michael@0: if (r) return r; michael@0: p1++; p2++; michael@0: } michael@0: return 0; michael@0: }