Skip to content

Instantly share code, notes, and snippets.

@heatd
Created April 15, 2017 19:59
Show Gist options
  • Save heatd/bcf5e00fc25eaaa02df0aef62c564d24 to your computer and use it in GitHub Desktop.
Save heatd/bcf5e00fc25eaaa02df0aef62c564d24 to your computer and use it in GitHub Desktop.
static struct irq_work *queue = NULL;
int irq_schedule_work(void (*callback)(void *, size_t), size_t payload_size, void *payload)
{
struct irq_work *q = queue;
while(q->callback)
{
q = (struct irq_work *) (char*) &q->payload + q->payload_size;
}
uintptr_t remaining_size = ((uintptr_t) queue + IRQ_WORK_QUEUE_SIZE) - (uintptr_t) q;
if(sizeof(struct irq_work) + payload_size > remaining_size)
return 1;
q->callback = callback;
q->payload_size = payload_size;
memcpy(&q->payload, payload, payload_size);
return 0;
}
int irq_get_work(struct irq_work *strct)
{
if(!queue->callback)
return -1;
memcpy(strct, queue, sizeof(struct irq_work) + queue->payload_size);
memset(queue, 0, sizeof(struct irq_work) + queue->payload_size);
return 0;
}
struct irq_work *worker_buffer = NULL;
void irq_worker(void *ctx)
{
while(1)
{
/* Do any work needed */
if(irq_get_work(worker_buffer) < 0)
{
sched_yield();
continue;
}
worker_buffer->callback(&worker_buffer->payload, worker_buffer->payload_size);
}
}
void irq_init(void)
{
if(!sched_create_thread(irq_worker, 1, NULL))
panic("irq_init: Could not create the worker thread!\n");
queue = malloc(IRQ_WORK_QUEUE_SIZE);
if(!queue)
panic("irq_init: failed to allocate queue!\n");
memset(queue, 0, IRQ_WORK_QUEUE_SIZE);
worker_buffer = malloc(IRQ_WORK_QUEUE_SIZE);
if(!worker_buffer)
panic("irq_init: failed to allocate buffer!\n");
memset(worker_buffer, 0, IRQ_WORK_QUEUE_SIZE);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment