Page MenuHomeFreeBSD

D26140.id76047.diff
No OneTemporary

D26140.id76047.diff

Index: sys/kern/subr_bus.c
===================================================================
--- sys/kern/subr_bus.c
+++ sys/kern/subr_bus.c
@@ -405,27 +405,30 @@
.d_name = "devctl",
};
+#define DEVCTL_BUFFER (1024 - sizeof(void *))
struct dev_event_info
{
- char *dei_data;
STAILQ_ENTRY(dev_event_info) dei_link;
+ char dei_data[DEVCTL_BUFFER];
};
STAILQ_HEAD(devq, dev_event_info);
static struct dev_softc
{
- int inuse;
- int nonblock;
- int queued;
- int async;
- struct mtx mtx;
- struct cv cv;
- struct selinfo sel;
- struct devq devq;
- struct sigio *sigio;
+ int inuse;
+ int nonblock;
+ int queued;
+ int async;
+ struct mtx mtx;
+ struct cv cv;
+ struct selinfo sel;
+ struct devq devq;
+ struct sigio *sigio;
+ uma_zone_t zone;
} devsoftc;
+
static void filt_devctl_detach(struct knote *kn);
static int filt_devctl_read(struct knote *kn, long hint);
@@ -446,6 +449,9 @@
cv_init(&devsoftc.cv, "dev cv");
STAILQ_INIT(&devsoftc.devq);
knlist_init_mtx(&devsoftc.sel.si_note, &devsoftc.mtx);
+ devsoftc.zone = uma_zcreate("DEVCTL", sizeof(struct dev_event_info),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ uma_prealloc(devsoftc.zone, devctl_queue_length);
devctl2_init();
}
@@ -510,8 +516,7 @@
devsoftc.queued--;
mtx_unlock(&devsoftc.mtx);
rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio);
- free(n1->dei_data, M_BUS);
- free(n1, M_BUS);
+ uma_zfree(devsoftc.zone, n1);
return (rv);
}
@@ -600,42 +605,41 @@
return (devsoftc.inuse == 1);
}
-/**
- * @brief Queue data to be read from the devctl device
- *
- * Generic interface to queue data to the devctl device. It is
- * assumed that @p data is properly formatted. It is further assumed
- * that @p data is allocated using the M_BUS malloc type.
- */
-static void
-devctl_queue_data_f(char *data, int flags)
+static struct dev_event_info *
+devctl_alloc_dei()
{
- struct dev_event_info *n1 = NULL, *n2 = NULL;
+ struct dev_event_info *dei = NULL;
- if (strlen(data) == 0)
- goto out;
+ mtx_lock(&devsoftc.mtx);
if (devctl_queue_length == 0)
goto out;
- n1 = malloc(sizeof(*n1), M_BUS, flags);
- if (n1 == NULL)
- goto out;
- n1->dei_data = data;
- mtx_lock(&devsoftc.mtx);
- if (devctl_queue_length == 0) {
- mtx_unlock(&devsoftc.mtx);
- free(n1->dei_data, M_BUS);
- free(n1, M_BUS);
- return;
- }
- /* Leave at least one spot in the queue... */
- while (devsoftc.queued > devctl_queue_length - 1) {
- n2 = STAILQ_FIRST(&devsoftc.devq);
+ if (devctl_queue_length == devsoftc.queued) {
+ dei = STAILQ_FIRST(&devsoftc.devq);
STAILQ_REMOVE_HEAD(&devsoftc.devq, dei_link);
- free(n2->dei_data, M_BUS);
- free(n2, M_BUS);
devsoftc.queued--;
+ } else {
+ /* dei can't be NULL -- we know we have at least one in the zone */
+ dei = uma_zalloc(devsoftc.zone, M_NOWAIT);
+ MPASS(dei != NULL);
}
- STAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link);
+ *dei->dei_data = '\0';
+out:
+ mtx_unlock(&devsoftc.mtx);
+ return (dei);
+}
+
+static void
+devctl_free_dei(struct dev_event_info *dei)
+{
+ uma_zfree(devsoftc.zone, dei);
+}
+
+static void
+devctl_queue(struct dev_event_info *dei)
+{
+// printf("%s", dei->dei_data);
+ mtx_lock(&devsoftc.mtx);
+ STAILQ_INSERT_TAIL(&devsoftc.devq, dei, dei_link);
devsoftc.queued++;
cv_broadcast(&devsoftc.cv);
KNOTE_LOCKED(&devsoftc.sel.si_note, 0);
@@ -643,31 +647,24 @@
selwakeup(&devsoftc.sel);
if (devsoftc.async && devsoftc.sigio != NULL)
pgsigio(&devsoftc.sigio, SIGIO, 0);
- return;
-out:
- /*
- * We have to free data on all error paths since the caller
- * assumes it will be free'd when this item is dequeued.
- */
- free(data, M_BUS);
- return;
}
-static void
-devctl_queue_data(char *data)
-{
- devctl_queue_data_f(data, M_NOWAIT);
-}
+#define CAT(w, s, e) \
+ strlcpy((w), (s), (e) - (w)); \
+ w += strlen(w); \
+ if ((w) + 1 >= (e)) \
+ goto bad;
/**
* @brief Send a 'notification' to userland, using standard ways
*/
void
devctl_notify_f(const char *system, const char *subsystem, const char *type,
- const char *data, int flags)
+ const char *data, int flags __unused)
{
- int len = 0;
- char *msg;
+ struct dev_event_info *dei;
+ char *walker;
+ char *ep;
if (system == NULL)
return; /* BOGUS! Must specify system. */
@@ -675,23 +672,28 @@
return; /* BOGUS! Must specify subsystem. */
if (type == NULL)
return; /* BOGUS! Must specify type. */
- len += strlen(" system=") + strlen(system);
- len += strlen(" subsystem=") + strlen(subsystem);
- len += strlen(" type=") + strlen(type);
- /* add in the data message plus newline. */
- if (data != NULL)
- len += strlen(data);
- len += 3; /* '!', '\n', and NUL */
- msg = malloc(len, M_BUS, flags);
- if (msg == NULL)
- return; /* Drop it on the floor */
- if (data != NULL)
- snprintf(msg, len, "!system=%s subsystem=%s type=%s %s\n",
- system, subsystem, type, data);
- else
- snprintf(msg, len, "!system=%s subsystem=%s type=%s\n",
- system, subsystem, type);
- devctl_queue_data_f(msg, flags);
+ dei = devctl_alloc_dei();
+ if (dei == NULL)
+ return;
+ walker = dei->dei_data;
+ ep = walker + sizeof(dei->dei_data);
+ *walker++ = '!';
+ CAT(walker, "system=", ep);
+ CAT(walker, system, ep);
+ CAT(walker, " subsystem=", ep);
+ CAT(walker, subsystem, ep);
+ CAT(walker, " type=", ep);
+ CAT(walker, type, ep);
+ if (data != NULL) {
+ CAT(walker, " ", ep);
+ CAT(walker, data, ep);
+ }
+ CAT(walker, "\n", ep);
+ devctl_queue(dei);
+ return;
+bad:
+ devctl_free_dei(dei);
+ return;
}
void
@@ -713,54 +715,51 @@
* object of that event, plus the plug and play info and location info
* for that event. This is likely most useful for devices, but less
* useful for other consumers of this interface. Those should use
- * the devctl_queue_data() interface instead.
+ * the devctl_notify() interface instead.
*/
static void
devaddq(const char *type, const char *what, device_t dev)
{
- char *data = NULL;
- char *loc = NULL;
- char *pnp = NULL;
+ struct dev_event_info *dei;
const char *parstr;
+ char *walker;
+ char *ep;
- if (!devctl_queue_length)/* Rare race, but lost races safely discard */
+ dei = devctl_alloc_dei();
+ if (dei == NULL)
return;
- data = malloc(1024, M_BUS, M_NOWAIT);
- if (data == NULL)
+ walker = dei->dei_data;
+ ep = walker + sizeof(dei->dei_data);
+
+ CAT(walker, type, ep);
+ CAT(walker, what, ep);
+ CAT(walker, " at ", ep);
+ bus_child_location_str(dev, walker, ep - walker);
+ walker += strlen(walker);
+ if (walker >= ep)
goto bad;
-
- /* get the bus specific location of this device */
- loc = malloc(1024, M_BUS, M_NOWAIT);
- if (loc == NULL)
+ CAT(walker, " ", ep);
+ bus_child_pnpinfo_str(dev, walker, ep - walker);
+ walker += strlen(walker);
+ if (walker >= ep)
goto bad;
- *loc = '\0';
- bus_child_location_str(dev, loc, 1024);
-
- /* Get the bus specific pnp info of this device */
- pnp = malloc(1024, M_BUS, M_NOWAIT);
- if (pnp == NULL)
- goto bad;
- *pnp = '\0';
- bus_child_pnpinfo_str(dev, pnp, 1024);
-
+ CAT(walker, " on ", ep);
/* Get the parent of this device, or / if high enough in the tree. */
if (device_get_parent(dev) == NULL)
parstr = "."; /* Or '/' ? */
else
parstr = device_get_nameunit(device_get_parent(dev));
- /* String it all together. */
- snprintf(data, 1024, "%s%s at %s %s on %s\n", type, what, loc, pnp,
- parstr);
- free(loc, M_BUS);
- free(pnp, M_BUS);
- devctl_queue_data(data);
+ CAT(walker, parstr, ep);
+ CAT(walker, "\n", ep);
+
+ devctl_queue(dei);
return;
bad:
- free(pnp, M_BUS);
- free(loc, M_BUS);
- free(data, M_BUS);
+ devctl_free_dei(dei);
return;
}
+#undef CAT
+
/*
* A device was added to the tree. We are called just after it successfully
@@ -814,13 +813,14 @@
while (!STAILQ_EMPTY(&devsoftc.devq)) {
n1 = STAILQ_FIRST(&devsoftc.devq);
STAILQ_REMOVE_HEAD(&devsoftc.devq, dei_link);
- free(n1->dei_data, M_BUS);
- free(n1, M_BUS);
+ uma_zfree(devsoftc.zone, n1);
}
devsoftc.queued = 0;
devctl_queue_length = 0;
+ /* XXX destroy the zone? */
} else {
devctl_queue_length = DEVCTL_DEFAULT_QUEUE_LEN;
+ /* XXX init the zone? */
}
if (mtx_initialized(&devsoftc.mtx))
mtx_unlock(&devsoftc.mtx);
@@ -845,8 +845,7 @@
while (devsoftc.queued > devctl_queue_length) {
n1 = STAILQ_FIRST(&devsoftc.devq);
STAILQ_REMOVE_HEAD(&devsoftc.devq, dei_link);
- free(n1->dei_data, M_BUS);
- free(n1, M_BUS);
+ uma_zfree(devsoftc.zone, n1);
devsoftc.queued--;
}
if (mtx_initialized(&devsoftc.mtx))

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 17, 10:24 AM (18 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28811466
Default Alt Text
D26140.id76047.diff (8 KB)

Event Timeline