QNX: NameServer_delete in NameServer daemon leaks memory
[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_elemClear(elem) { \
139         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
142 #define CIRCLEQ_traverse(x, y, tag) \
143         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
145 /* =============================================================================
146  *  Globals
147  * =============================================================================
148  */
149 /*
150  * NameServer_state
151  *
152  * Make the module gate "recursive" since NameServer_getHandle() needs to
153  * use it and NameServer_create() needs to hold it around its call to
154  * NameServer_getHandle().  Also, use the static initializer instead of a
155  * run-time init call, so we can use this gate immediately in _setup().
156  */
157 static NameServer_ModuleObject NameServer_state = {
158     .defInstParams.maxRuntimeEntries = 0u,
159     .defInstParams.tableHeap         = NULL,
160     .defInstParams.checkExisting     = TRUE,
161     .defInstParams.maxValueLen       = 0u,
162     .defInstParams.maxNameLen        = 16u,
163 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
164     .modGate                         = PTHREAD_RMUTEX_INITIALIZER,
165     .refCount                        = 0
166 };
168 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
170 static const UInt32 stringCrcTab[256u] = {
171   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
172   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
173   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
174   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
175   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
176   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
177   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
178   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
179   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
180   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
181   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
182   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
183   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
184   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
185   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
186   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
187   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
188   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
189   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
190   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
191   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
192   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
193   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
194   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
195   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
196   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
197   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
198   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
199   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
200   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
201   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
202   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
203   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
204   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
205   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
206   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
207   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
208   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
209   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
210   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
211   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
212   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
213   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
214 };
216 static UInt32 stringHash(String s)
218     UInt32 hash = strlen(s);
219     UInt32 i;
221     for (i = 0; i < strlen(s); i++) {
222         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
223     }
225     return (hash);
228 static void NameServerRemote_processMessage(NameServerRemote_Msg * msg, UInt16 procId)
230     NameServer_Handle handle;
231     Int               status = NameServer_E_FAIL;
232     char              buf = 'n';
233     int               waitFd = NameServer_module->waitFdW;
235     if (msg->request == NAMESERVER_REQUEST) {
236         GT_2trace(curTrace, GT_1CLASS, "NameServer Request: "
237                   "instanceName: %s, name: %s",
238                   (String)msg->instanceName, (String)msg->name);
240         assert(msg->valueLen <= MAXVALUELEN);
242         /*
243          *  Message is a request. Lookup name in NameServer table.
244          *  Send a response message back to source processor.
245          */
246         handle = NameServer_getHandle((String)msg->instanceName);
248         if (handle != NULL) {
249             /* Search for the NameServer entry */
250             if (msg->valueLen <= sizeof (Bits32)) {
251                 GT_0trace(curTrace, GT_1CLASS, "Calling NameServer_getLocalUInt32...");
252                 status = NameServer_getLocalUInt32(handle,
253                      (String)msg->name, &msg->value);
254             }
255             else {
256                 GT_0trace(curTrace, GT_1CLASS, "Calling NameServer_getLocal...");
257                 status = NameServer_getLocal(handle,
258                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
259             }
260         }
262         GT_2trace(curTrace, GT_1CLASS,
263              "NameServer Response: instanceName: %s, name: %s,",
264              (String)msg->instanceName, (String)msg->name);
265         /* set the request status */
266         if (status < 0) {
267             GT_1trace(curTrace, GT_1CLASS, " Value not found, status: %d",
268                       status);
269             msg->requestStatus = 0;
270         }
271         else {
272             msg->requestStatus = 1;
273             GT_1trace(curTrace, GT_1CLASS, " Value: 0x%x", msg->value);
274         }
276         /* specify message as a response */
277         msg->request = NAMESERVER_RESPONSE;
278         msg->reserved = NAMESERVER_MSG_TOKEN;
280         pthread_mutex_lock(&NameServer_module->modGate);
282         /*
283          * Check if MessageQCopy object is valid. If not, we received a request
284          * but we are not able to respond to it due to recovery.
285          * We will simply drop the request.
286          */
287         if (NameServer_module->mq == NULL) {
288             GT_0trace(curTrace, GT_3CLASS,
289                       "NameServerRemote_processMessage: MessageQCopy not ready."
290                       " Request dropped.");
291         }
292         else {
293             /* send response message to remote processor */
294             status = MessageQCopy_send(procId, MultiProc_self(),
295                 MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
296                 sizeof(NameServerRemote_Msg), TRUE);
297             if (status < 0) {
298                 GT_setFailureReason(curTrace, GT_4CLASS,
299                                     "NameServerRemote_processMessage",
300                                     status, "MessageQCopy_send failed");
301             }
302         }
304         pthread_mutex_unlock(&NameServer_module->modGate);
305     }
306     else {
307         GT_3trace(curTrace, GT_1CLASS, "NameServer Reply: instanceName: %s, "
308              "name: %s, value: 0x%x", (String)msg->instanceName,
309              (String)msg->name, msg->value);
311         /* Save the response message.  */
312         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerRemote_Msg));
314         /* Post the eventfd upon which NameServer_get() is waiting */
315         write(waitFd, &buf, sizeof(buf));
316     }
319 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
320     void * priv, UInt32 src, UInt16 srcProc)
322     NameServerRemote_Msg msg;
324     GT_6trace(curTrace, GT_ENTER, "_listener_cb", handle, data, len, priv, src, srcProc);
326     GT_1trace(curTrace, GT_1CLASS, "NameServer: Listener got NameServer message "
327          "from MessageQCopy: 0x%p!\n", handle);
328     /* Get NameServer message and process: */
329     memcpy(&msg, data, len);
331     if (len != sizeof(NameServerRemote_Msg)) {
332         GT_1trace(curTrace, GT_4CLASS, "NameServer: got bad "
333                   "NameServerRemote_Msg len (%d)\n", len);
334     }
335     else {
336         GT_1trace(curTrace, GT_1CLASS, "listener_cb: "
337                   "read from MessageQCopy 0x%p", handle);
338         GT_3trace(curTrace, GT_1CLASS, "\tReceived ns msg: "
339                   "byte count: %d, from addr: %d, from vproc: %d",
340                   len, src, srcProc);
341         NameServerRemote_processMessage(&msg, srcProc);
342     }
345 /* =============================================================================
346  * APIS
347  * =============================================================================
348  */
350 /* Function to setup the nameserver module. */
351 Int NameServer_setup(Void)
353     Int    status = NameServer_S_SUCCESS;
354     int    fd[2];
356     pthread_mutex_lock(&NameServer_module->modGate);
358     GT_1trace(curTrace, GT_ENTER, "NameServer_setup: refCount",
359               NameServer_module->refCount);
361     NameServer_module->refCount++;
363     if (NameServer_module->refCount > 1) {
364         GT_0trace(curTrace, GT_1CLASS, "NameServer_setup: already setup");
365         status = NameServer_S_ALREADYSETUP;
366         goto exit;
367     }
369     if (pipe(fd) == -1) {
370         status = NameServer_E_FAIL;
371         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_setup", status,
372                             "failed to create waitFd.");
373         goto exit;
374     }
375     NameServer_module->waitFdW = fd[1];
376     NameServer_module->waitFdR = fd[0];
378     /* Create the MessageQCopy for receiving messages from all remote proc */
379     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
380         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
382     if (NameServer_module->mq == NULL) {
383         status = NameServer_E_FAIL;
384         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_setup", status,
385                             "failed to create MessageQCopy instance.");
386         goto exit;
387     }
389     /* Construct the list object */
390     CIRCLEQ_INIT(&NameServer_module->objList);
392 exit:
393     GT_1trace(curTrace, GT_LEAVE, "NameServer_setup: refCount",
394               NameServer_module->refCount);
396     pthread_mutex_unlock(&NameServer_module->modGate);
398     return (status);
401 /*! Function to destroy the nameserver module. */
402 Int NameServer_destroy(void)
404     Int      status    = NameServer_S_SUCCESS;
406     pthread_mutex_lock(&NameServer_module->modGate);
408     GT_1trace(curTrace, GT_ENTER, "NameServer_destroy: refCount",
409               NameServer_module->refCount);
411     NameServer_module->refCount--;
413     if (NameServer_module->refCount > 0) {
414         GT_1trace(curTrace, GT_1CLASS,
415                   "NameServer_destroy(): refCount(%d) > 0, exiting",
416                   NameServer_module->refCount);
417         status = NameServer_S_SUCCESS;
419         goto exit;
420     }
422     /* Delete the MessageQCopy instances */
423     if (NameServer_module->mq != NULL) {
424         MessageQCopy_delete(&NameServer_module->mq);
425     }
427     /* TODO: delete any remaining instances */
429     close(NameServer_module->waitFdW);
430     close(NameServer_module->waitFdR);
432 exit:
433     GT_1trace(curTrace, GT_LEAVE, "NameServer_destroy: refCount",
434               NameServer_module->refCount);
436     pthread_mutex_unlock(&NameServer_module->modGate);
438     return (status);
441 /* Function to retrieve a NameServer handle from name. */
442 NameServer_Handle NameServer_getHandle(String name)
444     NameServer_Handle handle = NULL;
445     Bool              found = FALSE;
446     struct NameServer_Object * elem;
448     assert(name != NULL);
449     assert(NameServer_module->refCount != 0);
451     pthread_mutex_lock(&NameServer_module->modGate);
453     /* Lookup handle from name: */
454     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
455         handle = (NameServer_Handle) elem;
456         if (strcmp(handle->name, name) == 0) {
457             found = TRUE;
458             break;
459         }
460     }
462     if (found == FALSE) {
463         handle = NULL;
464     }
466     pthread_mutex_unlock(&NameServer_module->modGate);
468     return (handle);
472 /* Function to create a name server. */
473 NameServer_Handle NameServer_create(String name,
474                                     const NameServer_Params * params)
476     NameServer_Handle handle = NULL;
477     pthread_mutexattr_t mutex_attr;
479     assert(params != NULL);
480     assert(name != NULL);
481     assert(NameServer_module->refCount != 0);
483     GT_1trace(curTrace, GT_1CLASS, "NameServer_create(): '%s'\n", name);
485     pthread_mutex_lock(&NameServer_module->modGate);
487     /* check if the name is already created or not */
488     handle = NameServer_getHandle(name);
489     if (handle != NULL) {
490         if (memcmp((Ptr)&handle->params, (Ptr)params,
491             sizeof(NameServer_Params)) == 0) {
492             handle->refCount++;
493         }
494         else {
495             GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_create",
496                                 NameServer_E_FAIL, "NameServer params mismatch");
497             handle = NULL;
498         }
499         goto leave;
500     }
501     else {
502         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
503     }
505     if (!handle) {
506         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_create",
507                             NameServer_E_FAIL, "NameServer_Handle alloc failed");
508         goto leave;
509     }
511     handle->refCount = 1;
512     handle->name = (String)malloc(strlen(name) + 1u);
513     if (!handle->name) {
514         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_create",
515                             NameServer_E_FAIL, "instance name alloc failed");
516         goto cleanup;
517     }
518     strncpy(handle->name, name, strlen (name) + 1u);
519     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
521     assert(params.maxValueLen <= MAXVALUELEN);
523     if (params->maxValueLen < sizeof(UInt32)) {
524         handle->params.maxValueLen = sizeof(UInt32);
525     }
526     else {
527         handle->params.maxValueLen = params->maxValueLen;
528     }
530     CIRCLEQ_INIT(&handle->nameList);
531     handle->count = 0u;
533     /* Put in the local list */
534     CIRCLEQ_elemClear(&handle->elem);
535     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
537     /*
538      * NameServer_removeEntry() enters gate and is called by
539      * NameServer_remove() while holding the gate.
540      */
541     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
542     pthread_mutex_init(&handle->gate, &mutex_attr);
544     goto leave;
546 cleanup:
547     free(handle);
548     handle = NULL;
550 leave:
551     pthread_mutex_unlock(&NameServer_module->modGate);
553     return (handle);
557 /*
558  *  ======== NameServer_delete ========
559  *  Delete a name server instance
560  */
561 Int NameServer_delete(NameServer_Handle *handle)
563     Int status = NameServer_S_SUCCESS;
564     struct NameServer_Object *obj;
566     assert(handle != NULL);
567     assert(*handle != NULL);
568     assert(NameServer_module->refCount != 0);
570     obj = *(struct NameServer_Object **)handle;
572     pthread_mutex_lock(&NameServer_module->modGate);
574     obj->refCount--;
575     if (obj->refCount != 0) {
576         goto leave;
577     }
579     /* delete each entry on the name list */
580     while (obj->nameList.cqh_first != (void *)&obj->nameList) {
581         NameServer_removeEntry(*handle, (Ptr)(obj->nameList.cqh_first));
582     }
584     /* free the instance name */
585     if (obj->name != NULL) {
586         free(obj->name);
587         obj->name = NULL;
588     }
590     /* destroy the mutex */
591     pthread_mutex_destroy(&obj->gate);
593     /* remove from objList */
594     CIRCLEQ_REMOVE(&NameServer_module->objList, obj, elem);
596     /* finally, free the instance object */
597     free(obj);
599     /* set the caller's handle to null */
600     (*handle) = NULL;
602 leave:
603     pthread_mutex_unlock(&NameServer_module->modGate);
605     return (status);
608 /* Adds a variable length value into the local NameServer table */
609 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
611     Int                 status = NameServer_S_SUCCESS;
612     NameServer_TableEntry * node = NULL;
613     NameServer_TableEntry * new_node = NULL;
614     Bool                found = FALSE;
615     UInt32              hash;
617     assert(handle != NULL);
618     assert(name     != NULL);
619     assert(buf      != NULL);
620     assert(len      != 0);
621     assert(NameServer_module->refCount != 0);
623     /* Calculate the hash */
624     hash = stringHash(name);
626     pthread_mutex_lock(&handle->gate);
628     if (strlen(name) > handle->params.maxNameLen - 1) {
629         status = NameServer_E_INVALIDARG;
630         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status,
631                             "name length exceeded maximum!");
632         new_node = NULL;
633         goto exit;
634     }
636     if (len > handle->params.maxValueLen) {
637         status = NameServer_E_INVALIDARG;
638         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status,
639                             "value length exceeded maximum!");
640         new_node = NULL;
641         goto exit;
642     }
644     /* Traverse the list to find duplicate check */
645     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
646         /* Hash matches */
647         if (node->hash == hash) {
648             /* If the name matches, incase hash is duplicate */
649             if (strcmp(node->name, name) == 0) {
650                 if (handle->params.checkExisting == TRUE) {
651                     status = NameServer_E_INVALIDARG;
652                     GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status, "duplicate entry found!");
653                     GT_1trace(curTrace, GT_3CLASS, "\t'%s' - duplicate entry found!", name);
654                     break;
655                 }
656             }
657             else {
658                 found = TRUE;
659                 break;
660             } /* name does not match */
661         } /* hash does not match */
662     } /* CIRCLEQ_traverse */
664     if (status != NameServer_S_SUCCESS) {
665         new_node = NULL;
666         goto exit;
667     }
669     /* Now add the new entry. */
670     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
671     if (new_node == NULL) {
672         status = NameServer_E_MEMORY;
673         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_add", status,
674                             "malloc new_node failed!");
676         goto exit;
677     }
679     new_node->hash    = hash;
680     new_node->collide = found; /* Indicate if there is a collision*/
681     new_node->len     = len;
682     new_node->next    = NULL;
683     new_node->name = (String)malloc(strlen(name) + 1u);
684     new_node->value  = (Ptr)malloc(len);
685     strncpy(new_node->name, name, strlen(name) + 1u);
686     memcpy((Ptr)new_node->value, (Ptr)buf, len);
688     if (found == TRUE) {
689         /* If hash is found, need to stitch the list to link the
690          * new node to the existing node with the same hash.
691          */
692         new_node->next = node->next;
693         node->next = new_node;
694     }
695     else {
696         /* put the new node into the list */
697         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
698     }
700     handle->count++;
702     /* Only print a single byte of buf. Address may not be 32-bit aligned */
703     GT_2trace(curTrace, GT_1CLASS,
704               "NameServer_add: Entered key: '%s', data: 0x%x",
705               name, *(UInt8 *)buf);
706 exit:
707     pthread_mutex_unlock(&handle->gate);
709     return (new_node);
713 /* Function to add a UInt32 value into a name server. */
714 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
716     Ptr entry = NULL;
718     assert(handle != NULL);
719     assert(name   != NULL);
720     assert(NameServer_module->refCount != 0);
722     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
724     return (entry);
727 /* Function to remove a name/value pair from a name server. */
728 Int NameServer_remove(NameServer_Handle handle, String name)
730     Int                 status = NameServer_S_SUCCESS;
731     NameServer_TableEntry *prev = NULL;
732     NameServer_TableEntry *temp = NULL;
733     NameServer_TableEntry *node = NULL;
734     Bool                done   = FALSE;
735     UInt32              hash;
737     assert(handle != NULL);
738     assert(name   != NULL);
739     assert(NameServer_module->refCount != 0);
741     /* Calculate the hash */
742     hash = stringHash(name);
744     pthread_mutex_lock(&handle->gate);
746     /* Traverse the list to find duplicate check */
747     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
748         /* Hash matchs */
749         if (node->hash == hash) {
750             if (node->collide == TRUE) {
751                 if (strcmp(node->name, name) == 0){
752                     free(node->value);
753                     free(node->name);
754                     memcpy((Ptr)node, (Ptr) node->next,
755                            sizeof(NameServer_TableEntry));
756                     node->next = node->next->next;
757                     free(node->next);
758                     handle->count--;
759                     done = TRUE;
760                     break;
761                 }
762                 else {
763                     prev = node;
764                     temp = node->next;
765                     while (temp) {
766                         if (strcmp(temp->name, name) == 0){
767                             free(temp->value);
768                             free(temp->name);
769                             prev->next = temp->next;
770                             free(temp);
771                             handle->count--;
772                             done = TRUE;
773                             break;
774                         }
775                         temp = temp->next;
776                     }
777                     break;
778                 }
779             }
780             else {
781                 NameServer_removeEntry(handle, (Ptr)node);
783                 done = TRUE;
784                 break;
785             }
786         }
787     }
789     if (done == FALSE) {
790         status = NameServer_E_INVALIDARG;
791         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_remove", status,
792                             " Entry not found!");
793     }
795     pthread_mutex_unlock(&handle->gate);
797     return (status);
800 /* Function to remove a name/value pair from a name server. */
801 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
803     Int  status = NameServer_S_SUCCESS;
804     NameServer_TableEntry * node;
806     assert(handle != NULL);
807     assert(entry  != NULL);
808     assert(NameServer_module->refCount != 0);
810     pthread_mutex_lock(&handle->gate);
812     node = (NameServer_TableEntry *)entry;
814     free(node->value);
815     free(node->name);
816     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
817     free(node);
818     handle->count--;
820     pthread_mutex_unlock(&handle->gate);
822     return (status);
826 /* Initialize this config-params structure with supplier-specified
827  * defaults before instance creation.
828  */
829 Void NameServer_Params_init(NameServer_Params * params)
831     assert(params != NULL);
833     memcpy(params, &(NameServer_module->defInstParams),
834            sizeof (NameServer_Params));
838 Int NameServer_getRemote(NameServer_Handle handle,
839                      String            name,
840                      Ptr               value,
841                      UInt32 *          len,
842                      UInt16            procId)
844     Int status = NameServer_S_SUCCESS;
845     Int mqcStatus = -1;
846     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
847     NameServerRemote_Msg nsMsg;
848     NameServerRemote_Msg *replyMsg;
849     fd_set rfds;
850     int ret = 0, maxfd, waitFd;
851     struct timeval tv;
852     char buf = '1';
853     int numBytes;
854     static int seqNum = 0;
855     Bool done = FALSE;
857     if (strlen(name) >= MAXNAMEINCHAR) {
858         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
859                             NameServer_E_NAMETOOLONG,
860                             "Name is too long in remote query");
861         return NameServer_E_NAMETOOLONG;
862     }
864     if (strlen(obj->name) >= MAXNAMEINCHAR) {
865         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
866                             NameServer_E_NAMETOOLONG,
867                             "Instance name is too long for remote query");
868         return NameServer_E_NAMETOOLONG;
869     }
871     pthread_mutex_lock(&NameServer_module->modGate);
873     /* Set Timeout to wait: */
874     tv.tv_sec = 0;
875     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
877     /* Create request message and send to remote processor: */
878     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
879     nsMsg.request = NAMESERVER_REQUEST;
880     nsMsg.requestStatus = 0;
881     nsMsg.valueLen = *len;
882     nsMsg.seqNum = seqNum++;
884     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
885     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
887     GT_3trace(curTrace, GT_1CLASS,
888               "NameServer_getRemote: Requesting from procId %d, %s:%s...",
889               procId, (String)nsMsg.instanceName, (String)nsMsg.name);
891     /*
892      * Check if MessageQCopy object is valid. Technically we don't need it
893      * to send, but it is an indication of whether recovery is in process
894      */
895     if (NameServer_module->mq == NULL) {
896         status = NameServer_E_NOTFOUND;
897         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
898                             status, "MessageQCopy not ready");
899         goto exit;
900     }
902     /* send message */
903     mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
904             RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerRemote_Msg),
905             TRUE);
906     if (mqcStatus < 0) {
907         status = NameServer_E_NOTFOUND;
908         GT_1trace(curTrace, GT_3CLASS, "NameServer_getRemote: "
909                   "Can't send to remote endpoint on procId %d", procId);
910         goto exit;
911     }
913     while (!done) {
914         /* Block on waitFd for signal from listener thread: */
915         waitFd = NameServer_module->waitFdR;
916         FD_ZERO(&rfds);
917         FD_SET(waitFd, &rfds);
918         maxfd = waitFd + 1;
919         GT_1trace(curTrace, GT_1CLASS, "NameServer_getRemote: pending on waitFd: %d\n", waitFd);
920         ret = select(maxfd, &rfds, NULL, NULL, &tv);
921         if (ret == -1) {
922             status = NameServer_E_FAIL;
923             GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
924                                 status, "select failed.");
925             goto exit;
926         }
927         else if (!ret) {
928             status = NameServer_E_TIMEOUT;
929             GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
930                                 status, "select timed out.");
931             goto exit;
932         }
934         if (FD_ISSET(waitFd, &rfds)) {
935             /* Read, just to balance the write: */
936             numBytes = read(waitFd, &buf, sizeof(buf));
937             if (numBytes == -1) {
938                 status = NameServer_E_FAIL;
939                 GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_getRemote",
940                                     status, "read failure");
941                 goto exit;
942             }
944             /* Process response: */
945             replyMsg = &NameServer_module->nsMsg;
947             if (replyMsg->seqNum != seqNum - 1) {
948                 /* Ignore responses without current sequence # */
949                 continue;
950             }
952             if (replyMsg->requestStatus) {
953                 /* name is found */
955                 /* set length to amount of data that was copied */
956                 *len = replyMsg->valueLen;
958                 /* set the contents of value */
959                 if (*len <= sizeof (Bits32)) {
960                     *(UInt32 *)value = (UInt32)replyMsg->value;
961                     GT_4trace(curTrace, GT_1CLASS, "NameServer_getRemote: "
962                               "Reply from: %d, %s:%s, value: 0x%x...", procId,
963                               (String)replyMsg->instanceName,
964                               (String)replyMsg->name, *(UInt32 *)value);
965                 }
966                 else {
967                     memcpy(value, replyMsg->valueBuf, *len);
968                     GT_4trace(curTrace, GT_1CLASS, "NameServer_getRemote: "
969                               "Reply from: %d, %s:%s, value buffer at address:"
970                               " 0x%p...", procId,
971                               (String)replyMsg->instanceName,
972                               (String)replyMsg->name, value);
973                 }
975                 goto exit;
976             }
977             else {
978                 /* name is not found */
979                 GT_2trace(curTrace, GT_3CLASS, "NameServer_getRemote: "
980                           "value for %s:%s not found.",
981                           (String)replyMsg->instanceName,
982                           (String)replyMsg->name);
984                 /* set status to not found */
985                 status = NameServer_E_NOTFOUND;
986             }
987         }
988         done = TRUE;
989     }
990 exit:
991     pthread_mutex_unlock(&NameServer_module->modGate);
993     return (status);
996 /* Function to retrieve the value portion of a name/value pair from
997  * local table.
998  */
999 Int NameServer_get(NameServer_Handle handle,
1000                String            name,
1001                Ptr               value,
1002                UInt32 *          len,
1003                UInt16            procId[])
1005     Int status = NameServer_S_SUCCESS;
1006     UInt16 numProcs = MultiProc_getNumProcessors();
1007     UInt32 i;
1009     if (procId == NULL) {
1010         status = NameServer_getLocal(handle, name, value, len);
1011         if (status == NameServer_E_NOTFOUND) {
1012             for (i = 0; i < numProcs; i++) {
1013                 /* getLocal call already covers "self", keep going */
1014                 if (i == MultiProc_self()) {
1015                     continue;
1016                 }
1018                 status = NameServer_getRemote(handle, name, value, len, i);
1020                 if ((status >= 0) ||
1021                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1022                     (status != NameServer_E_TIMEOUT))) {
1023                     break;
1024                 }
1025             }
1026         }
1027     }
1028     else {
1029         /*
1030          *  Search the query list. It might contain the local proc
1031          *  somewhere in the list.
1032          */
1033         i = 0;
1034         while (procId[i] != MultiProc_INVALIDID) {
1035             if (procId[i] == MultiProc_self()) {
1036                 status = NameServer_getLocal(handle, name, value, len);
1037             }
1038             else {
1039                 status = NameServer_getRemote(handle, name, value, len, i);
1040             }
1042             if ((status >= 0) ||
1043                 ((status < 0) && (status != NameServer_E_NOTFOUND)
1044                 && (status != NameServer_E_TIMEOUT))) {
1045                 break;
1046             }
1048             i++;
1049         }
1050     }
1052     return (status);
1055 /* Gets a 32-bit value by name */
1056 Int NameServer_getUInt32(NameServer_Handle handle,
1057                      String            name,
1058                      Ptr               value,
1059                      UInt16            procId[])
1061     Int  status;
1062     UInt32 len = sizeof(UInt32);
1064     assert(handle != NULL);
1065     assert(name   != NULL);
1066     assert(value  != NULL);
1067     assert(NameServer_module->refCount != 0);
1069     status = NameServer_get(handle, name, value, &len, procId);
1071     return (status);
1074 /* Function to Retrieve the value portion of a name/value pair from
1075  * local table.
1076  */
1077 Int NameServer_getLocal(NameServer_Handle handle,
1078                     String            name,
1079                     Ptr               value,
1080                     UInt32 *          len)
1082     Int status = NameServer_E_NOTFOUND;
1083     NameServer_TableEntry * node = NULL;
1084     NameServer_TableEntry * temp = NULL;
1085     Bool done   = FALSE;
1086     UInt32 length;
1087     UInt32 hash;
1089     assert(handle != NULL);
1090     assert(name   != NULL);
1091     assert(value  != NULL);
1092     assert(len    != NULL);
1093     assert(NameServer_module->refCount != 0);
1095     length = *len;
1097     /* Calculate the hash */
1098     hash = stringHash(name);
1100     pthread_mutex_lock(&handle->gate);
1102     /* Traverse the list to find duplicate check */
1103     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1104         if (node->hash == hash) {
1105             if (node->collide == TRUE) {
1106                 temp = node;
1107                 while (temp) {
1108                     if (strcmp(temp->name, name) == 0u){
1109                         if (length <= node->len) {
1110                             memcpy(value, node->value, length);
1111                             *len = length;
1112                         }
1113                         else {
1114                             memcpy(value, node->value, node->len);
1115                             *len = node->len;
1116                         }
1117                         done = TRUE;
1118                         break;
1119                     }
1120                     temp = temp->next;
1121                 }
1122                 break;
1123             }
1124             else {
1125                 if (length <= node->len) {
1126                     memcpy(value, node->value, length);
1127                     *len = length;
1128                 }
1129                 else {
1130                     memcpy(value, node->value, node->len);
1131                     *len = node->len;
1132                 }
1133                 done = TRUE;
1134                 break;
1135             }
1136         }
1137     }
1139     pthread_mutex_unlock(&handle->gate);
1141     if (done == FALSE) {
1142         GT_1trace(curTrace, GT_1CLASS,
1143                   "NameServer_getLocal: entry key: '%s' not found!", name);
1144     }
1145     else {
1146         GT_2trace(curTrace, GT_1CLASS, "NameServer_getLocal: Found entry key: "
1147                   "'%s', data: 0x%x", node->name, (UInt32)node->value);
1148         status = NameServer_S_SUCCESS;
1149     }
1151     return (status);
1154 /*
1155  *  Gets a 32-bit value by name from the local table
1156  *
1157  *  If the name is found, the 32-bit value is copied into the value
1158  *  argument and a success status is returned.
1159  *
1160  *  If the name is not found, zero is returned in len and the contents
1161  *  of value are not modified. Not finding a name is not considered
1162  *  an error.
1163  *
1164  *  This function only searches the local name/value table.
1165  *
1166  */
1167 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1169     Int                 status;
1170     UInt32              len    = sizeof(UInt32);
1172     assert(handle != NULL);
1173     assert(name   != NULL);
1174     assert(value  != NULL);
1175     assert(NameServer_module->refCount != 0);
1177     GT_0trace(curTrace, GT_1CLASS,
1178               "NameServer_getLocalUInt32: calling NameServer_getLocal()...");
1179     status = NameServer_getLocal(handle, name, value, &len);
1181     return (status);
1184 Void NameServer_preRecovery(Void)
1186     Int status;
1188     pthread_mutex_lock(&NameServer_module->modGate);
1190     if (NameServer_module->mq != NULL) {
1191         status = MessageQCopy_delete(&NameServer_module->mq);
1192         if (status < 0) {
1193             GT_setFailureReason(curTrace, GT_3CLASS, "NameServer_preRecovery", status,
1194                                 "Cannot delete MessageQCopy");
1195         }
1196         NameServer_module->mq = NULL;
1197     }
1199     pthread_mutex_unlock(&NameServer_module->modGate);
1202 Int NameServer_postRecovery(Void)
1204     Int status = NameServer_S_SUCCESS;
1206     pthread_mutex_lock(&NameServer_module->modGate);
1208     /* Create the MessageQCopy for receiving messages from all remote proc */
1209     NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
1210         NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
1212     if (NameServer_module->mq == NULL) {
1213         status = NameServer_E_FAIL;
1214         GT_setFailureReason(curTrace, GT_4CLASS, "NameServer_postRecovery", status,
1215                             "failed to create MessageQCopy instance.");
1216     }
1218     pthread_mutex_unlock(&NameServer_module->modGate);
1220     return (status);
1223 #if defined (__cplusplus)
1225 #endif /* defined (__cplusplus) */