1 /* This is the file to support single-threading.
2 * We initialize the global data structure and the global access variable.
5 #if !defined(__AROS__) && !defined(_AMIGA)
6 # error mt_amiga.c only works on Amiga or AROS
10 # error compiling mt_amiga.c without being a library does not make sense
15 #include <proto/alib.h>
16 #include <exec/memory.h>
19 #include <aros/debug.h>
20 #include <aros/symbolsets.h>
24 APTR __regina_semaphorepool
;
26 typedef struct _mt_tsd_t
{
31 /* Lowest level memory allocation function for normal circumstances. */
32 static void *MTMalloc(const tsd_t
*TSD
,size_t size
)
34 mt_tsd_t
*mt
= (mt_tsd_t
*)TSD
->mt_tsd
;
37 size
+= sizeof(size_t);
38 mem
= AllocPooled( mt
->mempool
, size
);
43 return (void *)(((char *)mem
)+sizeof(size_t));
46 /* Lowest level memory deallocation function for normal circumstances. */
47 static void MTFree(const tsd_t
*TSD
,void *chunk
)
49 mt_tsd_t
*mt
= (mt_tsd_t
*)TSD
->mt_tsd
;
50 APTR mem
= (APTR
)(((char *)chunk
)-sizeof(size_t));
52 FreePooled( mt
->mempool
, (APTR
)mem
, *(size_t *)mem
);
55 /* Lowest level exit handler. Use this indirection to prevent errors. */
56 static void MTExit(int code
)
58 D(bug("[mt_amigalib::MTExit] exiting with code=%d\n", code
));
63 void exit_amigaf( APTR
); /* In amifuncs.c */
65 static void cleanup(int dummy
, void *ptr
)
67 tsd_node_t
*node
= (tsd_node_t
*)ptr
;
68 mt_tsd_t
*mt
= (mt_tsd_t
*)node
->TSD
->mt_tsd
;
70 D(bug("[mt_amigalib::cleanup] node=%p\n"));
72 exit_amigaf( node
->TSD
->ami_tsd
);
74 DeletePool( mt
->mempool
);
76 node
->TSD
= NULL
; /* Node is cleared */
79 int IfcReginaCleanup( VOID
)
81 /* Do nothing, currently cleanup is done through on_exit function */
85 tsd_t
*ReginaInitializeThread(void)
89 tsd_t
*__regina_tsd
= malloc(sizeof(tsd_t
));
92 D(bug("[mt_amigalib::ReginaInitializeThread] TSD=%p\n", __regina_tsd
));
94 /* Default all values to zero */
95 memset(__regina_tsd
,0,sizeof(tsd_t
));
96 __regina_tsd
->MTMalloc
= MTMalloc
;
97 __regina_tsd
->MTFree
= MTFree
;
98 __regina_tsd
->MTExit
= MTExit
;
100 OK
= ( __regina_tsd
->mt_tsd
= malloc(sizeof(mt_tsd_t
))) != NULL
;
101 mt
= (mt_tsd_t
*)__regina_tsd
->mt_tsd
;
102 OK
&= ( mt
->mempool
= CreatePool(MEMF_PUBLIC
, 8192, 1024) ) != NULL
;
104 OK
&= init_memory(__regina_tsd
); /* Initialize the memory module FIRST*/
106 D(bug("[mt_amigalib::ReginaInitializeThread] TSD->mem_tsd=%p\n", __regina_tsd
->mem_tsd
));
108 /* Without the initial memory we don't have ANY chance! */
113 extern OS_Dep_funcs __regina_OS_Amiga
;
114 __regina_tsd
->OS
= &__regina_OS_Amiga
;
117 OK
&= init_vars(__regina_tsd
); /* Initialize the variable module */
118 OK
&= init_stacks(__regina_tsd
); /* Initialize the stack module */
119 OK
&= init_filetable(__regina_tsd
); /* Initialize the files module */
120 OK
&= init_math(__regina_tsd
); /* Initialize the math module */
121 OK
&= init_spec_vars(__regina_tsd
); /* Initialize the interprt module */
122 OK
&= init_tracing(__regina_tsd
); /* Initialize the tracing module */
123 OK
&= init_builtin(__regina_tsd
); /* Initialize the builtin module */
124 OK
&= init_client(__regina_tsd
); /* Initialize the client module */
125 OK
&= init_library(__regina_tsd
); /* Initialize the library module */
126 OK
&= init_rexxsaa(__regina_tsd
); /* Initialize the rexxsaa module */
127 OK
&= init_shell(__regina_tsd
); /* Initialize the shell module */
128 OK
&= init_envir(__regina_tsd
); /* Initialize the envir module */
129 OK
&= init_expr(__regina_tsd
); /* Initialize the expr module */
130 OK
&= init_error(__regina_tsd
); /* Initialize the error module */
132 OK
&= init_vms(__regina_tsd
); /* Initialize the vmscmd module */
133 OK
&= init_vmf(__regina_tsd
); /* Initialize the vmsfuncs module */
135 OK
&= init_arexxf(__regina_tsd
); /* Initialize the arexxfuncs module */
136 OK
&= init_amigaf(__regina_tsd
); /* Initialize the amigafuncs module */
137 __regina_tsd
->loopcnt
= 1; /* stupid r2perl-module */
138 __regina_tsd
->traceparse
= -1;
139 __regina_tsd
->thread_id
= 1;
141 /* Initiliaze thread specific data */
143 exiterror( ERR_STORAGE_EXHAUSTED
, 0 ) ;
145 return(__regina_tsd
);
148 void AmigaLockSemaphore(struct SignalSemaphore
**semaphoreptr
)
150 if (*semaphoreptr
== NULL
)
154 if (*semaphoreptr
== NULL
)
156 *semaphoreptr
= AllocPooled (__regina_semaphorepool
, sizeof(struct SignalSemaphore
));
157 InitSemaphore(*semaphoreptr
);
163 ObtainSemaphore(*semaphoreptr
);
166 void AmigaUnlockSemaphore(struct SignalSemaphore
*semaphore
)
168 assert(semaphore
!=NULL
);
169 ReleaseSemaphore(semaphore
);
173 tsd_t
*__regina_get_tsd(void)
175 struct Task
*thistask
= FindTask(NULL
);
178 D(bug("[mt_amigalib::__regina_get_tsd] thistask=%p\n", thistask
));
180 node
= (tsd_node_t
*)GetHead(__regina_tsdlist
);
181 while (node
!=NULL
&& node
->task
!=thistask
)
182 node
= (tsd_node_t
*)GetSucc(node
);
184 D(bug("[mt_amigalib::__regina_get_tsd] node=%p\n", node
));
188 /* taskdata not found */
189 node
= (tsd_node_t
*)AllocPooled(__regina_semaphorepool
, sizeof(tsd_node_t
));
190 node
->task
= thistask
;
191 node
->TSD
= ReginaInitializeThread();
192 AddTail((struct List
*)__regina_tsdlist
, (struct Node
*)node
);
193 D(bug("[mt_amigalib::__regina_get_tsd] new node=%p, TSD=%p\n", node
, node
->TSD
));
195 else if (node
->TSD
==NULL
) /* Was MTExit called on this task ? */
197 node
->TSD
= ReginaInitializeThread();
198 D(bug("[mt_amigalib::__regina_get_tsd] new TSD=%p\n", node
->TSD
));
204 /* Run cleanup on closing of per-task library base */
205 void CloseLib(APTR base
)
207 struct Task
*thistask
= FindTask(NULL
);
210 node
= (tsd_node_t
*)GetHead(__regina_tsdlist
);
211 while (node
!=NULL
&& node
->task
!=thistask
)
212 node
= (tsd_node_t
*)GetSucc(node
);
218 ADD2CLOSELIB(CloseLib
, 0);