Skip to content

Commit 9e50a29

Browse files
committed
Batch up uevent notifications
Uevent notifications come in bursts especially at boot when we're iterating over all devices. This batches the reports to Erlang up so that there are significantly fewer context switches. On a simple RPi0 W application, this trims 1.5 seconds off the boot time.
1 parent 47bcc5e commit 9e50a29

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

src/uevent.c

+20-8
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,12 @@ static int nl_uevent_process_one(struct mnl_socket *nl_uevent, char *resp)
130130
{
131131
char nlbuf[8192]; // See MNL_SOCKET_BUFFER_SIZE
132132
int bytecount = mnl_socket_recvfrom(nl_uevent, nlbuf, sizeof(nlbuf));
133-
if (bytecount <= 0)
134-
err(EXIT_FAILURE, "mnl_socket_recvfrom");
133+
if (bytecount <= 0) {
134+
if (errno == EAGAIN)
135+
return -1;
136+
else
137+
err(EXIT_FAILURE, "mnl_socket_recvfrom");
138+
}
135139

136140
char *str = nlbuf;
137141
char *str_end = str + bytecount;
@@ -207,15 +211,23 @@ static int nl_uevent_process_one(struct mnl_socket *nl_uevent, char *resp)
207211

208212
static void nl_uevent_process_all(struct mnl_socket *nl_uevent)
209213
{
210-
// Erlang response processing
214+
// Erlang response buffer
211215
char resp[8192];
212-
int resp_index;
216+
size_t resp_index;
217+
218+
// Process uevents until there aren't any more or we're
219+
// within 1K of the end. This is pretty conservative since
220+
// the Erlang reports looks like they're nearly always < 200 bytes.
221+
for (resp_index = 0; resp_index < sizeof(resp) - 1024;) {
222+
int bytes_added = nl_uevent_process_one(nl_uevent, &resp[resp_index]);
223+
if (bytes_added < 0)
224+
break;
213225

214-
resp_index = nl_uevent_process_one(nl_uevent, resp);
215-
if (resp_index <= 0)
216-
return;
226+
resp_index += bytes_added;
227+
}
217228

218-
write_all(resp, resp_index);
229+
if (resp_index > 0)
230+
write_all(resp, resp_index);
219231
}
220232

221233
static int filter(const struct dirent *dirp)

0 commit comments

Comments
 (0)