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>
23 APTR __regina_semaphorepool
;
25 typedef struct _mt_tsd_t
{
30 /* Lowest level memory allocation function for normal circumstances. */
31 static void *MTMalloc(const tsd_t
*TSD
,size_t size
)
33 mt_tsd_t
*mt
= (mt_tsd_t
*)TSD
->mt_tsd
;
36 size
+= sizeof(size_t);
37 mem
= AllocPooled( mt
->mempool
, size
);
42 return (void *)(((char *)mem
)+sizeof(size_t));
45 /* Lowest level memory deallocation function for normal circumstances. */
46 static void MTFree(const tsd_t
*TSD
,void *chunk
)
48 mt_tsd_t
*mt
= (mt_tsd_t
*)TSD
->mt_tsd
;
49 APTR mem
= (APTR
)(((char *)chunk
)-sizeof(size_t));
51 FreePooled( mt
->mempool
, (APTR
)mem
, *(size_t *)mem
);
54 /* Lowest level exit handler. Use this indirection to prevent errors. */
55 static void MTExit(int code
)
57 D(bug("[mt_amigalib::MTExit] exiting with code=%d\n", code
));
62 void exit_amigaf( APTR
); /* In amifuncs.c */
64 static void cleanup(int dummy
, void *ptr
)
66 tsd_node_t
*node
= (tsd_node_t
*)ptr
;
67 mt_tsd_t
*mt
= (mt_tsd_t
*)node
->TSD
->mt_tsd
;
69 D(bug("[mt_amigalib::cleanup] node=%p\n"));
71 exit_amigaf( node
->TSD
->ami_tsd
);
73 DeletePool( mt
->mempool
);
75 node
->TSD
= NULL
; /* Node is cleared */
78 int IfcReginaCleanup( VOID
)
80 /* Do nothing, currently cleanup is done through on_exit function */
84 tsd_t
*ReginaInitializeThread(void)
88 tsd_t
*__regina_tsd
= malloc(sizeof(tsd_t
));
91 D(bug("[mt_amigalib::ReginaInitializeThread] TSD=%p\n", __regina_tsd
));
93 /* Default all values to zero */
94 memset(__regina_tsd
,0,sizeof(tsd_t
));
95 __regina_tsd
->MTMalloc
= MTMalloc
;
96 __regina_tsd
->MTFree
= MTFree
;
97 __regina_tsd
->MTExit
= MTExit
;
99 OK
= ( __regina_tsd
->mt_tsd
= malloc(sizeof(mt_tsd_t
))) != NULL
;
100 mt
= (mt_tsd_t
*)__regina_tsd
->mt_tsd
;
101 OK
&= ( mt
->mempool
= CreatePool(MEMF_PUBLIC
, 8192, 1024) ) != NULL
;
103 OK
&= init_memory(__regina_tsd
); /* Initialize the memory module FIRST*/
105 D(bug("[mt_amigalib::ReginaInitializeThread] TSD->mem_tsd=%p\n", __regina_tsd
->mem_tsd
));
107 /* Without the initial memory we don't have ANY chance! */
112 extern OS_Dep_funcs __regina_OS_Amiga
;
113 __regina_tsd
->OS
= &__regina_OS_Amiga
;
116 OK
&= init_vars(__regina_tsd
); /* Initialize the variable module */
117 OK
&= init_stacks(__regina_tsd
); /* Initialize the stack module */
118 OK
&= init_filetable(__regina_tsd
); /* Initialize the files module */
119 OK
&= init_math(__regina_tsd
); /* Initialize the math module */
120 OK
&= init_spec_vars(__regina_tsd
); /* Initialize the interprt module */
121 OK
&= init_tracing(__regina_tsd
); /* Initialize the tracing module */
122 OK
&= init_builtin(__regina_tsd
); /* Initialize the builtin module */
123 OK
&= init_client(__regina_tsd
); /* Initialize the client module */
124 OK
&= init_library(__regina_tsd
); /* Initialize the library module */
125 OK
&= init_rexxsaa(__regina_tsd
); /* Initialize the rexxsaa module */
126 OK
&= init_shell(__regina_tsd
); /* Initialize the shell module */
127 OK
&= init_envir(__regina_tsd
); /* Initialize the envir module */
128 OK
&= init_expr(__regina_tsd
); /* Initialize the expr module */
129 OK
&= init_error(__regina_tsd
); /* Initialize the error module */
131 OK
&= init_vms(__regina_tsd
); /* Initialize the vmscmd module */
132 OK
&= init_vmf(__regina_tsd
); /* Initialize the vmsfuncs module */
134 OK
&= init_arexxf(__regina_tsd
); /* Initialize the arexxfuncs module */
135 OK
&= init_amigaf(__regina_tsd
); /* Initialize the amigafuncs module */
136 __regina_tsd
->loopcnt
= 1; /* stupid r2perl-module */
137 __regina_tsd
->traceparse
= -1;
138 __regina_tsd
->thread_id
= 1;
140 /* Initiliaze thread specific data */
142 exiterror( ERR_STORAGE_EXHAUSTED
, 0 ) ;
144 return(__regina_tsd
);
147 void AmigaLockSemaphore(struct SignalSemaphore
**semaphoreptr
)
149 if (*semaphoreptr
== NULL
)
153 if (*semaphoreptr
== NULL
)
155 *semaphoreptr
= AllocPooled (__regina_semaphorepool
, sizeof(struct SignalSemaphore
));
156 InitSemaphore(*semaphoreptr
);
162 ObtainSemaphore(*semaphoreptr
);
165 void AmigaUnlockSemaphore(struct SignalSemaphore
*semaphore
)
167 assert(semaphore
!=NULL
);
168 ReleaseSemaphore(semaphore
);
172 tsd_t
*__regina_get_tsd(void)
174 struct Task
*thistask
= FindTask(NULL
);
177 D(bug("[mt_amigalib::__regina_get_tsd] thistask=%p\n", thistask
));
179 node
= (tsd_node_t
*)GetHead(__regina_tsdlist
);
180 while (node
!=NULL
&& node
->task
!=thistask
)
181 node
= (tsd_node_t
*)GetSucc(node
);
183 D(bug("[mt_amigalib::__regina_get_tsd] node=%p\n", node
));
187 /* taskdata not found */
188 node
= (tsd_node_t
*)AllocPooled(__regina_semaphorepool
, sizeof(tsd_node_t
));
189 node
->task
= thistask
;
190 node
->TSD
= ReginaInitializeThread();
191 AddTail((struct List
*)__regina_tsdlist
, (struct Node
*)node
);
192 on_exit(cleanup
, 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 on_exit(cleanup
, node
);
199 D(bug("[mt_amigalib::__regina_get_tsd] new TSD=%p\n", node
->TSD
));