* New interface; clients allocate their own callout structures. * * callout_reset() - establish or change a timeout * callout_stop() - disestablish a timeout * callout_init() - initialize a callout structure so that it can * safely be passed to callout_reset() and callout_stop() * * defines three convenience macros: * * callout_active() - returns truth if callout has no
| 690 | * callout_deactivate() - marks the callout as having been serviced |
| 691 | */ |
| 692 | int |
| 693 | callout_reset_tick_on(struct callout *c, int to_ticks, |
| 694 | void (*ftn)(void *), void *arg, int cpu, int flags) |
| 695 | { |
| 696 | struct callout_cpu *cc; |
| 697 | int cancelled, direct; |
| 698 | int ignore_cpu=0; |
| 699 | |
| 700 | cancelled = 0; |
| 701 | if (cpu == -1) { |
| 702 | ignore_cpu = 1; |
| 703 | } else if ((cpu >= MAXCPU) || |
| 704 | ((CC_CPU(cpu))->cc_inited == 0)) { |
| 705 | /* Invalid CPU spec */ |
| 706 | panic("Invalid CPU in callout %d", cpu); |
| 707 | } |
| 708 | |
| 709 | /* |
| 710 | * This flag used to be added by callout_cc_add, but the |
| 711 | * first time you call this we could end up with the |
| 712 | * wrong direct flag if we don't do it before we add. |
| 713 | */ |
| 714 | if (flags & C_DIRECT_EXEC) { |
| 715 | direct = 1; |
| 716 | } else { |
| 717 | direct = 0; |
| 718 | } |
| 719 | KASSERT(!direct || c->c_lock == NULL, |
| 720 | ("%s: direct callout %p has lock", __func__, c)); |
| 721 | cc = callout_lock(c); |
| 722 | /* |
| 723 | * Don't allow migration of pre-allocated callouts lest they |
| 724 | * become unbalanced or handle the case where the user does |
| 725 | * not care. |
| 726 | */ |
| 727 | if ((c->c_iflags & CALLOUT_LOCAL_ALLOC) || |
| 728 | ignore_cpu) { |
| 729 | cpu = c->c_cpu; |
| 730 | } |
| 731 | |
| 732 | if (cc_exec_curr(cc, direct) == c) { |
| 733 | /* |
| 734 | * We're being asked to reschedule a callout which is |
| 735 | * currently in progress. If there is a lock then we |
| 736 | * can cancel the callout if it has not really started. |
| 737 | */ |
| 738 | if (c->c_lock != NULL && !cc_exec_cancel(cc, direct)) |
| 739 | cancelled = cc_exec_cancel(cc, direct) = true; |
| 740 | if (cc_exec_waiting(cc, direct)) { |
| 741 | /* |
| 742 | * Someone has called callout_drain to kill this |
| 743 | * callout. Don't reschedule. |
| 744 | */ |
| 745 | CTR4(KTR_CALLOUT, "%s %p func %p arg %p", |
| 746 | cancelled ? "cancelled" : "failed to cancel", |
| 747 | c, c->c_func, c->c_arg); |
| 748 | CC_UNLOCK(cc); |
| 749 | return (cancelled); |
nothing calls this directly
no test coverage detected