Added Text2PDF, a tool which converts text files
[AROS-Contrib.git] / regina / mt_notmt.c
blobec791e21a127359ae8fb0d1f67209f19e5573b6c
1 /* This is the file to support single-threading.
2 * We initialize the global data structure and the global access variable.
3 */
5 #include "regina_c.h"
6 #include "rexxsaa.h"
7 #define DONT_TYPEDEF_PFN
8 #include "rexx.h"
10 typedef struct _MT_mem {
11 struct _MT_mem *prev;
12 struct _MT_mem *next;
13 /* real data follows here */
14 } MT_mem;
16 typedef struct { /* mt_tsd: static variables of this module (thread-safe) */
17 MT_mem *mem_base;
18 } mt_tsd_t; /* thread-specific but only needed by this module. see
19 * ReginaInitializeThread
22 int __regina_tsd_initialized = 0;
23 tsd_t __regina_tsd = {0,}; /* Be sure the var is initialized here */
25 /* Lowest level memory allocation function for normal circumstances. */
26 static void *MTMalloc(const tsd_t *TSD,size_t size)
28 mt_tsd_t *mt;
29 MT_mem *newptr = (MT_mem *)malloc(size + sizeof(MT_mem));
31 if (newptr == NULL) /* may happen. errors are detected in the above layers */
32 return(NULL);
34 mt = (mt_tsd_t *)TSD->mt_tsd;
35 newptr->prev = NULL;
36 newptr->next = mt->mem_base;
37 if (mt->mem_base)
38 mt->mem_base->prev = newptr;
39 mt->mem_base = newptr;
40 return(newptr + 1); /* jump over the head */
43 /* Lowest level memory deallocation function for normal circumstances. */
44 static void MTFree(const tsd_t *TSD,void *chunk)
46 mt_tsd_t *mt = (mt_tsd_t *)TSD->mt_tsd;
47 MT_mem *thisptr;
50 * Just in case...
52 if ( chunk == NULL)
53 return;
55 thisptr = (MT_mem *)chunk;
56 thisptr--; /* Go to the header of the chunk */
58 if (thisptr->prev)
60 if (thisptr->prev->next != thisptr)
61 return;
63 if (thisptr->next)
65 if (thisptr->next->prev != thisptr)
66 return;
69 /* This is a chunk allocated by MTMalloc */
70 if (thisptr->prev)
71 thisptr->prev->next = thisptr->next;
72 if (thisptr->next)
73 thisptr->next->prev = thisptr->prev;
74 if (thisptr == mt->mem_base)
75 mt->mem_base = thisptr->next;
77 /* Last not least we set the pointers to NULL. This prevents a double-free*/
78 thisptr->next = NULL;
79 thisptr->prev = NULL;
80 free(thisptr);
83 /* Lowest level exit handler. Use this indirection to prevent errors. */
84 static void MTExit(int code)
86 exit(code);
89 int IfcReginaCleanup( VOID )
91 tsd_t *TSD = &__regina_tsd;
92 mt_tsd_t *mt;
93 MT_mem *chunk;
95 if (!__regina_tsd_initialized)
96 return 0;
98 __regina_tsd_initialized = 0;
100 deinit_rexxsaa(TSD);
102 mt = (mt_tsd_t *)TSD->mt_tsd;
103 if (mt)
105 while ((chunk = mt->mem_base) != NULL)
107 TSD->MTFree(TSD,chunk + 1);
108 if (mt->mem_base == chunk)
109 break; /* something goes wrong. Don't run into an endless loop */
112 if (mt)
113 free(mt);
114 memset( TSD, 0, sizeof(tsd_t) );
115 return 1;
118 tsd_t *ReginaInitializeProcess(void)
120 int OK;
122 if (__regina_tsd_initialized)
123 return(&__regina_tsd);
124 __regina_tsd_initialized = 1;
126 /* Set up the current (single) tsd_t:*/
127 /* Default all values to zero */
128 memset(&__regina_tsd,0,sizeof(__regina_tsd));
129 __regina_tsd.MTMalloc = MTMalloc;
130 __regina_tsd.MTFree = MTFree;
131 __regina_tsd.MTExit = MTExit;
133 /* Since the local data structure contains a memory chain for the memory
134 * management we initialize it first.
136 if ((__regina_tsd.mt_tsd = malloc(sizeof(mt_tsd_t))) == NULL)
137 return(NULL); /* This is a catastrophy */
138 memset(__regina_tsd.mt_tsd,0,sizeof(mt_tsd_t));
140 OK = init_memory(&__regina_tsd); /* Initialize the memory module FIRST*/
142 /* Without the initial memory we don't have ANY chance! */
143 if (!OK)
144 return(NULL);
147 * Some systems with an own MT file don't compile in MT mode. But they
148 * still are systems of that kind.
150 #if defined(WIN32) || defined(__WIN32__)
152 extern OS_Dep_funcs __regina_OS_Win;
153 __regina_tsd.OS = &__regina_OS_Win;
155 #elif defined(OS2) && !defined(DOS)
157 extern OS_Dep_funcs __regina_OS_Os2;
158 __regina_tsd.OS = &__regina_OS_Os2;
160 #elif defined(GO32)
162 extern OS_Dep_funcs __regina_OS_Other;
163 __regina_tsd.OS = &__regina_OS_Other;
165 #elif defined(unix) || defined(__unix__) || defined(__unix) || defined(__QNX__) || defined(__BEOS__) || defined(SKYOS) || ( defined( __APPLE_CC__ ) && defined( __MACH__ ) ) || defined(AIX)
167 extern OS_Dep_funcs __regina_OS_Unx;
168 __regina_tsd.OS = &__regina_OS_Unx;
170 #elif defined(_AMIGA) || defined(__AROS__)
172 extern OS_Dep_funcs __regina_OS_Amiga;
173 __regina_tsd.OS = &__regina_OS_Amiga;
175 #else
177 extern OS_Dep_funcs __regina_OS_Other;
178 __regina_tsd.OS = &__regina_OS_Other;
180 #endif
181 __regina_tsd.OS->init();
182 OK |= init_vars(&__regina_tsd); /* Initialize the variable module */
183 OK |= init_stacks(&__regina_tsd); /* Initialize the stack module */
184 OK |= init_filetable(&__regina_tsd); /* Initialize the files module */
185 OK |= init_math(&__regina_tsd); /* Initialize the math module */
186 OK |= init_spec_vars(&__regina_tsd); /* Initialize the interprt module */
187 OK |= init_tracing(&__regina_tsd); /* Initialize the tracing module */
188 OK |= init_builtin(&__regina_tsd); /* Initialize the builtin module */
189 OK |= init_client(&__regina_tsd); /* Initialize the client module */
190 OK |= init_library(&__regina_tsd); /* Initialize the library module */
191 OK |= init_rexxsaa(&__regina_tsd); /* Initialize the rexxsaa module */
192 OK |= init_shell(&__regina_tsd); /* Initialize the shell module */
193 OK |= init_envir(&__regina_tsd); /* Initialize the envir module */
194 OK |= init_expr(&__regina_tsd); /* Initialize the expr module */
195 OK |= init_error(&__regina_tsd); /* Initialize the error module */
196 #ifdef VMS
197 OK |= init_vms(&__regina_tsd); /* Initialize the vmscmd module */
198 OK |= init_vmf(&__regina_tsd); /* Initialize the vmsfuncs module */
199 #endif
200 OK |= init_arexxf(&__regina_tsd); /* Initialize the arxfuncs modules */
201 #if defined(_AMIGA) || defined(__AROS__)
202 OK |= init_amigaf(&__regina_tsd);
203 #endif
204 __regina_tsd.loopcnt = 1; /* stupid r2perl-module */
205 __regina_tsd.traceparse = -1;
206 __regina_tsd.thread_id = 1;
208 if (!OK)
209 exiterror( ERR_STORAGE_EXHAUSTED, 0 ) ;
211 return(&__regina_tsd);
215 #ifdef TRACK_TSD_USAGE
216 /* We may want to check the counts of calls to __regina_get_tsd() which may do
217 * MUCH work on different platforms. We do some not optimizable work here.
218 * If you really wanna track down all calls to figure out WHERE to
219 * optimize try under a GNU friendly system:
220 * 1) In Makefile: Add "-pg -a" to the variable called "CFLAGS".
221 * 2) "make rexx" (Other targets might not work)
222 * 3) "./rexx whatyoulike.rexx"
223 * 4) "gprof rexx >usage.lst"
224 * 5) look at usage.lst for occurances of "WorkHeavy".
227 volatile int __regina_Calls = 300; /* factor to get a "feel" for multithreading */
228 volatile int __regina_Point = 1;
230 void __regina_Nop(void)
232 __regina_Point = 2;
235 /* WorkHeavy does some work and returns the correct thread-specific data. */
236 tsd_t *__regina_WorkHeavy(void)
238 int todo = __regina_Calls;
239 while (todo--)
240 __regina_Nop();
241 return(&__regina_tsd);
243 #endif