Compare commits
2 Commits
4a20a5b0af
...
8f0c73f4dc
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f0c73f4dc | |||
| 91b035c2a2 |
@@ -1,6 +1,7 @@
|
|||||||
# Freestanding libc functions that are needed in the kernel
|
# Freestanding libc functions that are needed in the kernel
|
||||||
|
|
||||||
kernel_sources += files(
|
kernel_sources += files(
|
||||||
|
'runtime.c',
|
||||||
'stdlib.c',
|
'stdlib.c',
|
||||||
'string.c',
|
'string.c',
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
// Compiler runtime support like libgcc or compiler-rt.
|
||||||
|
// Extend as required.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint64_t __udivdi3(uint64_t dividend, uint64_t divisor) {
|
||||||
|
if (divisor == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (dividend < divisor)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned shift = __builtin_clzll(divisor) - __builtin_clzll(dividend);
|
||||||
|
|
||||||
|
divisor <<= shift;
|
||||||
|
|
||||||
|
uint64_t quotient = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (dividend >= divisor) {
|
||||||
|
dividend -= divisor;
|
||||||
|
quotient |= (uint64_t)1 << shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shift == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
shift--;
|
||||||
|
divisor >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned clz128(__uint128_t value) {
|
||||||
|
uint64_t high = (uint64_t)(value >> 64);
|
||||||
|
|
||||||
|
if (high != 0)
|
||||||
|
return (unsigned)__builtin_clzll(high);
|
||||||
|
|
||||||
|
return 64 + (unsigned)__builtin_clzll((uint64_t)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
__uint128_t __udivmodti4(__uint128_t dividend, __uint128_t divisor, __uint128_t* remainder) {
|
||||||
|
if (divisor == 0) {
|
||||||
|
if (remainder)
|
||||||
|
*remainder = dividend;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dividend < divisor) {
|
||||||
|
if (remainder)
|
||||||
|
*remainder = dividend;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned shift = clz128(divisor) - clz128(dividend);
|
||||||
|
|
||||||
|
divisor <<= shift;
|
||||||
|
|
||||||
|
__uint128_t quotient = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (dividend >= divisor) {
|
||||||
|
dividend -= divisor;
|
||||||
|
quotient |= (__uint128_t)1 << shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shift == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
shift--;
|
||||||
|
divisor >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainder)
|
||||||
|
*remainder = dividend;
|
||||||
|
|
||||||
|
return quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
__uint128_t __udivti3(__uint128_t dividend, __uint128_t divisor) {
|
||||||
|
return __udivmodti4(dividend, divisor, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
__uint128_t __umodti3(__uint128_t dividend, __uint128_t divisor) {
|
||||||
|
__uint128_t remainder;
|
||||||
|
|
||||||
|
__udivmodti4(dividend, divisor, &remainder);
|
||||||
|
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ kernel_sources += files(
|
|||||||
'panic.c',
|
'panic.c',
|
||||||
'percpu.c',
|
'percpu.c',
|
||||||
'print.c',
|
'print.c',
|
||||||
'refcount.c',
|
|
||||||
'spin.c',
|
'spin.c',
|
||||||
'wait.c',
|
'wait.c',
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#include <zinnia/refcount.h>
|
|
||||||
#include <stdatomic.h>
|
|
||||||
|
|
||||||
void refcount_init(struct refcount* rc) {
|
|
||||||
atomic_store_explicit(&rc->count, 1, memory_order_relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void refcount_inc(struct refcount* rc) {
|
|
||||||
atomic_fetch_add_explicit(&rc->count, 1, memory_order_relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool refcount_dec(struct refcount* rc) {
|
|
||||||
if (atomic_fetch_sub_explicit(&rc->count, 1, memory_order_release) != 1)
|
|
||||||
return false;
|
|
||||||
atomic_thread_fence(memory_order_acquire);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,17 @@ struct refcount {
|
|||||||
_Atomic(size_t) count;
|
_Atomic(size_t) count;
|
||||||
};
|
};
|
||||||
|
|
||||||
void refcount_init(struct refcount* rc);
|
static inline void refcount_init(struct refcount* rc) {
|
||||||
void refcount_inc(struct refcount* rc);
|
atomic_store_explicit(&rc->count, 1, memory_order_relaxed);
|
||||||
bool refcount_dec(struct refcount* rc);
|
}
|
||||||
|
|
||||||
|
static inline void refcount_inc(struct refcount* rc) {
|
||||||
|
atomic_fetch_add_explicit(&rc->count, 1, memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool refcount_dec(struct refcount* rc) {
|
||||||
|
if (atomic_fetch_sub_explicit(&rc->count, 1, memory_order_release) != 1)
|
||||||
|
return false;
|
||||||
|
atomic_thread_fence(memory_order_acquire);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,8 +74,6 @@ kernel_c_args = ['-DIN_KERNEL']
|
|||||||
|
|
||||||
kernel_lds = meson.current_source_dir() / 'boot' / 'kernel.ld'
|
kernel_lds = meson.current_source_dir() / 'boot' / 'kernel.ld'
|
||||||
kernel_link_args = [
|
kernel_link_args = [
|
||||||
'-lgcc',
|
|
||||||
'-static-libgcc',
|
|
||||||
'-T' + kernel_lds,
|
'-T' + kernel_lds,
|
||||||
'-Wl,--export-dynamic',
|
'-Wl,--export-dynamic',
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user