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    hppa version.
00003    Copyright (C) 2000, 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 <sys/types.h>
00026 #include <bits/initspin.h>
00027 
00028 #ifndef PT_EI
00029 # define PT_EI extern inline __attribute__ ((always_inline))
00030 #endif
00031 
00032 extern inline long int testandset (__atomic_lock_t *spinlock);
00033 extern inline int __compare_and_swap (long int *p, long int oldval, long int newval);
00034 extern inline int lock_held (__atomic_lock_t *spinlock); 
00035 extern inline int __load_and_clear (__atomic_lock_t *spinlock);
00036 
00037 /* Get some notion of the current stack.  Need not be exactly the top
00038    of the stack, just something somewhere in the current frame.  */
00039 #define CURRENT_STACK_FRAME  stack_pointer
00040 register char * stack_pointer __asm__ ("%r30");
00041 
00042 /* Get/Set thread-specific pointer.  We have to call into the kernel to
00043  * modify it, but we can read it in user mode.  */
00044 #ifndef THREAD_SELF
00045 #define THREAD_SELF __get_cr27()
00046 #endif
00047 
00048 #ifndef SET_THREAD_SELF
00049 #define SET_THREAD_SELF(descr) __set_cr27(descr)
00050 #endif
00051 /* Use this to determine type */
00052 struct _pthread_descr_struct *__thread_self;
00053 
00054 static inline struct _pthread_descr_struct * __get_cr27(void)
00055 {
00056   long cr27;
00057   asm ("mfctl %%cr27, %0" : "=r" (cr27) : );
00058   return (struct _pthread_descr_struct *) cr27;
00059 }
00060 
00061 #ifndef INIT_THREAD_SELF
00062 #define INIT_THREAD_SELF(descr, nr) __set_cr27(descr)
00063 #endif
00064 
00065 static inline void __set_cr27(struct _pthread_descr_struct * cr27)
00066 {
00067   asm ( "ble  0xe0(%%sr2, %%r0)\n\t"
00068        "copy  %0, %%r26"
00069        : : "r" (cr27) : "r26" );
00070 }
00071 
00072 /* We want the OS to assign stack addresses.  */
00073 #define FLOATING_STACKS     1
00074 #define ARCH_STACK_MAX_SIZE 8*1024*1024
00075 
00076 /* The hppa only has one atomic read and modify memory operation,
00077    load and clear, so hppa spinlocks must use zero to signify that
00078    someone is holding the lock.  The address used for the ldcw
00079    semaphore must be 16-byte aligned.  */
00080 #define __ldcw(a) \
00081 ({                                                             \
00082   unsigned int __ret;                                                 \
00083   __asm__ __volatile__("ldcw 0(%1),%0"                                \
00084                       : "=r" (__ret) : "r" (a) : "memory");           \
00085   __ret;                                                       \
00086 })
00087 
00088 /* Strongly ordered lock reset */
00089 #define __lock_reset(lock_addr, tmp) \
00090 ({                                                                    \
00091        __asm__ __volatile__ ("stw,ma %1,0(%0)"                               \
00092                             : : "r" (lock_addr), "r" (tmp) : "memory");      \
00093 })
00094 
00095 /* Because malloc only guarantees 8-byte alignment for malloc'd data,
00096    and GCC only guarantees 8-byte alignment for stack locals, we can't
00097    be assured of 16-byte alignment for atomic lock data even if we
00098    specify "__attribute ((aligned(16)))" in the type declaration.  So,
00099    we use a struct containing an array of four ints for the atomic lock
00100    type and dynamically select the 16-byte aligned int from the array
00101    for the semaphore.  */
00102 #define __PA_LDCW_ALIGNMENT 16
00103 #define __ldcw_align(a) ({ \
00104   volatile unsigned int __ret = (unsigned int) a;                     \
00105   if ((__ret & ~(__PA_LDCW_ALIGNMENT - 1)) < (unsigned int) a)        \
00106     __ret = (__ret & ~(__PA_LDCW_ALIGNMENT - 1)) + __PA_LDCW_ALIGNMENT; \
00107   (unsigned int *) __ret;                                      \
00108 })
00109 
00110 /* Spinlock implementation; required.  */
00111 PT_EI int
00112 __load_and_clear (__atomic_lock_t *spinlock)
00113 {
00114   volatile unsigned int *a = __ldcw_align (spinlock);
00115 
00116   return __ldcw (a);
00117 }
00118 
00119 /* Emulate testandset */
00120 PT_EI long int
00121 testandset (__atomic_lock_t *spinlock)
00122 {
00123   return (__load_and_clear(spinlock) == 0);
00124 }
00125 
00126 PT_EI int
00127 lock_held (__atomic_lock_t *spinlock)
00128 {
00129   volatile unsigned int *a = __ldcw_align (spinlock);
00130 
00131   return *a == 0;
00132 }
00133               
00134 #endif /* pt-machine.h */