Commit 0c1ebc20 authored by Ben Avison's avatar Ben Avison

Added Dan Ellis's multithreading support, on a development branch for now.

Detail:
  This breaks the equivalence between tasks and AMB slots, allowing many
  threads of execution to share the same AMB slot, where an application's
  heap is usually located. In API terms, it is presented as an extension to
  Wimp_StartTask, see Docs/Multithreading for more information. It is the
  caller's responsibility to create a new stack chunk for the new thread if
  required. Note that BASIC's variable storage model is fundamentally
  unsuited for multithreading.
Admin:
  This was developed in 2001 and was not committed at the time due to lack
  of testing and peer review. It is now being added as a branch from a
  contemporary trunk Wimp. Hopefully somebody will be interested enough to
  merge the branch into a recent version!

Version 4.66, 4.77.2.1. Tagged as 'Wimp-4_66-4_77_2_1'
parent 604d85c3
......@@ -3,3 +3,4 @@ s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
**/s/** gitlab-language=armasm linguist-language=armasm linguist-detectable=true
*,ffb gitlab-language=bbcbasic linguist-language=bbcbasic linguist-detectable=true
**/c/** gitlab-language=c linguist-language=c linguist-detectable=true
**/h/** gitlab-language=c linguist-language=c linguist-detectable=true
Daniel Ellis Fri 10th August 2001
Multi-threading in the Wimp
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Introduction
~~~~~~~~~~~~
Many software tasks are made easier by being modelled as multiple threads of
execution each dedicated to their own task, especially if each thread can
indepentantly block on system events. This can be achieved in Wimps up to
version 4 only by starting an entirely different process, and communicating
via Wimp_TransferBlock and Wimp_Messages. This is not always sufficient,
especially for porting 3rd party software.
In principle starting a new thread is the same as starting a new process,
except that the memory isn't paged out, and no new memory needs paging in.
The only complication being that the memory needs reference counting so that
it doesn't get released multiple times when each thread exits.
Issues
~~~~~~
Starting a thread is done via Wimp_StartTask. However, since we are in the
same address space, the notion of a task has to change. Existing tasks each
have their own AMBControl block, this has to be abstracted to an application
pointer, a structure which contains the AMBControl block, and a reference
count for the number of tasks using it.
Wherever, previously a task_slotptr was referred to, now that pointer must
be dereferenced and a, app_slotptr referred to instead.
API
~~~
The suggested mechanism for starting a new thread is via Wimp_StartTask, as
this almost does what's needed already. Normally Wimp_StartTask takes as a
parameter a pointer to a string which is passed to OSCLI in the new wimp slot
allocated. The new variant is:
SWI Wimp_StartTask
In:
R0 = 0 (Start thread)
Out:
R0 = 0 if thread has exited,
task handle of thread if it has called wimp poll
-1 if we are the thread.
Use:
This call is used to start a new thread of execution within the same
address space as the current application. It returns twice, once for the
parent and once for the child.
SWI TaskWindow_Initialise
In:
R0 = pointer to name of thread
Out:
R0 = 0 if thread has exited,
handle of new thread if it is still alive
-1 if we are the thread
Use:
This call starts up the taskwindow module in the current address space.
It calls Wimp_StartTask 0 and Wimp_Initialise on the callers behalf.
Future enhancements
It has been proposed that the Message_TaskInitialise mechanism is extended
so that the Task Manager can display threads distinctly from applications.
......@@ -40,6 +40,10 @@ RESOURCES = manual
ASFLAGS = -cpu 3 -NoWarn -PreDefine "Options SETS \"${OPTIONS}\""
AIFDBG ?= aif.${MACHINE}.${TARGET}
GPADBG ?= gpa.${MACHINE}.${TARGET}
ASFLAGS += -G
include StdTools
include AAsmModule
......@@ -68,4 +72,13 @@ bbe-wimp: bbe-generic-resources-get-alias
BBE_Export_File_In_Dir Resources.${LOCALE} CmdHelp
BBE_Export_Dir Resources.${LOCALE}.${USERIF}
${AIFDBG}: ${ROM_OBJECT}
${MKDIR} aif.${MACHINE}
${LD} -aif -bin -d -o ${AIFDBG} ${ROM_OBJECT}
${GPADBG}: ${AIFDBG}
${MKDIR} gpa.${MACHINE}
ToGPA -s ${AIFDBG} ${GPADBG}
# Dynamic dependencies:
......@@ -97,5 +97,6 @@
OptionD sprprior, false ; ROM vs RAM sprite priority
OptionD autoscr, false ; autoscrolling / drags within windows
OptionD poll2, false ; stages through Wimp_Poll
OptionD thread, true ; thread specific debug
END
......@@ -86,5 +86,6 @@
Option RegisterSprites, false
Option RegisterSprites22, false
Option RegisterTemplates, false
Option Threads, false
END
......@@ -31,6 +31,7 @@ module_postfix SETS " 32-bit"
Option StickyEdges, false ; unimplemented ; Allow windows to "stick" when dragged over edge of screen
Option MultiClose, true ; Allow Ctrl-Alt clicks on close/iconise buttons
Option PushBothBars, true ; Push in both scrollbars on adjust-drags
Option Threads, true ; Supply multithreading support
ASSERT International_Help <> 0
......
......@@ -28,6 +28,7 @@ module_postfix SETS " RISC OS 3.7"
Option StickyEdges, false ; unimplemented ; Allow windows to "stick" when dragged over edge of screen
Option MultiClose, true ; Allow Ctrl-Alt clicks on close/iconise buttons
Option PushBothBars, true ; Push in both scrollbars on adjust-drags
Option Threads, true
ASSERT International_Help <> 0
......
......@@ -35,6 +35,7 @@ module_postfix SETS " Ursula"
Option StickyEdges, false ; unimplemented ; Allow windows to "stick" when dragged over edge of screen
Option MultiClose, true ; Allow Ctrl-Alt clicks on close/iconise buttons
Option PushBothBars, true ; Push in both scrollbars on adjust-drags
Option Threads, true ; Supply multithreading support
ASSERT International_Help <> 0
......
| Copyright 2007 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu_machine all THROWBACK=-throwback
| Copyright 2007 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
| Taskobey file to make NCMAlite as a standalone module with no debugging.
Dir <Obey$Dir>
amu_machine clean THROWBACK=-throwback
| Copyright 2007 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
Dir <Obey$Dir>
amu_machine all DEBUG=-DDEBUGLIB THROWBACK=-throwback
| Copyright 2007 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
|{ > null: }WimpTask TaskWindow -display -quit -name "Output" -wimpslot 0 "type pipe:out"
WimpSlot -min 128k -max 128k
Run <Obey$Dir>.!Runimage 2> null:
# Copyright 2007 Castle Technology Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Makefile
#
# Standard makefile elements
#
COMPONENT = !RunImage
TARGET = ${COMPONENT}
DIRS = o._dirs
OBJS = o.thread_init o.start_thread o.test
BASE_LIBS = ${CLIB} ${TBOXLIBS} ${DEBUGLIB} ${NET5LIBS} ${CALLXLIB}
LIBS = ${BASE_LIBS}
include StdTools
include AppStdRule
include AppLibs
#
# Debug targets
#
AIFDBG = aif.${COMPONENT}
GPADBG = gpa.${COMPONENT}
CFLAGS += -throwback -g
CINCLUDES = -IOS:,C:,tbox:,tcpiplibs:
ASFLAGS += -G
CDEFINES += ${DEBUG}
all: ${TARGET}
@${ECHO} ${COMPONENT}: app built
#
# Actually make the linked RAM target
#
${TARGET}: ${OBJS} ${LIBS} ${CLIB} ${DIRS} ${RAM_DEPEND}
${LD} ${LDFLAGS} ${LDRAMFLAGS} -o $@ ${OBJS} ${LIBS}
${CHMOD} -R a+rx rm
${AIFDBG}: ${OBJS} ${LIBS} ${DIRS}
link -base 0 -aif -bin -d -o $@ ${OBJS} ${LIBS}
${GPADBG}: ${AIFDBG}
togpa ${AIFDBG} $@
exception: ${GPADBG}
unmodsqz ${RAM_MODULE}
@find_error ${COMPONENT}
clean:
${WIPE} o ${WFLAGS}
${WIPE} aif ${WFLAGS}
${WIPE} gpa ${WFLAGS}
stripdepnd
o._dirs:
${MKDIR} o
${MKDIR} h
${MKDIR} gpa
${MKDIR} aif
${TOUCH} o._dirs
riscos.o: modhead.h
# Dynamic dependencies:
/* Copyright 2007 Castle Technology Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <string.h>
#include "kernel.h"
#include "wimplib.h"
#include "stdlib.h"
#include "swis.h"
#include "Global/EnvNumbers.h"
#define CHUNK_MAGIC 0xf60690ff
extern void thread_init (void);
extern void enter_taskwindow (char*);
extern void exit_handler (void);
extern void upcall_handler (void);
int null = 0;
void start_thread (const char* name, void (entry) (void*), int priority, int stack_size, void* txt, int* task_handle) {
char buf[255];
WimpSysInfo info;
int old_upcall_handler;
_kernel_stack_chunk* sc = calloc ((size_t) stack_size, 1);
if (sc == 0) {
abort ();
return ;
}
wimp_read_sys_info (5, &info);
memcpy (sc + 1, _kernel_current_stack_chunk () + 1, 28);
sc->sc_mark = CHUNK_MAGIC;
sc->sc_size = stack_size;
((int*) sc)[stack_size / 4 - 1] = (int) entry;
sprintf (buf,
"-nice %d -quit -name \"%s\" -txt &%x -task &%x \"go &%x; &%x\"",
priority, name, (int) txt, info.r0, (int) thread_init, (int) sc);
// sprintf (buf, "-display");
_swix (OS_ChangeEnvironment, _INR(0,1) | _OUT(1),
UpCallHandler,
upcall_handler,
&old_upcall_handler);
wimp_start_task (0, task_handle);
if (*task_handle == -1) {
wimp_close_down (0);
_swix (OS_ChangeEnvironment, _INR(0,1),
ExitHandler,
exit_handler);
// _swi (OS_Exit, 0);
enter_taskwindow (buf);
// _swi (OS_Module, _INR(0, 2), 2, "TaskWindow", buf);
}
_swix (OS_ChangeEnvironment, _INR(0,1),
UpCallHandler,
old_upcall_handler);
}
/* Copyright 2007 Castle Technology Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "kernel.h"
#include "wimplib.h"
#include "swis.h"
#include "unixlib.h"
#include "Taskwindow.h"
#include "DebugLib/DebugLib.h"
extern void start_thread (const char* name, void (entry) (void*), int priority, int stack_size, void* txt, int* task_handle);
void thread (void* n) {
printf ("started thread\n");
while (1) {
printf ("ticking...\n");
sleep (1);
}
}
/* This code initialises with the window manager and calls the above routine
every period */
int main (void) {
WimpMessage block;
int event_code;
_kernel_oserror* e;
int handle = 0;
int flag = -10;
FILE* f;
/* idle time in centi-seconds */
int idle = 100;
int next_call; /* time to next return */
/* messages we're interested in */
int messages[3] = {TaskWindow_Output, TaskWindow_Ego, Wimp_MQuit};
debug_initialise ("Thread", "", "");
debug_set_device (DEBUGIT_OUTPUT);
debug_set_unbuffered_files (TRUE);
/* initialise with the window manager */
e = wimp_initialise (310, "Thread test", messages, 0, 0);
if (e) {
_swi (OS_GenerateError, _IN (0), e);
return 1;
}
f = fopen ("pipe:out", "w");
fprintf (f, "Thread test initialised\n");
// fclose (f);
// fflush (f);
/* poll the window manager for events */
next_call = _swi (OS_ReadMonotonicTime, _RETURN (0)) + idle;
for (;;) {
int t = _swi (OS_ReadMonotonicTime, _RETURN (0));
if (t > next_call) {
next_call += idle;
dprintf (("", "master tick %d\n", t));
fprintf (f, "master tick %d\n", t);
fflush (f);
}
wimp_pollidle (0, (WimpPollBlock*) &block, next_call, 0, &event_code);
switch (event_code) {
case Wimp_ENull:
if (flag++ == 0) {
flag = 1;
start_thread ("Child thread", thread, 10, 256, 0, &handle);
}
break;
case Wimp_EUserMessage:
case Wimp_EUserMessageRecorded:
switch (block.hdr.action_code) {
case Wimp_MQuit:
if (handle != 0) wimp_close_down (handle);
return 1;
case TaskWindow_Ego:
handle = block.hdr.sender;
// f = fopen ("pipe:out", "w");
fprintf (f, "child created: %x\n", handle);
fflush (f);
// fclose (f);
break;
case TaskWindow_Output:
// f = fopen ("pipe:out", "w");
fwrite (block.data.bytes + 4, block.data.words[0], 1, f);
fflush (f);
// fclose (f);
break;
break;
}
}
}
return 0;
}
/* Copyright 2007 Castle Technology Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* TaskWindow messages */
#define TaskWindow_Input 0x808c0
#define TaskWindow_Output 0x808c1
#define TaskWindow_Ego 0x808c2
#define TaskWindow_Morio 0x808c3
#define TaskWindow_Morite 0x808c4
#define TaskWindow_NewTask 0x808c5
#define TaskWindow_Suspend 0x808c6
#define TaskWindow_Resume 0x808c7
| Copyright 2007 Castle Technology Ltd
|
| Licensed under the Apache License, Version 2.0 (the "License");
| you may not use this file except in compliance with the License.
| You may obtain a copy of the License at
|
| http://www.apache.org/licenses/LICENSE-2.0
|
| Unless required by applicable law or agreed to in writing, software
| distributed under the License is distributed on an "AS IS" BASIS,
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
| See the License for the specific language governing permissions and
| limitations under the License.
|
dir <obey$dir>
|cc -throwback -Itbox:,c: -lc:o.stubs,tbox:o.wimplib test
objasm -throwback s.otest o.otest
link -aif -o otest o.otest
; Copyright 2007 Castle Technology Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
GET Hdr:ListOpts
GET Hdr:Macros
GET Hdr:System
GET Hdr:Machine.<Machine>
GET Hdr:Wimp
AREA |C$$CODE|, CODE
ENTRY
; SWI OS_WriteS
; = "Entered test...", 10, 13, 0
MOV R0, #400
LDR R1, task
ADR R2, name
ADR R4, messages
SWI Wimp_Initialise
MOV R0, #0
SWI Wimp_StartTask
CMP R0, #-1
; SWIEQ OS_Exit
BEQ thread
; SWI OS_Exit
LDR R0, =(0:OR:(1:SHL:17):OR:(1:SHL:18))
; MOV R0, #0
MOV R1, #&9000
MOV R5, #10
10
SWI OS_ReadMonotonicTime
ADD R2, R0, #400
LDR R0, =(0:OR:(1:SHL:17):OR:(1:SHL:18))
SWI Wimp_PollIdle
SUBS R5, R5, #1
BHS %b10
SWI OS_Exit
thread
MOV R1, #0 ; Not TASK
SWI Wimp_CloseDown
ADR r0, taskwindow
SWI OS_CLI
MOV R0, #400
LDR R1, task
ADR R2, name2
ADR R4, messages
SWI Wimp_Initialise
LDR R0, =(1:OR:(1:SHL:17):OR:(1:SHL:18))
MOV R1, #&a000
MOV R5, #10
10
SWI Wimp_Poll
SUBS R5, R5, #1
BHS %b10
SWI OS_Exit
name
= "Test thread", 0
name2
= "New thread", 0
ALIGN
task
= "TASK"
ALIGN
taskwindow
= "TaskWindow -display -ctrl -name ""New Thread""", 0
ALIGN
messages
DCD 0
END
; Copyright 2007 Castle Technology Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
GET Hdr:ListOpts