events: fix signal overlapping in generic events
authorarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Thu, 3 Mar 2011 16:24:18 +0000 (16:24 +0000)
committerarighi <arighi@38d2e660-2303-0410-9eaa-f027e97ec537>
Thu, 3 Mar 2011 16:24:18 +0000 (16:24 +0000)
When the kernel is enabled the generic events subsystem uses SIG_SYSTEM5
to synchronize the completion of the events.

The owner (process) of an event is assigned when the event is
initialized via event_initGeneric().

It may happen that the same process initializes more than one event, so
when one of them is triggered the process is awakened independently on
the event it is waiting for.

Fix this by moving the signal masks into the generic event structure and
export a new signal API to directly accept the signal masks, instead of
implicitly using the signal masks of the current process.

git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4750 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/mware/event.c
bertos/mware/event.h

index 567e18a9a42ceaed9b907ec3ed7853bddbfa684d..489014dbc1f73ff76e3a6e637bcccc2f1cfdb48c 100644 (file)
@@ -50,6 +50,13 @@ void event_hook_signal(Event *e)
 {
        sig_post((e)->Ev.Sig.sig_proc, (e)->Ev.Sig.sig_bit);
 }
+
+void event_hook_generic_signal(Event *e)
+{
+       sig_postSignal(&e->Ev.SigGen.sig,
+                               e->Ev.SigGen.sig_proc,
+                               EVENT_GENERIC_SIGNAL);
+}
 #endif
 
 void event_hook_softint(Event *e)
index 0a87af1abe170dbf58a80156477c0b80135ec715..3d00605962e3a4aaca7b1c74d474a66eef2999ce 100644 (file)
@@ -123,6 +123,12 @@ typedef struct Event
                        struct Process *sig_proc;  /* Process to be signalled */
                        sigbit_t        sig_bit;   /* Signal to send */
                } Sig;
+
+               struct
+               {
+                       struct Process *sig_proc;  /* Process to be signalled */
+                       Signal          sig;       /* Signal structure */
+               } SigGen;
 #endif
                struct
                {
@@ -141,6 +147,7 @@ void event_hook_ignore(Event *event);
 void event_hook_signal(Event *event);
 void event_hook_softint(Event *event);
 void event_hook_generic(Event *event);
+void event_hook_generic_signal(Event *event);
 void event_hook_generic_timeout(Event *event);
 
 /** Initialize the event \a e as a no-op */
@@ -190,13 +197,20 @@ INLINE Event event_createSignal(struct Process *proc, sigbit_t bit)
 
 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
 /** Initialize the generic sleepable event \a e */
-#define event_initGeneric(e) \
-       event_initSignal(e, proc_current(), SIG_SYSTEM5)
+#define event_initGeneric(e)                                   \
+       ((e)->action = event_hook_generic_signal,               \
+               (e)->Ev.SigGen.sig_proc = proc_current(),       \
+               (e)->Ev.SigGen.sig.wait = 0, (e)->Ev.SigGen.sig.recv = 0)
 #else
 #define event_initGeneric(e) \
        ((e)->action = event_hook_generic, (e)->Ev.Gen.completed = false)
 #endif
 
+/**
+ * Signal used to implement generic events.
+ */
+#define EVENT_GENERIC_SIGNAL   SIG_SYSTEM5
+
 /**
  * Create a generic sleepable event.
  *
@@ -220,7 +234,7 @@ INLINE void event_wait(Event *e)
 {
 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
        e->Ev.Sig.sig_proc = proc_current();
-       sig_wait(e->Ev.Sig.sig_bit);
+       sig_waitSignal(&e->Ev.SigGen.sig, EVENT_GENERIC_SIGNAL);
 #else
        while (ACCESS_SAFE(e->Ev.Gen.completed) == false)
                cpu_relax();
@@ -247,7 +261,8 @@ INLINE bool event_waitTimeout(Event *e, ticks_t timeout)
 
 #if defined(CONFIG_KERN_SIGNALS) && CONFIG_KERN_SIGNALS
        e->Ev.Sig.sig_proc = proc_current();
-       ret = (sig_waitTimeout(e->Ev.Sig.sig_bit, timeout) & SIG_TIMEOUT) ?
+       ret = (sig_waitTimeoutSignal(&e->Ev.SigGen.sig,
+                               EVENT_GENERIC_SIGNAL, timeout) & SIG_TIMEOUT) ?
                                false : true;
 #else
        ticks_t end = timer_clock() + timeout;