OSHeap_Resize Should Have R3 as Output.

Jonathan Coxhead jonathan at doves.demon.co.uk
Tue Nov 6 20:33:20 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