Define _POSIX_MONOTONIC_CLOCK.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / i386 / lowlevelsem.h
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 #ifndef _LOWLEVELSEM_H
21 #define _LOWLEVELSEM_H  1
22
23 #include <dl-sysdep.h>
24 #include <tls.h>
25
26 #ifndef LOCK
27 # ifdef UP
28 #  define LOCK  /* nothing */
29 # else
30 #  define LOCK "lock;"
31 # endif
32 #endif
33
34 #define SYS_futex               240
35
36
37 #ifdef I386_USE_SYSENTER
38 # ifdef SHARED
39 # define LLL_SEM_ENTER_KERNEL(arg)      "call *%%gs:%P" #arg "\n\t"
40 # else
41 # define LLL_SEM_ENTER_KERNEL(arg)      "call *_dl_sysinfo\n\t"
42 # endif
43 #else
44 # define LLL_SEM_ENTER_KERNEL(arg)      "int $0x80\n\t"
45 #endif
46
47 #define lll_sem_wait(sem) \
48   ({ int result, ignore1, ignore2;                                            \
49      __asm __volatile ("1:\tincl 8(%4)\n\t"                                   \
50                        LOCK "incl (%4)\n\t"                                   \
51                        "jng 2f\n"                                             \
52                        ".subsection 1\n"                                      \
53                        "2:\tmovl %4, %%eax\n\t"                               \
54                        "call __lll_unlock_wake\n\t"                           \
55                        "jmp 3f\n\t"                                           \
56                        ".previous\n"                                          \
57                        "3:\tpushl %%ebx\n\t"                                  \
58                        "movl %%esi, %%ecx\n\t"                                \
59                        "movl %%esi, %%edx\n\t"                                \
60                        "leal 4(%4), %%ebx\n\t"                                \
61                        "movl %5, %%eax\n\t"                                   \
62                        LLL_SEM_ENTER_KERNEL (9)                               \
63                        "movl %%eax, %%edx\n\t"                                \
64                        "popl %%ebx\n\t"                                       \
65                        "orl $-1, %%eax\n\t"                                   \
66                        LOCK "xaddl %%eax, (%4)\n\t"                           \
67                        "jne 4f\n\t"                                           \
68                        ".subsection 1\n"                                      \
69                        "4:\tmovl %4, %%ecx\n\t"                               \
70                        "call __lll_lock_wait\n\t"                             \
71                        "jmp 5f\n\t"                                           \
72                        ".previous\n"                                          \
73                        "5:\tdecl 8(%4)\n\t"                                   \
74                        "xorl %0, %0\n\t"                                      \
75                        "cmpl $0, 4(%4)\n\t"                                   \
76                        "jne,pt 6f\n\t"                                        \
77                        "cmpl %7, %%edx\n\t"                                   \
78                        "jne,pn 1b\n\t"                                        \
79                        "addl %8, %0\n\t" /* Shorter than movl %7, %0 */       \
80                        "6:"                                                   \
81                        : "=a" (result), "=c" (ignore1), "=d" (ignore2),       \
82                          "=m" (*sem)                                          \
83                        : "D" (sem), "i" (SYS_futex), "S" (0),                 \
84                          "i" (-EINTR), "i" (EINTR),                           \
85                          "i" (offsetof (tcbhead_t, sysinfo)));                \
86      result; })
87
88
89 extern int __lll_sem_timedwait (struct sem *sem, const struct timespec *ts)
90      __attribute__ ((regparm (2))) attribute_hidden;
91 #define lll_sem_timedwait(sem, timeout) \
92   __lll_sem_timedwait (sem, timeout)
93
94
95 #define lll_sem_post(sem) \
96   (void) ({ int ignore1, ignore2, ignore3;                                    \
97             __asm __volatile ("movl $1, %%eax\n\t"                            \
98                               LOCK                                            \
99                               "xaddl %%eax, (%4)\n\t"                         \
100                               "pushl %%esi\n\t"                               \
101                               "pushl %%ebx\n\t"                               \
102                               "movl %4, %%ebx\n\t"                            \
103                               "leal 1(%%eax), %%edx\n\t"                      \
104                               "xorl %%esi, %%esi\n\t"                         \
105                               "movl %5, %%eax\n\t"                            \
106                               /* movl $FUTEX_WAKE, %ecx */                    \
107                               "movl $1, %%ecx\n\t"                            \
108                               LLL_SEM_ENTER_KERNEL (6)                        \
109                               "popl %%ebx\n\t"                                \
110                               "popl %%esi"                                    \
111                               : "=&a" (ignore1), "=c" (ignore2),              \
112                                 "=m" (*sem), "=d" (ignore3)                   \
113                               : "r" (sem), "i" (SYS_futex),                   \
114                                 "i" (offsetof (tcbhead_t, sysinfo))); })
115
116 #endif  /* lowlevelsem.h */