]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: threads/tasks: Add lock around notifications
authorThierry FOURNIER <thierry.fournier@ozon.io>
Sun, 16 Jul 2017 22:14:07 +0000 (00:14 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 31 Oct 2017 12:58:32 +0000 (13:58 +0100)
This patch add lock around some notification calls

include/common/hathreads.h
include/proto/task.h
include/types/task.h

index a5a25b47ecc8d884b4b13a06049707dacf77e883..774fe7b674ddf6abcbfe209d1df653b897abd659 100644 (file)
@@ -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++) {
index bc3a17316fbc8c2f7a79a8db2acf9a1e3e1ab2e1..cb98fefc7ee41d093584bbd3438e9b1d99cb0799 100644 (file)
@@ -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);
        }
 }
 
index da7c929bcd430b202e1011a9f247bf1ee7f95c21..799e6c5ed0ac54ef5c0c59e73fea27e9a04bd35d 100644 (file)
@@ -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 */