1 /*- 2 * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * substantially similar to the "NO WARRANTY" disclaimer below 13 * ("Disclaimer") and any redistribution must be conditioned upon 14 * including a substantially similar Disclaimer requirement for further 15 * binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGES. 29 * 30 * Authors: Justin T. Gibbs (Spectra Logic Corporation) 31 * 32 * $FreeBSD$ 33 */ 34 35 /** 36 * \file callout.h 37 * 38 * \brief Interface for timer based callback services. 39 * 40 * Header requirements: 41 * 42 * #include <sys/time.h> 43 * 44 * #include <list> 45 */ 46 47 #ifndef _CALLOUT_H_ 48 #define _CALLOUT_H_ 49 50 /** 51 * \brief Type of the function callback from a Callout. 52 */ 53 typedef void CalloutFunc_t(void *); 54 55 /** 56 * \brief Interface to a schedulable one-shot timer with the granularity 57 * of the system clock (see setitimer(2)). 58 * 59 * Determination of callback expiration is triggered by the SIGALRM 60 * signal. Callout callbacks are always delivered from Zfsd's event 61 * processing loop. 62 * 63 * Periodic actions can be triggered via the Callout mechanisms by 64 * resetting the Callout from within its callback. 65 */ 66 class Callout 67 { 68 public: 69 70 /** 71 * Initialize the Callout subsystem. 72 */ 73 static void Init(); 74 75 /** 76 * Function called (via SIGALRM) when our interval 77 * timer expires. 78 */ 79 static void AlarmSignalHandler(int); 80 81 /** 82 * Execute callbacks for all callouts that have the same 83 * expiration time as the first callout in the list. 84 */ 85 static void ExpireCallouts(); 86 87 /** Constructor. */ 88 Callout(); 89 90 /** 91 * Returns true if callout has not been stopped, 92 * or deactivated since the last time the callout was 93 * reset. 94 */ 95 bool IsActive() const; 96 97 /** 98 * Returns true if callout is still waiting to expire. 99 */ 100 bool IsPending() const; 101 102 /** 103 * Disestablish a callout. 104 */ 105 bool Stop(); 106 107 /** 108 * \brief Establish or change a timeout. 109 * 110 * \param interval Timeval indicating the time which must elapse 111 * before this callout fires. 112 * \param func Pointer to the callback function 113 * \param arg Argument pointer to pass to callback function 114 * 115 * \return Cancellation status. 116 * true: The previous callback was pending and therefore 117 * was cancelled. 118 * false: The callout was not pending at the time of this 119 * reset request. 120 * In all cases, a new callout is established. 121 */ 122 bool Reset(const timeval &interval, CalloutFunc_t *func, void *arg); 123 124 /** 125 * \brief Calculate the remaining time until this Callout's timer 126 * expires. 127 * 128 * The return value will be slightly greater than the actual time to 129 * expiry. 130 * 131 * If the callout is not pending, returns INT_MAX. 132 */ 133 timeval TimeRemaining() const; 134 135 private: 136 /** 137 * All active callouts sorted by expiration time. The callout 138 * with the nearest expiration time is at the head of the list. 139 */ 140 static std::list<Callout *> s_activeCallouts; 141 142 /** 143 * The interval timer has expired. This variable is set from 144 * signal handler context and tested from Zfsd::EventLoop() 145 * context via ExpireCallouts(). 146 */ 147 static bool s_alarmFired; 148 149 /** 150 * Time, relative to others in the active list, until 151 * this callout is fired. 152 */ 153 timeval m_interval; 154 155 /** Callback function argument. */ 156 void *m_arg; 157 158 /** 159 * The callback function associated with this timer 160 * entry. 161 */ 162 CalloutFunc_t *m_func; 163 164 /** State of this callout. */ 165 bool m_pending; 166 }; 167 168 //- Callout public const methods ---------------------------------------------- 169 inline bool 170 Callout::IsPending() const 171 { 172 return (m_pending); 173 } 174 175 //- Callout public methods ---------------------------------------------------- 176 inline 177 Callout::Callout() 178 : m_arg(0), 179 m_func(NULL), 180 m_pending(false) 181 { 182 timerclear(&m_interval); 183 } 184 185 #endif /* CALLOUT_H_ */ 186