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 */
129