|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "primpl.h" |
|
7 #include <setjmp.h> |
|
8 |
|
9 #if defined(HPUX_LW_TIMER) |
|
10 |
|
11 #include <machine/inline.h> |
|
12 #include <machine/clock.h> |
|
13 #include <unistd.h> |
|
14 #include <sys/time.h> |
|
15 #include <sys/pstat.h> |
|
16 |
|
17 int __lw_get_thread_times(int which, int64_t *sample, int64_t *time); |
|
18 |
|
19 static double msecond_per_itick; |
|
20 |
|
21 void _PR_HPUX_LW_IntervalInit(void) |
|
22 { |
|
23 struct pst_processor psp; |
|
24 int iticksperclktick, clk_tck; |
|
25 int rv; |
|
26 |
|
27 rv = pstat_getprocessor(&psp, sizeof(psp), 1, 0); |
|
28 PR_ASSERT(rv != -1); |
|
29 |
|
30 iticksperclktick = psp.psp_iticksperclktick; |
|
31 clk_tck = sysconf(_SC_CLK_TCK); |
|
32 msecond_per_itick = (1000.0)/(double)(iticksperclktick * clk_tck); |
|
33 } |
|
34 |
|
35 PRIntervalTime _PR_HPUX_LW_GetInterval(void) |
|
36 { |
|
37 int64_t time, sample; |
|
38 |
|
39 __lw_get_thread_times(1, &sample, &time); |
|
40 /* |
|
41 * Division is slower than float multiplication. |
|
42 * return (time / iticks_per_msecond); |
|
43 */ |
|
44 return (time * msecond_per_itick); |
|
45 } |
|
46 #endif /* HPUX_LW_TIMER */ |
|
47 |
|
48 #if !defined(PTHREADS_USER) |
|
49 |
|
50 void _MD_EarlyInit(void) |
|
51 { |
|
52 #ifndef _PR_PTHREADS |
|
53 /* |
|
54 * The following piece of code is taken from ns/nspr/src/md_HP-UX.c. |
|
55 * In the comment for revision 1.6, dated 1995/09/11 23:33:34, |
|
56 * robm says: |
|
57 * This version has some problems which need to be addressed. |
|
58 * First, intercept all system calls and prevent them from |
|
59 * executing the library code which performs stack switches |
|
60 * before normal system call invocation. In order for library |
|
61 * calls which make system calls to work (like stdio), however, |
|
62 * we must also allocate our own stack and switch the primordial |
|
63 * stack to use it. This isn't so bad, except that I fudged the |
|
64 * backtrace length when copying the old stack to the new one. |
|
65 * |
|
66 * This is the original comment of robm in the code: |
|
67 * XXXrobm Horrific. To avoid a problem with HP's system call |
|
68 * code, we allocate a new stack for the primordial thread and |
|
69 * use it. However, we don't know how far back the original stack |
|
70 * goes. We should create a routine that performs a backtrace and |
|
71 * finds out just how much we need to copy. As a temporary measure, |
|
72 * I just copy an arbitrary guess. |
|
73 * |
|
74 * In an email to servereng dated 2 Jan 1997, Mike Patnode (mikep) |
|
75 * suggests that this only needs to be done for HP-UX 9. |
|
76 */ |
|
77 #ifdef HPUX9 |
|
78 #define PIDOOMA_STACK_SIZE 524288 |
|
79 #define BACKTRACE_SIZE 8192 |
|
80 { |
|
81 jmp_buf jb; |
|
82 char *newstack; |
|
83 char *oldstack; |
|
84 |
|
85 if(!setjmp(jb)) { |
|
86 newstack = (char *) PR_MALLOC(PIDOOMA_STACK_SIZE); |
|
87 oldstack = (char *) (*(((int *) jb) + 1) - BACKTRACE_SIZE); |
|
88 memcpy(newstack, oldstack, BACKTRACE_SIZE); |
|
89 *(((int *) jb) + 1) = (int) (newstack + BACKTRACE_SIZE); |
|
90 longjmp(jb, 1); |
|
91 } |
|
92 } |
|
93 #endif /* HPUX9 */ |
|
94 #endif /* !_PR_PTHREADS */ |
|
95 } |
|
96 |
|
97 PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) |
|
98 { |
|
99 #ifndef _PR_PTHREADS |
|
100 if (isCurrent) { |
|
101 (void) setjmp(CONTEXT(t)); |
|
102 } |
|
103 *np = sizeof(CONTEXT(t)) / sizeof(PRWord); |
|
104 return (PRWord *) CONTEXT(t); |
|
105 #else |
|
106 *np = 0; |
|
107 return NULL; |
|
108 #endif |
|
109 } |
|
110 |
|
111 #ifndef _PR_PTHREADS |
|
112 void |
|
113 _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) |
|
114 { |
|
115 return; |
|
116 } |
|
117 |
|
118 PRStatus |
|
119 _MD_InitializeThread(PRThread *thread) |
|
120 { |
|
121 return PR_SUCCESS; |
|
122 } |
|
123 |
|
124 PRStatus |
|
125 _MD_WAIT(PRThread *thread, PRIntervalTime ticks) |
|
126 { |
|
127 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); |
|
128 _PR_MD_SWITCH_CONTEXT(thread); |
|
129 return PR_SUCCESS; |
|
130 } |
|
131 |
|
132 PRStatus |
|
133 _MD_WAKEUP_WAITER(PRThread *thread) |
|
134 { |
|
135 if (thread) { |
|
136 PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); |
|
137 } |
|
138 return PR_SUCCESS; |
|
139 } |
|
140 |
|
141 /* These functions should not be called for HP-UX */ |
|
142 void |
|
143 _MD_YIELD(void) |
|
144 { |
|
145 PR_NOT_REACHED("_MD_YIELD should not be called for HP-UX."); |
|
146 } |
|
147 |
|
148 PRStatus |
|
149 _MD_CREATE_THREAD( |
|
150 PRThread *thread, |
|
151 void (*start) (void *), |
|
152 PRThreadPriority priority, |
|
153 PRThreadScope scope, |
|
154 PRThreadState state, |
|
155 PRUint32 stackSize) |
|
156 { |
|
157 PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for HP-UX."); |
|
158 } |
|
159 #endif /* _PR_PTHREADS */ |
|
160 |
|
161 void |
|
162 _MD_suspend_thread(PRThread *thread) |
|
163 { |
|
164 #ifdef _PR_PTHREADS |
|
165 #endif |
|
166 } |
|
167 |
|
168 void |
|
169 _MD_resume_thread(PRThread *thread) |
|
170 { |
|
171 #ifdef _PR_PTHREADS |
|
172 #endif |
|
173 } |
|
174 #endif /* PTHREADS_USER */ |
|
175 |
|
176 /* |
|
177 * The HP version of strchr is buggy. It looks past the end of the |
|
178 * string and causes a segmentation fault when our (NSPR) version |
|
179 * of malloc is used. |
|
180 * |
|
181 * A better solution might be to put a cushion in our malloc just in |
|
182 * case HP's version of strchr somehow gets used instead of this one. |
|
183 */ |
|
184 char * |
|
185 strchr(const char *s, int c) |
|
186 { |
|
187 char ch; |
|
188 |
|
189 if (!s) { |
|
190 return NULL; |
|
191 } |
|
192 |
|
193 ch = (char) c; |
|
194 |
|
195 while ((*s) && ((*s) != ch)) { |
|
196 s++; |
|
197 } |
|
198 |
|
199 if ((*s) == ch) { |
|
200 return (char *) s; |
|
201 } |
|
202 |
|
203 return NULL; |
|
204 } |
|
205 |
|
206 /* |
|
207 * Implemementation of memcmp in HP-UX (verified on releases A.09.03, |
|
208 * A.09.07, and B.10.10) dumps core if called with: |
|
209 * 1. First operand with address = 1(mod 4). |
|
210 * 2. Size = 1(mod 4) |
|
211 * 3. Last byte of the second operand is the last byte of the page and |
|
212 * next page is not accessible(not mapped or protected) |
|
213 * Thus, using the following naive version (tons of optimizations are |
|
214 * possible;^) |
|
215 */ |
|
216 |
|
217 int memcmp(const void *s1, const void *s2, size_t n) |
|
218 { |
|
219 register unsigned char *p1 = (unsigned char *) s1, |
|
220 *p2 = (unsigned char *) s2; |
|
221 |
|
222 while (n-- > 0) { |
|
223 register int r = ((int) ((unsigned int) *p1)) |
|
224 - ((int) ((unsigned int) *p2)); |
|
225 if (r) return r; |
|
226 p1++; p2++; |
|
227 } |
|
228 return 0; |
|
229 } |