The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/tools/lockstat/lockstat.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include <mach/mach.h>
    2 #include <stdlib.h>
    3 #include <stdio.h>
    4 #include <signal.h>
    5 #include <unistd.h>
    6 #include <sys/time.h>
    7 #include <time.h>
    8 #include <mach/error.h>
    9 #include <mach/mach_error.h>
   10 #include <mach/mig_errors.h>
   11 #include <mach/machine.h>
   12 #include <mach/processor_info.h>
   13 #include <assert.h>
   14 #include <nlist.h>
   15 #include <fcntl.h>
   16 #include <string.h>
   17 #include <mach/mach.h>
   18 #include <mach/host_info.h>
   19 
   20 /*
   21  *      lockstat.c
   22  *
   23  *      Utility to display kernel lock contention statistics.
   24  *      Usage:
   25  *      lockstat [all, spin, mutex, rw, <lock group name>] {<repeat interval>} {abs}
   26  *
   27  *      Argument 1 specifies the type of lock to display contention statistics
   28  *      for; alternatively, a lock group (a logically grouped set of locks,
   29  *      which can encompass multiple types of locks) can be specified by name.
   30  *      When argument 1 is "all", statistics are displayed for all lock groups
   31  *      which have statistics enabled.
   32  *      Lock types include mutexes, reader-writer locks and spin locks.
   33  *      Note that support for gathering contention statistics may not be present
   34  *      for all types of locks on all platforms.
   35  *
   36  *      Argument 2 specifies a periodic interval. The program will display an
   37  *      updated list of statistics every <repeat interval> seconds. This
   38  *      argument is optional. The updates display the deltas from the previous
   39  *      set of statistics, unless "abs" is specified as argument 3.
   40  *
   41  *      Argument 3, if "abs", causes the periodically refreshed lock statistics
   42  *      to be displayed as absolute values rather than deltas from the previous
   43  *      display.
   44  *
   45  *      Types of statistics:
   46  *      Acquisitions: These can include both normal acquisitions, as well
   47  *      as acquisition attempts. These are listed in the first column.
   48  *      Examples include calls to lck_mtx_lock and lck_mtx_try_lock
   49  *      Misses: Incremented if  a lock acquisition attempt failed, due to
   50  *      contention.
   51  *      Waits (Meaningful only for lock types that can block): Incremented
   52  *      if a lock acquisition attempt proceeded to block.
   53  *
   54  *      Direct Waits (currently implemented only on i386/x86_64): For adaptive
   55  *      locks, such as mutexes, incremented if the owner of the mutex
   56  *      wasn't active on another processor at the time of the lock
   57  *      attempt. This indicates that no adaptive spin occurred.
   58  */
   59 
   60 /*
   61  * HISTORY
   62  * 2005: Bernard Semeria
   63  *              Created.
   64  * 2006: Derek Kumar
   65  *              Display i386 specific stats, fix incremental display, add
   66  *              explanatory block comment.
   67  */
   68 void usage(void);
   69 void print_spin_hdr(void);
   70 void print_spin(int requested, lockgroup_info_t *lockgroup);
   71 void print_all_spin(lockgroup_info_t *lockgroup);
   72 void print_mutex_hdr(void);
   73 void print_mutex(int requested, lockgroup_info_t *lockgroup);
   74 void print_all_mutex(lockgroup_info_t *lockgroup);
   75 void print_rw_hdr(void);
   76 void print_rw(int requested, lockgroup_info_t *lockgroup);
   77 void print_all_rw(lockgroup_info_t *lockgroup);
   78 void prime_lockgroup_deltas(void);
   79 void get_lockgroup_deltas(void);
   80 
   81 char *pgmname;
   82 mach_port_t host_control;
   83 
   84 lockgroup_info_t        *lockgroup_info, *lockgroup_start, *lockgroup_deltas;
   85 unsigned int            count;
   86 
   87 unsigned int            gDebug = 1;
   88 
   89 int
   90 main(int argc, char **argv)
   91 {
   92         kern_return_t           kr;
   93         int                     arg2;
   94         unsigned int            i;
   95         int                     found;
   96 
   97         setlinebuf(stdout);
   98 
   99         pgmname = argv[0];
  100         gDebug = (NULL != strstr(argv[0], "debug"));
  101 
  102         host_control = mach_host_self();
  103 
  104         kr = host_lockgroup_info(host_control, &lockgroup_info, &count);
  105 
  106         if (kr != KERN_SUCCESS) {
  107                 mach_error("host_statistics", kr);
  108                 exit(EXIT_FAILURE);
  109         }
  110         if (gDebug) {
  111                 printf("count = %d\n", count);
  112                 for (i = 0; i < count; i++) {
  113                         printf("%s\n", lockgroup_info[i].lockgroup_name);
  114                 }
  115         }
  116 
  117         switch (argc) {
  118         case 2:
  119                 if (strcmp(argv[1], "all") == 0) {
  120                         print_spin_hdr();
  121                         print_all_spin(lockgroup_info);
  122                         print_mutex_hdr();
  123                         print_all_mutex(lockgroup_info);
  124                         print_rw_hdr();
  125                         print_all_rw(lockgroup_info);
  126                 } else if (strcmp(argv[1], "spin") == 0) {
  127                         print_spin_hdr();
  128                         print_all_spin(lockgroup_info);
  129                 } else if (strcmp(argv[1], "mutex") == 0) {
  130                         print_mutex_hdr();
  131                         print_all_mutex(lockgroup_info);
  132                 } else if (strcmp(argv[1], "rw") == 0) {
  133                         print_rw_hdr();
  134                         print_all_rw(lockgroup_info);
  135                 } else {
  136                         found = 0;
  137                         for (i = 0; i < count; i++) {
  138                                 if (strcmp(argv[1], lockgroup_info[i].lockgroup_name) == 0) {
  139                                         found = 1;
  140                                         print_spin_hdr();
  141                                         print_spin(i, lockgroup_info);
  142                                         print_mutex_hdr();
  143                                         print_mutex(i, lockgroup_info);
  144                                         print_rw_hdr();
  145                                         print_rw(i, lockgroup_info);
  146                                         break;
  147                                 }
  148                         }
  149                         if (found == 0) {
  150                                 usage();
  151                         }
  152                 }
  153                 break;
  154         case 3:
  155                 if (sscanf(argv[2], "%d", &arg2) != 1) {
  156                         usage();
  157                 }
  158                 if (arg2 < 0) {
  159                         usage();
  160                 }
  161                 prime_lockgroup_deltas();
  162                 if (strcmp(argv[1], "all") == 0) {
  163                         while (1) {
  164                                 sleep(arg2);
  165                                 get_lockgroup_deltas();
  166                                 print_spin_hdr();
  167                                 print_all_spin(lockgroup_deltas);
  168                                 print_mutex_hdr();
  169                                 print_all_mutex(lockgroup_deltas);
  170                                 print_rw_hdr();
  171                                 print_all_rw(lockgroup_deltas);
  172                         }
  173                 } else if (strcmp(argv[1], "spin") == 0) {
  174                         while (1) {
  175                                 sleep(arg2);
  176                                 get_lockgroup_deltas();
  177                                 print_spin_hdr();
  178                                 print_all_spin(lockgroup_deltas);
  179                         }
  180                 } else if (strcmp(argv[1], "mutex") == 0) {
  181                         while (1) {
  182                                 sleep(arg2);
  183                                 get_lockgroup_deltas();
  184                                 print_mutex_hdr();
  185                                 print_all_mutex(lockgroup_deltas);
  186                         }
  187                 } else if (strcmp(argv[1], "rw") == 0) {
  188                         while (1) {
  189                                 sleep(arg2);
  190                                 get_lockgroup_deltas();
  191                                 print_rw_hdr();
  192                                 print_all_rw(lockgroup_deltas);
  193                         }
  194                 } else {
  195                         found = 0;
  196                         for (i = 0; i < count; i++) {
  197                                 if (strcmp(argv[1], lockgroup_info[i].lockgroup_name) == 0) {
  198                                         found = 1;
  199                                         while (1) {
  200                                                 sleep(arg2);
  201                                                 get_lockgroup_deltas();
  202                                                 print_spin_hdr();
  203                                                 print_spin(i, lockgroup_deltas);
  204                                                 print_mutex_hdr();
  205                                                 print_mutex(i, lockgroup_deltas);
  206                                                 print_rw_hdr();
  207                                                 print_rw(i, lockgroup_deltas);
  208                                         }
  209                                 }
  210                         }
  211                         if (found == 0) {
  212                                 usage();
  213                         }
  214                 }
  215                 break;
  216         case 4:
  217                 if (strcmp(argv[3], "abs") != 0) {
  218                         usage();
  219                 }
  220                 if (sscanf(argv[2], "%d", &arg2) != 1) {
  221                         usage();
  222                 }
  223                 if (strcmp(argv[1], "all") == 0) {
  224                         while (1) {
  225                                 print_spin_hdr();
  226                                 print_all_spin(lockgroup_info);
  227                                 print_mutex_hdr();
  228                                 print_all_mutex(lockgroup_info);
  229                                 print_rw_hdr();
  230                                 print_all_rw(lockgroup_info);
  231                                 sleep(arg2);
  232                         }
  233                 } else if (strcmp(argv[1], "spin") == 0) {
  234                         while (1) {
  235                                 print_all_spin(lockgroup_info);
  236                                 sleep(arg2);
  237                         }
  238                 } else if (strcmp(argv[1], "mutex") == 0) {
  239                         print_mutex_hdr();
  240                         while (1) {
  241                                 print_all_mutex(lockgroup_info);
  242                                 sleep(arg2);
  243                         }
  244                 } else if (strcmp(argv[1], "rw") == 0) {
  245                         print_rw_hdr();
  246                         while (1) {
  247                                 print_all_rw(lockgroup_info);
  248                                 sleep(arg2);
  249                         }
  250                 } else {
  251                         found = 0;
  252                         for (i = 0; i < count; i++) {
  253                                 if (strcmp(argv[1], lockgroup_info[i].lockgroup_name) == 0) {
  254                                         found = 1;
  255                                         while (1) {
  256                                                 print_spin_hdr();
  257                                                 print_spin(i, lockgroup_info);
  258                                                 print_mutex_hdr();
  259                                                 print_mutex(i, lockgroup_info);
  260                                                 print_rw_hdr();
  261                                                 print_rw(i, lockgroup_info);
  262                                                 sleep(arg2);
  263                                         }
  264                                 }
  265                         }
  266                         if (found == 0) {
  267                                 usage();
  268                         }
  269                 }
  270                 break;
  271         default:
  272                 usage();
  273                 break;
  274         }
  275 
  276         exit(0);
  277 }
  278 
  279 void
  280 usage()
  281 {
  282         fprintf(stderr, "Usage: %s [all, spin, mutex, rw, <lock group name>] {<repeat interval>} {abs}\n", pgmname);
  283         exit(EXIT_FAILURE);
  284 }
  285 
  286 void
  287 print_spin_hdr(void)
  288 {
  289         printf("    Spinlock acquires           misses   Name\n");
  290 }
  291 
  292 void
  293 print_spin(int requested, lockgroup_info_t *lockgroup)
  294 {
  295         lockgroup_info_t        *curptr = &lockgroup[requested];
  296 
  297         if (curptr->lock_spin_cnt != 0 && curptr->lock_spin_util_cnt != 0) {
  298                 printf("%16lld ", curptr->lock_spin_util_cnt);
  299                 printf("%16lld   ", curptr->lock_spin_miss_cnt);
  300                 printf("%-14s\n", curptr->lockgroup_name);
  301         }
  302 }
  303 
  304 void
  305 print_all_spin(lockgroup_info_t *lockgroup)
  306 {
  307         unsigned int            i;
  308 
  309         for (i = 0; i < count; i++) {
  310                 print_spin(i, lockgroup);
  311         }
  312         printf("\n");
  313 }
  314 
  315 void
  316 print_mutex_hdr(void)
  317 {
  318 #if defined(__i386__) || defined(__x86_64__)
  319         printf("Mutex lock attempts  Misses      Waits Direct Waits Name\n");
  320 #else
  321         printf("     mutex locks           misses            waits   name\n");
  322 #endif
  323 }
  324 
  325 void
  326 print_mutex(int requested, lockgroup_info_t *lockgroup)
  327 {
  328         lockgroup_info_t        *curptr = &lockgroup[requested];
  329 
  330         if (curptr->lock_mtx_cnt != 0 && curptr->lock_mtx_util_cnt != 0) {
  331                 printf("%16lld ", curptr->lock_mtx_util_cnt);
  332 #if defined(__i386__) || defined(__x86_64__)
  333                 printf("%10lld %10lld %10lld   ", curptr->lock_mtx_miss_cnt, curptr->lock_mtx_wait_cnt, curptr->lock_mtx_held_cnt);
  334 #else
  335                 printf("%16lld %16lld   ", curptr->lock_mtx_miss_cnt, curptr->lock_mtx_wait_cnt);
  336 #endif
  337                 printf("%-14s\n", curptr->lockgroup_name);
  338         }
  339 }
  340 
  341 void
  342 print_all_mutex(lockgroup_info_t *lockgroup)
  343 {
  344         unsigned int            i;
  345 
  346         for (i = 0; i < count; i++) {
  347                 print_mutex(i, lockgroup);
  348         }
  349         printf("\n");
  350 }
  351 
  352 void
  353 print_rw_hdr(void)
  354 {
  355         printf("        RW locks           Misses            Waits   Name\n");
  356 }
  357 
  358 void
  359 print_rw(int requested, lockgroup_info_t *lockgroup)
  360 {
  361         lockgroup_info_t        *curptr = &lockgroup[requested];
  362 
  363         if (curptr->lock_rw_cnt != 0 && curptr->lock_rw_util_cnt != 0) {
  364                 printf("%16lld ", curptr->lock_rw_util_cnt);
  365                 printf("%16lld %16lld   ", curptr->lock_rw_miss_cnt, curptr->lock_rw_wait_cnt);
  366                 printf("%-14s\n", curptr->lockgroup_name);
  367         }
  368 }
  369 
  370 void
  371 print_all_rw(lockgroup_info_t *lockgroup)
  372 {
  373         unsigned int            i;
  374 
  375         for (i = 0; i < count; i++) {
  376                 print_rw(i, lockgroup);
  377         }
  378         printf("\n");
  379 }
  380 
  381 void
  382 prime_lockgroup_deltas(void)
  383 {
  384         lockgroup_start = calloc(count, sizeof(lockgroup_info_t));
  385         if (lockgroup_start == NULL) {
  386                 fprintf(stderr, "Can't allocate memory for lockgroup info\n");
  387                 exit(EXIT_FAILURE);
  388         }
  389         memcpy(lockgroup_start, lockgroup_info, count * sizeof(lockgroup_info_t));
  390 
  391         lockgroup_deltas = calloc(count, sizeof(lockgroup_info_t));
  392         if (lockgroup_deltas == NULL) {
  393                 fprintf(stderr, "Can't allocate memory for lockgroup info\n");
  394                 exit(EXIT_FAILURE);
  395         }
  396 }
  397 
  398 void
  399 get_lockgroup_deltas(void)
  400 {
  401         kern_return_t                   kr;
  402         unsigned int                    i;
  403 
  404         kr = host_lockgroup_info(host_control, &lockgroup_info, &count);
  405 
  406         if (kr != KERN_SUCCESS) {
  407                 mach_error("host_statistics", kr);
  408                 exit(EXIT_FAILURE);
  409         }
  410 
  411         memcpy(lockgroup_deltas, lockgroup_info, count * sizeof(lockgroup_info_t));
  412         for (i = 0; i < count; i++) {
  413                 lockgroup_deltas[i].lock_spin_util_cnt =
  414                     lockgroup_info[i].lock_spin_util_cnt -
  415                     lockgroup_start[i].lock_spin_util_cnt;
  416                 lockgroup_deltas[i].lock_spin_miss_cnt =
  417                     lockgroup_info[i].lock_spin_miss_cnt -
  418                     lockgroup_start[i].lock_spin_miss_cnt;
  419                 lockgroup_deltas[i].lock_mtx_util_cnt =
  420                     lockgroup_info[i].lock_mtx_util_cnt -
  421                     lockgroup_start[i].lock_mtx_util_cnt;
  422                 lockgroup_deltas[i].lock_mtx_miss_cnt =
  423                     lockgroup_info[i].lock_mtx_miss_cnt -
  424                     lockgroup_start[i].lock_mtx_miss_cnt;
  425                 lockgroup_deltas[i].lock_mtx_wait_cnt =
  426                     lockgroup_info[i].lock_mtx_wait_cnt -
  427                     lockgroup_start[i].lock_mtx_wait_cnt;
  428                 lockgroup_deltas[i].lock_mtx_held_cnt =
  429                     lockgroup_info[i].lock_mtx_held_cnt -
  430                     lockgroup_start[i].lock_mtx_held_cnt;
  431                 lockgroup_deltas[i].lock_rw_util_cnt =
  432                     lockgroup_info[i].lock_rw_util_cnt -
  433                     lockgroup_start[i].lock_rw_util_cnt;
  434                 lockgroup_deltas[i].lock_rw_miss_cnt =
  435                     lockgroup_info[i].lock_rw_miss_cnt -
  436                     lockgroup_start[i].lock_rw_miss_cnt;
  437                 lockgroup_deltas[i].lock_rw_wait_cnt =
  438                     lockgroup_info[i].lock_rw_wait_cnt -
  439                     lockgroup_start[i].lock_rw_wait_cnt;
  440         }
  441         memcpy(lockgroup_start, lockgroup_info, count * sizeof(lockgroup_info_t));
  442 }

Cache object: 960db05b7d314063952c9045bd7879fb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.