Blame SOURCES/0006-Ticket-51131-improve-mutex-alloc-in-conntable.patch

47c2e9
From 1085823bf5586d55103cfba249fdf212e9afcb7c Mon Sep 17 00:00:00 2001
47c2e9
From: William Brown <william@blackhats.net.au>
47c2e9
Date: Thu, 4 Jun 2020 11:51:53 +1000
47c2e9
Subject: [PATCH] Ticket 51131 - improve mutex alloc in conntable
47c2e9
47c2e9
Bug Description: We previously did delayed allocation
47c2e9
of mutexs, which @tbordaz noted can lead to high usage
47c2e9
of the pthread mutex init routines. This was done under
47c2e9
the conntable lock, as well as cleaning the connection
47c2e9
47c2e9
Fix Description: rather than delayed allocation, we
47c2e9
initialise everything at start up instead, which means
47c2e9
that while startup may have a delay, at run time we have
47c2e9
a smaller and lighter connection allocation routine,
47c2e9
that is able to release the CT lock sooner.
47c2e9
47c2e9
https://pagure.io/389-ds-base/issue/51131
47c2e9
47c2e9
Author: William Brown <william@blackhats.net.au>
47c2e9
47c2e9
Review by: ???
47c2e9
---
47c2e9
 ldap/servers/slapd/conntable.c | 86 +++++++++++++++++++---------------
47c2e9
 1 file changed, 47 insertions(+), 39 deletions(-)
47c2e9
47c2e9
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
47c2e9
index b23dc3435..feb9c0d75 100644
47c2e9
--- a/ldap/servers/slapd/conntable.c
47c2e9
+++ b/ldap/servers/slapd/conntable.c
47c2e9
@@ -138,10 +138,21 @@ connection_table_new(int table_size)
47c2e9
     ct->conn_next_offset = 1;
47c2e9
     ct->conn_free_offset = 1;
47c2e9
 
47c2e9
+    pthread_mutexattr_t monitor_attr = {0};
47c2e9
+    pthread_mutexattr_init(&monitor_attr);
47c2e9
+    pthread_mutexattr_settype(&monitor_attr, PTHREAD_MUTEX_RECURSIVE);
47c2e9
+
47c2e9
     /* We rely on the fact that we called calloc, which zeros the block, so we don't
47c2e9
      * init any structure element unless a zero value is troublesome later
47c2e9
      */
47c2e9
     for (i = 0; i < table_size; i++) {
47c2e9
+        /*
47c2e9
+         * Technically this is a no-op due to calloc, but we should always be
47c2e9
+         * careful with things like this ....
47c2e9
+         */
47c2e9
+        ct->c[i].c_state = CONN_STATE_FREE;
47c2e9
+        /* Start the conn setup. */
47c2e9
+
47c2e9
         LBER_SOCKET invalid_socket;
47c2e9
         /* DBDB---move this out of here once everything works */
47c2e9
         ct->c[i].c_sb = ber_sockbuf_alloc();
47c2e9
@@ -161,11 +172,20 @@ connection_table_new(int table_size)
47c2e9
         ct->c[i].c_prev = NULL;
47c2e9
         ct->c[i].c_ci = i;
47c2e9
         ct->c[i].c_fdi = SLAPD_INVALID_SOCKET_INDEX;
47c2e9
-        /*
47c2e9
-         * Technically this is a no-op due to calloc, but we should always be
47c2e9
-         * careful with things like this ....
47c2e9
-         */
47c2e9
-        ct->c[i].c_state = CONN_STATE_FREE;
47c2e9
+
47c2e9
+        if (pthread_mutex_init(&(ct->c[i].c_mutex), &monitor_attr) != 0) {
47c2e9
+            slapi_log_err(SLAPI_LOG_ERR, "connection_table_get_connection", "pthread_mutex_init failed\n");
47c2e9
+            exit(1);
47c2e9
+        }
47c2e9
+
47c2e9
+        ct->c[i].c_pdumutex = PR_NewLock();
47c2e9
+        if (ct->c[i].c_pdumutex == NULL) {
47c2e9
+            slapi_log_err(SLAPI_LOG_ERR, "connection_table_get_connection", "PR_NewLock failed\n");
47c2e9
+            exit(1);
47c2e9
+        }
47c2e9
+
47c2e9
+        /* Ready to rock, mark as such. */
47c2e9
+        ct->c[i].c_state = CONN_STATE_INIT;
47c2e9
         /* Prepare the connection into the freelist. */
47c2e9
         ct->c_freelist[i] = &(ct->c[i]);
47c2e9
     }
47c2e9
@@ -241,44 +261,32 @@ connection_table_get_connection(Connection_Table *ct, int sd)
47c2e9
             /* Never use slot 0 */
47c2e9
             ct->conn_next_offset += 1;
47c2e9
         }
47c2e9
-        /* Now prep the slot for usage. */
47c2e9
-        PR_ASSERT(c->c_next == NULL);
47c2e9
-        PR_ASSERT(c->c_prev == NULL);
47c2e9
-        PR_ASSERT(c->c_extension == NULL);
47c2e9
-
47c2e9
-        if (c->c_state == CONN_STATE_FREE) {
47c2e9
-
47c2e9
-            c->c_state = CONN_STATE_INIT;
47c2e9
-
47c2e9
-            pthread_mutexattr_t monitor_attr = {0};
47c2e9
-            pthread_mutexattr_init(&monitor_attr);
47c2e9
-            pthread_mutexattr_settype(&monitor_attr, PTHREAD_MUTEX_RECURSIVE);
47c2e9
-            if (pthread_mutex_init(&(c->c_mutex), &monitor_attr) != 0) {
47c2e9
-                slapi_log_err(SLAPI_LOG_ERR, "connection_table_get_connection", "pthread_mutex_init failed\n");
47c2e9
-                exit(1);
47c2e9
-            }
47c2e9
-
47c2e9
-            c->c_pdumutex = PR_NewLock();
47c2e9
-            if (c->c_pdumutex == NULL) {
47c2e9
-                c->c_pdumutex = NULL;
47c2e9
-                slapi_log_err(SLAPI_LOG_ERR, "connection_table_get_connection", "PR_NewLock failed\n");
47c2e9
-                exit(1);
47c2e9
-            }
47c2e9
-        }
47c2e9
-        /* Let's make sure there's no cruft left on there from the last time this connection was used. */
47c2e9
-        /* Note: no need to lock c->c_mutex because this function is only
47c2e9
-         * called by one thread (the slapd_daemon thread), and if we got this
47c2e9
-         * far then `c' is not being used by any operation threads, etc.
47c2e9
-         */
47c2e9
-        connection_cleanup(c);
47c2e9
-        c->c_ct = ct; /* pointer to connection table that owns this connection */
47c2e9
+        PR_Unlock(ct->table_mutex);
47c2e9
     } else {
47c2e9
-        /* couldn't find a Connection */
47c2e9
+        /* couldn't find a Connection, table must be full */
47c2e9
         slapi_log_err(SLAPI_LOG_CONNS, "connection_table_get_connection", "Max open connections reached\n");
47c2e9
+        PR_Unlock(ct->table_mutex);
47c2e9
+        return NULL;
47c2e9
     }
47c2e9
 
47c2e9
-    /* We could move this to before the c alloc as there is no point to remain here. */
47c2e9
-    PR_Unlock(ct->table_mutex);
47c2e9
+    /* Now prep the slot for usage. */
47c2e9
+    PR_ASSERT(c != NULL);
47c2e9
+    PR_ASSERT(c->c_next == NULL);
47c2e9
+    PR_ASSERT(c->c_prev == NULL);
47c2e9
+    PR_ASSERT(c->c_extension == NULL);
47c2e9
+    PR_ASSERT(c->c_state == CONN_STATE_INIT);
47c2e9
+    /* Let's make sure there's no cruft left on there from the last time this connection was used. */
47c2e9
+
47c2e9
+    /*
47c2e9
+     * Note: no need to lock c->c_mutex because this function is only
47c2e9
+     * called by one thread (the slapd_daemon thread), and if we got this
47c2e9
+     * far then `c' is not being used by any operation threads, etc. The
47c2e9
+     * memory ordering will be provided by the work queue sending c to a
47c2e9
+     * thread.
47c2e9
+     */
47c2e9
+    connection_cleanup(c);
47c2e9
+    /* pointer to connection table that owns this connection */
47c2e9
+    c->c_ct = ct;
47c2e9
 
47c2e9
     return c;
47c2e9
 }
47c2e9
-- 
47c2e9
2.26.2
47c2e9