home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / dev / c / Asyncio.lha / AsyncIO / src / Lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-14  |  6.1 KB  |  230 lines

  1. /* Lib.c
  2.  *
  3.  * Basic Library Resource Handling
  4.  *
  5.  * This code is based on the example shared library,
  6.  * found on the DICE 3.0 disks.
  7.  *
  8.  * This code doesn't use any form of startup code (the example does).
  9.  * This is not something the novice C-programmer should attemt to do.
  10.  * You need to know what you are doing. :)
  11.  */
  12.  
  13. #include "async.h"
  14. #include <exec/libraries.h>
  15. #include <exec/resident.h>
  16. #include "rev.h"
  17.  
  18. #include <clib/asyncio_protos.h>
  19.  
  20. LibCall struct Library *LibInit( _REG( d0 ) struct Library *, _REG( a0 ) APTR, _REG( a6 ) struct ExecBase * );
  21. struct Library *LibOpen( _REG( a6 ) struct Library * );
  22. APTR LibClose( _REG( a6 ) struct Library * );
  23. APTR LibExpunge( _REG( a6 ) struct Library * );
  24.  
  25.  
  26. /* Due to a bug in the linker, we must have some initialized data.
  27.  * If not, the linker will not produce any smalldata section.
  28.  * By giving one of the fields a value, this problems is avoided.
  29.  *
  30.  * The other variables will be zero, since "The memory used for
  31.  * bss blocks is zeroed by the loader when it is allocated" (quote
  32.  * from the AmigaDOS manual).
  33.  */
  34. struct Library        *AsyncIOBase = NULL;    /* Our library structure */
  35. struct ExecBase        *SysBase;
  36. struct Library        *UtilityBase;
  37. struct DosLibrary    *DOSBase;
  38. APTR            SegList;
  39.  
  40.  
  41. /* In case the user tries to run us, simply exit immediately.
  42.  * This code is also used for the reserved library function,
  43.  * that all libraries currently must have.
  44.  *
  45.  * Note that this function *must* be placed before any const
  46.  * data, or else the "exit if run" effect is lost.
  47.  */
  48. LONG
  49. LibReserved( VOID )
  50. {
  51.     return( 0 );
  52. }
  53.  
  54.  
  55. /* The functions the library should have. Unfortunately, we can't
  56.  * use the more compact format, using 16-bit relative entries,
  57.  * due to the compiler (bug or limitation ;).
  58.  */
  59. const APTR FuncTable[] =
  60. {
  61.     LibOpen,    /* Standard library functions */
  62.     LibClose,
  63.     LibExpunge,
  64.     LibReserved,
  65.  
  66.     OpenAsync,    /* Our functions start here */
  67.     OpenAsyncFromFH,
  68.     CloseAsync,
  69.     SeekAsync,
  70.     ReadAsync,
  71.     WriteAsync,
  72.     ReadCharAsync,
  73.     WriteCharAsync,
  74.  
  75.     ( APTR ) -1    /* Terminate the table */
  76. };
  77.  
  78.  
  79. /* Table describing the library. We need this, since we use the
  80.  * autoinit feature. This means we don't need to call MakeLibrary()
  81.  * etc. in LibInit.
  82.  */
  83. const ULONG InitTable[] =
  84. {
  85.     sizeof( struct Library ),    /* Size of our library base, excluding jump table. We have no extra data here */
  86.     ( ULONG ) FuncTable,        /* The functions we have */
  87.     NULL,                /* InitStruct data. We init stuff ourselves instead */
  88.     ( ULONG ) LibInit        /* The library init function */
  89. };
  90.  
  91.  
  92. const TEXT LibId[] = "asyncio.library "VERSION" (" DATE ")\r\n";
  93. const TEXT LibName[] = "asyncio.library";
  94.  
  95.  
  96. /* And finaly the resident structure, used by InitResident(),
  97.  * in order to initialize everything.
  98.  */
  99. const struct Resident RomTag =
  100. {
  101.     RTC_MATCHWORD,        /* rt_MatchWord */
  102.     &RomTag,        /* rt_MatchTag */
  103.     LibExpunge,        /* rt_EndSkip */
  104.     RTF_AUTOINIT,        /* rt_Flags */
  105.     VERNUM,            /* rt_Version */
  106.     NT_LIBRARY,        /* rt_Type */
  107.     0,            /* rt_Pri */
  108.     LibName,        /* rt_Name */
  109.     LibId,            /* rt_IDString */
  110.     InitTable        /* rt_Init */
  111. };
  112.  
  113.  
  114. /* This small function is a frees the library structure,
  115.  * and any other allocated resources.
  116.  */
  117. VOID
  118. FreeLib( struct Library *lib )
  119. {
  120.     CloseLibrary( ( struct Library * ) DOSBase );
  121.     CloseLibrary( UtilityBase );
  122.     FreeMem( ( UBYTE * ) lib - lib->lib_NegSize, lib->lib_NegSize + lib->lib_PosSize );
  123. }
  124.  
  125.  
  126. /* This function is called when the library is loaded, and the library base
  127.  * have been allocated. We are in a forbid section here, so don't do anything
  128.  * time-consuming, Wait() or similar.
  129.  *
  130.  * If all ok, return the library base. If anything went wrong, deallocate
  131.  * the library structure, and return NULL.
  132.  */
  133. LibCall struct Library *
  134. LibInit( _REG( d0 ) struct Library *lib, _REG( a0 ) APTR seglist, _REG( a6 ) struct ExecBase *sysBase )
  135. {
  136.     SysBase = sysBase;
  137.  
  138.     if( ( DOSBase = ( struct DOSLibrary * ) OpenLibrary( "dos.library", 37 ) ) &&
  139.         ( UtilityBase = OpenLibrary( "utility.library", 37 ) ) )
  140.     {
  141.         lib->lib_Node.ln_Type    = NT_LIBRARY;
  142.         lib->lib_Node.ln_Pri    = 0;
  143.         lib->lib_Node.ln_Name    = LibName;
  144.         lib->lib_Flags        = LIBF_CHANGED | LIBF_SUMUSED;
  145.         lib->lib_Version    = VERNUM;
  146.         lib->lib_Revision    = REVNUM;
  147.         lib->lib_IdString    = ( APTR ) LibId;
  148.         SegList = seglist;
  149.         AsyncIOBase = lib;
  150.     }
  151.     else
  152.     {
  153.         FreeLib( lib );
  154.         lib = NULL;
  155.     }
  156.  
  157.     return( lib );
  158. }
  159.  
  160.  
  161. /* Open is given the library pointer. Either return the library pointer or NULL.
  162.  * Remove the delayed-expunge flag. Exec has Forbid() for us during the call.
  163.  *
  164.  * Since we don't refer to any smalldata here (directly or indirectly),
  165.  * we can safely skip "LibCall", to save a few bytes.
  166.  */
  167. struct Library *
  168. LibOpen( _REG( a6 ) struct Library *lib )
  169. {
  170.     ++lib->lib_OpenCnt;
  171.     lib->lib_Flags &= ~LIBF_DELEXP;
  172.     return( lib );
  173. }
  174.  
  175.  
  176. /* Close is given the library pointer. Be sure not to decrement the open
  177.  * count if already zero. If the open count is or becomes zero AND there
  178.  * is a LIBF_DELEXP, we expunge the library and return the seglist.
  179.  * Otherwise we return NULL.
  180.  *
  181.  * Note that this routine never sets LIBF_DELEXP on its own.
  182.  *
  183.  * Exec has Forbid() for us during the call.
  184.  *
  185.  * Since we don't refer to any smalldata here (directly. Indirectly we refer via
  186.  * LibExpunge, which is LibCall declared), we can safely skip "LibCall", to save
  187.  * a few bytes.
  188.  */
  189. APTR
  190. LibClose( _REG( a6 ) struct Library *lib )
  191. {
  192.     if( lib->lib_OpenCnt && --lib->lib_OpenCnt )
  193.     {
  194.         return( NULL );
  195.     }
  196.  
  197.     if( lib->lib_Flags & LIBF_DELEXP )
  198.     {
  199.         return( LibExpunge( lib ) );
  200.     }
  201.  
  202.     return( NULL );
  203. }
  204.  
  205.  
  206. /* We expunge the library and return the Seglist ONLY if the open count is zero.
  207.  * If the open count is not zero we set the delayed-expunge flag and return NULL.
  208.  *
  209.  * Exec has Forbid() for us during the call. NOTE ALSO that Expunge might be
  210.  * called from the memory allocator and thus we CANNOT DO A Wait() or otherwise
  211.  * take a long time to complete (straight from RKM).
  212.  *
  213.  * RemLibrary() calls our expunge routine and would therefore freeze if we called
  214.  * it ourselves. LibExpunge() must remove the library itself as shown below.
  215.  */
  216. LibCall APTR
  217. LibExpunge( _REG( a6 ) struct Library *lib )
  218. {
  219.     if( lib->lib_OpenCnt )
  220.     {
  221.         lib->lib_Flags |= LIBF_DELEXP;
  222.         return( NULL );
  223.     }
  224.  
  225.     Remove( &lib->lib_Node );
  226.     FreeLib( lib );
  227.  
  228.     return( SegList );
  229. }
  230.