Corrections to SVN properties.
[AROS.git] / workbench / libs / codesets / src / libinit.c
blobf12c5172e215ba53fd4af8dcd0c35035d3a9e54c
1 /***************************************************************************
3 codesets.library - Amiga shared library for handling different codesets
4 Copyright (C) 2001-2005 by Alfonso [alfie] Ranieri <alforan@tin.it>.
5 Copyright (C) 2005-2013 by codesets.library Open Source Team
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 codesets.library project: http://sourceforge.net/projects/codesetslib/
19 $Id$
21 ***************************************************************************/
23 #include "lib.h"
24 #include "version.h"
26 #include <exec/resident.h>
27 #include <proto/exec.h>
29 #include "debug.h"
31 /****************************************************************************/
34 * The system (and compiler) rely on a symbol named _start which marks
35 * the beginning of execution of an ELF file. To prevent others from
36 * executing this library, and to keep the compiler/linker happy, we
37 * define an empty _start symbol here.
39 * On the classic system (pre-AmigaOS4) this was usually done by
40 * moveq #0,d0
41 * rts
45 #if defined(__amigaos3__)
46 asm(".text\n\
47 .even\n\
48 .globl _start\n\
49 _start:\n\
50 moveq #20,d0\n\
51 rts");
52 #else
53 LONG _start(void)
55 return RETURN_FAIL;
57 #endif
59 /****************************************************************************/
61 #define MIN_STACKSIZE 65536
63 #if defined(__amigaos4__)
64 // stack cookie for shell v45+
65 static const char USED_VAR stack_size[] = "$STACK:" STR(MIN_STACKSIZE) "\n";
66 #endif
68 /****************************************************************************/
70 #if defined(__amigaos4__)
71 struct Library *SysBase = NULL;
72 struct ExecIFace* IExec = NULL;
73 #if defined(__NEWLIB__)
74 struct Library *NewlibBase = NULL;
75 struct NewlibIFace* INewlib = NULL;
76 #endif
77 #else
78 struct ExecBase *SysBase = NULL;
79 #endif
81 struct LibraryHeader *CodesetsBase = NULL;
83 static const char UserLibName[] = "codesets.library";
84 static const char UserLibID[] = "$VER: codesets.library " LIB_REV_STRING " [" SYSTEMSHORT "/" CPU "] (" LIB_DATE ") " LIB_COPYRIGHT;
86 /****************************************************************************/
88 #define libvector LibNull \
89 LFUNC_FA_(CodesetsConvertUTF32toUTF16) \
90 LFUNC_FA_(CodesetsConvertUTF16toUTF32) \
91 LFUNC_FA_(CodesetsConvertUTF16toUTF8) \
92 LFUNC_FA_(CodesetsIsLegalUTF8) \
93 LFUNC_FA_(CodesetsIsLegalUTF8Sequence) \
94 LFUNC_FA_(CodesetsConvertUTF8toUTF16) \
95 LFUNC_FA_(CodesetsConvertUTF32toUTF8) \
96 LFUNC_FA_(CodesetsConvertUTF8toUTF32) \
97 LFUNC_FA_(CodesetsSetDefaultA) \
98 LFUNC_VA_(CodesetsSetDefault) \
99 LFUNC_FA_(CodesetsFreeA) \
100 LFUNC_VA_(CodesetsFree) \
101 LFUNC_FA_(CodesetsSupportedA) \
102 LFUNC_VA_(CodesetsSupported) \
103 LFUNC_FA_(CodesetsFindA) \
104 LFUNC_VA_(CodesetsFind) \
105 LFUNC_FA_(CodesetsFindBestA) \
106 LFUNC_VA_(CodesetsFindBest) \
107 LFUNC_FA_(CodesetsUTF8Len) \
108 LFUNC_FA_(CodesetsUTF8ToStrA) \
109 LFUNC_VA_(CodesetsUTF8ToStr) \
110 LFUNC_FA_(CodesetsUTF8CreateA) \
111 LFUNC_VA_(CodesetsUTF8Create) \
112 LFUNC_FA_(CodesetsEncodeB64A) \
113 LFUNC_VA_(CodesetsEncodeB64) \
114 LFUNC_FA_(CodesetsDecodeB64A) \
115 LFUNC_VA_(CodesetsDecodeB64) \
116 LFUNC_FA_(CodesetsStrLenA) \
117 LFUNC_VA_(CodesetsStrLen) \
118 LFUNC_FA_(CodesetsIsValidUTF8) \
119 LFUNC_FA_(CodesetsFreeVecPooledA) \
120 LFUNC_VA_(CodesetsFreeVecPooled) \
121 LFUNC_FA_(CodesetsConvertStrA) \
122 LFUNC_VA_(CodesetsConvertStr) \
123 LFUNC_FA_(CodesetsListCreateA) \
124 LFUNC_VA_(CodesetsListCreate) \
125 LFUNC_FA_(CodesetsListDeleteA) \
126 LFUNC_VA_(CodesetsListDelete) \
127 LFUNC_FA_(CodesetsListAddA) \
128 LFUNC_VA_(CodesetsListAdd) \
129 LFUNC_FA_(CodesetsListRemoveA) \
130 LFUNC_VA_(CodesetsListRemove)
133 /****************************************************************************/
135 #if defined(__amigaos4__)
137 static struct LibraryHeader * LIBFUNC LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec);
138 static BPTR LIBFUNC LibExpunge (struct LibraryManagerInterface *Self);
139 static struct LibraryHeader * LIBFUNC LibOpen (struct LibraryManagerInterface *Self, ULONG version);
140 static BPTR LIBFUNC LibClose (struct LibraryManagerInterface *Self);
141 static LONG LIBFUNC LibNull (void);
143 #elif defined(__MORPHOS__)
145 static struct LibraryHeader * LIBFUNC LibInit (struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb);
146 static BPTR LIBFUNC LibExpunge(void);
147 static struct LibraryHeader * LIBFUNC LibOpen (void);
148 static BPTR LIBFUNC LibClose (void);
149 static LONG LIBFUNC LibNull (void);
151 #elif defined(__AROS__)
153 #include <aros/libcall.h>
155 #define Codesets_LibOpen LibOpen
156 #define Codesets_LibClose LibClose
157 #define Codesets_LibExpunge LibExpunge
159 static AROS_UFP3 (struct LibraryHeader *, LibInit,
160 AROS_UFPA(struct LibraryHeader *, base, D0),
161 AROS_UFPA(BPTR, librarySegment, A0),
162 AROS_UFPA(struct ExecBase *, sb, A6)
164 static AROS_LD1 (struct LibraryHeader *, LibOpen,
165 AROS_LPA (UNUSED ULONG, version, D0),
166 struct LibraryHeader *, base, 1, Codesets
168 static AROS_LD0 (BPTR, LibClose,
169 struct LibraryHeader *, base, 2, Codesets
171 static AROS_LD1(BPTR, LibExpunge,
172 AROS_LPA(UNUSED struct LibraryHeader *, __extrabase, D0),
173 struct LibraryHeader *, base, 3, Codesets
176 #else
178 static struct LibraryHeader * LIBFUNC LibInit (REG(d0, struct LibraryHeader *lh), REG(a0, BPTR Segment), REG(a6, struct ExecBase *sb));
179 static BPTR LIBFUNC LibExpunge (REG(a6, struct LibraryHeader *base));
180 static struct LibraryHeader * LIBFUNC LibOpen (REG(d0, ULONG version), REG(a6, struct LibraryHeader *base));
181 static BPTR LIBFUNC LibClose (REG(a6, struct LibraryHeader *base));
182 static LONG LIBFUNC LibNull (void);
184 #endif
186 /****************************************************************************/
188 static LONG LIBFUNC LibNull(VOID)
190 return(0);
193 /****************************************************************************/
195 #if defined(__amigaos4__)
196 /* ------------------- OS4 Manager Interface ------------------------ */
197 STATIC uint32 _manager_Obtain(struct LibraryManagerInterface *Self)
199 uint32 res;
200 __asm__ __volatile__(
201 "1: lwarx %0,0,%1\n"
202 " addic %0,%0,1\n"
203 " stwcx. %0,0,%1\n"
204 " bne- 1b"
205 : "=&r" (res)
206 : "r" (&Self->Data.RefCount)
207 : "cc", "memory");
209 return res;
212 STATIC uint32 _manager_Release(struct LibraryManagerInterface *Self)
214 uint32 res;
215 __asm__ __volatile__(
216 "1: lwarx %0,0,%1\n"
217 " addic %0,%0,-1\n"
218 " stwcx. %0,0,%1\n"
219 " bne- 1b"
220 : "=&r" (res)
221 : "r" (&Self->Data.RefCount)
222 : "cc", "memory");
224 return res;
227 STATIC CONST CONST_APTR lib_manager_vectors[] =
229 (CONST_APTR)_manager_Obtain,
230 (CONST_APTR)_manager_Release,
231 (CONST_APTR)NULL,
232 (CONST_APTR)NULL,
233 (CONST_APTR)LibOpen,
234 (CONST_APTR)LibClose,
235 (CONST_APTR)LibExpunge,
236 (CONST_APTR)NULL,
237 (CONST_APTR)-1
240 STATIC CONST struct TagItem lib_managerTags[] =
242 { MIT_Name, (Tag)"__library" },
243 { MIT_VectorTable, (Tag)lib_manager_vectors },
244 { MIT_Version, 1 },
245 { TAG_DONE, 0 }
248 /* ------------------- Library Interface(s) ------------------------ */
250 ULONG LibObtain(UNUSED struct Interface *Self)
252 return 0;
255 ULONG LibRelease(UNUSED struct Interface *Self)
257 return 0;
260 STATIC CONST CONST_APTR main_vectors[] =
262 (CONST_APTR)LibObtain,
263 (CONST_APTR)LibRelease,
264 (CONST_APTR)NULL,
265 (CONST_APTR)NULL,
266 (CONST_APTR)libvector,
267 (CONST_APTR)-1
270 STATIC CONST struct TagItem mainTags[] =
272 { MIT_Name, (Tag)"main" },
273 { MIT_VectorTable, (Tag)main_vectors },
274 { MIT_Version, 1 },
275 { TAG_DONE, 0 }
278 STATIC CONST CONST_APTR libInterfaces[] =
280 (CONST_APTR)lib_managerTags,
281 (CONST_APTR)mainTags,
282 (CONST_APTR)NULL
285 // Our libraries always have to carry a 68k jump table with it, so
286 // lets define it here as extern, as we are going to link it to
287 // our binary here.
288 #ifndef NO_VECTABLE68K
289 extern CONST APTR VecTable68K[];
290 #endif
292 STATIC CONST struct TagItem libCreateTags[] =
294 { CLT_DataSize, sizeof(struct LibraryHeader) },
295 { CLT_InitFunc, (Tag)LibInit },
296 { CLT_Interfaces, (Tag)libInterfaces },
297 #ifndef NO_VECTABLE68K
298 { CLT_Vector68K, (Tag)VecTable68K },
299 #endif
300 { TAG_DONE, 0 }
303 #else
305 STATIC CONST CONST_APTR LibVectors[] =
307 #ifdef __MORPHOS__
308 (CONST_APTR)FUNCARRAY_32BIT_NATIVE,
309 #endif
310 #if defined(__AROS__)
311 #ifdef AROS_ABI_V1
312 (CONST_APTR)AROS_SLIB_ENTRY(LibOpen, Codesets, 1),
313 (CONST_APTR)AROS_SLIB_ENTRY(LibClose, Codesets, 2),
314 (CONST_APTR)AROS_SLIB_ENTRY(LibExpunge, Codesets, 3),
315 #else
316 (CONST_APTR)AROS_SLIB_ENTRY(LibOpen, Codesets),
317 (CONST_APTR)AROS_SLIB_ENTRY(LibClose, Codesets),
318 (CONST_APTR)AROS_SLIB_ENTRY(LibExpunge, Codesets),
319 #endif
320 #else
321 (CONST_APTR)LibOpen,
322 (CONST_APTR)LibClose,
323 (CONST_APTR)LibExpunge,
324 #endif
325 (CONST_APTR)LibNull,
326 (CONST_APTR)libvector,
327 (CONST_APTR)-1
330 STATIC CONST IPTR LibInitTab[] =
332 sizeof(struct LibraryHeader),
333 (IPTR)LibVectors,
334 (IPTR)NULL,
335 (IPTR)LibInit
338 #endif
340 /****************************************************************************/
342 static const USED_VAR struct Resident ROMTag =
344 RTC_MATCHWORD,
345 (struct Resident *)&ROMTag,
346 (struct Resident *)(&ROMTag + 1),
347 #if defined(__amigaos4__)
348 RTF_AUTOINIT|RTF_NATIVE, // The Library should be set up according to the given table.
349 #elif defined(__MORPHOS__)
350 RTF_AUTOINIT|RTF_EXTENDED|RTF_PPC,
351 #elif defined(__AROS__)
352 RTF_AUTOINIT|RTF_EXTENDED,
353 #else
354 RTF_AUTOINIT,
355 #endif
356 LIB_VERSION,
357 NT_LIBRARY,
359 (char *)UserLibName,
360 (char *)UserLibID+6, // +6 to skip '$VER: '
361 #if defined(__amigaos4__)
362 (APTR)libCreateTags // This table is for initializing the Library.
363 #else
364 (APTR)LibInitTab,
365 #endif
366 #if defined(__MORPHOS__) || defined(__AROS__)
367 LIB_REVISION,
369 #endif
372 #if defined(__MORPHOS__)
374 * To tell the loader that this is a new emulppc elf and not
375 * one for the ppc.library.
376 * ** IMPORTANT **
378 const USED_VAR ULONG __abox__ = 1;
380 #endif /* __MORPHOS */
382 /****************************************************************************/
384 #if defined(MIN_STACKSIZE) && !defined(__amigaos4__)
386 /* generic StackSwap() function which calls function() surrounded by
387 StackSwap() calls */
389 #if defined(__mc68000__) && !defined(__AROS__)
390 ULONG stackswap_call(struct StackSwapStruct *stack,
391 ULONG (*function)(struct LibraryHeader *),
392 struct LibraryHeader *arg);
394 asm(".text \n\
395 .even \n\
396 .globl _stackswap_call \n\
397 _stackswap_call: \n\
398 moveml #0x3022,sp@- \n\
399 movel sp@(20),d3 \n\
400 movel sp@(24),a2 \n\
401 movel sp@(28),d2 \n\
402 movel _SysBase,a6 \n\
403 movel d3,a0 \n\
404 jsr a6@(-732:W) \n\
405 movel d2,sp@- \n\
406 jbsr a2@ \n\
407 movel d0,d2 \n\
408 addql #4,sp \n\
409 movel _SysBase,a6 \n\
410 movel d3,a0 \n\
411 jsr a6@(-732:W) \n\
412 movel d2,d0 \n\
413 moveml sp@+,#0x440c \n\
414 rts");
415 #elif defined(__MORPHOS__)
416 ULONG stackswap_call(struct StackSwapStruct *stack,
417 ULONG (*function)(struct LibraryHeader *),
418 struct LibraryHeader *arg)
420 struct PPCStackSwapArgs swapargs;
422 swapargs.Args[0] = (ULONG)arg;
424 return NewPPCStackSwap(stack, function, &swapargs);
426 #elif defined(__AROS__)
427 ULONG stackswap_call(struct StackSwapStruct *stack,
428 ULONG (*function)(struct LibraryHeader *),
429 struct LibraryHeader *arg)
431 struct StackSwapArgs swapargs;
433 swapargs.Args[0] = (IPTR)arg;
435 return NewStackSwap(stack, function, &swapargs);
437 #else
438 #error Bogus operating system
439 #endif
441 static BOOL callLibFunction(ULONG (*function)(struct LibraryHeader *), struct LibraryHeader *arg)
443 BOOL success = FALSE;
444 struct Task *tc;
445 ULONG stacksize;
447 // retrieve the task structure for the
448 // current task
449 tc = FindTask(NULL);
451 #if defined(__MORPHOS__)
452 // In MorphOS we have two stacks. One for PPC code and another for 68k code.
453 // We are only interested in the PPC stack.
454 NewGetTaskAttrsA(tc, &stacksize, sizeof(ULONG), TASKINFOTYPE_STACKSIZE, NULL);
455 #else
456 // on all other systems we query via SPUpper-SPLower calculation
457 stacksize = (UBYTE *)tc->tc_SPUpper - (UBYTE *)tc->tc_SPLower;
458 #endif
460 // Swap stacks only if current stack is insufficient
461 if(stacksize < MIN_STACKSIZE)
463 struct StackSwapStruct *stack;
465 if((stack = AllocVec(sizeof(*stack), MEMF_PUBLIC)) != NULL)
467 if((stack->stk_Lower = AllocVec(MIN_STACKSIZE, MEMF_PUBLIC)) != NULL)
469 // perform the StackSwap
470 #if defined(__AROS__)
471 // AROS uses an APTR type for stk_Upper
472 stack->stk_Upper = (APTR)((IPTR)stack->stk_Lower + MIN_STACKSIZE);
473 #else
474 // all other systems use ULONG
475 stack->stk_Upper = (ULONG)stack->stk_Lower + MIN_STACKSIZE;
476 #endif
477 stack->stk_Pointer = (APTR)stack->stk_Upper;
479 // call routine but with embedding it into a [NewPPC]StackSwap()
480 success = stackswap_call(stack, function, arg);
482 FreeVec(stack->stk_Lower);
484 FreeVec(stack);
487 else
488 success = function(arg);
490 return success;
492 #else // MIN_STACKSIZE && !__amigaos4__
493 #define callLibFunction(func, arg) func(arg)
494 #endif // MIN_STACKSIZE && !__amigaos4__
496 /****************************************************************************/
498 #if defined(__amigaos4__)
499 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecIFace *pIExec)
501 struct ExecBase *sb = (struct ExecBase *)pIExec->Data.LibBase;
502 IExec = pIExec;
503 #elif defined(__MORPHOS__)
504 static struct LibraryHeader * LibInit(struct LibraryHeader *base, BPTR librarySegment, struct ExecBase *sb)
506 #elif defined(__AROS__)
507 static AROS_UFH3(struct LibraryHeader *, LibInit,
508 AROS_UFHA(struct LibraryHeader *, base, D0),
509 AROS_UFHA(BPTR, librarySegment, A0),
510 AROS_UFHA(struct ExecBase *, sb, A6)
513 AROS_USERFUNC_INIT
514 #else
515 static struct LibraryHeader * LIBFUNC LibInit(REG(d0, struct LibraryHeader *base), REG(a0, BPTR librarySegment), REG(a6, struct ExecBase *sb))
517 #endif
519 SysBase = (APTR)sb;
521 // make sure that this is really a 68020+ machine if optimized for 020+
522 #if _M68060 || _M68040 || _M68030 || _M68020 || __mc68020 || __mc68030 || __mc68040 || __mc68060
523 if(!(SysBase->AttnFlags & AFF_68020))
524 return(NULL);
525 #endif
527 #if defined(__amigaos4__) && defined(__NEWLIB__)
528 if((NewlibBase = OpenLibrary("newlib.library", 3)) &&
529 GETINTERFACE(INewlib, NewlibBase))
530 #endif
532 BOOL success = FALSE;
534 #if defined(DEBUG)
535 // this must be called ahead of any debug output, otherwise we get stuck
536 InitDebug();
537 #endif
538 D(DBF_STARTUP, "LibInit()");
540 // cleanup the library header structure beginning with the
541 // library base.
542 base->libBase.lib_Node.ln_Type = NT_LIBRARY;
543 base->libBase.lib_Node.ln_Pri = 0;
544 base->libBase.lib_Node.ln_Name = (char *)UserLibName;
545 base->libBase.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
546 base->libBase.lib_Version = LIB_VERSION;
547 base->libBase.lib_Revision = LIB_REVISION;
548 base->libBase.lib_IdString = (char *)(UserLibID+6);
550 memset(&base->libSem, 0, sizeof(base->libSem));
551 InitSemaphore(&base->libSem);
552 memset(&base->poolSem, 0, sizeof(base->poolSem));
553 InitSemaphore(&base->poolSem);
555 base->sysBase = (APTR)SysBase;
556 base->pool = NULL;
557 base->flags = 0;
558 base->systemCodeset = NULL;
560 // protect access to initBase()
561 ObtainSemaphore(&base->libSem);
563 // set the CodesetsBase
564 CodesetsBase = base;
566 // If we are not running on AmigaOS4 (no stackswap required) we go and
567 // do an explicit StackSwap() in case the user wants to make sure we
568 // have enough stack for his user functions
569 success = callLibFunction(initBase, base);
571 // unprotect initBase()
572 ReleaseSemaphore(&base->libSem);
574 // check if everything worked out fine
575 if(success == TRUE)
577 // everything was successfully so lets
578 // set the initialized value and contiue
579 // with the class open phase
580 base->segList = librarySegment;
582 // return the library base as success
583 return base;
585 else
587 callLibFunction(freeBase, base);
588 CodesetsBase = NULL;
591 #if defined(__amigaos4__) && defined(__NEWLIB__)
592 if(NewlibBase)
594 DROPINTERFACE(INewlib);
595 CloseLibrary(NewlibBase);
596 NewlibBase = NULL;
598 #endif
601 return NULL;
602 #ifdef __AROS__
603 AROS_USERFUNC_EXIT
604 #endif
607 /****************************************************************************/
609 #ifndef __amigaos4__
610 #define DeleteLibrary(LIB) \
611 FreeMem((STRPTR)(LIB)-(LIB)->lib_NegSize, (ULONG)((LIB)->lib_NegSize+(LIB)->lib_PosSize))
612 #endif
614 STATIC BPTR LibDelete(struct LibraryHeader *base)
616 #if defined(__amigaos4__)
617 struct ExecIFace *IExec = (struct ExecIFace *)(*(struct ExecBase **)4)->MainInterface;
618 #endif
619 BPTR rc;
621 // make sure to restore the SysBase
622 SysBase = (APTR)base->sysBase;
624 // remove the library base from exec's lib list in advance
625 Remove((struct Node *)base);
627 // free all our private data and stuff.
628 ObtainSemaphore(&base->libSem);
630 // make sure we have enough stack here
631 callLibFunction(freeBase, base);
633 // unprotect
634 ReleaseSemaphore(&base->libSem);
636 #if defined(__amigaos4__) && defined(__NEWLIB__)
637 if(NewlibBase)
639 DROPINTERFACE(INewlib);
640 CloseLibrary(NewlibBase);
641 NewlibBase = NULL;
643 #endif
645 // make sure the system deletes the library as well.
646 rc = base->segList;
647 DeleteLibrary(&base->libBase);
649 return rc;
652 #if defined(__amigaos4__)
653 static BPTR LibExpunge(struct LibraryManagerInterface *Self)
655 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
656 #elif defined(__MORPHOS__)
657 static BPTR LibExpunge(void)
659 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
660 #elif defined(__AROS__)
661 static AROS_LH1(BPTR, LibExpunge,
662 AROS_LHA(UNUSED struct LibraryHeader *, __extrabase, D0),
663 struct LibraryHeader *, base, 3, Codesets
666 AROS_LIBFUNC_INIT
667 #else
668 static BPTR LIBFUNC LibExpunge(REG(a6, struct LibraryHeader *base))
670 #endif
671 BPTR rc;
673 D(DBF_STARTUP, "LibExpunge(): %ld", base->libBase.lib_OpenCnt);
675 // in case our open counter is still > 0, we have
676 // to set the late expunge flag and return immediately
677 if(base->libBase.lib_OpenCnt > 0)
679 base->libBase.lib_Flags |= LIBF_DELEXP;
680 rc = 0;
682 else
684 rc = LibDelete(base);
687 return rc;
688 #ifdef __AROS__
689 AROS_LIBFUNC_EXIT
690 #endif
693 /****************************************************************************/
695 #if defined(__amigaos4__)
696 static struct LibraryHeader *LibOpen(struct LibraryManagerInterface *Self, ULONG version UNUSED)
698 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
699 #elif defined(__MORPHOS__)
700 static struct LibraryHeader *LibOpen(void)
702 struct LibraryHeader *base = (struct LibraryHeader*)REG_A6;
703 #elif defined(__AROS__)
704 static AROS_LH1(struct LibraryHeader *, LibOpen,
705 AROS_LHA(UNUSED ULONG, version, D0),
706 struct LibraryHeader *, base, 1, Codesets
709 AROS_LIBFUNC_INIT
710 #else
711 static struct LibraryHeader * LIBFUNC LibOpen(REG(d0, UNUSED ULONG version), REG(a6, struct LibraryHeader *base))
713 #endif
714 struct LibraryHeader *res = base;
716 D(DBF_STARTUP, "LibOpen(): %ld", base->libBase.lib_OpenCnt);
718 // LibOpen(), LibClose() and LibExpunge() are called while the system is in
719 // Forbid() state. That means that these functions should be quick and should
720 // not break this Forbid()!! Therefore the open counter should be increased
721 // as the very first instruction during LibOpen(), because a ClassOpen()
722 // which breaks a Forbid() and another task calling LibExpunge() will cause
723 // to expunge this library while it is not yet fully initialized. A crash
724 // is unavoidable then. Even the semaphore does not guarantee 100% protection
725 // against such a race condition, because waiting for the semaphore to be
726 // obtained will effectively break the Forbid()!
728 // increase the open counter ahead of anything else
729 base->libBase.lib_OpenCnt++;
731 // delete the late expunge flag
732 base->libBase.lib_Flags &= ~LIBF_DELEXP;
734 return res;
735 #ifdef __AROS__
736 AROS_LIBFUNC_EXIT
737 #endif
740 /****************************************************************************/
742 #if defined(__amigaos4__)
743 static BPTR LibClose(struct LibraryManagerInterface *Self)
745 struct LibraryHeader *base = (struct LibraryHeader *)Self->Data.LibBase;
746 #elif defined(__MORPHOS__)
747 static BPTR LibClose(void)
749 struct LibraryHeader *base = (struct LibraryHeader *)REG_A6;
750 #elif defined(__AROS__)
751 static AROS_LH0(BPTR, LibClose,
752 struct LibraryHeader *, base, 2, Codesets
755 AROS_LIBFUNC_INIT
756 #else
757 static BPTR LIBFUNC LibClose(REG(a6, struct LibraryHeader *base))
759 #endif
760 BPTR rc = 0;
762 D(DBF_STARTUP, "LibClose(): %ld", base->libBase.lib_OpenCnt);
764 // decrease the open counter
765 base->libBase.lib_OpenCnt--;
767 // in case the opern counter is <= 0 we can
768 // make sure that we free everything
769 if(base->libBase.lib_OpenCnt <= 0)
771 // in case the late expunge flag is set we go and
772 // expunge the library base right now
773 if(base->libBase.lib_Flags & LIBF_DELEXP)
775 rc = LibDelete(base);
779 return rc;
780 #ifdef __AROS__
781 AROS_LIBFUNC_EXIT
782 #endif
785 /****************************************************************************/