prthinfo.c (3923B)
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 return _MD_HomeGCRegisters(t, isCurrent, np); 14 } 15 16 PR_IMPLEMENT(PRStatus) 17 PR_ThreadScanStackPointers(PRThread* t, PRScanStackFun scanFun, 18 void* scanClosure) { 19 PRThread* current = PR_GetCurrentThread(); 20 PRWord *sp, *esp, *p0; 21 int n; 22 void** ptd; 23 PRStatus status; 24 PRUint32 index; 25 int stack_end; 26 27 /* 28 ** Store the thread's registers in the thread structure so the GC 29 ** can scan them. Then scan them. 30 */ 31 p0 = _MD_HomeGCRegisters(t, t == current, &n); 32 status = scanFun(t, (void**)p0, n, scanClosure); 33 if (status != PR_SUCCESS) { 34 return status; 35 } 36 37 /* Scan the C stack for pointers into the GC heap */ 38 #ifdef HAVE_STACK_GROWING_UP 39 if (t == current) { 40 esp = (PRWord*)&stack_end; 41 } else { 42 esp = (PRWord*)PR_GetSP(t); 43 } 44 sp = (PRWord*)t->stack->stackTop; 45 if (t->stack->stackSize) { 46 PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && 47 (esp < (PRWord*)t->stack->stackBottom)); 48 } 49 #else /* ! HAVE_STACK_GROWING_UP */ 50 if (t == current) { 51 sp = (PRWord*)&stack_end; 52 } else { 53 sp = (PRWord*)PR_GetSP(t); 54 } 55 esp = (PRWord*)t->stack->stackTop; 56 if (t->stack->stackSize) { 57 PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && 58 (sp < (PRWord*)t->stack->stackTop)); 59 } 60 #endif /* ! HAVE_STACK_GROWING_UP */ 61 62 if (sp < esp) { 63 status = scanFun(t, (void**)sp, esp - sp, scanClosure); 64 if (status != PR_SUCCESS) { 65 return status; 66 } 67 } 68 69 /* 70 ** Mark all of the per-thread-data items attached to this thread 71 ** 72 ** The execution environment better be accounted for otherwise it 73 ** will be collected 74 */ 75 status = scanFun(t, (void**)&t->environment, 1, scanClosure); 76 if (status != PR_SUCCESS) { 77 return status; 78 } 79 80 /* if thread is not allocated on stack, this is redundant. */ 81 ptd = t->privateData; 82 for (index = 0; index < t->tpdLength; index++, ptd++) { 83 status = scanFun(t, (void**)ptd, 1, scanClosure); 84 if (status != PR_SUCCESS) { 85 return status; 86 } 87 } 88 89 return PR_SUCCESS; 90 } 91 92 /* transducer for PR_EnumerateThreads */ 93 typedef struct PRScanStackData { 94 PRScanStackFun scanFun; 95 void* scanClosure; 96 } PRScanStackData; 97 98 static PRStatus PR_CALLBACK pr_ScanStack(PRThread* t, int i, void* arg) { 99 PRScanStackData* data = (PRScanStackData*)arg; 100 return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure); 101 } 102 103 PR_IMPLEMENT(PRStatus) 104 PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure) { 105 PRScanStackData data; 106 data.scanFun = scanFun; 107 data.scanClosure = scanClosure; 108 return PR_EnumerateThreads(pr_ScanStack, &data); 109 } 110 111 PR_IMPLEMENT(PRUword) 112 PR_GetStackSpaceLeft(PRThread* t) { 113 PRThread* current = PR_GetCurrentThread(); 114 PRWord *sp, *esp; 115 int stack_end; 116 117 #ifdef HAVE_STACK_GROWING_UP 118 if (t == current) { 119 esp = (PRWord*)&stack_end; 120 } else { 121 esp = (PRWord*)PR_GetSP(t); 122 } 123 sp = (PRWord*)t->stack->stackTop; 124 if (t->stack->stackSize) { 125 PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && 126 (esp < (PRWord*)t->stack->stackBottom)); 127 } 128 #else /* ! HAVE_STACK_GROWING_UP */ 129 if (t == current) { 130 sp = (PRWord*)&stack_end; 131 } else { 132 sp = (PRWord*)PR_GetSP(t); 133 } 134 esp = (PRWord*)t->stack->stackTop; 135 if (t->stack->stackSize) { 136 PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && 137 (sp < (PRWord*)t->stack->stackTop)); 138 } 139 #endif /* ! HAVE_STACK_GROWING_UP */ 140 return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp); 141 }