mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
kernel: spinlocks
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
|
||||||
typedef struct slab_t {
|
typedef struct slab_t {
|
||||||
struct slab_t *next;
|
struct slab_t *next;
|
||||||
@@ -13,7 +14,7 @@ typedef struct slab_t {
|
|||||||
} slab_t;
|
} slab_t;
|
||||||
|
|
||||||
typedef struct scache_t {
|
typedef struct scache_t {
|
||||||
// TODO lock
|
spinlock_t lock;
|
||||||
void (*ctor)(struct scache_t *cache, void *obj);
|
void (*ctor)(struct scache_t *cache, void *obj);
|
||||||
void (*dtor)(struct scache_t *cache, void *obj);
|
void (*dtor)(struct scache_t *cache, void *obj);
|
||||||
slab_t *full;
|
slab_t *full;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <arch/context.h>
|
#include <arch/context.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
|
||||||
typedef struct timerentry_t {
|
typedef struct timerentry_t {
|
||||||
struct timerentry_t *next;
|
struct timerentry_t *next;
|
||||||
@@ -12,6 +13,7 @@ typedef struct timerentry_t {
|
|||||||
} timerentry_t;
|
} timerentry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
spinlock_t lock;
|
||||||
time_t ticksperus;
|
time_t ticksperus;
|
||||||
time_t tickcurrent;
|
time_t tickcurrent;
|
||||||
void (*arm)(time_t);
|
void (*arm)(time_t);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define _VMM_H
|
#define _VMM_H
|
||||||
|
|
||||||
#include <arch/mmu.h>
|
#include <arch/mmu.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
|
||||||
#define VMM_FLAGS_PAGESIZE 1
|
#define VMM_FLAGS_PAGESIZE 1
|
||||||
#define VMM_FLAGS_ALLOCATE 2
|
#define VMM_FLAGS_ALLOCATE 2
|
||||||
@@ -29,7 +30,7 @@ typedef struct vmmrange_t{
|
|||||||
} vmmrange_t;
|
} vmmrange_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// TODO lock
|
spinlock_t lock;
|
||||||
struct vmmcache_t *next;
|
struct vmmcache_t *next;
|
||||||
size_t freecount;
|
size_t freecount;
|
||||||
uintmax_t firstfree;
|
uintmax_t firstfree;
|
||||||
@@ -43,6 +44,7 @@ typedef struct vmmcache_t {
|
|||||||
} vmmcache_t;
|
} vmmcache_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
spinlock_t lock;
|
||||||
vmmrange_t *ranges;
|
vmmrange_t *ranges;
|
||||||
void *start;
|
void *start;
|
||||||
void *end;
|
void *end;
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _SPINLOCK_H
|
||||||
|
#define _SPINLOCK_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef int spinlock_t;
|
||||||
|
|
||||||
|
#define SPINLOCK_INIT(x) x = 0;
|
||||||
|
|
||||||
|
static inline void spinlock_acquire(spinlock_t *lock){
|
||||||
|
while(!__sync_bool_compare_and_swap(lock, 0, 1)) asm("pause");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool spinlock_try(spinlock_t *lock){
|
||||||
|
return __sync_bool_compare_and_swap(lock, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void spinlock_release(spinlock_t *lock){
|
||||||
|
*lock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+9
-5
@@ -3,12 +3,14 @@
|
|||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <arch/mmu.h>
|
#include <arch/mmu.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
|
||||||
uintptr_t hhdmbase;
|
uintptr_t hhdmbase;
|
||||||
static size_t memorysize;
|
static size_t memorysize;
|
||||||
static size_t physicalpagecount;
|
static size_t physicalpagecount;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
spinlock_t lock;
|
||||||
uintmax_t base;
|
uintmax_t base;
|
||||||
uintmax_t top;
|
uintmax_t top;
|
||||||
uintmax_t searchstart;
|
uintmax_t searchstart;
|
||||||
@@ -75,11 +77,12 @@ static inline void initsection(int section, uintmax_t base, uintmax_t top) {
|
|||||||
.top = top,
|
.top = top,
|
||||||
.searchstart = base
|
.searchstart = base
|
||||||
};
|
};
|
||||||
|
SPINLOCK_INIT(bmsections[section].lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *pmm_alloc(size_t size, int section) {
|
void *pmm_alloc(size_t size, int section) {
|
||||||
for (int i = section; i >= 0; --i) {
|
for (int i = section; i >= 0; --i) {
|
||||||
// TODO lock section
|
spinlock_acquire(&bmsections[i].lock);
|
||||||
uintmax_t page = getfreearea(&bmsections[i], size);
|
uintmax_t page = getfreearea(&bmsections[i], size);
|
||||||
|
|
||||||
if (page) {
|
if (page) {
|
||||||
@@ -88,10 +91,11 @@ void *pmm_alloc(size_t size, int section) {
|
|||||||
|
|
||||||
for (size_t j = 0; j < size; ++j)
|
for (size_t j = 0; j < size; ++j)
|
||||||
bmset((void *)((page + j) * PAGE_SIZE), 0);
|
bmset((void *)((page + j) * PAGE_SIZE), 0);
|
||||||
// TODO unlock
|
|
||||||
|
spinlock_release(&bmsections[i].lock);
|
||||||
return (void *)(page * PAGE_SIZE);
|
return (void *)(page * PAGE_SIZE);
|
||||||
}
|
}
|
||||||
// TODO unlock section
|
spinlock_release(&bmsections[i].lock);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -101,7 +105,7 @@ void pmm_free(void *addr, size_t size) {
|
|||||||
|
|
||||||
for (int i = 0; i < PMM_SECTION_COUNT; ++i) {
|
for (int i = 0; i < PMM_SECTION_COUNT; ++i) {
|
||||||
if (page >= bmsections[i].base && page < bmsections[i].top) {
|
if (page >= bmsections[i].base && page < bmsections[i].top) {
|
||||||
// TODO lock
|
spinlock_acquire(&bmsections[i].lock);
|
||||||
|
|
||||||
if ((uintptr_t)addr / PAGE_SIZE < bmsections[i].searchstart)
|
if ((uintptr_t)addr / PAGE_SIZE < bmsections[i].searchstart)
|
||||||
bmsections[i].searchstart = (uintptr_t)addr / PAGE_SIZE;
|
bmsections[i].searchstart = (uintptr_t)addr / PAGE_SIZE;
|
||||||
@@ -109,7 +113,7 @@ void pmm_free(void *addr, size_t size) {
|
|||||||
for (uintmax_t j = 0; j < size; ++j)
|
for (uintmax_t j = 0; j < size; ++j)
|
||||||
bmset((void *)((page + j) * PAGE_SIZE), 1);
|
bmset((void *)((page + j) * PAGE_SIZE), 1);
|
||||||
|
|
||||||
// TODO unlock
|
spinlock_release(&bmsections[i].lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ static slab_t *returnobject(scache_t *cache, void *obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *slab_allocate(scache_t *cache) {
|
void *slab_allocate(scache_t *cache) {
|
||||||
// TODO lock
|
spinlock_acquire(&cache->lock);
|
||||||
slab_t *slab = NULL;
|
slab_t *slab = NULL;
|
||||||
if (cache->partial != NULL)
|
if (cache->partial != NULL)
|
||||||
slab = cache->partial;
|
slab = cache->partial;
|
||||||
@@ -170,12 +170,12 @@ void *slab_allocate(scache_t *cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
// TODO unlock
|
spinlock_release(&cache->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void slab_free(scache_t *cache, void *addr) {
|
void slab_free(scache_t *cache, void *addr) {
|
||||||
// TODO lock
|
spinlock_acquire(&cache->lock);
|
||||||
|
|
||||||
slab_t *slab = returnobject(cache, addr);
|
slab_t *slab = returnobject(cache, addr);
|
||||||
__assert(slab);
|
__assert(slab);
|
||||||
@@ -205,8 +205,7 @@ void slab_free(scache_t *cache, void *addr) {
|
|||||||
slab->prev = NULL;
|
slab->prev = NULL;
|
||||||
cache->partial = slab;
|
cache->partial = slab;
|
||||||
}
|
}
|
||||||
|
spinlock_release(&cache->lock);
|
||||||
// TODO unlock
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scache_t *slab_newcache(size_t size, size_t alignment, void (*ctor)(scache_t *, void *), void (*dtor)(scache_t *, void *)) {
|
scache_t *slab_newcache(size_t size, size_t alignment, void (*ctor)(scache_t *, void *), void (*dtor)(scache_t *, void *)) {
|
||||||
@@ -227,6 +226,7 @@ scache_t *slab_newcache(size_t size, size_t alignment, void (*ctor)(scache_t *,
|
|||||||
cache->full = NULL;
|
cache->full = NULL;
|
||||||
cache->empty = NULL;
|
cache->empty = NULL;
|
||||||
cache->partial = NULL;
|
cache->partial = NULL;
|
||||||
|
SPINLOCK_INIT(cache->lock);
|
||||||
|
|
||||||
printf("slab: new cache: size %lu align %lu truesize %lu objcount %lu\n", cache->size, cache->alignment, cache->truesize, cache->slabobjcount);
|
printf("slab: new cache: size %lu align %lu truesize %lu objcount %lu\n", cache->size, cache->alignment, cache->truesize, cache->slabobjcount);
|
||||||
|
|
||||||
@@ -256,13 +256,11 @@ static size_t purge(scache_t *cache, size_t maxcount){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void slab_freecache(scache_t *cache) {
|
void slab_freecache(scache_t *cache) {
|
||||||
// TODO lock
|
spinlock_acquire(&cache->lock);
|
||||||
__assert(cache->partial == NULL);
|
__assert(cache->partial == NULL);
|
||||||
__assert(cache->full == NULL);
|
__assert(cache->full == NULL);
|
||||||
|
|
||||||
purge(cache, (size_t)-1);
|
purge(cache, (size_t)-1);
|
||||||
|
|
||||||
slab_free(&selfcache, cache);
|
slab_free(&selfcache, cache);
|
||||||
|
|
||||||
// TODO unlock
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-11
@@ -9,7 +9,6 @@
|
|||||||
#define RANGE_TOP(x) (void *)((uintptr_t)x->start + x->size)
|
#define RANGE_TOP(x) (void *)((uintptr_t)x->start + x->size)
|
||||||
|
|
||||||
static vmmcache_t *newcache() {
|
static vmmcache_t *newcache() {
|
||||||
// TODO initialize lock
|
|
||||||
vmmcache_t *ptr = pmm_alloc(1, PMM_SECTION_DEFAULT);
|
vmmcache_t *ptr = pmm_alloc(1, PMM_SECTION_DEFAULT);
|
||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -17,6 +16,7 @@ static vmmcache_t *newcache() {
|
|||||||
ptr->header.freecount = VMM_RANGES_PER_CACHE;
|
ptr->header.freecount = VMM_RANGES_PER_CACHE;
|
||||||
ptr->header.firstfree = 0;
|
ptr->header.firstfree = 0;
|
||||||
ptr->header.next = NULL;
|
ptr->header.next = NULL;
|
||||||
|
SPINLOCK_INIT(ptr->header.lock);
|
||||||
|
|
||||||
for (uintmax_t i = 0; i < VMM_RANGES_PER_CACHE; ++i) {
|
for (uintmax_t i = 0; i < VMM_RANGES_PER_CACHE; ++i) {
|
||||||
ptr->ranges[i].size = 0;
|
ptr->ranges[i].size = 0;
|
||||||
@@ -42,23 +42,22 @@ static vmmrange_t *allocrange() {
|
|||||||
vmmcache_t *cache = cachelist;
|
vmmcache_t *cache = cachelist;
|
||||||
vmmrange_t *range = NULL;
|
vmmrange_t *range = NULL;
|
||||||
while (cache) {
|
while (cache) {
|
||||||
// TODO lock
|
spinlock_acquire(&cache->header.lock);
|
||||||
if (cache->header.freecount > 0) {
|
if (cache->header.freecount > 0) {
|
||||||
--cache->header.freecount;
|
--cache->header.freecount;
|
||||||
uintmax_t r = getentrynumber(cache);
|
uintmax_t r = getentrynumber(cache);
|
||||||
cache->header.firstfree = r + 1;
|
cache->header.firstfree = r + 1;
|
||||||
range = &cache->ranges[r];
|
range = &cache->ranges[r];
|
||||||
range->size = -1; // set as allocated temporarily
|
range->size = -1; // set as allocated temporarily
|
||||||
|
spinlock_release(&cache->header.lock);
|
||||||
break;
|
break;
|
||||||
} else if (cache->header.next == NULL)
|
} else if (cache->header.next == NULL)
|
||||||
cache->header.next = newcache();
|
cache->header.next = newcache();
|
||||||
|
|
||||||
cache = cache->header.next;
|
cache = cache->header.next;
|
||||||
// TODO unlock
|
spinlock_release(&cache->header.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO unlock cache
|
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +232,7 @@ bool vmm_pagefault(void *addr, bool user, int actions) {
|
|||||||
if (space == NULL || (space == &kernelspace && user))
|
if (space == NULL || (space == &kernelspace && user))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO lock
|
spinlock_acquire(&space->lock);
|
||||||
vmmrange_t *range = getrange(space, addr);
|
vmmrange_t *range = getrange(space, addr);
|
||||||
|
|
||||||
bool status = false;
|
bool status = false;
|
||||||
@@ -267,7 +266,7 @@ bool vmm_pagefault(void *addr, bool user, int actions) {
|
|||||||
status = true;
|
status = true;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
// TODO unlock
|
spinlock_release(&space->lock);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +287,7 @@ void *vmm_map(void *addr, volatile size_t size, int flags, mmuflags_t mmuflags,
|
|||||||
if (space == NULL)
|
if (space == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// TODO lock space
|
spinlock_acquire(&space->lock);
|
||||||
|
|
||||||
void *start = getfreerange(space, addr, size);
|
void *start = getfreerange(space, addr, size);
|
||||||
void *retaddr = NULL;
|
void *retaddr = NULL;
|
||||||
@@ -345,7 +344,7 @@ void *vmm_map(void *addr, volatile size_t size, int flags, mmuflags_t mmuflags,
|
|||||||
if (start == NULL && range) {
|
if (start == NULL && range) {
|
||||||
// TODO free range
|
// TODO free range
|
||||||
}
|
}
|
||||||
// TODO unlock
|
spinlock_release(&space->lock);
|
||||||
return retaddr;
|
return retaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,11 +362,11 @@ void vmm_unmap(void *addr, size_t size, int flags) {
|
|||||||
if (space == NULL)
|
if (space == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO lock space
|
spinlock_acquire(&space->lock);
|
||||||
|
|
||||||
unmap(space, addr, size);
|
unmap(space, addr, size);
|
||||||
|
|
||||||
// TODO unlock space
|
spinlock_release(&space->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
vmmcontext_t *vmm_newcontext() {
|
vmmcontext_t *vmm_newcontext() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <kernel/interrupt.h>
|
#include <kernel/interrupt.h>
|
||||||
|
|
||||||
void timer_isr(timer_t *timer, context_t *context) {
|
void timer_isr(timer_t *timer, context_t *context) {
|
||||||
// TODO lock
|
spinlock_acquire(&timer->lock);
|
||||||
__assert(timer->queue);
|
__assert(timer->queue);
|
||||||
timer->tickcurrent = timer->queue->absolutetick;
|
timer->tickcurrent = timer->queue->absolutetick;
|
||||||
timerentry_t *oldentry = timer->queue;
|
timerentry_t *oldentry = timer->queue;
|
||||||
@@ -16,13 +16,13 @@ void timer_isr(timer_t *timer, context_t *context) {
|
|||||||
timer->arm(timer->queue->absolutetick - timer->tickcurrent);
|
timer->arm(timer->queue->absolutetick - timer->tickcurrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO unlock
|
spinlock_release(&timer->lock);
|
||||||
oldentry->func(oldentry->private, context);
|
oldentry->func(oldentry->private, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_insert(timer_t *timer, timerentry_t* entry, time_t us) {
|
void timer_insert(timer_t *timer, timerentry_t* entry, time_t us) {
|
||||||
long oldipl = interrupt_setipl(IPL_TIMER);
|
long oldipl = interrupt_setipl(IPL_TIMER);
|
||||||
// TODO lock
|
spinlock_acquire(&timer->lock);
|
||||||
|
|
||||||
timer->tickcurrent += timer->stop(timer);
|
timer->tickcurrent += timer->stop(timer);
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ void timer_insert(timer_t *timer, timerentry_t* entry, time_t us) {
|
|||||||
__assert(timer->queue->absolutetick > timer->tickcurrent);
|
__assert(timer->queue->absolutetick > timer->tickcurrent);
|
||||||
timer->arm(timer->queue->absolutetick - timer->tickcurrent);
|
timer->arm(timer->queue->absolutetick - timer->tickcurrent);
|
||||||
|
|
||||||
// TODO unlock
|
spinlock_release(&timer->lock);
|
||||||
interrupt_setipl(oldipl);
|
interrupt_setipl(oldipl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +68,7 @@ timer_t *timer_new(time_t ticksperus, void (*arm)(time_t), time_t (*stop)()) {
|
|||||||
timer->ticksperus = ticksperus;
|
timer->ticksperus = ticksperus;
|
||||||
timer->arm = arm;
|
timer->arm = arm;
|
||||||
timer->stop = stop;
|
timer->stop = stop;
|
||||||
|
SPINLOCK_INIT(timer->lock);
|
||||||
|
|
||||||
return timer;
|
return timer;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user