[BACK]Return to module_hook.h CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / sys

File: [cvs.NetBSD.org] / src / sys / sys / module_hook.h (download)

Revision 1.6, Thu Dec 12 22:55:20 2019 UTC (4 years, 4 months ago) by pgoyette
Branch: MAIN
CVS Tags: thorpej-ifq-base, thorpej-ifq, thorpej-i2c-spi-conf2-base, thorpej-i2c-spi-conf2, thorpej-i2c-spi-conf-base, thorpej-i2c-spi-conf, thorpej-futex2-base, thorpej-futex2, thorpej-futex-base, thorpej-futex, thorpej-cfargs2-base, thorpej-cfargs2, thorpej-cfargs-base, thorpej-cfargs, thorpej-altq-separation-base, thorpej-altq-separation, phil-wifi-20200421, phil-wifi-20200411, phil-wifi-20200406, netbsd-10-base, netbsd-10-0-RELEASE, netbsd-10-0-RC6, netbsd-10-0-RC5, netbsd-10-0-RC4, netbsd-10-0-RC3, netbsd-10-0-RC2, netbsd-10-0-RC1, netbsd-10, is-mlppp-base, is-mlppp, cjep_sun2x-base1, cjep_sun2x-base, cjep_sun2x, cjep_staticlib_x-base1, cjep_staticlib_x-base, cjep_staticlib_x, bouyer-xenpvh-base2, bouyer-xenpvh-base1, bouyer-xenpvh-base, bouyer-xenpvh, bouyer-sunxi-drm-base, bouyer-sunxi-drm, ad-namecache-base3, ad-namecache-base2, ad-namecache-base1, ad-namecache-base, ad-namecache, HEAD
Changes since 1.5: +21 -75 lines

Eliminate per-hook duplication of common code as suggested by
(and with major contributions from) riastradh@

Welcome to 9.99.23

/* $NetBSD: module_hook.h,v 1.6 2019/12/12 22:55:20 pgoyette Exp $	*/

/*-
 * Copyright (c) 2018 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Paul Goyette
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _SYS_MODULE_HOOK_H
#define _SYS_MODULE_HOOK_H

#include <sys/param.h>	/* for COHERENCY_UNIT, for __cacheline_aligned */
#include <sys/localcount.h>
#include <sys/stdbool.h>

void module_hook_init(void);
void module_hook_set(bool *, struct localcount *);
void module_hook_unset(bool *, struct localcount *);
bool module_hook_tryenter(bool *, struct localcount *);
void module_hook_exit(struct localcount *); 

/*
 * Macros for creating MP-safe vectored function calls, where
 * the function implementations are in modules which could be
 * unloaded.
 */

#define MODULE_HOOK(hook, type, args)				\
extern struct hook ## _t {					\
	struct localcount	lc;				\
	type			(*f)args;			\
	bool			hooked;				\
} hook __cacheline_aligned;

/*
 * We use pserialize_perform() to issue a memory barrier on the current
 * CPU and on all other CPUs so that all prior memory operations on the
 * current CPU globally happen before all subsequent memory operations
 * on the current CPU, as perceived by any other CPU.
 *
 * pserialize_perform() might be rather heavy-weight here, but it only
 * happens during module loading, and it allows MODULE_HOOK_CALL() to
 * work without any other memory barriers.
 */

#define MODULE_HOOK_SET(hook, func)				\
do {								\
	(hook).f = func;					\
	module_hook_set(&(hook).hooked, &(hook).lc);		\
} while /* CONSTCOND */ (0)

#define MODULE_HOOK_UNSET(hook)					\
do {								\
	KASSERT((hook).f);					\
	module_hook_unset(&(hook).hooked, &(hook).lc);		\
	(hook).f = NULL;	/* paranoia */			\
} while /* CONSTCOND */ (0)

#define MODULE_HOOK_CALL(hook, args, default, retval)		\
do {								\
	if (module_hook_tryenter(&(hook).hooked, &(hook).lc)) {	\
		(retval) = (*(hook).f)args;			\
		module_hook_exit(&(hook).lc);			\
	} else {						\
		(retval) = (default);				\
	}							\
} while /* CONSTCOND */ (0)

#define MODULE_HOOK_CALL_VOID(hook, args, default)		\
do {								\
	if (module_hook_tryenter(&(hook).hooked, &(hook).lc)) {	\
		(*(hook).f)args;				\
		module_hook_exit(&(hook).lc);			\
	} else {						\
		default;					\
	}							\
} while /* CONSTCOND */ (0)

#endif	/* _SYS_MODULE_HOOK_H */