summaryrefslogtreecommitdiff
path: root/na/kernel/pid.cc
blob: 04b846b352fc0689bfd359842d387a07e636720d (plain)
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
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Copyright (C) 2026 Richard Qin */

/*
 * PID Allocator — Bitmap-based O(1) block search
 * Reference: docs/specs/task.md §3.2
 */

#include <lume/pid.h>

void PidAllocator::init()
{
    for (int i = 0; i < kBitmapWords; i++)
        bitmap_[i] = 0;
    next_hint_ = 1;
    bitmap_[0] |= 0x1ULL; /* Reserve PID 0 (idle/swapper) only.
                           * PID 1 (init) is allocated normally — the first
                           * kthread_create() call gets it, matching Linux. */
}

int32 PidAllocator::alloc()
{
    LockGuard guard(lock_);

    int32 word_start = next_hint_ / 64;

    for (int32 passes = 0; passes < kBitmapWords; passes++) {
        int32 w = (word_start + passes) % kBitmapWords;
        uint64 free_bits = ~bitmap_[w];
        if (free_bits == 0)
            continue;

        int bit = 0;
        uint64 v = free_bits;
        while ((v & 1ULL) == 0) { v >>= 1; bit++; }
        int32 pid = w * 64 + bit;

        if (pid >= kMaxPid)
            continue;

        bitmap_[w] |= (1ULL << bit);
        next_hint_ = pid + 1;
        if (next_hint_ >= kMaxPid)
            next_hint_ = 2;

        return pid;
    }

    return -1;
}

void PidAllocator::free(int32 pid)
{
    if (pid < 0 || pid >= kMaxPid)
        return;

    LockGuard guard(lock_);
    int32 w = pid / 64;
    int32 bit = pid % 64;
    bitmap_[w] &= ~(1ULL << bit);
}

PidAllocator g_pid_alloc;