mirror of
https://github.com/mmueller41/mxtasking.git
synced 2026-01-21 12:42:57 +01:00
Added bit allocator from NOVA.
This commit is contained in:
61
src/mx/util/atomic.h
Normal file
61
src/mx/util/atomic.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Atomic Operations
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-2011 Udo Steinberg <udo@hypervisor.org>
|
||||||
|
* Economic rights: Technische Universitaet Dresden (Germany)
|
||||||
|
*
|
||||||
|
* This file is part of the NOVA microhypervisor.
|
||||||
|
*
|
||||||
|
* NOVA is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* NOVA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License version 2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
class Atomic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
|
||||||
|
static inline bool cmp_swap (T &ptr, T o, T n) { return __sync_bool_compare_and_swap (&ptr, o, n); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
|
||||||
|
static inline T add (T &ptr, T v) { return __sync_add_and_fetch (&ptr, v); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
|
||||||
|
static inline T sub (T &ptr, T v) { return __sync_sub_and_fetch (&ptr, v); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
|
||||||
|
static inline void set_mask (T &ptr, T v) { __sync_or_and_fetch (&ptr, v); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
|
||||||
|
static inline void clr_mask (T &ptr, T v) { __sync_and_and_fetch (&ptr, ~v); }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline bool test_set_bit (T &val, unsigned long bit)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
asm volatile ("lock; bts %2, %1; setc %0" : "=q" (ret), "+m" (val) : "ir" (bit) : "cc");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline bool test_clr_bit (T &val, unsigned long bit)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
asm volatile ("lock; btr %2, %1; setc %0" : "=q" (ret), "+m" (val) : "ir" (bit) : "cc");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
154
src/mx/util/bit_alloc.h
Normal file
154
src/mx/util/bit_alloc.h
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Bit allocator
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Alexander Boettcher, Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the NOVA microhypervisor.
|
||||||
|
*
|
||||||
|
* NOVA is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* NOVA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License version 2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "bits.h"
|
||||||
|
#include "atomic.h"
|
||||||
|
|
||||||
|
namespace mx::util {
|
||||||
|
template<unsigned C, unsigned INV> class Bit_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned C, unsigned INV>
|
||||||
|
class mx::util::Bit_alloc
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
alignas(64) std::uint64_t bits [C / 8 / sizeof(std::uint64_t)];
|
||||||
|
std::uint64_t last { 0 };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BITS_CNT = sizeof(bits[0]) * 8,
|
||||||
|
MAX = sizeof(bits) / sizeof(bits [0])
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
inline std::uint64_t max() const { return C; }
|
||||||
|
|
||||||
|
|
||||||
|
inline Bit_alloc()
|
||||||
|
{
|
||||||
|
static_assert(MAX*BITS_CNT == C, "bit allocator");
|
||||||
|
static_assert(INV < C, "bit allocator");
|
||||||
|
|
||||||
|
Atomic::test_set_bit(bits[INV / BITS_CNT], INV % BITS_CNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::uint64_t alloc_with_mask(std::uint64_t bitmask[C/8/sizeof(std::uint64_t)], bool inverse = false)
|
||||||
|
{
|
||||||
|
for (std::uint64_t i = ACCESS_ONCE(last), j = 0; j < MAX; i++, j++)
|
||||||
|
{
|
||||||
|
i %= MAX;
|
||||||
|
|
||||||
|
std::uint64_t mask = ~bits[i] & (inverse ? ~bitmask[i] : bitmask[i]);
|
||||||
|
|
||||||
|
if (mask == 0UL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
long b = bit_scan_forward (mask);
|
||||||
|
if (b < 0 || b >= BITS_CNT || Atomic::test_set_bit (bits[i], b)) {
|
||||||
|
j--;
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bits[i] != ~0UL && last != i)
|
||||||
|
last = i;
|
||||||
|
|
||||||
|
return i * BITS_CNT + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return INV;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::uint64_t alloc()
|
||||||
|
{
|
||||||
|
return alloc_with_mask(bits, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void release(std::uint64_t const id)
|
||||||
|
{
|
||||||
|
if (id == INV || id >= C)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::uint64_t i = id / BITS_CNT;
|
||||||
|
std::uint64_t b = id % BITS_CNT;
|
||||||
|
|
||||||
|
while (ACCESS_ONCE(bits[i]) & (1ul << b))
|
||||||
|
Atomic::test_clr_bit (ACCESS_ONCE(bits[i]), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool reserve(std::uint64_t const id)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (id == INV || id >= C)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::uint64_t i = id / BITS_CNT;
|
||||||
|
std::uint64_t b = id % BITS_CNT;
|
||||||
|
|
||||||
|
return Atomic::test_set_bit (ACCESS_ONCE(bits[i]), b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(std::uint64_t const start, std::uint64_t const count)
|
||||||
|
{
|
||||||
|
if (start >= C)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::uint64_t i = start / BITS_CNT;
|
||||||
|
std::uint64_t b = start % BITS_CNT;
|
||||||
|
|
||||||
|
std::uint64_t cnt = count > C ? C : count;
|
||||||
|
if (start + cnt > C)
|
||||||
|
cnt = C - start;
|
||||||
|
|
||||||
|
while (cnt) {
|
||||||
|
std::uint64_t const c = (cnt > BITS_CNT) ? std::uint64_t(BITS_CNT) : cnt;
|
||||||
|
std::uint64_t const bc = (c > (BITS_CNT - b)) ? std::uint64_t(BITS_CNT - b) : c;
|
||||||
|
if (bits[i] != ~0UL) {
|
||||||
|
if (bc >= BITS_CNT) {
|
||||||
|
bits[i] = ~0UL;
|
||||||
|
} else {
|
||||||
|
bits[i] |= ((1ul << bc) - 1) << b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
cnt -= bc;
|
||||||
|
b = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve_with_mask(std::uint64_t const mask, std::uint64_t const offset)
|
||||||
|
{
|
||||||
|
Atomic::set_mask(bits[offset], mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_trace()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MAX; i++)
|
||||||
|
trace(0, "bitmap[%d]: %lx", i, bits[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
14
src/mx/util/bits.old
Normal file
14
src/mx/util/bits.old
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace mx::util {
|
||||||
|
inline long int bit_scan_forward(std::uint64_t val)
|
||||||
|
{
|
||||||
|
if (!val)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
asm volatile("bsf %1, %0" : "=r"(val) : "rm"(val));
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/mx/util/compiler.h
Normal file
26
src/mx/util/compiler.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Compiler Macros
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-2011 Udo Steinberg <udo@hypervisor.org>
|
||||||
|
* Economic rights: Technische Universitaet Dresden (Germany)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2013 Udo Steinberg, Intel Corporation.
|
||||||
|
*
|
||||||
|
* This file is part of the NOVA microhypervisor.
|
||||||
|
*
|
||||||
|
* NOVA is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* NOVA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License version 2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define EXPECT_FALSE(X) __builtin_expect(!!(X), 0)
|
||||||
|
#define EXPECT_TRUE(X) __builtin_expect(!!(X), 1)
|
||||||
|
|
||||||
|
#define ACCESS_ONCE(x) (*static_cast<volatile typeof(x) *>(&(x)))
|
||||||
33
src/mx/util/util.h
Normal file
33
src/mx/util/util.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Utility Functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009-2011 Udo Steinberg <udo@hypervisor.org>
|
||||||
|
* Economic rights: Technische Universitaet Dresden (Germany)
|
||||||
|
*
|
||||||
|
* This file is part of the NOVA microhypervisor.
|
||||||
|
*
|
||||||
|
* NOVA is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* NOVA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License version 2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline T min (T v1, T v2)
|
||||||
|
{
|
||||||
|
return v1 < v2 ? v1 : v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline T max (T v1, T v2)
|
||||||
|
{
|
||||||
|
return v1 > v2 ? v1 : v2;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user