source: trunk/nom/src/nomgc.c@ 193

Last change on this file since 193 was 193, checked in by cinc, 19 years ago

Improvements to the GC interface and some more stuff

File size: 13.8 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2* Version: CDDL 1.0/LGPL 2.1
3*
4* The contents of this file are subject to the COMMON DEVELOPMENT AND
5* DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6* this file except in compliance with the License. You may obtain a copy of
7* the License at http://www.sun.com/cddl/
8*
9* Software distributed under the License is distributed on an "AS IS" basis,
10* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11* for the specific language governing rights and limitations under the
12* License.
13*
14* The Original Code is "NOM" Netlabs Object Model
15*
16* The Initial Developer of the Original Code is
17* netlabs.org: Chris Wohlgemuth <cinc-ml@netlabs.org>.
18* Portions created by the Initial Developer are Copyright (C) 2005-2006
19* the Initial Developer. All Rights Reserved.
20*
21* Contributor(s):
22*
23* Alternatively, the contents of this file may be used under the terms of
24* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
25* case the provisions of the LGPL are applicable instead of those above. If
26* you wish to allow use of your version of this file only under the terms of
27* the LGPL, and not to allow others to use your version of this file under
28* the terms of the CDDL, indicate your decision by deleting the provisions
29* above and replace them with the notice and other provisions required by the
30* LGPL. If you do not delete the provisions above, a recipient may use your
31* version of this file under the terms of any one of the CDDL or the LGPL.
32*
33* ***** END LICENSE BLOCK ***** */
34
35/*
36 This file contains functions for working with the garbage collector.
37 */
38
39#define INCL_DOS
40#define INCL_DOSERRORS
41#define INCL_DOSMEMMGR
42#include <os2.h>
43
44#include <stdio.h>
45#include <string.h>
46#include <stdlib.h>
47
48/* For nomToken etc. */
49#include <nom.h>
50#include "nomtk.h"
51#include "nomgc.h"
52
53/* Garbage collector */
54#include <gc.h>
55
56gboolean bUseGC=FALSE; /* Mark if we use the garbage collector */
57
58static gpointer gcMalloc(gulong ulBytes)
59{
60 //printf("Hi there...\n");
61 // return malloc(ulBytes);
62 return (gpointer) GC_malloc(ulBytes);
63}
64
65static gpointer gcRealloc(gpointer mem, gulong ulBytes)
66{
67 // printf("...and here\n");
68 // return realloc(mem, ulBytes);
69 return (gpointer) GC_realloc(mem, ulBytes);
70}
71
72static void gcFree(gpointer mem)
73{
74 // printf("free(): %x\n", mem);
75 return;
76 GC_free(mem);
77}
78
79
80/*
81 This is called from the EMX wrapper to set the garbage collector
82 memory functions as the GLIB default allocation function.
83 */
84void _System nomInitGarbageCollection(void* pMemInExe)
85{
86 GMemVTable vtbl={0};
87
88 /* Init the garbage collector */
89 GC_init();
90
91 vtbl.malloc=(gpointer)gcMalloc;
92 vtbl.realloc=(gpointer)gcRealloc;
93 vtbl.free=(gpointer)gcFree;
94
95 g_mem_set_vtable(&vtbl);
96 /* fprintf(stderr, " GC memory functions set for GLIB. (%s: %d)\n", __FILE__, __LINE__); */
97
98 bUseGC=TRUE;
99}
100
101NOMEXTERN void NOMLINK nomRegisterDataAreaForGC(char* pStart, char* pEnd)
102{
103 GC_add_roots(pStart, pEnd);
104}
105
106static void qsAddDLLToList(HREGDLL hReg, qsLrec_t* rec)
107{
108 if(NULLHANDLE==g_slist_find(hReg->dllList, rec))
109 hReg->dllList=g_slist_append(hReg->dllList, rec);
110}
111
112#if 0
113static void qsPrintDLLList(HREGDLL hReg)
114{
115 GSList* lTemp;
116 int a=0;
117
118 lTemp=hReg->dllList;
119 while(lTemp)
120 {
121 qsLrec_t* rec;
122 rec=(qsLrec_t*)lTemp->data;
123 a++;
124 g_message(" %d: %s", a, rec->pName);
125 lTemp=g_slist_next(lTemp);
126 }
127}
128#endif
129
130/*
131 Find a library record in the buffer filled by DosQuerySysState().
132 */
133static qsLrec_t* qsFindModuleRec(const qsPtrRec_t * hRegisterDLL, USHORT hMod){
134 qsLrec_t * pModRec;
135 int a=0;
136
137 pModRec=hRegisterDLL->pLibRec;
138 while(NULL!=pModRec)
139 {
140 a++;
141 /* printf("%d Checking: %x -> %04X (%s)\n", a, pModRec, pModRec->hmte, pModRec->pName); */
142
143 if (NULLHANDLE==pModRec->pObjInfo && pModRec->ctObj > 0)
144 {
145 pModRec->pObjInfo = (qsLObjrec_t*)((char*)pModRec
146 + ((sizeof(qsLrec_t)
147 + pModRec->ctImpMod * sizeof(short)
148 + strlen((char*)pModRec->pName) + 1 /* filename */
149 + 3) & ~3));
150 pModRec->pNextRec = (void*)((char*)pModRec->pObjInfo
151 + sizeof(qsLObjrec_t) * pModRec->ctObj);
152 }
153 if(pModRec->hmte==hMod)
154 break;
155
156 pModRec=(qsLrec_t *)pModRec->pNextRec;
157 }
158
159 return pModRec;
160}
161
162#define BUFSIZE 1024*1024
163NOMEXTERN HREGDLL NOMLINK nomBeginRegisterDLLWithGC(void)
164{
165 ULONG rc;
166 HREGDLL hReg=NULLHANDLE;
167 PTIB ptib;
168 PPIB ppib;
169 char * buf;
170 HREGDLL pRegDLL=NULLHANDLE;
171
172 rc = DosGetInfoBlocks(&ptib, &ppib);
173 if (rc!=NO_ERROR)
174 return NULLHANDLE;
175
176 buf = malloc(BUFSIZE);
177 if(!buf)
178 return NULLHANDLE;
179
180 pRegDLL =(HREGDLL) malloc(sizeof(REGDLL));
181 if(!pRegDLL){
182 free(buf);
183 return NULLHANDLE;
184 }
185 pRegDLL->dllList=NULLHANDLE;
186
187 memset(buf,0,BUFSIZE);
188
189 rc = DosQuerySysState(QS_PROCESS | QS_SEMAPHORE | QS_MTE | QS_FILESYS | QS_SHMEMORY ,
190 QS_MTE, /*0x96*/ ppib->pib_ulpid , 1UL, (PCHAR)buf, BUFSIZE);
191 if (rc==NO_ERROR) {
192 qsPrec_t * p;
193 GSList* lTemp;
194
195 pRegDLL->pMainAnchor=(qsPtrRec_t*) buf;
196
197 p=pRegDLL->pMainAnchor->pProcRec;
198
199 while(p && p->RecType == 1)
200 {
201
202 if (p->cLib) {
203 int i;
204
205 for (i=0; i<p->cLib; i++){
206 qsLrec_t * pModRec;
207
208 pModRec=qsFindModuleRec(pRegDLL->pMainAnchor, p->pLibRec[i]);
209
210 if(pModRec){
211 //if(pModRec->pName)
212 //g_message("%s", pModRec->pName);
213 qsAddDLLToList(pRegDLL, pModRec);
214 }
215 }/* for() */
216 }/* if(p->clib) */
217 break;
218 };/* while() */
219
220 /* Ok, got directly imported DLLs. Now go over these and check them for additional imports.
221 Every import is added to the end of the list (except duplicates). So while going over
222 the list we touch every DLL and check every import. Import cycles are no problem, because
223 later duplicates are ignored. */
224 lTemp=pRegDLL->dllList;
225 while(lTemp)
226 {
227 qsLrec_t* rec;
228
229 rec=(qsLrec_t*)lTemp->data;
230
231 /* Check the imports of this DLL if any */
232 if(rec->ctImpMod >0)
233 {
234 int iImps;
235 PUSHORT pImpHmte;
236
237 pImpHmte=(PUSHORT)((void*)rec + sizeof(qsLrec_t));
238 for(iImps=0; iImps < rec->ctImpMod; iImps++)
239 {
240 qsLrec_t * pModImp;
241
242 pModImp=qsFindModuleRec(pRegDLL->pMainAnchor, pImpHmte[iImps]);
243 if(pModImp)
244 qsAddDLLToList(pRegDLL, pModImp);
245 }/* for()*/
246 }/* if() */
247 lTemp=g_slist_next(lTemp);
248 };/* while() */
249 //qsPrintDLLList();
250 hReg=pRegDLL;
251 }
252 else{
253 free(pRegDLL);
254 free(buf);
255 }
256 return hReg;
257}
258
259NOMEXTERN void NOMLINK nomEndRegisterDLLWithGC(const HREGDLL hRegisterDLL )
260{
261 g_slist_free(hRegisterDLL->dllList);
262 free((char*)hRegisterDLL->pMainAnchor);
263 free((char*)hRegisterDLL);
264}
265
266#define OBJREAD 0x0001L
267#define OBJWRITE 0x0002L
268#define OBJINVALID 0x0080L
269NOMEXTERN BOOL NOMLINK nomRegisterDLLByName(const HREGDLL hRegisterDLL, const char* chrDLLName)
270{
271 GSList* lTemp;
272
273 //printf("Trying to register DLL %s\n", chrDLLName);
274 lTemp=hRegisterDLL->dllList;
275 while(lTemp)
276 {
277 qsLrec_t* pModRec;
278
279 pModRec=(qsLrec_t*)lTemp->data;
280 if(pModRec){
281 // printf("DLL name: %s\n", pModRec->pName);
282 if(pModRec->pName && (NULLHANDLE!=strstr( pModRec->pName, chrDLLName)))
283 {
284 qsLObjrec_t *pObjInfo;
285 //g_message(" --> Found DLL %s", pModRec->pName);
286 pObjInfo=pModRec->pObjInfo;
287 if(NULLHANDLE!=pObjInfo)
288 {
289 int iObj;
290 for(iObj=0; iObj<pModRec->ctObj ;iObj++)
291 {
292 if (!(pObjInfo[iObj].oflags & OBJWRITE)) continue;
293 if (!(pObjInfo[iObj].oflags & OBJREAD)) continue;
294 if ((pObjInfo[iObj].oflags & OBJINVALID)) continue;
295 //g_message(" #%d: %04lX, size: %04lX %04lX",
296 // iObj, pObjInfo[iObj].oaddr, pObjInfo[iObj].osize, pObjInfo[iObj].oflags);
297 nomRegisterDataAreaForGC((char*)pObjInfo[iObj].oaddr,
298 (char*)(pObjInfo[iObj].oaddr+pObjInfo[iObj].osize));
299 }
300 }
301 return TRUE;
302 }
303 }
304 lTemp=g_slist_next(lTemp);
305 };/* while() */
306 return FALSE;
307}
308
309#if 0
310#define BUFSIZE 1024*1024
311NOMEXTERN HREGDLL NOMLINK nomBeginRegisterDLLWithGC(void)
312{
313 ULONG rc;
314 HREGDLL hReg=NULLHANDLE;
315 PTIB ptib;
316 PPIB ppib;
317 char * buf;
318
319 rc = DosGetInfoBlocks(&ptib, &ppib);
320 if (rc!=NO_ERROR)
321 return NULLHANDLE;
322
323 buf = malloc(BUFSIZE);
324 if(!buf)
325 return NULLHANDLE;
326
327 memset(buf,0,BUFSIZE);
328
329 rc = DosQuerySysState(QS_PROCESS | QS_SEMAPHORE | QS_MTE | QS_FILESYS | QS_SHMEMORY ,
330 QS_MTE, /*0x96*/ ppib->pib_ulpid , 1UL, (PCHAR)buf, BUFSIZE);
331 if (rc==NO_ERROR) {
332 hReg=(qsPtrRec_t*) buf;
333 }
334 else
335 free(buf);
336
337 return hReg;
338}
339/*
340 FIXME:
341
342 This function will not find every given DLL because it doesn't follow every import of
343 each DLL.
344 It's only meant for registering the GTK+, GLIB and friends DLLs. This works because GTK2.DLL
345 is directly loaded by the exe and all the friends DLLs are imported by it.
346
347 Feel free to make this function really useful...
348
349 Oh, and some refactoring would be nice, too.
350
351 */
352#define OBJREAD 0x0001L
353#define OBJWRITE 0x0002L
354#define OBJINVALID 0x0080L
355NOMEXTERN BOOL NOMLINK nomRegisterDLLByName(const HREGDLL hRegisterDLL, const char* chrDLLName)
356{
357 qsPrec_t * p;
358 int a=0;
359
360 //printf("Trying to register DLL %s\n", chrDLLName);
361
362 p=hRegisterDLL->pProcRec;
363 while(p && p->RecType == 1)
364 {
365 a++;
366 if (p->cLib) {
367 int i;
368
369 for (i=0; i<p->cLib; i++){
370 qsLrec_t * pModRec;
371
372 //printf("%d %04X (p: %04x %04X, %04X) ",i, p->pLibRec[i], p, &p->pLibRec[i], &p->pLibRec);
373
374 pModRec=qsFindModuleRec(hRegisterDLL, p->pLibRec[i]);
375 if(pModRec){
376 // printf("DLL name: %s\n", pModRec->pName);
377 if(NULLHANDLE!=strstr( pModRec->pName, chrDLLName))
378 {
379 qsLObjrec_t *pObjInfo;
380 //printf(" --> Found DLL %s\n", pModRec->pName);
381 pObjInfo=pModRec->pObjInfo;
382 if(NULLHANDLE!=pObjInfo)
383 {
384 int iObj;
385 for(iObj=0; iObj<pModRec->ctObj ;iObj++)
386 {
387 if (!(pObjInfo[iObj].oflags & OBJWRITE)) continue;
388 if (!(pObjInfo[iObj].oflags & OBJREAD)) continue;
389 if ((pObjInfo[iObj].oflags & OBJINVALID)) continue;
390 printf(" #%d: %04lX, size: %04lX %04lX",
391 iObj, pObjInfo[iObj].oaddr, pObjInfo[iObj].osize, pObjInfo[iObj].oflags);
392 nomRegisterDataAreaForGC((char*)pObjInfo[iObj].oaddr,
393 (char*)(pObjInfo[iObj].oaddr+pObjInfo[iObj].osize));
394 }
395 }
396 return TRUE;
397 }
398 /* Check the imports of this DLL if any */
399 if(pModRec->ctImpMod >0)
400 {
401 int iImps;
402 PUSHORT pImpHmte;
403
404 pImpHmte=(PUSHORT)((void*)pModRec + sizeof(qsLrec_t));
405
406 for(iImps=0; iImps < pModRec->ctImpMod; iImps++)
407 {
408 qsLrec_t * pModImp;
409 // printf(" Trying import #%d (%04X)\n", iImps, pImpHmte[iImps]);
410 pModImp=qsFindModuleRec(hRegisterDLL, pImpHmte[iImps]);
411 if(pModImp){
412 //printf(" DLL name: %s\n", pModImp->pName);
413 if(NULLHANDLE!=strstr( pModImp->pName, chrDLLName))
414 {
415 qsLObjrec_t *pObjInfo;
416 //printf(" --> Found DLL %s\n", pModImp->pName);
417 pObjInfo=pModImp->pObjInfo;
418 if(NULLHANDLE!=pObjInfo)
419 {
420 int iObj;
421 for(iObj=0; iObj<pModImp->ctObj ;iObj++)
422 {
423 if (!(pObjInfo[iObj].oflags & OBJWRITE)) continue;
424 if (!(pObjInfo[iObj].oflags & OBJREAD)) continue;
425 if ((pObjInfo[iObj].oflags & OBJINVALID)) continue;
426
427 //printf(" #%d: %04lX, size: %04lX %04lX\n",
428 // iObj, pObjInfo[iObj].oaddr, pObjInfo[iObj].osize, pObjInfo[iObj].oflags);
429 nomRegisterDataAreaForGC((char*)pObjInfo[iObj].oaddr,
430 (char*)(pObjInfo[iObj].oaddr+pObjInfo[iObj].osize));
431 }
432 }
433 return TRUE;
434 }
435 }/* for() */
436 }/* for()*/
437 }/* if() */
438 }
439 }/* For() */
440 }
441 break;
442 }
443 return FALSE;
444}
445#endif
Note: See TracBrowser for help on using the repository browser.