Deleted Added
full compact
kern_sx.c (168333) kern_sx.c (169394)
1/*-
2 * Copyright (c) 2007 Attilio Rao <attilio@freebsd.org>
3 * Copyright (c) 2001 Jason Evans <jasone@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 26 unchanged lines hidden (view full) ---

35 * Priority propagation will not generally raise the priority of lock holders,
36 * so should not be relied upon in combination with sx locks.
37 */
38
39#include "opt_adaptive_sx.h"
40#include "opt_ddb.h"
41
42#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2007 Attilio Rao <attilio@freebsd.org>
3 * Copyright (c) 2001 Jason Evans <jasone@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 26 unchanged lines hidden (view full) ---

35 * Priority propagation will not generally raise the priority of lock holders,
36 * so should not be relied upon in combination with sx locks.
37 */
38
39#include "opt_adaptive_sx.h"
40#include "opt_ddb.h"
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/sys/kern/kern_sx.c 168333 2007-04-04 00:11:22Z kmacy $");
43__FBSDID("$FreeBSD: head/sys/kern/kern_sx.c 169394 2007-05-08 21:51:37Z jhb $");
44
45#include <sys/param.h>
46#include <sys/ktr.h>
47#include <sys/lock.h>
48#include <sys/lock_profile.h>
49#include <sys/mutex.h>
50#include <sys/proc.h>
51#include <sys/sleepqueue.h>

--- 136 unchanged lines hidden (view full) ---

188}
189
190void
191sx_destroy(struct sx *sx)
192{
193
194 KASSERT(sx->sx_lock == SX_LOCK_UNLOCKED, ("sx lock still held"));
195 KASSERT(sx->sx_recurse == 0, ("sx lock still recursed"));
44
45#include <sys/param.h>
46#include <sys/ktr.h>
47#include <sys/lock.h>
48#include <sys/lock_profile.h>
49#include <sys/mutex.h>
50#include <sys/proc.h>
51#include <sys/sleepqueue.h>

--- 136 unchanged lines hidden (view full) ---

188}
189
190void
191sx_destroy(struct sx *sx)
192{
193
194 KASSERT(sx->sx_lock == SX_LOCK_UNLOCKED, ("sx lock still held"));
195 KASSERT(sx->sx_recurse == 0, ("sx lock still recursed"));
196 sx->sx_lock = SX_LOCK_DESTROYED;
196 lock_profile_object_destroy(&sx->lock_object);
197 lock_destroy(&sx->lock_object);
198}
199
200void
201_sx_slock(struct sx *sx, const char *file, int line)
202{
203
204 MPASS(curthread != NULL);
197 lock_profile_object_destroy(&sx->lock_object);
198 lock_destroy(&sx->lock_object);
199}
200
201void
202_sx_slock(struct sx *sx, const char *file, int line)
203{
204
205 MPASS(curthread != NULL);
206 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
207 ("sx_slock() of destroyed sx @ %s:%d", file, line));
205 WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line);
206 __sx_slock(sx, file, line);
207 LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line);
208 WITNESS_LOCK(&sx->lock_object, 0, file, line);
209 curthread->td_locks++;
210}
211
212int
213_sx_try_slock(struct sx *sx, const char *file, int line)
214{
215 uintptr_t x;
216
217 x = sx->sx_lock;
208 WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line);
209 __sx_slock(sx, file, line);
210 LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line);
211 WITNESS_LOCK(&sx->lock_object, 0, file, line);
212 curthread->td_locks++;
213}
214
215int
216_sx_try_slock(struct sx *sx, const char *file, int line)
217{
218 uintptr_t x;
219
220 x = sx->sx_lock;
221 KASSERT(x != SX_LOCK_DESTROYED,
222 ("sx_try_slock() of destroyed sx @ %s:%d", file, line));
218 if ((x & SX_LOCK_SHARED) && atomic_cmpset_acq_ptr(&sx->sx_lock, x,
219 x + SX_ONE_SHARER)) {
220 LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 1, file, line);
221 WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line);
222 curthread->td_locks++;
223 return (1);
224 }
225
226 LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 0, file, line);
227 return (0);
228}
229
230void
231_sx_xlock(struct sx *sx, const char *file, int line)
232{
233
234 MPASS(curthread != NULL);
223 if ((x & SX_LOCK_SHARED) && atomic_cmpset_acq_ptr(&sx->sx_lock, x,
224 x + SX_ONE_SHARER)) {
225 LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 1, file, line);
226 WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line);
227 curthread->td_locks++;
228 return (1);
229 }
230
231 LOCK_LOG_TRY("SLOCK", &sx->lock_object, 0, 0, file, line);
232 return (0);
233}
234
235void
236_sx_xlock(struct sx *sx, const char *file, int line)
237{
238
239 MPASS(curthread != NULL);
240 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
241 ("sx_xlock() of destroyed sx @ %s:%d", file, line));
235 WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
236 line);
237 __sx_xlock(sx, curthread, file, line);
238 LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse, file, line);
239 WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
240 curthread->td_locks++;
241}
242
243int
244_sx_try_xlock(struct sx *sx, const char *file, int line)
245{
246 int rval;
247
248 MPASS(curthread != NULL);
242 WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
243 line);
244 __sx_xlock(sx, curthread, file, line);
245 LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse, file, line);
246 WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
247 curthread->td_locks++;
248}
249
250int
251_sx_try_xlock(struct sx *sx, const char *file, int line)
252{
253 int rval;
254
255 MPASS(curthread != NULL);
256 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
257 ("sx_try_xlock() of destroyed sx @ %s:%d", file, line));
249
250 if (sx_xlocked(sx)) {
251 sx->sx_recurse++;
252 atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
253 rval = 1;
254 } else
255 rval = atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED,
256 (uintptr_t)curthread);

--- 7 unchanged lines hidden (view full) ---

264 return (rval);
265}
266
267void
268_sx_sunlock(struct sx *sx, const char *file, int line)
269{
270
271 MPASS(curthread != NULL);
258
259 if (sx_xlocked(sx)) {
260 sx->sx_recurse++;
261 atomic_set_ptr(&sx->sx_lock, SX_LOCK_RECURSED);
262 rval = 1;
263 } else
264 rval = atomic_cmpset_acq_ptr(&sx->sx_lock, SX_LOCK_UNLOCKED,
265 (uintptr_t)curthread);

--- 7 unchanged lines hidden (view full) ---

273 return (rval);
274}
275
276void
277_sx_sunlock(struct sx *sx, const char *file, int line)
278{
279
280 MPASS(curthread != NULL);
281 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
282 ("sx_sunlock() of destroyed sx @ %s:%d", file, line));
272 _sx_assert(sx, SX_SLOCKED, file, line);
273 curthread->td_locks--;
274 WITNESS_UNLOCK(&sx->lock_object, 0, file, line);
275 LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
276 if (SX_SHARERS(sx->sx_lock) == 0)
277 lock_profile_release_lock(&sx->lock_object);
278 __sx_sunlock(sx, file, line);
279}
280
281void
282_sx_xunlock(struct sx *sx, const char *file, int line)
283{
284
285 MPASS(curthread != NULL);
283 _sx_assert(sx, SX_SLOCKED, file, line);
284 curthread->td_locks--;
285 WITNESS_UNLOCK(&sx->lock_object, 0, file, line);
286 LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
287 if (SX_SHARERS(sx->sx_lock) == 0)
288 lock_profile_release_lock(&sx->lock_object);
289 __sx_sunlock(sx, file, line);
290}
291
292void
293_sx_xunlock(struct sx *sx, const char *file, int line)
294{
295
296 MPASS(curthread != NULL);
297 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
298 ("sx_xunlock() of destroyed sx @ %s:%d", file, line));
286 _sx_assert(sx, SX_XLOCKED, file, line);
287 curthread->td_locks--;
288 WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
289 LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file,
290 line);
291 if (!sx_recursed(sx))
292 lock_profile_release_lock(&sx->lock_object);
293 __sx_xunlock(sx, curthread, file, line);

--- 5 unchanged lines hidden (view full) ---

299 * Return 1 if if the upgrade succeed, 0 otherwise.
300 */
301int
302_sx_try_upgrade(struct sx *sx, const char *file, int line)
303{
304 uintptr_t x;
305 int success;
306
299 _sx_assert(sx, SX_XLOCKED, file, line);
300 curthread->td_locks--;
301 WITNESS_UNLOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
302 LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file,
303 line);
304 if (!sx_recursed(sx))
305 lock_profile_release_lock(&sx->lock_object);
306 __sx_xunlock(sx, curthread, file, line);

--- 5 unchanged lines hidden (view full) ---

312 * Return 1 if if the upgrade succeed, 0 otherwise.
313 */
314int
315_sx_try_upgrade(struct sx *sx, const char *file, int line)
316{
317 uintptr_t x;
318 int success;
319
320 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
321 ("sx_try_upgrade() of destroyed sx @ %s:%d", file, line));
307 _sx_assert(sx, SX_SLOCKED, file, line);
308
309 /*
310 * Try to switch from one shared lock to an exclusive lock. We need
311 * to maintain the SX_LOCK_EXCLUSIVE_WAITERS flag if set so that
312 * we will wake up the exclusive waiters when we drop the lock.
313 */
314 x = sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS;

--- 9 unchanged lines hidden (view full) ---

324/*
325 * Downgrade an unrecursed exclusive lock into a single shared lock.
326 */
327void
328_sx_downgrade(struct sx *sx, const char *file, int line)
329{
330 uintptr_t x;
331
322 _sx_assert(sx, SX_SLOCKED, file, line);
323
324 /*
325 * Try to switch from one shared lock to an exclusive lock. We need
326 * to maintain the SX_LOCK_EXCLUSIVE_WAITERS flag if set so that
327 * we will wake up the exclusive waiters when we drop the lock.
328 */
329 x = sx->sx_lock & SX_LOCK_EXCLUSIVE_WAITERS;

--- 9 unchanged lines hidden (view full) ---

339/*
340 * Downgrade an unrecursed exclusive lock into a single shared lock.
341 */
342void
343_sx_downgrade(struct sx *sx, const char *file, int line)
344{
345 uintptr_t x;
346
347 KASSERT(sx->sx_lock != SX_LOCK_DESTROYED,
348 ("sx_downgrade() of destroyed sx @ %s:%d", file, line));
332 _sx_assert(sx, SX_XLOCKED | SX_NOTRECURSED, file, line);
333#ifndef INVARIANTS
334 if (sx_recursed(sx))
335 panic("downgrade of a recursed lock");
336#endif
337
338 WITNESS_DOWNGRADE(&sx->lock_object, 0, file, line);
339

--- 571 unchanged lines hidden (view full) ---

911 struct thread *td;
912 struct sx *sx;
913
914 sx = (struct sx *)lock;
915
916 db_printf(" state: ");
917 if (sx->sx_lock == SX_LOCK_UNLOCKED)
918 db_printf("UNLOCKED\n");
349 _sx_assert(sx, SX_XLOCKED | SX_NOTRECURSED, file, line);
350#ifndef INVARIANTS
351 if (sx_recursed(sx))
352 panic("downgrade of a recursed lock");
353#endif
354
355 WITNESS_DOWNGRADE(&sx->lock_object, 0, file, line);
356

--- 571 unchanged lines hidden (view full) ---

928 struct thread *td;
929 struct sx *sx;
930
931 sx = (struct sx *)lock;
932
933 db_printf(" state: ");
934 if (sx->sx_lock == SX_LOCK_UNLOCKED)
935 db_printf("UNLOCKED\n");
919 else if (sx->sx_lock & SX_LOCK_SHARED)
936 else if (sx->sx_lock == SX_LOCK_DESTROYED) {
937 db_printf("DESTROYED\n");
938 return;
939 } else if (sx->sx_lock & SX_LOCK_SHARED)
920 db_printf("SLOCK: %ju\n", (uintmax_t)SX_SHARERS(sx->sx_lock));
921 else {
922 td = sx_xholder(sx);
923 db_printf("XLOCK: %p (tid %d, pid %d, \"%s\")\n", td,
924 td->td_tid, td->td_proc->p_pid, td->td_proc->p_comm);
925 if (sx_recursed(sx))
926 db_printf(" recursed: %d\n", sx->sx_recurse);
927 }

--- 49 unchanged lines hidden ---
940 db_printf("SLOCK: %ju\n", (uintmax_t)SX_SHARERS(sx->sx_lock));
941 else {
942 td = sx_xholder(sx);
943 db_printf("XLOCK: %p (tid %d, pid %d, \"%s\")\n", td,
944 td->td_tid, td->td_proc->p_pid, td->td_proc->p_comm);
945 if (sx_recursed(sx))
946 db_printf(" recursed: %d\n", sx->sx_recurse);
947 }

--- 49 unchanged lines hidden ---