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_sched.S < prev    next >
Text File  |  1996-09-28  |  18KB  |  555 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_sched.S    2.5 4/12/95
  26.  
  27. */
  28.  
  29. #include <pthread/config.h>
  30. #include <../src/config_internals.h>
  31.  
  32. #ifndef C_CONTEXT_SWITCH
  33. /*
  34.  * Context switch supporting assembly routines and other assembly routines
  35.  * Portability notes:
  36.  * The assembly code in this file is only needed for the following conditional
  37.  * compilation:
  38.  * !C_CONTEXT_SWITCH: for all routines (slow version of context switch etc.
  39.  *                    if C_CONTEXT_SWITCH defined).
  40.  */
  41.  
  42. #define LOCORE
  43. #define _ASM
  44.  
  45. #ifdef SOLARIS
  46. #include <sys/asm_linkage.h>
  47. #define NAME(x) x
  48. #else !SOLARIS
  49. #include <sparc/asm_linkage.h>
  50. #endif !SOLARIS
  51.  
  52. #include <sys/errno.h>
  53.  
  54. #ifdef STAND_ALONE
  55. #define DISABLE_INTERRUPTS    ta 0x08
  56. #define ENABLE_INTERRUPTS    call NAME(enable_traps)
  57. #include <sun4e/trap.h>
  58. #else !STAND_ALONE
  59. #define DISABLE_INTERRUPTS    call NAME(pthread_p_sigprocmask)
  60. #define ENABLE_INTERRUPTS    call NAME(pthread_p_sigprocmask)
  61. #ifdef SOLARIS
  62. #include <sys/trap.h>
  63. #define GLOBAL
  64. #else !SORLARIS
  65. #include <sparc/trap.h>
  66. #endif !SOLARIS
  67. #endif !STAND_ALONE
  68.  
  69. #include <pthread/unistd.h>
  70. #include "pthread_offsets.h"
  71. #include <pthread/pthread_asm.h>
  72. #include "signal_internals.h"
  73.  
  74. #define SCHED_WINDOW MINFRAME
  75.  
  76.     .seg    "text"
  77.  
  78. !    void pthread_sched
  79. !
  80.         ENTRY(pthread_sched)
  81.     set    NAME(pthread_kern),%g1    ! Get kernel address
  82. #ifdef NO_INLINE
  83.     st    %g0,[%g1+is_in_kernel]    ! Clear kernel flag
  84.     ld    [%g1+state_change],%g2    ! Get kernel state
  85.     tst    %g2            ! check if state changed
  86.     bne    state_changed
  87.     nop
  88.     retl
  89.     nop
  90. state_changed:
  91. #endif
  92.     st    %i7,[%g1+is_in_kernel]    ! Enter kernel again
  93.     save    %sp,-SA(SCHED_WINDOW),%sp    ! Get a new window
  94. pthread_sched_no_save:
  95.     ld    [%g1+pthread_self],%l0    ! Get current thread
  96.     sethi    %hi(NAME(errno)),%l5        ! Get high addr of process errno
  97.     ld    [%g1+ready_head],%i0    ! Load new thread
  98.  
  99.     ld    [%l0+state],%l2        ! Get the current context state
  100.  
  101.     mov    %g1,%l3            ! Do not lose address of kernel
  102.     call    NAME(pthread_signonemptyset)!    pthread_signonemptyset(
  103.     add    %g1, new_signals, %o0    ! Delay: &new_signals);
  104.     mov    %l3,%g1            ! Do not lose address of kernel
  105.     
  106.     btst    T_RETURNED,%l2        ! Returned?
  107.     be    test_old        ! No, save old state and restore new
  108.     mov    %o0, %l4        ! Delay: pending signals
  109.  
  110.     ta    ST_FLUSH_WINDOWS
  111.  
  112.     btst    T_DETACHED,%l2        ! Both returned and detached?
  113.     be    test_new        ! No, restore the new state
  114.     tst    %l4            ! Delay: Test if signals pending
  115.     mov    %g1,%l3            ! Delay: Do not lose address of kernel
  116.  
  117. ! Free the stack of the current context.
  118. ! But before, switch to a temporary stack in case the OS really takes away
  119. ! our thread stack (which it does when sbrk() is called with a negative
  120. ! argument). The temporary stack must be large enough to accommodate the
  121. ! calling chain of the free() routines itself.
  122.  
  123. dealloc:
  124.     sethi    %hi(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%l1
  125.     add    %l1,%lo(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%sp
  126. #if defined(MALLOC) || defined(STAND_ALONE)
  127.     call    NAME(pthread_free)
  128. #else !(MALLOC || STAND_ALONE)
  129.     call    NAME(free)
  130. #endif MALLOC || STAND_ALONE
  131.     ld    [%l0+stack_base],%o0    ! Delay slot - Free the stack
  132.  
  133. ! Free the thread structure for the current thread.  After this, we must be
  134. ! careful not to store a context into it.
  135. #ifndef STAND_ALONE
  136. #ifdef MALLOC
  137.     call    NAME(pthread_free)
  138. #else !MALLOC
  139.     call    NAME(free)
  140. #endif MALLOC
  141.     mov    %l0,%o0            ! Delay slot
  142. #endif !STAND_ALONE
  143.  
  144.     mov    %l3, %g1        ! Do not lose address of kernel
  145.  
  146.     st    %g0, [%g1+pthread_self]    ! mac_pthread_self() =
  147.     clr    %l0            !   old = NO_PTHREAD;
  148.  
  149.     b    test_new        ! Skip save
  150.     tst    %l4            ! Delay: Test if signals pending
  151. test_old:
  152.     cmp    %l0,%i0
  153.     bne    save_old        ! Jump if new thread on head of ready
  154.     tst    %l4            ! Delay: Test if signals pending
  155.     be    no_switch        ! Jump if no pending signals
  156.                     ! Delay: Load high interrupt ret addr
  157.         sethi    %hi(NAME(called_from_sighandler)),%g2
  158. save_old:
  159.     ta    ST_FLUSH_WINDOWS
  160.  
  161.     ld    [%l5+%lo(NAME(errno))],%l6    ! Get errno
  162.     st    %l6,[%l0+thread_errno]    ! Save errno of current thread
  163.     std    %fp,[%l0+sp_offset]    ! Save the current stack pointer
  164. !impl.    st    %i7,[%l0+pc_offset]    ! Save the current return pc
  165. test_new:
  166.                     ! Jump if signals pending
  167.     bne    handle_pending_signals
  168.     tst    %i0
  169.     be    no_threads        ! Jump if no thread on ready queue
  170.     .empty                ! Label Ok in delay slot
  171. restore_new:
  172.                     ! (Delay:) Load high interrupt ret addr
  173.         sethi    %hi(NAME(called_from_sighandler)),%g2
  174.     ld    [%i0+thread_errno],%l6    ! Errno of new thread
  175.     st    %l6,[%l5+%lo(NAME(errno))]    ! Save errno
  176.         ldd     [%i0+sp_offset],%fp     ! Load the new stack pointer
  177. !impl.    ld    [%i0+pc_offset],%i7    ! Load the new pc
  178. no_switch:
  179. #ifdef DEF_RR
  180.     ld    [%i0+sched],%l0        ! Load schedular attribute
  181.      cmp    %l0,SCHED_RR        ! Is it RR (round-robin) ?
  182.      bne    no_rr            ! Do not set timer for RR
  183.                     ! Delay: Load low interrupt ret address
  184.         or    %g2,%lo(NAME(called_from_sighandler)),%g2
  185.     mov    %g1,%l3            ! Do not lose the address of kernel
  186.      mov    %i0,%o0            ! Move parameter - thread_t
  187.      call    NAME(pthread_timed_sigwait)    ! Set the timer for RR
  188.      mov    RR_TIME,%o2        ! Move parameter - Mode
  189.     mov    %l3,%g1            ! Do not lose the address of kernel
  190.                                         ! Load high interrupt return addr
  191.         sethi    %hi(NAME(called_from_sighandler)),%g2
  192. #endif
  193.                     ! Load low interrupt return address
  194.         or    %g2,%lo(NAME(called_from_sighandler)),%g2
  195. #ifdef DEF_RR
  196. no_rr:
  197. #endif
  198.     cmp    %g2,%i7            ! Compare pc-map with new pc
  199.     bne    skip_sig1        ! Jump if mask not interrupt return
  200.     st    %i0,[%g1+pthread_self]    ! Delay: Store new thread
  201.     mov    %g1, %l3        ! Do not lose address of kernel
  202.     mov    SIG_BLOCK, %o0        ! param 0: block
  203.     add    %g1, all_signals, %o1    ! param 1: all signals
  204.     DISABLE_INTERRUPTS        ! Disable signals
  205.     clr    %o2            ! Delay: param 2
  206.     mov    %l3, %g1        ! Do not lose address of kernel
  207.  
  208.  
  209. ! Return into the new context.  Since all windows have been flushed, the
  210. ! RESTORE will cause a window underflow trap, restoring the registers of the
  211. ! new context from its stack.
  212. skip_sig1:
  213.     restore
  214.     st    %g0,[%g1+state_change]    ! Clear state_change flag
  215.     st    %g0,[%g1+is_in_kernel]    ! Clear kernel flag
  216.  
  217.     save    %sp,-SA(SCHED_WINDOW),%sp    ! Get a new window
  218.     call    NAME(pthread_signonemptyset)!    pthread_signonemptyset(
  219.     add    %g1, new_signals, %o0    ! Delay: &new_signals);
  220.  
  221.     tst    %o0            ! Any signals received while in kernel?
  222.     bne    sig_pending
  223.     restore
  224.  
  225.     retl                ! Activate new thread
  226.     nop
  227. sig_pending:
  228.     set    NAME(pthread_kern), %g1
  229.     st    %i7,[%g1+is_in_kernel]    ! Enter kernel again
  230.     save    %sp,-SA(SCHED_WINDOW),%sp    ! Get a new window
  231.  
  232.     ld    [%g1+pthread_self],%l0    ! Get current thread
  233.  
  234.     sethi    %hi(NAME(errno)),%l5        ! Get (high) address of process errno
  235.     ld    [%l5+%lo(NAME(errno))],%l6    ! Get errno
  236.     st    %l6,[%l0+thread_errno]    ! Save errno of current thread
  237.     std    %fp,[%l0+sp_offset]    ! Save the current stack pointer
  238. !impl.    st    %i7,[%l0+pc_offset]    ! Save the current return pc
  239.  
  240.                                         ! Load interrupt return address
  241.         set     NAME(called_from_sighandler),%g2
  242.     cmp    %g2,%i7            ! Compare pc-map w/ new pc again
  243.     bne    skip_sig2        ! Jump if mask not interrupt return
  244.     mov    %g1,%l3            ! Delay: Do not lose address of kernel
  245.  
  246.     mov    SIG_UNBLOCK, %o0    ! param 0: unblock
  247.     add    %g1, all_signals, %o1    ! param 1: all signals
  248.     ENABLE_INTERRUPTS        ! Enable signals
  249.     clr    %o2            ! Delay: param 2
  250.  
  251. skip_sig2:
  252.     ta    ST_FLUSH_WINDOWS
  253.  
  254.     ba,a    kern_saved        ! Ignore Delay: Jump always
  255.  
  256. handle_pending_signals:
  257. no_threads:
  258.     mov     %g1,%l3            ! Do not lose address of kernel
  259.  
  260. kern_saved:
  261.                     ! Get temp. stack address
  262.     sethi    %hi(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%l1
  263.     call    NAME(pthread_handle_many_process_signals)
  264.     add    %l1,%lo(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%sp
  265.     cmp    %g0,%l0            ! test if deallocated
  266.     bne    restore_stack        ! No
  267.     nop                ! Delay:
  268.     mov    %o0,%l0            ! Copy return Val (ready.head) to %l0
  269. restore_stack:
  270.     ld    [%l0+sp_offset],%l2    ! Switch back to stack of thread
  271.     add    %l2,-SA(SCHED_WINDOW),%sp
  272.     mov    %o0,%i0            ! Move ret val from call into i0
  273.  
  274.     cmp    %l0,%i0            ! Thread at the head of ready?
  275.     be    restore_new        ! Jump if so
  276.     mov    %l3, %g1        ! Do not lose address of kernel
  277.     ld    [%l0+state],%l2        ! Get the current context state
  278.     btst    T_RETURNED,%l2        ! Returned?
  279.     be    restore_new        ! No, restore the new state
  280.     btst    T_DETACHED,%l2        ! Delay: both returned and detached?
  281.     be    restore_new        ! No, restore the new state
  282.     nop
  283.  
  284.     call    NAME(pthread_signonemptyset)!    pthread_signonemptyset(
  285.     add    %g1, new_signals, %o0    ! Dealy: &new_signals);
  286.     
  287.     b    dealloc            ! Free structures
  288.     mov    %o0, %l4        ! Delay: pending signals
  289.  
  290. #ifndef STAND_ALONE
  291. !    void pthread_sched_wrapper(sig, code)
  292. !    int sig;
  293. !    int code;
  294. !
  295. !    wrapper for pthread_sched() to determine the pc
  296. !    called from the sighandler()
  297. !    calls pthread_sched() and provides a global address for this call
  298. !    which can be used by pthread_sched() to determine if it is about
  299. !    to switch context to an interrupted thread (by comparing the
  300. !    return value with the global address NAME(called_from_sighandler).
  301.         .global  NAME(called_from_sighandler)
  302.         .global  NAME(pthread_sched_wrapper)
  303. NAME(pthread_sched_wrapper):
  304.     save    %sp,-SA(MINFRAME),%sp    ! Get a new window.
  305.  
  306.     mov    %i1, %o1        ! Delay: Pass parameter 2
  307. NAME(called_from_sighandler):        ! Address of call instruction
  308.     call    NAME(pthread_signal_sched) ! Call 2nd dispatcher (handle signal)
  309.     mov    %i0, %o0        ! Delay: Pass parameter 1
  310. is_longjmp:
  311.     ret
  312.     restore
  313. #endif !STAND_ALONE
  314.  
  315. !       int pthread_not_called_from_sighandler(addr)
  316. !       int addr;
  317. !
  318. !       returns FALSE iff the address passed in corresponds to the sighandler
  319.         ENTRY(pthread_not_called_from_sighandler)
  320.         set     NAME(called_from_sighandler),%o1
  321.         retl
  322.         sub     %o0,%o1,%o0             ! Delay: return difference of param
  323.                                         ! and sighandler return address
  324.  
  325. !    void pthread_fake_call_wrapper(user_handler, smask, sig, infop, scp,
  326. !                   restore_context, oscp, cond)
  327. !    void (*user_handler)();
  328. !    sigset_t *smask;
  329. !    int sig;
  330. !    struct siginfo *infop;
  331. !    struct sigcontext *scp, *oscp;
  332. !    int new_context;
  333. !    pthread_cond_t *cond;
  334. !
  335. !       If the conditional variable pointer is non-null, the pending
  336. !    conditional wait terminates and the mutex is relocked
  337. !    before the user handler is called. This is only done once for
  338. !    nested handlers by the innermost handler (see check for zero-value
  339. !    of the condition variable).
  340. !    Then the user handler is called with parameters sig, infop, scp.
  341. !    The errno is saved across the user handler call.
  342.  
  343. !    Notice that the frame of this wrapper is already put the
  344. !    stack by fake_call, therefore, we should NOT use "save" to
  345. !    get a new window.
  346. !    Notice that the address of the condition variable is
  347. !       passed(!) in %l6 if the signal came in during a conditional wait.
  348. !    Notice that oscp is passed(!) in %l7 and is restored as p->nscp
  349. !    upon return from the wrapper.
  350.     ENTRY(pthread_fake_call_wrapper)
  351.     sethi    %hi(NAME(errno)), %l0! Get process errno (high)
  352.     ld    [%l6], %l6    ! Get condition variable
  353.     tst    %l6        ! Cond. var. == 0 ?
  354.     be    no_cond_wait
  355.                 ! Delay: Get process errno (low)
  356.     ld    [%l0+%lo(NAME(errno))], %l3
  357.                 ! Terminate cond. wait
  358.     call    NAME(pthread_cond_wait_terminate)
  359.     .empty                ! Label Ok in delay slot
  360. no_cond_wait:
  361.                 ! Delay: omask = smask + sizeof(sigset_t);
  362.     add    %i1, sigset_t_size, %l2
  363.  
  364.     mov    %l2, %o0    ! pthread_sigcpyset2set(omask, &scp->mask);
  365.     call    NAME(pthread_sigcpyset2set)
  366.     add    %i4, sc_mask, %o1
  367.  
  368.     mov    %i2, %o0
  369.     mov    %i3, %o1
  370.     call    %i0        ! user_signal_handler(sig, infop, scp);
  371.     mov    %i4, %o2
  372.  
  373.                 ! Get base address of kernel structure
  374.     set    NAME(pthread_kern), %l4
  375.                 ! Enter kernel again
  376.     st    %i7, [%l4+is_in_kernel]
  377.     ld    [%l4+pthread_self], %i3
  378.     tst    %i5        ! Check if context needs to be restored
  379.     be    UNIX_restore
  380.                 ! Delay: Restore errno
  381.     st    %l3, [%l0+%lo(NAME(errno))]
  382.     mov    %i1, %o0    ! pthread_sigcpyset2set(smask, &scp->sc_mask);
  383.     call    NAME(pthread_sigcpyset2set)
  384.     add    %i4, sc_mask, %o1
  385.  
  386.     ld    [%i4+sc_sp], %fp! Load stack pointer to be restored
  387.     ld    [%i4+sc_pc], %i7! Load program counter to be restored
  388.     ba    context_restored
  389.                 ! Delay: Subtract offset added by ret instr
  390.     add    %i7, -RETURN_OFFSET, %i7
  391.  
  392. UNIX_restore:
  393.     mov    %i1, %o0    ! pthread_sigcpyset2set(smask, &scp->sc_mask);
  394.     call    NAME(pthread_sigcpyset2set)
  395.     add    %i4, sc_mask, %o1
  396.                 ! pthread_sigcpyset2set(&scp->sc_mask, omask);
  397.     add    %i4, sc_mask, %o0
  398.     call    NAME(pthread_sigcpyset2set)
  399.     mov    %l2, %o1
  400.     
  401. context_restored:
  402.     add    %i3, mask, %o0    ! pthread_sigcpyset2set(&p->mask, smask);
  403.     call    NAME(pthread_sigcpyset2set)
  404.     mov    %i1, %o1
  405.  
  406.     mov    %i1, %o1    ! pthread_sigcpyset2set(smask,&p->pending);
  407.     call    NAME(pthread_sigcpyset2set)
  408.     add    %i3, pending, %o1
  409.  
  410.     mov    %i1, %o1    ! pthread_sigaddset2set(smask,&pending_signals);
  411.     call    NAME(pthread_sigaddset2set)
  412.     add    %l4, pending_signals, %o1
  413.  
  414.     mov    %i1, %o1    ! pthread_sigdelset2set(smask,&p->mask);
  415.     call    NAME(pthread_sigdelset2set)
  416.     add    %i3, mask, %o1
  417.                 ! if (pthread_signonemptyset(smask))
  418.     call    NAME(pthread_signonemptyset)
  419.     mov    %i1, %o1
  420.  
  421.     tst    %o0
  422.         be      not_pending     ! Any pending signal cleared ?
  423.     mov    %l4, %g1    ! save kernel address
  424.                 ! If branch, leave kernel but stick
  425.                 ! with current frame
  426.  
  427.                 ! Handle signals pending on thread
  428.     call    NAME(pthread_handle_pending_signals_wrapper)
  429.     clr    %o0        ! Delay: parameter no initial save
  430.                 ! Should never return to this point
  431. not_pending:                    ! Leave kernel but stick with current frame
  432.         ba      pthread_sched_no_save
  433.     st    %l7, [%i3+nscp]    ! Delay: Copy prev sigcontext into current one    
  434.  
  435. !    void pthread_handle_pending_signals_wrapper(initial_save)
  436. !    int initial_save;
  437. !
  438. !    change to temp stack and call handle_pending_signals()
  439. !    then jumps into regular scheduler
  440. !    creates own frame at beginning or after save thread context
  441. !    depending on initial_save in %i0/%o0
  442. !    assumes SET_KERNEL_FLAG
  443.  
  444.     ENTRY(pthread_handle_pending_signals_wrapper)
  445.                 ! Get the kernel address
  446.     set    NAME(pthread_kern),%g3
  447.     tst    %o0
  448.     be    no_initial_save
  449.     ld    [%g3+pthread_self],%g4    ! Delay: get current thread
  450.  
  451.     save    %sp,-SA(SCHED_WINDOW),%sp    ! Get a new window
  452. no_initial_save:
  453.     sethi    %hi(NAME(errno)),%g1        ! Save the thread context
  454.     ld    [%g1+%lo(NAME(errno))],%g2    ! Get errno
  455.     st    %g2,[%g4+thread_errno]    ! Save errno of current thread
  456.     std    %fp,[%g4+sp_offset]    ! Save the current stack pointer
  457. !impl.    st    %i7,[%g4+pc_offset]    ! Save the current return pc
  458.  
  459.     bne    initial_save
  460.                     ! Delay: load temp. stack address
  461.     sethi    %hi(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%g2
  462.  
  463.     save    %sp,-SA(SCHED_WINDOW),%sp    ! Get a new window
  464. initial_save:
  465.     ta    ST_FLUSH_WINDOWS
  466.  
  467.     mov    %g3, %l3        ! Save kernel address
  468.     mov    %g4, %l0        ! Save pthread_self
  469.     mov    %g1, %l5        ! Save errno address
  470.  
  471.     call    NAME(pthread_handle_pending_signals)
  472.                     ! Delay: switch to _tempstack
  473.     add    %g2,%lo(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%sp
  474.  
  475.     ba    restore_stack
  476.     ld    [%l3+ready_head],%o0        ! Delay: parameter ready.head
  477.  
  478.  
  479.  
  480. !    void pthread_signal_sched(sig, code)
  481. !    int sig;
  482. !    int code;
  483. !
  484. !    change to temp stack and call pthread_handle_one_process_signal(sig)
  485. !    then jumps into regular scheduler
  486. !    This is called by the universal signal handler to minimize calls
  487. !    to set the process signal mask which is an expensive UNIX system call.
  488. !    assumes SET_KERNEL_FLAG
  489.  
  490.     ENTRY(pthread_signal_sched)
  491.     save    %sp,-SA(SCHED_WINDOW),%sp    ! Get a new window
  492.  
  493.     ta    ST_FLUSH_WINDOWS
  494.  
  495.     set    NAME(pthread_kern),%l3    ! Get kernel address
  496.     ld    [%l3+pthread_self],%l0    ! Get current thread
  497.  
  498.     sethi    %hi(NAME(errno)),%l5        ! Save the thread context
  499.     ld    [%l5+%lo(NAME(errno))],%g2    ! Get errno
  500.     st    %g2,[%l0+thread_errno]    ! Save errno of current thread
  501.     std    %fp,[%l0+sp_offset]    ! Save the current stack pointer
  502. !impl.    st    %i7,[%l0+pc_offset]    ! Save the current return pc
  503.  
  504.                     ! Load temp. stack address
  505.     sethi    %hi(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%g2    
  506.     mov    %i0, %o0        ! Parameter 1: signal number
  507.     mov    %i1, %o1        ! Parameter 2: signal code
  508.     call    NAME(pthread_handle_one_process_signal)
  509.                     ! Delay: switch to _tempstack
  510.     add    %g2,%lo(NAME(pthread_tempstack)-SA(WINDOWSIZE)),%sp
  511.  
  512.     ba    restore_stack
  513.     ld    [%l3+ready_head],%o0    ! Delay: parameter ready.head
  514.  
  515.  
  516.     .seg    "bss"            ! Could also use data segment
  517.     .skip   50*SA(MINFRAME)
  518. #ifdef STAND_ALONE
  519.         .align  STACK_ALIGN
  520.     .global    NAME(newstack)
  521. NAME(newstack):
  522. #endif STAND_ALONE
  523. !    Temporary stack space
  524.  
  525.     .skip    SA(MINFRAME)        ! Spare window in case lower windows
  526.                     !   take up more space (e.g. locals)
  527.     .skip    SA(MINFRAME)        ! Universal handler window
  528.     .skip    SA(MINFRAME)        ! UNIX sigtramp window
  529.     .skip    TEMPSTACK_SIZE        ! Calls by handle_many_process_signals
  530. !    .skip    SA(WINDOWSIZE)        ! Handle_many_process_signals window
  531. !    .skip    SA(WINDOWSIZE)        ! Dispatcher window
  532.     .align    STACK_ALIGN
  533. #ifdef STACK_CHECK
  534.     .global    NAME(pthread_tempstack)
  535. #endif STACK_CHECK
  536. NAME(pthread_tempstack):        ! Stack base for dispatcher
  537.     .skip    SA(MINFRAME)        ! Empty previous frame (callee save)
  538.  
  539. #ifdef STAND_ALONE
  540.     .skip    SA(64)            ! Kernel Stack Area for Globals
  541.         .align  STACK_ALIGN
  542.     .global    NAME(global_save_area)
  543. NAME(global_save_area):
  544.     .skip    32
  545.     
  546.     .global    NAME(heap_start)
  547. NAME(heap_start):
  548.     .skip    HEAP_SIZE
  549. #endif STAND_ALONE
  550.  
  551.     .seg    "text"
  552.     .seg    "data"
  553.  
  554. #endif !C_CONTEXT_SWITCH
  555.