]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libpthread / linuxthreads.old / sysdeps / i386 / pt-machine.h
1 /* Machine-dependent pthreads configuration and inline functions.
2    i386 version.
3    Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Richard Henderson <rth@tamu.edu>.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of the
10    License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; see the file COPYING.LIB.  If
19    not, see <http://www.gnu.org/licenses/>.  */
20
21 #ifndef _PT_MACHINE_H
22 #define _PT_MACHINE_H   1
23
24 #include <features.h>
25
26 #ifndef __ASSEMBLER__
27 #ifndef PT_EI
28 # define PT_EI __extern_always_inline __attribute__((visibility("hidden")))
29 #endif
30
31 extern long int testandset (int *spinlock);
32 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
33
34 /* Get some notion of the current stack.  Need not be exactly the top
35    of the stack, just something somewhere in the current frame.  */
36 #define CURRENT_STACK_FRAME  __builtin_frame_address (0)
37
38
39 /* See if we can optimize for newer cpus... */
40 #if defined __GNUC__ && __GNUC__ >= 2 && \
41    (defined __i486__ || defined __pentium__ || defined __pentiumpro__ || defined __pentium4__ || \
42     defined __athlon__ || defined __k8__)
43
44 /* Spinlock implementation; required.  */
45 PT_EI long int
46 testandset (int *spinlock)
47 {
48   long int ret;
49
50   __asm__ __volatile__ (
51         "xchgl %0, %1"
52         : "=r" (ret), "=m" (*spinlock)
53         : "0" (1), "m" (*spinlock)
54         : "memory");
55
56   return ret;
57 }
58
59 /* Compare-and-swap for semaphores.  It's always available on i686.  */
60 #define HAS_COMPARE_AND_SWAP
61
62 PT_EI int
63 __compare_and_swap (long int *p, long int oldval, long int newval)
64 {
65   char ret;
66   long int readval;
67
68   __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
69                         : "=q" (ret), "=m" (*p), "=a" (readval)
70                         : "r" (newval), "m" (*p), "a" (oldval)
71                         : "memory");
72   return ret;
73 }
74
75 #if defined(__ASSUME_LDT_WORKS) && __ASSUME_LDT_WORKS > 0
76 #include "useldt.h"
77 #endif
78
79 /* The P4 and above really want some help to prevent overheating.  */
80 #define BUSY_WAIT_NOP   __asm__ ("rep; nop")
81
82
83 #else /* Generic i386 implementation */
84
85 extern int compare_and_swap_is_available (void);
86
87 /* Spinlock implementation; required.  */
88 PT_EI long int
89 testandset (int *spinlock)
90 {
91   long int ret;
92
93   __asm__ __volatile__(
94        "xchgl %0, %1"
95        : "=r"(ret), "=m"(*spinlock)
96        : "0"(1), "m"(*spinlock)
97        : "memory");
98
99   return ret;
100 }
101
102
103 /* Compare-and-swap for semaphores.
104    Available on the 486 and above, but not on the 386.
105    We test dynamically whether it's available or not. */
106
107 #define HAS_COMPARE_AND_SWAP
108 #define TEST_FOR_COMPARE_AND_SWAP
109
110 PT_EI int
111 __compare_and_swap (long int *p, long int oldval, long int newval)
112 {
113   char ret;
114   long int readval;
115
116   __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
117                         : "=q" (ret), "=m" (*p), "=a" (readval)
118                         : "r" (newval), "m" (*p), "a" (oldval)
119                         : "memory");
120   return ret;
121 }
122
123 PT_EI int
124 compare_and_swap_is_available (void)
125 {
126   int changed;
127   int oldflags;
128   /* get EFLAGS */
129   __asm__ __volatile__ ("pushfl; popl %0" : "=r" (oldflags) : );
130   /* Flip AC bit in EFLAGS.  */
131   __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags ^ 0x40000) : "cc");
132   /* reread EFLAGS */
133   __asm__ __volatile__ ("pushfl; popl %0" : "=r" (changed) : );
134   /* See if bit changed.  */
135   changed = (changed ^ oldflags) & 0x40000;
136   /* Restore EFLAGS.  */
137   __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags) : "cc");
138   /* If the AC flag did not change, it's a 386 and it lacks cmpxchg.
139      Otherwise, it's a 486 or above and it has cmpxchg.  */
140   return changed != 0;
141 }
142 #endif /* Generic i386 implementation */
143
144 #endif /* __ASSEMBLER__ */
145
146 #endif /* pt-machine.h */