#Pure modules
17 messages in this thread
Hi.
How does one make a pure program using the Aztec 5.0 complier/linker?
Thanks for your help,
Bob Clark
It is not easy. You need to not use any global data at all. From talking
to Talin about this once, he indicated that he had to rewrite the startup
code and not use the standard libraries. Beyond that, we will have to ask
someone here who uses Manx to help out. I am out of my water on this type
of question…
John A. Toebes, VIII – via Whap!
A 'nit-picking' reply. You need to not use any INITIALIZED (my
emphasis added) global data (or static data, for that matter) which
your program then changes.
Actually, that is not true. The Manx startup code uses the hidden
BSS trick to make the BSS section appear as part of the Data hunk.
Hence, both the initialized and uninitialized data are part of the
data segment in memory and neither should be modified in order to be
truely residentable.
I didn't read the other reply, but basically, you can't use global
variables. It might be ok to use a global, but you have to be very
carefull. My understanding is that, after the first time you invoke
a program, it remains in the state that it was in when it exited.
(Ooops, that is, when you make a program RESIDENT.) Globals aren't
re-initialized so you can end up with garbage. You can allocate
memory and store stuff and, I think, you could use globals if your
program specifically initializes its values (and you don't
multitask). I've only played a little with trying to crash code and
I am by far not an expert………………………WW
You *can* use globals, but they ought to be things that are relevant to
global operation of the program, like, how many invocations are running
now, what is the total amount of memory allocated by it now, etc. Not items
related to the individual jobs it's doing.
Ben
Let me make that a little stronger. Items on the resident list are
expected to NOT modify any of the image loaded from disk. Wshell has
an option to check the resident list to keep an image from being
trashed. If you think about it, a residentable module should be able
to be put into a ROM and still be able to run correctly. For this
reason, you should NOT write to any global data.
John,
I think much of the confusion comes from the way some people equate
'pure' with 're-entrant'. 'pure' is a CBM term that means pretty much what
you say; that it not modify any of its loaded image. This is a much more
stringent requirement than what is necessary for reentrancy, which is in
itself more stringent than what is necessary for 're-usability'.
I only disagree with your statement that a 'residentable module should be
able to be put in a ROM and still be able to run correctly'. In my opinion,
the requirements should be the same as for reentrancy.
-larry
A resident list is maintained in private memory owned by the shell and as
such is owned by the shell. An application that is modifying the segments
in the resident list is modifying memory owned by the shell. For this
reason, it is appropriate to treat the memory as if it were ROM.
We have several levels to consider:
* Serially Reusable – An application may be run multiple times in a row,
but not more than one copy at a time.
* ReEntrant – An application may run multiple times even more than one
copy at the same time.
* Pure – An application does not modify any portions of its segment list.
By definition, a Pure module is ReEntrant and Romable.
The only thing separating pure from reentrant is modification of the data
segment. There are three types of data that an application might use.
* Global Constants – These are configuration items which allow for easy
passing to routines. Since these are not changed, they do not affect the
status.
* Global Invocation private data – This is data that is private to an
invocation of the application. It includes things like unprotected memory
pools, library bases, and allocated memory. Note that a library does NOT
have to return the same pointer for each call to OpenLibrary and hence must
not be shared. Also, in order to ensure safe access, these variables must
be protected with Semaphores or Forbid() Permit() sequences. Note that
most C runtime libraries use data in this form.
* Global Invocation Independent data – This is data that would be shared
amongst all invocations of an application. With applications that are not
talking to one another, the amount of data here is zero. Even for data
that does exist, there are far better mechanisms for dealing with it –
global messages ports being a very good one. For CLI type commands it is
almost never found. In fact, this would virtually REQUIRE that the
application to be on the resident list if it is to function correctly
because each non-resident copy of the application would NOT get
[ MORE ]
[ continuation ]
the same data.
Perhaps I have missed a class of data above, but once you group it out,
there is little opportunity for shared data to exist in my mind. More
often than not it is a mistake and not a deliberate design.
John A. Toebes, VIII – via Whap!
John,
While it is true that the shell owns the memory, it can also be said that
the application owns its data. I realize there is a philosophical
difference here, of course, and that CBM has decided to embrace the first
case, and to exclude the second case, and that in doing so, they have made
the requiremnts more stringent than is absolutely necessary.
We have a number of classes of programs that are reentrant without being
pure already, those being such things as devices and shared libraries. I
just think it would have been more elegant to allow reentrancy without the
purity.
Of course reentrancy without purity is virtually impossible to check for,
so perhaps it is better they did it the way they did.
-larry
Actually, Libraries and Devices are Pure. However we have a different
point here because they are NOT residentable. Also note that a properly
written device or library is pure because the Library initialization
allocates the data and code vector for the library (creating the library
base). From experience in making libraries work, the number one thing that
is recommended against is using global data because of the problem of
reentrant access to the data. It is for this reason that SAS/C recommends
that you do NOT use C library routines in a library/device unless you are
sure they do not use global data. If you are thinking about XPR libraries
as an example, ask how many problems Mr. Langeveld had with the design.
John A. Toebes, VIII – via Whap!
Actually, I was thinking about the library data area where such things as
the open count are stored.
-larry
Ah, but these things are maintained by the system and are managed under
careful forbids and permits. Again note that this is something that is not
storable in a resident list. Programming libraries in general is a very
special case that has to be considered and has its own set of restrictions
associated with them (such as A6 register requirements and restrictions on
what can be called in a Expunge routine).
John A. Toebes, VIII – via Whap!
There are no global variables in the program I have written. The message
(from ARP) is that the program has a checksum error. According to the ARP
docs to make a program pure with the Aztec compiler, you use the "+b"
option. That is an option for the old version of the compiler and I don't
have the docs available for that version so that I can find out what the
corresponding option is in the new version.
Do you know?
Thanks,
Bob
If there are no global variables, then you should have only one hunk. This
message seems to imply that you might be using the Ares command. It had
its own form of resident that is not the same as the Amigados form of
resident because of the way they did the resident header.
John A. Toebes, VIII – via Whap!
I am not using ARP but I have Aztec 3.6. The only reference to a "+b"
option is a "+B" option which is used if you are supply your own .begin
code. From what I understand from you, you should only need to compile and
link the code normally IMHO………………WW