abaf757f800809cf808bc438ab8e8be84f0248de
[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;
973     /* Set Timeout to wait: */
974     tv.tv_sec = 0;
975     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
977     /* Create request message and send to remote: */
978     sock = NameServer_module->sendSock[procId];
979     if (sock == INVALIDSOCKET) {
980         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
981              procId);
982         status = NameServer_E_RESOURCE;
983         goto exit;
984     }
986     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
988     /* Create request message and send to remote processor: */
989     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
990     nsMsg.request = NAMESERVER_REQUEST;
991     nsMsg.requestStatus = 0;
992     nsMsg.valueLen = *len;
994     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
995     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
997     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
998            procId, (String)nsMsg.instanceName)
999     LOG1("%s...\n", (String)nsMsg.name)
1001     err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
1002     if (err < 0) {
1003         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1004              errno, strerror(errno))
1005         status = NameServer_E_FAIL;
1006         goto exit;
1007     }
1009     /* Block on waitFd for signal from listener thread: */
1010     waitFd = NameServer_module->waitFd;
1011     FD_ZERO(&rfds);
1012     FD_SET(waitFd, &rfds);
1013     maxfd = waitFd + 1;
1014     LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1015     ret = select(maxfd, &rfds, NULL, NULL, &tv);
1016     if (ret == -1) {
1017         LOG0("NameServer_getRemote: select failed.")
1018         status = NameServer_E_FAIL;
1019         goto exit;
1020     }
1021     else if (!ret) {
1022         LOG0("NameServer_getRemote: select timed out.\n")
1023         status = NameServer_E_TIMEOUT;
1024         goto exit;
1025     }
1027     if (FD_ISSET(waitFd, &rfds)) {
1028         /* Read, just to balance the write: */
1029         numBytes = read(waitFd, &buf, sizeof(uint64_t));
1031         /* Process response: */
1032         replyMsg = &NameServer_module->nsMsg;
1034         if (replyMsg->requestStatus) {
1035             /* name is found */
1037             /* set length to amount of data that was copied */
1038             *len = replyMsg->valueLen;
1040             /* set the contents of value */
1041             if (*len <= sizeof (Bits32)) {
1042                 *(UInt32 *)value = (UInt32)replyMsg->value;
1043                 LOG2("NameServer_getRemote: Reply from: %d, %s:",
1044                     procId, (String)replyMsg->instanceName)
1045                 LOG2("%s, value: 0x%x...\n",
1046                     (String)replyMsg->name, *(UInt32 *)value)
1047             }
1048             else {
1049                 memcpy(value, replyMsg->valueBuf, *len);
1050                 LOG2("NameServer_getRemote: Reply from: %d, %s:",
1051                     procId, (String)replyMsg->instanceName)
1052                 for (i = 0; i < *len/4; i++) {
1053                     LOG2("%s, value buffer content: 0x%x...\n",
1054                         (String)replyMsg->name, ((uint32_t *)value)[i])
1055                 }
1056             }
1058             goto exit;
1059         }
1060         else {
1061             /* name is not found */
1062             LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1063                  (String)replyMsg->instanceName, (String)replyMsg->name)
1065             /* set status to not found */
1066             status = NameServer_E_NOTFOUND;
1067         }
1068     }
1070 exit:
1071     return (status);
1074 /* Function to retrieve the value portion of a name/value pair from
1075  * local table.
1076  */
1077 Int NameServer_get(NameServer_Handle handle,
1078                String            name,
1079                Ptr               value,
1080                UInt32 *          len,
1081                UInt16            procId[])
1083     Int status = NameServer_S_SUCCESS;
1084     UInt16 numProcs = MultiProc_getNumProcessors();
1085     UInt32 i;
1087     /*
1088      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1089      * since this goes in a daemon, it will not be necessary.
1090      */
1092     if (procId == NULL) {
1093         status = NameServer_getLocal(handle, name, value, len);
1094         if (status == NameServer_E_NOTFOUND) {
1095             for (i = 0; i < numProcs; i++) {
1096                 /* getLocal call already covers "self", keep going */
1097                 if (i == MultiProc_self()) {
1098                     continue;
1099                 }
1101                 status = NameServer_getRemote(handle, name, value, len, i);
1103                 if ((status >= 0) ||
1104                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1105                                      (status != NameServer_E_RESOURCE))) {
1106                     break;
1107                 }
1108             }
1109         }
1110     }
1111     else {
1112         /*
1113          *  Search the query list. It might contain the local proc
1114          *  somewhere in the list.
1115          */
1116         i = 0;
1117         while (procId[i] != MultiProc_INVALIDID) {
1118             if (procId[i] == MultiProc_self()) {
1119                 status = NameServer_getLocal(handle, name, value, len);
1120             }
1121             else {
1122                 status = NameServer_getRemote(handle, name, value, len, i);
1123             }
1125             if ((status >= 0) ||
1126                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1127                                  (status != NameServer_E_RESOURCE))) {
1128                 break;
1129             }
1131             i++;
1132         }
1133     }
1135     if (status == NameServer_E_RESOURCE) {
1136         status = NameServer_E_NOTFOUND;
1137     }
1139     return (status);
1142 /* Gets a 32-bit value by name */
1143 Int NameServer_getUInt32(NameServer_Handle handle,
1144                      String            name,
1145                      Ptr               value,
1146                      UInt16            procId[])
1148     Int  status;
1149     UInt32 len = sizeof(UInt32);
1151     assert(handle != NULL);
1152     assert(name   != NULL);
1153     assert(value  != NULL);
1154     assert(NameServer_module->refCount != 0);
1156     status = NameServer_get(handle, name, value, &len, procId);
1158     return (status);
1161 /* Function to Retrieve the value portion of a name/value pair from
1162  * local table.
1163  */
1164 Int NameServer_getLocal(NameServer_Handle handle,
1165                     String            name,
1166                     Ptr               value,
1167                     UInt32 *          len)
1169     Int status = NameServer_E_NOTFOUND;
1170     NameServer_TableEntry * node = NULL;
1171     NameServer_TableEntry * temp = NULL;
1172     Bool done   = FALSE;
1173     UInt32 length;
1174     UInt32 hash;
1176     assert(handle != NULL);
1177     assert(name   != NULL);
1178     assert(value  != NULL);
1179     assert(len    != NULL);
1180     assert(NameServer_module->refCount != 0);
1182     length = *len;
1184     /* Calculate the hash */
1185     hash = stringHash(name);
1187     pthread_mutex_lock(&handle->gate);
1189     /* Traverse the list to find duplicate check */
1190     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1191         if (node->hash == hash) {
1192             if (node->collide == TRUE) {
1193                 temp = node;
1194                 while (temp) {
1195                     if (strcmp(temp->name, name) == 0u){
1196                         if (length <= node->len) {
1197                             memcpy(value, node->value, length);
1198                             *len = length;
1199                         }
1200                         else {
1201                             memcpy(value, node->value, node->len);
1202                             *len = node->len;
1203                         }
1204                         done = TRUE;
1205                         break;
1206                     }
1207                     temp = temp->next;
1208                 }
1209                 break;
1210             }
1211             else {
1212                 if (length <= node->len) {
1213                     memcpy(value, node->value, length);
1214                     *len = length;
1215                 }
1216                 else {
1217                     memcpy(value, node->value, node->len);
1218                     *len = node->len;
1219                 }
1220                 done = TRUE;
1221                 break;
1222             }
1223         }
1224     }
1226     pthread_mutex_unlock(&handle->gate);
1228     if (done == FALSE) {
1229         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1230     }
1231     else {
1232         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1233              node->name, (UInt32)node->value)
1234         status = NameServer_S_SUCCESS;
1235     }
1237     return (status);
1240 /*
1241  *  Gets a 32-bit value by name from the local table
1242  *
1243  *  If the name is found, the 32-bit value is copied into the value
1244  *  argument and a success status is returned.
1245  *
1246  *  If the name is not found, zero is returned in len and the contents
1247  *  of value are not modified. Not finding a name is not considered
1248  *  an error.
1249  *
1250  *  This function only searches the local name/value table.
1251  *
1252  */
1253 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1255     Int                 status;
1256     UInt32              len    = sizeof(UInt32);
1258     assert(handle != NULL);
1259     assert(name   != NULL);
1260     assert(value  != NULL);
1261     assert(NameServer_module->refCount != 0);
1263     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1264     status = NameServer_getLocal(handle, name, value, &len);
1266     return (status);
1270 #if defined (__cplusplus)
1272 #endif /* defined (__cplusplus) */