feat: initial locking etc.
This commit is contained in:
@@ -85,6 +85,8 @@ void print(const char *arg) {
|
|||||||
print_bootinfo();
|
print_bootinfo();
|
||||||
} else if (strcmp(arg, "pci") == 0) {
|
} else if (strcmp(arg, "pci") == 0) {
|
||||||
pci_print_info();
|
pci_print_info();
|
||||||
|
} else if (strcmp(arg, "pci_caps") == 0) {
|
||||||
|
pci_dump_caps();
|
||||||
} else if (strcmp(arg, "ide") == 0) {
|
} else if (strcmp(arg, "ide") == 0) {
|
||||||
ide_print_devices();
|
ide_print_devices();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -12,10 +12,17 @@ void syscall_handle(isr_registers_t *registers) {
|
|||||||
task_start_first();
|
task_start_first();
|
||||||
break;
|
break;
|
||||||
case SYSCALL_YIELD_JOB:
|
case SYSCALL_YIELD_JOB:
|
||||||
|
task_ensure_enabled();
|
||||||
task_switch_next();
|
task_switch_next();
|
||||||
break;
|
break;
|
||||||
case SYSCALL_YIELD_IRQ:
|
case SYSCALL_YIELD_IRQ:
|
||||||
|
task_ensure_enabled();
|
||||||
task_wait_irq(registers->ebx);
|
task_wait_irq(registers->ebx);
|
||||||
|
break;
|
||||||
|
case SYSCALL_SUSPEND:
|
||||||
|
task_ensure_enabled();
|
||||||
|
task_suspend();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <libc/kprintf.h>
|
#include <libc/kprintf.h>
|
||||||
#include <fs/blockdev.h>
|
#include <fs/blockdev.h>
|
||||||
#include <mem/malloc.h>
|
#include <mem/malloc.h>
|
||||||
|
#include <tasks/locking.h>
|
||||||
|
|
||||||
#define ATA_SR_BSY 0x80 // Busy
|
#define ATA_SR_BSY 0x80 // Busy
|
||||||
#define ATA_SR_DRDY 0x40 // Drive ready
|
#define ATA_SR_DRDY 0x40 // Drive ready
|
||||||
@@ -135,6 +136,8 @@ typedef struct {
|
|||||||
uint8_t print_error: 1;
|
uint8_t print_error: 1;
|
||||||
} ide_block_device_info;
|
} ide_block_device_info;
|
||||||
|
|
||||||
|
mutex_t *ide_lock = NULL;
|
||||||
|
|
||||||
uint8_t ide_read(uint8_t channel, uint8_t reg);
|
uint8_t ide_read(uint8_t channel, uint8_t reg);
|
||||||
|
|
||||||
void ide_write(uint8_t channel, uint8_t reg, uint8_t data);
|
void ide_write(uint8_t channel, uint8_t reg, uint8_t data);
|
||||||
@@ -437,6 +440,12 @@ uint8_t ide_pci_initialize(pci_device *device) {
|
|||||||
return PCI_INIT_FAIL;
|
return PCI_INIT_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ide_lock != NULL) {
|
||||||
|
k_panics("IDE already initialized\n");
|
||||||
|
}
|
||||||
|
ide_lock = mutex_create();
|
||||||
|
mutex_acquire(ide_lock);
|
||||||
|
|
||||||
// disable IRQ
|
// disable IRQ
|
||||||
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
|
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
|
||||||
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
|
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
|
||||||
@@ -518,6 +527,7 @@ uint8_t ide_pci_initialize(pci_device *device) {
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mutex_release(ide_lock);
|
||||||
ide_register_block_devices();
|
ide_register_block_devices();
|
||||||
|
|
||||||
return PCI_INIT_OK;
|
return PCI_INIT_OK;
|
||||||
@@ -673,5 +683,8 @@ uint8_t ide_access(uint8_t direction, uint8_t drive, uint32_t lba, uint8_t numse
|
|||||||
|| ide_devices[drive].type == IDE_ATAPI) {
|
|| ide_devices[drive].type == IDE_ATAPI) {
|
||||||
return 0xF1;
|
return 0xF1;
|
||||||
}
|
}
|
||||||
return ide_read_ata_access(direction, drive, lba, numsects, target);
|
mutex_acquire(ide_lock);
|
||||||
|
uint8_t result = ide_read_ata_access(direction, drive, lba, numsects, target);
|
||||||
|
mutex_release(ide_lock);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,22 @@ void pci_config_write_byte(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offs
|
|||||||
port_byte_out(PORT_PCI_CONFIG_DATA, value);
|
port_byte_out(PORT_PCI_CONFIG_DATA, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pci_command_register_t pci_get_config(pci_device *device) {
|
||||||
|
pci_command_register_t status;
|
||||||
|
status.value = pci_config_read_word(device->bus, device->slot, device->func, PCI_CONFIG_COMMAND);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pci_set_status(pci_device *device, pci_status_register_t status) {
|
||||||
|
pci_config_write_word(device->bus, device->slot, device->func, PCI_CONFIG_STATUS, status.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_status_register_t pci_get_status(pci_device *device) {
|
||||||
|
pci_status_register_t status;
|
||||||
|
status.value = pci_config_read_word(device->bus, device->slot, device->func, PCI_CONFIG_STATUS);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t pci_get_vendor_id(uint8_t bus, uint8_t slot, uint8_t func) {
|
uint16_t pci_get_vendor_id(uint8_t bus, uint8_t slot, uint8_t func) {
|
||||||
return pci_config_read_word(bus, slot, func, PCI_CONFIG_VENDOR_ID);
|
return pci_config_read_word(bus, slot, func, PCI_CONFIG_VENDOR_ID);
|
||||||
}
|
}
|
||||||
@@ -193,6 +209,31 @@ void pci_print_info() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pci_dump_caps_internal(pci_device *device) {
|
||||||
|
if (pci_devices->headerType >= 0x02) {
|
||||||
|
printf("\tNot supported for PCI-to-CardBus bridge\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!pci_get_status(device).status.capabilities_list) {
|
||||||
|
printf("\tNo caps\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t cap_ptr = pci_config_read_byte(device->bus, device->slot, device->func, PCI_CONFIG_CAP_POINTER);
|
||||||
|
printf("\t%x\n", cap_ptr);
|
||||||
|
// todo traverse
|
||||||
|
}
|
||||||
|
|
||||||
|
void pci_dump_caps() {
|
||||||
|
for (int i = 0; i < last_pci_device_index; ++i) {
|
||||||
|
printf("PCI BSF: %2x/%2x/%2x, CSI: %2x/%2x/%2x, V/D: %4x/%4x, driver: %s\n",
|
||||||
|
pci_devices[i].bus, pci_devices[i].slot, pci_devices[i].func,
|
||||||
|
pci_devices[i].class, pci_devices[i].subclass, pci_devices[i].programInterface,
|
||||||
|
pci_devices[i].vendorId, pci_devices[i].deviceId,
|
||||||
|
(pci_devices[i].pci_driver == NULL ? "none" : pci_devices[i].pci_driver->name));
|
||||||
|
pci_dump_caps_internal(&pci_devices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pci_init_bar(pci_device *device, uint8_t bar_index) {
|
void pci_init_bar(pci_device *device, uint8_t bar_index) {
|
||||||
if (device->headerType != 0x00) {
|
if (device->headerType != 0x00) {
|
||||||
k_panics("Only header 0x00 supported for now");
|
k_panics("Only header 0x00 supported for now");
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#define NEW_KERNEL_PCI_H
|
#define NEW_KERNEL_PCI_H
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
#define PCI_CLASS_MASS_STORAGE 0x01
|
#define PCI_CLASS_MASS_STORAGE 0x01
|
||||||
|
|
||||||
@@ -130,8 +132,47 @@ typedef struct pci_device {
|
|||||||
} driver_state;
|
} driver_state;
|
||||||
} pci_device;
|
} pci_device;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint16_t value;
|
||||||
|
struct {
|
||||||
|
bool io_space: 1;
|
||||||
|
bool mem_space: 1;
|
||||||
|
bool bus_master: 1;
|
||||||
|
bool special_cycles: 1;
|
||||||
|
bool mem_write_invalidate_enable: 1;
|
||||||
|
bool vga_palette_snoop: 1;
|
||||||
|
bool parity_error_response: 1;
|
||||||
|
uint8_t reserved: 1;
|
||||||
|
bool serr_enable: 1;
|
||||||
|
bool fast_b2b_enable: 1;
|
||||||
|
bool interrupt_disable: 1;
|
||||||
|
uint8_t reserved2: 5;
|
||||||
|
} packed command;
|
||||||
|
} pci_command_register_t;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint16_t value;
|
||||||
|
struct {
|
||||||
|
uint8_t reserved: 3;
|
||||||
|
bool interrupt_status: 1;
|
||||||
|
bool capabilities_list: 1;
|
||||||
|
bool speed_66mhz_capable: 1;
|
||||||
|
uint8_t reserved2: 1;
|
||||||
|
bool fast_b2b_capable: 1;
|
||||||
|
bool master_data_parity_error: 1;
|
||||||
|
uint8_t devsel_timing: 2;
|
||||||
|
bool signaled_target_abort: 1;
|
||||||
|
bool received_target_abort: 1;
|
||||||
|
bool received_master_abort: 1;
|
||||||
|
bool signaled_system_error: 1;
|
||||||
|
bool detected_parity_error: 1;
|
||||||
|
} packed status;
|
||||||
|
} pci_status_register_t;
|
||||||
|
|
||||||
void pci_print_info();
|
void pci_print_info();
|
||||||
|
|
||||||
|
void pci_dump_caps();
|
||||||
|
|
||||||
uint32_t pci_register_driver(const pci_driver *pci_driver);
|
uint32_t pci_register_driver(const pci_driver *pci_driver);
|
||||||
|
|
||||||
void pci_sort_drivers();
|
void pci_sort_drivers();
|
||||||
|
|||||||
@@ -70,13 +70,29 @@ int print_char(char character, int col, int row, char attributes) {
|
|||||||
offset = get_cursor_offset();
|
offset = get_cursor_offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (character == '\n') {
|
switch (character) {
|
||||||
|
case '\n':
|
||||||
|
row = get_offset_row(offset);
|
||||||
|
offset = get_offset(0, row + 1);
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
col = (col + 4) & (~0b11);
|
||||||
|
if (col > VGA_COL_MAX) {
|
||||||
row = get_offset_row(offset);
|
row = get_offset_row(offset);
|
||||||
offset = get_offset(0, row + 1);
|
offset = get_offset(0, row + 1);
|
||||||
} else {
|
} else {
|
||||||
|
offset = get_offset(col, row);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
row = get_offset_row(offset);
|
||||||
|
offset = get_offset(0, row);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
_vga_character_memory[offset] = character;
|
_vga_character_memory[offset] = character;
|
||||||
_vga_character_memory[offset + 1] = attributes;
|
_vga_character_memory[offset + 1] = attributes;
|
||||||
offset += 2;
|
offset += 2;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset >= (VGA_COL_MAX * 2 * VGA_ROW_MAX)) {
|
if (offset >= (VGA_COL_MAX * 2 * VGA_ROW_MAX)) {
|
||||||
|
|||||||
@@ -30,3 +30,7 @@ void syscall_yield_job() {
|
|||||||
void syscall_yield_irq(uint16_t irq) {
|
void syscall_yield_irq(uint16_t irq) {
|
||||||
syscall2(SYSCALL_YIELD_IRQ, irq );
|
syscall2(SYSCALL_YIELD_IRQ, irq );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void syscall_job_suspend() {
|
||||||
|
syscall1(SYSCALL_SUSPEND);
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#define SYSCALL_START_SCHEDULER 0x01
|
#define SYSCALL_START_SCHEDULER 0x01
|
||||||
#define SYSCALL_YIELD_JOB 0x02
|
#define SYSCALL_YIELD_JOB 0x02
|
||||||
#define SYSCALL_YIELD_IRQ 0x03
|
#define SYSCALL_YIELD_IRQ 0x03
|
||||||
|
#define SYSCALL_SUSPEND 0x04
|
||||||
|
|
||||||
void noreturn syscall_start_scheduler();
|
void noreturn syscall_start_scheduler();
|
||||||
|
|
||||||
@@ -17,4 +18,6 @@ void syscall_yield_job();
|
|||||||
|
|
||||||
void syscall_yield_irq(uint16_t irq);
|
void syscall_yield_irq(uint16_t irq);
|
||||||
|
|
||||||
|
void syscall_job_suspend();
|
||||||
|
|
||||||
#endif //NEW_KERNEL_SYSCALL_H
|
#endif //NEW_KERNEL_SYSCALL_H
|
||||||
|
|||||||
58
kernel/mem/paging.c
Normal file
58
kernel/mem/paging.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 21-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "paging.h"
|
||||||
|
#include <types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
|
#define TABLE_ADDR_MASK 0xFFFFF000
|
||||||
|
#define DIRECTORY_SIZE 1024
|
||||||
|
|
||||||
|
const uint32_t x = TABLE_ADDR_MASK;
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
bool present: 1;
|
||||||
|
bool read_write: 1;
|
||||||
|
bool user_mode: 1;
|
||||||
|
bool write_through: 1;
|
||||||
|
bool cache_disabled: 1;
|
||||||
|
bool accessed: 1;
|
||||||
|
char ignored: 1;
|
||||||
|
bool page_size: 1;
|
||||||
|
bool global: 1; // ignored
|
||||||
|
uint8_t avail: 3;
|
||||||
|
} packed;
|
||||||
|
uint32_t addr;
|
||||||
|
};
|
||||||
|
} packed page_directory_entry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
bool present: 1;
|
||||||
|
bool read_write: 1;
|
||||||
|
bool user_supervisor: 1;
|
||||||
|
bool write_through: 1;
|
||||||
|
bool cache_disabled: 1;
|
||||||
|
bool accessed: 1;
|
||||||
|
bool dirty: 1;
|
||||||
|
char ignored: 1;
|
||||||
|
bool global: 1;
|
||||||
|
uint8_t available: 3;
|
||||||
|
} packed;
|
||||||
|
uint32_t addr;
|
||||||
|
};
|
||||||
|
} packed page_table_entry;
|
||||||
|
|
||||||
|
page_directory_entry page_directory[DIRECTORY_SIZE] at_aligned(4096);
|
||||||
|
|
||||||
|
void page_pre_init() {
|
||||||
|
for (int i = 0; i < DIRECTORY_SIZE; ++i) {
|
||||||
|
page_directory[i].read_write = true;
|
||||||
|
page_directory[i].user_mode = false;
|
||||||
|
page_directory[i].present = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
kernel/mem/paging.h
Normal file
8
kernel/mem/paging.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 21-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_PAGING_H
|
||||||
|
#define NEW_KERNEL_PAGING_H
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_PAGING_H
|
||||||
@@ -3,3 +3,136 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
|
#include <mem/malloc.h>
|
||||||
|
#include <tasks/task.h>
|
||||||
|
#include <libk/syscall.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <libc/kprintf.h>
|
||||||
|
|
||||||
|
typedef struct lock_fifo_entry {
|
||||||
|
uint32_t tid;
|
||||||
|
struct lock_fifo_entry *next;
|
||||||
|
} lock_fifo_entry_t;
|
||||||
|
|
||||||
|
struct semaphore {
|
||||||
|
volatile int32_t value;
|
||||||
|
lock_fifo_entry_t *first_wait;
|
||||||
|
lock_fifo_entry_t *last_wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mutex {
|
||||||
|
volatile bool value;
|
||||||
|
lock_fifo_entry_t *first_wait;
|
||||||
|
lock_fifo_entry_t *last_wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spinlock {
|
||||||
|
volatile uint32_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
semaphore_t *semaphore_create() {
|
||||||
|
semaphore_t *semaphore = malloc(sizeof(semaphore_t));
|
||||||
|
semaphore->value = 1;
|
||||||
|
return semaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
void semaphore_wait(semaphore_t *semaphore) {
|
||||||
|
if (__sync_sub_and_fetch(&semaphore->value, 1) == 0) {
|
||||||
|
return; // first to lock
|
||||||
|
}
|
||||||
|
task_lock_acquire();
|
||||||
|
lock_fifo_entry_t *lock = malloc(sizeof(lock_fifo_entry_t));
|
||||||
|
lock->tid = task_get_current_tid();
|
||||||
|
if (semaphore->first_wait == NULL) {
|
||||||
|
semaphore->first_wait = lock;
|
||||||
|
} else {
|
||||||
|
semaphore->last_wait->next = lock;
|
||||||
|
}
|
||||||
|
semaphore->last_wait = lock;
|
||||||
|
task_lock_free();
|
||||||
|
syscall_job_suspend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void semaphore_signal(semaphore_t *semaphore) {
|
||||||
|
if (__sync_add_and_fetch(&semaphore->value, 1) == 1) {
|
||||||
|
return; // last in queue
|
||||||
|
}
|
||||||
|
task_lock_acquire();
|
||||||
|
task_signal(semaphore->first_wait->tid);
|
||||||
|
lock_fifo_entry_t *first_entry = semaphore->first_wait;
|
||||||
|
semaphore->first_wait = first_entry->next;
|
||||||
|
free(first_entry);
|
||||||
|
task_lock_free();
|
||||||
|
}
|
||||||
|
|
||||||
|
void semaphore_free(semaphore_t *semaphore) {
|
||||||
|
if (semaphore->value < 1) {
|
||||||
|
printf("WARN: freeing semaphore which still has a task waiting\n");
|
||||||
|
}
|
||||||
|
free(semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_t *mutex_create() {
|
||||||
|
mutex_t *mutex = malloc(sizeof(mutex_t));
|
||||||
|
mutex->value = 1;
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_acquire(mutex_t *mutex) {
|
||||||
|
if (__sync_bool_compare_and_swap(&mutex->value, true, false) == true) {
|
||||||
|
return; // first one to lock
|
||||||
|
}
|
||||||
|
task_lock_acquire();
|
||||||
|
lock_fifo_entry_t *lock = malloc(sizeof(lock_fifo_entry_t));
|
||||||
|
lock->tid = task_get_current_tid();
|
||||||
|
if (mutex->first_wait == NULL) {
|
||||||
|
mutex->first_wait = lock;
|
||||||
|
} else {
|
||||||
|
mutex->last_wait->next = lock;
|
||||||
|
}
|
||||||
|
mutex->last_wait = lock;
|
||||||
|
task_lock_free();
|
||||||
|
syscall_job_suspend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_release(mutex_t *mutex) {
|
||||||
|
task_lock_acquire();
|
||||||
|
if (mutex->first_wait == NULL) {
|
||||||
|
mutex->value = true;
|
||||||
|
task_lock_free();
|
||||||
|
return; // no one left
|
||||||
|
}
|
||||||
|
lock_fifo_entry_t *entry = mutex->first_wait;
|
||||||
|
task_signal(entry->tid);
|
||||||
|
mutex->first_wait = entry->next;
|
||||||
|
free(entry);
|
||||||
|
task_lock_free();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_free(mutex_t *mutex) {
|
||||||
|
if (mutex->value != true) {
|
||||||
|
printf("WARN: freeing mutex which still has a task waiting\n");
|
||||||
|
}
|
||||||
|
free(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_t *spinlock_create() {
|
||||||
|
return malloc(sizeof(spinlock_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void spinlock_acquire(spinlock_t *spinlock) {
|
||||||
|
while (!__sync_bool_compare_and_swap(&spinlock->lock, false, true));
|
||||||
|
__sync_synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spinlock_release(spinlock_t *spinlock) {
|
||||||
|
__sync_synchronize();
|
||||||
|
spinlock->lock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spinlock_free(spinlock_t *spinlock) {
|
||||||
|
if (spinlock->lock != false) {
|
||||||
|
printf("WARN: freeing spinlock which is still spinning\n");
|
||||||
|
}
|
||||||
|
free(spinlock);
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,4 +5,36 @@
|
|||||||
#ifndef NEW_KERNEL_LOCKING_H
|
#ifndef NEW_KERNEL_LOCKING_H
|
||||||
#define NEW_KERNEL_LOCKING_H
|
#define NEW_KERNEL_LOCKING_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct semaphore semaphore_t;
|
||||||
|
|
||||||
|
typedef struct mutex mutex_t;
|
||||||
|
|
||||||
|
typedef struct spinlock spinlock_t;
|
||||||
|
|
||||||
|
semaphore_t *semaphore_create();
|
||||||
|
|
||||||
|
void semaphore_wait(semaphore_t *semaphore);
|
||||||
|
|
||||||
|
void semaphore_signal(semaphore_t *semaphore);
|
||||||
|
|
||||||
|
void semaphore_free(semaphore_t *semaphore);
|
||||||
|
|
||||||
|
mutex_t *mutex_create();
|
||||||
|
|
||||||
|
void mutex_acquire(mutex_t *mutex);
|
||||||
|
|
||||||
|
void mutex_release(mutex_t *mutex);
|
||||||
|
|
||||||
|
void mutex_free(mutex_t *mutex);
|
||||||
|
|
||||||
|
spinlock_t *spinlock_create();
|
||||||
|
|
||||||
|
void spinlock_acquire(spinlock_t *spinlock);
|
||||||
|
|
||||||
|
void spinlock_release(spinlock_t *spinlock);
|
||||||
|
|
||||||
|
void spinlock_free(spinlock_t *spinlock);
|
||||||
|
|
||||||
#endif //NEW_KERNEL_LOCKING_H
|
#endif //NEW_KERNEL_LOCKING_H
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <mem/pmm.h>
|
#include <mem/pmm.h>
|
||||||
|
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
|
#include <libk/libk.h>
|
||||||
|
|
||||||
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
|
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
|
||||||
|
|
||||||
@@ -17,7 +18,9 @@
|
|||||||
#define TASK_STATE_RUNNABLE (1 << 0)
|
#define TASK_STATE_RUNNABLE (1 << 0)
|
||||||
#define TASK_STATE_RUNNING (1 << 1)
|
#define TASK_STATE_RUNNING (1 << 1)
|
||||||
#define TASK_STATE_WAIT_IRQ (1 << 2)
|
#define TASK_STATE_WAIT_IRQ (1 << 2)
|
||||||
|
#define TASK_STATE_WAIT_SIGNAL (1 << 3)
|
||||||
|
|
||||||
|
#define TASK_STATE_STOPPED (1 << 6)
|
||||||
#define TASK_STATE_ERROR (1 << 7)
|
#define TASK_STATE_ERROR (1 << 7)
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +47,7 @@ typedef struct {
|
|||||||
char alignment[4];
|
char alignment[4];
|
||||||
} packed task_stack_start;
|
} packed task_stack_start;
|
||||||
|
|
||||||
bool task_locked = false;
|
volatile uint32_t task_locked = 0;
|
||||||
|
|
||||||
task_t *idle_task = NULL;
|
task_t *idle_task = NULL;
|
||||||
task_t *first_task = NULL;
|
task_t *first_task = NULL;
|
||||||
@@ -67,12 +70,45 @@ void cdecl noreturn task_entry_point(task_entrypoint entrypoint, void *entry_dat
|
|||||||
while (true); // halt
|
while (true); // halt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void task_ensure_enabled() {
|
||||||
|
if (current_task == NULL) {
|
||||||
|
k_panics("Tasking should be enabled\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void task_lock_acquire() {
|
void task_lock_acquire() {
|
||||||
task_locked = true;
|
if (__sync_add_and_fetch(&task_locked, 1) == UINT32_MAX) {
|
||||||
|
k_panics("To many task locks");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_lock_free() {
|
void task_lock_free() {
|
||||||
task_locked = false;
|
if (__sync_sub_and_fetch(&task_locked, 1) == UINT32_MAX) {
|
||||||
|
k_panics("To many task free's");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t task_get_current_tid() {
|
||||||
|
return current_task->tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_signal(uint32_t tid) {
|
||||||
|
task_t *t = first_task;
|
||||||
|
while (t != NULL) {
|
||||||
|
if (t->tid == tid) {
|
||||||
|
if (t->state != TASK_STATE_WAIT_SIGNAL) {
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
t->state = TASK_STATE_RUNNABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t = t->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_suspend() {
|
||||||
|
current_task->state = TASK_STATE_WAIT_SIGNAL;
|
||||||
|
task_switch_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
void noreturn task_idle(void *data) {
|
void noreturn task_idle(void *data) {
|
||||||
@@ -98,7 +134,7 @@ void task_wait_irq(uint16_t irq_bits) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void task_switch_next_inner(task_t *next_task) {
|
void task_switch_next_inner(task_t *next_task) {
|
||||||
if (task_locked) {
|
if (task_locked != 0) {
|
||||||
return; // don't switch while the task is locked
|
return; // don't switch while the task is locked
|
||||||
}
|
}
|
||||||
if (next_task == current_task) {
|
if (next_task == current_task) {
|
||||||
@@ -115,6 +151,9 @@ void task_switch_next_inner(task_t *next_task) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void task_start_first() {
|
void task_start_first() {
|
||||||
|
if (task_locked > 0) {
|
||||||
|
k_panics("Tasking locked before start\n");
|
||||||
|
}
|
||||||
task_switch_next_inner(first_task);
|
task_switch_next_inner(first_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,5 +242,13 @@ uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
|
|||||||
return new_task->tid;
|
return new_task->tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_end(uint32_t pid) {
|
void task_end(uint32_t tid) {
|
||||||
|
task_t *t = first_task;
|
||||||
|
while (t != NULL) {
|
||||||
|
if (t->tid == tid) {
|
||||||
|
t->state = TASK_STATE_STOPPED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t = t->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,18 @@ void task_switch_next();
|
|||||||
|
|
||||||
uint32_t task_spawn(task_entrypoint, void *entry_data);
|
uint32_t task_spawn(task_entrypoint, void *entry_data);
|
||||||
|
|
||||||
void task_end(uint32_t pid);
|
void task_end(uint32_t tid);
|
||||||
|
|
||||||
|
void task_suspend();
|
||||||
|
|
||||||
|
uint32_t task_get_current_tid();
|
||||||
|
|
||||||
|
void task_signal(uint32_t tid);
|
||||||
|
|
||||||
void task_lock_acquire();
|
void task_lock_acquire();
|
||||||
|
|
||||||
|
void task_ensure_enabled();
|
||||||
|
|
||||||
void task_lock_free();
|
void task_lock_free();
|
||||||
|
|
||||||
#endif //NEW_KERNEL_TASK_H
|
#endif //NEW_KERNEL_TASK_H
|
||||||
|
|||||||
Reference in New Issue
Block a user