xref: /aoo41x/main/sal/osl/unx/interlck.c (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 #include "system.h"
30 
31 #include <osl/interlck.h>
32 #include <osl/diagnose.h>
33 
34 #if  ( defined ( SOLARIS ) || defined ( NETBSD ) ) && defined ( SPARC )
35 #error please use asm/interlck_sparc.s
36 #elif defined ( SOLARIS) && defined ( X86 )
37 #error please use asm/interlck_x86.s
38 #elif defined ( GCC ) && ( defined ( X86 ) || defined ( X86_64 ) )
39 /* That's possible on x86-64 too since oslInterlockedCount is a sal_Int32 */
40 
41 extern int osl_isSingleCPU;
42 
43 /*****************************************************************************/
44 /* osl_incrementInterlockedCount */
45 /*****************************************************************************/
46 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
47 {
48     register oslInterlockedCount nCount asm("%eax");
49 
50     nCount = 1;
51 
52     if ( osl_isSingleCPU ) {
53         __asm__ __volatile__ (
54             "xaddl %0, %1\n\t"
55         :   "+r" (nCount), "+m" (*pCount)
56         :   /* nothing */
57         :   "memory");
58     }
59     else {
60         __asm__ __volatile__ (
61             "lock\n\t"
62             "xaddl %0, %1\n\t"
63         :   "+r" (nCount), "+m" (*pCount)
64         :   /* nothing */
65         :   "memory");
66     }
67 
68     return ++nCount;
69 }
70 
71 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
72 {
73     register oslInterlockedCount nCount asm("%eax");
74 
75     nCount = -1;
76 
77     if ( osl_isSingleCPU ) {
78         __asm__ __volatile__ (
79             "xaddl %0, %1\n\t"
80         :   "+r" (nCount), "+m" (*pCount)
81         :   /* nothing */
82         :   "memory");
83     }
84     else {
85         __asm__ __volatile__ (
86             "lock\n\t"
87             "xaddl %0, %1\n\t"
88         :   "+r" (nCount), "+m" (*pCount)
89         :   /* nothing */
90         :   "memory");
91     }
92 
93     return --nCount;
94 }
95 
96 #elif defined ( GCC ) && defined ( POWERPC )
97 
98 /*****************************************************************************/
99 /* osl_incrementInterlockedCount */
100 /*****************************************************************************/
101 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
102 {
103     /* "addi" doesn't work with r0 as second parameter */
104     register oslInterlockedCount nCount __asm__ ("r4");
105 
106     __asm__ __volatile__ (
107         "1: lwarx   %0,0,%2\n\t"
108         "   addi    %0,%0,1\n\t"
109         "   stwcx.  %0,0,%2\n\t"
110         "   bne-    1b\n\t"
111         "   isync"
112         : "=&r" (nCount), "=m" (*pCount)
113         : "r" (pCount)
114         : "memory");
115 
116     return nCount;
117 }
118 
119 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
120 {
121     /* "subi" doesn't work with r0 as second parameter */
122     register oslInterlockedCount nCount __asm__ ("r4");
123 
124     __asm__ __volatile__ (
125         "1: lwarx   %0,0,%2\n\t"
126         "   subi    %0,%0,1\n\t"
127         "   stwcx.  %0,0,%2\n\t"
128         "   bne-    1b\n\t"
129         "   isync"
130         : "=&r" (nCount), "=m" (*pCount)
131         : "r" (pCount)
132         : "memory");
133 
134     return nCount;
135 }
136 
137 #else
138 /* use only if nothing else works, expensive due to single mutex for all reference counts */
139 
140 static pthread_mutex_t InterLock = PTHREAD_MUTEX_INITIALIZER;
141 
142 /*****************************************************************************/
143 /* osl_incrementInterlockedCount */
144 /*****************************************************************************/
145 oslInterlockedCount SAL_CALL osl_incrementInterlockedCount(oslInterlockedCount* pCount)
146 {
147     oslInterlockedCount Count;
148 
149     pthread_mutex_lock(&InterLock);
150     Count = ++(*pCount);
151     pthread_mutex_unlock(&InterLock);
152 
153     return (Count);
154 }
155 
156 /*****************************************************************************/
157 /* osl_decrementInterlockedCount */
158 /*****************************************************************************/
159 oslInterlockedCount SAL_CALL osl_decrementInterlockedCount(oslInterlockedCount* pCount)
160 {
161     oslInterlockedCount Count;
162 
163     pthread_mutex_lock(&InterLock);
164     Count = --(*pCount);
165     pthread_mutex_unlock(&InterLock);
166 
167     return (Count);
168 }
169 
170 #endif /* default */
171