[CRIU] [PATCH v3 14/26] files: Implement {set,get}_fds_event()
Kirill Tkhai
ktkhai at virtuozzo.com
Mon Dec 5 06:09:35 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: if (!socket_bound)
get_fds_event(); /* sleep */
Task B: bind_socket();
set_fds_event(); /* wake up */
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 | 34 ++++++++++++++++++++++++++++++++++
criu/include/files.h | 2 ++
include/common/lock.h | 5 +++++
3 files changed, 41 insertions(+)
diff --git a/criu/files.c b/criu/files.c
index 4039803..69a43c6 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -1631,3 +1631,37 @@ int open_transport_socket(void)
return 0;
}
+
+int set_fds_event(pid_t virt)
+{
+ struct pstree_item *item;
+ int old, st;
+
+ item = pstree_item_by_virt(virt);
+ BUG_ON(!item);
+
+ /* Set FDS_EVENT and wake up if need */
+ do {
+ old = futex_get(&item->task_st);
+ if (old & FDS_EVENT)
+ break;
+ st = atomic_cmpxchg(&item->task_st.raw, old, old | FDS_EVENT);
+ } while (st != old);
+
+ if (!(old & FDS_EVENT))
+ futex_wake(&item->task_st);
+ return 0;
+}
+
+int wait_fds_event(void)
+{
+ int old, st;
+
+ futex_wait_if_cond(¤t->task_st, FDS_EVENT, &);
+ do {
+ old = futex_get(¤t->task_st);
+ st = atomic_cmpxchg(¤t->task_st.raw, old, old & ~FDS_EVENT);
+ } while (st != old);
+
+ return 0;
+}
diff --git a/criu/include/files.h b/criu/include/files.h
index 5719004..7fdb3cf 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 int wait_fds_event(void);
#endif /* __CR_FILES_H__ */
diff --git a/include/common/lock.h b/include/common/lock.h
index afc0f96..2261cf9 100644
--- a/include/common/lock.h
+++ b/include/common/lock.h
@@ -78,6 +78,11 @@ 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);
}
+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