Skip to content

Commit c6bf675

Browse files
fyin1jren1
authored andcommitted
DM: mevent_add/del refine for Linux
Unlike kqueue/kevent of BSD, the epoll of Linux could be add/del by using different API on the fly. This patch drops the notify used by mevent_add/del and call epoll_ctl to add/delete target fd. Only keeps global_head to track mevent added and makes the code logic in mevent_dispatch() a littel bit simpler. Another thing is related with epoll_ctl. If the target fd is regular fd which doesn't support epoll, epoll_ctl will return -1. When DM is start by systemd, the STDIO is not mapped to terminal, epoll_ctl on STDIO could return -1. Which block UOS boot. We only call mevent_add after confirm STDIO is mapped to terminal. Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Reviewed-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com>
1 parent db46df9 commit c6bf675

File tree

3 files changed

+52
-135
lines changed

3 files changed

+52
-135
lines changed

devicemodel/core/mevent.c

Lines changed: 39 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,7 @@ struct mevent {
7575
LIST_ENTRY(mevent) me_list;
7676
};
7777

78-
struct ctl_event {
79-
int op;
80-
int fd;
81-
struct epoll_event ee;
82-
};
83-
84-
static LIST_HEAD(listhead, mevent) global_head, change_head;
78+
static LIST_HEAD(listhead, mevent) global_head;
8579

8680
static void
8781
mevent_qlock(void)
@@ -141,80 +135,25 @@ mevent_kq_filter(struct mevent *mevp)
141135
return retval;
142136
}
143137

144-
static int
145-
mevent_kq_flags(struct mevent *mevp)
146-
{
147-
int ret;
148-
149-
switch (mevp->me_state) {
150-
case MEV_ADD:
151-
ret = EPOLL_CTL_ADD; /* implicitly enabled */
152-
break;
153-
case MEV_DEL_PENDING:
154-
ret = EPOLL_CTL_DEL;
155-
break;
156-
default:
157-
assert(0);
158-
break;
159-
}
160-
161-
return ret;
162-
}
163-
164-
static int
165-
mevent_build(int mfd, struct ctl_event *kev)
166-
{
167-
struct mevent *mevp, *tmpp;
168-
int i;
169-
170-
i = 0;
171-
172-
mevent_qlock();
173-
174-
list_foreach_safe(mevp, &change_head, me_list, tmpp) {
175-
if (mevp->me_closefd) {
176-
/*
177-
* A close of the file descriptor will remove the
178-
* event
179-
*/
180-
close(mevp->me_fd);
181-
} else {
182-
kev[i].fd = mevp->me_fd;
183-
kev[i].ee.events = mevent_kq_filter(mevp);
184-
kev[i].op = mevent_kq_flags(mevp);
185-
kev[i].ee.data.ptr = mevp;
186-
i++;
187-
}
188-
189-
mevp->me_cq = 0;
190-
LIST_REMOVE(mevp, me_list);
191-
192-
if (mevp->me_state == MEV_DEL_PENDING)
193-
free(mevp);
194-
else
195-
LIST_INSERT_HEAD(&global_head, mevp, me_list);
196-
197-
assert(i < MEVENT_MAX);
198-
}
199-
200-
mevent_qunlock();
201-
202-
return i;
203-
}
204-
205138
static void
206139
mevent_destroy()
207140
{
208141
struct mevent *mevp, *tmpp;
142+
struct epoll_event ee;
209143

210144
mevent_qlock();
211145

212146
list_foreach_safe(mevp, &global_head, me_list, tmpp) {
147+
LIST_REMOVE(mevp, me_list);
148+
ee.events = mevent_kq_filter(mevp);
149+
ee.data.ptr = mevp;
150+
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, mevp->me_fd, &ee);
151+
213152
if ((mevp->me_type == EVF_READ ||
214153
mevp->me_type == EVF_WRITE)
215154
&& mevp->me_fd != STDIN_FILENO)
216155
close(mevp->me_fd);
217-
LIST_REMOVE(mevp, me_list);
156+
218157
free(mevp);
219158
}
220159

@@ -239,6 +178,8 @@ struct mevent *
239178
mevent_add(int tfd, enum ev_type type,
240179
void (*func)(int, enum ev_type, void *), void *param)
241180
{
181+
int ret;
182+
struct epoll_event ee;
242183
struct mevent *lp, *mevp;
243184

244185
if (tfd < 0 || func == NULL)
@@ -247,44 +188,41 @@ mevent_add(int tfd, enum ev_type type,
247188
if (type == EVF_TIMER)
248189
return NULL;
249190

250-
mevp = NULL;
251-
252191
mevent_qlock();
253-
254-
/*
255-
* Verify that the fd/type tuple is not present in any list
256-
*/
192+
/* Verify that the fd/type tuple is not present in the list */
257193
LIST_FOREACH(lp, &global_head, me_list) {
258-
if (lp->me_fd == tfd && lp->me_type == type)
259-
goto exit;
260-
}
261-
262-
LIST_FOREACH(lp, &change_head, me_list) {
263-
if (lp->me_fd == tfd && lp->me_type == type)
264-
goto exit;
194+
if (lp->me_fd == tfd && lp->me_type == type) {
195+
mevent_qunlock();
196+
return lp;
197+
}
265198
}
199+
mevent_qunlock();
266200

267201
/*
268-
* Allocate an entry, populate it, and add it to the change list.
202+
* Allocate an entry, populate it, and add it to the list.
269203
*/
270204
mevp = calloc(1, sizeof(struct mevent));
271205
if (mevp == NULL)
272-
goto exit;
206+
return NULL;
273207

274208
mevp->me_fd = tfd;
275209
mevp->me_type = type;
276210
mevp->me_func = func;
277211
mevp->me_param = param;
278212

279-
LIST_INSERT_HEAD(&change_head, mevp, me_list);
280-
mevp->me_cq = 1;
281-
mevp->me_state = MEV_ADD;
282-
mevent_notify();
283-
284-
exit:
285-
mevent_qunlock();
213+
ee.events = mevent_kq_filter(mevp);
214+
ee.data.ptr = mevp;
215+
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mevp->me_fd, &ee);
216+
if (ret == 0) {
217+
mevent_qlock();
218+
LIST_INSERT_HEAD(&global_head, mevp, me_list);
219+
mevent_qunlock();
286220

287-
return mevp;
221+
return mevp;
222+
} else {
223+
free(mevp);
224+
return NULL;
225+
}
288226
}
289227

290228
int
@@ -302,25 +240,20 @@ mevent_disable(struct mevent *evp)
302240
static int
303241
mevent_delete_event(struct mevent *evp, int closefd)
304242
{
243+
struct epoll_event ee;
244+
305245
mevent_qlock();
246+
LIST_REMOVE(evp, me_list);
247+
mevent_qunlock();
306248

307-
/*
308-
* Place the entry onto the changed list if not already there, and
309-
* mark as to be deleted.
310-
*/
311-
if (evp->me_cq == 0) {
312-
evp->me_cq = 1;
313-
LIST_REMOVE(evp, me_list);
314-
LIST_INSERT_HEAD(&change_head, evp, me_list);
315-
mevent_notify();
316-
}
317-
evp->me_state = MEV_DEL_PENDING;
249+
ee.events = mevent_kq_filter(evp);
250+
ee.data.ptr = evp;
251+
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, evp->me_fd, &ee);
318252

319253
if (closefd)
320-
evp->me_closefd = 1;
321-
322-
mevent_qunlock();
254+
close(evp->me_fd);
323255

256+
free(evp);
324257
return 0;
325258
}
326259

@@ -364,11 +297,9 @@ mevent_deinit(void)
364297
void
365298
mevent_dispatch(void)
366299
{
367-
struct ctl_event clist[MEVENT_MAX];
368300
struct epoll_event eventlist[MEVENT_MAX];
369301

370302
struct mevent *pipev;
371-
int numev;
372303
int ret;
373304

374305
mevent_tid = pthread_self();
@@ -392,24 +323,6 @@ mevent_dispatch(void)
392323
assert(pipev != NULL);
393324

394325
for (;;) {
395-
/*
396-
* Build changelist if required.
397-
* XXX the changelist can be put into the blocking call
398-
* to eliminate the extra syscall. Currently better for
399-
* debug.
400-
*/
401-
int i;
402-
struct epoll_event *e;
403-
404-
numev = mevent_build(epoll_fd, clist);
405-
406-
for (i = 0; i < numev; i++) {
407-
e = &clist[i].ee;
408-
ret = epoll_ctl(epoll_fd, clist[i].op, clist[i].fd, e);
409-
if (ret == -1)
410-
perror("Error return from epoll_ctl");
411-
}
412-
413326
/*
414327
* Block awaiting events
415328
*/
@@ -425,5 +338,4 @@ mevent_dispatch(void)
425338
if (vm_get_suspend_mode() != VM_SUSPEND_NONE)
426339
break;
427340
}
428-
mevent_build(epoll_fd, clist);
429341
}

devicemodel/hw/pci/virtio/virtio_console.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -691,12 +691,14 @@ virtio_console_add_backend(struct virtio_console *console,
691691
}
692692

693693
if (virtio_console_backend_can_read(be_type)) {
694-
be->evp = mevent_add(fd, EVF_READ,
695-
virtio_console_backend_read, be);
696-
if (be->evp == NULL) {
697-
WPRINTF(("vtcon: mevent_add failed\n"));
698-
error = -1;
699-
goto out;
694+
if (isatty(fd)) {
695+
be->evp = mevent_add(fd, EVF_READ,
696+
virtio_console_backend_read, be);
697+
if (be->evp == NULL) {
698+
WPRINTF(("vtcon: mevent_add failed\n"));
699+
error = -1;
700+
goto out;
701+
}
700702
}
701703
}
702704

devicemodel/hw/platform/uart_core.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,11 @@ static void
267267
uart_opentty(struct uart_vdev *uart)
268268
{
269269
ttyopen(&uart->tty);
270-
uart->mev = mevent_add(uart->tty.fd, EVF_READ, uart_drain, uart);
271-
assert(uart->mev != NULL);
270+
if (isatty(uart->tty.fd)) {
271+
uart->mev = mevent_add(uart->tty.fd, EVF_READ,
272+
uart_drain, uart);
273+
assert(uart->mev != NULL);
274+
}
272275
}
273276

274277
static uint8_t

0 commit comments

Comments
 (0)