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