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/kern/subr_cpu_topology.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  * Copyright (c) 2012 The DragonFly Project.  All rights reserved.
    3  * 
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in
   12  *    the documentation and/or other materials provided with the
   13  *    distribution.
   14  * 3. Neither the name of The DragonFly Project nor the names of its
   15  *    contributors may be used to endorse or promote products derived
   16  *    from this software without specific, prior written permission.
   17  * 
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   22  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  * 
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/sysctl.h>
   37 #include <sys/sbuf.h>
   38 #include <sys/cpu_topology.h>
   39 
   40 #include <machine/smp.h>
   41 
   42 #ifndef NAPICID
   43 #define NAPICID 256
   44 #endif
   45 
   46 #define INDENT_BUF_SIZE LEVEL_NO*3
   47 #define INVALID_ID -1
   48 
   49 /* Per-cpu sysctl nodes and info */
   50 struct per_cpu_sysctl_info {
   51         struct sysctl_ctx_list sysctl_ctx;
   52         struct sysctl_oid *sysctl_tree;
   53         char cpu_name[32];
   54         int physical_id;
   55         int core_id;
   56         char physical_siblings[8*MAXCPU];
   57         char core_siblings[8*MAXCPU];
   58 };
   59 typedef struct per_cpu_sysctl_info per_cpu_sysctl_info_t;
   60 
   61 static cpu_node_t cpu_topology_nodes[MAXCPU];   /* Memory for topology */
   62 static cpu_node_t *cpu_root_node;               /* Root node pointer */
   63 
   64 static struct sysctl_ctx_list cpu_topology_sysctl_ctx;
   65 static struct sysctl_oid *cpu_topology_sysctl_tree;
   66 static char cpu_topology_members[8*MAXCPU];
   67 static per_cpu_sysctl_info_t pcpu_sysctl[MAXCPU];
   68 
   69 int cpu_topology_levels_number = 1;
   70 cpu_node_t *root_cpu_node;
   71 
   72 /* Get the next valid apicid starting
   73  * from current apicid (curr_apicid
   74  */
   75 static int
   76 get_next_valid_apicid(int curr_apicid)
   77 {
   78         int next_apicid = curr_apicid;
   79         do {
   80                 next_apicid++;
   81         }
   82         while(get_cpuid_from_apicid(next_apicid) == -1 &&
   83            next_apicid < NAPICID);
   84         if (next_apicid == NAPICID) {
   85                 kprintf("Warning: No next valid APICID found. Returning -1\n");
   86                 return -1;
   87         }
   88         return next_apicid;
   89 }
   90 
   91 /* Generic topology tree. The parameters have the following meaning:
   92  * - children_no_per_level : the number of children on each level
   93  * - level_types : the type of the level (THREAD, CORE, CHIP, etc)
   94  * - cur_level : the current level of the tree
   95  * - node : the current node
   96  * - last_free_node : the last free node in the global array.
   97  * - cpuid : basicly this are the ids of the leafs
   98  */ 
   99 static void
  100 build_topology_tree(int *children_no_per_level,
  101    uint8_t *level_types,
  102    int cur_level, 
  103    cpu_node_t *node,
  104    cpu_node_t **last_free_node,
  105    int *apicid)
  106 {
  107         int i;
  108 
  109         node->child_no = children_no_per_level[cur_level];
  110         node->type = level_types[cur_level];
  111         node->members = 0;
  112 
  113         if (node->child_no == 0) {
  114                 node->child_node = NULL;
  115                 *apicid = get_next_valid_apicid(*apicid);
  116                 node->members = CPUMASK(get_cpuid_from_apicid(*apicid));
  117                 return;
  118         }
  119 
  120         node->child_node = *last_free_node;
  121         (*last_free_node) += node->child_no;
  122         if (node->parent_node == NULL)
  123                 root_cpu_node = node;
  124         
  125         for (i = 0; i < node->child_no; i++) {
  126                 node->child_node[i].parent_node = node;
  127 
  128                 build_topology_tree(children_no_per_level,
  129                     level_types,
  130                     cur_level + 1,
  131                     &(node->child_node[i]),
  132                     last_free_node,
  133                     apicid);
  134 
  135                 node->members |= node->child_node[i].members;
  136         }
  137 }
  138 
  139 /* Build CPU topology. The detection is made by comparing the
  140  * chip, core and logical IDs of each CPU with the IDs of the 
  141  * BSP. When we found a match, at that level the CPUs are siblings.
  142  */
  143 static cpu_node_t *
  144 build_cpu_topology(void)
  145 {
  146         detect_cpu_topology();
  147         int i;
  148         int BSPID = 0;
  149         int threads_per_core = 0;
  150         int cores_per_chip = 0;
  151         int chips_per_package = 0;
  152         int children_no_per_level[LEVEL_NO];
  153         uint8_t level_types[LEVEL_NO];
  154         int apicid = -1;
  155 
  156         cpu_node_t *root = &cpu_topology_nodes[0];
  157         cpu_node_t *last_free_node = root + 1;
  158 
  159         /* Assume that the topology is uniform.
  160          * Find the number of siblings within chip
  161          * and witin core to build up the topology
  162          */
  163         for (i = 0; i < ncpus; i++) {
  164 
  165                 cpumask_t mask = CPUMASK(i);
  166 
  167                 if ((mask & smp_active_mask) == 0)
  168                         continue;
  169 
  170                 if (get_chip_ID(BSPID) == get_chip_ID(i))
  171                         cores_per_chip++;
  172                 else
  173                         continue;
  174 
  175                 if (get_core_number_within_chip(BSPID) ==
  176                     get_core_number_within_chip(i))
  177                         threads_per_core++;
  178         }
  179 
  180         cores_per_chip /= threads_per_core;
  181         chips_per_package = ncpus / (cores_per_chip * threads_per_core);
  182         
  183         if (bootverbose)
  184                 kprintf("CPU Topology: cores_per_chip: %d; threads_per_core: %d; chips_per_package: %d;\n",
  185                     cores_per_chip, threads_per_core, chips_per_package);
  186 
  187         if (threads_per_core > 1) { /* HT available - 4 levels */
  188 
  189                 children_no_per_level[0] = chips_per_package;
  190                 children_no_per_level[1] = cores_per_chip;
  191                 children_no_per_level[2] = threads_per_core;
  192                 children_no_per_level[3] = 0;
  193 
  194                 level_types[0] = PACKAGE_LEVEL;
  195                 level_types[1] = CHIP_LEVEL;
  196                 level_types[2] = CORE_LEVEL;
  197                 level_types[3] = THREAD_LEVEL;
  198         
  199                 build_topology_tree(children_no_per_level,
  200                     level_types,
  201                     0,
  202                     root,
  203                     &last_free_node,
  204                     &apicid);
  205 
  206                 cpu_topology_levels_number = 4;
  207 
  208         } else if (cores_per_chip > 1) { /* No HT available - 3 levels */
  209 
  210                 children_no_per_level[0] = chips_per_package;
  211                 children_no_per_level[1] = cores_per_chip;
  212                 children_no_per_level[2] = 0;
  213 
  214                 level_types[0] = PACKAGE_LEVEL;
  215                 level_types[1] = CHIP_LEVEL;
  216                 level_types[2] = CORE_LEVEL;
  217         
  218                 build_topology_tree(children_no_per_level,
  219                     level_types,
  220                     0,
  221                     root,
  222                     &last_free_node,
  223                     &apicid);
  224 
  225                 cpu_topology_levels_number = 3;
  226 
  227         } else { /* No HT and no Multi-Core - 2 levels */
  228 
  229                 children_no_per_level[0] = chips_per_package;
  230                 children_no_per_level[1] = 0;
  231 
  232                 level_types[0] = PACKAGE_LEVEL;
  233                 level_types[1] = CHIP_LEVEL;
  234         
  235                 build_topology_tree(children_no_per_level,
  236                     level_types,
  237                     0,
  238                     root,
  239                     &last_free_node,
  240                     &apicid);
  241 
  242                 cpu_topology_levels_number = 2;
  243 
  244         }
  245 
  246         return root;
  247 }
  248 
  249 /* Recursive function helper to print the CPU topology tree */
  250 static void
  251 print_cpu_topology_tree_sysctl_helper(cpu_node_t *node,
  252     struct sbuf *sb,
  253     char * buf,
  254     int buf_len,
  255     int last)
  256 {
  257         int i;
  258         int bsr_member;
  259 
  260         sbuf_bcat(sb, buf, buf_len);
  261         if (last) {
  262                 sbuf_printf(sb, "\\-");
  263                 buf[buf_len] = ' ';buf_len++;
  264                 buf[buf_len] = ' ';buf_len++;
  265         } else {
  266                 sbuf_printf(sb, "|-");
  267                 buf[buf_len] = '|';buf_len++;
  268                 buf[buf_len] = ' ';buf_len++;
  269         }
  270         
  271         bsr_member = BSRCPUMASK(node->members);
  272 
  273         if (node->type == PACKAGE_LEVEL) {
  274                 sbuf_printf(sb,"PACKAGE MEMBERS: ");
  275         } else if (node->type == CHIP_LEVEL) {
  276                 sbuf_printf(sb,"CHIP ID %d: ",
  277                         get_chip_ID(bsr_member));
  278         } else if (node->type == CORE_LEVEL) {
  279                 sbuf_printf(sb,"CORE ID %d: ",
  280                         get_core_number_within_chip(bsr_member));
  281         } else if (node->type == THREAD_LEVEL) {
  282                 sbuf_printf(sb,"THREAD ID %d: ",
  283                         get_logical_CPU_number_within_core(bsr_member));
  284         } else {
  285                 sbuf_printf(sb,"UNKNOWN: ");
  286         }
  287         CPUSET_FOREACH(i, node->members) {
  288                 sbuf_printf(sb,"cpu%d ", i);
  289         }       
  290         
  291         sbuf_printf(sb,"\n");
  292 
  293         for (i = 0; i < node->child_no; i++) {
  294                 print_cpu_topology_tree_sysctl_helper(&(node->child_node[i]),
  295                     sb, buf, buf_len, i == (node->child_no -1));
  296         }
  297 }
  298 
  299 /* SYSCTL PROCEDURE for printing the CPU Topology tree */
  300 static int
  301 print_cpu_topology_tree_sysctl(SYSCTL_HANDLER_ARGS)
  302 {
  303         struct sbuf *sb;
  304         int ret;
  305         char buf[INDENT_BUF_SIZE];
  306 
  307         KASSERT(cpu_root_node != NULL, ("cpu_root_node isn't initialized"));
  308 
  309         sb = sbuf_new(NULL, NULL, 500, SBUF_AUTOEXTEND);
  310         if (sb == NULL) {
  311                 return (ENOMEM);
  312         }
  313         sbuf_printf(sb,"\n");
  314         print_cpu_topology_tree_sysctl_helper(cpu_root_node, sb, buf, 0, 1);
  315 
  316         sbuf_finish(sb);
  317 
  318         ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
  319 
  320         sbuf_delete(sb);
  321 
  322         return ret;
  323 }
  324 
  325 /* SYSCTL PROCEDURE for printing the CPU Topology level description */
  326 static int
  327 print_cpu_topology_level_description_sysctl(SYSCTL_HANDLER_ARGS)
  328 {
  329         struct sbuf *sb;
  330         int ret;
  331 
  332         sb = sbuf_new(NULL, NULL, 500, SBUF_AUTOEXTEND);
  333         if (sb == NULL)
  334                 return (ENOMEM);
  335 
  336         if (cpu_topology_levels_number == 4) /* HT available */
  337                 sbuf_printf(sb, "0 - thread; 1 - core; 2 - socket; 3 - anything");
  338         else if (cpu_topology_levels_number == 3) /* No HT available */
  339                 sbuf_printf(sb, "0 - core; 1 - socket; 2 - anything");
  340         else if (cpu_topology_levels_number == 2) /* No HT and no Multi-Core */
  341                 sbuf_printf(sb, "0 - socket; 1 - anything");
  342         else
  343                 sbuf_printf(sb, "Unknown");
  344 
  345         sbuf_finish(sb);
  346 
  347         ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
  348 
  349         sbuf_delete(sb);
  350 
  351         return ret;     
  352 }
  353 
  354 /* Find a cpu_node_t by a mask */
  355 static cpu_node_t *
  356 get_cpu_node_by_cpumask(cpu_node_t * node,
  357                         cpumask_t mask) {
  358 
  359         cpu_node_t * found = NULL;
  360         int i;
  361 
  362         if (node->members == mask) {
  363                 return node;
  364         }
  365 
  366         for (i = 0; i < node->child_no; i++) {
  367                 found = get_cpu_node_by_cpumask(&(node->child_node[i]), mask);
  368                 if (found != NULL) {
  369                         return found;
  370                 }
  371         }
  372         return NULL;
  373 }
  374 
  375 cpu_node_t *
  376 get_cpu_node_by_cpuid(int cpuid) {
  377         cpumask_t mask = CPUMASK(cpuid);
  378 
  379         KASSERT(cpu_root_node != NULL, ("cpu_root_node isn't initialized"));
  380 
  381         return get_cpu_node_by_cpumask(cpu_root_node, mask);
  382 }
  383 
  384 /* Get the mask of siblings for level_type of a cpuid */
  385 cpumask_t
  386 get_cpumask_from_level(int cpuid,
  387                         uint8_t level_type)
  388 {
  389         cpu_node_t * node;
  390         cpumask_t mask = CPUMASK(cpuid);
  391 
  392         KASSERT(cpu_root_node != NULL, ("cpu_root_node isn't initialized"));
  393 
  394         node = get_cpu_node_by_cpumask(cpu_root_node, mask);
  395 
  396         if (node == NULL) {
  397                 return 0;
  398         }
  399 
  400         while (node != NULL) {
  401                 if (node->type == level_type) {
  402                         return node->members;
  403                 }
  404                 node = node->parent_node;
  405         }
  406 
  407         return 0;
  408 }
  409 
  410 /* init pcpu_sysctl structure info */
  411 static void
  412 init_pcpu_topology_sysctl(void)
  413 {
  414         int cpu;
  415         int i;
  416         cpumask_t mask;
  417         struct sbuf sb;
  418 
  419         for (i = 0; i < ncpus; i++) {
  420 
  421                 sbuf_new(&sb, pcpu_sysctl[i].cpu_name,
  422                     sizeof(pcpu_sysctl[i].cpu_name), SBUF_FIXEDLEN);
  423                 sbuf_printf(&sb,"cpu%d", i);
  424                 sbuf_finish(&sb);
  425 
  426 
  427                 /* Get physical siblings */
  428                 mask = get_cpumask_from_level(i, CHIP_LEVEL);
  429                 if (mask == 0) {
  430                         pcpu_sysctl[i].physical_id = INVALID_ID;
  431                         continue;
  432                 }
  433 
  434                 sbuf_new(&sb, pcpu_sysctl[i].physical_siblings,
  435                     sizeof(pcpu_sysctl[i].physical_siblings), SBUF_FIXEDLEN);
  436                 CPUSET_FOREACH(cpu, mask) {
  437                         sbuf_printf(&sb,"cpu%d ", cpu);
  438                 }
  439                 sbuf_trim(&sb);
  440                 sbuf_finish(&sb);
  441 
  442                 pcpu_sysctl[i].physical_id = get_chip_ID(i); 
  443 
  444                 /* Get core siblings */
  445                 mask = get_cpumask_from_level(i, CORE_LEVEL);
  446                 if (mask == 0) {
  447                         pcpu_sysctl[i].core_id = INVALID_ID;
  448                         continue;
  449                 }
  450 
  451                 sbuf_new(&sb, pcpu_sysctl[i].core_siblings,
  452                     sizeof(pcpu_sysctl[i].core_siblings), SBUF_FIXEDLEN);
  453                 CPUSET_FOREACH(cpu, mask) {
  454                         sbuf_printf(&sb,"cpu%d ", cpu);
  455                 }
  456                 sbuf_trim(&sb);
  457                 sbuf_finish(&sb);
  458 
  459                 pcpu_sysctl[i].core_id = get_core_number_within_chip(i);
  460 
  461         }
  462 }
  463 
  464 /* Build SYSCTL structure for revealing
  465  * the CPU Topology to user-space.
  466  */
  467 static void
  468 build_sysctl_cpu_topology(void)
  469 {
  470         int i;
  471         struct sbuf sb;
  472         
  473         /* SYSCTL new leaf for "cpu_topology" */
  474         sysctl_ctx_init(&cpu_topology_sysctl_ctx);
  475         cpu_topology_sysctl_tree = SYSCTL_ADD_NODE(&cpu_topology_sysctl_ctx,
  476             SYSCTL_STATIC_CHILDREN(_hw),
  477             OID_AUTO,
  478             "cpu_topology",
  479             CTLFLAG_RD, 0, "");
  480 
  481         /* SYSCTL cpu_topology "tree" entry */
  482         SYSCTL_ADD_PROC(&cpu_topology_sysctl_ctx,
  483             SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
  484             OID_AUTO, "tree", CTLTYPE_STRING | CTLFLAG_RD,
  485             NULL, 0, print_cpu_topology_tree_sysctl, "A",
  486             "Tree print of CPU topology");
  487 
  488         /* SYSCTL cpu_topology "level_description" entry */
  489         SYSCTL_ADD_PROC(&cpu_topology_sysctl_ctx,
  490             SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
  491             OID_AUTO, "level_description", CTLTYPE_STRING | CTLFLAG_RD,
  492             NULL, 0, print_cpu_topology_level_description_sysctl, "A",
  493             "Level description of CPU topology");
  494 
  495         /* SYSCTL cpu_topology "members" entry */
  496         sbuf_new(&sb, cpu_topology_members,
  497             sizeof(cpu_topology_members), SBUF_FIXEDLEN);
  498         CPUSET_FOREACH(i, cpu_root_node->members) {
  499                 sbuf_printf(&sb,"cpu%d ", i);
  500         }
  501         sbuf_trim(&sb);
  502         sbuf_finish(&sb);
  503         SYSCTL_ADD_STRING(&cpu_topology_sysctl_ctx,
  504             SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
  505             OID_AUTO, "members", CTLFLAG_RD,
  506             cpu_topology_members, 0,
  507             "Members of the CPU Topology");
  508 
  509         /* SYSCTL per_cpu info */
  510         for (i = 0; i < ncpus; i++) {
  511                 /* New leaf : hw.cpu_topology.cpux */
  512                 sysctl_ctx_init(&pcpu_sysctl[i].sysctl_ctx); 
  513                 pcpu_sysctl[i].sysctl_tree = SYSCTL_ADD_NODE(&pcpu_sysctl[i].sysctl_ctx,
  514                     SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
  515                     OID_AUTO,
  516                     pcpu_sysctl[i].cpu_name,
  517                     CTLFLAG_RD, 0, "");
  518 
  519                 /* Check if the physical_id found is valid */
  520                 if (pcpu_sysctl[i].physical_id == INVALID_ID) {
  521                         continue;
  522                 }
  523 
  524                 /* Add physical id info */
  525                 SYSCTL_ADD_INT(&pcpu_sysctl[i].sysctl_ctx,
  526                     SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
  527                     OID_AUTO, "physical_id", CTLFLAG_RD,
  528                     &pcpu_sysctl[i].physical_id, 0,
  529                     "Physical ID");
  530 
  531                 /* Add physical siblings */
  532                 SYSCTL_ADD_STRING(&pcpu_sysctl[i].sysctl_ctx,
  533                     SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
  534                     OID_AUTO, "physical_siblings", CTLFLAG_RD,
  535                     pcpu_sysctl[i].physical_siblings, 0,
  536                     "Physical siblings");
  537 
  538                 /* Check if the core_id found is valid */
  539                 if (pcpu_sysctl[i].core_id == INVALID_ID) {
  540                         continue;
  541                 }
  542 
  543                 /* Add core id info */
  544                 SYSCTL_ADD_INT(&pcpu_sysctl[i].sysctl_ctx,
  545                     SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
  546                     OID_AUTO, "core_id", CTLFLAG_RD,
  547                     &pcpu_sysctl[i].core_id, 0,
  548                     "Core ID");
  549                 
  550                 /*Add core siblings */
  551                 SYSCTL_ADD_STRING(&pcpu_sysctl[i].sysctl_ctx,
  552                     SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
  553                     OID_AUTO, "core_siblings", CTLFLAG_RD,
  554                     pcpu_sysctl[i].core_siblings, 0,
  555                     "Core siblings");
  556         }
  557 }
  558 
  559 /* Build the CPU Topology and SYSCTL Topology tree */
  560 static void
  561 init_cpu_topology(void)
  562 {
  563         cpu_root_node = build_cpu_topology();
  564 
  565         init_pcpu_topology_sysctl();
  566         build_sysctl_cpu_topology();
  567 }
  568 SYSINIT(cpu_topology, SI_BOOT2_CPU_TOPOLOGY, SI_ORDER_FIRST,
  569     init_cpu_topology, NULL)

Cache object: 915bf45de000c54d397c6576b18b5b03


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