summaryrefslogtreecommitdiff
path: root/frontends
diff options
context:
space:
mode:
authorChris Young <chris@unsatisfactorysoftware.co.uk>2016-08-09 18:36:09 +0100
committerChris Young <chris@unsatisfactorysoftware.co.uk>2016-08-09 18:36:09 +0100
commit1ca5b7332c2b10b671e6844b79ed58d50337ce52 (patch)
tree2cb1fbe16191d60c8157f9b83b276971ffa413e8 /frontends
parent94de23dce9b4cb490bcaf08433c6ba75abf4a29c (diff)
downloadnetsurf-1ca5b7332c2b10b671e6844b79ed58d50337ce52.tar.gz
netsurf-1ca5b7332c2b10b671e6844b79ed58d50337ce52.tar.bz2
Decouple the scheduler from system time
This is a hang-over from the old polling scheduler. I've modified it to use relative times and pass the callback along with the TimeRequest so events get executed in the order they arrive. The list of events is still in a heap sorted by expected execution time, but this may need to change to something more efficient for random lookups.
Diffstat (limited to 'frontends')
-rw-r--r--[-rwxr-xr-x]frontends/amiga/schedule.c123
1 files changed, 54 insertions, 69 deletions
diff --git a/frontends/amiga/schedule.c b/frontends/amiga/schedule.c
index f6145a19f..eaa307add 100755..100644
--- a/frontends/amiga/schedule.c
+++ b/frontends/amiga/schedule.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 - 2014 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008 - 2016 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -32,22 +32,21 @@
#include "amiga/misc.h"
#include "amiga/schedule.h"
-static struct TimeRequest *tioreq;
+struct nscallback
+{
+ struct TimeRequest timereq;
+ struct TimeVal tv; /* time we expect the event to occur */
+ void *restrict callback;
+ void *restrict p;
+};
+
+static struct nscallback *tioreq;
struct Device *TimerBase;
#ifdef __amigaos4__
struct TimerIFace *ITimer;
#endif
static APTR restrict pool_nscb = NULL;
-static APTR restrict pool_timereq = NULL;
-
-struct nscallback
-{
- struct TimeVal tv;
- void *restrict callback;
- void *restrict p;
- struct TimeRequest *treq;
-};
static PblHeap *schedule_list;
@@ -63,14 +62,10 @@ static void ami_schedule_remove_timer_event(struct nscallback *nscb)
{
if(!nscb) return;
- if(nscb->treq)
- {
- if(CheckIO((struct IORequest *)nscb->treq)==NULL)
- AbortIO((struct IORequest *)nscb->treq);
+ if(CheckIO((struct IORequest *)nscb)==NULL)
+ AbortIO((struct IORequest *)nscb);
- WaitIO((struct IORequest *)nscb->treq);
- ami_misc_itempool_free(pool_timereq, nscb->treq, sizeof(struct TimeRequest));
- }
+ WaitIO((struct IORequest *)nscb);
}
/**
@@ -87,25 +82,20 @@ static nserror ami_schedule_add_timer_event(struct nscallback *nscb, int t)
struct TimeVal tv;
ULONG time_us = t * 1000; /* t converted to µs */
- nscb->tv.Seconds = time_us / 1000000;
- nscb->tv.Microseconds = time_us % 1000000;
+ tv.Seconds = time_us / 1000000;
+ tv.Microseconds = time_us % 1000000;
- if(nscb->tv.Microseconds >= 1000000) {
+ if(tv.Microseconds >= 1000000) {
LOG("Microseconds invalid value: %ld", nscb->tv.Microseconds);
}
- GetSysTime(&tv);
- AddTime(&nscb->tv,&tv); // now contains time when event occurs
-
- if((nscb->treq = ami_misc_itempool_alloc(pool_timereq, sizeof(struct TimeRequest)))) {
- *nscb->treq = *tioreq;
- nscb->treq->Request.io_Command=TR_ADDREQUEST;
- nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs
- nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro
- SendIO((struct IORequest *)nscb->treq);
- } else {
- return NSERROR_NOMEM;
- }
+ GetSysTime(&nscb->tv);
+ AddTime(&nscb->tv, &tv); // now contains time when event occurs (for debug and heap sorting)
+
+ nscb->timereq.Request.io_Command = TR_ADDREQUEST;
+ nscb->timereq.Time.Seconds = tv.Seconds; // secs
+ nscb->timereq.Time.Microseconds = tv.Microseconds; // micro
+ SendIO((struct IORequest *)nscb);
return NSERROR_OK;
}
@@ -181,7 +171,7 @@ static nserror schedule_remove(void (*callback)(void *p), void *p)
nscb = ami_schedule_locate(callback, p, true);
if(nscb != NULL) {
- LOG("Event scheduled for following time was deleted: %ld.%ld", nscb->tv.Seconds, nscb->tv.Microseconds);
+ LOG("deleted callback %p", nscb);
ami_schedule_remove_timer_event(nscb);
ami_misc_itempool_free(pool_nscb, nscb, sizeof(struct nscallback));
pblHeapConstruct(schedule_list);
@@ -214,50 +204,39 @@ static int ami_schedule_compare(const void *prev, const void *next)
struct nscallback *nscb1 = *(struct nscallback **)prev;
struct nscallback *nscb2 = *(struct nscallback **)next;
+ /**\todo a heap probably isn't the best idea now */
return CmpTime(&nscb1->tv, &nscb2->tv);
}
/**
- * Process events up to current time.
+ * Process signalled event
*
- * This implementation only takes the top entry off the heap, it does not
- * venture to later scheduled events until the next time it is called -
- * immediately afterwards, if we're in a timer signalled loop.
+ * This implementation only processes the callback that arrives in the message from timer.device.
*/
-static bool ami_scheduler_run(void)
+static bool ami_scheduler_run(struct nscallback *nscb)
{
- struct nscallback *nscb;
- struct TimeVal tv;
void (*callback)(void *p);
void *p;
- nscb = pblHeapGetFirst(schedule_list);
- if(nscb == -1) {
- LOG("Scheduler has no tasks to run!");
- return false;
- }
-
- /* Ensure the scheduled event time has passed (CmpTime<=0)
- * in case something been deleted between the timer
- * signalling us and us responding to it.
- */
+ LOG("callback %p", nscb);
+
+ /*** vvv Debugging vvv ***/
+ struct TimeVal tv;
GetSysTime(&tv);
if(CmpTime(&tv, &nscb->tv) > 0) {
- LOG("Scheduled time of next event has not passed: %ld.%ld < %ld.%ld", tv.Seconds, tv.Microseconds, nscb->tv.Seconds, nscb->tv.Microseconds);
- return false;
+ LOG("Expected scheduled time of event has not passed: %ld.%ld < %ld.%ld", tv.Seconds, tv.Microseconds, nscb->tv.Seconds, nscb->tv.Microseconds);
}
-
+ /*** ^^^ Debugging ^^^ ***/
+
callback = nscb->callback;
p = nscb->p;
- ami_schedule_remove_timer_event(nscb);
- pblHeapRemoveFirst(schedule_list);
- ami_misc_itempool_free(pool_nscb, nscb, sizeof(struct nscallback));
+ schedule_remove(callback, p); /* this does a lookup as we don't know if we're the first item on the heap */
LOG("Running scheduled callback %p with arg %p", callback, p);
callback(p);
-
+ LOG("Callback finished...");
return true;
}
@@ -265,17 +244,17 @@ static void ami_schedule_open_timer(struct MsgPort *msgport)
{
#ifdef __amigaos4__
tioreq = (struct TimeRequest *)AllocSysObjectTags(ASOT_IOREQUEST,
- ASOIOR_Size,sizeof(struct TimeRequest),
+ ASOIOR_Size,sizeof(struct nscallback),
ASOIOR_ReplyPort,msgport,
ASO_NoTrack,FALSE,
TAG_DONE);
#else
- tioreq = (struct TimeRequest *)CreateIORequest(msgport, sizeof(struct TimeRequest));
+ tioreq = (struct nscallback *)CreateIORequest(msgport, sizeof(struct nscallback));
#endif
- OpenDevice("timer.device", UNIT_WAITUNTIL, (struct IORequest *)tioreq, 0);
+ OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)tioreq, 0);
- TimerBase = (struct Device *)tioreq->Request.io_Device;
+ TimerBase = (struct Device *)tioreq->timereq.Request.io_Device;
#ifdef __amigaos4__
ITimer = (struct TimerIFace *)GetInterface((struct Library *)TimerBase, "main", 1, NULL);
#endif
@@ -294,7 +273,7 @@ static void ami_schedule_close_timer(void)
nserror ami_schedule_create(struct MsgPort *msgport)
{
pool_nscb = ami_misc_itempool_create(sizeof(struct nscallback));
- pool_timereq = ami_misc_itempool_create(sizeof(struct TimeRequest));
+ if(pool_nscb == NULL) return NSERROR_NOMEM;
ami_schedule_open_timer(msgport);
schedule_list = pblHeapNew();
@@ -314,7 +293,6 @@ void ami_schedule_free(void)
ami_schedule_close_timer();
- ami_misc_itempool_delete(pool_timereq);
ami_misc_itempool_delete(pool_nscb);
}
@@ -323,6 +301,8 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p)
{
struct nscallback *nscb;
+ LOG("Scheduling callback %p with arg %p", callback, p);
+
if(schedule_list == NULL) return NSERROR_INIT_FAILED;
if(t < 0) return schedule_remove(callback, p);
@@ -333,6 +313,10 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p)
nscb = ami_misc_itempool_alloc(pool_nscb, sizeof(struct nscallback));
if(!nscb) return NSERROR_NOMEM;
+ LOG("new nscb");
+
+ *nscb = *tioreq;
+
if (ami_schedule_add_timer_event(nscb, t) != NSERROR_OK)
return NSERROR_NOMEM;
@@ -348,13 +332,14 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p)
/* exported interface documented in amiga/schedule.h */
void ami_schedule_handle(struct MsgPort *nsmsgport)
{
- /* nsmsgport is the NetSurf message port that the scheduler task
- * (or timer.device in no-async mode) is sending messages to. */
+ /* nsmsgport is the NetSurf message port that
+ * timer.device is sending messages to. */
- struct TimerRequest *timermsg;
+ struct nscallback *timermsg;
- while((timermsg = (struct TimerRequest *)GetMsg(nsmsgport))) {
- ami_scheduler_run();
+ while((timermsg = (struct nscallback *)GetMsg(nsmsgport))) {
+ LOG("timereq err = %d (should be 0)", timermsg->timereq.Request.io_Error);
+ ami_scheduler_run(timermsg);
}
}