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/dev/kstat.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 /* $OpenBSD: kstat.c,v 1.2 2022/01/31 05:09:17 dlg Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2020 David Gwynne <dlg@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/systm.h>
   21 #include <sys/types.h>
   22 #include <sys/malloc.h>
   23 #include <sys/pool.h>
   24 #include <sys/time.h>
   25 
   26 /* for kstat_set_cpu */
   27 #include <sys/proc.h>
   28 #include <sys/sched.h>
   29 
   30 #include <sys/kstat.h>
   31 
   32 RBT_HEAD(kstat_id_tree, kstat);
   33 
   34 static inline int
   35 kstat_id_cmp(const struct kstat *a, const struct kstat *b)
   36 {
   37         if (a->ks_id > b->ks_id)
   38                 return (1);
   39         if (a->ks_id < b->ks_id)
   40                 return (-1);
   41 
   42         return (0);
   43 }
   44 
   45 RBT_PROTOTYPE(kstat_id_tree, kstat, ks_id_entry, kstat_id_cmp);
   46 
   47 RBT_HEAD(kstat_pv_tree, kstat);
   48 
   49 static inline int
   50 kstat_pv_cmp(const struct kstat *a, const struct kstat *b)
   51 {
   52         int rv;
   53 
   54         rv = strcmp(a->ks_provider, b->ks_provider);
   55         if (rv != 0)
   56                 return (rv);
   57 
   58         if (a->ks_instance > b->ks_instance)
   59                 return (1);
   60         if (a->ks_instance < b->ks_instance)
   61                 return (-1);
   62 
   63         rv = strcmp(a->ks_name, b->ks_name);
   64         if (rv != 0)
   65                 return (rv);
   66 
   67         if (a->ks_unit > b->ks_unit)
   68                 return (1);
   69         if (a->ks_unit < b->ks_unit)
   70                 return (-1);
   71 
   72         return (0);
   73 }
   74 
   75 RBT_PROTOTYPE(kstat_pv_tree, kstat, ks_pv_entry, kstat_pv_cmp);
   76 
   77 RBT_HEAD(kstat_nm_tree, kstat);
   78 
   79 static inline int
   80 kstat_nm_cmp(const struct kstat *a, const struct kstat *b)
   81 {
   82         int rv;
   83 
   84         rv = strcmp(a->ks_name, b->ks_name);
   85         if (rv != 0)
   86                 return (rv);
   87 
   88         if (a->ks_unit > b->ks_unit)
   89                 return (1);
   90         if (a->ks_unit < b->ks_unit)
   91                 return (-1);
   92 
   93         rv = strcmp(a->ks_provider, b->ks_provider);
   94         if (rv != 0)
   95                 return (rv);
   96 
   97         if (a->ks_instance > b->ks_instance)
   98                 return (1);
   99         if (a->ks_instance < b->ks_instance)
  100                 return (-1);
  101 
  102         return (0);
  103 }
  104 
  105 RBT_PROTOTYPE(kstat_nm_tree, kstat, ks_nm_entry, kstat_nm_cmp);
  106 
  107 struct kstat_lock_ops {
  108         void    (*enter)(void *);
  109         void    (*leave)(void *);
  110 };
  111 
  112 #define kstat_enter(_ks) (_ks)->ks_lock_ops->enter((_ks)->ks_lock)
  113 #define kstat_leave(_ks) (_ks)->ks_lock_ops->leave((_ks)->ks_lock)
  114 
  115 const struct kstat_lock_ops kstat_rlock_ops = {
  116         (void (*)(void *))rw_enter_read,
  117         (void (*)(void *))rw_exit_read,
  118 };
  119 
  120 const struct kstat_lock_ops kstat_wlock_ops = {
  121         (void (*)(void *))rw_enter_write,
  122         (void (*)(void *))rw_exit_write,
  123 };
  124 
  125 const struct kstat_lock_ops kstat_mutex_ops = {
  126         (void (*)(void *))mtx_enter,
  127         (void (*)(void *))mtx_leave,
  128 };
  129 
  130 void kstat_cpu_enter(void *);
  131 void kstat_cpu_leave(void *);
  132 
  133 const struct kstat_lock_ops kstat_cpu_ops = {
  134         kstat_cpu_enter,
  135         kstat_cpu_leave,
  136 };
  137 
  138 struct rwlock           kstat_lock = RWLOCK_INITIALIZER("kstat");
  139 
  140 /*
  141  * The global state is versioned so changes to the set of kstats
  142  * can be detected. This is an int so it can be read atomically on
  143  * any arch, which is a ridiculous optimisation, really.
  144  */
  145 unsigned int            kstat_version = 0;
  146 
  147 /*
  148  * kstat structures have a unique identifier so they can be found
  149  * quickly. Identifiers are 64bit in the hope that it won't wrap
  150  * during the runtime of a system. The identifiers start at 1 so that
  151  * 0 can be used as the first value for userland to iterate with.
  152  */
  153 uint64_t                        kstat_next_id = 1;
  154 
  155 struct kstat_id_tree    kstat_id_tree = RBT_INITIALIZER();
  156 struct kstat_pv_tree    kstat_pv_tree = RBT_INITIALIZER();
  157 struct kstat_nm_tree    kstat_nm_tree = RBT_INITIALIZER();
  158 struct pool             kstat_pool;
  159 
  160 struct rwlock           kstat_default_lock = RWLOCK_INITIALIZER("kstatlk");
  161 
  162 int     kstat_read(struct kstat *);
  163 int     kstat_copy(struct kstat *, void *);
  164 
  165 int
  166 kstatattach(int num)
  167 {
  168         /* XXX install system stats here */
  169         return (0);
  170 }
  171 
  172 int
  173 kstatopen(dev_t dev, int flag, int mode, struct proc *p)
  174 {
  175         return (0);
  176 }
  177 
  178 int
  179 kstatclose(dev_t dev, int flag, int mode, struct proc *p)
  180 {
  181         return (0);
  182 }
  183 
  184 int
  185 kstatioc_enter(struct kstat_req *ksreq)
  186 {
  187         int error;
  188 
  189         error = rw_enter(&kstat_lock, RW_READ | RW_INTR);
  190         if (error != 0)
  191                 return (error);
  192 
  193         if (!ISSET(ksreq->ks_rflags, KSTATIOC_F_IGNVER) &&
  194             ksreq->ks_version != kstat_version) {
  195                 error = EINVAL;
  196                 goto error;
  197         }
  198 
  199         return (0);
  200 
  201 error:
  202         rw_exit(&kstat_lock);
  203         return (error);
  204 }
  205 
  206 int
  207 kstatioc_leave(struct kstat_req *ksreq, struct kstat *ks)
  208 {
  209         void *buf = NULL;
  210         size_t klen = 0, ulen = 0;
  211         struct timespec updated;
  212         int error = 0;
  213 
  214         if (ks == NULL) {
  215                 error = ENOENT;
  216                 goto error;
  217         }
  218 
  219         switch (ks->ks_state) {
  220         case KSTAT_S_CREATED:
  221                 ksreq->ks_updated = ks->ks_created;
  222                 ksreq->ks_interval.tv_sec = 0;
  223                 ksreq->ks_interval.tv_nsec = 0;
  224                 ksreq->ks_datalen = 0;
  225                 ksreq->ks_dataver = 0;
  226                 break;
  227 
  228         case KSTAT_S_INSTALLED:
  229                 ksreq->ks_dataver = ks->ks_dataver;
  230                 ksreq->ks_interval = ks->ks_interval;
  231 
  232                 if (ksreq->ks_data == NULL) {
  233                         /* userland doesn't want actual data, so shortcut */ 
  234                         kstat_enter(ks);
  235                         ksreq->ks_datalen = ks->ks_datalen;
  236                         ksreq->ks_updated = ks->ks_updated;
  237                         kstat_leave(ks);
  238                         break;
  239                 }
  240 
  241                 klen = ks->ks_datalen; /* KSTAT_F_REALLOC */
  242                 buf = malloc(klen, M_TEMP, M_WAITOK|M_CANFAIL);
  243                 if (buf == NULL) {
  244                         error = ENOMEM;
  245                         goto error;
  246                 }
  247 
  248                 kstat_enter(ks);
  249                 error = (*ks->ks_read)(ks);
  250                 if (error == 0) {
  251                         updated = ks->ks_updated;
  252 
  253                         /* KSTAT_F_REALLOC */
  254                         KASSERTMSG(ks->ks_datalen == klen,
  255                             "kstat doesnt support resized data yet");
  256 
  257                         error = (*ks->ks_copy)(ks, buf);
  258                 }
  259                 kstat_leave(ks);
  260 
  261                 if (error != 0)
  262                         goto error;
  263 
  264                 ulen = ksreq->ks_datalen;
  265                 ksreq->ks_datalen = klen; /* KSTAT_F_REALLOC */
  266                 ksreq->ks_updated = updated;
  267                 break;
  268         default:
  269                 panic("ks %p unexpected state %u", ks, ks->ks_state);
  270         }
  271 
  272         ksreq->ks_version = kstat_version;
  273         ksreq->ks_id = ks->ks_id;
  274 
  275         if (strlcpy(ksreq->ks_provider, ks->ks_provider,
  276             sizeof(ksreq->ks_provider)) >= sizeof(ksreq->ks_provider))
  277                 panic("kstat %p provider string has grown", ks);
  278         ksreq->ks_instance = ks->ks_instance;
  279         if (strlcpy(ksreq->ks_name, ks->ks_name,
  280             sizeof(ksreq->ks_name)) >= sizeof(ksreq->ks_name))
  281                 panic("kstat %p name string has grown", ks);
  282         ksreq->ks_unit = ks->ks_unit;
  283 
  284         ksreq->ks_created = ks->ks_created;
  285         ksreq->ks_type = ks->ks_type;
  286         ksreq->ks_state = ks->ks_state;
  287 
  288 error:
  289         rw_exit(&kstat_lock);
  290 
  291         if (buf != NULL) {
  292                 if (error == 0)
  293                         error = copyout(buf, ksreq->ks_data, min(klen, ulen));
  294 
  295                 free(buf, M_TEMP, klen);
  296         }
  297 
  298         return (error);
  299 }
  300 
  301 int
  302 kstatioc_find_id(struct kstat_req *ksreq)
  303 {
  304         struct kstat *ks, key;
  305         int error;
  306 
  307         error = kstatioc_enter(ksreq);
  308         if (error != 0)
  309                 return (error);
  310 
  311         key.ks_id = ksreq->ks_id;
  312 
  313         ks = RBT_FIND(kstat_id_tree, &kstat_id_tree, &key);
  314 
  315         return (kstatioc_leave(ksreq, ks));
  316 }
  317 
  318 int
  319 kstatioc_nfind_id(struct kstat_req *ksreq)
  320 {
  321         struct kstat *ks, key;
  322         int error;
  323 
  324         error = kstatioc_enter(ksreq);
  325         if (error != 0)
  326                 return (error);
  327 
  328         key.ks_id = ksreq->ks_id;
  329 
  330         ks = RBT_NFIND(kstat_id_tree, &kstat_id_tree, &key);
  331 
  332         return (kstatioc_leave(ksreq, ks));
  333 }
  334 
  335 int
  336 kstatioc_find_pv(struct kstat_req *ksreq)
  337 {
  338         struct kstat *ks, key;
  339         int error;
  340 
  341         error = kstatioc_enter(ksreq);
  342         if (error != 0)
  343                 return (error);
  344 
  345         key.ks_provider = ksreq->ks_provider;
  346         key.ks_instance = ksreq->ks_instance;
  347         key.ks_name = ksreq->ks_name;
  348         key.ks_unit = ksreq->ks_unit;
  349 
  350         ks = RBT_FIND(kstat_pv_tree, &kstat_pv_tree, &key);
  351 
  352         return (kstatioc_leave(ksreq, ks));
  353 }
  354 
  355 int
  356 kstatioc_nfind_pv(struct kstat_req *ksreq)
  357 {
  358         struct kstat *ks, key;
  359         int error;
  360 
  361         error = kstatioc_enter(ksreq);
  362         if (error != 0)
  363                 return (error);
  364 
  365         key.ks_provider = ksreq->ks_provider;
  366         key.ks_instance = ksreq->ks_instance;
  367         key.ks_name = ksreq->ks_name;
  368         key.ks_unit = ksreq->ks_unit;
  369 
  370         ks = RBT_NFIND(kstat_pv_tree, &kstat_pv_tree, &key);
  371 
  372         return (kstatioc_leave(ksreq, ks));
  373 }
  374 
  375 int
  376 kstatioc_find_nm(struct kstat_req *ksreq)
  377 {
  378         struct kstat *ks, key;
  379         int error;
  380 
  381         error = kstatioc_enter(ksreq);
  382         if (error != 0)
  383                 return (error);
  384 
  385         key.ks_name = ksreq->ks_name;
  386         key.ks_unit = ksreq->ks_unit;
  387         key.ks_provider = ksreq->ks_provider;
  388         key.ks_instance = ksreq->ks_instance;
  389 
  390         ks = RBT_FIND(kstat_nm_tree, &kstat_nm_tree, &key);
  391 
  392         return (kstatioc_leave(ksreq, ks));
  393 }
  394 
  395 int
  396 kstatioc_nfind_nm(struct kstat_req *ksreq)
  397 {
  398         struct kstat *ks, key;
  399         int error;
  400 
  401         error = kstatioc_enter(ksreq);
  402         if (error != 0)
  403                 return (error);
  404 
  405         key.ks_name = ksreq->ks_name;
  406         key.ks_unit = ksreq->ks_unit;
  407         key.ks_provider = ksreq->ks_provider;
  408         key.ks_instance = ksreq->ks_instance;
  409 
  410         ks = RBT_NFIND(kstat_nm_tree, &kstat_nm_tree, &key);
  411 
  412         return (kstatioc_leave(ksreq, ks));
  413 }
  414 
  415 int
  416 kstatioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  417 {
  418         struct kstat_req *ksreq = (struct kstat_req *)data;
  419         int error = 0;
  420 
  421         KERNEL_UNLOCK();
  422 
  423         switch (cmd) {
  424         case KSTATIOC_VERSION:
  425                 *(unsigned int *)data = kstat_version;
  426                 break;
  427 
  428         case KSTATIOC_FIND_ID:
  429                 error = kstatioc_find_id(ksreq);
  430                 break;
  431         case KSTATIOC_NFIND_ID:
  432                 error = kstatioc_nfind_id(ksreq);
  433                 break;
  434         case KSTATIOC_FIND_PROVIDER:
  435                 error = kstatioc_find_pv(ksreq);
  436                 break;
  437         case KSTATIOC_NFIND_PROVIDER:
  438                 error = kstatioc_nfind_pv(ksreq);
  439                 break;
  440         case KSTATIOC_FIND_NAME:
  441                 error = kstatioc_find_nm(ksreq);
  442                 break;
  443         case KSTATIOC_NFIND_NAME:
  444                 error = kstatioc_nfind_nm(ksreq);
  445                 break;
  446 
  447         default:
  448                 error = ENOTTY;
  449                 break;
  450         }
  451 
  452         KERNEL_LOCK();
  453 
  454         return (error);
  455 }
  456 
  457 void
  458 kstat_init(void)
  459 {
  460         static int initialized = 0;
  461 
  462         if (initialized)
  463                 return;
  464 
  465         pool_init(&kstat_pool, sizeof(struct kstat), 0, IPL_NONE,
  466             PR_WAITOK | PR_RWLOCK, "kstatmem", NULL);
  467 
  468         initialized = 1;
  469 }
  470 
  471 int
  472 kstat_strcheck(const char *str)
  473 {
  474         size_t i, l;
  475 
  476         l = strlen(str);
  477         if (l == 0 || l >= KSTAT_STRLEN)
  478                 return (-1);
  479         for (i = 0; i < l; i++) {
  480                 int ch = str[i];
  481                 if (ch >= 'a' && ch <= 'z')
  482                         continue;
  483                 if (ch >= 'A' && ch <= 'Z')
  484                         continue;
  485                 if (ch >= '' && ch <= '9')
  486                         continue;
  487                 switch (ch) {
  488                 case '-':
  489                 case '_':
  490                 case '.':
  491                         break;
  492                 default:
  493                         return (-1);
  494                 }
  495         }
  496 
  497         return (0);
  498 }
  499 
  500 struct kstat *
  501 kstat_create(const char *provider, unsigned int instance,
  502     const char *name, unsigned int unit,
  503     unsigned int type, unsigned int flags)
  504 {
  505         struct kstat *ks, *oks;
  506 
  507         if (kstat_strcheck(provider) == -1)
  508                 panic("invalid provider string");
  509         if (kstat_strcheck(name) == -1)
  510                 panic("invalid name string");
  511 
  512         kstat_init();
  513 
  514         ks = pool_get(&kstat_pool, PR_WAITOK|PR_ZERO);
  515 
  516         ks->ks_provider = provider;
  517         ks->ks_instance = instance;
  518         ks->ks_name = name;
  519         ks->ks_unit = unit;
  520         ks->ks_flags = flags;
  521         ks->ks_type = type;
  522         ks->ks_state = KSTAT_S_CREATED;
  523 
  524         getnanouptime(&ks->ks_created);
  525         ks->ks_updated = ks->ks_created;
  526 
  527         ks->ks_lock = &kstat_default_lock;
  528         ks->ks_lock_ops = &kstat_wlock_ops;
  529         ks->ks_read = kstat_read;
  530         ks->ks_copy = kstat_copy;
  531 
  532         rw_enter_write(&kstat_lock);
  533         ks->ks_id = kstat_next_id;
  534 
  535         oks = RBT_INSERT(kstat_pv_tree, &kstat_pv_tree, ks);
  536         if (oks == NULL) {
  537                 /* commit */
  538                 kstat_next_id++;
  539                 kstat_version++;
  540 
  541                 oks = RBT_INSERT(kstat_nm_tree, &kstat_nm_tree, ks);
  542                 if (oks != NULL)
  543                         panic("kstat name collision! (%llu)", ks->ks_id);
  544 
  545                 oks = RBT_INSERT(kstat_id_tree, &kstat_id_tree, ks);
  546                 if (oks != NULL)
  547                         panic("kstat id collision! (%llu)", ks->ks_id);
  548         }
  549         rw_exit_write(&kstat_lock);
  550 
  551         if (oks != NULL) {
  552                 pool_put(&kstat_pool, ks);
  553                 return (NULL);
  554         }
  555 
  556         return (ks);
  557 }
  558 
  559 void
  560 kstat_set_rlock(struct kstat *ks, struct rwlock *rwl)
  561 {
  562         KASSERT(ks->ks_state == KSTAT_S_CREATED);
  563 
  564         ks->ks_lock = rwl;
  565         ks->ks_lock_ops = &kstat_rlock_ops;
  566 }
  567 
  568 void
  569 kstat_set_wlock(struct kstat *ks, struct rwlock *rwl)
  570 {
  571         KASSERT(ks->ks_state == KSTAT_S_CREATED);
  572 
  573         ks->ks_lock = rwl;
  574         ks->ks_lock_ops = &kstat_wlock_ops;
  575 }
  576 
  577 void
  578 kstat_set_mutex(struct kstat *ks, struct mutex *mtx)
  579 {
  580         KASSERT(ks->ks_state == KSTAT_S_CREATED);
  581 
  582         ks->ks_lock = mtx;
  583         ks->ks_lock_ops = &kstat_mutex_ops;
  584 }
  585 
  586 void
  587 kstat_cpu_enter(void *p)
  588 {
  589         struct cpu_info *ci = p;
  590         sched_peg_curproc(ci);
  591 }
  592 
  593 void
  594 kstat_cpu_leave(void *p)
  595 {
  596         atomic_clearbits_int(&curproc->p_flag, P_CPUPEG);
  597 }
  598 
  599 void
  600 kstat_set_cpu(struct kstat *ks, struct cpu_info *ci)
  601 {
  602         KASSERT(ks->ks_state == KSTAT_S_CREATED);
  603 
  604         ks->ks_lock = ci;
  605         ks->ks_lock_ops = &kstat_cpu_ops;
  606 }
  607 
  608 int
  609 kstat_read_nop(struct kstat *ks)
  610 {
  611         return (0);
  612 }
  613 
  614 void
  615 kstat_install(struct kstat *ks)
  616 {
  617         if (!ISSET(ks->ks_flags, KSTAT_F_REALLOC)) {
  618                 KASSERTMSG(ks->ks_copy != NULL || ks->ks_data != NULL,
  619                     "kstat %p %s:%u:%s:%u must provide ks_copy or ks_data", ks,
  620                     ks->ks_provider, ks->ks_instance, ks->ks_name, ks->ks_unit);
  621                 KASSERT(ks->ks_datalen > 0);
  622         }
  623 
  624         rw_enter_write(&kstat_lock);
  625         ks->ks_state = KSTAT_S_INSTALLED;
  626         rw_exit_write(&kstat_lock);
  627 }
  628 
  629 void
  630 kstat_remove(struct kstat *ks)
  631 {
  632         rw_enter_write(&kstat_lock);
  633         KASSERTMSG(ks->ks_state == KSTAT_S_INSTALLED,
  634             "kstat %p %s:%u:%s:%u is not installed", ks,
  635             ks->ks_provider, ks->ks_instance, ks->ks_name, ks->ks_unit);
  636           
  637         ks->ks_state = KSTAT_S_CREATED;
  638         rw_exit_write(&kstat_lock);
  639 }
  640 
  641 void
  642 kstat_destroy(struct kstat *ks)
  643 {
  644         rw_enter_write(&kstat_lock);
  645         RBT_REMOVE(kstat_id_tree, &kstat_id_tree, ks);
  646         RBT_REMOVE(kstat_pv_tree, &kstat_pv_tree, ks);
  647         RBT_REMOVE(kstat_nm_tree, &kstat_nm_tree, ks);
  648         kstat_version++;
  649         rw_exit_write(&kstat_lock);
  650 
  651         pool_put(&kstat_pool, ks);
  652 }
  653 
  654 int
  655 kstat_read(struct kstat *ks)
  656 {
  657         getnanouptime(&ks->ks_updated);
  658         return (0);
  659 }
  660 
  661 int
  662 kstat_copy(struct kstat *ks, void *buf)
  663 {
  664         memcpy(buf, ks->ks_data, ks->ks_datalen);
  665         return (0);
  666 }
  667 
  668 RBT_GENERATE(kstat_id_tree, kstat, ks_id_entry, kstat_id_cmp);
  669 RBT_GENERATE(kstat_pv_tree, kstat, ks_pv_entry, kstat_pv_cmp);
  670 RBT_GENERATE(kstat_nm_tree, kstat, ks_nm_entry, kstat_nm_cmp);
  671 
  672 void
  673 kstat_kv_init(struct kstat_kv *kv, const char *name, enum kstat_kv_type type)
  674 {
  675         memset(kv, 0, sizeof(*kv));
  676         strlcpy(kv->kv_key, name, sizeof(kv->kv_key)); /* XXX truncated? */
  677         kv->kv_type = type;
  678         kv->kv_unit = KSTAT_KV_U_NONE;
  679 }
  680 
  681 void
  682 kstat_kv_unit_init(struct kstat_kv *kv, const char *name,
  683     enum kstat_kv_type type, enum kstat_kv_unit unit)
  684 {
  685         switch (type) {
  686         case KSTAT_KV_T_COUNTER64:
  687         case KSTAT_KV_T_COUNTER32:
  688         case KSTAT_KV_T_UINT64:
  689         case KSTAT_KV_T_INT64:
  690         case KSTAT_KV_T_UINT32:
  691         case KSTAT_KV_T_INT32:
  692                 break;
  693         default:
  694                 panic("kv unit init %s: unit for non-integer type", name);
  695         }
  696 
  697         memset(kv, 0, sizeof(*kv));
  698         strlcpy(kv->kv_key, name, sizeof(kv->kv_key)); /* XXX truncated? */
  699         kv->kv_type = type;
  700         kv->kv_unit = unit;
  701 }

Cache object: 56684e9ebce4670e2a9c4005e318b8fb


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