/*************************************************************************** * * Copyright (C) 2001 International Business Machines * All rights reserved. * * This file is part of the GPFS mmfslinux kernel module. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************** */ /* @(#)09 1.126 src/avs/fs/mmfs/ts/kernext/ibm-linux/cxiTypes-plat.h, mmfs, avs_rgpfs24, rgpfs240610b 11/15/05 13:25:02 */ /* * Definitions for system dependent types, Linux version * * Contents: * system dependent types * */ #ifndef _h_cxiTypes_plat #define _h_cxiTypes_plat #ifndef _h_cxiTypes #error Platform header (XXX-plat.h) should not be included directly #endif /* Use system types.h except in portability kernel code */ #if !defined(GPFS_GPL) || !defined(_KERNEL) #include #endif /* Suffix of a routine declaration to tell GCC to pass parameters in registers */ #ifdef GPFS_ARCH_I386 #define REGPARMS __attribute__((regparm(3))) #else #define REGPARMS #endif /* Inline functions to byte-swap integers of various sizes. These use assembler helpers on some architectures. If the input parameter is a constant, the GCC compiler will generate better code by compile-time optimization of a (complicated) expression involving shifts and masks rather than calling the inline asm code. */ #ifdef GPFS_ARCH_I386 static inline const UInt16 _asm_swap16(UInt16 val) { /* "q" means any of regs AX-DX, which are the only ones that can be addressed as bytes */ __asm__("xchgb %b0,%h0 # _asm_swap16" \ : "=q" (val) \ : "0" (val)); return val; } static inline UInt16 ByteSwap16(UInt16 val) { return __builtin_constant_p(val) ? _ByteSwap16(val) : _asm_swap16(val); } #else static inline UInt16 ByteSwap16(UInt16 val) { return _ByteSwap16(val); } #endif #if defined(GPFS_ARCH_I386) || defined(GPFS_ARCH_X86_64) static inline const UInt32 _asm_swap32(UInt32 val) { __asm__("bswap %0 # _asm_swap32" \ : "=r" (val) \ : "0" (val)); return val; } static inline UInt32 ByteSwap32(UInt32 val) { return __builtin_constant_p(val) ? _ByteSwap32(val) : _asm_swap32(val); } #elif defined(GPFS_ARCH_IA64) static inline UInt32 ByteSwap32(UInt32 val) { UInt64 swapval1 = (UInt64)val, swapval2; __asm__("shl %0=%1,32;;" : "=r"(swapval2) : "r"(swapval1) ); __asm__("mux1 %0=%1,@rev" : "=r"(swapval1) : "r"(swapval2) ); return (UInt32)swapval1; } #else static inline UInt32 ByteSwap32(UInt32 val) { return _ByteSwap32(val); } #endif #ifdef GPFS_ARCH_I386 /* Use an external assembler routine to do the swap, since inline assembler either generates poor code or incorrect code in some cases. The inline asembler is preserved in tasking/i386/swap.S. */ EXTERNC const UInt64 _asm_swap64(UInt64 val) REGPARMS; static inline UInt64 ByteSwap64(UInt64 val) { return __builtin_constant_p(val) ? _ByteSwap64(val) : _asm_swap64(val); } #elif defined(GPFS_ARCH_IA64) static inline UInt64 ByteSwap64(UInt64 val) { UInt64 swapval; __asm__("mux1 %0=%1,@rev" : "=r"(swapval) : "r"(val) ); return swapval; } #elif defined(GPFS_ARCH_X86_64) static inline UInt64 ByteSwap64(UInt64 val) { UInt64 swapval = val; __asm__("bswap %0" : "=r"(swapval) : "0"(swapval) ); return swapval; } #else static inline UInt64 ByteSwap64(UInt64 val) { return _ByteSwap64(val); } #endif /* GPFS_ARCH_I386 */ /* On little-endian machines, declare classes for big-endian integers of various sizes. Each class provides operator= and integer cast operators, so the compiler will insert code to do conversions automatically when evaluating expressions involving big-endian integers. When passing a BigEndIntxx as a value parameter to a function without a prototype for its arguments, be sure to explicitly cast to the corresponding native arithmetic type. Otherwise, passing the class instance by value will result in the wrong byte order in the called routine. This most often occurs with printf and related functions. Notice that the code generated by TRACEn macros already contains such an explicit cast, so no case is needed in the source code. */ #ifdef __cplusplus # ifdef GPFS_LITTLE_ENDIAN class BigEndInt16 { private: Int16 val16; public: operator Int16() const { return ByteSwap16(val16); } BigEndInt16 operator=(Int16 newVal16) { val16 = ByteSwap16(newVal16); return *this; } int operator==(BigEndInt16 rhs) const { return val16 == rhs.val16; } int operator!=(BigEndInt16 rhs) const { return val16 != rhs.val16; } BigEndInt16 operator+=(Int16 inc) { val16 = ByteSwap16(ByteSwap16(val16)+inc); return *this; } BigEndInt16 operator-=(Int16 inc) { val16 = ByteSwap16(ByteSwap16(val16)-inc); return *this; } BigEndInt16 operator&=(Int16 mask) { val16 &= ByteSwap16(mask); return *this; } BigEndInt16 operator|=(Int16 mask) { val16 |= ByteSwap16(mask); return *this; } }; class BigEndUInt16 { private: UInt16 uval16; public: operator UInt16() const { return ByteSwap16(uval16); } BigEndUInt16 operator=(UInt16 newVal16) { uval16 = ByteSwap16(newVal16); return *this; } int operator==(BigEndUInt16 rhs) const { return uval16 == rhs.uval16; } int operator!=(BigEndUInt16 rhs) const { return uval16 != rhs.uval16; } BigEndUInt16 operator+=(UInt16 inc) { uval16 = ByteSwap16(ByteSwap16(uval16)+inc); return *this; } BigEndUInt16 operator-=(UInt16 inc) { uval16 = ByteSwap16(ByteSwap16(uval16)-inc); return *this; } BigEndUInt16 operator&=(UInt16 mask) { uval16 &= ByteSwap16(mask); return *this; } BigEndUInt16 operator|=(UInt16 mask) { uval16 |= ByteSwap16(mask); return *this; } }; class BigEndInt32 { private: Int32 val32; public: operator Int32() const { return ByteSwap32(val32); } BigEndInt32 operator=(Int32 newVal32) { val32 = ByteSwap32(newVal32); return *this; } int operator==(BigEndInt32 rhs) const { return val32 == rhs.val32; } int operator!=(BigEndInt32 rhs) const { return val32 != rhs.val32; } BigEndInt32 operator+=(Int32 inc) { val32 = ByteSwap32(ByteSwap32(val32)+inc); return *this; } BigEndInt32 operator-=(Int32 inc) { val32 = ByteSwap32(ByteSwap32(val32)-inc); return *this; } }; class BigEndUInt32 { private: UInt32 uval32; public: operator UInt32() const { return ByteSwap32(uval32); } BigEndUInt32 operator=(UInt32 newVal32) { uval32 = ByteSwap32(newVal32); return *this; } int operator==(BigEndUInt32 rhs) const { return uval32 == rhs.uval32; } int operator!=(BigEndUInt32 rhs) const { return uval32 != rhs.uval32; } BigEndUInt32 operator+=(UInt32 inc) { uval32 = ByteSwap32(ByteSwap32(uval32)+inc); return *this; } BigEndUInt32 operator-=(UInt32 inc) { uval32 = ByteSwap32(ByteSwap32(uval32)-inc); return *this; } BigEndUInt32 operator&=(UInt32 mask) { uval32 &= ByteSwap32(mask); return *this; } BigEndUInt32 operator|=(UInt32 mask) { uval32 |= ByteSwap32(mask); return *this; } BigEndUInt32 operator^=(UInt32 mask) { uval32 ^= ByteSwap32(mask); return *this; } }; class BigEndInt64 { private: Int64 val64; public: operator Int64() const { return ByteSwap64(val64); } BigEndInt64 operator=(Int64 newVal64) { val64 = ByteSwap64(newVal64); return *this; } int operator==(BigEndInt64 rhs) const { return val64 == rhs.val64; } int operator!=(BigEndInt64 rhs) const { return val64 != rhs.val64; } BigEndInt64 operator+=(Int64 inc) { val64 = ByteSwap64(ByteSwap64(val64)+inc); return *this; } BigEndInt64 operator-=(Int64 inc) { val64 = ByteSwap64(ByteSwap64(val64)-inc); return *this; } }; class BigEndUInt64 { private: UInt64 uval64; public: operator UInt64() const { return ByteSwap64(uval64); } BigEndUInt64 operator=(UInt64 newVal64) { uval64 = ByteSwap64(newVal64); return *this; } int operator==(BigEndUInt64 rhs) const { return uval64 == rhs.uval64; } int operator!=(BigEndUInt64 rhs) const { return uval64 != rhs.uval64; } BigEndUInt64 operator+=(UInt64 inc) { uval64 = ByteSwap64(ByteSwap64(uval64)+inc); return *this; } BigEndUInt64 operator-=(UInt64 inc) { uval64 = ByteSwap64(ByteSwap64(uval64)-inc); return *this; } }; # else /* GPFS_LITTLE_ENDIAN */ typedef Int16 BigEndInt16; typedef UInt16 BigEndUInt16; typedef Int32 BigEndInt32; typedef UInt32 BigEndUInt32; typedef Int64 BigEndInt64; typedef UInt64 BigEndUInt64; # endif /* GPFS_LITTLE_ENDIAN */ # else /* not __cplusplus */ typedef Int16 BigEndInt16; typedef UInt16 BigEndUInt16; typedef Int32 BigEndInt32; typedef UInt32 BigEndUInt32; typedef Int64 BigEndInt64; typedef UInt64 BigEndUInt64; #endif /* __cplusplus */ /* GPFS stores special file device numbers as 32 bit values * (the original AIX dev_t size). The cxiDev_t type is 64 bits * since this is the size of the user space dev_t and the prevalent * type that we're always presented with from the stat structure. */ typedef UInt64 cxiDev_t; /* user space dev_t definition */ typedef int cxiVmid_t; // dummy on Linux typedef UIntPtr cxiVmhandle_t; // try this for now /* Time types equivalent to linux definitions of time_t * and suseconds_t. */ typedef long int cxiNSec_t; typedef long int cxiTime_t; /* Type used as parameter of ATOMIC_ADD, etc. */ typedef int *atomic_p; /* Type used as parameter of ATOMIC_ADDLP, etc. */ typedef long *atomic_l; /* File offset */ typedef long long offset_t; /* Complex system types */ struct xmem { int x; }; /* Cross-memory descriptor */ typedef struct { /* Pointer to buffer descriptor object in kernel address space */ struct cxiKernelIOBufferDesc_t *kibdP; } cxiXmem_t; #ifdef _KERNEL #define CXIXMEM_TO_XMEM(_XMEM, _CXIXMEM) \ { \ memcpy(_XMEM, _CXIXMEM, sizeof(cxiXmem_t)); \ }; #endif /* Describes address space of a cxiUio_t buffer. * User address space buffers get extra validity * checking to ensure they are indeed in user space. */ #define UIO_SYSSPACE 1 #define UIO_USERSPACE 0 /* Structure representing a buffer in user space that needs to be accessed from kernel code. */ struct cxiUio_t { struct cxiIovec_t *uio_iov; /* ptr to array of iovec structs */ unsigned long uio_iovcnt; /* #iovec elements remaining to be processed */ unsigned long uio_iovdcnt;/* #iovec elements already processed */ offset_t uio_offset; /* byte offset in file/dev to read/write */ long uio_resid; /* #bytes left in data area */ short uio_segflg; /* description of which address space in use */ long uio_fmode; /* copy of file modes from open file struct */ cxiXmem_t *uio_xmem; /* dummy field for AIX compatibility */ }; #define UIO_XMEM 0 /* First parameter on return call to cxiFillDir(). This structure * describes the operating systems' filldir() routine and any uninterpreted * arguments that need to be passed back to it. The cxiFillDir() routine * has a static set of parameters that are passed to it, whereas the * Linux filldir() routine has changed signatures for different kernel * levels. We thus use cxiFillDir() in the portability layer to map * the arguments correctly to the Linux filldir(). */ typedef struct cxiFillDirArg_t { void *fnP; void *argP; } cxiFillDirArg_t; /* Callback function to return directory entries. * Called by readddir for each directory entry to be returned to the user. * Should return zero if the entry still fits in the user's buffer; * otherwise a negative value should be returned. The 'offset' parameter * is the logical offset of the current entry, i.e., a seekdir to that * offset followed by a readdir will return the same directory entry again. */ typedef int (*cxiFillDir_t)(void *, const char *, int, offset_t, ino_t); #define CALL_FILLDIR(fnP, argP, nameP, namelen, offset, ino) \ (*fnP)(argP, nameP, namelen, offset, ino) #define GPFS_DIR_EOF 0x7FFFFFFF /* Advisory locking types and defines */ typedef cxiFlock_t eflock_t; #define MNT_NFS 2 #define MNT_NFS3 18 #define MNT_RFS4 36 /* Define analagous kernel types here for now */ /* These should ONLY be used for typecasting kernel service call parms */ typedef cxiPid_t gpfs_Kpid_t; /* GPFS file types. These match the AIX vtype definitions from vnode.h */ enum cxiVtype { cxiVNON, cxiVREG, cxiVDIR, cxiVBLK, cxiVCHR, cxiVLNK, cxiVSOCK, cxiVBAD, cxiVFIFO, cxiVMPC }; #define cxiVUNDEF cxiVNON /* undefined is same as nothing */ typedef enum cxiVtype cxiVtype_t; /* Maximum size defined within Linux kernel for spinlock_t * We abstract this class to just a hunk of storage and let the OS * specific piece handle the implementation. */ #ifdef DEBUG_SPINLOCK # if defined (GPFS_ARCH_I386) # define SPINLOCK_T_SIZE 8 # elif defined(GPFS_ARCH_POWER) # define SPINLOCK_T_SIZE 12 # elif defined(GPFS_ARCH_IA64) # define SPINLOCK_T_SIZE 4 # elif defined(GPFS_ARCH_PPC64) # define SPINLOCK_T_SIZE 16 # elif defined(GPFS_ARCH_X86_64) # define SPINLOCK_T_SIZE 8 # endif #else #if defined(GPFS_ARCH_PPC64) && (LINUX_KERNEL_VERSION >= 2042100) #define SPINLOCK_T_SIZE 8 #elif defined(GPFS_ARCH_X86_64) /* Same size as DEBUG_SPINLOCK * Changing this size requires an adjustment of CXINODE_SIZE */ #define SPINLOCK_T_SIZE 8 #elif defined(GPFS_ARCH_I386) /* Same size as DEBUG_SPINLOCK */ #define SPINLOCK_T_SIZE 8 #else #define SPINLOCK_T_SIZE 4 #endif #endif /* Base VFS node class portion that is OS specific. * Consult gpfsNode_t for full definition */ typedef struct cxiNode_t { void *osNodeP; /* pointer to operating system specific inode */ enum cxiVtype nType; /* directory, link, file, dev */ int mapReadCount; /* count of map for read */ int mapWriteCount; /* count of map for write */ int readCount; /* total opens for read */ int icValid; /* CXI_IC_XXX flags (see definitions below) */ int xinfo; /* Extended info bits (see va_xinfo definition) */ void *nfsP; /* nfs information */ unsigned long ctFlags; cxiThreadId createRaceLoserThreadId; /* Set if file exist */ } cxiNode_t; /* various ctFlags */ #define mmapFlush 1 /* True if nopage/mmFlush in progress */ #define destroyIfDelInode 2 /* True if file should be destroyed in gpfs_s_delete_inode */ #define invalidateCalled 4 /* True if OSNode on hash chain has been invalidated on this pass. */ #define pruneDCacheNeeded 8 #define SetCtFlag(cnP,flag_bit) cxiSetBit(&(cnP)->ctFlags,flag_bit) #define ClearCtFlag(cnP,flag_bit) cxiClearBit(&(cnP)->ctFlags,flag_bit) #define TestCtFlag(cnP,flag_bit) cxiTestBit(&(cnP)->ctFlags,flag_bit) /* Size of a full gpfsNode_t */ #ifdef GPFS_ARCH_I386 # define CXINODE_SIZE (176 + SPINLOCK_T_SIZE) #endif #ifdef GPFS_ARCH_POWER # define CXINODE_SIZE (176 + SPINLOCK_T_SIZE) #endif #ifdef GPFS_ARCH_IA64 # define CXINODE_SIZE (260 + SPINLOCK_T_SIZE) #endif #ifdef GPFS_ARCH_PPC64 # if LINUX_KERNEL_VERSION < 2042100 # define CXINODE_SIZE (236 + SPINLOCK_T_SIZE) # else # define CXINODE_SIZE (232 + SPINLOCK_T_SIZE) # endif #endif #ifdef GPFS_ARCH_X86_64 /* Changing the non-debug size of SPINLOCK_T_SIZE * requires an adjustment of CXINODE_SIZE in order * to account for padding due to single or double word * alignment requirements of the architecture. */ # define CXINODE_SIZE (232 + SPINLOCK_T_SIZE) #endif /* Access OS dependent portion of cxiNode */ #define GNP_IS_DIR(GNP) ((GNP)->nType == cxiVDIR) #define GNP_IS_FILE(GNP) ((GNP)->nType == cxiVREG) #define GNP_IS_LINK(GNP) ((GNP)->nType == cxiVLNK) #define GNP_IS_STEALABLE(GNP) ((GNP)->osNodeP == NULL) #define GNP_RDCOUNT(GNP) ((GNP)->readCount) #define GNP_EXCOUNT(GNP) 0 #define GNP_MAP_RDCOUNT(GNP) ((GNP)->mapReadCount) #define GNP_MAP_WRCOUNT(GNP) ((GNP)->mapWriteCount) #define GNP_MAP_SEG(GNP) 0 #define GNP_CHANNEL(GNP) 0 #define GNP_TO_VP(GNP) ((struct inode *)((GNP)->osNodeP)) #define GP_TO_GNP(x) ((gpfsNode_t *)((x))) /* d_off and name length of Linux struct dirent */ #define CXI_DIR_D_OFFSET(deP) deP->d_off #define CXI_DIR_D_NAMLEN(deP) strlen(deP->d_name) /* Parameter passed to find_actor and read_inode2 through iget4 */ typedef struct cxiIGetArg_t { cxiIno_t extInodeNum; UInt32 inodeNum; UInt32 snapId; UInt32 filesetId; struct cxiVattr_t *vattrP; Boolean readInodeCalled; } cxiIGetArg_t; typedef struct cxiWaitList_t { struct cxiWaitList_t *nextP; struct cxiWaitList_t *prevP; } cxiWaitList_t; typedef struct cxiWaitEvent_t { /* List of wait elements. Wakeup is FIFO ordered with entries * entering the list at prevP and the first to be awaken at * nextP. */ cxiWaitList_t waitList; char lword[SPINLOCK_T_SIZE]; } cxiWaitEvent_t; #define LOCK_ALLOC_PIN 0 /* not used */ #define LOCK_ALLOC_PAGED 1 /* not used */ /* Needs to be changed to cxi name XXX */ typedef struct Simple_lock { int slCount; volatile unsigned int slState; /* Pointer into stack of owning thread. This is * sufficient to compute which thread owns the mutex. */ char* slOwnerP; cxiWaitEvent_t slEvent; } Simple_lock; /* Kernel-only mutexes. Largest possible size (including debug) */ #ifdef GPFS_ARCH_I386 #define GPFS_LINUX_SEM_SIZE 36 #endif #ifdef GPFS_ARCH_POWER #define GPFS_LINUX_SEM_SIZE 36 #endif #ifdef GPFS_ARCH_IA64 #define GPFS_LINUX_SEM_SIZE 56 #endif #ifdef GPFS_ARCH_PPC64 #define GPFS_LINUX_SEM_SIZE 32 #endif #ifdef GPFS_ARCH_X86_64 #define GPFS_LINUX_SEM_SIZE 32 #endif typedef struct cxiBlockingMutex_t { /* Space to store a Linux struct semaphore. If a semaphore does not fit in the space provided, the implementation should use this space as a pointer to a dynamically-allocated semaphore. */ char bmSem[GPFS_LINUX_SEM_SIZE]; /* Pointer into stack of owning thread. This is sufficient to compute which thread owns the mutex. */ char* bmOwnerP; /* Index of the name of this mutex */ int lockNameIndex; } cxiBlockingMutex_t; /* Structure encapsulating information about a particular physical disk */ struct cxiDiskInfo_t { Int64 totalSectors; /* number of sectors on disk */ int sectorSize; /* size of each physical sector in bytes */ }; typedef struct ucontext cxiSigContext_t; typedef struct siginfo cxiSigInfo_t; /* Type that should always correspond to the system ino_t */ typedef Int32 cxiInoSys_t; /* type to store disable_lock result. On Linux this is a machine state word, and should be unsigned long */ typedef unsigned long cxiIntrState_t; /* Work request for mmap pager kproc */ typedef struct _cxibuf_t { struct _cxibuf_t *av_forw; /* forward pointer */ struct _cxibuf_t *av_back; /* backward pointer */ struct page *pageP; /* pointer to the page being processed */ struct cxiNode_t *b_vp; struct MMFSVInfo *vinfoP; /* used by sendfile */ struct gpfsVfsData_t *privVfsP; caddr_t b_baddr; /* not used */ unsigned long b_flags; /* operation flag: see definitions below */ unsigned long b_blkno; /* file offset in PAGE_SIZE units */ int b_bcount; int b_error; void *b_inodeP; } cxibuf_t; /* b_flags flags. */ #define B_WRITE (long)0x0000 /* non-read pseudo-flag */ #define B_READ (long)0x0001 /* read when I/O occurs */ #define B_ERROR (long)0x0004 /* error detected */ #define B_ASYNC (long)0x0100 /* don't wait for I/O completion */ #define B_PFSTORE (long)0x2000 /* store operation */ #define B_PFPROT (long)0x4000 /* protection violation */ #define B_PFEOF (long)0x10000 /* check for ref. beyond end-of-file */ #define B_SENDFILE (long)0x20000 /* read from sendfile */ /* Define macros to cause code to be placed far away from the spot where it normally would be generated. This is typically used on whichever branch of an if is expected not to be executed in the common case. Moving rarely executed code away from the mainline code can help reduce I-cache misses, and therefore improve performance. Every BEGIN_FAR_CODE directive must be matched by an END_FAR_CODE directive, and they may not be nested. If FAR_CODE is not #defined, these macros are NOOPs. Use of the FAR_CODE option is not compatible with -g, and requires compiler options -fno-exceptions and -fno-defer-pop to insure that correct code is generated. */ #ifdef FAR_CODE # if defined(GPFS_ARCH_I386) # ifndef FAR_TRACE # error "-DFAR_CODE requires -DFAR_TRACE" # endif # define BEGIN_FAR_CODE __asm__( \ " jmp 9f\n" \ ".section .text.far,\"ax\"\n" \ "9:\n" \ ); # define END_FAR_CODE __asm__( \ " jmp 8f\n" \ ".section .text,\"ax\"\n" \ "8:\n" \ ); # elif defined(GPFS_ARCH_IA64) # ifndef FAR_TRACE # error "-DFAR_CODE requires -DFAR_TRACE" # endif /* Changing sections in the middle of a function is apparently a fairly bad thing to do for IA64 (screws up unwinding information, probably the debugging information, and also insn binding) and causes the gnu assembler to spew when optimizations are turned on. The gcc __buildin_expect(x,0) directive may be an alternative in the future, but this currently doesn't provide any performance enhancements with gcc 3.2, so we'll do nothing for now. */ #if 0 # define BEGIN_FAR_CODE __asm__( \ " (p0) br.cond.sptk.few 9f\n" \ ".section .text.far,\"ax\"\n" \ "9:\n" \ ); # define END_FAR_CODE __asm__( \ " (p0) br.cond.sptk.many 8f\n" \ ".section .text,\"ax\"\n" \ "8:\n" \ ); #endif # define BEGIN_FAR_CODE # define END_FAR_CODE # else # define BEGIN_FAR_CODE # define END_FAR_CODE # endif /* GPFS_ARCH_I386 */ #else # define BEGIN_FAR_CODE # define END_FAR_CODE #endif /* FAR_TRACE */ #ifndef EXTERNC #ifdef __cplusplus #define EXTERNC extern "C" #else #define EXTERNC extern #endif #endif /* EXTERNC */ /* Some macros to help catching certain problems at compile time vs at run time, to save time on unnecessary recompiles and reboots. This can be accomplished when operating on static data that has known (to the compiler) values at compile time, notably complex structure sizes. */ /* This macro asserts that both arguments have the same value. If the assertion is false, a compiler error about conflicting function declarations will be produced. */ #define STATIC_DBGASSERT(_a, _b) \ EXTERNC void __static_assert_dummy_func(int __FoO[][2]); \ EXTERNC void __static_assert_dummy_func(int __FoO[][_a/_b+_b/_a]); /* This macro could be used to trick g++ into telling you what is the size of a particular data type at compile time. It takes one argument that should be a valid argument for a sizeof operation, and produces a compiler error that will have size of the object included in the message. Only to be used during development, has to be disabled for the build to work. */ #define TELLSIZEOF(_a) \ EXTERNC void __static_tellsizeof_dummy_func(int __FoO[][1]); \ EXTERNC void __static_tellsizeof_dummy_func(int __FoO[][sizeof(_a)]); #endif /* _h_cxiTypes_plat */