1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 #include "system.h" 30 31 #include <osl/interlck.h> 32 #include <osl/diagnose.h> 33 34 #if ( defined ( SOLARIS ) || defined ( NETBSD ) ) && defined ( SPARC ) 35 #error please use asm/interlck_sparc.s 36 #elif defined ( SOLARIS) && defined ( X86 ) 37 #error please use asm/interlck_x86.s 38 #elif defined ( GCC ) && ( defined ( X86 ) || defined ( X86_64 ) ) 39 /* That's possible on x86-64 too since oslInterlockedCount is a sal_Int32 */ 40 41 extern int osl_isSingleCPU; 42 43 /*****************************************************************************/ 44 /* osl_incrementInterlockedCount */ 45 /*****************************************************************************/ 46 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 47 { 48 register oslInterlockedCount nCount asm("%eax"); 49 50 nCount = 1; 51 52 if ( osl_isSingleCPU ) { 53 __asm__ __volatile__ ( 54 "xaddl %0, %1\n\t" 55 : "+r" (nCount), "+m" (*pCount) 56 : /* nothing */ 57 : "memory"); 58 } 59 else { 60 __asm__ __volatile__ ( 61 "lock\n\t" 62 "xaddl %0, %1\n\t" 63 : "+r" (nCount), "+m" (*pCount) 64 : /* nothing */ 65 : "memory"); 66 } 67 68 return ++nCount; 69 } 70 71 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 72 { 73 register oslInterlockedCount nCount asm("%eax"); 74 75 nCount = -1; 76 77 if ( osl_isSingleCPU ) { 78 __asm__ __volatile__ ( 79 "xaddl %0, %1\n\t" 80 : "+r" (nCount), "+m" (*pCount) 81 : /* nothing */ 82 : "memory"); 83 } 84 else { 85 __asm__ __volatile__ ( 86 "lock\n\t" 87 "xaddl %0, %1\n\t" 88 : "+r" (nCount), "+m" (*pCount) 89 : /* nothing */ 90 : "memory"); 91 } 92 93 return --nCount; 94 } 95 96 #elif defined ( GCC ) && defined ( POWERPC ) 97 98 /*****************************************************************************/ 99 /* osl_incrementInterlockedCount */ 100 /*****************************************************************************/ 101 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 102 { 103 /* "addi" doesn't work with r0 as second parameter */ 104 register oslInterlockedCount nCount __asm__ ("r4"); 105 106 __asm__ __volatile__ ( 107 "1: lwarx %0,0,%2\n\t" 108 " addi %0,%0,1\n\t" 109 " stwcx. %0,0,%2\n\t" 110 " bne- 1b\n\t" 111 " isync" 112 : "=&r" (nCount), "=m" (*pCount) 113 : "r" (pCount) 114 : "memory"); 115 116 return nCount; 117 } 118 119 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 120 { 121 /* "subi" doesn't work with r0 as second parameter */ 122 register oslInterlockedCount nCount __asm__ ("r4"); 123 124 __asm__ __volatile__ ( 125 "1: lwarx %0,0,%2\n\t" 126 " subi %0,%0,1\n\t" 127 " stwcx. %0,0,%2\n\t" 128 " bne- 1b\n\t" 129 " isync" 130 : "=&r" (nCount), "=m" (*pCount) 131 : "r" (pCount) 132 : "memory"); 133 134 return nCount; 135 } 136 137 #elif defined ( GCC ) && defined ( ARM ) 138 139 /*****************************************************************************/ 140 /* osl_incrementInterlockedCount */ 141 /*****************************************************************************/ 142 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 143 { 144 #if defined( ARMV7 ) || defined( ARMV6 ) 145 register oslInterlockedCount nCount __asm__ ("r1"); 146 int nResult; 147 148 __asm__ __volatile__ ( 149 "1: ldrex %0, [%3]\n" 150 " add %0, %0, #1\n" 151 " strex %1, %0, [%3]\n" 152 " teq %1, #0\n" 153 " bne 1b" 154 : "=&r" (nCount), "=&r" (nResult), "=m" (*pCount) 155 : "r" (pCount) 156 : "memory"); 157 158 return nCount; 159 #else 160 return __sync_add_and_fetch( pCount, 1 ); 161 #endif 162 } 163 164 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 165 { 166 #if defined( ARMV7 ) || defined( ARMV6 ) 167 register oslInterlockedCount nCount __asm__ ("r1"); 168 int nResult; 169 170 __asm__ __volatile__ ( 171 "0: ldrex %0, [%3]\n" 172 " sub %0, %0, #1\n" 173 " strex %1, %0, [%3]\n" 174 " teq %1, #0\n" 175 " bne 0b" 176 : "=&r" (nCount), "=&r" (nResult), "=m" (*pCount) 177 : "r" (pCount) 178 : "memory"); 179 return nCount; 180 #else 181 return __sync_sub_and_fetch( pCount, 1 ); 182 #endif 183 } 184 185 #else 186 /* use only if nothing else works, expensive due to single mutex for all reference counts */ 187 188 static pthread_mutex_t InterLock = PTHREAD_MUTEX_INITIALIZER; 189 190 /*****************************************************************************/ 191 /* osl_incrementInterlockedCount */ 192 /*****************************************************************************/ 193 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 194 { 195 oslInterlockedCount Count; 196 197 pthread_mutex_lock(&InterLock); 198 Count = ++(*pCount); 199 pthread_mutex_unlock(&InterLock); 200 201 return (Count); 202 } 203 204 /*****************************************************************************/ 205 /* osl_decrementInterlockedCount */ 206 /*****************************************************************************/ 207 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 208 { 209 oslInterlockedCount Count; 210 211 pthread_mutex_lock(&InterLock); 212 Count = --(*pCount); 213 pthread_mutex_unlock(&InterLock); 214 215 return (Count); 216 } 217 218 #endif /* default */ 219