sem_timedwait implementation on Linux/SH.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / sh / lowlevelmutex.S
1 /* Copyright (C) 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <sysdep.h>
20 #include "lowlevel-atomic.h"
21
22         .text
23
24 #define SYS_gettimeofday        __NR_gettimeofday
25 #define SYS_futex               240
26 #define FUTEX_WAIT              0
27 #define FUTEX_WAKE              1
28
29 #define EWOULDBLOCK             11
30 #define EINVAL                  22
31 #define ETIMEDOUT               110
32
33
34         .globl  __lll_mutex_lock_wait
35         .type   __lll_mutex_lock_wait,@function
36         .hidden __lll_mutex_lock_wait
37         .align  5
38 __lll_mutex_lock_wait:
39         mov     r4, r6
40         mov     r5, r4
41         mov     #0, r7          /* No timeout.  */
42         mov     #FUTEX_WAIT, r5
43 1:
44         add     #1, r6          /* account for the preceeded xadd.  */
45         mov     #SYS_futex, r3
46         extu.b  r3, r3
47         trapa   #0x14
48         SYSCALL_INST_PAD
49
50         mov     #1, r3
51         XADD (r3, @r4, r6)
52         tst     r6, r6
53         bf      1b
54         mov     #2, r1
55         mov.l   r1, @r4
56         ret
57          mov    #0, r0
58         .size   __lll_mutex_lock_wait,.-__lll_mutex_lock_wait
59
60
61         .globl  __lll_mutex_timedlock_wait
62         .type   __lll_mutex_timedlock_wait,@function
63         .hidden __lll_mutex_timedlock_wait
64         .align  5
65 __lll_mutex_timedlock_wait:
66         /* Check for a valid timeout value.  */
67         mov.l   @(4,r6), r1
68         mov.l   .L1g, r0
69         cmp/hs  r0, r1
70         bt      3f
71
72         mov.l   r10, @-r15
73         mov.l   r9, @-r15
74         mov.l   r8, @-r15
75         mov     r5, r8
76         mov     r6, r9
77         mov     r4, r10
78         add     #1, r10
79
80         /* Stack frame for the timespec and timeval structs.  */
81         add     #-8, r15
82
83 1:
84         /* Get current time.  */
85         mov     r15, r4
86         mov     #0, r5
87         mov     #SYS_gettimeofday, r3
88         trapa   #0x12
89         SYSCALL_INST_PAD
90
91         /* Compute relative timeout.  */
92         mov.l   @(4,r15), r0
93         mov.w   .L1k, r1
94         dmulu.l r0, r1          /* Micro seconds to nano seconds.  */
95         mov.l   @r9, r2
96         mov.l   @(4,r9), r3
97         mov.l   @r15, r0
98         sts     macl, r1
99         sub     r0, r2
100         clrt
101         subc    r1, r3
102         bf      4f
103         mov.l   .L1g, r1
104         add     r1, r3
105         add     #-1, r2
106 4:
107         cmp/pz  r2
108         bf      5f              /* Time is already up.  */
109
110         mov.l   r2, @r15        /* Store relative timeout.  */
111         mov.l   r3, @(4,r15)
112
113         mov     r8, r4
114         mov     #FUTEX_WAIT, r5
115         mov     r10, r6
116         mov     r15, r7
117         mov     #SYS_futex, r3
118         extu.b  r3, r3
119         trapa   #0x14
120         SYSCALL_INST_PAD
121
122         mov     #1, r3
123         XADD (r3, @r8, r10)
124         tst     r10, r10
125         bf      7f
126
127         mov     #2, r1
128         mov.l   r1, @r8
129         mov     #0, r0
130 6:
131         add     #8, r15
132         mov.l   @r15+, r8
133         mov.l   @r15+, r9
134         rts
135          mov.l  @r15+, r10
136 7:
137         /* Check whether the time expired.  */
138         mov     #-ETIMEDOUT, r1
139         cmp/eq  r0, r1
140         bt      5f
141         bra     1b
142          nop
143 3:
144         rts
145          mov    #EINVAL, r0
146 5:
147         bra     6b
148          mov    #ETIMEDOUT, r0
149
150 .L1k:
151         .word   1000
152         .align  2
153 .L1g:
154         .long   1000000000
155
156         .size   __lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait
157
158
159         .globl  __lll_mutex_unlock_wake
160         .type   __lll_mutex_unlock_wake,@function
161         .hidden __lll_mutex_unlock_wake
162         .align  5
163 __lll_mutex_unlock_wake:
164         mov     #FUTEX_WAKE, r5
165         mov     #1, r6          /* Wake one thread.  */
166         mov     #0, r7
167         mov.l   r7, @r4         /* Stores 0.  */
168         mov     #SYS_futex, r3
169         extu.b  r3, r3
170         trapa   #0x14
171         SYSCALL_INST_PAD
172         rts
173          nop
174         .size   __lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake