2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
6 #include <exec/types.h>
7 #include <exec/resident.h>
8 #include <exec/memory.h>
9 #include <proto/exec.h>
10 #include <proto/dos.h>
11 #include <aros/libcall.h>
12 #include <aros/asmcall.h>
13 #include <aros/symbolsets.h>
14 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
15 # include "arosc_gcc.h"
24 #include <aros/debug.h>
27 #include "__arosc_privdata.h"
28 #include "arosc_init.h"
30 THIS_PROGRAM_HANDLES_SYMBOLSETS
32 extern const char name
[];
33 extern const char version
[];
34 extern const APTR inittabl
[4];
35 extern void *const arosc_functable
[];
36 extern const struct inittable datatable
;
37 extern struct aroscbase
*AROS_SLIB_ENTRY(init
,arosc
)();
38 AROS_LD1(struct aroscbase
*, open
, AROS_LDA(ULONG
, version
, D0
), struct aroscbase
*, aroscbase
, 1, arosc
);
39 AROS_LD0(BPTR
, close
, struct aroscbase
*, aroscbase
, 2, arosc
);
40 AROS_LD0(BPTR
, expunge
, struct aroscbase
*, aroscbase
, 3, arosc
);
41 AROS_LD0I(int, null
, struct aroscbase
*, aroscbase
, 4, arosc
);
42 extern const char arosc_end
;
44 struct ExecBase
*SysBase
;
45 struct aroscbase
*aroscbase
;
47 extern struct DosLibrary
*DOSBase
;
52 /* If the library was executed by accident return error code. */
56 const struct Resident resident
=
59 (struct Resident
*)&resident
,
70 const char name
[]="arosc.library";
72 const char version
[]="$VER: arosc.library 41.1 (" __DATE__
")\n\015";
74 const APTR inittabl
[4]=
76 (APTR
)sizeof(struct aroscbase
),
77 (APTR
)arosc_functable
,
79 &AROS_SLIB_ENTRY(init
,arosc
)
85 AROS_UFH3(struct aroscbase
*, AROS_SLIB_ENTRY(init
,arosc
),
86 AROS_UFHA(struct aroscbase
*, __aroscbase
, D0
),
87 AROS_UFHA(BPTR
, segList
, A0
),
88 AROS_UFHA(struct ExecBase
*, __SysBase
, A6
)
93 /* This function is single-threaded by exec by calling Forbid. */
96 aroscbase
= __aroscbase
;
99 aroscbase
->seglist
=segList
;
101 if (!set_open_libraries())
103 set_close_libraries();
108 /* You would return NULL here if the init failed. */
114 AROS_LH1(struct aroscbase
*, open
,
115 AROS_LHA(ULONG
, version
, D0
),
116 struct aroscbase
*, aroscbase
, 1, arosc
)
120 This function is single-threaded by exec by calling Forbid.
121 If you break the Forbid() another task may enter this function
122 at the same time. Take care.
125 /* Keep compiler happy */
128 if (!arosc_internalinit())
130 arosc_internalexit();
134 /* I have one more opener. */
135 aroscbase
->library
.lib_OpenCnt
++;
136 aroscbase
->library
.lib_Flags
&= ~LIBF_DELEXP
;
138 /* You would return NULL if the open failed. */
144 AROS_LH0(BPTR
, close
, struct aroscbase
*, aroscbase
, 2, arosc
)
148 This function is single-threaded by exec by calling Forbid.
149 If you break the Forbid() another task may enter this function
150 at the same time. Take care.
153 /* I have one fewer opener. */
154 if(!--aroscbase
->library
.lib_OpenCnt
)
156 /* Delayed expunge pending? */
157 if(aroscbase
->library
.lib_Flags
&LIBF_DELEXP
)
158 /* Then expunge the library */
162 arosc_internalexit();
168 AROS_LH0(BPTR
, expunge
, struct aroscbase
*, aroscbase
, 3, arosc
)
174 This function is single-threaded by exec by calling Forbid.
175 Never break the Forbid() or strange things might happen.
178 /* Test for openers. */
179 if(aroscbase
->library
.lib_OpenCnt
)
181 /* Set the delayed expunge flag and return. */
182 aroscbase
->library
.lib_Flags
|=LIBF_DELEXP
;
186 /* Get rid of the library. Remove it from the list. */
187 Remove(&aroscbase
->library
.lib_Node
);
189 /* Get returncode here - FreeMem() will destroy the field. */
190 ret
=aroscbase
->seglist
;
192 set_close_libraries();
194 /* Free the memory. */
195 FreeMem((char *)aroscbase
-aroscbase
->library
.lib_NegSize
,
196 aroscbase
->library
.lib_NegSize
+aroscbase
->library
.lib_PosSize
);
201 AROS_LH0I(int, null
, struct aroscbase
*, aroscbase
, 4, arosc
)
208 int arosc_internalinit(void)
210 struct arosc_privdata
*oldprivdata
, *privdata
;
211 struct Process
*me
= (struct Process
*)FindTask(NULL
);
214 privdata
= oldprivdata
= GetIntETask(me
)->iet_acpd
;
216 D(bug("\nEntering arosc_internalinit(): me->name = %s\n", me
->pr_Task
.tc_Node
.ln_Name
));
217 D(bug("arosc_internalinit(): oldprivdata = %p\n", oldprivdata
));
221 (!oldprivdata
->acpd_spawned
&& oldprivdata
->acpd_process_returnaddr
!= me
->pr_ReturnAddr
)
224 D(bug("arosc_internalinit(): AllocMem()\n"));
225 privdata
= AllocMem(sizeof *privdata
, MEMF_CLEAR
|MEMF_ANY
);
229 SetIoErr(ERROR_NO_FREE_STORE
);
233 D(bug("arosc_internalinit(): newprivdata = %p\n", privdata
));
234 privdata
->acpd_oldprivdata
= oldprivdata
;
235 privdata
->acpd_process_returnaddr
= me
->pr_ReturnAddr
;
237 GetIntETask(me
)->iet_acpd
= privdata
;
239 res
= set_call_funcs(SETNAME(INIT
), 1, 1);
242 D(bug("arosc_internalinit(): acpd_usercount++\n"));
243 privdata
->acpd_usercount
++;
248 int arosc_internalexit(void)
250 struct arosc_privdata
*privdata
= GetIntETask(FindTask(NULL
))->iet_acpd
;
252 D(bug("arosc_internalexit(): --acpd_usercount\n"));
254 #warning FIXME: privdata should NEVER be NULL here
255 ASSERT_VALID_PTR(privdata
);
256 if (privdata
&& --privdata
->acpd_usercount
== 0)
258 set_call_funcs(SETNAME(EXIT
), -1, 0);
260 /*restore the old value */
261 GetIntETask(FindTask(NULL
))->iet_acpd
= privdata
->acpd_oldprivdata
;
263 D(bug("arosc_internalexit(): FreeMem()\n"));
264 FreeMem(privdata
, sizeof(*privdata
));
267 D(bug("Exiting arosc_internalexit(): me->name = %s\n\n", FindTask(NULL
)->tc_Node
.ln_Name
));