]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: listener: pre-compute some thread counts per bind_conf
authorWilly Tarreau <w@1wt.eu>
Sun, 3 Feb 2019 10:14:25 +0000 (11:14 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 27 Feb 2019 13:27:07 +0000 (14:27 +0100)
In order to quickly pick a thread ID when accepting a connection, we'll
need to know certain pre-computed values derived from the thread mask,
which are counts of bits per position multiples of 1, 2, 4, 8, 16 and
32. In practice it is sufficient to compute only the 4 first ones and
store them in the bind_conf. We update the count every time the
bind_thread value is adjusted.

The fields in the bind_conf struct have been moved around a little bit
to make it easier to group all thread bit values into the same cache
line.

The function used to return a thread number is bind_map_thread_id(),
and it maps a number between 0 and 31/63 to a thread ID between 0 and
31/63, starting from the left.

include/proto/listener.h
include/types/listener.h
src/cfgparse.c
src/listener.c

index fdace2b5f967a4a2f2846c32e2c20d7e76958875..3a6762ccbd73f66699a4368af5e80ebfcb43ff55 100644 (file)
@@ -127,6 +127,9 @@ struct bind_kw *bind_find_kw(const char *kw);
 /* Dumps all registered "bind" keywords to the <out> string pointer. */
 void bind_dump_kws(char **out);
 
+void bind_recount_thread_bits(struct bind_conf *conf);
+unsigned int bind_map_thread_id(const struct bind_conf *conf, unsigned int r);
+
 /* allocate an bind_conf struct for a bind line, and chain it to the frontend <fe>.
  * If <arg> is not NULL, it is duplicated into ->arg to store useful config
  * information for error reporting.
index f9eeafaa9af569c8f7315b3fd8b18a04d02ca28a..8e9db71dc35e4d43179dd987ff3fd11268fce295 100644 (file)
@@ -165,21 +165,23 @@ struct bind_conf {
        struct xprt_ops *xprt;     /* transport-layer operations for all listeners */
        int is_ssl;                /* SSL is required for these listeners */
        int generate_certs;        /* 1 if generate-certificates option is set, else 0 */
-       unsigned long bind_proc;   /* bitmask of processes allowed to use these listeners */
-       unsigned long bind_thread; /* bitmask of threads allowed to use these listeners */
-       struct {                   /* UNIX socket permissions */
-               uid_t uid;         /* -1 to leave unchanged */
-               gid_t gid;         /* -1 to leave unchanged */
-               mode_t mode;       /* 0 to leave unchanged */
-       } ux;
        int level;                 /* stats access level (ACCESS_LVL_*) */
        int severity_output;       /* default severity output format in cli feedback messages */
-       struct list by_fe;         /* next binding for the same frontend, or NULL */
        struct list listeners;     /* list of listeners using this bind config */
+       unsigned long bind_proc;   /* bitmask of processes allowed to use these listeners */
+       unsigned long bind_thread; /* bitmask of threads allowed to use these listeners */
+       unsigned long thr_2, thr_4, thr_8, thr_16; /* intermediate values for bind_thread counting */
+       unsigned int thr_count;    /* #threads bound */
        uint32_t ns_cip_magic;     /* Excepted NetScaler Client IP magic number */
+       struct list by_fe;         /* next binding for the same frontend, or NULL */
        char *arg;                 /* argument passed to "bind" for better error reporting */
        char *file;                /* file where the section appears */
        int line;                  /* line where the section appears */
+       struct {                   /* UNIX socket permissions */
+               uid_t uid;         /* -1 to leave unchanged */
+               gid_t gid;         /* -1 to leave unchanged */
+               mode_t mode;       /* 0 to leave unchanged */
+       } ux;
 };
 
 /* The listener will be directly referenced by the fdtab[] which holds its
index 16d92512cd7b62ccc59f91178876ca9cfea42bc8..0833574e9ad1b2e826df91ef7c4cd751b81f13d2 100644 (file)
@@ -2318,6 +2318,8 @@ int check_config_validity()
                                           curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line, new_mask);
                        }
 
+                       bind_recount_thread_bits(bind_conf);
+
                        /* detect process and nbproc affinity inconsistencies */
                        mask = proc_mask(bind_conf->bind_proc) & proc_mask(curproxy->bind_proc);
                        if (!(mask & all_proc_mask)) {
index f642eb4d0b6f6b8f86314cced419228f57b8e807..fb527ab16d60de9866cef68b275fbfe9d5de7a86 100644 (file)
@@ -802,6 +802,33 @@ void bind_dump_kws(char **out)
        }
 }
 
+/* recompute the bit counts per parity for the bind_thread value. This will be
+ * used to quickly map a thread number from 1 to #thread to a thread ID among
+ * the ones bound. This is the preparation phase of the bit rank counting algo
+ * described here: https://graphics.stanford.edu/~seander/bithacks.html
+ */
+void bind_recount_thread_bits(struct bind_conf *conf)
+{
+       unsigned long m;
+
+       m = thread_mask(conf->bind_thread);
+       conf->thr_count = my_popcountl(m);
+       mask_prep_rank_map(m, &conf->thr_2, &conf->thr_4, &conf->thr_8, &conf->thr_16);
+}
+
+/* Report the ID of thread <r> in bind_conf <conf> according to its thread_mask.
+ * <r> must be between 0 and LONGBITS-1. This makes use of the pre-computed
+ * bits resulting from bind_recount_thread_bits. See this function for more
+ * info.
+ */
+unsigned int bind_map_thread_id(const struct bind_conf *conf, unsigned int r)
+{
+       unsigned long m;
+
+       m = thread_mask(conf->bind_thread);
+       return mask_find_rank_bit_fast(r, m, conf->thr_2, conf->thr_4, conf->thr_8, conf->thr_16);
+}
+
 /************************************************************************/
 /*      All supported sample and ACL keywords must be declared here.    */
 /************************************************************************/
@@ -1012,6 +1039,7 @@ static int bind_parse_process(char **args, int cur_arg, struct proxy *px, struct
 
        conf->bind_proc |= proc;
        conf->bind_thread |= thread;
+       bind_recount_thread_bits(conf);
        return 0;
 }