Date: Sun, 12 Dec 1999 11:10:39 -0800 (PST) From: jburkhol@home.com To: FreeBSD-gnats-submit@freebsd.org Subject: kern/15440: support atomic locks in the UP kernel Message-ID: <19991212191039.F2AB01FCD@io.yi.org>
next in thread | raw e-mail | index | archive | help
>Number: 15440 >Category: kern >Synopsis: support atomic locks in the UP kernel >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Sun Dec 12 11:20:01 PST 1999 >Closed-Date: >Last-Modified: >Originator: Jake Burkholder >Release: FreeBSD 4.0-CURRENT i386 >Organization: none >Environment: 4.0-CURRENT >Description: This patch brings in alpha inline asm versions of s_lock_init, s_lock, s_lock_try and s_unlock from netbsd, and converts the existing i386 routines to inline asm as well. This way the locks are useable from userland, simply by including <machine/lock.h>. It is hoped that these routines will aid in making the linuxthreads port pltaform independent, and serve as a basis for more advanvced synchronization primitives when native threads are developed. I've tested this on a UP i386 machine, but do not have access to SMP or alpha hardware. An SMP kernel compiles, and there should be no functional changes in that case, since the debug versions in simplelock.s are used rather than these inline ones. The alpha versions are taken directly from netbsd, so I assume they work fine. >How-To-Repeat: n/a >Fix: The patch is included below, and is also available at http://io.yi.org/lock.diff. Index: alpha/include/lock.h =================================================================== RCS file: /home/ncvs/src/sys/alpha/include/lock.h,v retrieving revision 1.5 diff -c -r1.5 lock.h *** lock.h 1999/08/28 00:38:47 1.5 --- lock.h 1999/12/12 10:24:43 *************** *** 29,34 **** --- 29,38 ---- #ifndef _MACHINE_LOCK_H_ #define _MACHINE_LOCK_H_ + #define COM_LOCK() + #define COM_UNLOCK() + + #define SIMPLELOCK_LOCKED 1 /* * Simple spin lock. *************** *** 38,44 **** volatile int lock_data; }; ! #define COM_LOCK() ! #define COM_UNLOCK() #endif /* !_MACHINE_LOCK_H_ */ --- 42,165 ---- volatile int lock_data; }; ! /* inline simplelock functions */ ! static __inline void s_lock_init __P((struct simplelock *)); ! static __inline void s_lock __P((struct simplelock *)); ! static __inline void s_lock_try __P((struct simplelock *)); ! static __inline void s_unlock __P((struct simplelock *)); ! ! /* ! * void ! * s_lock_init(struct simplelock *lkp) ! * { ! * lkp->lock_data = 0; ! * } ! */ ! static __inline void ! s_lock_init(lkp) ! struct simplelock *lkp; ! { ! ! __asm __volatile( ! "# BEGIN cpu_simple_lock_init\n" ! " stl $31, %0 \n" ! " mb \n" ! " # END cpu_simple_lock_init" ! : "=m" (lkp->lock_data)); ! } ! ! /* ! * void ! * s_lock(struct simplelock *lkp) ! * { ! * while (test_and_set(&lkp->lock_data)) ! * continue; ! * } ! */ ! static __inline void ! s_lock(lkp) ! struct simplelock *lkp; ! { ! unsigned long t0; ! ! /* ! * Note, if we detect that the lock is held when ! * we do the initial load-locked, we spin using ! * a non-locked load to save the coherency logic ! * some work. ! */ ! ! __asm __volatile( ! "# BEGIN cpu_simple_lock\n" ! "1: ldl_l %0, %3 \n" ! " bne %0, 2f \n" ! " bis $31, %2, %0 \n" ! " stl_c %0, %1 \n" ! " beq %0, 3f \n" ! " mb \n" ! " br 4f \n" ! "2: ldl %0, %3 \n" ! " beq %0, 1b \n" ! " br 2b \n" ! "3: br 1b \n" ! "4: \n" ! " # END cpu_simple_lock\n" ! : "=r" (t0), "=m" (lkp->lock_data) ! : "i" (SIMPLELOCK_LOCKED), "1" (lkp->lock_data)); ! } ! ! /* ! * int ! * s_lock_try(struct simplelock *lkp) ! * { ! * return (!test_and_set(&lkp->lock_data)); ! * } ! */ ! static __inline int ! s_lock_try(lkp) ! struct simplelock *lkp; ! { ! unsigned long t0, v0; ! ! __asm __volatile( ! "# BEGIN cpu_simple_lock_try\n" ! "1: ldl_l %0, %4 \n" ! " bne %0, 2f \n" ! " bis $31, %3, %0 \n" ! " stl_c %0, %2 \n" ! " beq %0, 3f \n" ! " mb \n" ! " bis $31, 1, %1 \n" ! " br 4f \n" ! "2: bis $31, $31, %1 \n" ! " br 4f \n" ! "3: br 1b \n" ! "4: \n" ! " # END cpu_simple_lock_try" ! : "=r" (t0), "=r" (v0), "=m" (lkp->lock_data) ! : "i" (SIMPLELOCK_LOCKED), "2" (lkp->lock_data)); ! ! return (v0); ! } ! ! /* ! * void ! * s_unlock(struct simplelock *lkp) ! * { ! * lkp->lock_data = 0; ! * } ! */ ! static __inline void ! s_unlock(lkp) ! struct simplelock *lkp; ! { ! ! __asm __volatile( ! "# BEGIN cpu_simple_unlock\n" ! " stl $31, %0 \n" ! " mb \n" ! " # END cpu_simple_unlock" ! : "=m" (lkp->lock_data)); ! } #endif /* !_MACHINE_LOCK_H_ */ Index: i386/i386/simplelock.s =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/simplelock.s,v retrieving revision 1.11 diff -c -r1.11 simplelock.s *** simplelock.s 1999/08/28 00:43:50 1.11 --- simplelock.s 1999/12/12 10:28:58 *************** *** 57,75 **** /* * void - * s_lock_init(struct simplelock *lkp) - * { - * lkp->lock_data = 0; - * } - */ - ENTRY(s_lock_init) - movl 4(%esp), %eax /* get the address of the lock */ - movl $0, (%eax) - ret - - - /* - * void * s_lock(struct simplelock *lkp) * { * while (test_and_set(&lkp->lock_data)) --- 57,62 ---- *************** *** 84,106 **** * the local cache (and thus causing external bus writes) with repeated * writes to the lock. */ ! #ifndef SL_DEBUG ! ! ENTRY(s_lock) ! movl 4(%esp), %eax /* get the address of the lock */ ! movl $1, %ecx ! setlock: ! xchgl %ecx, (%eax) ! testl %ecx, %ecx ! jz gotit /* it was clear, return */ ! wait: ! cmpl $0, (%eax) /* wait to empty */ ! jne wait /* still set... */ ! jmp setlock /* empty again, try once more */ ! gotit: ! ret ! ! #else /* SL_DEBUG */ ENTRY(s_lock) movl 4(%esp), %edx /* get the address of the lock */ --- 71,77 ---- * the local cache (and thus causing external bus writes) with repeated * writes to the lock. */ ! #ifdef SL_DEBUG ENTRY(s_lock) movl 4(%esp), %edx /* get the address of the lock */ *************** *** 143,164 **** * return (!test_and_set(&lkp->lock_data)); * } */ ! #ifndef SL_DEBUG ENTRY(s_lock_try) - movl 4(%esp), %eax /* get the address of the lock */ - movl $1, %ecx - - xchgl %ecx, (%eax) - testl %ecx, %ecx - setz %al /* 1 if previous value was 0 */ - movzbl %al, %eax /* convert to an int */ - - ret - - #else /* SL_DEBUG */ - - ENTRY(s_lock_try) movl 4(%esp), %edx /* get the address of the lock */ movl _cpu_lockid, %ecx /* add cpu id portion */ incl %ecx /* add lock portion */ --- 114,122 ---- * return (!test_and_set(&lkp->lock_data)); * } */ ! #ifdef SL_DEBUG ENTRY(s_lock_try) movl 4(%esp), %edx /* get the address of the lock */ movl _cpu_lockid, %ecx /* add cpu id portion */ incl %ecx /* add lock portion */ *************** *** 172,191 **** ret #endif /* SL_DEBUG */ - - - /* - * void - * s_unlock(struct simplelock *lkp) - * { - * lkp->lock_data = 0; - * } - */ - ENTRY(s_unlock) - movl 4(%esp), %eax /* get the address of the lock */ - movl $0, (%eax) - ret - /* * These versions of simple_lock block interrupts, --- 130,135 ---- Index: i386/include/lock.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/lock.h,v retrieving revision 1.11 diff -c -r1.11 lock.h *** lock.h 1999/11/19 22:47:19 1.11 --- lock.h 1999/12/12 10:34:22 *************** *** 211,220 **** volatile int lock_data; }; ! /* functions in simplelock.s */ ! void s_lock_init __P((struct simplelock *)); void s_lock __P((struct simplelock *)); int s_lock_try __P((struct simplelock *)); void ss_lock __P((struct simplelock *)); void ss_unlock __P((struct simplelock *)); void s_lock_np __P((struct simplelock *)); --- 211,229 ---- volatile int lock_data; }; ! /* functions used by both UP and SMP */ ! static __inline void s_lock_init __P((struct simplelock *)); ! static __inline void s_unlock __P((struct simplelock *)); ! ! #ifndef SL_DEBUG ! static __inline void s_lock __P((struct simplelock *)); ! static __inline int s_lock_try __P((struct simplelock *)); ! #else void s_lock __P((struct simplelock *)); int s_lock_try __P((struct simplelock *)); + #endif /* SL_DEBUG */ + + /* functions in simplelock.s */ void ss_lock __P((struct simplelock *)); void ss_unlock __P((struct simplelock *)); void s_lock_np __P((struct simplelock *)); *************** *** 222,232 **** --- 231,305 ---- /* inline simplelock functions */ static __inline void + s_lock_init(struct simplelock *lkp) + { + lkp->lock_data = 0; + } + + static __inline void s_unlock(struct simplelock *lkp) { lkp->lock_data = 0; } + #ifndef SL_DEBUG + + /* + * void + * s_lock(struct simplelock *lkp) + * { + * while (test_and_set(&lkp->lock_data)) + * continue; + * } + */ + static __inline void + s_lock(struct simplelock *lkp) + { + + __asm __volatile( + " movl $1, %%eax \n" + "1: \n" + " xchgl %%eax, %0 \n" + " testl %%eax, %%eax \n" + " jz 3f \n" + "2: \n" + " cmpl $0, %0 \n" + " jne 2b \n" + " jmp 1b \n" + "3: \n" + : "=m" (lkp->lock_data) + : "0" (lkp->lock_data) + : "eax"); + } + + /* + * int + * s_lock_try(struct simplelock *lkp) + * { + * return (!test_and_set(&lkp->lock_data)); + * } + */ + static __inline int + s_lock_try(struct simplelock *lkp) + { + int r; + + __asm __volatile( + " movl $1, %1 \n" + " xorl %%ecx, %%ecx \n" + " xchgl %1, %0 \n" + " testl %1, %1 \n" + " setz %%cl \n" + " movzbl %%cl, %1 \n" + : "=m" (lkp->lock_data), "=r" (r) + : "0" (lkp->lock_data) + : "ecx"); + + return (r); + } + + #endif /* SL_DEBUG */ + /* global data in mp_machdep.c */ extern struct simplelock imen_lock; extern struct simplelock cpl_lock; *************** *** 239,245 **** #if !defined(SIMPLELOCK_DEBUG) && NCPUS > 1 /* ! * This set of defines turns on the real functions in i386/isa/apic_ipl.s. */ #define simple_lock_init(alp) s_lock_init(alp) #define simple_lock(alp) s_lock(alp) --- 312,318 ---- #if !defined(SIMPLELOCK_DEBUG) && NCPUS > 1 /* ! * This set of defines turns on the real functions in i386/i386/simplelock.s. */ #define simple_lock_init(alp) s_lock_init(alp) #define simple_lock(alp) s_lock(alp) >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19991212191039.F2AB01FCD>