c72af3eb0ad5bc4e0eb7edd36e2f3f53f860bc89
[sip-router] / fastlock.h
1 /*
2  * fast arhitecture specific locking
3  *
4  * $Id$
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  *
34  *  2003-01-16  added PPC locking code contributed by Dinos Dorkofikis
35  *               <kdor@intranet.gr>
36  *
37  */
38
39
40 #ifndef fastlock_h
41 #define fastlock_h
42
43 #ifdef HAVE_SCHED_YIELD
44 #include <sched.h>
45 #else
46 #include <unistd.h>
47         /* fake sched_yield */
48         #define sched_yield()   sleep(0)
49 #endif
50
51
52 typedef  volatile int fl_lock_t;
53
54
55
56 #define init_lock( l ) (l)=0
57
58
59
60 /*test and set lock, ret 1 if lock held by someone else, 0 otherwise*/
61 inline static int tsl(fl_lock_t* lock)
62 {
63         int val;
64
65 #ifdef __CPU_i386
66
67 #ifdef NOSMP
68         val=0;
69         asm volatile(
70                 " btsl $0, %1 \n\t"
71                 " adcl $0, %0 \n\t"
72                 : "=q" (val), "=m" (*lock) : "0"(val) : "memory", "cc" /* "cc" */
73         );
74 #else
75         val=1;
76         asm volatile( 
77                 " xchg %b1, %0" : "=q" (val), "=m" (*lock) : "0" (val) : "memory"
78         );
79 #endif /*NOSMP*/
80 #elif defined __CPU_sparc64
81         asm volatile(
82                         "ldstub [%1], %0 \n\t"
83 #ifndef NOSMP
84                         "membar #StoreStore | #StoreLoad \n\t"
85 #endif
86                         : "=r"(val) : "r"(lock):"memory"
87         );
88         
89 #elif defined __CPU_arm
90         asm volatile(
91                         "# here \n\t"
92                         "swpb %0, %1, [%2] \n\t"
93                         : "=r" (val)
94                         : "r"(1), "r" (lock) : "memory"
95         );
96         
97 #elif defined __CPU_ppc
98         asm volatile(
99                         "1: lwarx  %0, 0, %2\n\t"
100                         "   cmpwi  %0, 0\n\t"
101                         "   bne    0f\n\t"
102                         "   stwcx. %1, 0, %2\n\t"
103                         "   bne-   1b\n\t"
104                         "0:\n\t"
105                         : "=r" (val)
106                         : "r"(1), "b" (lock) :
107                         "memory", "cc"
108         );
109 #else
110 #error "unknown arhitecture"
111 #endif
112         return val;
113 }
114
115
116
117 inline static void get_lock(fl_lock_t* lock)
118 {
119 #ifdef ADAPTIVE_WAIT
120         int i=ADAPTIVE_WAIT_LOOPS;
121 #endif
122         
123         while(tsl(lock)){
124 #ifdef BUSY_WAIT
125 #elif defined ADAPTIVE_WAIT
126                 if (i>0) i--;
127                 else sched_yield();
128 #else
129                 sched_yield();
130 #endif
131         }
132 }
133
134
135
136 inline static void release_lock(fl_lock_t* lock)
137 {
138 #ifdef __CPU_i386
139         char val;
140         val=0;
141         asm volatile(
142                 " movb $0, (%0)" : /*no output*/ : "r"(lock): "memory"
143                 /*" xchg %b0, %1" : "=q" (val), "=m" (*lock) : "0" (val) : "memory"*/
144         ); 
145 #elif defined __CPU_sparc64
146         asm volatile(
147 #ifndef NOSMP
148                         "membar #LoadStore | #StoreStore \n\t" /*is this really needed?*/
149 #endif
150                         "stb %%g0, [%0] \n\t"
151                         : /*no output*/
152                         : "r" (lock)
153                         : "memory"
154         );
155 #elif defined __CPU_arm
156         asm volatile(
157                 " str %0, [%1] \n\r" 
158                 : /*no outputs*/ 
159                 : "r"(0), "r"(lock)
160                 : "memory"
161         );
162 #elif defined __CPU_ppc
163         asm volatile(
164                         "sync\n\t"
165                         "stw %0, 0(%1)\n\t"
166                         : /* no output */
167                         : "r"(0), "b" (lock)
168                         : "memory"
169         );
170         *lock = 0;
171 #else
172 #error "unknown arhitecture"
173 #endif
174 }
175
176
177
178 #endif