OSHeap_Resize Should Have R3 as Output.
Jonathan Coxhead
jonathan at doves.demon.co.uk
Tue Nov 6 20:33:07 GMT 2001
On 6 Nov 2001, at 13:10, Tony van der Hoff wrote:
> In the overwhelming majority of cases an error return from a SWI indicates
> that all bets are off. It wouldn't have been unreasonable for the OS to
> return the shrunk amount in R3 in any case, without throwing an error, and
> expect the client to make the comparison, but that's not what was done. We had
> to patch round this for OS_ReadVarVal, and I guess we could do something similar
> here, if there was demand for it. It would be possible to define new veneers,
> say OSHeap_ResizeReturnAmount, and OS_ChangeDynamicAreaReturnAmount, which could
> interpret any error return, and if appropriate, then return R3 with V clear, and
> R0 preserved, as if no error occurred.
>
> Is this worth doing?
Worth doing, but very hard! Anything involving changes to DefMod's code
generation should only be undertaken after reading & understanding thoroughly
the "manual.htm" file (especially the section "APCS to SWI"), a period of
fasting in the desert, attaining oneness with the code, etc. Any change, no
matter how innocuous-seeming, breaks it. (In my experience ...)
For OS_ReadVarVal we just wrote a veneer by hand, called riscos_var_len(),
and put it in the support directory. I think a similar way forward would be
best here: functions riscos_resize_heap(), riscos_change_dynamic_area() in
Support, with comments in the real veneer telling you about the "gotcha"
involved and pointing you at the new function.
"Did You Know" section
==== === ===== =======
It is *very hard* to write a correct calling sequence for OS_ReadVarVal---I
mean, code that will always get the right value, never truncate it, and never
return an error (memory limitations excepted). Intuition suggests something
like this should work:
len = riscos_var_len ("Var", os_VARTYPE_EXPANDED);
val = malloc (len + 1);
assert (val != NULL); /*should return an error "out of memory" to client*/
os_read_var_val ("Var", val, len, 0, os_VARTYPE_EXPANDED, &used, NULL);
val [used] = '\0';
The trouble is that some variables are code variables, and they can change
length in arbitrary ways at any time---including at any point between the
riscos_var_len() call and the call to os_read_var_val(). So os_read_var_val
might return an error in the above, and truncate the variable. So you need to
write something more like this:
len = 256;
val = malloc (len + 1);
assert (val != NULL);
while (xos_read_var_val ("Var", val, len, 0, os_VARTYPE_EXPANDED, &used,
NULL) != NULL)
{
tmp = realloc (val, len + 256 + 1);
assert (tmp != NULL);
val = tmp;
len += 256;
}
val [used] = '\0';
where an expanding buffer is used.
How many places in RISC OS actually do this? Probably none!
/|
o o o (_|/
/|
(_/
More information about the oslib-user
mailing list