[CRIU] [PATCH v5 15/33] files: Implement {set, clear, wait}_fds_event()

Kirill Tkhai ktkhai at virtuozzo.com
Mon Dec 26 06:27:08 PST 2016


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.

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 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 bff8880bf..87d8fc655 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -149,6 +149,35 @@ unsigned int find_unused_fd(struct list_head *head, int hint_fd)
 	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 = &current->task_st;
+
+	clear_bit(FDS_EVENT_BIT, (unsigned long *)&f->raw.counter);
+}
+
+void wait_fds_event(void)
+{
+	futex_t *f = &current->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 afc0f96d5..49b1af149 100644
--- a/include/common/lock.h
+++ b/include/common/lock.h
@@ -78,6 +78,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)
 {



More information about the CRIU mailing list