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/kern_sensors.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: kern_sensors.c,v 1.40 2022/12/05 23:18:37 deraadt Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
    5  * Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 #include <sys/param.h>
   21 #include <sys/systm.h>
   22 #include <sys/malloc.h>
   23 #include <sys/queue.h>
   24 #include <sys/device.h>
   25 #include <sys/hotplug.h>
   26 #include <sys/timeout.h>
   27 #include <sys/task.h>
   28 #include <sys/rwlock.h>
   29 #include <sys/atomic.h>
   30 
   31 #include <sys/sensors.h>
   32 #include "hotplug.h"
   33 
   34 struct taskq            *sensors_taskq;
   35 int                     sensordev_count;
   36 SLIST_HEAD(, ksensordev) sensordev_list =
   37     SLIST_HEAD_INITIALIZER(sensordev_list);
   38 
   39 void
   40 sensordev_install(struct ksensordev *sensdev)
   41 {
   42         struct ksensordev *v, *nv;
   43         int s;
   44 
   45         s = splhigh();
   46         if (sensordev_count == 0) {
   47                 sensdev->num = 0;
   48                 SLIST_INSERT_HEAD(&sensordev_list, sensdev, list);
   49         } else {
   50                 for (v = SLIST_FIRST(&sensordev_list);
   51                     (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
   52                         if (nv->num - v->num > 1)
   53                                 break;
   54                 sensdev->num = v->num + 1;
   55                 SLIST_INSERT_AFTER(v, sensdev, list);
   56         }
   57         sensordev_count++;
   58         splx(s);
   59 
   60 #if NHOTPLUG > 0
   61         hotplug_device_attach(DV_DULL, "sensordev");
   62 #endif
   63 }
   64 
   65 void
   66 sensor_attach(struct ksensordev *sensdev, struct ksensor *sens)
   67 {
   68         struct ksensor *v, *nv;
   69         struct ksensors_head *sh;
   70         int s, i;
   71 
   72         s = splhigh();
   73         sh = &sensdev->sensors_list;
   74         if (sensdev->sensors_count == 0) {
   75                 for (i = 0; i < SENSOR_MAX_TYPES; i++)
   76                         sensdev->maxnumt[i] = 0;
   77                 sens->numt = 0;
   78                 SLIST_INSERT_HEAD(sh, sens, list);
   79         } else {
   80                 for (v = SLIST_FIRST(sh);
   81                     (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
   82                         if (v->type == sens->type && (v->type != nv->type || 
   83                             (v->type == nv->type && nv->numt - v->numt > 1)))
   84                                 break;
   85                 /* sensors of the same type go after each other */
   86                 if (v->type == sens->type)
   87                         sens->numt = v->numt + 1;
   88                 else
   89                         sens->numt = 0;
   90                 SLIST_INSERT_AFTER(v, sens, list);
   91         }
   92         /* we only increment maxnumt[] if the sensor was added
   93          * to the last position of sensors of this type
   94          */
   95         if (sensdev->maxnumt[sens->type] == sens->numt)
   96                 sensdev->maxnumt[sens->type]++;
   97         sensdev->sensors_count++;
   98         splx(s);
   99 }
  100 
  101 void
  102 sensordev_deinstall(struct ksensordev *sensdev)
  103 {
  104         int s;
  105 
  106         s = splhigh();
  107         sensordev_count--;
  108         SLIST_REMOVE(&sensordev_list, sensdev, ksensordev, list);
  109         splx(s);
  110 
  111 #if NHOTPLUG > 0
  112         hotplug_device_detach(DV_DULL, "sensordev");
  113 #endif
  114 }
  115 
  116 void
  117 sensor_detach(struct ksensordev *sensdev, struct ksensor *sens)
  118 {
  119         struct ksensors_head *sh;
  120         int s;
  121 
  122         s = splhigh();
  123         sh = &sensdev->sensors_list;
  124         sensdev->sensors_count--;
  125         SLIST_REMOVE(sh, sens, ksensor, list);
  126         /* we only decrement maxnumt[] if this is the tail 
  127          * sensor of this type
  128          */
  129         if (sens->numt == sensdev->maxnumt[sens->type] - 1)
  130                 sensdev->maxnumt[sens->type]--;
  131         splx(s);
  132 }
  133 
  134 int
  135 sensordev_get(int num, struct ksensordev **sensdev)
  136 {
  137         struct ksensordev *sd;
  138 
  139         SLIST_FOREACH(sd, &sensordev_list, list) {
  140                 if (sd->num == num) {
  141                         *sensdev = sd;
  142                         return (0);
  143                 }
  144                 if (sd->num > num)
  145                         return (ENXIO);
  146         }
  147         return (ENOENT);
  148 }
  149 
  150 int
  151 sensor_find(int dev, enum sensor_type type, int numt, struct ksensor **ksensorp)
  152 {
  153         struct ksensor *s;
  154         struct ksensordev *sensdev;
  155         struct ksensors_head *sh;
  156         int ret;
  157 
  158         ret = sensordev_get(dev, &sensdev);
  159         if (ret)
  160                 return (ret);
  161 
  162         sh = &sensdev->sensors_list;
  163         SLIST_FOREACH(s, sh, list)
  164                 if (s->type == type && s->numt == numt) {
  165                         *ksensorp = s;
  166                         return (0);
  167                 }
  168 
  169         return (ENOENT);
  170 }
  171 
  172 struct sensor_task {
  173         void                            (*func)(void *);
  174         void                            *arg;
  175 
  176         unsigned int                    period;
  177         struct timeout                  timeout;
  178         struct task                     task;
  179         struct rwlock                   lock;
  180 };
  181 
  182 void    sensor_task_tick(void *);
  183 void    sensor_task_work(void *);
  184 
  185 struct sensor_task *
  186 sensor_task_register(void *arg, void (*func)(void *), unsigned int period)
  187 {
  188         struct sensor_task *st;
  189 
  190 #ifdef DIAGNOSTIC
  191         if (period == 0)
  192                 panic("sensor_task_register: period is 0");
  193 #endif
  194 
  195         if (sensors_taskq == NULL &&
  196             (sensors_taskq = taskq_create("sensors", 1, IPL_HIGH, 0)) == NULL)
  197                 sensors_taskq = systq;
  198 
  199         st = malloc(sizeof(*st), M_DEVBUF, M_NOWAIT);
  200         if (st == NULL)
  201                 return (NULL);
  202 
  203         st->func = func;
  204         st->arg = arg;
  205         st->period = period;
  206         timeout_set(&st->timeout, sensor_task_tick, st);
  207         task_set(&st->task, sensor_task_work, st);
  208         rw_init(&st->lock, "sensor");
  209 
  210         sensor_task_tick(st);
  211 
  212         return (st);
  213 }
  214 
  215 void
  216 sensor_task_unregister(struct sensor_task *st)
  217 {
  218         /*
  219          * we can't reliably timeout_del or task_del because there's a window
  220          * between when they come off the lists and the timeout or task code
  221          * actually runs the respective handlers for them. mark the sensor_task
  222          * as dying by setting period to 0 and let sensor_task_work mop up.
  223          */
  224 
  225         rw_enter_write(&st->lock);
  226         st->period = 0;
  227         rw_exit_write(&st->lock);
  228 }
  229 
  230 void
  231 sensor_task_tick(void *arg)
  232 {
  233         struct sensor_task *st = arg;
  234         task_add(sensors_taskq, &st->task);
  235 }
  236 
  237 static int sensors_quiesced;
  238 static int sensors_running;
  239 
  240 void
  241 sensor_quiesce(void)
  242 {
  243         sensors_quiesced = 1;
  244         while (sensors_running > 0)
  245                 tsleep_nsec(&sensors_running, PZERO, "sensorpause", INFSLP);
  246 
  247 }
  248 void
  249 sensor_restart(void)
  250 {
  251         sensors_quiesced = 0;
  252 }
  253 
  254 void
  255 sensor_task_work(void *xst)
  256 {
  257         struct sensor_task *st = xst;
  258         unsigned int period = 0;
  259 
  260         atomic_inc_int(&sensors_running);
  261         rw_enter_write(&st->lock);
  262         period = st->period;
  263         if (period > 0 && !sensors_quiesced)
  264                 st->func(st->arg);
  265         rw_exit_write(&st->lock);
  266         if (atomic_dec_int_nv(&sensors_running) == 0) {
  267                 if (sensors_quiesced)
  268                         wakeup(&sensors_running);
  269         }
  270 
  271         if (period == 0)
  272                 free(st, M_DEVBUF, sizeof(*st));
  273         else 
  274                 timeout_add_sec(&st->timeout, period);
  275 }

Cache object: 7560ca1c65fe77e179e09d39a2912a77


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