Annotation of XNU/osfmk/kern/etap.c, revision 1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.