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/kernel/lockdep_proc.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 /*
    2  * kernel/lockdep_proc.c
    3  *
    4  * Runtime locking correctness validator
    5  *
    6  * Started by Ingo Molnar:
    7  *
    8  *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
    9  *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
   10  *
   11  * Code for /proc/lockdep and /proc/lockdep_stats:
   12  *
   13  */
   14 #include <linux/export.h>
   15 #include <linux/proc_fs.h>
   16 #include <linux/seq_file.h>
   17 #include <linux/kallsyms.h>
   18 #include <linux/debug_locks.h>
   19 #include <linux/vmalloc.h>
   20 #include <linux/sort.h>
   21 #include <asm/uaccess.h>
   22 #include <asm/div64.h>
   23 
   24 #include "lockdep_internals.h"
   25 
   26 static void *l_next(struct seq_file *m, void *v, loff_t *pos)
   27 {
   28         return seq_list_next(v, &all_lock_classes, pos);
   29 }
   30 
   31 static void *l_start(struct seq_file *m, loff_t *pos)
   32 {
   33         return seq_list_start_head(&all_lock_classes, *pos);
   34 }
   35 
   36 static void l_stop(struct seq_file *m, void *v)
   37 {
   38 }
   39 
   40 static void print_name(struct seq_file *m, struct lock_class *class)
   41 {
   42         char str[KSYM_NAME_LEN];
   43         const char *name = class->name;
   44 
   45         if (!name) {
   46                 name = __get_key_name(class->key, str);
   47                 seq_printf(m, "%s", name);
   48         } else{
   49                 seq_printf(m, "%s", name);
   50                 if (class->name_version > 1)
   51                         seq_printf(m, "#%d", class->name_version);
   52                 if (class->subclass)
   53                         seq_printf(m, "/%d", class->subclass);
   54         }
   55 }
   56 
   57 static int l_show(struct seq_file *m, void *v)
   58 {
   59         struct lock_class *class = list_entry(v, struct lock_class, lock_entry);
   60         struct lock_list *entry;
   61         char usage[LOCK_USAGE_CHARS];
   62 
   63         if (v == &all_lock_classes) {
   64                 seq_printf(m, "all lock classes:\n");
   65                 return 0;
   66         }
   67 
   68         seq_printf(m, "%p", class->key);
   69 #ifdef CONFIG_DEBUG_LOCKDEP
   70         seq_printf(m, " OPS:%8ld", class->ops);
   71 #endif
   72 #ifdef CONFIG_PROVE_LOCKING
   73         seq_printf(m, " FD:%5ld", lockdep_count_forward_deps(class));
   74         seq_printf(m, " BD:%5ld", lockdep_count_backward_deps(class));
   75 #endif
   76 
   77         get_usage_chars(class, usage);
   78         seq_printf(m, " %s", usage);
   79 
   80         seq_printf(m, ": ");
   81         print_name(m, class);
   82         seq_puts(m, "\n");
   83 
   84         list_for_each_entry(entry, &class->locks_after, entry) {
   85                 if (entry->distance == 1) {
   86                         seq_printf(m, " -> [%p] ", entry->class->key);
   87                         print_name(m, entry->class);
   88                         seq_puts(m, "\n");
   89                 }
   90         }
   91         seq_puts(m, "\n");
   92 
   93         return 0;
   94 }
   95 
   96 static const struct seq_operations lockdep_ops = {
   97         .start  = l_start,
   98         .next   = l_next,
   99         .stop   = l_stop,
  100         .show   = l_show,
  101 };
  102 
  103 static int lockdep_open(struct inode *inode, struct file *file)
  104 {
  105         return seq_open(file, &lockdep_ops);
  106 }
  107 
  108 static const struct file_operations proc_lockdep_operations = {
  109         .open           = lockdep_open,
  110         .read           = seq_read,
  111         .llseek         = seq_lseek,
  112         .release        = seq_release,
  113 };
  114 
  115 #ifdef CONFIG_PROVE_LOCKING
  116 static void *lc_start(struct seq_file *m, loff_t *pos)
  117 {
  118         if (*pos == 0)
  119                 return SEQ_START_TOKEN;
  120 
  121         if (*pos - 1 < nr_lock_chains)
  122                 return lock_chains + (*pos - 1);
  123 
  124         return NULL;
  125 }
  126 
  127 static void *lc_next(struct seq_file *m, void *v, loff_t *pos)
  128 {
  129         (*pos)++;
  130         return lc_start(m, pos);
  131 }
  132 
  133 static void lc_stop(struct seq_file *m, void *v)
  134 {
  135 }
  136 
  137 static int lc_show(struct seq_file *m, void *v)
  138 {
  139         struct lock_chain *chain = v;
  140         struct lock_class *class;
  141         int i;
  142 
  143         if (v == SEQ_START_TOKEN) {
  144                 seq_printf(m, "all lock chains:\n");
  145                 return 0;
  146         }
  147 
  148         seq_printf(m, "irq_context: %d\n", chain->irq_context);
  149 
  150         for (i = 0; i < chain->depth; i++) {
  151                 class = lock_chain_get_class(chain, i);
  152                 if (!class->key)
  153                         continue;
  154 
  155                 seq_printf(m, "[%p] ", class->key);
  156                 print_name(m, class);
  157                 seq_puts(m, "\n");
  158         }
  159         seq_puts(m, "\n");
  160 
  161         return 0;
  162 }
  163 
  164 static const struct seq_operations lockdep_chains_ops = {
  165         .start  = lc_start,
  166         .next   = lc_next,
  167         .stop   = lc_stop,
  168         .show   = lc_show,
  169 };
  170 
  171 static int lockdep_chains_open(struct inode *inode, struct file *file)
  172 {
  173         return seq_open(file, &lockdep_chains_ops);
  174 }
  175 
  176 static const struct file_operations proc_lockdep_chains_operations = {
  177         .open           = lockdep_chains_open,
  178         .read           = seq_read,
  179         .llseek         = seq_lseek,
  180         .release        = seq_release,
  181 };
  182 #endif /* CONFIG_PROVE_LOCKING */
  183 
  184 static void lockdep_stats_debug_show(struct seq_file *m)
  185 {
  186 #ifdef CONFIG_DEBUG_LOCKDEP
  187         unsigned long long hi1 = debug_atomic_read(hardirqs_on_events),
  188                            hi2 = debug_atomic_read(hardirqs_off_events),
  189                            hr1 = debug_atomic_read(redundant_hardirqs_on),
  190                            hr2 = debug_atomic_read(redundant_hardirqs_off),
  191                            si1 = debug_atomic_read(softirqs_on_events),
  192                            si2 = debug_atomic_read(softirqs_off_events),
  193                            sr1 = debug_atomic_read(redundant_softirqs_on),
  194                            sr2 = debug_atomic_read(redundant_softirqs_off);
  195 
  196         seq_printf(m, " chain lookup misses:           %11llu\n",
  197                 debug_atomic_read(chain_lookup_misses));
  198         seq_printf(m, " chain lookup hits:             %11llu\n",
  199                 debug_atomic_read(chain_lookup_hits));
  200         seq_printf(m, " cyclic checks:                 %11llu\n",
  201                 debug_atomic_read(nr_cyclic_checks));
  202         seq_printf(m, " find-mask forwards checks:     %11llu\n",
  203                 debug_atomic_read(nr_find_usage_forwards_checks));
  204         seq_printf(m, " find-mask backwards checks:    %11llu\n",
  205                 debug_atomic_read(nr_find_usage_backwards_checks));
  206 
  207         seq_printf(m, " hardirq on events:             %11llu\n", hi1);
  208         seq_printf(m, " hardirq off events:            %11llu\n", hi2);
  209         seq_printf(m, " redundant hardirq ons:         %11llu\n", hr1);
  210         seq_printf(m, " redundant hardirq offs:        %11llu\n", hr2);
  211         seq_printf(m, " softirq on events:             %11llu\n", si1);
  212         seq_printf(m, " softirq off events:            %11llu\n", si2);
  213         seq_printf(m, " redundant softirq ons:         %11llu\n", sr1);
  214         seq_printf(m, " redundant softirq offs:        %11llu\n", sr2);
  215 #endif
  216 }
  217 
  218 static int lockdep_stats_show(struct seq_file *m, void *v)
  219 {
  220         struct lock_class *class;
  221         unsigned long nr_unused = 0, nr_uncategorized = 0,
  222                       nr_irq_safe = 0, nr_irq_unsafe = 0,
  223                       nr_softirq_safe = 0, nr_softirq_unsafe = 0,
  224                       nr_hardirq_safe = 0, nr_hardirq_unsafe = 0,
  225                       nr_irq_read_safe = 0, nr_irq_read_unsafe = 0,
  226                       nr_softirq_read_safe = 0, nr_softirq_read_unsafe = 0,
  227                       nr_hardirq_read_safe = 0, nr_hardirq_read_unsafe = 0,
  228                       sum_forward_deps = 0;
  229 
  230         list_for_each_entry(class, &all_lock_classes, lock_entry) {
  231 
  232                 if (class->usage_mask == 0)
  233                         nr_unused++;
  234                 if (class->usage_mask == LOCKF_USED)
  235                         nr_uncategorized++;
  236                 if (class->usage_mask & LOCKF_USED_IN_IRQ)
  237                         nr_irq_safe++;
  238                 if (class->usage_mask & LOCKF_ENABLED_IRQ)
  239                         nr_irq_unsafe++;
  240                 if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ)
  241                         nr_softirq_safe++;
  242                 if (class->usage_mask & LOCKF_ENABLED_SOFTIRQ)
  243                         nr_softirq_unsafe++;
  244                 if (class->usage_mask & LOCKF_USED_IN_HARDIRQ)
  245                         nr_hardirq_safe++;
  246                 if (class->usage_mask & LOCKF_ENABLED_HARDIRQ)
  247                         nr_hardirq_unsafe++;
  248                 if (class->usage_mask & LOCKF_USED_IN_IRQ_READ)
  249                         nr_irq_read_safe++;
  250                 if (class->usage_mask & LOCKF_ENABLED_IRQ_READ)
  251                         nr_irq_read_unsafe++;
  252                 if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ)
  253                         nr_softirq_read_safe++;
  254                 if (class->usage_mask & LOCKF_ENABLED_SOFTIRQ_READ)
  255                         nr_softirq_read_unsafe++;
  256                 if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ)
  257                         nr_hardirq_read_safe++;
  258                 if (class->usage_mask & LOCKF_ENABLED_HARDIRQ_READ)
  259                         nr_hardirq_read_unsafe++;
  260 
  261 #ifdef CONFIG_PROVE_LOCKING
  262                 sum_forward_deps += lockdep_count_forward_deps(class);
  263 #endif
  264         }
  265 #ifdef CONFIG_DEBUG_LOCKDEP
  266         DEBUG_LOCKS_WARN_ON(debug_atomic_read(nr_unused_locks) != nr_unused);
  267 #endif
  268         seq_printf(m, " lock-classes:                  %11lu [max: %lu]\n",
  269                         nr_lock_classes, MAX_LOCKDEP_KEYS);
  270         seq_printf(m, " direct dependencies:           %11lu [max: %lu]\n",
  271                         nr_list_entries, MAX_LOCKDEP_ENTRIES);
  272         seq_printf(m, " indirect dependencies:         %11lu\n",
  273                         sum_forward_deps);
  274 
  275         /*
  276          * Total number of dependencies:
  277          *
  278          * All irq-safe locks may nest inside irq-unsafe locks,
  279          * plus all the other known dependencies:
  280          */
  281         seq_printf(m, " all direct dependencies:       %11lu\n",
  282                         nr_irq_unsafe * nr_irq_safe +
  283                         nr_hardirq_unsafe * nr_hardirq_safe +
  284                         nr_list_entries);
  285 
  286 #ifdef CONFIG_PROVE_LOCKING
  287         seq_printf(m, " dependency chains:             %11lu [max: %lu]\n",
  288                         nr_lock_chains, MAX_LOCKDEP_CHAINS);
  289         seq_printf(m, " dependency chain hlocks:       %11d [max: %lu]\n",
  290                         nr_chain_hlocks, MAX_LOCKDEP_CHAIN_HLOCKS);
  291 #endif
  292 
  293 #ifdef CONFIG_TRACE_IRQFLAGS
  294         seq_printf(m, " in-hardirq chains:             %11u\n",
  295                         nr_hardirq_chains);
  296         seq_printf(m, " in-softirq chains:             %11u\n",
  297                         nr_softirq_chains);
  298 #endif
  299         seq_printf(m, " in-process chains:             %11u\n",
  300                         nr_process_chains);
  301         seq_printf(m, " stack-trace entries:           %11lu [max: %lu]\n",
  302                         nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES);
  303         seq_printf(m, " combined max dependencies:     %11u\n",
  304                         (nr_hardirq_chains + 1) *
  305                         (nr_softirq_chains + 1) *
  306                         (nr_process_chains + 1)
  307         );
  308         seq_printf(m, " hardirq-safe locks:            %11lu\n",
  309                         nr_hardirq_safe);
  310         seq_printf(m, " hardirq-unsafe locks:          %11lu\n",
  311                         nr_hardirq_unsafe);
  312         seq_printf(m, " softirq-safe locks:            %11lu\n",
  313                         nr_softirq_safe);
  314         seq_printf(m, " softirq-unsafe locks:          %11lu\n",
  315                         nr_softirq_unsafe);
  316         seq_printf(m, " irq-safe locks:                %11lu\n",
  317                         nr_irq_safe);
  318         seq_printf(m, " irq-unsafe locks:              %11lu\n",
  319                         nr_irq_unsafe);
  320 
  321         seq_printf(m, " hardirq-read-safe locks:       %11lu\n",
  322                         nr_hardirq_read_safe);
  323         seq_printf(m, " hardirq-read-unsafe locks:     %11lu\n",
  324                         nr_hardirq_read_unsafe);
  325         seq_printf(m, " softirq-read-safe locks:       %11lu\n",
  326                         nr_softirq_read_safe);
  327         seq_printf(m, " softirq-read-unsafe locks:     %11lu\n",
  328                         nr_softirq_read_unsafe);
  329         seq_printf(m, " irq-read-safe locks:           %11lu\n",
  330                         nr_irq_read_safe);
  331         seq_printf(m, " irq-read-unsafe locks:         %11lu\n",
  332                         nr_irq_read_unsafe);
  333 
  334         seq_printf(m, " uncategorized locks:           %11lu\n",
  335                         nr_uncategorized);
  336         seq_printf(m, " unused locks:                  %11lu\n",
  337                         nr_unused);
  338         seq_printf(m, " max locking depth:             %11u\n",
  339                         max_lockdep_depth);
  340 #ifdef CONFIG_PROVE_LOCKING
  341         seq_printf(m, " max bfs queue depth:           %11u\n",
  342                         max_bfs_queue_depth);
  343 #endif
  344         lockdep_stats_debug_show(m);
  345         seq_printf(m, " debug_locks:                   %11u\n",
  346                         debug_locks);
  347 
  348         return 0;
  349 }
  350 
  351 static int lockdep_stats_open(struct inode *inode, struct file *file)
  352 {
  353         return single_open(file, lockdep_stats_show, NULL);
  354 }
  355 
  356 static const struct file_operations proc_lockdep_stats_operations = {
  357         .open           = lockdep_stats_open,
  358         .read           = seq_read,
  359         .llseek         = seq_lseek,
  360         .release        = single_release,
  361 };
  362 
  363 #ifdef CONFIG_LOCK_STAT
  364 
  365 struct lock_stat_data {
  366         struct lock_class *class;
  367         struct lock_class_stats stats;
  368 };
  369 
  370 struct lock_stat_seq {
  371         struct lock_stat_data *iter_end;
  372         struct lock_stat_data stats[MAX_LOCKDEP_KEYS];
  373 };
  374 
  375 /*
  376  * sort on absolute number of contentions
  377  */
  378 static int lock_stat_cmp(const void *l, const void *r)
  379 {
  380         const struct lock_stat_data *dl = l, *dr = r;
  381         unsigned long nl, nr;
  382 
  383         nl = dl->stats.read_waittime.nr + dl->stats.write_waittime.nr;
  384         nr = dr->stats.read_waittime.nr + dr->stats.write_waittime.nr;
  385 
  386         return nr - nl;
  387 }
  388 
  389 static void seq_line(struct seq_file *m, char c, int offset, int length)
  390 {
  391         int i;
  392 
  393         for (i = 0; i < offset; i++)
  394                 seq_puts(m, " ");
  395         for (i = 0; i < length; i++)
  396                 seq_printf(m, "%c", c);
  397         seq_puts(m, "\n");
  398 }
  399 
  400 static void snprint_time(char *buf, size_t bufsiz, s64 nr)
  401 {
  402         s64 div;
  403         s32 rem;
  404 
  405         nr += 5; /* for display rounding */
  406         div = div_s64_rem(nr, 1000, &rem);
  407         snprintf(buf, bufsiz, "%lld.%02d", (long long)div, (int)rem/10);
  408 }
  409 
  410 static void seq_time(struct seq_file *m, s64 time)
  411 {
  412         char num[15];
  413 
  414         snprint_time(num, sizeof(num), time);
  415         seq_printf(m, " %14s", num);
  416 }
  417 
  418 static void seq_lock_time(struct seq_file *m, struct lock_time *lt)
  419 {
  420         seq_printf(m, "%14lu", lt->nr);
  421         seq_time(m, lt->min);
  422         seq_time(m, lt->max);
  423         seq_time(m, lt->total);
  424 }
  425 
  426 static void seq_stats(struct seq_file *m, struct lock_stat_data *data)
  427 {
  428         char name[39];
  429         struct lock_class *class;
  430         struct lock_class_stats *stats;
  431         int i, namelen;
  432 
  433         class = data->class;
  434         stats = &data->stats;
  435 
  436         namelen = 38;
  437         if (class->name_version > 1)
  438                 namelen -= 2; /* XXX truncates versions > 9 */
  439         if (class->subclass)
  440                 namelen -= 2;
  441 
  442         if (!class->name) {
  443                 char str[KSYM_NAME_LEN];
  444                 const char *key_name;
  445 
  446                 key_name = __get_key_name(class->key, str);
  447                 snprintf(name, namelen, "%s", key_name);
  448         } else {
  449                 snprintf(name, namelen, "%s", class->name);
  450         }
  451         namelen = strlen(name);
  452         if (class->name_version > 1) {
  453                 snprintf(name+namelen, 3, "#%d", class->name_version);
  454                 namelen += 2;
  455         }
  456         if (class->subclass) {
  457                 snprintf(name+namelen, 3, "/%d", class->subclass);
  458                 namelen += 2;
  459         }
  460 
  461         if (stats->write_holdtime.nr) {
  462                 if (stats->read_holdtime.nr)
  463                         seq_printf(m, "%38s-W:", name);
  464                 else
  465                         seq_printf(m, "%40s:", name);
  466 
  467                 seq_printf(m, "%14lu ", stats->bounces[bounce_contended_write]);
  468                 seq_lock_time(m, &stats->write_waittime);
  469                 seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_write]);
  470                 seq_lock_time(m, &stats->write_holdtime);
  471                 seq_puts(m, "\n");
  472         }
  473 
  474         if (stats->read_holdtime.nr) {
  475                 seq_printf(m, "%38s-R:", name);
  476                 seq_printf(m, "%14lu ", stats->bounces[bounce_contended_read]);
  477                 seq_lock_time(m, &stats->read_waittime);
  478                 seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_read]);
  479                 seq_lock_time(m, &stats->read_holdtime);
  480                 seq_puts(m, "\n");
  481         }
  482 
  483         if (stats->read_waittime.nr + stats->write_waittime.nr == 0)
  484                 return;
  485 
  486         if (stats->read_holdtime.nr)
  487                 namelen += 2;
  488 
  489         for (i = 0; i < LOCKSTAT_POINTS; i++) {
  490                 char ip[32];
  491 
  492                 if (class->contention_point[i] == 0)
  493                         break;
  494 
  495                 if (!i)
  496                         seq_line(m, '-', 40-namelen, namelen);
  497 
  498                 snprintf(ip, sizeof(ip), "[<%p>]",
  499                                 (void *)class->contention_point[i]);
  500                 seq_printf(m, "%40s %14lu %29s %pS\n",
  501                            name, stats->contention_point[i],
  502                            ip, (void *)class->contention_point[i]);
  503         }
  504         for (i = 0; i < LOCKSTAT_POINTS; i++) {
  505                 char ip[32];
  506 
  507                 if (class->contending_point[i] == 0)
  508                         break;
  509 
  510                 if (!i)
  511                         seq_line(m, '-', 40-namelen, namelen);
  512 
  513                 snprintf(ip, sizeof(ip), "[<%p>]",
  514                                 (void *)class->contending_point[i]);
  515                 seq_printf(m, "%40s %14lu %29s %pS\n",
  516                            name, stats->contending_point[i],
  517                            ip, (void *)class->contending_point[i]);
  518         }
  519         if (i) {
  520                 seq_puts(m, "\n");
  521                 seq_line(m, '.', 0, 40 + 1 + 10 * (14 + 1));
  522                 seq_puts(m, "\n");
  523         }
  524 }
  525 
  526 static void seq_header(struct seq_file *m)
  527 {
  528         seq_printf(m, "lock_stat version 0.3\n");
  529 
  530         if (unlikely(!debug_locks))
  531                 seq_printf(m, "*WARNING* lock debugging disabled!! - possibly due to a lockdep warning\n");
  532 
  533         seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1));
  534         seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s "
  535                         "%14s %14s\n",
  536                         "class name",
  537                         "con-bounces",
  538                         "contentions",
  539                         "waittime-min",
  540                         "waittime-max",
  541                         "waittime-total",
  542                         "acq-bounces",
  543                         "acquisitions",
  544                         "holdtime-min",
  545                         "holdtime-max",
  546                         "holdtime-total");
  547         seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1));
  548         seq_printf(m, "\n");
  549 }
  550 
  551 static void *ls_start(struct seq_file *m, loff_t *pos)
  552 {
  553         struct lock_stat_seq *data = m->private;
  554         struct lock_stat_data *iter;
  555 
  556         if (*pos == 0)
  557                 return SEQ_START_TOKEN;
  558 
  559         iter = data->stats + (*pos - 1);
  560         if (iter >= data->iter_end)
  561                 iter = NULL;
  562 
  563         return iter;
  564 }
  565 
  566 static void *ls_next(struct seq_file *m, void *v, loff_t *pos)
  567 {
  568         (*pos)++;
  569         return ls_start(m, pos);
  570 }
  571 
  572 static void ls_stop(struct seq_file *m, void *v)
  573 {
  574 }
  575 
  576 static int ls_show(struct seq_file *m, void *v)
  577 {
  578         if (v == SEQ_START_TOKEN)
  579                 seq_header(m);
  580         else
  581                 seq_stats(m, v);
  582 
  583         return 0;
  584 }
  585 
  586 static const struct seq_operations lockstat_ops = {
  587         .start  = ls_start,
  588         .next   = ls_next,
  589         .stop   = ls_stop,
  590         .show   = ls_show,
  591 };
  592 
  593 static int lock_stat_open(struct inode *inode, struct file *file)
  594 {
  595         int res;
  596         struct lock_class *class;
  597         struct lock_stat_seq *data = vmalloc(sizeof(struct lock_stat_seq));
  598 
  599         if (!data)
  600                 return -ENOMEM;
  601 
  602         res = seq_open(file, &lockstat_ops);
  603         if (!res) {
  604                 struct lock_stat_data *iter = data->stats;
  605                 struct seq_file *m = file->private_data;
  606 
  607                 list_for_each_entry(class, &all_lock_classes, lock_entry) {
  608                         iter->class = class;
  609                         iter->stats = lock_stats(class);
  610                         iter++;
  611                 }
  612                 data->iter_end = iter;
  613 
  614                 sort(data->stats, data->iter_end - data->stats,
  615                                 sizeof(struct lock_stat_data),
  616                                 lock_stat_cmp, NULL);
  617 
  618                 m->private = data;
  619         } else
  620                 vfree(data);
  621 
  622         return res;
  623 }
  624 
  625 static ssize_t lock_stat_write(struct file *file, const char __user *buf,
  626                                size_t count, loff_t *ppos)
  627 {
  628         struct lock_class *class;
  629         char c;
  630 
  631         if (count) {
  632                 if (get_user(c, buf))
  633                         return -EFAULT;
  634 
  635                 if (c != '')
  636                         return count;
  637 
  638                 list_for_each_entry(class, &all_lock_classes, lock_entry)
  639                         clear_lock_stats(class);
  640         }
  641         return count;
  642 }
  643 
  644 static int lock_stat_release(struct inode *inode, struct file *file)
  645 {
  646         struct seq_file *seq = file->private_data;
  647 
  648         vfree(seq->private);
  649         return seq_release(inode, file);
  650 }
  651 
  652 static const struct file_operations proc_lock_stat_operations = {
  653         .open           = lock_stat_open,
  654         .write          = lock_stat_write,
  655         .read           = seq_read,
  656         .llseek         = seq_lseek,
  657         .release        = lock_stat_release,
  658 };
  659 #endif /* CONFIG_LOCK_STAT */
  660 
  661 static int __init lockdep_proc_init(void)
  662 {
  663         proc_create("lockdep", S_IRUSR, NULL, &proc_lockdep_operations);
  664 #ifdef CONFIG_PROVE_LOCKING
  665         proc_create("lockdep_chains", S_IRUSR, NULL,
  666                     &proc_lockdep_chains_operations);
  667 #endif
  668         proc_create("lockdep_stats", S_IRUSR, NULL,
  669                     &proc_lockdep_stats_operations);
  670 
  671 #ifdef CONFIG_LOCK_STAT
  672         proc_create("lock_stat", S_IRUSR | S_IWUSR, NULL,
  673                     &proc_lock_stat_operations);
  674 #endif
  675 
  676         return 0;
  677 }
  678 
  679 __initcall(lockdep_proc_init);
  680 

Cache object: 4c0f9aa479ebb131baabc401a43e3680


[ 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.