Improve MessageQ recovery on DRA7xx 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 <_NameServer_daemon.h>
70 #include <ti/ipc/namesrv/_NameServerRemoteRpmsg.h>
71 #include <_IpcLog.h>
73 #define MESSAGEQ_RPMSG_PORT       61
74 #define NAME_SERVER_RPMSG_ADDR    0
75 #define RPMSG_RESERVED_ADDRESSES  (1024)
77 #define INVALIDSOCKET     (-1)
79 #if defined (__cplusplus)
80 extern "C" {
81 #endif
84 /* =============================================================================
85  * Structures & Enums
86  * =============================================================================
87  */
89 /* Structure of entry in Name/Value table */
90 typedef struct NameServer_TableEntry_tag {
91     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
92     /* List element */
93     UInt32                    hash;
94     /* Hash value */
95     String                    name;
96     /* Name portion of the name/value pair. */
97     UInt                      len;
98     /* Length of the value field. */
99     Ptr                       value;
100     /* Value portion of the name/value entry. */
101     Bool                      collide;
102     /* Does the hash collide? */
103     struct NameServer_TableEntry_tag * next;
104     /* Pointer to the next entry, used incase of collision only */
105 } NameServer_TableEntry;
107 /* Structure defining object for the NameServer */
108 struct NameServer_Object {
109     CIRCLEQ_ENTRY(NameServer_Object) elem;
110     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
111     String             name;            /* name of the instance */
112     NameServer_Params  params;          /* the parameter structure */
113     UInt32             count;           /* count of entries */
114     UInt32             refCount;        /* reference count to this object */
115     pthread_mutex_t    gate;            /* crit sect gate */
116 } NameServer_Object;
118 /* structure for NameServer module state */
119 typedef struct NameServer_ModuleObject {
120     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
121     Int32                refCount;
122     MessageQCopy_Handle  mq;
123     /* MessageQCopy instance to receive from remote proc nameserver ports: */
124     UInt32               recvAddr;
125     /* Local endpoint for receiving from remote proc nameserver ports: */
126     pthread_t            listener;
127     /* Listener thread for NameServer replies and requests. */
128     int                  waitFdW;
129     int                  waitFdR;
130     /* Pipe to post to NameServer_get. */
131     NameServerRemote_Msg nsMsg;
132     /* NameServer Message cache. */
133     NameServer_Params    defInstParams;
134     /* Default instance paramters */
135     pthread_mutex_t      modGate;
136 } NameServer_ModuleObject;
138 #define CIRCLEQ_destruct(head) { \
139         (head)->cqh_first = NULL; \
140         (head)->cqh_last = NULL; \
143 #define CIRCLEQ_elemClear(elem) { \
144         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
147 #define CIRCLEQ_traverse(x, y, tag) \
148         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
150 /* =============================================================================
151  *  Globals
152  * =============================================================================
153  */
154 /*
155  * NameServer_state
156  *
157  * Make the module gate "recursive" since NameServer_getHandle() needs to
158  * use it and NameServer_create() needs to hold it around its call to
159  * NameServer_getHandle().  Also, use the static initializer instead of a
160  * run-time init call, so we can use this gate immediately in _setup().
161  */
162 static NameServer_ModuleObject NameServer_state = {
163     .defInstParams.maxRuntimeEntries = 0u,
164     .defInstParams.tableHeap         = NULL,
165     .defInstParams.checkExisting     = TRUE,
166     .defInstParams.maxValueLen       = 0u,
167     .defInstParams.maxNameLen        = 16u,
168 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
169     .modGate                         = PTHREAD_RMUTEX_INITIALIZER,
170     .refCount                        = 0
171 };
173 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
175 static const UInt32 stringCrcTab[256u] = {
176   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
177   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
178   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
179   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
180   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
181   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
182   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
183   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
184   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
185   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
186   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
187   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
188   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
189   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
190   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
191   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
192   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
193   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
194   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
195   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
196   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
197   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
198   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
199   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
200   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
201   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
202   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
203   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
204   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
205   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
206   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
207   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
208   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
209   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
210   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
211   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
212   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
213   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
214   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
215   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
216   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
217   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
218   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
219 };
221 static UInt32 stringHash(String s)
223     UInt32 hash = strlen(s);
224     UInt32 i;
226     for (i = 0; i < strlen(s); i++) {
227         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
228     }
230     return (hash);
233 static void NameServerRemote_processMessage(NameServerRemote_Msg * msg, UInt16 procId)
235     NameServer_Handle handle;
236     Int               status = NameServer_E_FAIL;
237     char              buf = 'n';
238     int               waitFd = NameServer_module->waitFdW;
240     if (msg->request == NAMESERVER_REQUEST) {
241         LOG2("NameServer Request: instanceName: %s, name: %s\n",
242              (String)msg->instanceName, (String)msg->name)
244         assert(msg->valueLen <= MAXVALUELEN);
246         /*
247          *  Message is a request. Lookup name in NameServer table.
248          *  Send a response message back to source processor.
249          */
250         handle = NameServer_getHandle((String)msg->instanceName);
252         if (handle != NULL) {
253             /* Search for the NameServer entry */
254             if (msg->valueLen <= sizeof (Bits32)) {
255                 LOG0("Calling NameServer_getLocalUInt32...\n")
256                 status = NameServer_getLocalUInt32(handle,
257                      (String)msg->name, &msg->value);
258             }
259             else {
260                 LOG0("Calling NameServer_getLocal...\n")
261                 status = NameServer_getLocal(handle,
262                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
263             }
264         }
266         LOG2("NameServer Response: instanceName: %s, name: %s,",
267              (String)msg->instanceName, (String)msg->name)
268         /* set the request status */
269         if (status < 0) {
270             LOG1(" Value not found, status: %d\n", status)
271             msg->requestStatus = 0;
272         }
273         else {
274             msg->requestStatus = 1;
275             LOG1(" Value: 0x%x\n", msg->value)
276         }
278         /* specify message as a response */
279         msg->request = NAMESERVER_RESPONSE;
280         msg->reserved = NAMESERVER_MSG_TOKEN;
282         pthread_mutex_lock(&NameServer_module->modGate);
284         /*
285          * Check if MessageQCopy object is valid. If not, we received a request
286          * but we are not able to respond to it due to recovery.
287          * We will simply drop the request.
288          */
289         if (NameServer_module->mq == NULL) {
290             LOG0("NameServerRemote_processMessage: MessageQCopy not ready. Request "
291                 "dropped.\n")
292         }
293         else {
294             /* send response message to remote processor */
295             status = MessageQCopy_send(procId, MultiProc_self(),
296                 MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
297                 sizeof(NameServerRemote_Msg), TRUE);
298             if (status < 0) {
299                 LOG0("NameServer: MessageQCopy_send failed\n")
300             }
301         }
303         pthread_mutex_unlock(&NameServer_module->modGate);
304     }
305     else {
306         LOG2("NameServer Reply: instanceName: %s, name: %s",
307              (String)msg->instanceName, (String)msg->name)
308         LOG1(", value: 0x%x\n", msg->value)
310         /* Save the response message.  */
311         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerRemote_Msg));
313         /* Post the eventfd upon which NameServer_get() is waiting */
314         write(waitFd, &buf, sizeof(buf));
315     }
318 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
319     void * priv, UInt32 src, UInt16 srcProc)
321     NameServerRemote_Msg msg;
323     LOG0("listener_cb: Entered Listener thread.\n")
325     LOG1("NameServer: Listener got NameServer message "
326          "from MessageQCopy: 0x%p!\n", handle);
327     /* Get NameServer message and process: */
328     memcpy(&msg, data, len);
330     if (len != sizeof(NameServerRemote_Msg)) {
331         LOG1("NameServer: got bad NameServerRemote_Msg len (%d)\n",
332             len)
333     }
334     else {
335         LOG1("listener_cb: read from MessageQCopy 0x%p\n", handle)
336         LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
337              len, src)
338         LOG1("from vproc: %d\n", srcProc)
339         NameServerRemote_processMessage(&msg, srcProc);
340     }
343 /* =============================================================================
344  * APIS
345  * =============================================================================
346  */
348 /* Function to setup the nameserver module. */
349 Int NameServer_setup(Void)
351     Int    status = NameServer_S_SUCCESS;
352     int    fd[2];
354     pthread_mutex_lock(&NameServer_module->modGate);
356     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
358     NameServer_module->refCount++;
360     if (NameServer_module->refCount > 1) {
361         LOG0("NameServer_setup: already setup\n")
362         status = NameServer_S_ALREADYSETUP;
363         goto exit;
364     }
366     if (pipe(fd) == -1) {
367         status = NameServer_E_FAIL;
368         LOG0("NameServer_setup: failed to create waitFd.\n")
369         goto exit;
370     }
371     NameServer_module->waitFdW = fd[1];
372     NameServer_module->waitFdR = fd[0];
374     /* Create the MessageQCopy for receiving messages from all remote proc */
375     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
376         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
378     if (NameServer_module->mq == NULL) {
379         status = NameServer_E_FAIL;
380         LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
381         goto exit;
382     }
384     /* Construct the list object */
385     CIRCLEQ_INIT(&NameServer_module->objList);
387 exit:
388     LOG1("NameServer_setup: exiting, refCount=%d\n", \
389         NameServer_module->refCount)
391     pthread_mutex_unlock(&NameServer_module->modGate);
393     return (status);
396 /*! Function to destroy the nameserver module. */
397 Int NameServer_destroy(void)
399     Int      status    = NameServer_S_SUCCESS;
401     pthread_mutex_lock(&NameServer_module->modGate);
403     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
405     NameServer_module->refCount--;
407     if (NameServer_module->refCount > 0) {
408         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
409         status = NameServer_S_SUCCESS;
411         goto exit;
412     }
414     /* Delete the MessageQCopy instances */
415     if (NameServer_module->mq != NULL) {
416         MessageQCopy_delete(&NameServer_module->mq);
417     }
419     CIRCLEQ_destruct(&NameServer_module->objList);
421     close(NameServer_module->waitFdW);
422     close(NameServer_module->waitFdR);
424 exit:
425     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
427     pthread_mutex_unlock(&NameServer_module->modGate);
429     return (status);
432 /* Function to retrieve a NameServer handle from name. */
433 NameServer_Handle NameServer_getHandle(String name)
435     NameServer_Handle handle = NULL;
436     Bool              found = FALSE;
437     struct NameServer_Object * elem;
439     assert(name != NULL);
440     assert(NameServer_module->refCount != 0);
442     pthread_mutex_lock(&NameServer_module->modGate);
444     /* Lookup handle from name: */
445     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
446         handle = (NameServer_Handle) elem;
447         if (strcmp(handle->name, name) == 0) {
448             found = TRUE;
449             break;
450         }
451     }
453     if (found == FALSE) {
454         handle = NULL;
455     }
457     pthread_mutex_unlock(&NameServer_module->modGate);
459     return (handle);
463 /* Function to create a name server. */
464 NameServer_Handle NameServer_create(String name,
465                                     const NameServer_Params * params)
467     NameServer_Handle handle = NULL;
468     pthread_mutexattr_t mutex_attr;
470     assert(params != NULL);
471     assert(name != NULL);
472     assert(NameServer_module->refCount != 0);
474     LOG1("NameServer_create(): '%s'\n", name)
476     pthread_mutex_lock(&NameServer_module->modGate);
478     /* check if the name is already created or not */
479     handle = NameServer_getHandle(name);
480     if (handle != NULL) {
481         if (memcmp((Ptr)&handle->params, (Ptr)params,
482             sizeof(NameServer_Params)) == 0) {
483             handle->refCount++;
484         }
485         else {
486             LOG0("NameServer_create: NameServer params mismatch\n")
487             handle = NULL;
488         }
489         goto leave;
490     }
491     else {
492         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
493     }
495     if (!handle) {
496         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
497         goto leave;
498     }
500     handle->refCount = 1;
501     handle->name = (String)malloc(strlen(name) + 1u);
502     if (!handle->name) {
503         LOG0("NameServer_create: instance name alloc failed\n")
504         goto cleanup;
505     }
506     strncpy(handle->name, name, strlen (name) + 1u);
507     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
509     assert(params.maxValueLen <= MAXVALUELEN);
511     if (params->maxValueLen < sizeof(UInt32)) {
512         handle->params.maxValueLen = sizeof(UInt32);
513     }
514     else {
515         handle->params.maxValueLen = params->maxValueLen;
516     }
518     CIRCLEQ_INIT(&handle->nameList);
519     handle->count = 0u;
521     /* Put in the local list */
522     CIRCLEQ_elemClear(&handle->elem);
523     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
525     /*
526      * NameServer_removeEntry() enters gate and is called by
527      * NameServer_remove() while holding the gate.
528      */
529     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
530     pthread_mutex_init(&handle->gate, &mutex_attr);
532     goto leave;
534 cleanup:
535     free(handle);
536     handle = NULL;
538 leave:
539     pthread_mutex_unlock(&NameServer_module->modGate);
541     return (handle);
545 /* Function to delete a name server. */
546 Int NameServer_delete(NameServer_Handle * handle)
548     Int status = NameServer_S_SUCCESS;
550     assert(handle != NULL);
551     assert(*handle != NULL);
552     assert((*handle)->count == 0);
553     assert(NameServer_module->refCount != 0);
555     pthread_mutex_lock(&NameServer_module->modGate);
557     (*handle)->refCount--;
558     if ((*handle)->refCount != 0) {
559         goto leave;
560     }
562     if ((*handle)->count == 0) {
563         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
565         if ((*handle)->name != NULL) {
566             free((*handle)->name);
567             (*handle)->name = NULL;
568         }
570         CIRCLEQ_destruct(&(*handle)->nameList);
572         pthread_mutex_destroy(&(*handle)->gate);
574         free((*handle));
575         (*handle) = NULL;
576     }
578 leave:
579     pthread_mutex_unlock(&NameServer_module->modGate);
581     return (status);
584 /* Adds a variable length value into the local NameServer table */
585 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
587     Int                 status = NameServer_S_SUCCESS;
588     NameServer_TableEntry * node = NULL;
589     NameServer_TableEntry * new_node = NULL;
590     Bool                found = FALSE;
591     UInt32              hash;
593     assert(handle != NULL);
594     assert(name     != NULL);
595     assert(buf      != NULL);
596     assert(len      != 0);
597     assert(NameServer_module->refCount != 0);
599     /* Calculate the hash */
600     hash = stringHash(name);
602     pthread_mutex_lock(&handle->gate);
604     if (strlen(name) > handle->params.maxNameLen - 1) {
605         status = NameServer_E_INVALIDARG;
606         LOG0("NameServer_add: name length exceeded maximum!\n")
607         new_node = NULL;
608         goto exit;
609     }
611     if (len > handle->params.maxValueLen) {
612         status = NameServer_E_INVALIDARG;
613         LOG0("NameServer_add: value length exceeded maximum!\n")
614         new_node = NULL;
615         goto exit;
616     }
618     /* Traverse the list to find duplicate check */
619     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
620         /* Hash matches */
621         if (node->hash == hash) {
622             /* If the name matches, incase hash is duplicate */
623             if (strcmp(node->name, name) == 0) {
624                 if (handle->params.checkExisting == TRUE) {
625                     status = NameServer_E_INVALIDARG;
626                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
627                     break;
628                 }
629             }
630             else {
631                 found = TRUE;
632                 break;
633             } /* name does not match */
634         } /* hash does not match */
635     } /* CIRCLEQ_traverse */
637     if (status != NameServer_S_SUCCESS) {
638         new_node = NULL;
639         goto exit;
640     }
642     /* Now add the new entry. */
643     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
644     if (new_node == NULL) {
645         status = NameServer_E_MEMORY;
646         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
648         goto exit;
649     }
651     new_node->hash    = hash;
652     new_node->collide = found; /* Indicate if there is a collision*/
653     new_node->len     = len;
654     new_node->next    = NULL;
655     new_node->name = (String)malloc(strlen(name) + 1u);
656     new_node->value  = (Ptr)malloc(len);
657     strncpy(new_node->name, name, strlen(name) + 1u);
658     memcpy((Ptr)new_node->value, (Ptr)buf, len);
660     if (found == TRUE) {
661         /* If hash is found, need to stitch the list to link the
662          * new node to the existing node with the same hash.
663          */
664         new_node->next = node->next;
665         node->next = new_node;
666     }
667     else {
668         /* put the new node into the list */
669         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
670     }
672     handle->count++;
674     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
675          name, *(UInt32 *)buf)
677 exit:
678     pthread_mutex_unlock(&handle->gate);
680     return (new_node);
684 /* Function to add a UInt32 value into a name server. */
685 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
687     Ptr entry = NULL;
689     assert(handle != NULL);
690     assert(name   != NULL);
691     assert(NameServer_module->refCount != 0);
693     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
695     return (entry);
698 /* Function to remove a name/value pair from a name server. */
699 Int NameServer_remove(NameServer_Handle handle, String name)
701     Int                 status = NameServer_S_SUCCESS;
702     NameServer_TableEntry *prev = NULL;
703     NameServer_TableEntry *temp = NULL;
704     NameServer_TableEntry *node = NULL;
705     Bool                done   = FALSE;
706     UInt32              hash;
708     assert(handle != NULL);
709     assert(name   != NULL);
710     assert(NameServer_module->refCount != 0);
712     /* Calculate the hash */
713     hash = stringHash(name);
715     pthread_mutex_lock(&handle->gate);
717     /* Traverse the list to find duplicate check */
718     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
719         /* Hash matchs */
720         if (node->hash == hash) {
721             if (node->collide == TRUE) {
722                 if (strcmp(node->name, name) == 0){
723                     free(node->value);
724                     free(node->name);
725                     memcpy((Ptr)node, (Ptr) node->next,
726                            sizeof(NameServer_TableEntry));
727                     node->next = node->next->next;
728                     free(node->next);
729                     handle->count--;
730                     done = TRUE;
731                     break;
732                 }
733                 else {
734                     prev = node;
735                     temp = node->next;
736                     while (temp) {
737                         if (strcmp(temp->name, name) == 0){
738                             free(temp->value);
739                             free(temp->name);
740                             prev->next = temp->next;
741                             free(temp);
742                             handle->count--;
743                             done = TRUE;
744                             break;
745                         }
746                         temp = temp->next;
747                     }
748                     break;
749                 }
750             }
751             else {
752                 NameServer_removeEntry(handle, (Ptr)node);
754                 done = TRUE;
755                 break;
756             }
757         }
758     }
760     if (done == FALSE) {
761         status = NameServer_E_INVALIDARG;
762         LOG1("NameServer_remove %d Entry not found!\n", status)
763     }
765     pthread_mutex_unlock(&handle->gate);
767     return (status);
770 /* Function to remove a name/value pair from a name server. */
771 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
773     Int  status = NameServer_S_SUCCESS;
774     NameServer_TableEntry * node;
776     assert(handle != NULL);
777     assert(entry  != NULL);
778     assert(NameServer_module->refCount != 0);
780     pthread_mutex_lock(&handle->gate);
782     node = (NameServer_TableEntry *)entry;
784     free(node->value);
785     free(node->name);
786     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
787     free(node);
788     handle->count--;
790     pthread_mutex_unlock(&handle->gate);
792     return (status);
796 /* Initialize this config-params structure with supplier-specified
797  * defaults before instance creation.
798  */
799 Void NameServer_Params_init(NameServer_Params * params)
801     assert(params != NULL);
803     memcpy(params, &(NameServer_module->defInstParams),
804            sizeof (NameServer_Params));
808 Int NameServer_getRemote(NameServer_Handle handle,
809                      String            name,
810                      Ptr               value,
811                      UInt32 *          len,
812                      UInt16            procId)
814     Int status = NameServer_S_SUCCESS;
815     Int mqcStatus = -1;
816     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
817     NameServerRemote_Msg nsMsg;
818     NameServerRemote_Msg *replyMsg;
819     fd_set rfds;
820     int ret = 0, maxfd, waitFd;
821     struct timeval tv;
822     char buf = '1';
823     int numBytes;
824     static int seqNum = 0;
825     Bool done = FALSE;
827     if (strlen(name) >= MAXNAMEINCHAR) {
828         LOG0("Name is too long in remote query\n");
829         return NameServer_E_NAMETOOLONG;
830     }
832     if (strlen(obj->name) >= MAXNAMEINCHAR) {
833         LOG0("Instance name is too long for remote query\n");
834         return NameServer_E_NAMETOOLONG;
835     }
837     pthread_mutex_lock(&NameServer_module->modGate);
839     /* Set Timeout to wait: */
840     tv.tv_sec = 0;
841     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
843     /* Create request message and send to remote processor: */
844     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
845     nsMsg.request = NAMESERVER_REQUEST;
846     nsMsg.requestStatus = 0;
847     nsMsg.valueLen = *len;
848     nsMsg.seqNum = seqNum++;
850     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
851     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
853     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
854            procId, (String)nsMsg.instanceName)
855     LOG1("%s...\n", (String)nsMsg.name)
857     /*
858      * Check if MessageQCopy object is valid. Technically we don't need it
859      * to send, but it is an indication of whether recovery is in process
860      */
861     if (NameServer_module->mq == NULL) {
862         LOG0("NameServer_getRemote: MessageQCopy not ready\n")
863         status = NameServer_E_NOTFOUND;
864         goto exit;
865     }
867     /* send message */
868     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
869             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerRemote_Msg),
870             TRUE);
871     if (mqcStatus < 0) {
872         LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
873         status = NameServer_E_NOTFOUND;
874         goto exit;
875     }
877     while (!done) {
878         /* Block on waitFd for signal from listener thread: */
879         waitFd = NameServer_module->waitFdR;
880         FD_ZERO(&rfds);
881         FD_SET(waitFd, &rfds);
882         maxfd = waitFd + 1;
883         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
884         ret = select(maxfd, &rfds, NULL, NULL, &tv);
885         if (ret == -1) {
886             LOG0("NameServer_getRemote: select failed.")
887             status = NameServer_E_FAIL;
888             goto exit;
889         }
890         else if (!ret) {
891             LOG0("NameServer_getRemote: select timed out.\n")
892             status = NameServer_E_TIMEOUT;
893             goto exit;
894         }
896         if (FD_ISSET(waitFd, &rfds)) {
897             /* Read, just to balance the write: */
898             numBytes = read(waitFd, &buf, sizeof(buf));
899             if (numBytes == -1) {
900                 LOG0("NameServer_getRemote: read failure\n")
901                 status = NameServer_E_FAIL;
902                 goto exit;
903             }
905             /* Process response: */
906             replyMsg = &NameServer_module->nsMsg;
908             if (replyMsg->seqNum != seqNum - 1) {
909                 /* Ignore responses without current sequence # */
910                 continue;
911             }
913             if (replyMsg->requestStatus) {
914                 /* name is found */
916                 /* set length to amount of data that was copied */
917                 *len = replyMsg->valueLen;
919                 /* set the contents of value */
920                 if (*len <= sizeof (Bits32)) {
921                     *(UInt32 *)value = (UInt32)replyMsg->value;
922                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
923                         procId, (String)replyMsg->instanceName)
924                     LOG2("%s, value: 0x%x...\n",
925                         (String)replyMsg->name, *(UInt32 *)value)
926                 }
927                 else {
928                     memcpy(value, replyMsg->valueBuf, *len);
929                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
930                         procId, (String)replyMsg->instanceName)
931                     LOG2("%s, value buffer at address: 0x%p...\n",
932                         (String)replyMsg->name, value)
933                 }
935                 goto exit;
936             }
937             else {
938                 /* name is not found */
939                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
940                      (String)replyMsg->instanceName, (String)replyMsg->name)
942                 /* set status to not found */
943                 status = NameServer_E_NOTFOUND;
944             }
945         }
946         done = TRUE;
947     }
948 exit:
949     pthread_mutex_unlock(&NameServer_module->modGate);
951     return (status);
954 /* Function to retrieve the value portion of a name/value pair from
955  * local table.
956  */
957 Int NameServer_get(NameServer_Handle handle,
958                String            name,
959                Ptr               value,
960                UInt32 *          len,
961                UInt16            procId[])
963     Int status = NameServer_S_SUCCESS;
964     UInt16 numProcs = MultiProc_getNumProcessors();
965     UInt32 i;
967     if (procId == NULL) {
968         status = NameServer_getLocal(handle, name, value, len);
969         if (status == NameServer_E_NOTFOUND) {
970             for (i = 0; i < numProcs; i++) {
971                 /* getLocal call already covers "self", keep going */
972                 if (i == MultiProc_self()) {
973                     continue;
974                 }
976                 status = NameServer_getRemote(handle, name, value, len, i);
978                 if ((status >= 0) ||
979                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
980                     (status != NameServer_E_TIMEOUT))) {
981                     break;
982                 }
983             }
984         }
985     }
986     else {
987         /*
988          *  Search the query list. It might contain the local proc
989          *  somewhere in the list.
990          */
991         i = 0;
992         while (procId[i] != MultiProc_INVALIDID) {
993             if (procId[i] == MultiProc_self()) {
994                 status = NameServer_getLocal(handle, name, value, len);
995             }
996             else {
997                 status = NameServer_getRemote(handle, name, value, len, i);
998             }
1000             if ((status >= 0) ||
1001                 ((status < 0) && (status != NameServer_E_NOTFOUND)
1002                 && (status != NameServer_E_TIMEOUT))) {
1003                 break;
1004             }
1006             i++;
1007         }
1008     }
1010     return (status);
1013 /* Gets a 32-bit value by name */
1014 Int NameServer_getUInt32(NameServer_Handle handle,
1015                      String            name,
1016                      Ptr               value,
1017                      UInt16            procId[])
1019     Int  status;
1020     UInt32 len = sizeof(UInt32);
1022     assert(handle != NULL);
1023     assert(name   != NULL);
1024     assert(value  != NULL);
1025     assert(NameServer_module->refCount != 0);
1027     status = NameServer_get(handle, name, value, &len, procId);
1029     return (status);
1032 /* Function to Retrieve the value portion of a name/value pair from
1033  * local table.
1034  */
1035 Int NameServer_getLocal(NameServer_Handle handle,
1036                     String            name,
1037                     Ptr               value,
1038                     UInt32 *          len)
1040     Int status = NameServer_E_NOTFOUND;
1041     NameServer_TableEntry * node = NULL;
1042     NameServer_TableEntry * temp = NULL;
1043     Bool done   = FALSE;
1044     UInt32 length;
1045     UInt32 hash;
1047     assert(handle != NULL);
1048     assert(name   != NULL);
1049     assert(value  != NULL);
1050     assert(len    != NULL);
1051     assert(NameServer_module->refCount != 0);
1053     length = *len;
1055     /* Calculate the hash */
1056     hash = stringHash(name);
1058     pthread_mutex_lock(&handle->gate);
1060     /* Traverse the list to find duplicate check */
1061     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1062         if (node->hash == hash) {
1063             if (node->collide == TRUE) {
1064                 temp = node;
1065                 while (temp) {
1066                     if (strcmp(temp->name, name) == 0u){
1067                         if (length <= node->len) {
1068                             memcpy(value, node->value, length);
1069                             *len = length;
1070                         }
1071                         else {
1072                             memcpy(value, node->value, node->len);
1073                             *len = node->len;
1074                         }
1075                         done = TRUE;
1076                         break;
1077                     }
1078                     temp = temp->next;
1079                 }
1080                 break;
1081             }
1082             else {
1083                 if (length <= node->len) {
1084                     memcpy(value, node->value, length);
1085                     *len = length;
1086                 }
1087                 else {
1088                     memcpy(value, node->value, node->len);
1089                     *len = node->len;
1090                 }
1091                 done = TRUE;
1092                 break;
1093             }
1094         }
1095     }
1097     pthread_mutex_unlock(&handle->gate);
1099     if (done == FALSE) {
1100         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1101     }
1102     else {
1103         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1104              node->name, (UInt32)node->value)
1105         status = NameServer_S_SUCCESS;
1106     }
1108     return (status);
1111 /*
1112  *  Gets a 32-bit value by name from the local table
1113  *
1114  *  If the name is found, the 32-bit value is copied into the value
1115  *  argument and a success status is returned.
1116  *
1117  *  If the name is not found, zero is returned in len and the contents
1118  *  of value are not modified. Not finding a name is not considered
1119  *  an error.
1120  *
1121  *  This function only searches the local name/value table.
1122  *
1123  */
1124 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1126     Int                 status;
1127     UInt32              len    = sizeof(UInt32);
1129     assert(handle != NULL);
1130     assert(name   != NULL);
1131     assert(value  != NULL);
1132     assert(NameServer_module->refCount != 0);
1134     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1135     status = NameServer_getLocal(handle, name, value, &len);
1137     return (status);
1140 Void NameServer_preRecovery(Void)
1142     Int status;
1144     pthread_mutex_lock(&NameServer_module->modGate);
1146     if (NameServer_module->mq != NULL) {
1147         status = MessageQCopy_delete(&NameServer_module->mq);
1148         if (status < 0) {
1149             LOG0("NameServer_preRecovery: Cannot delete MessageQCopy\n");
1150         }
1151         NameServer_module->mq = NULL;
1152     }
1154     pthread_mutex_unlock(&NameServer_module->modGate);
1157 Int NameServer_postRecovery(Void)
1159     Int status = NameServer_S_SUCCESS;
1161     pthread_mutex_lock(&NameServer_module->modGate);
1163     /* Create the MessageQCopy for receiving messages from all remote proc */
1164     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
1165         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
1167     if (NameServer_module->mq == NULL) {
1168         status = NameServer_E_FAIL;
1169         LOG0("NameServer_postRecovery: failed to create MessageQCopy instance.\n")
1170     }
1172     pthread_mutex_unlock(&NameServer_module->modGate);
1174     return (status);
1177 #if defined (__cplusplus)
1179 #endif /* defined (__cplusplus) */