Start of port of AsyncIO library.
[AROS-Contrib.git] / workbench / libs / asyncio / src / Lib.c
blob217625a98205556ff3f101ac18d410eb55dc8429
1 /* Lib.c
3 * Basic Library Resource Handling
5 * This code is based on the example shared library,
6 * found on the DICE 3.0 disks.
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. :)
13 #include "async.h"
14 #include <exec/libraries.h>
15 #include <exec/resident.h>
16 #include "rev.h"
18 #include <clib/asyncio_protos.h>
20 _LIBCALL struct Library *LibInit( _REG( d0 ) struct Library *, _REG( a0 ) APTR, _REG( a6 ) struct ExecBase * );
21 _CALL struct Library *LibOpen( _REG( a6 ) struct Library * );
22 _CALL APTR LibClose( _REG( a6 ) struct Library * );
23 _LIBCALL APTR LibExpunge( _REG( a6 ) struct Library * );
26 /* These variables will be zero, since "The memory used for bss
27 * blocks is zeroed by the loader when it is allocated" (quote
28 * from the AmigaDOS manual).
30 struct Library *AsyncIOBase; /* Our library structure */
31 struct ExecBase *SysBase;
32 struct Library *UtilityBase;
33 struct DosLibrary *DOSBase;
34 APTR SegList;
37 /* In case the user tries to run us, simply exit immediately.
38 * This code is also used for the reserved library function,
39 * that all libraries currently must have.
41 * Note that this function *must* be placed before any const
42 * data, or else the "exit if run" effect is lost (you are
43 * more likely to get a "crash if run" effect ;).
45 LONG
46 LibReserved( VOID )
48 return( 0 );
52 /* The functions the library should have. Unfortunately, we can't
53 * use the more compact format, using 16-bit relative entries,
54 * due to the compiler (bug or limitation ;).
57 static const APTR FuncTable[] =
59 LibOpen, /* Standard library functions */
60 LibClose,
61 LibExpunge,
62 LibReserved,
64 OpenAsync, /* Our functions start here */
65 OpenAsyncFromFH,
66 CloseAsync,
67 SeekAsync,
68 ReadAsync,
69 WriteAsync,
70 ReadCharAsync,
71 WriteCharAsync,
72 ReadLineAsync,
73 WriteLineAsync,
74 FGetsAsync,
75 FGetsLenAsync,
76 PeekAsync,
77 ( APTR ) -1 /* Terminate the table */
81 /* Table describing the library. We need this, since we use the
82 * autoinit feature. This means we don't need to call MakeLibrary()
83 * etc. in LibInit.
85 static const ULONG InitTable[] =
87 sizeof( struct Library ), /* Size of our library base, excluding jump table. We have no extra data here */
88 ( ULONG ) FuncTable, /* The functions we have */
89 NULL, /* InitStruct data. We init stuff ourselves instead */
90 ( ULONG ) LibInit /* The library init function */
94 static const TEXT LibId[] = "asyncio.library "VERSION" (" DATE ")\r\n";
95 static const TEXT LibName[] = "asyncio.library";
98 /* And finaly the resident structure, used by InitResident(),
99 * in order to initialize everything.
101 static const struct Resident RomTag =
103 RTC_MATCHWORD, /* rt_MatchWord */
104 &RomTag, /* rt_MatchTag */
105 LibExpunge, /* rt_EndSkip */
106 RTF_AUTOINIT, /* rt_Flags */
107 VERNUM, /* rt_Version */
108 NT_LIBRARY, /* rt_Type */
109 0, /* rt_Pri */
110 LibName, /* rt_Name */
111 LibId, /* rt_IDString */
112 InitTable /* rt_Init */
116 /* This small function frees the library structure,
117 * and any other allocated resources.
119 static VOID
120 FreeLib( struct Library *lib )
122 if( DOSBase ) /* In case we are loaded under kick 35 or earlier */
124 CloseLibrary( ( struct Library * ) DOSBase );
125 CloseLibrary( UtilityBase );
128 FreeMem( ( UBYTE * ) lib - lib->lib_NegSize, lib->lib_NegSize + lib->lib_PosSize );
132 /* This function is called when the library is loaded, and the library base
133 * have been allocated. We are in a forbid section here, so don't do anything
134 * time-consuming, Wait() or similar.
136 * If all ok, return the library base. If anything went wrong, deallocate
137 * the library structure, and return NULL.
139 _LIBCALL struct Library *
140 LibInit( _REG( d0 ) struct Library *lib, _REG( a0 ) APTR seglist, _REG( a6 ) struct ExecBase *sysBase )
142 SysBase = sysBase;
144 /* Opening libraries in LibInit might not be a good idea under OS 1.x.
145 * Should be safe enough under 2.x and 3.x.
147 if( ( DOSBase = ( struct DosLibrary * ) OpenLibrary( "dos.library", 37 ) ) &&
148 ( UtilityBase = OpenLibrary( "utility.library", 37 ) ) )
150 lib->lib_Node.ln_Type = NT_LIBRARY;
151 lib->lib_Node.ln_Pri = 0;
152 lib->lib_Node.ln_Name = LibName;
153 /* Request that checksum should be calculated */
154 lib->lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
155 lib->lib_Version = VERNUM;
156 lib->lib_Revision = REVNUM;
157 lib->lib_IdString = ( APTR ) LibId;
158 SegList = seglist;
159 AsyncIOBase = lib;
161 else
163 FreeLib( lib );
164 lib = NULL;
167 return( lib );
171 /* Open is given the library pointer. Either return the library pointer or NULL.
172 * Remove the delayed-expunge flag. Exec has Forbid() for us during the call.
174 * Since we don't refer to any smalldata here (directly or indirectly),
175 * we can safely skip "_LIBCALL", to save a few bytes.
177 _CALL struct Library *
178 LibOpen( _REG( a6 ) struct Library *lib )
180 ++lib->lib_OpenCnt;
181 lib->lib_Flags &= ~LIBF_DELEXP;
182 return( lib );
186 /* Close is given the library pointer. Be sure not to decrement the open
187 * count if already zero. If the open count is or becomes zero AND there
188 * is a LIBF_DELEXP, we expunge the library and return the seglist.
189 * Otherwise we return NULL.
191 * Note that this routine never sets LIBF_DELEXP on its own.
193 * Exec has Forbid() for us during the call.
195 * Since we don't refer to any smalldata here (directly. Indirectly we refer via
196 * LibExpunge, which is LibCall declared), we can safely skip "LibCall", to save
197 * a few bytes.
199 _CALL APTR
200 LibClose( _REG( a6 ) struct Library *lib )
202 if( lib->lib_OpenCnt && --lib->lib_OpenCnt )
204 return( NULL );
207 if( lib->lib_Flags & LIBF_DELEXP )
209 return( LibExpunge( lib ) );
212 return( NULL );
216 /* We expunge the library and return the Seglist ONLY if the open count is zero.
217 * If the open count is not zero we set the delayed-expunge flag and return NULL.
219 * Exec has Forbid() for us during the call. NOTE ALSO that Expunge might be
220 * called from the memory allocator and thus we CANNOT DO A Wait() or otherwise
221 * take a long time to complete (straight from RKM).
223 * RemLibrary() calls our expunge routine and would therefore freeze if we called
224 * it ourselves. LibExpunge() must remove the library itself as shown below.
226 _LIBCALL APTR
227 LibExpunge( _REG( a6 ) struct Library *lib )
229 if( lib->lib_OpenCnt )
231 lib->lib_Flags |= LIBF_DELEXP;
232 return( NULL );
235 Remove( &lib->lib_Node );
236 FreeLib( lib );
238 return( SegList );