home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / thread / initializeThreads.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  8.7 KB  |  369 lines

  1. /*
  2.  *   $RCSfile: initializeThreads.c,v $  
  3.  *   $Revision: 1.2 $  
  4.  *   $Date: 1996/05/04 23:51:55 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37. #include "sysdefs.h"
  38.  
  39. #ifdef mips
  40. #    include <mips/param.h>
  41. #    include <mips/vmparam.h>
  42. #elif defined(sparc)
  43. #    include <machine/param.h>
  44. #    include <machine/vmparam.h>
  45. #elif defined(_AIX)
  46. #    include <sys/pseg.h>
  47. #    undef n_name            /* nlist.h messes this up    */
  48. #elif defined(hpux)
  49. #   include <sys/param.h>
  50. #   include <sys/vmparam.h>
  51. #   include <sys/user.h>
  52. #elif defined(linux)
  53. #   include <sys/param.h>
  54. #   include <sys/user.h>
  55. #elif !(defined(mips) || defined(sparc) || defined(_AIX) || defined(hpux) || defined(linux))
  56.     not supported
  57. #else
  58.     /* this else should have the not supported code, but the
  59.        ultrix cpp is broken */
  60. #endif
  61.  
  62. #include "ess.h"
  63. #include "checking.h"
  64. #include "trace.h"
  65. #include "error.h"
  66. #include "list.h"
  67. #include "tid.h"
  68. #include "io.h"
  69. #include "lock.h"
  70. #include "object.h"
  71. #include "msgdefs.h"
  72. #include "thread.h"
  73. #include "thread_funcs.h"
  74. #include "thread_globals.h"
  75. #include "ips_support.h"
  76.  
  77. #ifdef    linux
  78. /*
  79.   This routine is required to force the allocation of stack pages to our
  80.   process.  Attempting to access pages below the current SP causes a
  81.   access violation in Linux.
  82. */
  83. void    touchStack(int nBytes)
  84. {
  85. char    someSpace[1024];
  86.  
  87.     if (nBytes > 1024)
  88.         touchStack(nBytes-1024);
  89. }
  90.  
  91. #endif    linux
  92. /*
  93.  *    This function initializes threads and their stacks.
  94.  *
  95.  *    The macro NBPG used in the following code is the number
  96.  *    of bytes per VM page (defined in /usr/include/machine/param.h
  97.  */
  98.  
  99. static int StackSize = 0;
  100.  
  101.  void
  102. initializeThreads (
  103.     register FOUR    stackSize,
  104.     PFI                procedure 
  105. )
  106. {
  107.     FOUR    numThreads = NumThreads; /* from initializeEnv() */
  108.     TCB        *tcb;
  109.     FOUR    *sp;
  110.     FOUR    j;
  111.     int        i;
  112.     int        stackLoc = (int) &(stackLoc); /* integer address of stack location */
  113.  
  114. /*
  115.  *    DEBUG_THREAD can be defined to allow extra stack space to 
  116.  *    track down bugs related to stack corruption.
  117.  */
  118. #ifdef DEBUG_THREAD
  119.     ExtraStackSpace = NBPG;  
  120. #else
  121.     ExtraStackSpace = 0;  
  122. #endif
  123.  
  124. #ifdef DEBUG
  125.     StackSize = stackSize;
  126. #endif DEBUG
  127.  
  128. #ifdef  linux
  129. /*
  130.    Allocate stack pages before initializeTcb starts poking around in memory
  131.    below the current SP.
  132. */
  133.     touchStack((numThreads+4)*(stackSize+ExtraStackSpace)*sizeof(FOUR));
  134. #endif
  135.  
  136.     TRPRINT(TR_THREAD, TR_LEVEL_1, ("numThreads:%d, stackSize:%d", numThreads, stackSize));
  137.  
  138.     /*
  139.      *    initialize the free list and the ready list, and the
  140.      *    waiting list for thread forks
  141.      */
  142.     initializeList( &FreeList );
  143.     initializeList( &ReadyList );
  144.     initializeList( &ThreadForkWaitList );
  145.  
  146.     /*
  147.      *    allocate space for tcbs
  148.      */
  149.     if ((Tcbs = (TCB *) malloc((unsigned int) (numThreads * sizeof(TCB)))) == NULL)    {
  150.  
  151.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  152.     }
  153.  
  154.     /*
  155.      *    allocate space for stacks on the stack
  156.      *
  157.      */
  158. #ifdef hpux
  159.     /* stacks on the HP's grow up!!! So start farther up */
  160.     sp = (FOUR *) (((stackLoc + NBPG) & ~0x7)+(stackSize+ExtraStackSpace));
  161.  
  162. #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
  163.     sp = (FOUR *) (((stackLoc - NBPG) & ~0x7)-(stackSize+ExtraStackSpace));
  164.  
  165.     /* sp = (FOUR *) ((USRSTACK - NBPG) & ~0x7); */
  166.  
  167. #else
  168. not supported
  169. #endif
  170.     TRPRINT(TR_THREAD, TR_LEVEL_2, ("sp:%x", sp));
  171.  
  172.     tcb = Tcbs;
  173. #ifdef IPS_SUPPORT
  174.     IPSinitThread();
  175. #endif IPS_SUPPORT
  176.  
  177.     /*
  178.      *  initialize all the threads
  179.      */
  180. #ifdef hpux
  181.     /* stacks on the HP's grow up!!! */
  182. #    define OP_DIR +=
  183. #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
  184.     /* stacks grow down */
  185. #    define OP_DIR -=
  186. #else
  187. not supported
  188. #endif
  189.     for (i = 0; i < numThreads; i++, tcb++, sp OP_DIR (stackSize+ExtraStackSpace))    {
  190.  
  191.         tcb->id = i;
  192.  
  193.         initializeTcb(procedure, tcb, sp, (stackSize+ExtraStackSpace));
  194.         TRPRINT(TR_THREAD, TR_LEVEL_2, ("tcb:%i loc:%x stack:%x SP:%x",
  195.                 tcb->id, tcb, tcb->stack, tcb->sp));
  196.  
  197.         /*
  198.          *    put the thread on the free queue
  199.          */
  200.         listEnq( &FreeList, &(tcb->controlList) );
  201.     }
  202.  
  203.     /*
  204.      *    mark the stack areas so that the usage patterns can
  205.      *    be monitored to check adequacy of stack sizes
  206.      */
  207. #ifdef hpux
  208.     /* stacks on the HP's grow up!!! So go the other way */
  209.     sp = (FOUR *) (((stackLoc + NBPG) & ~0x7)+(stackSize+ExtraStackSpace));
  210.     for (i = 0; i < numThreads; i++)
  211. {
  212.         /*
  213.          *  don't blow away the initialized part
  214.          */
  215.         sp += USEDSTACK;
  216.  
  217.         for (j = USEDSTACK; j < (stackSize+ExtraStackSpace); j++, sp++) {
  218.  
  219.             *sp = STACKPATTERN;
  220.         }
  221.     }
  222.  
  223. #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
  224.  
  225.     sp = (FOUR *) (((stackLoc - NBPG) & ~0x7)-(stackSize+ExtraStackSpace));
  226.     for (i = 0; i < numThreads; i++)    {
  227.  
  228.         /*
  229.          *    don't blow away the initialized part
  230.          */
  231.         sp -= USEDSTACK;
  232.  
  233.         for (j = USEDSTACK; j < (stackSize+ExtraStackSpace); j++, sp--)    {
  234.  
  235.             *sp = STACKPATTERN;
  236.         }
  237.     }
  238. #else
  239. not supported
  240. #endif
  241.  
  242.     /*
  243.      *    take a thread off the free list to use for
  244.      *    a spare in case of congestion
  245.      */
  246.     Spare = (TCB *) listDeq( &FreeList );
  247.     TRPRINT(TR_THREAD, TR_LEVEL_2, ("Spare:%x id:%d", Spare, Spare->id));
  248.  
  249.     /*
  250.      *    take from the free list a thread to run.
  251.      */
  252.     Active = (TCB *) listDeq( &FreeList );
  253.     TRPRINT(TR_THREAD, TR_LEVEL_2, ("Active:%x id:%d", Active, Active->id));
  254. }
  255.  
  256.  void
  257. freeThread(TCB *thread)
  258. {
  259.     reinitTcb(thread); /* clean it up before putting it on the FreeList */
  260.     listEnq( &FreeList, &(thread->controlList) );
  261.     notify(&ThreadForkWaitList, esmNOERROR, esmNOERROR);
  262. }
  263.  
  264. void
  265. checkStacks()
  266. {
  267.     TCB *tcb = Tcbs;
  268.     FOUR    *sp;
  269.     int        i, j;
  270.  
  271.     for (i = 0, tcb = Tcbs; i < NumThreads; i++, tcb++) {
  272. #ifdef hpux
  273.     /* stack grows up */
  274.     /* check stack[StackSize+ExtraStackSpace] down to stack[StackSize] */
  275.         sp = tcb->stack + StackSize + ExtraStackSpace; 
  276. #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
  277.     /* stack grows down */
  278.     /* check stack[-(StackSize+ExtraStackSpace] up to  stack[-StackSize] */
  279.         sp = tcb->stack - (StackSize + ExtraStackSpace);
  280. #else
  281. not supported
  282. #endif
  283.         /*
  284.         fprintf(stderr,  "Checking tcb %d, %d words from 0x%x to 0x%x\n",
  285.             tcb->id, ExtraStackSpace-1,
  286.             &sp[1], &sp[ExtraStackSpace-1]);
  287.         */
  288.         for(j=1; j< (ExtraStackSpace + 100); j++) {
  289.             FOUR *place = 
  290. #ifdef hpux
  291.             &sp[-j];
  292. #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
  293.             &sp[j] ;
  294. #else
  295. not supported
  296. #endif
  297.  
  298.             if(  *place != STACKPATTERN ) {
  299.                 fprintf(stderr, 
  300.                 "tcb %d,state %d (stack @0x%x): loc 0x%x(%d) trashed: 0x%x\n",
  301.                     tcb->id, tcb->state, tcb->stack,
  302.                     place, 
  303. #ifdef hpux
  304.             -j, 
  305. #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
  306.             j,
  307. #else
  308. not supported
  309. #endif
  310.                     *place);
  311.                 SM_ERROR(TYPE_SYS, esmINTERNAL);
  312.             }
  313.         }
  314.     }
  315. }
  316.  
  317. int LargestStack = 0;
  318.  
  319. void
  320. checkMyStack()
  321. {
  322.     TCB     *tcb = Active;
  323.     FOUR    *current;
  324.  
  325.     /* DO NOT PUT ANY SM_ASSERTS IN THIS FUNCTION!!!!!!!!!!*/
  326.  
  327. #ifdef hpux
  328. #define ABOVE <
  329. #define BELOW > 
  330. #define END_STACK(s) ((s) + StackSize)
  331. #elif defined(mips) || defined(sparc) || defined(_IBMR2) || defined(linux)
  332. #define ABOVE >
  333. #define BELOW <
  334. #define END_STACK(s) ((s) - StackSize)
  335. #else
  336. not supported
  337. #endif
  338.  
  339.     current = (FOUR *)(&tcb);
  340.     if( (current ABOVE tcb->stack) || 
  341.         (current BELOW END_STACK(tcb->stack))
  342.     ) {
  343.         fprintf(stderr, 
  344.             "STACK OVERFLOW FOR tcb %d!\n", tcb->id);
  345.         SM_ERROR(TYPE_SYS, esmINTERNAL);
  346.     } else {
  347.         int diff;
  348.  
  349.         diff = current - tcb->stack;
  350.         if(diff < 0) 
  351.             diff = 0-diff;
  352.  
  353.         if(diff > LargestStack)  
  354.             LargestStack = diff;
  355.     }
  356. }
  357.  
  358. #ifdef DEBUG
  359. int
  360. SanityCheck()
  361. {
  362.     /* DO NOT PUT ANY SM_ASSERTS IN THIS FUNCTION!!!!!!!!!!*/
  363.     if(InitializationCompleted)
  364.         checkMyStack();
  365.     return 0;
  366. }
  367. #endif DEBUG
  368.  
  369.