From 735461e1bf54a61eeb9b13fa19b44a67c699a2c8 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Mon, 26 Dec 2016 17:27:08 +0300 Subject: [PATCH] files: Implement {set,clear,wait}_fds_event() The idea is symilar to kernel's wake_up() and wait_event(). One task needs some event. It checks the event has not happened yet (fle hasn't received, unix peer hasn't bound, etc) and calls get_fds_event(). Other task makes the event (sends a fle, binds the peer to a name, etc) and calls set_fds_event(). So, while there is no an event, the first task is sleeping, and the second wakes it up later: Task A: clear_fds_event(); if (!socket_bound) wait_fds_event(); /* sleep */ Task B: bind_socket(); set_fds_event(); /* wake up */ For the details of using see next patches. v5: Use bit operations. Split clear_fds_event from wait function. v2: Do not wait for foreign transport sock is ready, as it's guarantied by we create it before CR_STATE_FORKING. travis-ci: success for Rework file opening scheme to make it asynchronous (rev5) Signed-off-by: Kirill Tkhai Signed-off-by: Pavel Emelyanov --- criu/files.c | 29 +++++++++++++++++++++++++++++ criu/include/files.h | 2 ++ include/common/lock.h | 6 ++++++ 3 files changed, 37 insertions(+) diff --git a/criu/files.c b/criu/files.c index 162332a90..a98081151 100644 --- a/criu/files.c +++ b/criu/files.c @@ -149,6 +149,35 @@ out: return fd; } +int set_fds_event(pid_t virt) +{ + struct pstree_item *item; + int old; + + item = pstree_item_by_virt(virt); + BUG_ON(!item); + + old = test_and_set_bit(FDS_EVENT_BIT, (unsigned long *)&item->task_st); + + if (!(old & FDS_EVENT)) + futex_wake(&item->task_st); + return 0; +} + +void clear_fds_event(void) +{ + futex_t *f = ¤t->task_st; + + clear_bit(FDS_EVENT_BIT, (unsigned long *)&f->raw.counter); +} + +void wait_fds_event(void) +{ + futex_t *f = ¤t->task_st; + + futex_wait_if_cond(f, FDS_EVENT, &); + clear_fds_event(); +} /* * A file may be shared between several file descriptors. E.g * when doing a fork() every fd of a forker and respective fds diff --git a/criu/include/files.h b/criu/include/files.h index 57190049d..1b44960de 100644 --- a/criu/include/files.h +++ b/criu/include/files.h @@ -193,5 +193,7 @@ int dup_fle(struct pstree_item *task, struct fdinfo_list_entry *ple, int fd, unsigned flags); extern int open_transport_socket(void); +extern int set_fds_event(pid_t virt); +extern void wait_fds_event(void); #endif /* __CR_FILES_H__ */ diff --git a/include/common/lock.h b/include/common/lock.h index cb48ea602..f68045cfe 100644 --- a/include/common/lock.h +++ b/include/common/lock.h @@ -79,6 +79,12 @@ static inline void futex_set_and_wake(futex_t *f, uint32_t v) LOCK_BUG_ON(sys_futex((uint32_t *)&f->raw.counter, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) < 0); } +/* Wake up all futex @f waiters */ +static inline void futex_wake(futex_t *f) +{ + LOCK_BUG_ON(sys_futex((uint32_t *)&f->raw.counter, FUTEX_WAKE, INT_MAX, NULL, NULL, 0) < 0); +} + /* Mark futex @f as wait abort needed and wake up all waiters */ static inline void futex_abort_and_wake(futex_t *f) {