LCOV - code coverage report
Current view: top level - kern - kern_sensors.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 124 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: kern_sensors.c,v 1.38 2017/04/09 15:47:18 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           0 : sensordev_install(struct ksensordev *sensdev)
      41             : {
      42             :         struct ksensordev *v, *nv;
      43             :         int s;
      44             : 
      45           0 :         s = splhigh();
      46           0 :         if (sensordev_count == 0) {
      47           0 :                 sensdev->num = 0;
      48           0 :                 SLIST_INSERT_HEAD(&sensordev_list, sensdev, list);
      49           0 :         } else {
      50           0 :                 for (v = SLIST_FIRST(&sensordev_list);
      51           0 :                     (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
      52           0 :                         if (nv->num - v->num > 1)
      53             :                                 break;
      54           0 :                 sensdev->num = v->num + 1;
      55           0 :                 SLIST_INSERT_AFTER(v, sensdev, list);
      56             :         }
      57           0 :         sensordev_count++;
      58           0 :         splx(s);
      59             : 
      60             : #if NHOTPLUG > 0
      61           0 :         hotplug_device_attach(DV_DULL, "sensordev");
      62             : #endif
      63           0 : }
      64             : 
      65             : void
      66           0 : 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           0 :         s = splhigh();
      73           0 :         sh = &sensdev->sensors_list;
      74           0 :         if (sensdev->sensors_count == 0) {
      75           0 :                 for (i = 0; i < SENSOR_MAX_TYPES; i++)
      76           0 :                         sensdev->maxnumt[i] = 0;
      77           0 :                 sens->numt = 0;
      78           0 :                 SLIST_INSERT_HEAD(sh, sens, list);
      79           0 :         } else {
      80           0 :                 for (v = SLIST_FIRST(sh);
      81           0 :                     (nv = SLIST_NEXT(v, list)) != NULL; v = nv)
      82           0 :                         if (v->type == sens->type && (v->type != nv->type || 
      83           0 :                             (v->type == nv->type && nv->numt - v->numt > 1)))
      84             :                                 break;
      85             :                 /* sensors of the same type go after each other */
      86           0 :                 if (v->type == sens->type)
      87           0 :                         sens->numt = v->numt + 1;
      88             :                 else
      89           0 :                         sens->numt = 0;
      90           0 :                 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           0 :         if (sensdev->maxnumt[sens->type] == sens->numt)
      96           0 :                 sensdev->maxnumt[sens->type]++;
      97           0 :         sensdev->sensors_count++;
      98           0 :         splx(s);
      99           0 : }
     100             : 
     101             : void
     102           0 : sensordev_deinstall(struct ksensordev *sensdev)
     103             : {
     104             :         int s;
     105             : 
     106           0 :         s = splhigh();
     107           0 :         sensordev_count--;
     108           0 :         SLIST_REMOVE(&sensordev_list, sensdev, ksensordev, list);
     109           0 :         splx(s);
     110             : 
     111             : #if NHOTPLUG > 0
     112           0 :         hotplug_device_detach(DV_DULL, "sensordev");
     113             : #endif
     114           0 : }
     115             : 
     116             : void
     117           0 : sensor_detach(struct ksensordev *sensdev, struct ksensor *sens)
     118             : {
     119             :         struct ksensors_head *sh;
     120             :         int s;
     121             : 
     122           0 :         s = splhigh();
     123           0 :         sh = &sensdev->sensors_list;
     124           0 :         sensdev->sensors_count--;
     125           0 :         SLIST_REMOVE(sh, sens, ksensor, list);
     126             :         /* we only decrement maxnumt[] if this is the tail 
     127             :          * sensor of this type
     128             :          */
     129           0 :         if (sens->numt == sensdev->maxnumt[sens->type] - 1)
     130           0 :                 sensdev->maxnumt[sens->type]--;
     131           0 :         splx(s);
     132           0 : }
     133             : 
     134             : int
     135           0 : sensordev_get(int num, struct ksensordev **sensdev)
     136             : {
     137             :         struct ksensordev *sd;
     138             : 
     139           0 :         SLIST_FOREACH(sd, &sensordev_list, list) {
     140           0 :                 if (sd->num == num) {
     141           0 :                         *sensdev = sd;
     142           0 :                         return (0);
     143             :                 }
     144           0 :                 if (sd->num > num)
     145           0 :                         return (ENXIO);
     146             :         }
     147           0 :         return (ENOENT);
     148           0 : }
     149             : 
     150             : int
     151           0 : sensor_find(int dev, enum sensor_type type, int numt, struct ksensor **ksensorp)
     152             : {
     153             :         struct ksensor *s;
     154           0 :         struct ksensordev *sensdev;
     155             :         struct ksensors_head *sh;
     156             :         int ret;
     157             : 
     158           0 :         ret = sensordev_get(dev, &sensdev);
     159           0 :         if (ret)
     160           0 :                 return (ret);
     161             : 
     162           0 :         sh = &sensdev->sensors_list;
     163           0 :         SLIST_FOREACH(s, sh, list)
     164           0 :                 if (s->type == type && s->numt == numt) {
     165           0 :                         *ksensorp = s;
     166           0 :                         return (0);
     167             :                 }
     168             : 
     169           0 :         return (ENOENT);
     170           0 : }
     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           0 : sensor_task_register(void *arg, void (*func)(void *), unsigned int period)
     187             : {
     188             :         struct sensor_task *st;
     189             : 
     190             : #ifdef DIAGNOSTIC
     191           0 :         if (period == 0)
     192           0 :                 panic("sensor_task_register: period is 0");
     193             : #endif
     194             : 
     195           0 :         if (sensors_taskq == NULL &&
     196           0 :             (sensors_taskq = taskq_create("sensors", 1, IPL_HIGH, 0)) == NULL)
     197           0 :                 sensors_taskq = systq;
     198             : 
     199           0 :         st = malloc(sizeof(*st), M_DEVBUF, M_NOWAIT);
     200           0 :         if (st == NULL)
     201           0 :                 return (NULL);
     202             : 
     203           0 :         st->func = func;
     204           0 :         st->arg = arg;
     205           0 :         st->period = period;
     206           0 :         timeout_set(&st->timeout, sensor_task_tick, st);
     207           0 :         task_set(&st->task, sensor_task_work, st);
     208           0 :         rw_init(&st->lock, "sensor");
     209             : 
     210           0 :         sensor_task_tick(st);
     211             : 
     212           0 :         return (st);
     213           0 : }
     214             : 
     215             : void
     216           0 : 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           0 :         rw_enter_write(&st->lock);
     226           0 :         st->period = 0;
     227           0 :         rw_exit_write(&st->lock);
     228           0 : }
     229             : 
     230             : void
     231           0 : sensor_task_tick(void *arg)
     232             : {
     233           0 :         struct sensor_task *st = arg;
     234           0 :         task_add(sensors_taskq, &st->task);
     235           0 : }
     236             : 
     237             : static int sensors_quiesced;
     238             : static int sensors_running;
     239             : 
     240             : void
     241           0 : sensor_quiesce(void)
     242             : {
     243           0 :         sensors_quiesced = 1;
     244           0 :         while (sensors_running > 0)
     245           0 :                 tsleep(&sensors_running, PZERO, "sensorpause", 0);
     246             :         
     247           0 : }
     248             : void
     249           0 : sensor_restart(void)
     250             : {
     251           0 :         sensors_quiesced = 0;
     252           0 : }
     253             : 
     254             : void
     255           0 : sensor_task_work(void *xst)
     256             : {
     257           0 :         struct sensor_task *st = xst;
     258             :         unsigned int period = 0;
     259             : 
     260           0 :         atomic_inc_int(&sensors_running);
     261           0 :         rw_enter_write(&st->lock);
     262           0 :         period = st->period;
     263           0 :         if (period > 0 && !sensors_quiesced)
     264           0 :                 st->func(st->arg);
     265           0 :         rw_exit_write(&st->lock);
     266           0 :         if (atomic_dec_int_nv(&sensors_running) == 0) {
     267           0 :                 if (sensors_quiesced)
     268           0 :                         wakeup(&sensors_running);
     269             :         }
     270             : 
     271           0 :         if (period == 0)
     272           0 :                 free(st, M_DEVBUF, sizeof(*st));
     273             :         else 
     274           0 :                 timeout_add_sec(&st->timeout, period);
     275           0 : }

Generated by: LCOV version 1.13