xref: /aoo4110/main/sal/osl/unx/interlck.c (revision b1cdbd2c)
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