Turn TiIpcFxns.h into a public header for QNX
[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         free((*handle));
557         (*handle) = NULL;
558     }
560 leave:
561     pthread_mutex_unlock(&NameServer_module->modGate);
563     return (status);
566 /* Adds a variable length value into the local NameServer table */
567 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
569     Int                 status = NameServer_S_SUCCESS;
570     NameServer_TableEntry * node = NULL;
571     NameServer_TableEntry * new_node = NULL;
572     Bool                found = FALSE;
573     UInt32              hash;
575     assert(handle != NULL);
576     assert(name     != NULL);
577     assert(buf      != NULL);
578     assert(len      != 0);
579     assert(NameServer_module->refCount != 0);
581     /* Calculate the hash */
582     hash = stringHash(name);
584     pthread_mutex_lock(&handle->gate);
586     if (strlen(name) > handle->params.maxNameLen - 1) {
587         status = NameServer_E_INVALIDARG;
588         LOG0("NameServer_add: name length exceeded maximum!\n")
589         new_node = NULL;
590         goto exit;
591     }
593     if (len > handle->params.maxValueLen) {
594         status = NameServer_E_INVALIDARG;
595         LOG0("NameServer_add: value length exceeded maximum!\n")
596         new_node = NULL;
597         goto exit;
598     }
600     /* Traverse the list to find duplicate check */
601     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
602         /* Hash matches */
603         if (node->hash == hash) {
604             /* If the name matches, incase hash is duplicate */
605             if (strcmp(node->name, name) == 0) {
606                 if (handle->params.checkExisting == TRUE) {
607                     status = NameServer_E_INVALIDARG;
608                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
609                     break;
610                 }
611             }
612             else {
613                 found = TRUE;
614                 break;
615             } /* name does not match */
616         } /* hash does not match */
617     } /* CIRCLEQ_traverse */
619     if (status != NameServer_S_SUCCESS) {
620         new_node = NULL;
621         goto exit;
622     }
624     /* Now add the new entry. */
625     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
626     if (new_node == NULL) {
627         status = NameServer_E_MEMORY;
628         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
630         goto exit;
631     }
633     new_node->hash    = hash;
634     new_node->collide = found; /* Indicate if there is a collision*/
635     new_node->len     = len;
636     new_node->next    = NULL;
637     new_node->name = (String)malloc(strlen(name) + 1u);
638     new_node->value  = (Ptr)malloc(len);
639     strncpy(new_node->name, name, strlen(name) + 1u);
640     memcpy((Ptr)new_node->value, (Ptr)buf, len);
642     if (found == TRUE) {
643         /* If hash is found, need to stitch the list to link the
644          * new node to the existing node with the same hash.
645          */
646         new_node->next = node->next;
647         node->next = new_node;
648     }
649     else {
650         /* put the new node into the list */
651         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
652     }
654     handle->count++;
656     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
657          name, *(UInt32 *)buf)
659 exit:
660     pthread_mutex_unlock(&handle->gate);
662     return (new_node);
666 /* Function to add a UInt32 value into a name server. */
667 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
669     Ptr entry = NULL;
671     assert(handle != NULL);
672     assert(name   != NULL);
673     assert(NameServer_module->refCount != 0);
675     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
677     return (entry);
680 /* Function to remove a name/value pair from a name server. */
681 Int NameServer_remove(NameServer_Handle handle, String name)
683     Int                 status = NameServer_S_SUCCESS;
684     NameServer_TableEntry *prev = NULL;
685     NameServer_TableEntry *temp = NULL;
686     NameServer_TableEntry *node = NULL;
687     Bool                done   = FALSE;
688     UInt32              hash;
690     assert(handle != NULL);
691     assert(name   != NULL);
692     assert(NameServer_module->refCount != 0);
694     /* Calculate the hash */
695     hash = stringHash(name);
697     pthread_mutex_lock(&handle->gate);
699     /* Traverse the list to find duplicate check */
700     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
701         /* Hash matchs */
702         if (node->hash == hash) {
703             if (node->collide == TRUE) {
704                 if (strcmp(node->name, name) == 0){
705                     free(node->value);
706                     free(node->name);
707                     memcpy((Ptr)node, (Ptr) node->next,
708                            sizeof(NameServer_TableEntry));
709                     node->next = node->next->next;
710                     free(node->next);
711                     handle->count--;
712                     done = TRUE;
713                     break;
714                 }
715                 else {
716                     prev = node;
717                     temp = node->next;
718                     while (temp) {
719                         if (strcmp(temp->name, name) == 0){
720                             free(temp->value);
721                             free(temp->name);
722                             prev->next = temp->next;
723                             free(temp);
724                             handle->count--;
725                             done = TRUE;
726                             break;
727                         }
728                         temp = temp->next;
729                     }
730                     break;
731                 }
732             }
733             else {
734                 NameServer_removeEntry(handle, (Ptr)node);
736                 done = TRUE;
737                 break;
738             }
739         }
740     }
742     if (done == FALSE) {
743         status = NameServer_E_INVALIDARG;
744         LOG1("NameServer_remove %d Entry not found!\n", status)
745     }
747     pthread_mutex_unlock(&handle->gate);
749     return (status);
752 /* Function to remove a name/value pair from a name server. */
753 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
755     Int  status = NameServer_S_SUCCESS;
756     NameServer_TableEntry * node;
758     assert(handle != NULL);
759     assert(entry  != NULL);
760     assert(NameServer_module->refCount != 0);
762     pthread_mutex_lock(&handle->gate);
764     node = (NameServer_TableEntry *)entry;
766     free(node->value);
767     free(node->name);
768     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
769     free(node);
770     handle->count--;
772     pthread_mutex_unlock(&handle->gate);
774     return (status);
778 /* Initialize this config-params structure with supplier-specified
779  * defaults before instance creation.
780  */
781 Void NameServer_Params_init(NameServer_Params * params)
783     assert(params != NULL);
785     memcpy(params, &(NameServer_module->defInstParams),
786            sizeof (NameServer_Params));
790 Int NameServer_getRemote(NameServer_Handle handle,
791                      String            name,
792                      Ptr               value,
793                      UInt32 *          len,
794                      UInt16            procId)
796     Int status = NameServer_S_SUCCESS;
797     Int mqcStatus = -1;
798     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
799     NameServerRemote_Msg nsMsg;
800     NameServerRemote_Msg *replyMsg;
801     fd_set rfds;
802     int ret = 0, maxfd, waitFd;
803     struct timeval tv;
804     char buf = '1';
805     int numBytes;
806     static int seqNum = 0;
807     Bool done = FALSE;
809     if (strlen(name) >= MAXNAMEINCHAR) {
810         LOG0("Name is too long in remote query\n");
811         return NameServer_E_NAMETOOLONG;
812     }
814     if (strlen(obj->name) >= MAXNAMEINCHAR) {
815         LOG0("Instance name is too long for remote query\n");
816         return NameServer_E_NAMETOOLONG;
817     }
819     pthread_mutex_lock(&NameServer_module->modGate);
821     /* Set Timeout to wait: */
822     tv.tv_sec = 0;
823     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
825     /* Create request message and send to remote processor: */
826     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
827     nsMsg.request = NAMESERVER_REQUEST;
828     nsMsg.requestStatus = 0;
829     nsMsg.valueLen = *len;
830     nsMsg.seqNum = seqNum++;
832     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
833     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
835     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
836            procId, (String)nsMsg.instanceName)
837     LOG1("%s...\n", (String)nsMsg.name)
839     /* send message */
840     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
841             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerRemote_Msg),
842         TRUE);
843     if (mqcStatus < 0) {
844         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
845         status = NameServer_E_NOTFOUND;
846         goto exit;
847     }
849     while (!done) {
850         /* Block on waitFd for signal from listener thread: */
851         waitFd = NameServer_module->waitFdR;
852         FD_ZERO(&rfds);
853         FD_SET(waitFd, &rfds);
854         maxfd = waitFd + 1;
855         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
856         ret = select(maxfd, &rfds, NULL, NULL, &tv);
857         if (ret == -1) {
858             LOG0("NameServer_getRemote: select failed.")
859             status = NameServer_E_FAIL;
860             goto exit;
861         }
862         else if (!ret) {
863             LOG0("NameServer_getRemote: select timed out.\n")
864             status = NameServer_E_TIMEOUT;
865             goto exit;
866         }
868         if (FD_ISSET(waitFd, &rfds)) {
869             /* Read, just to balance the write: */
870             numBytes = read(waitFd, &buf, sizeof(buf));
871             if (numBytes == -1) {
872                 LOG0("NameServer_getRemote: read failure\n")
873                 status = NameServer_E_FAIL;
874                 goto exit;
875             }
877             /* Process response: */
878             replyMsg = &NameServer_module->nsMsg;
880             if (replyMsg->seqNum != seqNum - 1) {
881                 /* Ignore responses without current sequence # */
882                 continue;
883             }
885             if (replyMsg->requestStatus) {
886                 /* name is found */
888                 /* set length to amount of data that was copied */
889                 *len = replyMsg->valueLen;
891                 /* set the contents of value */
892                 if (*len <= sizeof (Bits32)) {
893                     *(UInt32 *)value = (UInt32)replyMsg->value;
894                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
895                         procId, (String)replyMsg->instanceName)
896                     LOG2("%s, value: 0x%x...\n",
897                         (String)replyMsg->name, *(UInt32 *)value)
898                 }
899                 else {
900                     memcpy(value, replyMsg->valueBuf, *len);
901                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
902                         procId, (String)replyMsg->instanceName)
903                     LOG2("%s, value buffer at address: 0x%p...\n",
904                         (String)replyMsg->name, value)
905                 }
907                 goto exit;
908             }
909             else {
910                 /* name is not found */
911                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
912                      (String)replyMsg->instanceName, (String)replyMsg->name)
914                 /* set status to not found */
915                 status = NameServer_E_NOTFOUND;
916             }
917         }
918         done = TRUE;
919     }
920 exit:
921     pthread_mutex_unlock(&NameServer_module->modGate);
923     return (status);
926 /* Function to retrieve the value portion of a name/value pair from
927  * local table.
928  */
929 Int NameServer_get(NameServer_Handle handle,
930                String            name,
931                Ptr               value,
932                UInt32 *          len,
933                UInt16            procId[])
935     Int status = NameServer_S_SUCCESS;
936     UInt16 numProcs = MultiProc_getNumProcessors();
937     UInt32 i;
939     if (procId == NULL) {
940         status = NameServer_getLocal(handle, name, value, len);
941         if (status == NameServer_E_NOTFOUND) {
942             for (i = 0; i < numProcs; i++) {
943                 /* getLocal call already covers "self", keep going */
944                 if (i == MultiProc_self()) {
945                     continue;
946                 }
948                 status = NameServer_getRemote(handle, name, value, len, i);
950                 if ((status >= 0) ||
951                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
952                     (status != NameServer_E_TIMEOUT))) {
953                     break;
954                 }
955             }
956         }
957     }
958     else {
959         /*
960          *  Search the query list. It might contain the local proc
961          *  somewhere in the list.
962          */
963         i = 0;
964         while (procId[i] != MultiProc_INVALIDID) {
965             if (procId[i] == MultiProc_self()) {
966                 status = NameServer_getLocal(handle, name, value, len);
967             }
968             else {
969                 status = NameServer_getRemote(handle, name, value, len, i);
970             }
972             if ((status >= 0) ||
973                 ((status < 0) && (status != NameServer_E_NOTFOUND)
974                 && (status != NameServer_E_TIMEOUT))) {
975                 break;
976             }
978             i++;
979         }
980     }
982     return (status);
985 /* Gets a 32-bit value by name */
986 Int NameServer_getUInt32(NameServer_Handle handle,
987                      String            name,
988                      Ptr               value,
989                      UInt16            procId[])
991     Int  status;
992     UInt32 len = sizeof(UInt32);
994     assert(handle != NULL);
995     assert(name   != NULL);
996     assert(value  != NULL);
997     assert(NameServer_module->refCount != 0);
999     status = NameServer_get(handle, name, value, &len, procId);
1001     return (status);
1004 /* Function to Retrieve the value portion of a name/value pair from
1005  * local table.
1006  */
1007 Int NameServer_getLocal(NameServer_Handle handle,
1008                     String            name,
1009                     Ptr               value,
1010                     UInt32 *          len)
1012     Int status = NameServer_E_NOTFOUND;
1013     NameServer_TableEntry * node = NULL;
1014     NameServer_TableEntry * temp = NULL;
1015     Bool done   = FALSE;
1016     UInt32 length;
1017     UInt32 hash;
1019     assert(handle != NULL);
1020     assert(name   != NULL);
1021     assert(value  != NULL);
1022     assert(len    != NULL);
1023     assert(NameServer_module->refCount != 0);
1025     length = *len;
1027     /* Calculate the hash */
1028     hash = stringHash(name);
1030     pthread_mutex_lock(&handle->gate);
1032     /* Traverse the list to find duplicate check */
1033     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1034         if (node->hash == hash) {
1035             if (node->collide == TRUE) {
1036                 temp = node;
1037                 while (temp) {
1038                     if (strcmp(temp->name, name) == 0u){
1039                         if (length <= node->len) {
1040                             memcpy(value, node->value, length);
1041                             *len = length;
1042                         }
1043                         else {
1044                             memcpy(value, node->value, node->len);
1045                             *len = node->len;
1046                         }
1047                         done = TRUE;
1048                         break;
1049                     }
1050                     temp = temp->next;
1051                 }
1052                 break;
1053             }
1054             else {
1055                 if (length <= node->len) {
1056                     memcpy(value, node->value, length);
1057                     *len = length;
1058                 }
1059                 else {
1060                     memcpy(value, node->value, node->len);
1061                     *len = node->len;
1062                 }
1063                 done = TRUE;
1064                 break;
1065             }
1066         }
1067     }
1069     pthread_mutex_unlock(&handle->gate);
1071     if (done == FALSE) {
1072         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1073     }
1074     else {
1075         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1076              node->name, (UInt32)node->value)
1077         status = NameServer_S_SUCCESS;
1078     }
1080     return (status);
1083 /*
1084  *  Gets a 32-bit value by name from the local table
1085  *
1086  *  If the name is found, the 32-bit value is copied into the value
1087  *  argument and a success status is returned.
1088  *
1089  *  If the name is not found, zero is returned in len and the contents
1090  *  of value are not modified. Not finding a name is not considered
1091  *  an error.
1092  *
1093  *  This function only searches the local name/value table.
1094  *
1095  */
1096 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1098     Int                 status;
1099     UInt32              len    = sizeof(UInt32);
1101     assert(handle != NULL);
1102     assert(name   != NULL);
1103     assert(value  != NULL);
1104     assert(NameServer_module->refCount != 0);
1106     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1107     status = NameServer_getLocal(handle, name, value, &len);
1109     return (status);
1113 #if defined (__cplusplus)
1115 #endif /* defined (__cplusplus) */