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 #else 138 /* use only if nothing else works, expensive due to single mutex for all reference counts */ 139 140 static pthread_mutex_t InterLock = PTHREAD_MUTEX_INITIALIZER; 141 142 /*****************************************************************************/ 143 /* osl_incrementInterlockedCount */ 144 /*****************************************************************************/ 145 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 146 { 147 oslInterlockedCount Count; 148 149 pthread_mutex_lock(&InterLock); 150 Count = ++(*pCount); 151 pthread_mutex_unlock(&InterLock); 152 153 return (Count); 154 } 155 156 /*****************************************************************************/ 157 /* osl_decrementInterlockedCount */ 158 /*****************************************************************************/ 159 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 160 { 161 oslInterlockedCount Count; 162 163 pthread_mutex_lock(&InterLock); 164 Count = --(*pCount); 165 pthread_mutex_unlock(&InterLock); 166 167 return (Count); 168 } 169 170 #endif /* default */ 171