| 380 | } |
| 381 | |
| 382 | static void |
| 383 | softclock_call_cc(struct callout *c, struct callout_cpu *cc, |
| 384 | #ifdef CALLOUT_PROFILING |
| 385 | int *mpcalls, int *lockcalls, int *gcalls, |
| 386 | #endif |
| 387 | int direct) |
| 388 | { |
| 389 | struct rm_priotracker tracker; |
| 390 | void (*c_func)(void *); |
| 391 | void *c_arg; |
| 392 | struct lock_class *class; |
| 393 | struct lock_object *c_lock; |
| 394 | uintptr_t lock_status; |
| 395 | int c_iflags; |
| 396 | #if defined(DIAGNOSTIC) || defined(CALLOUT_PROFILING) |
| 397 | sbintime_t sbt1, sbt2; |
| 398 | struct timespec ts2; |
| 399 | static sbintime_t maxdt = 2 * SBT_1MS; /* 2 msec */ |
| 400 | static timeout_t *lastfunc; |
| 401 | #endif |
| 402 | |
| 403 | KASSERT((c->c_iflags & CALLOUT_PENDING) == CALLOUT_PENDING, |
| 404 | ("softclock_call_cc: pend %p %x", c, c->c_iflags)); |
| 405 | KASSERT((c->c_flags & CALLOUT_ACTIVE) == CALLOUT_ACTIVE, |
| 406 | ("softclock_call_cc: act %p %x", c, c->c_flags)); |
| 407 | class = (c->c_lock != NULL) ? LOCK_CLASS(c->c_lock) : NULL; |
| 408 | lock_status = 0; |
| 409 | if (c->c_flags & CALLOUT_SHAREDLOCK) { |
| 410 | if (class == &lock_class_rm) |
| 411 | lock_status = (uintptr_t)&tracker; |
| 412 | else |
| 413 | lock_status = 1; |
| 414 | } |
| 415 | c_lock = c->c_lock; |
| 416 | c_func = c->c_func; |
| 417 | c_arg = c->c_arg; |
| 418 | c_iflags = c->c_iflags; |
| 419 | if (c->c_iflags & CALLOUT_LOCAL_ALLOC) |
| 420 | c->c_iflags = CALLOUT_LOCAL_ALLOC; |
| 421 | else |
| 422 | c->c_iflags &= ~CALLOUT_PENDING; |
| 423 | |
| 424 | cc_exec_curr(cc, direct) = c; |
| 425 | cc_exec_cancel(cc, direct) = false; |
| 426 | cc_exec_drain(cc, direct) = NULL; |
| 427 | CC_UNLOCK(cc); |
| 428 | if (c_lock != NULL) { |
| 429 | class->lc_lock(c_lock, lock_status); |
| 430 | /* |
| 431 | * The callout may have been cancelled |
| 432 | * while we switched locks. |
| 433 | */ |
| 434 | if (cc_exec_cancel(cc, direct)) { |
| 435 | class->lc_unlock(c_lock); |
| 436 | goto skip; |
| 437 | } |
| 438 | /* The callout cannot be stopped now. */ |
| 439 | cc_exec_cancel(cc, direct) = true; |
no test coverage detected