Fix: interrupt preemption
This commit is contained in:
@@ -101,11 +101,11 @@ logger_cur = _Generic((msg), \
|
|||||||
// #define DEBUG_DTB(val) DEBUG(val)
|
// #define DEBUG_DTB(val) DEBUG(val)
|
||||||
#define DEBUG_DTB(val) CLEAN
|
#define DEBUG_DTB(val) CLEAN
|
||||||
|
|
||||||
// #define DEBUG_EXCEP(val) DEBUG(val)
|
#define DEBUG_EXCEP(val) DEBUG(val)
|
||||||
#define DEBUG_EXCEP(val) CLEAN
|
// #define DEBUG_EXCEP(val) CLEAN
|
||||||
|
|
||||||
#define DEBUG_MEM(val) DEBUG(val)
|
// #define DEBUG_MEM(val) DEBUG(val)
|
||||||
// #define DEBUG_MEM(val) CLEAN
|
#define DEBUG_MEM(val) CLEAN
|
||||||
|
|
||||||
// #define DEBUG_INITRD(val) DEBUG(val)
|
// #define DEBUG_INITRD(val) DEBUG(val)
|
||||||
#define DEBUG_INITRD(val) CLEAN
|
#define DEBUG_INITRD(val) CLEAN
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ typedef struct interrupt {
|
|||||||
uint64_t priority;
|
uint64_t priority;
|
||||||
interrupt_callback_func_t func;
|
interrupt_callback_func_t func;
|
||||||
uint64_t param;
|
uint64_t param;
|
||||||
|
|
||||||
|
int is_start;
|
||||||
} interrupt_t;
|
} interrupt_t;
|
||||||
|
|
||||||
void add_interrupt_task(uint64_t priority,
|
void add_interrupt_task(uint64_t priority,
|
||||||
|
|||||||
@@ -73,16 +73,27 @@ void add_interrupt_task(uint64_t priority,
|
|||||||
|
|
||||||
.priority = priority,
|
.priority = priority,
|
||||||
.func = func,
|
.func = func,
|
||||||
.param = param
|
.param = param,
|
||||||
|
|
||||||
|
.is_start = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
global_interrupt_pool = _merge(global_interrupt_pool, newint);
|
global_interrupt_pool = _merge(global_interrupt_pool, newint);
|
||||||
|
|
||||||
|
while (global_interrupt_pool) {
|
||||||
|
// LOG("check interrupt"); DEBUG_EXCEP(global_interrupt_pool->priority);
|
||||||
|
if (global_interrupt_pool->is_start)
|
||||||
|
return;
|
||||||
|
global_interrupt_pool->is_start = true;
|
||||||
|
global_interrupt_pool->func(global_interrupt_pool->param);
|
||||||
|
global_interrupt_pool = _pop(global_interrupt_pool);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_interrupt(void)
|
void init_interrupt(void)
|
||||||
{
|
{
|
||||||
W_SYSREG(cntp_ctl_el0, 1);
|
|
||||||
_enable_interrupt();
|
_enable_interrupt();
|
||||||
|
_enable_timer_irq(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_handler(void)
|
void irq_handler(void)
|
||||||
@@ -99,6 +110,8 @@ void irq_handler(void)
|
|||||||
|
|
||||||
void wfe(void)
|
void wfe(void)
|
||||||
{
|
{
|
||||||
|
return; // do nothing for now
|
||||||
|
|
||||||
if (!global_interrupt_pool) {
|
if (!global_interrupt_pool) {
|
||||||
// asm volatile("wfe");
|
// asm volatile("wfe");
|
||||||
asm volatile("nop");
|
asm volatile("nop");
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include <uart.h>
|
|
||||||
#include <logger.h>
|
#include <logger.h>
|
||||||
#include <errcode.h>
|
#include <errcode.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|||||||
@@ -118,16 +118,12 @@ uint64_t _allocate_page(size_t req, int idx, uint64_t l, uint64_t r)
|
|||||||
switch (CUR->state) {
|
switch (CUR->state) {
|
||||||
case PAGE_FREE:
|
case PAGE_FREE:
|
||||||
if (req == sz) {
|
if (req == sz) {
|
||||||
LOG("page allocated");
|
LOG("page allocated"); LOG(l); DEBUG_MEM(r);
|
||||||
LOG(l);
|
|
||||||
DEBUG_MEM(r);
|
|
||||||
CUR->state = PAGE_ALLOCATED;
|
CUR->state = PAGE_ALLOCATED;
|
||||||
CUR->size = 0;
|
CUR->size = 0;
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
LOG("page divided");
|
LOG("page divided"); LOG(l); DEBUG_MEM(r);
|
||||||
LOG(l);
|
|
||||||
DEBUG(r);
|
|
||||||
LCH->state = RCH->state = PAGE_FREE;
|
LCH->state = RCH->state = PAGE_FREE;
|
||||||
LCH->size = m - l;
|
LCH->size = m - l;
|
||||||
RCH->size = r - m;
|
RCH->size = r - m;
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ static inline
|
|||||||
void _settimeout_cb_func(uint64_t args)
|
void _settimeout_cb_func(uint64_t args)
|
||||||
{
|
{
|
||||||
vector_t *v = (void *)args;
|
vector_t *v = (void *)args;
|
||||||
|
uart_puts("timeout: ");
|
||||||
for (int i = 2; i < (int)v->size; ++i) {
|
for (int i = 2; i < (int)v->size; ++i) {
|
||||||
uart_puts(VEC_AT(char, v, i));
|
uart_puts(VEC_AT(char, v, i));
|
||||||
uart_puts(" ");
|
uart_puts(" ");
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ timer_t *_pop(timer_t *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void _set_timer_interrupt()
|
void _check_enable_timer()
|
||||||
{
|
{
|
||||||
if (global_timer) {
|
if (global_timer) {
|
||||||
uint64_t cntpct_el0;
|
uint64_t cntpct_el0;
|
||||||
@@ -59,8 +59,9 @@ void _set_timer_interrupt()
|
|||||||
else
|
else
|
||||||
W_SYSREG(cntp_cval_el0, global_timer->data.firing_tick);
|
W_SYSREG(cntp_cval_el0, global_timer->data.firing_tick);
|
||||||
|
|
||||||
_enable_timer_irq(true);
|
W_SYSREG(cntp_ctl_el0, 1);
|
||||||
}
|
} else
|
||||||
|
W_SYSREG(cntp_ctl_el0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@@ -87,8 +88,23 @@ void add_timer_task(task_t task)
|
|||||||
|
|
||||||
global_timer = _merge(global_timer, newtimer);
|
global_timer = _merge(global_timer, newtimer);
|
||||||
|
|
||||||
_traverse(global_timer);
|
// _traverse(global_timer);
|
||||||
_set_timer_interrupt();
|
_check_enable_timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
interrupt_callback_func_t func;
|
||||||
|
uint64_t param;
|
||||||
|
} _timer_task_wrapper_param_t;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _timer_task_wrapper(uint64_t param)
|
||||||
|
{
|
||||||
|
_timer_task_wrapper_param_t *data = (void *)param;
|
||||||
|
data->func(data->param);
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
|
_enable_timer_irq(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_irq_handler(void)
|
void timer_irq_handler(void)
|
||||||
@@ -100,9 +116,15 @@ void timer_irq_handler(void)
|
|||||||
LOG("timer irq"); DEBUG_EXCEP(cntpct_el0);
|
LOG("timer irq"); DEBUG_EXCEP(cntpct_el0);
|
||||||
|
|
||||||
if (global_timer) {
|
if (global_timer) {
|
||||||
add_interrupt_task(20, global_timer->data.func, global_timer->data.param);
|
_timer_task_wrapper_param_t *param =
|
||||||
global_timer = _pop(global_timer);
|
kmalloc(sizeof(_timer_task_wrapper_param_t));
|
||||||
}
|
*param = (_timer_task_wrapper_param_t){
|
||||||
|
.func = global_timer->data.func,
|
||||||
|
.param = global_timer->data.param,
|
||||||
|
};
|
||||||
|
add_interrupt_task(20, _timer_task_wrapper, (uint64_t)param);
|
||||||
|
|
||||||
_set_timer_interrupt();
|
global_timer = _pop(global_timer);
|
||||||
|
_check_enable_timer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ size_t (*uart_putb)(const uint8_t *bytes, size_t len) = uart_putb_sync;
|
|||||||
size_t (*uart_getb)(uint8_t *bytes, size_t len) = uart_getb_sync;
|
size_t (*uart_getb)(uint8_t *bytes, size_t len) = uart_getb_sync;
|
||||||
int is_uart_inited = false;
|
int is_uart_inited = false;
|
||||||
|
|
||||||
|
int is_uart_in_interrupt_queue = false;
|
||||||
|
|
||||||
ringbuffer_t *uart_readbuf;
|
ringbuffer_t *uart_readbuf;
|
||||||
ringbuffer_t *uart_writebuf;
|
ringbuffer_t *uart_writebuf;
|
||||||
|
|
||||||
@@ -83,37 +85,47 @@ void uart_init(void)
|
|||||||
is_uart_inited = true;
|
is_uart_inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_transmit_interrupt_handler()
|
static inline
|
||||||
|
void _enable_uart_interrupt()
|
||||||
{
|
{
|
||||||
|
_uart_enable_receive_interrupt(true);
|
||||||
if (uart_writebuf->size > 0)
|
if (uart_writebuf->size > 0)
|
||||||
_uart_write_data(ringbuffer_bump(uart_writebuf));
|
_uart_enable_transmit_interrupt(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ringbuffer_t *buf;
|
|
||||||
uint8_t val;
|
|
||||||
} uart_interrupt_callback_payload_t;
|
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void uart_receive_interrupt_callback(uint64_t param)
|
void _uart_transmit_interrupt_callback(uint64_t)
|
||||||
{
|
{
|
||||||
uart_interrupt_callback_payload_t *payload = (void *)param;
|
_uart_write_data(ringbuffer_bump(uart_writebuf));
|
||||||
ringbuffer_push(payload->buf, payload->val);
|
|
||||||
kfree(payload);
|
is_uart_in_interrupt_queue = false;
|
||||||
|
_enable_uart_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_receive_interrupt_handler()
|
static inline
|
||||||
|
void _uart_transmit_interrupt_handler()
|
||||||
|
{
|
||||||
|
if (uart_writebuf->size > 0) {
|
||||||
|
is_uart_in_interrupt_queue = true;
|
||||||
|
add_interrupt_task(11, _uart_transmit_interrupt_callback, 0x0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _uart_receive_interrupt_callback(uint64_t)
|
||||||
|
{
|
||||||
|
ringbuffer_push(uart_readbuf, _uart_read_data());
|
||||||
|
|
||||||
|
is_uart_in_interrupt_queue = false;
|
||||||
|
_enable_uart_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void _uart_receive_interrupt_handler()
|
||||||
{
|
{
|
||||||
if (uart_readbuf->size < uart_readbuf->cap) {
|
if (uart_readbuf->size < uart_readbuf->cap) {
|
||||||
uint8_t b = _uart_read_data();
|
is_uart_in_interrupt_queue = true;
|
||||||
|
add_interrupt_task(12, _uart_receive_interrupt_callback, 0x0);
|
||||||
uart_interrupt_callback_payload_t *param = kmalloc(
|
|
||||||
sizeof(uart_interrupt_callback_payload_t));
|
|
||||||
*param = (uart_interrupt_callback_payload_t){
|
|
||||||
.buf = uart_readbuf,
|
|
||||||
.val = b,
|
|
||||||
};
|
|
||||||
add_interrupt_task(10, uart_receive_interrupt_callback, (uint64_t)param);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,14 +133,11 @@ void uart_irq_handler(void)
|
|||||||
{
|
{
|
||||||
_uart_enable_receive_interrupt(false);
|
_uart_enable_receive_interrupt(false);
|
||||||
_uart_enable_transmit_interrupt(false);
|
_uart_enable_transmit_interrupt(false);
|
||||||
|
|
||||||
if (_uart_receive_interrupt())
|
if (_uart_receive_interrupt())
|
||||||
uart_receive_interrupt_handler();
|
_uart_receive_interrupt_handler();
|
||||||
if (_uart_transmit_interrupt())
|
if (_uart_transmit_interrupt())
|
||||||
uart_transmit_interrupt_handler();
|
_uart_transmit_interrupt_handler();
|
||||||
|
|
||||||
_uart_enable_receive_interrupt(true);
|
|
||||||
if (uart_writebuf->size > 0)
|
|
||||||
_uart_enable_transmit_interrupt(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t uart_putb_async(const uint8_t *bytes, size_t len)
|
size_t uart_putb_async(const uint8_t *bytes, size_t len)
|
||||||
@@ -137,8 +146,8 @@ size_t uart_putb_async(const uint8_t *bytes, size_t len)
|
|||||||
for (; sentlen < len; ++bytes, ++sentlen)
|
for (; sentlen < len; ++bytes, ++sentlen)
|
||||||
ringbuffer_push(uart_writebuf, *bytes);
|
ringbuffer_push(uart_writebuf, *bytes);
|
||||||
|
|
||||||
if (uart_writebuf->size > 0)
|
if (!is_uart_in_interrupt_queue && uart_writebuf)
|
||||||
_uart_enable_transmit_interrupt(true);
|
_enable_uart_interrupt();
|
||||||
|
|
||||||
return sentlen;
|
return sentlen;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user