subr_witness.c (69369) | subr_witness.c (69376) |
---|---|
1/*- 2 * Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 13 unchanged lines hidden (view full) --- 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * from BSDI $Id: mutex_witness.c,v 1.1.2.20 2000/04/27 03:10:27 cp Exp $ 29 * and BSDI $Id: synch_machdep.c,v 2.3.2.39 2000/04/27 03:10:25 cp Exp $ | 1/*- 2 * Copyright (c) 1998 Berkeley Software Design, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 13 unchanged lines hidden (view full) --- 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * from BSDI $Id: mutex_witness.c,v 1.1.2.20 2000/04/27 03:10:27 cp Exp $ 29 * and BSDI $Id: synch_machdep.c,v 2.3.2.39 2000/04/27 03:10:25 cp Exp $ |
30 * $FreeBSD: head/sys/kern/subr_witness.c 69369 2000-11-29 20:17:15Z jhb $ | 30 * $FreeBSD: head/sys/kern/subr_witness.c 69376 2000-11-30 00:51:16Z jhb $ |
31 */ 32 33/* 34 * Main Entry: witness 35 * Pronunciation: 'wit-n&s 36 * Function: noun 37 * Etymology: Middle English witnesse, from Old English witnes knowledge, 38 * testimony, witness, from 2wit --- 58 unchanged lines hidden (view full) --- 97 { NULL, NULL }, &all_mtx, &all_mtx }; 98#endif /* MUTEX_DEBUG */ 99 100static int mtx_cur_cnt; 101static int mtx_max_cnt; 102 103void _mtx_enter_giant_def(void); 104void _mtx_exit_giant_def(void); | 31 */ 32 33/* 34 * Main Entry: witness 35 * Pronunciation: 'wit-n&s 36 * Function: noun 37 * Etymology: Middle English witnesse, from Old English witnes knowledge, 38 * testimony, witness, from 2wit --- 58 unchanged lines hidden (view full) --- 97 { NULL, NULL }, &all_mtx, &all_mtx }; 98#endif /* MUTEX_DEBUG */ 99 100static int mtx_cur_cnt; 101static int mtx_max_cnt; 102 103void _mtx_enter_giant_def(void); 104void _mtx_exit_giant_def(void); |
105static void propagate_priority(struct proc *) __unused; | 105static void propagate_priority(struct proc *); |
106 107#define mtx_unowned(m) ((m)->mtx_lock == MTX_UNOWNED) 108#define mtx_owner(m) (mtx_unowned(m) ? NULL \ 109 : (struct proc *)((m)->mtx_lock & MTX_FLAGMASK)) 110 111#define RETIP(x) *(((uintptr_t *)(&x)) - 1) 112#define SET_PRIO(p, pri) (p)->p_priority = (pri) 113 --- 16 unchanged lines hidden (view full) --- 130} 131 132static void 133propagate_priority(struct proc *p) 134{ 135 int pri = p->p_priority; 136 struct mtx *m = p->p_blocked; 137 | 106 107#define mtx_unowned(m) ((m)->mtx_lock == MTX_UNOWNED) 108#define mtx_owner(m) (mtx_unowned(m) ? NULL \ 109 : (struct proc *)((m)->mtx_lock & MTX_FLAGMASK)) 110 111#define RETIP(x) *(((uintptr_t *)(&x)) - 1) 112#define SET_PRIO(p, pri) (p)->p_priority = (pri) 113 --- 16 unchanged lines hidden (view full) --- 130} 131 132static void 133propagate_priority(struct proc *p) 134{ 135 int pri = p->p_priority; 136 struct mtx *m = p->p_blocked; 137 |
138 mtx_assert(&sched_lock, MA_OWNED); |
|
138 for (;;) { 139 struct proc *p1; 140 141 p = mtx_owner(m); 142 143 if (p == NULL) { 144 /* 145 * This really isn't quite right. Really 146 * ought to bump priority of process that 147 * next acquires the mutex. 148 */ 149 MPASS(m->mtx_lock == MTX_CONTESTED); 150 return; 151 } 152 MPASS(p->p_magic == P_MAGIC); | 139 for (;;) { 140 struct proc *p1; 141 142 p = mtx_owner(m); 143 144 if (p == NULL) { 145 /* 146 * This really isn't quite right. Really 147 * ought to bump priority of process that 148 * next acquires the mutex. 149 */ 150 MPASS(m->mtx_lock == MTX_CONTESTED); 151 return; 152 } 153 MPASS(p->p_magic == P_MAGIC); |
154 KASSERT(p->p_stat != SSLEEP, ("sleeping process owns a mutex")); |
|
153 if (p->p_priority <= pri) 154 return; | 155 if (p->p_priority <= pri) 156 return; |
157 |
|
155 /* | 158 /* |
159 * Bump this process' priority. 160 */ 161 SET_PRIO(p, pri); 162 163 /* |
|
156 * If lock holder is actually running, just bump priority. 157 */ | 164 * If lock holder is actually running, just bump priority. 165 */ |
158 if (TAILQ_NEXT(p, p_procq) == NULL) { | 166#ifdef SMP 167 /* 168 * For SMP, we can check the p_oncpu field to see if we are 169 * running. 170 */ 171 if (p->p_oncpu != 0xff) { |
159 MPASS(p->p_stat == SRUN || p->p_stat == SZOMB); | 172 MPASS(p->p_stat == SRUN || p->p_stat == SZOMB); |
160 SET_PRIO(p, pri); | |
161 return; 162 } | 173 return; 174 } |
175#else |
|
163 /* | 176 /* |
177 * For UP, we check to see if p is curproc (this shouldn't 178 * ever happen however as it would mean we are in a deadlock.) 179 */ 180 if (p == curproc) { 181 panic("Deadlock detected"); 182 return; 183 } 184#endif 185 /* |
|
164 * If on run queue move to new run queue, and 165 * quit. 166 */ 167 if (p->p_stat == SRUN) { | 186 * If on run queue move to new run queue, and 187 * quit. 188 */ 189 if (p->p_stat == SRUN) { |
190 printf("XXX: moving process %d(%s) to a new run queue\n", 191 p->p_pid, p->p_comm); |
|
168 MPASS(p->p_blocked == NULL); 169 remrunqueue(p); | 192 MPASS(p->p_blocked == NULL); 193 remrunqueue(p); |
170 SET_PRIO(p, pri); | |
171 setrunqueue(p); 172 return; 173 } 174 175 /* | 194 setrunqueue(p); 195 return; 196 } 197 198 /* |
176 * If we aren't blocked on a mutex, give up and quit. | 199 * If we aren't blocked on a mutex, we should be. |
177 */ | 200 */ |
178 if (p->p_stat != SMTX) { 179 printf( 180 "XXX: process %d(%s):%d holds %s but isn't blocked on a mutex\n", 181 p->p_pid, p->p_comm, p->p_stat, m->mtx_description); 182 return; 183 } | 201 KASSERT(p->p_stat == SMTX, ( 202 "process %d(%s):%d holds %s but isn't blocked on a mutex\n", 203 p->p_pid, p->p_comm, p->p_stat, 204 m->mtx_description)); |
184 185 /* 186 * Pick up the mutex that p is blocked on. 187 */ 188 m = p->p_blocked; 189 MPASS(m != NULL); 190 191 printf("XXX: process %d(%s) is blocked on %s\n", p->p_pid, 192 p->p_comm, m->mtx_description); 193 /* 194 * Check if the proc needs to be moved up on 195 * the blocked chain 196 */ | 205 206 /* 207 * Pick up the mutex that p is blocked on. 208 */ 209 m = p->p_blocked; 210 MPASS(m != NULL); 211 212 printf("XXX: process %d(%s) is blocked on %s\n", p->p_pid, 213 p->p_comm, m->mtx_description); 214 /* 215 * Check if the proc needs to be moved up on 216 * the blocked chain 217 */ |
197 if ((p1 = TAILQ_PREV(p, rq, p_procq)) == NULL || 198 p1->p_priority <= pri) { 199 if (p1) 200 printf( | 218 if (p == TAILQ_FIRST(&m->mtx_blocked)) { 219 printf("XXX: process at head of run queue\n"); 220 continue; 221 } 222 p1 = TAILQ_PREV(p, rq, p_procq); 223 if (p1->p_priority <= pri) { 224 printf( |
201 "XXX: previous process %d(%s) has higher priority\n", | 225 "XXX: previous process %d(%s) has higher priority\n", |
202 p->p_pid, p->p_comm); 203 else 204 printf("XXX: process at head of run queue\n"); | 226 p->p_pid, p->p_comm); |
205 continue; 206 } 207 208 /* | 227 continue; 228 } 229 230 /* |
209 * Remove proc from blocked chain | 231 * Remove proc from blocked chain and determine where 232 * it should be moved up to. Since we know that p1 has 233 * a lower priority than p, we know that at least one 234 * process in the chain has a lower priority and that 235 * p1 will thus not be NULL after the loop. |
210 */ 211 TAILQ_REMOVE(&m->mtx_blocked, p, p_procq); 212 TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq) { 213 MPASS(p1->p_magic == P_MAGIC); 214 if (p1->p_priority > pri) 215 break; 216 } | 236 */ 237 TAILQ_REMOVE(&m->mtx_blocked, p, p_procq); 238 TAILQ_FOREACH(p1, &m->mtx_blocked, p_procq) { 239 MPASS(p1->p_magic == P_MAGIC); 240 if (p1->p_priority > pri) 241 break; 242 } |
217 if (p1) 218 TAILQ_INSERT_BEFORE(p1, p, p_procq); 219 else 220 TAILQ_INSERT_TAIL(&m->mtx_blocked, p, p_procq); | 243 MPASS(p1 != NULL); 244 TAILQ_INSERT_BEFORE(p1, p, p_procq); |
221 CTR4(KTR_LOCK, | 245 CTR4(KTR_LOCK, |
222 "propagate priority: p 0x%p moved before 0x%p on [0x%p] %s", | 246 "propagate_priority: p 0x%p moved before 0x%p on [0x%p] %s", |
223 p, p1, m, m->mtx_description); 224 } 225} 226 227void 228mtx_enter_hard(struct mtx *m, int type, int saveintr) 229{ 230 struct proc *p = CURPROC; --- 5 unchanged lines hidden (view full) --- 236 if ((m->mtx_lock & MTX_FLAGMASK) == (uintptr_t)p) { 237 m->mtx_recurse++; 238 atomic_set_ptr(&m->mtx_lock, MTX_RECURSE); 239 CTR1(KTR_LOCK, "mtx_enter: 0x%p recurse", m); 240 return; 241 } 242 CTR3(KTR_LOCK, "mtx_enter: 0x%p contested (lock=%p) [0x%p]", 243 m, (void *)m->mtx_lock, (void *)RETIP(m)); | 247 p, p1, m, m->mtx_description); 248 } 249} 250 251void 252mtx_enter_hard(struct mtx *m, int type, int saveintr) 253{ 254 struct proc *p = CURPROC; --- 5 unchanged lines hidden (view full) --- 260 if ((m->mtx_lock & MTX_FLAGMASK) == (uintptr_t)p) { 261 m->mtx_recurse++; 262 atomic_set_ptr(&m->mtx_lock, MTX_RECURSE); 263 CTR1(KTR_LOCK, "mtx_enter: 0x%p recurse", m); 264 return; 265 } 266 CTR3(KTR_LOCK, "mtx_enter: 0x%p contested (lock=%p) [0x%p]", 267 m, (void *)m->mtx_lock, (void *)RETIP(m)); |
268 269 /* 270 * Save our priority. Even though p_nativepri is protected 271 * by sched_lock, we don't obtain it here as it can be 272 * expensive. Since this is the only place p_nativepri is 273 * set, and since two CPUs will not be executing the same 274 * process concurrently, we know that no other CPU is going 275 * to be messing with this. Also, p_nativepri is only read 276 * when we are blocked on a mutex, so that can't be happening 277 * right now either. 278 */ 279 p->p_nativepri = p->p_priority; |
|
244 while (!_obtain_lock(m, p)) { 245 uintptr_t v; 246 struct proc *p1; 247 248 mtx_enter(&sched_lock, MTX_SPIN | MTX_RLIKELY); 249 /* 250 * check if the lock has been released while 251 * waiting for the schedlock. --- 1093 unchanged lines hidden --- | 280 while (!_obtain_lock(m, p)) { 281 uintptr_t v; 282 struct proc *p1; 283 284 mtx_enter(&sched_lock, MTX_SPIN | MTX_RLIKELY); 285 /* 286 * check if the lock has been released while 287 * waiting for the schedlock. --- 1093 unchanged lines hidden --- |