os_claim

Jonathan Coxhead jonathan at doves.demon.co.uk
Mon Dec 11 20:02:20 GMT 2000


 | However, if you've been following UseNet recently, you'll be aware of
 | the following infelicity:
 | 
 | Presently, os_claim is prototyped as:
 |   os_claim( int vector, void const *routine, byte *handle );
 | 
 | I believe this is incorrect, and should be something like
 |   os_claim( int vector, void (*routine)(void), byte *handle );
 | 
 | The same problem exists for os_release, os_change_environment and its
 | clients, and probably many others. I don't see any obvious way of
 | persuading DefMod to generate this syntax, so it probably isn't
 | possible. 

   It's not. :-(

   The trouble is that the |routine| argument is not actually pointing at a 
piece of C code: it's pointing at a piece of assembler. Though sometimes 
you can call such a thing by casting the argument to a function pointer and 
jumping, it's not clean because of the different calling conventions and 
return mechanism. (Consider returning from a vector with/without "claiming" 
it.)

   (This is the exact same problem that DefMod solves, but in the other 
order: calling a C function that obeys the APCS from assembler with some 
given calling convention.)

   In CMHG, there is a facility to declare an irq-handler. This generates a 
wrapper that makes a piece of assembler (by intent, an IRQ handler, though 
it works for other things too) into a "real" C function. Let's suppose that 
the real code has type

      void os_cmhg_handler (void *arg);

(I can't remember what it really is), so the programmer writes a function 
of that type

      void handler (void *arg)
      {
         ...
      }

and then the CMHG wrapper comes along and emits some code at a location

      void *wrapper;

and let's call the type of that os_cmhg_wrapper.

   Then a good step would be to have typedefs in OSLib

      typedef void  os_cmhg_handler (void *);
      typedef void *os_cmhg_wrapper;

and give the prototypes as

      os_error *os_claim (int vector, os_cmhg_wrapper routine,
            byte *handle);

and make it clear in the documentation that you have to use CMHG to paste 
the wrapper onto the handler.

   Another tool could be written to do a similiar job, if CMHG is not 
supported any more.

   OSLib has the built-in type |.Asm| for anything that's supposed to point 
to code; so it would be easy to map |.Asm| to |os_cmhg_wrapper|. 

  1 remaining issue springs to mind: since there are different calling 
conventions for different assembler fragments---service calls, IRQ 
handlers, vectors, events, pre- and post-filters, etc, it would be nice to 
have a tool that generated custom veneers for each one, and for each one to 
have a different type for its C function and its wrapper. So we could have

      typedef bool  osservice_handler (int no, ..., void *handle);
      typedef void *osservice_wrapper;

   Then I could write, say, my service call handler in "service.c" as

      bool service (...)
      {
         ...
      }

   In the CMHG file, we'd have something like

      service-handler: service/service-wrapper

which generates the wrapper |service_wrapper|, and OSLib functions that 
deal with service calls would have parameters of that type 
(|osservice_wrapper|).

   So finally, we'd need a tool that read the CMHG file, and produced a C 
header file like this:

      #include "os.h"
 
      extern osservice_handler service;
      extern osservice_wrapper service_wrapper;

   With those extra peices, I think we'd have type-safe integration between 
the various ways of hooking C code into RISC O S.

        /|
 o o o (_|/
        /|
       (_/



More information about the oslib-team mailing list