mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-19 01:54:37 +00:00
MINOR: threads: add a new function to resolve config groups and masks
In the configuration sometimes we'll omit a thread group number to designate a global thread number range, and sometimes we'll mention the group and designate IDs within that group. The operation is more complex than it seems due to the need to check for ranges spanning between multiple groups and determining groups from threads from bit masks and remapping bit masks between local/global. This patch adds a function to perform this operation, it takes a group and mask on input and updates them on output. It's designed to be used by "bind" lines but will likely be usable at other places if needed. For situations where specified threads do not exist in the group, we have the choice in the code between silently fixing the thread set or failing with a message. For now the better option seems to return an error, but if it turns out to be an issue we can easily change that in the future. Note that it should only happen with "x/even" when group x only has one thread.
This commit is contained in:
parent
d57b9ff7af
commit
627def9e50
@ -44,6 +44,7 @@ void ha_tkill(unsigned int thr, int sig);
|
||||
void ha_tkillall(int sig);
|
||||
void ha_thread_relax(void);
|
||||
int thread_map_to_groups();
|
||||
int thread_resolve_group_mask(uint igid, ulong imask, uint *ogid, ulong *omask, char **err);
|
||||
extern int thread_cpus_enabled_at_boot;
|
||||
|
||||
|
||||
|
102
src/thread.c
102
src/thread.c
@ -1087,6 +1087,108 @@ int thread_map_to_groups()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* converts a configuration thread group+mask to a global group+mask depending on
|
||||
* the configured thread group id. This is essentially for use with the "thread"
|
||||
* directive on "bind" lines, where "thread 2/1-3" might be turned to "4-6" for
|
||||
* the global ID. It cannot be used before the thread mapping above was completed
|
||||
* and the thread group number configured. Possible options:
|
||||
* - igid == 0: imask represents global IDs. We have to check that all
|
||||
* configured threads in the mask belong to the same group. If imask is zero
|
||||
* it means everything, so for now we only support this with a single group.
|
||||
* - igid > 0, imask = 0: convert local values to global values for this thread
|
||||
* - igid > 0, imask > 0: convert local values to global values
|
||||
*
|
||||
* Returns <0 on failure, >=0 on success.
|
||||
*/
|
||||
int thread_resolve_group_mask(uint igid, ulong imask, uint *ogid, ulong *omask, char **err)
|
||||
{
|
||||
ulong mask;
|
||||
uint t;
|
||||
|
||||
if (igid == 0) {
|
||||
/* unspecified group, IDs are global */
|
||||
if (!imask) {
|
||||
/* all threads of all groups */
|
||||
if (global.nbtgroups > 1) {
|
||||
memprintf(err, "'thread' directive spans multiple groups");
|
||||
return -1;
|
||||
}
|
||||
mask = 0;
|
||||
*ogid = 1; // first and only group
|
||||
*omask = all_threads_mask;
|
||||
return 0;
|
||||
} else {
|
||||
/* some global threads */
|
||||
imask &= all_threads_mask;
|
||||
for (t = 0; t < global.nbthread; t++) {
|
||||
if (imask & (1UL << t)) {
|
||||
if (ha_thread_info[t].tg->tgid != igid) {
|
||||
if (!igid)
|
||||
igid = ha_thread_info[t].tg->tgid;
|
||||
else {
|
||||
memprintf(err, "'thread' directive spans multiple groups (at least %u and %u)", igid, ha_thread_info[t].tg->tgid);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!igid) {
|
||||
memprintf(err, "'thread' directive contains threads that belong to no group");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we have a valid group, convert this to global thread IDs */
|
||||
*ogid = igid;
|
||||
*omask = imask << ha_tgroup_info[igid - 1].base;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* group was specified */
|
||||
if (igid > global.nbtgroups) {
|
||||
memprintf(err, "'thread' directive references non-existing thread group %u", igid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!imask) {
|
||||
/* all threads of this groups. Let's make a mask from their count and base. */
|
||||
*ogid = igid;
|
||||
mask = 1UL << (ha_tgroup_info[igid - 1].count - 1);
|
||||
mask |= mask - 1;
|
||||
*omask = mask << ha_tgroup_info[igid - 1].base;
|
||||
return 0;
|
||||
} else {
|
||||
/* some local threads. Keep only existing ones for this group */
|
||||
|
||||
mask = 1UL << (ha_tgroup_info[igid - 1].count - 1);
|
||||
mask |= mask - 1;
|
||||
|
||||
if (!(mask & imask)) {
|
||||
/* no intersection between the thread group's
|
||||
* threads and the bind line's.
|
||||
*/
|
||||
#ifdef THREAD_AUTO_ADJUST_GROUPS
|
||||
unsigned long new_mask = 0;
|
||||
|
||||
while (imask) {
|
||||
new_mask |= imask & mask;
|
||||
imask >>= ha_tgroup_info[igid - 1].count;
|
||||
}
|
||||
imask = new_mask;
|
||||
#else
|
||||
memprintf(err, "'thread' directive only references threads not belonging to the group");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
mask &= imask;
|
||||
*omask = mask << ha_tgroup_info[igid - 1].base;
|
||||
*ogid = igid;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the "nbthread" global directive, which takes an integer argument that
|
||||
* contains the desired number of threads.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user