b84cbd5c81edcb6b5c55c347d25afe0122d6b91b
[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.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         /*
249          *  Message is a request. Lookup name in NameServer table.
250          *  Send a response message back to source processor.
251          */
252         handle = NameServer_getHandle((String)msg->instanceName);
254         if (handle != NULL) {
255             /* Search for the NameServer entry */
256             LOG0("Calling NameServer_getLocalUInt32...\n")
257             status = NameServer_getLocalUInt32(handle,
258                      (String)msg->name, &msg->value);
259         }
261         LOG2("NameServer Response: instanceName: %s, name: %s,",
262              (String)msg->instanceName, (String)msg->name)
263         /* set the request status */
264         if (status < 0) {
265             LOG1(" Value not found, status: %d\n", status)
266             msg->requestStatus = 0;
267         }
268         else {
269             msg->requestStatus = 1;
270             LOG1(" Value: 0x%x\n", msg->value)
271         }
273         /* specify message as a response */
274         msg->request = NAMESERVER_RESPONSE;
275         msg->reserved = NAMESERVER_MSG_TOKEN;
277         /* send response message to remote processor */
278         status = MessageQCopy_send(procId, MultiProc_self(),
279             MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
280             sizeof(NameServerMsg), TRUE);
281         if (status < 0) {
282             LOG0("NameServer: MessageQCopy_send failed\n")
283         }
284     }
285     else {
286         LOG2("NameServer Reply: instanceName: %s, name: %s",
287              (String)msg->instanceName, (String)msg->name)
288         LOG1(", value: 0x%x\n", msg->value)
290         /* Save the response message.  */
291         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
293         /* Post the eventfd upon which NameServer_get() is waiting */
294         numBytes = write(waitFd, &buf, sizeof(buf));
295     }
298 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
299     void * priv, UInt32 src, UInt16 srcProc)
301     NameServerMsg msg;
303     LOG0("listener_cb: Entered Listener thread.\n")
305     LOG1("NameServer: Listener got NameServer message "
306          "from MessageQCopy: 0x%x!\n", handle);
307     /* Get NameServer message and process: */
308     memcpy(&msg, data, len);
310     if (len != sizeof(NameServerMsg)) {
311         LOG1("NameServer: got bad NameServerMsg len (%d)\n",
312             len)
313     }
314     else {
315         LOG1("listener_cb: read from MessageQCopy 0x%x\n", handle)
316         LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
317              len, src)
318         LOG1("from vproc: %d\n", srcProc)
319         NameServerRemote_processMessage(&msg, srcProc);
320     }
323 /* =============================================================================
324  * APIS
325  * =============================================================================
326  */
328 /* Function to setup the nameserver module. */
329 Int NameServer_setup(Void)
331     Int    status = NameServer_S_SUCCESS;
332     UInt16 numProcs;
333     int    fd[2];
335     pthread_mutex_lock(&NameServer_module->modGate);
337     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
339     NameServer_module->refCount++;
341     if (NameServer_module->refCount > 1) {
342         LOG0("NameServer_setup: already setup\n")
343         status = NameServer_S_ALREADYSETUP;
344         goto exit;
345     }
347     numProcs = MultiProc_getNumProcessors();
349     if (pipe(fd) == -1) {
350         status = NameServer_E_FAIL;
351         LOG0("NameServer_setup: failed to create waitFd.\n")
352         goto exit;
353     }
354     NameServer_module->waitFdW = fd[1];
355     NameServer_module->waitFdR = fd[0];
357     /* Create the MessageQCopy for receiving messages from all remote proc */
358     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
359         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
361     if (NameServer_module->mq == NULL) {
362         status = NameServer_E_FAIL;
363         LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
364         goto exit;
365     }
367     /* Construct the list object */
368     CIRCLEQ_INIT(&NameServer_module->objList);
370 exit:
371     LOG1("NameServer_setup: exiting, refCount=%d\n", \
372         NameServer_module->refCount)
374     pthread_mutex_unlock(&NameServer_module->modGate);
376     return (status);
379 /*! Function to destroy the nameserver module. */
380 Int NameServer_destroy(void)
382     Int      status    = NameServer_S_SUCCESS;
384     pthread_mutex_lock(&NameServer_module->modGate);
386     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
388     NameServer_module->refCount--;
390     if (NameServer_module->refCount > 0) {
391         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
392         status = NameServer_S_SUCCESS;
394         goto exit;
395     }
397     /* Delete the MessageQCopy instances */
398     if (NameServer_module->mq != NULL) {
399         MessageQCopy_delete(&NameServer_module->mq);
400     }
402     CIRCLEQ_destruct(&NameServer_module->objList);
404     close(NameServer_module->waitFdW);
405     close(NameServer_module->waitFdR);
407 exit:
408     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
410     pthread_mutex_unlock(&NameServer_module->modGate);
412     return (status);
415 /* Function to retrieve a NameServer handle from name. */
416 NameServer_Handle NameServer_getHandle(String name)
418     NameServer_Handle handle = NULL;
419     Bool              found = FALSE;
420     struct NameServer_Object * elem;
422     assert(name != NULL);
423     assert(NameServer_module->refCount != 0);
425     pthread_mutex_lock(&NameServer_module->modGate);
427     /* Lookup handle from name: */
428     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
429         handle = (NameServer_Handle) elem;
430         if (strcmp(handle->name, name) == 0) {
431             found = TRUE;
432             break;
433         }
434     }
436     if (found == FALSE) {
437         handle = NULL;
438     }
440     pthread_mutex_unlock(&NameServer_module->modGate);
442     return (handle);
446 /* Function to create a name server. */
447 NameServer_Handle NameServer_create(String name,
448                                     const NameServer_Params * params)
450     NameServer_Handle handle = NULL;
451     pthread_mutexattr_t mutex_attr;
453     assert(params != NULL);
454     assert(name != NULL);
455     assert(NameServer_module->refCount != 0);
457     LOG1("NameServer_create(): '%s'\n", name)
459     pthread_mutex_lock(&NameServer_module->modGate);
461     if (params->maxValueLen > sizeof(UInt32)) {
462         LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
463        /* Can't handle more than UInt32 at this time: */
464        goto leave;
465     }
467     /* check if the name is already created or not */
468     if (NameServer_getHandle(name)) {
469         LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
470         handle = NULL;
471         goto leave;
472     }
473     else {
474         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
475     }
477     if (!handle) {
478         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
479         goto leave;
480     }
482     handle->name = (String)malloc(strlen(name) + 1u);
483     if (!handle->name) {
484         LOG0("NameServer_create: instance name alloc failed\n")
485         goto cleanup;
486     }
487     strncpy(handle->name, name, strlen (name) + 1u);
488     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
490     if (params->maxValueLen < sizeof(UInt32)) {
491         handle->params.maxValueLen = sizeof(UInt32);
492     }
493     else {
494         handle->params.maxValueLen = params->maxValueLen;
495     }
497     CIRCLEQ_INIT(&handle->nameList);
498     handle->count = 0u;
500     /* Put in the local list */
501     CIRCLEQ_elemClear(&handle->elem);
502     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
504     /*
505      * NameServer_removeEntry() enters gate and is called by
506      * NameServer_remove() while holding the gate.
507      */
508     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
509     pthread_mutex_init(&handle->gate, &mutex_attr);
511     goto leave;
513 cleanup:
514     free(handle);
515     handle = NULL;
517 leave:
518     pthread_mutex_unlock(&NameServer_module->modGate);
520     return (handle);
524 /* Function to delete a name server. */
525 Int NameServer_delete(NameServer_Handle * handle)
527     Int status = NameServer_S_SUCCESS;
529     assert(handle != NULL);
530     assert(*handle != NULL);
531     assert((*handle)->count == 0);
532     assert(NameServer_module->refCount != 0);
534     pthread_mutex_lock(&NameServer_module->modGate);
536     if ((*handle)->count == 0) {
537         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
539         if ((*handle)->name != NULL) {
540             free((*handle)->name);
541             (*handle)->name = NULL;
542         }
544         CIRCLEQ_destruct(&(*handle)->nameList);
546         free((*handle));
547         (*handle) = NULL;
548     }
550     pthread_mutex_unlock(&NameServer_module->modGate);
552     return (status);
555 /* Adds a variable length value into the local NameServer table */
556 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
558     Int                 status = NameServer_S_SUCCESS;
559     NameServer_TableEntry * node = NULL;
560     NameServer_TableEntry * new_node = NULL;
561     Bool                found = FALSE;
562     UInt32              hash;
564     assert(handle != NULL);
565     assert(name     != NULL);
566     assert(buf      != NULL);
567     assert(len      != 0);
568     assert(NameServer_module->refCount != 0);
570     /* Calculate the hash */
571     hash = stringHash(name);
573     pthread_mutex_lock(&handle->gate);
575     /* Traverse the list to find duplicate check */
576     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
577         /* Hash matches */
578         if (node->hash == hash) {
579             /* If the name matches, incase hash is duplicate */
580             if (strcmp(node->name, name) == 0) {
581                 if (handle->params.checkExisting == TRUE) {
582                     status = NameServer_E_INVALIDARG;
583                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
584                     break;
585                 }
586             }
587             else {
588                 found = TRUE;
589                 break;
590             } /* name does not match */
591         } /* hash does not match */
592     } /* CIRCLEQ_traverse */
594     if (status != NameServer_S_SUCCESS) {
595         new_node = NULL;
596         goto exit;
597     }
599     /* Now add the new entry. */
600     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
601     if (new_node == NULL) {
602         status = NameServer_E_MEMORY;
603         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
605         goto exit;
606     }
608     new_node->hash    = hash;
609     new_node->collide = found; /* Indicate if there is a collision*/
610     new_node->len     = len;
611     new_node->next    = NULL;
612     new_node->name = (String)malloc(strlen(name) + 1u);
613     new_node->value  = (Ptr)malloc(len);
614     strncpy(new_node->name, name, strlen(name) + 1u);
615     memcpy((Ptr)new_node->value, (Ptr)buf, len);
617     if (found == TRUE) {
618         /* If hash is found, need to stitch the list to link the
619          * new node to the existing node with the same hash.
620          */
621         new_node->next = node->next;
622         node->next = new_node;
623     }
624     else {
625         /* put the new node into the list */
626         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
627     }
629     handle->count++;
631     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
632          name, *(UInt32 *)buf)
634 exit:
635     pthread_mutex_unlock(&handle->gate);
637     return (new_node);
641 /* Function to add a UInt32 value into a name server. */
642 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
644     Ptr entry = NULL;
646     assert(handle != NULL);
647     assert(name   != NULL);
648     assert(NameServer_module->refCount != 0);
650     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
652     return (entry);
655 /* Function to remove a name/value pair from a name server. */
656 Int NameServer_remove(NameServer_Handle handle, String name)
658     Int                 status = NameServer_S_SUCCESS;
659     NameServer_TableEntry *prev = NULL;
660     NameServer_TableEntry *temp = NULL;
661     NameServer_TableEntry *node = NULL;
662     Bool                done   = FALSE;
663     UInt32              hash;
665     assert(handle != NULL);
666     assert(name   != NULL);
667     assert(NameServer_module->refCount != 0);
669     /* Calculate the hash */
670     hash = stringHash(name);
672     pthread_mutex_lock(&handle->gate);
674     /* Traverse the list to find duplicate check */
675     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
676         /* Hash matchs */
677         if (node->hash == hash) {
678             if (node->collide == TRUE) {
679                 if (strcmp(node->name, name) == 0){
680                     free(node->value);
681                     free(node->name);
682                     memcpy((Ptr)node, (Ptr) node->next,
683                            sizeof(NameServer_TableEntry));
684                     node->next = node->next->next;
685                     free(node->next);
686                     handle->count--;
687                     done = TRUE;
688                     break;
689                 }
690                 else {
691                     prev = node;
692                     temp = node->next;
693                     while (temp) {
694                         if (strcmp(temp->name, name) == 0){
695                             free(temp->value);
696                             free(temp->name);
697                             prev->next = temp->next;
698                             free(temp);
699                             handle->count--;
700                             done = TRUE;
701                             break;
702                         }
703                         temp = temp->next;
704                     }
705                     break;
706                 }
707             }
708             else {
709                 NameServer_removeEntry(handle, (Ptr)node);
711                 done = TRUE;
712                 break;
713             }
714         }
715     }
717     if (done == FALSE) {
718         status = NameServer_E_INVALIDARG;
719         LOG1("NameServer_remove %d Entry not found!\n", status)
720     }
722     pthread_mutex_unlock(&handle->gate);
724     return (status);
727 /* Function to remove a name/value pair from a name server. */
728 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
730     Int  status = NameServer_S_SUCCESS;
731     NameServer_TableEntry * node;
733     assert(handle != NULL);
734     assert(entry  != NULL);
735     assert(NameServer_module->refCount != 0);
737     pthread_mutex_lock(&handle->gate);
739     node = (NameServer_TableEntry *)entry;
741     free(node->value);
742     free(node->name);
743     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
744     free(node);
745     handle->count--;
747     pthread_mutex_unlock(&handle->gate);
749     return (status);
753 /* Initialize this config-params structure with supplier-specified
754  * defaults before instance creation.
755  */
756 Void NameServer_Params_init(NameServer_Params * params)
758     assert(params != NULL);
760     memcpy(params, &(NameServer_module->defInstParams),
761            sizeof (NameServer_Params));
765 Int NameServer_getRemote(NameServer_Handle handle,
766                      String            name,
767                      Ptr               value,
768                      UInt32 *          len,
769                      UInt16            procId)
771     Int status = NameServer_S_SUCCESS;
772     Int mqcStatus = -1;
773     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
774     NameServerMsg nsMsg;
775     NameServerMsg *replyMsg;
776     fd_set rfds;
777     int ret = 0, maxfd, waitFd;
778     struct timeval tv;
779     char buf = '1';
780     int numBytes;
782     pthread_mutex_lock(&NameServer_module->modGate);
784     /* Set Timeout to wait: */
785     tv.tv_sec = NAMESERVER_GET_TIMEOUT;
786     tv.tv_usec = 0;
788     /* Create request message and send to remote processor: */
789     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
790     nsMsg.request = NAMESERVER_REQUEST;
791     nsMsg.requestStatus = 0;
793     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
794     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
796     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
797            procId, (String)nsMsg.instanceName)
798     LOG1("%s...\n", (String)nsMsg.name)
799     /* send message */
800     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
801             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
802         TRUE);
803     if (mqcStatus < 0) {
804         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
805         status = NameServer_E_NOTFOUND;
806         goto exit;
807     }
809     /* Block on waitFd for signal from listener thread: */
810     waitFd = NameServer_module->waitFdR;
811     FD_ZERO(&rfds);
812     FD_SET(waitFd, &rfds);
813     maxfd = waitFd + 1;
814     LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
815     ret = select(maxfd, &rfds, NULL, NULL, &tv);
816     if (ret == -1) {
817         LOG0("NameServer_getRemote: select failed.")
818         status = NameServer_E_FAIL;
819         goto exit;
820     }
821     else if (!ret) {
822         LOG0("NameServer_getRemote: select timed out.\n")
823         status = NameServer_E_TIMEOUT;
824         goto exit;
825     }
827     if (FD_ISSET(waitFd, &rfds)) {
828         /* Read, just to balance the write: */
829         numBytes = read(waitFd, &buf, sizeof(buf));
831         /* Process response: */
832         replyMsg = &NameServer_module->nsMsg;
834         if (replyMsg->requestStatus) {
835             /* name is found */
836             /* set the contents of value */
837             *(UInt32 *)value = (UInt32)replyMsg->value;
839             LOG2("NameServer_getRemote: Reply from: %d, %s:",
840                  procId, (String)replyMsg->instanceName)
841             LOG2("%s, value: 0x%x...\n",
842                  (String)replyMsg->name, *(UInt32 *)value)
843             goto exit;
844         }
845         else {
846             /* name is not found */
847             LOG2("NameServer_getRemote: value for %s:%s not found.\n",
848                  (String)replyMsg->instanceName, (String)replyMsg->name)
850             /* set status to not found */
851             status = NameServer_E_NOTFOUND;
852         }
853     }
855 exit:
856     pthread_mutex_unlock(&NameServer_module->modGate);
858     return (status);
861 /* Function to retrieve the value portion of a name/value pair from
862  * local table.
863  */
864 Int NameServer_get(NameServer_Handle handle,
865                String            name,
866                Ptr               value,
867                UInt32 *          len,
868                UInt16            procId[])
870     Int status = NameServer_S_SUCCESS;
871     UInt16 numProcs = MultiProc_getNumProcessors();
872     UInt32 i;
874     if (procId == NULL) {
875         status = NameServer_getLocal(handle, name, value, len);
876         if (status == NameServer_E_NOTFOUND) {
877             for (i = 0; i < numProcs; i++) {
878                 /* getLocal call already covers "self", keep going */
879                 if (i == MultiProc_self()) {
880                     continue;
881                 }
883                 status = NameServer_getRemote(handle, name, value, len, i);
885                 if ((status >= 0) ||
886                     ((status < 0) && (status != NameServer_E_NOTFOUND))) {
887                     break;
888                 }
889             }
890         }
891     }
892     else {
893         /*
894          *  Search the query list. It might contain the local proc
895          *  somewhere in the list.
896          */
897         i = 0;
898         while (procId[i] != MultiProc_INVALIDID) {
899             if (procId[i] == MultiProc_self()) {
900                 status = NameServer_getLocal(handle, name, value, len);
901             }
902             else {
903                 status = NameServer_getRemote(handle, name, value, len, i);
904             }
906             if ((status >= 0) ||
907                 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
908                 break;
909             }
911             i++;
912         }
913     }
915     return (status);
918 /* Gets a 32-bit value by name */
919 Int NameServer_getUInt32(NameServer_Handle handle,
920                      String            name,
921                      Ptr               value,
922                      UInt16            procId[])
924     Int  status;
925     UInt32 len = sizeof(UInt32);
927     assert(handle != NULL);
928     assert(name   != NULL);
929     assert(value  != NULL);
930     assert(NameServer_module->refCount != 0);
932     status = NameServer_get(handle, name, value, &len, procId);
934     return (status);
937 /* Function to Retrieve the value portion of a name/value pair from
938  * local table.
939  */
940 Int NameServer_getLocal(NameServer_Handle handle,
941                     String            name,
942                     Ptr               value,
943                     UInt32 *          len)
945     Int status = NameServer_E_NOTFOUND;
946     NameServer_TableEntry * node = NULL;
947     NameServer_TableEntry * temp = NULL;
948     Bool done   = FALSE;
949     UInt32 length;
950     UInt32 hash;
952     assert(handle != NULL);
953     assert(name   != NULL);
954     assert(value  != NULL);
955     assert(len    != NULL);
956     assert(NameServer_module->refCount != 0);
958     length = *len;
960     /* Calculate the hash */
961     hash = stringHash(name);
963     pthread_mutex_lock(&handle->gate);
965     /* Traverse the list to find duplicate check */
966     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
967         if (node->hash == hash) {
968             if (node->collide == TRUE) {
969                 temp = node;
970                 while (temp) {
971                     if (strcmp(temp->name, name) == 0u){
972                         if (length <= node->len) {
973                             memcpy(value, node->value, length);
974                             *len = length;
975                         }
976                         else {
977                             memcpy(value, node->value, node->len);
978                             *len = node->len;
979                         }
980                         done = TRUE;
981                         break;
982                     }
983                     temp = temp->next;
984                 }
985                 break;
986             }
987             else {
988                 if (length <= node->len) {
989                     memcpy(value, node->value, length);
990                     *len = length;
991                 }
992                 else {
993                     memcpy(value, node->value, node->len);
994                     *len = node->len;
995                 }
996                 done = TRUE;
997                 break;
998             }
999         }
1000     }
1002     pthread_mutex_unlock(&handle->gate);
1004     if (done == FALSE) {
1005         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1006     }
1007     else {
1008         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1009              node->name, (UInt32)node->value)
1010         status = NameServer_S_SUCCESS;
1011     }
1013     return (status);
1016 /*
1017  *  Gets a 32-bit value by name from the local table
1018  *
1019  *  If the name is found, the 32-bit value is copied into the value
1020  *  argument and a success status is returned.
1021  *
1022  *  If the name is not found, zero is returned in len and the contents
1023  *  of value are not modified. Not finding a name is not considered
1024  *  an error.
1025  *
1026  *  This function only searches the local name/value table.
1027  *
1028  */
1029 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1031     Int                 status;
1032     UInt32              len    = sizeof(UInt32);
1034     assert(handle != NULL);
1035     assert(name   != NULL);
1036     assert(value  != NULL);
1037     assert(NameServer_module->refCount != 0);
1039     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1040     status = NameServer_getLocal(handle, name, value, &len);
1042     return (status);
1046 #if defined (__cplusplus)
1048 #endif /* defined (__cplusplus) */