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