sched/wqueue: Fix unexpected dq entry status

When we do not drop notifier from g_notifier_pending, we need an
isolated dq entry for this queue, otherwise the queued work_s's dq entry
may be modified by the work queue and breaks the chain of
g_notifier_pending.

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2024-09-14 18:15:23 +08:00 committed by Xiang Xiao
parent 4d6203d4c6
commit f8bd93575c

View File

@ -53,10 +53,9 @@
struct work_notifier_entry_s struct work_notifier_entry_s
{ {
/* This must appear at the beginning of the structure. A reference to struct dq_entry_s entry;
* the struct work_notifier_entry_s instance must be cast-compatible with
* struct dq_entry_s. /* The work structure */
*/
struct work_s work; /* Used for scheduling the work */ struct work_s work; /* Used for scheduling the work */
@ -170,11 +169,11 @@ static void work_notifier_worker(FAR void *arg)
/* Remove the notification from the pending list */ /* Remove the notification from the pending list */
dq_rem((FAR dq_entry_t *)notifier, &g_notifier_pending); dq_rem(&notifier->entry, &g_notifier_pending);
/* Put the notification to the free list */ /* Put the notification to the free list */
dq_addlast((FAR dq_entry_t *)notifier, &g_notifier_free); dq_addlast(&notifier->entry, &g_notifier_free);
leave_critical_section(flags); leave_critical_section(flags);
} }
@ -259,7 +258,7 @@ int work_notifier_setup(FAR struct work_notifier_s *info)
* notifications executed in a saner order? * notifications executed in a saner order?
*/ */
dq_addlast((FAR dq_entry_t *)notifier, &g_notifier_pending); dq_addlast(&notifier->entry, &g_notifier_pending);
ret = notifier->key; ret = notifier->key;
leave_critical_section(flags); leave_critical_section(flags);
@ -308,11 +307,11 @@ void work_notifier_teardown(int key)
{ {
/* Remove the notification from the pending list */ /* Remove the notification from the pending list */
dq_rem((FAR dq_entry_t *)notifier, &g_notifier_pending); dq_rem(&notifier->entry, &g_notifier_pending);
/* Put the notification to the free list */ /* Put the notification to the free list */
dq_addlast((FAR dq_entry_t *)notifier, &g_notifier_free); dq_addlast(&notifier->entry, &g_notifier_free);
} }
} }