|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: *
25: */
26: /*
27: * File: etap.c
28: */
29:
30: #include <cpus.h>
31: #include <kern/lock.h>
32: #include <kern/etap_macros.h>
33: #include <kern/misc_protos.h>
34: #include <kern/host.h>
35: #include <types.h>
36: #include <mach/kern_return.h>
37: #include <mach/port.h>
38: #include <vm/vm_map.h>
39: #include <vm/vm_kern.h> /* for kernel_map, ipc_kernel_map */
40: #if ETAP_MONITOR
41: #include <machine/machine_tables.h>
42: #include <mach/bootstrap_server.h>
43: #include <mach/clock.h>
44: #include <mach/clock_reply.h>
45: #include <mach/default_pager_object.h>
46: #include <device/device.h>
47: #include <device/device_reply.h>
48: #include <device/device_request.h>
49: #include <mach_debug/mach_debug.h>
50: /*#include <mach/mach_host.h>*/
51: #include <mach/mach_norma.h>
52: #include <mach/mach_port.h>
53: #include <mach/memory_object_default.h>
54: #include <mach/memory_object_user.h>
55: #include <mach/notify_server.h>
56: #include <mach/prof.h>
57: #include <machine/unix_map.h>
58: #endif
59: #if MACH_KDB
60: #include <ddb/db_output.h>
61: #include <ddb/db_sym.h>
62: #include <ddb/db_command.h>
63: #if 0 /* WHY?? */
64: #include <i386/ipl.h>
65: #endif
66: #endif
67:
68: /*
69: * Forwards
70: */
71:
72: kern_return_t
73: etap_get_info(host_t, int*, int*, vm_offset_t*, vm_offset_t*,
74: int*, int*, int*, int*);
75:
76: kern_return_t
77: etap_mon_reconfig(host_t, int);
78:
79: kern_return_t
80: etap_new_probe(host_t, vm_address_t, vm_size_t, boolean_t, vm_address_t);
81:
82: kern_return_t
83: etap_trace_thread(thread_act_t, boolean_t);
84:
85: void
86: etap_trace_reset(int);
87:
88: void
89: etap_interrupt_probe(int, int);
90:
91: void
92: etap_machcall_probe1(int);
93:
94: void
95: etap_machcall_probe2(void);
96:
97: void
98: etap_print(void);
99:
100:
101: #if ETAP
102:
103: #ifndef max
104: #define max(x,y) ((x > y) ? x : y)
105: #endif /* max */
106:
107: event_table_t
108: etap_event_table_find(etap_event_t);
109:
110: /* =======================
111: * ETAP Lock definitions
112: * =======================
113: */
114:
115: #if ETAP_LOCK_TRACE
116: #define etap_lock simple_lock_no_trace
117: #define etap_unlock simple_unlock_no_trace
118: #else /* ETAP_LOCK_TRACE */
119: #define etap_lock simple_lock
120: #define etap_unlock simple_unlock
121: #endif /* ETAP_LOCK_TRACE */
122:
123: #define event_table_lock() etap_lock(&event_table_lock)
124: #define event_table_unlock() etap_unlock(&event_table_lock)
125:
126: #define cumulative_buffer_lock(s) \
127: MACRO_BEGIN \
128: s = splhigh(); \
129: etap_lock(&cbuff_lock); \
130: MACRO_END
131:
132: #define cumulative_buffer_unlock(s) \
133: MACRO_BEGIN \
134: etap_unlock(&cbuff_lock); \
135: splx(s); \
136: MACRO_END
137:
138:
139: #if ETAP_LOCK_ACCUMULATE
140:
141: /* ========================================
142: * ETAP Cumulative lock trace definitions
143: * ========================================
144: */
145:
146: int cbuff_width = ETAP_CBUFF_WIDTH;
147:
148: /*
149: * Cumulative buffer declaration
150: *
151: * For both protection and mapping purposes, the cumulative
152: * buffer must be aligned on a page boundary. Since the cumulative
153: * buffer must be statically defined, page boundary alignment is not
154: * garenteed. Instead, the buffer is allocated with 2 extra pages.
155: * The cumulative buffer pointer will round up to the nearest page.
156: *
157: * This will garentee page boundary alignment.
158: */
159:
160: #define TWO_PAGES 16384 /* XXX does this apply ??*/
161: #define CBUFF_ALLOCATED_SIZE sizeof(struct cumulative_buffer)+TWO_PAGES
162:
163: decl_simple_lock_data (,cbuff_lock)
164: #if MACH_LDEBUG
165: simple_lock_t cbuff_locks;
166: #else
167: simple_lock_data_t cbuff_locks;
168: #endif
169: char cbuff_allocated [CBUFF_ALLOCATED_SIZE];
170: cumulative_buffer_t cbuff = {0};
171:
172: #endif /* ETAP_LOCK_ACCUMULATE */
173:
174: #if ETAP_MONITOR
175:
176: int mbuff_entries = ETAP_MBUFF_ENTRIES;
177:
178: /*
179: * Create an array of pointers to monitor buffers.
180: * The buffers themselves are allocated at run-time.
181: */
182:
183: struct monitor_buffer *mbuff[NCPUS];
184: #endif /* ETAP_MONITOR */
185:
186: /* ==========================
187: * Event table declarations
188: * ==========================
189: */
190:
191: decl_simple_lock_data(,event_table_lock)
192:
193: const struct event_table_entry event_table_init[] =
194: {
195:
196: /*-----------------------------------------------------------------------*
197: * ETAP EVENT TRACE STATUS TEXT NAME DYNAMIC *
198: *-----------------------------------------------------------------------*/
199:
200: #if ETAP_EVENT_MONITOR
201: {ETAP_P_USER_EVENT0 , ETAP_TRACE_OFF , "p_user_event0" , STATIC},
202: {ETAP_P_USER_EVENT1 , ETAP_TRACE_OFF , "p_user_event1" , STATIC},
203: {ETAP_P_USER_EVENT2 , ETAP_TRACE_OFF , "p_user_event2" , STATIC},
204: {ETAP_P_USER_EVENT3 , ETAP_TRACE_OFF , "p_user_event3" , STATIC},
205: {ETAP_P_USER_EVENT4 , ETAP_TRACE_OFF , "p_user_event4" , STATIC},
206: {ETAP_P_USER_EVENT5 , ETAP_TRACE_OFF , "p_user_event5" , STATIC},
207: {ETAP_P_USER_EVENT6 , ETAP_TRACE_OFF , "p_user_event6" , STATIC},
208: {ETAP_P_USER_EVENT7 , ETAP_TRACE_OFF , "p_user_event7" , STATIC},
209: {ETAP_P_USER_EVENT8 , ETAP_TRACE_OFF , "p_user_event8" , STATIC},
210: {ETAP_P_USER_EVENT9 , ETAP_TRACE_OFF , "p_user_event9" , STATIC},
211: {ETAP_P_USER_EVENT10 , ETAP_TRACE_OFF , "p_user_event10" , STATIC},
212: {ETAP_P_USER_EVENT11 , ETAP_TRACE_OFF , "p_user_event11" , STATIC},
213: {ETAP_P_USER_EVENT12 , ETAP_TRACE_OFF , "p_user_event12" , STATIC},
214: {ETAP_P_USER_EVENT13 , ETAP_TRACE_OFF , "p_user_event13" , STATIC},
215: {ETAP_P_USER_EVENT14 , ETAP_TRACE_OFF , "p_user_event14" , STATIC},
216: {ETAP_P_USER_EVENT15 , ETAP_TRACE_OFF , "p_user_event15" , STATIC},
217: {ETAP_P_USER_EVENT16 , ETAP_TRACE_OFF , "p_user_event16" , STATIC},
218: {ETAP_P_USER_EVENT17 , ETAP_TRACE_OFF , "p_user_event17" , STATIC},
219: {ETAP_P_USER_EVENT18 , ETAP_TRACE_OFF , "p_user_event18" , STATIC},
220: {ETAP_P_USER_EVENT19 , ETAP_TRACE_OFF , "p_user_event19" , STATIC},
221: {ETAP_P_USER_EVENT20 , ETAP_TRACE_OFF , "p_user_event20" , STATIC},
222: {ETAP_P_USER_EVENT21 , ETAP_TRACE_OFF , "p_user_event21" , STATIC},
223: {ETAP_P_USER_EVENT22 , ETAP_TRACE_OFF , "p_user_event22" , STATIC},
224: {ETAP_P_USER_EVENT23 , ETAP_TRACE_OFF , "p_user_event23" , STATIC},
225: {ETAP_P_USER_EVENT24 , ETAP_TRACE_OFF , "p_user_event24" , STATIC},
226: {ETAP_P_USER_EVENT25 , ETAP_TRACE_OFF , "p_user_event25" , STATIC},
227: {ETAP_P_USER_EVENT26 , ETAP_TRACE_OFF , "p_user_event26" , STATIC},
228: {ETAP_P_USER_EVENT27 , ETAP_TRACE_OFF , "p_user_event27" , STATIC},
229: {ETAP_P_USER_EVENT28 , ETAP_TRACE_OFF , "p_user_event28" , STATIC},
230: {ETAP_P_USER_EVENT29 , ETAP_TRACE_OFF , "p_user_event29" , STATIC},
231: {ETAP_P_USER_EVENT30 , ETAP_TRACE_OFF , "p_user_event30" , STATIC},
232: {ETAP_P_USER_EVENT31 , ETAP_TRACE_OFF , "p_user_event31" , STATIC},
233: {ETAP_P_SYSCALL_MACH , ETAP_TRACE_OFF , "p_syscall_mach" , STATIC},
234: {ETAP_P_SYSCALL_UNIX , ETAP_TRACE_OFF , "p_syscall_unix" , STATIC},
235: {ETAP_P_THREAD_LIFE , ETAP_TRACE_OFF , "p_thread_life" , STATIC},
236: {ETAP_P_THREAD_CTX , ETAP_TRACE_OFF , "p_thread_ctx" , STATIC},
237: {ETAP_P_RPC , ETAP_TRACE_OFF , "p_rpc" , STATIC},
238: {ETAP_P_INTERRUPT , ETAP_TRACE_OFF , "p_interrupt" , STATIC},
239: {ETAP_P_ACT_ABORT , ETAP_TRACE_OFF , "p_act_abort" , STATIC},
240: {ETAP_P_PRIORITY , ETAP_TRACE_OFF , "p_priority" , STATIC},
241: {ETAP_P_EXCEPTION , ETAP_TRACE_OFF , "p_exception" , STATIC},
242: {ETAP_P_DEPRESSION , ETAP_TRACE_OFF , "p_depression" , STATIC},
243: {ETAP_P_MISC , ETAP_TRACE_OFF , "p_misc" , STATIC},
244: {ETAP_P_DETAP , ETAP_TRACE_OFF , "p_detap" , STATIC},
245: #endif /* ETAP_EVENT_MONITOR */
246:
247: #if ETAP_LOCK_TRACE
248: {ETAP_VM_BUCKET , ETAP_TRACE_OFF , "vm_bucket" , STATIC},/**/
249: {ETAP_VM_HIMEM , ETAP_TRACE_OFF , "vm_himem" , STATIC},
250: {ETAP_VM_MAP , ETAP_TRACE_OFF , "vm_map" , 1},
251: {ETAP_VM_MAP_I , ETAP_TRACE_OFF , "vm_map_i" , 2},
252: {ETAP_VM_MEMMAN , ETAP_TRACE_OFF , "vm_memman" , STATIC},/**/
253: {ETAP_VM_MSYNC , ETAP_TRACE_OFF , "vm_msync" , 3},
254: {ETAP_VM_OBJ , ETAP_TRACE_OFF , "vm_obj" , 4},
255: {ETAP_VM_OBJ_CACHE , ETAP_TRACE_OFF , "vm_obj_cache" , 5},
256: {ETAP_VM_PAGE_ALLOC , ETAP_TRACE_OFF , "vm_page_alloc" , STATIC},/**/
257: {ETAP_VM_PAGEOUT , ETAP_TRACE_OFF , "vm_pageout" , STATIC},
258: {ETAP_VM_PAGEQ , ETAP_TRACE_OFF , "vm_pageq" , STATIC},
259: {ETAP_VM_PAGEQ_FREE , ETAP_TRACE_OFF , "vm_pageq_free" , STATIC},
260: {ETAP_VM_PMAP , ETAP_TRACE_OFF , "vm_pmap" , 6},
261: {ETAP_VM_PMAP_CACHE , ETAP_TRACE_OFF , "vm_pmap_cache" , STATIC},
262: {ETAP_VM_PMAP_FREE , ETAP_TRACE_OFF , "vm_pmap_free" , STATIC},
263: {ETAP_VM_PMAP_KERNEL , ETAP_TRACE_OFF , "vm_pmap_kern" , STATIC},
264: {ETAP_VM_PMAP_SYS , ETAP_TRACE_OFF , "vm_pmap_sys" , 7},
265: {ETAP_VM_PMAP_SYS_I , ETAP_TRACE_OFF , "vm_pmap_sys_i" , 8},
266: {ETAP_VM_PMAP_UPDATE , ETAP_TRACE_OFF , "vm_pmap_update" , STATIC},
267: {ETAP_VM_PREPPIN , ETAP_TRACE_OFF , "vm_preppin" , STATIC},
268: {ETAP_VM_RESULT , ETAP_TRACE_OFF , "vm_result" , 9},
269: {ETAP_VM_TEST , ETAP_TRACE_OFF , "vm_tes" , STATIC},/**/
270: {ETAP_VM_PMAP_PHYSENTRIES, ETAP_TRACE_OFF , "vm_pmap_physentries", STATIC},
271: {ETAP_VM_PMAP_SID , ETAP_TRACE_OFF , "vm_pmap_sid" , STATIC},
272: {ETAP_VM_PMAP_PTE , ETAP_TRACE_OFF , "vm_pmap_pte" , STATIC},
273: {ETAP_VM_PMAP_PTE_OVFLW , ETAP_TRACE_OFF , "vm_pmap_pte_ovflw", STATIC},
274: {ETAP_VM_PMAP_TLB , ETAP_TRACE_OFF , "vm_pmap_tlb" , STATIC},
275:
276: {ETAP_IPC_IHGB , ETAP_TRACE_OFF , "ipc_ihgb" , 10},/**/
277: {ETAP_IPC_IS , ETAP_TRACE_OFF , "ipc_is" , 11},/**/
278: {ETAP_IPC_IS_REF , ETAP_TRACE_OFF , "ipc_is_ref" , 12},/**/
279: {ETAP_IPC_MQUEUE , ETAP_TRACE_OFF , "ipc_mqueue" , STATIC},/**/
280: {ETAP_IPC_OBJECT , ETAP_TRACE_OFF , "ipc_object" , STATIC},/**/
281: {ETAP_IPC_PORT_MULT , ETAP_TRACE_OFF , "ipc_port_mult" , 13},/**/
282: {ETAP_IPC_PORT_TIME , ETAP_TRACE_OFF , "ipc_port_time" , 14},/**/
283: {ETAP_IPC_RPC , ETAP_TRACE_OFF , "ipc_rpc" , 15},/**/
284: {ETAP_IPC_PORT_ALLOCQ , ETAP_TRACE_OFF , "ipc_port_allocq" , STATIC},/**/
285:
286: {ETAP_IO_AHA , ETAP_TRACE_OFF , "io_aha" , STATIC},
287: {ETAP_IO_CHIP , ETAP_TRACE_OFF , "io_chip" , STATIC},
288: {ETAP_IO_DEV , ETAP_TRACE_OFF , "io_dev" , 16},/**/
289: {ETAP_IO_DEV_NUM , ETAP_TRACE_OFF , "io_dev_num" , STATIC},
290: {ETAP_IO_DEV_PAGEH , ETAP_TRACE_OFF , "io_dev_pageh" , STATIC},/**/
291: {ETAP_IO_DEV_PAGER , ETAP_TRACE_OFF , "io_dev_pager" , STATIC},/**/
292: {ETAP_IO_DEV_PORT , ETAP_TRACE_OFF , "io_dev_port" , STATIC},/**/
293: {ETAP_IO_DEV_REF , ETAP_TRACE_OFF , "io_dev_new" , 17},/**/
294: {ETAP_IO_DEVINS , ETAP_TRACE_OFF , "io_devins" , STATIC},
295: {ETAP_IO_DONE_LIST , ETAP_TRACE_OFF , "io_done_list" , STATIC},
296: {ETAP_IO_DONE_Q , ETAP_TRACE_OFF , "io_doneq" , 18},
297: {ETAP_IO_DONE_REF , ETAP_TRACE_OFF , "io_done_ref" , 19},
298: {ETAP_IO_EAHA , ETAP_TRACE_OFF , "io_eaha" , STATIC},
299: {ETAP_IO_HD_PROBE , ETAP_TRACE_OFF , "io_hd_probe" , STATIC},
300: {ETAP_IO_IOPB , ETAP_TRACE_OFF , "io_iopb" , STATIC},
301: {ETAP_IO_KDQ , ETAP_TRACE_OFF , "io_kdq" , STATIC},
302: {ETAP_IO_KDTTY , ETAP_TRACE_OFF , "io_kdtty" , STATIC},
303: {ETAP_IO_REQ , ETAP_TRACE_OFF , "io_req" , 20},
304: {ETAP_IO_TARGET , ETAP_TRACE_OFF , "io_target" , STATIC},
305: {ETAP_IO_TTY , ETAP_TRACE_OFF , "io_tty" , STATIC},
306: {ETAP_IO_IOP_LOCK , ETAP_TRACE_OFF , "io_iop" , STATIC},/**/
307: {ETAP_IO_DEV_NAME , ETAP_TRACE_OFF , "io_dev_name" , STATIC},/**/
308: {ETAP_IO_CDLI , ETAP_TRACE_OFF , "io_cdli" , STATIC},/**/
309: {ETAP_IO_HIPPI_FILTER , ETAP_TRACE_OFF , "io_hippi_filter" , STATIC},/**/
310: {ETAP_IO_HIPPI_SRC , ETAP_TRACE_OFF , "io_hippi_src" , STATIC},/**/
311: {ETAP_IO_HIPPI_DST , ETAP_TRACE_OFF , "io_hippi_dst" , STATIC},/**/
312: {ETAP_IO_HIPPI_PKT , ETAP_TRACE_OFF , "io_hippi_pkt" , STATIC},/**/
313: {ETAP_IO_NOTIFY , ETAP_TRACE_OFF , "io_notify" , STATIC},/**/
314: {ETAP_IO_DATADEV , ETAP_TRACE_OFF , "io_data_device" , STATIC},/**/
315: {ETAP_IO_OPEN , ETAP_TRACE_OFF , "io_open" , STATIC},
316: {ETAP_IO_OPEN_I , ETAP_TRACE_OFF , "io_open_i" , STATIC},
317:
318: {ETAP_THREAD_ACT , ETAP_TRACE_OFF , "th_act" , 21},
319: {ETAP_THREAD_ACTION , ETAP_TRACE_OFF , "th_action" , STATIC},
320: {ETAP_THREAD_LOCK , ETAP_TRACE_OFF , "th_lock" , 22},
321: {ETAP_THREAD_LOCK_SET , ETAP_TRACE_OFF , "th_lock_set" , 23},
322: {ETAP_THREAD_NEW , ETAP_TRACE_OFF , "th_new" , 24},
323: {ETAP_THREAD_PSET , ETAP_TRACE_OFF , "th_pset" , STATIC},/**/
324: {ETAP_THREAD_PSET_ALL , ETAP_TRACE_OFF , "th_pset_all" , STATIC},
325: {ETAP_THREAD_PSET_RUNQ , ETAP_TRACE_OFF , "th_pset_runq" , STATIC},
326: {ETAP_THREAD_PSET_IDLE , ETAP_TRACE_OFF , "th_pset_idle" , STATIC},
327: {ETAP_THREAD_PSET_QUANT , ETAP_TRACE_OFF , "th_pset_quant" , STATIC},
328: {ETAP_THREAD_PROC , ETAP_TRACE_OFF , "th_proc" , STATIC},
329: {ETAP_THREAD_PROC_RUNQ , ETAP_TRACE_OFF , "th_proc_runq" , STATIC},
330: {ETAP_THREAD_REAPER , ETAP_TRACE_OFF , "th_reaper" , STATIC},
331: {ETAP_THREAD_RPC , ETAP_TRACE_OFF , "th_rpc" , 25},
332: {ETAP_THREAD_SEMA , ETAP_TRACE_OFF , "th_sema" , 26},
333: {ETAP_THREAD_STACK , ETAP_TRACE_OFF , "th_stack" , STATIC},
334: {ETAP_THREAD_STACK_USAGE , ETAP_TRACE_OFF , "th_stack_usage" , STATIC},
335: {ETAP_THREAD_TASK_NEW , ETAP_TRACE_OFF , "th_task_new" , 27},
336: {ETAP_THREAD_TASK_ITK , ETAP_TRACE_OFF , "th_task_itk" , 28},
337: {ETAP_THREAD_ULOCK , ETAP_TRACE_OFF , "th_ulock" , 29},
338: {ETAP_THREAD_WAIT , ETAP_TRACE_OFF , "th_wait" , STATIC},
339: {ETAP_THREAD_WAKE , ETAP_TRACE_OFF , "th_wake" , 30},
340: {ETAP_THREAD_ACT_LIST , ETAP_TRACE_OFF , "th_act_list" , 31},
341: {ETAP_THREAD_TASK_SWAP , ETAP_TRACE_OFF , "th_task_swap" , 32},
342: {ETAP_THREAD_TASK_SWAPOUT, ETAP_TRACE_OFF , "th_task_swapout" , 33},
343: {ETAP_THREAD_SWAPPER , ETAP_TRACE_OFF , "th_swapper" , STATIC},
344:
345: {ETAP_NET_IFQ , ETAP_TRACE_OFF , "net_ifq" , STATIC},
346: {ETAP_NET_KMSG , ETAP_TRACE_OFF , "net_kmsg" , STATIC},
347: {ETAP_NET_MBUF , ETAP_TRACE_OFF , "net_mbuf" , STATIC},/**/
348: {ETAP_NET_POOL , ETAP_TRACE_OFF , "net_pool" , STATIC},
349: {ETAP_NET_Q , ETAP_TRACE_OFF , "net_q" , STATIC},
350: {ETAP_NET_QFREE , ETAP_TRACE_OFF , "net_qfree" , STATIC},
351: {ETAP_NET_RCV , ETAP_TRACE_OFF , "net_rcv" , STATIC},
352: {ETAP_NET_RCV_PLIST , ETAP_TRACE_OFF , "net_rcv_plist" , STATIC},/**/
353: {ETAP_NET_THREAD , ETAP_TRACE_OFF , "net_thread" , STATIC},
354:
355: {ETAP_NORMA_XMM , ETAP_TRACE_OFF , "norma_xmm" , STATIC},
356: {ETAP_NORMA_XMMOBJ , ETAP_TRACE_OFF , "norma_xmmobj" , STATIC},
357: {ETAP_NORMA_XMMCACHE , ETAP_TRACE_OFF , "norma_xmmcache" , STATIC},
358: {ETAP_NORMA_MP , ETAP_TRACE_OFF , "norma_mp" , STATIC},
359: {ETAP_NORMA_VOR , ETAP_TRACE_OFF , "norma_vor" , STATIC},/**/
360: {ETAP_NORMA_TASK , ETAP_TRACE_OFF , "norma_task" , 38},/**/
361:
362: {ETAP_DIPC_CLEANUP , ETAP_TRACE_OFF , "dipc_cleanup" , STATIC},/**/
363: {ETAP_DIPC_MSG_PROG , ETAP_TRACE_OFF , "dipc_msgp_prog" , STATIC},/**/
364: {ETAP_DIPC_PREP_QUEUE , ETAP_TRACE_OFF , "dipc_prep_queue" , STATIC},/**/
365: {ETAP_DIPC_PREP_FILL , ETAP_TRACE_OFF , "dipc_prep_fill" , STATIC},/**/
366: {ETAP_DIPC_MIGRATE , ETAP_TRACE_OFF , "dipc_migrate" , STATIC},/**/
367: {ETAP_DIPC_DELIVER , ETAP_TRACE_OFF , "dipc_deliver" , STATIC},/**/
368: {ETAP_DIPC_RECV_SYNC , ETAP_TRACE_OFF , "dipc_recv_sync" , STATIC},/**/
369: {ETAP_DIPC_RPC , ETAP_TRACE_OFF , "dipc_rpc" , STATIC},/**/
370: {ETAP_DIPC_MSG_REQ , ETAP_TRACE_OFF , "dipc_msg_req" , STATIC},/**/
371: {ETAP_DIPC_MSG_ORDER , ETAP_TRACE_OFF , "dipc_msg_order" , STATIC},/**/
372: {ETAP_DIPC_MSG_PREPQ , ETAP_TRACE_OFF , "dipc_msg_prepq" , STATIC},/**/
373: {ETAP_DIPC_MSG_FREE , ETAP_TRACE_OFF , "dipc_msg_free" , STATIC},/**/
374: {ETAP_DIPC_KMSG_AST , ETAP_TRACE_OFF , "dipc_kmsg_ast" , STATIC},/**/
375: {ETAP_DIPC_TEST_LOCK , ETAP_TRACE_OFF , "dipc_test_lock" , STATIC},/**/
376: {ETAP_DIPC_SPINLOCK , ETAP_TRACE_OFF , "dipc_spinlock" , STATIC},/**/
377: {ETAP_DIPC_TRACE , ETAP_TRACE_OFF , "dipc_trace" , STATIC},/**/
378: {ETAP_DIPC_REQ_CALLBACK , ETAP_TRACE_OFF , "dipc_req_clbck" , STATIC},/**/
379: {ETAP_DIPC_PORT_NAME , ETAP_TRACE_OFF , "dipc_port_name" , STATIC},/**/
380: {ETAP_DIPC_RESTART_PORT , ETAP_TRACE_OFF , "dipc_restart_port", STATIC},/**/
381: {ETAP_DIPC_ZERO_PAGE , ETAP_TRACE_OFF , "dipc_zero_page" , STATIC},/**/
382: {ETAP_DIPC_BLOCKED_NODE , ETAP_TRACE_OFF , "dipc_blocked_node", STATIC},/**/
383: {ETAP_DIPC_TIMER , ETAP_TRACE_OFF , "dipc_timer" , STATIC},/**/
384: {ETAP_DIPC_SPECIAL_PORT , ETAP_TRACE_OFF , "dipc_special_port", STATIC},/**/
385:
386: {ETAP_KKT_TEST_WORK , ETAP_TRACE_OFF , "kkt_test_work" , STATIC},/**/
387: {ETAP_KKT_TEST_MP , ETAP_TRACE_OFF , "kkt_work_mp" , STATIC},/**/
388: {ETAP_KKT_NODE , ETAP_TRACE_OFF , "kkt_node" , STATIC},/**/
389: {ETAP_KKT_CHANNEL_LIST , ETAP_TRACE_OFF , "kkt_channel_list" , STATIC},/**/
390: {ETAP_KKT_CHANNEL , ETAP_TRACE_OFF , "kkt_channel" , STATIC},/**/
391: {ETAP_KKT_HANDLE , ETAP_TRACE_OFF , "kkt_handle" , STATIC},/**/
392: {ETAP_KKT_MAP , ETAP_TRACE_OFF , "kkt_map" , STATIC},/**/
393: {ETAP_KKT_RESOURCE , ETAP_TRACE_OFF , "kkt_resource" , STATIC},/**/
394:
395: {ETAP_XKERNEL_MASTER , ETAP_TRACE_OFF , "xkernel_master" , STATIC},/**/
396: {ETAP_XKERNEL_EVENT , ETAP_TRACE_OFF , "xkernel_event" , STATIC},/**/
397: {ETAP_XKERNEL_ETHINPUT , ETAP_TRACE_OFF , "xkernel_input" , STATIC},/**/
398:
399: {ETAP_MISC_AST , ETAP_TRACE_OFF , "m_ast" , STATIC},
400: {ETAP_MISC_CLOCK , ETAP_TRACE_OFF , "m_clock" , STATIC},
401: {ETAP_MISC_EMULATE , ETAP_TRACE_OFF , "m_emulate" , 34},
402: {ETAP_MISC_EVENT , ETAP_TRACE_OFF , "m_event" , STATIC},
403: {ETAP_MISC_KDB , ETAP_TRACE_OFF , "m_kdb" , STATIC},
404: {ETAP_MISC_PCB , ETAP_TRACE_OFF , "m_pcb" , 35},
405: {ETAP_MISC_PRINTF , ETAP_TRACE_OFF , "m_printf" , STATIC},
406: {ETAP_MISC_Q , ETAP_TRACE_OFF , "m_q" , STATIC},
407: {ETAP_MISC_RPC_SUBSYS , ETAP_TRACE_OFF , "m_rpc_sub" , 36},
408: {ETAP_MISC_RT_CLOCK , ETAP_TRACE_OFF , "m_rt_clock" , STATIC},
409: {ETAP_MISC_SD_POOL , ETAP_TRACE_OFF , "m_sd_pool" , STATIC},
410: {ETAP_MISC_TIMER , ETAP_TRACE_OFF , "m_timer" , STATIC},
411: {ETAP_MISC_UTIME , ETAP_TRACE_OFF , "m_utime" , STATIC},
412: {ETAP_MISC_XPR , ETAP_TRACE_OFF , "m_xpr" , STATIC},
413: {ETAP_MISC_ZONE , ETAP_TRACE_OFF , "m_zone" , 37},
414: {ETAP_MISC_ZONE_ALL , ETAP_TRACE_OFF , "m_zone_all" , STATIC},
415: {ETAP_MISC_ZONE_GET , ETAP_TRACE_OFF , "m_zone_get" , STATIC},
416: {ETAP_MISC_ZONE_PTABLE , ETAP_TRACE_OFF , "m_zone_ptable" , STATIC},/**/
417: {ETAP_MISC_LEDGER , ETAP_TRACE_OFF , "m_ledger" , STATIC},/**/
418: {ETAP_MISC_SCSIT_TGT , ETAP_TRACE_OFF , "m_scsit_tgt_lock" , STATIC},/**/
419: {ETAP_MISC_SCSIT_SELF , ETAP_TRACE_OFF , "m_scsit_self_lock", STATIC},/**/
420: {ETAP_MISC_SPL , ETAP_TRACE_OFF , "m_spl_lock" , STATIC},/**/
421: {ETAP_MISC_MASTER , ETAP_TRACE_OFF , "m_master" , STATIC},/**/
422: {ETAP_MISC_FLOAT , ETAP_TRACE_OFF , "m_float" , STATIC},/**/
423: {ETAP_MISC_GROUP , ETAP_TRACE_OFF , "m_group" , STATIC},/**/
424: {ETAP_MISC_FLIPC , ETAP_TRACE_OFF , "m_flipc" , STATIC},/**/
425: {ETAP_MISC_MP_IO , ETAP_TRACE_OFF , "m_mp_io" , STATIC},/**/
426: {ETAP_MISC_KERNEL_TEST , ETAP_TRACE_OFF , "m_kernel_test" , STATIC},/**/
427:
428: {ETAP_NO_TRACE , ETAP_TRACE_OFF , "NEVER_TRACE" , STATIC},
429: #endif /* ETAP_LOCK_TRACE */
430: };
431:
432: /*
433: * Variable initially pointing to the event table, then to its mappable
434: * copy. The cast is needed to discard the `const' qualifier; without it
435: * gcc issues a warning.
436: */
437: event_table_t event_table = (event_table_t) event_table_init;
438:
439: /*
440: * Linked list of pointers into event_table_init[] so they can be switched
441: * into the mappable copy when it is made.
442: */
443: struct event_table_chain *event_table_chain;
444:
445: /*
446: * max number of event types in the event table
447: */
448:
449: int event_table_max = sizeof(event_table_init)/sizeof(struct event_table_entry);
450:
451: const struct subs_table_entry subs_table_init[] =
452: {
453: /*------------------------------------------*
454: * ETAP SUBSYSTEM TEXT NAME *
455: *------------------------------------------*/
456:
457: #if ETAP_EVENT_MONITOR
458: {ETAP_SUBS_PROBE , "event_probes" },
459: #endif /* ETAP_EVENT_MONITOR */
460:
461: #if ETAP_LOCK_TRACE
462: {ETAP_SUBS_LOCK_DIPC , "lock_dipc" },
463: {ETAP_SUBS_LOCK_IO , "lock_io" },
464: {ETAP_SUBS_LOCK_IPC , "lock_ipc" },
465: {ETAP_SUBS_LOCK_KKT , "lock_kkt" },
466: {ETAP_SUBS_LOCK_MISC , "lock_misc" },
467: {ETAP_SUBS_LOCK_NET , "lock_net" },
468: {ETAP_SUBS_LOCK_NORMA , "lock_norma" },
469: {ETAP_SUBS_LOCK_THREAD , "lock_thread" },
470: {ETAP_SUBS_LOCK_VM , "lock_vm" },
471: {ETAP_SUBS_LOCK_XKERNEL , "lock_xkernel" },
472: #endif /* ETAP_LOCK_TRACE */
473: };
474:
475: /*
476: * Variable initially pointing to the subsystem table, then to its mappable
477: * copy.
478: */
479: subs_table_t subs_table = (subs_table_t) subs_table_init;
480:
481: /*
482: * max number of subsystem types in the subsystem table
483: */
484:
485: int subs_table_max = sizeof(subs_table_init)/sizeof(struct subs_table_entry);
486:
487: #if ETAP_MONITOR
488: #define MAX_NAME_SIZE 35
489:
490: #define SYS_TABLE_MACH_TRAP 0
491: #define SYS_TABLE_MACH_MESSAGE 1
492: #define SYS_TABLE_UNIX_SYSCALL 2
493: #define SYS_TABLE_INTERRUPT 3
494: #define SYS_TABLE_EXCEPTION 4
495:
496:
497: extern char *system_table_lookup (unsigned int table,
498: unsigned int number);
499:
500:
501: char *mach_trap_names[] = {
502: /* 0 */ "undefined",
503: /* 1 */ NULL,
504: /* 2 */ NULL,
505: /* 3 */ NULL,
506: /* 4 */ NULL,
507: /* 5 */ NULL,
508: /* 6 */ NULL,
509: /* 7 */ NULL,
510: /* 8 */ NULL,
511: /* 9 */ NULL,
512: /* 10 */ NULL,
513: /* 11 */ NULL,
514: /* 12 */ NULL,
515: /* 13 */ NULL,
516: /* 14 */ NULL,
517: /* 15 */ NULL,
518: /* 16 */ NULL,
519: /* 17 */ NULL,
520: /* 18 */ NULL,
521: /* 19 */ NULL,
522: /* 20 */ NULL,
523: /* 21 */ NULL,
524: /* 22 */ NULL,
525: /* 23 */ NULL,
526: /* 24 */ NULL,
527: /* 25 */ NULL,
528: /* 26 */ "mach_reply_port",
529: /* 27 */ "mach_thread_self",
530: /* 28 */ "mach_task_self",
531: /* 29 */ "mach_host_self",
532: /* 30 */ "vm_read_overwrite",
533: /* 31 */ "vm_write",
534: /* 32 */ "mach_msg_overwrite_trap",
535: /* 33 */ NULL,
536: /* 34 */ NULL,
537: #ifdef i386
538: /* 35 */ "mach_rpc_trap",
539: /* 36 */ "mach_rpc_return_trap",
540: #else
541: /* 35 */ NULL,
542: /* 36 */ NULL,
543: #endif /* i386 */
544: /* 37 */ NULL,
545: /* 38 */ NULL,
546: /* 39 */ NULL,
547: /* 40 */ NULL,
548: /* 41 */ "init_process",
549: /* 42 */ NULL,
550: /* 43 */ "map_fd",
551: /* 44 */ NULL,
552: /* 45 */ NULL,
553: /* 46 */ NULL,
554: /* 47 */ NULL,
555: /* 48 */ NULL,
556: /* 49 */ NULL,
557: /* 50 */ NULL,
558: /* 51 */ NULL,
559: /* 52 */ NULL,
560: /* 53 */ NULL,
561: /* 54 */ NULL,
562: /* 55 */ NULL,
563: /* 56 */ NULL,
564: /* 57 */ NULL,
565: /* 58 */ NULL,
566: /* 59 */ "swtch_pri",
567: /* 60 */ "swtch",
568: /* 61 */ "thread_switch",
569: /* 62 */ "clock_sleep_trap",
570: /* 63 */ NULL,
571: /* 64 */ NULL,
572: /* 65 */ NULL,
573: /* 66 */ NULL,
574: /* 67 */ NULL,
575: /* 68 */ NULL,
576: /* 69 */ NULL,
577: /* 70 */ NULL,
578: /* 71 */ NULL,
579: /* 72 */ NULL,
580: /* 73 */ NULL,
581: /* 74 */ NULL,
582: /* 75 */ NULL,
583: /* 76 */ NULL,
584: /* 77 */ NULL,
585: /* 78 */ NULL,
586: /* 79 */ NULL,
587: /* 80 */ NULL,
588: /* 81 */ NULL,
589: /* 82 */ NULL,
590: /* 83 */ NULL,
591: /* 84 */ NULL,
592: /* 85 */ NULL,
593: /* 86 */ NULL,
594: /* 87 */ NULL,
595: /* 88 */ NULL,
596: /* 89 */ NULL,
597: /* 90 */ NULL,
598: /* 91 */ NULL,
599: /* 92 */ NULL,
600: /* 93 */ NULL,
601: /* 94 */ NULL,
602: /* 95 */ NULL,
603: /* 96 */ NULL,
604: /* 97 */ NULL,
605: /* 98 */ NULL,
606: /* 99 */ NULL,
607: /* 100 */ NULL,
608: /* 101 */ NULL,
609: /* 102 */ NULL,
610: /* 103 */ NULL,
611: /* 104 */ NULL,
612: /* 105 */ NULL,
613: /* 106 */ NULL,
614: /* 107 */ NULL,
615: /* 108 */ NULL,
616: /* 109 */ NULL,
617: };
618: #define N_MACH_TRAP_NAMES (sizeof mach_trap_names / sizeof mach_trap_names[0])
619: #define mach_trap_name(nu) \
620: (((nu) < N_MACH_TRAP_NAMES) ? mach_trap_names[nu] : NULL)
621:
622: struct table_entry {
623: char name[MAX_NAME_SIZE];
624: u_int number;
625: };
626:
627: /*
628: * Mach message table
629: *
630: * Note: Most mach system calls are actually implemented as messages.
631: */
632: struct table_entry mach_message_table[] = {
633: subsystem_to_name_map_bootstrap,
634: subsystem_to_name_map_clock,
635: subsystem_to_name_map_clock_reply,
636: subsystem_to_name_map_default_pager_object,
637: subsystem_to_name_map_device,
638: subsystem_to_name_map_device_reply,
639: subsystem_to_name_map_device_request,
640: subsystem_to_name_map_exc,
641: /* subsystem_to_name_map_mach,*/
642: subsystem_to_name_map_mach_debug,
643: /* subsystem_to_name_map_mach_host,*/
644: subsystem_to_name_map_mach_norma,
645: subsystem_to_name_map_mach_port,
646: subsystem_to_name_map_memory_object,
647: subsystem_to_name_map_memory_object_default,
648: subsystem_to_name_map_notify,
649: subsystem_to_name_map_prof,
650: subsystem_to_name_map_sync
651: };
652:
653: int mach_message_table_entries = sizeof(mach_message_table) /
654: sizeof(struct table_entry);
655:
656:
657: #endif
658:
659: /*
660: * ================================
661: * Initialization routines for ETAP
662: * ================================
663: */
664:
665: /*
666: * ROUTINE: etap_init_phase1 [internal]
667: *
668: * FUNCTION: Event trace instrumentation initialization phase
669: * one of two. The static phase. The cumulative buffer
670: * is initialized.
671: *
672: * NOTES: The cumulative buffer is statically allocated and
673: * must be initialized before the first simple_lock_init()
674: * or lock_init() call is made.
675: *
676: * The first lock init call is made before dynamic allocation
677: * is available. Hence, phase one is executed before dynamic
678: * memory allocation is available.
679: *
680: */
681:
682: void
683: etap_init_phase1(void)
684: {
685: #if ETAP_LOCK_ACCUMULATE || MACH_ASSERT
686: int x;
687: #if MACH_ASSERT
688: boolean_t out_of_order;
689: #endif /* MACH_ASSERT */
690: #endif /* ETAP_LOCK_ACCUMULATE || MACH_ASSERT */
691:
692: #if ETAP_LOCK_ACCUMULATE
693: /*
694: * Initialize Cumulative Buffer
695: *
696: * Note: The cumulative buffer is statically allocated.
697: * This static allocation is necessary since most
698: * of the lock_init calls are made before dynamic
699: * allocation routines are available.
700: */
701:
702: /*
703: * Align cumulative buffer pointer to a page boundary
704: * (so it can be maped).
705: */
706:
707: bzero(&cbuff_allocated[0], CBUFF_ALLOCATED_SIZE);
708: cbuff = (cumulative_buffer_t) round_page(&cbuff_allocated);
709:
710: simple_lock_init(&cbuff_lock, ETAP_NO_TRACE);
711:
712: /*
713: * Set the starting point for cumulative buffer entry
714: * reservations.
715: *
716: * This value must leave enough head room in the
717: * cumulative buffer to contain all dynamic events.
718: */
719:
720: for (x=0; x < event_table_max; x++)
721: if (event_table[x].dynamic > cbuff->static_start)
722: cbuff->static_start = event_table[x].dynamic;
723:
724: cbuff->next = cbuff->static_start;
725: #endif /* ETAP_LOCK_ACCUMULATE */
726:
727: /*
728: * Initialize the event table lock
729: */
730:
731: simple_lock_init(&event_table_lock, ETAP_NO_TRACE);
732:
733: #if MACH_ASSERT
734: /*
735: * Check that events are in numerical order so we can do a binary
736: * search on them. Even better would be to make event numbers be
737: * simple contiguous indexes into event_table[], but that would
738: * break the coding of subsystems in the event number.
739: */
740: out_of_order = FALSE;
741: for (x = 1; x < event_table_max; x++) {
742: if (event_table[x - 1].event > event_table[x].event) {
743: printf("events out of order: %s > %s\n",
744: event_table[x - 1].name, event_table[x].name);
745: out_of_order = TRUE;
746: }
747: }
748: if (out_of_order)
749: panic("etap_init_phase1");
750: #endif /* MACH_ASSERT */
751: }
752:
753:
754: /*
755: * ROUTINE: etap_init_phase2 [internal]
756: *
757: * FUNCTION: Event trace instrumentation initialization phase
758: * two of two. The dynamic phase. The monitored buffers
759: * are dynamically allocated and initialized. Cumulative
760: * dynamic entry locks are allocated and initialized. The
761: * start_data_pool is initialized.
762: *
763: * NOTES: Phase two is executed once dynamic memory allocation
764: * is available.
765: *
766: */
767:
768: void
769: etap_init_phase2(void)
770: {
771: int size;
772: int x;
773: int ret;
774: vm_offset_t table_copy;
775: struct event_table_chain *chainp;
776:
777: /*
778: * Make mappable copies of the event_table and the subs_table.
779: * These tables were originally mapped as they appear in the
780: * kernel image, but that meant that other kernel variables could
781: * end up being mapped with them, which is ugly. It also didn't
782: * work on the HP/PA, where pages with physical address == virtual
783: * do not have real pmap entries allocated and therefore can't be
784: * mapped elsewhere.
785: */
786: size = sizeof event_table_init + sizeof subs_table_init;
787: ret = kmem_alloc(kernel_map, &table_copy, size);
788: if (ret != KERN_SUCCESS)
789: panic("ETAP: error allocating table copies");
790: event_table = (event_table_t) table_copy;
791: subs_table = (subs_table_t) (table_copy + sizeof event_table_init);
792: bcopy((char *) event_table_init, (char *) event_table,
793: sizeof event_table_init);
794: bcopy((char *) subs_table_init, (char *) subs_table,
795: sizeof subs_table_init);
796:
797: /* Switch pointers from the old event_table to the new. */
798: for (chainp = event_table_chain; chainp != NULL;
799: chainp = chainp->event_table_link) {
800: x = chainp->event_tablep - event_table_init;
801: assert(x < event_table_max);
802: chainp->event_tablep = event_table + x;
803: }
804:
805: #if ETAP_LOCK_ACCUMULATE
806:
807: /*
808: * Because several dynamic locks can point to a single
809: * cumulative buffer entry, dynamic lock writes to the
810: * entry are synchronized.
811: *
812: * The spin locks are allocated here.
813: *
814: */
815: #if MACH_LDEBUG
816: size = sizeof(simple_lock_t) * cbuff->static_start;
817: #else
818: /*
819: * Note: These locks are different from traditional spin locks.
820: * They are of type int instead of type simple_lock_t.
821: * We can reduce lock size this way, since no tracing will
822: * EVER be performed on these locks.
823: */
824: size = sizeof(simple_lock_data_t) * cbuff->static_start;
825: #endif
826:
827: ret = kmem_alloc(kernel_map, (vm_offset_t *) &cbuff_locks, size);
828:
829: if (ret != KERN_SUCCESS)
830: panic("ETAP: error allocating cumulative write locks");
831:
832: #if MACH_LDEBUG
833: for(x = 0; x < cbuff->static_start; ++x) {
834: simple_lock_init(&cbuff_locks[x], ETAP_NO_TRACE);
835: }
836: #else
837: bzero((const char *) cbuff_locks, size);
838: #endif
839:
840: #endif /* ETAP_LOCK_ACCUMULATE */
841:
842:
843: #if ETAP_MONITOR
844:
845: /*
846: * monitor buffer allocation
847: */
848:
849: size = ((mbuff_entries-1) * sizeof(struct mbuff_entry)) +
850: sizeof(struct monitor_buffer);
851:
852: for (x=0; x < NCPUS; x++) {
853: ret = kmem_alloc(kernel_map,
854: (vm_offset_t *) &mbuff[x],
855: size);
856:
857: if (ret != KERN_SUCCESS)
858: panic ("ETAP: error allocating monitor buffer\n");
859:
860: /* zero fill buffer */
861: bzero((char *) mbuff[x], size);
862: }
863:
864: #endif /* ETAP_MONITOR */
865:
866:
867: #if ETAP_LOCK_TRACE
868:
869: /*
870: * Initialize the start_data_pool
871: */
872:
873: init_start_data_pool();
874:
875: #endif /* ETAP_LOCK_TRACE */
876: }
877:
878:
879: #if ETAP_LOCK_ACCUMULATE
880:
881: /*
882: * ROUTINE: etap_cbuff_reserve [internal]
883: *
884: * FUNCTION: The cumulative buffer operation which returns a pointer
885: * to a free entry in the cumulative buffer.
886: *
887: * NOTES: Disables interrupts.
888: *
889: */
890:
891: cbuff_entry_t
892: etap_cbuff_reserve(event_table_t etp)
893: {
894: cbuff_entry_t avail;
895: unsigned short de;
896: spl_t s;
897:
898: /* see if type pointer is initialized */
899: if (etp == EVENT_TABLE_NULL || etp->event == ETAP_NO_TRACE)
900: return (CBUFF_ENTRY_NULL);
901:
902: /* check for DYNAMIC lock */
903: if (de = etp->dynamic) {
904: if (de <= cbuff->static_start)
905: return (&cbuff->entry[de-1]);
906: else {
907: printf("ETAP: dynamic lock index error [%lu]\n", de);
908: return (CBUFF_ENTRY_NULL);
909: }
910: }
911:
912: cumulative_buffer_lock(s);
913:
914: /* if buffer is full, reservation requests fail */
915: if (cbuff->next >= ETAP_CBUFF_ENTRIES) {
916: cumulative_buffer_unlock(s);
917: return (CBUFF_ENTRY_NULL);
918: }
919:
920: avail = &cbuff->entry[cbuff->next++];
921:
922: cumulative_buffer_unlock(s);
923:
924: return (avail);
925: }
926:
927: #endif /* ETAP_LOCK_ACCUMULATE */
928:
929: /*
930: * ROUTINE: etap_event_table_assign [internal]
931: *
932: * FUNCTION: Returns a pointer to the assigned event type table entry,
933: * using the event type as the index key.
934: *
935: */
936:
937: event_table_t
938: etap_event_table_find(etap_event_t event)
939: {
940: int last_before, first_after, try;
941:
942: /* Binary search for the event number. last_before is the highest-
943: numbered element known to be <= the number we're looking for;
944: first_after is the lowest-numbered element known to be >. */
945: last_before = 0;
946: first_after = event_table_max;
947: while (last_before < first_after) {
948: try = (last_before + first_after) >> 1;
949: if (event_table[try].event == event)
950: return (&event_table[try]);
951: else if (event_table[try].event < event)
952: last_before = try;
953: else
954: first_after = try;
955: }
956: return EVENT_TABLE_NULL;
957: }
958:
959: void
960: etap_event_table_assign(struct event_table_chain *chainp, etap_event_t event)
961: {
962: event_table_t event_tablep;
963:
964: event_tablep = etap_event_table_find(event);
965: if (event_tablep == EVENT_TABLE_NULL)
966: printf("\nETAP: event not found in event table: %x\n", event);
967: else {
968: if (event_table == event_table_init) {
969: chainp->event_table_link = event_table_chain;
970: event_table_chain = chainp;
971: }
972: chainp->event_tablep = event_tablep;
973: }
974: }
975:
976: #endif /* ETAP */
977:
978: /*
979: *
980: * MESSAGE: etap_get_info [exported]
981: *
982: * FUNCTION: provides the server with ETAP buffer configurations.
983: *
984: */
985:
986: kern_return_t
987: etap_get_info(
988: host_t host_priv,
989: int *et_entries,
990: int *st_entries,
991: vm_offset_t *et_offset,
992: vm_offset_t *st_offset,
993: int *cb_width,
994: int *mb_size,
995: int *mb_entries,
996: int *mb_cpus)
997: {
998:
999: #if ETAP
1000: *et_entries = event_table_max;
1001: *st_entries = subs_table_max;
1002: *et_offset = (vm_offset_t) ((char*) event_table -
1003: trunc_page((char*) event_table));
1004: *st_offset = (vm_offset_t) ((char*) subs_table -
1005: trunc_page((char*) subs_table));
1006: #else /* ETAP */
1007: *et_entries = 0;
1008: *st_entries = 0;
1009: *et_offset = 0;
1010: *st_offset = 0;
1011: #endif /* ETAP */
1012:
1013: #if ETAP_LOCK_ACCUMULATE
1014: *cb_width = cbuff_width;
1015: #else /* ETAP_LOCK_ACCUMULATE */
1016: *cb_width = 0;
1017: #endif /* ETAP_LOCK_ACCUMULATE */
1018:
1019: #if ETAP_MONITOR
1020: *mb_size = ((mbuff_entries-1) * sizeof(struct mbuff_entry)) +
1021: sizeof(struct monitor_buffer);
1022: *mb_entries = mbuff_entries;
1023: *mb_cpus = NCPUS;
1024: #else /* ETAP_MONITOR */
1025: *mb_size = 0;
1026: *mb_entries = 0;
1027: *mb_cpus = 0;
1028: #endif /* ETAP_MONITOR */
1029:
1030: return (KERN_SUCCESS);
1031: }
1032:
1033: /*
1034: * ROUTINE: etap_trace_event [exported]
1035: *
1036: * FUNCTION: The etap_trace_event system call is the user's interface to
1037: * the ETAP kernel instrumentation.
1038: *
1039: * This call allows the user to enable and disable tracing modes
1040: * on specific event types. The call also supports a reset option,
1041: * where the cumulative buffer data and all event type tracing
1042: * is reset to zero. When the reset option is used, a new
1043: * interval width can also be defined using the op parameter.
1044: *
1045: */
1046:
1047: kern_return_t
1048: etap_trace_event (
1049: unsigned short mode,
1050: unsigned short type,
1051: boolean_t enable,
1052: unsigned int nargs,
1053: unsigned short args[])
1054: {
1055: #if ETAP
1056: event_table_t event_tablep;
1057: kern_return_t ret;
1058: int i, args_size;
1059: unsigned short status_mask;
1060: unsigned short *tmp_args;
1061:
1062: /*
1063: * Initialize operation
1064: */
1065:
1066: if (mode == ETAP_RESET) {
1067: etap_trace_reset(nargs);
1068: return (KERN_SUCCESS);
1069: }
1070:
1071: status_mask = mode & type;
1072:
1073: /*
1074: * Copy args array from user space to kernel space
1075: */
1076:
1077: args_size = nargs * sizeof *args;
1078: tmp_args = (unsigned short *) kalloc(args_size);
1079:
1080: if (tmp_args == NULL)
1081: return (KERN_NO_SPACE);
1082:
1083: if (copyin((const char *) args, (char *) tmp_args, args_size))
1084: return (KERN_INVALID_ADDRESS);
1085:
1086: /*
1087: * Change appropriate status fields in the event table
1088: */
1089:
1090: event_table_lock();
1091:
1092: for (i = 0; i < nargs; i++) {
1093: if (tmp_args[i] != ETAP_NO_TRACE) {
1094: event_tablep = etap_event_table_find(tmp_args[i]);
1095: if (event_tablep == EVENT_TABLE_NULL)
1096: break;
1097: if (enable)
1098: event_tablep->status |= status_mask;
1099: else
1100: event_tablep->status &= ~status_mask;
1101: }
1102: }
1103:
1104: ret = (i < nargs) ? KERN_INVALID_ARGUMENT : KERN_SUCCESS;
1105:
1106: event_table_unlock();
1107:
1108: kfree((vm_offset_t) tmp_args, args_size);
1109:
1110: return (ret);
1111:
1112: #else /* ETAP */
1113:
1114: return (KERN_FAILURE);
1115:
1116: #endif /* ETAP */
1117: }
1118:
1119:
1120: #if ETAP
1121:
1122: /*
1123: * ROUTINE: etap_trace_reset [internal]
1124: *
1125: * FUNCTION: Turns off all tracing and erases all the data accumulated
1126: * in the cumulative buffer. If the user defined a new
1127: * cumulative buffer interval width, it will be assigned here.
1128: *
1129: */
1130: void
1131: etap_trace_reset(int new_interval)
1132: {
1133: event_table_t scan;
1134: int x;
1135: register s;
1136:
1137: /*
1138: * Wipe out trace fields in event table
1139: */
1140:
1141: scan = event_table;
1142:
1143: event_table_lock();
1144:
1145: for (x=0; x < event_table_max; x++) {
1146: scan->status = ETAP_TRACE_OFF;
1147: scan++;
1148: }
1149:
1150: event_table_unlock();
1151:
1152: #if ETAP_LOCK_ACCUMULATE
1153:
1154: /*
1155: * Wipe out cumulative buffer statistical fields for all entries
1156: */
1157:
1158: cumulative_buffer_lock(s);
1159:
1160: for (x=0; x < ETAP_CBUFF_ENTRIES; x++) {
1161: bzero ((char *) &cbuff->entry[x].hold,
1162: sizeof(struct cbuff_data));
1163: bzero ((char *) &cbuff->entry[x].wait,
1164: sizeof(struct cbuff_data));
1165: bzero ((char *) &cbuff->entry[x].hold_interval[0],
1166: sizeof(unsigned long) * ETAP_CBUFF_IBUCKETS);
1167: bzero ((char *) &cbuff->entry[x].wait_interval[0],
1168: sizeof(unsigned long) * ETAP_CBUFF_IBUCKETS);
1169: }
1170:
1171: /*
1172: * Assign interval width if the user defined a new one.
1173: */
1174:
1175: if (new_interval != 0)
1176: cbuff_width = new_interval;
1177:
1178: cumulative_buffer_unlock(s);
1179:
1180: #endif /* ETAP_LOCK_ACCUMULATE */
1181: }
1182:
1183: #endif /* ETAP */
1184:
1185: /*
1186: * ROUTINE: etap_probe [exported]
1187: *
1188: * FUNCTION: The etap_probe system call serves as a user-level probe,
1189: * allowing user-level code to store event data into
1190: * the monitored buffer(s).
1191: */
1192:
1193: kern_return_t
1194: etap_probe(
1195: unsigned short event_type,
1196: unsigned short event_id,
1197: unsigned int data_size, /* total size in bytes */
1198: etap_data_t *data)
1199: {
1200:
1201: #if ETAP_MONITOR
1202:
1203: mbuff_entry_t mbuff_entryp;
1204: int cpu;
1205: int free;
1206: spl_t s;
1207:
1208:
1209: if (data_size > ETAP_DATA_SIZE)
1210: return (KERN_INVALID_ARGUMENT);
1211:
1212: if (event_table[event_type].status == ETAP_TRACE_OFF ||
1213: event_table[event_type].event != event_type)
1214: return (KERN_NO_ACCESS);
1215:
1216: mp_disable_preemption();
1217: cpu = cpu_number();
1218: s = splhigh();
1219:
1220: free = mbuff[cpu]->free;
1221: mbuff_entryp = &mbuff[cpu]->entry[free];
1222:
1223: /*
1224: * Load monitor buffer entry
1225: */
1226:
1227: ETAP_TIMESTAMP(mbuff_entryp->time);
1228: mbuff_entryp->event = event_id;
1229: mbuff_entryp->flags = USER_EVENT;
1230: mbuff_entryp->instance = (u_int) current_thread();
1231: mbuff_entryp->pc = 0;
1232:
1233: if (data != ETAP_DATA_NULL)
1234: copyin((const char *) data,
1235: (char *) mbuff_entryp->data,
1236: data_size);
1237:
1238: mbuff[cpu]->free = (free+1) % mbuff_entries;
1239:
1240: if (mbuff[cpu]->free == 0)
1241: mbuff[cpu]->timestamp++;
1242:
1243: splx(s);
1244: mp_enable_preemption();
1245:
1246: return (KERN_SUCCESS);
1247:
1248: #else /* ETAP_MONITOR */
1249: return (KERN_FAILURE);
1250: #endif /* ETAP_MONITOR */
1251: }
1252:
1253: /*
1254: * ROUTINE: etap_trace_thread [exported]
1255: *
1256: * FUNCTION: Toggles thread's ETAP trace status bit.
1257: */
1258:
1259: kern_return_t
1260: etap_trace_thread(
1261: thread_act_t thr_act,
1262: boolean_t trace_status)
1263: {
1264: #if ETAP_EVENT_MONITOR
1265:
1266: thread_t thread;
1267: boolean_t old_status;
1268: etap_data_t probe_data;
1269: spl_t s;
1270:
1271: if (thr_act == THR_ACT_NULL)
1272: return (KERN_INVALID_ARGUMENT);
1273:
1274: thread = act_lock_thread(thr_act);
1275:
1276: if (thread == THREAD_NULL) {
1277: act_unlock_thread(thr_act);
1278: return (KERN_INVALID_ARGUMENT);
1279: }
1280:
1281: s = splsched();
1282: thread_lock(thread);
1283:
1284: old_status = thread->etap_trace;
1285: thread->etap_trace = trace_status;
1286:
1287: ETAP_DATA_LOAD(probe_data[0],thr_act->task);
1288: ETAP_DATA_LOAD(probe_data[1],thr_act);
1289: ETAP_DATA_LOAD(probe_data[2],thread->sched_pri);
1290:
1291: thread_unlock(thread);
1292: splx(s);
1293:
1294: act_unlock_thread(thr_act);
1295:
1296: /*
1297: * Thread creation (ETAP_P_THREAD_LIFE: BEGIN) is ONLY recorded
1298: * here since a threads trace status is disabled by default.
1299: */
1300: if (trace_status == TRUE && old_status == FALSE) {
1301: ETAP_PROBE_DATA(ETAP_P_THREAD_LIFE,
1302: EVENT_BEGIN,
1303: thread,
1304: &probe_data,
1305: ETAP_DATA_ENTRY*3);
1306: }
1307:
1308: /*
1309: * Thread termination is (falsely) recorded here if the trace
1310: * status has been disabled. This event is recorded to allow
1311: * users the option of tracing a portion of a threads execution.
1312: */
1313: if (trace_status == FALSE && old_status == TRUE) {
1314: ETAP_PROBE_DATA(ETAP_P_THREAD_LIFE,
1315: EVENT_END,
1316: thread,
1317: &probe_data,
1318: ETAP_DATA_ENTRY*3);
1319: }
1320:
1321: return (KERN_SUCCESS);
1322:
1323: #else /* ETAP_EVENT_MONITOR */
1324: return (KERN_FAILURE);
1325: #endif /* ETAP_EVENT_MONITOR */
1326: }
1327:
1328: /*
1329: * ROUTINE: etap_mon_reconfig [exported]
1330: *
1331: * FUNCTION: Reallocates monitor buffers to hold specified number
1332: * of entries.
1333: *
1334: * NOTES: In multiprocessor (SMP) case, a lock needs to be added
1335: * here and in data collection macros to protect access
1336: * to mbuff_entries.
1337: */
1338: kern_return_t
1339: etap_mon_reconfig(
1340: host_t host_priv,
1341: int nentries)
1342: {
1343: #if ETAP_EVENT_MONITOR
1344: struct monitor_buffer *nmbuff[NCPUS], *ombuff[NCPUS];
1345: int s, size, osize, i, ret;
1346:
1347: if (nentries <= 0) /* must be at least 1 */
1348: return (KERN_FAILURE);
1349:
1350: size = ((nentries-1) * sizeof(struct mbuff_entry)) +
1351: sizeof(struct monitor_buffer);
1352:
1353: for (i = 0; i < NCPUS; ++i) {
1354: ret = kmem_alloc(kernel_map,
1355: (vm_offset_t *)&nmbuff[i],
1356: size);
1357: if (ret != KERN_SUCCESS) {
1358: if (i > 0) {
1359: int j;
1360:
1361: for (j = 0; j < i; ++j) {
1362: kmem_free(kernel_map,
1363: (vm_offset_t)nmbuff[j],
1364: size);
1365: }
1366: }
1367: return (ret);
1368: }
1369: bzero((char *) nmbuff[i], size);
1370: }
1371: osize = ((mbuff_entries-1) * sizeof (struct mbuff_entry)) +
1372: sizeof (struct monitor_buffer);
1373:
1374: s = splhigh();
1375: event_table_lock();
1376: for (i = 0; i < NCPUS; ++i) {
1377: ombuff[i] = mbuff[i];
1378: mbuff[i] = nmbuff[i];
1379: }
1380: mbuff_entries = nentries;
1381: event_table_unlock();
1382: splx(s);
1383:
1384: for (i = 0; i < NCPUS; ++i) {
1385: kmem_free(kernel_map,
1386: (vm_offset_t)ombuff[i],
1387: osize);
1388: }
1389: return (KERN_SUCCESS);
1390: #else
1391: return (KERN_FAILURE);
1392: #endif /* ETAP_MONITOR */
1393: }
1394:
1395: /*
1396: * ROUTINE: etap_new_probe [exported]
1397: *
1398: * FUNCTION: Reallocates monitor probe table, adding a new entry
1399: *
1400: */
1401: kern_return_t
1402: etap_new_probe(
1403: host_t host_priv,
1404: vm_address_t name,
1405: vm_size_t namlen,
1406: boolean_t trace_on,
1407: vm_address_t id)
1408: {
1409: #if ETAP_EVENT_MONITOR
1410: event_table_t newtable, oldtable;
1411: unsigned short i, nid;
1412: int s;
1413: vm_size_t newsize = (event_table_max + 1) *
1414: sizeof (struct event_table_entry);
1415: boolean_t duplicate_name = FALSE;
1416: kern_return_t ret;
1417:
1418: if (namlen > EVENT_NAME_LENGTH - 1)
1419: return (KERN_INVALID_ARGUMENT);
1420:
1421: if ((ret = kmem_alloc(kernel_map, (vm_address_t *)&newtable,
1422: newsize)) != KERN_SUCCESS)
1423: return (ret);
1424:
1425: bcopy((const char *)event_table, (char *)newtable, event_table_max *
1426: sizeof (struct event_table_entry));
1427:
1428: if (copyin((const char *)name,
1429: (char *)&newtable[event_table_max].name, namlen))
1430: return (KERN_INVALID_ADDRESS);
1431:
1432: newtable[event_table_max].name[EVENT_NAME_LENGTH - 1] = '\0';
1433: newtable[event_table_max].status = trace_on;
1434: newtable[event_table_max].dynamic = 0;
1435:
1436: for (nid = i = 0; i < event_table_max; ++i) {
1437: if (strcmp((char *)newtable[event_table_max].name,
1438: newtable[i].name) == 0) {
1439: duplicate_name = TRUE;
1440: printf("duplicate name\n");
1441: }
1442: nid = max(nid, newtable[i].event);
1443: }
1444: ++nid;
1445:
1446: if (nid >= ETAP_NO_TRACE || duplicate_name == TRUE) {
1447: kmem_free(kernel_map, (vm_address_t)newtable, newsize);
1448: if (nid >= ETAP_NO_TRACE) {
1449: printf("KERN_RESOURCE_SHORTAGE\n");
1450: return (KERN_RESOURCE_SHORTAGE);
1451: }
1452: else {
1453: printf("KERN_NAME_EXISTS\n");
1454: return (KERN_NAME_EXISTS);
1455: }
1456: }
1457:
1458: newtable[event_table_max].event = nid;
1459:
1460: s = splhigh();
1461: event_table_lock();
1462: oldtable = event_table;
1463: event_table = newtable;
1464: ++event_table_max;
1465: event_table_unlock();
1466: splx(s);
1467:
1468: if (oldtable != event_table_init)
1469: kmem_free(kernel_map, (vm_address_t)oldtable,
1470: (event_table_max - 1) *
1471: sizeof (struct event_table_entry));
1472:
1473: *(unsigned short *)id = nid;
1474:
1475: return (KERN_SUCCESS);
1476: #else
1477: return (KERN_FAILURE);
1478: #endif /* ETAP_EVENT_MONITOR */
1479:
1480: }
1481: /*
1482: * ETAP trap probe hooks
1483: */
1484:
1485: void
1486: etap_interrupt_probe(int interrupt, int flag_setting)
1487: {
1488: u_short flag;
1489:
1490: if (flag_setting == 1)
1491: flag = EVENT_BEGIN;
1492: else
1493: flag = EVENT_END;
1494:
1495: ETAP_PROBE_DATA_COND(ETAP_P_INTERRUPT,
1496: flag,
1497: current_thread(),
1498: &interrupt,
1499: sizeof(int),
1500: 1);
1501: }
1502:
1503: void
1504: etap_machcall_probe1(int syscall)
1505: {
1506: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
1507: EVENT_BEGIN | SYSCALL_TRAP,
1508: current_thread(),
1509: &syscall,
1510: sizeof(int));
1511: }
1512:
1513: void
1514: etap_machcall_probe2(void)
1515: {
1516: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH,
1517: EVENT_END | SYSCALL_TRAP,
1518: current_thread(),
1519: 0,
1520: 0);
1521: }
1522:
1523: static void print_user_event(mbuff_entry_t);
1524: static void print_kernel_event(mbuff_entry_t, boolean_t);
1525: static void print_lock_event(mbuff_entry_t, const char *);
1526:
1527: #if MACH_KDB
1528: void db_show_etap_log(db_expr_t, boolean_t, db_expr_t, char *);
1529: /*
1530: *
1531: * ROUTINE: etap_print [internal]
1532: *
1533: * FUNCTION: print each mbuff table (for use in debugger)
1534: *
1535: */
1536: void
1537: db_show_etap_log(
1538: db_expr_t addr,
1539: boolean_t have_addr,
1540: db_expr_t count,
1541: char * modif)
1542: {
1543: #if ETAP_MONITOR
1544: int cpu = cpu_number(), last, i, first, step, end, restart;
1545: boolean_t show_data = FALSE;
1546:
1547: last = (mbuff[cpu]->free - 1) % mbuff_entries;
1548:
1549: if(db_option(modif, 'r')) {
1550: first = last;
1551: step = -1;
1552: end = -1;
1553: restart = mbuff_entries - 1;
1554: } else {
1555: first = last + 1;
1556: step = 1;
1557: end = mbuff_entries;
1558: restart = 0;
1559: }
1560:
1561: if(db_option(modif, 'd'))
1562: show_data = TRUE;
1563:
1564: for(i = first; i != end; i += step) {
1565: if (mbuff[cpu]->entry[i].flags & USER_EVENT)
1566: print_user_event(&mbuff[cpu]->entry[i]);
1567: else
1568: print_kernel_event(&mbuff[cpu]->entry[i], show_data);
1569: }
1570: for(i = restart; i != first; i += step) {
1571: if (mbuff[cpu]->entry[i].flags & USER_EVENT)
1572: print_user_event(&mbuff[cpu]->entry[i]);
1573: else
1574: print_kernel_event(&mbuff[cpu]->entry[i], show_data);
1575: }
1576: #else
1577: printf("ETAP event monitor not configured\n");
1578: #endif /* ETAP_MONITOR */
1579: }
1580:
1581: #if ETAP_MONITOR
1582: static
1583: void
1584: print_user_event(mbuff_entry_t record)
1585: {
1586: char *s, buf[256];
1587:
1588: db_printf("%x: %x%08x: ", record->instance, record->time.tv_sec,
1589: record->time.tv_nsec);
1590: switch (record->pc)
1591: {
1592: case ETAP_P_USER_EVENT0: s = "0"; break;
1593: case ETAP_P_USER_EVENT1: s = "1"; break;
1594: case ETAP_P_USER_EVENT2: s = "2"; break;
1595: case ETAP_P_USER_EVENT3: s = "3"; break;
1596: case ETAP_P_USER_EVENT4: s = "4"; break;
1597: case ETAP_P_USER_EVENT5: s = "5"; break;
1598: case ETAP_P_USER_EVENT6: s = "6"; break;
1599: case ETAP_P_USER_EVENT7: s = "7"; break;
1600: case ETAP_P_USER_EVENT8: s = "8"; break;
1601: case ETAP_P_USER_EVENT9: s = "9"; break;
1602: case ETAP_P_USER_EVENT10: s = "10"; break;
1603: case ETAP_P_USER_EVENT11: s = "11"; break;
1604: case ETAP_P_USER_EVENT12: s = "12"; break;
1605: case ETAP_P_USER_EVENT13: s = "13"; break;
1606: case ETAP_P_USER_EVENT14: s = "14"; break;
1607: case ETAP_P_USER_EVENT15: s = "15"; break;
1608: case ETAP_P_USER_EVENT16: s = "16"; break;
1609: case ETAP_P_USER_EVENT17: s = "17"; break;
1610: case ETAP_P_USER_EVENT18: s = "18"; break;
1611: case ETAP_P_USER_EVENT19: s = "19"; break;
1612: case ETAP_P_USER_EVENT20: s = "20"; break;
1613: case ETAP_P_USER_EVENT21: s = "21"; break;
1614: case ETAP_P_USER_EVENT22: s = "22"; break;
1615: case ETAP_P_USER_EVENT23: s = "23"; break;
1616: case ETAP_P_USER_EVENT24: s = "24"; break;
1617: case ETAP_P_USER_EVENT25: s = "25"; break;
1618: case ETAP_P_USER_EVENT26: s = "26"; break;
1619: case ETAP_P_USER_EVENT27: s = "27"; break;
1620: case ETAP_P_USER_EVENT28: s = "28"; break;
1621: case ETAP_P_USER_EVENT29: s = "29"; break;
1622: case ETAP_P_USER_EVENT30: s = "30"; break;
1623: case ETAP_P_USER_EVENT31: s = "31"; break;
1624: default:
1625: sprintf(buf, "dynamic %x", record->pc);
1626: s = buf;
1627: break;
1628: }
1629:
1630: db_printf("user probe %s: [%x] data = %x %x %x %x\n",
1631: s,
1632: record->event,
1633: record->data[0],
1634: record->data[1],
1635: record->data[2],
1636: record->data[3]);
1637: }
1638:
1639: static
1640: void
1641: print_kernel_event(mbuff_entry_t record, boolean_t data)
1642: {
1643: char *text_name;
1644: int i;
1645:
1646: /* assume zero event means that record was never written to */
1647: if(record->event == 0)
1648: return;
1649:
1650: db_printf("%x: %x%08x: ", record->instance, record->time.tv_sec,
1651: record->time.tv_nsec);
1652:
1653: switch (record->event) {
1654:
1655: case ETAP_P_THREAD_LIFE :
1656: if (record->flags & EVENT_BEGIN)
1657: db_printf("thread created [T:%x A:%x] P:%d\n",
1658: record->data[0],
1659: record->data[1],
1660: record->data[2]);
1661: else
1662: db_printf("thread terminated [T:%x A:%x] P:%d\n",
1663: record->data[0],
1664: record->data[1],
1665: record->data[2]);
1666: break;
1667:
1668: case ETAP_P_SYSCALL_MACH :
1669: if (record->flags & SYSCALL_TRAP)
1670: text_name = system_table_lookup(SYS_TABLE_MACH_TRAP,
1671: record->data[0]);
1672: else
1673: text_name = system_table_lookup(SYS_TABLE_MACH_MESSAGE,
1674: record->data[0]);
1675:
1676: if (record->flags & EVENT_BEGIN)
1677: db_printf("mach enter: %s [%x]\n",
1678: text_name,
1679: record->data[0]);
1680: else
1681: db_printf("mach exit :\n");
1682: break;
1683:
1684: case ETAP_P_SYSCALL_UNIX :
1685: text_name = system_table_lookup(SYS_TABLE_UNIX_SYSCALL,
1686: record->data[0]);
1687:
1688: if (record->flags & EVENT_BEGIN)
1689: db_printf("unix enter: %s\n", text_name);
1690: else
1691: db_printf("unix exit : %s\n", text_name);
1692: break;
1693:
1694: case ETAP_P_THREAD_CTX :
1695: if (record->flags & EVENT_END)
1696: db_printf("context switch to %x ",
1697: record->data[0]);
1698: else /* EVENT_BEGIN */
1699: db_printf("context switch from %x ",
1700: record->data[0]);
1701:
1702: switch (record->data[1]) {
1703: case BLOCKED_ON_SEMAPHORE :
1704: db_printf("R: semaphore\n"); break;
1705: case BLOCKED_ON_LOCK :
1706: db_printf("R: lock\n"); break;
1707: case BLOCKED_ON_MUTEX_LOCK :
1708: db_printf("R: mutex lock\n"); break;
1709: case BLOCKED_ON_COMPLEX_LOCK :
1710: db_printf("R: complex lock\n"); break;
1711: case BLOCKED_ON_PORT_RCV :
1712: db_printf("R: port receive\n"); break;
1713: case BLOCKED_ON_REAPER_DONE :
1714: db_printf("R: reaper thread done\n"); break;
1715: case BLOCKED_ON_IDLE_DONE :
1716: db_printf("R: idle thread done\n"); break;
1717: case BLOCKED_ON_TERMINATION :
1718: db_printf("R: termination\n"); break;
1719: default :
1720: if (record->data[2])
1721: db_printf("R: ast %x\n", record->data[2]);
1722: else
1723: db_printf("R: undefined block\n");
1724: };
1725: break;
1726:
1727: case ETAP_P_INTERRUPT :
1728: if (record->flags & EVENT_BEGIN) {
1729: text_name = system_table_lookup(SYS_TABLE_INTERRUPT,
1730: record->data[0]);
1731: db_printf("intr enter: %s\n", text_name);
1732: } else
1733: db_printf("intr exit\n");
1734: break;
1735:
1736: case ETAP_P_ACT_ABORT :
1737: db_printf("activation abort [A %x : S %x]\n",
1738: record->data[1],
1739:
1740: record->data[0]);
1741: break;
1742:
1743: case ETAP_P_PRIORITY :
1744: db_printf("priority changed for %x N:%d O:%d\n",
1745: record->data[0],
1746: record->data[1],
1747: record->data[2]);
1748: break;
1749:
1750: case ETAP_P_EXCEPTION :
1751: text_name = system_table_lookup(SYS_TABLE_EXCEPTION,
1752: record->data[0]);
1753: db_printf("exception: %s\n", text_name);
1754: break;
1755:
1756: case ETAP_P_DEPRESSION :
1757: if (record->flags & EVENT_BEGIN)
1758: db_printf("priority depressed\n");
1759: else {
1760: if (record->data[0] == 0)
1761: db_printf("priority undepressed : timed out\n");
1762: else
1763: db_printf("priority undepressed : self inflicted\n");
1764: }
1765: break;
1766:
1767: case ETAP_P_MISC :
1768: db_printf("flags: %x data: %x %x %x %x\n", record->flags,
1769: record->data[0], record->data[1], record->data[2],
1770: record->data[3]);
1771: break;
1772:
1773: case ETAP_P_DETAP :
1774: printf("flags: %x rtc: %x %09x dtime: %x %09x\n",
1775: record->flags, record->data[0], record->data[1],
1776: record->data[2], record->data[3]);
1777: break;
1778:
1779: default:
1780: for(i = 0; event_table_init[i].event != ETAP_NO_TRACE; ++i)
1781: if(record->event == event_table_init[i].event) {
1782: print_lock_event(record, event_table_init[i].name);
1783: return;
1784: }
1785: db_printf("Unknown event: %d\n", record->event);
1786: break;
1787: }
1788: if(data)
1789: db_printf(" Data: %08x %08x %08x %08x\n", record->data[0],
1790: record->data[1], record->data[2], record->data[3]);
1791: }
1792:
1793: void print_lock_event(mbuff_entry_t record, const char *name)
1794: {
1795: char *sym1, *sym2;
1796: db_addr_t offset1, offset2;
1797:
1798: db_find_sym_and_offset(record->data[0], &sym1, &offset1);
1799:
1800: db_printf("%15s", name);
1801: if (record->flags & SPIN_LOCK)
1802: printf(" spin ");
1803: else if (record->flags & READ_LOCK)
1804: printf(" read ");
1805: else if (record->flags & WRITE_LOCK)
1806: printf(" write ");
1807: else
1808: printf(" undef ");
1809:
1810: if (record->flags & ETAP_CONTENTION) {
1811: db_printf("wait lock %s+%x\n",
1812: sym1, offset1);
1813: }
1814: else if (record->flags & ETAP_DURATION) {
1815: db_find_sym_and_offset(record->data[1], &sym2, &offset2);
1816: db_printf("lock %x+%x unlock %x+%x\n",
1817: sym1, offset1, sym2, offset2);
1818: } else {
1819: db_printf("illegal op: neither HOLD or WAIT are specified\n");
1820: }
1821:
1822: }
1823:
1824: char *
1825: system_table_lookup(unsigned int table, unsigned int number)
1826: {
1827: int x;
1828: char *name = NULL;
1829: unsigned int offset;
1830:
1831: switch (table) {
1832: case SYS_TABLE_MACH_TRAP:
1833: name = mach_trap_name(number >> 4);
1834: break;
1835: case SYS_TABLE_MACH_MESSAGE:
1836: for (x=0; x < mach_message_table_entries; x++) {
1837: if (mach_message_table[x].number == number) {
1838: name = mach_message_table[x].name;
1839: break;
1840: }
1841: }
1842: break;
1843: case SYS_TABLE_UNIX_SYSCALL:
1844: number = -number;
1845: name = syscall_name(number);
1846: break;
1847: case SYS_TABLE_INTERRUPT:
1848: db_find_sym_and_offset((int)ivect[number], &name, &offset);
1849: break;
1850: case SYS_TABLE_EXCEPTION:
1851: name = exception_name(number);
1852: break;
1853: }
1854: return (name != NULL) ? name : "undefined";
1855: }
1856:
1857: #endif /* MACH_KDB */
1858: #endif /* ETAP_MONITOR */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.