1 /* 2 * Copyright (c) 2014,2018,2019 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #ifndef _SYS_CALLOUT_H_ 36 #define _SYS_CALLOUT_H_ 37 38 #ifndef _SYS_QUEUE_H_ 39 #include <sys/queue.h> 40 #endif 41 #ifndef _SYS_LOCK_H_ 42 #include <sys/lock.h> 43 #endif 44 #ifndef _SYS_SPINLOCK_H_ 45 #include <sys/spinlock.h> 46 #endif 47 48 /* 49 * WITH TYPESTABLE (currently disabled) 50 * 51 * This is a mechanism to use a separate internal _callout structure 52 * for kern_timeout's internals instead of embedding. At the moment 53 * it doesn't work properly because tsleep() is using a temporary callout 54 * and can't afford to block on setup. 55 * 56 * WITHOUT TYPESTABLE <--- 57 * 58 * Without typestable we embed the internal _callout structure within 59 * the external callout structure. We will still use the verifier to 60 * try to catch corruption. 61 */ 62 struct callout; 63 #undef CALLOUT_TYPESTABLE 64 65 struct _callout { 66 struct spinlock spin; 67 TAILQ_ENTRY(_callout) entry; 68 struct callout *verifier; 69 uint32_t flags; 70 uint32_t lineno; 71 struct lock *lk; 72 const char *ident; 73 74 struct softclock_pcpu *rsc; /* request info */ 75 void *rarg; 76 void (*rfunc)(void *); 77 int rtick; 78 int unused01; 79 80 struct softclock_pcpu *qsc; /* active info */ 81 void *qarg; 82 void (*qfunc)(void *); 83 int qtick; 84 int waiters; 85 }; 86 87 struct callout { 88 #ifdef CALLOUT_TYPESTABLE 89 struct _callout *toc; /* opaque internal structure */ 90 uint32_t flags; /* initial flags */ 91 uint32_t lineno; /* debugging */ 92 struct lock *lk; /* interlock */ 93 const char *ident; /* debugging */ 94 void *arg; /* ONLY used for callout_arg() XXX */ 95 #else 96 struct _callout toc; 97 uint32_t flags; 98 #endif 99 }; 100 101 /* 102 * Legacy access/setting of the function and argument. Used only 103 * by netgraph7 and ieee80211_dfs.c. DO NOT USE FOR NEW CODE! 104 */ 105 #ifdef CALLOUT_TYPESTABLE 106 #define callout_set_arg(cc, _arg) ((cc)->qarg = (_arg)) 107 #define callout_arg(cc) ((cc)->qarg) 108 #define callout_func(cc) ((cc)->qfunc) 109 #else 110 #define callout_set_arg(cc, _arg) ((cc)->toc.qarg = (_arg)) 111 #define callout_arg(cc) ((cc)->toc.qarg) 112 #define callout_func(cc) ((cc)->toc.qfunc) 113 #endif 114 115 #ifdef _KERNEL 116 117 #define CALLOUT_DEBUG 118 #ifdef CALLOUT_DEBUG 119 #define CALLOUT_DEBUG_ARGS , const char *ident, int lineno 120 #define CALLOUT_DEBUG_PASSTHRU , ident, lineno 121 #else 122 #define CALLOUT_DEBUG_ARGS 123 #define CALLOUT_DEBUG_PASSTHRU 124 #endif 125 126 struct globaldata; 127 128 extern int ncallout; 129 130 int callout_active(struct callout *ext); 131 int callout_pending(struct callout *ext); 132 void callout_deactivate(struct callout *ext); 133 134 void hardclock_softtick(struct globaldata *); 135 void _callout_init (struct callout *cc 136 CALLOUT_DEBUG_ARGS); 137 void _callout_init_mp (struct callout *cc 138 CALLOUT_DEBUG_ARGS); 139 void _callout_init_lk (struct callout *cc, struct lock *lk 140 CALLOUT_DEBUG_ARGS); 141 void callout_reset (struct callout *, int, 142 void (*)(void *), void *); 143 void callout_reset_bycpu (struct callout *, int, 144 void (*)(void *), void *, 145 int); 146 int callout_stop (struct callout *cc); 147 int callout_stop_async (struct callout *cc); 148 void callout_terminate (struct callout *cc); 149 int callout_cancel (struct callout *cc); 150 int callout_drain (struct callout *cc); 151 152 #ifdef CALLOUT_DEBUG 153 #define callout_init(co) _callout_init(co, __FILE__, __LINE__) 154 #define callout_init_mp(co) _callout_init_mp(co, __FILE__, __LINE__) 155 #define callout_init_lk(co, lk) _callout_init_lk(co, lk, __FILE__, __LINE__) 156 #else 157 #define callout_init(co) _callout_init(co) 158 #define callout_init_mp(co) _callout_init_mp(co) 159 #define callout_init_lk(co, lk) _callout_init_lk(co, lk) 160 #endif 161 162 #endif /* _KERNEL */ 163 164 #endif /* _SYS_CALLOUT_H_ */ 165