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) {