master
  1/*	$NetBSD: psref.h,v 1.4 2019/05/17 03:34:27 ozaki-r Exp $	*/
  2
  3/*-
  4 * Copyright (c) 2016 The NetBSD Foundation, Inc.
  5 * All rights reserved.
  6 *
  7 * This code is derived from software contributed to The NetBSD Foundation
  8 * by Taylor R. Campbell.
  9 *
 10 * Redistribution and use in source and binary forms, with or without
 11 * modification, are permitted provided that the following conditions
 12 * are met:
 13 * 1. Redistributions of source code must retain the above copyright
 14 *    notice, this list of conditions and the following disclaimer.
 15 * 2. Redistributions in binary form must reproduce the above copyright
 16 *    notice, this list of conditions and the following disclaimer in the
 17 *    documentation and/or other materials provided with the distribution.
 18 *
 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 29 * POSSIBILITY OF SUCH DAMAGE.
 30 */
 31
 32#ifndef	_SYS_PSREF_H
 33#define	_SYS_PSREF_H
 34
 35#ifdef _KERNEL_OPT
 36#include "opt_psref_debug.h"
 37#endif
 38
 39#include <sys/types.h>
 40#include <sys/queue.h>
 41
 42struct cpu_info;
 43struct lwp;
 44
 45struct psref;
 46struct psref_class;
 47struct psref_target;
 48
 49/*
 50 * struct psref_target
 51 *
 52 *	Bookkeeping for an object to which users can acquire passive
 53 *	references.  This is compact so that it can easily be embedded
 54 *	into many multitudes of objects, e.g. IP packet flows.
 55 *
 56 *	prt_draining is false on initialization, and may be written
 57 *	only once, to make it true, when someone has prevented new
 58 *	references from being created and wants to drain the target in
 59 *	order to destroy it.
 60 */
 61struct psref_target {
 62	struct psref_class	*prt_class;
 63	bool			prt_draining;
 64};
 65
 66/*
 67 * struct psref
 68 *
 69 *	Bookkeeping for a single passive reference.  There should only
 70 *	be a few of these per CPU in the system at once, no matter how
 71 *	many targets are stored, so these are a bit larger than struct
 72 *	psref_target.  The contents of struct psref may be read and
 73 *	written only on the local CPU.
 74 */
 75struct psref {
 76	SLIST_ENTRY(psref)		psref_entry;
 77	void				*psref_debug; /* For debugging */
 78	const struct psref_target	*psref_target;
 79	struct lwp			*psref_lwp;
 80	struct cpu_info			*psref_cpu;
 81};
 82
 83#ifdef _KERNEL
 84void	psref_init(void);
 85
 86struct psref_class *
 87	psref_class_create(const char *, int);
 88void	psref_class_destroy(struct psref_class *);
 89
 90void	psref_target_init(struct psref_target *, struct psref_class *);
 91void	psref_target_destroy(struct psref_target *, struct psref_class *);
 92
 93void	psref_acquire(struct psref *, const struct psref_target *,
 94	    struct psref_class *);
 95void	psref_release(struct psref *, const struct psref_target *,
 96	    struct psref_class *);
 97void	psref_copy(struct psref *, const struct psref *,
 98	    struct psref_class *);
 99
100/* For use only in assertions.  */
101bool	psref_held(const struct psref_target *, struct psref_class *);
102
103
104#ifdef PSREF_DEBUG
105void	psref_debug_barrier(void);
106void	psref_debug_init_lwp(struct lwp *);
107
108#define PSREF_DEBUG_BARRIER()		psref_debug_barrier()
109#define PSREF_DEBUG_INIT_LWP(l)		psref_debug_init_lwp((l))
110#define PSREF_DEBUG_FILL_RETURN_ADDRESS0(psref, addr)	do {		\
111	(psref)->psref_debug = (addr);					\
112} while (0)
113#define PSREF_DEBUG_FILL_RETURN_ADDRESS(psref)	do {			\
114	PSREF_DEBUG_FILL_RETURN_ADDRESS0(psref, __builtin_return_address(0));\
115} while (0)
116
117#else
118
119#define PSREF_DEBUG_BARRIER()		__nothing
120#define PSREF_DEBUG_INIT_LWP(l)		__nothing
121#define PSREF_DEBUG_FILL_RETURN_ADDRESS0(psref, addr)	__nothing
122#define PSREF_DEBUG_FILL_RETURN_ADDRESS(psref)		__nothing
123
124#endif /* PSREF_DEBUG */
125
126#endif /* _KERNEL */
127
128#endif	/* _SYS_PSREF_H */