mirror of
https://github.com/aap/pdp6.git
synced 2026-01-11 23:53:31 +00:00
170 lines
2.9 KiB
C
170 lines
2.9 KiB
C
#include "pdp6.h"
|
|
#include <time.h>
|
|
|
|
struct timespec
|
|
timesub(struct timespec t1, struct timespec t2)
|
|
{
|
|
struct timespec d;
|
|
d.tv_sec = t2.tv_sec - t1.tv_sec;
|
|
d.tv_nsec = t2.tv_nsec - t1.tv_nsec;
|
|
if(d.tv_nsec < 0){
|
|
d.tv_nsec += 1000000000;
|
|
d.tv_sec -= 1;
|
|
}
|
|
return d;
|
|
}
|
|
|
|
struct timespec
|
|
timeadd(struct timespec t1, struct timespec t2)
|
|
{
|
|
struct timespec s;
|
|
s.tv_sec = t1.tv_sec + t2.tv_sec;
|
|
s.tv_nsec = t1.tv_nsec + t2.tv_nsec;
|
|
if(s.tv_nsec >= 1000000000){
|
|
s.tv_nsec -= 1000000000;
|
|
s.tv_sec += 1;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/* is t2 after t1 */
|
|
int
|
|
timeafter(struct timespec t1, struct timespec t2)
|
|
{
|
|
if(t1.tv_sec == t2.tv_sec)
|
|
return t1.tv_nsec < t2.tv_nsec;
|
|
return t1.tv_sec < t2.tv_sec;
|
|
}
|
|
|
|
/* is t2 before t1 */
|
|
int
|
|
timebefore(struct timespec t1, struct timespec t2)
|
|
{
|
|
if(t1.tv_sec == t2.tv_sec)
|
|
return t1.tv_nsec > t2.tv_nsec;
|
|
return t1.tv_sec > t2.tv_sec;
|
|
}
|
|
|
|
typedef struct Clockchan Clockchan;
|
|
struct Clockchan
|
|
{
|
|
int active;
|
|
Channel *c;
|
|
struct timespec start;
|
|
struct timespec timeout;
|
|
struct timespec interval;
|
|
int repeat;
|
|
Clockchan *next;
|
|
};
|
|
static Clockchan *channels;
|
|
Channel *rtcchan;
|
|
|
|
static Clockchan*
|
|
getchan(Channel *c)
|
|
{
|
|
Clockchan *cc;
|
|
for(cc = channels; cc; cc = cc->next)
|
|
if(cc->c == c)
|
|
return cc;
|
|
return nil;
|
|
}
|
|
|
|
static void
|
|
rtcstart(Channel *c, word interval, int repeat)
|
|
{
|
|
Clockchan *cc;
|
|
|
|
cc = getchan(c);
|
|
if(cc == nil){
|
|
cc = malloc(sizeof(Clockchan));
|
|
memset(cc, 0, sizeof(Clockchan));
|
|
cc->next = channels;
|
|
channels = cc;
|
|
}
|
|
|
|
cc->active = 1;
|
|
cc->c = c;
|
|
clock_gettime(CLOCK_REALTIME, &cc->start);
|
|
cc->interval.tv_sec = interval / 1000000000;
|
|
cc->interval.tv_nsec = interval % 1000000000;
|
|
cc->timeout = timeadd(cc->start, cc->interval);
|
|
cc->repeat = repeat;
|
|
}
|
|
|
|
static void
|
|
rtcstop(Channel *c)
|
|
{
|
|
Clockchan *cc;
|
|
|
|
cc = getchan(c);
|
|
if(cc)
|
|
cc->active = 0;
|
|
}
|
|
|
|
void*
|
|
rtcthread(void *p)
|
|
{
|
|
struct timespec now;
|
|
Clockchan *cc;
|
|
RtcMsg msg;
|
|
int loss;
|
|
|
|
threadname("rtc");
|
|
|
|
struct timespec slp = { 0, 1*1000*1000 }; // 1ms
|
|
loss = 0;
|
|
for(;;){
|
|
clock_gettime(CLOCK_REALTIME, &now);
|
|
|
|
/* Check all channels for a timeout */
|
|
for(cc = channels; cc; cc = cc->next){
|
|
if(!cc->active || timebefore(cc->timeout, now))
|
|
continue;
|
|
|
|
/* I *hope* this is ok */
|
|
if(channbsend(cc->c, &loss) == 0)
|
|
;//printf("missed clock\n");
|
|
if(cc->repeat)
|
|
cc->timeout = timeadd(cc->timeout, cc->interval);
|
|
else
|
|
cc->active = 0;
|
|
}
|
|
|
|
if(channbrecv(rtcchan, &msg) == 1){
|
|
if(msg.msg == 1)
|
|
rtcstart(msg.c, msg.interval, msg.repeat);
|
|
else
|
|
rtcstop(msg.c);
|
|
}
|
|
|
|
// make this thread sleep a bit
|
|
nanosleep(&slp, nil);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
int
|
|
main()
|
|
{
|
|
long max = 0;
|
|
int n = 0x7FFFFFFF;
|
|
|
|
struct timespec interval = { 0, 500000000 };
|
|
struct timespec timeout, now;
|
|
|
|
clock_gettime(CLOCK_REALTIME, &timeout);
|
|
timeout = timeadd(timeout, interval);
|
|
|
|
while(n--){
|
|
clock_gettime(CLOCK_REALTIME, &now);
|
|
if(timeafter(timeout, now)){
|
|
timeout = timeadd(timeout, interval);
|
|
printf("tick\n");
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
*/
|