r10563@lvps87-230-33-50: verhaegs | 2009-03-14 15:24:28 +0100
[cake.git] / compiler / clib / arosc_init.c
blob3faa2a28fc5169ee00ae50b636f7f9a29f0a00e1
1 /*
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 $Id$
4 */
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"
16 #endif
18 #include <stddef.h>
19 #include <ctype.h>
20 #include <sys/stat.h>
21 #include <setjmp.h>
22 #include <assert.h>
24 #define DEBUG 0
25 #include <aros/debug.h>
27 #include "etask.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;
51 int entry(void)
53 /* If the library was executed by accident return error code. */
54 return -1;
57 const struct Resident resident=
59 RTC_MATCHWORD,
60 (struct Resident *)&resident,
61 (APTR)&arosc_end,
62 RTF_AUTOINIT,
63 41,
64 NT_LIBRARY,
66 (char *)name,
67 (char *)&version[6],
68 (ULONG *)inittabl
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,
79 NULL,
80 &AROS_SLIB_ENTRY(init,arosc)
83 DECLARESET(INIT);
84 DECLARESET(EXIT);
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)
92 AROS_USERFUNC_INIT
94 /* This function is single-threaded by exec by calling Forbid. */
96 /* Store arguments */
97 aroscbase = __aroscbase;
98 SysBase = __SysBase;
100 aroscbase->seglist=segList;
102 if (!set_open_libraries())
104 set_close_libraries();
106 return NULL;
109 /* You would return NULL here if the init failed. */
110 return aroscbase;
111 AROS_USERFUNC_EXIT
115 AROS_LH1(struct aroscbase *, open,
116 AROS_LHA(ULONG, version, D0),
117 struct aroscbase *, aroscbase, 1, arosc)
119 AROS_LIBFUNC_INIT
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 */
127 version=0;
129 if (!arosc_internalinit())
131 arosc_internalexit();
132 return NULL;
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. */
140 return aroscbase;
142 AROS_LIBFUNC_EXIT
145 AROS_LH0(BPTR, close, struct aroscbase *, aroscbase, 2, arosc)
147 AROS_LIBFUNC_INIT
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 */
160 return expunge();
163 arosc_internalexit();
165 return 0;
166 AROS_LIBFUNC_EXIT
169 AROS_LH0(BPTR, expunge, struct aroscbase *, aroscbase, 3, arosc)
171 AROS_LIBFUNC_INIT
173 BPTR ret;
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;
184 return 0;
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);
199 return ret;
200 AROS_LIBFUNC_EXIT
202 AROS_LH0I(int, null, struct aroscbase *, aroscbase, 4, arosc)
204 AROS_LIBFUNC_INIT
205 return 0;
206 AROS_LIBFUNC_EXIT
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));
220 if (!oldprivdata)
222 /* This process does not have arosc_privdata. Check parent */
223 struct arosc_privdata * parentprivdata = __get_arosc_privdata();
225 if (parentprivdata)
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) */
231 return res;
236 if (!oldprivdata)
238 makenew = TRUE;
240 else
242 assert(!(oldprivdata->acpd_flags & (CREATE_NEW_ACPD | KEEP_OLD_ACPD)));
243 if (oldprivdata->acpd_flags & CREATE_NEW_ACPD)
245 makenew = TRUE;
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;
253 else
255 makenew = oldprivdata->acpd_process_returnaddr != me->pr_ReturnAddr;
259 if (makenew)
261 D(bug("arosc_internalinit(): AllocMem()\n"));
262 privdata = AllocMem(sizeof *privdata, MEMF_CLEAR|MEMF_ANY);
264 if (!privdata)
266 SetIoErr(ERROR_NO_FREE_STORE);
267 return FALSE;
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++;
282 return res;
285 int arosc_internalexit(void)
287 struct arosc_privdata *privdata = GetIntETask(FindTask(NULL))->iet_acpd;
289 D(bug("arosc_internalexit(): --acpd_usercount\n"));
291 if (!privdata)
293 /* This process does not have priv data. Check if parent has */
294 struct arosc_privdata * parentprivdata = __get_arosc_privdata();
296 if (parentprivdata)
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. */
302 return 0;
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));
321 return 0;
324 DEFINESET(INIT);
325 DEFINESET(EXIT);