MEDIUM: threads/tasks: Add lock around notifications

This patch add lock around some notification calls
This commit is contained in:
Thierry FOURNIER 2017-07-17 00:14:07 +02:00 committed by Willy Tarreau
parent 952939d294
commit 738a6d76f6
3 changed files with 23 additions and 5 deletions

View File

@ -166,6 +166,7 @@ enum lock_label {
VARS_LOCK, VARS_LOCK,
COMP_POOL_LOCK, COMP_POOL_LOCK,
LUA_LOCK, LUA_LOCK,
NOTIF_LOCK,
LOCK_LABELS LOCK_LABELS
}; };
struct lock_stat { struct lock_stat {
@ -253,7 +254,8 @@ static inline void show_lock_stats()
"LISTENER", "LISTENER_QUEUE", "PROXY", "SERVER", "LISTENER", "LISTENER_QUEUE", "PROXY", "SERVER",
"UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS", "UPDATED_SERVERS", "LBPRM", "SIGNALS", "STK_TABLE", "STK_SESS",
"APPLETS", "PEER", "BUF_WQ", "STREAMS", "SSL", "SSL_GEN_CERTS", "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; int lbl;
for (lbl = 0; lbl < LOCK_LABELS; lbl++) { for (lbl = 0; lbl < LOCK_LABELS; lbl++) {

View File

@ -294,6 +294,7 @@ static inline struct notification *notification_new(struct list *purge, struct l
return NULL; return NULL;
LIST_ADDQ(purge, &com->purge_me); LIST_ADDQ(purge, &com->purge_me);
LIST_ADDQ(event, &com->wake_me); LIST_ADDQ(event, &com->wake_me);
SPIN_INIT(&com->lock);
com->task = wakeup; com->task = wakeup;
return com; return com;
} }
@ -308,9 +309,15 @@ static inline void notification_purge(struct list *purge)
/* Delete all pending communication signals. */ /* Delete all pending communication signals. */
list_for_each_entry_safe(com, back, purge, purge_me) { list_for_each_entry_safe(com, back, purge, purge_me) {
SPIN_LOCK(NOTIF_LOCK, &com->lock);
LIST_DEL(&com->purge_me); LIST_DEL(&com->purge_me);
LIST_DEL(&com->wake_me); if (!com->task) {
SPIN_UNLOCK(NOTIF_LOCK, &com->lock);
pool_free2(pool2_notification, com); 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. */ /* Wake task and delete all pending communication signals. */
list_for_each_entry_safe(com, back, wake, wake_me) { 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); LIST_DEL(&com->wake_me);
task_wakeup(com->task, TASK_WOKEN_MSG); if (!com->task) {
SPIN_UNLOCK(NOTIF_LOCK, &com->lock);
pool_free2(pool2_notification, com); pool_free2(pool2_notification, com);
continue;
}
task_wakeup(com->task, TASK_WOKEN_MSG);
com->task = NULL;
SPIN_UNLOCK(NOTIF_LOCK, &com->lock);
} }
} }

View File

@ -56,6 +56,9 @@ struct notification {
struct list wake_me; /* Part of list of signals to be targeted if an struct list wake_me; /* Part of list of signals to be targeted if an
event occurs. */ event occurs. */
struct task *task; /* The task to be wake 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 */ /* The base for all tasks */