diff --git a/include/proto/listener.h b/include/proto/listener.h index fdace2b5f..3a6762ccb 100644 --- a/include/proto/listener.h +++ b/include/proto/listener.h @@ -127,6 +127,9 @@ struct bind_kw *bind_find_kw(const char *kw); /* Dumps all registered "bind" keywords to the 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 . * If is not NULL, it is duplicated into ->arg to store useful config * information for error reporting. diff --git a/include/types/listener.h b/include/types/listener.h index f9eeafaa9..8e9db71dc 100644 --- a/include/types/listener.h +++ b/include/types/listener.h @@ -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 */ + int level; /* stats access level (ACCESS_LVL_*) */ + int severity_output; /* default severity output format in cli feedback messages */ + 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; - 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 */ - uint32_t ns_cip_magic; /* Excepted NetScaler Client IP magic number */ - char *arg; /* argument passed to "bind" for better error reporting */ - char *file; /* file where the section appears */ - int line; /* line where the section appears */ }; /* The listener will be directly referenced by the fdtab[] which holds its diff --git a/src/cfgparse.c b/src/cfgparse.c index 16d92512c..0833574e9 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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)) { diff --git a/src/listener.c b/src/listener.c index f642eb4d0..fb527ab16 100644 --- a/src/listener.c +++ b/src/listener.c @@ -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 in bind_conf according to its thread_mask. + * 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; }