Usage Guide and Examples

Relevant source files

This page provides practical examples and common usage patterns for the cpumask library in operating system contexts. It demonstrates how to effectively use the CpuMask<SIZE> struct for CPU affinity management, process scheduling, and system resource allocation.

For detailed API documentation, see API Reference. For implementation details and performance characteristics, see Architecture and Design.

Basic Usage Patterns

Creating CPU Masks

The most common way to start working with CPU masks is through the various construction methods provided by CpuMask<SIZE>:

flowchart TD
A["CpuMask::new()"]
B["Empty mask - all false"]
C["CpuMask::full()"]
D["Full mask - all true"]
E["CpuMask::mask(bits)"]
F["Range mask - first bits true"]
G["CpuMask::one_shot(index)"]
H["Single CPU mask"]
I["CpuMask::from_raw_bits(value)"]
J["From usize value"]
K["CpuMask::from_value(data)"]
L["From backing store type"]
M["Basic CPU set operations"]

A --> B
B --> M
C --> D
D --> M
E --> F
F --> M
G --> H
H --> M
I --> J
J --> M
K --> L
L --> M

Sources: src/lib.rs(L72 - L128) 

Basic Manipulation Operations

The fundamental operations for working with individual CPU bits follow a consistent pattern:

OperationMethodDescriptionReturn Value
Test bitget(index)Check if CPU is in maskbool
Set bitset(index, value)Add/remove CPU from maskPreviousboolvalue
Count bitslen()Number of CPUs in maskusize
Test emptyis_empty()Check if no CPUs setbool
Test fullis_full()Check if all CPUs setbool

Sources: src/lib.rs(L148 - L179) 

Finding CPUs in Masks

The library provides efficient methods for locating specific CPUs within masks:

flowchart TD
A["CpuMask"]
B["first_index()"]
C["last_index()"]
D["next_index(current)"]
E["prev_index(current)"]
F["Inverse operations"]
G["first_false_index()"]
H["last_false_index()"]
I["next_false_index(current)"]
J["prev_false_index(current)"]
K["Option<usize>"]

A --> B
A --> C
A --> D
A --> E
B --> K
C --> K
D --> K
E --> K
F --> G
F --> H
F --> I
F --> J
G --> K
H --> K
I --> K
J --> K

Sources: src/lib.rs(L182 - L228) 

Set Operations and Logic

Bitwise Operations

CPU masks support standard bitwise operations for combining and manipulating sets of CPUs:

flowchart TD
A["mask1: CpuMask<N>"]
E["mask1 & mask2"]
B["mask2: CpuMask<N>"]
F["Intersection - CPUs in both"]
G["mask1 | mask2"]
H["Union - CPUs in either"]
I["mask1 ^ mask2"]
J["Symmetric difference - CPUs in one but not both"]
K["!mask1"]
L["Complement - inverse of mask"]
M["Assignment variants"]
N["&=, |=, ^="]
O["In-place operations"]

A --> E
A --> G
A --> I
A --> K
B --> E
B --> G
B --> I
E --> F
G --> H
I --> J
K --> L
M --> N
N --> O

Sources: src/lib.rs(L253 - L326) 

Practical Set Operations Example

Consider a scenario where you need to manage CPU allocation for different process types:

  1. System processes - CPUs 0-3 (reserved for kernel)
  2. User processes - CPUs 4-15 (general workload)
  3. Real-time processes - CPUs 12-15 (high-performance subset)

This demonstrates how set operations enable sophisticated CPU management policies.

Sources: src/lib.rs(L253 - L287) 

Iteration and Traversal

Forward and Backward Iteration

The CpuMask implements both Iterator and DoubleEndedIterator, enabling flexible traversal patterns:


Sources: src/lib.rs(L237 - L518) 

Iteration Use Cases

The iterator yields CPU indices where the bit is set to true, making it ideal for:

  • Process scheduling: Iterate through available CPUs for task assignment
  • Load balancing: Traverse CPU sets to find optimal placement
  • Resource monitoring: Check specific CPU states in sequence
  • Affinity enforcement: Validate process can run on assigned CPUs

Sources: src/lib.rs(L412 - L427) 

Operating System Scenarios

Process Scheduling Workflow

This diagram shows how CpuMask integrates into a typical process scheduler:

flowchart TD
A["Process creation"]
B["Determine CPU affinity policy"]
C["CpuMask::new() or policy-specific constructor"]
D["Store affinity in process control block"]
E["Scheduler activation"]
F["Load process affinity mask"]
G["available_cpus & process_affinity"]
H["Any CPUs available?"]
I["Select CPU from mask"]
J["Wait or migrate"]
K["Schedule process on selected CPU"]
L["Update available_cpus"]
M["CPU hotplug event"]
N["Update system CPU mask"]
O["Revalidate all process affinities"]
P["Migrate processes if needed"]

A --> B
B --> C
C --> D
E --> F
F --> G
G --> H
H --> I
H --> J
I --> K
J --> L
L --> G
M --> N
N --> O
O --> P

Sources: src/lib.rs(L9 - L23) 

NUMA-Aware CPU Management

In NUMA systems, CPU masks help maintain memory locality:

flowchart TD
subgraph subGraph1["NUMA Node 1"]
    C["CPUs 8-15"]
    D["Local Memory"]
end
subgraph subGraph0["NUMA Node 0"]
    A["CPUs 0-7"]
    B["Local Memory"]
end
E["Process A"]
F["CpuMask::mask(8) - Node 0 only"]
G["Process B"]
H["CpuMask::from_raw_bits(0xFF00) - Node 1 only"]
I["System Process"]
J["CpuMask::full() - Any CPU"]
K["Load balancer decides"]

E --> F
F --> A
G --> H
H --> C
I --> J
J --> K
K --> A
K --> C

Sources: src/lib.rs(L86 - L94)  src/lib.rs(L106 - L119) 

Thread Affinity Management

For multi-threaded applications, CPU masks enable fine-grained control:

Thread TypeAffinity StrategyImplementation
Main threadSingle CPUCpuMask::one_shot(0)
Worker threadsSubset of CPUsCpuMask::mask(worker_count)
I/O threadsNon-main CPUs!CpuMask::one_shot(0)
RT threadsDedicated CPUsCpuMask::from_raw_bits(rt_mask)

Sources: src/lib.rs(L121 - L128)  src/lib.rs(L289 - L299) 

Advanced Usage Patterns

Dynamic CPU Set Management

Real systems require dynamic adjustment of CPU availability:


Sources: src/lib.rs(L177 - L180)  src/lib.rs(L301 - L326) 

Performance Optimization Strategies

The choice of SIZE parameter significantly impacts performance:

System SizeRecommended SIZEStorage TypeUse Case
Single coreSIZE = 1boolEmbedded systems
Small SMP (≤8)SIZE = 8u8IoT devices
Desktop/Server (≤32)SIZE = 32u32General purpose
Large server (≤128)SIZE = 128u128HPC systems
Massive systemsSIZE = 1024[u128; 8]Cloud infrastructure

The automatic storage selection in src/lib.rs(L12 - L16)  ensures optimal memory usage and performance characteristics for each size category.

Error Handling Patterns

While CpuMask operations are generally infallible, certain usage patterns require validation:

  • Bounds checking: Methods use debug_assert! for index validation
  • Size validation: from_raw_bits() asserts value fits in SIZE bits
  • Range validation: one_shot() panics if index exceeds SIZE

In production systems, wrap these operations with appropriate error handling based on your safety requirements.

Sources: src/lib.rs(L106 - L108)  src/lib.rs(L123 - L124)  src/lib.rs(L168 - L170)