425b0678dca960b22b734e39199488c626d19c8e
[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 <ti/syslink/utils/Trace.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         GT_2trace(curTrace, GT_1CLASS, "NameServer Request: "
242                   "instanceName: %s, name: %s",
243                   (String)msg->instanceName, (String)msg->name);
245         assert(msg->valueLen <= MAXVALUELEN);
247         /*
248          *  Message is a request. Lookup name in NameServer table.
249          *  Send a response message back to source processor.
250          */
251         handle = NameServer_getHandle((String)msg->instanceName);
253         if (handle != NULL) {
254             /* Search for the NameServer entry */
255             if (msg->valueLen <= sizeof (Bits32)) {
256                 GT_0trace(curTrace, GT_1CLASS, "Calling NameServer_getLocalUInt32...");
257                 status = NameServer_getLocalUInt32(handle,
258                      (String)msg->name, &msg->value);
259             }
260             else {
261                 GT_0trace(curTrace, GT_1CLASS, "Calling NameServer_getLocal...");
262                 status = NameServer_getLocal(handle,
263                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
264             }
265         }
267         GT_2trace(curTrace, GT_1CLASS,
268              "NameServer Response: instanceName: %s, name: %s,",
269              (String)msg->instanceName, (String)msg->name);
270         /* set the request status */
271         if (status < 0) {
272             GT_1trace(curTrace, GT_1CLASS, " Value not found, status: %d",
273                       status);
274             msg->requestStatus = 0;
275         }
276         else {
277             msg->requestStatus = 1;
278             GT_1trace(curTrace, GT_1CLASS, " Value: 0x%x", msg->value);
279         }
281         /* specify message as a response */
282         msg->request = NAMESERVER_RESPONSE;
283         msg->reserved = NAMESERVER_MSG_TOKEN;
285         pthread_mutex_lock(&NameServer_module->modGate);
287         /*
288          * Check if MessageQCopy object is valid. If not, we received a request
289          * but we are not able to respond to it due to recovery.
290          * We will simply drop the request.
291          */
292         if (NameServer_module->mq == NULL) {
293             GT_0trace(curTrace, GT_3CLASS,
294                       "NameServerRemote_processMessage: MessageQCopy not ready."
295                       " Request dropped.");
296         }
297         else {
298             /* send response message to remote processor */
299             status = MessageQCopy_send(procId, MultiProc_self(),
300                 MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
301                 sizeof(NameServerRemote_Msg), TRUE);
302             if (status < 0) {
303                 GT_setFailureReason(curTrace, GT_4CLASS,
304                                     "NameServerRemote_processMessage",
305                                     status, "MessageQCopy_send failed");
306             }
307         }
309         pthread_mutex_unlock(&NameServer_module->modGate);
310     }
311     else {
312         GT_3trace(curTrace, GT_1CLASS, "NameServer Reply: instanceName: %s, "
313              "name: %s, value: 0x%x", (String)msg->instanceName,
314              (String)msg->name, msg->value);
316         /* Save the response message.  */
317         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerRemote_Msg));
319         /* Post the eventfd upon which NameServer_get() is waiting */
320         write(waitFd, &buf, sizeof(buf));
321     }
324 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
325     void * priv, UInt32 src, UInt16 srcProc)
327     NameServerRemote_Msg msg;
329     GT_6trace(curTrace, GT_ENTER, "_listener_cb", handle, data, len, priv, src, srcProc);
331     GT_1trace(curTrace, GT_1CLASS, "NameServer: Listener got NameServer message "
332          "from MessageQCopy: 0x%p!\n", handle);
333     /* Get NameServer message and process: */
334     memcpy(&msg, data, len);
336     if (len != sizeof(NameServerRemote_Msg)) {
337         GT_1trace(curTrace, GT_4CLASS, "NameServer: got bad "
338                   "NameServerRemote_Msg len (%d)\n", len);
339     }
340     else {
341         GT_1trace(curTrace, GT_1CLASS, "listener_cb: "
342                   "read from MessageQCopy 0x%p", handle);
343         GT_3trace(curTrace, GT_1CLASS, "\tReceived ns msg: "
344                   "byte count: %d, from addr: %d, from vproc: %d",
345                   len, src, srcProc);
346         NameServerRemote_processMessage(&msg, srcProc);
347     }
350 /* =============================================================================
351  * APIS
352  * =============================================================================
353  */
355 /* Function to setup the nameserver module. */
356 Int NameServer_setup(Void)
358     Int    status = NameServer_S_SUCCESS;
359     int    fd[2];
361     pthread_mutex_lock(&NameServer_module->modGate);
363     GT_1trace(curTrace, GT_ENTER, "NameServer_setup: refCount",
364               NameServer_module->refCount);
366     NameServer_module->refCount++;
368     if (NameServer_module->refCount > 1) {
369         GT_0trace(curTrace, GT_1CLASS, "NameServer_setup: already setup");
370         status = NameServer_S_ALREADYSETUP;
371         goto exit;
372     }
374     if (pipe(fd) == -1) {
375         status = NameServer_E_FAIL;
376         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_setup", status,
377                             "failed to create waitFd.");
378         goto exit;
379     }
380     NameServer_module->waitFdW = fd[1];
381     NameServer_module->waitFdR = fd[0];
383     /* Create the MessageQCopy for receiving messages from all remote proc */
384     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
385         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
387     if (NameServer_module->mq == NULL) {
388         status = NameServer_E_FAIL;
389         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_setup", status,
390                             "failed to create MessageQCopy instance.");
391         goto exit;
392     }
394     /* Construct the list object */
395     CIRCLEQ_INIT(&NameServer_module->objList);
397 exit:
398     GT_1trace(curTrace, GT_LEAVE, "NameServer_setup: refCount",
399               NameServer_module->refCount);
401     pthread_mutex_unlock(&NameServer_module->modGate);
403     return (status);
406 /*! Function to destroy the nameserver module. */
407 Int NameServer_destroy(void)
409     Int      status    = NameServer_S_SUCCESS;
411     pthread_mutex_lock(&NameServer_module->modGate);
413     GT_1trace(curTrace, GT_ENTER, "NameServer_destroy: refCount",
414               NameServer_module->refCount);
416     NameServer_module->refCount--;
418     if (NameServer_module->refCount > 0) {
419         GT_1trace(curTrace, GT_1CLASS,
420                   "NameServer_destroy(): refCount(%d) > 0, exiting",
421                   NameServer_module->refCount);
422         status = NameServer_S_SUCCESS;
424         goto exit;
425     }
427     /* Delete the MessageQCopy instances */
428     if (NameServer_module->mq != NULL) {
429         MessageQCopy_delete(&NameServer_module->mq);
430     }
432     CIRCLEQ_destruct(&NameServer_module->objList);
434     close(NameServer_module->waitFdW);
435     close(NameServer_module->waitFdR);
437 exit:
438     GT_1trace(curTrace, GT_LEAVE, "NameServer_destroy: refCount",
439               NameServer_module->refCount);
441     pthread_mutex_unlock(&NameServer_module->modGate);
443     return (status);
446 /* Function to retrieve a NameServer handle from name. */
447 NameServer_Handle NameServer_getHandle(String name)
449     NameServer_Handle handle = NULL;
450     Bool              found = FALSE;
451     struct NameServer_Object * elem;
453     assert(name != NULL);
454     assert(NameServer_module->refCount != 0);
456     pthread_mutex_lock(&NameServer_module->modGate);
458     /* Lookup handle from name: */
459     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
460         handle = (NameServer_Handle) elem;
461         if (strcmp(handle->name, name) == 0) {
462             found = TRUE;
463             break;
464         }
465     }
467     if (found == FALSE) {
468         handle = NULL;
469     }
471     pthread_mutex_unlock(&NameServer_module->modGate);
473     return (handle);
477 /* Function to create a name server. */
478 NameServer_Handle NameServer_create(String name,
479                                     const NameServer_Params * params)
481     NameServer_Handle handle = NULL;
482     pthread_mutexattr_t mutex_attr;
484     assert(params != NULL);
485     assert(name != NULL);
486     assert(NameServer_module->refCount != 0);
488     GT_1trace(curTrace, GT_1CLASS, "NameServer_create(): '%s'\n", name);
490     pthread_mutex_lock(&NameServer_module->modGate);
492     /* check if the name is already created or not */
493     handle = NameServer_getHandle(name);
494     if (handle != NULL) {
495         if (memcmp((Ptr)&handle->params, (Ptr)params,
496             sizeof(NameServer_Params)) == 0) {
497             handle->refCount++;
498         }
499         else {
500             GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_create",
501                                 NameServer_E_FAIL, "NameServer params mismatch");
502             handle = NULL;
503         }
504         goto leave;
505     }
506     else {
507         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
508     }
510     if (!handle) {
511         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_create",
512                             NameServer_E_FAIL, "NameServer_Handle alloc failed");
513         goto leave;
514     }
516     handle->refCount = 1;
517     handle->name = (String)malloc(strlen(name) + 1u);
518     if (!handle->name) {
519         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_create",
520                             NameServer_E_FAIL, "instance name alloc failed");
521         goto cleanup;
522     }
523     strncpy(handle->name, name, strlen (name) + 1u);
524     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
526     assert(params.maxValueLen <= MAXVALUELEN);
528     if (params->maxValueLen < sizeof(UInt32)) {
529         handle->params.maxValueLen = sizeof(UInt32);
530     }
531     else {
532         handle->params.maxValueLen = params->maxValueLen;
533     }
535     CIRCLEQ_INIT(&handle->nameList);
536     handle->count = 0u;
538     /* Put in the local list */
539     CIRCLEQ_elemClear(&handle->elem);
540     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
542     /*
543      * NameServer_removeEntry() enters gate and is called by
544      * NameServer_remove() while holding the gate.
545      */
546     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
547     pthread_mutex_init(&handle->gate, &mutex_attr);
549     goto leave;
551 cleanup:
552     free(handle);
553     handle = NULL;
555 leave:
556     pthread_mutex_unlock(&NameServer_module->modGate);
558     return (handle);
562 /* Function to delete a name server. */
563 Int NameServer_delete(NameServer_Handle * handle)
565     Int status = NameServer_S_SUCCESS;
567     assert(handle != NULL);
568     assert(*handle != NULL);
569     assert((*handle)->count == 0);
570     assert(NameServer_module->refCount != 0);
572     pthread_mutex_lock(&NameServer_module->modGate);
574     (*handle)->refCount--;
575     if ((*handle)->refCount != 0) {
576         goto leave;
577     }
579     if ((*handle)->count == 0) {
580         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
582         if ((*handle)->name != NULL) {
583             free((*handle)->name);
584             (*handle)->name = NULL;
585         }
587         CIRCLEQ_destruct(&(*handle)->nameList);
589         pthread_mutex_destroy(&(*handle)->gate);
591         free((*handle));
592         (*handle) = NULL;
593     }
595 leave:
596     pthread_mutex_unlock(&NameServer_module->modGate);
598     return (status);
601 /* Adds a variable length value into the local NameServer table */
602 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
604     Int                 status = NameServer_S_SUCCESS;
605     NameServer_TableEntry * node = NULL;
606     NameServer_TableEntry * new_node = NULL;
607     Bool                found = FALSE;
608     UInt32              hash;
610     assert(handle != NULL);
611     assert(name     != NULL);
612     assert(buf      != NULL);
613     assert(len      != 0);
614     assert(NameServer_module->refCount != 0);
616     /* Calculate the hash */
617     hash = stringHash(name);
619     pthread_mutex_lock(&handle->gate);
621     if (strlen(name) > handle->params.maxNameLen - 1) {
622         status = NameServer_E_INVALIDARG;
623         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status,
624                             "name length exceeded maximum!");
625         new_node = NULL;
626         goto exit;
627     }
629     if (len > handle->params.maxValueLen) {
630         status = NameServer_E_INVALIDARG;
631         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status,
632                             "value length exceeded maximum!");
633         new_node = NULL;
634         goto exit;
635     }
637     /* Traverse the list to find duplicate check */
638     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
639         /* Hash matches */
640         if (node->hash == hash) {
641             /* If the name matches, incase hash is duplicate */
642             if (strcmp(node->name, name) == 0) {
643                 if (handle->params.checkExisting == TRUE) {
644                     status = NameServer_E_INVALIDARG;
645                     GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status, "duplicate entry found!");
646                     GT_1trace(curTrace, GT_3CLASS, "\t'%s' - duplicate entry found!", name);
647                     break;
648                 }
649             }
650             else {
651                 found = TRUE;
652                 break;
653             } /* name does not match */
654         } /* hash does not match */
655     } /* CIRCLEQ_traverse */
657     if (status != NameServer_S_SUCCESS) {
658         new_node = NULL;
659         goto exit;
660     }
662     /* Now add the new entry. */
663     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
664     if (new_node == NULL) {
665         status = NameServer_E_MEMORY;
666         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status,
667                             "malloc new_node failed!");
669         goto exit;
670     }
672     new_node->hash    = hash;
673     new_node->collide = found; /* Indicate if there is a collision*/
674     new_node->len     = len;
675     new_node->next    = NULL;
676     new_node->name = (String)malloc(strlen(name) + 1u);
677     new_node->value  = (Ptr)malloc(len);
678     strncpy(new_node->name, name, strlen(name) + 1u);
679     memcpy((Ptr)new_node->value, (Ptr)buf, len);
681     if (found == TRUE) {
682         /* If hash is found, need to stitch the list to link the
683          * new node to the existing node with the same hash.
684          */
685         new_node->next = node->next;
686         node->next = new_node;
687     }
688     else {
689         /* put the new node into the list */
690         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
691     }
693     handle->count++;
695     /* Only print a single byte of buf. Address may not be 32-bit aligned */
696     GT_2trace(curTrace, GT_1CLASS,
697               "NameServer_add: Entered key: '%s', data: 0x%x",
698               name, *(UInt8 *)buf);
699 exit:
700     pthread_mutex_unlock(&handle->gate);
702     return (new_node);
706 /* Function to add a UInt32 value into a name server. */
707 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
709     Ptr entry = NULL;
711     assert(handle != NULL);
712     assert(name   != NULL);
713     assert(NameServer_module->refCount != 0);
715     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
717     return (entry);
720 /* Function to remove a name/value pair from a name server. */
721 Int NameServer_remove(NameServer_Handle handle, String name)
723     Int                 status = NameServer_S_SUCCESS;
724     NameServer_TableEntry *prev = NULL;
725     NameServer_TableEntry *temp = NULL;
726     NameServer_TableEntry *node = NULL;
727     Bool                done   = FALSE;
728     UInt32              hash;
730     assert(handle != NULL);
731     assert(name   != NULL);
732     assert(NameServer_module->refCount != 0);
734     /* Calculate the hash */
735     hash = stringHash(name);
737     pthread_mutex_lock(&handle->gate);
739     /* Traverse the list to find duplicate check */
740     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
741         /* Hash matchs */
742         if (node->hash == hash) {
743             if (node->collide == TRUE) {
744                 if (strcmp(node->name, name) == 0){
745                     free(node->value);
746                     free(node->name);
747                     memcpy((Ptr)node, (Ptr) node->next,
748                            sizeof(NameServer_TableEntry));
749                     node->next = node->next->next;
750                     free(node->next);
751                     handle->count--;
752                     done = TRUE;
753                     break;
754                 }
755                 else {
756                     prev = node;
757                     temp = node->next;
758                     while (temp) {
759                         if (strcmp(temp->name, name) == 0){
760                             free(temp->value);
761                             free(temp->name);
762                             prev->next = temp->next;
763                             free(temp);
764                             handle->count--;
765                             done = TRUE;
766                             break;
767                         }
768                         temp = temp->next;
769                     }
770                     break;
771                 }
772             }
773             else {
774                 NameServer_removeEntry(handle, (Ptr)node);
776                 done = TRUE;
777                 break;
778             }
779         }
780     }
782     if (done == FALSE) {
783         status = NameServer_E_INVALIDARG;
784         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_remove", status,
785                             " Entry not found!");
786     }
788     pthread_mutex_unlock(&handle->gate);
790     return (status);
793 /* Function to remove a name/value pair from a name server. */
794 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
796     Int  status = NameServer_S_SUCCESS;
797     NameServer_TableEntry * node;
799     assert(handle != NULL);
800     assert(entry  != NULL);
801     assert(NameServer_module->refCount != 0);
803     pthread_mutex_lock(&handle->gate);
805     node = (NameServer_TableEntry *)entry;
807     free(node->value);
808     free(node->name);
809     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
810     free(node);
811     handle->count--;
813     pthread_mutex_unlock(&handle->gate);
815     return (status);
819 /* Initialize this config-params structure with supplier-specified
820  * defaults before instance creation.
821  */
822 Void NameServer_Params_init(NameServer_Params * params)
824     assert(params != NULL);
826     memcpy(params, &(NameServer_module->defInstParams),
827            sizeof (NameServer_Params));
831 Int NameServer_getRemote(NameServer_Handle handle,
832                      String            name,
833                      Ptr               value,
834                      UInt32 *          len,
835                      UInt16            procId)
837     Int status = NameServer_S_SUCCESS;
838     Int mqcStatus = -1;
839     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
840     NameServerRemote_Msg nsMsg;
841     NameServerRemote_Msg *replyMsg;
842     fd_set rfds;
843     int ret = 0, maxfd, waitFd;
844     struct timeval tv;
845     char buf = '1';
846     int numBytes;
847     static int seqNum = 0;
848     Bool done = FALSE;
850     if (strlen(name) >= MAXNAMEINCHAR) {
851         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
852                             NameServer_E_NAMETOOLONG,
853                             "Name is too long in remote query");
854         return NameServer_E_NAMETOOLONG;
855     }
857     if (strlen(obj->name) >= MAXNAMEINCHAR) {
858         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
859                             NameServer_E_NAMETOOLONG,
860                             "Instance name is too long for remote query");
861         return NameServer_E_NAMETOOLONG;
862     }
864     pthread_mutex_lock(&NameServer_module->modGate);
866     /* Set Timeout to wait: */
867     tv.tv_sec = 0;
868     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
870     /* Create request message and send to remote processor: */
871     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
872     nsMsg.request = NAMESERVER_REQUEST;
873     nsMsg.requestStatus = 0;
874     nsMsg.valueLen = *len;
875     nsMsg.seqNum = seqNum++;
877     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
878     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
880     GT_3trace(curTrace, GT_1CLASS,
881               "NameServer_getRemote: Requesting from procId %d, %s:%s...",
882               procId, (String)nsMsg.instanceName, (String)nsMsg.name);
884     /*
885      * Check if MessageQCopy object is valid. Technically we don't need it
886      * to send, but it is an indication of whether recovery is in process
887      */
888     if (NameServer_module->mq == NULL) {
889         status = NameServer_E_NOTFOUND;
890         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
891                             status, "MessageQCopy not ready");
892         goto exit;
893     }
895     /* send message */
896     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
897             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerRemote_Msg),
898             TRUE);
899     if (mqcStatus < 0) {
900         status = NameServer_E_NOTFOUND;
901         GT_1trace(curTrace, GT_3CLASS, "NameServer_getRemote: "
902                   "Can't send to remote endpoint on procId %d", procId);
903         goto exit;
904     }
906     while (!done) {
907         /* Block on waitFd for signal from listener thread: */
908         waitFd = NameServer_module->waitFdR;
909         FD_ZERO(&rfds);
910         FD_SET(waitFd, &rfds);
911         maxfd = waitFd + 1;
912         GT_1trace(curTrace, GT_1CLASS, "NameServer_getRemote: pending on waitFd: %d\n", waitFd);
913         ret = select(maxfd, &rfds, NULL, NULL, &tv);
914         if (ret == -1) {
915             status = NameServer_E_FAIL;
916             GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
917                                 status, "select failed.");
918             goto exit;
919         }
920         else if (!ret) {
921             status = NameServer_E_TIMEOUT;
922             GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
923                                 status, "select timed out.");
924             goto exit;
925         }
927         if (FD_ISSET(waitFd, &rfds)) {
928             /* Read, just to balance the write: */
929             numBytes = read(waitFd, &buf, sizeof(buf));
930             if (numBytes == -1) {
931                 status = NameServer_E_FAIL;
932                 GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
933                                     status, "read failure");
934                 goto exit;
935             }
937             /* Process response: */
938             replyMsg = &NameServer_module->nsMsg;
940             if (replyMsg->seqNum != seqNum - 1) {
941                 /* Ignore responses without current sequence # */
942                 continue;
943             }
945             if (replyMsg->requestStatus) {
946                 /* name is found */
948                 /* set length to amount of data that was copied */
949                 *len = replyMsg->valueLen;
951                 /* set the contents of value */
952                 if (*len <= sizeof (Bits32)) {
953                     *(UInt32 *)value = (UInt32)replyMsg->value;
954                     GT_4trace(curTrace, GT_1CLASS, "NameServer_getRemote: "
955                               "Reply from: %d, %s:%s, value: 0x%x...", procId,
956                               (String)replyMsg->instanceName,
957                               (String)replyMsg->name, *(UInt32 *)value);
958                 }
959                 else {
960                     memcpy(value, replyMsg->valueBuf, *len);
961                     GT_4trace(curTrace, GT_1CLASS, "NameServer_getRemote: "
962                               "Reply from: %d, %s:%s, value buffer at address:"
963                               " 0x%p...", procId,
964                               (String)replyMsg->instanceName,
965                               (String)replyMsg->name, value);
966                 }
968                 goto exit;
969             }
970             else {
971                 /* name is not found */
972                 GT_2trace(curTrace, GT_3CLASS, "NameServer_getRemote: "
973                           "value for %s:%s not found.",
974                           (String)replyMsg->instanceName,
975                           (String)replyMsg->name);
977                 /* set status to not found */
978                 status = NameServer_E_NOTFOUND;
979             }
980         }
981         done = TRUE;
982     }
983 exit:
984     pthread_mutex_unlock(&NameServer_module->modGate);
986     return (status);
989 /* Function to retrieve the value portion of a name/value pair from
990  * local table.
991  */
992 Int NameServer_get(NameServer_Handle handle,
993                String            name,
994                Ptr               value,
995                UInt32 *          len,
996                UInt16            procId[])
998     Int status = NameServer_S_SUCCESS;
999     UInt16 numProcs = MultiProc_getNumProcessors();
1000     UInt32 i;
1002     if (procId == NULL) {
1003         status = NameServer_getLocal(handle, name, value, len);
1004         if (status == NameServer_E_NOTFOUND) {
1005             for (i = 0; i < numProcs; i++) {
1006                 /* getLocal call already covers "self", keep going */
1007                 if (i == MultiProc_self()) {
1008                     continue;
1009                 }
1011                 status = NameServer_getRemote(handle, name, value, len, i);
1013                 if ((status >= 0) ||
1014                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1015                     (status != NameServer_E_TIMEOUT))) {
1016                     break;
1017                 }
1018             }
1019         }
1020     }
1021     else {
1022         /*
1023          *  Search the query list. It might contain the local proc
1024          *  somewhere in the list.
1025          */
1026         i = 0;
1027         while (procId[i] != MultiProc_INVALIDID) {
1028             if (procId[i] == MultiProc_self()) {
1029                 status = NameServer_getLocal(handle, name, value, len);
1030             }
1031             else {
1032                 status = NameServer_getRemote(handle, name, value, len, i);
1033             }
1035             if ((status >= 0) ||
1036                 ((status < 0) && (status != NameServer_E_NOTFOUND)
1037                 && (status != NameServer_E_TIMEOUT))) {
1038                 break;
1039             }
1041             i++;
1042         }
1043     }
1045     return (status);
1048 /* Gets a 32-bit value by name */
1049 Int NameServer_getUInt32(NameServer_Handle handle,
1050                      String            name,
1051                      Ptr               value,
1052                      UInt16            procId[])
1054     Int  status;
1055     UInt32 len = sizeof(UInt32);
1057     assert(handle != NULL);
1058     assert(name   != NULL);
1059     assert(value  != NULL);
1060     assert(NameServer_module->refCount != 0);
1062     status = NameServer_get(handle, name, value, &len, procId);
1064     return (status);
1067 /* Function to Retrieve the value portion of a name/value pair from
1068  * local table.
1069  */
1070 Int NameServer_getLocal(NameServer_Handle handle,
1071                     String            name,
1072                     Ptr               value,
1073                     UInt32 *          len)
1075     Int status = NameServer_E_NOTFOUND;
1076     NameServer_TableEntry * node = NULL;
1077     NameServer_TableEntry * temp = NULL;
1078     Bool done   = FALSE;
1079     UInt32 length;
1080     UInt32 hash;
1082     assert(handle != NULL);
1083     assert(name   != NULL);
1084     assert(value  != NULL);
1085     assert(len    != NULL);
1086     assert(NameServer_module->refCount != 0);
1088     length = *len;
1090     /* Calculate the hash */
1091     hash = stringHash(name);
1093     pthread_mutex_lock(&handle->gate);
1095     /* Traverse the list to find duplicate check */
1096     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1097         if (node->hash == hash) {
1098             if (node->collide == TRUE) {
1099                 temp = node;
1100                 while (temp) {
1101                     if (strcmp(temp->name, name) == 0u){
1102                         if (length <= node->len) {
1103                             memcpy(value, node->value, length);
1104                             *len = length;
1105                         }
1106                         else {
1107                             memcpy(value, node->value, node->len);
1108                             *len = node->len;
1109                         }
1110                         done = TRUE;
1111                         break;
1112                     }
1113                     temp = temp->next;
1114                 }
1115                 break;
1116             }
1117             else {
1118                 if (length <= node->len) {
1119                     memcpy(value, node->value, length);
1120                     *len = length;
1121                 }
1122                 else {
1123                     memcpy(value, node->value, node->len);
1124                     *len = node->len;
1125                 }
1126                 done = TRUE;
1127                 break;
1128             }
1129         }
1130     }
1132     pthread_mutex_unlock(&handle->gate);
1134     if (done == FALSE) {
1135         GT_1trace(curTrace, GT_1CLASS,
1136                   "NameServer_getLocal: entry key: '%s' not found!", name);
1137     }
1138     else {
1139         GT_2trace(curTrace, GT_1CLASS, "NameServer_getLocal: Found entry key: "
1140                   "'%s', data: 0x%x", node->name, (UInt32)node->value);
1141         status = NameServer_S_SUCCESS;
1142     }
1144     return (status);
1147 /*
1148  *  Gets a 32-bit value by name from the local table
1149  *
1150  *  If the name is found, the 32-bit value is copied into the value
1151  *  argument and a success status is returned.
1152  *
1153  *  If the name is not found, zero is returned in len and the contents
1154  *  of value are not modified. Not finding a name is not considered
1155  *  an error.
1156  *
1157  *  This function only searches the local name/value table.
1158  *
1159  */
1160 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1162     Int                 status;
1163     UInt32              len    = sizeof(UInt32);
1165     assert(handle != NULL);
1166     assert(name   != NULL);
1167     assert(value  != NULL);
1168     assert(NameServer_module->refCount != 0);
1170     GT_0trace(curTrace, GT_1CLASS,
1171               "NameServer_getLocalUInt32: calling NameServer_getLocal()...");
1172     status = NameServer_getLocal(handle, name, value, &len);
1174     return (status);
1177 Void NameServer_preRecovery(Void)
1179     Int status;
1181     pthread_mutex_lock(&NameServer_module->modGate);
1183     if (NameServer_module->mq != NULL) {
1184         status = MessageQCopy_delete(&NameServer_module->mq);
1185         if (status < 0) {
1186             GT_setFailureReason(curTrace, GT_3CLASS, "NameServer_preRecovery", status,
1187                                 "Cannot delete MessageQCopy");
1188         }
1189         NameServer_module->mq = NULL;
1190     }
1192     pthread_mutex_unlock(&NameServer_module->modGate);
1195 Int NameServer_postRecovery(Void)
1197     Int status = NameServer_S_SUCCESS;
1199     pthread_mutex_lock(&NameServer_module->modGate);
1201     /* Create the MessageQCopy for receiving messages from all remote proc */
1202     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
1203         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
1205     if (NameServer_module->mq == NULL) {
1206         status = NameServer_E_FAIL;
1207         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_postRecovery", status,
1208                             "failed to create MessageQCopy instance.");
1209     }
1211     pthread_mutex_unlock(&NameServer_module->modGate);
1213     return (status);
1216 #if defined (__cplusplus)
1218 #endif /* defined (__cplusplus) */