1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// This file is part of context-allocator. It is subject to the license terms in the COPYRIGHT file found in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/context-allocator/master/COPYRIGHT. No part of context-allocator, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the COPYRIGHT file.
// Copyright © 2019 The developers of context-allocator. See the COPYRIGHT file in the top-level directory of this distribution and at https://raw.githubusercontent.com/lemonrock/context-allocator/master/COPYRIGHT.


/// NUMA nodes to allocate on.
///
/// If set to no nodes (the `Default::default()`) then memory is allocated on the local node if possible.
///
/// Ignored on operating systems other than Android and Linux.
#[derive(Default, Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct NumaNodeBitSet
{
	bits: usize,

	/// Specifies physical node IDs.
	///
	/// Linux does not remap the nodemask when the thread moves to a different cpuset context, nor when the set of nodes allowed by the thread's current cpuset context changes.
	///
	/// (Not used if there are no nodes specified).
	pub static_nodes: bool,

	/// Specifies specifies node IDs that are relative to the set of node IDs allowed by the thread's current cpuset.
	///
	/// (Not used if there are no nodes specified).
	pub relative_nodes: bool,
}

impl NumaNodeBitSet
{
	#[allow(dead_code)] const no_mode_flags_nodemask_maxnode: (i32, Option<usize>, usize) = (0, None, 0);

	/// Is this the empty set?
	#[inline(always)]
	pub fn is_empty(&self) -> bool
	{
		self.bits == 0
	}

	/// Add a NUMA node into the set.
	#[inline(always)]
	pub fn insert_numa_node(&mut self, zero_based_node_index: u8)
	{
		self.bits |= 1 << (zero_based_node_index as usize)
	}

	/// Remove a NUMA node from the set.
	#[inline(always)]
	pub fn remove_numa_node(&mut self, zero_based_node_index: u8)
	{
		self.bits &= !(1 << (zero_based_node_index as usize))
	}

	#[cfg(any(target_os = "android", target_os = "linux"))]
	#[inline(always)]
	fn mask_and_size(&self) -> (i32, Option<usize>, usize)
	{
		if likely!(self.is_empty())
		{
			Self::no_mode_flags_nodemask_maxnode
		}
		else
		{
			let size = size_of::<usize>();

			let mut mode_flags = 0;
			if unlikely!(self.static_nodes)
			{
				const MPOL_F_STATIC_NODES: i32 = 1 << 15;
				mode_flags |= MPOL_F_STATIC_NODES
			}
			if unlikely!(self.relative_nodes)
			{
				const MPOL_F_RELATIVE_NODES: i32 = 1 << 14;
				mode_flags |= MPOL_F_RELATIVE_NODES
			}

			(mode_flags, Some(self.bits), size + 1)
		}
	}
}