eventhandler.h revision 107136
150107Smsmith/*- 250107Smsmith * Copyright (c) 1999 Michael Smith <msmith@freebsd.org> 350107Smsmith * All rights reserved. 450107Smsmith * 550107Smsmith * Redistribution and use in source and binary forms, with or without 650107Smsmith * modification, are permitted provided that the following conditions 750107Smsmith * are met: 850107Smsmith * 1. Redistributions of source code must retain the above copyright 950107Smsmith * notice, this list of conditions and the following disclaimer. 1050107Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1150107Smsmith * notice, this list of conditions and the following disclaimer in the 1250107Smsmith * documentation and/or other materials provided with the distribution. 1350107Smsmith * 1450107Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1550107Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1650107Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1750107Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1850107Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1950107Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2050107Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2150107Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2250107Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2350107Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2450107Smsmith * SUCH DAMAGE. 2550107Smsmith * 2650477Speter * $FreeBSD: head/sys/sys/eventhandler.h 107136 2002-11-21 09:17:56Z jeff $ 2750107Smsmith */ 2850107Smsmith 2967535Sjhb#ifndef SYS_EVENTHANDLER_H 3067535Sjhb#define SYS_EVENTHANDLER_H 3167535Sjhb 3293615Salfred#include <sys/lock.h> 3393615Salfred#include <sys/sx.h> 3450107Smsmith#include <sys/queue.h> 3550107Smsmith 3695193Smarkmstruct eventhandler_entry { 3795193Smarkm TAILQ_ENTRY(eventhandler_entry) ee_link; 3895193Smarkm int ee_priority; 3995193Smarkm void *ee_arg; 4050107Smsmith}; 4150107Smsmith 4295193Smarkmstruct eventhandler_list { 4395193Smarkm char *el_name; 4495193Smarkm int el_flags; 4550107Smsmith#define EHE_INITTED (1<<0) 4695193Smarkm struct sx el_lock; 4795193Smarkm TAILQ_ENTRY(eventhandler_list) el_link; 4895193Smarkm TAILQ_HEAD(,eventhandler_entry) el_entries; 4950107Smsmith}; 5050107Smsmith 5150107Smsmithtypedef struct eventhandler_entry *eventhandler_tag; 5250107Smsmith 5393615Salfred#define EHE_LOCK(p) sx_xlock(&(p)->el_lock) 5493615Salfred#define EHE_UNLOCK(p) sx_xunlock(&(p)->el_lock) 5593615Salfred 5650107Smsmith/* 5750107Smsmith * Fast handler lists require the eventhandler list be present 5850107Smsmith * at link time. They don't allow addition of entries to 5950107Smsmith * unknown eventhandler lists, ie. each list must have an 6050107Smsmith * "owner". 6150107Smsmith * 6250107Smsmith * Fast handler lists must be defined once by the owner 6350107Smsmith * of the eventhandler list, and the declaration must be in 6450107Smsmith * scope at any point the list is manipulated. 6550107Smsmith */ 6695193Smarkm#define EVENTHANDLER_FAST_DECLARE(name, type) \ 6795193Smarkmextern struct eventhandler_list Xeventhandler_list_ ## name ; \ 6895193Smarkmstruct eventhandler_entry_ ## name { \ 6995193Smarkm struct eventhandler_entry ee; \ 7095193Smarkm type eh_func; \ 7195193Smarkm}; \ 7256093Sbdestruct __hack 7350107Smsmith 7456093Sbde#define EVENTHANDLER_FAST_DEFINE(name, type) \ 7556093Sbdestruct eventhandler_list Xeventhandler_list_ ## name = { #name }; \ 7656093Sbdestruct __hack 7750107Smsmith 78100111Smarkm#define EVENTHANDLER_FAST_INVOKE(name, ...) \ 7995193Smarkmdo { \ 8095193Smarkm struct eventhandler_list *_el = &Xeventhandler_list_ ## name ; \ 8195193Smarkm struct eventhandler_entry *_ep, *_en; \ 8295193Smarkm struct eventhandler_entry_ ## name *_t; \ 8395193Smarkm \ 8495193Smarkm if (_el->el_flags & EHE_INITTED) { \ 8595193Smarkm EHE_LOCK(_el); \ 8695193Smarkm _ep = TAILQ_FIRST(&(_el->el_entries)); \ 8795193Smarkm while (_ep != NULL) { \ 8895193Smarkm _en = TAILQ_NEXT(_ep, ee_link); \ 8995193Smarkm _t = (struct eventhandler_entry_ ## name *)_ep; \ 90100111Smarkm _t->eh_func(_ep->ee_arg , __VA_ARGS__); \ 9197164Smarkm _ep = _en; \ 9297164Smarkm } \ 9397164Smarkm EHE_UNLOCK(_el); \ 9495193Smarkm } \ 9556093Sbde} while (0) 9650107Smsmith 9795193Smarkm#define EVENTHANDLER_FAST_REGISTER(name, func, arg, priority) \ 9895193Smarkm eventhandler_register(&Xeventhandler_list_ ## name, \ 9995193Smarkm #name, func, arg, priority) 10050107Smsmith 10195193Smarkm#define EVENTHANDLER_FAST_DEREGISTER(name, tag) \ 10295193Smarkm eventhandler_deregister(&Xeventhandler_list_ ## name, tag) 10350107Smsmith 10450107Smsmith/* 10566205Smsmith * Slow handlers are entirely dynamic; lists are created 10650107Smsmith * when entries are added to them, and thus have no concept of "owner", 10750107Smsmith * 10866205Smsmith * Slow handlers need to be declared, but do not need to be defined. The 10950107Smsmith * declaration must be in scope wherever the handler is to be invoked. 11050107Smsmith */ 11195193Smarkm#define EVENTHANDLER_DECLARE(name, type) \ 11295193Smarkmstruct eventhandler_entry_ ## name \ 11395193Smarkm{ \ 11495193Smarkm struct eventhandler_entry ee; \ 11595193Smarkm type eh_func; \ 11695193Smarkm}; \ 11756093Sbdestruct __hack 11850107Smsmith 119100111Smarkm#define EVENTHANDLER_INVOKE(name, ...) \ 12095193Smarkmdo { \ 12195193Smarkm struct eventhandler_list *_el; \ 12295193Smarkm struct eventhandler_entry *_ep, *_en; \ 12395193Smarkm struct eventhandler_entry_ ## name *_t; \ 12495193Smarkm \ 12595193Smarkm if (((_el = eventhandler_find_list(#name)) != NULL) && \ 12695193Smarkm (_el->el_flags & EHE_INITTED)) { \ 12795193Smarkm EHE_LOCK(_el); \ 12895193Smarkm _ep = TAILQ_FIRST(&(_el->el_entries)); \ 12995193Smarkm while (_ep != NULL) { \ 13095193Smarkm _en = TAILQ_NEXT(_ep, ee_link); \ 13195193Smarkm _t = (struct eventhandler_entry_ ## name *)_ep; \ 132100111Smarkm _t->eh_func(_ep->ee_arg , __VA_ARGS__); \ 13395193Smarkm _ep = _en; \ 13495193Smarkm } \ 13595193Smarkm EHE_UNLOCK(_el); \ 13695193Smarkm } \ 13756093Sbde} while (0) 13850107Smsmith 13995193Smarkm#define EVENTHANDLER_REGISTER(name, func, arg, priority) \ 14095193Smarkm eventhandler_register(NULL, #name, func, arg, priority) 14150107Smsmith 14295193Smarkm#define EVENTHANDLER_DEREGISTER(name, tag) \ 14395193Smarkmdo { \ 14495193Smarkm struct eventhandler_list *_el; \ 14595193Smarkm \ 14695193Smarkm if ((_el = eventhandler_find_list(#name)) != NULL) \ 14795193Smarkm eventhandler_deregister(_el, tag); \ 14856093Sbde} while(0) 14950107Smsmith 15050107Smsmith 15150107Smsmithextern eventhandler_tag eventhandler_register(struct eventhandler_list *list, 15250107Smsmith char *name, 15350107Smsmith void *func, 15450107Smsmith void *arg, 15550107Smsmith int priority); 15650107Smsmithextern void eventhandler_deregister(struct eventhandler_list *list, 15750107Smsmith eventhandler_tag tag); 15850107Smsmithextern struct eventhandler_list *eventhandler_find_list(char *name); 15950107Smsmith 16050107Smsmith/* 16150107Smsmith * Standard system event queues. 16250107Smsmith */ 16350107Smsmith 16450107Smsmith/* Shutdown events */ 16592719Salfredtypedef void (*shutdown_fn)(void *, int); 16650107Smsmith 16750107Smsmith#define SHUTDOWN_PRI_FIRST 0 16850107Smsmith#define SHUTDOWN_PRI_DEFAULT 10000 16950107Smsmith#define SHUTDOWN_PRI_LAST 20000 17050107Smsmith 17150107SmsmithEVENTHANDLER_DECLARE(shutdown_pre_sync, shutdown_fn); /* before fs sync */ 17250107SmsmithEVENTHANDLER_DECLARE(shutdown_post_sync, shutdown_fn); /* after fs sync */ 17350107SmsmithEVENTHANDLER_DECLARE(shutdown_final, shutdown_fn); 17450107Smsmith 17566205Smsmith/* Idle process event */ 17692719Salfredtypedef void (*idle_eventhandler_t)(void *, int); 17766205Smsmith 17866841Smsmith#define IDLE_PRI_FIRST 10000 17966205Smsmith#define IDLE_PRI_LAST 20000 18066205SmsmithEVENTHANDLER_FAST_DECLARE(idle_event, idle_eventhandler_t); 18166205Smsmith 182107136Sjeff/* Low memory event */ 183107136Sjefftypedef void (*vm_lowmem_handler_t)(void *, int); 184107136Sjeff#define LOWMEM_PRI_DEFAULT 0 185107136SjeffEVENTHANDLER_DECLARE(vm_lowmem, vm_lowmem_handler_t); 18666205Smsmith 18750107Smsmith#endif /* SYS_EVENTHANDLER_H */ 188