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
42extern uint64_t syscall_counts[SYS_NSYSENT];
43extern 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>
49extern 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