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 #ifdef CALLOUT_TYPESTABLE 102 #define callout_arg(cc) ((cc)->arg) 103 #else 104 #define callout_arg(cc) ((cc)->toc.rarg) 105 #endif 106 #ifndef _SYS_SPINLOCK_H_ 107 #include <sys/spinlock.h> 108 #endif 109 110 #ifdef _KERNEL 111 112 #define CALLOUT_DEBUG 113 #ifdef CALLOUT_DEBUG 114 #define CALLOUT_DEBUG_ARGS , const char *ident, int lineno 115 #define CALLOUT_DEBUG_PASSTHRU , ident, lineno 116 #else 117 #define CALLOUT_DEBUG_ARGS 118 #define CALLOUT_DEBUG_PASSTHRU 119 #endif 120 121 struct globaldata; 122 123 extern int ncallout; 124 125 int callout_active(struct callout *ext); 126 int callout_pending(struct callout *ext); 127 void callout_deactivate(struct callout *ext); 128 129 void hardclock_softtick(struct globaldata *); 130 void _callout_init (struct callout *cc 131 CALLOUT_DEBUG_ARGS); 132 void _callout_init_mp (struct callout *cc 133 CALLOUT_DEBUG_ARGS); 134 void _callout_init_lk (struct callout *cc, struct lock *lk 135 CALLOUT_DEBUG_ARGS); 136 void callout_reset (struct callout *, int, 137 void (*)(void *), void *); 138 void callout_reset_bycpu (struct callout *, int, 139 void (*)(void *), void *, 140 int); 141 int callout_stop (struct callout *cc); 142 int callout_stop_async (struct callout *cc); 143 void callout_terminate (struct callout *cc); 144 int callout_cancel (struct callout *cc); 145 int callout_drain (struct callout *cc); 146 147 #ifdef CALLOUT_DEBUG 148 #define callout_init(co) _callout_init(co, __FILE__, __LINE__) 149 #define callout_init_mp(co) _callout_init_mp(co, __FILE__, __LINE__) 150 #define callout_init_lk(co, lk) _callout_init_lk(co, lk, __FILE__, __LINE__) 151 #else 152 #define callout_init(co) _callout_init(co) 153 #define callout_init_mp(co) _callout_init_mp(co) 154 #define callout_init_lk(co, lk) _callout_init_lk(co, lk) 155 #endif 156 157 #endif /* _KERNEL */ 158 159 #endif /* _SYS_CALLOUT_H_ */ 160