1647f063dSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3647f063dSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4647f063dSAndrew Rist * or more contributor license agreements. See the NOTICE file 5647f063dSAndrew Rist * distributed with this work for additional information 6647f063dSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7647f063dSAndrew Rist * to you under the Apache License, Version 2.0 (the 8647f063dSAndrew Rist * "License"); you may not use this file except in compliance 9647f063dSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11647f063dSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13647f063dSAndrew Rist * Unless required by applicable law or agreed to in writing, 14647f063dSAndrew Rist * software distributed under the License is distributed on an 15647f063dSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16647f063dSAndrew Rist * KIND, either express or implied. See the License for the 17647f063dSAndrew Rist * specific language governing permissions and limitations 18647f063dSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20647f063dSAndrew Rist *************************************************************/ 21647f063dSAndrew Rist 22647f063dSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir 25cdf0e10cSrcweir #include "system.h" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <osl/interlck.h> 28cdf0e10cSrcweir #include <osl/diagnose.h> 29cdf0e10cSrcweir 30cdf0e10cSrcweir #if ( defined ( SOLARIS ) || defined ( NETBSD ) ) && defined ( SPARC ) 31cdf0e10cSrcweir #error please use asm/interlck_sparc.s 32cdf0e10cSrcweir #elif defined ( SOLARIS) && defined ( X86 ) 33cdf0e10cSrcweir #error please use asm/interlck_x86.s 34*4dbb87e9SHerbert Dürr #elif (defined(__GNUC__) || defined(__clang__)) && (defined(X86) || defined(X86_64)) 35cdf0e10cSrcweir /* That's possible on x86-64 too since oslInterlockedCount is a sal_Int32 */ 36cdf0e10cSrcweir 37cdf0e10cSrcweir extern int osl_isSingleCPU; 38cdf0e10cSrcweir 39cdf0e10cSrcweir /*****************************************************************************/ 40cdf0e10cSrcweir /* osl_incrementInterlockedCount */ 41cdf0e10cSrcweir /*****************************************************************************/ 42cdf0e10cSrcweir oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 43cdf0e10cSrcweir { 44cdf0e10cSrcweir register oslInterlockedCount nCount asm("%eax"); 45cdf0e10cSrcweir 46cdf0e10cSrcweir nCount = 1; 47cdf0e10cSrcweir 48cdf0e10cSrcweir if ( osl_isSingleCPU ) { 49cdf0e10cSrcweir __asm__ __volatile__ ( 50cdf0e10cSrcweir "xaddl %0, %1\n\t" 51cdf0e10cSrcweir : "+r" (nCount), "+m" (*pCount) 52cdf0e10cSrcweir : /* nothing */ 53cdf0e10cSrcweir : "memory"); 54cdf0e10cSrcweir } 55cdf0e10cSrcweir else { 56cdf0e10cSrcweir __asm__ __volatile__ ( 57cdf0e10cSrcweir "lock\n\t" 58cdf0e10cSrcweir "xaddl %0, %1\n\t" 59cdf0e10cSrcweir : "+r" (nCount), "+m" (*pCount) 60cdf0e10cSrcweir : /* nothing */ 61cdf0e10cSrcweir : "memory"); 62cdf0e10cSrcweir } 63cdf0e10cSrcweir 64cdf0e10cSrcweir return ++nCount; 65cdf0e10cSrcweir } 66cdf0e10cSrcweir 67cdf0e10cSrcweir oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 68cdf0e10cSrcweir { 69cdf0e10cSrcweir register oslInterlockedCount nCount asm("%eax"); 70cdf0e10cSrcweir 71cdf0e10cSrcweir nCount = -1; 72cdf0e10cSrcweir 73cdf0e10cSrcweir if ( osl_isSingleCPU ) { 74cdf0e10cSrcweir __asm__ __volatile__ ( 75cdf0e10cSrcweir "xaddl %0, %1\n\t" 76cdf0e10cSrcweir : "+r" (nCount), "+m" (*pCount) 77cdf0e10cSrcweir : /* nothing */ 78cdf0e10cSrcweir : "memory"); 79cdf0e10cSrcweir } 80cdf0e10cSrcweir else { 81cdf0e10cSrcweir __asm__ __volatile__ ( 82cdf0e10cSrcweir "lock\n\t" 83cdf0e10cSrcweir "xaddl %0, %1\n\t" 84cdf0e10cSrcweir : "+r" (nCount), "+m" (*pCount) 85cdf0e10cSrcweir : /* nothing */ 86cdf0e10cSrcweir : "memory"); 87cdf0e10cSrcweir } 88cdf0e10cSrcweir 89cdf0e10cSrcweir return --nCount; 90cdf0e10cSrcweir } 91cdf0e10cSrcweir 92cdf0e10cSrcweir #elif defined ( GCC ) && defined ( POWERPC ) 93cdf0e10cSrcweir 94cdf0e10cSrcweir /*****************************************************************************/ 95cdf0e10cSrcweir /* osl_incrementInterlockedCount */ 96cdf0e10cSrcweir /*****************************************************************************/ 97cdf0e10cSrcweir oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 98cdf0e10cSrcweir { 99cdf0e10cSrcweir /* "addi" doesn't work with r0 as second parameter */ 100cdf0e10cSrcweir register oslInterlockedCount nCount __asm__ ("r4"); 101cdf0e10cSrcweir 102cdf0e10cSrcweir __asm__ __volatile__ ( 103cdf0e10cSrcweir "1: lwarx %0,0,%2\n\t" 104cdf0e10cSrcweir " addi %0,%0,1\n\t" 105cdf0e10cSrcweir " stwcx. %0,0,%2\n\t" 106cdf0e10cSrcweir " bne- 1b\n\t" 107cdf0e10cSrcweir " isync" 108cdf0e10cSrcweir : "=&r" (nCount), "=m" (*pCount) 109cdf0e10cSrcweir : "r" (pCount) 110cdf0e10cSrcweir : "memory"); 111cdf0e10cSrcweir 112cdf0e10cSrcweir return nCount; 113cdf0e10cSrcweir } 114cdf0e10cSrcweir 115cdf0e10cSrcweir oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 116cdf0e10cSrcweir { 117cdf0e10cSrcweir /* "subi" doesn't work with r0 as second parameter */ 118cdf0e10cSrcweir register oslInterlockedCount nCount __asm__ ("r4"); 119cdf0e10cSrcweir 120cdf0e10cSrcweir __asm__ __volatile__ ( 121cdf0e10cSrcweir "1: lwarx %0,0,%2\n\t" 122cdf0e10cSrcweir " subi %0,%0,1\n\t" 123cdf0e10cSrcweir " stwcx. %0,0,%2\n\t" 124cdf0e10cSrcweir " bne- 1b\n\t" 125cdf0e10cSrcweir " isync" 126cdf0e10cSrcweir : "=&r" (nCount), "=m" (*pCount) 127cdf0e10cSrcweir : "r" (pCount) 128cdf0e10cSrcweir : "memory"); 129cdf0e10cSrcweir 130cdf0e10cSrcweir return nCount; 131cdf0e10cSrcweir } 132cdf0e10cSrcweir 1331309f2c9SPedro Giffuni #elif defined ( GCC ) && defined ( ARM ) 1341309f2c9SPedro Giffuni 1351309f2c9SPedro Giffuni /*****************************************************************************/ 1361309f2c9SPedro Giffuni /* osl_incrementInterlockedCount */ 1371309f2c9SPedro Giffuni /*****************************************************************************/ 1381309f2c9SPedro Giffuni oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 1391309f2c9SPedro Giffuni { 1401309f2c9SPedro Giffuni #if defined( ARMV7 ) || defined( ARMV6 ) 1411309f2c9SPedro Giffuni register oslInterlockedCount nCount __asm__ ("r1"); 1421309f2c9SPedro Giffuni int nResult; 1431309f2c9SPedro Giffuni 1441309f2c9SPedro Giffuni __asm__ __volatile__ ( 1451309f2c9SPedro Giffuni "1: ldrex %0, [%3]\n" 1461309f2c9SPedro Giffuni " add %0, %0, #1\n" 1471309f2c9SPedro Giffuni " strex %1, %0, [%3]\n" 1481309f2c9SPedro Giffuni " teq %1, #0\n" 1491309f2c9SPedro Giffuni " bne 1b" 1501309f2c9SPedro Giffuni : "=&r" (nCount), "=&r" (nResult), "=m" (*pCount) 1511309f2c9SPedro Giffuni : "r" (pCount) 1521309f2c9SPedro Giffuni : "memory"); 1531309f2c9SPedro Giffuni 1541309f2c9SPedro Giffuni return nCount; 1551309f2c9SPedro Giffuni #else 1561309f2c9SPedro Giffuni return __sync_add_and_fetch( pCount, 1 ); 1571309f2c9SPedro Giffuni #endif 1581309f2c9SPedro Giffuni } 1591309f2c9SPedro Giffuni 1601309f2c9SPedro Giffuni oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 1611309f2c9SPedro Giffuni { 1621309f2c9SPedro Giffuni #if defined( ARMV7 ) || defined( ARMV6 ) 1631309f2c9SPedro Giffuni register oslInterlockedCount nCount __asm__ ("r1"); 1641309f2c9SPedro Giffuni int nResult; 1651309f2c9SPedro Giffuni 1661309f2c9SPedro Giffuni __asm__ __volatile__ ( 1671309f2c9SPedro Giffuni "0: ldrex %0, [%3]\n" 1681309f2c9SPedro Giffuni " sub %0, %0, #1\n" 1691309f2c9SPedro Giffuni " strex %1, %0, [%3]\n" 1701309f2c9SPedro Giffuni " teq %1, #0\n" 1711309f2c9SPedro Giffuni " bne 0b" 1721309f2c9SPedro Giffuni : "=&r" (nCount), "=&r" (nResult), "=m" (*pCount) 1731309f2c9SPedro Giffuni : "r" (pCount) 1741309f2c9SPedro Giffuni : "memory"); 1751309f2c9SPedro Giffuni return nCount; 1761309f2c9SPedro Giffuni #else 1771309f2c9SPedro Giffuni return __sync_sub_and_fetch( pCount, 1 ); 1781309f2c9SPedro Giffuni #endif 1791309f2c9SPedro Giffuni } 1801309f2c9SPedro Giffuni 181cdf0e10cSrcweir #else 182cdf0e10cSrcweir /* use only if nothing else works, expensive due to single mutex for all reference counts */ 183cdf0e10cSrcweir 184cdf0e10cSrcweir static pthread_mutex_t InterLock = PTHREAD_MUTEX_INITIALIZER; 185cdf0e10cSrcweir 186cdf0e10cSrcweir /*****************************************************************************/ 187cdf0e10cSrcweir /* osl_incrementInterlockedCount */ 188cdf0e10cSrcweir /*****************************************************************************/ 189cdf0e10cSrcweir oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount) 190cdf0e10cSrcweir { 191cdf0e10cSrcweir oslInterlockedCount Count; 192cdf0e10cSrcweir 193cdf0e10cSrcweir pthread_mutex_lock(&InterLock); 194cdf0e10cSrcweir Count = ++(*pCount); 195cdf0e10cSrcweir pthread_mutex_unlock(&InterLock); 196cdf0e10cSrcweir 197cdf0e10cSrcweir return (Count); 198cdf0e10cSrcweir } 199cdf0e10cSrcweir 200cdf0e10cSrcweir /*****************************************************************************/ 201cdf0e10cSrcweir /* osl_decrementInterlockedCount */ 202cdf0e10cSrcweir /*****************************************************************************/ 203cdf0e10cSrcweir oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount) 204cdf0e10cSrcweir { 205cdf0e10cSrcweir oslInterlockedCount Count; 206cdf0e10cSrcweir 207cdf0e10cSrcweir pthread_mutex_lock(&InterLock); 208cdf0e10cSrcweir Count = --(*pCount); 209cdf0e10cSrcweir pthread_mutex_unlock(&InterLock); 210cdf0e10cSrcweir 211cdf0e10cSrcweir return (Count); 212cdf0e10cSrcweir } 213cdf0e10cSrcweir 214cdf0e10cSrcweir #endif /* default */ 215*4dbb87e9SHerbert Dürr 216