1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski
25*b1cdbd2cSJim Jagielski #include "system.h"
26*b1cdbd2cSJim Jagielski
27*b1cdbd2cSJim Jagielski #include <osl/interlck.h>
28*b1cdbd2cSJim Jagielski #include <osl/diagnose.h>
29*b1cdbd2cSJim Jagielski
30*b1cdbd2cSJim Jagielski #if ( defined ( SOLARIS ) || defined ( NETBSD ) ) && defined ( SPARC )
31*b1cdbd2cSJim Jagielski #error please use asm/interlck_sparc.s
32*b1cdbd2cSJim Jagielski #elif defined ( SOLARIS) && defined ( X86 )
33*b1cdbd2cSJim Jagielski #error please use asm/interlck_x86.s
34*b1cdbd2cSJim Jagielski #elif (defined(__GNUC__) || defined(__clang__)) && (defined(X86) || defined(X86_64))
35*b1cdbd2cSJim Jagielski /* That's possible on x86-64 too since oslInterlockedCount is a sal_Int32 */
36*b1cdbd2cSJim Jagielski
37*b1cdbd2cSJim Jagielski extern int osl_isSingleCPU;
38*b1cdbd2cSJim Jagielski
39*b1cdbd2cSJim Jagielski /*****************************************************************************/
40*b1cdbd2cSJim Jagielski /* osl_incrementInterlockedCount */
41*b1cdbd2cSJim Jagielski /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)42*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
43*b1cdbd2cSJim Jagielski {
44*b1cdbd2cSJim Jagielski register oslInterlockedCount nCount asm("%eax");
45*b1cdbd2cSJim Jagielski
46*b1cdbd2cSJim Jagielski nCount = 1;
47*b1cdbd2cSJim Jagielski
48*b1cdbd2cSJim Jagielski if ( osl_isSingleCPU ) {
49*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
50*b1cdbd2cSJim Jagielski "xaddl %0, %1\n\t"
51*b1cdbd2cSJim Jagielski : "+r" (nCount), "+m" (*pCount)
52*b1cdbd2cSJim Jagielski : /* nothing */
53*b1cdbd2cSJim Jagielski : "memory");
54*b1cdbd2cSJim Jagielski }
55*b1cdbd2cSJim Jagielski else {
56*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
57*b1cdbd2cSJim Jagielski "lock\n\t"
58*b1cdbd2cSJim Jagielski "xaddl %0, %1\n\t"
59*b1cdbd2cSJim Jagielski : "+r" (nCount), "+m" (*pCount)
60*b1cdbd2cSJim Jagielski : /* nothing */
61*b1cdbd2cSJim Jagielski : "memory");
62*b1cdbd2cSJim Jagielski }
63*b1cdbd2cSJim Jagielski
64*b1cdbd2cSJim Jagielski return ++nCount;
65*b1cdbd2cSJim Jagielski }
66*b1cdbd2cSJim Jagielski
osl_decrementInterlockedCount(oslInterlockedCount * pCount)67*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
68*b1cdbd2cSJim Jagielski {
69*b1cdbd2cSJim Jagielski register oslInterlockedCount nCount asm("%eax");
70*b1cdbd2cSJim Jagielski
71*b1cdbd2cSJim Jagielski nCount = -1;
72*b1cdbd2cSJim Jagielski
73*b1cdbd2cSJim Jagielski if ( osl_isSingleCPU ) {
74*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
75*b1cdbd2cSJim Jagielski "xaddl %0, %1\n\t"
76*b1cdbd2cSJim Jagielski : "+r" (nCount), "+m" (*pCount)
77*b1cdbd2cSJim Jagielski : /* nothing */
78*b1cdbd2cSJim Jagielski : "memory");
79*b1cdbd2cSJim Jagielski }
80*b1cdbd2cSJim Jagielski else {
81*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
82*b1cdbd2cSJim Jagielski "lock\n\t"
83*b1cdbd2cSJim Jagielski "xaddl %0, %1\n\t"
84*b1cdbd2cSJim Jagielski : "+r" (nCount), "+m" (*pCount)
85*b1cdbd2cSJim Jagielski : /* nothing */
86*b1cdbd2cSJim Jagielski : "memory");
87*b1cdbd2cSJim Jagielski }
88*b1cdbd2cSJim Jagielski
89*b1cdbd2cSJim Jagielski return --nCount;
90*b1cdbd2cSJim Jagielski }
91*b1cdbd2cSJim Jagielski
92*b1cdbd2cSJim Jagielski #elif defined ( GCC ) && defined ( POWERPC )
93*b1cdbd2cSJim Jagielski
94*b1cdbd2cSJim Jagielski /*****************************************************************************/
95*b1cdbd2cSJim Jagielski /* osl_incrementInterlockedCount */
96*b1cdbd2cSJim Jagielski /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)97*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
98*b1cdbd2cSJim Jagielski {
99*b1cdbd2cSJim Jagielski /* "addi" doesn't work with r0 as second parameter */
100*b1cdbd2cSJim Jagielski register oslInterlockedCount nCount __asm__ ("r4");
101*b1cdbd2cSJim Jagielski
102*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
103*b1cdbd2cSJim Jagielski "1: lwarx %0,0,%2\n\t"
104*b1cdbd2cSJim Jagielski " addi %0,%0,1\n\t"
105*b1cdbd2cSJim Jagielski " stwcx. %0,0,%2\n\t"
106*b1cdbd2cSJim Jagielski " bne- 1b\n\t"
107*b1cdbd2cSJim Jagielski " isync"
108*b1cdbd2cSJim Jagielski : "=&r" (nCount), "=m" (*pCount)
109*b1cdbd2cSJim Jagielski : "r" (pCount)
110*b1cdbd2cSJim Jagielski : "memory");
111*b1cdbd2cSJim Jagielski
112*b1cdbd2cSJim Jagielski return nCount;
113*b1cdbd2cSJim Jagielski }
114*b1cdbd2cSJim Jagielski
osl_decrementInterlockedCount(oslInterlockedCount * pCount)115*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
116*b1cdbd2cSJim Jagielski {
117*b1cdbd2cSJim Jagielski /* "subi" doesn't work with r0 as second parameter */
118*b1cdbd2cSJim Jagielski register oslInterlockedCount nCount __asm__ ("r4");
119*b1cdbd2cSJim Jagielski
120*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
121*b1cdbd2cSJim Jagielski "1: lwarx %0,0,%2\n\t"
122*b1cdbd2cSJim Jagielski " subi %0,%0,1\n\t"
123*b1cdbd2cSJim Jagielski " stwcx. %0,0,%2\n\t"
124*b1cdbd2cSJim Jagielski " bne- 1b\n\t"
125*b1cdbd2cSJim Jagielski " isync"
126*b1cdbd2cSJim Jagielski : "=&r" (nCount), "=m" (*pCount)
127*b1cdbd2cSJim Jagielski : "r" (pCount)
128*b1cdbd2cSJim Jagielski : "memory");
129*b1cdbd2cSJim Jagielski
130*b1cdbd2cSJim Jagielski return nCount;
131*b1cdbd2cSJim Jagielski }
132*b1cdbd2cSJim Jagielski
133*b1cdbd2cSJim Jagielski #elif defined ( GCC ) && defined ( ARM )
134*b1cdbd2cSJim Jagielski
135*b1cdbd2cSJim Jagielski /*****************************************************************************/
136*b1cdbd2cSJim Jagielski /* osl_incrementInterlockedCount */
137*b1cdbd2cSJim Jagielski /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)138*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
139*b1cdbd2cSJim Jagielski {
140*b1cdbd2cSJim Jagielski #if defined( ARMV7 ) || defined( ARMV6 )
141*b1cdbd2cSJim Jagielski register oslInterlockedCount nCount __asm__ ("r1");
142*b1cdbd2cSJim Jagielski int nResult;
143*b1cdbd2cSJim Jagielski
144*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
145*b1cdbd2cSJim Jagielski "1: ldrex %0, [%3]\n"
146*b1cdbd2cSJim Jagielski " add %0, %0, #1\n"
147*b1cdbd2cSJim Jagielski " strex %1, %0, [%3]\n"
148*b1cdbd2cSJim Jagielski " teq %1, #0\n"
149*b1cdbd2cSJim Jagielski " bne 1b"
150*b1cdbd2cSJim Jagielski : "=&r" (nCount), "=&r" (nResult), "=m" (*pCount)
151*b1cdbd2cSJim Jagielski : "r" (pCount)
152*b1cdbd2cSJim Jagielski : "memory");
153*b1cdbd2cSJim Jagielski
154*b1cdbd2cSJim Jagielski return nCount;
155*b1cdbd2cSJim Jagielski #else
156*b1cdbd2cSJim Jagielski return __sync_add_and_fetch( pCount, 1 );
157*b1cdbd2cSJim Jagielski #endif
158*b1cdbd2cSJim Jagielski }
159*b1cdbd2cSJim Jagielski
osl_decrementInterlockedCount(oslInterlockedCount * pCount)160*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
161*b1cdbd2cSJim Jagielski {
162*b1cdbd2cSJim Jagielski #if defined( ARMV7 ) || defined( ARMV6 )
163*b1cdbd2cSJim Jagielski register oslInterlockedCount nCount __asm__ ("r1");
164*b1cdbd2cSJim Jagielski int nResult;
165*b1cdbd2cSJim Jagielski
166*b1cdbd2cSJim Jagielski __asm__ __volatile__ (
167*b1cdbd2cSJim Jagielski "0: ldrex %0, [%3]\n"
168*b1cdbd2cSJim Jagielski " sub %0, %0, #1\n"
169*b1cdbd2cSJim Jagielski " strex %1, %0, [%3]\n"
170*b1cdbd2cSJim Jagielski " teq %1, #0\n"
171*b1cdbd2cSJim Jagielski " bne 0b"
172*b1cdbd2cSJim Jagielski : "=&r" (nCount), "=&r" (nResult), "=m" (*pCount)
173*b1cdbd2cSJim Jagielski : "r" (pCount)
174*b1cdbd2cSJim Jagielski : "memory");
175*b1cdbd2cSJim Jagielski return nCount;
176*b1cdbd2cSJim Jagielski #else
177*b1cdbd2cSJim Jagielski return __sync_sub_and_fetch( pCount, 1 );
178*b1cdbd2cSJim Jagielski #endif
179*b1cdbd2cSJim Jagielski }
180*b1cdbd2cSJim Jagielski
181*b1cdbd2cSJim Jagielski #else
182*b1cdbd2cSJim Jagielski /* use only if nothing else works, expensive due to single mutex for all reference counts */
183*b1cdbd2cSJim Jagielski
184*b1cdbd2cSJim Jagielski static pthread_mutex_t InterLock = PTHREAD_MUTEX_INITIALIZER;
185*b1cdbd2cSJim Jagielski
186*b1cdbd2cSJim Jagielski /*****************************************************************************/
187*b1cdbd2cSJim Jagielski /* osl_incrementInterlockedCount */
188*b1cdbd2cSJim Jagielski /*****************************************************************************/
osl_incrementInterlockedCount(oslInterlockedCount * pCount)189*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
190*b1cdbd2cSJim Jagielski {
191*b1cdbd2cSJim Jagielski oslInterlockedCount Count;
192*b1cdbd2cSJim Jagielski
193*b1cdbd2cSJim Jagielski pthread_mutex_lock(&InterLock);
194*b1cdbd2cSJim Jagielski Count = ++(*pCount);
195*b1cdbd2cSJim Jagielski pthread_mutex_unlock(&InterLock);
196*b1cdbd2cSJim Jagielski
197*b1cdbd2cSJim Jagielski return (Count);
198*b1cdbd2cSJim Jagielski }
199*b1cdbd2cSJim Jagielski
200*b1cdbd2cSJim Jagielski /*****************************************************************************/
201*b1cdbd2cSJim Jagielski /* osl_decrementInterlockedCount */
202*b1cdbd2cSJim Jagielski /*****************************************************************************/
osl_decrementInterlockedCount(oslInterlockedCount * pCount)203*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
204*b1cdbd2cSJim Jagielski {
205*b1cdbd2cSJim Jagielski oslInterlockedCount Count;
206*b1cdbd2cSJim Jagielski
207*b1cdbd2cSJim Jagielski pthread_mutex_lock(&InterLock);
208*b1cdbd2cSJim Jagielski Count = --(*pCount);
209*b1cdbd2cSJim Jagielski pthread_mutex_unlock(&InterLock);
210*b1cdbd2cSJim Jagielski
211*b1cdbd2cSJim Jagielski return (Count);
212*b1cdbd2cSJim Jagielski }
213*b1cdbd2cSJim Jagielski
214*b1cdbd2cSJim Jagielski #endif /* default */
215*b1cdbd2cSJim Jagielski
216