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    powerpc version.
00003    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public License as
00008    published by the Free Software Foundation; either version 2 of the
00009    License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public
00017    License along with the GNU C Library; see the file COPYING.LIB.  If
00018    not, write to the Free Software Foundation, Inc.,
00019    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00020 
00021 /* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor
00022    User's Manual', by IBM and Motorola.  */
00023 
00024 #ifndef _PT_MACHINE_H
00025 #define _PT_MACHINE_H   1
00026 
00027 #ifndef PT_EI
00028 # define PT_EI extern inline __attribute__ ((always_inline))
00029 #endif
00030 
00031 extern long int testandset (int *spinlock);
00032 extern int __compare_and_swap (long int *p, long int oldval, long int newval);
00033 extern int __compare_and_swap32 (int *p, int oldval, int newval);
00034 
00035 /* For multiprocessor systems, we want to ensure all memory accesses
00036    are completed before we reset a lock.  On other systems, we still
00037    need to make sure that the compiler has flushed everything to memory.  */
00038 #define MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory")
00039 #define READ_MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory")
00040 #define WRITE_MEMORY_BARRIER() __asm__ __volatile__ ("eieio" : : : "memory")
00041 
00042 /* We want the OS to assign stack addresses.  */
00043 #define FLOATING_STACKS 1
00044 
00045 /* Maximum size of the stack if the rlimit is unlimited.  */
00046 #define ARCH_STACK_MAX_SIZE     16*1024*1024
00047 
00048 /* Get some notion of the current stack.  Need not be exactly the top
00049    of the stack, just something somewhere in the current frame.  */
00050 #define CURRENT_STACK_FRAME  stack_pointer
00051 register char * stack_pointer __asm__ ("r1");
00052 
00053 /* Register r13 (tp) is reserved by the ABI as "thread pointer". */
00054 struct _pthread_descr_struct;
00055 register struct _pthread_descr_struct *__thread_self __asm__("r13");
00056 
00057 /* Return the thread descriptor for the current thread.  */
00058 #define THREAD_SELF  __thread_self
00059 
00060 /* Initialize the thread-unique value.  */
00061 #define INIT_THREAD_SELF(descr, nr)  (__thread_self = (descr))
00062 
00063 /* Access to data in the thread descriptor is easy.  */
00064 #define THREAD_GETMEM(descr, member) \
00065   ((void) (descr), THREAD_SELF->member)
00066 #define THREAD_GETMEM_NC(descr, member) \
00067   ((void) (descr), THREAD_SELF->member)
00068 #define THREAD_SETMEM(descr, member, value) \
00069   ((void) (descr), THREAD_SELF->member = (value))
00070 #define THREAD_SETMEM_NC(descr, member, value) \
00071   ((void) (descr), THREAD_SELF->member = (value))
00072 
00073 /* Compare-and-swap for semaphores. */
00074 /* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */
00075 
00076 #define HAS_COMPARE_AND_SWAP
00077 #define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS
00078 
00079 PT_EI int
00080 __compare_and_swap (long int *p, long int oldval, long int newval)
00081 {
00082   long int ret;
00083 
00084   __asm__ __volatile__ (
00085           "0:    ldarx %0,0,%1 ;"
00086           "      xor. %0,%3,%0;"
00087           "      bne 1f;"
00088           "      stdcx. %2,0,%1;"
00089           "      bne- 0b;"
00090           "1:    "
00091        : "=&r"(ret)
00092        : "r"(p), "r"(newval), "r"(oldval)
00093        : "cr0", "memory");
00094   /* This version of __compare_and_swap is to be used when acquiring
00095      a lock, so we don't need to worry about whether other memory
00096      operations have completed, but we do need to be sure that any loads
00097      after this point really occur after we have acquired the lock.  */
00098   __asm__ __volatile__ ("isync" : : : "memory");
00099   return (int)(ret == 0);
00100 }
00101 
00102 PT_EI int
00103 __compare_and_swap_with_release_semantics (long int *p,
00104                                       long int oldval, long int newval)
00105 {
00106   long int ret;
00107 
00108   MEMORY_BARRIER ();
00109   __asm__ __volatile__ (
00110           "0:    ldarx %0,0,%1 ;"
00111           "      xor. %0,%3,%0;"
00112           "      bne 1f;"
00113           "      stdcx. %2,0,%1;"
00114           "      bne- 0b;"
00115           "1:    "
00116        : "=&r"(ret)
00117        : "r"(p), "r"(newval), "r"(oldval)
00118        : "cr0", "memory");
00119   return (int)(ret == 0);
00120 }
00121 
00122 PT_EI int
00123 __compare_and_swap32 (int *p, int oldval, int newval)
00124 {
00125   int ret;
00126 
00127   __asm__ __volatile__ (
00128           "0:    lwarx %0,0,%1 ;"
00129           "      xor. %0,%3,%0;"
00130           "      bne 1f;"
00131           "      stwcx. %2,0,%1;"
00132           "      bne- 0b;"
00133           "1:    "
00134        : "=&r"(ret)
00135        : "r"(p), "r"(newval), "r"(oldval)
00136        : "cr0", "memory");
00137   /* This version of __compare_and_swap is to be used when acquiring
00138      a lock, so we don't need to worry about whether other memory
00139      operations have completed, but we do need to be sure that any loads
00140      after this point really occur after we have acquired the lock.  */
00141   __asm__ __volatile__ ("isync" : : : "memory");
00142   return (int)(ret == 0);
00143 }
00144 
00145 PT_EI int
00146 __compare_and_swap32_with_release_semantics (long int *p,
00147                                       long int oldval, long int newval)
00148 {
00149   long int ret;
00150 
00151   MEMORY_BARRIER ();
00152   __asm__ __volatile__ (
00153           "0:    lwarx %0,0,%1 ;"
00154           "      xor. %0,%3,%0;"
00155           "      bne 1f;"
00156           "      stwcx. %2,0,%1;"
00157           "      bne- 0b;"
00158           "1:    "
00159        : "=&r"(ret)
00160        : "r"(p), "r"(newval), "r"(oldval)
00161        : "cr0", "memory");
00162   return (int)(ret == 0);
00163 }
00164 
00165 PT_EI long int
00166 testandset (int *p)
00167 {
00168   long int ret, val = 1;
00169 
00170   MEMORY_BARRIER ();
00171   __asm__ __volatile__ (
00172           "0:    lwarx %0,0,%1 ;"
00173           "      cmpwi  0,%0,0;"
00174           "      bne 1f;"
00175           "      stwcx. %2,0,%1;"
00176           "      bne- 0b;"
00177           "1:    "
00178        : "=&r"(ret)
00179        : "r"(p), "r" (val)
00180        : "cr0", "memory");
00181   MEMORY_BARRIER ();
00182   return ret != 0;
00183 }
00184 
00185 #endif /* pt-machine.h */