1 | /* $NetBSD: syscall_stats.h,v 1.4 2008/11/12 12:36:28 ad Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2007 The NetBSD Foundation, Inc. |
5 | * All rights reserved. |
6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by David Laight. |
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_SYCALL_STAT_H_ |
33 | #define _SYS_SYCALL_STAT_H_ |
34 | |
35 | #ifdef _KERNEL_OPT |
36 | #include "opt_syscall_stats.h" |
37 | #endif |
38 | |
39 | #ifdef SYSCALL_STATS |
40 | #include <sys/syscall.h> |
41 | |
42 | extern uint64_t syscall_counts[SYS_NSYSENT]; |
43 | extern uint64_t syscall_count_user, syscall_count_system, syscall_count_interrupt; |
44 | #define SYSCALL_COUNT(table, code) ((table)[code]++) |
45 | |
46 | #if defined(SYSCALL_TIMES) && defined(__HAVE_CPU_COUNTER) |
47 | |
48 | #include <machine/cpu_counter.h> |
49 | extern uint64_t syscall_times[SYS_NSYSENT]; |
50 | |
51 | #ifdef SYSCALL_TIMES_HASCOUNTER |
52 | /* Force use of cycle counter - needed for Soekris systems */ |
53 | #define SYSCALL_TIME() (cpu_counter32()) |
54 | #else |
55 | #define SYSCALL_TIME() (cpu_hascounter() ? cpu_counter32() : 0u) |
56 | #endif |
57 | |
58 | #ifdef SYSCALL_TIMES_PROCTIMES |
59 | #define SYSCALL_TIME_UPDATE_PROC(l, fld, delta) \ |
60 | (l)->l_proc->p_##fld##ticks += (delta) |
61 | #else |
62 | #define SYSCALL_TIME_UPDATE_PROC(l, fld, delta) |
63 | #endif |
64 | |
65 | /* lwp creation */ |
66 | #define SYSCALL_TIME_LWP_INIT(l) do { \ |
67 | (l)->l_syscall_counter = &syscall_count_system; \ |
68 | SYSCALL_TIME_WAKEUP(l); \ |
69 | } while (0) |
70 | |
71 | /* System call entry hook */ |
72 | #define SYSCALL_TIME_SYS_ENTRY(l, table, code) do { \ |
73 | uint32_t now = SYSCALL_TIME(); \ |
74 | SYSCALL_TIME_UPDATE_PROC(l, u, elapsed = now - (l)->l_syscall_time); \ |
75 | (l)->l_syscall_counter = (table) + (code); \ |
76 | (l)->l_syscall_time = now; \ |
77 | } while (0) |
78 | |
79 | /* System call - process sleep */ |
80 | #define SYSCALL_TIME_SLEEP(l) do { \ |
81 | uint32_t now = SYSCALL_TIME(); \ |
82 | uint32_t elapsed = now - (l)->l_syscall_time; \ |
83 | (l)->l_syscall_time = now; \ |
84 | *(l)->l_syscall_counter += elapsed; \ |
85 | SYSCALL_TIME_UPDATE_PROC(l, s, elapsed); \ |
86 | } while (0) |
87 | |
88 | /* Process wakeup */ |
89 | #define SYSCALL_TIME_WAKEUP(l) \ |
90 | (l)->l_syscall_time = SYSCALL_TIME() |
91 | |
92 | /* System call exit */ |
93 | #define SYSCALL_TIME_SYS_EXIT(l) do { \ |
94 | uint32_t now = SYSCALL_TIME(); \ |
95 | uint32_t elapsed = now - (l)->l_syscall_time; \ |
96 | (l)->l_syscall_time = now; \ |
97 | *(l)->l_syscall_counter += elapsed; \ |
98 | (l)->l_syscall_counter = &syscall_count_user; \ |
99 | SYSCALL_TIME_UPDATE_PROC(l, s, elapsed); \ |
100 | } while (0) |
101 | |
102 | #ifdef _notyet |
103 | /* Interrupt entry hook */ |
104 | #define SYSCALL_TIME_ISR_ENTRY(l, old) do { \ |
105 | uint32_t now = SYSCALL_TIME(); \ |
106 | uint32_t elapsed = now - (l)->l_syscall_time; \ |
107 | (l)->l_syscall_time = now; \ |
108 | old = (l)->l_syscall_counter; \ |
109 | if ((l)->l_syscall_counter != &syscall_count_interrupt) \ |
110 | if ((l)->l_syscall_counter == &syscall_count_user) \ |
111 | SYSCALL_TIME_UPDATE_PROC(l, u, elapsed); \ |
112 | else { \ |
113 | *(l)->l_syscall_counter += elapsed; \ |
114 | SYSCALL_TIME_UPDATE_PROC(l, s, elapsed); \ |
115 | } \ |
116 | (l)->l_syscall_counter = &syscall_count_interrupt; \ |
117 | } \ |
118 | } while (0) |
119 | |
120 | /* Interrupt exit hook */ |
121 | #define SYSCALL_TIME_ISR_EXIT(l, saved) do { \ |
122 | uint32_t now = SYSCALL_TIME(); \ |
123 | SYSCALL_TIME_UPDATE_PROC(l, i, now - (l)->l_syscall_time); \ |
124 | (l)->l_syscall_time = now; \ |
125 | (l)->l_syscall_counter = saved; \ |
126 | } while (0) |
127 | #endif |
128 | |
129 | #endif |
130 | #endif |
131 | |
132 | #ifndef SYSCALL_TIME_SYS_ENTRY |
133 | #define SYSCALL_TIME_LWP_INIT(l) |
134 | #define SYSCALL_TIME_SYS_ENTRY(l,table,code) |
135 | #define SYSCALL_TIME_SLEEP(l) |
136 | #define SYSCALL_TIME_WAKEUP(l) |
137 | #define SYSCALL_TIME_SYS_EXIT(l) |
138 | #define SYSCALL_TIME_ISR_ENTRY(l,old) |
139 | #define SYSCALL_TIME_ISR_EXIT(l,saved) |
140 | #undef SYSCALL_TIMES |
141 | #endif |
142 | |
143 | #ifndef SYSCALL_COUNT |
144 | #define SYSCALL_COUNT(table, code) |
145 | #endif |
146 | |
147 | #endif /* !_SYS_SYCALL_STAT_H_ */ |
148 | |