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