GateMP: Introduce support for GateMP on 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     pthread_mutex_t    gate;            /* crit sect gate */
119 } NameServer_Object;
121 /* structure for NameServer module state */
122 typedef struct NameServer_ModuleObject {
123     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
124     Int32               refCount;
125     MessageQCopy_Handle mq;
126     /* MessageQCopy instance to receive from remote proc nameserver ports: */
127     UInt32              recvAddr;
128     /* Local endpoint for receiving from remote proc nameserver ports: */
129     pthread_t           listener;
130     /* Listener thread for NameServer replies and requests. */
131     int                 waitFdW;
132     int                 waitFdR;
133     /* Pipe to post to NameServer_get. */
134     NameServerMsg       nsMsg;
135     /* NameServer Message cache. */
136     NameServer_Params   defInstParams;
137     /* Default instance paramters */
138     pthread_mutex_t     modGate;
139 } NameServer_ModuleObject;
141 #define CIRCLEQ_destruct(head) { \
142         (head)->cqh_first = NULL; \
143         (head)->cqh_last = NULL; \
146 #define CIRCLEQ_elemClear(elem) { \
147         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
150 #define CIRCLEQ_traverse(x, y, tag) \
151         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
153 /* =============================================================================
154  *  Globals
155  * =============================================================================
156  */
157 /*
158  * NameServer_state
159  *
160  * Make the module gate "recursive" since NameServer_getHandle() needs to
161  * use it and NameServer_create() needs to hold it around its call to
162  * NameServer_getHandle().  Also, use the static initializer instead of a
163  * run-time init call, so we can use this gate immediately in _setup().
164  */
165 static NameServer_ModuleObject NameServer_state = {
166     .defInstParams.maxRuntimeEntries = 0u,
167     .defInstParams.tableHeap         = NULL,
168     .defInstParams.checkExisting     = TRUE,
169     .defInstParams.maxValueLen       = 0u,
170     .defInstParams.maxNameLen        = 16u,
171 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
172     .modGate                         = PTHREAD_RMUTEX_INITIALIZER,
173     .refCount                        = 0
174 };
176 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
178 static const UInt32 stringCrcTab[256u] = {
179   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
180   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
181   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
182   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
183   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
184   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
185   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
186   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
187   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
188   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
189   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
190   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
191   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
192   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
193   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
194   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
195   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
196   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
197   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
198   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
199   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
200   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
201   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
202   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
203   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
204   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
205   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
206   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
207   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
208   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
209   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
210   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
211   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
212   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
213   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
214   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
215   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
216   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
217   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
218   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
219   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
220   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
221   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
222 };
224 static UInt32 stringHash(String s)
226     UInt32 hash = strlen(s);
227     UInt32 i;
229     for (i = 0; i < strlen(s); i++) {
230         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
231     }
233     return (hash);
236 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
238     NameServer_Handle handle;
239     Int               status = NameServer_E_FAIL;
240     char              buf = 'n';
241     int               numBytes;
242     int               waitFd = NameServer_module->waitFdW;
244     if (msg->request == NAMESERVER_REQUEST) {
245         LOG2("NameServer Request: instanceName: %s, name: %s\n",
246              (String)msg->instanceName, (String)msg->name)
248         assert(msg->valueLen <= MAXVALUELEN);
250         /*
251          *  Message is a request. Lookup name in NameServer table.
252          *  Send a response message back to source processor.
253          */
254         handle = NameServer_getHandle((String)msg->instanceName);
256         if (handle != NULL) {
257             /* Search for the NameServer entry */
258             if (msg->valueLen <= sizeof (Bits32)) {
259                 LOG0("Calling NameServer_getLocalUInt32...\n")
260                 status = NameServer_getLocalUInt32(handle,
261                      (String)msg->name, &msg->value);
262             }
263             else {
264                 LOG0("Calling NameServer_getLocal...\n")
265                 status = NameServer_getLocal(handle,
266                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
267             }
268         }
270         LOG2("NameServer Response: instanceName: %s, name: %s,",
271              (String)msg->instanceName, (String)msg->name)
272         /* set the request status */
273         if (status < 0) {
274             LOG1(" Value not found, status: %d\n", status)
275             msg->requestStatus = 0;
276         }
277         else {
278             msg->requestStatus = 1;
279             LOG1(" Value: 0x%x\n", msg->value)
280         }
282         /* specify message as a response */
283         msg->request = NAMESERVER_RESPONSE;
284         msg->reserved = NAMESERVER_MSG_TOKEN;
286         /* send response message to remote processor */
287         status = MessageQCopy_send(procId, MultiProc_self(),
288             MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
289             sizeof(NameServerMsg), TRUE);
290         if (status < 0) {
291             LOG0("NameServer: MessageQCopy_send failed\n")
292         }
293     }
294     else {
295         LOG2("NameServer Reply: instanceName: %s, name: %s",
296              (String)msg->instanceName, (String)msg->name)
297         LOG1(", value: 0x%x\n", msg->value)
299         /* Save the response message.  */
300         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
302         /* Post the eventfd upon which NameServer_get() is waiting */
303         numBytes = write(waitFd, &buf, sizeof(buf));
304     }
307 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
308     void * priv, UInt32 src, UInt16 srcProc)
310     NameServerMsg msg;
312     LOG0("listener_cb: Entered Listener thread.\n")
314     LOG1("NameServer: Listener got NameServer message "
315          "from MessageQCopy: 0x%p!\n", handle);
316     /* Get NameServer message and process: */
317     memcpy(&msg, data, len);
319     if (len != sizeof(NameServerMsg)) {
320         LOG1("NameServer: got bad NameServerMsg len (%d)\n",
321             len)
322     }
323     else {
324         LOG1("listener_cb: read from MessageQCopy 0x%p\n", handle)
325         LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
326              len, src)
327         LOG1("from vproc: %d\n", srcProc)
328         NameServerRemote_processMessage(&msg, srcProc);
329     }
332 /* =============================================================================
333  * APIS
334  * =============================================================================
335  */
337 /* Function to setup the nameserver module. */
338 Int NameServer_setup(Void)
340     Int    status = NameServer_S_SUCCESS;
341     UInt16 numProcs;
342     int    fd[2];
344     pthread_mutex_lock(&NameServer_module->modGate);
346     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
348     NameServer_module->refCount++;
350     if (NameServer_module->refCount > 1) {
351         LOG0("NameServer_setup: already setup\n")
352         status = NameServer_S_ALREADYSETUP;
353         goto exit;
354     }
356     numProcs = MultiProc_getNumProcessors();
358     if (pipe(fd) == -1) {
359         status = NameServer_E_FAIL;
360         LOG0("NameServer_setup: failed to create waitFd.\n")
361         goto exit;
362     }
363     NameServer_module->waitFdW = fd[1];
364     NameServer_module->waitFdR = fd[0];
366     /* Create the MessageQCopy for receiving messages from all remote proc */
367     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
368         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
370     if (NameServer_module->mq == NULL) {
371         status = NameServer_E_FAIL;
372         LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
373         goto exit;
374     }
376     /* Construct the list object */
377     CIRCLEQ_INIT(&NameServer_module->objList);
379 exit:
380     LOG1("NameServer_setup: exiting, refCount=%d\n", \
381         NameServer_module->refCount)
383     pthread_mutex_unlock(&NameServer_module->modGate);
385     return (status);
388 /*! Function to destroy the nameserver module. */
389 Int NameServer_destroy(void)
391     Int      status    = NameServer_S_SUCCESS;
393     pthread_mutex_lock(&NameServer_module->modGate);
395     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
397     NameServer_module->refCount--;
399     if (NameServer_module->refCount > 0) {
400         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
401         status = NameServer_S_SUCCESS;
403         goto exit;
404     }
406     /* Delete the MessageQCopy instances */
407     if (NameServer_module->mq != NULL) {
408         MessageQCopy_delete(&NameServer_module->mq);
409     }
411     CIRCLEQ_destruct(&NameServer_module->objList);
413     close(NameServer_module->waitFdW);
414     close(NameServer_module->waitFdR);
416 exit:
417     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
419     pthread_mutex_unlock(&NameServer_module->modGate);
421     return (status);
424 /* Function to retrieve a NameServer handle from name. */
425 NameServer_Handle NameServer_getHandle(String name)
427     NameServer_Handle handle = NULL;
428     Bool              found = FALSE;
429     struct NameServer_Object * elem;
431     assert(name != NULL);
432     assert(NameServer_module->refCount != 0);
434     pthread_mutex_lock(&NameServer_module->modGate);
436     /* Lookup handle from name: */
437     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
438         handle = (NameServer_Handle) elem;
439         if (strcmp(handle->name, name) == 0) {
440             found = TRUE;
441             break;
442         }
443     }
445     if (found == FALSE) {
446         handle = NULL;
447     }
449     pthread_mutex_unlock(&NameServer_module->modGate);
451     return (handle);
455 /* Function to create a name server. */
456 NameServer_Handle NameServer_create(String name,
457                                     const NameServer_Params * params)
459     NameServer_Handle handle = NULL;
460     pthread_mutexattr_t mutex_attr;
462     assert(params != NULL);
463     assert(name != NULL);
464     assert(NameServer_module->refCount != 0);
466     LOG1("NameServer_create(): '%s'\n", name)
468     pthread_mutex_lock(&NameServer_module->modGate);
470     /* check if the name is already created or not */
471     if (NameServer_getHandle(name)) {
472         LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
473         handle = NULL;
474         goto leave;
475     }
476     else {
477         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
478     }
480     if (!handle) {
481         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
482         goto leave;
483     }
485     handle->name = (String)malloc(strlen(name) + 1u);
486     if (!handle->name) {
487         LOG0("NameServer_create: instance name alloc failed\n")
488         goto cleanup;
489     }
490     strncpy(handle->name, name, strlen (name) + 1u);
491     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
493     assert(params.maxValueLen <= MAXVALUELEN);
495     if (params->maxValueLen < sizeof(UInt32)) {
496         handle->params.maxValueLen = sizeof(UInt32);
497     }
498     else {
499         handle->params.maxValueLen = params->maxValueLen;
500     }
502     CIRCLEQ_INIT(&handle->nameList);
503     handle->count = 0u;
505     /* Put in the local list */
506     CIRCLEQ_elemClear(&handle->elem);
507     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
509     /*
510      * NameServer_removeEntry() enters gate and is called by
511      * NameServer_remove() while holding the gate.
512      */
513     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
514     pthread_mutex_init(&handle->gate, &mutex_attr);
516     goto leave;
518 cleanup:
519     free(handle);
520     handle = NULL;
522 leave:
523     pthread_mutex_unlock(&NameServer_module->modGate);
525     return (handle);
529 /* Function to delete a name server. */
530 Int NameServer_delete(NameServer_Handle * handle)
532     Int status = NameServer_S_SUCCESS;
534     assert(handle != NULL);
535     assert(*handle != NULL);
536     assert((*handle)->count == 0);
537     assert(NameServer_module->refCount != 0);
539     pthread_mutex_lock(&NameServer_module->modGate);
541     if ((*handle)->count == 0) {
542         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
544         if ((*handle)->name != NULL) {
545             free((*handle)->name);
546             (*handle)->name = NULL;
547         }
549         CIRCLEQ_destruct(&(*handle)->nameList);
551         free((*handle));
552         (*handle) = NULL;
553     }
555     pthread_mutex_unlock(&NameServer_module->modGate);
557     return (status);
560 /* Adds a variable length value into the local NameServer table */
561 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
563     Int                 status = NameServer_S_SUCCESS;
564     NameServer_TableEntry * node = NULL;
565     NameServer_TableEntry * new_node = NULL;
566     Bool                found = FALSE;
567     UInt32              hash;
569     assert(handle != NULL);
570     assert(name     != NULL);
571     assert(buf      != NULL);
572     assert(len      != 0);
573     assert(NameServer_module->refCount != 0);
575     /* Calculate the hash */
576     hash = stringHash(name);
578     if (len > handle->params.maxValueLen) {
579         status = NameServer_E_INVALIDARG;
580         LOG0("NameServer_add: value length exceeded maximum!\n")
581         new_node = NULL;
582         goto exit;
583     }
585     pthread_mutex_lock(&handle->gate);
587     /* Traverse the list to find duplicate check */
588     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
589         /* Hash matches */
590         if (node->hash == hash) {
591             /* If the name matches, incase hash is duplicate */
592             if (strcmp(node->name, name) == 0) {
593                 if (handle->params.checkExisting == TRUE) {
594                     status = NameServer_E_INVALIDARG;
595                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
596                     break;
597                 }
598             }
599             else {
600                 found = TRUE;
601                 break;
602             } /* name does not match */
603         } /* hash does not match */
604     } /* CIRCLEQ_traverse */
606     if (status != NameServer_S_SUCCESS) {
607         new_node = NULL;
608         goto exit;
609     }
611     /* Now add the new entry. */
612     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
613     if (new_node == NULL) {
614         status = NameServer_E_MEMORY;
615         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
617         goto exit;
618     }
620     new_node->hash    = hash;
621     new_node->collide = found; /* Indicate if there is a collision*/
622     new_node->len     = len;
623     new_node->next    = NULL;
624     new_node->name = (String)malloc(strlen(name) + 1u);
625     new_node->value  = (Ptr)malloc(len);
626     strncpy(new_node->name, name, strlen(name) + 1u);
627     memcpy((Ptr)new_node->value, (Ptr)buf, len);
629     if (found == TRUE) {
630         /* If hash is found, need to stitch the list to link the
631          * new node to the existing node with the same hash.
632          */
633         new_node->next = node->next;
634         node->next = new_node;
635     }
636     else {
637         /* put the new node into the list */
638         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
639     }
641     handle->count++;
643     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
644          name, *(UInt32 *)buf)
646 exit:
647     pthread_mutex_unlock(&handle->gate);
649     return (new_node);
653 /* Function to add a UInt32 value into a name server. */
654 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
656     Ptr entry = NULL;
658     assert(handle != NULL);
659     assert(name   != NULL);
660     assert(NameServer_module->refCount != 0);
662     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
664     return (entry);
667 /* Function to remove a name/value pair from a name server. */
668 Int NameServer_remove(NameServer_Handle handle, String name)
670     Int                 status = NameServer_S_SUCCESS;
671     NameServer_TableEntry *prev = NULL;
672     NameServer_TableEntry *temp = NULL;
673     NameServer_TableEntry *node = NULL;
674     Bool                done   = FALSE;
675     UInt32              hash;
677     assert(handle != NULL);
678     assert(name   != NULL);
679     assert(NameServer_module->refCount != 0);
681     /* Calculate the hash */
682     hash = stringHash(name);
684     pthread_mutex_lock(&handle->gate);
686     /* Traverse the list to find duplicate check */
687     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
688         /* Hash matchs */
689         if (node->hash == hash) {
690             if (node->collide == TRUE) {
691                 if (strcmp(node->name, name) == 0){
692                     free(node->value);
693                     free(node->name);
694                     memcpy((Ptr)node, (Ptr) node->next,
695                            sizeof(NameServer_TableEntry));
696                     node->next = node->next->next;
697                     free(node->next);
698                     handle->count--;
699                     done = TRUE;
700                     break;
701                 }
702                 else {
703                     prev = node;
704                     temp = node->next;
705                     while (temp) {
706                         if (strcmp(temp->name, name) == 0){
707                             free(temp->value);
708                             free(temp->name);
709                             prev->next = temp->next;
710                             free(temp);
711                             handle->count--;
712                             done = TRUE;
713                             break;
714                         }
715                         temp = temp->next;
716                     }
717                     break;
718                 }
719             }
720             else {
721                 NameServer_removeEntry(handle, (Ptr)node);
723                 done = TRUE;
724                 break;
725             }
726         }
727     }
729     if (done == FALSE) {
730         status = NameServer_E_INVALIDARG;
731         LOG1("NameServer_remove %d Entry not found!\n", status)
732     }
734     pthread_mutex_unlock(&handle->gate);
736     return (status);
739 /* Function to remove a name/value pair from a name server. */
740 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
742     Int  status = NameServer_S_SUCCESS;
743     NameServer_TableEntry * node;
745     assert(handle != NULL);
746     assert(entry  != NULL);
747     assert(NameServer_module->refCount != 0);
749     pthread_mutex_lock(&handle->gate);
751     node = (NameServer_TableEntry *)entry;
753     free(node->value);
754     free(node->name);
755     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
756     free(node);
757     handle->count--;
759     pthread_mutex_unlock(&handle->gate);
761     return (status);
765 /* Initialize this config-params structure with supplier-specified
766  * defaults before instance creation.
767  */
768 Void NameServer_Params_init(NameServer_Params * params)
770     assert(params != NULL);
772     memcpy(params, &(NameServer_module->defInstParams),
773            sizeof (NameServer_Params));
777 Int NameServer_getRemote(NameServer_Handle handle,
778                      String            name,
779                      Ptr               value,
780                      UInt32 *          len,
781                      UInt16            procId)
783     Int status = NameServer_S_SUCCESS;
784     Int mqcStatus = -1;
785     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
786     NameServerMsg nsMsg;
787     NameServerMsg *replyMsg;
788     fd_set rfds;
789     int ret = 0, maxfd, waitFd;
790     struct timeval tv;
791     char buf = '1';
792     int numBytes;
794     pthread_mutex_lock(&NameServer_module->modGate);
796     /* Set Timeout to wait: */
797     tv.tv_sec = NAMESERVER_GET_TIMEOUT;
798     tv.tv_usec = 0;
800     /* Create request message and send to remote processor: */
801     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
802     nsMsg.request = NAMESERVER_REQUEST;
803     nsMsg.requestStatus = 0;
804     nsMsg.valueLen = *len;
806     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
807     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
809     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
810            procId, (String)nsMsg.instanceName)
811     LOG1("%s...\n", (String)nsMsg.name)
812     /* send message */
813     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
814             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
815         TRUE);
816     if (mqcStatus < 0) {
817         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
818         status = NameServer_E_NOTFOUND;
819         goto exit;
820     }
822     /* Block on waitFd for signal from listener thread: */
823     waitFd = NameServer_module->waitFdR;
824     FD_ZERO(&rfds);
825     FD_SET(waitFd, &rfds);
826     maxfd = waitFd + 1;
827     LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
828     ret = select(maxfd, &rfds, NULL, NULL, &tv);
829     if (ret == -1) {
830         LOG0("NameServer_getRemote: select failed.")
831         status = NameServer_E_FAIL;
832         goto exit;
833     }
834     else if (!ret) {
835         LOG0("NameServer_getRemote: select timed out.\n")
836         status = NameServer_E_TIMEOUT;
837         goto exit;
838     }
840     if (FD_ISSET(waitFd, &rfds)) {
841         /* Read, just to balance the write: */
842         numBytes = read(waitFd, &buf, sizeof(buf));
844         /* Process response: */
845         replyMsg = &NameServer_module->nsMsg;
847         if (replyMsg->requestStatus) {
848             /* name is found */
850             /* set length to amount of data that was copied */
851             *len = replyMsg->valueLen;
853             /* set the contents of value */
854             if (*len <= sizeof (Bits32)) {
855                 *(UInt32 *)value = (UInt32)replyMsg->value;
856                 LOG2("NameServer_getRemote: Reply from: %d, %s:",
857                     procId, (String)replyMsg->instanceName)
858                 LOG2("%s, value: 0x%x...\n",
859                     (String)replyMsg->name, *(UInt32 *)value)
860             }
861             else {
862                 memcpy(value, replyMsg->valueBuf, *len);
863                 LOG2("NameServer_getRemote: Reply from: %d, %s:",
864                     procId, (String)replyMsg->instanceName)
865                 LOG2("%s, value buffer at address: 0x%p...\n",
866                     (String)replyMsg->name, value)
867             }
869             goto exit;
870         }
871         else {
872             /* name is not found */
873             LOG2("NameServer_getRemote: value for %s:%s not found.\n",
874                  (String)replyMsg->instanceName, (String)replyMsg->name)
876             /* set status to not found */
877             status = NameServer_E_NOTFOUND;
878         }
879     }
881 exit:
882     pthread_mutex_unlock(&NameServer_module->modGate);
884     return (status);
887 /* Function to retrieve the value portion of a name/value pair from
888  * local table.
889  */
890 Int NameServer_get(NameServer_Handle handle,
891                String            name,
892                Ptr               value,
893                UInt32 *          len,
894                UInt16            procId[])
896     Int status = NameServer_S_SUCCESS;
897     UInt16 numProcs = MultiProc_getNumProcessors();
898     UInt32 i;
900     if (procId == NULL) {
901         status = NameServer_getLocal(handle, name, value, len);
902         if (status == NameServer_E_NOTFOUND) {
903             for (i = 0; i < numProcs; i++) {
904                 /* getLocal call already covers "self", keep going */
905                 if (i == MultiProc_self()) {
906                     continue;
907                 }
909                 status = NameServer_getRemote(handle, name, value, len, i);
911                 if ((status >= 0) ||
912                     ((status < 0) && (status != NameServer_E_NOTFOUND))) {
913                     break;
914                 }
915             }
916         }
917     }
918     else {
919         /*
920          *  Search the query list. It might contain the local proc
921          *  somewhere in the list.
922          */
923         i = 0;
924         while (procId[i] != MultiProc_INVALIDID) {
925             if (procId[i] == MultiProc_self()) {
926                 status = NameServer_getLocal(handle, name, value, len);
927             }
928             else {
929                 status = NameServer_getRemote(handle, name, value, len, i);
930             }
932             if ((status >= 0) ||
933                 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
934                 break;
935             }
937             i++;
938         }
939     }
941     return (status);
944 /* Gets a 32-bit value by name */
945 Int NameServer_getUInt32(NameServer_Handle handle,
946                      String            name,
947                      Ptr               value,
948                      UInt16            procId[])
950     Int  status;
951     UInt32 len = sizeof(UInt32);
953     assert(handle != NULL);
954     assert(name   != NULL);
955     assert(value  != NULL);
956     assert(NameServer_module->refCount != 0);
958     status = NameServer_get(handle, name, value, &len, procId);
960     return (status);
963 /* Function to Retrieve the value portion of a name/value pair from
964  * local table.
965  */
966 Int NameServer_getLocal(NameServer_Handle handle,
967                     String            name,
968                     Ptr               value,
969                     UInt32 *          len)
971     Int status = NameServer_E_NOTFOUND;
972     NameServer_TableEntry * node = NULL;
973     NameServer_TableEntry * temp = NULL;
974     Bool done   = FALSE;
975     UInt32 length;
976     UInt32 hash;
978     assert(handle != NULL);
979     assert(name   != NULL);
980     assert(value  != NULL);
981     assert(len    != NULL);
982     assert(NameServer_module->refCount != 0);
984     length = *len;
986     /* Calculate the hash */
987     hash = stringHash(name);
989     pthread_mutex_lock(&handle->gate);
991     /* Traverse the list to find duplicate check */
992     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
993         if (node->hash == hash) {
994             if (node->collide == TRUE) {
995                 temp = node;
996                 while (temp) {
997                     if (strcmp(temp->name, name) == 0u){
998                         if (length <= node->len) {
999                             memcpy(value, node->value, length);
1000                             *len = length;
1001                         }
1002                         else {
1003                             memcpy(value, node->value, node->len);
1004                             *len = node->len;
1005                         }
1006                         done = TRUE;
1007                         break;
1008                     }
1009                     temp = temp->next;
1010                 }
1011                 break;
1012             }
1013             else {
1014                 if (length <= node->len) {
1015                     memcpy(value, node->value, length);
1016                     *len = length;
1017                 }
1018                 else {
1019                     memcpy(value, node->value, node->len);
1020                     *len = node->len;
1021                 }
1022                 done = TRUE;
1023                 break;
1024             }
1025         }
1026     }
1028     pthread_mutex_unlock(&handle->gate);
1030     if (done == FALSE) {
1031         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1032     }
1033     else {
1034         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1035              node->name, (UInt32)node->value)
1036         status = NameServer_S_SUCCESS;
1037     }
1039     return (status);
1042 /*
1043  *  Gets a 32-bit value by name from the local table
1044  *
1045  *  If the name is found, the 32-bit value is copied into the value
1046  *  argument and a success status is returned.
1047  *
1048  *  If the name is not found, zero is returned in len and the contents
1049  *  of value are not modified. Not finding a name is not considered
1050  *  an error.
1051  *
1052  *  This function only searches the local name/value table.
1053  *
1054  */
1055 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1057     Int                 status;
1058     UInt32              len    = sizeof(UInt32);
1060     assert(handle != NULL);
1061     assert(name   != NULL);
1062     assert(value  != NULL);
1063     assert(NameServer_module->refCount != 0);
1065     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1066     status = NameServer_getLocal(handle, name, value, &len);
1068     return (status);
1072 #if defined (__cplusplus)
1074 #endif /* defined (__cplusplus) */