1 1.19 mrg /* $NetBSD: mutex.h,v 1.19 2023/07/13 07:46:43 mrg Exp $ */ 2 1.2 ad 3 1.2 ad /*- 4 1.2 ad * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc. 5 1.2 ad * All rights reserved. 6 1.2 ad * 7 1.2 ad * This code is derived from software contributed to The NetBSD Foundation 8 1.2 ad * by Jason R. Thorpe and Andrew Doran. 9 1.2 ad * 10 1.2 ad * Redistribution and use in source and binary forms, with or without 11 1.2 ad * modification, are permitted provided that the following conditions 12 1.2 ad * are met: 13 1.2 ad * 1. Redistributions of source code must retain the above copyright 14 1.2 ad * notice, this list of conditions and the following disclaimer. 15 1.2 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 ad * notice, this list of conditions and the following disclaimer in the 17 1.2 ad * documentation and/or other materials provided with the distribution. 18 1.2 ad * 19 1.2 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 ad * POSSIBILITY OF SUCH DAMAGE. 30 1.2 ad */ 31 1.2 ad 32 1.2 ad #ifndef _HPPA_MUTEX_H_ 33 1.2 ad #define _HPPA_MUTEX_H_ 34 1.2 ad 35 1.2 ad /* 36 1.2 ad * The HPPA mutex implementation is troublesome, because HPPA lacks 37 1.2 ad * a compare-and-set operation, yet there are many SMP HPPA machines 38 1.2 ad * in circulation. SMP for spin mutexes is easy - we don't need to 39 1.2 ad * know who owns the lock. For adaptive mutexes, we need an owner 40 1.2 ad * field and additional interlock 41 1.2 ad */ 42 1.5 skrll 43 1.2 ad #ifndef __ASSEMBLER__ 44 1.5 skrll 45 1.18 riastrad #include <sys/types.h> 46 1.18 riastrad 47 1.16 riastrad #ifdef __MUTEX_PRIVATE 48 1.19 mrg #include <machine/lock.h> 49 1.16 riastrad #include <machine/intr.h> 50 1.16 riastrad #endif 51 1.5 skrll 52 1.2 ad struct kmutex { 53 1.2 ad union { 54 1.2 ad /* 55 1.6 skrll * Only the 16 bytes aligned word of __cpu_simple_lock_t will 56 1.6 skrll * be used. It's 16 bytes to simplify the allocation. 57 1.6 skrll * See hppa/lock.h 58 1.2 ad */ 59 1.2 ad #ifdef __MUTEX_PRIVATE 60 1.2 ad struct { 61 1.6 skrll __cpu_simple_lock_t mtxu_lock; /* 0-15 */ 62 1.6 skrll volatile uint32_t mtxs_owner; /* 16-19 */ 63 1.6 skrll ipl_cookie_t mtxs_ipl; /* 20-23 */ 64 1.6 skrll volatile uint8_t mtxs_waiters; /* 24 */ 65 1.2 ad 66 1.2 ad /* For LOCKDEBUG */ 67 1.8 yamt uint8_t mtxs_dodebug; /* 25 */ 68 1.2 ad } s; 69 1.2 ad #endif 70 1.6 skrll uint8_t mtxu_pad[32]; /* 0 - 32 */ 71 1.2 ad } u; 72 1.2 ad } __aligned (16); 73 1.2 ad #endif 74 1.2 ad 75 1.2 ad #ifdef __MUTEX_PRIVATE 76 1.2 ad 77 1.2 ad #define __HAVE_MUTEX_STUBS 1 78 1.2 ad 79 1.6 skrll #define mtx_lock u.s.mtxu_lock 80 1.2 ad #define mtx_owner u.s.mtxs_owner 81 1.2 ad #define mtx_ipl u.s.mtxs_ipl 82 1.2 ad #define mtx_waiters u.s.mtxs_waiters 83 1.8 yamt #define mtx_dodebug u.s.mtxs_dodebug 84 1.2 ad 85 1.2 ad /* Magic constants for mtx_owner */ 86 1.2 ad #define MUTEX_ADAPTIVE_UNOWNED 0xffffff00 87 1.2 ad #define MUTEX_SPIN_FLAG 0xffffff10 88 1.2 ad #define MUTEX_UNOWNED_OR_SPIN(x) (((x) & 0xffffffef) == 0xffffff00) 89 1.2 ad 90 1.17 mrg #if !defined(__ASSEMBLER__) && defined(_KERNEL) 91 1.2 ad 92 1.2 ad static inline uintptr_t 93 1.2 ad MUTEX_OWNER(uintptr_t owner) 94 1.2 ad { 95 1.2 ad return owner; 96 1.2 ad } 97 1.2 ad 98 1.2 ad static inline int 99 1.2 ad MUTEX_OWNED(uintptr_t owner) 100 1.2 ad { 101 1.2 ad return owner != MUTEX_ADAPTIVE_UNOWNED; 102 1.2 ad } 103 1.2 ad 104 1.2 ad static inline int 105 1.10 uebayasi MUTEX_SET_WAITERS(struct kmutex *mtx, uintptr_t owner) 106 1.2 ad { 107 1.14 riastrad __sync(); /* formerly mb_read */ 108 1.2 ad mtx->mtx_waiters = 1; 109 1.14 riastrad __sync(); /* formerly mb_memory */ 110 1.2 ad return mtx->mtx_owner != MUTEX_ADAPTIVE_UNOWNED; 111 1.2 ad } 112 1.2 ad 113 1.2 ad static inline int 114 1.12 christos MUTEX_HAS_WAITERS(const volatile struct kmutex *mtx) 115 1.2 ad { 116 1.2 ad return mtx->mtx_waiters != 0; 117 1.2 ad } 118 1.2 ad 119 1.2 ad static inline void 120 1.10 uebayasi MUTEX_INITIALIZE_SPIN(struct kmutex *mtx, bool dodebug, int ipl) 121 1.2 ad { 122 1.2 ad mtx->mtx_ipl = makeiplcookie(ipl); 123 1.8 yamt mtx->mtx_dodebug = dodebug; 124 1.2 ad mtx->mtx_owner = MUTEX_SPIN_FLAG; 125 1.2 ad __cpu_simple_lock_init(&mtx->mtx_lock); 126 1.2 ad } 127 1.2 ad 128 1.2 ad static inline void 129 1.10 uebayasi MUTEX_INITIALIZE_ADAPTIVE(struct kmutex *mtx, bool dodebug) 130 1.2 ad { 131 1.8 yamt mtx->mtx_dodebug = dodebug; 132 1.2 ad mtx->mtx_owner = MUTEX_ADAPTIVE_UNOWNED; 133 1.2 ad __cpu_simple_lock_init(&mtx->mtx_lock); 134 1.2 ad } 135 1.2 ad 136 1.2 ad static inline void 137 1.10 uebayasi MUTEX_DESTROY(struct kmutex *mtx) 138 1.2 ad { 139 1.3 skrll mtx->mtx_owner = 0xffffffff; 140 1.2 ad } 141 1.2 ad 142 1.8 yamt static inline bool 143 1.12 christos MUTEX_DEBUG_P(const volatile struct kmutex *mtx) 144 1.2 ad { 145 1.8 yamt return mtx->mtx_dodebug != 0; 146 1.2 ad } 147 1.2 ad 148 1.2 ad static inline int 149 1.15 ad MUTEX_SPIN_P(const uintptr_t owner) 150 1.2 ad { 151 1.15 ad return owner == MUTEX_SPIN_FLAG; 152 1.2 ad } 153 1.2 ad 154 1.2 ad static inline int 155 1.15 ad MUTEX_ADAPTIVE_P(const uintptr_t owner) 156 1.2 ad { 157 1.15 ad return owner != MUTEX_SPIN_FLAG; 158 1.2 ad } 159 1.2 ad 160 1.2 ad /* Acquire an adaptive mutex */ 161 1.2 ad static inline int 162 1.10 uebayasi MUTEX_ACQUIRE(struct kmutex *mtx, uintptr_t curthread) 163 1.2 ad { 164 1.2 ad if (!__cpu_simple_lock_try(&mtx->mtx_lock)) 165 1.2 ad return 0; 166 1.2 ad mtx->mtx_owner = curthread; 167 1.2 ad return 1; 168 1.2 ad } 169 1.2 ad 170 1.2 ad /* Release an adaptive mutex */ 171 1.2 ad static inline void 172 1.10 uebayasi MUTEX_RELEASE(struct kmutex *mtx) 173 1.2 ad { 174 1.2 ad mtx->mtx_owner = MUTEX_ADAPTIVE_UNOWNED; 175 1.2 ad __cpu_simple_unlock(&mtx->mtx_lock); 176 1.2 ad mtx->mtx_waiters = 0; 177 1.2 ad } 178 1.2 ad 179 1.4 ad static inline void 180 1.10 uebayasi MUTEX_CLEAR_WAITERS(struct kmutex *mtx) 181 1.4 ad { 182 1.4 ad mtx->mtx_waiters = 0; 183 1.4 ad } 184 1.4 ad 185 1.17 mrg #endif /* !__ASSEMBLER__ && _KERNEL */ 186 1.2 ad 187 1.2 ad #endif /* __MUTEX_PRIVATE */ 188 1.2 ad 189 1.2 ad #endif /* _HPPA_MUTEX_H_ */ 190