Print this page
9936 atomic ops in syscall_mstate() induce significant overhead
9942 zone secflags are not initialized correctly

@@ -19,11 +19,11 @@
  * CDDL HEADER END
  */
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
- * Copyright 2012 Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2018, Joyent, Inc.
  */
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/systm.h>

@@ -414,20 +414,25 @@
         while (newtime < 0) {
                 curtime = gethrtime_unscaled();
                 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;
         kpreempt_disable(); /* don't change CPU while changing CPU's state */
         cpu = CPU;
         ASSERT(cpu == t->t_cpu);
+
+        if (fromms == LMS_USER) {
+                CPU_UARRAY_VAL(z->zone_ustate, cpu->cpu_id,
+                    ZONE_USTATE_UTIME) += newtime;
+        } else if (fromms == LMS_SYSTEM) {
+                CPU_UARRAY_VAL(z->zone_ustate, cpu->cpu_id,
+                    ZONE_USTATE_STIME) += newtime;
+        }
+
         if ((toms != LMS_USER) && (cpu->cpu_mstate != CMS_SYSTEM)) {
                 NEW_CPU_MSTATE(CMS_SYSTEM);
         } else if ((toms == LMS_USER) && (cpu->cpu_mstate != CMS_USER)) {
                 NEW_CPU_MSTATE(CMS_USER);
         }

@@ -651,23 +656,10 @@
                 ms->ms_state_start = curtime;
         } while (atomic_cas_64((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.
          */
         if (state != LMS_SLEEP && state != LMS_STOPPED)
                 ms->ms_prev = state;
 

@@ -674,11 +666,29 @@
         /*
          * Switch CPU microstate if appropriate
          */
 
         kpreempt_disable(); /* MUST disable kpreempt before touching t->cpu */
+
         ASSERT(t->t_cpu == CPU);
+
+        /*
+         * 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) {
+                        CPU_UARRAY_VAL(z->zone_ustate, t->t_cpu->cpu_id,
+                            ZONE_USTATE_UTIME) += ztime;
+                } else if (state == LMS_SYSTEM) {
+                        CPU_UARRAY_VAL(z->zone_ustate, t->t_cpu->cpu_id,
+                            ZONE_USTATE_STIME) += ztime;
+                }
+        }
+
         if (!CPU_ON_INTR(t->t_cpu) && curthread->t_intr == NULL) {
                 if (new_state == LMS_USER && t->t_cpu->cpu_mstate != CMS_USER)
                         new_cpu_mstate(CMS_USER, curtime);
                 else if (new_state != LMS_USER &&
                     t->t_cpu->cpu_mstate != CMS_SYSTEM)

@@ -781,11 +791,17 @@
          * Update the WAIT_CPU timer and per-cpu waitrq total.
          */
         z = ttozone(t);
         waittime = curtime - waitrq;
         ms->ms_acct[LMS_WAIT_CPU] += waittime;
-        atomic_add_64(&z->zone_wtime, waittime);
+
+        /*
+         * We are in a disp context where we're not going to migrate CPUs.
+         */
+        CPU_UARRAY_VAL(z->zone_ustate, CPU->cpu_id,
+            ZONE_USTATE_WTIME) += waittime;
+
         CPU->cpu_waitrq += waittime;
         ms->ms_state_start = curtime;
 }
 
 /*