1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/* $Id$
*
* Scheduler for VHDL processes.
*
* Copyright (C) 2008-2009 FAUmachine Team <info@faumachine.org>.
* This program is free software. You can redistribute it and/or modify it
* under the terms of the GNU General Public License, either version 2 of
* the License, or (at your option) any later version. See COPYING.
*/
#include "vhdl_sched.h"
#include <stdlib.h>
#include <assert.h>
#include "glue-log.h"
struct vhdl_sched_process {
/** callback object instance */
void *s;
/** callback to execute the process */
void (*run)(void *s);
/** name of the process */
const char *name;
};
static void
vhdl_sched_destroy_process(
struct vhdl_sched_process *p,
const struct glue_vhdl_cb *callbacks
)
{
callbacks->free(p);
}
struct vhdl_sched *
vhdl_sched_create(const struct glue_vhdl_cb *callbacks)
{
struct vhdl_sched *ret;
ret = callbacks->malloc(sizeof(struct vhdl_sched));
assert(ret != NULL);
ret->run_q = slset_create(NULL, callbacks->malloc);
ret->wait_q = slset_create(NULL, callbacks->malloc);
return ret;
}
void
vhdl_sched_destroy(
struct vhdl_sched *sched,
const struct glue_vhdl_cb *callbacks
)
{
struct slset_entry *i;
assert(sched != NULL);
for (i = sched->run_q->first; i != NULL; i = i->next) {
vhdl_sched_destroy_process(
(struct vhdl_sched_process *)i->data,
callbacks);
}
for (i = sched->wait_q->first; i != NULL; i = i->next) {
vhdl_sched_destroy_process(
(struct vhdl_sched_process *)i->data,
callbacks);
}
slset_destroy(sched->run_q, callbacks->free);
slset_destroy(sched->wait_q, callbacks->free);
callbacks->free(sched);
}
void
vhdl_sched_add_process(
struct vhdl_sched *sched,
void *s,
void (*run)(void *s),
const char *name,
const struct glue_vhdl_cb *callbacks
)
{
struct vhdl_sched_process *p;
p = callbacks->malloc(sizeof(struct vhdl_sched_process));
assert(p != NULL);
/* TODO sort by time? */
assert(s != NULL);
assert(run != NULL);
p->s = s;
p->run = run;
p->name = name;
slset_add(sched->run_q, p, callbacks->malloc);
}
void
vhdl_sched_run(
struct vhdl_sched *sched,
const struct glue_vhdl_cb *callbacks
)
{
struct slset_entry *i;
for (i = sched->run_q->first; i != NULL; i = i->next) {
struct vhdl_sched_process *p =
(struct vhdl_sched_process *)i->data;
#if 0 /* not needed atm. */
faum_log(FAUM_LOG_DEBUG, "fauhdli", "sched",
"running process \"%s\"\n", p->name);
#endif
p->run(p->s);
}
slset_move_all(
sched->run_q,
sched->wait_q,
callbacks->malloc,
callbacks->free);
}
bool
vhdl_sched_has_runnable(struct vhdl_sched *sched)
{
return ! slset_empty(sched->run_q);
}
void
vhdl_sched_wakeup(
struct vhdl_sched *sched,
void *s,
const struct glue_vhdl_cb *callbacks
)
{
struct slset_entry *i;
struct vhdl_sched_process *p = NULL;
for (i = sched->wait_q->first; i != NULL; i = i->next) {
p = (struct vhdl_sched_process *)i->data;
if (p->s == s) {
break;
}
}
if (p != NULL) {
#if 0 /* not needed atm. */
faum_log(FAUM_LOG_DEBUG, "fauhdli", "sched",
"waking up %s\n", p->name);
#endif
slset_remove(sched->wait_q, p, callbacks->free);
slset_add(sched->run_q, p, callbacks->malloc);
}
}
|