17a0c41d5SAlan Somers /*- 27a0c41d5SAlan Somers * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation 37a0c41d5SAlan Somers * All rights reserved. 47a0c41d5SAlan Somers * 57a0c41d5SAlan Somers * Redistribution and use in source and binary forms, with or without 67a0c41d5SAlan Somers * modification, are permitted provided that the following conditions 77a0c41d5SAlan Somers * are met: 87a0c41d5SAlan Somers * 1. Redistributions of source code must retain the above copyright 97a0c41d5SAlan Somers * notice, this list of conditions, and the following disclaimer, 107a0c41d5SAlan Somers * without modification. 117a0c41d5SAlan Somers * 2. Redistributions in binary form must reproduce at minimum a disclaimer 127a0c41d5SAlan Somers * substantially similar to the "NO WARRANTY" disclaimer below 137a0c41d5SAlan Somers * ("Disclaimer") and any redistribution must be conditioned upon 147a0c41d5SAlan Somers * including a substantially similar Disclaimer requirement for further 157a0c41d5SAlan Somers * binary redistribution. 167a0c41d5SAlan Somers * 177a0c41d5SAlan Somers * NO WARRANTY 187a0c41d5SAlan Somers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 197a0c41d5SAlan Somers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 207a0c41d5SAlan Somers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 217a0c41d5SAlan Somers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 227a0c41d5SAlan Somers * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 237a0c41d5SAlan Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 247a0c41d5SAlan Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 257a0c41d5SAlan Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 267a0c41d5SAlan Somers * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 277a0c41d5SAlan Somers * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 287a0c41d5SAlan Somers * POSSIBILITY OF SUCH DAMAGES. 297a0c41d5SAlan Somers * 307a0c41d5SAlan Somers * Authors: Justin T. Gibbs (Spectra Logic Corporation) 317a0c41d5SAlan Somers * 327a0c41d5SAlan Somers * $FreeBSD$ 337a0c41d5SAlan Somers */ 347a0c41d5SAlan Somers 357a0c41d5SAlan Somers /** 367a0c41d5SAlan Somers * \file callout.h 377a0c41d5SAlan Somers * 387a0c41d5SAlan Somers * \brief Interface for timer based callback services. 397a0c41d5SAlan Somers * 407a0c41d5SAlan Somers * Header requirements: 417a0c41d5SAlan Somers * 427a0c41d5SAlan Somers * #include <sys/time.h> 437a0c41d5SAlan Somers * 447a0c41d5SAlan Somers * #include <list> 457a0c41d5SAlan Somers */ 467a0c41d5SAlan Somers 477a0c41d5SAlan Somers #ifndef _CALLOUT_H_ 487a0c41d5SAlan Somers #define _CALLOUT_H_ 497a0c41d5SAlan Somers 507a0c41d5SAlan Somers /** 517a0c41d5SAlan Somers * \brief Type of the function callback from a Callout. 527a0c41d5SAlan Somers */ 537a0c41d5SAlan Somers typedef void CalloutFunc_t(void *); 547a0c41d5SAlan Somers 557a0c41d5SAlan Somers /** 567a0c41d5SAlan Somers * \brief Interface to a schedulable one-shot timer with the granularity 577a0c41d5SAlan Somers * of the system clock (see setitimer(2)). 587a0c41d5SAlan Somers * 597a0c41d5SAlan Somers * Determination of callback expiration is triggered by the SIGALRM 607a0c41d5SAlan Somers * signal. Callout callbacks are always delivered from Zfsd's event 617a0c41d5SAlan Somers * processing loop. 627a0c41d5SAlan Somers * 637a0c41d5SAlan Somers * Periodic actions can be triggered via the Callout mechanisms by 647a0c41d5SAlan Somers * resetting the Callout from within its callback. 657a0c41d5SAlan Somers */ 667a0c41d5SAlan Somers class Callout 677a0c41d5SAlan Somers { 687a0c41d5SAlan Somers public: 697a0c41d5SAlan Somers 707a0c41d5SAlan Somers /** 717a0c41d5SAlan Somers * Initialize the Callout subsystem. 727a0c41d5SAlan Somers */ 737a0c41d5SAlan Somers static void Init(); 747a0c41d5SAlan Somers 757a0c41d5SAlan Somers /** 767a0c41d5SAlan Somers * Function called (via SIGALRM) when our interval 777a0c41d5SAlan Somers * timer expires. 787a0c41d5SAlan Somers */ 797a0c41d5SAlan Somers static void AlarmSignalHandler(int); 807a0c41d5SAlan Somers 817a0c41d5SAlan Somers /** 827a0c41d5SAlan Somers * Execute callbacks for all callouts that have the same 837a0c41d5SAlan Somers * expiration time as the first callout in the list. 847a0c41d5SAlan Somers */ 857a0c41d5SAlan Somers static void ExpireCallouts(); 867a0c41d5SAlan Somers 877a0c41d5SAlan Somers /** Constructor. */ 887a0c41d5SAlan Somers Callout(); 897a0c41d5SAlan Somers 907a0c41d5SAlan Somers /** 917a0c41d5SAlan Somers * Returns true if callout has not been stopped, 927a0c41d5SAlan Somers * or deactivated since the last time the callout was 937a0c41d5SAlan Somers * reset. 947a0c41d5SAlan Somers */ 957a0c41d5SAlan Somers bool IsActive() const; 967a0c41d5SAlan Somers 977a0c41d5SAlan Somers /** 987a0c41d5SAlan Somers * Returns true if callout is still waiting to expire. 997a0c41d5SAlan Somers */ 1007a0c41d5SAlan Somers bool IsPending() const; 1017a0c41d5SAlan Somers 1027a0c41d5SAlan Somers /** 1037a0c41d5SAlan Somers * Disestablish a callout. 1047a0c41d5SAlan Somers */ 1057a0c41d5SAlan Somers bool Stop(); 1067a0c41d5SAlan Somers 1077a0c41d5SAlan Somers /** 1087a0c41d5SAlan Somers * \brief Establish or change a timeout. 1097a0c41d5SAlan Somers * 1107a0c41d5SAlan Somers * \param interval Timeval indicating the time which must elapse 1117a0c41d5SAlan Somers * before this callout fires. 112*52832d77SPedro F. Giffuni * \param func Pointer to the callback function 1137a0c41d5SAlan Somers * \param arg Argument pointer to pass to callback function 1147a0c41d5SAlan Somers * 1157a0c41d5SAlan Somers * \return Cancellation status. 1167a0c41d5SAlan Somers * true: The previous callback was pending and therefore 1177a0c41d5SAlan Somers * was cancelled. 1187a0c41d5SAlan Somers * false: The callout was not pending at the time of this 1197a0c41d5SAlan Somers * reset request. 1207a0c41d5SAlan Somers * In all cases, a new callout is established. 1217a0c41d5SAlan Somers */ 1227a0c41d5SAlan Somers bool Reset(const timeval &interval, CalloutFunc_t *func, void *arg); 1237a0c41d5SAlan Somers 1247a0c41d5SAlan Somers /** 1257a0c41d5SAlan Somers * \brief Calculate the remaining time until this Callout's timer 1267a0c41d5SAlan Somers * expires. 1277a0c41d5SAlan Somers * 1287a0c41d5SAlan Somers * The return value will be slightly greater than the actual time to 1297a0c41d5SAlan Somers * expiry. 1307a0c41d5SAlan Somers * 1317a0c41d5SAlan Somers * If the callout is not pending, returns INT_MAX. 1327a0c41d5SAlan Somers */ 1337a0c41d5SAlan Somers timeval TimeRemaining() const; 1347a0c41d5SAlan Somers 1357a0c41d5SAlan Somers private: 1367a0c41d5SAlan Somers /** 1377a0c41d5SAlan Somers * All active callouts sorted by expiration time. The callout 1387a0c41d5SAlan Somers * with the nearest expiration time is at the head of the list. 1397a0c41d5SAlan Somers */ 1407a0c41d5SAlan Somers static std::list<Callout *> s_activeCallouts; 1417a0c41d5SAlan Somers 1427a0c41d5SAlan Somers /** 1437a0c41d5SAlan Somers * The interval timer has expired. This variable is set from 1447a0c41d5SAlan Somers * signal handler context and tested from Zfsd::EventLoop() 1457a0c41d5SAlan Somers * context via ExpireCallouts(). 1467a0c41d5SAlan Somers */ 1477a0c41d5SAlan Somers static bool s_alarmFired; 1487a0c41d5SAlan Somers 1497a0c41d5SAlan Somers /** 1507a0c41d5SAlan Somers * Time, relative to others in the active list, until 1517a0c41d5SAlan Somers * this callout is fired. 1527a0c41d5SAlan Somers */ 1537a0c41d5SAlan Somers timeval m_interval; 1547a0c41d5SAlan Somers 1557a0c41d5SAlan Somers /** Callback function argument. */ 1567a0c41d5SAlan Somers void *m_arg; 1577a0c41d5SAlan Somers 1587a0c41d5SAlan Somers /** 1597a0c41d5SAlan Somers * The callback function associated with this timer 1607a0c41d5SAlan Somers * entry. 1617a0c41d5SAlan Somers */ 1627a0c41d5SAlan Somers CalloutFunc_t *m_func; 1637a0c41d5SAlan Somers 1647a0c41d5SAlan Somers /** State of this callout. */ 1657a0c41d5SAlan Somers bool m_pending; 1667a0c41d5SAlan Somers }; 1677a0c41d5SAlan Somers 1687a0c41d5SAlan Somers //- Callout public const methods ---------------------------------------------- 1697a0c41d5SAlan Somers inline bool 1707a0c41d5SAlan Somers Callout::IsPending() const 1717a0c41d5SAlan Somers { 1727a0c41d5SAlan Somers return (m_pending); 1737a0c41d5SAlan Somers } 1747a0c41d5SAlan Somers 1757a0c41d5SAlan Somers //- Callout public methods ---------------------------------------------------- 1767a0c41d5SAlan Somers inline 1777a0c41d5SAlan Somers Callout::Callout() 1787a0c41d5SAlan Somers : m_arg(0), 1797a0c41d5SAlan Somers m_func(NULL), 1807a0c41d5SAlan Somers m_pending(false) 1817a0c41d5SAlan Somers { 1827a0c41d5SAlan Somers timerclear(&m_interval); 1837a0c41d5SAlan Somers } 1847a0c41d5SAlan Somers 1857a0c41d5SAlan Somers #endif /* CALLOUT_H_ */ 186