odyssey/third_party/machinarium/sources/task_mgr.c

122 lines
2.5 KiB
C
Raw Normal View History

2017-05-23 12:34:35 +00:00
/*
* machinarium.
*
* cooperative multitasking engine.
*/
2017-05-23 12:34:35 +00:00
#include <machinarium.h>
#include <machinarium_private.h>
enum { MM_TASK, MM_TASK_EXIT };
2017-05-23 12:34:35 +00:00
static void mm_taskmgr_main(void *arg __attribute__((unused)))
2017-05-23 12:34:35 +00:00
{
sigset_t mask;
sigfillset(&mask);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
for (;;) {
2017-05-23 12:34:35 +00:00
mm_msg_t *msg;
msg = mm_channel_read(&machinarium.task_mgr.channel,
UINT32_MAX);
2017-05-23 12:34:35 +00:00
assert(msg != NULL);
if (msg->type == MM_TASK_EXIT) {
free(msg);
2017-05-23 12:34:35 +00:00
break;
}
assert(msg->type == MM_TASK);
assert(mm_buf_used(&msg->data) == sizeof(mm_task_t));
mm_task_t *task;
task = (mm_task_t *)msg->data.start;
2017-05-23 12:34:35 +00:00
task->function(task->arg);
int event_mgr_fd;
event_mgr_fd = mm_eventmgr_signal(&task->on_complete);
if (event_mgr_fd > 0)
mm_eventmgr_wakeup(event_mgr_fd);
2017-05-23 12:34:35 +00:00
}
}
void mm_taskmgr_init(mm_taskmgr_t *mgr)
2017-05-23 12:34:35 +00:00
{
mgr->workers_count = 0;
mgr->workers = NULL;
mm_channel_init(&mgr->channel);
2017-05-23 12:34:35 +00:00
}
int mm_taskmgr_start(mm_taskmgr_t *mgr, int workers_count)
2017-05-23 12:34:35 +00:00
{
mgr->workers_count = workers_count;
mgr->workers = malloc(sizeof(int) * workers_count);
2017-05-23 12:34:35 +00:00
if (mgr->workers == NULL)
return -1;
int i = 0;
for (; i < workers_count; i++) {
char name[32];
mm_snprintf(name, sizeof(name), "resolver: %d", i);
2017-05-23 12:34:35 +00:00
mgr->workers[i] = machine_create(name, mm_taskmgr_main, NULL);
}
return 0;
}
void mm_taskmgr_stop(mm_taskmgr_t *mgr)
2017-05-23 12:34:35 +00:00
{
int i;
int rc;
for (i = 0; i < mgr->workers_count; i++) {
mm_msg_t *msg;
msg = malloc(sizeof(mm_msg_t));
if (msg == NULL) {
/* todo: */
abort();
return;
}
mm_msg_init(msg, MM_TASK_EXIT);
mm_channel_write(&mgr->channel, msg);
2017-05-23 12:34:35 +00:00
}
for (i = 0; i < mgr->workers_count; i++) {
rc = machine_wait(mgr->workers[i]);
if (rc != MM_OK_RETCODE) {
/* TODO: handle gracefully */
abort();
return;
}
2017-05-23 12:34:35 +00:00
}
mm_channel_free(&mgr->channel);
2017-05-23 12:34:35 +00:00
free(mgr->workers);
}
int mm_taskmgr_new(mm_taskmgr_t *mgr, mm_task_function_t function, void *arg,
uint32_t time_ms)
2017-05-23 12:34:35 +00:00
{
mm_msg_t *msg;
msg = (mm_msg_t *)machine_msg_create(sizeof(mm_task_t));
if (msg == NULL)
2017-05-23 12:34:35 +00:00
return -1;
msg->type = MM_TASK;
2017-05-23 12:34:35 +00:00
mm_task_t *task;
task = (mm_task_t *)msg->data.start;
2017-05-23 12:34:35 +00:00
task->function = function;
task->arg = arg;
mm_eventmgr_add(&mm_self->event_mgr, &task->on_complete);
2017-05-23 12:34:35 +00:00
/* schedule task */
mm_channel_write(&mgr->channel, msg);
2017-05-23 12:34:35 +00:00
/* wait for completion */
time_ms = UINT32_MAX;
2017-05-23 12:34:35 +00:00
int ready;
ready = mm_eventmgr_wait(&mm_self->event_mgr, &task->on_complete,
time_ms);
if (!ready) {
2017-05-23 12:34:35 +00:00
/* todo: */
abort();
return 0;
2017-05-23 12:34:35 +00:00
}
machine_msg_free((machine_msg_t *)msg);
2017-05-23 12:34:35 +00:00
return 0;
}