1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 
11 
12 #include <dx/dx.h>
13 #include "exobject.h"
14 #include "config.h"
15 #include "log.h"
16 #include "graph.h"
17 #include "parse.h"
18 
19 /* DXFree lists of GLOBAL objects only */
20 typedef struct {
21     lock_type	lock;
22     gvar 	*gvarHead;
23     gvar 	*gvarTail;
24 } FreeList;
25 static FreeList *freeList;
26 
27 static node *FuncFreeList	= NULL;
28 
29 #define INIT_GVARS	512	/* Number of gvars to allocate initially */
30 
31 PFIP _dxd_EXO_default_methods[] =
32 {
33     _dxf__EXO_delete
34 };
35 
36 static lock_type *allocLock;
37 
38 #ifdef LEAK_DEBUG
39     EXObj head;
40 #endif
41 
42 
43 /*
44  * Initialize the executive's object facility.
45  */
46 
47 Error
_dxf_EXO_init(void)48 _dxf_EXO_init (void)
49 {
50 #if 0
51     int i;
52     gvar *gvars;
53 #endif
54 
55     freeList = (FreeList *)DXAllocateZero (sizeof (FreeList));
56     if (freeList == NULL)
57 	return (ERROR);
58     if (DXcreate_lock (&freeList->lock, "exobj freeList") != OK)
59 	return (ERROR);
60     allocLock = (lock_type *)DXAllocateZero (sizeof (lock_type));
61     if (DXcreate_lock (allocLock, "exobj freeList allocation") != OK)
62 	return (ERROR);
63 
64 #if 0
65     gvars = freeList->gvarHead = (gvar *)DXAllocateZero (INIT_GVARS * sizeof (gvar));
66     if (gvars == NULL)
67 	return (ERROR);
68     for (i = 0; i < INIT_GVARS - 1; ++i)
69     {
70 	if (DXcreate_lock (&gvars[i].object.lock, "exobj gvar") != OK)
71 	    return (ERROR);
72 	gvars[i].next = &gvars[i+1];
73     }
74     freeList->gvarTail = &gvars[INIT_GVARS-1];
75     if (DXcreate_lock (&gvars[i].object.lock, "exobj gvar") != OK)
76 	return (ERROR);
77 #endif
78 
79 #ifdef LEAK_DEBUG
80     head = (EXObj) DXAllocateZero (sizeof (exo_object));
81     head->DBGnext = head->DBGprev = head;
82 #endif
83 
84     return (OK);
85 }
86 
87 
88 /*
89  * DXFree the executive's object locking structures.
90  */
91 
92 Error
_dxf_EXO_cleanup(void)93 _dxf_EXO_cleanup (void)
94 {
95     return (OK);
96 }
97 
98 int
_dxf_EXO_compact(void)99 _dxf_EXO_compact (void)
100 {
101     int			result;
102     EXO_Object		obj;
103 
104     DXlock (allocLock, 0);
105     DXlock (&freeList->lock, exJID);
106     result = freeList->gvarHead != NULL;
107     while (freeList->gvarHead)
108     {
109 	if (freeList->gvarHead->next == NULL)
110 	{
111 	    if (freeList->gvarHead->next == NULL)
112 		freeList->gvarTail = NULL;
113 	}
114 	obj = (EXO_Object) freeList->gvarHead;
115 	freeList->gvarHead = ((gvar *) obj)->next;
116 	DXFree((Pointer) obj);
117     }
118     DXunlock (allocLock, 0);
119     DXunlock (&freeList->lock, exJID);
120 
121     if (!result && exJID == 1)
122     {
123 	result = FuncFreeList != NULL;
124 	while (FuncFreeList != NULL)
125 	{
126 	    obj = (EXObj) FuncFreeList;
127 	    FuncFreeList = FuncFreeList->next;
128 	    DXFree((Pointer) obj);
129 	}
130     }
131     return (result);
132 }
133 
134 /*
135  * Check a piece of data to make sure that it has the proper tag to be
136  * an executive object.
137  */
138 
_dxf_EXOCheck(EXO_Object obj)139 Error _dxf_EXOCheck (EXO_Object obj)
140 {
141     if (obj && !((long)obj & 0x03) && obj->tag == EXO_TAG)
142     {
143 	switch (obj->exclass)
144 	{
145 	    case EXO_CLASS_DELETED:
146 	    case EXO_CLASS_FUNCTION:
147 	    case EXO_CLASS_GVAR:
148 	    case EXO_CLASS_TASK:
149 		return (OK);
150 
151 	    default:
152 		break;
153 	}
154     }
155 
156     DXWarning ("#4610", obj);
157 
158     DXqflush ();
159     abort();			/* Die here please */
160 
161     return (ERROR);
162 }
163 
164 /*
165  * Create a new object and use default method vector if new methods
166  * not specified
167  */
168 
169 static EXO_Object
EXO_create_object_worker(EXO_Class exclass,int size,PFIP * methods,int local)170 EXO_create_object_worker (EXO_Class exclass, int size, PFIP *methods, int local)
171 {
172     EXO_Object		obj;
173     int			locked;
174 
175     switch (exclass)
176     {
177 	case EXO_CLASS_FUNCTION:
178 	    if (FuncFreeList == NULL)
179 		obj = (EXObj) DXAllocateLocal (size);
180 	    else
181 	    {
182 		obj = (EXObj) FuncFreeList;
183 		FuncFreeList = FuncFreeList->next;
184 	    }
185 	    break;
186 
187 	case EXO_CLASS_GVAR:
188 	    DXlock (allocLock, 0);
189 	    if (freeList->gvarHead)
190 	    {
191 		locked = freeList->gvarHead->next == NULL;
192 		if (locked)
193 		{
194 		    DXlock (&freeList->lock, exJID);
195 		    if (freeList->gvarHead->next == NULL)
196 			freeList->gvarTail = NULL;
197 		}
198 		obj = (EXO_Object) freeList->gvarHead;
199 		freeList->gvarHead = ((gvar *) obj)->next;
200 		if (locked)
201 		    DXunlock (&freeList->lock, exJID);
202 		DXunlock (allocLock, 0);
203 	    }
204 	    else
205 	    {
206 		DXunlock (allocLock, 0);
207 		obj = (EXO_Object) DXAllocate (size);
208 	    }
209 	    break;
210 
211 	default:
212 	    obj = (EXO_Object) (local ? DXAllocateLocal (size)
213 				      : DXAllocate (size));
214 	    break;
215     }
216 
217 
218     if (obj == NULL)
219 	_dxf_ExDie ("_dxf_EXO_create_object:  can't DXAllocate");
220 
221     if (! local && DXcreate_lock (&obj->lock, "exec object") != OK)
222 	_dxf_ExDie ("_dxf_EXO_create_object: can't create lock\n");
223 
224     ExZero (obj + 1, size - sizeof (exo_object));
225 
226     obj->tag	   = EXO_TAG;
227     obj->exclass   = exclass;
228     obj->local	   = local;
229     obj->refs	   = 0;
230     obj->m.copy    = FALSE;
231     obj->m.methods = methods ? methods : _dxd_EXO_default_methods;
232     obj->lastref  = 0;
233 
234 #ifdef LEAK_DEBUG
235     if (!local) {
236 	obj->DBGnext = head->DBGnext;
237 	obj->DBGprev = head;
238 	head->DBGnext->DBGprev = obj;
239 	head->DBGnext = obj;
240     }
241 #endif
242 
243     return (obj);
244 }
245 
246 
_dxf_EXO_create_object(EXO_Class exclass,int size,PFIP * methods)247 EXO_Object _dxf_EXO_create_object (EXO_Class exclass, int size, PFIP *methods)
248 {
249     return (EXO_create_object_worker (exclass, size, methods, FALSE));
250 }
251 
252 
_dxf_EXO_create_object_local(EXO_Class exclass,int size,PFIP * methods)253 EXO_Object _dxf_EXO_create_object_local (EXO_Class exclass, int size, PFIP *methods)
254 {
255     return (EXO_create_object_worker (exclass, size, methods, TRUE));
256 }
257 
258 
259 /*
260  * DXDelete an object.  Note that the delete macro has already decremented the
261  * reference count and decided the object should go away
262  */
_dxf_EXO_delete(EXO_Object obj)263 int _dxf_EXO_delete (EXO_Object obj)
264 {
265     int		del	= FALSE;
266     if (obj->refs == 0)
267     {
268 #ifdef LEAK_DEBUG
269 	if (!obj->local) {
270 	    obj->DBGnext->DBGprev = obj->DBGprev;
271 	    obj->DBGprev->DBGnext = obj->DBGnext;
272 	}
273 #endif
274 	switch (obj->exclass)
275 	{
276 	    case EXO_CLASS_FUNCTION:
277 		((node *) obj)->next = FuncFreeList;
278 		FuncFreeList = (node *) obj;
279 		break;
280 
281 	    case EXO_CLASS_GVAR:
282 		((gvar *) obj)->next = NULL;
283 		DXlock (&freeList->lock, exJID);
284 		if (freeList->gvarTail)
285 		    freeList->gvarTail->next = (gvar *) obj;
286 		else
287 		    freeList->gvarHead = (gvar *) obj;
288 		freeList->gvarTail = (gvar *) obj;
289 		DXunlock (&freeList->lock, exJID);
290 		break;
291 
292 	    default:
293 		del = TRUE;
294 		break;
295 	}
296 
297 	obj->exclass = EXO_CLASS_DELETED;
298 	if (obj->m.copy)
299 	    DXFree ((Pointer) obj->m.methods);
300 	if (! obj->local)
301 	    DXdestroy_lock (&obj->lock);
302 	if (del)
303 	    DXFree ((Pointer) obj);
304     }
305     else
306     {
307 	DXWarning ("#4620", obj, obj->refs);
308 	DXqflush ();
309 	if (_dxd_exDebug)
310 	    abort();		/* Die here please */
311     }
312 
313     return (0);
314 }
315 
316 /*
317  * Default delete routine does nothing
318  */
_dxf__EXO_delete(EXO_Object obj)319 int _dxf__EXO_delete (EXO_Object obj)
320 {
321     return (OK);
322 }
323 
324 
325 #ifdef LEAK_DEBUG
326 void
PrintEXObj()327 PrintEXObj()
328 {
329     EXObj o;
330 
331     for (o = head->DBGnext; o != head; o = o->DBGnext) {
332 	switch (o->exclass) {
333 	case EXO_CLASS_DELETED:
334 	    printf ("0x%08x (refs %d) EXO_CLASS_DELETED\n", o, o->refs);
335 	    break;
336 	case EXO_CLASS_FUNCTION:
337 	    printf ("0x%08x (refs %d) EXO_CLASS_FUNCTION\n", o, o->refs);
338 	    break;
339 	case EXO_CLASS_GVAR:
340 	    printf ("0x%08x (refs %d) EXO_CLASS_GVAR, type is %d\n",
341 		o, o->refs, ((gvar*)o)->type);
342 	    break;
343 	case EXO_CLASS_TASK:
344 	    printf ("0x%08x (refs %d) EXO_CLASS_TASK\n", o, o->refs);
345 	    break;
346 	case EXO_CLASS_UNKNOWN:
347 	    printf ("0x%08x (refs %d) EXO_CLASS_UNKNOWN\n", o, o->refs);
348 	    break;
349 	default:
350 	    printf ("0x%08x (refs %d) of unknown class %d\n", o, o->refs, o->exclass);
351 	    break;
352 	}
353     }
354 }
355 #endif
356