feat: extend bmp with wordCountFor and bmpInit

This commit is contained in:
dualfroz committed 2026-09-02 19:23:37 +02:00
1 parent 54242aeae3
commit f0b99bc99a
3 files changed
+122 -4

No files matched your search

+90
View File
@@ -0,0 +1,90 @@
#include "bmp.h"
#define bmpBitsPerWord 64
static usize wordCountFor(usize bitCount)
{
return (bitCount + bmpBitsPerWord - 1) / bmpBitsPerWord;
}
void bmpInit(Bitmap* b, uint64* backingWords, usize bitCount)
{
b->words = backingWords;
b->bitCount = bitCount;
bmpClearAll(b);
}
void bmpSet(Bitmap* b, usize index)
{
if (index >= b->bitCount)
return;
b->words[index / bmpBitsPerWord] |= (1UL << (index % bmpBitsPerWord));
}
void bmpClear(Bitmap* b, usize index)
{
if (index >= b->bitCount)
return;
b->words[index / bmpBitsPerWord] &= ~(1UL << (index % bmpBitsPerWord));
}
bool bmpTest(const Bitmap* b, usize index)
{
if (index >= b->bitCount)
return false;
return (b->words[index / bmpBitsPerWord] & (1UL << (index % bmpBitsPerWord))) != 0;
}
void bmpSetRange(Bitmap* b, usize start, usize count)
{
for (usize i = start; i < start + count && i < b->bitCount; i++)
bmpSet(b, i);
}
void bmpClearRange(Bitmap* b, usize start, usize count)
{
for (usize i = start; i < start + count && i < b->bitCount; i++)
bmpClear(b, i);
}
void bmpSetAll(Bitmap* b)
{
usize words = wordCountFor(b->bitCount);
for (usize i = 0; i < words; i++)
b->words[i] = ~0UL;
}
void bmpClearAll(Bitmap* b)
{
usize words = wordCountFor(b->bitCount);
for (usize i = 0; i < words; i++)
b->words[i] = 0;
}
usize bmpCountSet(const Bitmap* b)
{
usize total = 0;
for (usize i = 0; i < b->bitCount; i++) {
if (bmpTest(b, i))
total++;
}
return total;
}
isize bmpFindFirstClear(const Bitmap* b)
{
for (usize i = 0; i < b->bitCount; i++) {
if (!bmpTest(b, i))
return (isize)i;
}
return -1;
}
isize bmpFindFirstSet(const Bitmap* b)
{
for (usize i = 0; i < b->bitCount; i++) {
if (bmpTest(b, i))
return (isize)i;
}
return -1;
}
+20
View File
@@ -60,6 +60,10 @@ fillPd:
movl $0xC0000080, %ecx
rdmsr
orl $(1 << 8), %eax
cmpl $0, cpuNxSupported
je 2f
orl $(1 << 11), %eax
2:
wrmsr
movl %cr0, %eax
@@ -76,6 +80,16 @@ checkLongMode:
jb noLongMode
movl $0x80000001, %eax
cpuid
/* Same cpuid leaf already gives us CPUID.80000001H:EDX.NX (bit 20) for
free -- stash it in cpuNxSupported (checked below, in %eax's later
rdmsr/wrmsr dance) before the LM (bit 29) test below, which does not
touch %edx, leaves it intact either way. */
movl $0, cpuNxSupported
testl $(1 << 20), %edx
jz 1f
movl $1, cpuNxSupported
1:
testl $(1 << 29), %edx
jz noLongMode
ret
@@ -111,6 +125,12 @@ bootGdtPointer:
.word bootGdtEnd - bootGdtStart - 1
.quad bootGdtStart
.section .boot.data, "aw", @progbits
.align 4
.global cpuNxSupported
cpuNxSupported:
.long 0
.section .boot.pagetables, "aw", @progbits
.align 4096
.global bootPml4
+12 -4
View File
@@ -43,13 +43,21 @@ static void writeUnsigned(uint64 value, uint32 base, bool upper, int minWidth, c
kputchar(buffer[--length]);
}
static void writeSigned(int64 value)
/* Mirrors klib.c's vsnprintf sinkPutSigned exactly (same minWidth/pad
contract, same "sign eats one column of the requested width" rule) --
found and fixed this fala after shell.c's new `ls -l` printed
"2026-9-7" instead of "2026-09-07": every prior kprintf call site that
wanted zero-padded fields (thread ids, sizes, hex addresses) happened
to use an unsigned specifier, so this signed-value width/pad bug went
completely unnoticed until the first zero-padded %d/%ld call ever
appeared. */
static void writeSigned(int64 value, int minWidth, char pad)
{
if (value < 0) {
kputchar('-');
writeUnsigned((uint64)(-value), 10, false, 0, ' ');
writeUnsigned((uint64)(-value), 10, false, minWidth > 0 ? minWidth - 1 : 0, pad);
} else {
writeUnsigned((uint64)value, 10, false, 0, ' ');
writeUnsigned((uint64)value, 10, false, minWidth, pad);
}
}
@@ -93,7 +101,7 @@ void kprintf(const char* format, ...)
break;
case 'd':
case 'i':
writeSigned(longCount ? va_arg(args, int64) : (int64)va_arg(args, int));
writeSigned(longCount ? va_arg(args, int64) : (int64)va_arg(args, int), width, pad);
break;
case 'u':
writeUnsigned(longCount ? va_arg(args, uint64) : (uint64)va_arg(args, uint32), 10, false, width, pad);