"Fossies" - the Fresh Open Source Software Archive

Member "threads/src/init.c" (8 Nov 2000, 7423 Bytes) of package /linux/misc/old/pthreads-3.14.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "init.c" see the Fossies "Dox" file reference documentation.

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