|
@@ -92,7 +92,7 @@
|
|
|
*/
|
|
|
|
|
|
/* Epoll private bits inside the event mask */
|
|
|
-#define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET)
|
|
|
+#define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET | EPOLLEXCLUSIVE)
|
|
|
|
|
|
/* Maximum number of nesting allowed inside epoll sets */
|
|
|
#define EP_MAX_NESTS 4
|
|
@@ -1002,6 +1002,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
|
|
|
unsigned long flags;
|
|
|
struct epitem *epi = ep_item_from_wait(wait);
|
|
|
struct eventpoll *ep = epi->ep;
|
|
|
+ int ewake = 0;
|
|
|
|
|
|
if ((unsigned long)key & POLLFREE) {
|
|
|
ep_pwq_from_wait(wait)->whead = NULL;
|
|
@@ -1066,8 +1067,10 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
|
|
|
* Wake up ( if active ) both the eventpoll wait list and the ->poll()
|
|
|
* wait list.
|
|
|
*/
|
|
|
- if (waitqueue_active(&ep->wq))
|
|
|
+ if (waitqueue_active(&ep->wq)) {
|
|
|
+ ewake = 1;
|
|
|
wake_up_locked(&ep->wq);
|
|
|
+ }
|
|
|
if (waitqueue_active(&ep->poll_wait))
|
|
|
pwake++;
|
|
|
|
|
@@ -1078,6 +1081,9 @@ out_unlock:
|
|
|
if (pwake)
|
|
|
ep_poll_safewake(&ep->poll_wait);
|
|
|
|
|
|
+ if (epi->event.events & EPOLLEXCLUSIVE)
|
|
|
+ return ewake;
|
|
|
+
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
@@ -1095,7 +1101,10 @@ static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
|
|
|
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
|
|
|
pwq->whead = whead;
|
|
|
pwq->base = epi;
|
|
|
- add_wait_queue(whead, &pwq->wait);
|
|
|
+ if (epi->event.events & EPOLLEXCLUSIVE)
|
|
|
+ add_wait_queue_exclusive(whead, &pwq->wait);
|
|
|
+ else
|
|
|
+ add_wait_queue(whead, &pwq->wait);
|
|
|
list_add_tail(&pwq->llink, &epi->pwqlist);
|
|
|
epi->nwait++;
|
|
|
} else {
|
|
@@ -1861,6 +1870,15 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
|
|
|
if (f.file == tf.file || !is_file_epoll(f.file))
|
|
|
goto error_tgt_fput;
|
|
|
|
|
|
+ /*
|
|
|
+ * epoll adds to the wakeup queue at EPOLL_CTL_ADD time only,
|
|
|
+ * so EPOLLEXCLUSIVE is not allowed for a EPOLL_CTL_MOD operation.
|
|
|
+ * Also, we do not currently supported nested exclusive wakeups.
|
|
|
+ */
|
|
|
+ if ((epds.events & EPOLLEXCLUSIVE) && (op == EPOLL_CTL_MOD ||
|
|
|
+ (op == EPOLL_CTL_ADD && is_file_epoll(tf.file))))
|
|
|
+ goto error_tgt_fput;
|
|
|
+
|
|
|
/*
|
|
|
* At this point it is safe to assume that the "private_data" contains
|
|
|
* our own data structure.
|