2 * fast architecture specific locking
4 * $Id: fastlock.h,v 1.25.2.2 2005/06/06 16:27:32 andrei Exp $
8 * Copyright (C) 2001-2003 FhG Fokus
10 * This file is part of ser, a free SIP server.
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
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:
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.
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
35 * 2002-02-05 created by andrei
36 * 2003-01-16 added PPC locking code contributed by Dinos Dorkofikis
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)
51 #ifdef HAVE_SCHED_YIELD
55 /* fake sched_yield */
56 #define sched_yield() sleep(0)
60 typedef volatile int fl_lock_t;
64 #define init_lock( l ) (l)=0
68 /*test and set lock, ret 1 if lock held by someone else, 0 otherwise*/
69 inline static int tsl(fl_lock_t* lock)
73 #if defined(__CPU_i386) || defined(__CPU_x86_64)
80 : "=q" (val), "=m" (*lock) : "0"(val) : "memory", "cc" /* "cc" */
85 " xchg %b1, %0" : "=q" (val), "=m" (*lock) : "0" (val) : "memory"
88 #elif defined(__CPU_sparc64) || defined(__CPU_sparc)
90 "ldstub [%1], %0 \n\t"
92 "membar #StoreStore | #StoreLoad \n\t"
94 : "=r"(val) : "r"(lock):"memory"
97 #elif defined __CPU_arm
100 "swpb %0, %1, [%2] \n\t"
102 : "r"(1), "r" (lock) : "memory"
105 #elif defined(__CPU_ppc) || defined(__CPU_ppc64)
107 "1: lwarx %0, 0, %2\n\t"
110 " stwcx. %1, 0, %2\n\t"
114 : "r"(1), "b" (lock) :
117 #elif defined __CPU_mips2
119 tmp=1; /* just to kill a gcc 2.95 warning */
129 : "=&r" (tmp), "=&r" (val), "=m" (*lock)
130 : "0" (tmp), "2" (*lock)
133 #elif defined __CPU_alpha
136 /* lock low bit set to 1 when the lock is hold and to 0 otherwise */
139 " blbs %0, 2f \n\t" /* optimization if locked */
142 " lda %2, 1 \n\t" /* or: or $31, 1, %2 ??? */
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 ? */
153 #error "unknown architecture"
160 inline static void get_lock(fl_lock_t* lock)
163 int i=ADAPTIVE_WAIT_LOOPS;
168 #elif defined ADAPTIVE_WAIT
179 inline static void release_lock(fl_lock_t* lock)
181 #if defined(__CPU_i386) || defined(__CPU_x86_64)
185 " movb $0, (%0)" : /*no output*/ : "r"(lock): "memory"
186 /*" xchg %b0, %1" : "=q" (val), "=m" (*lock) : "0" (val) : "memory"*/
188 #elif defined(__CPU_sparc64) || defined(__CPU_sparc)
191 "membar #LoadStore | #StoreStore \n\t" /*is this really needed?*/
193 "stb %%g0, [%0] \n\t"
198 #elif defined __CPU_arm
205 #elif defined(__CPU_ppc) || defined(__CPU_ppc64)
214 #elif defined __CPU_mips2
216 ".set noreorder \n\t"
220 : /*no output*/ : "m" (*lock) : "memory"
222 #elif defined __CPU_alpha
226 : "=m"(*lock) :/* no input*/ : "memory" /* because of the mb */
229 #error "unknown architecture"