Article on Unixlib
alex at alexwaugh.com
Mon Jan 10 12:42:12 PST 2005
In message <41DBE79F.6010600 at alexwaugh.com>
Alex Waugh <alex at alexwaugh.com> wrote:
> Nick Burrett wrote:
> > I'd like to think that we could make more use of the SharedUnixLibrary.
> > Some musings I have had this morning, could mean that we could use it to
> > implement 'shm_open' by creating a dynamic area that is private to the SUL
> > and using it to manage shared memory requests by the user-land application
> > i.e.
> > program calls shm_open
> > shm_open calls SharedUnixLibrary_Shm_Open
> > SUL allocates appropriate dynamic area space
> > shm_open returns pointer to allocated space
> > program uses space
> For a while now I've been intending to make more use of the SUL for
> improving fork(), and have spent a while thinking about the best way to
> implement the interface to the SUL. I don't think SWIs are the best
> option, and I'll try and find time within the next week to explain a bit
There are two main problems I'm trying to solve:
fork() just maps to vfork(), and therefore if the child program
alters anything in memory, or unwinds the stack, then the parent has
problems when the child returns.
If the child calls exec(), then the new program finds its environment
by poking about inside the __u struct of its parent, which is not very
nice and breaks every time __u changes, or various other
internal structures change.
Also, I'm not convinced that the code to set and retore handlers with
OS_ChangeEnvironment is entirely correct in all circumstances, although
I can't see anything specifically wrong with it. I hope to simplify
this which may flush out any remaining bugs in this area.
My plan is to have SUL store all data that needs to be shared between
processes, so that a child process doesn't need to poke around in the
parent for anything.
You can only have one version of the SUL loaded at once, so it has to
be able to cope with programs compiled with different versions of
Any code in SUL has to be written in assembly.
I want to keep the amount of assembler needed to a minimum.
A SWI interface could be quite slow if it is needed to access
regularly used bits of data such as file descriptors.
A SWI interface for implementing fork() wouldn't work because it would
need to return from the SWI twice.
Any code implementing a SWI will be running in SVC mode, which I want
to avoid as much as possible.
The general idea is as follows.
When a program starts, it RMEnsures the minimum version of SUL it
knows it needs, and then calls a SWI eg. SUL_Initialise, and passes it
the the minimum SUL version it needs. The SUL knows if it can support
the client or if it is too old, in which case it can return an error.
SUL then sets up environment handlers, and creates a structure (which
I'll call the process structure) in shared memory (RMA or a dynamic
area) to hold all the details of the process. It will fill in some of
this structure, such as the process' PID. It will then return from the
SWI to the program.
The program can then fill in some more of the structure, such as
pointers to its environment handlers. When eg. a data abort happens,
RISC OS will call the current handler which will be part of SUL, the
SUL can then look up the address of the program's handler from the
process structure and then call it.
As the program runs, things that potentially need to be passed to a
child process, such as file descriptors, will be part of the process
structure, or stored in shared memory and linked to from the process
Some of the process structure will contain pointers to routines within
the SUL, and whenever the program needs to call a SUL routime, it will
do so via one of these pointers rather than a SWI. The SUL routines will
be called as APCS in USR mode (This aspect is probably quite similar to
how the Shared C Library works, however I don't want to use it for
general library functions, only for those needed for process creation
When the program ends, it will call the exit routine from the process
structure, and the SUL will deregister any environment handlers and
call OS_Exit as appropriate.
If a process calls fork(), vfork() or exec() then it will call the
corresponding routine from the process structure. SUL can then handle
duplication of the adrress space for a fork, or shifting the
parent program out of the way when execing a child.
If an execed child is a unixlib program then it will call
SUL_Initialise and SUL will know it is a child, so it can fill in the
process structure with the appropriate details from the parent.
Alex Waugh alex at alexwaugh.com
PHP, Roots, Subversion, WebJames and more from http://www.alexwaugh.com/
More information about the gcc