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. :)
14 #include <exec/libraries.h>
15 #include <exec/resident.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
;
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 ;).
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 */
64 OpenAsync
, /* Our functions start here */
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()
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 */
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.
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
)
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
;
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
)
181 lib
->lib_Flags
&= ~LIBF_DELEXP
;
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
200 LibClose( _REG( a6
) struct Library
*lib
)
202 if( lib
->lib_OpenCnt
&& --lib
->lib_OpenCnt
)
207 if( lib
->lib_Flags
& LIBF_DELEXP
)
209 return( LibExpunge( lib
) );
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.
227 LibExpunge( _REG( a6
) struct Library
*lib
)
229 if( lib
->lib_OpenCnt
)
231 lib
->lib_Flags
|= LIBF_DELEXP
;
235 Remove( &lib
->lib_Node
);