summaryrefslogtreecommitdiff
path: root/amiga
diff options
context:
space:
mode:
authorChris Young <chris@unsatisfactorysoftware.co.uk>2014-11-22 16:24:26 +0000
committerChris Young <chris@unsatisfactorysoftware.co.uk>2014-11-22 16:27:39 +0000
commit2de1553a002aff7fa89bb466cdba1b3414413901 (patch)
tree2ad599d6f20e8280036b6d464d070fdeb1359071 /amiga
parentf8d8d218d8d5f7fdeb2edc0c5fa3f0a22e6d5a1b (diff)
downloadnetsurf-2de1553a002aff7fa89bb466cdba1b3414413901.tar.gz
netsurf-2de1553a002aff7fa89bb466cdba1b3414413901.tar.bz2
New scheduler
Diffstat (limited to 'amiga')
-rw-r--r--amiga/gui.c45
-rwxr-xr-xamiga/schedule.c179
-rwxr-xr-xamiga/schedule.h19
3 files changed, 186 insertions, 57 deletions
diff --git a/amiga/gui.c b/amiga/gui.c
index 0f5210179..461a20dab 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -167,6 +167,7 @@ struct ami_gui_tb_userdata {
int items;
};
+static struct MsgPort *schedulermsgport = NULL;
static struct MsgPort *appport;
static Class *urlStringClass;
@@ -416,7 +417,9 @@ static bool ami_open_resources(void)
ASO_NoTrack, FALSE,
TAG_DONE))) return false;
- ami_file_req_init();
+ if(!(schedulermsgport = AllocSysObjectTags(ASOT_PORT,
+ ASO_NoTrack, FALSE,
+ TAG_DONE))) return false;
return true;
}
@@ -2689,7 +2692,7 @@ void ami_get_msg(void)
{
ULONG winsignal = 1L << sport->mp_SigBit;
ULONG appsig = 1L << appport->mp_SigBit;
- ULONG schedulesig = 1L << schedulermsgport->mp_SigBit; /* \todo create schedulermsgport */
+ ULONG schedulesig = 1L << schedulermsgport->mp_SigBit;
ULONG ctrlcsig = SIGBREAKF_CTRL_C;
uint32 signal = 0;
fd_set read_fd_set, write_fd_set, except_fd_set;
@@ -2741,11 +2744,8 @@ void ami_get_msg(void)
ami_print_cont();
}
- if(signal & schedulesig) { /* \todo rewrite */
- while((timermsg = (struct TimerRequest *)GetMsg(msgport))) {
- ReplyMsg((struct Message *)timermsg);
- schedule_run();
- }
+ if(signal & schedulesig) {
+ ami_schedule_handle(schedulermsgport);
}
if(signal & helpsignal)
@@ -2993,17 +2993,17 @@ static void gui_quit(void)
ami_mouse_pointers_free();
LOG(("Freeing clipboard"));
ami_clipboard_free();
+ LOG(("Removing scheduler process"));
+ ami_scheduler_process_delete();
- FreeSysObject(ASOT_PORT,appport);
- FreeSysObject(ASOT_PORT,sport);
+ FreeSysObject(ASOT_PORT, appport);
+ FreeSysObject(ASOT_PORT, sport);
+ FreeSysObject(ASOT_PORT, schedulermsgport);
ami_file_req_free();
ami_openurl_close();
FreeStringClass(urlStringClass);
- LOG(("Freeing scheduler"));
- ami_schedule_free();
-
FreeObjList(window_list);
FreeVec(current_user_options);
@@ -5347,6 +5347,16 @@ int main(int argc, char** argv)
CloseLibrary(PopupMenuBase);
}
+ if (ami_open_resources() == false) { /* alloc message ports */
+ ami_misc_fatal_error("Unable to allocate resources");
+ return RETURN_FAIL;
+ }
+
+ if(ami_scheduler_process_create(schedulermsgport) != NSERROR_OK) {
+ ami_misc_fatal_error("Failed to initialise scheduler");
+ return RETURN_FAIL;
+ }
+
user = GetVar("user", temp, 1024, GVF_GLOBAL_ONLY);
current_user = ASPrintf("%s", (user == -1) ? "Default" : temp);
current_user_dir = ASPrintf("PROGDIR:Users/%s", current_user);
@@ -5364,11 +5374,6 @@ int main(int argc, char** argv)
ami_mime_init("PROGDIR:Resources/mimetypes");
sprintf(temp, "%s/mimetypes.user", current_user_dir);
ami_mime_init(temp);
- if(ami_schedule_create() == false) {
- ami_misc_fatal_error("Failed to initialise scheduler");
- return RETURN_FAIL;
- }
-
amiga_plugin_hack_init();
ret = amiga_datatypes_init();
@@ -5395,11 +5400,6 @@ int main(int argc, char** argv)
if(current_user_cache != NULL) FreeVec(current_user_cache);
ret = amiga_icon_init();
- if (ami_open_resources() == false) { /* alloc ports/asl reqs, open libraries/devices */
- ami_misc_fatal_error("Unable to allocate resources");
- return RETURN_FAIL;
- }
-
search_web_init(nsoption_charp(search_engines_file));
ami_clipboard_init();
ami_openurl_open();
@@ -5409,6 +5409,7 @@ int main(int argc, char** argv)
save_complete_init();
ami_theme_init();
ami_init_mouse_pointers();
+ ami_file_req_init();
win_destroyed = false;
ami_font_setdevicedpi(0); /* for early font requests, eg treeview init */
diff --git a/amiga/schedule.c b/amiga/schedule.c
index fa6de688d..607c3d8e5 100755
--- a/amiga/schedule.c
+++ b/amiga/schedule.c
@@ -18,6 +18,7 @@
#include "amiga/os3support.h"
+#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/timer.h>
@@ -26,9 +27,11 @@
#include <pbl.h>
#include "utils/errors.h"
+#include "utils/log.h"
#include "amiga/schedule.h"
+static struct MsgPort *smsgport = NULL; /* to send messages for the scheduler to */
static struct TimeRequest *tioreq;
struct Device *TimerBase;
struct TimerIFace *ITimer;
@@ -44,11 +47,14 @@ struct nscallback
struct ami_schedule_message {
struct Message msg;
int type;
- struct nscallback *nscb;
-}
+ int t;
+ void *callback;
+ void *p;
+};
enum {
AMI_S_SCHEDULE = 0,
+ AMI_S_RUN,
AMI_S_STARTUP,
AMI_S_EXIT
};
@@ -217,13 +223,35 @@ static int ami_schedule_compare(const void *prev, const void *next)
}
-/* exported function documented in amiga/schedule.h */
-void schedule_run(void)
+/**
+ * Process events up to current time.
+ * NetSurf entry point after being signalled by the scheduler process.
+ */
+static void schedule_run(struct ami_schedule_message *asmsg)
+{
+ void (*callback)(void *p) = asmsg->callback;
+ void *p = asmsg->p;
+
+ callback(p);
+}
+
+/**
+ * Process events up to current time.
+ *
+ * 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.
+ */
+static void ami_scheduler_run(struct MsgPort *nsmsgport)
{
struct nscallback *nscb;
void (*callback)(void *p);
void *p;
+ struct ami_schedule_message *asmsg = AllocSysObjectTags(ASOT_MESSAGE,
+ ASOMSG_Size, sizeof(struct ami_schedule_message),
+ TAG_END);
+
nscb = pblHeapGetFirst(schedule_list);
if(nscb == -1) return;
@@ -232,9 +260,17 @@ void schedule_run(void)
ami_schedule_remove_timer_event(nscb);
pblHeapRemoveFirst(schedule_list);
FreeVec(nscb);
- callback(p);
+
+ asmsg->type = AMI_S_RUN;
+ asmsg->callback = callback;
+ asmsg->p = p;
+
+ PutMsg(nsmsgport, (struct Message *)asmsg);
+
+ return;
}
+
static struct MsgPort *ami_schedule_open_timer(void)
{
struct MsgPort *msgport = AllocSysObjectTags(ASOT_PORT,
@@ -268,7 +304,7 @@ static void ami_schedule_close_timer(struct MsgPort *msgport)
*
* /return true if initialised ok or false on error.
*/
-struct MsgPort *ami_schedule_create(void)
+static struct MsgPort *ami_schedule_create(void)
{
struct MsgPort *msgport = ami_schedule_open_timer();
schedule_list = pblHeapNew();
@@ -283,7 +319,7 @@ struct MsgPort *ami_schedule_create(void)
* Finalise amiga scheduler
*
*/
-void ami_schedule_free(struct MsgPort *msgport)
+static void ami_schedule_free(struct MsgPort *msgport)
{
schedule_remove_all();
pblHeapFree(schedule_list); // this should be empty at this point
@@ -295,40 +331,86 @@ void ami_schedule_free(struct MsgPort *msgport)
/* exported function documented in amiga/schedule.h */
nserror ami_schedule(int t, void (*callback)(void *p), void *p)
{
+ if(smsgport == NULL) return NSERROR_INIT_FAILED;
+
+ struct ami_schedule_message *asmsg = AllocSysObjectTags(ASOT_MESSAGE,
+ ASOMSG_Size, sizeof(struct ami_schedule_message),
+ TAG_END);
+
+ asmsg->type = AMI_S_SCHEDULE;
+ asmsg->t = t;
+ asmsg->callback = callback;
+ asmsg->p = p;
+
+ PutMsg(smsgport, (struct Message *)asmsg);
+
+ return NSERROR_OK;
+}
+
+static nserror ami_scheduler_schedule(struct ami_schedule_message *asmsg)
+{
struct nscallback *nscb;
if(schedule_list == NULL) return NSERROR_INIT_FAILED;
- if (t < 0) return schedule_remove(callback, p);
-
- if ((nscb = ami_schedule_locate(callback, p, false))) {
- return ami_schedule_reschedule(nscb, t);
+ if (asmsg->t < 0) return schedule_remove(asmsg->callback, asmsg->p);
+
+ if ((nscb = ami_schedule_locate(asmsg->callback, asmsg->p, false))) {
+ return ami_schedule_reschedule(nscb, asmsg->t);
}
nscb = AllocVecTagList(sizeof(struct nscallback), NULL);
if(!nscb) return NSERROR_NOMEM;
- if (ami_schedule_add_timer_event(nscb, t) != NSERROR_OK)
+ if (ami_schedule_add_timer_event(nscb, asmsg->t) != NSERROR_OK)
return NSERROR_NOMEM;
- nscb->callback = callback;
- nscb->p = p;
+ nscb->callback = asmsg->callback;
+ nscb->p = asmsg->p;
pblHeapInsert(schedule_list, nscb);
return NSERROR_OK;
}
+/* exported interface documented in amiga/schedule.h */
+void ami_schedule_handle(struct MsgPort *nsmsgport)
+{
+ /* nsmsgport is the NetSurf message port that the
+ * scheduler task is sending messages to. */
+ struct ami_schedule_message *asmsg;
+
+ while((asmsg = (struct ami_schedule_message *)GetMsg(nsmsgport))) {
+ if(asmsg->msg.mn_Node.ln_Type == NT_REPLYMSG) {
+ /* if it's a reply, free stuff */
+ FreeSysObject(ASOT_MESSAGE, asmsg);
+ } else {
+ switch(asmsg->type) {
+ case AMI_S_STARTUP:
+ smsgport = asmsg->msg.mn_ReplyPort;
+ break;
+
+ case AMI_S_RUN:
+ schedule_run(asmsg);
+ break;
+
+ default:
+ // unknown message
+ break;
+ }
+ FreeSysObject(ASOT_MESSAGE, asmsg); /* don't reply, just free */
+ }
+ }
+}
static int32 ami_scheduler_process(STRPTR args, int32 length, APTR execbase)
{
struct Process *proc = (struct Process *)FindTask(NULL);
struct MsgPort *nsmsgport = proc->pr_Task.tc_UserData;
- struct MsgPort *schedulermsgport = IExec->AllocSysObjectTags(ASOT_PORT, TAG_END);
+ struct MsgPort *schedulermsgport = AllocSysObjectTags(ASOT_PORT, TAG_END);
struct MsgPort *timermsgport = ami_schedule_create();
bool running = true;
struct TimerRequest *timermsg = NULL;
- struct ami_schedule_message *schedulemsg = NULL;
ULONG schedulesig = 1L << schedulermsgport->mp_SigBit;
ULONG timersig = 1L << timermsgport->mp_SigBit;
uint32 signalmask = schedulesig | timersig;
@@ -337,13 +419,13 @@ static int32 ami_scheduler_process(STRPTR args, int32 length, APTR execbase)
/* Send a startup message to the message port we were given when we were created.
* This tells NetSurf where to send scheduler events to. */
- struct ami_schedule_message *asmsg = IExec->AllocSysObjectTags(ASOT_MESSAGE,
+ struct ami_schedule_message *asmsg = AllocSysObjectTags(ASOT_MESSAGE,
ASOMSG_Size, sizeof(struct ami_schedule_message),
ASOMSG_ReplyPort, schedulermsgport,
TAG_END);
- asmsg.type = AMI_S_STARTUP;
- PutMsg(nsmsgport, asmsg);
+ asmsg->type = AMI_S_STARTUP;
+ PutMsg(nsmsgport, (struct Message *)asmsg);
/* Main loop for this process */
@@ -352,18 +434,32 @@ static int32 ami_scheduler_process(STRPTR args, int32 length, APTR execbase)
if(signal & timersig) {
while((timermsg = (struct TimerRequest *)GetMsg(timermsgport))) {
- schedule_run(); /* \todo get top scheduled event and signal nsmsgport to run the callback */
- ReplyMsg((struct Message *)timermsg);
+ ami_scheduler_run(nsmsgport);
+ //ReplyMsg((struct Message *)timermsg); /* \todo why does this crash? */
}
}
if(signal & schedulesig) {
while((asmsg = (struct ami_schedule_message *)GetMsg(schedulermsgport))) {
- /* \todo if it's a reply, free stuff
- if(asmsg->nscb) FreeVec(asmg->nscb);
- FreeSysObject(ASOT_Message, asmsg);
- */
- //ReplyMsg((struct Message *)asmsg);
+ if(asmsg->msg.mn_Node.ln_Type == NT_REPLYMSG) {
+ /* if it's a reply, free stuff */
+ FreeSysObject(ASOT_MESSAGE, asmsg);
+ } else {
+ switch(asmsg->type) {
+ case AMI_S_SCHEDULE:
+ ami_scheduler_schedule(asmsg);
+ break;
+
+ case AMI_S_EXIT:
+ running = false;
+ break;
+
+ default:
+ // unknown message
+ break;
+ }
+ FreeSysObject(ASOT_MESSAGE, asmsg); /* don't reply, just free */
+ }
}
}
}
@@ -382,9 +478,11 @@ static int32 ami_scheduler_process(STRPTR args, int32 length, APTR execbase)
*/
nserror ami_scheduler_process_create(struct MsgPort *nsmsgport)
{
+ if(nsmsgport == NULL) return NSERROR_INIT_FAILED;
+
struct Process *proc = CreateNewProcTags(
NP_Name, "NetSurf scheduler",
- NP_Entry, ami_schedule_process,
+ NP_Entry, ami_scheduler_process,
NP_Child, TRUE,
NP_StackSize, 16384,
NP_Priority, 1,
@@ -395,6 +493,33 @@ nserror ami_scheduler_process_create(struct MsgPort *nsmsgport)
return NSERROR_NOMEM;
}
+ LOG(("Waiting for scheduler process to start up..."));
+
+ WaitPort(nsmsgport);
+ struct ami_schedule_message *asmsg = (struct ami_schedule_message *)GetMsg(nsmsgport);
+
+ if(asmsg->type == AMI_S_STARTUP) { /* We shouldn't get any other messages at this stage */
+ smsgport = asmsg->msg.mn_ReplyPort;
+ ReplyMsg((struct Message *)asmsg);
+ }
+
+ LOG(("Scheduler started"));
+
return NSERROR_OK;
}
+/* exported function documented in amiga/schedule.h */
+void ami_scheduler_process_delete(void)
+{
+ if(smsgport == NULL) return;
+
+ struct ami_schedule_message *asmsg = AllocSysObjectTags(ASOT_MESSAGE,
+ ASOMSG_Size, sizeof(struct ami_schedule_message),
+ TAG_END);
+
+ asmsg->type = AMI_S_EXIT;
+ PutMsg(smsgport, (struct Message *)asmsg);
+
+ return;
+}
+
diff --git a/amiga/schedule.h b/amiga/schedule.h
index 70255a96e..cfea4d917 100755
--- a/amiga/schedule.h
+++ b/amiga/schedule.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ * Copyright 2008-2014 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -34,20 +34,23 @@
nserror ami_schedule(int t, void (*callback)(void *p), void *p);
/**
- * Process events up to current time.
+ * Handle a message received from the scheduler process.
*
- * 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.
+ * \param nsmsgport Message port to process.
*/
-void schedule_run(void);
+void ami_schedule_handle(struct MsgPort *nsmsgport);
/**
* Create a new process for the scheduler.
*
- * \param nsmsgport Message port to send timer events to.
- * \return NSERROR_OK on success or error code on faliure.
+ * \param nsmsgport Message port for the scheduler to send events to.
+ * \return NSERROR_OK on success or error code on failure.
*/
nserror ami_scheduler_process_create(struct MsgPort *nsmsgport);
+
+/**
+ * Signal the scheduler process to exit.
+ */
+void ami_scheduler_process_delete(void);
#endif