OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / user / ser / fastlock.h
1 /*
2  * fast architecture specific locking
3  *
4  * $Id: fastlock.h,v 1.25.2.2 2005/06/06 16:27:32 andrei Exp $
5  *
6  * 
7  *
8  * Copyright (C) 2001-2003 FhG Fokus
9  *
10  * This file is part of ser, a free SIP server.
11  *
12  * ser is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version
16  *
17  * For a license to use the ser software under conditions
18  * other than those described here, or to purchase support for this
19  * software, please contact iptel.org by e-mail at the following addresses:
20  *    info@iptel.org
21  *
22  * ser is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License 
28  * along with this program; if not, write to the Free Software 
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30  */
31 /*
32  *
33  *History:
34  *--------
35  *  2002-02-05  created by andrei
36  *  2003-01-16  added PPC locking code contributed by Dinos Dorkofikis
37  *               <kdor@intranet.gr>
38  *  2004-09-12  added MIPS locking for ISA>=2 (>r3000)  (andrei)
39  *  2004-12-16  for now use the same locking code for sparc32 as for sparc64
40  *               (it will work only if NOSMP is defined) (andrei)
41  *  2005-04-27  added alpha locking code (andrei)
42  *  2005-06-06  ppc locking code enabled also for ppc64, note however
43  *               that the version in HEAD might be more reliable (andrei)
44  *
45  */
46
47
48 #ifndef fastlock_h
49 #define fastlock_h
50
51 #ifdef HAVE_SCHED_YIELD
52 #include <sched.h>
53 #else
54 #include <unistd.h>
55         /* fake sched_yield */
56         #define sched_yield()   sleep(0)
57 #endif
58
59
60 typedef  volatile int fl_lock_t;
61
62
63
64 #define init_lock( l ) (l)=0
65
66
67
68 /*test and set lock, ret 1 if lock held by someone else, 0 otherwise*/
69 inline static int tsl(fl_lock_t* lock)
70 {
71         int val;
72
73 #if defined(__CPU_i386) || defined(__CPU_x86_64)
74
75 #ifdef NOSMP
76         val=0;
77         asm volatile(
78                 " btsl $0, %1 \n\t"
79                 " adcl $0, %0 \n\t"
80                 : "=q" (val), "=m" (*lock) : "0"(val) : "memory", "cc" /* "cc" */
81         );
82 #else
83         val=1;
84         asm volatile( 
85                 " xchg %b1, %0" : "=q" (val), "=m" (*lock) : "0" (val) : "memory"
86         );
87 #endif /*NOSMP*/
88 #elif defined(__CPU_sparc64) || defined(__CPU_sparc)
89         asm volatile(
90                         "ldstub [%1], %0 \n\t"
91 #ifndef NOSMP
92                         "membar #StoreStore | #StoreLoad \n\t"
93 #endif
94                         : "=r"(val) : "r"(lock):"memory"
95         );
96         
97 #elif defined __CPU_arm
98         asm volatile(
99                         "# here \n\t"
100                         "swpb %0, %1, [%2] \n\t"
101                         : "=r" (val)
102                         : "r"(1), "r" (lock) : "memory"
103         );
104         
105 #elif defined(__CPU_ppc) || defined(__CPU_ppc64)
106         asm volatile(
107                         "1: lwarx  %0, 0, %2\n\t"
108                         "   cmpwi  %0, 0\n\t"
109                         "   bne    0f\n\t"
110                         "   stwcx. %1, 0, %2\n\t"
111                         "   bne-   1b\n\t"
112                         "0:\n\t"
113                         : "=r" (val)
114                         : "r"(1), "b" (lock) :
115                         "memory", "cc"
116         );
117 #elif defined __CPU_mips2
118         long tmp;
119         tmp=1; /* just to kill a gcc 2.95 warning */
120         
121         asm volatile(
122                 ".set noreorder\n\t"
123                 "1:  ll %1, %2   \n\t"
124                 "    li %0, 1 \n\t"
125                 "    sc %0, %2  \n\t"
126                 "    beqz %0, 1b \n\t"
127                 "    nop \n\t"
128                 ".set reorder\n\t"
129                 : "=&r" (tmp), "=&r" (val), "=m" (*lock) 
130                 : "0" (tmp), "2" (*lock) 
131                 : "cc"
132         );
133 #elif defined __CPU_alpha
134         long tmp;
135         tmp=0;
136         /* lock low bit set to 1 when the lock is hold and to 0 otherwise */
137         asm volatile(
138                 "1:  ldl %0, %1   \n\t"
139                 "    blbs %0, 2f  \n\t"  /* optimization if locked */
140                 "    ldl_l %0, %1 \n\t"
141                 "    blbs %0, 2f  \n\t" 
142                 "    lda %2, 1    \n\t"  /* or: or $31, 1, %2 ??? */
143                 "    stl_c %2, %1 \n\t"
144                 "    beq %2, 1b   \n\t"
145                 "    mb           \n\t"
146                 "2:               \n\t"
147                 :"=&r" (val), "=m"(*lock), "=r"(tmp)
148                 :"1"(*lock)  /* warning on gcc 3.4: replace it with m or remove
149                                                 it and use +m in the input line ? */
150                 : "memory"
151         );
152 #else
153 #error "unknown architecture"
154 #endif
155         return val;
156 }
157
158
159
160 inline static void get_lock(fl_lock_t* lock)
161 {
162 #ifdef ADAPTIVE_WAIT
163         int i=ADAPTIVE_WAIT_LOOPS;
164 #endif
165         
166         while(tsl(lock)){
167 #ifdef BUSY_WAIT
168 #elif defined ADAPTIVE_WAIT
169                 if (i>0) i--;
170                 else sched_yield();
171 #else
172                 sched_yield();
173 #endif
174         }
175 }
176
177
178
179 inline static void release_lock(fl_lock_t* lock)
180 {
181 #if defined(__CPU_i386) || defined(__CPU_x86_64)
182         char val;
183         val=0;
184         asm volatile(
185                 " movb $0, (%0)" : /*no output*/ : "r"(lock): "memory"
186                 /*" xchg %b0, %1" : "=q" (val), "=m" (*lock) : "0" (val) : "memory"*/
187         ); 
188 #elif defined(__CPU_sparc64) || defined(__CPU_sparc)
189         asm volatile(
190 #ifndef NOSMP
191                         "membar #LoadStore | #StoreStore \n\t" /*is this really needed?*/
192 #endif
193                         "stb %%g0, [%0] \n\t"
194                         : /*no output*/
195                         : "r" (lock)
196                         : "memory"
197         );
198 #elif defined __CPU_arm
199         asm volatile(
200                 " str %0, [%1] \n\r" 
201                 : /*no outputs*/ 
202                 : "r"(0), "r"(lock)
203                 : "memory"
204         );
205 #elif defined(__CPU_ppc) || defined(__CPU_ppc64)
206         asm volatile(
207                         "sync\n\t"
208                         "stw %0, 0(%1)\n\t"
209                         : /* no output */
210                         : "r"(0), "b" (lock)
211                         : "memory"
212         );
213         *lock = 0;
214 #elif defined __CPU_mips2
215         asm volatile(
216                 ".set noreorder \n\t"
217                 "    sync \n\t"
218                 "    sw $0, %0 \n\t"
219                 ".set reorder \n\t"
220                 : /*no output*/  : "m" (*lock) : "memory"
221         );
222 #elif defined __CPU_alpha
223         asm volatile(
224                 "    mb          \n\t"
225                 "    stl $31, %0 \n\t"
226                 : "=m"(*lock) :/* no input*/ : "memory"  /* because of the mb */
227         );  
228 #else
229 #error "unknown architecture"
230 #endif
231 }
232
233
234
235 #endif