Back to index

glibc  2.9
pt-machine.h
Go to the documentation of this file.
00001 /* Machine-dependent pthreads configuration and inline functions.
00002    i386 version.
00003    Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Richard Henderson <rth@tamu.edu>.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public License as
00009    published by the Free Software Foundation; either version 2.1 of the
00010    License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; see the file COPYING.LIB.  If not,
00019    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020    Boston, MA 02111-1307, USA.  */
00021 
00022 #ifndef _PT_MACHINE_H
00023 #define _PT_MACHINE_H       1
00024 
00025 #include <kernel-features.h>
00026 
00027 #ifndef __ASSEMBLER__
00028 #ifndef PT_EI
00029 # define PT_EI extern inline __attribute__ ((always_inline))
00030 #endif
00031 
00032 extern long int testandset (int *spinlock);
00033 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
00034 
00035 /* Get some notion of the current stack.  Need not be exactly the top
00036    of the stack, just something somewhere in the current frame.  */
00037 #define CURRENT_STACK_FRAME  __builtin_frame_address (0)
00038 
00039 
00040 /* Spinlock implementation; required.  */
00041 PT_EI long int
00042 testandset (int *spinlock)
00043 {
00044   long int ret;
00045 
00046   __asm__ __volatile__(
00047        "xchgl %0, %1"
00048        : "=r"(ret), "=m"(*spinlock)
00049        : "0"(1), "m"(*spinlock)
00050        : "memory");
00051 
00052   return ret;
00053 }
00054 
00055 
00056 /* Compare-and-swap for semaphores.
00057    Available on the 486 and above, but not on the 386.
00058    We test dynamically whether it's available or not. */
00059 
00060 #define HAS_COMPARE_AND_SWAP
00061 #define TEST_FOR_COMPARE_AND_SWAP
00062 
00063 PT_EI int
00064 __compare_and_swap (long int *p, long int oldval, long int newval)
00065 {
00066   char ret;
00067   long int readval;
00068 
00069   __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
00070                      : "=q" (ret), "=m" (*p), "=a" (readval)
00071                      : "r" (newval), "m" (*p), "a" (oldval)
00072                      : "memory");
00073   return ret;
00074 }
00075 
00076 
00077 PT_EI int
00078 get_eflags (void)
00079 {
00080   int res;
00081   __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : );
00082   return res;
00083 }
00084 
00085 
00086 PT_EI void
00087 set_eflags (int newflags)
00088 {
00089   __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc");
00090 }
00091 
00092 
00093 PT_EI int
00094 compare_and_swap_is_available (void)
00095 {
00096   int oldflags = get_eflags ();
00097   int changed;
00098   /* Flip AC bit in EFLAGS.  */
00099   set_eflags (oldflags ^ 0x40000);
00100   /* See if bit changed.  */
00101   changed = (get_eflags () ^ oldflags) & 0x40000;
00102   /* Restore EFLAGS.  */
00103   set_eflags (oldflags);
00104   /* If the AC flag did not change, it's a 386 and it lacks cmpxchg.
00105      Otherwise, it's a 486 or above and it has cmpxchg.  */
00106   return changed != 0;
00107 }
00108 #endif /* __ASSEMBLER__ */
00109 
00110 #if __ASSUME_LDT_WORKS > 0
00111 #include <useldt.h>
00112 #endif
00113 
00114 /* The P4 and above really want some help to prevent overheating.  */
00115 #define BUSY_WAIT_NOP       __asm__ ("rep; nop")
00116 
00117 #endif /* pt-machine.h */