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