xref: /aoo42x/main/sal/osl/unx/interlck.c (revision 4dbb87e9)
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
10647f063dSAndrew Rist  *
11647f063dSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12647f063dSAndrew Rist  *
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.
19647f063dSAndrew Rist  *
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 /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)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 
osl_decrementInterlockedCount(oslInterlockedCount * pCount)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 /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)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 
osl_decrementInterlockedCount(oslInterlockedCount * pCount)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 /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)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 
osl_decrementInterlockedCount(oslInterlockedCount * pCount)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 /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)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 /*****************************************************************************/
osl_decrementInterlockedCount(oslInterlockedCount * pCount)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