home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / threads / src / stack.c < prev   
C/C++ Source or Header  |  1996-09-28  |  7KB  |  301 lines

  1. /* Copyright (C) 1992, the Florida State University
  2.    Distributed by the Florida State University under the terms of the
  3.    GNU Library General Public License.
  4.  
  5. This file is part of Pthreads.
  6.  
  7. Pthreads is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public
  9. License as published by the Free Software Foundation (version 2).
  10.  
  11. Pthreads is distributed "AS IS" in the hope that it will be
  12. useful, but WITHOUT ANY WARRANTY; without even the implied
  13. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. See the GNU Library General Public License for more details.
  15.  
  16. You should have received a copy of the GNU Library General Public
  17. License along with Pthreads; see the file COPYING.  If not, write
  18. to the Free Software Foundation, 675 Mass Ave, Cambridge,
  19. MA 02139, USA.
  20.  
  21. Report problems and direct all questions to:
  22.  
  23.   pthreads-bugs@ada.cs.fsu.edu
  24.  
  25.   @(#)stack.c    2.5 4/12/95
  26.  
  27. */
  28.  
  29. /*
  30.  * Thread stack allocation.
  31.  * This handles all stack allocation including defined policies.
  32.  */
  33.  
  34. #include "pthread_internals.h"
  35. #include <sys/resource.h>
  36.  
  37. #include <sys/mman.h>
  38.  
  39. extern char *pthread_get_sp();
  40. extern int *pthread_get_fp();
  41. void pthread_set_sp();
  42. void pthread_set_fp();
  43.  
  44. #ifdef STAND_ALONE
  45. int pthread_page_size = 8192;
  46. #else !STAND_ALONE
  47. #ifdef STACK_CHECK
  48. int pthread_page_size;
  49. #endif
  50. #endif
  51.  
  52. #if defined(STACK_CHECK) && defined(SIGNAL_STACK)
  53. #ifdef SOLARIS
  54. #include <sys/frame.h>
  55. #else !SOLARIS
  56. #include <sparc/frame.h>
  57. #endif !SOLARIS
  58.  
  59. static struct frame f;
  60. static int fp_offset = (int)&f.fr_savfp - (int)&f;
  61. static int fp_index = ((int)&f.fr_savfp - (int)&f) / sizeof(int);
  62. #endif
  63.  
  64. #ifdef STACK_CHECK
  65. extern KERNEL_STACK pthread_tempstack;
  66. #ifdef SIGNAL_STACK
  67. #define NUM_PAGES 3
  68. #else !SIGNAL_STACK
  69. #define NUM_PAGES 1
  70. #endif !SIGNAL_STACK
  71. #else !STACK_CHECK
  72. #define NUM_PAGES -1
  73. #endif !STACK_CHECK
  74.  
  75. /*------------------------------------------------------------*/
  76. /*
  77.  * pthread_stack_init - initialize the main thread's stack
  78.  */
  79. void pthread_stack_init(p)
  80. pthread_t p;
  81. {
  82.   struct rlimit rlim;
  83.   extern int pthread_started;
  84.   
  85. #if defined(STACK_CHECK) && !defined(STAND_ALONE)
  86.   pthread_page_size = (int) GETPAGESIZE(_SC_PAGESIZE);
  87. #endif
  88.  
  89.   /*
  90.    * Stack size of the main thread is the stack size of the process
  91.    */
  92. #ifdef STAND_ALONE
  93.   p->attr.stacksize = 150*SA(MINFRAME);
  94. #else
  95.   if (getrlimit(RLIMIT_STACK, &rlim) != 0) {
  96.     perror("getrlimit");
  97.     pthread_process_exit(1);
  98.   }
  99.   p->attr.stacksize = rlim.rlim_cur;
  100. #endif
  101.  
  102.   /*
  103.    * dummy stack base which can be freed
  104.    */
  105. #ifdef MALLOC
  106.   if (!pthread_started)
  107.     p->stack_base = (char *) pthread_malloc(sizeof(int));
  108.   else
  109. #endif MALLOC
  110.     p->stack_base = (char *) malloc(sizeof(int));
  111. #ifdef STACK_CHECK
  112.   pthread_lock_stack_np(p);
  113. #endif STACK_CHECK
  114. }
  115.  
  116. /*------------------------------------------------------------*/
  117. /*
  118.  * pthread_lock_stack_np - lock memory page on stack
  119.  * lock page at lower bound of stack to cause segmentation violation
  120.  * when stack overflows
  121.  */
  122. int pthread_lock_stack_np(p)
  123. pthread_t p;
  124. {
  125. #ifndef STACK_CHECK
  126.   set_errno(ENOSYS);
  127.   return (-1);
  128. #else STACK_CHECK
  129.   SIGSTACK_T ss;
  130. #ifndef SVR4
  131.  
  132. #ifndef STAND_ALONE
  133.   ss.ss_sp = (char *) SA((int) pthread_tempstack_top - STACK_OFFSET);
  134.   CLR_SS_ONSTACK;
  135.   if (SIGSTACK(&ss, (SIGSTACK_T *) NULL)) {
  136. #ifdef DEBUG
  137.     fprintf(stderr,
  138.         "Pthreads: Could not specify signal stack, errno %d\n", errno);
  139. #endif DEBUG
  140.     return(-1);
  141.   }
  142. #endif !STAND_ALONE
  143. #endif !SVR4
  144.  
  145.   if (p->state & T_MAIN ||
  146.       !mprotect((caddr_t) PA(p->stack_base),
  147.         NUM_PAGES * pthread_page_size,
  148.         PROT_NONE)) {
  149. #ifdef SIGNAL_STACK
  150.     p->state |= T_LOCKED;
  151. #endif SIGNAL_STACK
  152.     return (0);
  153.   }
  154. #ifdef DEBUG
  155.     fprintf(stderr,
  156.         "Pthreads: Could not lock stack, errno %d\n", errno);
  157. #endif DEBUG
  158.   return (-1);
  159. #endif STACK_CHECK
  160. }
  161.  
  162. #ifdef STACK_CHECK
  163. /*------------------------------------------------------------*/
  164. /*
  165.  * pthread_unlock_all_stack - unlock all pages of stack, called at thread
  166.  *                    termination.
  167.  */
  168. int pthread_unlock_all_stack(p)
  169. pthread_t p;
  170. {
  171.   if (p->state & T_MAIN)
  172.     return(0);
  173.   else
  174.     return mprotect((caddr_t) PA(p->stack_base), 
  175.             NUM_PAGES * pthread_page_size,
  176.             PROT_READ | PROT_WRITE);
  177. }
  178. #endif STACK_CHECK
  179.  
  180. #if defined(SIGNAL_STACK) && defined(STACK_CHECK)
  181. /*------------------------------------------------------------*/
  182. /*
  183.  * pthread_unlock_stack - unlock memory pages on stack if overflow occurs
  184.  */
  185. int pthread_unlock_stack(p)
  186. pthread_t p;
  187. {
  188.   if (p->state & T_MAIN ||
  189.       !mprotect((caddr_t) PA(p->stack_base)+pthread_page_size,
  190.         (NUM_PAGES-1) * pthread_page_size, 
  191.         PROT_READ | PROT_WRITE)) {
  192.     p->state &= ~T_LOCKED;
  193.     return (0);
  194.   }
  195.   return (-1);
  196. }
  197. #endif SIGNAL_STACK && STACK_CHECK
  198.  
  199. /*------------------------------------------------------------*/
  200. /*
  201.  * pthread_alloc_stack - allocate stack space on heap for a thread
  202.  * Stacks are deallocated when the thread has returned and is detached.
  203.  * In case, SIGNAL_STACK is defined, 2 extra pages are allocated and
  204.  * locked to detect stack overflow condition. These pages are unlocked to
  205.  * allow the stack overflow handling.
  206.  */
  207. int pthread_alloc_stack(p)
  208. pthread_t p;
  209. {
  210. #ifndef _POSIX_THREAD_ATTR_STACKSIZE
  211.   p->attr.stacksize = DEFAULT_STACKSIZE;
  212. #endif
  213.  
  214.   p->stack_base = (char *)
  215. #ifdef MALLOC
  216.     pthread_malloc
  217. #else !MALLOC
  218.     malloc
  219. #endif !MALLOC
  220.       (p->attr.stacksize + PTHREAD_BODY_OFFSET
  221. #ifdef STACK_CHECK
  222.                   + pthread_page_size * (NUM_PAGES+1)
  223. #endif STACK_CHECK
  224.                   );
  225.   
  226.   if ((int) p->stack_base == NULL) {
  227. #ifdef DEBUG
  228.     fprintf(stderr, "\n*** Out of space for thread stacks. ***\n");
  229.     fflush(stderr);
  230. #endif
  231.     return(FALSE);
  232.   }
  233.   
  234. #ifdef STACK_CHECK
  235.   if (pthread_lock_stack_np(p))
  236.     return(FALSE);
  237. #endif
  238.  
  239.   return(TRUE);
  240. }
  241.  
  242. #if defined(STACK_CHECK) && defined(SIGNAL_STACK)
  243. /*------------------------------------------------------------*/
  244. /*
  245.  * switch_stacks - Flushes the windows and copies the stack frames from signal 
  246.  *   stack to thread's stack and then sets the frame pointer links correctly for
  247.  *   thread's stack and then finally switches to thread's stack.
  248.  */
  249.  
  250. void switch_stacks(oldsp)
  251. int oldsp;
  252. {
  253.   char *sp = pthread_get_sp();
  254.   int *fp = pthread_get_fp();
  255.   int size = (char *) SA((int) pthread_tempstack_top) - sp;
  256.   int *target = (int *)(oldsp - size);
  257.   int *user_fp = target;
  258.  
  259.   pthread_ST_FLUSH_WINDOWS();
  260.   memcpy(target, sp, size);
  261.  
  262.   do {
  263.     user_fp[fp_index] = (int)user_fp + (int)((char *)fp - sp);
  264.     user_fp = (int *)user_fp[fp_index];
  265.     sp = (char *)fp;
  266.     fp = (int *)fp[fp_index];
  267.   } while (fp && ((char *)fp < ((char *) SA((int) pthread_tempstack_top))));
  268.  
  269.   user_fp[fp_index] = oldsp;
  270.   pthread_set_fp(target[fp_index]);
  271.   pthread_set_sp(target);
  272. }
  273. /*------------------------------------------------------------*/
  274. #endif
  275.  
  276. #ifdef STAND_ALONE
  277.  
  278. /*------------------------------------------------------------*/
  279. /*
  280.  * sbrk - change segment size (for heap allocation)
  281.  */
  282.  
  283. int sbrk(incr)
  284.      int incr;
  285. {
  286.   extern char heap_start;
  287.   int old;
  288.   
  289.   if ((cur_heap + incr) < ((int)(&heap_start) + HEAP_SIZE)) {
  290.     old = cur_heap;
  291.     cur_heap += incr;
  292.     return old;
  293.   }
  294.   else {
  295.     set_errno(ENOMEM);
  296.     return (-1);
  297.   }
  298. }
  299.  
  300. #endif STAND_ALONE
  301.