static int sdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { sdt_provider_t *prov; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (ddi_create_minor_node(devi, "sdt", S_IFCHR, 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { ddi_remove_minor_node(devi, NULL); return (DDI_FAILURE); } ddi_report_dev(devi); sdt_devi = devi; for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) { if (dtrace_register(prov->sdtp_name, prov->sdtp_attr, DTRACE_PRIV_KERNEL, NULL, &sdt_pops, prov, &prov->sdtp_id) != 0) { cmn_err(CE_WARN, "failed to register sdt provider %s", prov->sdtp_name); } } return (DDI_SUCCESS); }
static int profile_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (ddi_create_minor_node(devi, "profile", S_IFCHR, 0, DDI_PSEUDO, NULL) == DDI_FAILURE || dtrace_register("profile", &profile_attr, DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER, NULL, &profile_pops, NULL, &profile_id) != 0) { ddi_remove_minor_node(devi, NULL); return (DDI_FAILURE); } profile_max = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, "profile-max-probes", PROFILE_MAX_DEFAULT); ddi_report_dev(devi); profile_devi = devi; return (DDI_SUCCESS); }
static void sdt_create_provider(struct sdt_provider *prov) { struct sdt_provider *curr, *newprov; TAILQ_FOREACH(curr, &sdt_prov_list, prov_entry) if (strcmp(prov->name, curr->name) == 0) { /* The provider has already been defined. */ curr->sdt_refs++; return; } /* * Make a copy of prov so that we don't lose fields if its module is * unloaded but the provider isn't destroyed. This could happen with * a provider that spans multiple modules. */ newprov = malloc(sizeof(*newprov), M_SDT, M_WAITOK | M_ZERO); newprov->name = strdup(prov->name, M_SDT); prov->sdt_refs = newprov->sdt_refs = 1; TAILQ_INSERT_TAIL(&sdt_prov_list, newprov, prov_entry); (void)dtrace_register(newprov->name, &sdt_attr, DTRACE_PRIV_USER, NULL, &sdt_pops, NULL, (dtrace_provider_id_t *)&newprov->id); prov->id = newprov->id; }
int fbt_init(void) { int ret; ret = misc_register(&fbt_dev); if (ret) { printk(KERN_WARNING "fbt: Unable to register misc device\n"); return ret; } /***********************************************/ /* Helper not presently implemented :-( */ /***********************************************/ // printk(KERN_WARNING "fbt loaded: /dev/fbt now available\n"); if (fbt_probetab_size == 0) fbt_probetab_size = FBT_PROBETAB_SIZE; fbt_probetab_mask = fbt_probetab_size - 1; fbt_probetab = kmem_zalloc(fbt_probetab_size * sizeof (fbt_probe_t *), KM_SLEEP); /* dtrace_invop_add(fbt_invop);*/ proc_create("dtrace/fbt", 0444, NULL, &fbt_proc_fops); if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_KERNEL, 0, &fbt_pops, NULL, &fbt_id)) { printk("Failed to register fbt - insufficient priviledge\n"); } initted = 1; return 0; }
static int systrace_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } systrace_probe = (void (*)())dtrace_probe; membar_enter(); if (ddi_create_minor_node(devi, "systrace", S_IFCHR, 0, DDI_PSEUDO, NULL) == DDI_FAILURE || dtrace_register("syscall", &systrace_attr, DTRACE_PRIV_USER, NULL, &systrace_pops, NULL, &systrace_id) != 0) { systrace_probe = systrace_stub; ddi_remove_minor_node(devi, NULL); return (DDI_FAILURE); } ddi_report_dev(devi); systrace_devi = devi; return (DDI_SUCCESS); }
/*ARGSUSED*/ static int sdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { #pragma unused(cmd) sdt_provider_t *prov; if (ddi_create_minor_node(devi, "sdt", S_IFCHR, 0, DDI_PSEUDO, 0) == DDI_FAILURE) { cmn_err(CE_NOTE, "/dev/sdt couldn't create minor node"); ddi_remove_minor_node(devi, NULL); return (DDI_FAILURE); } ddi_report_dev(devi); sdt_devi = devi; if (sdt_probetab_size == 0) sdt_probetab_size = SDT_PROBETAB_SIZE; sdt_probetab_mask = sdt_probetab_size - 1; sdt_probetab = kmem_zalloc(sdt_probetab_size * sizeof (sdt_probe_t *), KM_SLEEP); dtrace_invop_add(sdt_invop); for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) { if (dtrace_register(prov->sdtp_name, prov->sdtp_attr, DTRACE_PRIV_KERNEL, NULL, &sdt_pops, prov, &prov->sdtp_id) != 0) { cmn_err(CE_WARN, "failed to register sdt provider %s", prov->sdtp_name); } } return (DDI_SUCCESS); }
static int lockstat_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (ddi_create_minor_node(devi, "lockstat", S_IFCHR, 0, DDI_PSEUDO, 0) == DDI_FAILURE || dtrace_register("lockstat", &lockstat_attr, DTRACE_PRIV_KERNEL, NULL, &lockstat_pops, NULL, &lockstat_id) != 0) { ddi_remove_minor_node(devi, NULL); return (DDI_FAILURE); } lockstat_probe = dtrace_probe; membar_producer(); ddi_report_dev(devi); lockstat_devi = devi; return (DDI_SUCCESS); }
static int fbt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (fbt_probetab_size == 0) fbt_probetab_size = FBT_PROBETAB_SIZE; fbt_probetab_mask = fbt_probetab_size - 1; fbt_probetab = kmem_zalloc(fbt_probetab_size * sizeof (fbt_probe_t *), KM_SLEEP); dtrace_invop_add(fbt_invop); if (ddi_create_minor_node(devi, "fbt", S_IFCHR, 0, DDI_PSEUDO, 0) == DDI_FAILURE || dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_KERNEL, NULL, &fbt_pops, NULL, &fbt_id) != 0) { fbt_cleanup(devi); return (DDI_FAILURE); } ddi_report_dev(devi); fbt_devi = devi; return (DDI_SUCCESS); }
int sdt_register(sdt_provider_t *prov) { int ind; int res; /* make sure the provider is not already registered */ for (ind = 0; ind < sdt_count; ind++) { if (strncmp(sdt_list[ind]->name, prov->name, SDT_MAX_NAME_SIZE) == 0) { printf("sdt: provider %s already registered\n", prov->name); return -1; } } /* register the new provider */ if ((res = dtrace_register(prov->name, &prov->attr, DTRACE_PRIV_USER, NULL, &sdt_pops, prov, &(prov->id))) != 0) { printf("sdt: failed to register %s res = %d\n", prov->name, res); return -1; } sdt_list[sdt_count++] = prov; return 0; }
static void systrace_load(void *dummy) { if (dtrace_register(PROVNAME, &systrace_attr, DTRACE_PRIV_USER, NULL, &systrace_pops, NULL, &systrace_id) != 0) return; EMUL.e_dtrace_syscall = systrace_probe; }
static void prototype_load(void *dummy) { /* Create the /dev/dtrace/prototype entry. */ prototype_cdev = make_dev(&prototype_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "dtrace/prototype"); if (dtrace_register("prototype", &prototype_attr, DTRACE_PRIV_USER, NULL, &prototype_pops, NULL, &prototype_id) != 0) return; }
static int profile_attach(void) { if (dtrace_register("profile", &profile_attr, DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER, NULL, &profile_pops, NULL, &profile_id) != 0) { printk("profile_attach: Failed to register 'profile' probes\n"); return (DDI_FAILURE); } return (DDI_SUCCESS); }
static void dtnfsclient_load(void *dummy) { if (dtrace_register("nfsclient", &dtnfsclient_attr, DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL, &dtnfsclient_id) != 0) return; dtrace_nfsclient_nfs23_start_probe = (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe; dtrace_nfsclient_nfs23_done_probe = (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe; }
static void systrace_load(void *dummy) { /* Create the /dev/dtrace/systrace entry. */ systrace_cdev = make_dev(&systrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, DEVNAME); if (dtrace_register(PROVNAME, &systrace_attr, DTRACE_PRIV_USER, NULL, &systrace_pops, NULL, &systrace_id) != 0) return; #if !defined(LINUX_SYSTRACE) systrace_probe_func = systrace_probe; #endif }
/** * interface_method_impl{SUPDRVTRACERREG,pfnProviderRegister} */ static DECLCALLBACK(int) vboxDtTOps_ProviderRegister(PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore) { LOG_DTRACE(("%s: %p %s/%s\n", __FUNCTION__, pThis, pCore->pszModName, pCore->pszName)); AssertReturn(pCore->TracerData.DTrace.idProvider == 0, VERR_INTERNAL_ERROR_3); PVTGDESCPROVIDER pDesc = pCore->pDesc; dtrace_pattr_t DtAttrs; vboxDtVtgConvAttr(&DtAttrs.dtpa_provider, &pDesc->AttrSelf); vboxDtVtgConvAttr(&DtAttrs.dtpa_mod, &pDesc->AttrModules); vboxDtVtgConvAttr(&DtAttrs.dtpa_func, &pDesc->AttrFunctions); vboxDtVtgConvAttr(&DtAttrs.dtpa_name, &pDesc->AttrNames); vboxDtVtgConvAttr(&DtAttrs.dtpa_args, &pDesc->AttrArguments); /* Note! DTrace may call us back before dtrace_register returns, so we have to point it to pCore->TracerData.DTrace.idProvider. */ AssertCompile(sizeof(dtrace_provider_id_t) == sizeof(pCore->TracerData.DTrace.idProvider)); int rc = dtrace_register(pCore->pszName, &DtAttrs, DTRACE_PRIV_KERNEL, NULL /* cred */, &g_vboxDtVtgProvOps, pCore, &pCore->TracerData.DTrace.idProvider); if (!rc) { LOG_DTRACE(("%s: idProvider=%p\n", __FUNCTION__, pCore->TracerData.DTrace.idProvider)); AssertPtr(pCore->TracerData.DTrace.idProvider); rc = VINF_SUCCESS; } else { pCore->TracerData.DTrace.idProvider = 0; rc = RTErrConvertFromErrno(FIX_UEK_RC(rc)); } LOG_DTRACE(("%s: returns %Rrc\n", __FUNCTION__, rc)); return rc; }
int instr_init(void) { int ret; struct proc_dir_entry *ent; ret = misc_register(&instr_dev); if (ret) { printk(KERN_WARNING "instr: Unable to register misc device\n"); return ret; } /***********************************************/ /* Helper not presently implemented :-( */ /***********************************************/ printk(KERN_WARNING "instr loaded: /dev/instr now available\n"); if (instr_probetab_size == 0) instr_probetab_size = INSTR_PROBETAB_SIZE; instr_probetab_mask = instr_probetab_size - 1; instr_probetab = kmem_zalloc(instr_probetab_size * sizeof (instr_probe_t *), KM_SLEEP); dtrace_invop_add(instr_invop); ent = create_proc_entry("dtrace/instr", 0444, NULL); if (ent) ent->proc_fops = &instr_proc_fops; if (dtrace_register("instr", &instr_attr, DTRACE_PRIV_KERNEL, 0, &instr_pops, NULL, &instr_id)) { printk("Failed to register instr - insufficient privilege\n"); } initted = 1; return 0; }
static void dtrace_load(void *dummy) { dtrace_provider_id_t id; CPU_INFO_ITERATOR cpuind; struct cpu_info *cinfo; dtrace_debug_init(NULL); dtrace_gethrtime_init(NULL); /* Hook into the trap handler. */ dtrace_trap_func = dtrace_trap; /* Hang our hook for thread switches. */ dtrace_vtime_switch_func = dtrace_vtime_switch; /* Hang our hook for exceptions. */ dtrace_invop_init(); /* * XXX This is a short term hack to avoid having to comment * out lots and lots of lock/unlock calls. */ mutex_init(&mod_lock,"XXX mod_lock hack", MUTEX_DEFAULT, NULL); /* * Initialise the mutexes without 'witness' because the dtrace * code is mostly written to wait for memory. To have the * witness code change a malloc() from M_WAITOK to M_NOWAIT * because a lock is held would surely create a panic in a * low memory situation. And that low memory situation might be * the very problem we are trying to trace. */ mutex_init(&dtrace_lock,"dtrace probe state", MUTEX_DEFAULT, NULL); mutex_init(&dtrace_provider_lock,"dtrace provider state", MUTEX_DEFAULT, NULL); mutex_init(&dtrace_meta_lock,"dtrace meta-provider state", MUTEX_DEFAULT, NULL); mutex_init(&dtrace_errlock,"dtrace error lock", MUTEX_DEFAULT, NULL); mutex_enter(&dtrace_provider_lock); mutex_enter(&dtrace_lock); mutex_enter(&cpu_lock); ASSERT(MUTEX_HELD(&cpu_lock)); dtrace_arena = vmem_create("dtrace", 1, INT_MAX, 1, NULL, NULL, NULL, 0, VM_SLEEP, IPL_NONE); dtrace_state_cache = kmem_cache_create(__UNCONST("dtrace_state_cache"), sizeof (dtrace_dstate_percpu_t) * NCPU, DTRACE_STATE_ALIGN, NULL, NULL, NULL, NULL, NULL, 0); ASSERT(MUTEX_HELD(&cpu_lock)); dtrace_bymod = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_mod), offsetof(dtrace_probe_t, dtpr_nextmod), offsetof(dtrace_probe_t, dtpr_prevmod)); dtrace_byfunc = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_func), offsetof(dtrace_probe_t, dtpr_nextfunc), offsetof(dtrace_probe_t, dtpr_prevfunc)); dtrace_byname = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_name), offsetof(dtrace_probe_t, dtpr_nextname), offsetof(dtrace_probe_t, dtpr_prevname)); if (dtrace_retain_max < 1) { cmn_err(CE_WARN, "illegal value (%lu) for dtrace_retain_max; " "setting to 1", dtrace_retain_max); dtrace_retain_max = 1; } /* * Now discover our toxic ranges. */ dtrace_toxic_ranges(dtrace_toxrange_add); /* * Before we register ourselves as a provider to our own framework, * we would like to assert that dtrace_provider is NULL -- but that's * not true if we were loaded as a dependency of a DTrace provider. * Once we've registered, we can assert that dtrace_provider is our * pseudo provider. */ (void) dtrace_register("dtrace", &dtrace_provider_attr, DTRACE_PRIV_NONE, 0, &dtrace_provider_ops, NULL, &id); ASSERT(dtrace_provider != NULL); ASSERT((dtrace_provider_id_t)dtrace_provider == id); dtrace_probeid_begin = dtrace_probe_create((dtrace_provider_id_t) dtrace_provider, NULL, NULL, "BEGIN", 0, NULL); dtrace_probeid_end = dtrace_probe_create((dtrace_provider_id_t) dtrace_provider, NULL, NULL, "END", 0, NULL); dtrace_probeid_error = dtrace_probe_create((dtrace_provider_id_t) dtrace_provider, NULL, NULL, "ERROR", 1, NULL); mutex_exit(&cpu_lock); /* * If DTrace helper tracing is enabled, we need to allocate the * trace buffer and initialize the values. */ if (dtrace_helptrace_enabled) { ASSERT(dtrace_helptrace_buffer == NULL); dtrace_helptrace_buffer = kmem_zalloc(dtrace_helptrace_bufsize, KM_SLEEP); dtrace_helptrace_next = 0; dtrace_helptrace_size = dtrace_helptrace_bufsize; } mutex_exit(&dtrace_lock); mutex_exit(&dtrace_provider_lock); mutex_enter(&cpu_lock); /* Setup the CPUs */ for (CPU_INFO_FOREACH(cpuind, cinfo)) { (void) dtrace_cpu_setup(CPU_CONFIG, cpu_index(cinfo)); } mutex_exit(&cpu_lock); dtrace_anon_init(NULL); #if 0 dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "dtrace/dtrace"); #endif return; }
static int machtrace_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } #if !defined(__APPLE__) machtrace_probe = (void (*)())dtrace_probe; membar_enter(); if (ddi_create_minor_node(devi, "machtrace", S_IFCHR, 0, DDI_PSEUDO, NULL) == DDI_FAILURE || dtrace_register("mach_trap", &machtrace_attr, DTRACE_PRIV_USER, NULL, &machtrace_pops, NULL, &machtrace_id) != 0) { machtrace_probe = systrace_stub; #else machtrace_probe = dtrace_probe; membar_enter(); if (ddi_create_minor_node(devi, "machtrace", S_IFCHR, 0, DDI_PSEUDO, 0) == DDI_FAILURE || dtrace_register("mach_trap", &machtrace_attr, DTRACE_PRIV_USER, NULL, &machtrace_pops, NULL, &machtrace_id) != 0) { machtrace_probe = (void (*))&systrace_stub; #endif /* __APPLE__ */ ddi_remove_minor_node(devi, NULL); return (DDI_FAILURE); } ddi_report_dev(devi); machtrace_devi = devi; return (DDI_SUCCESS); } d_open_t _systrace_open; int _systrace_open(dev_t dev, int flags, int devtype, struct proc *p) { #pragma unused(dev,flags,devtype,p) return 0; } #define SYSTRACE_MAJOR -24 /* let the kernel pick the device number */ /* * A struct describing which functions will get invoked for certain * actions. */ static struct cdevsw systrace_cdevsw = { _systrace_open, /* open */ eno_opcl, /* close */ eno_rdwrt, /* read */ eno_rdwrt, /* write */ eno_ioctl, /* ioctl */ (stop_fcn_t *)nulldev, /* stop */ (reset_fcn_t *)nulldev, /* reset */ NULL, /* tty's */ eno_select, /* select */ eno_mmap, /* mmap */ eno_strat, /* strategy */ eno_getc, /* getc */ eno_putc, /* putc */ 0 /* type */ }; static int gSysTraceInited = 0; void systrace_init( void ); void systrace_init( void ) { if (0 == gSysTraceInited) { int majdevno = cdevsw_add(SYSTRACE_MAJOR, &systrace_cdevsw); if (majdevno < 0) { printf("systrace_init: failed to allocate a major number!\n"); gSysTraceInited = 0; return; } systrace_attach( (dev_info_t *)(uintptr_t)majdevno, DDI_ATTACH ); machtrace_attach( (dev_info_t *)(uintptr_t)majdevno, DDI_ATTACH ); gSysTraceInited = 1; } else panic("systrace_init: called twice!\n"); } #undef SYSTRACE_MAJOR #endif /* __APPLE__ */ static uint64_t systrace_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes) { #pragma unused(arg,id,parg,aframes) /* __APPLE__ */ uint64_t val = 0; syscall_arg_t *stack = (syscall_arg_t *)NULL; uthread_t uthread = (uthread_t)get_bsdthread_info(current_thread()); if (uthread) stack = (syscall_arg_t *)uthread->t_dtrace_syscall_args; if (!stack) return(0); DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); /* dtrace_probe arguments arg0 .. arg4 are 64bits wide */ val = (uint64_t)*(stack+argno); DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); return (val); }
static void dtrace_load(void *dummy) { dtrace_provider_id_t id; /* Hook into the trap handler. */ dtrace_trap_func = dtrace_trap; /* Hang our hook for thread switches. */ dtrace_vtime_switch_func = dtrace_vtime_switch; /* Hang our hook for exceptions. */ dtrace_invop_init(); dtrace_taskq = taskq_create("dtrace_taskq", 1, maxclsyspri, 0, 0, 0); dtrace_arena = new_unrhdr(1, INT_MAX, &dtrace_unr_mtx); /* Register callbacks for linker file load and unload events. */ dtrace_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, dtrace_kld_load, NULL, EVENTHANDLER_PRI_ANY); dtrace_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try, dtrace_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY); /* * Initialise the mutexes without 'witness' because the dtrace * code is mostly written to wait for memory. To have the * witness code change a malloc() from M_WAITOK to M_NOWAIT * because a lock is held would surely create a panic in a * low memory situation. And that low memory situation might be * the very problem we are trying to trace. */ mutex_init(&dtrace_lock,"dtrace probe state", MUTEX_DEFAULT, NULL); mutex_init(&dtrace_provider_lock,"dtrace provider state", MUTEX_DEFAULT, NULL); mutex_init(&dtrace_meta_lock,"dtrace meta-provider state", MUTEX_DEFAULT, NULL); #ifdef DEBUG mutex_init(&dtrace_errlock,"dtrace error lock", MUTEX_DEFAULT, NULL); #endif mutex_enter(&dtrace_provider_lock); mutex_enter(&dtrace_lock); mutex_enter(&cpu_lock); ASSERT(MUTEX_HELD(&cpu_lock)); dtrace_state_cache = kmem_cache_create("dtrace_state_cache", sizeof (dtrace_dstate_percpu_t) * NCPU, DTRACE_STATE_ALIGN, NULL, NULL, NULL, NULL, NULL, 0); ASSERT(MUTEX_HELD(&cpu_lock)); dtrace_bymod = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_mod), offsetof(dtrace_probe_t, dtpr_nextmod), offsetof(dtrace_probe_t, dtpr_prevmod)); dtrace_byfunc = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_func), offsetof(dtrace_probe_t, dtpr_nextfunc), offsetof(dtrace_probe_t, dtpr_prevfunc)); dtrace_byname = dtrace_hash_create(offsetof(dtrace_probe_t, dtpr_name), offsetof(dtrace_probe_t, dtpr_nextname), offsetof(dtrace_probe_t, dtpr_prevname)); if (dtrace_retain_max < 1) { cmn_err(CE_WARN, "illegal value (%lu) for dtrace_retain_max; " "setting to 1", dtrace_retain_max); dtrace_retain_max = 1; } /* * Now discover our toxic ranges. */ dtrace_toxic_ranges(dtrace_toxrange_add); /* * Before we register ourselves as a provider to our own framework, * we would like to assert that dtrace_provider is NULL -- but that's * not true if we were loaded as a dependency of a DTrace provider. * Once we've registered, we can assert that dtrace_provider is our * pseudo provider. */ (void) dtrace_register("dtrace", &dtrace_provider_attr, DTRACE_PRIV_NONE, 0, &dtrace_provider_ops, NULL, &id); ASSERT(dtrace_provider != NULL); ASSERT((dtrace_provider_id_t)dtrace_provider == id); dtrace_probeid_begin = dtrace_probe_create((dtrace_provider_id_t) dtrace_provider, NULL, NULL, "BEGIN", 0, NULL); dtrace_probeid_end = dtrace_probe_create((dtrace_provider_id_t) dtrace_provider, NULL, NULL, "END", 0, NULL); dtrace_probeid_error = dtrace_probe_create((dtrace_provider_id_t) dtrace_provider, NULL, NULL, "ERROR", 1, NULL); mutex_exit(&cpu_lock); /* * If DTrace helper tracing is enabled, we need to allocate the * trace buffer and initialize the values. */ if (dtrace_helptrace_enabled) { ASSERT(dtrace_helptrace_buffer == NULL); dtrace_helptrace_buffer = kmem_zalloc(dtrace_helptrace_bufsize, KM_SLEEP); dtrace_helptrace_next = 0; } mutex_exit(&dtrace_lock); mutex_exit(&dtrace_provider_lock); mutex_enter(&cpu_lock); /* Setup the boot CPU */ (void) dtrace_cpu_setup(CPU_CONFIG, 0); mutex_exit(&cpu_lock); #if __FreeBSD_version < 800039 /* Enable device cloning. */ clone_setup(&dtrace_clones); /* Setup device cloning events. */ eh_tag = EVENTHANDLER_REGISTER(dev_clone, dtrace_clone, 0, 1000); #else dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "dtrace/dtrace"); helper_dev = make_dev(&helper_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660, "dtrace/helper"); #endif return; }