11.23Sriastrad/* $NetBSD: lock.h,v 1.23 2022/04/09 23:43:20 riastradh 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.22Sriastrad#include <sys/atomic.h> 451.22Sriastrad 461.13Sskrllstatic __inline int 471.20Schristos__SIMPLELOCK_LOCKED_P(const __cpu_simple_lock_t *__ptr) 481.13Sskrll{ 491.18Smatt return *__ptr != __SIMPLELOCK_UNLOCKED; 501.13Sskrll} 511.13Sskrll 521.13Sskrllstatic __inline int 531.20Schristos__SIMPLELOCK_UNLOCKED_P(const __cpu_simple_lock_t *__ptr) 541.13Sskrll{ 551.13Sskrll return *__ptr == __SIMPLELOCK_UNLOCKED; 561.13Sskrll} 571.13Sskrll 581.13Sskrllstatic __inline void 591.13Sskrll__cpu_simple_lock_clear(__cpu_simple_lock_t *__ptr) 601.13Sskrll{ 611.13Sskrll *__ptr = __SIMPLELOCK_UNLOCKED; 621.13Sskrll} 631.13Sskrll 641.13Sskrllstatic __inline void 651.13Sskrll__cpu_simple_lock_set(__cpu_simple_lock_t *__ptr) 661.13Sskrll{ 671.13Sskrll *__ptr = __SIMPLELOCK_LOCKED; 681.13Sskrll} 691.13Sskrll 701.17Spooka#ifndef _HARDKERNEL 711.3Sgmcgarry 721.8Sperrystatic __inline int 731.3Sgmcgarry__cpu_simple_lock_try(__cpu_simple_lock_t *lp) 741.3Sgmcgarry{ 751.3Sgmcgarry unsigned long t0, v0; 761.3Sgmcgarry 771.7Sperry __asm volatile( 781.3Sgmcgarry "# -- BEGIN __cpu_simple_lock_try\n" 791.3Sgmcgarry " .set push \n" 801.3Sgmcgarry " .set mips2 \n" 811.3Sgmcgarry "1: ll %0, %4 \n" 821.3Sgmcgarry " bnez %0, 2f \n" 831.21Ssimonb " nop \n" 841.3Sgmcgarry " li %0, %3 \n" 851.3Sgmcgarry " sc %0, %2 \n" 861.3Sgmcgarry " beqz %0, 2f \n" 871.21Ssimonb " nop \n" 881.3Sgmcgarry " li %1, 1 \n" 891.3Sgmcgarry " sync \n" 901.3Sgmcgarry " j 3f \n" 911.21Ssimonb " nop \n" 921.3Sgmcgarry " nop \n" 931.3Sgmcgarry "2: li %1, 0 \n" 941.3Sgmcgarry "3: \n" 951.3Sgmcgarry " .set pop \n" 961.3Sgmcgarry "# -- END __cpu_simple_lock_try \n" 971.3Sgmcgarry : "=r" (t0), "=r" (v0), "+m" (*lp) 981.9Ssimonb : "i" (__SIMPLELOCK_LOCKED), "m" (*lp)); 991.3Sgmcgarry 1001.3Sgmcgarry return (v0 != 0); 1011.3Sgmcgarry} 1021.3Sgmcgarry 1031.17Spooka#else /* !_HARDKERNEL */ 1041.10Sad 1051.18Smattu_int _atomic_cas_uint(volatile u_int *, u_int, u_int); 1061.18Smattu_long _atomic_cas_ulong(volatile u_long *, u_long, u_long); 1071.18Smattvoid * _atomic_cas_ptr(volatile void *, void *, void *); 1081.10Sad 1091.10Sadstatic __inline int 1101.10Sad__cpu_simple_lock_try(__cpu_simple_lock_t *lp) 1111.10Sad{ 1121.10Sad 1131.22Sriastrad /* 1141.22Sriastrad * Successful _atomic_cas_uint functions as a load-acquire -- 1151.22Sriastrad * on MP systems, it issues sync after the LL/SC CAS succeeds; 1161.22Sriastrad * on non-MP systems every load is a load-acquire so it's moot. 1171.23Sriastrad * This pairs with the membar_release and store sequence in 1181.22Sriastrad * __cpu_simple_unlock that functions as a store-release 1191.22Sriastrad * operation. 1201.22Sriastrad * 1211.22Sriastrad * NOTE: This applies only to _atomic_cas_uint (with the 1221.22Sriastrad * underscore), in sys/arch/mips/mips/lock_stubs_*.S. Not true 1231.22Sriastrad * for atomic_cas_uint (without the underscore), from 1241.22Sriastrad * common/lib/libc/arch/mips/atomic/atomic_cas.S which does not 1251.22Sriastrad * imply a load-acquire. It is unclear why these disagree. 1261.22Sriastrad */ 1271.18Smatt return _atomic_cas_uint(lp, 1281.15Sad __SIMPLELOCK_UNLOCKED, __SIMPLELOCK_LOCKED) == 1291.15Sad __SIMPLELOCK_UNLOCKED; 1301.10Sad} 1311.10Sad 1321.17Spooka#endif /* _HARDKERNEL */ 1331.10Sad 1341.10Sadstatic __inline void 1351.10Sad__cpu_simple_lock_init(__cpu_simple_lock_t *lp) 1361.10Sad{ 1371.10Sad 1381.10Sad *lp = __SIMPLELOCK_UNLOCKED; 1391.10Sad} 1401.10Sad 1411.10Sadstatic __inline void 1421.10Sad__cpu_simple_lock(__cpu_simple_lock_t *lp) 1431.10Sad{ 1441.10Sad 1451.18Smatt while (!__cpu_simple_lock_try(lp)) { 1461.10Sad while (*lp == __SIMPLELOCK_LOCKED) 1471.10Sad /* spin */; 1481.18Smatt } 1491.10Sad} 1501.10Sad 1511.8Sperrystatic __inline void 1521.3Sgmcgarry__cpu_simple_unlock(__cpu_simple_lock_t *lp) 1531.3Sgmcgarry{ 1541.3Sgmcgarry 1551.22Sriastrad /* 1561.23Sriastrad * The membar_release and then store functions as a 1571.23Sriastrad * store-release operation that pairs with the load-acquire 1581.23Sriastrad * operation in successful __cpu_simple_lock_try. 1591.22Sriastrad * 1601.22Sriastrad * Can't use atomic_store_release here because that's not 1611.22Sriastrad * available in userland at the moment. 1621.22Sriastrad */ 1631.23Sriastrad membar_release(); 1641.10Sad *lp = __SIMPLELOCK_UNLOCKED; 1651.22Sriastrad 1661.19Smatt#ifdef _MIPS_ARCH_OCTEONP 1671.22Sriastrad /* 1681.22Sriastrad * On Cavium's recommendation, we issue an extra SYNCW that is 1691.22Sriastrad * not necessary for correct ordering because apparently stores 1701.22Sriastrad * can get stuck in Octeon store buffers for hundreds of 1711.22Sriastrad * thousands of cycles, according to the following note: 1721.22Sriastrad * 1731.22Sriastrad * Programming Notes: 1741.22Sriastrad * [...] 1751.22Sriastrad * Core A (writer) 1761.22Sriastrad * SW R1, DATA 1771.22Sriastrad * LI R2, 1 1781.22Sriastrad * SYNCW 1791.22Sriastrad * SW R2, FLAG 1801.22Sriastrad * SYNCW 1811.22Sriastrad * [...] 1821.22Sriastrad * 1831.22Sriastrad * The second SYNCW instruction executed by core A is not 1841.22Sriastrad * necessary for correctness, but has very important 1851.22Sriastrad * performance effects on OCTEON. Without it, the store 1861.22Sriastrad * to FLAG may linger in core A's write buffer before it 1871.22Sriastrad * becomes visible to other cores. (If core A is not 1881.22Sriastrad * performing many stores, this may add hundreds of 1891.22Sriastrad * thousands of cycles to the flag release time since the 1901.22Sriastrad * OCTEON core normally retains stores to attempt to merge 1911.22Sriastrad * them before sending the store on the CMB.) 1921.22Sriastrad * Applications should include this second SYNCW 1931.22Sriastrad * instruction after flag or lock releases. 1941.22Sriastrad * 1951.22Sriastrad * Cavium Networks OCTEON Plus CN50XX Hardware Reference 1961.22Sriastrad * Manual, July 2008, Appendix A, p. 943. 1971.22Sriastrad * https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/hactive/CN50XX-HRM-V0.99E.pdf 1981.22Sriastrad * 1991.22Sriastrad * XXX It might be prudent to put this into 2001.22Sriastrad * atomic_store_release itself. 2011.22Sriastrad */ 2021.22Sriastrad __asm volatile("syncw" ::: "memory"); 2031.19Smatt#endif 2041.3Sgmcgarry} 2051.10Sad 2061.1Sthorpej#endif /* _MIPS_LOCK_H_ */ 207