8d682d94c046483d661956e8d275ab4891a9dc6e
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / i486 / lowlevelrwlock.S
1 /* Copyright (C) 2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.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 EAGAIN          11
30 #define EDEADLK         35
31 #define ETIMEDOUT       110
32
33 /* Offsets in the pthread_rwlock_t structure.  */
34 #define MUTEX           0
35 #define NR_READERS      4
36 #define READERS_WAKEUP  8
37 #define WRITERS_WAKEUP  12
38 #define READERS_QUEUED  16
39 #define WRITERS_QUEUED  20
40 #define FLAGS           24
41 #define WRITER  28
42
43 #ifndef UP
44 # define LOCK lock
45 #else
46 # define LOCK
47 #endif
48
49
50         .globl  __pthread_rwlock_rdlock
51         .type   __pthread_rwlock_rdlock,@function
52         .align  16
53 __pthread_rwlock_rdlock:
54         pushl   %esi
55         pushl   %ebx
56
57         xorl    %esi, %esi
58         xorl    %edx, %edx
59         movl    12(%esp), %ebx
60
61         /* Get the lock.  */
62         movl    $1, %eax
63         LOCK
64         xaddl   %eax, MUTEX(%ebx)
65         testl   %eax, %eax
66         jne     1f
67
68 2:      movl    WRITER(%ebx), %eax
69         testl   %eax, %eax
70         jne     14f
71         cmp     $0, WRITERS_QUEUED(%ebx)
72         je      5f
73         cmpl    $0, FLAGS(%ebx)
74         je      5f
75
76 3:      incl    READERS_QUEUED(%ebx)
77         je      4f
78
79         LOCK
80         decl    MUTEX(%ebx)
81         jne     10f
82
83 11:     addl    $READERS_WAKEUP-MUTEX, %ebx
84         movl    %esi, %ecx      /* movl $FUTEX_WAIT, %ecx */
85         movl    $SYS_futex, %eax
86         int     $0x80
87
88         subl    $READERS_WAKEUP-MUTEX, %ebx
89
90         /* Reget the lock.  */
91         movl    $1, %eax
92         LOCK
93         xaddl   %eax, MUTEX(%ebx)
94         testl   %eax, %eax
95         jne     12f
96
97 13:     decl    READERS_QUEUED(%ebx)
98         jne     2b
99         movl    $0, READERS_WAKEUP(%ebx)
100         jmp     2b
101
102 5:      xorl    %ecx, %ecx
103         incl    NR_READERS(%ebx)
104         je      8f
105 9:      LOCK
106         decl    MUTEX(%ebx)
107         jne     6f
108 7:
109
110         movl    %ecx, %eax
111         popl    %ebx
112         popl    %esi
113         ret
114
115 1:      movl    %ebx, %ecx
116         call    __lll_mutex_lock_wait
117         jmp     2b
118
119 14:     cmpl    %gs:8, %eax
120         jne     3b
121         /* Deadlock detected.  */
122         movl    $EDEADLK, %ecx
123         jmp     9b
124
125 6:      movl    %ebx, %eax
126         call    __lll_mutex_unlock_wake
127         jmp     7b
128
129         /* Overflow.  */
130 8:      decl    NR_READERS(%ebx)
131         movl    $EAGAIN, %ecx
132         jmp     9b
133
134         /* Overflow.  */
135 4:      decl    READERS_QUEUED(%ebx)
136         movl    $EAGAIN, %ecx
137         jmp     9b
138
139 10:     movl    %ebx, %eax
140         call    __lll_mutex_unlock_wake
141         jmp     11b
142
143 12:     movl    %ebx, %ecx
144         call    __lll_mutex_lock_wait
145         jmp     13b
146         .size   __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
147
148         .globl  pthread_rwlock_rdlock
149 pthread_rwlock_rdlock = __pthread_rwlock_rdlock
150
151
152         .globl  pthread_rwlock_timedrdlock
153         .type   pthread_rwlock_timedrdlock,@function
154         .align  16
155 pthread_rwlock_timedrdlock:
156         pushl   %esi
157         pushl   %edi
158         pushl   %ebx
159         pushl   %ebp
160         subl    $8, %esp
161
162         movl    28(%esp), %ebp
163         movl    32(%esp), %edi
164
165         /* Get the lock.  */
166         movl    $1, %eax
167         LOCK
168         xaddl   %eax, MUTEX(%ebp)
169         testl   %eax, %eax
170         jne     1f
171
172 2:      movl    WRITER(%ebp), %eax
173         testl   %eax, %eax
174         jne     14f
175         cmp     $0, WRITERS_QUEUED(%ebp)
176         je      5f
177         cmpl    $0, FLAGS(%ebp)
178         je      5f
179
180 3:      incl    READERS_QUEUED(%ebp)
181         je      4f
182
183         LOCK
184         decl    MUTEX(%ebp)
185         jne     10f
186
187         /* Get current time.  */
188         movl    %esp, %ebx
189         xorl    %ecx, %ecx
190         movl    $SYS_gettimeofday, %eax
191         int     $0x80
192
193         /* Compute relative timeout.  */
194         movl    4(%esp), %eax
195         movl    $1000, %edx
196         mul     %edx            /* Milli seconds to nano seconds.  */
197         movl    (%edi), %ecx
198         movl    4(%edi), %edx
199         subl    (%esp), %ecx
200         subl    %eax, %edx
201         jns     15f
202         addl    $1000000000, %edx
203         decl    %ecx
204 15:     testl   %ecx, %ecx
205         js      16f             /* Time is already up.  */
206
207         /* Futex call.  */
208         movl    %ecx, (%esp)    /* Store relative timeout.  */
209         movl    %edx, 4(%esp)
210         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
211         movl    %esp, %esi
212         movl    %ecx, %edx
213         leal    READERS_WAKEUP(%ebp), %ebx
214         movl    $SYS_futex, %eax
215         int     $0x80
216         movl    %eax, %edx
217 17:
218
219         /* Reget the lock.  */
220         movl    $1, %eax
221         LOCK
222         xaddl   %eax, MUTEX(%ebp)
223         testl   %eax, %eax
224         jne     12f
225
226 13:     cmpl    $-ETIMEDOUT, %ecx
227         je      18f
228         decl    READERS_QUEUED(%ebp)
229         jne     2b
230         movl    $0, READERS_WAKEUP(%ebp)
231         jmp     2b
232
233
234 5:      xorl    %ecx, %ecx
235         incl    NR_READERS(%ebp)
236         je      8f
237 9:      LOCK
238         decl    MUTEX(%ebp)
239         jne     6f
240
241 7:      movl    %ecx, %eax
242
243         addl    $8, %esp
244         popl    %ebp
245         popl    %ebx
246         popl    %edi
247         popl    %esi
248         ret
249
250 1:      movl    %ebp, %ecx
251         call    __lll_mutex_lock_wait
252         jmp     2b
253
254 14:     cmpl    %gs:8, %eax
255         jne     3b
256         movl    $EDEADLK, %ecx
257         jmp     9b
258
259 6:      movl    %ebp, %eax
260         call    __lll_mutex_unlock_wake
261         jmp     7b
262
263         /* Overflow.  */
264 8:      decl    NR_READERS(%ebp)
265         movl    $EAGAIN, %ecx
266         jmp     9b
267
268         /* Overflow.  */
269 4:      decl    READERS_QUEUED(%ebp)
270         movl    $EAGAIN, %ecx
271         jmp     9b
272
273 10:     movl    %ebp, %eax
274         call    __lll_mutex_unlock_wake
275         jmp     11b
276
277 12:     movl    %ebx, %ecx
278         call    __lll_mutex_lock_wait
279         jmp     13b
280
281 16:     movl    $-ETIMEDOUT, %ecx
282         jmp     17b
283
284 18:     movl    $ETIMEDOUT, %ecx
285         jmp     9b
286         .size   pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock
287
288
289         .globl  __pthread_rwlock_wrlock
290         .type   __pthread_rwlock_wrlock,@function
291         .align  16
292 __pthread_rwlock_wrlock:
293         pushl   %esi
294         pushl   %ebx
295
296         xorl    %esi, %esi
297         xorl    %edx, %edx
298         movl    12(%esp), %ebx
299
300         /* Get the lock.  */
301         movl    $1, %eax
302         LOCK
303         xaddl   %eax, MUTEX(%ebx)
304         testl   %eax, %eax
305         jne     1f
306
307 2:      movl    WRITER(%ebx), %eax
308         testl   %eax, %eax
309         jne     14f
310         cmp     $0, NR_READERS(%ebx)
311         je      5f
312
313 3:      incl    WRITERS_QUEUED(%ebx)
314         je      4f
315
316         LOCK
317         decl    MUTEX(%ebx)
318         jne     10f
319
320 11:     addl    $WRITERS_WAKEUP-MUTEX, %ebx
321         movl    %esi, %ecx      /* movl $FUTEX_WAIT, %ecx */
322         movl    $SYS_futex, %eax
323         int     $0x80
324
325         subl    $WRITERS_WAKEUP-MUTEX, %ebx
326
327         /* Reget the lock.  */
328         movl    $1, %eax
329         LOCK
330         xaddl   %eax, MUTEX(%ebx)
331         testl   %eax, %eax
332         jne     12f
333
334 13:     decl    WRITERS_QUEUED(%ebx)
335         movl    $0, WRITERS_WAKEUP(%ebx)
336         jmp     2b
337
338 5:      xorl    %ecx, %ecx
339         movl    %gs:8, %eax
340         movl    %eax, WRITER(%ebx)
341 9:      LOCK
342         decl    MUTEX(%ebx)
343         jne     6f
344 7:
345
346         movl    %ecx, %eax
347         popl    %ebx
348         popl    %esi
349         ret
350
351 1:      movl    %ebx, %ecx
352         call    __lll_mutex_lock_wait
353         jmp     2b
354
355 14:     cmpl    %gs:8, %eax
356         jne     3b
357         movl    $EDEADLK, %ecx
358         jmp     9b
359
360 6:      movl    %ebx, %eax
361         call    __lll_mutex_unlock_wake
362         jmp     7b
363
364 4:      decl    WRITERS_QUEUED(%ebx)
365         movl    $EAGAIN, %ecx
366         jmp     9b
367
368 10:     movl    %ebx, %eax
369         call    __lll_mutex_unlock_wake
370         jmp     11b
371
372 12:     movl    %ebx, %ecx
373         call    __lll_mutex_lock_wait
374         jmp     13b
375         .size   __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
376
377         .globl  pthread_rwlock_wrlock
378 pthread_rwlock_wrlock = __pthread_rwlock_wrlock
379
380
381         .globl  pthread_rwlock_timedwrlock
382         .type   pthread_rwlock_timedwrlock,@function
383         .align  16
384 pthread_rwlock_timedwrlock:
385         pushl   %esi
386         pushl   %edi
387         pushl   %ebx
388         pushl   %ebp
389         subl    $8, %esp
390
391         movl    28(%esp), %ebp
392         movl    32(%esp), %edi
393
394         /* Get the lock.  */
395         movl    $1, %eax
396         LOCK
397         xaddl   %eax, MUTEX(%ebp)
398         testl   %eax, %eax
399         jne     1f
400
401 2:      movl    WRITER(%ebp), %eax
402         testl   %eax, %eax
403         jne     14f
404         cmp     $0, NR_READERS(%ebp)
405         je      5f
406
407 3:      incl    WRITERS_QUEUED(%ebp)
408         je      4f
409
410         LOCK
411         decl    MUTEX(%ebp)
412         jne     10f
413
414         /* Get current time.  */
415         movl    %esp, %ebx
416         xorl    %ecx, %ecx
417         movl    $SYS_gettimeofday, %eax
418         int     $0x80
419
420         /* Compute relative timeout.  */
421         movl    4(%esp), %eax
422         movl    $1000, %edx
423         mul     %edx            /* Milli seconds to nano seconds.  */
424         movl    (%edi), %ecx
425         movl    4(%edi), %edx
426         subl    (%esp), %ecx
427         subl    %eax, %edx
428         jns     15f
429         addl    $1000000000, %edx
430         decl    %ecx
431 15:     testl   %ecx, %ecx
432         js      16f             /* Time is already up.  */
433
434         /* Futex call.  */
435         movl    %ecx, (%esp)    /* Store relative timeout.  */
436         movl    %edx, 4(%esp)
437         xorl    %ecx, %ecx      /* movl $FUTEX_WAIT, %ecx */
438         movl    %esp, %esi
439         movl    %ecx, %edx
440         leal    WRITERS_WAKEUP(%ebp), %ebx
441         movl    $SYS_futex, %eax
442         int     $0x80
443         movl    %eax, %edx
444 17:
445
446         /* Reget the lock.  */
447         movl    $1, %eax
448         LOCK
449         xaddl   %eax, MUTEX(%ebp)
450         testl   %eax, %eax
451         jne     12f
452
453 13:     cmpl    $-ETIMEDOUT, %ecx
454         je      18f
455         decl    WRITERS_QUEUED(%ebp)
456         movl    $0, WRITERS_WAKEUP(%ebp)
457         jmp     2b
458
459
460 5:      xorl    %ecx, %ecx
461         movl    %gs:8, %eax
462         movl    %eax, WRITER(%ebp)
463 9:      LOCK
464         decl    MUTEX(%ebp)
465         jne     6f
466
467 7:      movl    %ecx, %eax
468
469         addl    $8, %esp
470         popl    %ebp
471         popl    %ebx
472         popl    %edi
473         popl    %esi
474         ret
475
476 1:      movl    %ebp, %ecx
477         call    __lll_mutex_lock_wait
478         jmp     2b
479
480 14:     cmpl    %gs:8, %eax
481         jne     3b
482         movl    $EDEADLK, %ecx
483         jmp     9b
484
485 6:      movl    %ebp, %eax
486         call    __lll_mutex_unlock_wake
487         jmp     7b
488
489         /* Overflow.  */
490 4:      decl    WRITERS_QUEUED(%ebp)
491         movl    $EAGAIN, %ecx
492         jmp     9b
493
494 10:     movl    %ebp, %eax
495         call    __lll_mutex_unlock_wake
496         jmp     11b
497
498 12:     movl    %ebx, %ecx
499         call    __lll_mutex_lock_wait
500         jmp     13b
501
502 16:     movl    $-ETIMEDOUT, %ecx
503         jmp     17b
504
505 18:     movl    $ETIMEDOUT, %ecx
506         jmp     9b
507         .size   pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock
508
509         .globl  __pthread_rwlock_unlock
510         .type   __pthread_rwlock_unlock,@function
511         .align  16
512 __pthread_rwlock_unlock:
513         pushl   %ebx
514         pushl   %esi
515         pushl   %edi
516
517         xorl    %esi, %esi
518         xorl    %edx, %edx
519         movl    16(%esp), %edi
520
521         /* Get the lock.  */
522         movl    $1, %eax
523         LOCK
524         xaddl   %eax, MUTEX(%edi)
525         testl   %eax, %eax
526         jne     1f
527
528 2:      cmpl    $0, WRITER(%edi)
529         jne     5f
530         decl    NR_READERS(%edi)
531         jnz     6f
532
533 5:      movl    $0, WRITER(%edi)
534
535         movl    $0x7fffffff, %edx
536         leal    READERS_WAKEUP(%edi), %ebx
537         movl    $1, %ecx
538         leal    WRITERS_WAKEUP(%edi), %eax
539         cmpl    $0, WRITERS_QUEUED(%edi)
540 #ifdef HAVE_CMOV
541         cmovnel %ecx, %edx
542         cmovnel %eax, %ebx
543 #else
544         je      0f
545         movl    %ecx, %edx
546         movl    %eax, %ebx
547 0:
548 #endif
549         movl    $SYS_futex, %eax
550         int     $0x80
551
552 6:      LOCK
553         decl    MUTEX(%edi)
554         jne     3f
555
556 4:      xorl    %eax, %eax
557         popl    %edi
558         popl    %esi
559         popl    %ebx
560         ret
561
562 1:      movl    %edi, %ecx
563         call    __lll_mutex_lock_wait
564         jmp     2b
565
566 3:      movl    %edi, %eax
567         call    __lll_mutex_unlock_wake
568         jmp     4b
569
570         .size   __pthread_rwlock_unlock,.-__pthread_rwlock_unlock
571
572         .globl  pthread_rwlock_unlock
573 pthread_rwlock_unlock = __pthread_rwlock_unlock