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/rcupreempt_trace.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  * Read-Copy Update tracing for realtime implementation
    3  *
    4  * This program is free software; you can redistribute it and/or modify
    5  * it under the terms of the GNU General Public License as published by
    6  * the Free Software Foundation; either version 2 of the License, or
    7  * (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   17  *
   18  * Copyright IBM Corporation, 2006
   19  *
   20  * Papers:  http://www.rdrop.com/users/paulmck/RCU
   21  *
   22  * For detailed explanation of Read-Copy Update mechanism see -
   23  *              Documentation/RCU/ *.txt
   24  *
   25  */
   26 #include <linux/types.h>
   27 #include <linux/kernel.h>
   28 #include <linux/init.h>
   29 #include <linux/spinlock.h>
   30 #include <linux/smp.h>
   31 #include <linux/rcupdate.h>
   32 #include <linux/interrupt.h>
   33 #include <linux/sched.h>
   34 #include <asm/atomic.h>
   35 #include <linux/bitops.h>
   36 #include <linux/module.h>
   37 #include <linux/completion.h>
   38 #include <linux/moduleparam.h>
   39 #include <linux/percpu.h>
   40 #include <linux/notifier.h>
   41 #include <linux/cpu.h>
   42 #include <linux/mutex.h>
   43 #include <linux/rcupreempt_trace.h>
   44 #include <linux/debugfs.h>
   45 
   46 static struct mutex rcupreempt_trace_mutex;
   47 static char *rcupreempt_trace_buf;
   48 #define RCUPREEMPT_TRACE_BUF_SIZE 4096
   49 
   50 void rcupreempt_trace_move2done(struct rcupreempt_trace *trace)
   51 {
   52         trace->done_length += trace->wait_length;
   53         trace->done_add += trace->wait_length;
   54         trace->wait_length = 0;
   55 }
   56 void rcupreempt_trace_move2wait(struct rcupreempt_trace *trace)
   57 {
   58         trace->wait_length += trace->next_length;
   59         trace->wait_add += trace->next_length;
   60         trace->next_length = 0;
   61 }
   62 void rcupreempt_trace_try_flip_1(struct rcupreempt_trace *trace)
   63 {
   64         atomic_inc(&trace->rcu_try_flip_1);
   65 }
   66 void rcupreempt_trace_try_flip_e1(struct rcupreempt_trace *trace)
   67 {
   68         atomic_inc(&trace->rcu_try_flip_e1);
   69 }
   70 void rcupreempt_trace_try_flip_i1(struct rcupreempt_trace *trace)
   71 {
   72         trace->rcu_try_flip_i1++;
   73 }
   74 void rcupreempt_trace_try_flip_ie1(struct rcupreempt_trace *trace)
   75 {
   76         trace->rcu_try_flip_ie1++;
   77 }
   78 void rcupreempt_trace_try_flip_g1(struct rcupreempt_trace *trace)
   79 {
   80         trace->rcu_try_flip_g1++;
   81 }
   82 void rcupreempt_trace_try_flip_a1(struct rcupreempt_trace *trace)
   83 {
   84         trace->rcu_try_flip_a1++;
   85 }
   86 void rcupreempt_trace_try_flip_ae1(struct rcupreempt_trace *trace)
   87 {
   88         trace->rcu_try_flip_ae1++;
   89 }
   90 void rcupreempt_trace_try_flip_a2(struct rcupreempt_trace *trace)
   91 {
   92         trace->rcu_try_flip_a2++;
   93 }
   94 void rcupreempt_trace_try_flip_z1(struct rcupreempt_trace *trace)
   95 {
   96         trace->rcu_try_flip_z1++;
   97 }
   98 void rcupreempt_trace_try_flip_ze1(struct rcupreempt_trace *trace)
   99 {
  100         trace->rcu_try_flip_ze1++;
  101 }
  102 void rcupreempt_trace_try_flip_z2(struct rcupreempt_trace *trace)
  103 {
  104         trace->rcu_try_flip_z2++;
  105 }
  106 void rcupreempt_trace_try_flip_m1(struct rcupreempt_trace *trace)
  107 {
  108         trace->rcu_try_flip_m1++;
  109 }
  110 void rcupreempt_trace_try_flip_me1(struct rcupreempt_trace *trace)
  111 {
  112         trace->rcu_try_flip_me1++;
  113 }
  114 void rcupreempt_trace_try_flip_m2(struct rcupreempt_trace *trace)
  115 {
  116         trace->rcu_try_flip_m2++;
  117 }
  118 void rcupreempt_trace_check_callbacks(struct rcupreempt_trace *trace)
  119 {
  120         trace->rcu_check_callbacks++;
  121 }
  122 void rcupreempt_trace_done_remove(struct rcupreempt_trace *trace)
  123 {
  124         trace->done_remove += trace->done_length;
  125         trace->done_length = 0;
  126 }
  127 void rcupreempt_trace_invoke(struct rcupreempt_trace *trace)
  128 {
  129         atomic_inc(&trace->done_invoked);
  130 }
  131 void rcupreempt_trace_next_add(struct rcupreempt_trace *trace)
  132 {
  133         trace->next_add++;
  134         trace->next_length++;
  135 }
  136 
  137 static void rcupreempt_trace_sum(struct rcupreempt_trace *sp)
  138 {
  139         struct rcupreempt_trace *cp;
  140         int cpu;
  141 
  142         memset(sp, 0, sizeof(*sp));
  143         for_each_possible_cpu(cpu) {
  144                 cp = rcupreempt_trace_cpu(cpu);
  145                 sp->next_length += cp->next_length;
  146                 sp->next_add += cp->next_add;
  147                 sp->wait_length += cp->wait_length;
  148                 sp->wait_add += cp->wait_add;
  149                 sp->done_length += cp->done_length;
  150                 sp->done_add += cp->done_add;
  151                 sp->done_remove += cp->done_remove;
  152                 atomic_set(&sp->done_invoked, atomic_read(&cp->done_invoked));
  153                 sp->rcu_check_callbacks += cp->rcu_check_callbacks;
  154                 atomic_set(&sp->rcu_try_flip_1,
  155                            atomic_read(&cp->rcu_try_flip_1));
  156                 atomic_set(&sp->rcu_try_flip_e1,
  157                            atomic_read(&cp->rcu_try_flip_e1));
  158                 sp->rcu_try_flip_i1 += cp->rcu_try_flip_i1;
  159                 sp->rcu_try_flip_ie1 += cp->rcu_try_flip_ie1;
  160                 sp->rcu_try_flip_g1 += cp->rcu_try_flip_g1;
  161                 sp->rcu_try_flip_a1 += cp->rcu_try_flip_a1;
  162                 sp->rcu_try_flip_ae1 += cp->rcu_try_flip_ae1;
  163                 sp->rcu_try_flip_a2 += cp->rcu_try_flip_a2;
  164                 sp->rcu_try_flip_z1 += cp->rcu_try_flip_z1;
  165                 sp->rcu_try_flip_ze1 += cp->rcu_try_flip_ze1;
  166                 sp->rcu_try_flip_z2 += cp->rcu_try_flip_z2;
  167                 sp->rcu_try_flip_m1 += cp->rcu_try_flip_m1;
  168                 sp->rcu_try_flip_me1 += cp->rcu_try_flip_me1;
  169                 sp->rcu_try_flip_m2 += cp->rcu_try_flip_m2;
  170         }
  171 }
  172 
  173 static ssize_t rcustats_read(struct file *filp, char __user *buffer,
  174                                 size_t count, loff_t *ppos)
  175 {
  176         struct rcupreempt_trace trace;
  177         ssize_t bcount;
  178         int cnt = 0;
  179 
  180         rcupreempt_trace_sum(&trace);
  181         mutex_lock(&rcupreempt_trace_mutex);
  182         snprintf(&rcupreempt_trace_buf[cnt], RCUPREEMPT_TRACE_BUF_SIZE - cnt,
  183                  "ggp=%ld rcc=%ld\n",
  184                  rcu_batches_completed(),
  185                  trace.rcu_check_callbacks);
  186         snprintf(&rcupreempt_trace_buf[cnt], RCUPREEMPT_TRACE_BUF_SIZE - cnt,
  187                  "na=%ld nl=%ld wa=%ld wl=%ld da=%ld dl=%ld dr=%ld di=%d\n"
  188                  "1=%d e1=%d i1=%ld ie1=%ld g1=%ld a1=%ld ae1=%ld a2=%ld\n"
  189                  "z1=%ld ze1=%ld z2=%ld m1=%ld me1=%ld m2=%ld\n",
  190 
  191                  trace.next_add, trace.next_length,
  192                  trace.wait_add, trace.wait_length,
  193                  trace.done_add, trace.done_length,
  194                  trace.done_remove, atomic_read(&trace.done_invoked),
  195                  atomic_read(&trace.rcu_try_flip_1),
  196                  atomic_read(&trace.rcu_try_flip_e1),
  197                  trace.rcu_try_flip_i1, trace.rcu_try_flip_ie1,
  198                  trace.rcu_try_flip_g1,
  199                  trace.rcu_try_flip_a1, trace.rcu_try_flip_ae1,
  200                          trace.rcu_try_flip_a2,
  201                  trace.rcu_try_flip_z1, trace.rcu_try_flip_ze1,
  202                          trace.rcu_try_flip_z2,
  203                  trace.rcu_try_flip_m1, trace.rcu_try_flip_me1,
  204                         trace.rcu_try_flip_m2);
  205         bcount = simple_read_from_buffer(buffer, count, ppos,
  206                         rcupreempt_trace_buf, strlen(rcupreempt_trace_buf));
  207         mutex_unlock(&rcupreempt_trace_mutex);
  208         return bcount;
  209 }
  210 
  211 static ssize_t rcugp_read(struct file *filp, char __user *buffer,
  212                                 size_t count, loff_t *ppos)
  213 {
  214         long oldgp = rcu_batches_completed();
  215         ssize_t bcount;
  216 
  217         mutex_lock(&rcupreempt_trace_mutex);
  218         synchronize_rcu();
  219         snprintf(rcupreempt_trace_buf, RCUPREEMPT_TRACE_BUF_SIZE,
  220                 "oldggp=%ld  newggp=%ld\n", oldgp, rcu_batches_completed());
  221         bcount = simple_read_from_buffer(buffer, count, ppos,
  222                         rcupreempt_trace_buf, strlen(rcupreempt_trace_buf));
  223         mutex_unlock(&rcupreempt_trace_mutex);
  224         return bcount;
  225 }
  226 
  227 static ssize_t rcuctrs_read(struct file *filp, char __user *buffer,
  228                                 size_t count, loff_t *ppos)
  229 {
  230         int cnt = 0;
  231         int cpu;
  232         int f = rcu_batches_completed() & 0x1;
  233         ssize_t bcount;
  234 
  235         mutex_lock(&rcupreempt_trace_mutex);
  236 
  237         cnt += snprintf(&rcupreempt_trace_buf[cnt], RCUPREEMPT_TRACE_BUF_SIZE,
  238                                 "CPU last cur F M\n");
  239         for_each_online_cpu(cpu) {
  240                 long *flipctr = rcupreempt_flipctr(cpu);
  241                 cnt += snprintf(&rcupreempt_trace_buf[cnt],
  242                                 RCUPREEMPT_TRACE_BUF_SIZE - cnt,
  243                                         "%3d %4ld %3ld %d %d\n",
  244                                cpu,
  245                                flipctr[!f],
  246                                flipctr[f],
  247                                rcupreempt_flip_flag(cpu),
  248                                rcupreempt_mb_flag(cpu));
  249         }
  250         cnt += snprintf(&rcupreempt_trace_buf[cnt],
  251                         RCUPREEMPT_TRACE_BUF_SIZE - cnt,
  252                         "ggp = %ld, state = %s\n",
  253                         rcu_batches_completed(),
  254                         rcupreempt_try_flip_state_name());
  255         cnt += snprintf(&rcupreempt_trace_buf[cnt],
  256                         RCUPREEMPT_TRACE_BUF_SIZE - cnt,
  257                         "\n");
  258         bcount = simple_read_from_buffer(buffer, count, ppos,
  259                         rcupreempt_trace_buf, strlen(rcupreempt_trace_buf));
  260         mutex_unlock(&rcupreempt_trace_mutex);
  261         return bcount;
  262 }
  263 
  264 static struct file_operations rcustats_fops = {
  265         .owner = THIS_MODULE,
  266         .read = rcustats_read,
  267 };
  268 
  269 static struct file_operations rcugp_fops = {
  270         .owner = THIS_MODULE,
  271         .read = rcugp_read,
  272 };
  273 
  274 static struct file_operations rcuctrs_fops = {
  275         .owner = THIS_MODULE,
  276         .read = rcuctrs_read,
  277 };
  278 
  279 static struct dentry *rcudir, *statdir, *ctrsdir, *gpdir;
  280 static int rcupreempt_debugfs_init(void)
  281 {
  282         rcudir = debugfs_create_dir("rcu", NULL);
  283         if (!rcudir)
  284                 goto out;
  285         statdir = debugfs_create_file("rcustats", 0444, rcudir,
  286                                                 NULL, &rcustats_fops);
  287         if (!statdir)
  288                 goto free_out;
  289 
  290         gpdir = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops);
  291         if (!gpdir)
  292                 goto free_out;
  293 
  294         ctrsdir = debugfs_create_file("rcuctrs", 0444, rcudir,
  295                                                 NULL, &rcuctrs_fops);
  296         if (!ctrsdir)
  297                 goto free_out;
  298         return 0;
  299 free_out:
  300         if (statdir)
  301                 debugfs_remove(statdir);
  302         if (gpdir)
  303                 debugfs_remove(gpdir);
  304         debugfs_remove(rcudir);
  305 out:
  306         return 1;
  307 }
  308 
  309 static int __init rcupreempt_trace_init(void)
  310 {
  311         int ret;
  312 
  313         mutex_init(&rcupreempt_trace_mutex);
  314         rcupreempt_trace_buf = kmalloc(RCUPREEMPT_TRACE_BUF_SIZE, GFP_KERNEL);
  315         if (!rcupreempt_trace_buf)
  316                 return 1;
  317         ret = rcupreempt_debugfs_init();
  318         if (ret)
  319                 kfree(rcupreempt_trace_buf);
  320         return ret;
  321 }
  322 
  323 static void __exit rcupreempt_trace_cleanup(void)
  324 {
  325         debugfs_remove(statdir);
  326         debugfs_remove(gpdir);
  327         debugfs_remove(ctrsdir);
  328         debugfs_remove(rcudir);
  329         kfree(rcupreempt_trace_buf);
  330 }
  331 
  332 
  333 module_init(rcupreempt_trace_init);
  334 module_exit(rcupreempt_trace_cleanup);

Cache object: 778acda5e69d7a3dae6313e84f1396cc


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