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