lock.h revision 1.18
11.18Smatt/*	$NetBSD: lock.h,v 1.18 2011/02/20 07:45:47 matt Exp $	*/
21.1Sthorpej
31.1Sthorpej/*-
41.10Sad * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
51.1Sthorpej * All rights reserved.
61.1Sthorpej *
71.1Sthorpej * This code is derived from software contributed to The NetBSD Foundation
81.10Sad * by Wayne Knowles and Andrew Doran.
91.1Sthorpej *
101.1Sthorpej * Redistribution and use in source and binary forms, with or without
111.1Sthorpej * modification, are permitted provided that the following conditions
121.1Sthorpej * are met:
131.1Sthorpej * 1. Redistributions of source code must retain the above copyright
141.1Sthorpej *    notice, this list of conditions and the following disclaimer.
151.1Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
161.1Sthorpej *    notice, this list of conditions and the following disclaimer in the
171.1Sthorpej *    documentation and/or other materials provided with the distribution.
181.1Sthorpej *
191.1Sthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201.1Sthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211.1Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221.1Sthorpej * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231.1Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241.1Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251.1Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261.1Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271.1Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281.1Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291.1Sthorpej * POSSIBILITY OF SUCH DAMAGE.
301.1Sthorpej */
311.1Sthorpej
321.1Sthorpej/*
331.10Sad * Machine-dependent spin lock operations for MIPS processors.
341.3Sgmcgarry *
351.10Sad * Note: R2000/R3000 doesn't have any atomic update instructions; this
361.10Sad * will cause problems for user applications using this header.
371.1Sthorpej */
381.1Sthorpej
391.1Sthorpej#ifndef _MIPS_LOCK_H_
401.1Sthorpej#define	_MIPS_LOCK_H_
411.3Sgmcgarry
421.17Spooka#include <sys/param.h>
431.17Spooka
441.13Sskrllstatic __inline int
451.13Sskrll__SIMPLELOCK_LOCKED_P(__cpu_simple_lock_t *__ptr)
461.13Sskrll{
471.18Smatt	return *__ptr != __SIMPLELOCK_UNLOCKED;
481.13Sskrll}
491.13Sskrll
501.13Sskrllstatic __inline int
511.13Sskrll__SIMPLELOCK_UNLOCKED_P(__cpu_simple_lock_t *__ptr)
521.13Sskrll{
531.13Sskrll	return *__ptr == __SIMPLELOCK_UNLOCKED;
541.13Sskrll}
551.13Sskrll
561.13Sskrllstatic __inline void
571.13Sskrll__cpu_simple_lock_clear(__cpu_simple_lock_t *__ptr)
581.13Sskrll{
591.13Sskrll	*__ptr = __SIMPLELOCK_UNLOCKED;
601.13Sskrll}
611.13Sskrll
621.13Sskrllstatic __inline void
631.13Sskrll__cpu_simple_lock_set(__cpu_simple_lock_t *__ptr)
641.13Sskrll{
651.13Sskrll	*__ptr = __SIMPLELOCK_LOCKED;
661.13Sskrll}
671.13Sskrll
681.17Spooka#ifndef _HARDKERNEL
691.3Sgmcgarry
701.8Sperrystatic __inline int
711.3Sgmcgarry__cpu_simple_lock_try(__cpu_simple_lock_t *lp)
721.3Sgmcgarry{
731.3Sgmcgarry	unsigned long t0, v0;
741.3Sgmcgarry
751.7Sperry	__asm volatile(
761.3Sgmcgarry		"# -- BEGIN __cpu_simple_lock_try\n"
771.3Sgmcgarry		"	.set push		\n"
781.3Sgmcgarry		"	.set mips2		\n"
791.3Sgmcgarry		"1:	ll	%0, %4		\n"
801.3Sgmcgarry		"	bnez	%0, 2f		\n"
811.3Sgmcgarry		"	nop	       # BDslot	\n"
821.3Sgmcgarry		"	li	%0, %3		\n"
831.3Sgmcgarry		"	sc	%0, %2		\n"
841.3Sgmcgarry		"	beqz	%0, 2f		\n"
851.3Sgmcgarry		"	nop	       # BDslot	\n"
861.3Sgmcgarry		"	li	%1, 1		\n"
871.3Sgmcgarry		"	sync			\n"
881.3Sgmcgarry		"	j	3f		\n"
891.3Sgmcgarry		"	nop			\n"
901.3Sgmcgarry		"	nop			\n"
911.3Sgmcgarry		"2:	li	%1, 0		\n"
921.3Sgmcgarry		"3:				\n"
931.3Sgmcgarry		"	.set pop		\n"
941.3Sgmcgarry		"# -- END __cpu_simple_lock_try	\n"
951.3Sgmcgarry		: "=r" (t0), "=r" (v0), "+m" (*lp)
961.9Ssimonb		: "i" (__SIMPLELOCK_LOCKED), "m" (*lp));
971.3Sgmcgarry
981.3Sgmcgarry	return (v0 != 0);
991.3Sgmcgarry}
1001.3Sgmcgarry
1011.10Sad#ifdef MIPS1
1021.10Sadstatic __inline void
1031.10Sadmb_read(void)
1041.10Sad{
1051.10Sad	__insn_barrier();
1061.10Sad}
1071.10Sad
1081.10Sadstatic __inline void
1091.10Sadmb_write(void)
1101.10Sad{
1111.10Sad	__insn_barrier();
1121.10Sad}
1131.10Sad
1141.10Sadstatic __inline void
1151.10Sadmb_memory(void)
1161.10Sad{
1171.10Sad	__insn_barrier();
1181.10Sad}
1191.10Sad#else	/* MIPS1*/
1201.10Sadstatic __inline void
1211.10Sadmb_read(void)
1221.10Sad{
1231.12Sad	__asm volatile(
1241.12Sad	    "	.set push\n"
1251.12Sad	    "	.set mips2\n"
1261.12Sad	    "	sync\n"
1271.12Sad	    "	.set pop"
1281.12Sad	    ::: "memory"
1291.12Sad	);
1301.10Sad}
1311.10Sad
1321.10Sadstatic __inline void
1331.10Sadmb_write(void)
1341.10Sad{
1351.12Sad	mb_read();
1361.10Sad}
1371.10Sad
1381.10Sadstatic __inline void
1391.10Sadmb_memory(void)
1401.10Sad{
1411.12Sad	mb_read();
1421.10Sad}
1431.10Sad#endif	/* MIPS1 */
1441.10Sad
1451.17Spooka#else	/* !_HARDKERNEL */
1461.10Sad
1471.18Smattu_int	_atomic_cas_uint(volatile u_int *, u_int, u_int);
1481.18Smattu_long	_atomic_cas_ulong(volatile u_long *, u_long, u_long);
1491.18Smattvoid *	_atomic_cas_ptr(volatile void *, void *, void *);
1501.10Sadvoid	mb_read(void);
1511.10Sadvoid	mb_write(void);
1521.10Sadvoid	mb_memory(void);
1531.10Sad
1541.10Sadstatic __inline int
1551.10Sad__cpu_simple_lock_try(__cpu_simple_lock_t *lp)
1561.10Sad{
1571.10Sad
1581.18Smatt	return _atomic_cas_uint(lp,
1591.15Sad	    __SIMPLELOCK_UNLOCKED, __SIMPLELOCK_LOCKED) ==
1601.15Sad	    __SIMPLELOCK_UNLOCKED;
1611.10Sad}
1621.10Sad
1631.17Spooka#endif	/* _HARDKERNEL */
1641.10Sad
1651.10Sadstatic __inline void
1661.10Sad__cpu_simple_lock_init(__cpu_simple_lock_t *lp)
1671.10Sad{
1681.10Sad
1691.10Sad	*lp = __SIMPLELOCK_UNLOCKED;
1701.10Sad	mb_memory();
1711.10Sad}
1721.10Sad
1731.10Sadstatic __inline void
1741.10Sad__cpu_simple_lock(__cpu_simple_lock_t *lp)
1751.10Sad{
1761.10Sad
1771.18Smatt	while (!__cpu_simple_lock_try(lp)) {
1781.10Sad		while (*lp == __SIMPLELOCK_LOCKED)
1791.10Sad			/* spin */;
1801.18Smatt	}
1811.10Sad}
1821.10Sad
1831.8Sperrystatic __inline void
1841.3Sgmcgarry__cpu_simple_unlock(__cpu_simple_lock_t *lp)
1851.3Sgmcgarry{
1861.3Sgmcgarry
1871.10Sad	mb_memory();
1881.10Sad	*lp = __SIMPLELOCK_UNLOCKED;
1891.3Sgmcgarry}
1901.10Sad
1911.1Sthorpej#endif /* _MIPS_LOCK_H_ */
192