Skip to content

Commit

Permalink
thread_setaffinity: Allow affinity param to have a length less than c…
Browse files Browse the repository at this point in the history
…pumask_size()

Instead of enforcing that the table length is >= cpumask_size(), any missing CPU numbers get assigned an affinity of `false`. This makes this API a bit more user-friendly, since users no longer have to initialize a table of length `cpumask_size()` before setting the particular  affinities they actually want.

As an example, before this commit, you'd have to do something like:

    local affinity = {}
    for i=1,uv.cpumask_size() do
      affinity[i] = false
    end
    affinity[3] = true
    affinity[5] = true

But after this commit, this table:

    local affinity = { [3] = true, [5] = true }

will now be accepted and all the missing keys up to `uv_cpumask_size()` will be treated as `false` in the `thread_setaffinity` call.
  • Loading branch information
squeek502 committed May 24, 2023
1 parent 802b944 commit 8bd2991
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 9 deletions.
5 changes: 3 additions & 2 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -3299,8 +3299,9 @@ equivalent to the `__eq` metamethod.
Sets the specified thread's affinity setting. `affinity` must be an array-like
table where each of the keys correspond to a CPU number and the values are
booleans that represent whether the `thread` should be eligible to run on that
CPU. The length of the `affinity` table must be greater than or equal to
`uv.cpumask_size()`. If `get_old_affinity` is `true`, the previous affinity
CPU. If the length of the `affinity` table is not greater than or equal to
`uv.cpumask_size()`, any CPU numbers missing from the table will have their
affinity set to `false`. If `get_old_affinity` is `true`, the previous affinity
settings for the `thread` will be returned. Otherwise, `true` is returned after
a successful call.

Expand Down
5 changes: 4 additions & 1 deletion src/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,8 +417,11 @@ static int luv_thread_setaffinity(lua_State* L) {
return luv_error(L, min_mask_size);
}
int mask_size = lua_rawlen(L, 2);
// If the provided table's length is not at least min_mask_size,
// we'll use the min_mask_size and fill in any missing values with
// false.
if (mask_size < min_mask_size) {
return luaL_argerror(L, 2, lua_pushfstring(L, "cpumask size must be >= %d (from cpumask_size()), got %d", min_mask_size, mask_size));
mask_size = min_mask_size;
}
char* cpumask = malloc(mask_size);
for (int i = 0; i < mask_size; i++) {
Expand Down
15 changes: 9 additions & 6 deletions tests/test-thread.lua
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,12 @@ return require('lib/tap')(function (test)

-- set every cpu's affinity to false except the current cpu
local cur_cpu = _uv.thread_getcpu()
local affinity_to_set = {}
for i=1,cpumask_size do
affinity_to_set[i] = i == cur_cpu
end
-- even though this table may not be a full array-like table,
-- this still works because `setaffinity` will treat any missing
-- CPU numbers up to cpumask_size as having a setting of `false`
local affinity_to_set = {
[cur_cpu] = true,
}
local prev_affinity = assert(thread:setaffinity(affinity_to_set, true))
-- the returned affinity should match the original affinity
assert(#prev_affinity == #affinity)
Expand All @@ -145,9 +147,10 @@ return require('lib/tap')(function (test)
end

local new_affinity = thread:getaffinity()
assert(#new_affinity == #affinity_to_set)
assert(#new_affinity == cpumask_size)
for i=1,#new_affinity do
assert(new_affinity[i] == affinity_to_set[i])
local expected_setting = i == cur_cpu
assert(new_affinity[i] == expected_setting)
end
end, mask_size):join()
end, "1.45.0")
Expand Down

0 comments on commit 8bd2991

Please sign in to comment.