Line data Source code
1 : /* $OpenBSD: subr_evcount.c,v 1.12 2015/03/14 03:38:50 jsg Exp $ */
2 : /*
3 : * Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
4 : * Copyright (c) 2004 Aaron Campbell <aaron@openbsd.org>
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : *
11 : * 1. Redistributions of source code must retain the above copyright
12 : * notice, this list of conditions and the following disclaimer.
13 : * 2. The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 : *
16 : * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 : * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 : * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 : * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 :
28 : #include <sys/param.h>
29 : #include <sys/evcount.h>
30 : #include <sys/timeout.h>
31 : #include <sys/systm.h>
32 : #include <sys/sysctl.h>
33 :
34 : static TAILQ_HEAD(,evcount) evcount_list = TAILQ_HEAD_INITIALIZER(evcount_list);
35 :
36 : void
37 0 : evcount_attach(struct evcount *ec, const char *name, void *data)
38 : {
39 : static int nextid = 0;
40 :
41 0 : memset(ec, 0, sizeof(*ec));
42 0 : ec->ec_name = name;
43 0 : ec->ec_id = ++nextid;
44 0 : ec->ec_data = data;
45 0 : TAILQ_INSERT_TAIL(&evcount_list, ec, next);
46 0 : }
47 :
48 : void
49 0 : evcount_detach(struct evcount *ec)
50 : {
51 0 : TAILQ_REMOVE(&evcount_list, ec, next);
52 0 : }
53 :
54 : #ifndef SMALL_KERNEL
55 :
56 : int
57 0 : evcount_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
58 : void *newp, size_t newlen)
59 : {
60 : int error = 0, s, nintr, i;
61 : struct evcount *ec;
62 : u_int64_t count;
63 :
64 0 : if (newp != NULL)
65 0 : return (EPERM);
66 :
67 0 : if (name[0] != KERN_INTRCNT_NUM) {
68 0 : if (namelen != 2)
69 0 : return (ENOTDIR);
70 0 : if (name[1] < 0)
71 0 : return (EINVAL);
72 : i = name[1];
73 0 : } else
74 : i = -1;
75 :
76 : nintr = 0;
77 0 : TAILQ_FOREACH(ec, &evcount_list, next) {
78 0 : if (nintr++ == i)
79 : break;
80 : }
81 :
82 0 : switch (name[0]) {
83 : case KERN_INTRCNT_NUM:
84 0 : error = sysctl_rdint(oldp, oldlenp, NULL, nintr);
85 0 : break;
86 : case KERN_INTRCNT_CNT:
87 0 : if (ec == NULL)
88 0 : return (ENOENT);
89 0 : s = splhigh();
90 0 : count = ec->ec_count;
91 0 : splx(s);
92 0 : error = sysctl_rdquad(oldp, oldlenp, NULL, count);
93 0 : break;
94 : case KERN_INTRCNT_NAME:
95 0 : if (ec == NULL)
96 0 : return (ENOENT);
97 0 : error = sysctl_rdstring(oldp, oldlenp, NULL, ec->ec_name);
98 0 : break;
99 : case KERN_INTRCNT_VECTOR:
100 0 : if (ec == NULL || ec->ec_data == NULL)
101 0 : return (ENOENT);
102 0 : error = sysctl_rdint(oldp, oldlenp, NULL,
103 0 : *((int *)ec->ec_data));
104 0 : break;
105 : default:
106 : error = EOPNOTSUPP;
107 0 : break;
108 : }
109 :
110 0 : return (error);
111 0 : }
112 : #endif /* SMALL_KERNEL */
|