Ignore 'remote get' timeouts in NameServer_get when procId array is supplied in QNX.
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / utils / hlos / knl / NameServer_daemon.c
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*!
33  *  @file       NameServer_daemon.c
34  *
35  *  @brief      NameServer Manager
36  *
37  */
40 /* Standard headers */
41 #include <ti/ipc/Std.h>
43 /* Qnx specific header files */
44 #include <pthread.h>
46 /* Socket Headers */
47 #include <sys/queue.h>
48 #include <sys/select.h>
49 #include <sys/time.h>
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <errno.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <assert.h>
58 #include <fcntl.h>
60 /* Module level headers */
61 #include <ti/ipc/NameServer.h>
62 #include <ti/ipc/MultiProc.h>
63 #include <_MultiProc.h>
64 #include <ti/ipc/MessageQCopy.h>
66 /* Internal stuff: */
67 #include <_MessageQCopy.h>
68 #include <_NameServer.h>
69 #include <_NameServerRemoteRpmsg.h>
70 #include <_IpcLog.h>
72 /* TI Ipc utils: */
73 #include <TiIpcFxns.h>
75 #include "ti/ipc/ti_ipc.h"
77 #define MESSAGEQ_RPMSG_PORT       61
78 #define NAME_SERVER_RPMSG_ADDR    0
79 #define RPMSG_RESERVED_ADDRESSES  (1024)
81 #define INVALIDSOCKET     (-1)
83 #if defined (__cplusplus)
84 extern "C" {
85 #endif
88 /* =============================================================================
89  * Structures & Enums
90  * =============================================================================
91  */
93 /* Structure of entry in Name/Value table */
94 typedef struct NameServer_TableEntry_tag {
95     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
96     /* List element */
97     UInt32                    hash;
98     /* Hash value */
99     String                    name;
100     /* Name portion of the name/value pair. */
101     UInt                      len;
102     /* Length of the value field. */
103     Ptr                       value;
104     /* Value portion of the name/value entry. */
105     Bool                      collide;
106     /* Does the hash collide? */
107     struct NameServer_TableEntry_tag * next;
108     /* Pointer to the next entry, used incase of collision only */
109 } NameServer_TableEntry;
111 /* Structure defining object for the NameServer */
112 struct NameServer_Object {
113     CIRCLEQ_ENTRY(NameServer_Object) elem;
114     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
115     String             name;            /* name of the instance */
116     NameServer_Params  params;          /* the parameter structure */
117     UInt32             count;           /* count of entries */
118     UInt32             refCount;        /* reference count to this object */
119     pthread_mutex_t    gate;            /* crit sect gate */
120 } NameServer_Object;
122 /* structure for NameServer module state */
123 typedef struct NameServer_ModuleObject {
124     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
125     Int32               refCount;
126     MessageQCopy_Handle mq;
127     /* MessageQCopy instance to receive from remote proc nameserver ports: */
128     UInt32              recvAddr;
129     /* Local endpoint for receiving from remote proc nameserver ports: */
130     pthread_t           listener;
131     /* Listener thread for NameServer replies and requests. */
132     int                 waitFdW;
133     int                 waitFdR;
134     /* Pipe to post to NameServer_get. */
135     NameServerMsg       nsMsg;
136     /* NameServer Message cache. */
137     NameServer_Params   defInstParams;
138     /* Default instance paramters */
139     pthread_mutex_t     modGate;
140 } NameServer_ModuleObject;
142 #define CIRCLEQ_destruct(head) { \
143         (head)->cqh_first = NULL; \
144         (head)->cqh_last = NULL; \
147 #define CIRCLEQ_elemClear(elem) { \
148         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
151 #define CIRCLEQ_traverse(x, y, tag) \
152         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
154 /* =============================================================================
155  *  Globals
156  * =============================================================================
157  */
158 /*
159  * NameServer_state
160  *
161  * Make the module gate "recursive" since NameServer_getHandle() needs to
162  * use it and NameServer_create() needs to hold it around its call to
163  * NameServer_getHandle().  Also, use the static initializer instead of a
164  * run-time init call, so we can use this gate immediately in _setup().
165  */
166 static NameServer_ModuleObject NameServer_state = {
167     .defInstParams.maxRuntimeEntries = 0u,
168     .defInstParams.tableHeap         = NULL,
169     .defInstParams.checkExisting     = TRUE,
170     .defInstParams.maxValueLen       = 0u,
171     .defInstParams.maxNameLen        = 16u,
172 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
173     .modGate                         = PTHREAD_RMUTEX_INITIALIZER,
174     .refCount                        = 0
175 };
177 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
179 static const UInt32 stringCrcTab[256u] = {
180   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
181   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
182   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
183   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
184   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
185   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
186   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
187   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
188   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
189   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
190   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
191   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
192   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
193   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
194   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
195   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
196   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
197   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
198   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
199   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
200   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
201   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
202   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
203   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
204   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
205   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
206   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
207   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
208   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
209   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
210   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
211   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
212   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
213   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
214   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
215   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
216   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
217   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
218   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
219   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
220   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
221   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
222   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
223 };
225 static UInt32 stringHash(String s)
227     UInt32 hash = strlen(s);
228     UInt32 i;
230     for (i = 0; i < strlen(s); i++) {
231         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
232     }
234     return (hash);
237 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
239     NameServer_Handle handle;
240     Int               status = NameServer_E_FAIL;
241     char              buf = 'n';
242     int               numBytes;
243     int               waitFd = NameServer_module->waitFdW;
245     if (msg->request == NAMESERVER_REQUEST) {
246         LOG2("NameServer Request: instanceName: %s, name: %s\n",
247              (String)msg->instanceName, (String)msg->name)
249         assert(msg->valueLen <= MAXVALUELEN);
251         /*
252          *  Message is a request. Lookup name in NameServer table.
253          *  Send a response message back to source processor.
254          */
255         handle = NameServer_getHandle((String)msg->instanceName);
257         if (handle != NULL) {
258             /* Search for the NameServer entry */
259             if (msg->valueLen <= sizeof (Bits32)) {
260                 LOG0("Calling NameServer_getLocalUInt32...\n")
261                 status = NameServer_getLocalUInt32(handle,
262                      (String)msg->name, &msg->value);
263             }
264             else {
265                 LOG0("Calling NameServer_getLocal...\n")
266                 status = NameServer_getLocal(handle,
267                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
268             }
269         }
271         LOG2("NameServer Response: instanceName: %s, name: %s,",
272              (String)msg->instanceName, (String)msg->name)
273         /* set the request status */
274         if (status < 0) {
275             LOG1(" Value not found, status: %d\n", status)
276             msg->requestStatus = 0;
277         }
278         else {
279             msg->requestStatus = 1;
280             LOG1(" Value: 0x%x\n", msg->value)
281         }
283         /* specify message as a response */
284         msg->request = NAMESERVER_RESPONSE;
285         msg->reserved = NAMESERVER_MSG_TOKEN;
287         /* send response message to remote processor */
288         status = MessageQCopy_send(procId, MultiProc_self(),
289             MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
290             sizeof(NameServerMsg), TRUE);
291         if (status < 0) {
292             LOG0("NameServer: MessageQCopy_send failed\n")
293         }
294     }
295     else {
296         LOG2("NameServer Reply: instanceName: %s, name: %s",
297              (String)msg->instanceName, (String)msg->name)
298         LOG1(", value: 0x%x\n", msg->value)
300         /* Save the response message.  */
301         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
303         /* Post the eventfd upon which NameServer_get() is waiting */
304         numBytes = write(waitFd, &buf, sizeof(buf));
305     }
308 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
309     void * priv, UInt32 src, UInt16 srcProc)
311     NameServerMsg msg;
313     LOG0("listener_cb: Entered Listener thread.\n")
315     LOG1("NameServer: Listener got NameServer message "
316          "from MessageQCopy: 0x%p!\n", handle);
317     /* Get NameServer message and process: */
318     memcpy(&msg, data, len);
320     if (len != sizeof(NameServerMsg)) {
321         LOG1("NameServer: got bad NameServerMsg len (%d)\n",
322             len)
323     }
324     else {
325         LOG1("listener_cb: read from MessageQCopy 0x%p\n", handle)
326         LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
327              len, src)
328         LOG1("from vproc: %d\n", srcProc)
329         NameServerRemote_processMessage(&msg, srcProc);
330     }
333 /* =============================================================================
334  * APIS
335  * =============================================================================
336  */
338 /* Function to setup the nameserver module. */
339 Int NameServer_setup(Void)
341     Int    status = NameServer_S_SUCCESS;
342     UInt16 numProcs;
343     int    fd[2];
345     pthread_mutex_lock(&NameServer_module->modGate);
347     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
349     NameServer_module->refCount++;
351     if (NameServer_module->refCount > 1) {
352         LOG0("NameServer_setup: already setup\n")
353         status = NameServer_S_ALREADYSETUP;
354         goto exit;
355     }
357     numProcs = MultiProc_getNumProcessors();
359     if (pipe(fd) == -1) {
360         status = NameServer_E_FAIL;
361         LOG0("NameServer_setup: failed to create waitFd.\n")
362         goto exit;
363     }
364     NameServer_module->waitFdW = fd[1];
365     NameServer_module->waitFdR = fd[0];
367     /* Create the MessageQCopy for receiving messages from all remote proc */
368     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
369         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
371     if (NameServer_module->mq == NULL) {
372         status = NameServer_E_FAIL;
373         LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
374         goto exit;
375     }
377     /* Construct the list object */
378     CIRCLEQ_INIT(&NameServer_module->objList);
380 exit:
381     LOG1("NameServer_setup: exiting, refCount=%d\n", \
382         NameServer_module->refCount)
384     pthread_mutex_unlock(&NameServer_module->modGate);
386     return (status);
389 /*! Function to destroy the nameserver module. */
390 Int NameServer_destroy(void)
392     Int      status    = NameServer_S_SUCCESS;
394     pthread_mutex_lock(&NameServer_module->modGate);
396     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
398     NameServer_module->refCount--;
400     if (NameServer_module->refCount > 0) {
401         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
402         status = NameServer_S_SUCCESS;
404         goto exit;
405     }
407     /* Delete the MessageQCopy instances */
408     if (NameServer_module->mq != NULL) {
409         MessageQCopy_delete(&NameServer_module->mq);
410     }
412     CIRCLEQ_destruct(&NameServer_module->objList);
414     close(NameServer_module->waitFdW);
415     close(NameServer_module->waitFdR);
417 exit:
418     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
420     pthread_mutex_unlock(&NameServer_module->modGate);
422     return (status);
425 /* Function to retrieve a NameServer handle from name. */
426 NameServer_Handle NameServer_getHandle(String name)
428     NameServer_Handle handle = NULL;
429     Bool              found = FALSE;
430     struct NameServer_Object * elem;
432     assert(name != NULL);
433     assert(NameServer_module->refCount != 0);
435     pthread_mutex_lock(&NameServer_module->modGate);
437     /* Lookup handle from name: */
438     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
439         handle = (NameServer_Handle) elem;
440         if (strcmp(handle->name, name) == 0) {
441             found = TRUE;
442             break;
443         }
444     }
446     if (found == FALSE) {
447         handle = NULL;
448     }
450     pthread_mutex_unlock(&NameServer_module->modGate);
452     return (handle);
456 /* Function to create a name server. */
457 NameServer_Handle NameServer_create(String name,
458                                     const NameServer_Params * params)
460     NameServer_Handle handle = NULL;
461     pthread_mutexattr_t mutex_attr;
463     assert(params != NULL);
464     assert(name != NULL);
465     assert(NameServer_module->refCount != 0);
467     LOG1("NameServer_create(): '%s'\n", name)
469     pthread_mutex_lock(&NameServer_module->modGate);
471     /* check if the name is already created or not */
472     handle = NameServer_getHandle(name);
473     if (handle != NULL) {
474         if (memcmp((Ptr)&handle->params, (Ptr)params,
475             sizeof(NameServer_Params)) == 0) {
476             handle->refCount++;
477         }
478         else {
479             LOG0("NameServer_create: NameServer params mismatch\n")
480             handle = NULL;
481         }
482         goto leave;
483     }
484     else {
485         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
486     }
488     if (!handle) {
489         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
490         goto leave;
491     }
493     handle->refCount = 1;
494     handle->name = (String)malloc(strlen(name) + 1u);
495     if (!handle->name) {
496         LOG0("NameServer_create: instance name alloc failed\n")
497         goto cleanup;
498     }
499     strncpy(handle->name, name, strlen (name) + 1u);
500     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
502     assert(params.maxValueLen <= MAXVALUELEN);
504     if (params->maxValueLen < sizeof(UInt32)) {
505         handle->params.maxValueLen = sizeof(UInt32);
506     }
507     else {
508         handle->params.maxValueLen = params->maxValueLen;
509     }
511     CIRCLEQ_INIT(&handle->nameList);
512     handle->count = 0u;
514     /* Put in the local list */
515     CIRCLEQ_elemClear(&handle->elem);
516     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
518     /*
519      * NameServer_removeEntry() enters gate and is called by
520      * NameServer_remove() while holding the gate.
521      */
522     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
523     pthread_mutex_init(&handle->gate, &mutex_attr);
525     goto leave;
527 cleanup:
528     free(handle);
529     handle = NULL;
531 leave:
532     pthread_mutex_unlock(&NameServer_module->modGate);
534     return (handle);
538 /* Function to delete a name server. */
539 Int NameServer_delete(NameServer_Handle * handle)
541     Int status = NameServer_S_SUCCESS;
543     assert(handle != NULL);
544     assert(*handle != NULL);
545     assert((*handle)->count == 0);
546     assert(NameServer_module->refCount != 0);
548     pthread_mutex_lock(&NameServer_module->modGate);
550     (*handle)->refCount--;
551     if ((*handle)->refCount != 0) {
552         goto leave;
553     }
555     if ((*handle)->count == 0) {
556         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
558         if ((*handle)->name != NULL) {
559             free((*handle)->name);
560             (*handle)->name = NULL;
561         }
563         CIRCLEQ_destruct(&(*handle)->nameList);
565         free((*handle));
566         (*handle) = NULL;
567     }
569 leave:
570     pthread_mutex_unlock(&NameServer_module->modGate);
572     return (status);
575 /* Adds a variable length value into the local NameServer table */
576 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
578     Int                 status = NameServer_S_SUCCESS;
579     NameServer_TableEntry * node = NULL;
580     NameServer_TableEntry * new_node = NULL;
581     Bool                found = FALSE;
582     UInt32              hash;
584     assert(handle != NULL);
585     assert(name     != NULL);
586     assert(buf      != NULL);
587     assert(len      != 0);
588     assert(NameServer_module->refCount != 0);
590     /* Calculate the hash */
591     hash = stringHash(name);
593     if (len > handle->params.maxValueLen) {
594         status = NameServer_E_INVALIDARG;
595         LOG0("NameServer_add: value length exceeded maximum!\n")
596         new_node = NULL;
597         goto exit;
598     }
600     pthread_mutex_lock(&handle->gate);
602     /* Traverse the list to find duplicate check */
603     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
604         /* Hash matches */
605         if (node->hash == hash) {
606             /* If the name matches, incase hash is duplicate */
607             if (strcmp(node->name, name) == 0) {
608                 if (handle->params.checkExisting == TRUE) {
609                     status = NameServer_E_INVALIDARG;
610                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
611                     break;
612                 }
613             }
614             else {
615                 found = TRUE;
616                 break;
617             } /* name does not match */
618         } /* hash does not match */
619     } /* CIRCLEQ_traverse */
621     if (status != NameServer_S_SUCCESS) {
622         new_node = NULL;
623         goto exit;
624     }
626     /* Now add the new entry. */
627     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
628     if (new_node == NULL) {
629         status = NameServer_E_MEMORY;
630         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
632         goto exit;
633     }
635     new_node->hash    = hash;
636     new_node->collide = found; /* Indicate if there is a collision*/
637     new_node->len     = len;
638     new_node->next    = NULL;
639     new_node->name = (String)malloc(strlen(name) + 1u);
640     new_node->value  = (Ptr)malloc(len);
641     strncpy(new_node->name, name, strlen(name) + 1u);
642     memcpy((Ptr)new_node->value, (Ptr)buf, len);
644     if (found == TRUE) {
645         /* If hash is found, need to stitch the list to link the
646          * new node to the existing node with the same hash.
647          */
648         new_node->next = node->next;
649         node->next = new_node;
650     }
651     else {
652         /* put the new node into the list */
653         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
654     }
656     handle->count++;
658     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
659          name, *(UInt32 *)buf)
661 exit:
662     pthread_mutex_unlock(&handle->gate);
664     return (new_node);
668 /* Function to add a UInt32 value into a name server. */
669 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
671     Ptr entry = NULL;
673     assert(handle != NULL);
674     assert(name   != NULL);
675     assert(NameServer_module->refCount != 0);
677     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
679     return (entry);
682 /* Function to remove a name/value pair from a name server. */
683 Int NameServer_remove(NameServer_Handle handle, String name)
685     Int                 status = NameServer_S_SUCCESS;
686     NameServer_TableEntry *prev = NULL;
687     NameServer_TableEntry *temp = NULL;
688     NameServer_TableEntry *node = NULL;
689     Bool                done   = FALSE;
690     UInt32              hash;
692     assert(handle != NULL);
693     assert(name   != NULL);
694     assert(NameServer_module->refCount != 0);
696     /* Calculate the hash */
697     hash = stringHash(name);
699     pthread_mutex_lock(&handle->gate);
701     /* Traverse the list to find duplicate check */
702     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
703         /* Hash matchs */
704         if (node->hash == hash) {
705             if (node->collide == TRUE) {
706                 if (strcmp(node->name, name) == 0){
707                     free(node->value);
708                     free(node->name);
709                     memcpy((Ptr)node, (Ptr) node->next,
710                            sizeof(NameServer_TableEntry));
711                     node->next = node->next->next;
712                     free(node->next);
713                     handle->count--;
714                     done = TRUE;
715                     break;
716                 }
717                 else {
718                     prev = node;
719                     temp = node->next;
720                     while (temp) {
721                         if (strcmp(temp->name, name) == 0){
722                             free(temp->value);
723                             free(temp->name);
724                             prev->next = temp->next;
725                             free(temp);
726                             handle->count--;
727                             done = TRUE;
728                             break;
729                         }
730                         temp = temp->next;
731                     }
732                     break;
733                 }
734             }
735             else {
736                 NameServer_removeEntry(handle, (Ptr)node);
738                 done = TRUE;
739                 break;
740             }
741         }
742     }
744     if (done == FALSE) {
745         status = NameServer_E_INVALIDARG;
746         LOG1("NameServer_remove %d Entry not found!\n", status)
747     }
749     pthread_mutex_unlock(&handle->gate);
751     return (status);
754 /* Function to remove a name/value pair from a name server. */
755 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
757     Int  status = NameServer_S_SUCCESS;
758     NameServer_TableEntry * node;
760     assert(handle != NULL);
761     assert(entry  != NULL);
762     assert(NameServer_module->refCount != 0);
764     pthread_mutex_lock(&handle->gate);
766     node = (NameServer_TableEntry *)entry;
768     free(node->value);
769     free(node->name);
770     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
771     free(node);
772     handle->count--;
774     pthread_mutex_unlock(&handle->gate);
776     return (status);
780 /* Initialize this config-params structure with supplier-specified
781  * defaults before instance creation.
782  */
783 Void NameServer_Params_init(NameServer_Params * params)
785     assert(params != NULL);
787     memcpy(params, &(NameServer_module->defInstParams),
788            sizeof (NameServer_Params));
792 Int NameServer_getRemote(NameServer_Handle handle,
793                      String            name,
794                      Ptr               value,
795                      UInt32 *          len,
796                      UInt16            procId)
798     Int status = NameServer_S_SUCCESS;
799     Int mqcStatus = -1;
800     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
801     NameServerMsg nsMsg;
802     NameServerMsg *replyMsg;
803     fd_set rfds;
804     int ret = 0, maxfd, waitFd;
805     struct timeval tv;
806     char buf = '1';
807     int numBytes;
809     pthread_mutex_lock(&NameServer_module->modGate);
811     /* Set Timeout to wait: */
812     tv.tv_sec = 0;
813     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
815     /* Create request message and send to remote processor: */
816     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
817     nsMsg.request = NAMESERVER_REQUEST;
818     nsMsg.requestStatus = 0;
819     nsMsg.valueLen = *len;
821     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
822     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
824     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
825            procId, (String)nsMsg.instanceName)
826     LOG1("%s...\n", (String)nsMsg.name)
827     /* send message */
828     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
829             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
830         TRUE);
831     if (mqcStatus < 0) {
832         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
833         status = NameServer_E_NOTFOUND;
834         goto exit;
835     }
837     /* Block on waitFd for signal from listener thread: */
838     waitFd = NameServer_module->waitFdR;
839     FD_ZERO(&rfds);
840     FD_SET(waitFd, &rfds);
841     maxfd = waitFd + 1;
842     LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
843     ret = select(maxfd, &rfds, NULL, NULL, &tv);
844     if (ret == -1) {
845         LOG0("NameServer_getRemote: select failed.")
846         status = NameServer_E_FAIL;
847         goto exit;
848     }
849     else if (!ret) {
850         LOG0("NameServer_getRemote: select timed out.\n")
851         status = NameServer_E_TIMEOUT;
852         goto exit;
853     }
855     if (FD_ISSET(waitFd, &rfds)) {
856         /* Read, just to balance the write: */
857         numBytes = read(waitFd, &buf, sizeof(buf));
859         /* Process response: */
860         replyMsg = &NameServer_module->nsMsg;
862         if (replyMsg->requestStatus) {
863             /* name is found */
865             /* set length to amount of data that was copied */
866             *len = replyMsg->valueLen;
868             /* set the contents of value */
869             if (*len <= sizeof (Bits32)) {
870                 *(UInt32 *)value = (UInt32)replyMsg->value;
871                 LOG2("NameServer_getRemote: Reply from: %d, %s:",
872                     procId, (String)replyMsg->instanceName)
873                 LOG2("%s, value: 0x%x...\n",
874                     (String)replyMsg->name, *(UInt32 *)value)
875             }
876             else {
877                 memcpy(value, replyMsg->valueBuf, *len);
878                 LOG2("NameServer_getRemote: Reply from: %d, %s:",
879                     procId, (String)replyMsg->instanceName)
880                 LOG2("%s, value buffer at address: 0x%p...\n",
881                     (String)replyMsg->name, value)
882             }
884             goto exit;
885         }
886         else {
887             /* name is not found */
888             LOG2("NameServer_getRemote: value for %s:%s not found.\n",
889                  (String)replyMsg->instanceName, (String)replyMsg->name)
891             /* set status to not found */
892             status = NameServer_E_NOTFOUND;
893         }
894     }
896 exit:
897     pthread_mutex_unlock(&NameServer_module->modGate);
899     return (status);
902 /* Function to retrieve the value portion of a name/value pair from
903  * local table.
904  */
905 Int NameServer_get(NameServer_Handle handle,
906                String            name,
907                Ptr               value,
908                UInt32 *          len,
909                UInt16            procId[])
911     Int status = NameServer_S_SUCCESS;
912     UInt16 numProcs = MultiProc_getNumProcessors();
913     UInt32 i;
915     if (procId == NULL) {
916         status = NameServer_getLocal(handle, name, value, len);
917         if (status == NameServer_E_NOTFOUND) {
918             for (i = 0; i < numProcs; i++) {
919                 /* getLocal call already covers "self", keep going */
920                 if (i == MultiProc_self()) {
921                     continue;
922                 }
924                 status = NameServer_getRemote(handle, name, value, len, i);
926                 if ((status >= 0) ||
927                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
928                     (status != NameServer_E_TIMEOUT))) {
929                     break;
930                 }
931             }
932         }
933     }
934     else {
935         /*
936          *  Search the query list. It might contain the local proc
937          *  somewhere in the list.
938          */
939         i = 0;
940         while (procId[i] != MultiProc_INVALIDID) {
941             if (procId[i] == MultiProc_self()) {
942                 status = NameServer_getLocal(handle, name, value, len);
943             }
944             else {
945                 status = NameServer_getRemote(handle, name, value, len, i);
946             }
948             if ((status >= 0) ||
949                 ((status < 0) && (status != NameServer_E_NOTFOUND)
950                 && (status != NameServer_E_TIMEOUT))) {
951                 break;
952             }
954             i++;
955         }
956     }
958     return (status);
961 /* Gets a 32-bit value by name */
962 Int NameServer_getUInt32(NameServer_Handle handle,
963                      String            name,
964                      Ptr               value,
965                      UInt16            procId[])
967     Int  status;
968     UInt32 len = sizeof(UInt32);
970     assert(handle != NULL);
971     assert(name   != NULL);
972     assert(value  != NULL);
973     assert(NameServer_module->refCount != 0);
975     status = NameServer_get(handle, name, value, &len, procId);
977     return (status);
980 /* Function to Retrieve the value portion of a name/value pair from
981  * local table.
982  */
983 Int NameServer_getLocal(NameServer_Handle handle,
984                     String            name,
985                     Ptr               value,
986                     UInt32 *          len)
988     Int status = NameServer_E_NOTFOUND;
989     NameServer_TableEntry * node = NULL;
990     NameServer_TableEntry * temp = NULL;
991     Bool done   = FALSE;
992     UInt32 length;
993     UInt32 hash;
995     assert(handle != NULL);
996     assert(name   != NULL);
997     assert(value  != NULL);
998     assert(len    != NULL);
999     assert(NameServer_module->refCount != 0);
1001     length = *len;
1003     /* Calculate the hash */
1004     hash = stringHash(name);
1006     pthread_mutex_lock(&handle->gate);
1008     /* Traverse the list to find duplicate check */
1009     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1010         if (node->hash == hash) {
1011             if (node->collide == TRUE) {
1012                 temp = node;
1013                 while (temp) {
1014                     if (strcmp(temp->name, name) == 0u){
1015                         if (length <= node->len) {
1016                             memcpy(value, node->value, length);
1017                             *len = length;
1018                         }
1019                         else {
1020                             memcpy(value, node->value, node->len);
1021                             *len = node->len;
1022                         }
1023                         done = TRUE;
1024                         break;
1025                     }
1026                     temp = temp->next;
1027                 }
1028                 break;
1029             }
1030             else {
1031                 if (length <= node->len) {
1032                     memcpy(value, node->value, length);
1033                     *len = length;
1034                 }
1035                 else {
1036                     memcpy(value, node->value, node->len);
1037                     *len = node->len;
1038                 }
1039                 done = TRUE;
1040                 break;
1041             }
1042         }
1043     }
1045     pthread_mutex_unlock(&handle->gate);
1047     if (done == FALSE) {
1048         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1049     }
1050     else {
1051         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1052              node->name, (UInt32)node->value)
1053         status = NameServer_S_SUCCESS;
1054     }
1056     return (status);
1059 /*
1060  *  Gets a 32-bit value by name from the local table
1061  *
1062  *  If the name is found, the 32-bit value is copied into the value
1063  *  argument and a success status is returned.
1064  *
1065  *  If the name is not found, zero is returned in len and the contents
1066  *  of value are not modified. Not finding a name is not considered
1067  *  an error.
1068  *
1069  *  This function only searches the local name/value table.
1070  *
1071  */
1072 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1074     Int                 status;
1075     UInt32              len    = sizeof(UInt32);
1077     assert(handle != NULL);
1078     assert(name   != NULL);
1079     assert(value  != NULL);
1080     assert(NameServer_module->refCount != 0);
1082     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1083     status = NameServer_getLocal(handle, name, value, &len);
1085     return (status);
1089 #if defined (__cplusplus)
1091 #endif /* defined (__cplusplus) */