blob: 05bfd9178573f2abf0758978f2da68a3fab6cb84 [file] [log] [blame]
/* Copyright (c) 2015 Google Inc
* Barret Rhoden <brho@cs.berkeley.edu>
* See LICENSE for details.
*
* Hacked BSD taskqueues. In lieu of actually running a kproc or something that
* sleeps on a queue of tasks, we'll just blast out a kmsg. We can always
* change the implementation if we need more control. */
#include <taskqueue.h>
#include <trap.h>
#include <kthread.h>
/* BSD Taskqueue wrappers. */
int taskqueue_enqueue(struct taskqueue *queue, struct task *task)
{
run_as_rkm(task->ta_func, task->ta_context, 0);
return 0;
}
/* Linux workqueue wrappers */
void flush_workqueue(struct workqueue_struct *wq)
{
}
void destroy_workqueue(struct workqueue_struct *wq)
{
}
struct workqueue_struct *create_singlethread_workqueue(char *name)
{
/* Non-canonical addr on AMD64. No one should be derefing this. */
return (void*)0xf0f0f0f0f0f0f0f0;
}
static void __wq_wrapper(uint32_t srcid, long a0, long a1, long a2)
{
struct work_struct *work = (struct work_struct*)a0;
work->func(work);
}
/* Linux callers use jiffies as the unit of delay. We pretend to be a 1000 HZ
* machine with 1 msec jiffies. */
static void __wq_wrapper_delay(uint32_t srcid, long a0, long a1, long a2)
{
struct work_struct *work = (struct work_struct*)a0;
unsigned long delay = (unsigned long)a1;
kthread_usleep(delay * 1000);
work->func(work);
}
static void send_work(int coreid, struct work_struct *work)
{
send_kernel_message(coreid, __wq_wrapper, (long)work, 0, 0,
KMSG_ROUTINE);
}
static void send_work_delay(int coreid, struct delayed_work *work,
unsigned long delay)
{
send_kernel_message(coreid, __wq_wrapper_delay, (long)work, (long)delay,
0, KMSG_ROUTINE);
}
bool queue_work(struct workqueue_struct *wq, struct work_struct *work)
{
send_work(core_id(), work);
return TRUE;
}
bool schedule_work(struct work_struct *work)
{
send_work(0, work);
return TRUE;
}
bool cancel_work(struct work_struct *dwork)
{
return FALSE;
}
bool cancel_work_sync(struct work_struct *dwork)
{
return FALSE;
}
bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork,
unsigned long delay)
{
send_work_delay(core_id(), dwork, delay);
return TRUE;
}
bool schedule_delayed_work(struct delayed_work *dwork, unsigned long delay)
{
send_work_delay(0, dwork, delay);
return TRUE;
}
bool cancel_delayed_work(struct delayed_work *dwork)
{
return FALSE;
}
bool cancel_delayed_work_sync(struct delayed_work *dwork)
{
return FALSE;
}