From: enevill@acorn.co.uk (Edward Nevill)
Newsgroups: comp.sys.acorn.tech
Subject: Re: RISC-OS apps in modules
Date: 13 Oct 92 11:40:49 GMT
Organization: Acorn Computers Ltd, Cambridge, England

In article <1992Oct12.161759.2143@infodev.cam.ac.uk> idg10@cl.cam.ac.uk (I.D. Griffiths) writes:

>Not entirely surprised.  I would be quite surprised if the RiscOSLib bits and
>pieces worked in the context of a module app.  In fact I'm almost certain they
>won't, particularly if any bits have been written in C, which they are quite
>likely to have been.

Indeed, RISC_OSLib will not work in a module app. For C code to work in a module
app it must be compiled with the -zm flag. RISC_OSLib is not compiled with the
-zm flag.

The -zm flag changes the way C accesses its static data so that the static data
can be allocated at run time rather than being directly linked with the code.

For example it changes

    ADR Rn, some_var

to the equivalent of

    ADR Rn, some_var
    LDR Rm, [sl, #Sl_Client_Offset]
    ADD Rn, Rn, Rm

That is, it adds the client static data relocation, stored at offset
SL_Client_Offset from the stack limit register to the address of any static data
it access.

This allows restartability (any statically initialised data is preserved as the
actual static data used is a copy of the statically initialised data in the module),
multiple instantiation (each instantiation can have a separate copy of the static
data) and ROMability (the static data can reside in RAM while the module resides
in ROM).

>The reason for this is that the C compiler stomps all over R12 (aargh!)

As it is quite entitled to.

>and so alternative measures need to be taken to work in a module.

The alternative measures have nothing to do with whether R12 is preserved or not.

>What actually happens is cmgh (popular pronunciation: "see-munge") provides
>'veneer' code, which stuffs two relocation pointers at the bottom of the
>supervisor stack. (nyurgh!) I think one is the address of the module code, and
>the other of the workspace of the current instantiation, or at least a derivative
>thereof (there seems to be some global magic number like 536 by which these are offset).

The two static data relocations are stored on the base of the current stack chunk,
in SVC mode this happens to be the supervisor stack, for a module app which is run in
user mode this will be a separately allocated user stack chunk.

The two static data relocation are SL_Client_Offset and SL_Lib_Offset the client
and libraries static data offsets respectively.

>Apart from being utterly horrible, the problem with this is that context
>switches don't tend to work unless they decide to preserve the two words at the
>very bottom of the stack, which isn't necessarily what you would think of doing. 

Since in SVC mode they are the bottom two words of the SVC stack you have to work
quite hard to overwrite them, if you do overwrite them you have probably just
overflowed the SVC stack so your application is dead anyway.

>This is why *logon from within a task window under NFS causes the machine to hang.
>(yup! NFS is written in C, even some of the low level bits...)  So basically if two
>tasks written in C are running at once, the machine will hang.  Obviously this
>only applies to SVC mode C, since user mode apps obviously seem to work.

This is not the case. The CMHG veneers preserve the two words on the base of the
stack on entry, write the correct static data relocations for the module and restore
the orignal two words on exit, so any number of C modules can be run simultaneously.

The *logon feature occurs for a completely different reason. At one point in the
Internet code it replaces the CallBack handler, to do this it reads the old value
of the CallBack handler, then writes the new value. It does this with interrupts
enabled. If an interrupt occurs between reading the old value and writing the new
value the old value read becomes invalid. This is solved by reading and writing
the CallBack handler using a single OS_ChangEnvironment call.

This feature has been removed in RISC OS 3 (version 3.10)

>|> I've successfully created applications in modules to do real simple stuff,
>|> mainly just to test that I've got the header set up okay.  I've trapped
>|> service call 11, and dealt with it using the code supplied in the manual
>|> and on the examples disk.  What other things have to be set up before
>|> calling Wimp_Initialise?  Currently when I call it, it causes an internal
>|> error at &38?????  Note, I'm not linking with RISC-OSLib, but calling
>|> the SWI directly using _kernel_swi.

The problem is that that should be service call 17, not service call 11.

>Oh.. oops, maybe I should read before I write.  Still, I think the above
>paragraph may be useful to some -it came as a revalation to me.  Caused me to
>not wish to use the compiler apart from anything else.

>The only approach I can suggest is writing your own assembler routines to call
>the swis, which stack these two pointers before calling Wimp_Polll. 

This will not help.

>Quite why it falls over at Wimp_Initialise though I don't know, but it could be that
>kernle_swi is not used to being called in SVC mode, since the compiler
>prodecues its code somewhat differently in that mode, although there's no good
>reason it shouldn't work.

_kernel_swi can be used safely in SVC mode, however, Wimp_Initialise must be
called from User mode with a flat SVC stack and interrupts enabled. However,
a module's run entry is not called in SVC mode, it is called in user mode
(with a flat SVC stack, and interrupts enabled), so this is OK.

>|>  Before I resort to disassembling
>|> !Edit from rom, have you got any ideas on what I'm missing?
>You're missing the fact that !Edit runs as a normal application and not a
>module application...  Although maybe it doesn't, it's hard to tell
>since I think the task manager only uses memory allocation to decide (i.e. 0k of app
>space means it's a module task...).  I don't know precisely what edit does, although
>it is quite likely to have some assembler patching...

!Edit on RISC OS 3 runs as a module task using a variant of CMHG.

>|>  Any other 
>|> tips for things to look out for would be appreciated.
>|>
>Use assembler.

Don't listen to misinformed speculation,

Edward (enevill@acorn.co.uk)