mm: fix page frame allocator bugs
This also includes a minor refactor of everything, as well as some optimizations. The bitmap operations have been moved into a separate file because they are probably gonna come in handy in other parts of the system as well.main
parent
96378f019c
commit
743424d15f
@ -0,0 +1,65 @@
|
||||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gay/cdefs.h>
|
||||
#include <gay/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/**
|
||||
* @brief Test whether a bit in a bitfield is set.
|
||||
*
|
||||
* @param bitfield Bitfield to test a bit of
|
||||
* @param pos Index of the bit within the bitfield, counting from 0
|
||||
* @return `true` if the bit is set, `false` if not
|
||||
*/
|
||||
bool bit_tst(const unsigned long *bitfield, usize pos);
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in a bitfield.
|
||||
*
|
||||
* @param bitfield Bitfield to set the bit in
|
||||
* @param pos Index of the bit within the bitfield, counting from 0
|
||||
*/
|
||||
void bit_set(unsigned long *bitfield, usize pos);
|
||||
|
||||
/**
|
||||
* @brief Clear a single bit in a bitfield.
|
||||
*
|
||||
* @param bitfield Bitfield to clear the bit in
|
||||
* @param pos Index of the bit within the bitfield, counting from 0
|
||||
*/
|
||||
void bit_clr(unsigned long *bitfield, usize pos);
|
||||
|
||||
/**
|
||||
* @brief Set a range of bits in a bitfield.
|
||||
*
|
||||
* @param bitfield Bitfield to set bits in
|
||||
* @param first Index of the first bit to set in the bitfield, counting from 0
|
||||
* @param count Number of bits to set, starting from index `first`
|
||||
*/
|
||||
void bit_set_range(unsigned long *bitfield, usize first, usize count);
|
||||
|
||||
/**
|
||||
* @brief Clear a range of bits in a bitfield.
|
||||
*
|
||||
* @param bitfield Bitfield to clear bits in
|
||||
* @param first Index of the first bit to clear in the bitfield, counting from 0
|
||||
* @param count Number of bits to clear, starting from index `first`
|
||||
*/
|
||||
void bit_clr_range(unsigned long *bitfield, usize first, usize count);
|
||||
|
||||
/*
|
||||
* This file is part of GayBSD.
|
||||
* Copyright (c) 2021 fef <owo@fef.moe>.
|
||||
*
|
||||
* GayBSD is nonviolent software: you may only use, redistribute, and/or
|
||||
* modify it under the terms of the Cooperative Nonviolent Public License
|
||||
* (CNPL) as found in the LICENSE file in the source code root directory
|
||||
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
|
||||
* of the license, or (at your option) any later version.
|
||||
*
|
||||
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPL for details.
|
||||
*/
|
@ -0,0 +1,104 @@
|
||||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#include <gay/bits.h>
|
||||
#include <gay/types.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
void bit_set_range(unsigned long *bitfield, usize first, usize count)
|
||||
{
|
||||
/* skip ahead to the longword containing the first bit we need to set */
|
||||
bitfield += first / LONG_BIT;
|
||||
unsigned int bit = first % LONG_BIT;
|
||||
|
||||
/* test if the entire bit range is contained within this longword */
|
||||
if (bit + count < LONG_BIT) {
|
||||
unsigned long low_mask = (1lu << bit) - 1; /* 0b000..011 */
|
||||
unsigned long high_mask = ~0lu ^ ((1lu << (bit + count)) - 1); /* 0b110..000 */
|
||||
*bitfield |= ~(low_mask | high_mask);
|
||||
} else {
|
||||
/* if the first bit isn't longword aligned, manually set the upper
|
||||
* bits in that longword, starting from the first bit's position */
|
||||
if (bit != 0) {
|
||||
unsigned long mask = (1lu << bit) - 1;
|
||||
*bitfield++ |= ~mask;
|
||||
count -= LONG_BIT - bit;
|
||||
}
|
||||
|
||||
/* write out full longwords while we can */
|
||||
while (count >= LONG_BIT) {
|
||||
*bitfield++ = ~0lu;
|
||||
count -= LONG_BIT;
|
||||
}
|
||||
|
||||
/* set the remaining lower bits in the last longword, if any */
|
||||
if (count != 0) {
|
||||
unsigned long mask = (1lu << count) - 1;
|
||||
*bitfield |= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this works the same way as bit_set_range, it's just the inverse */
|
||||
void bit_clr_range(unsigned long *bitfield, usize first, usize count)
|
||||
{
|
||||
bitfield += first / LONG_BIT;
|
||||
unsigned int bit = first % LONG_BIT;
|
||||
|
||||
if (bit + count < LONG_BIT) {
|
||||
unsigned long low_mask = (1lu << bit) - 1;
|
||||
unsigned long high_mask = ~0lu ^ ((1lu << (bit + count)) - 1);
|
||||
*bitfield &= low_mask | high_mask;
|
||||
} else {
|
||||
if (bit != 0) {
|
||||
unsigned long mask = (1lu << bit) - 1;
|
||||
*bitfield++ &= mask;
|
||||
count -= LONG_BIT - bit;
|
||||
}
|
||||
|
||||
while (count >= LONG_BIT) {
|
||||
*bitfield++ = 0;
|
||||
count -= LONG_BIT;
|
||||
}
|
||||
|
||||
if (count != 0) {
|
||||
unsigned long mask = (1lu << count) - 1;
|
||||
*bitfield &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool bit_tst(const unsigned long *bitfield, usize pos)
|
||||
{
|
||||
usize index = pos / LONG_BIT;
|
||||
unsigned long mask = 1 << (pos % LONG_BIT);
|
||||
return (bitfield[index] & mask) != 0;
|
||||
}
|
||||
|
||||
void bit_set(unsigned long *bitfield, usize pos)
|
||||
{
|
||||
usize index = pos / LONG_BIT;
|
||||
unsigned long mask = 1 << (pos % LONG_BIT);
|
||||
bitfield[index] |= mask;
|
||||
}
|
||||
|
||||
void bit_clr(unsigned long *bitfield, usize pos)
|
||||
{
|
||||
usize index = pos / LONG_BIT;
|
||||
unsigned long mask = 1 << (pos % LONG_BIT);
|
||||
bitfield[index] &= ~mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* This file is part of GayBSD.
|
||||
* Copyright (c) 2021 fef <owo@fef.moe>.
|
||||
*
|
||||
* GayBSD is nonviolent software: you may only use, redistribute, and/or
|
||||
* modify it under the terms of the Cooperative Nonviolent Public License
|
||||
* (CNPL) as found in the LICENSE file in the source code root directory
|
||||
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
|
||||
* of the license, or (at your option) any later version.
|
||||
*
|
||||
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPL for details.
|
||||
*/
|
Loading…
Reference in New Issue