3159feea17216b95a0daaff94ddd081cd1520134
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / utils / hlos / knl / NameServer_daemon.c
1 /*
2  * Copyright (c) 2012-2015, 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 <ti/ipc/namesrv/_NameServerRemoteRpmsg.h>
70 #include <_IpcLog.h>
72 #define MESSAGEQ_RPMSG_PORT       61
73 #define NAME_SERVER_RPMSG_ADDR    0
74 #define RPMSG_RESERVED_ADDRESSES  (1024)
76 #define INVALIDSOCKET     (-1)
78 #if defined (__cplusplus)
79 extern "C" {
80 #endif
83 /* =============================================================================
84  * Structures & Enums
85  * =============================================================================
86  */
88 /* Structure of entry in Name/Value table */
89 typedef struct NameServer_TableEntry_tag {
90     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
91     /* List element */
92     UInt32                    hash;
93     /* Hash value */
94     String                    name;
95     /* Name portion of the name/value pair. */
96     UInt                      len;
97     /* Length of the value field. */
98     Ptr                       value;
99     /* Value portion of the name/value entry. */
100     Bool                      collide;
101     /* Does the hash collide? */
102     struct NameServer_TableEntry_tag * next;
103     /* Pointer to the next entry, used incase of collision only */
104 } NameServer_TableEntry;
106 /* Structure defining object for the NameServer */
107 struct NameServer_Object {
108     CIRCLEQ_ENTRY(NameServer_Object) elem;
109     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
110     String             name;            /* name of the instance */
111     NameServer_Params  params;          /* the parameter structure */
112     UInt32             count;           /* count of entries */
113     UInt32             refCount;        /* reference count to this object */
114     pthread_mutex_t    gate;            /* crit sect gate */
115 } NameServer_Object;
117 /* structure for NameServer module state */
118 typedef struct NameServer_ModuleObject {
119     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
120     Int32                refCount;
121     MessageQCopy_Handle  mq;
122     /* MessageQCopy instance to receive from remote proc nameserver ports: */
123     UInt32               recvAddr;
124     /* Local endpoint for receiving from remote proc nameserver ports: */
125     pthread_t            listener;
126     /* Listener thread for NameServer replies and requests. */
127     int                  waitFdW;
128     int                  waitFdR;
129     /* Pipe to post to NameServer_get. */
130     NameServerRemote_Msg nsMsg;
131     /* NameServer Message cache. */
132     NameServer_Params    defInstParams;
133     /* Default instance paramters */
134     pthread_mutex_t      modGate;
135 } NameServer_ModuleObject;
137 #define CIRCLEQ_destruct(head) { \
138         (head)->cqh_first = NULL; \
139         (head)->cqh_last = NULL; \
142 #define CIRCLEQ_elemClear(elem) { \
143         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
146 #define CIRCLEQ_traverse(x, y, tag) \
147         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
149 /* =============================================================================
150  *  Globals
151  * =============================================================================
152  */
153 /*
154  * NameServer_state
155  *
156  * Make the module gate "recursive" since NameServer_getHandle() needs to
157  * use it and NameServer_create() needs to hold it around its call to
158  * NameServer_getHandle().  Also, use the static initializer instead of a
159  * run-time init call, so we can use this gate immediately in _setup().
160  */
161 static NameServer_ModuleObject NameServer_state = {
162     .defInstParams.maxRuntimeEntries = 0u,
163     .defInstParams.tableHeap         = NULL,
164     .defInstParams.checkExisting     = TRUE,
165     .defInstParams.maxValueLen       = 0u,
166     .defInstParams.maxNameLen        = 16u,
167 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
168     .modGate                         = PTHREAD_RMUTEX_INITIALIZER,
169     .refCount                        = 0
170 };
172 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
174 static const UInt32 stringCrcTab[256u] = {
175   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
176   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
177   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
178   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
179   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
180   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
181   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
182   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
183   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
184   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
185   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
186   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
187   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
188   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
189   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
190   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
191   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
192   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
193   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
194   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
195   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
196   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
197   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
198   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
199   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
200   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
201   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
202   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
203   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
204   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
205   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
206   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
207   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
208   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
209   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
210   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
211   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
212   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
213   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
214   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
215   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
216   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
217   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
218 };
220 static UInt32 stringHash(String s)
222     UInt32 hash = strlen(s);
223     UInt32 i;
225     for (i = 0; i < strlen(s); i++) {
226         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
227     }
229     return (hash);
232 static void NameServerRemote_processMessage(NameServerRemote_Msg * msg, UInt16 procId)
234     NameServer_Handle handle;
235     Int               status = NameServer_E_FAIL;
236     char              buf = 'n';
237     int               waitFd = NameServer_module->waitFdW;
239     if (msg->request == NAMESERVER_REQUEST) {
240         LOG2("NameServer Request: instanceName: %s, name: %s\n",
241              (String)msg->instanceName, (String)msg->name)
243         assert(msg->valueLen <= MAXVALUELEN);
245         /*
246          *  Message is a request. Lookup name in NameServer table.
247          *  Send a response message back to source processor.
248          */
249         handle = NameServer_getHandle((String)msg->instanceName);
251         if (handle != NULL) {
252             /* Search for the NameServer entry */
253             if (msg->valueLen <= sizeof (Bits32)) {
254                 LOG0("Calling NameServer_getLocalUInt32...\n")
255                 status = NameServer_getLocalUInt32(handle,
256                      (String)msg->name, &msg->value);
257             }
258             else {
259                 LOG0("Calling NameServer_getLocal...\n")
260                 status = NameServer_getLocal(handle,
261                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
262             }
263         }
265         LOG2("NameServer Response: instanceName: %s, name: %s,",
266              (String)msg->instanceName, (String)msg->name)
267         /* set the request status */
268         if (status < 0) {
269             LOG1(" Value not found, status: %d\n", status)
270             msg->requestStatus = 0;
271         }
272         else {
273             msg->requestStatus = 1;
274             LOG1(" Value: 0x%x\n", msg->value)
275         }
277         /* specify message as a response */
278         msg->request = NAMESERVER_RESPONSE;
279         msg->reserved = NAMESERVER_MSG_TOKEN;
281         /* send response message to remote processor */
282         status = MessageQCopy_send(procId, MultiProc_self(),
283             MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
284             sizeof(NameServerRemote_Msg), TRUE);
285         if (status < 0) {
286             LOG0("NameServer: MessageQCopy_send failed\n")
287         }
288     }
289     else {
290         LOG2("NameServer Reply: instanceName: %s, name: %s",
291              (String)msg->instanceName, (String)msg->name)
292         LOG1(", value: 0x%x\n", msg->value)
294         /* Save the response message.  */
295         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerRemote_Msg));
297         /* Post the eventfd upon which NameServer_get() is waiting */
298         write(waitFd, &buf, sizeof(buf));
299     }
302 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
303     void * priv, UInt32 src, UInt16 srcProc)
305     NameServerRemote_Msg msg;
307     LOG0("listener_cb: Entered Listener thread.\n")
309     LOG1("NameServer: Listener got NameServer message "
310          "from MessageQCopy: 0x%p!\n", handle);
311     /* Get NameServer message and process: */
312     memcpy(&msg, data, len);
314     if (len != sizeof(NameServerRemote_Msg)) {
315         LOG1("NameServer: got bad NameServerRemote_Msg len (%d)\n",
316             len)
317     }
318     else {
319         LOG1("listener_cb: read from MessageQCopy 0x%p\n", handle)
320         LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
321              len, src)
322         LOG1("from vproc: %d\n", srcProc)
323         NameServerRemote_processMessage(&msg, srcProc);
324     }
327 /* =============================================================================
328  * APIS
329  * =============================================================================
330  */
332 /* Function to setup the nameserver module. */
333 Int NameServer_setup(Void)
335     Int    status = NameServer_S_SUCCESS;
336     int    fd[2];
338     pthread_mutex_lock(&NameServer_module->modGate);
340     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
342     NameServer_module->refCount++;
344     if (NameServer_module->refCount > 1) {
345         LOG0("NameServer_setup: already setup\n")
346         status = NameServer_S_ALREADYSETUP;
347         goto exit;
348     }
350     if (pipe(fd) == -1) {
351         status = NameServer_E_FAIL;
352         LOG0("NameServer_setup: failed to create waitFd.\n")
353         goto exit;
354     }
355     NameServer_module->waitFdW = fd[1];
356     NameServer_module->waitFdR = fd[0];
358     /* Create the MessageQCopy for receiving messages from all remote proc */
359     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
360         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
362     if (NameServer_module->mq == NULL) {
363         status = NameServer_E_FAIL;
364         LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
365         goto exit;
366     }
368     /* Construct the list object */
369     CIRCLEQ_INIT(&NameServer_module->objList);
371 exit:
372     LOG1("NameServer_setup: exiting, refCount=%d\n", \
373         NameServer_module->refCount)
375     pthread_mutex_unlock(&NameServer_module->modGate);
377     return (status);
380 /*! Function to destroy the nameserver module. */
381 Int NameServer_destroy(void)
383     Int      status    = NameServer_S_SUCCESS;
385     pthread_mutex_lock(&NameServer_module->modGate);
387     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
389     NameServer_module->refCount--;
391     if (NameServer_module->refCount > 0) {
392         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
393         status = NameServer_S_SUCCESS;
395         goto exit;
396     }
398     /* Delete the MessageQCopy instances */
399     if (NameServer_module->mq != NULL) {
400         MessageQCopy_delete(&NameServer_module->mq);
401     }
403     CIRCLEQ_destruct(&NameServer_module->objList);
405     close(NameServer_module->waitFdW);
406     close(NameServer_module->waitFdR);
408 exit:
409     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
411     pthread_mutex_unlock(&NameServer_module->modGate);
413     return (status);
416 /* Function to retrieve a NameServer handle from name. */
417 NameServer_Handle NameServer_getHandle(String name)
419     NameServer_Handle handle = NULL;
420     Bool              found = FALSE;
421     struct NameServer_Object * elem;
423     assert(name != NULL);
424     assert(NameServer_module->refCount != 0);
426     pthread_mutex_lock(&NameServer_module->modGate);
428     /* Lookup handle from name: */
429     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
430         handle = (NameServer_Handle) elem;
431         if (strcmp(handle->name, name) == 0) {
432             found = TRUE;
433             break;
434         }
435     }
437     if (found == FALSE) {
438         handle = NULL;
439     }
441     pthread_mutex_unlock(&NameServer_module->modGate);
443     return (handle);
447 /* Function to create a name server. */
448 NameServer_Handle NameServer_create(String name,
449                                     const NameServer_Params * params)
451     NameServer_Handle handle = NULL;
452     pthread_mutexattr_t mutex_attr;
454     assert(params != NULL);
455     assert(name != NULL);
456     assert(NameServer_module->refCount != 0);
458     LOG1("NameServer_create(): '%s'\n", name)
460     pthread_mutex_lock(&NameServer_module->modGate);
462     /* check if the name is already created or not */
463     handle = NameServer_getHandle(name);
464     if (handle != NULL) {
465         if (memcmp((Ptr)&handle->params, (Ptr)params,
466             sizeof(NameServer_Params)) == 0) {
467             handle->refCount++;
468         }
469         else {
470             LOG0("NameServer_create: NameServer params mismatch\n")
471             handle = NULL;
472         }
473         goto leave;
474     }
475     else {
476         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
477     }
479     if (!handle) {
480         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
481         goto leave;
482     }
484     handle->refCount = 1;
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     (*handle)->refCount--;
542     if ((*handle)->refCount != 0) {
543         goto leave;
544     }
546     if ((*handle)->count == 0) {
547         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
549         if ((*handle)->name != NULL) {
550             free((*handle)->name);
551             (*handle)->name = NULL;
552         }
554         CIRCLEQ_destruct(&(*handle)->nameList);
556         pthread_mutex_destroy(&(*handle)->gate);
558         free((*handle));
559         (*handle) = NULL;
560     }
562 leave:
563     pthread_mutex_unlock(&NameServer_module->modGate);
565     return (status);
568 /* Adds a variable length value into the local NameServer table */
569 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
571     Int                 status = NameServer_S_SUCCESS;
572     NameServer_TableEntry * node = NULL;
573     NameServer_TableEntry * new_node = NULL;
574     Bool                found = FALSE;
575     UInt32              hash;
577     assert(handle != NULL);
578     assert(name     != NULL);
579     assert(buf      != NULL);
580     assert(len      != 0);
581     assert(NameServer_module->refCount != 0);
583     /* Calculate the hash */
584     hash = stringHash(name);
586     pthread_mutex_lock(&handle->gate);
588     if (strlen(name) > handle->params.maxNameLen - 1) {
589         status = NameServer_E_INVALIDARG;
590         LOG0("NameServer_add: name length exceeded maximum!\n")
591         new_node = NULL;
592         goto exit;
593     }
595     if (len > handle->params.maxValueLen) {
596         status = NameServer_E_INVALIDARG;
597         LOG0("NameServer_add: value length exceeded maximum!\n")
598         new_node = NULL;
599         goto exit;
600     }
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     NameServerRemote_Msg nsMsg;
802     NameServerRemote_Msg *replyMsg;
803     fd_set rfds;
804     int ret = 0, maxfd, waitFd;
805     struct timeval tv;
806     char buf = '1';
807     int numBytes;
808     static int seqNum = 0;
809     Bool done = FALSE;
811     if (strlen(name) >= MAXNAMEINCHAR) {
812         LOG0("Name is too long in remote query\n");
813         return NameServer_E_NAMETOOLONG;
814     }
816     if (strlen(obj->name) >= MAXNAMEINCHAR) {
817         LOG0("Instance name is too long for remote query\n");
818         return NameServer_E_NAMETOOLONG;
819     }
821     pthread_mutex_lock(&NameServer_module->modGate);
823     /* Set Timeout to wait: */
824     tv.tv_sec = 0;
825     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
827     /* Create request message and send to remote processor: */
828     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
829     nsMsg.request = NAMESERVER_REQUEST;
830     nsMsg.requestStatus = 0;
831     nsMsg.valueLen = *len;
832     nsMsg.seqNum = seqNum++;
834     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
835     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
837     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
838            procId, (String)nsMsg.instanceName)
839     LOG1("%s...\n", (String)nsMsg.name)
841     /* send message */
842     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
843             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerRemote_Msg),
844         TRUE);
845     if (mqcStatus < 0) {
846         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
847         status = NameServer_E_NOTFOUND;
848         goto exit;
849     }
851     while (!done) {
852         /* Block on waitFd for signal from listener thread: */
853         waitFd = NameServer_module->waitFdR;
854         FD_ZERO(&rfds);
855         FD_SET(waitFd, &rfds);
856         maxfd = waitFd + 1;
857         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
858         ret = select(maxfd, &rfds, NULL, NULL, &tv);
859         if (ret == -1) {
860             LOG0("NameServer_getRemote: select failed.")
861             status = NameServer_E_FAIL;
862             goto exit;
863         }
864         else if (!ret) {
865             LOG0("NameServer_getRemote: select timed out.\n")
866             status = NameServer_E_TIMEOUT;
867             goto exit;
868         }
870         if (FD_ISSET(waitFd, &rfds)) {
871             /* Read, just to balance the write: */
872             numBytes = read(waitFd, &buf, sizeof(buf));
873             if (numBytes == -1) {
874                 LOG0("NameServer_getRemote: read failure\n")
875                 status = NameServer_E_FAIL;
876                 goto exit;
877             }
879             /* Process response: */
880             replyMsg = &NameServer_module->nsMsg;
882             if (replyMsg->seqNum != seqNum - 1) {
883                 /* Ignore responses without current sequence # */
884                 continue;
885             }
887             if (replyMsg->requestStatus) {
888                 /* name is found */
890                 /* set length to amount of data that was copied */
891                 *len = replyMsg->valueLen;
893                 /* set the contents of value */
894                 if (*len <= sizeof (Bits32)) {
895                     *(UInt32 *)value = (UInt32)replyMsg->value;
896                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
897                         procId, (String)replyMsg->instanceName)
898                     LOG2("%s, value: 0x%x...\n",
899                         (String)replyMsg->name, *(UInt32 *)value)
900                 }
901                 else {
902                     memcpy(value, replyMsg->valueBuf, *len);
903                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
904                         procId, (String)replyMsg->instanceName)
905                     LOG2("%s, value buffer at address: 0x%p...\n",
906                         (String)replyMsg->name, value)
907                 }
909                 goto exit;
910             }
911             else {
912                 /* name is not found */
913                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
914                      (String)replyMsg->instanceName, (String)replyMsg->name)
916                 /* set status to not found */
917                 status = NameServer_E_NOTFOUND;
918             }
919         }
920         done = TRUE;
921     }
922 exit:
923     pthread_mutex_unlock(&NameServer_module->modGate);
925     return (status);
928 /* Function to retrieve the value portion of a name/value pair from
929  * local table.
930  */
931 Int NameServer_get(NameServer_Handle handle,
932                String            name,
933                Ptr               value,
934                UInt32 *          len,
935                UInt16            procId[])
937     Int status = NameServer_S_SUCCESS;
938     UInt16 numProcs = MultiProc_getNumProcessors();
939     UInt32 i;
941     if (procId == NULL) {
942         status = NameServer_getLocal(handle, name, value, len);
943         if (status == NameServer_E_NOTFOUND) {
944             for (i = 0; i < numProcs; i++) {
945                 /* getLocal call already covers "self", keep going */
946                 if (i == MultiProc_self()) {
947                     continue;
948                 }
950                 status = NameServer_getRemote(handle, name, value, len, i);
952                 if ((status >= 0) ||
953                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
954                     (status != NameServer_E_TIMEOUT))) {
955                     break;
956                 }
957             }
958         }
959     }
960     else {
961         /*
962          *  Search the query list. It might contain the local proc
963          *  somewhere in the list.
964          */
965         i = 0;
966         while (procId[i] != MultiProc_INVALIDID) {
967             if (procId[i] == MultiProc_self()) {
968                 status = NameServer_getLocal(handle, name, value, len);
969             }
970             else {
971                 status = NameServer_getRemote(handle, name, value, len, i);
972             }
974             if ((status >= 0) ||
975                 ((status < 0) && (status != NameServer_E_NOTFOUND)
976                 && (status != NameServer_E_TIMEOUT))) {
977                 break;
978             }
980             i++;
981         }
982     }
984     return (status);
987 /* Gets a 32-bit value by name */
988 Int NameServer_getUInt32(NameServer_Handle handle,
989                      String            name,
990                      Ptr               value,
991                      UInt16            procId[])
993     Int  status;
994     UInt32 len = sizeof(UInt32);
996     assert(handle != NULL);
997     assert(name   != NULL);
998     assert(value  != NULL);
999     assert(NameServer_module->refCount != 0);
1001     status = NameServer_get(handle, name, value, &len, procId);
1003     return (status);
1006 /* Function to Retrieve the value portion of a name/value pair from
1007  * local table.
1008  */
1009 Int NameServer_getLocal(NameServer_Handle handle,
1010                     String            name,
1011                     Ptr               value,
1012                     UInt32 *          len)
1014     Int status = NameServer_E_NOTFOUND;
1015     NameServer_TableEntry * node = NULL;
1016     NameServer_TableEntry * temp = NULL;
1017     Bool done   = FALSE;
1018     UInt32 length;
1019     UInt32 hash;
1021     assert(handle != NULL);
1022     assert(name   != NULL);
1023     assert(value  != NULL);
1024     assert(len    != NULL);
1025     assert(NameServer_module->refCount != 0);
1027     length = *len;
1029     /* Calculate the hash */
1030     hash = stringHash(name);
1032     pthread_mutex_lock(&handle->gate);
1034     /* Traverse the list to find duplicate check */
1035     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1036         if (node->hash == hash) {
1037             if (node->collide == TRUE) {
1038                 temp = node;
1039                 while (temp) {
1040                     if (strcmp(temp->name, name) == 0u){
1041                         if (length <= node->len) {
1042                             memcpy(value, node->value, length);
1043                             *len = length;
1044                         }
1045                         else {
1046                             memcpy(value, node->value, node->len);
1047                             *len = node->len;
1048                         }
1049                         done = TRUE;
1050                         break;
1051                     }
1052                     temp = temp->next;
1053                 }
1054                 break;
1055             }
1056             else {
1057                 if (length <= node->len) {
1058                     memcpy(value, node->value, length);
1059                     *len = length;
1060                 }
1061                 else {
1062                     memcpy(value, node->value, node->len);
1063                     *len = node->len;
1064                 }
1065                 done = TRUE;
1066                 break;
1067             }
1068         }
1069     }
1071     pthread_mutex_unlock(&handle->gate);
1073     if (done == FALSE) {
1074         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1075     }
1076     else {
1077         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1078              node->name, (UInt32)node->value)
1079         status = NameServer_S_SUCCESS;
1080     }
1082     return (status);
1085 /*
1086  *  Gets a 32-bit value by name from the local table
1087  *
1088  *  If the name is found, the 32-bit value is copied into the value
1089  *  argument and a success status is returned.
1090  *
1091  *  If the name is not found, zero is returned in len and the contents
1092  *  of value are not modified. Not finding a name is not considered
1093  *  an error.
1094  *
1095  *  This function only searches the local name/value table.
1096  *
1097  */
1098 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1100     Int                 status;
1101     UInt32              len    = sizeof(UInt32);
1103     assert(handle != NULL);
1104     assert(name   != NULL);
1105     assert(value  != NULL);
1106     assert(NameServer_module->refCount != 0);
1108     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1109     status = NameServer_getLocal(handle, name, value, &len);
1111     return (status);
1115 #if defined (__cplusplus)
1117 #endif /* defined (__cplusplus) */