From 738a6d76f6afc92e53776f6aa9f8d8493598dc8a Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Mon, 17 Jul 2017 00:14:07 +0200 Subject: [PATCH] MEDIUM: threads/tasks: Add lock around notifications This patch add lock around some notification calls --- include/common/hathreads.h | 4 +++- include/proto/task.h | 21 +++++++++++++++++---- include/types/task.h | 3 +++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/common/hathreads.h b/include/common/hathreads.h index a5a25b47e..774fe7b67 100644 --- a/include/common/hathreads.h +++ b/include/common/hathreads.h @@ -166,6 +166,7 @@ enum lock_label { VARS_LOCK, COMP_POOL_LOCK, LUA_LOCK, + NOTIF_LOCK, LOCK_LABELS }; struct lock_stat { @@ -253,7 +254,8 @@ static inline void show_lock_stats() "LISTENER", "LISTENER_QUEUE", "PROXY", "SERVER", "UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS", "APPLETS", "PEER", "BUF_WQ", "STREAMS", "SSL", "SSL_GEN_CERTS", - "PATREF", "PATEXP", "PATLRU", "VARS", "COMP_POOL", "LUA" }; + "PATREF", "PATEXP", "PATLRU", "VARS", "COMP_POOL", "LUA", + "NOTIF" }; int lbl; for (lbl = 0; lbl < LOCK_LABELS; lbl++) { diff --git a/include/proto/task.h b/include/proto/task.h index bc3a17316..cb98fefc7 100644 --- a/include/proto/task.h +++ b/include/proto/task.h @@ -294,6 +294,7 @@ static inline struct notification *notification_new(struct list *purge, struct l return NULL; LIST_ADDQ(purge, &com->purge_me); LIST_ADDQ(event, &com->wake_me); + SPIN_INIT(&com->lock); com->task = wakeup; return com; } @@ -308,9 +309,15 @@ static inline void notification_purge(struct list *purge) /* Delete all pending communication signals. */ list_for_each_entry_safe(com, back, purge, purge_me) { + SPIN_LOCK(NOTIF_LOCK, &com->lock); LIST_DEL(&com->purge_me); - LIST_DEL(&com->wake_me); - pool_free2(pool2_notification, com); + if (!com->task) { + SPIN_UNLOCK(NOTIF_LOCK, &com->lock); + pool_free2(pool2_notification, com); + continue; + } + com->task = NULL; + SPIN_UNLOCK(NOTIF_LOCK, &com->lock); } } @@ -324,10 +331,16 @@ static inline void notification_wake(struct list *wake) /* Wake task and delete all pending communication signals. */ list_for_each_entry_safe(com, back, wake, wake_me) { - LIST_DEL(&com->purge_me); + SPIN_LOCK(NOTIF_LOCK, &com->lock); LIST_DEL(&com->wake_me); + if (!com->task) { + SPIN_UNLOCK(NOTIF_LOCK, &com->lock); + pool_free2(pool2_notification, com); + continue; + } task_wakeup(com->task, TASK_WOKEN_MSG); - pool_free2(pool2_notification, com); + com->task = NULL; + SPIN_UNLOCK(NOTIF_LOCK, &com->lock); } } diff --git a/include/types/task.h b/include/types/task.h index da7c929bc..799e6c5ed 100644 --- a/include/types/task.h +++ b/include/types/task.h @@ -56,6 +56,9 @@ struct notification { struct list wake_me; /* Part of list of signals to be targeted if an event occurs. */ struct task *task; /* The task to be wake if an event occurs. */ +#ifdef USE_THREAD + HA_SPINLOCK_T lock; +#endif }; /* The base for all tasks */