Bug 1792034 [wpt PR 36019] - Make location.search always expect UTF-8, a=testonly
[gecko.git] / nsprpub / pr / src / misc / prthinfo.c
blob14602df0be45d78bdb9908b38bfd8ddeb2229c05
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/. */
6 #include "prlog.h"
7 #include "prthread.h"
8 #include "private/pprthred.h"
9 #include "primpl.h"
11 PR_IMPLEMENT(PRWord *)
12 PR_GetGCRegisters(PRThread *t, int isCurrent, int *np)
14 return _MD_HomeGCRegisters(t, isCurrent, np);
17 PR_IMPLEMENT(PRStatus)
18 PR_ThreadScanStackPointers(PRThread* t,
19 PRScanStackFun scanFun, void* scanClosure)
21 PRThread* current = PR_GetCurrentThread();
22 PRWord *sp, *esp, *p0;
23 int n;
24 void **ptd;
25 PRStatus status;
26 PRUint32 index;
27 int stack_end;
30 ** Store the thread's registers in the thread structure so the GC
31 ** can scan them. Then scan them.
33 p0 = _MD_HomeGCRegisters(t, t == current, &n);
34 status = scanFun(t, (void**)p0, n, scanClosure);
35 if (status != PR_SUCCESS) {
36 return status;
39 /* Scan the C stack for pointers into the GC heap */
40 #if defined(XP_PC) && defined(WIN16)
42 ** Under WIN16, the stack of the current thread is always mapped into
43 ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan
44 ** the "task stack". Otherwise, scan the "cached stack" of the inactive
45 ** thread...
47 if (t == current) {
48 sp = (PRWord*) &stack_end;
49 esp = (PRWord*) _pr_top_of_task_stack;
51 PR_ASSERT(sp <= esp);
52 } else {
53 sp = (PRWord*) PR_GetSP(t);
54 esp = (PRWord*) t->stack->stackTop;
56 PR_ASSERT((t->stack->stackSize == 0) ||
57 ((sp > (PRWord*)t->stack->stackBottom) &&
58 (sp <= (PRWord*)t->stack->stackTop)));
60 #else /* ! WIN16 */
61 #ifdef HAVE_STACK_GROWING_UP
62 if (t == current) {
63 esp = (PRWord*) &stack_end;
64 } else {
65 esp = (PRWord*) PR_GetSP(t);
67 sp = (PRWord*) t->stack->stackTop;
68 if (t->stack->stackSize) {
69 PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
70 (esp < (PRWord*)t->stack->stackBottom));
72 #else /* ! HAVE_STACK_GROWING_UP */
73 if (t == current) {
74 sp = (PRWord*) &stack_end;
75 } else {
76 sp = (PRWord*) PR_GetSP(t);
78 esp = (PRWord*) t->stack->stackTop;
79 if (t->stack->stackSize) {
80 PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
81 (sp < (PRWord*)t->stack->stackTop));
83 #endif /* ! HAVE_STACK_GROWING_UP */
84 #endif /* ! WIN16 */
86 #if defined(WIN16)
88 prword_t scan;
89 prword_t limit;
91 scan = (prword_t) sp;
92 limit = (prword_t) esp;
93 while (scan < limit) {
94 prword_t *test;
96 test = *((prword_t **)scan);
97 status = scanFun(t, (void**)&test, 1, scanClosure);
98 if (status != PR_SUCCESS) {
99 return status;
101 scan += sizeof(char);
104 #else
105 if (sp < esp) {
106 status = scanFun(t, (void**)sp, esp - sp, scanClosure);
107 if (status != PR_SUCCESS) {
108 return status;
111 #endif
114 ** Mark all of the per-thread-data items attached to this thread
116 ** The execution environment better be accounted for otherwise it
117 ** will be collected
119 status = scanFun(t, (void**)&t->environment, 1, scanClosure);
120 if (status != PR_SUCCESS) {
121 return status;
124 /* if thread is not allocated on stack, this is redundant. */
125 ptd = t->privateData;
126 for (index = 0; index < t->tpdLength; index++, ptd++) {
127 status = scanFun(t, (void**)ptd, 1, scanClosure);
128 if (status != PR_SUCCESS) {
129 return status;
133 return PR_SUCCESS;
136 /* transducer for PR_EnumerateThreads */
137 typedef struct PRScanStackData {
138 PRScanStackFun scanFun;
139 void* scanClosure;
140 } PRScanStackData;
142 static PRStatus PR_CALLBACK
143 pr_ScanStack(PRThread* t, int i, void* arg)
145 PRScanStackData* data = (PRScanStackData*)arg;
146 return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure);
149 PR_IMPLEMENT(PRStatus)
150 PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure)
152 PRScanStackData data;
153 data.scanFun = scanFun;
154 data.scanClosure = scanClosure;
155 return PR_EnumerateThreads(pr_ScanStack, &data);
158 PR_IMPLEMENT(PRUword)
159 PR_GetStackSpaceLeft(PRThread* t)
161 PRThread *current = PR_GetCurrentThread();
162 PRWord *sp, *esp;
163 int stack_end;
165 #if defined(WIN16)
167 ** Under WIN16, the stack of the current thread is always mapped into
168 ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan
169 ** the "task stack". Otherwise, scan the "cached stack" of the inactive
170 ** thread...
172 if (t == current) {
173 sp = (PRWord*) &stack_end;
174 esp = (PRWord*) _pr_top_of_task_stack;
176 PR_ASSERT(sp <= esp);
177 } else {
178 sp = (PRWord*) PR_GetSP(t);
179 esp = (PRWord*) t->stack->stackTop;
181 PR_ASSERT((t->stack->stackSize == 0) ||
182 ((sp > (PRWord*)t->stack->stackBottom) &&
183 (sp <= (PRWord*)t->stack->stackTop)));
185 #else /* ! WIN16 */
186 #ifdef HAVE_STACK_GROWING_UP
187 if (t == current) {
188 esp = (PRWord*) &stack_end;
189 } else {
190 esp = (PRWord*) PR_GetSP(t);
192 sp = (PRWord*) t->stack->stackTop;
193 if (t->stack->stackSize) {
194 PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
195 (esp < (PRWord*)t->stack->stackBottom));
197 #else /* ! HAVE_STACK_GROWING_UP */
198 if (t == current) {
199 sp = (PRWord*) &stack_end;
200 } else {
201 sp = (PRWord*) PR_GetSP(t);
203 esp = (PRWord*) t->stack->stackTop;
204 if (t->stack->stackSize) {
205 PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
206 (sp < (PRWord*)t->stack->stackTop));
208 #endif /* ! HAVE_STACK_GROWING_UP */
209 #endif /* ! WIN16 */
210 return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp);