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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/msacct.c
          +++ new/usr/src/uts/common/os/msacct.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24      - * Copyright 2012 Joyent, Inc.  All rights reserved.
       24 + * Copyright (c) 2018, Joyent, Inc.
  25   25   */
  26   26  
  27   27  #include <sys/types.h>
  28   28  #include <sys/param.h>
  29   29  #include <sys/systm.h>
  30   30  #include <sys/user.h>
  31   31  #include <sys/proc.h>
  32   32  #include <sys/cpuvar.h>
  33   33  #include <sys/thread.h>
  34   34  #include <sys/debug.h>
↓ open down ↓ 374 lines elided ↑ open up ↑
 409  409  
 410  410          ms = &lwp->lwp_mstate;
 411  411          mstimep = &ms->ms_acct[fromms];
 412  412          curtime = gethrtime_unscaled();
 413  413          newtime = curtime - ms->ms_state_start;
 414  414          while (newtime < 0) {
 415  415                  curtime = gethrtime_unscaled();
 416  416                  newtime = curtime - ms->ms_state_start;
 417  417          }
 418  418          *mstimep += newtime;
 419      -        if (fromms == LMS_USER)
 420      -                atomic_add_64(&z->zone_utime, newtime);
 421      -        else if (fromms == LMS_SYSTEM)
 422      -                atomic_add_64(&z->zone_stime, newtime);
 423  419          t->t_mstate = toms;
 424  420          ms->ms_state_start = curtime;
 425  421          ms->ms_prev = fromms;
 426  422          kpreempt_disable(); /* don't change CPU while changing CPU's state */
 427  423          cpu = CPU;
 428  424          ASSERT(cpu == t->t_cpu);
      425 +
      426 +        if (fromms == LMS_USER) {
      427 +                CPU_UARRAY_VAL(z->zone_ustate, cpu->cpu_id,
      428 +                    ZONE_USTATE_UTIME) += newtime;
      429 +        } else if (fromms == LMS_SYSTEM) {
      430 +                CPU_UARRAY_VAL(z->zone_ustate, cpu->cpu_id,
      431 +                    ZONE_USTATE_STIME) += newtime;
      432 +        }
      433 +
 429  434          if ((toms != LMS_USER) && (cpu->cpu_mstate != CMS_SYSTEM)) {
 430  435                  NEW_CPU_MSTATE(CMS_SYSTEM);
 431  436          } else if ((toms == LMS_USER) && (cpu->cpu_mstate != CMS_USER)) {
 432  437                  NEW_CPU_MSTATE(CMS_USER);
 433  438          }
 434  439          kpreempt_enable();
 435  440  }
 436  441  
 437  442  #undef NEW_CPU_MSTATE
 438  443  
↓ open down ↓ 207 lines elided ↑ open up ↑
 646  651                          continue;
 647  652                  }
 648  653                  oldtime = *mstimep;
 649  654                  newtime += oldtime;
 650  655                  t->t_mstate = new_state;
 651  656                  ms->ms_state_start = curtime;
 652  657          } while (atomic_cas_64((uint64_t *)mstimep, oldtime, newtime) !=
 653  658              oldtime);
 654  659  
 655  660          /*
 656      -         * When the system boots the initial startup thread will have a
 657      -         * ms_state_start of 0 which would add a huge system time to the global
 658      -         * zone.  We want to skip aggregating that initial bit of work.
 659      -         */
 660      -        if (origstart != 0) {
 661      -                z = ttozone(t);
 662      -                if (state == LMS_USER)
 663      -                        atomic_add_64(&z->zone_utime, ztime);
 664      -                else if (state == LMS_SYSTEM)
 665      -                        atomic_add_64(&z->zone_stime, ztime);
 666      -        }
 667      -
 668      -        /*
 669  661           * Remember the previous running microstate.
 670  662           */
 671  663          if (state != LMS_SLEEP && state != LMS_STOPPED)
 672  664                  ms->ms_prev = state;
 673  665  
 674  666          /*
 675  667           * Switch CPU microstate if appropriate
 676  668           */
 677  669  
 678  670          kpreempt_disable(); /* MUST disable kpreempt before touching t->cpu */
      671 +
 679  672          ASSERT(t->t_cpu == CPU);
      673 +
      674 +        /*
      675 +         * When the system boots the initial startup thread will have a
      676 +         * ms_state_start of 0 which would add a huge system time to the global
      677 +         * zone.  We want to skip aggregating that initial bit of work.
      678 +         */
      679 +        if (origstart != 0) {
      680 +                z = ttozone(t);
      681 +                if (state == LMS_USER) {
      682 +                        CPU_UARRAY_VAL(z->zone_ustate, t->t_cpu->cpu_id,
      683 +                            ZONE_USTATE_UTIME) += ztime;
      684 +                } else if (state == LMS_SYSTEM) {
      685 +                        CPU_UARRAY_VAL(z->zone_ustate, t->t_cpu->cpu_id,
      686 +                            ZONE_USTATE_STIME) += ztime;
      687 +                }
      688 +        }
      689 +
 680  690          if (!CPU_ON_INTR(t->t_cpu) && curthread->t_intr == NULL) {
 681  691                  if (new_state == LMS_USER && t->t_cpu->cpu_mstate != CMS_USER)
 682  692                          new_cpu_mstate(CMS_USER, curtime);
 683  693                  else if (new_state != LMS_USER &&
 684  694                      t->t_cpu->cpu_mstate != CMS_SYSTEM)
 685  695                          new_cpu_mstate(CMS_SYSTEM, curtime);
 686  696          }
 687  697          kpreempt_enable();
 688  698  
 689  699          return (ms->ms_prev);
↓ open down ↓ 86 lines elided ↑ open up ↑
 776  786                  newtime += oldtime;
 777  787          } while (atomic_cas_64((uint64_t *)mstimep, oldtime, newtime) !=
 778  788              oldtime);
 779  789  
 780  790          /*
 781  791           * Update the WAIT_CPU timer and per-cpu waitrq total.
 782  792           */
 783  793          z = ttozone(t);
 784  794          waittime = curtime - waitrq;
 785  795          ms->ms_acct[LMS_WAIT_CPU] += waittime;
 786      -        atomic_add_64(&z->zone_wtime, waittime);
      796 +
      797 +        /*
      798 +         * We are in a disp context where we're not going to migrate CPUs.
      799 +         */
      800 +        CPU_UARRAY_VAL(z->zone_ustate, CPU->cpu_id,
      801 +            ZONE_USTATE_WTIME) += waittime;
      802 +
 787  803          CPU->cpu_waitrq += waittime;
 788  804          ms->ms_state_start = curtime;
 789  805  }
 790  806  
 791  807  /*
 792  808   * Copy lwp microstate accounting and resource usage information
 793  809   * to the process.  (lwp is terminating)
 794  810   */
 795  811  void
 796  812  term_mstate(kthread_t *t)
↓ open down ↓ 34 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX