mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
semaphores
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#ifndef _SMP_H_INCLUDE
|
||||
#define _SMP_H_INCLUDE
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void smp_init();
|
||||
|
||||
#define IPI_CPU_ALLBUTSELF 3
|
||||
@@ -9,7 +11,7 @@ void smp_init();
|
||||
#define IPI_CPU_TARGET 0
|
||||
|
||||
void arch_smp_sendipi(int cpu, int vector, int mode);
|
||||
|
||||
size_t arch_smp_cpucount();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -137,7 +137,6 @@ asmisr_panic:
|
||||
except asmisr_pagefault, isr_pagefault
|
||||
isr asmisr_general, isr_general
|
||||
except asmisr_except, isr_except
|
||||
isr asmisr_schedtimer, isr_schedtimer
|
||||
isr asmisr_lapicnmi, isr_lapicnmi
|
||||
isr asmisr_mmuinval, isr_mmuinval
|
||||
isr asmisr_timer, isr_timer
|
||||
|
||||
@@ -3,13 +3,6 @@
|
||||
#include <kernel/vmm.h>
|
||||
#include <arch/apic.h>
|
||||
|
||||
void isr_schedtimer(arch_regs *reg){
|
||||
printf("schedtimer irq\n");
|
||||
|
||||
apic_eoi();
|
||||
|
||||
}
|
||||
|
||||
void isr_general(arch_regs *reg){
|
||||
_panic("Unhandled interrupt", reg);
|
||||
asm("hlt");
|
||||
@@ -33,8 +26,9 @@ void isr_lapicnmi(){
|
||||
|
||||
void isr_mmuinval(){
|
||||
arch_mmu_invalidateipi();
|
||||
apic_eoi();
|
||||
}
|
||||
|
||||
void isr_timer(arch_regs* reg){
|
||||
|
||||
apic_eoi();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <arch/cls.h>
|
||||
#include <arch/idt.h>
|
||||
#include <arch/smp.h>
|
||||
#include <kernel/semaphore.h>
|
||||
|
||||
volatile struct limine_kernel_address_request kaddrreq = {
|
||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||
@@ -29,20 +30,23 @@ static void switchcontext(arch_mmu_tableptr context){
|
||||
asm("mov %%rax, %%cr3" : : "a"(context));
|
||||
}
|
||||
|
||||
// FIXME add a semaphore here
|
||||
|
||||
// XXX only do this on an unmap or other specific situations
|
||||
|
||||
void* inv = NULL;
|
||||
|
||||
semaphore_t sem;
|
||||
|
||||
void arch_mmu_invalidateipi(){
|
||||
asm("invlpg (%%rax)" : : "a"(inv));
|
||||
sem_signal(&sem);
|
||||
}
|
||||
|
||||
static void invalidate(void* addr){
|
||||
asm("invlpg (%%rax)" : : "a"(addr));
|
||||
sem.count = -arch_smp_cpucount();
|
||||
if(!sem.count) return;
|
||||
sem.count += 2;
|
||||
inv = addr;
|
||||
arch_smp_sendipi(0, VECTOR_MMUINVAL, IPI_CPU_ALLBUTSELF);
|
||||
while(!sem_tryacquire(&sem));
|
||||
}
|
||||
|
||||
|
||||
@@ -145,8 +149,6 @@ int arch_mmu_map(arch_mmu_tableptr context, void* paddr, void* vaddr, size_t fla
|
||||
int ret = setpage(context, vaddr, entry);
|
||||
|
||||
|
||||
if(ret) invalidate(vaddr);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
@@ -156,6 +158,7 @@ void arch_mmu_unmap(arch_mmu_tableptr context, void* vaddr){
|
||||
if(!getmapping(context, vaddr)) return;
|
||||
|
||||
arch_mmu_map(context, 0, vaddr, 0);
|
||||
invalidate(vaddr);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+15
-5
@@ -10,13 +10,12 @@
|
||||
#include <arch/mmu.h>
|
||||
#include <arch/apic.h>
|
||||
#include <kernel/pmm.h>
|
||||
#include <kernel/semaphore.h>
|
||||
|
||||
cls_t* apcls;
|
||||
static cls_t* apcls;
|
||||
static semaphore_t* sem;
|
||||
|
||||
|
||||
size_t oncpucount = 1;
|
||||
static int lock = 0;
|
||||
static size_t cpucount = 1;
|
||||
static size_t cpucount = 0;
|
||||
|
||||
static void apstartup(struct limine_smp_info *info){
|
||||
|
||||
@@ -31,11 +30,17 @@ static void apstartup(struct limine_smp_info *info){
|
||||
apic_lapicinit();
|
||||
|
||||
printf("CPU %lu ready!\n", info->lapic_id);
|
||||
|
||||
sem_signal(sem);
|
||||
|
||||
for(;;) asm("hlt");
|
||||
|
||||
}
|
||||
|
||||
size_t arch_smp_cpucount(){
|
||||
return cpucount;
|
||||
}
|
||||
|
||||
void arch_smp_sendipi(int processor, int vector, int mode){
|
||||
apic_sendipi(processor, vector, mode, 0, 1);
|
||||
}
|
||||
@@ -59,6 +64,8 @@ void smp_init(){
|
||||
|
||||
printf("System has %lu CPUs\n", cpucount);
|
||||
|
||||
sem = sem_init(-cpucount + 2, 0);
|
||||
|
||||
for(size_t i = 0; i < cpucount; ++i){
|
||||
if(cpus[i]->lapic_id == r->bsp_lapic_id) continue;
|
||||
printf("Dispatching CPU %lu\n", i);
|
||||
@@ -69,4 +76,7 @@ void smp_init(){
|
||||
: "b"(&cpus[i]->goto_address), "a"(apstartup));
|
||||
}
|
||||
|
||||
while(!sem_tryacquire(sem)) asm volatile("pause");
|
||||
|
||||
printf("All processors ready!\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifndef _SEMAPHORE_H_INCLUDE
|
||||
#define _SEMAPHORE_H_INCLUDE
|
||||
|
||||
#include <kernel/sched.h>
|
||||
#include <kernel/alloc.h>
|
||||
#include <arch/spinlock.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct{
|
||||
thread_t** waitingthreads;
|
||||
int lock, count, threadcount;
|
||||
} semaphore_t;
|
||||
|
||||
|
||||
// a thread count of 0 will be a blockless semaphore
|
||||
|
||||
static semaphore_t* sem_init(size_t count, size_t threadptrcount){
|
||||
|
||||
semaphore_t* semaphore = alloc(sizeof(semaphore_t));
|
||||
if(!semaphore) return NULL;
|
||||
|
||||
if(threadptrcount){
|
||||
semaphore->waitingthreads = alloc(sizeof(thread_t*) * threadptrcount);
|
||||
semaphore->threadcount = threadptrcount;
|
||||
}
|
||||
|
||||
semaphore->count = count;
|
||||
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
static bool sem_tryacquire(semaphore_t* sem){
|
||||
|
||||
spinlock_acquire(&sem->lock);
|
||||
|
||||
bool res = (sem->count > 0);
|
||||
|
||||
if(res)
|
||||
--sem->count;
|
||||
|
||||
|
||||
spinlock_release(&sem->lock);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
static void sem_wait(semaphore_t* sem){
|
||||
|
||||
|
||||
spinlock_acquire(&sem->lock);
|
||||
|
||||
--sem->count;
|
||||
|
||||
if(sem->count < 0 && sem->threadcount > 0){
|
||||
// TODO block
|
||||
}
|
||||
else if(sem->threadcount == 0){
|
||||
_panic("sem_wait with threadcount 0", 0);
|
||||
}
|
||||
|
||||
spinlock_release(&sem->lock);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void sem_signal(semaphore_t* sem){
|
||||
|
||||
|
||||
spinlock_acquire(&sem->lock);
|
||||
|
||||
++sem->count;
|
||||
|
||||
if(sem->count <= 0 && sem->threadcount > 0){
|
||||
//TODO run a thread
|
||||
}
|
||||
|
||||
spinlock_release(&sem->lock);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user