Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145144379
D26140.id76047.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D26140.id76047.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D26140: devctl: move to using a uma zone
Attached
Detach File
Event Timeline
Log In to Comment