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 / pthread_init.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  199 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.   @(#)pthread_init.c    2.5 4/12/95
  26.  
  27. */
  28.  
  29. #include "pthread_setjmp.h"
  30. #include "pthread_internals.h"
  31.  
  32. #ifndef C_CONTEXT_SWITCH
  33.  
  34. #ifdef SOLARIS
  35. #include <sys/frame.h>
  36. #else !SOLARIS
  37. #include <sparc/frame.h>
  38. #endif !SOLARIS
  39. /*
  40.  * additional parameters passed on stack by fake call
  41.  */
  42. #define PARAM_OFFSET 0+2*sizeof(sigset_t)
  43.  
  44. #endif !C_CONTEXT_SWITCH
  45.  
  46. extern pthread_body();
  47. #ifdef STACK_CHECK
  48. extern int pthread_page_size;
  49. #endif
  50.  
  51. /*
  52.  * Stack layout:
  53.  * high +-----------+ + +
  54.  *      |           | | | WINDOWSIZE (prev. window for callee save area)
  55.  *      +-----------+ | +
  56.  *      |           | PTHREAD_BODY_OFFSET (space for pthread_body())
  57.  *      |           | |
  58.  *      +-----------+ + start of user stack space
  59.  *      |           | |
  60.  *      |           | |
  61.  *      |           | |
  62.  *      |           | |
  63.  *      |           | attr.stacksize (space for user functions)
  64.  *      |           | |
  65.  *      |           | |
  66.  *      |           | |
  67.  *      |           | |
  68.  *      +-----------+ + end of user stack space
  69.  *      | --------- | | +
  70.  *      |  locked   | | pthread_page_size: locked page, bus error on overflow
  71.  *      | --------- | | + PA(stack_base): next smallest page aligned address
  72.  *      |           | 2*pthread_page_size
  73.  *      |           | |
  74.  * low  +-----------+ + stack_base
  75.  *
  76.  * ifdef STACK_CHECK:
  77.  * Lock the closest page to the end of the stack to cause a bus error
  78.  * (or and illegal instruction if no signal handler cannot be pushed
  79.  * because the stack limit is exceeded, causes bad signal stack message)
  80.  * on stack overflow. We allocate space conservatively (two pages) to
  81.  * ensure that the locked page does not cross into the allocated stack
  82.  * stack due to page alignment. Notice that only whole pages can be
  83.  * locked, i.e. smaller amounts will be extended to the next page
  84.  * boundary.
  85.  */
  86.  
  87. /*------------------------------------------------------------*/
  88. /*
  89.  * pthread_initialize - associate stack space with thread
  90.  */
  91. void pthread_initialize(t)
  92. pthread_t t;
  93. {
  94.   struct frame *sp;
  95.  
  96. #ifdef STACK_CHECK
  97.   sp = (struct frame *) (t->stack_base + 
  98. #ifdef SIGNAL_STACK
  99.      pthread_page_size * 4 +
  100. #else !SIGNAL_STACK
  101.      pthread_page_size * 2 +
  102. #endif !SIGNAL_STACK
  103.      SA(t->attr.stacksize + PTHREAD_BODY_OFFSET - WINDOWSIZE));
  104. #else !STACK_CHECK
  105.   sp = (struct frame *)
  106.     (t->stack_base + SA(t->attr.stacksize + PTHREAD_BODY_OFFSET - WINDOWSIZE));
  107. #endif !STACK_CHECK
  108.  
  109.   /*
  110.    * set up a jump buffer environment, then manipulate the pc and stack
  111.    */
  112. #ifdef C_CONTEXT_SWITCH
  113.   sigsetjmp(t->context, FALSE);
  114.   t->errno = errno;
  115. #endif
  116.   t->context[JB_SP] = (int) sp;
  117.   t->context[JB_PC] = (int) pthread_body;
  118. #if defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  119.   t->context[JB_PC] -= RETURN_OFFSET;
  120. #endif defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  121. }
  122.  
  123. #ifndef C_CONTEXT_SWITCH
  124. /*------------------------------------------------------------*/
  125. /*
  126.  * pthread_push_fake_call - push a user handler for a signal on some thread's 
  127.  * stack. The user handler will be the first code executed when control
  128.  * returns to the thread.
  129.  */
  130. void pthread_push_fake_call(p, handler_addr, sig, scp, handler_mask)
  131.      pthread_t p;
  132.      void (*handler_addr)();
  133.      int sig;
  134.      struct context_t *scp;
  135.      sigset_t *handler_mask;
  136. {
  137.   extern void pthread_fake_call_wrapper();
  138.   struct frame *framep;
  139.   int new_context = scp == (struct context_t *) DIRECTED_AT_THREAD;
  140.  
  141.   /*
  142.    * create a new frame for the wrapper, and bind sp of the new 
  143.    * frame to the frame structure.
  144.    */
  145.   if (new_context) {                /* init context structure if neccessary */
  146.                                     /* allocate space on stack */
  147.     scp = (struct context_t *)
  148.       (p->context[JB_SP] - SA(sizeof(struct context_t)));
  149.     /*
  150.      * need space for new window and 2 params on stack
  151.      */
  152.     framep = (struct frame *) ((int) scp - SA(MINFRAME + PARAM_OFFSET));
  153.     pthread_sigcpyset2set(&scp->sc_mask, &p->mask);
  154.     scp->sc_sp = p->context[JB_SP];
  155.     /*
  156.      * The offset will be subtracted in the wrapper to hide this issue
  157.      * from the user (in case he changes the return address)
  158.      */
  159.     scp->sc_pc = p->context[JB_PC];
  160. #if defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  161.     scp->sc_pc += RETURN_OFFSET;
  162. #endif defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  163.   }
  164.   else
  165.     framep = (struct frame *) (p->context[JB_SP] - SA(MINFRAME + PARAM_OFFSET));
  166.  
  167.   framep->fr_savfp = (struct frame *) p->context[JB_SP];
  168.                                     /* put fp in saved area of i6. */
  169.   framep->fr_savpc = p->context[JB_PC];
  170.                                     /* put pc in saved area of i7. */
  171. #ifndef ASM_SETJMP
  172.   framep->fr_savpc -= RETURN_OFFSET;
  173. #endif !ASM_SETJMP
  174.   framep->fr_arg[0] = (int) handler_addr;
  175.                                     /* save handler's address as i0. */
  176.   framep->fr_arg[1] = (int) &framep->fr_argx[0]; /* save ptr->sig mask as i1. */
  177.   pthread_sigcpyset2set(&framep->fr_argx[0], &p->mask); /* sig mask on stack. */
  178.   framep->fr_arg[2] = sig;          /* arg0 to user handler in i2. */
  179.   framep->fr_arg[3] = (int) &p->sig_info[sig == -1 ? 0 : sig];
  180.                     /* arg1 to user handler in i3. */
  181.   framep->fr_arg[4] = (int) scp;    /* arg2 to user handler in i4. */
  182.   framep->fr_arg[5] = new_context;  /* used by wrapper to restore context */
  183.   framep->fr_local[6] = (int) &p->cond; /* addr. of inter. cond. wait in l6 */
  184.   framep->fr_local[7] = (int) p->scp;   /* old context pointer in l7 */
  185.   p->context[JB_SP] = (int) framep;     /* store new sp */
  186.   p->context[JB_PC] = (int) pthread_fake_call_wrapper; /* store new pc */
  187. #if defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  188.   p->context[JB_PC] -= RETURN_OFFSET;
  189. #endif defined(ASM_SETJMP) || !defined(C_CONTEXT_SWITCH)
  190.  
  191.   if (handler_mask)
  192.     pthread_sigcpyset2set(&p->mask, handler_mask); /* new thread mask */
  193.   if (sig > 0)
  194.     sigaddset(&p->mask, sig);
  195. }
  196. #endif !C_CONTEXT_SWITCH
  197.  
  198. /*------------------------------------------------------------*/
  199.