0f794355e000381dfb414cadf6f362b4825c8051
[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 /* TI Ipc utils: */
73 #include <_TiIpcFxns.h>
75 #include "ti/ipc/ti_ipc.h"
77 #define MESSAGEQ_RPMSG_PORT       61
78 #define NAME_SERVER_RPMSG_ADDR    0
79 #define RPMSG_RESERVED_ADDRESSES  (1024)
81 #define INVALIDSOCKET     (-1)
83 #if defined (__cplusplus)
84 extern "C" {
85 #endif
88 /* =============================================================================
89  * Structures & Enums
90  * =============================================================================
91  */
93 /* Structure of entry in Name/Value table */
94 typedef struct NameServer_TableEntry_tag {
95     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
96     /* List element */
97     UInt32                    hash;
98     /* Hash value */
99     String                    name;
100     /* Name portion of the name/value pair. */
101     UInt                      len;
102     /* Length of the value field. */
103     Ptr                       value;
104     /* Value portion of the name/value entry. */
105     Bool                      collide;
106     /* Does the hash collide? */
107     struct NameServer_TableEntry_tag * next;
108     /* Pointer to the next entry, used incase of collision only */
109 } NameServer_TableEntry;
111 /* Structure defining object for the NameServer */
112 struct NameServer_Object {
113     CIRCLEQ_ENTRY(NameServer_Object) elem;
114     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
115     String             name;            /* name of the instance */
116     NameServer_Params  params;          /* the parameter structure */
117     UInt32             count;           /* count of entries */
118     UInt32             refCount;        /* reference count to this object */
119     pthread_mutex_t    gate;            /* crit sect gate */
120 } NameServer_Object;
122 /* structure for NameServer module state */
123 typedef struct NameServer_ModuleObject {
124     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
125     Int32                refCount;
126     MessageQCopy_Handle  mq;
127     /* MessageQCopy instance to receive from remote proc nameserver ports: */
128     UInt32               recvAddr;
129     /* Local endpoint for receiving from remote proc nameserver ports: */
130     pthread_t            listener;
131     /* Listener thread for NameServer replies and requests. */
132     int                  waitFdW;
133     int                  waitFdR;
134     /* Pipe to post to NameServer_get. */
135     NameServerRemote_Msg nsMsg;
136     /* NameServer Message cache. */
137     NameServer_Params    defInstParams;
138     /* Default instance paramters */
139     pthread_mutex_t      modGate;
140 } NameServer_ModuleObject;
142 #define CIRCLEQ_destruct(head) { \
143         (head)->cqh_first = NULL; \
144         (head)->cqh_last = NULL; \
147 #define CIRCLEQ_elemClear(elem) { \
148         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
151 #define CIRCLEQ_traverse(x, y, tag) \
152         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
154 /* =============================================================================
155  *  Globals
156  * =============================================================================
157  */
158 /*
159  * NameServer_state
160  *
161  * Make the module gate "recursive" since NameServer_getHandle() needs to
162  * use it and NameServer_create() needs to hold it around its call to
163  * NameServer_getHandle().  Also, use the static initializer instead of a
164  * run-time init call, so we can use this gate immediately in _setup().
165  */
166 static NameServer_ModuleObject NameServer_state = {
167     .defInstParams.maxRuntimeEntries = 0u,
168     .defInstParams.tableHeap         = NULL,
169     .defInstParams.checkExisting     = TRUE,
170     .defInstParams.maxValueLen       = 0u,
171     .defInstParams.maxNameLen        = 16u,
172 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
173     .modGate                         = PTHREAD_RMUTEX_INITIALIZER,
174     .refCount                        = 0
175 };
177 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
179 static const UInt32 stringCrcTab[256u] = {
180   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
181   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
182   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
183   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
184   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
185   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
186   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
187   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
188   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
189   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
190   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
191   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
192   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
193   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
194   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
195   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
196   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
197   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
198   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
199   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
200   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
201   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
202   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
203   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
204   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
205   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
206   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
207   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
208   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
209   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
210   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
211   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
212   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
213   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
214   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
215   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
216   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
217   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
218   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
219   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
220   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
221   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
222   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
223 };
225 static UInt32 stringHash(String s)
227     UInt32 hash = strlen(s);
228     UInt32 i;
230     for (i = 0; i < strlen(s); i++) {
231         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
232     }
234     return (hash);
237 static void NameServerRemote_processMessage(NameServerRemote_Msg * msg, UInt16 procId)
239     NameServer_Handle handle;
240     Int               status = NameServer_E_FAIL;
241     char              buf = 'n';
242     int               waitFd = NameServer_module->waitFdW;
244     if (msg->request == NAMESERVER_REQUEST) {
245         LOG2("NameServer Request: instanceName: %s, name: %s\n",
246              (String)msg->instanceName, (String)msg->name)
248         assert(msg->valueLen <= MAXVALUELEN);
250         /*
251          *  Message is a request. Lookup name in NameServer table.
252          *  Send a response message back to source processor.
253          */
254         handle = NameServer_getHandle((String)msg->instanceName);
256         if (handle != NULL) {
257             /* Search for the NameServer entry */
258             if (msg->valueLen <= sizeof (Bits32)) {
259                 LOG0("Calling NameServer_getLocalUInt32...\n")
260                 status = NameServer_getLocalUInt32(handle,
261                      (String)msg->name, &msg->value);
262             }
263             else {
264                 LOG0("Calling NameServer_getLocal...\n")
265                 status = NameServer_getLocal(handle,
266                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
267             }
268         }
270         LOG2("NameServer Response: instanceName: %s, name: %s,",
271              (String)msg->instanceName, (String)msg->name)
272         /* set the request status */
273         if (status < 0) {
274             LOG1(" Value not found, status: %d\n", status)
275             msg->requestStatus = 0;
276         }
277         else {
278             msg->requestStatus = 1;
279             LOG1(" Value: 0x%x\n", msg->value)
280         }
282         /* specify message as a response */
283         msg->request = NAMESERVER_RESPONSE;
284         msg->reserved = NAMESERVER_MSG_TOKEN;
286         /* send response message to remote processor */
287         status = MessageQCopy_send(procId, MultiProc_self(),
288             MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
289             sizeof(NameServerRemote_Msg), TRUE);
290         if (status < 0) {
291             LOG0("NameServer: MessageQCopy_send failed\n")
292         }
293     }
294     else {
295         LOG2("NameServer Reply: instanceName: %s, name: %s",
296              (String)msg->instanceName, (String)msg->name)
297         LOG1(", value: 0x%x\n", msg->value)
299         /* Save the response message.  */
300         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerRemote_Msg));
302         /* Post the eventfd upon which NameServer_get() is waiting */
303         write(waitFd, &buf, sizeof(buf));
304     }
307 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
308     void * priv, UInt32 src, UInt16 srcProc)
310     NameServerRemote_Msg msg;
312     LOG0("listener_cb: Entered Listener thread.\n")
314     LOG1("NameServer: Listener got NameServer message "
315          "from MessageQCopy: 0x%p!\n", handle);
316     /* Get NameServer message and process: */
317     memcpy(&msg, data, len);
319     if (len != sizeof(NameServerRemote_Msg)) {
320         LOG1("NameServer: got bad NameServerRemote_Msg len (%d)\n",
321             len)
322     }
323     else {
324         LOG1("listener_cb: read from MessageQCopy 0x%p\n", handle)
325         LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
326              len, src)
327         LOG1("from vproc: %d\n", srcProc)
328         NameServerRemote_processMessage(&msg, srcProc);
329     }
332 /* =============================================================================
333  * APIS
334  * =============================================================================
335  */
337 /* Function to setup the nameserver module. */
338 Int NameServer_setup(Void)
340     Int    status = NameServer_S_SUCCESS;
341     int    fd[2];
343     pthread_mutex_lock(&NameServer_module->modGate);
345     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
347     NameServer_module->refCount++;
349     if (NameServer_module->refCount > 1) {
350         LOG0("NameServer_setup: already setup\n")
351         status = NameServer_S_ALREADYSETUP;
352         goto exit;
353     }
355     if (pipe(fd) == -1) {
356         status = NameServer_E_FAIL;
357         LOG0("NameServer_setup: failed to create waitFd.\n")
358         goto exit;
359     }
360     NameServer_module->waitFdW = fd[1];
361     NameServer_module->waitFdR = fd[0];
363     /* Create the MessageQCopy for receiving messages from all remote proc */
364     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
365         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
367     if (NameServer_module->mq == NULL) {
368         status = NameServer_E_FAIL;
369         LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
370         goto exit;
371     }
373     /* Construct the list object */
374     CIRCLEQ_INIT(&NameServer_module->objList);
376 exit:
377     LOG1("NameServer_setup: exiting, refCount=%d\n", \
378         NameServer_module->refCount)
380     pthread_mutex_unlock(&NameServer_module->modGate);
382     return (status);
385 /*! Function to destroy the nameserver module. */
386 Int NameServer_destroy(void)
388     Int      status    = NameServer_S_SUCCESS;
390     pthread_mutex_lock(&NameServer_module->modGate);
392     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
394     NameServer_module->refCount--;
396     if (NameServer_module->refCount > 0) {
397         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
398         status = NameServer_S_SUCCESS;
400         goto exit;
401     }
403     /* Delete the MessageQCopy instances */
404     if (NameServer_module->mq != NULL) {
405         MessageQCopy_delete(&NameServer_module->mq);
406     }
408     CIRCLEQ_destruct(&NameServer_module->objList);
410     close(NameServer_module->waitFdW);
411     close(NameServer_module->waitFdR);
413 exit:
414     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
416     pthread_mutex_unlock(&NameServer_module->modGate);
418     return (status);
421 /* Function to retrieve a NameServer handle from name. */
422 NameServer_Handle NameServer_getHandle(String name)
424     NameServer_Handle handle = NULL;
425     Bool              found = FALSE;
426     struct NameServer_Object * elem;
428     assert(name != NULL);
429     assert(NameServer_module->refCount != 0);
431     pthread_mutex_lock(&NameServer_module->modGate);
433     /* Lookup handle from name: */
434     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
435         handle = (NameServer_Handle) elem;
436         if (strcmp(handle->name, name) == 0) {
437             found = TRUE;
438             break;
439         }
440     }
442     if (found == FALSE) {
443         handle = NULL;
444     }
446     pthread_mutex_unlock(&NameServer_module->modGate);
448     return (handle);
452 /* Function to create a name server. */
453 NameServer_Handle NameServer_create(String name,
454                                     const NameServer_Params * params)
456     NameServer_Handle handle = NULL;
457     pthread_mutexattr_t mutex_attr;
459     assert(params != NULL);
460     assert(name != NULL);
461     assert(NameServer_module->refCount != 0);
463     LOG1("NameServer_create(): '%s'\n", name)
465     pthread_mutex_lock(&NameServer_module->modGate);
467     /* check if the name is already created or not */
468     handle = NameServer_getHandle(name);
469     if (handle != NULL) {
470         if (memcmp((Ptr)&handle->params, (Ptr)params,
471             sizeof(NameServer_Params)) == 0) {
472             handle->refCount++;
473         }
474         else {
475             LOG0("NameServer_create: NameServer params mismatch\n")
476             handle = NULL;
477         }
478         goto leave;
479     }
480     else {
481         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
482     }
484     if (!handle) {
485         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
486         goto leave;
487     }
489     handle->refCount = 1;
490     handle->name = (String)malloc(strlen(name) + 1u);
491     if (!handle->name) {
492         LOG0("NameServer_create: instance name alloc failed\n")
493         goto cleanup;
494     }
495     strncpy(handle->name, name, strlen (name) + 1u);
496     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
498     assert(params.maxValueLen <= MAXVALUELEN);
500     if (params->maxValueLen < sizeof(UInt32)) {
501         handle->params.maxValueLen = sizeof(UInt32);
502     }
503     else {
504         handle->params.maxValueLen = params->maxValueLen;
505     }
507     CIRCLEQ_INIT(&handle->nameList);
508     handle->count = 0u;
510     /* Put in the local list */
511     CIRCLEQ_elemClear(&handle->elem);
512     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
514     /*
515      * NameServer_removeEntry() enters gate and is called by
516      * NameServer_remove() while holding the gate.
517      */
518     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
519     pthread_mutex_init(&handle->gate, &mutex_attr);
521     goto leave;
523 cleanup:
524     free(handle);
525     handle = NULL;
527 leave:
528     pthread_mutex_unlock(&NameServer_module->modGate);
530     return (handle);
534 /* Function to delete a name server. */
535 Int NameServer_delete(NameServer_Handle * handle)
537     Int status = NameServer_S_SUCCESS;
539     assert(handle != NULL);
540     assert(*handle != NULL);
541     assert((*handle)->count == 0);
542     assert(NameServer_module->refCount != 0);
544     pthread_mutex_lock(&NameServer_module->modGate);
546     (*handle)->refCount--;
547     if ((*handle)->refCount != 0) {
548         goto leave;
549     }
551     if ((*handle)->count == 0) {
552         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
554         if ((*handle)->name != NULL) {
555             free((*handle)->name);
556             (*handle)->name = NULL;
557         }
559         CIRCLEQ_destruct(&(*handle)->nameList);
561         free((*handle));
562         (*handle) = NULL;
563     }
565 leave:
566     pthread_mutex_unlock(&NameServer_module->modGate);
568     return (status);
571 /* Adds a variable length value into the local NameServer table */
572 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
574     Int                 status = NameServer_S_SUCCESS;
575     NameServer_TableEntry * node = NULL;
576     NameServer_TableEntry * new_node = NULL;
577     Bool                found = FALSE;
578     UInt32              hash;
580     assert(handle != NULL);
581     assert(name     != NULL);
582     assert(buf      != NULL);
583     assert(len      != 0);
584     assert(NameServer_module->refCount != 0);
586     /* Calculate the hash */
587     hash = stringHash(name);
589     pthread_mutex_lock(&handle->gate);
591     if (strlen(name) > handle->params.maxNameLen - 1) {
592         status = NameServer_E_INVALIDARG;
593         LOG0("NameServer_add: name length exceeded maximum!\n")
594         new_node = NULL;
595         goto exit;
596     }
598     if (len > handle->params.maxValueLen) {
599         status = NameServer_E_INVALIDARG;
600         LOG0("NameServer_add: value length exceeded maximum!\n")
601         new_node = NULL;
602         goto exit;
603     }
605     /* Traverse the list to find duplicate check */
606     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
607         /* Hash matches */
608         if (node->hash == hash) {
609             /* If the name matches, incase hash is duplicate */
610             if (strcmp(node->name, name) == 0) {
611                 if (handle->params.checkExisting == TRUE) {
612                     status = NameServer_E_INVALIDARG;
613                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
614                     break;
615                 }
616             }
617             else {
618                 found = TRUE;
619                 break;
620             } /* name does not match */
621         } /* hash does not match */
622     } /* CIRCLEQ_traverse */
624     if (status != NameServer_S_SUCCESS) {
625         new_node = NULL;
626         goto exit;
627     }
629     /* Now add the new entry. */
630     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
631     if (new_node == NULL) {
632         status = NameServer_E_MEMORY;
633         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
635         goto exit;
636     }
638     new_node->hash    = hash;
639     new_node->collide = found; /* Indicate if there is a collision*/
640     new_node->len     = len;
641     new_node->next    = NULL;
642     new_node->name = (String)malloc(strlen(name) + 1u);
643     new_node->value  = (Ptr)malloc(len);
644     strncpy(new_node->name, name, strlen(name) + 1u);
645     memcpy((Ptr)new_node->value, (Ptr)buf, len);
647     if (found == TRUE) {
648         /* If hash is found, need to stitch the list to link the
649          * new node to the existing node with the same hash.
650          */
651         new_node->next = node->next;
652         node->next = new_node;
653     }
654     else {
655         /* put the new node into the list */
656         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
657     }
659     handle->count++;
661     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
662          name, *(UInt32 *)buf)
664 exit:
665     pthread_mutex_unlock(&handle->gate);
667     return (new_node);
671 /* Function to add a UInt32 value into a name server. */
672 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
674     Ptr entry = NULL;
676     assert(handle != NULL);
677     assert(name   != NULL);
678     assert(NameServer_module->refCount != 0);
680     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
682     return (entry);
685 /* Function to remove a name/value pair from a name server. */
686 Int NameServer_remove(NameServer_Handle handle, String name)
688     Int                 status = NameServer_S_SUCCESS;
689     NameServer_TableEntry *prev = NULL;
690     NameServer_TableEntry *temp = NULL;
691     NameServer_TableEntry *node = NULL;
692     Bool                done   = FALSE;
693     UInt32              hash;
695     assert(handle != NULL);
696     assert(name   != NULL);
697     assert(NameServer_module->refCount != 0);
699     /* Calculate the hash */
700     hash = stringHash(name);
702     pthread_mutex_lock(&handle->gate);
704     /* Traverse the list to find duplicate check */
705     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
706         /* Hash matchs */
707         if (node->hash == hash) {
708             if (node->collide == TRUE) {
709                 if (strcmp(node->name, name) == 0){
710                     free(node->value);
711                     free(node->name);
712                     memcpy((Ptr)node, (Ptr) node->next,
713                            sizeof(NameServer_TableEntry));
714                     node->next = node->next->next;
715                     free(node->next);
716                     handle->count--;
717                     done = TRUE;
718                     break;
719                 }
720                 else {
721                     prev = node;
722                     temp = node->next;
723                     while (temp) {
724                         if (strcmp(temp->name, name) == 0){
725                             free(temp->value);
726                             free(temp->name);
727                             prev->next = temp->next;
728                             free(temp);
729                             handle->count--;
730                             done = TRUE;
731                             break;
732                         }
733                         temp = temp->next;
734                     }
735                     break;
736                 }
737             }
738             else {
739                 NameServer_removeEntry(handle, (Ptr)node);
741                 done = TRUE;
742                 break;
743             }
744         }
745     }
747     if (done == FALSE) {
748         status = NameServer_E_INVALIDARG;
749         LOG1("NameServer_remove %d Entry not found!\n", status)
750     }
752     pthread_mutex_unlock(&handle->gate);
754     return (status);
757 /* Function to remove a name/value pair from a name server. */
758 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
760     Int  status = NameServer_S_SUCCESS;
761     NameServer_TableEntry * node;
763     assert(handle != NULL);
764     assert(entry  != NULL);
765     assert(NameServer_module->refCount != 0);
767     pthread_mutex_lock(&handle->gate);
769     node = (NameServer_TableEntry *)entry;
771     free(node->value);
772     free(node->name);
773     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
774     free(node);
775     handle->count--;
777     pthread_mutex_unlock(&handle->gate);
779     return (status);
783 /* Initialize this config-params structure with supplier-specified
784  * defaults before instance creation.
785  */
786 Void NameServer_Params_init(NameServer_Params * params)
788     assert(params != NULL);
790     memcpy(params, &(NameServer_module->defInstParams),
791            sizeof (NameServer_Params));
795 Int NameServer_getRemote(NameServer_Handle handle,
796                      String            name,
797                      Ptr               value,
798                      UInt32 *          len,
799                      UInt16            procId)
801     Int status = NameServer_S_SUCCESS;
802     Int mqcStatus = -1;
803     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
804     NameServerRemote_Msg nsMsg;
805     NameServerRemote_Msg *replyMsg;
806     fd_set rfds;
807     int ret = 0, maxfd, waitFd;
808     struct timeval tv;
809     char buf = '1';
810     int numBytes;
811     static int seqNum = 0;
812     Bool done = FALSE;
814     if (strlen(name) >= MAXNAMEINCHAR) {
815         LOG0("Name is too long in remote query\n");
816         return NameServer_E_NAMETOOLONG;
817     }
819     if (strlen(obj->name) >= MAXNAMEINCHAR) {
820         LOG0("Instance name is too long for remote query\n");
821         return NameServer_E_NAMETOOLONG;
822     }
824     pthread_mutex_lock(&NameServer_module->modGate);
826     /* Set Timeout to wait: */
827     tv.tv_sec = 0;
828     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
830     /* Create request message and send to remote processor: */
831     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
832     nsMsg.request = NAMESERVER_REQUEST;
833     nsMsg.requestStatus = 0;
834     nsMsg.valueLen = *len;
835     nsMsg.seqNum = seqNum++;
837     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
838     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
840     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
841            procId, (String)nsMsg.instanceName)
842     LOG1("%s...\n", (String)nsMsg.name)
844     /* send message */
845     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
846             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerRemote_Msg),
847         TRUE);
848     if (mqcStatus < 0) {
849         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
850         status = NameServer_E_NOTFOUND;
851         goto exit;
852     }
854     while (!done) {
855         /* Block on waitFd for signal from listener thread: */
856         waitFd = NameServer_module->waitFdR;
857         FD_ZERO(&rfds);
858         FD_SET(waitFd, &rfds);
859         maxfd = waitFd + 1;
860         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
861         ret = select(maxfd, &rfds, NULL, NULL, &tv);
862         if (ret == -1) {
863             LOG0("NameServer_getRemote: select failed.")
864             status = NameServer_E_FAIL;
865             goto exit;
866         }
867         else if (!ret) {
868             LOG0("NameServer_getRemote: select timed out.\n")
869             status = NameServer_E_TIMEOUT;
870             goto exit;
871         }
873         if (FD_ISSET(waitFd, &rfds)) {
874             /* Read, just to balance the write: */
875             numBytes = read(waitFd, &buf, sizeof(buf));
876             if (numBytes == -1) {
877                 LOG0("NameServer_getRemote: read failure\n")
878                 status = NameServer_E_FAIL;
879                 goto exit;
880             }
882             /* Process response: */
883             replyMsg = &NameServer_module->nsMsg;
885             if (replyMsg->seqNum != seqNum - 1) {
886                 /* Ignore responses without current sequence # */
887                 continue;
888             }
890             if (replyMsg->requestStatus) {
891                 /* name is found */
893                 /* set length to amount of data that was copied */
894                 *len = replyMsg->valueLen;
896                 /* set the contents of value */
897                 if (*len <= sizeof (Bits32)) {
898                     *(UInt32 *)value = (UInt32)replyMsg->value;
899                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
900                         procId, (String)replyMsg->instanceName)
901                     LOG2("%s, value: 0x%x...\n",
902                         (String)replyMsg->name, *(UInt32 *)value)
903                 }
904                 else {
905                     memcpy(value, replyMsg->valueBuf, *len);
906                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
907                         procId, (String)replyMsg->instanceName)
908                     LOG2("%s, value buffer at address: 0x%p...\n",
909                         (String)replyMsg->name, value)
910                 }
912                 goto exit;
913             }
914             else {
915                 /* name is not found */
916                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
917                      (String)replyMsg->instanceName, (String)replyMsg->name)
919                 /* set status to not found */
920                 status = NameServer_E_NOTFOUND;
921             }
922         }
923         done = TRUE;
924     }
925 exit:
926     pthread_mutex_unlock(&NameServer_module->modGate);
928     return (status);
931 /* Function to retrieve the value portion of a name/value pair from
932  * local table.
933  */
934 Int NameServer_get(NameServer_Handle handle,
935                String            name,
936                Ptr               value,
937                UInt32 *          len,
938                UInt16            procId[])
940     Int status = NameServer_S_SUCCESS;
941     UInt16 numProcs = MultiProc_getNumProcessors();
942     UInt32 i;
944     if (procId == NULL) {
945         status = NameServer_getLocal(handle, name, value, len);
946         if (status == NameServer_E_NOTFOUND) {
947             for (i = 0; i < numProcs; i++) {
948                 /* getLocal call already covers "self", keep going */
949                 if (i == MultiProc_self()) {
950                     continue;
951                 }
953                 status = NameServer_getRemote(handle, name, value, len, i);
955                 if ((status >= 0) ||
956                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
957                     (status != NameServer_E_TIMEOUT))) {
958                     break;
959                 }
960             }
961         }
962     }
963     else {
964         /*
965          *  Search the query list. It might contain the local proc
966          *  somewhere in the list.
967          */
968         i = 0;
969         while (procId[i] != MultiProc_INVALIDID) {
970             if (procId[i] == MultiProc_self()) {
971                 status = NameServer_getLocal(handle, name, value, len);
972             }
973             else {
974                 status = NameServer_getRemote(handle, name, value, len, i);
975             }
977             if ((status >= 0) ||
978                 ((status < 0) && (status != NameServer_E_NOTFOUND)
979                 && (status != NameServer_E_TIMEOUT))) {
980                 break;
981             }
983             i++;
984         }
985     }
987     return (status);
990 /* Gets a 32-bit value by name */
991 Int NameServer_getUInt32(NameServer_Handle handle,
992                      String            name,
993                      Ptr               value,
994                      UInt16            procId[])
996     Int  status;
997     UInt32 len = sizeof(UInt32);
999     assert(handle != NULL);
1000     assert(name   != NULL);
1001     assert(value  != NULL);
1002     assert(NameServer_module->refCount != 0);
1004     status = NameServer_get(handle, name, value, &len, procId);
1006     return (status);
1009 /* Function to Retrieve the value portion of a name/value pair from
1010  * local table.
1011  */
1012 Int NameServer_getLocal(NameServer_Handle handle,
1013                     String            name,
1014                     Ptr               value,
1015                     UInt32 *          len)
1017     Int status = NameServer_E_NOTFOUND;
1018     NameServer_TableEntry * node = NULL;
1019     NameServer_TableEntry * temp = NULL;
1020     Bool done   = FALSE;
1021     UInt32 length;
1022     UInt32 hash;
1024     assert(handle != NULL);
1025     assert(name   != NULL);
1026     assert(value  != NULL);
1027     assert(len    != NULL);
1028     assert(NameServer_module->refCount != 0);
1030     length = *len;
1032     /* Calculate the hash */
1033     hash = stringHash(name);
1035     pthread_mutex_lock(&handle->gate);
1037     /* Traverse the list to find duplicate check */
1038     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1039         if (node->hash == hash) {
1040             if (node->collide == TRUE) {
1041                 temp = node;
1042                 while (temp) {
1043                     if (strcmp(temp->name, name) == 0u){
1044                         if (length <= node->len) {
1045                             memcpy(value, node->value, length);
1046                             *len = length;
1047                         }
1048                         else {
1049                             memcpy(value, node->value, node->len);
1050                             *len = node->len;
1051                         }
1052                         done = TRUE;
1053                         break;
1054                     }
1055                     temp = temp->next;
1056                 }
1057                 break;
1058             }
1059             else {
1060                 if (length <= node->len) {
1061                     memcpy(value, node->value, length);
1062                     *len = length;
1063                 }
1064                 else {
1065                     memcpy(value, node->value, node->len);
1066                     *len = node->len;
1067                 }
1068                 done = TRUE;
1069                 break;
1070             }
1071         }
1072     }
1074     pthread_mutex_unlock(&handle->gate);
1076     if (done == FALSE) {
1077         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1078     }
1079     else {
1080         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1081              node->name, (UInt32)node->value)
1082         status = NameServer_S_SUCCESS;
1083     }
1085     return (status);
1088 /*
1089  *  Gets a 32-bit value by name from the local table
1090  *
1091  *  If the name is found, the 32-bit value is copied into the value
1092  *  argument and a success status is returned.
1093  *
1094  *  If the name is not found, zero is returned in len and the contents
1095  *  of value are not modified. Not finding a name is not considered
1096  *  an error.
1097  *
1098  *  This function only searches the local name/value table.
1099  *
1100  */
1101 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1103     Int                 status;
1104     UInt32              len    = sizeof(UInt32);
1106     assert(handle != NULL);
1107     assert(name   != NULL);
1108     assert(value  != NULL);
1109     assert(NameServer_module->refCount != 0);
1111     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1112     status = NameServer_getLocal(handle, name, value, &len);
1114     return (status);
1118 #if defined (__cplusplus)
1120 #endif /* defined (__cplusplus) */