1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/src/misc/prthinfo.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,206 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "prlog.h" 1.10 +#include "prthread.h" 1.11 +#include "private/pprthred.h" 1.12 +#include "primpl.h" 1.13 + 1.14 +PR_IMPLEMENT(PRWord *) 1.15 +PR_GetGCRegisters(PRThread *t, int isCurrent, int *np) 1.16 +{ 1.17 + return _MD_HomeGCRegisters(t, isCurrent, np); 1.18 +} 1.19 + 1.20 +PR_IMPLEMENT(PRStatus) 1.21 +PR_ThreadScanStackPointers(PRThread* t, 1.22 + PRScanStackFun scanFun, void* scanClosure) 1.23 +{ 1.24 + PRThread* current = PR_GetCurrentThread(); 1.25 + PRWord *sp, *esp, *p0; 1.26 + int n; 1.27 + void **ptd; 1.28 + PRStatus status; 1.29 + PRUint32 index; 1.30 + int stack_end; 1.31 + 1.32 + /* 1.33 + ** Store the thread's registers in the thread structure so the GC 1.34 + ** can scan them. Then scan them. 1.35 + */ 1.36 + p0 = _MD_HomeGCRegisters(t, t == current, &n); 1.37 + status = scanFun(t, (void**)p0, n, scanClosure); 1.38 + if (status != PR_SUCCESS) 1.39 + return status; 1.40 + 1.41 + /* Scan the C stack for pointers into the GC heap */ 1.42 +#if defined(XP_PC) && defined(WIN16) 1.43 + /* 1.44 + ** Under WIN16, the stack of the current thread is always mapped into 1.45 + ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan 1.46 + ** the "task stack". Otherwise, scan the "cached stack" of the inactive 1.47 + ** thread... 1.48 + */ 1.49 + if (t == current) { 1.50 + sp = (PRWord*) &stack_end; 1.51 + esp = (PRWord*) _pr_top_of_task_stack; 1.52 + 1.53 + PR_ASSERT(sp <= esp); 1.54 + } else { 1.55 + sp = (PRWord*) PR_GetSP(t); 1.56 + esp = (PRWord*) t->stack->stackTop; 1.57 + 1.58 + PR_ASSERT((t->stack->stackSize == 0) || 1.59 + ((sp > (PRWord*)t->stack->stackBottom) && 1.60 + (sp <= (PRWord*)t->stack->stackTop))); 1.61 + } 1.62 +#else /* ! WIN16 */ 1.63 +#ifdef HAVE_STACK_GROWING_UP 1.64 + if (t == current) { 1.65 + esp = (PRWord*) &stack_end; 1.66 + } else { 1.67 + esp = (PRWord*) PR_GetSP(t); 1.68 + } 1.69 + sp = (PRWord*) t->stack->stackTop; 1.70 + if (t->stack->stackSize) { 1.71 + PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && 1.72 + (esp < (PRWord*)t->stack->stackBottom)); 1.73 + } 1.74 +#else /* ! HAVE_STACK_GROWING_UP */ 1.75 + if (t == current) { 1.76 + sp = (PRWord*) &stack_end; 1.77 + } else { 1.78 + sp = (PRWord*) PR_GetSP(t); 1.79 + } 1.80 + esp = (PRWord*) t->stack->stackTop; 1.81 + if (t->stack->stackSize) { 1.82 + PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && 1.83 + (sp < (PRWord*)t->stack->stackTop)); 1.84 + } 1.85 +#endif /* ! HAVE_STACK_GROWING_UP */ 1.86 +#endif /* ! WIN16 */ 1.87 + 1.88 +#if defined(WIN16) 1.89 + { 1.90 + prword_t scan; 1.91 + prword_t limit; 1.92 + 1.93 + scan = (prword_t) sp; 1.94 + limit = (prword_t) esp; 1.95 + while (scan < limit) { 1.96 + prword_t *test; 1.97 + 1.98 + test = *((prword_t **)scan); 1.99 + status = scanFun(t, (void**)&test, 1, scanClosure); 1.100 + if (status != PR_SUCCESS) 1.101 + return status; 1.102 + scan += sizeof(char); 1.103 + } 1.104 + } 1.105 +#else 1.106 + if (sp < esp) { 1.107 + status = scanFun(t, (void**)sp, esp - sp, scanClosure); 1.108 + if (status != PR_SUCCESS) 1.109 + return status; 1.110 + } 1.111 +#endif 1.112 + 1.113 + /* 1.114 + ** Mark all of the per-thread-data items attached to this thread 1.115 + ** 1.116 + ** The execution environment better be accounted for otherwise it 1.117 + ** will be collected 1.118 + */ 1.119 + status = scanFun(t, (void**)&t->environment, 1, scanClosure); 1.120 + if (status != PR_SUCCESS) 1.121 + return status; 1.122 + 1.123 + /* if thread is not allocated on stack, this is redundant. */ 1.124 + ptd = t->privateData; 1.125 + for (index = 0; index < t->tpdLength; index++, ptd++) { 1.126 + status = scanFun(t, (void**)ptd, 1, scanClosure); 1.127 + if (status != PR_SUCCESS) 1.128 + return status; 1.129 + } 1.130 + 1.131 + return PR_SUCCESS; 1.132 +} 1.133 + 1.134 +/* transducer for PR_EnumerateThreads */ 1.135 +typedef struct PRScanStackData { 1.136 + PRScanStackFun scanFun; 1.137 + void* scanClosure; 1.138 +} PRScanStackData; 1.139 + 1.140 +static PRStatus PR_CALLBACK 1.141 +pr_ScanStack(PRThread* t, int i, void* arg) 1.142 +{ 1.143 + PRScanStackData* data = (PRScanStackData*)arg; 1.144 + return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure); 1.145 +} 1.146 + 1.147 +PR_IMPLEMENT(PRStatus) 1.148 +PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure) 1.149 +{ 1.150 + PRScanStackData data; 1.151 + data.scanFun = scanFun; 1.152 + data.scanClosure = scanClosure; 1.153 + return PR_EnumerateThreads(pr_ScanStack, &data); 1.154 +} 1.155 + 1.156 +PR_IMPLEMENT(PRUword) 1.157 +PR_GetStackSpaceLeft(PRThread* t) 1.158 +{ 1.159 + PRThread *current = PR_GetCurrentThread(); 1.160 + PRWord *sp, *esp; 1.161 + int stack_end; 1.162 + 1.163 +#if defined(WIN16) 1.164 + /* 1.165 + ** Under WIN16, the stack of the current thread is always mapped into 1.166 + ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan 1.167 + ** the "task stack". Otherwise, scan the "cached stack" of the inactive 1.168 + ** thread... 1.169 + */ 1.170 + if (t == current) { 1.171 + sp = (PRWord*) &stack_end; 1.172 + esp = (PRWord*) _pr_top_of_task_stack; 1.173 + 1.174 + PR_ASSERT(sp <= esp); 1.175 + } else { 1.176 + sp = (PRWord*) PR_GetSP(t); 1.177 + esp = (PRWord*) t->stack->stackTop; 1.178 + 1.179 + PR_ASSERT((t->stack->stackSize == 0) || 1.180 + ((sp > (PRWord*)t->stack->stackBottom) && 1.181 + (sp <= (PRWord*)t->stack->stackTop))); 1.182 + } 1.183 +#else /* ! WIN16 */ 1.184 +#ifdef HAVE_STACK_GROWING_UP 1.185 + if (t == current) { 1.186 + esp = (PRWord*) &stack_end; 1.187 + } else { 1.188 + esp = (PRWord*) PR_GetSP(t); 1.189 + } 1.190 + sp = (PRWord*) t->stack->stackTop; 1.191 + if (t->stack->stackSize) { 1.192 + PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && 1.193 + (esp < (PRWord*)t->stack->stackBottom)); 1.194 + } 1.195 +#else /* ! HAVE_STACK_GROWING_UP */ 1.196 + if (t == current) { 1.197 + sp = (PRWord*) &stack_end; 1.198 + } else { 1.199 + sp = (PRWord*) PR_GetSP(t); 1.200 + } 1.201 + esp = (PRWord*) t->stack->stackTop; 1.202 + if (t->stack->stackSize) { 1.203 + PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && 1.204 + (sp < (PRWord*)t->stack->stackTop)); 1.205 + } 1.206 +#endif /* ! HAVE_STACK_GROWING_UP */ 1.207 +#endif /* ! WIN16 */ 1.208 + return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp); 1.209 +}