summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn-Mark Bell <jmb@netsurf-browser.org>2023-12-27 02:46:49 +0000
committerJohn-Mark Bell <jmb@netsurf-browser.org>2024-03-14 00:09:58 +0000
commit9e4f598b7b2f6f92304f5f9e4ed359e7905b37a9 (patch)
tree7a5dd0f2772e2c37a7926dcba9d73d042a15b498
parent98b3d3c191fe9097cd4b8d67060aebcea095a85d (diff)
downloadnetsurf-9e4f598b7b2f6f92304f5f9e4ed359e7905b37a9.tar.gz
netsurf-9e4f598b7b2f6f92304f5f9e4ed359e7905b37a9.tar.bz2
RISC OS: use SocketWatch for socket activity
Use SocketWatch to monitor our sockets and convert activity into a pollword update. This allows us to ditch the schedule-based fetch path and take the same one as we do on other platforms. This also allows us to refactor the main poll loop such that we need only poll idle while waiting for things to happen (once something has happened, we poll aggressively until there are no non-pollword events left).
-rw-r--r--frontends/riscos/gui.c203
-rw-r--r--frontends/riscos/scripts/Run4
2 files changed, 177 insertions, 30 deletions
diff --git a/frontends/riscos/gui.c b/frontends/riscos/gui.c
index 1a2b944a8..56296951f 100644
--- a/frontends/riscos/gui.c
+++ b/frontends/riscos/gui.c
@@ -26,8 +26,10 @@
#include <assert.h>
#include <errno.h>
#include <signal.h>
+#include <unistd.h>
#include <unixlib/local.h>
#include <fpu_control.h>
+#include <swis.h>
#include <oslib/help.h>
#include <oslib/uri.h>
#include <oslib/inetsuite.h>
@@ -38,6 +40,7 @@
#include <oslib/osbyte.h>
#include <oslib/osmodule.h>
#include <oslib/osfscontrol.h>
+#include <oslib/socket.h>
#include "utils/utils.h"
#include "utils/nsoption.h"
@@ -57,6 +60,7 @@
#include "desktop/save_complete.h"
#include "desktop/hotlist.h"
#include "content/backing_store.h"
+#include "content/fetch.h"
#include "riscos/gui.h"
#include "riscos/bitmap.h"
@@ -113,11 +117,14 @@ static const char *task_name = "NetSurf";
ro_gui_drag_type gui_current_drag_type;
wimp_t task_handle; /**< RISC OS wimp task handle. */
-static clock_t gui_last_poll; /**< Time of last wimp_poll. */
osspriteop_area *gui_sprites; /**< Sprite area containing pointer and hotlist sprites */
#define DIR_SEP ('.')
+static void *pollword;
+static int *sockets_active;
+static size_t sockets_active_size;
+
/**
* Accepted wimp user messages.
*/
@@ -388,6 +395,19 @@ static void ro_gui_cleanup(void)
xhourglass_off();
/* Uninstall NetSurf-specific fonts */
xos_cli("FontRemove NetSurf:Resources.Fonts.");
+ if (pollword != NULL) {
+ size_t i;
+ /* Deregister any remaining sockets from SocketWatch */
+ for (i = 0; i < sockets_active_size; i++) {
+ if (sockets_active[i] != -1) {
+ /* SocketWatch_Deregister */
+ (void) _swix(0x52281, _INR(0,1),
+ sockets_active[i], pollword);
+ sockets_active[i] = -1;
+ }
+ }
+ xosmodule_free(pollword);
+ }
}
@@ -1113,6 +1133,101 @@ static bool ro_gui__os_alpha_sprites_supported(void)
return (var_val == (1 << 15));
}
+static int ro_gui_socket_open(int domain, int type, int protocol)
+{
+ int sock = socket(domain, type, protocol);
+ if (sock != -1) {
+ size_t i;
+ int rosock;
+ _kernel_oserror *error;
+
+ rosock = __get_ro_socket(sock);
+ if (rosock == -1) {
+ close(sock);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* SocketWatch_Register */
+ error = _swix(0x52280, _INR(0,2), pollword, 0x1, rosock);
+ if (error != NULL) {
+ close(sock);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Insert RISC OS socket handle into sockets_active */
+ for (i = 0; i < sockets_active_size; i++) {
+ if (sockets_active[i] == -1) {
+ sockets_active[i] = rosock;
+ break;
+ }
+ }
+ if (i == sockets_active_size) {
+ /* No free slots: expand table */
+ int *tmp = realloc(sockets_active,
+ sockets_active_size * 2 * sizeof(int));
+ if (tmp == NULL) {
+ /* SocketWatch_Deregister */
+ (void) _swix(0x52281, _INR(0,1), rosock, pollword);
+ close(sock);
+ errno = ENOMEM;
+ return -1;
+ }
+ memset(sockets_active + sockets_active_size, 0xff,
+ sockets_active_size * sizeof(int));
+ sockets_active_size *= 2;
+ sockets_active[i] = rosock;
+ }
+ }
+ return sock;
+}
+
+static int ro_gui_socket_close(int socket)
+{
+ int rosock;
+
+ rosock = __get_ro_socket(socket);
+ if (rosock != -1) {
+ size_t i;
+ /* Invalidate active sockets entry */
+ for (i = 0; i < sockets_active_size; i++) {
+ if (sockets_active[i] == rosock) {
+ sockets_active[i] = -1;
+ break;
+ }
+ }
+ /* SocketWatch_Deregister */
+ (void) _swix(0x52281, _INR(0,1), rosock, pollword);
+ }
+
+ return close(socket);
+}
+
+/**
+ * Set up internet event handling
+ */
+static os_error *ro_gui_init_internet_event(void)
+{
+ static os_error nomem = { 1, "No memory"};
+ os_error *error;
+
+ sockets_active = malloc(32 * sizeof(int));
+ if (sockets_active == NULL) {
+ return &nomem;
+ }
+ memset(sockets_active, 0xff, 32 * sizeof(int));
+ sockets_active_size = 32;
+
+ error = xosmodule_alloc(4, &pollword);
+ if (error != NULL) {
+ return error;
+ }
+
+ *((uint32_t*) pollword) = 0;
+ return NULL;
+}
+
/**
* Initialise the RISC OS specific GUI.
*
@@ -1214,6 +1329,14 @@ static nserror gui_init(int argc, char** argv)
urldb_load(nsoption_charp(url_path));
urldb_load_cookies(nsoption_charp(cookie_file));
+ /* Setup Internet event handling (must be after atexit) */
+ error = ro_gui_init_internet_event();
+ if (error != NULL) {
+ NSLOG(netsurf, INFO, "init_internet_event: 0x%x: %s",
+ error->errnum, error->errmess);
+ die(error->errmess);
+ }
+
/* Initialise with the wimp */
error = xwimp_initialise(wimp_VERSION_RO38, task_name,
PTR_WIMP_MESSAGE_LIST(&task_messages), 0,
@@ -1837,6 +1960,14 @@ static void ro_gui_handle_event(wimp_event_no event, wimp_block *block)
ro_gui_scroll(&(block->scroll));
break;
+ case wimp_POLLWORD_NON_ZERO:
+ /* simply reset pollword */
+ if (pollword != NULL) {
+ /* SocketWatch_AtomicReset */
+ _swix(0x52282, _INR(0,1), pollword, 0);
+ }
+ break;
+
case wimp_USER_MESSAGE:
case wimp_USER_MESSAGE_RECORDED:
case wimp_USER_MESSAGE_ACKNOWLEDGE:
@@ -1853,44 +1984,54 @@ static void riscos_poll(void)
{
wimp_event_no event;
wimp_block block;
- const wimp_poll_flags mask = wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_SAVE_FP;
- os_t track_poll_offset;
+ const wimp_poll_flags mask = wimp_MASK_LOSE | wimp_MASK_GAIN |
+ wimp_GIVEN_POLLWORD | wimp_SAVE_FP;
+ os_t t, track_poll_offset;
- /* Poll wimp. */
- xhourglass_off();
- track_poll_offset = ro_mouse_poll_interval();
- if (sched_active || (track_poll_offset > 0)) {
- os_t t = os_read_monotonic_time();
+ /* Drain pending non-pollword events until the first NULL event */
+ do {
+ xhourglass_off();
+ event = wimp_poll(wimp_MASK_POLLWORD | mask, &block, pollword);
+ xhourglass_on();
- if (track_poll_offset > 0) {
- t += track_poll_offset;
- } else {
- t += 10;
- }
+ ro_gui_handle_event(event, &block);
+ } while (event != wimp_NULL_REASON_CODE);
- if (sched_active && (sched_time - t) < 0) {
- t = sched_time;
- }
+ /* Redraw window contents */
+ ro_gui_window_update_boxes();
+
+ /* Run scheduled callbacks, if any */
+ schedule_run();
+
+ /* Drive any active fetches. */
+ {
+ fd_set read_fd_set, write_fd_set, exc_fd_set;
+ int max_fd;
+
+ fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
+ }
- event = wimp_poll_idle(mask, &block, t, 0);
+ /* Poll wimp in the ordinary way. */
+ xhourglass_off();
+ t = os_read_monotonic_time();
+ track_poll_offset = ro_mouse_poll_interval();
+ /* Work out how long we're prepared to wait for an event */
+ if (track_poll_offset > 0) {
+ t += track_poll_offset;
+ } else if (sched_active) {
+ t += 10;
} else {
- event = wimp_poll(wimp_MASK_NULL | mask, &block, 0);
+ t += 100;
+ }
+ /* And then clamp that to min(sched_time, t) */
+ if (sched_active && (sched_time - t) < 0) {
+ t = sched_time;
}
+ event = wimp_poll_idle(mask, &block, t, pollword);
+
xhourglass_on();
- gui_last_poll = clock();
ro_gui_handle_event(event, &block);
-
- /* Only run scheduled callbacks on a null poll
- * We cannot do this in the null event handler, as that may be called
- * from gui_multitask(). Scheduled callbacks must only be run from the
- * top-level.
- */
- if (event == wimp_NULL_REASON_CODE) {
- schedule_run();
- }
-
- ro_gui_window_update_boxes();
}
@@ -2389,6 +2530,8 @@ static struct gui_fetch_table riscos_fetch_table = {
.get_resource_url = gui_get_resource_url,
.mimetype = fetch_mimetype,
+ .socket_open = ro_gui_socket_open,
+ .socket_close = ro_gui_socket_close,
};
static struct gui_misc_table riscos_misc_table = {
diff --git a/frontends/riscos/scripts/Run b/frontends/riscos/scripts/Run
index 3368140d2..233322e39 100644
--- a/frontends/riscos/scripts/Run
+++ b/frontends/riscos/scripts/Run
@@ -95,6 +95,10 @@ RMEnsure Iconv 0.12 Error NetSurf requires Iconv 0.12 or later. Please use the R
RMEnsure CryptRandom 0.13 NetSurfRMLoad System:Modules.CryptRand
RMEnsure CryptRandom 0.13 Error NetSurf requires CryptRandom 0.13 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+| Ensure SocketWatch
+RMEnsure SocketWatch 0.07 NetSurfRMLoad System:Modules.Network.SockWatch
+RMEnsure SocketWatch 0.07 Error NetSurf requires SocketWatch 0.07 or later. Please use the RISC OS Configure app to update the computer's !System directory from the NetSurf archive.
+
| Disable SpecialFX, if present
Set NetSurf$SpecialFX 1
RMEnsure SpecialFX 1.00 Set NetSurf$SpecialFX 0