basekernel/kernel/event_queue.c

109 lines
2.0 KiB
C
Raw Normal View History

2024-10-14 23:07:35 +02:00
#include "event_queue.h"
#include "interrupt.h"
#include "process.h"
#include "list.h"
#include "kmalloc.h"
#define EVENT_BUFFER_SIZE 32
struct event_queue {
struct event buffer[EVENT_BUFFER_SIZE];
struct list process_queue;
int head;
int tail;
int overflow_count;
};
struct event_queue event_queue_root;
struct event_queue * event_queue_create_root()
{
memset(&event_queue_root,0,sizeof(event_queue_root));
return &event_queue_root;
}
struct event_queue * event_queue_create()
{
struct event_queue *q = kmalloc(sizeof(*q));
memset(q,0,sizeof(*q));
return q;
}
void event_queue_delete( struct event_queue *q )
{
kfree(q);
}
/* INTERRUPT CONTEXT */
void event_queue_post( struct event_queue *q, struct event *e )
{
/* If ring buffer is full, return immediately. */
int next = (q->head+1) % EVENT_BUFFER_SIZE;
if(next==q->tail) {
q->overflow_count++;
return;
}
/* Copy event to current buffer position */
q->buffer[q->head] = *e;
/* Advance head pointer and wake up waiting process (if any) */
q->head = next;
process_wakeup(&q->process_queue);
}
/* INTERRUPT CONTEXT */
void event_queue_post_root( uint16_t type, uint16_t code, int16_t x, int16_t y )
{
struct event e;
e.type = type;
e.code = code;
e.x = x;
e.y = y;
event_queue_post(&event_queue_root,&e);
}
static int event_queue_read_raw( struct event_queue *q, struct event *e, int size, int blocking )
{
int total=0;
if(size<sizeof(struct event)) return KERROR_INVALID_REQUEST;
interrupt_block();
while(size>=sizeof(struct event)) {
if(q->head==q->tail) {
if(blocking && total==0) {
process_wait(&q->process_queue);
continue;
} else {
break;
}
}
*e = q->buffer[q->tail];
q->tail = (q->tail+1) % EVENT_BUFFER_SIZE;
e++;
total++;
size -= sizeof(struct event);
}
interrupt_unblock();
return total;
}
int event_queue_read( struct event_queue *q, struct event *e, int size )
{
return event_queue_read_raw(q,e,size,1);
}
int event_queue_read_nonblock( struct event_queue *q, struct event *e, int size )
{
return event_queue_read_raw(q,e,size,0);
}