Page MenuHomeFreeBSD

D31215.id.diff
No OneTemporary

D31215.id.diff

Index: sys/dev/led/led.c
===================================================================
--- sys/dev/led/led.c
+++ sys/dev/led/led.c
@@ -17,6 +17,7 @@
#include <sys/conf.h>
#include <sys/ctype.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -41,21 +42,23 @@
char *ptr;
int count;
time_t last_second;
+ bool in_use;
+ bool destroying;
};
static struct unrhdr *led_unit;
static struct mtx led_mtx;
static struct sx led_sx;
static LIST_HEAD(, ledsc) led_list = LIST_HEAD_INITIALIZER(led_list);
-static struct callout led_ch;
static int blinkers = 0;
static MALLOC_DEFINE(M_LED, "LED", "LED driver");
static void
-led_timeout(void *p)
+led_timeout(void)
{
struct ledsc *sc;
+ int state;
LIST_FOREACH(sc, &led_list, list) {
if (sc->ptr == NULL)
@@ -72,20 +75,42 @@
if (sc->last_second == time_second)
continue;
sc->last_second = time_second;
- sc->func(sc->private, *sc->ptr == 'U');
+ state = *sc->ptr == 'U';
} else if (*sc->ptr >= 'a' && *sc->ptr <= 'j') {
- sc->func(sc->private, 0);
+ state = 0;
sc->count = (*sc->ptr & 0xf) - 1;
} else if (*sc->ptr >= 'A' && *sc->ptr <= 'J') {
- sc->func(sc->private, 1);
+ state = 1;
sc->count = (*sc->ptr & 0xf) - 1;
}
sc->ptr++;
if (*sc->ptr == '\0')
sc->ptr = sc->str;
+ sc->in_use = true;
+ mtx_unlock(&led_mtx);
+ sc->func(sc->private, state);
+ mtx_lock(&led_mtx);
+ sc->in_use = false;
+ if (sc->destroying)
+ wakeup(sc);
}
- if (blinkers > 0)
- callout_reset(&led_ch, hz / 10, led_timeout, p);
+}
+
+static void
+led_blinker_thread(void *arg __unused)
+{
+ int timeout;
+
+ mtx_lock(&led_mtx);
+ for (;;) {
+ if (blinkers > 0)
+ timeout = hz / 10;
+ else
+ timeout = 0;
+ (void)mtx_sleep(&led_list, &led_mtx, 0, "blnkwt", timeout);
+ led_timeout();
+ }
+ mtx_unlock(&led_mtx);
}
static int
@@ -95,11 +120,13 @@
sb2 = sc->spec;
sc->spec = *sb;
+ sc->count = 0;
if (*sb != NULL) {
sc->str = sbuf_data(*sb);
if (sc->ptr == NULL) {
blinkers++;
- callout_reset(&led_ch, hz / 10, led_timeout, NULL);
+ if (blinkers == 1)
+ wakeup(&led_list);
}
sc->ptr = sc->str;
} else {
@@ -107,9 +134,12 @@
if (sc->ptr != NULL)
blinkers--;
sc->ptr = NULL;
+ sc->in_use = true;
+ mtx_unlock(&led_mtx);
sc->func(sc->private, state);
+ mtx_lock(&led_mtx);
+ sc->in_use = false;
}
- sc->count = 0;
*sb = sb2;
return(0);
}
@@ -298,9 +328,9 @@
mtx_lock(&led_mtx);
sc->dev->si_drv1 = sc;
LIST_INSERT_HEAD(&led_list, sc, list);
+ mtx_unlock(&led_mtx);
if (state != -1)
sc->func(sc->private, state != 0);
- mtx_unlock(&led_mtx);
return (sc->dev);
}
@@ -312,12 +342,13 @@
mtx_lock(&led_mtx);
sc = dev->si_drv1;
+ sc->destroying = true;
+ while (sc->in_use)
+ (void)mtx_sleep(sc, &led_mtx, 0, "ledbsy", 0);
dev->si_drv1 = NULL;
if (sc->ptr != NULL)
blinkers--;
LIST_REMOVE(sc, list);
- if (LIST_EMPTY(&led_list))
- callout_stop(&led_ch);
mtx_unlock(&led_mtx);
sx_xlock(&led_sx);
@@ -337,7 +368,11 @@
led_unit = new_unrhdr(0, INT_MAX, NULL);
mtx_init(&led_mtx, "LED mtx", NULL, MTX_DEF);
sx_init(&led_sx, "LED sx");
- callout_init_mtx(&led_ch, &led_mtx, 0);
+
+ if (kproc_create(led_blinker_thread, NULL, NULL, 0, 0,
+ "led blinker") != 0) {
+ panic("led_drvinit: can't create thread");
+ }
}
SYSINIT(leddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, led_drvinit, NULL);

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 21, 5:53 AM (5 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30050571
Default Alt Text
D31215.id.diff (3 KB)

Event Timeline