Ejemplo n.º 1
0
/*
 * Get the time accounting information for the calling LWP.
 */
int
lwp_info(timestruc_t *tvp)
{
	timestruc_t tv[2];
	hrtime_t hrutime, hrstime;
	klwp_t *lwp = ttolwp(curthread);

	hrutime = lwp->lwp_mstate.ms_acct[LMS_USER];
	hrstime = lwp->lwp_mstate.ms_acct[LMS_SYSTEM] +
	    lwp->lwp_mstate.ms_acct[LMS_TRAP];
	scalehrtime(&hrutime);
	scalehrtime(&hrstime);

	hrt2ts(hrutime, &tv[0]);
	hrt2ts(hrstime, &tv[1]);

	if (get_udatamodel() == DATAMODEL_NATIVE) {
		if (copyout(tv, tvp, sizeof (tv)))
			return (set_errno(EFAULT));
	} else {
		timestruc32_t tv32[2];

		if (TIMESPEC_OVERFLOW(&tv[0]) ||
		    TIMESPEC_OVERFLOW(&tv[1]))
			return (set_errno(EOVERFLOW));	/* unlikely */

		TIMESPEC_TO_TIMESPEC32(&tv32[0], &tv[0]);
		TIMESPEC_TO_TIMESPEC32(&tv32[1], &tv[1]);

		if (copyout(tv32, tvp, sizeof (tv32)))
			return (set_errno(EFAULT));
	}
	return (0);
}
Ejemplo n.º 2
0
/*
 * Given a source tick, stick, and tod value, set the tick and stick offsets
 * such that the (current physical register value) + offset == (source value)
 * and in addition account for some variation between the %tick/%stick on
 * different CPUs. We account for this variation by adding in double the value
 * of suspend_tick_stick_max_delta. The following is an explanation of why
 * suspend_tick_stick_max_delta must be multplied by two and added to
 * native_stick_offset.
 *
 * Consider a guest instance that is yet to be suspended with CPUs p0 and p1
 * with physical "source" %stick values s0 and s1 respectively. When the guest
 * is first resumed, the physical "target" %stick values are t0 and t1
 * respectively. The virtual %stick values after the resume are v0 and v1
 * respectively. Let x be the maximum difference between any two CPU's %stick
 * register at a given point in time and let the %stick values be assigned
 * such that
 *
 *     s1 = s0 + x and
 *     t1 = t0 - x
 *
 * Let us assume that p0 is driving the suspend and resume. Then, we will
 * calculate the stick offset f and the virtual %stick on p0 after the
 * resume as follows.
 *
 *      f = s0 - t0 and
 *     v0 = t0 + f
 *
 * We calculate the virtual %stick v1 on p1 after the resume as
 *
 *     v1 = t1 + f
 *
 * Substitution yields
 *
 *     v1 = t1 + (s0 - t0)
 *     v1 = (t0 - x) + (s0 - t0)
 *     v1 = -x + s0
 *     v1 = s0 - x
 *     v1 = (s1 - x) - x
 *     v1 = s1 - 2x
 *
 * Therefore, in this scenario, without accounting for %stick variation in
 * the calculation of the native_stick_offset f, the virtual %stick on p1
 * is less than the value of the %stick on p1 before the suspend which is
 * unacceptable. By adding 2x to v1, we guarantee it will be equal to s1
 * which means the %stick on p1 after the resume will always be greater
 * than or equal to the %stick on p1 before the suspend. Since v1 = t1 + f
 * at any point in time, we can accomplish this by adding 2x to f. This
 * guarantees any processes bound to CPU P0 or P1 will not see a %stick
 * decrease across a suspend/resume. Hence, in the code below, we multiply
 * suspend_tick_stick_max_delta by two in the calculation for
 * native_stick_offset, native_tick_offset, and target_hrtime.
 */
static void
set_tick_offsets(uint64_t source_tick, uint64_t source_stick, timestruc_t *tsp)
{
	uint64_t target_tick;
	uint64_t target_stick;
	hrtime_t source_hrtime;
	hrtime_t target_hrtime;

	/*
	 * Temporarily set the offsets to zero so that the following reads
	 * of the registers will yield physical unadjusted counter values.
	 */
	native_tick_offset = 0;
	native_stick_offset = 0;

	target_tick = gettick_counter();	/* returns %tick */
	target_stick = gettick();		/* returns %stick */

	/*
	 * Calculate the new offsets. In addition to the delta observed on
	 * this CPU, add an additional value. Multiply the %tick/%stick
	 * frequency by suspend_tick_stick_max_delta (us). Then, multiply by 2
	 * to account for a delta between CPUs before the suspend and a
	 * delta between CPUs after the resume.
	 */
	native_tick_offset = (source_tick - target_tick) +
	    (CPU->cpu_curr_clock * suspend_tick_stick_max_delta * 2 / MICROSEC);
	native_stick_offset = (source_stick - target_stick) +
	    (sys_tick_freq * suspend_tick_stick_max_delta * 2 / MICROSEC);

	/*
	 * We've effectively increased %stick and %tick by twice the value
	 * of suspend_tick_stick_max_delta to account for variation across
	 * CPUs. Now adjust the preserved TOD by the same amount.
	 */
	source_hrtime = ts2hrt(tsp);
	target_hrtime = source_hrtime +
	    (suspend_tick_stick_max_delta * 2 * (NANOSEC/MICROSEC));
	hrt2ts(target_hrtime, tsp);
}
Ejemplo n.º 3
0
/*
 * Arrange for the real time profiling signal to be dispatched.
 */
void
realsigprof(int sysnum, int error)
{
	proc_t *p;
	klwp_t *lwp;

	if (curthread->t_rprof->rp_anystate == 0)
		return;
	p = ttoproc(curthread);
	lwp = ttolwp(curthread);
	mutex_enter(&p->p_lock);
	if (sigismember(&p->p_ignore, SIGPROF) ||
	    signal_is_blocked(curthread, SIGPROF)) {
		mutex_exit(&p->p_lock);
		return;
	}
	lwp->lwp_siginfo.si_signo = SIGPROF;
	lwp->lwp_siginfo.si_code = PROF_SIG;
	lwp->lwp_siginfo.si_errno = error;
	hrt2ts(gethrtime(), &lwp->lwp_siginfo.si_tstamp);
	lwp->lwp_siginfo.si_syscall = sysnum;
	lwp->lwp_siginfo.si_nsysarg = (sysnum > 0 && sysnum < NSYSCALL) ?
		LWP_GETSYSENT(lwp)[sysnum].sy_narg : 0;
	lwp->lwp_siginfo.si_fault = lwp->lwp_lastfault;
	lwp->lwp_siginfo.si_faddr = lwp->lwp_lastfaddr;
	lwp->lwp_lastfault = 0;
	lwp->lwp_lastfaddr = NULL;
	sigtoproc(p, curthread, SIGPROF);
	mutex_exit(&p->p_lock);
	ASSERT(lwp->lwp_cursig == 0);
	if (issig(FORREAL)) {
		psig();
	}
	mutex_enter(&p->p_lock);
	lwp->lwp_siginfo.si_signo = 0;
	bzero(curthread->t_rprof, sizeof (*curthread->t_rprof));
	mutex_exit(&p->p_lock);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
static int
exacct_attach_task_item(task_t *tk, task_usage_t *tu, ea_object_t *record,
    int res)
{
	int attached = 1;

	switch (res) {
	case AC_TASK_TASKID:
		(void) ea_attach_item(record, &tk->tk_tkid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_TASK_TASKID);
		break;
	case AC_TASK_PROJID:
		(void) ea_attach_item(record, &tk->tk_proj->kpj_id,
		    sizeof (uint32_t), EXT_UINT32 | EXD_TASK_PROJID);
		break;
	case AC_TASK_CPU: {
			timestruc_t ts;
			uint64_t ui;

			hrt2ts(tu->tu_stime, &ts);
			ui = ts.tv_sec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_SYS_SEC);
			ui = ts.tv_nsec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_SYS_NSEC);

			hrt2ts(tu->tu_utime, &ts);
			ui = ts.tv_sec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_USER_SEC);
			ui = ts.tv_nsec;
			(void) ea_attach_item(record, &ui, sizeof (uint64_t),
			    EXT_UINT64 | EXD_TASK_CPU_USER_NSEC);
		}
		break;
	case AC_TASK_TIME:
		(void) ea_attach_item(record, &tu->tu_startsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_START_SEC);
		(void) ea_attach_item(record, &tu->tu_startnsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_START_NSEC);
		(void) ea_attach_item(record, &tu->tu_finishsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FINISH_SEC);
		(void) ea_attach_item(record, &tu->tu_finishnsec,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FINISH_NSEC);
		break;
	case AC_TASK_HOSTNAME:
		(void) ea_attach_item(record, tk->tk_zone->zone_nodename,
		    strlen(tk->tk_zone->zone_nodename) + 1,
		    EXT_STRING | EXD_TASK_HOSTNAME);
			break;
	case AC_TASK_MICROSTATE:
		(void) ea_attach_item(record, &tu->tu_majflt,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FAULTS_MAJOR);
		(void) ea_attach_item(record, &tu->tu_minflt,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_FAULTS_MINOR);
		(void) ea_attach_item(record, &tu->tu_sndmsg,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_MESSAGES_SND);
		(void) ea_attach_item(record, &tu->tu_rcvmsg,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_MESSAGES_RCV);
		(void) ea_attach_item(record, &tu->tu_iblk,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_BLOCKS_IN);
		(void) ea_attach_item(record, &tu->tu_oblk,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_BLOCKS_OUT);
		(void) ea_attach_item(record, &tu->tu_ioch,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_CHARS_RDWR);
		(void) ea_attach_item(record, &tu->tu_vcsw,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_CONTEXT_VOL);
		(void) ea_attach_item(record, &tu->tu_icsw,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_CONTEXT_INV);
		(void) ea_attach_item(record, &tu->tu_nsig,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_SIGNALS);
		(void) ea_attach_item(record, &tu->tu_nswp,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_SWAPS);
		(void) ea_attach_item(record, &tu->tu_nscl,
		    sizeof (uint64_t), EXT_UINT64 | EXD_TASK_SYSCALLS);
		break;
	case AC_TASK_ANCTASKID:
		(void) ea_attach_item(record, &tu->tu_anctaskid,
		    sizeof (uint32_t), EXT_UINT32 | EXD_TASK_ANCTASKID);
		break;
	case AC_TASK_ZONENAME:
		(void) ea_attach_item(record, tk->tk_zone->zone_name,
		    strlen(tk->tk_zone->zone_name) + 1,
		    EXT_STRING | EXD_TASK_ZONENAME);
		break;
	default:
		attached = 0;
	}
	return (attached);
}
Ejemplo n.º 6
0
static int
look(pid_t pid)
{
	char pathname[PATH_MAX];
	int rval = 0;
	int fd;
	psinfo_t psinfo;
	prusage_t prusage;
	timestruc_t real, user, sys;
	hrtime_t hrtime;
	prusage_t *pup = &prusage;

	pfirst++;

	if (proc_get_psinfo(pid, &psinfo) < 0)
		return (perr("read psinfo"));

	(void) proc_snprintf(pathname, sizeof (pathname), "/proc/%d/usage",
	    (int)pid);
	if ((fd = open(pathname, O_RDONLY)) < 0)
		return (perr("open usage"));

	if (read(fd, &prusage, sizeof (prusage)) != sizeof (prusage))
		rval = perr("read usage");
	else {
		if (pidarg) {
			hrtime = gethrtime();
			hrt2ts(hrtime, &real);
		} else {
			real = pup->pr_term;
		}
		tssub(&real, &real, &pup->pr_create);
		user = pup->pr_utime;
		sys = pup->pr_stime;
		if (!mflag)
			tsadd(&sys, &sys, &pup->pr_ttime);

		if (!pflag || pfirst > 1)
			(void) fprintf(stderr, "\n");
		if (pflag)
			(void) fprintf(stderr, "%d:\t%.70s\n",
			    (int)psinfo.pr_pid, psinfo.pr_psargs);
		prtime("real", &real);
		prtime("user", &user);
		prtime("sys", &sys);

		if (mflag) {
			prtime("trap", &pup->pr_ttime);
			prtime("tflt", &pup->pr_tftime);
			prtime("dflt", &pup->pr_dftime);
			prtime("kflt", &pup->pr_kftime);
			prtime("lock", &pup->pr_ltime);
			prtime("slp", &pup->pr_slptime);
			prtime("lat", &pup->pr_wtime);
			prtime("stop", &pup->pr_stoptime);
		}
	}

	(void) close(fd);
	return (rval);
}