2 Copyright © 1995-2009, 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"
25 #include <aros/debug.h>
28 #include "__arosc_privdata.h"
29 #include "arosc_init.h"
31 THIS_PROGRAM_HANDLES_SYMBOLSETS
33 extern const char name
[];
34 extern const char version
[];
35 extern const APTR inittabl
[4];
36 extern void *const arosc_functable
[];
37 extern const struct inittable datatable
;
38 extern struct aroscbase
*AROS_SLIB_ENTRY(init
,arosc
)();
39 AROS_LD1(struct aroscbase
*, open
, AROS_LDA(ULONG
, version
, D0
), struct aroscbase
*, aroscbase
, 1, arosc
);
40 AROS_LD0(BPTR
, close
, struct aroscbase
*, aroscbase
, 2, arosc
);
41 AROS_LD0(BPTR
, expunge
, struct aroscbase
*, aroscbase
, 3, arosc
);
42 AROS_LD0I(int, null
, struct aroscbase
*, aroscbase
, 4, arosc
);
43 extern const char arosc_end
;
45 struct ExecBase
*SysBase
;
46 struct aroscbase
*aroscbase
;
48 extern struct DosLibrary
*DOSBase
;
53 /* If the library was executed by accident return error code. */
57 const struct Resident resident
=
60 (struct Resident
*)&resident
,
71 const char name
[]="arosc.library";
73 const char version
[]="$VER: arosc.library 41.1 (" __DATE__
")\n\015";
75 const APTR inittabl
[4]=
77 (APTR
)sizeof(struct aroscbase
),
78 (APTR
)arosc_functable
,
80 &AROS_SLIB_ENTRY(init
,arosc
)
86 AROS_UFH3(struct aroscbase
*, AROS_SLIB_ENTRY(init
,arosc
),
87 AROS_UFHA(struct aroscbase
*, __aroscbase
, D0
),
88 AROS_UFHA(BPTR
, segList
, A0
),
89 AROS_UFHA(struct ExecBase
*, __SysBase
, A6
)
94 /* This function is single-threaded by exec by calling Forbid. */
97 aroscbase
= __aroscbase
;
100 aroscbase
->seglist
=segList
;
102 if (!set_open_libraries())
104 set_close_libraries();
109 /* You would return NULL here if the init failed. */
115 AROS_LH1(struct aroscbase
*, open
,
116 AROS_LHA(ULONG
, version
, D0
),
117 struct aroscbase
*, aroscbase
, 1, arosc
)
121 This function is single-threaded by exec by calling Forbid.
122 If you break the Forbid() another task may enter this function
123 at the same time. Take care.
126 /* Keep compiler happy */
129 if (!arosc_internalinit())
131 arosc_internalexit();
135 /* I have one more opener. */
136 aroscbase
->library
.lib_OpenCnt
++;
137 aroscbase
->library
.lib_Flags
&= ~LIBF_DELEXP
;
139 /* You would return NULL if the open failed. */
145 AROS_LH0(BPTR
, close
, struct aroscbase
*, aroscbase
, 2, arosc
)
149 This function is single-threaded by exec by calling Forbid.
150 If you break the Forbid() another task may enter this function
151 at the same time. Take care.
154 /* I have one fewer opener. */
155 if(!--aroscbase
->library
.lib_OpenCnt
)
157 /* Delayed expunge pending? */
158 if(aroscbase
->library
.lib_Flags
&LIBF_DELEXP
)
159 /* Then expunge the library */
163 arosc_internalexit();
169 AROS_LH0(BPTR
, expunge
, struct aroscbase
*, aroscbase
, 3, arosc
)
175 This function is single-threaded by exec by calling Forbid.
176 Never break the Forbid() or strange things might happen.
179 /* Test for openers. */
180 if(aroscbase
->library
.lib_OpenCnt
)
182 /* Set the delayed expunge flag and return. */
183 aroscbase
->library
.lib_Flags
|=LIBF_DELEXP
;
187 /* Get rid of the library. Remove it from the list. */
188 Remove(&aroscbase
->library
.lib_Node
);
190 /* Get returncode here - FreeMem() will destroy the field. */
191 ret
=aroscbase
->seglist
;
193 set_close_libraries();
195 /* Free the memory. */
196 FreeMem((char *)aroscbase
-aroscbase
->library
.lib_NegSize
,
197 aroscbase
->library
.lib_NegSize
+aroscbase
->library
.lib_PosSize
);
202 AROS_LH0I(int, null
, struct aroscbase
*, aroscbase
, 4, arosc
)
209 int arosc_internalinit(void)
211 struct arosc_privdata
*oldprivdata
, *privdata
;
212 struct Process
*me
= (struct Process
*)FindTask(NULL
);
213 int res
= TRUE
, makenew
= FALSE
;
215 privdata
= oldprivdata
= GetIntETask(me
)->iet_acpd
;
217 D(bug("\nEntering arosc_internalinit(): me->name = %s\n", me
->pr_Task
.tc_Node
.ln_Name
));
218 D(bug("arosc_internalinit(): oldprivdata = %p\n", oldprivdata
));
222 /* This process does not have arosc_privdata. Check parent */
223 struct arosc_privdata
* parentprivdata
= __get_arosc_privdata();
227 /* Parent has arosc_privdata. Is is shared it with this process? */
228 if (parentprivdata
->acpd_flags
& SHARE_ACPD_WITH_CHILD
)
230 /* Yes. Do nothing. (reuse parents arosc_privdata) */
242 assert(!(oldprivdata
->acpd_flags
& (CREATE_NEW_ACPD
| KEEP_OLD_ACPD
)));
243 if (oldprivdata
->acpd_flags
& CREATE_NEW_ACPD
)
246 oldprivdata
->acpd_flags
&= ~CREATE_NEW_ACPD
;
248 else if (oldprivdata
->acpd_flags
& KEEP_OLD_ACPD
)
250 oldprivdata
->acpd_flags
&= ~KEEP_OLD_ACPD
;
251 oldprivdata
->acpd_process_returnaddr
= me
->pr_ReturnAddr
;
255 makenew
= oldprivdata
->acpd_process_returnaddr
!= me
->pr_ReturnAddr
;
261 D(bug("arosc_internalinit(): AllocMem()\n"));
262 privdata
= AllocMem(sizeof *privdata
, MEMF_CLEAR
|MEMF_ANY
);
266 SetIoErr(ERROR_NO_FREE_STORE
);
270 D(bug("arosc_internalinit(): newprivdata = %p\n", privdata
));
271 privdata
->acpd_oldprivdata
= oldprivdata
;
272 privdata
->acpd_process_returnaddr
= me
->pr_ReturnAddr
;
274 GetIntETask(me
)->iet_acpd
= privdata
;
276 res
= set_call_funcs(SETNAME(INIT
), 1, 1);
279 D(bug("arosc_internalinit(): acpd_usercount++\n"));
280 privdata
->acpd_usercount
++;
285 int arosc_internalexit(void)
287 struct arosc_privdata
*privdata
= GetIntETask(FindTask(NULL
))->iet_acpd
;
289 D(bug("arosc_internalexit(): --acpd_usercount\n"));
293 /* This process does not have priv data. Check if parent has */
294 struct arosc_privdata
* parentprivdata
= __get_arosc_privdata();
298 /* Parent has arosc_privdata. Is is shared it with this process? */
299 if (parentprivdata
->acpd_flags
& SHARE_ACPD_WITH_CHILD
)
301 /* Yes. Do nothing. */
307 #warning FIXME: privdata should NEVER be NULL here
308 ASSERT_VALID_PTR(privdata
);
309 if (privdata
&& --privdata
->acpd_usercount
== 0)
311 set_call_funcs(SETNAME(EXIT
), -1, 0);
313 /*restore the old value */
314 GetIntETask(FindTask(NULL
))->iet_acpd
= privdata
->acpd_oldprivdata
;
316 D(bug("arosc_internalexit(): FreeMem()\n"));
317 FreeMem(privdata
, sizeof(*privdata
));
320 D(bug("Exiting arosc_internalexit(): me->name = %s\n\n", FindTask(NULL
)->tc_Node
.ln_Name
));