Initial draft of events with GNU PTH
This commit is contained in:
parent
5e0e1caef3
commit
a1fc4290f4
@ -6,6 +6,40 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
|
||||||
|
#include <pth.h>
|
||||||
|
|
||||||
|
// TODO set JOINABLE to false
|
||||||
|
|
||||||
|
static int startTime;
|
||||||
|
static map<pair<int, int>, Action> handlersMap;
|
||||||
|
static pth_msgport_t evMsgPort;
|
||||||
|
|
||||||
|
struct Thread {
|
||||||
|
struct Thread *next;
|
||||||
|
Action act;
|
||||||
|
TValue arg0;
|
||||||
|
pth_t pid;
|
||||||
|
pth_msgport_t waitEventPort;
|
||||||
|
int waitSource;
|
||||||
|
int waitValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct Thread *allThreads;
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
pth_message_t msg;
|
||||||
|
int source;
|
||||||
|
int value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Event *mkEvent(int source, int value) {
|
||||||
|
auto res = new Event();
|
||||||
|
memset(res, 0, sizeof(Event));
|
||||||
|
res->source = source;
|
||||||
|
res->value = value;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
void dmesg(const char *format, ...) {
|
void dmesg(const char *format, ...) {
|
||||||
char buf[500];
|
char buf[500];
|
||||||
|
|
||||||
@ -34,7 +68,17 @@ extern "C" void target_reset() {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sleep_ms(uint32_t ms) {
|
||||||
|
struct timeval tv;
|
||||||
|
tv.tv_sec = ms / 1000;
|
||||||
|
tv.tv_usec = (ms % 1000) * 1000;
|
||||||
|
pth_nap(tv);
|
||||||
|
}
|
||||||
|
|
||||||
void sleep_us(uint64_t us) {
|
void sleep_us(uint64_t us) {
|
||||||
|
if (us > 20000) {
|
||||||
|
sleep_ms(us / 1000);
|
||||||
|
}
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = us / 1000000;
|
ts.tv_sec = us / 1000000;
|
||||||
ts.tv_nsec = (us % 1000000) * 1000;
|
ts.tv_nsec = (us % 1000000) * 1000;
|
||||||
@ -42,22 +86,12 @@ void sleep_us(uint64_t us) {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sleep_ms(uint32_t ms) {
|
|
||||||
sleep_us((uint64_t)ms * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t currTime() {
|
uint64_t currTime() {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int startTime;
|
|
||||||
|
|
||||||
void initRuntime() {
|
|
||||||
startTime = currTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
int current_time_ms() {
|
int current_time_ms() {
|
||||||
return currTime() - startTime;
|
return currTime() - startTime;
|
||||||
}
|
}
|
||||||
@ -66,23 +100,115 @@ int getSerialNumber() {
|
|||||||
return 42; // TODO
|
return 42; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerWithDal(int id, int event, Action a) {
|
void disposeThread(Thread *t) {
|
||||||
// TODO
|
if (allThreads == t) {
|
||||||
|
allThreads = t->next;
|
||||||
|
} else {
|
||||||
|
for (auto tt = allThreads; tt; tt = tt->next) {
|
||||||
|
if (tt->next == t) {
|
||||||
|
tt->next = t->next;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decr(t->act);
|
||||||
|
pth_msgport_destroy(t->waitEventPort);
|
||||||
|
delete t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void runAct(Thread *thr) {
|
||||||
|
pxt::runAction1(thr->act, thr->arg0);
|
||||||
|
disposeThread(thr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupThread(Action a, TValue arg = 0, void (*runner)(Thread *) = runAct) {
|
||||||
|
auto thr = new Thread();
|
||||||
|
memset(thr, 0, sizeof(Thread));
|
||||||
|
thr->next = allThreads;
|
||||||
|
allThreads = thr;
|
||||||
|
thr->act = a;
|
||||||
|
thr->arg0 = a;
|
||||||
|
thr->waitEventPort = pth_msgport_create(NULL);
|
||||||
|
incr(a);
|
||||||
|
pth_spawn(PTH_ATTR_DEFAULT, runner, thr);
|
||||||
|
}
|
||||||
|
|
||||||
void runInBackground(Action a) {
|
void runInBackground(Action a) {
|
||||||
// TODO
|
setupThread(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void runFor(Thread *t) {
|
||||||
|
while (true) {
|
||||||
|
pxt::runAction0(t->act);
|
||||||
|
sleep_ms(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void runForever(Action a) {
|
void runForever(Action a) {
|
||||||
// TODO
|
setupThread(a, 0, runFor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitForEvent(int id, int event) {
|
void waitForEvent(int id, int event) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dispatchEvent(Event &e) {
|
||||||
|
// lastEvent = e;
|
||||||
|
|
||||||
|
Action curr = handlersMap[{e.source, e.value}];
|
||||||
|
if (curr)
|
||||||
|
runAction1(curr, fromInt(e.value));
|
||||||
|
|
||||||
|
curr = handlersMap[{e.source, DEVICE_EVT_ANY}];
|
||||||
|
if (curr)
|
||||||
|
runAction1(curr, fromInt(e.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *evtDispatcher(void *dummy) {
|
||||||
|
pth_event_t msgEv = pth_event(PTH_EVENT_MSG, evMsgPort);
|
||||||
|
Event *ev;
|
||||||
|
while (true) {
|
||||||
|
pth_wait(msgEv);
|
||||||
|
while (NULL != (ev = (Event *)pth_msgport_get(evMsgPort))) {
|
||||||
|
for (auto thr = allThreads; thr; thr = thr->next) {
|
||||||
|
if (thr->waitSource == ev->source &&
|
||||||
|
(thr->waitValue == ev->value || thr->waitValue == DEVICE_EVT_ANY)) {
|
||||||
|
Event *copy = mkEvent(ev->source, ev->value);
|
||||||
|
pth_msgport_put(thr->waitEventPort, copy);
|
||||||
|
thr->waitSource = 0; // once!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispatchEvent(*ev);
|
||||||
|
delete ev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void raiseEvent(int id, int event) {
|
||||||
|
auto e = mkEvent(id, event);
|
||||||
|
pth_msgport_put(evMsgPort, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerWithDal(int id, int event, Action a) {
|
||||||
|
Action prev = handlersMap[{id, event}];
|
||||||
|
if (prev)
|
||||||
|
decr(prev);
|
||||||
|
else {
|
||||||
|
// first time processing?
|
||||||
|
}
|
||||||
|
incr(a);
|
||||||
|
handlersMap[{id, event}] = a;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t afterProgramPage() {
|
uint32_t afterProgramPage() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void dumpDmesg() {
|
void dumpDmesg() {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initRuntime() {
|
||||||
|
startTime = currTime();
|
||||||
|
pth_init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,9 @@ let f = 0.5
|
|||||||
let plus = i + f
|
let plus = i + f
|
||||||
let minus = i - f
|
let minus = i - f
|
||||||
|
|
||||||
while (true) {
|
|
||||||
let r = Math.random()
|
loops.forever(() => {
|
||||||
|
let r = Math.randomRange(0, 100)
|
||||||
serial.writeValue("R", r)
|
serial.writeValue("R", r)
|
||||||
loops.pause(1000)
|
loops.pause(1000)
|
||||||
}
|
})
|
||||||
|
|
||||||
//loops.forever(() => {
|
|
||||||
//})
|
|
||||||
|
Loading…
Reference in New Issue
Block a user