home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / misc / prthinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  6.7 KB  |  230 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "prlog.h"
  20. #include "prthread.h"
  21. #ifdef XP_MAC
  22. #include "pprthred.h"
  23. #else
  24. #include "private/pprthred.h"
  25. #endif
  26. #include "primpl.h"
  27.  
  28. PR_IMPLEMENT(PRWord *)
  29. PR_GetGCRegisters(PRThread *t, int isCurrent, int *np)
  30. {
  31.     return _MD_HomeGCRegisters(t, isCurrent, np);
  32. }
  33.  
  34. PR_IMPLEMENT(PRStatus)
  35. PR_ThreadScanStackPointers(PRThread* t,
  36.                            PRScanStackFun scanFun, void* scanClosure)
  37. {
  38.     PRThread* current = PR_GetCurrentThread();
  39.     PRWord *sp, *esp, *p0;
  40.     int n;
  41.     void **ptd;
  42.     PRStatus status;
  43.     PRUint32 index;
  44.     int stack_end;
  45.  
  46.     /*
  47.     ** Store the thread's registers in the thread structure so the GC
  48.     ** can scan them. Then scan them.
  49.     */
  50.     p0 = _MD_HomeGCRegisters(t, t == current, &n);
  51.     status = scanFun(t, (void**)p0, n, scanClosure);
  52.     if (status != PR_SUCCESS)
  53.         return status;
  54.  
  55.     /* Scan the C stack for pointers into the GC heap */
  56. #if defined(XP_PC) && defined(WIN16)
  57.     /*
  58.     ** Under WIN16, the stack of the current thread is always mapped into
  59.     ** the "task stack" (at SS:xxxx).  So, if t is the current thread, scan
  60.     ** the "task stack".  Otherwise, scan the "cached stack" of the inactive
  61.     ** thread...
  62.     */
  63.     if (t == current) {
  64.         sp  = (PRWord*) &stack_end;
  65.         esp = (PRWord*) _pr_top_of_task_stack;
  66.  
  67.         PR_ASSERT(sp <= esp);
  68.     } else {
  69.         sp  = (PRWord*) PR_GetSP(t);
  70.         esp = (PRWord*) t->stack->stackTop;
  71.  
  72.         PR_ASSERT((t->stack->stackSize == 0) ||
  73.                   ((sp >  (PRWord*)t->stack->stackBottom) &&
  74.                    (sp <= (PRWord*)t->stack->stackTop)));
  75.     }
  76. #else   /* ! WIN16 */
  77. #ifdef HAVE_STACK_GROWING_UP
  78.     if (t == current) {
  79.         esp = (PRWord*) &stack_end;
  80.     } else {
  81.         esp = (PRWord*) PR_GetSP(t);
  82.     }
  83.     sp = (PRWord*) t->stack->stackTop;
  84.     if (t->stack->stackSize) {
  85.         PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
  86.                   (esp < (PRWord*)t->stack->stackBottom));
  87.     }
  88. #else   /* ! HAVE_STACK_GROWING_UP */
  89.     if (t == current) {
  90.         sp = (PRWord*) &stack_end;
  91.     } else {
  92.         sp = (PRWord*) PR_GetSP(t);
  93.     }
  94.     esp = (PRWord*) t->stack->stackTop;
  95.     if (t->stack->stackSize) {
  96.         PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
  97.                   (sp < (PRWord*)t->stack->stackTop));
  98.     }
  99. #endif  /* ! HAVE_STACK_GROWING_UP */
  100. #endif  /* ! WIN16 */
  101.  
  102. #if defined(WIN16)
  103.     {
  104.         prword_t scan;
  105.         prword_t limit;
  106.         
  107.         scan = (prword_t) sp;
  108.         limit = (prword_t) esp;
  109.         while (scan < limit) {
  110.             prword_t *test;
  111.  
  112.             test = *((prword_t **)scan);
  113.             status = scanFun(t, (void**)&test, 1, scanClosure);
  114.             if (status != PR_SUCCESS)
  115.                 return status;
  116.             scan += sizeof(char);
  117.         }
  118.     }
  119. #else
  120.     if (sp < esp) {
  121.         status = scanFun(t, (void**)sp, esp - sp, scanClosure);
  122.         if (status != PR_SUCCESS)
  123.             return status;
  124.     }
  125. #endif
  126.  
  127.     /*
  128.     ** Mark all of the per-thread-data items attached to this thread
  129.     */
  130.  
  131. #if defined(_PR_PTHREADS)
  132. /*    PR_ASSERT(!"I can't do this!"); */
  133. #else /* defined(_PR_PTHREADS) */
  134.     
  135.     /* the execution environment better be accounted for otherwise it will be collected */
  136.     status = scanFun(t, (void**)&t->environment, 1, scanClosure);
  137.     if (status != PR_SUCCESS)
  138.         return status;
  139.  
  140.     ptd = t->privateData;
  141.     for (index = 0; index < t->tpdLength; index++, ptd++) {
  142.         status = scanFun(t, (void**)ptd, 1, scanClosure);
  143.         if (status != PR_SUCCESS)
  144.             return status;
  145.     }
  146. #endif /* defined(_PR_PTHREADS) */
  147.  
  148.     return PR_SUCCESS;
  149. }
  150.  
  151. /* transducer for PR_EnumerateThreads */
  152. typedef struct PRScanStackData {
  153.     PRScanStackFun      scanFun;
  154.     void*               scanClosure;
  155. } PRScanStackData;
  156.  
  157. static PRStatus PR_CALLBACK
  158. pr_ScanStack(PRThread* t, int i, void* arg)
  159. {
  160. #if defined(XP_MAC)
  161. #pragma unused (i)
  162. #endif
  163.     PRScanStackData* data = (PRScanStackData*)arg;
  164.     return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure);
  165. }
  166.  
  167. PR_IMPLEMENT(PRStatus)
  168. PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure)
  169. {
  170.     PRScanStackData data;
  171.     data.scanFun = scanFun;
  172.     data.scanClosure = scanClosure;
  173.     return PR_EnumerateThreads(pr_ScanStack, &data);
  174. }
  175.  
  176. PR_PUBLIC_API(PRUword)
  177. PR_GetStackSpaceLeft(PRThread* t)
  178. {
  179.     PRThread *current = PR_CurrentThread();
  180.     PRWord *sp, *esp;
  181.     int stack_end;
  182.  
  183. #if defined(WIN16)
  184.     /*
  185.     ** Under WIN16, the stack of the current thread is always mapped into
  186.     ** the "task stack" (at SS:xxxx).  So, if t is the current thread, scan
  187.     ** the "task stack".  Otherwise, scan the "cached stack" of the inactive
  188.     ** thread...
  189.     */
  190.     if (t == current) {
  191.         sp  = (PRWord*) &stack_end;
  192.         esp = (PRWord*) _pr_top_of_task_stack;
  193.  
  194.         PR_ASSERT(sp <= esp);
  195.     } else {
  196.         sp  = (PRWord*) PR_GetSP(t);
  197.         esp = (PRWord*) t->stack->stackTop;
  198.  
  199.     PR_ASSERT((t->stack->stackSize == 0) ||
  200.                  ((sp >  (PRWord*)t->stack->stackBottom) &&
  201.           (sp <= (PRWord*)t->stack->stackTop)));
  202.     }
  203. #else   /* ! WIN16 */
  204. #ifdef HAVE_STACK_GROWING_UP
  205.     if (t == current) {
  206.         esp = (PRWord*) &stack_end;
  207.     } else {
  208.         esp = (PRWord*) PR_GetSP(t);
  209.     }
  210.     sp = (PRWord*) t->stack->stackTop;
  211.     if (t->stack->stackSize) {
  212.         PR_ASSERT((esp > (PRWord*)t->stack->stackTop) &&
  213.                   (esp < (PRWord*)t->stack->stackBottom));
  214.     }
  215. #else   /* ! HAVE_STACK_GROWING_UP */
  216.     if (t == current) {
  217.         sp = (PRWord*) &stack_end;
  218.     } else {
  219.         sp = (PRWord*) PR_GetSP(t);
  220.     }
  221.     esp = (PRWord*) t->stack->stackTop;
  222.     if (t->stack->stackSize) {
  223.     PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) &&
  224.           (sp < (PRWord*)t->stack->stackTop));
  225.     }
  226. #endif  /* ! HAVE_STACK_GROWING_UP */
  227. #endif  /* ! WIN16 */
  228.     return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp);
  229. }
  230.