Linux: Addresses timed-out NameServer requests in LAD
[ipc/ipcdev.git] / linux / src / daemon / NameServer_daemon.c
1 /*
2  * Copyright (c) 2012-2014, 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.c
34  *
35  *  @brief      NameServer Manager
36  */
38 /* Standard IPC headers */
39 #include <ti/ipc/Std.h>
41 /* POSIX thread support */
42 #include <pthread.h>
44 /* Socket Headers */
45 #include <sys/queue.h>
46 #include <sys/select.h>
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/eventfd.h>
51 #include <sys/socket.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>
59 /* Socket Protocol Family */
60 #include <net/rpmsg.h>
62 /* Module level headers */
63 #include <ti/ipc/NameServer.h>
64 #include <ti/ipc/MultiProc.h>
65 #include <_MultiProc.h>
67 /* Internal stuff: */
68 #include <_NameServer.h>
69 #include <_NameServerRemoteRpmsg.h>
71 /* Socket utils: */
72 #include <SocketFxns.h>
74 #include <_lad.h>
76 #define MESSAGEQ_RPMSG_PORT       61
77 #define NAME_SERVER_RPMSG_ADDR    0
79 #define INVALIDSOCKET     (-1)
81 #if defined (__cplusplus)
82 extern "C" {
83 #endif
86 /* =============================================================================
87  * Structures & Enums
88  * =============================================================================
89  */
91 /* Structure of entry in Name/Value table */
92 typedef struct NameServer_TableEntry_tag {
93     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
94     /* List element */
95     UInt32                    hash;
96     /* Hash value */
97     String                    name;
98     /* Name portion of the name/value pair. */
99     UInt                      len;
100     /* Length of the value field. */
101     Ptr                       value;
102     /* Value portion of the name/value entry. */
103     Bool                      collide;
104     /* Does the hash collide? */
105     struct NameServer_TableEntry_tag * next;
106     /* Pointer to the next entry, used incase of collision only */
107 } NameServer_TableEntry;
109 /* Structure defining object for the NameServer */
110 struct NameServer_Object {
111     CIRCLEQ_ENTRY(NameServer_Object) elem;
112     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
113     String             name;            /* name of the instance */
114     NameServer_Params  params;          /* the parameter structure */
115     UInt32             count;           /* count of entries */
116     UInt32             refCount;        /* reference count to this object */
117     pthread_mutex_t    gate;            /* crit sect gate */
118 } NameServer_Object;
120 /* structure for NameServer module state */
121 typedef struct NameServer_ModuleObject {
122     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
123     Int32               refCount;
124     int                 sendSock[MultiProc_MAXPROCESSORS];
125     /* Sockets for sending to remote proc nameserver ports: */
126     int                 recvSock[MultiProc_MAXPROCESSORS];
127     /* Sockets for recving from remote proc nameserver ports: */
128     pthread_t           listener;
129     /* Listener thread for NameServer replies and requests. */
130     int                 unblockFd;
131     /* Event to post to exit listener. */
132     int                 waitFd;
133     /* Event to post to NameServer_get. */
134     NameServerMsg       nsMsg;
135     /* NameServer Message cache. */
136     NameServer_Params   defInstParams;
137     /* Default instance paramters */
138     pthread_mutex_t     modGate;
139 } NameServer_ModuleObject;
141 #define CIRCLEQ_destruct(head) { \
142         (head)->cqh_first = NULL; \
143         (head)->cqh_last = NULL; \
146 #define CIRCLEQ_elemClear(elem) { \
147         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
150 #define CIRCLEQ_traverse(x, y, tag) \
151         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
153 /* =============================================================================
154  *  Globals
155  * =============================================================================
156  */
157 /*
158  * NameServer_state
159  *
160  * Make the module gate "recursive" since NameServer_getHandle() needs to
161  * use it and NameServer_create() needs to hold it around its call to
162  * NameServer_getHandle().  Also, use the static initializer instead of a
163  * run-time init call, so we can use this gate immediately in _setup().
164  */
165 static NameServer_ModuleObject NameServer_state = {
166     .defInstParams.maxRuntimeEntries = 0u,
167     .defInstParams.tableHeap         = NULL,
168     .defInstParams.checkExisting     = TRUE,
169     .defInstParams.maxValueLen       = 0u,
170     .defInstParams.maxNameLen        = 16u,
171 #if defined(IPC_BUILDOS_ANDROID)
172     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
173 #else
174 // only _NP (non-portable) type available in CG tools which we're using
175     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
176 #endif
177     .refCount                        = 0
178 };
180 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
182 static const UInt32 stringCrcTab[256u] = {
183   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
184   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
185   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
186   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
187   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
188   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
189   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
190   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
191   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
192   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
193   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
194   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
195   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
196   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
197   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
198   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
199   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
200   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
201   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
202   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
203   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
204   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
205   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
206   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
207   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
208   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
209   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
210   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
211   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
212   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
213   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
214   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
215   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
216   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
217   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
218   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
219   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
220   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
221   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
222   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
223   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
224   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
225   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
226 };
228 static UInt32 stringHash(String s)
230     UInt32 hash = strlen(s);
231     UInt32 i;
233     for (i = 0; i < strlen(s); i++) {
234         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
235     }
237     return (hash);
240 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
242     NameServer_Handle handle;
243     Int               status = NameServer_E_FAIL;
244     int               err;
245     uint64_t          buf = 1;
246     int               numBytes;
247     int               waitFd = NameServer_module->waitFd;
249     if (msg->request == NAMESERVER_REQUEST) {
250         LOG2("NameServer Request: instanceName: %s, name: %s\n",
251              (String)msg->instanceName, (String)msg->name)
253         assert(msg->valueLen <= MAXVALUELEN);
254         /*
255          *  Message is a request. Lookup name in NameServer table.
256          *  Send a response message back to source processor.
257          */
258         handle = NameServer_getHandle((String)msg->instanceName);
260         if (handle != NULL) {
261             /* Search for the NameServer entry */
262             if (msg->valueLen <= sizeof (Bits32)) {
263                 LOG0("Calling NameServer_getLocalUInt32...\n")
264                 status = NameServer_getLocalUInt32(handle,
265                      (String)msg->name, &msg->value);
266             }
267             else {
268                 LOG0("Calling NameServer_getLocal...\n")
269                 status = NameServer_getLocal(handle,
270                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
271             }
272         }
274         LOG2("NameServer Response: instanceName: %s, name: %s,",
275              (String)msg->instanceName, (String)msg->name)
276         /* set the request status */
277         if (status < 0) {
278             LOG1(" Value not found, status: %d\n", status)
279             msg->requestStatus = 0;
280         }
281         else {
282             msg->requestStatus = 1;
283             LOG1(" Value: 0x%x\n", msg->value)
284         }
286         /* specify message as a response */
287         msg->request = NAMESERVER_RESPONSE;
288         msg->reserved = NAMESERVER_MSG_TOKEN;
290         /* send response message to remote processor */
291         err = send(NameServer_module->sendSock[procId], msg,
292                    sizeof(NameServerMsg), 0);
293         if (err < 0) {
294             LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
295         }
296     }
297     else {
298         LOG2("NameServer Reply: instanceName: %s, name: %s",
299              (String)msg->instanceName, (String)msg->name)
300         LOG1(", value: 0x%x\n", msg->value)
302         /* Save the response message.  */
303         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
305         /* Post the eventfd upon which NameServer_get() is waiting */
306         numBytes = write(waitFd, &buf, sizeof(uint64_t));
307     }
311 static void *listener_cb(void *arg)
313     fd_set rfds;
314     int ret = 0, maxfd;
315     UInt16 procId;
316     struct  sockaddr_rpmsg  fromAddr;
317     unsigned int len;
318     NameServerMsg msg;
319     int     byteCount;
320     UInt16  numProcs = MultiProc_getNumProcessors();
321     int     sock;
323     LOG0("listener_cb: Entered Listener thread.\n")
325     do {
326         /* Wait for NameServer messages or unblockFd notification */
327         FD_ZERO(&rfds);
328         FD_SET(NameServer_module->unblockFd, &rfds);
329         maxfd = NameServer_module->unblockFd;
330         for (procId = 0; procId < numProcs; procId++) {
331             if (procId == MultiProc_self() ||
332                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
333                 continue;
334             }
335             sock = NameServer_module->recvSock[procId];
336             FD_SET(sock, &rfds);
337             maxfd = MAX(sock, maxfd);
338         }
340         maxfd = maxfd + 1;
341         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
342              NameServer_module->unblockFd, maxfd)
343         ret = select(maxfd, &rfds, NULL, NULL, NULL);
344         if (ret == -1) {
345             LOG0("listener_cb: select failed.")
346             break;
347         }
348         LOG0("NameServer: back from select()\n")
350         for (procId = 0; procId < numProcs; procId++) {
351             if (procId == MultiProc_self() ||
352                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
353                 continue;
354             }
355             sock = NameServer_module->recvSock[procId];
356             if (FD_ISSET(sock, &rfds)) {
357                 LOG1("NameServer: Listener got NameServer message "
358                      "from sock: %d!\n", sock);
359                 /* Get NameServer message and process: */
360                 memset(&fromAddr, 0, sizeof(fromAddr));
361                 len = sizeof(fromAddr);
363                 byteCount = recvfrom(sock, &msg, sizeof(NameServerMsg), 0,
364                                 (struct sockaddr *)&fromAddr, &len);
365                 if (len != sizeof(fromAddr)) {
366                     LOG1("recvfrom: got bad addr len (%d)\n", len)
367                     break;
368                 }
369                 if (byteCount < 0) {
370                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
371                     break;
372                 }
373                 else {
374                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
375                     LOG2("\tReceived ns msg: byteCount: %d, from addr: %d, ",
376                          byteCount, fromAddr.addr)
377                     LOG1("from vproc: %d\n", fromAddr.vproc_id)
378                     NameServerRemote_processMessage(&msg, procId);
379                 }
380             }
381         }
382         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
383             /* We are told to unblock and exit: */
384             LOG0("NameServer: Listener thread exiting\n")
385             break;
386         }
387     } while (1);
389     return ((void *)ret);
392 /* =============================================================================
393  * APIS
394  * =============================================================================
395  */
397 /* Function to setup the nameserver module. */
398 Int NameServer_setup(Void)
400     Int    status = NameServer_S_SUCCESS;
401     int    err;
402     int    sock;
403     int    ret;
404     UInt16 procId;
405     UInt16 numProcs;
407     pthread_mutex_lock(&NameServer_module->modGate);
409     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
411     NameServer_module->refCount++;
413     if (NameServer_module->refCount > 1) {
414         LOG0("NameServer_setup: already setup\n")
415         status = NameServer_S_ALREADYSETUP;
416         goto exit;
417     }
419     numProcs = MultiProc_getNumProcessors();
421     NameServer_module->unblockFd = eventfd(0, 0);
422     if (NameServer_module->unblockFd < 0) {
423         status = NameServer_E_FAIL;
424         LOG0("NameServer_setup: failed to create unblockFd.\n")
425         goto exit;
426     }
428     NameServer_module->waitFd = eventfd(0, 0);
429     if (NameServer_module->waitFd < 0) {
430         status = NameServer_E_FAIL;
431         LOG0("NameServer_setup: failed to create waitFd.\n")
432         goto exit;
433     }
435     for (procId = 0; procId < numProcs; procId++) {
436         NameServer_module->sendSock[procId] = INVALIDSOCKET;
437         NameServer_module->recvSock[procId] = INVALIDSOCKET;
439         /* Only support NameServer to remote procs: */
440         if (procId == MultiProc_self()) {
441             continue;
442         }
444         /* Create the socket for sending messages to each remote proc: */
445         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
446         if (sock < 0) {
447             status = NameServer_E_FAIL;
448             LOG2("NameServer_setup: socket failed: %d, %s\n",
449                  errno, strerror(errno))
450         }
451         else  {
452             LOG1("NameServer_setup: created send socket: %d\n", sock)
453             err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
454             if (err < 0) {
455                 status = NameServer_E_FAIL;
456                 LOG2("NameServer_setup: connect failed: %d, %s\n",
457                      errno, strerror(errno))
459                 LOG1("    closing send socket: %d\n", sock)
460                 close(sock);
461             }
462             else {
463                 NameServer_module->sendSock[procId] = sock;
464             }
465         }
467         /* Create the socket for recving messages from each remote proc: */
468         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
469         if (sock < 0) {
470             status = NameServer_E_FAIL;
471             LOG2("NameServer_setup: socket failed: %d, %s\n",
472                  errno, strerror(errno))
473         }
474         else  {
475             LOG1("NameServer_setup: created recv socket: %d\n", sock)
477             err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
478             if (err < 0) {
479                 status = NameServer_E_FAIL;
480                 LOG2("NameServer_setup: bind failed: %d, %s\n",
481                     errno, strerror(errno))
483                 LOG1("    closing recv socket: %d\n", sock)
484                 close(sock);
485             }
486             else {
487                 NameServer_module->recvSock[procId] = sock;
488             }
489         }
490     }
492     /* Construct the list object */
493     CIRCLEQ_INIT(&NameServer_module->objList);
495     /* Create the listener thread: */
496     LOG0("NameServer_setup: creating listener thread\n")
497     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
498     if (ret) {
499         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
500         LOG0("NameServer_setup: eventfd failed");
502         status = NameServer_E_FAIL;
503     }
504     else {
505         /* look for at least one good send/recv pair to indicate success */
506         for (procId = 0; procId < numProcs; procId++) {
507             if (NameServer_module->sendSock[procId] != INVALIDSOCKET &&
508                 NameServer_module->recvSock[procId] != INVALIDSOCKET) {
509                 status = NameServer_S_SUCCESS;
511                 break;
512             }
513         }
514     }
516 exit:
517     LOG1("NameServer_setup: exiting, refCount=%d\n", NameServer_module->refCount)
519     pthread_mutex_unlock(&NameServer_module->modGate);
521     return (status);
524 /*! Function to destroy the nameserver module. */
525 Int NameServer_destroy(void)
527     Int      status    = NameServer_S_SUCCESS;
528     UInt16   numProcs = MultiProc_getNumProcessors();
529     UInt16   procId;
530     int      sock;
531     uint64_t buf = 1;
532     int      numBytes;
534     pthread_mutex_lock(&NameServer_module->modGate);
536     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
538     NameServer_module->refCount--;
540     if (NameServer_module->refCount > 0) {
541         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
542         status = NameServer_S_SUCCESS;
544         goto exit;
545     }
547     for (procId = 0; procId < numProcs; procId++) {
548         /* Only support NameServer to remote procs: */
549         if (procId == MultiProc_self()) {
550             continue;
551         }
553         /* Close the socket: */
554         sock = NameServer_module->sendSock[procId];
555         if (sock != INVALIDSOCKET) {
556             LOG1("NameServer_destroy: closing socket: %d\n", sock)
557             close(sock);
558             NameServer_module->sendSock[procId] = INVALIDSOCKET;
559         }
560         /* Close the socket: */
561         sock = NameServer_module->recvSock[procId];
562         if (sock != INVALIDSOCKET) {
563             LOG1("NameServer_destroy: closing socket: %d\n", sock)
564             close(sock);
565             NameServer_module->recvSock[procId] = INVALIDSOCKET;
566         }
567     }
569     CIRCLEQ_destruct(&NameServer_module->objList);
571     /* Unblock the NameServer listener thread: */
572     LOG0("NameServer_destroy: unblocking listener...\n")
573     numBytes = write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
575     /* Join: */
576     LOG0("NameServer_destroy: joining listener thread...\n")
577     pthread_join(NameServer_module->listener, NULL);
579     close(NameServer_module->unblockFd);
580     close(NameServer_module->waitFd);
582 exit:
583     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
585     pthread_mutex_unlock(&NameServer_module->modGate);
587     return (status);
590 /* Function to retrieve a NameServer handle from name. */
591 NameServer_Handle NameServer_getHandle(String name)
593     NameServer_Handle handle = NULL;
594     Bool              found = FALSE;
595     struct NameServer_Object * elem;
597     assert(name != NULL);
598     assert(NameServer_module->refCount != 0);
600     pthread_mutex_lock(&NameServer_module->modGate);
602     /* Lookup handle from name: */
603     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
604         handle = (NameServer_Handle) elem;
605         if (strcmp(handle->name, name) == 0) {
606             found = TRUE;
607             break;
608         }
609     }
611     if (found == FALSE) {
612         handle = NULL;
613     }
615     pthread_mutex_unlock(&NameServer_module->modGate);
617     return (handle);
621 /* Function to create a name server. */
622 NameServer_Handle NameServer_create(String name,
623                                     const NameServer_Params * params)
625     NameServer_Handle handle = NULL;
626     pthread_mutexattr_t mutex_attr;
628     assert(params != NULL);
629     assert(name != NULL);
630     assert(NameServer_module->refCount != 0);
632     LOG1("NameServer_create(): '%s'\n", name)
634     pthread_mutex_lock(&NameServer_module->modGate);
636     /* check if the name is already created or not */
637     handle = NameServer_getHandle(name);
638     if (handle != NULL) {
639         if (memcmp((Ptr)&handle->params, (Ptr)params,
640             sizeof(NameServer_Params)) == 0) {
641             handle->refCount++;
642         }
643         else {
644             LOG0("NameServer_create: NameServer params mismatch\n")
645             handle = NULL;
646         }
647         goto leave;
648     }
649     else {
650         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
651     }
653     if (!handle) {
654         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
655         goto leave;
656     }
658     handle->refCount = 1;
659     handle->name = (String)malloc(strlen(name) + 1u);
660     if (!handle->name) {
661         LOG0("NameServer_create: instance name alloc failed\n")
662         goto cleanup;
663     }
664     strncpy(handle->name, name, strlen (name) + 1u);
665     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
667     if (params->maxValueLen < sizeof(UInt32)) {
668         handle->params.maxValueLen = sizeof(UInt32);
669     }
670     else {
671         handle->params.maxValueLen = params->maxValueLen;
672     }
674     CIRCLEQ_INIT(&handle->nameList);
675     handle->count = 0u;
677     /* Put in the local list */
678     CIRCLEQ_elemClear(&handle->elem);
679     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
681     /*
682      * NameServer_removeEntry() enters gate and is called by
683      * NameServer_remove() while holding the gate.
684      */
685     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
686     pthread_mutex_init(&handle->gate, &mutex_attr);
688     goto leave;
690 cleanup:
691     free(handle);
692     handle = NULL;
694 leave:
695     pthread_mutex_unlock(&NameServer_module->modGate);
697     return (handle);
701 /* Function to delete a name server. */
702 Int NameServer_delete(NameServer_Handle * handle)
704     Int status = NameServer_S_SUCCESS;
706     assert(handle != NULL);
707     assert(*handle != NULL);
708     assert((*handle)->count == 0);
709     assert(NameServer_module->refCount != 0);
711     pthread_mutex_lock(&NameServer_module->modGate);
713     (*handle)->refCount--;
714     if ((*handle)->refCount != 0) {
715         goto leave;
716     }
718     if ((*handle)->count == 0) {
719         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
721         if ((*handle)->name != NULL) {
722             free((*handle)->name);
723             (*handle)->name = NULL;
724         }
726         CIRCLEQ_destruct(&(*handle)->nameList);
728         free((*handle));
729         (*handle) = NULL;
730     }
732 leave:
733     pthread_mutex_unlock(&NameServer_module->modGate);
735     return (status);
738 /* Adds a variable length value into the local NameServer table */
739 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
741     Int                 status = NameServer_S_SUCCESS;
742     NameServer_TableEntry * node = NULL;
743     NameServer_TableEntry * new_node = NULL;
744     Bool                found = FALSE;
745     UInt32              hash;
747     assert(handle != NULL);
748     assert(name     != NULL);
749     assert(buf      != NULL);
750     assert(len      != 0);
751     assert(NameServer_module->refCount != 0);
753     /* Calculate the hash */
754     hash = stringHash(name);
756     if (len > handle->params.maxValueLen) {
757         status = NameServer_E_INVALIDARG;
758         LOG0("NameServer_add: value length exceeded maximum!\n")
759         new_node = NULL;
760         goto exit;
761     }
763     pthread_mutex_lock(&handle->gate);
765     /* Traverse the list to find duplicate check */
766     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
767         /* Hash matches */
768         if (node->hash == hash) {
769             /* If the name matches, incase hash is duplicate */
770             if (strcmp(node->name, name) == 0) {
771                 if (handle->params.checkExisting == TRUE) {
772                     status = NameServer_E_INVALIDARG;
773                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
774                     break;
775                 }
776             }
777             else {
778                 found = TRUE;
779                 break;
780             } /* name does not match */
781         } /* hash does not match */
782     } /* CIRCLEQ_traverse */
784     if (status != NameServer_S_SUCCESS) {
785         new_node = NULL;
786         goto exit;
787     }
789     /* Now add the new entry. */
790     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
791     if (new_node == NULL) {
792         status = NameServer_E_MEMORY;
793         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
795         goto exit;
796     }
798     new_node->hash    = hash;
799     new_node->collide = found; /* Indicate if there is a collision*/
800     new_node->len     = len;
801     new_node->next    = NULL;
802     new_node->name = (String)malloc(strlen(name) + 1u);
803     new_node->value  = (Ptr)malloc(len);
804     strncpy(new_node->name, name, strlen(name) + 1u);
805     memcpy((Ptr)new_node->value, (Ptr)buf, len);
807     if (found == TRUE) {
808         /* If hash is found, need to stitch the list to link the
809          * new node to the existing node with the same hash.
810          */
811         new_node->next = node->next;
812         node->next = new_node;
813     }
814     else {
815         /* put the new node into the list */
816         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
817     }
819     handle->count++;
821     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
822          name, *(UInt32 *)buf)
824 exit:
825     pthread_mutex_unlock(&handle->gate);
827     return (new_node);
831 /* Function to add a UInt32 value into a name server. */
832 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
834     Ptr entry = NULL;
836     assert(handle != NULL);
837     assert(name   != NULL);
838     assert(NameServer_module->refCount != 0);
840     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
842     return (entry);
845 /* Function to remove a name/value pair from a name server. */
846 Int NameServer_remove(NameServer_Handle handle, String name)
848     Int                 status = NameServer_S_SUCCESS;
849     NameServer_TableEntry *prev = NULL;
850     NameServer_TableEntry *temp = NULL;
851     NameServer_TableEntry *node = NULL;
852     Bool                done   = FALSE;
853     UInt32              hash;
855     assert(handle != NULL);
856     assert(name   != NULL);
857     assert(NameServer_module->refCount != 0);
859     /* Calculate the hash */
860     hash = stringHash(name);
862     pthread_mutex_lock(&handle->gate);
864     /* Traverse the list to find duplicate check */
865     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
866         /* Hash matchs */
867         if (node->hash == hash) {
868             if (node->collide == TRUE) {
869                 if (strcmp(node->name, name) == 0){
870                     free(node->value);
871                     free(node->name);
872                     memcpy((Ptr)node, (Ptr) node->next,
873                            sizeof(NameServer_TableEntry));
874                     node->next = node->next->next;
875                     free(node->next);
876                     handle->count--;
877                     done = TRUE;
878                     break;
879                 }
880                 else {
881                     prev = node;
882                     temp = node->next;
883                     while (temp) {
884                         if (strcmp(temp->name, name) == 0){
885                             free(temp->value);
886                             free(temp->name);
887                             prev->next = temp->next;
888                             free(temp);
889                             handle->count--;
890                             done = TRUE;
891                             break;
892                         }
893                         temp = temp->next;
894                     }
895                     break;
896                 }
897             }
898             else {
899                 NameServer_removeEntry(handle, (Ptr)node);
901                 done = TRUE;
902                 break;
903             }
904         }
905     }
907     if (done == FALSE) {
908         status = NameServer_E_INVALIDARG;
909         LOG1("NameServer_remove %d Entry not found!\n", status)
910     }
912     pthread_mutex_unlock(&handle->gate);
914     return (status);
917 /* Function to remove a name/value pair from a name server. */
918 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
920     Int  status = NameServer_S_SUCCESS;
921     NameServer_TableEntry * node;
923     assert(handle != NULL);
924     assert(entry  != NULL);
925     assert(NameServer_module->refCount != 0);
927     pthread_mutex_lock(&handle->gate);
929     node = (NameServer_TableEntry *)entry;
931     free(node->value);
932     free(node->name);
933     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
934     free(node);
935     handle->count--;
937     pthread_mutex_unlock(&handle->gate);
939     return (status);
943 /* Initialize this config-params structure with supplier-specified
944  * defaults before instance creation.
945  */
946 Void NameServer_Params_init(NameServer_Params * params)
948     assert(params != NULL);
950     memcpy(params, &(NameServer_module->defInstParams),
951            sizeof (NameServer_Params));
955 Int NameServer_getRemote(NameServer_Handle handle,
956                      String            name,
957                      Ptr               value,
958                      UInt32 *          len,
959                      UInt16            procId)
961     Int status = NameServer_S_SUCCESS;
962     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
963     NameServerMsg nsMsg;
964     NameServerMsg *replyMsg;
965     fd_set rfds;
966     int ret = 0, sock, maxfd, waitFd;
967     struct timeval tv;
968     uint64_t buf = 1;
969     int numBytes;
970     int err;
971     int i;
972     static int seqNum = 0;
973     Bool done = FALSE;
975     /* Set Timeout to wait: */
976     tv.tv_sec = 0;
977     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
979     /* Create request message and send to remote: */
980     sock = NameServer_module->sendSock[procId];
981     if (sock == INVALIDSOCKET) {
982         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
983              procId);
984         status = NameServer_E_RESOURCE;
985         goto exit;
986     }
988     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
990     /* Create request message and send to remote processor: */
991     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
992     nsMsg.request = NAMESERVER_REQUEST;
993     nsMsg.requestStatus = 0;
994     nsMsg.valueLen = *len;
995     nsMsg.seqNum = seqNum++;
997     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
998     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1000     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
1001            procId, (String)nsMsg.instanceName)
1002     LOG1("%s...\n", (String)nsMsg.name)
1004     err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
1005     if (err < 0) {
1006         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1007              errno, strerror(errno))
1008         status = NameServer_E_FAIL;
1009         goto exit;
1010     }
1012     while (!done) {
1013         /* Block on waitFd for signal from listener thread: */
1014         waitFd = NameServer_module->waitFd;
1015         FD_ZERO(&rfds);
1016         FD_SET(waitFd, &rfds);
1017         maxfd = waitFd + 1;
1018         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1019         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1020         if (ret == -1) {
1021             LOG0("NameServer_getRemote: select failed.")
1022             status = NameServer_E_FAIL;
1023             goto exit;
1024         }
1025         else if (!ret) {
1026             LOG0("NameServer_getRemote: select timed out.\n")
1027             status = NameServer_E_TIMEOUT;
1028             goto exit;
1029         }
1031         if (FD_ISSET(waitFd, &rfds)) {
1032             /* Read, just to balance the write: */
1033             numBytes = read(waitFd, &buf, sizeof(uint64_t));
1035             /* Process response: */
1036             replyMsg = &NameServer_module->nsMsg;
1038             if (replyMsg->seqNum != seqNum - 1) {
1039                 /* Ignore responses without current sequence # */
1040                 continue;
1041             }
1043             if (replyMsg->requestStatus) {
1044                 /* name is found */
1046                 /* set length to amount of data that was copied */
1047                 *len = replyMsg->valueLen;
1049                 /* set the contents of value */
1050                 if (*len <= sizeof (Bits32)) {
1051                     *(UInt32 *)value = (UInt32)replyMsg->value;
1052                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1053                         procId, (String)replyMsg->instanceName)
1054                     LOG2("%s, value: 0x%x...\n",
1055                         (String)replyMsg->name, *(UInt32 *)value)
1056                 }
1057                 else {
1058                     memcpy(value, replyMsg->valueBuf, *len);
1059                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1060                         procId, (String)replyMsg->instanceName)
1061                     for (i = 0; i < *len/4; i++) {
1062                         LOG2("%s, value buffer content: 0x%x...\n",
1063                             (String)replyMsg->name, ((uint32_t *)value)[i])
1064                     }
1065                 }
1067                 goto exit;
1068             }
1069             else {
1070                 /* name is not found */
1071                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1072                      (String)replyMsg->instanceName, (String)replyMsg->name)
1074                 /* set status to not found */
1075                 status = NameServer_E_NOTFOUND;
1076             }
1077         }
1078         done= TRUE;
1079     }
1081 exit:
1082     return (status);
1085 /* Function to retrieve the value portion of a name/value pair from
1086  * local table.
1087  */
1088 Int NameServer_get(NameServer_Handle handle,
1089                String            name,
1090                Ptr               value,
1091                UInt32 *          len,
1092                UInt16            procId[])
1094     Int status = NameServer_S_SUCCESS;
1095     UInt16 numProcs = MultiProc_getNumProcessors();
1096     UInt32 i;
1098     /*
1099      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1100      * since this goes in a daemon, it will not be necessary.
1101      */
1103     if (procId == NULL) {
1104         status = NameServer_getLocal(handle, name, value, len);
1105         if (status == NameServer_E_NOTFOUND) {
1106             for (i = 0; i < numProcs; i++) {
1107                 /* getLocal call already covers "self", keep going */
1108                 if (i == MultiProc_self()) {
1109                     continue;
1110                 }
1112                 status = NameServer_getRemote(handle, name, value, len, i);
1114                 if ((status >= 0) ||
1115                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1116                                      (status != NameServer_E_RESOURCE))) {
1117                     break;
1118                 }
1119             }
1120         }
1121     }
1122     else {
1123         /*
1124          *  Search the query list. It might contain the local proc
1125          *  somewhere in the list.
1126          */
1127         i = 0;
1128         while (procId[i] != MultiProc_INVALIDID) {
1129             if (procId[i] == MultiProc_self()) {
1130                 status = NameServer_getLocal(handle, name, value, len);
1131             }
1132             else {
1133                 status = NameServer_getRemote(handle, name, value, len, i);
1134             }
1136             if ((status >= 0) ||
1137                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1138                                  (status != NameServer_E_RESOURCE))) {
1139                 break;
1140             }
1142             i++;
1143         }
1144     }
1146     if (status == NameServer_E_RESOURCE) {
1147         status = NameServer_E_NOTFOUND;
1148     }
1150     return (status);
1153 /* Gets a 32-bit value by name */
1154 Int NameServer_getUInt32(NameServer_Handle handle,
1155                      String            name,
1156                      Ptr               value,
1157                      UInt16            procId[])
1159     Int  status;
1160     UInt32 len = sizeof(UInt32);
1162     assert(handle != NULL);
1163     assert(name   != NULL);
1164     assert(value  != NULL);
1165     assert(NameServer_module->refCount != 0);
1167     status = NameServer_get(handle, name, value, &len, procId);
1169     return (status);
1172 /* Function to Retrieve the value portion of a name/value pair from
1173  * local table.
1174  */
1175 Int NameServer_getLocal(NameServer_Handle handle,
1176                     String            name,
1177                     Ptr               value,
1178                     UInt32 *          len)
1180     Int status = NameServer_E_NOTFOUND;
1181     NameServer_TableEntry * node = NULL;
1182     NameServer_TableEntry * temp = NULL;
1183     Bool done   = FALSE;
1184     UInt32 length;
1185     UInt32 hash;
1187     assert(handle != NULL);
1188     assert(name   != NULL);
1189     assert(value  != NULL);
1190     assert(len    != NULL);
1191     assert(NameServer_module->refCount != 0);
1193     length = *len;
1195     /* Calculate the hash */
1196     hash = stringHash(name);
1198     pthread_mutex_lock(&handle->gate);
1200     /* Traverse the list to find duplicate check */
1201     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1202         if (node->hash == hash) {
1203             if (node->collide == TRUE) {
1204                 temp = node;
1205                 while (temp) {
1206                     if (strcmp(temp->name, name) == 0u){
1207                         if (length <= node->len) {
1208                             memcpy(value, node->value, length);
1209                             *len = length;
1210                         }
1211                         else {
1212                             memcpy(value, node->value, node->len);
1213                             *len = node->len;
1214                         }
1215                         done = TRUE;
1216                         break;
1217                     }
1218                     temp = temp->next;
1219                 }
1220                 break;
1221             }
1222             else {
1223                 if (length <= node->len) {
1224                     memcpy(value, node->value, length);
1225                     *len = length;
1226                 }
1227                 else {
1228                     memcpy(value, node->value, node->len);
1229                     *len = node->len;
1230                 }
1231                 done = TRUE;
1232                 break;
1233             }
1234         }
1235     }
1237     pthread_mutex_unlock(&handle->gate);
1239     if (done == FALSE) {
1240         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1241     }
1242     else {
1243         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1244              node->name, (UInt32)node->value)
1245         status = NameServer_S_SUCCESS;
1246     }
1248     return (status);
1251 /*
1252  *  Gets a 32-bit value by name from the local table
1253  *
1254  *  If the name is found, the 32-bit value is copied into the value
1255  *  argument and a success status is returned.
1256  *
1257  *  If the name is not found, zero is returned in len and the contents
1258  *  of value are not modified. Not finding a name is not considered
1259  *  an error.
1260  *
1261  *  This function only searches the local name/value table.
1262  *
1263  */
1264 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1266     Int                 status;
1267     UInt32              len    = sizeof(UInt32);
1269     assert(handle != NULL);
1270     assert(name   != NULL);
1271     assert(value  != NULL);
1272     assert(NameServer_module->refCount != 0);
1274     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1275     status = NameServer_getLocal(handle, name, value, &len);
1277     return (status);
1281 #if defined (__cplusplus)
1283 #endif /* defined (__cplusplus) */