Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
5003 want kstats for per-zone cpu usage
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Reviewed by: Richard Elling <richard.elling@gmail.com>
Approved by: Rich Lowe <richlowe@richlowe.net>
  • Loading branch information
jjelinek authored and rmustacc committed Jul 16, 2014
1 parent 732efd5 commit 542a813
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 8 deletions.
36 changes: 33 additions & 3 deletions usr/src/uts/common/os/msacct.c
Expand Up @@ -33,6 +33,7 @@
#include <sys/debug.h>
#include <sys/msacct.h>
#include <sys/time.h>
#include <sys/zone.h>

/*
* Mega-theory block comment:
Expand Down Expand Up @@ -390,6 +391,7 @@ void
syscall_mstate(int fromms, int toms)
{
kthread_t *t = curthread;
zone_t *z = ttozone(t);
struct mstate *ms;
hrtime_t *mstimep;
hrtime_t curtime;
Expand All @@ -413,6 +415,10 @@ syscall_mstate(int fromms, int toms)
newtime = curtime - ms->ms_state_start;
}
*mstimep += newtime;
if (fromms == LMS_USER)
atomic_add_64(&z->zone_utime, newtime);
else if (fromms == LMS_SYSTEM)
atomic_add_64(&z->zone_stime, newtime);
t->t_mstate = toms;
ms->ms_state_start = curtime;
ms->ms_prev = fromms;
Expand Down Expand Up @@ -602,7 +608,10 @@ new_mstate(kthread_t *t, int new_state)
hrtime_t curtime;
hrtime_t newtime;
hrtime_t oldtime;
hrtime_t ztime;
hrtime_t origstart;
klwp_t *lwp;
zone_t *z;

ASSERT(new_state != LMS_WAIT_CPU);
ASSERT((unsigned)new_state < NMSTATES);
Expand All @@ -625,6 +634,7 @@ new_mstate(kthread_t *t, int new_state)

ms = &lwp->lwp_mstate;
state = t->t_mstate;
origstart = ms->ms_state_start;
do {
switch (state) {
case LMS_TFAULT:
Expand All @@ -637,7 +647,7 @@ new_mstate(kthread_t *t, int new_state)
mstimep = &ms->ms_acct[state];
break;
}
newtime = curtime - ms->ms_state_start;
ztime = newtime = curtime - ms->ms_state_start;
if (newtime < 0) {
curtime = gethrtime_unscaled();
oldtime = *mstimep - 1; /* force CAS to fail */
Expand All @@ -648,6 +658,20 @@ new_mstate(kthread_t *t, int new_state)
t->t_mstate = new_state;
ms->ms_state_start = curtime;
} while (cas64((uint64_t *)mstimep, oldtime, newtime) != oldtime);

/*
* When the system boots the initial startup thread will have a
* ms_state_start of 0 which would add a huge system time to the global
* zone. We want to skip aggregating that initial bit of work.
*/
if (origstart != 0) {
z = ttozone(t);
if (state == LMS_USER)
atomic_add_64(&z->zone_utime, ztime);
else if (state == LMS_SYSTEM)
atomic_add_64(&z->zone_stime, ztime);
}

/*
* Remember the previous running microstate.
*/
Expand Down Expand Up @@ -686,6 +710,8 @@ restore_mstate(kthread_t *t)
hrtime_t waitrq;
hrtime_t newtime;
hrtime_t oldtime;
hrtime_t waittime;
zone_t *z;

/*
* Don't call restore mstate of threads without lwps. (Kernel threads)
Expand Down Expand Up @@ -756,11 +782,15 @@ restore_mstate(kthread_t *t)
oldtime = *mstimep;
newtime += oldtime;
} while (cas64((uint64_t *)mstimep, oldtime, newtime) != oldtime);

/*
* Update the WAIT_CPU timer and per-cpu waitrq total.
*/
ms->ms_acct[LMS_WAIT_CPU] += (curtime - waitrq);
CPU->cpu_waitrq += (curtime - waitrq);
z = ttozone(t);
waittime = curtime - waitrq;
ms->ms_acct[LMS_WAIT_CPU] += waittime;
atomic_add_64(&z->zone_wtime, waittime);
CPU->cpu_waitrq += waittime;
ms->ms_state_start = curtime;
}

Expand Down
83 changes: 78 additions & 5 deletions usr/src/uts/common/os/zone.c
Expand Up @@ -21,6 +21,7 @@

/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013, Joyent Inc. All rights reserved.
*/

/*
Expand Down Expand Up @@ -1820,6 +1821,63 @@ zone_kstat_create_common(zone_t *zone, char *name,
return (ksp);
}

static int
zone_misc_kstat_update(kstat_t *ksp, int rw)
{
zone_t *zone = ksp->ks_private;
zone_misc_kstat_t *zmp = ksp->ks_data;
hrtime_t tmp;

if (rw == KSTAT_WRITE)
return (EACCES);

tmp = zone->zone_utime;
scalehrtime(&tmp);
zmp->zm_utime.value.ui64 = tmp;
tmp = zone->zone_stime;
scalehrtime(&tmp);
zmp->zm_stime.value.ui64 = tmp;
tmp = zone->zone_wtime;
scalehrtime(&tmp);
zmp->zm_wtime.value.ui64 = tmp;

return (0);
}

static kstat_t *
zone_misc_kstat_create(zone_t *zone)
{
kstat_t *ksp;
zone_misc_kstat_t *zmp;

if ((ksp = kstat_create_zone("zones", zone->zone_id,
zone->zone_name, "zone_misc", KSTAT_TYPE_NAMED,
sizeof (zone_misc_kstat_t) / sizeof (kstat_named_t),
KSTAT_FLAG_VIRTUAL, zone->zone_id)) == NULL)
return (NULL);

if (zone->zone_id != GLOBAL_ZONEID)
kstat_zone_add(ksp, GLOBAL_ZONEID);

zmp = ksp->ks_data = kmem_zalloc(sizeof (zone_misc_kstat_t), KM_SLEEP);
ksp->ks_data_size += strlen(zone->zone_name) + 1;
ksp->ks_lock = &zone->zone_misc_lock;
zone->zone_misc_stats = zmp;

/* The kstat "name" field is not large enough for a full zonename */
kstat_named_init(&zmp->zm_zonename, "zonename", KSTAT_DATA_STRING);
kstat_named_setstr(&zmp->zm_zonename, zone->zone_name);
kstat_named_init(&zmp->zm_utime, "nsec_user", KSTAT_DATA_UINT64);
kstat_named_init(&zmp->zm_stime, "nsec_sys", KSTAT_DATA_UINT64);
kstat_named_init(&zmp->zm_wtime, "nsec_waitrq", KSTAT_DATA_UINT64);

ksp->ks_update = zone_misc_kstat_update;
ksp->ks_private = zone;

kstat_install(ksp);
return (ksp);
}

static void
zone_kstat_create(zone_t *zone)
{
Expand All @@ -1829,27 +1887,37 @@ zone_kstat_create(zone_t *zone)
"swapresv", zone_swapresv_kstat_update);
zone->zone_nprocs_kstat = zone_kstat_create_common(zone,
"nprocs", zone_nprocs_kstat_update);

if ((zone->zone_misc_ksp = zone_misc_kstat_create(zone)) == NULL) {
zone->zone_misc_stats = kmem_zalloc(
sizeof (zone_misc_kstat_t), KM_SLEEP);
}
}

static void
zone_kstat_delete_common(kstat_t **pkstat)
zone_kstat_delete_common(kstat_t **pkstat, size_t datasz)
{
void *data;

if (*pkstat != NULL) {
data = (*pkstat)->ks_data;
kstat_delete(*pkstat);
kmem_free(data, sizeof (zone_kstat_t));
kmem_free(data, datasz);
*pkstat = NULL;
}
}

static void
zone_kstat_delete(zone_t *zone)
{
zone_kstat_delete_common(&zone->zone_lockedmem_kstat);
zone_kstat_delete_common(&zone->zone_swapresv_kstat);
zone_kstat_delete_common(&zone->zone_nprocs_kstat);
zone_kstat_delete_common(&zone->zone_lockedmem_kstat,
sizeof (zone_kstat_t));
zone_kstat_delete_common(&zone->zone_swapresv_kstat,
sizeof (zone_kstat_t));
zone_kstat_delete_common(&zone->zone_nprocs_kstat,
sizeof (zone_kstat_t));
zone_kstat_delete_common(&zone->zone_misc_ksp,
sizeof (zone_misc_kstat_t));
}

/*
Expand Down Expand Up @@ -1907,6 +1975,11 @@ zone_zsd_init(void)
zone0.zone_lockedmem_kstat = NULL;
zone0.zone_swapresv_kstat = NULL;
zone0.zone_nprocs_kstat = NULL;

zone0.zone_stime = 0;
zone0.zone_utime = 0;
zone0.zone_wtime = 0;

list_create(&zone0.zone_ref_list, sizeof (zone_ref_t),
offsetof(zone_ref_t, zref_linkage));
list_create(&zone0.zone_zsd, sizeof (struct zsd_entry),
Expand Down
26 changes: 26 additions & 0 deletions usr/src/uts/common/sys/zone.h
Expand Up @@ -378,6 +378,13 @@ typedef struct zone_kstat {

struct cpucap;

typedef struct {
kstat_named_t zm_zonename; /* full name, kstat truncates name */
kstat_named_t zm_utime;
kstat_named_t zm_stime;
kstat_named_t zm_wtime;
} zone_misc_kstat_t;

typedef struct zone {
/*
* zone_name is never modified once set.
Expand Down Expand Up @@ -539,6 +546,25 @@ typedef struct zone {
/* zone_rctls->rcs_lock */
kstat_t *zone_nprocs_kstat;

/*
* Misc. kstats and counters for zone cpu-usage aggregation.
* The zone_Xtime values are the sum of the micro-state accounting
* values for all threads that are running or have run in the zone.
* This is tracked in msacct.c as threads change state.
* The zone_stime is the sum of the LMS_SYSTEM times.
* The zone_utime is the sum of the LMS_USER times.
* The zone_wtime is the sum of the LMS_WAIT_CPU times.
* As with per-thread micro-state accounting values, these values are
* not scaled to nanosecs. The scaling is done by the
* zone_misc_kstat_update function when kstats are requested.
*/
kmutex_t zone_misc_lock; /* protects misc statistics */
kstat_t *zone_misc_ksp;
zone_misc_kstat_t *zone_misc_stats;
uint64_t zone_stime; /* total system time */
uint64_t zone_utime; /* total user time */
uint64_t zone_wtime; /* total time waiting in runq */

/*
* DTrace-private per-zone state
*/
Expand Down

0 comments on commit 542a813

Please sign in to comment.