On 06.04.22 17:56, Philippe Gerum via Xenomai wrote:
> From: Philippe Gerum <r...@xenomai.org>
> 
> Allow for sending a set of event bits to the heading waiter only,
> instead of broadcasting them to all waiters.
> 
> This change affects the ABI, since we add a set of operation flags to
> the cobalt_event_sync service, to pass the new COBALT_EVENT_BCAST
> flag. It also affects the internal API as follows:
> 
> - the new cobalt_event_broadcast() call behaves like
>   cobalt_event_post() formerly did, which is broadcasting the event to
>   all waiters atomically.
> 
> - the new cobalt_event_signal() call implements the single-waiter
>   delivery mode we introduce.
> 
> - the former cobalt_event_post() is now a wrapper to
>   cobalt_event_broadcast(), marked with a deprecation flag.

Strictly spoken, deprecation will come with patch 4 only.

Can we have some test cases for the new features as well? Who will use them?

Jan

> 
> Signed-off-by: Philippe Gerum <r...@xenomai.org>
> ---
>  include/cobalt/sys/cobalt.h | 12 +++++++++++-
>  include/cobalt/uapi/event.h | 10 +++++-----
>  kernel/cobalt/posix/event.c | 37 +++++++++++++++----------------------
>  kernel/cobalt/posix/event.h |  3 ++-
>  lib/cobalt/internal.c       | 20 ++++++++++++--------
>  5 files changed, 45 insertions(+), 37 deletions(-)
> 
> diff --git a/include/cobalt/sys/cobalt.h b/include/cobalt/sys/cobalt.h
> index 46096e8801..1035a29d52 100644
> --- a/include/cobalt/sys/cobalt.h
> +++ b/include/cobalt/sys/cobalt.h
> @@ -106,9 +106,19 @@ int cobalt_event_init(cobalt_event_t *event,
>                     unsigned int value,
>                     int flags);
>  
> -int cobalt_event_post(cobalt_event_t *event,
> +int cobalt_event_signal(cobalt_event_t *event,
>                     unsigned int bits);
>  
> +int cobalt_event_broadcast(cobalt_event_t *event,
> +                     unsigned int bits);
> +
> +/* Backward compatibility with 3.2.x and earlier. */
> +static inline int cobalt_event_post(cobalt_event_t *event,
> +                             unsigned int bits)
> +{
> +     return cobalt_event_broadcast(event, bits);
> +}
> +
>  int cobalt_event_wait(cobalt_event_t *event,
>                     unsigned int bits,
>                     unsigned int *bits_r,
> diff --git a/include/cobalt/uapi/event.h b/include/cobalt/uapi/event.h
> index 14ddbcf567..52b71d4e3b 100644
> --- a/include/cobalt/uapi/event.h
> +++ b/include/cobalt/uapi/event.h
> @@ -22,9 +22,6 @@
>  
>  struct cobalt_event_state {
>       __u32 value;
> -     __u32 flags;
> -#define COBALT_EVENT_PENDED  0x1
> -     __u32 nwaiters;
>  };
>  
>  struct cobalt_event;
> @@ -36,8 +33,11 @@ struct cobalt_event;
>  #define COBALT_EVENT_AUTOCLEAR  0x4
>  
>  /* Wait mode. */
> -#define COBALT_EVENT_ALL  0x0
> -#define COBALT_EVENT_ANY  0x1
> +#define COBALT_EVENT_ALL    0x0
> +#define COBALT_EVENT_ANY    0x1
> +
> +/* Sync mode. */
> +#define COBALT_EVENT_BCAST  0x1
>  
>  struct cobalt_event_shadow {
>       __u32 state_offset;
> diff --git a/kernel/cobalt/posix/event.c b/kernel/cobalt/posix/event.c
> index 0a1236ad73..4433e733fd 100644
> --- a/kernel/cobalt/posix/event.c
> +++ b/kernel/cobalt/posix/event.c
> @@ -85,8 +85,6 @@ COBALT_SYSCALL(event_init, current,
>       synflags = (flags & COBALT_EVENT_PRIO) ? XNSYNCH_PRIO : XNSYNCH_FIFO;
>       xnsynch_init(&event->synch, synflags, NULL);
>       state->value = value;
> -     state->flags = 0;
> -     state->nwaiters = 0;
>       stateoff = cobalt_umm_offset(umm, state);
>       XENO_BUG_ON(COBALT, stateoff != (__u32)stateoff);
>  
> @@ -152,37 +150,31 @@ int __cobalt_event_wait(struct cobalt_event_shadow 
> __user *u_event,
>               goto out;
>       }
>  
> -     state->flags |= COBALT_EVENT_PENDED;
>       rbits = state->value & bits;
>       testval = mode & COBALT_EVENT_ANY ? rbits : bits;
>       if (rbits && rbits == testval) {
>               if (event->flags & COBALT_EVENT_AUTOCLEAR)
>                       state->value &= ~rbits;
> -             goto done;
> +             goto out;
>       }
>  
>       if (timeout == XN_NONBLOCK) {
>               ret = -EWOULDBLOCK;
> -             goto done;
> +             goto out;
>       }
>  
>       ewc.value = bits;
>       ewc.mode = mode;
>       xnthread_prepare_wait(&ewc.wc);
> -     state->nwaiters++;
>       info = xnsynch_sleep_on(&event->synch, timeout, tmode);
>       if (info & XNRMID) {
>               ret = -EIDRM;
>               goto out;
>       }
> -     if (info & (XNBREAK|XNTIMEO)) {
> -             state->nwaiters--;
> +     if (info & (XNBREAK|XNTIMEO))
>               ret = (info & XNBREAK) ? -EINTR : -ETIMEDOUT;
> -     } else
> +     else
>               rbits = ewc.value;
> -done:
> -     if (!xnsynch_pended_p(&event->synch))
> -             state->flags &= ~COBALT_EVENT_PENDED;
>  out:
>       xnlock_put_irqrestore(&nklock, s);
>  
> @@ -240,9 +232,10 @@ COBALT_SYSCALL(event_wait64, primary,
>  }
>  
>  COBALT_SYSCALL(event_sync, current,
> -            (struct cobalt_event_shadow __user *u_event))
> +     (struct cobalt_event_shadow __user *u_event,
> +             unsigned int bits, int flags))
>  {
> -     unsigned int bits, waitval, testval, consumed = 0;
> +     unsigned int waitval, testval, consumed = 0;
>       struct xnthread_wait_context *wc;
>       struct cobalt_event_state *state;
>       struct event_wait_context *ewc;
> @@ -262,24 +255,24 @@ COBALT_SYSCALL(event_sync, current,
>               goto out;
>       }
>  
> -     /*
> -      * Userland has already updated the bitmask, our job is to
> -      * wake up any thread which could be satisfied by its current
> -      * value.
> -      */
>       state = event->state;
> -     bits = state->value;
> +     state->value |= bits;
>  
> +     /*
> +      * Wake up one or more threads satisfied by state->value,
> +      * depending on the flags.
> +      */
>       xnsynch_for_each_sleeper_safe(p, tmp, &event->synch) {
>               wc = xnthread_get_wait_context(p);
>               ewc = container_of(wc, struct event_wait_context, wc);
> -             waitval = ewc->value & bits;
> +             waitval = ewc->value & state->value;
>               testval = ewc->mode & COBALT_EVENT_ANY ? waitval : ewc->value;
>               if (waitval && waitval == testval) {
> -                     state->nwaiters--;
>                       ewc->value = waitval;
>                       consumed |= waitval;
>                       xnsynch_wakeup_this_sleeper(&event->synch, p);
> +                     if (!(flags & COBALT_EVENT_BCAST))
> +                             break;
>               }
>       }
>  
> diff --git a/kernel/cobalt/posix/event.h b/kernel/cobalt/posix/event.h
> index 919774c9af..85b8031b22 100644
> --- a/kernel/cobalt/posix/event.h
> +++ b/kernel/cobalt/posix/event.h
> @@ -66,7 +66,8 @@ COBALT_SYSCALL_DECL(event_wait64,
>                    const struct __kernel_timespec __user *u_ts));
>  
>  COBALT_SYSCALL_DECL(event_sync,
> -                 (struct cobalt_event_shadow __user *u_evtsh));
> +             (struct cobalt_event_shadow __user *u_evtsh,
> +             unsigned int bits, int flags));
>  
>  COBALT_SYSCALL_DECL(event_destroy,
>                   (struct cobalt_event_shadow __user *u_evtsh));
> diff --git a/lib/cobalt/internal.c b/lib/cobalt/internal.c
> index bf1e940b71..b142b3b551 100644
> --- a/lib/cobalt/internal.c
> +++ b/lib/cobalt/internal.c
> @@ -460,19 +460,23 @@ int cobalt_event_destroy(cobalt_event_t *event)
>       return XENOMAI_SYSCALL1(sc_cobalt_event_destroy, event);
>  }
>  
> -int cobalt_event_post(cobalt_event_t *event, unsigned int bits)
> +static int do_sync_events(cobalt_event_t *event,
> +                     unsigned int bits, int flags)
>  {
> -     struct cobalt_event_state *state = get_event_state(event);
> -
>       if (bits == 0)
>               return 0;
>  
> -     __sync_or_and_fetch(&state->value, bits); /* full barrier. */
> +     return XENOMAI_SYSCALL3(sc_cobalt_event_sync, event, bits, flags);
> +}
>  
> -     if ((state->flags & COBALT_EVENT_PENDED) == 0)
> -             return 0;
> +int cobalt_event_signal(cobalt_event_t *event, unsigned int bits)
> +{
> +     return do_sync_events(event, bits, 0);
> +}
>  
> -     return XENOMAI_SYSCALL1(sc_cobalt_event_sync, event);
> +int cobalt_event_broadcast(cobalt_event_t *event, unsigned int bits)
> +{
> +     return do_sync_events(event, bits, COBALT_EVENT_BCAST);
>  }
>  
>  int cobalt_event_wait(cobalt_event_t *event,
> @@ -516,7 +520,7 @@ int cobalt_sem_inquire(sem_t *sem, struct cobalt_sem_info 
> *info,
>                      pid_t *waitlist, size_t waitsz)
>  {
>       struct cobalt_sem_shadow *_sem = &((union cobalt_sem_union 
> *)sem)->shadow_sem;
> -     
> +
>       return XENOMAI_SYSCALL4(sc_cobalt_sem_inquire, _sem,
>                               info, waitlist, waitsz);
>  }

-- 
Siemens AG, Technology
Competence Center Embedded Linux

Reply via email to