[CRIU] [PATCH v5 15/33] files: Implement {set, clear, wait}_fds_event()
Andrei Vagin
avagin at virtuozzo.com
Wed Jan 18 18:46:28 PST 2017
On Mon, Dec 26, 2016 at 05:27:08PM +0300, Kirill Tkhai wrote:
> 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 = ¤t->task_st;
> +
> + clear_bit(FDS_EVENT_BIT, (unsigned long *)&f->raw.counter);
CID 174702 (#1 of 1): Out-of-bounds access (INCOMPATIBLE_CAST)
incompatible_cast: Pointer &f->raw.counter points to an object whose
effective type is int (32 bits, signed) but is dereferenced as a wider
unsigned long (64 bits, unsigned). This may lead to memory corruption.
[show details]
> +}
> +
> +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 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)
> {
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list