home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
comm
/
misc
/
cyberpager
/
source
/
library
/
libhandler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-07
|
5KB
|
190 lines
/* LibHandler.c
Copyright 1993 by Christopher A. Wichura (caw@miroc.chi.il.us)
All Rights Reserved.
*/
struct SignalSemaphore HandleListSema;
struct MinList HandleList;
/*
* we need to serialize people calling our Open and Close routines so use
* another semaphore for that
*/
static struct SignalSemaphore OpenCloseSema;
/* pointers to a couple of librarys we open */
struct DosLibrary *DOSBase;
struct Library *UtilityBase;
struct Library *OwnDevUnitBase;
/* pointer to SysBase used by the rest of the system */
struct ExecBase *SysBase;
APTR pool;
struct SignalSemaphore poolSema;
struct MyLibrary {
struct Library ml_Lib;
BPTR ml_SegList;
};
/***************************************************************************/
/***************************************************************************/
/** These are the library base routines used to open/close us, etc **/
/***************************************************************************/
/***************************************************************************/
struct MyLibrary *__saveds __asm LibInit(register __d0 struct MyLibrary *LibBase, register __a0 BPTR LibSegment)
{
SysBase = *(struct ExecBase **)4L;
LibBase->ml_SegList = LibSegment;
NewList((struct List *)&HandleList);
InitSemaphore(&HandleListSema);
InitSemaphore(&OpenCloseSema);
InitSemaphore(&poolSema);
#define POOLSIZE (4096)
if (!(pool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR, POOLSIZE, POOLSIZE / 2))) {
Alert(AT_Recovery | AG_NoMemory);
return 0L;
}
return LibBase;
}
ULONG __saveds __asm LibExpunge(register __a6 struct MyLibrary *LibraryBase)
{
BOOL KillLib;
LONG LibSize;
BPTR LibrarySeg;
KillLib = FALSE;
/*
* we will refuse to expunge if we are currently tracking devices,
* regardless of our OpenCnt. We AttemptSemaphore() the HandleList
* before checking it. If someone else owns it then obviously we
* can't try to shut down.
*/
if (LibraryBase->ml_Lib.lib_OpenCnt == 0 && AttemptSemaphore(&HandleListSema)) {
if (HandleList.mlh_TailPred == (struct MinNode *)&HandleList.mlh_Head) {
Remove((struct Node *)LibraryBase);
KillLib = TRUE;
}
ReleaseSemaphore(&HandleListSema);
}
if (KillLib) {
DeletePool(pool);
LibrarySeg = LibraryBase->ml_SegList;
LibSize = LibraryBase->ml_Lib.lib_NegSize + LibraryBase->ml_Lib.lib_PosSize;
FreeMem((char *)LibraryBase - LibraryBase->ml_Lib.lib_NegSize, LibSize);
return (ULONG)LibrarySeg;
}
LibraryBase->ml_Lib.lib_Flags |= LIBF_DELEXP;
return (ULONG)NULL;
}
struct MyLibrary *__saveds __asm LibOpen(register __a6 struct MyLibrary *LibraryBase)
{
ObtainSemaphore(&OpenCloseSema);
if (++LibraryBase->ml_Lib.lib_OpenCnt == 1) {
/* when opencount = 1 then we need to open libraries */
if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37)) {
if (UtilityBase = OpenLibrary("utility.library", 37)) {
/*
* note that we really do care if we can open
* ODU or not. This is because ODU is the
* principal mechanism used by the lock
* routines and if ODU isn't around then we
* can't insure that we have really locked a
* file and could potentially run into
* problems.
*/
if (OwnDevUnitBase = OpenLibrary(ODU_NAME, 0)) {
/*
* we have opened everything we need
* successfully so clear the delayed
* expunge flag and return
* LibraryBase to indicate that the
* library opened ok.
*/
LibraryBase->ml_Lib.lib_Flags &= ~LIBF_DELEXP;
ReleaseSemaphore(&OpenCloseSema);
return LibraryBase;
}
else
Alert(AT_Recovery | AG_OpenLib | AO_Unknown);
CloseLibrary(UtilityBase);
UtilityBase = NULL;
}
else
Alert(AT_Recovery | AG_OpenLib | AO_UtilityLib);
CloseLibrary((struct Library *)DOSBase);
DOSBase = NULL;
}
else
Alert(AT_Recovery | AG_OpenLib | AO_DOSLib);
ReleaseSemaphore(&OpenCloseSema);
return (struct MyLibrary *)NULL;
}
LibraryBase->ml_Lib.lib_Flags &= ~LIBF_DELEXP;
ReleaseSemaphore(&OpenCloseSema);
return LibraryBase;
}
ULONG __saveds __asm LibClose(register __a6 struct MyLibrary *LibraryBase)
{
BOOL DoExpunge = FALSE;
ObtainSemaphore(&OpenCloseSema);
if (--LibraryBase->ml_Lib.lib_OpenCnt == 0) {
CloseLibrary(OwnDevUnitBase); /* relies on KS 2.0+ allowing
* one to call CloseLibrary()
* with a NULL base. If
* making a library for user
* under 1.3 (ugh!) make sure
* that closing of library
* bases which are not
* mandatory have checks to
* make sure they are not
* NULL before calling
* CloseLibrary(). */
OwnDevUnitBase = NULL;
CloseLibrary(UtilityBase);
UtilityBase = NULL;
CloseLibrary((struct Library *)DOSBase);
DOSBase = NULL;
if (LibraryBase->ml_Lib.lib_Flags & LIBF_DELEXP) {
DoExpunge = TRUE;
}
}
ReleaseSemaphore(&OpenCloseSema);
if (DoExpunge)
return LibExpunge(LibraryBase);
else
return (ULONG)NULL;
}