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_opt.S < prev    next >
Text File  |  1996-09-28  |  9KB  |  305 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_opt.S    2.5 4/12/95
  26.  
  27. */
  28.  
  29. /*
  30.  * Optional assembly routines for speed
  31.  *
  32.  * Portability notes:
  33.  * The assembly code in this file is only needed for the following conditional
  34.  * compilation:
  35.  * STAND_ALONE:   exit
  36.  * ASM_SETJMP:    [sig]set/longjmp (if not defined, C lib set/longjmp is used).
  37.  * NOERR_CHECK:   fast mutex [un]locking (for slower version in C,
  38.  *                do NOT defined -DNOERR_CHECK).
  39.  * !CLEANUP_HEAP: cleanup handlers on stack (for slow version on heap,
  40.  *                define CLEANUP_HEAP).
  41.  */
  42.  
  43. #include <pthread/config.h>
  44. #include <../src/config_internals.h>
  45.  
  46. #define LOCORE
  47. #define _ASM
  48.  
  49. #ifdef SOLARIS
  50. #include <sys/asm_linkage.h>
  51. #define NAME(x) x
  52. #else !SOLARIS
  53. #include <sparc/asm_linkage.h>
  54. #endif !SOLARIS
  55.  
  56. #include <sys/errno.h>
  57.  
  58. #include <pthread/unistd.h>
  59. #include "pthread_offsets.h"
  60. #include <pthread/pthread_asm.h>
  61.  
  62. #ifdef STAND_ALONE
  63. #include <sun4e/trap.h>
  64. #else !STAND_ALONE
  65. #ifdef SOLARIS
  66. #include <sys/trap.h>
  67. #else !SORLARIS
  68. #include <sparc/trap.h>
  69. #endif !SOLARIS
  70. #endif !STAND_ALONE
  71.  
  72. #ifdef STAND_ALONE
  73. !
  74. ! exit() - exits to ROM Monitor by s/w trap 255.
  75. !
  76.  
  77.     ENTRY(exit)
  78.     t    ST_MON_BREAKPOINT    ! Termination
  79. #endif STAND_ALONE
  80.  
  81. #ifdef ASM_SETJMP
  82. !    int setjmp(env)
  83. !    jmp_buf env;
  84. !
  85. !    setjmp - set up jump environment across procedures, preserve signal mask
  86. !    longjmp() will return to this place and supply a return value
  87.     ENTRY(setjmp)
  88.     b    NAME(sigsetjmp)        ! sigsetjmp(env, TRUE);
  89.     mov    %sp,%o1
  90.  
  91. !    int sigsetjmp(env, savemask)
  92. !    sigjmp_buf env;
  93. !    int savemask;
  94. !
  95. !    sigsetjmp - set up jump environment across procedures,
  96. !    preserve signal mask if savemask non-zero
  97. !    siglongjmp() will return to this place and supply a return value
  98.     ENTRY(sigsetjmp)
  99.     save    %sp,-SA(MINFRAME),%sp    ! Get a new window
  100.      ta    ST_FLUSH_WINDOWS    ! Make sure the registers are saved
  101.     st    %fp,[%i0+jmp_sp]    ! Save stack pointer of previous frame
  102.     set    NAME(pthread_kern),%l2    ! Get kernel address
  103.     st    %i1,[%i0+jmp_svmask]    ! env[JB_SVMASK] = TRUE;
  104.     tst    %i1            ! savemask == 0 ?
  105.     be    sigsetjmp_nomask
  106.     st    %i7,[%i0+jmp_pc]    ! Delay: Save return PC
  107.     ld    [%l2+pthread_self],%l2    ! Get current thread
  108.     add    %l2, mask, %o1        ! Copy thread mask
  109. sigsetjmp_savemask:
  110.     call    NAME(pthread_sigcpyset2set)
  111.     add    %i0, jmp_mask, %o0
  112. sigsetjmp_nomask:
  113.     clr    %i0
  114.     ret
  115.     restore
  116.  
  117. !    void longjmp(env, val)
  118. !    jmp_buf env;
  119. !    int val;
  120. !
  121. !    longjmp - execute jump across procedures according to save environment
  122. !    and return specified value at corresponding setjmp().
  123. !
  124. !    implemented as alias og siglongjmp (see below)
  125.  
  126. !    void siglongjmp(env, val)
  127. !    sigjmp_buf env;
  128. !    int val;
  129. !
  130. !    siglongjmp - exec. jump across procedures according to save environment
  131. !    and return specified value at corresponding sigsetjmp().
  132.     ENTRY(longjmp)
  133.     ENTRY(siglongjmp)
  134.     save    %sp,-SA(MINFRAME),%sp    ! Get a new window
  135.     ta    ST_FLUSH_WINDOWS
  136.     ld    [%i0+jmp_sp],%fp    ! Restore stack pointer
  137.  
  138.     ld    [%i0+jmp_svmask],%l1    ! if (env[JB_SVMASK])
  139.     tst    %l1
  140.     bz    siglongjmp_nomask
  141.     mov    SIG_SETMASK, %o0    ! Delay: Parameter 0: SIG_SETMASK
  142.     add    %i0, jmp_mask, %o1    ! Parameter 1: &env->mask
  143.     call    NAME(sigprocmask)
  144.     clr    %o2            ! Delay: Parameter 2: NULL
  145. siglongjmp_nomask:
  146.     orcc    %i1,%g0,%o0        ! val == 0 ?
  147.     bne    siglongjmp_ret
  148.     ld    [%i0+jmp_pc],%i7    ! Delay: Restore return PC
  149.     mov    1,%o0            ! val = 1
  150. siglongjmp_ret:
  151.     ret                ! return(val);
  152.     restore    %o0, 0, %o0
  153. #endif ASM_SETJMP
  154.  
  155. #ifdef NOERR_CHECK
  156. !    int pthread_mutex_lock(mutex)
  157. !    pthread_mutex_t *mutex;
  158. !
  159. !    When mutex can be locked immediately, execute as leaf;
  160. !    otherwise call C routine to suspend.
  161.     ENTRY(pthread_mutex_lock)
  162. #ifdef _POSIX_THREADS_PRIO_PROTECT
  163.                                         ! load protocol type of mutex
  164.     ld      [%o0+mutex_protocol],%o1
  165.     cmp     %o1, PRIO_PROTECT    ! test if PRIO_PROTECT
  166.     be      slow_lock               ! yes
  167.     nop                             ! Delay
  168. #endif _POSIX_THREADS_PRIO_PROTECT
  169.     ldstub    [%o0+mutex_lock],%o1    ! test_and_set(&mutex->lock)
  170.     tst    %o1            ! prev. lock == 0 ?
  171.     bne    mutex_locked
  172.     sethi    %hi(NAME(pthread_kern)),%o1    ! Get kernel address    
  173.     or    %o1,%lo(NAME(pthread_kern)),%o1
  174.     ld    [%o1+pthread_self],%o1
  175.     st    %o1,[%o0+mutex_owner]    ! mutex->owner = mac_pthread_self()
  176.     retl
  177.     clr    %o0            ! return(0);
  178. #ifdef _POSIX_THREADS_PRIO_PROTECT
  179. slow_lock:
  180. #endif _POSIX_THREADS_PRIO_PROTECT
  181. mutex_locked:
  182.     save    %sp,-SA(MINFRAME),%sp    ! Get a new window
  183.     call    NAME(slow_mutex_lock)    ! return(slow_mutex_lock(mutex));
  184.     mov    %i0, %o0        ! Delay: Pass parameter
  185.     mov    %o0, %i0        ! Return value
  186.     ret
  187.     restore
  188.  
  189. !    int pthread_mutex_trylock(mutex)
  190. !    pthread_mutex_t *mutex;
  191. !
  192. !    When mutex can be locked immediately, execute as leaf and return 1;
  193. !    otherwise return 0
  194.     ENTRY(pthread_mutex_trylock)
  195. #ifdef _POSIX_THREADS_PRIO_PROTECT
  196.                                         ! load protocol type of mutex
  197.     ld      [%o0+mutex_protocol],%o1
  198.     cmp     %o1, PRIO_PROTECT    ! test if PRIO_PROTECT
  199.     bne     fast_trylock        ! yes
  200.     nop                             ! Delay
  201.     save    %sp,-SA(MINFRAME),%sp    ! Get a new window
  202.     call    NAME(slow_mutex_trylock)! return(slow_mutex_lock(mutex));
  203.     mov    %i0, %o0        ! Delay: Pass parameter
  204.     mov    %o0, %i0        ! Return value
  205.     ret
  206.     restore
  207. fast_trylock:
  208. #endif _POSIX_THREADS_PRIO_PROTECT
  209.     ldstub    [%o0+mutex_lock],%o1    ! test_and_set(&mutex->lock)
  210.     tst    %o1            ! prev. lock == 0 ?
  211.     bne    mutex_trylocked
  212.     sethi    %hi(NAME(pthread_kern)),%o1    ! Get kernel address    
  213.     or    %o1,%lo(NAME(pthread_kern)),%o1
  214.     ld    [%o1+pthread_self],%o1
  215.     st    %o1,[%o0+mutex_owner]    ! mutex->owner = mac_pthread_self()
  216.     retl
  217.     clr    %o0            ! return(0);
  218. mutex_trylocked:
  219.     set    NAME(errno),%o1        ! errno = EBUSY;
  220.     mov    EBUSY,%o0
  221.     st    %o0,[%o1]
  222.     retl
  223.     mov    -1,%o0        ! return(-1);
  224.  
  225. !    int pthread_mutex_unlock(mutex)
  226. !    pthread_mutex_t *mutex;
  227. !
  228. !    When mutex can be unlocked immediately, execute as leaf;
  229. !    otherwise call C routine to wakeup a thread blocked on the mutex
  230.     ENTRY(pthread_mutex_unlock)
  231. #ifdef _POSIX_THREADS_PRIO_PROTECT
  232.                                         ! load protocol type of mutex
  233.     ld      [%o0+mutex_protocol],%o1
  234.     cmp     %o1, PRIO_PROTECT    ! test if PRIO_PROTECT
  235.     be      slow_unlock             ! yes
  236.     nop                             ! Delay
  237. #endif _POSIX_THREADS_PRIO_PROTECT
  238.     ld    [%o0+mutex_queue],%o1
  239.     tst    %o1            ! mutex->queue.head == NULL ?
  240.     bne    mutex_unlocked
  241.     st    %g0,[%o0+mutex_owner]    ! Delay: mutex->owner = NO_PTHREAD;
  242.     st    %g0,[%o0+mutex_lock]    ! mutex->lock = FALSE;
  243.     ld    [%o0+mutex_queue],%o1
  244.     tst    %o1            ! mutex->queue.head == NULL ?
  245.     bne    queue_unlocked
  246.     nop
  247. ret_unlocked:
  248.     retl
  249.     clr    %o0            ! return(0);
  250. queue_unlocked:
  251.     ldstub    [%o0+mutex_lock],%o1    ! test_and_set(&mutex->lock)
  252.     tst    %o1            ! prev. lock == 0 ?
  253.     bne    ret_unlocked
  254.     nop
  255. #ifdef _POSIX_THREADS_PRIO_PROTECT
  256. slow_unlock:
  257. #endif _POSIX_THREADS_PRIO_PROTECT
  258. mutex_unlocked:
  259.     save    %sp,-SA(MINFRAME),%sp    ! Get a new window
  260.     call    NAME(slow_mutex_unlock)    ! return(slow_mutex_unlock(mutex));
  261.     mov    %i0, %o0        ! Pass parameter
  262.     mov    %o0, %i0        ! Return value
  263.     ret
  264.     restore
  265. #endif NOERR_CHECK
  266.  
  267. #ifndef CLEANUP_HEAP
  268. !    int pthread_cleanup_push(func, arg)
  269. !    void (*func)();
  270. !    any_t arg;
  271. !
  272. !    Get space on stack for cleanup structure (new) and then call
  273. !    pthread_cleanup_push_body with this "new"
  274.     ENTRY(pthread_cleanup_push)
  275.                     ! Get space for cleanup     
  276. #ifndef C_INTERFACE
  277.     add    %sp,-SA(cleanup_size+SA(MINFRAME)-WINDOWSIZE),%sp
  278. #else    !C_INTERFACE
  279.     add    %sp,-SA(cleanup_size),%sp
  280. #endif    !C_INTERFACE
  281.     b    NAME(pthread_cleanup_push_body)
  282.     add    %sp,SA(MINFRAME),%o2    ! Delay: param 3 "new"
  283. !     Should never reach here
  284.  
  285. !    int pthread_cleanup_pop(execute)
  286. !    int execute;
  287. !
  288. !    Remove space from stack for cleanup structure (new) and 
  289. !    then call pthread_cleanup_pop_body.
  290.     ENTRY(pthread_cleanup_pop)
  291.     save    %sp,-SA(MINFRAME),%sp    ! Get a new frame
  292.     call    NAME(pthread_cleanup_pop_body)
  293.     mov    %i0, %o0        ! Delay: param 1
  294.                     ! Remove space for cleanup     
  295.     restore                ! Restore here, otherwise %sp
  296.                     !   increment does not work.
  297.     retl                ! Leaf return - already restored.
  298. #ifndef C_INTERFACE
  299.                     ! Delay: restore prev. stack pointer
  300.     add    %sp,SA(cleanup_size+SA(MINFRAME)-WINDOWSIZE),%sp
  301. #else    !C_INTERFACE
  302.     add    %sp,SA(cleanup_size),%sp
  303. #endif !C_INTERFACE
  304. #endif !CLEANUP_HEAP
  305.