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/. */
8 #include "private/pprthred.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
;
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
) {
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
48 sp
= (PRWord
*) &stack_end
;
49 esp
= (PRWord
*) _pr_top_of_task_stack
;
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
)));
61 #ifdef HAVE_STACK_GROWING_UP
63 esp
= (PRWord
*) &stack_end
;
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 */
74 sp
= (PRWord
*) &stack_end
;
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 */
92 limit
= (prword_t
) esp
;
93 while (scan
< limit
) {
96 test
= *((prword_t
**)scan
);
97 status
= scanFun(t
, (void**)&test
, 1, scanClosure
);
98 if (status
!= PR_SUCCESS
) {
101 scan
+= sizeof(char);
106 status
= scanFun(t
, (void**)sp
, esp
- sp
, scanClosure
);
107 if (status
!= PR_SUCCESS
) {
114 ** Mark all of the per-thread-data items attached to this thread
116 ** The execution environment better be accounted for otherwise it
119 status
= scanFun(t
, (void**)&t
->environment
, 1, scanClosure
);
120 if (status
!= PR_SUCCESS
) {
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
) {
136 /* transducer for PR_EnumerateThreads */
137 typedef struct PRScanStackData
{
138 PRScanStackFun scanFun
;
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();
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
173 sp
= (PRWord
*) &stack_end
;
174 esp
= (PRWord
*) _pr_top_of_task_stack
;
176 PR_ASSERT(sp
<= esp
);
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
)));
186 #ifdef HAVE_STACK_GROWING_UP
188 esp
= (PRWord
*) &stack_end
;
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 */
199 sp
= (PRWord
*) &stack_end
;
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 */
210 return (PRUword
)t
->stack
->stackSize
- ((PRWord
)esp
- (PRWord
)sp
);