/*ARGSUSED*/ uint_t xc_serv(caddr_t arg1, caddr_t arg2) { struct machcpu *mcpup = &(CPU->cpu_m); xc_msg_t *msg; xc_data_t *data; xc_msg_t *xc_waiters = NULL; uint32_t num_waiting = 0; xc_func_t func; xc_arg_t a1; xc_arg_t a2; xc_arg_t a3; uint_t rc = DDI_INTR_UNCLAIMED; while (mcpup->xc_work_cnt != 0) { rc = DDI_INTR_CLAIMED; /* * We may have to wait for a message to arrive. */ for (msg = NULL; msg == NULL; msg = xc_extract(&mcpup->xc_msgbox)) { /* * Alway check for and handle a priority message. */ if (BT_TEST(xc_priority_set, CPU->cpu_id)) { func = xc_priority_data.xc_func; a1 = xc_priority_data.xc_a1; a2 = xc_priority_data.xc_a2; a3 = xc_priority_data.xc_a3; XC_BT_CLEAR(xc_priority_set, CPU->cpu_id); xc_decrement(mcpup); func(a1, a2, a3); if (mcpup->xc_work_cnt == 0) return (rc); } /* * wait for a message to arrive */ SMT_PAUSE(); } /* * process the message */ switch (msg->xc_command) { /* * ASYNC gives back the message immediately, then we do the * function and return with no more waiting. */ case XC_MSG_ASYNC: data = &cpu[msg->xc_master]->cpu_m.xc_data; func = data->xc_func; a1 = data->xc_a1; a2 = data->xc_a2; a3 = data->xc_a3; msg->xc_command = XC_MSG_DONE; xc_insert(&cpu[msg->xc_master]->cpu_m.xc_msgbox, msg); if (func != NULL) (void) (*func)(a1, a2, a3); xc_decrement(mcpup); break; /* * SYNC messages do the call, then send it back to the master * in WAITING mode */ case XC_MSG_SYNC: data = &cpu[msg->xc_master]->cpu_m.xc_data; if (data->xc_func != NULL) (void) (*data->xc_func)(data->xc_a1, data->xc_a2, data->xc_a3); msg->xc_command = XC_MSG_WAITING; xc_insert(&cpu[msg->xc_master]->cpu_m.xc_msgbox, msg); break; /* * WAITING messsages are collected by the master until all * have arrived. Once all arrive, we release them back to * the slaves */ case XC_MSG_WAITING: xc_insert(&xc_waiters, msg); if (++num_waiting < mcpup->xc_wait_cnt) break; while ((msg = xc_extract(&xc_waiters)) != NULL) { msg->xc_command = XC_MSG_RELEASED; xc_insert(&cpu[msg->xc_slave]->cpu_m.xc_msgbox, msg); --num_waiting; } if (num_waiting != 0) panic("wrong number waiting"); mcpup->xc_wait_cnt = 0; break; /* * CALL messages do the function and then, like RELEASE, * send the message is back to master as DONE. */ case XC_MSG_CALL: data = &cpu[msg->xc_master]->cpu_m.xc_data; if (data->xc_func != NULL) (void) (*data->xc_func)(data->xc_a1, data->xc_a2, data->xc_a3); /*FALLTHROUGH*/ case XC_MSG_RELEASED: msg->xc_command = XC_MSG_DONE; xc_insert(&cpu[msg->xc_master]->cpu_m.xc_msgbox, msg); xc_decrement(mcpup); break; /* * DONE means a slave has completely finished up. * Once we collect all the DONE messages, we'll exit * processing too. */ case XC_MSG_DONE: msg->xc_command = XC_MSG_FREE; xc_insert(&mcpup->xc_free, msg); xc_decrement(mcpup); break; case XC_MSG_FREE: panic("free message 0x%p in msgbox", (void *)msg); break; default: panic("bad message 0x%p in msgbox", (void *)msg); break; } } return (rc); }
static int dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) { dtrace_hdl_t *dtp = ddo->ddo_hdl; dof_provider_t dofpv; dof_relohdr_t dofr; dof_secidx_t *dofs; ulong_t xr, nxr; size_t sz; id_t i; if (pvp->pv_flags & DT_PROVIDER_IMPL) { /* * ignore providers that are exported by dtrace(7D) */ return (0); } nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax); dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1)); xr = 1; /* reserve dofs[0] for the provider itself */ /* * For each translator referenced by the provider (pv_xrefs), emit an * exported translator section for it if one hasn't been created yet. */ for (i = 0; i < pvp->pv_xrmax; i++) { if (BT_TEST(pvp->pv_xrefs, i) && dtp->dt_xlatemode == DT_XL_DYNAMIC) { dof_add_translator(ddo, dt_xlator_lookup_id(dtp, i), DOF_SECT_XLEXPORT); dofs[xr++] = ddo->ddo_xlexport[i]; } } dt_buf_reset(dtp, &ddo->ddo_probes); dt_buf_reset(dtp, &ddo->ddo_args); dt_buf_reset(dtp, &ddo->ddo_offs); dt_buf_reset(dtp, &ddo->ddo_enoffs); dt_buf_reset(dtp, &ddo->ddo_rels); (void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo); if (dt_buf_len(&ddo->ddo_probes) == 0) return (dt_set_errno(dtp, EDT_NOPROBES)); dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES, sizeof (uint64_t), 0, sizeof (dof_probe_t), dt_buf_len(&ddo->ddo_probes)); dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_probes, sizeof (uint64_t)); dofpv.dofpv_prargs = dof_add_lsect(ddo, NULL, DOF_SECT_PRARGS, sizeof (uint8_t), 0, sizeof (uint8_t), dt_buf_len(&ddo->ddo_args)); dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_args, sizeof (uint8_t)); dofpv.dofpv_proffs = dof_add_lsect(ddo, NULL, DOF_SECT_PROFFS, sizeof (uint_t), 0, sizeof (uint_t), dt_buf_len(&ddo->ddo_offs)); dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_offs, sizeof (uint_t)); if ((sz = dt_buf_len(&ddo->ddo_enoffs)) != 0) { dofpv.dofpv_prenoffs = dof_add_lsect(ddo, NULL, DOF_SECT_PRENOFFS, sizeof (uint_t), 0, sizeof (uint_t), sz); } else { dofpv.dofpv_prenoffs = DOF_SECT_NONE; } dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_enoffs, sizeof (uint_t)); dofpv.dofpv_strtab = ddo->ddo_strsec; dofpv.dofpv_name = dof_add_string(ddo, pvp->pv_desc.dtvd_name); dofpv.dofpv_provattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_provider); dofpv.dofpv_modattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_mod); dofpv.dofpv_funcattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_func); dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name); dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args); dofs[0] = dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER, sizeof (dof_secidx_t), 0, 0, sizeof (dof_provider_t)); dofr.dofr_strtab = dofpv.dofpv_strtab; dofr.dofr_tgtsec = dofpv.dofpv_probes; dofr.dofr_relsec = dof_add_lsect(ddo, NULL, DOF_SECT_RELTAB, sizeof (uint64_t), 0, sizeof (dof_relodesc_t), dt_buf_len(&ddo->ddo_rels)); dt_buf_concat(dtp, &ddo->ddo_ldata, &ddo->ddo_rels, sizeof (uint64_t)); (void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR, sizeof (dof_secidx_t), 0, 0, sizeof (dof_relohdr_t)); if (nxr != 0 && dtp->dt_xlatemode == DT_XL_DYNAMIC) { (void) dof_add_lsect(ddo, dofs, DOF_SECT_PREXPORT, sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t), sizeof (dof_secidx_t) * (nxr + 1)); } return (0); }
/* * Accumulate media entries from recycler's dat file. */ int DatAccumulate( CsdEntry_t *csd) { size_t size; MediaTable_t *dat_table; MediaEntry_t *datfile_cache; MediaEntry_t *vsn; MediaEntry_t *datfile; /* vsn entry from dat file */ MediaEntry_t *dat; /* vsn entry in samfs dump's dat table */ size_t ngot; int i; int idx; int num_inodes; DatTable_t table; int rval; off_t pos; char *path; int fd; path = csd->ce_datPath; /* path to dat file */ fd = readOpen(path); /* open file descriptor for dat file */ if (fd < 0) { Trace(TR_MISC, "%s '%s', dat file open failed, errno= %d", errmsg1, path, errno); return (-1); } dat_table = csd->ce_table; /* media table generated for dat file */ /* * Need to search from the beginning. Rewind dat file and * the read header again. */ rval = readHeader(fd, path); if (rval != 0) { Trace(TR_MISC, "%s '%s', dat table header read failed", errmsg1, path); DatClose(fd); return (-1); } num_inodes = 0; /* * Read datfile table entries until we find the entry we are * currently processing. */ while (InfiniteLoop) { datfile_cache = NULL; ngot = read(fd, &table, sizeof (DatTable_t)); if (ngot != sizeof (DatTable_t)) { Trace(TR_MISC, "%s '%s', dat table read failed", errmsg1, path); DatClose(fd); return (-1); } if (table.dt_mapmin != dat_table->mt_mapmin) { continue; } if (table.dt_mapchunk != dat_table->mt_mapchunk) { Trace(TR_MISC, "%s '%s', map chunk does not match", errmsg1, path); DatClose(fd); return (-1); } pos = lseek(fd, 0, SEEK_CUR); Trace(TR_MISC, "[%s] Read dat entries 0x%lx " "count: %d seqnum candidates: %lld-%lld", dat_table->mt_name, pos, table.dt_count, table.dt_mapmin, table.dt_mapmin + table.dt_mapchunk - 1); size = table.dt_count * sizeof (MediaEntry_t); SamMalloc(datfile_cache, size); (void) memset(datfile_cache, 0, size); for (i = 0; i < table.dt_count; i++) { datfile = &datfile_cache[i]; ngot = read(fd, datfile, sizeof (MediaEntry_t)); if (ngot != sizeof (MediaEntry_t)) { Trace(TR_MISC, "%s '%s', header read error " "read: %d expected: %d, errno= %d", errmsg1, path, ngot, sizeof (MediaEntry_t), errno); num_inodes = -1; goto out; } if ((datfile->me_type == DT_DISK) && (datfile->me_mapsize != 0)) { SamMalloc(datfile->me_bitmap, datfile->me_mapsize); (void) memset(datfile->me_bitmap, 0, datfile->me_mapsize); ngot = read(fd, datfile->me_bitmap, datfile->me_mapsize); if (ngot != datfile->me_mapsize) { Trace(TR_MISC, "%s '%s', bitmap read error " "read: %d expected: %d, errno= %d", errmsg1, path, ngot, datfile->me_mapsize, errno); num_inodes = -1; goto out; } } vsn = MediaFind(&ArchMedia, datfile->me_type, datfile->me_name); if (vsn == NULL) { Trace(TR_MISC, "%s '%s', failed to find vsn %s.%s", errmsg1, path, sam_mediatoa(datfile->me_type), datfile->me_name); num_inodes = -1; goto out; } /* * For completeness, update in-memory's dat_table for * samfs dump file. This is not really necessary but * might be useful for debugging purposes. */ dat = NULL; if (dat_table != NULL) { dat = MediaFind(dat_table, datfile->me_type, datfile->me_name); if (dat == NULL) { Trace(TR_MISC, "Error failed to find vsn %s.%s", sam_mediatoa(datfile->me_type), datfile->me_name); num_inodes = -1; goto out; } } Trace(TR_SAMDEV, "[%s.%s] Accumulate dat active files: %d", sam_mediatoa(vsn->me_type), vsn->me_name, datfile->me_files); PthreadMutexLock(&vsn->me_mutex); vsn->me_files += datfile->me_files; PthreadMutexUnlock(&vsn->me_mutex); if (dat != NULL) { PthreadMutexLock(&dat->me_mutex); dat->me_files += datfile->me_files; PthreadMutexUnlock(&dat->me_mutex); } num_inodes += datfile->me_files; if ((datfile->me_type == DT_DISK) && (datfile->me_mapsize != 0)) { for (idx = 0; idx <= dat_table->mt_mapchunk; idx++) { /* FIXME */ if (BT_TEST(datfile->me_bitmap, idx) == 1) { PthreadMutexLock(&vsn->me_mutex); BT_SET(vsn->me_bitmap, idx); PthreadMutexUnlock(&vsn->me_mutex); if (dat != NULL) { PthreadMutexLock(&dat->me_mutex); BT_SET(dat->me_bitmap, idx); PthreadMutexUnlock(&dat->me_mutex); } } } } /* * Free memory allocated for bitmap read from disk. */ if (datfile->me_bitmap != NULL) { SamFree(datfile->me_bitmap); datfile->me_bitmap = NULL; } } break; } out: if (datfile_cache != NULL) { SamFree(datfile_cache); for (i = 0; i < table.dt_count; i++) { datfile = &datfile_cache[i]; if (datfile->me_bitmap != NULL) { SamFree(datfile->me_bitmap); datfile->me_bitmap = NULL; } } } DatClose(fd); return (num_inodes); }
void exacct_calculate_proc_usage(proc_t *p, proc_usage_t *pu, ulong_t *mask, int flag, int wstat) { timestruc_t ts, ts_run; ASSERT(MUTEX_HELD(&p->p_lock)); /* * Convert CPU and execution times to sec/nsec format. */ if (BT_TEST(mask, AC_PROC_CPU)) { hrt2ts(mstate_aggr_state(p, LMS_USER), &ts); pu->pu_utimesec = (uint64_t)(ulong_t)ts.tv_sec; pu->pu_utimensec = (uint64_t)(ulong_t)ts.tv_nsec; hrt2ts(mstate_aggr_state(p, LMS_SYSTEM), &ts); pu->pu_stimesec = (uint64_t)(ulong_t)ts.tv_sec; pu->pu_stimensec = (uint64_t)(ulong_t)ts.tv_nsec; } if (BT_TEST(mask, AC_PROC_TIME)) { gethrestime(&ts); pu->pu_finishsec = (uint64_t)(ulong_t)ts.tv_sec; pu->pu_finishnsec = (uint64_t)(ulong_t)ts.tv_nsec; hrt2ts(gethrtime() - p->p_mstart, &ts_run); ts.tv_sec -= ts_run.tv_sec; ts.tv_nsec -= ts_run.tv_nsec; if (ts.tv_nsec < 0) { ts.tv_sec--; if ((ts.tv_nsec = ts.tv_nsec + NANOSEC) >= NANOSEC) { ts.tv_sec++; ts.tv_nsec -= NANOSEC; } } pu->pu_startsec = (uint64_t)(ulong_t)ts.tv_sec; pu->pu_startnsec = (uint64_t)(ulong_t)ts.tv_nsec; } pu->pu_pid = p->p_pidp->pid_id; pu->pu_acflag = p->p_user.u_acflag; pu->pu_projid = p->p_task->tk_proj->kpj_id; pu->pu_taskid = p->p_task->tk_tkid; pu->pu_major = getmajor(p->p_sessp->s_dev); pu->pu_minor = getminor(p->p_sessp->s_dev); pu->pu_ancpid = p->p_ancpid; pu->pu_wstat = wstat; /* * Compute average RSS in K. The denominator is the number of * samples: the number of clock ticks plus the initial value. */ pu->pu_mem_rss_avg = (PTOU(p)->u_mem / (p->p_stime + p->p_utime + 1)) * (PAGESIZE / 1024); pu->pu_mem_rss_max = PTOU(p)->u_mem_max * (PAGESIZE / 1024); mutex_enter(&p->p_crlock); pu->pu_ruid = crgetruid(p->p_cred); pu->pu_rgid = crgetrgid(p->p_cred); mutex_exit(&p->p_crlock); bcopy(p->p_user.u_comm, pu->pu_command, strlen(p->p_user.u_comm) + 1); bcopy(p->p_zone->zone_name, pu->pu_zonename, strlen(p->p_zone->zone_name) + 1); bcopy(p->p_zone->zone_nodename, pu->pu_nodename, strlen(p->p_zone->zone_nodename) + 1); /* * Calculate microstate accounting data for a process that is still * running. Presently, we explicitly collect all of the LWP usage into * the proc usage structure here. */ if (flag & EW_PARTIAL) exacct_calculate_proc_mstate(p, pu); if (flag & EW_FINAL) exacct_copy_proc_mstate(p, pu); }
/*ARGSUSED*/ static faultcode_t segkmem_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t size, enum fault_type type, enum seg_rw rw) { pgcnt_t npages; spgcnt_t pg; page_t *pp; struct vnode *vp = seg->s_data; ASSERT(RW_READ_HELD(&seg->s_as->a_lock)); if (seg->s_as != &kas || size > seg->s_size || addr < seg->s_base || addr + size > seg->s_base + seg->s_size) panic("segkmem_fault: bad args"); /* * If it is one of segkp pages, call segkp_fault. */ if (segkp_bitmap && seg == &kvseg && BT_TEST(segkp_bitmap, btop((uintptr_t)(addr - seg->s_base)))) return (SEGOP_FAULT(hat, segkp, addr, size, type, rw)); if (rw != S_READ && rw != S_WRITE && rw != S_OTHER) return (FC_NOSUPPORT); npages = btopr(size); switch (type) { case F_SOFTLOCK: /* lock down already-loaded translations */ for (pg = 0; pg < npages; pg++) { pp = page_lookup(vp, (u_offset_t)(uintptr_t)addr, SE_SHARED); if (pp == NULL) { /* * Hmm, no page. Does a kernel mapping * exist for it? */ if (!hat_probe(kas.a_hat, addr)) { addr -= PAGESIZE; while (--pg >= 0) { pp = page_find(vp, (u_offset_t) (uintptr_t)addr); if (pp) page_unlock(pp); addr -= PAGESIZE; } return (FC_NOMAP); } } addr += PAGESIZE; } if (rw == S_OTHER) hat_reserve(seg->s_as, addr, size); return (0); case F_SOFTUNLOCK: while (npages--) { pp = page_find(vp, (u_offset_t)(uintptr_t)addr); if (pp) page_unlock(pp); addr += PAGESIZE; } return (0); default: return (FC_NOSUPPORT); } /*NOTREACHED*/ }
/* * Install/uninstall ACPI system event handler for child objects of hdl. * Return DDI_SUCCESS on success, and DDI_FAILURE on failure. */ static int acpinex_event_walk(boolean_t init, acpinex_softstate_t *sp, ACPI_HANDLE hdl) { int rc; int retval = DDI_SUCCESS; dev_info_t *dip; ACPI_HANDLE child = NULL; ACPI_OBJECT_TYPE type; ACPI_DEVICE_INFO *infop; acpidev_data_handle_t dhdl; /* Walk all child objects. */ ASSERT(hdl != NULL); while (ACPI_SUCCESS(AcpiGetNextObject(ACPI_TYPE_ANY, hdl, child, &child))) { /* Skip unwanted object types. */ if (ACPI_FAILURE(AcpiGetType(child, &type)) || type > ACPI_TYPE_NS_NODE_MAX || BT_TEST(acpinex_object_type_mask, type) == 0) { continue; } /* Get data associated with the object. Skip it if fails. */ dhdl = acpidev_data_get_handle(child); if (dhdl == NULL) { ACPINEX_DEBUG(CE_NOTE, "!acpinex: failed to get data " "associated with %p, skip.", child); continue; } /* Query ACPI object info for the object. */ if (ACPI_FAILURE(AcpiGetObjectInfo(child, &infop))) { cmn_err(CE_WARN, "!acpidnex: failed to get object info for %p.", child); continue; } if (init) { rc = acpinex_event_install_handler(child, sp, infop, dhdl); if (rc != DDI_SUCCESS) { ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to " "install handler for child %p of %s.", child, sp->ans_path); retval = DDI_FAILURE; /* * Try to handle descendants if both of the * following two conditions are true: * 1) Device corresponding to the current object is * enabled. If the device is absent/disabled, * no notification should be generated from * descendant objects of it. * 2) No Solaris device node has been created for the * current object yet. If the device node has been * created for the current object, notification * events from child objects should be handled by * the corresponding driver. */ } else if (acpidev_check_device_enabled( acpidev_data_get_status(dhdl)) && ACPI_FAILURE(acpica_get_devinfo(child, &dip))) { rc = acpinex_event_walk(B_TRUE, sp, child); if (rc != DDI_SUCCESS) { ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to install " "handler for descendants of %s.", sp->ans_path); retval = DDI_FAILURE; } } } else { rc = DDI_SUCCESS; /* Uninstall handler for descendants if needed. */ if (ACPI_FAILURE(acpica_get_devinfo(child, &dip))) { rc = acpinex_event_walk(B_FALSE, sp, child); } if (rc == DDI_SUCCESS) { rc = acpinex_event_uninstall_handler(child, infop, dhdl); } /* Undo will be done by caller in case of failure. */ if (rc != DDI_SUCCESS) { ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to " "uninstall handler for descendants of %s.", sp->ans_path); AcpiOsFree(infop); retval = DDI_FAILURE; break; } } /* Release cached resources. */ AcpiOsFree(infop); } return (retval); }