| OLD | NEW |
| (Empty) |
| 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 "prlog.h" | |
| 7 #include "prthread.h" | |
| 8 #include "private/pprthred.h" | |
| 9 #include "primpl.h" | |
| 10 | |
| 11 PR_IMPLEMENT(PRWord *) | |
| 12 PR_GetGCRegisters(PRThread *t, int isCurrent, int *np) | |
| 13 { | |
| 14 return _MD_HomeGCRegisters(t, isCurrent, np); | |
| 15 } | |
| 16 | |
| 17 PR_IMPLEMENT(PRStatus) | |
| 18 PR_ThreadScanStackPointers(PRThread* t, | |
| 19 PRScanStackFun scanFun, void* scanClosure) | |
| 20 { | |
| 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; | |
| 28 | |
| 29 /* | |
| 30 ** Store the thread's registers in the thread structure so the GC | |
| 31 ** can scan them. Then scan them. | |
| 32 */ | |
| 33 p0 = _MD_HomeGCRegisters(t, t == current, &n); | |
| 34 status = scanFun(t, (void**)p0, n, scanClosure); | |
| 35 if (status != PR_SUCCESS) | |
| 36 return status; | |
| 37 | |
| 38 /* Scan the C stack for pointers into the GC heap */ | |
| 39 #if defined(XP_PC) && defined(WIN16) | |
| 40 /* | |
| 41 ** Under WIN16, the stack of the current thread is always mapped into | |
| 42 ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan | |
| 43 ** the "task stack". Otherwise, scan the "cached stack" of the inactive | |
| 44 ** thread... | |
| 45 */ | |
| 46 if (t == current) { | |
| 47 sp = (PRWord*) &stack_end; | |
| 48 esp = (PRWord*) _pr_top_of_task_stack; | |
| 49 | |
| 50 PR_ASSERT(sp <= esp); | |
| 51 } else { | |
| 52 sp = (PRWord*) PR_GetSP(t); | |
| 53 esp = (PRWord*) t->stack->stackTop; | |
| 54 | |
| 55 PR_ASSERT((t->stack->stackSize == 0) || | |
| 56 ((sp > (PRWord*)t->stack->stackBottom) && | |
| 57 (sp <= (PRWord*)t->stack->stackTop))); | |
| 58 } | |
| 59 #else /* ! WIN16 */ | |
| 60 #ifdef HAVE_STACK_GROWING_UP | |
| 61 if (t == current) { | |
| 62 esp = (PRWord*) &stack_end; | |
| 63 } else { | |
| 64 esp = (PRWord*) PR_GetSP(t); | |
| 65 } | |
| 66 sp = (PRWord*) t->stack->stackTop; | |
| 67 if (t->stack->stackSize) { | |
| 68 PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && | |
| 69 (esp < (PRWord*)t->stack->stackBottom)); | |
| 70 } | |
| 71 #else /* ! HAVE_STACK_GROWING_UP */ | |
| 72 if (t == current) { | |
| 73 sp = (PRWord*) &stack_end; | |
| 74 } else { | |
| 75 sp = (PRWord*) PR_GetSP(t); | |
| 76 } | |
| 77 esp = (PRWord*) t->stack->stackTop; | |
| 78 if (t->stack->stackSize) { | |
| 79 PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && | |
| 80 (sp < (PRWord*)t->stack->stackTop)); | |
| 81 } | |
| 82 #endif /* ! HAVE_STACK_GROWING_UP */ | |
| 83 #endif /* ! WIN16 */ | |
| 84 | |
| 85 #if defined(WIN16) | |
| 86 { | |
| 87 prword_t scan; | |
| 88 prword_t limit; | |
| 89 | |
| 90 scan = (prword_t) sp; | |
| 91 limit = (prword_t) esp; | |
| 92 while (scan < limit) { | |
| 93 prword_t *test; | |
| 94 | |
| 95 test = *((prword_t **)scan); | |
| 96 status = scanFun(t, (void**)&test, 1, scanClosure); | |
| 97 if (status != PR_SUCCESS) | |
| 98 return status; | |
| 99 scan += sizeof(char); | |
| 100 } | |
| 101 } | |
| 102 #else | |
| 103 if (sp < esp) { | |
| 104 status = scanFun(t, (void**)sp, esp - sp, scanClosure); | |
| 105 if (status != PR_SUCCESS) | |
| 106 return status; | |
| 107 } | |
| 108 #endif | |
| 109 | |
| 110 /* | |
| 111 ** Mark all of the per-thread-data items attached to this thread | |
| 112 ** | |
| 113 ** The execution environment better be accounted for otherwise it | |
| 114 ** will be collected | |
| 115 */ | |
| 116 status = scanFun(t, (void**)&t->environment, 1, scanClosure); | |
| 117 if (status != PR_SUCCESS) | |
| 118 return status; | |
| 119 | |
| 120 /* if thread is not allocated on stack, this is redundant. */ | |
| 121 ptd = t->privateData; | |
| 122 for (index = 0; index < t->tpdLength; index++, ptd++) { | |
| 123 status = scanFun(t, (void**)ptd, 1, scanClosure); | |
| 124 if (status != PR_SUCCESS) | |
| 125 return status; | |
| 126 } | |
| 127 | |
| 128 return PR_SUCCESS; | |
| 129 } | |
| 130 | |
| 131 /* transducer for PR_EnumerateThreads */ | |
| 132 typedef struct PRScanStackData { | |
| 133 PRScanStackFun scanFun; | |
| 134 void* scanClosure; | |
| 135 } PRScanStackData; | |
| 136 | |
| 137 static PRStatus PR_CALLBACK | |
| 138 pr_ScanStack(PRThread* t, int i, void* arg) | |
| 139 { | |
| 140 PRScanStackData* data = (PRScanStackData*)arg; | |
| 141 return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure); | |
| 142 } | |
| 143 | |
| 144 PR_IMPLEMENT(PRStatus) | |
| 145 PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure) | |
| 146 { | |
| 147 PRScanStackData data; | |
| 148 data.scanFun = scanFun; | |
| 149 data.scanClosure = scanClosure; | |
| 150 return PR_EnumerateThreads(pr_ScanStack, &data); | |
| 151 } | |
| 152 | |
| 153 PR_IMPLEMENT(PRUword) | |
| 154 PR_GetStackSpaceLeft(PRThread* t) | |
| 155 { | |
| 156 PRThread *current = PR_GetCurrentThread(); | |
| 157 PRWord *sp, *esp; | |
| 158 int stack_end; | |
| 159 | |
| 160 #if defined(WIN16) | |
| 161 /* | |
| 162 ** Under WIN16, the stack of the current thread is always mapped into | |
| 163 ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan | |
| 164 ** the "task stack". Otherwise, scan the "cached stack" of the inactive | |
| 165 ** thread... | |
| 166 */ | |
| 167 if (t == current) { | |
| 168 sp = (PRWord*) &stack_end; | |
| 169 esp = (PRWord*) _pr_top_of_task_stack; | |
| 170 | |
| 171 PR_ASSERT(sp <= esp); | |
| 172 } else { | |
| 173 sp = (PRWord*) PR_GetSP(t); | |
| 174 esp = (PRWord*) t->stack->stackTop; | |
| 175 | |
| 176 PR_ASSERT((t->stack->stackSize == 0) || | |
| 177 ((sp > (PRWord*)t->stack->stackBottom) && | |
| 178 (sp <= (PRWord*)t->stack->stackTop))); | |
| 179 } | |
| 180 #else /* ! WIN16 */ | |
| 181 #ifdef HAVE_STACK_GROWING_UP | |
| 182 if (t == current) { | |
| 183 esp = (PRWord*) &stack_end; | |
| 184 } else { | |
| 185 esp = (PRWord*) PR_GetSP(t); | |
| 186 } | |
| 187 sp = (PRWord*) t->stack->stackTop; | |
| 188 if (t->stack->stackSize) { | |
| 189 PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && | |
| 190 (esp < (PRWord*)t->stack->stackBottom)); | |
| 191 } | |
| 192 #else /* ! HAVE_STACK_GROWING_UP */ | |
| 193 if (t == current) { | |
| 194 sp = (PRWord*) &stack_end; | |
| 195 } else { | |
| 196 sp = (PRWord*) PR_GetSP(t); | |
| 197 } | |
| 198 esp = (PRWord*) t->stack->stackTop; | |
| 199 if (t->stack->stackSize) { | |
| 200 PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && | |
| 201 (sp < (PRWord*)t->stack->stackTop)); | |
| 202 } | |
| 203 #endif /* ! HAVE_STACK_GROWING_UP */ | |
| 204 #endif /* ! WIN16 */ | |
| 205 return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp); | |
| 206 } | |
| OLD | NEW |