1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #ifndef _XOPEN_SOURCE
6 #define _XOPEN_SOURCE 600 /* PTHREAD_MUTEX_RECURSIVE */
7 #endif
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <assert.h>
12
13 #if defined (HAVE_EXECINFO_H)
14 #include <execinfo.h>
15 #endif
16
17 static
show_stackframe()18 void show_stackframe()
19 {
20 #if defined HAVE_EXECINFO_H && defined backtrace_size_t && defined HAVE_BACKTRACE
21 void *trace[16];
22 backtrace_size_t trace_size = backtrace(trace, 16);
23 char **messages = backtrace_symbols(trace, trace_size);
24
25 fprintf(stderr, "[bt] Execution path:\n");
26 if ( messages ) {
27 for ( backtrace_size_t i = 0; i < trace_size; ++i )
28 fprintf(stderr, "[bt] %s\n", messages[i]);
29 free(messages);
30 }
31 #endif
32 }
33
34 #include "dmemory.h"
35 #include "resource_handle.h"
36 #include "namespace.h"
37 #include "serialize.h"
38 #include "cdi.h"
39 #include "error.h"
40 #include "file.h"
41 #include "resource_unpack.h"
42 #include "institution.h"
43 #include "model.h"
44
45 enum { MIN_LIST_SIZE = 128 };
46
47 static void listInitialize(void);
48
49 typedef struct listElem {
50 union
51 {
52 /* free-list management data */
53 struct
54 {
55 int next, prev;
56 } free;
57 /* holding an actual value */
58 struct
59 {
60 const resOps *ops;
61 void *val;//ptr
62 } v;
63 } res;
64 int status;
65 } listElem_t;
66
67 struct resHList_t
68 {
69 int size, freeHead, hasDefaultRes;
70 listElem_t *resources;
71 };
72
73 static struct resHList_t *resHList;
74
75 static int resHListSize = 0;
76
77 #if defined (HAVE_LIBPTHREAD)
78 # include <pthread.h>
79
80 static pthread_once_t listInitThread = PTHREAD_ONCE_INIT;
81 static pthread_mutex_t listMutex;
82
83 # define LIST_LOCK() pthread_mutex_lock(&listMutex)
84 # define LIST_UNLOCK() pthread_mutex_unlock(&listMutex)
85 # define LIST_INIT(init0) do { \
86 pthread_once(&listInitThread, listInitialize); \
87 pthread_mutex_lock(&listMutex); \
88 if ((init0) && (!resHList || !resHList[0].resources)) \
89 reshListCreate(0); \
90 pthread_mutex_unlock(&listMutex); \
91 } while (0)
92
93
94
95 #else
96
97 static int listInit = 0;
98
99 # define LIST_LOCK()
100 # define LIST_UNLOCK()
101 # define LIST_INIT(init0) do { \
102 if ( !listInit ) \
103 { \
104 listInitialize(); \
105 if ((init0) && (!resHList || !resHList[0].resources)) \
106 reshListCreate(0); \
107 listInit = 1; \
108 } \
109 } while(0)
110
111 #endif
112
113 /**************************************************************/
114
115 static void
listInitResources(int nsp)116 listInitResources(int nsp)
117 {
118 xassert(nsp < resHListSize && nsp >= 0);
119 int size = resHList[nsp].size = MIN_LIST_SIZE;
120 xassert(resHList[nsp].resources == NULL);
121 resHList[nsp].resources = (listElem_t*) Calloc(MIN_LIST_SIZE, sizeof(listElem_t));
122 listElem_t *p = resHList[nsp].resources;
123
124 for (int i = 0; i < size; i++ )
125 {
126 p[i].res.free.next = i + 1;
127 p[i].res.free.prev = i - 1;
128 p[i].status = RESH_UNUSED;
129 }
130
131 p[size-1].res.free.next = -1;
132 resHList[nsp].freeHead = 0;
133 int oldNsp = namespaceGetActive();
134 namespaceSetActive(nsp);
135 instituteDefaultEntries();
136 modelDefaultEntries();
137 namespaceSetActive(oldNsp);
138 }
139
140 static inline void
reshListClearEntry(int i)141 reshListClearEntry(int i)
142 {
143 resHList[i].size = 0;
144 resHList[i].resources = NULL;
145 resHList[i].freeHead = -1;
146 }
147
148 void
reshListCreate(int namespaceID)149 reshListCreate(int namespaceID)
150 {
151 LIST_INIT(namespaceID != 0);
152 LIST_LOCK();
153 if (resHListSize <= namespaceID)
154 {
155 resHList = (struct resHList_t *) Realloc(resHList, (size_t)(namespaceID + 1) * sizeof (resHList[0]));
156 for (int i = resHListSize; i <= namespaceID; ++i)
157 reshListClearEntry(i);
158 resHListSize = namespaceID + 1;
159 }
160 listInitResources(namespaceID);
161 LIST_UNLOCK();
162 }
163
164
165 /**************************************************************/
166
167 void
reshListDestruct(int namespaceID)168 reshListDestruct(int namespaceID)
169 {
170 LIST_LOCK();
171 xassert(resHList && namespaceID >= 0 && namespaceID < resHListSize);
172 int callerNamespaceID = namespaceGetActive();
173 namespaceSetActive(namespaceID);
174 if (resHList[namespaceID].resources)
175 {
176 for ( int j = 0; j < resHList[namespaceID].size; j++ )
177 {
178 listElem_t *listElem = resHList[namespaceID].resources + j;
179 if (listElem->status & RESH_IN_USE_BIT)
180 listElem->res.v.ops->valDestroy(listElem->res.v.val);
181 }
182 Free(resHList[namespaceID].resources);
183 resHList[namespaceID].resources = NULL;
184 reshListClearEntry(namespaceID);
185 }
186 if (resHList[callerNamespaceID].resources)
187 namespaceSetActive(callerNamespaceID);
188 LIST_UNLOCK();
189 }
190
191
listDestroy(void)192 static void listDestroy ( void )
193 {
194 LIST_LOCK();
195 for (int i = resHListSize; i > 0; --i)
196 if (resHList[i-1].resources)
197 namespaceDelete(i-1);
198 resHListSize = 0;
199 Free(resHList);
200 resHList = NULL;
201 cdiReset();
202 LIST_UNLOCK();
203 }
204
205 /**************************************************************/
206
207 static
listInitialize(void)208 void listInitialize ( void )
209 {
210 #if defined (HAVE_LIBPTHREAD)
211 #if defined(PTHREAD_MUTEXATTR)
212 pthread_mutexattr_t ma;
213 pthread_mutexattr_init(&ma);
214 pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
215 /* initialize global API mutex lock */
216 pthread_mutex_init ( &listMutex, &ma);
217 pthread_mutexattr_destroy(&ma);
218 #endif
219 #endif
220 /* file is special and has its own table, which needs to be
221 * created, before we register the listDestroy exit handler */
222 {
223 int null_id;
224 null_id = fileOpen_serial("/dev/null", "r");
225 if (null_id != -1)
226 fileClose_serial(null_id);
227 }
228 atexit ( listDestroy );
229 }
230
231 /**************************************************************/
232
233 static
listSizeExtend()234 void listSizeExtend()
235 {
236 int nsp = namespaceGetActive ();
237 int oldSize = resHList[nsp].size;
238 size_t newListSize = (size_t)oldSize + MIN_LIST_SIZE;
239
240 resHList[nsp].resources = (listElem_t*) Realloc(resHList[nsp].resources,
241 newListSize * sizeof(listElem_t));
242
243 listElem_t *r = resHList[nsp].resources;
244 for (size_t i = (size_t)oldSize; i < newListSize; ++i)
245 {
246 r[i].res.free.next = (int)i + 1;
247 r[i].res.free.prev = (int)i - 1;
248 r[i].status = RESH_UNUSED;
249 }
250
251 if (resHList[nsp].freeHead != -1)
252 r[resHList[nsp].freeHead].res.free.prev = (int)newListSize - 1;
253 r[newListSize-1].res.free.next = resHList[nsp].freeHead;
254 r[oldSize].res.free.prev = -1;
255 resHList[nsp].freeHead = oldSize;
256 resHList[nsp].size = (int)newListSize;
257 }
258
259 /**************************************************************/
260
261 static void
reshPut_(int nsp,int entry,void * p,const resOps * ops)262 reshPut_(int nsp, int entry, void *p, const resOps *ops)
263 {
264 listElem_t *newListElem = resHList[nsp].resources + entry;
265 int next = newListElem->res.free.next,
266 prev = newListElem->res.free.prev;
267 if (next != -1)
268 resHList[nsp].resources[next].res.free.prev = prev;
269 if (prev != -1)
270 resHList[nsp].resources[prev].res.free.next = next;
271 else
272 resHList[nsp].freeHead = next;
273 newListElem->res.v.val = p;
274 newListElem->res.v.ops = ops;
275 newListElem->status = RESH_DESYNC_IN_USE;
276 }
277
reshPut(void * p,const resOps * ops)278 int reshPut ( void *p, const resOps *ops )
279 {
280 xassert ( p && ops );
281
282 LIST_INIT(1);
283
284 LIST_LOCK();
285
286 int nsp = namespaceGetActive ();
287
288 if ( resHList[nsp].freeHead == -1) listSizeExtend();
289 int entry = resHList[nsp].freeHead;
290 cdiResH resH = namespaceIdxEncode2(nsp, entry);
291 reshPut_(nsp, entry, p, ops);
292
293 LIST_UNLOCK();
294
295 return resH;
296 }
297
298 /**************************************************************/
299
300 static void
reshRemove_(int nsp,int idx)301 reshRemove_(int nsp, int idx)
302 {
303 int curFree = resHList[nsp].freeHead;
304 listElem_t *r = resHList[nsp].resources;
305 r[idx].res.free.next = curFree;
306 r[idx].res.free.prev = -1;
307 if (curFree != -1)
308 r[curFree].res.free.prev = idx;
309 r[idx].status = RESH_DESYNC_DELETED;
310 resHList[nsp].freeHead = idx;
311 }
312
reshDestroy(cdiResH resH)313 void reshDestroy(cdiResH resH)
314 {
315 int nsp;
316 namespaceTuple_t nspT;
317
318 LIST_LOCK();
319
320 nsp = namespaceGetActive ();
321
322 nspT = namespaceResHDecode ( resH );
323
324 xassert ( nspT.nsp == nsp
325 && nspT.idx >= 0
326 && nspT.idx < resHList[nsp].size
327 && resHList[nsp].resources[nspT.idx].res.v.ops);
328
329 if (resHList[nsp].resources[nspT.idx].status & RESH_IN_USE_BIT)
330 reshRemove_(nsp, nspT.idx);
331
332 LIST_UNLOCK();
333 }
334
reshRemove(cdiResH resH,const resOps * ops)335 void reshRemove ( cdiResH resH, const resOps * ops )
336 {
337 int nsp;
338 namespaceTuple_t nspT;
339
340 LIST_LOCK();
341
342 nsp = namespaceGetActive ();
343
344 nspT = namespaceResHDecode ( resH );
345
346 xassert ( nspT.nsp == nsp
347 && nspT.idx >= 0
348 && nspT.idx < resHList[nsp].size
349 && (resHList[nsp].resources[nspT.idx].status & RESH_IN_USE_BIT)
350 && resHList[nsp].resources[nspT.idx].res.v.ops
351 && resHList[nsp].resources[nspT.idx].res.v.ops == ops );
352
353 reshRemove_(nsp, nspT.idx);
354
355 LIST_UNLOCK();
356 }
357
358 /**************************************************************/
359
reshReplace(cdiResH resH,void * p,const resOps * ops)360 void reshReplace(cdiResH resH, void *p, const resOps *ops)
361 {
362 xassert(p && ops);
363 LIST_INIT(1);
364 LIST_LOCK();
365 int nsp = namespaceGetActive();
366 namespaceTuple_t nspT = namespaceResHDecode(resH);
367 while (resHList[nsp].size <= nspT.idx)
368 listSizeExtend();
369 listElem_t *q = resHList[nsp].resources + nspT.idx;
370 if (q->status & RESH_IN_USE_BIT)
371 {
372 q->res.v.ops->valDestroy(q->res.v.val);
373 reshRemove_(nsp, nspT.idx);
374 }
375 reshPut_(nsp, nspT.idx, p, ops);
376 LIST_UNLOCK();
377 }
378
379
380 static listElem_t *
reshGetElem(const char * caller,const char * expressionString,cdiResH resH,const resOps * ops)381 reshGetElem(const char *caller, const char* expressionString, cdiResH resH, const resOps *ops)
382 {
383 listElem_t *listElem;
384 xassert ( ops );
385
386 LIST_INIT(1);
387
388 LIST_LOCK();
389
390 int nsp = namespaceGetActive ();
391
392 namespaceTuple_t nspT = namespaceResHDecode ( resH );
393 assert(nspT.idx >= 0);
394
395 if (nspT.nsp == nsp &&
396 nspT.idx < resHList[nsp].size)
397 {
398 listElem = resHList[nsp].resources + nspT.idx;
399 LIST_UNLOCK();
400 }
401 else
402 {
403 LIST_UNLOCK();
404 show_stackframe();
405
406 if ( resH == CDI_UNDEFID )
407 {
408 xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: the value is CDI_UNDEFID (= %d).\n\tThis is most likely the result of a failed earlier call. Please check the IDs returned by CDI.", expressionString, caller, resH);
409 }
410 else
411 {
412 xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: the value is garbage (= %d, which resolves to namespace = %d, index = %d).\n\tThis is either the result of using an uninitialized variable,\n\tof using a value as an ID that is not an ID,\n\tor of using an ID after it has been invalidated.", expressionString, caller, resH, nspT.nsp, nspT.idx);
413 }
414 }
415
416 if ( !(listElem && listElem->res.v.ops == ops) )
417 {
418 show_stackframe();
419
420 xabortC(caller, "Error while trying to resolve the ID \"%s\" in `%s()`: list element not found. The failed ID is %d", expressionString, caller, (int)resH);
421 }
422
423 return listElem;
424 }
425
reshGetValue(const char * caller,const char * expressionString,cdiResH resH,const resOps * ops)426 void *reshGetValue(const char * caller, const char* expressionString, cdiResH resH, const resOps * ops)
427 {
428 return reshGetElem(caller, expressionString, resH, ops)->res.v.val;
429 }
430
431 /**************************************************************/
432
reshGetResHListOfType(unsigned numIDs,int resHs[],const resOps * ops)433 void reshGetResHListOfType(unsigned numIDs, int resHs[], const resOps *ops)
434 {
435 xassert ( resHs && ops );
436
437 LIST_INIT(1);
438
439 LIST_LOCK();
440
441 int nsp = namespaceGetActive();
442 unsigned j = 0;
443 for (int i = 0; i < resHList[nsp].size && j < numIDs; i++ )
444 if ((resHList[nsp].resources[i].status & RESH_IN_USE_BIT)
445 && resHList[nsp].resources[i].res.v.ops == ops)
446 resHs[j++] = namespaceIdxEncode2(nsp, i);
447
448 LIST_UNLOCK();
449 }
450
451 enum cdiApplyRet
cdiResHApply(enum cdiApplyRet (* func)(int id,void * res,const resOps * p,void * data),void * data)452 cdiResHApply(enum cdiApplyRet (*func)(int id, void *res, const resOps *p,
453 void *data), void *data)
454 {
455 xassert(func);
456
457 LIST_INIT(1);
458
459 LIST_LOCK();
460
461 int nsp = namespaceGetActive ();
462 enum cdiApplyRet ret = CDI_APPLY_GO_ON;
463 for (int i = 0; i < resHList[nsp].size && ret > 0; ++i)
464 if (resHList[nsp].resources[i].status & RESH_IN_USE_BIT)
465 ret = func(namespaceIdxEncode2(nsp, i),
466 resHList[nsp].resources[i].res.v.val,
467 resHList[nsp].resources[i].res.v.ops, data);
468 LIST_UNLOCK();
469 return ret;
470 }
471
472
473 enum cdiApplyRet
cdiResHFilterApply(const resOps * p,enum cdiApplyRet (* func)(int id,void * res,void * data),void * data)474 cdiResHFilterApply(const resOps *p,
475 enum cdiApplyRet (*func)(int id, void *res, void *data),
476 void *data)
477 {
478 xassert(p && func);
479
480 LIST_INIT(1);
481
482 LIST_LOCK();
483
484 int nsp = namespaceGetActive ();
485 enum cdiApplyRet ret = CDI_APPLY_GO_ON;
486 listElem_t *r = resHList[nsp].resources;
487 for (int i = 0; i < resHList[nsp].size && ret > 0; ++i)
488 if ((r[i].status & RESH_IN_USE_BIT) && r[i].res.v.ops == p)
489 ret = func(namespaceIdxEncode2(nsp, i), r[i].res.v.val,
490 data);
491 LIST_UNLOCK();
492 return ret;
493 }
494
495
496
497
498 /**************************************************************/
499
reshCountType(const resOps * ops)500 unsigned reshCountType(const resOps *ops)
501 {
502 unsigned countType = 0;
503
504 xassert(ops);
505
506 LIST_INIT(1);
507
508 LIST_LOCK();
509
510 int nsp = namespaceGetActive ();
511
512 listElem_t *r = resHList[nsp].resources;
513 size_t len = (size_t)resHList[nsp].size;
514 for (size_t i = 0; i < len; i++ )
515 countType += ((r[i].status & RESH_IN_USE_BIT) && r[i].res.v.ops == ops);
516
517 LIST_UNLOCK();
518
519 return countType;
520 }
521
522 /**************************************************************/
523
524 int
reshResourceGetPackSize_intern(int resH,const resOps * ops,void * context,const char * caller,const char * expressionString)525 reshResourceGetPackSize_intern(int resH, const resOps *ops, void *context, const char* caller, const char* expressionString)
526 {
527 listElem_t *curr = reshGetElem(caller, expressionString, resH, ops);
528 return curr->res.v.ops->valGetPackSize(curr->res.v.val, context);
529 }
530
531 void
reshPackResource_intern(int resH,const resOps * ops,void * buf,int buf_size,int * position,void * context,const char * caller,const char * expressionString)532 reshPackResource_intern(int resH, const resOps *ops, void *buf, int buf_size, int *position, void *context,
533 const char* caller, const char* expressionString)
534 {
535 listElem_t *curr = reshGetElem(caller, expressionString, resH, ops);
536 curr->res.v.ops->valPack(curr->res.v.val, buf, buf_size, position, context);
537 }
538
539 enum {
540 resHPackHeaderNInt = 2,
541 resHDeleteNInt = 2,
542 };
543
getPackBufferSize(void * context)544 static int getPackBufferSize(void *context)
545 {
546 int intpacksize, packBufferSize = 0;
547
548 int nsp = namespaceGetActive ();
549
550 /* pack start marker, namespace and sererator marker */
551 packBufferSize += resHPackHeaderNInt * (intpacksize = serializeGetSize(1, CDI_DATATYPE_INT, context));
552
553 /* pack resources, type marker and seperator marker */
554 listElem_t *r = resHList[nsp].resources;
555 for ( int i = 0; i < resHList[nsp].size; i++)
556 if (r[i].status & RESH_SYNC_BIT)
557 {
558 if (r[i].status == RESH_DESYNC_DELETED)
559 {
560 packBufferSize += resHDeleteNInt * intpacksize;
561 }
562 else if (r[i].status == RESH_DESYNC_IN_USE)
563 {
564 xassert ( r[i].res.v.ops );
565 /* packed resource plus 1 int for type */
566 packBufferSize +=
567 r[i].res.v.ops->valGetPackSize(r[i].res.v.val, context)
568 + intpacksize;
569 }
570 }
571 /* end marker */
572 packBufferSize += intpacksize;
573
574 return packBufferSize;
575 }
576
577 /**************************************************************/
578
reshPackBufferDestroy(char ** buffer)579 void reshPackBufferDestroy ( char ** buffer )
580 {
581 if ( buffer ) free ( *buffer );
582 }
583
584 /**************************************************************/
585
reshGetTxCode(cdiResH resH)586 int reshGetTxCode(cdiResH resH)
587 {
588 int type = 0;
589
590 LIST_LOCK();
591
592 int nsp = namespaceGetActive ();
593
594 namespaceTuple_t nspT = namespaceResHDecode ( resH );
595 assert(nspT.idx >= 0);
596
597 if (nspT.nsp == nsp &&
598 nspT.idx < resHList[nsp].size)
599 {
600 listElem_t *listElem = resHList[nsp].resources + nspT.idx;
601 xassert ( listElem->res.v.ops );
602 type = listElem->res.v.ops->valTxCode();
603 }
604
605 LIST_UNLOCK();
606
607 return type;
608 }
609
610 /**************************************************************/
611
reshPackBufferCreate(char ** packBuffer,int * packBufferSize,void * context)612 int reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context)
613 {
614 int packBufferPos = 0;
615 int end = END;
616
617 xassert ( packBuffer );
618
619 LIST_LOCK();
620
621 int nsp = namespaceGetActive ();
622
623 int pBSize = *packBufferSize = getPackBufferSize(context);
624 char *pB = *packBuffer = (char *) Malloc((size_t)pBSize);
625
626 {
627 int header[resHPackHeaderNInt] = { START, nsp };
628 serializePack(header, resHPackHeaderNInt, CDI_DATATYPE_INT, pB, pBSize, &packBufferPos, context);
629 }
630
631 listElem_t *r = resHList[nsp].resources;
632 for ( int i = 0; i < resHList[nsp].size; i++ )
633 if (r[i].status & RESH_SYNC_BIT)
634 {
635 if (r[i].status == RESH_DESYNC_DELETED)
636 {
637 int temp[resHDeleteNInt]
638 = { RESH_DELETE, namespaceIdxEncode2(nsp, i) };
639 serializePack(temp, resHDeleteNInt, CDI_DATATYPE_INT,
640 pB, pBSize, &packBufferPos, context);
641 }
642 else
643 {
644 listElem_t * curr = r + i;
645 xassert ( curr->res.v.ops );
646 int type = curr->res.v.ops->valTxCode();
647 if ( ! type ) continue;
648 serializePack(&type, 1, CDI_DATATYPE_INT, pB,
649 pBSize, &packBufferPos, context);
650 curr->res.v.ops->valPack(curr->res.v.val,
651 pB, pBSize, &packBufferPos, context);
652 }
653 r[i].status &= ~RESH_SYNC_BIT;
654 }
655
656 LIST_UNLOCK();
657
658 serializePack(&end, 1, CDI_DATATYPE_INT, pB, pBSize, &packBufferPos, context);
659
660 return packBufferPos;
661 }
662
663 /**************************************************************/
664
665 /* for thread safety this feature would have to be integrated in reshPut */
666
reshSetStatus(cdiResH resH,const resOps * ops,int status)667 void reshSetStatus ( cdiResH resH, const resOps * ops, int status )
668 {
669 int nsp;
670 namespaceTuple_t nspT;
671 listElem_t * listElem;
672
673 xassert((ops != NULL) ^ !(status & RESH_IN_USE_BIT));
674
675 LIST_INIT(1);
676
677 LIST_LOCK();
678
679 nsp = namespaceGetActive ();
680
681 nspT = namespaceResHDecode ( resH );
682
683 xassert ( nspT.nsp == nsp &&
684 nspT.idx >= 0 &&
685 nspT.idx < resHList[nsp].size );
686
687 xassert ( resHList[nsp].resources );
688 listElem = resHList[nsp].resources + nspT.idx;
689
690 xassert((!ops || (listElem->res.v.ops == ops))
691 && (listElem->status & RESH_IN_USE_BIT) == (status & RESH_IN_USE_BIT));
692
693 listElem->status = status;
694
695 LIST_UNLOCK();
696 }
697
698 /**************************************************************/
699
reshGetStatus(cdiResH resH,const resOps * ops)700 int reshGetStatus ( cdiResH resH, const resOps * ops )
701 {
702 LIST_INIT(1);
703
704 LIST_LOCK();
705
706 int nsp = namespaceGetActive ();
707
708 namespaceTuple_t nspT = namespaceResHDecode ( resH );
709
710 xassert ( nspT.nsp == nsp &&
711 nspT.idx >= 0 );
712
713 int status = RESH_UNUSED;
714 if (nspT.idx < resHList[nsp].size)
715 {
716 listElem_t *listElem = resHList[nsp].resources + nspT.idx;
717 const resOps *elemOps = listElem->res.v.ops;
718 xassert(listElem && (!(listElem->status & RESH_IN_USE_BIT) || elemOps == ops));
719 status = listElem->status;
720 }
721
722 LIST_UNLOCK();
723
724 return status;
725 }
726
727 /**************************************************************/
728
reshLock()729 void reshLock ()
730 {
731 LIST_LOCK();
732 }
733
734 /**************************************************************/
735
reshUnlock()736 void reshUnlock ()
737 {
738 LIST_UNLOCK();
739 }
740
741 /**************************************************************/
742
reshListCompare(int nsp0,int nsp1)743 int reshListCompare ( int nsp0, int nsp1 )
744 {
745 LIST_INIT(1);
746 LIST_LOCK();
747
748 xassert(resHListSize > nsp0 && resHListSize > nsp1 &&
749 nsp0 >= 0 && nsp1 >= 0);
750
751 int valCompare = 0;
752 int i, listSizeMin = (resHList[nsp0].size <= resHList[nsp1].size)
753 ? resHList[nsp0].size : resHList[nsp1].size;
754 listElem_t *resources0 = resHList[nsp0].resources,
755 *resources1 = resHList[nsp1].resources;
756 for (i = 0; i < listSizeMin; i++)
757 {
758 int occupied0 = (resources0[i].status & RESH_IN_USE_BIT) != 0,
759 occupied1 = (resources1[i].status & RESH_IN_USE_BIT) != 0;
760 /* occupation mismatch ? */
761 int diff = occupied0 ^ occupied1;
762 valCompare |= (diff << cdiResHListOccupationMismatch);
763 if (!diff && occupied0)
764 {
765 /* both occupied, do resource types match? */
766 diff = (resources0[i].res.v.ops != resources1[i].res.v.ops
767 || resources0[i].res.v.ops == NULL);
768 valCompare |= (diff << cdiResHListResourceTypeMismatch);
769 if (!diff)
770 {
771 /* types match, does content match also? */
772 diff
773 = resources0[i].res.v.ops->valCompare(resources0[i].res.v.val,
774 resources1[i].res.v.val);
775 valCompare |= (diff << cdiResHListResourceContentMismatch);
776 }
777 }
778 }
779 /* find resources in nsp 0 beyond end of nsp 1 */
780 for (int j = listSizeMin; j < resHList[nsp0].size; ++j)
781 valCompare |= (((resources0[j].status & RESH_IN_USE_BIT) != 0)
782 << cdiResHListOccupationMismatch);
783 /* find resources in nsp 1 beyond end of nsp 0 */
784 for (; i < resHList[nsp1].size; ++i)
785 valCompare |= (((resources1[i].status & RESH_IN_USE_BIT) != 0)
786 << cdiResHListOccupationMismatch);
787
788 LIST_UNLOCK();
789
790 return valCompare;
791 }
792
793 /**************************************************************/
794
reshListPrint(FILE * fp)795 void reshListPrint(FILE *fp)
796 {
797 int i, j, temp;
798 listElem_t * curr;
799
800 LIST_INIT(1);
801
802
803 temp = namespaceGetActive ();
804
805 fprintf ( fp, "\n\n##########################################\n#\n# print " \
806 "global resource list \n#\n" );
807
808 for ( i = 0; i < namespaceGetNumber (); i++ )
809 {
810 namespaceSetActive ( i );
811
812 fprintf ( fp, "\n" );
813 fprintf ( fp, "##################################\n" );
814 fprintf ( fp, "#\n" );
815 fprintf ( fp, "# namespace=%d\n", i );
816 fprintf ( fp, "#\n" );
817 fprintf ( fp, "##################################\n\n" );
818
819 fprintf ( fp, "resHList[%d].size=%d\n", i, resHList[i].size );
820
821 for ( j = 0; j < resHList[i].size; j++ )
822 {
823 curr = resHList[i].resources + j;
824 if (!(curr->status & RESH_IN_USE_BIT))
825 {
826 curr->res.v.ops->valPrint(curr->res.v.val, fp);
827 fprintf ( fp, "\n" );
828 }
829 }
830 }
831 fprintf ( fp, "#\n# end global resource list" \
832 "\n#\n##########################################\n\n" );
833
834 namespaceSetActive ( temp );
835 }
836
837
838 /*
839 * Local Variables:
840 * c-file-style: "Java"
841 * c-basic-offset: 2
842 * indent-tabs-mode: nil
843 * show-trailing-whitespace: t
844 * require-trailing-newline: t
845 * End:
846 */
847