]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/NameServer_daemon.c
SDOCM00114391 IPC cluster support is missing on Linux
[ipc/ipcdev.git] / linux / src / daemon / NameServer_daemon.c
1 /*
2  * Copyright (c) 2012-2015 Texas Instruments Incorporated - http://www.ti.com
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               waitFd = NameServer_module->waitFd;
247     UInt16            clusterId;
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         clusterId = procId - MultiProc_getBaseIdOfCluster();
292         err = send(NameServer_module->sendSock[clusterId], msg,
293                    sizeof(NameServerMsg), 0);
294         if (err < 0) {
295             LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
296         }
297     }
298     else {
299         LOG2("NameServer Reply: instanceName: %s, name: %s",
300              (String)msg->instanceName, (String)msg->name)
301         LOG1(", value: 0x%x\n", msg->value)
303         /* Save the response message.  */
304         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
306         /* Post the eventfd upon which NameServer_get() is waiting */
307         write(waitFd, &buf, sizeof(uint64_t));
308     }
312 static void *listener_cb(void *arg)
314     fd_set rfds;
315     int ret = 0, maxfd;
316     int i;
317     UInt16 procId;
318     struct  sockaddr_rpmsg  fromAddr;
319     unsigned int len;
320     NameServerMsg msg;
321     int     byteCount;
322     UInt16  numProcs = MultiProc_getNumProcsInCluster();
323     UInt16  baseId = MultiProc_getBaseIdOfCluster();
324     int     sock;
326     LOG0("listener_cb: Entered Listener thread.\n")
328     do {
329         /* Wait for NameServer messages or unblockFd notification */
330         FD_ZERO(&rfds);
331         FD_SET(NameServer_module->unblockFd, &rfds);
332         maxfd = NameServer_module->unblockFd;
334         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
335             if ((MultiProc_self() == procId)
336                 || (NameServer_module->recvSock[i] == INVALIDSOCKET)) {
337                 continue;
338             }
339             sock = NameServer_module->recvSock[i];
340             FD_SET(sock, &rfds);
341             maxfd = MAX(sock, maxfd);
342         }
344         maxfd = maxfd + 1;
345         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
346              NameServer_module->unblockFd, maxfd)
347         ret = select(maxfd, &rfds, NULL, NULL, NULL);
348         if (ret == -1) {
349             LOG0("listener_cb: select failed.")
350             break;
351         }
352         LOG0("NameServer: back from select()\n")
354         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
355             if ((MultiProc_self() == procId)
356                 || (NameServer_module->recvSock[i] == INVALIDSOCKET)) {
357                 continue;
358             }
359             sock = NameServer_module->recvSock[i];
360             if (FD_ISSET(sock, &rfds)) {
361                 LOG1("NameServer: Listener got NameServer message "
362                      "from sock: %d!\n", sock);
363                 /* Get NameServer message and process: */
364                 memset(&fromAddr, 0, sizeof(fromAddr));
365                 len = sizeof(fromAddr);
367                 byteCount = recvfrom(sock, &msg, sizeof(NameServerMsg), 0,
368                                 (struct sockaddr *)&fromAddr, &len);
369                 if (len != sizeof(fromAddr)) {
370                     LOG1("recvfrom: got bad addr len (%d)\n", len)
371                     break;
372                 }
373                 if (byteCount < 0) {
374                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
375                     break;
376                 }
377                 else {
378                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
379                     LOG2("\tReceived ns msg: byteCount: %d, from addr: %d, ",
380                          byteCount, fromAddr.addr)
381                     LOG1("from vproc: %d\n", fromAddr.vproc_id)
382                     NameServerRemote_processMessage(&msg, procId);
383                 }
384             }
385         }
386         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
387             /* We are told to unblock and exit: */
388             LOG0("NameServer: Listener thread exiting\n")
389             break;
390         }
391     } while (1);
393     return ((void *)ret);
396 /* =============================================================================
397  * APIS
398  * =============================================================================
399  */
401 /* Function to setup the nameserver module. */
402 Int NameServer_setup(Void)
404     Int    status = NameServer_S_SUCCESS;
405     int    err;
406     int    sock;
407     int    ret;
408     int    clId;
409     UInt16 procId;
410     UInt16 numProcs;
411     UInt16 baseId;
413     pthread_mutex_lock(&NameServer_module->modGate);
415     LOG1("NameServer_setup: entered, refCount=%d\n",
416             NameServer_module->refCount)
418     NameServer_module->refCount++;
420     if (NameServer_module->refCount > 1) {
421         LOG0("NameServer_setup: already setup\n")
422         status = NameServer_S_ALREADYSETUP;
423         goto exit;
424     }
426     NameServer_module->unblockFd = eventfd(0, 0);
427     if (NameServer_module->unblockFd < 0) {
428         status = NameServer_E_FAIL;
429         LOG0("NameServer_setup: failed to create unblockFd.\n")
430         goto exit;
431     }
433     NameServer_module->waitFd = eventfd(0, 0);
434     if (NameServer_module->waitFd < 0) {
435         status = NameServer_E_FAIL;
436         LOG0("NameServer_setup: failed to create waitFd.\n")
437         goto exit;
438     }
440     numProcs = MultiProc_getNumProcsInCluster();
441     baseId = MultiProc_getBaseIdOfCluster();
443     for (clId = 0, procId = baseId; clId < numProcs; clId++, procId++) {
444         NameServer_module->sendSock[clId] = INVALIDSOCKET;
445         NameServer_module->recvSock[clId] = INVALIDSOCKET;
447         /* Only support NameServer to remote procs: */
448         if (MultiProc_self() == procId) {
449             continue;
450         }
452         /* Create the socket for sending messages to each remote proc: */
453         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
454         if (sock < 0) {
455             status = NameServer_E_FAIL;
456             LOG2("NameServer_setup: socket failed: %d, %s\n",
457                  errno, strerror(errno))
458         }
459         else  {
460             LOG1("NameServer_setup: created send socket: %d\n", sock)
461             err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
462             if (err < 0) {
463                 status = NameServer_E_FAIL;
464                 LOG3("NameServer_setup: connect failed: procId=%d, "
465                         "errno=%d (%s)\n", procId, errno, strerror(errno))
467                 LOG1("    closing send socket: %d\n", sock)
468                 close(sock);
469             }
470             else {
471                 NameServer_module->sendSock[clId] = sock;
472             }
473         }
475         /* Create the socket for recving messages from each remote proc: */
476         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
477         if (sock < 0) {
478             status = NameServer_E_FAIL;
479             LOG2("NameServer_setup: socket failed: %d, %s\n",
480                  errno, strerror(errno))
481         }
482         else  {
483             LOG1("NameServer_setup: created recv socket: %d\n", sock)
485             err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
486             if (err < 0) {
487                 status = NameServer_E_FAIL;
488                 LOG2("NameServer_setup: bind failed: %d, %s\n",
489                     errno, strerror(errno))
491                 LOG1("    closing recv socket: %d\n", sock)
492                 close(sock);
493             }
494             else {
495                 NameServer_module->recvSock[clId] = sock;
496             }
497         }
498     }
500     /* Construct the list object */
501     CIRCLEQ_INIT(&NameServer_module->objList);
503     /* Create the listener thread: */
504     LOG0("NameServer_setup: creating listener thread\n")
505     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
506     if (ret) {
507         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
508         LOG0("NameServer_setup: eventfd failed");
510         status = NameServer_E_FAIL;
511     }
512     else {
513         /* look for at least one good send/recv pair to indicate success */
514         for (clId = 0; clId < numProcs; clId++) {
515             if (NameServer_module->sendSock[clId] != INVALIDSOCKET &&
516                 NameServer_module->recvSock[clId] != INVALIDSOCKET) {
517                 status = NameServer_S_SUCCESS;
518                 break;
519             }
520         }
521     }
523 exit:
524     LOG1("NameServer_setup: exiting, refCount=%d\n",
525             NameServer_module->refCount)
527     pthread_mutex_unlock(&NameServer_module->modGate);
529     return (status);
532 /*! Function to destroy the nameserver module. */
533 Int NameServer_destroy(void)
535     Int      status = NameServer_S_SUCCESS;
536     UInt16   numProcs;
537     UInt16   baseId;
538     UInt16   procId;
539     int      clId;
540     int      sock;
541     uint64_t buf = 1;
543     pthread_mutex_lock(&NameServer_module->modGate);
545     LOG1("NameServer_destroy: entered, refCount=%d\n",
546             NameServer_module->refCount)
548     NameServer_module->refCount--;
550     if (NameServer_module->refCount > 0) {
551         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n",
552                 NameServer_module->refCount)
553         status = NameServer_S_SUCCESS;
554         goto exit;
555     }
557     numProcs = MultiProc_getNumProcsInCluster();
558     baseId = MultiProc_getBaseIdOfCluster();
560     LOG2("NameServer_destroy: numProcs=%d, baseId=%d\n", numProcs, baseId);
562     for (clId = 0, procId = baseId; clId < numProcs; clId++, procId++) {
564         /* Only support NameServer to remote procs: */
565         if (MultiProc_self() == procId) {
566             continue;
567         }
569         /* Close the socket: */
570         sock = NameServer_module->sendSock[clId];
571         if (sock != INVALIDSOCKET) {
572             LOG1("NameServer_destroy: closing socket: %d\n", sock)
573             close(sock);
574             NameServer_module->sendSock[clId] = INVALIDSOCKET;
575         }
576         /* Close the socket: */
577         sock = NameServer_module->recvSock[clId];
578         if (sock != INVALIDSOCKET) {
579             LOG1("NameServer_destroy: closing socket: %d\n", sock)
580             close(sock);
581             NameServer_module->recvSock[clId] = INVALIDSOCKET;
582         }
583     }
585     CIRCLEQ_destruct(&NameServer_module->objList);
587     /* Unblock the NameServer listener thread: */
588     LOG0("NameServer_destroy: unblocking listener...\n")
589     write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
591     /* Join: */
592     LOG0("NameServer_destroy: joining listener thread...\n")
593     pthread_join(NameServer_module->listener, NULL);
595     close(NameServer_module->unblockFd);
596     close(NameServer_module->waitFd);
598 exit:
599     LOG1("NameServer_destroy: exiting, refCount=%d\n",
600             NameServer_module->refCount)
602     pthread_mutex_unlock(&NameServer_module->modGate);
604     return (status);
607 /* Function to retrieve a NameServer handle from name. */
608 NameServer_Handle NameServer_getHandle(String name)
610     NameServer_Handle handle = NULL;
611     Bool              found = FALSE;
612     struct NameServer_Object * elem;
614     assert(name != NULL);
615     assert(NameServer_module->refCount != 0);
617     pthread_mutex_lock(&NameServer_module->modGate);
619     /* Lookup handle from name: */
620     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
621         handle = (NameServer_Handle) elem;
622         if (strcmp(handle->name, name) == 0) {
623             found = TRUE;
624             break;
625         }
626     }
628     if (found == FALSE) {
629         handle = NULL;
630     }
632     pthread_mutex_unlock(&NameServer_module->modGate);
634     return (handle);
638 /* Function to create a name server. */
639 NameServer_Handle NameServer_create(String name,
640                                     const NameServer_Params * params)
642     NameServer_Handle handle = NULL;
643     pthread_mutexattr_t mutex_attr;
645     assert(params != NULL);
646     assert(name != NULL);
647     assert(NameServer_module->refCount != 0);
649     LOG1("NameServer_create(): '%s'\n", name)
651     pthread_mutex_lock(&NameServer_module->modGate);
653     /* check if the name is already created or not */
654     handle = NameServer_getHandle(name);
655     if (handle != NULL) {
656         if (memcmp((Ptr)&handle->params, (Ptr)params,
657             sizeof(NameServer_Params)) == 0) {
658             handle->refCount++;
659         }
660         else {
661             LOG0("NameServer_create: NameServer params mismatch\n")
662             handle = NULL;
663         }
664         goto leave;
665     }
666     else {
667         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
668     }
670     if (!handle) {
671         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
672         goto leave;
673     }
675     handle->refCount = 1;
676     handle->name = (String)malloc(strlen(name) + 1u);
677     if (!handle->name) {
678         LOG0("NameServer_create: instance name alloc failed\n")
679         goto cleanup;
680     }
681     strncpy(handle->name, name, strlen (name) + 1u);
682     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
684     if (params->maxValueLen < sizeof(UInt32)) {
685         handle->params.maxValueLen = sizeof(UInt32);
686     }
687     else {
688         handle->params.maxValueLen = params->maxValueLen;
689     }
691     CIRCLEQ_INIT(&handle->nameList);
692     handle->count = 0u;
694     /* Put in the local list */
695     CIRCLEQ_elemClear(&handle->elem);
696     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
698     /*
699      * NameServer_removeEntry() enters gate and is called by
700      * NameServer_remove() while holding the gate.
701      */
702     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
703     pthread_mutex_init(&handle->gate, &mutex_attr);
705     goto leave;
707 cleanup:
708     free(handle);
709     handle = NULL;
711 leave:
712     pthread_mutex_unlock(&NameServer_module->modGate);
714     return (handle);
718 /* Function to delete a name server. */
719 Int NameServer_delete(NameServer_Handle * handle)
721     Int status = NameServer_S_SUCCESS;
723     assert(handle != NULL);
724     assert(*handle != NULL);
725     assert((*handle)->count == 0);
726     assert(NameServer_module->refCount != 0);
728     pthread_mutex_lock(&NameServer_module->modGate);
730     (*handle)->refCount--;
731     if ((*handle)->refCount != 0) {
732         goto leave;
733     }
735     if ((*handle)->count == 0) {
736         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
738         if ((*handle)->name != NULL) {
739             free((*handle)->name);
740             (*handle)->name = NULL;
741         }
743         CIRCLEQ_destruct(&(*handle)->nameList);
745         free((*handle));
746         (*handle) = NULL;
747     }
749 leave:
750     pthread_mutex_unlock(&NameServer_module->modGate);
752     return (status);
755 /* Adds a variable length value into the local NameServer table */
756 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
758     Int                 status = NameServer_S_SUCCESS;
759     NameServer_TableEntry * node = NULL;
760     NameServer_TableEntry * new_node = NULL;
761     Bool                found = FALSE;
762     UInt32              hash;
764     assert(handle != NULL);
765     assert(name     != NULL);
766     assert(buf      != NULL);
767     assert(len      != 0);
768     assert(NameServer_module->refCount != 0);
770     /* Calculate the hash */
771     hash = stringHash(name);
773     if (len > handle->params.maxValueLen) {
774         status = NameServer_E_INVALIDARG;
775         LOG0("NameServer_add: value length exceeded maximum!\n")
776         new_node = NULL;
777         goto exit;
778     }
780     pthread_mutex_lock(&handle->gate);
782     /* Traverse the list to find duplicate check */
783     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
784         /* Hash matches */
785         if (node->hash == hash) {
786             /* If the name matches, incase hash is duplicate */
787             if (strcmp(node->name, name) == 0) {
788                 if (handle->params.checkExisting == TRUE) {
789                     status = NameServer_E_INVALIDARG;
790                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
791                     break;
792                 }
793             }
794             else {
795                 found = TRUE;
796                 break;
797             } /* name does not match */
798         } /* hash does not match */
799     } /* CIRCLEQ_traverse */
801     if (status != NameServer_S_SUCCESS) {
802         new_node = NULL;
803         goto exit;
804     }
806     /* Now add the new entry. */
807     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
808     if (new_node == NULL) {
809         status = NameServer_E_MEMORY;
810         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
812         goto exit;
813     }
815     new_node->hash    = hash;
816     new_node->collide = found; /* Indicate if there is a collision*/
817     new_node->len     = len;
818     new_node->next    = NULL;
819     new_node->name = (String)malloc(strlen(name) + 1u);
820     new_node->value  = (Ptr)malloc(len);
821     strncpy(new_node->name, name, strlen(name) + 1u);
822     memcpy((Ptr)new_node->value, (Ptr)buf, len);
824     if (found == TRUE) {
825         /* If hash is found, need to stitch the list to link the
826          * new node to the existing node with the same hash.
827          */
828         new_node->next = node->next;
829         node->next = new_node;
830     }
831     else {
832         /* put the new node into the list */
833         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
834     }
836     handle->count++;
838     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
839          name, *(UInt32 *)buf)
841 exit:
842     pthread_mutex_unlock(&handle->gate);
844     return (new_node);
848 /* Function to add a UInt32 value into a name server. */
849 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
851     Ptr entry = NULL;
853     assert(handle != NULL);
854     assert(name   != NULL);
855     assert(NameServer_module->refCount != 0);
857     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
859     return (entry);
862 /* Function to remove a name/value pair from a name server. */
863 Int NameServer_remove(NameServer_Handle handle, String name)
865     Int                 status = NameServer_S_SUCCESS;
866     NameServer_TableEntry *prev = NULL;
867     NameServer_TableEntry *temp = NULL;
868     NameServer_TableEntry *node = NULL;
869     Bool                done   = FALSE;
870     UInt32              hash;
872     assert(handle != NULL);
873     assert(name   != NULL);
874     assert(NameServer_module->refCount != 0);
876     /* Calculate the hash */
877     hash = stringHash(name);
879     pthread_mutex_lock(&handle->gate);
881     /* Traverse the list to find duplicate check */
882     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
883         /* Hash matchs */
884         if (node->hash == hash) {
885             if (node->collide == TRUE) {
886                 if (strcmp(node->name, name) == 0){
887                     free(node->value);
888                     free(node->name);
889                     memcpy((Ptr)node, (Ptr) node->next,
890                            sizeof(NameServer_TableEntry));
891                     node->next = node->next->next;
892                     free(node->next);
893                     handle->count--;
894                     done = TRUE;
895                     break;
896                 }
897                 else {
898                     prev = node;
899                     temp = node->next;
900                     while (temp) {
901                         if (strcmp(temp->name, name) == 0){
902                             free(temp->value);
903                             free(temp->name);
904                             prev->next = temp->next;
905                             free(temp);
906                             handle->count--;
907                             done = TRUE;
908                             break;
909                         }
910                         temp = temp->next;
911                     }
912                     break;
913                 }
914             }
915             else {
916                 NameServer_removeEntry(handle, (Ptr)node);
918                 done = TRUE;
919                 break;
920             }
921         }
922     }
924     if (done == FALSE) {
925         status = NameServer_E_INVALIDARG;
926         LOG1("NameServer_remove %d Entry not found!\n", status)
927     }
929     pthread_mutex_unlock(&handle->gate);
931     return (status);
934 /* Function to remove a name/value pair from a name server. */
935 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
937     Int  status = NameServer_S_SUCCESS;
938     NameServer_TableEntry * node;
940     assert(handle != NULL);
941     assert(entry  != NULL);
942     assert(NameServer_module->refCount != 0);
944     pthread_mutex_lock(&handle->gate);
946     node = (NameServer_TableEntry *)entry;
948     free(node->value);
949     free(node->name);
950     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
951     free(node);
952     handle->count--;
954     pthread_mutex_unlock(&handle->gate);
956     return (status);
960 /* Initialize this config-params structure with supplier-specified
961  * defaults before instance creation.
962  */
963 Void NameServer_Params_init(NameServer_Params * params)
965     assert(params != NULL);
967     memcpy(params, &(NameServer_module->defInstParams),
968            sizeof (NameServer_Params));
972 Int NameServer_getRemote(NameServer_Handle handle,
973                      String            name,
974                      Ptr               value,
975                      UInt32 *          len,
976                      UInt16            procId)
978     Int status = NameServer_S_SUCCESS;
979     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
980     NameServerMsg nsMsg;
981     NameServerMsg *replyMsg;
982     fd_set rfds;
983     int ret = 0, sock, maxfd, waitFd;
984     struct timeval tv;
985     uint64_t buf = 1;
986     int err;
987     int i;
988     static int seqNum = 0;
989     Bool done = FALSE;
990     UInt16 clusterId;
992     /* Set Timeout to wait: */
993     tv.tv_sec = 0;
994     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
996     /* Create request message and send to remote: */
997     clusterId = procId - MultiProc_getBaseIdOfCluster();
998     sock = NameServer_module->sendSock[clusterId];
999     if (sock == INVALIDSOCKET) {
1000         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
1001              procId);
1002         status = NameServer_E_RESOURCE;
1003         goto exit;
1004     }
1006     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
1008     /* Create request message and send to remote processor: */
1009     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
1010     nsMsg.request = NAMESERVER_REQUEST;
1011     nsMsg.requestStatus = 0;
1012     nsMsg.valueLen = *len;
1013     nsMsg.seqNum = seqNum++;
1015     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
1016     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1018     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
1019            procId, (String)nsMsg.instanceName)
1020     LOG1("%s...\n", (String)nsMsg.name)
1022     err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
1023     if (err < 0) {
1024         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1025              errno, strerror(errno))
1026         status = NameServer_E_FAIL;
1027         goto exit;
1028     }
1030     while (!done) {
1031         /* Block on waitFd for signal from listener thread: */
1032         waitFd = NameServer_module->waitFd;
1033         FD_ZERO(&rfds);
1034         FD_SET(waitFd, &rfds);
1035         maxfd = waitFd + 1;
1036         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1037         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1038         if (ret == -1) {
1039             LOG0("NameServer_getRemote: select failed.")
1040             status = NameServer_E_FAIL;
1041             goto exit;
1042         }
1043         else if (!ret) {
1044             LOG0("NameServer_getRemote: select timed out.\n")
1045             status = NameServer_E_TIMEOUT;
1046             goto exit;
1047         }
1049         if (FD_ISSET(waitFd, &rfds)) {
1050             /* Read, just to balance the write: */
1051             read(waitFd, &buf, sizeof(uint64_t));
1053             /* Process response: */
1054             replyMsg = &NameServer_module->nsMsg;
1056             if (replyMsg->seqNum != seqNum - 1) {
1057                 /* Ignore responses without current sequence # */
1058                 continue;
1059             }
1061             if (replyMsg->requestStatus) {
1062                 /* name is found */
1064                 /* set length to amount of data that was copied */
1065                 *len = replyMsg->valueLen;
1067                 /* set the contents of value */
1068                 if (*len <= sizeof (Bits32)) {
1069                     *(UInt32 *)value = (UInt32)replyMsg->value;
1070                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1071                         procId, (String)replyMsg->instanceName)
1072                     LOG2("%s, value: 0x%x...\n",
1073                         (String)replyMsg->name, *(UInt32 *)value)
1074                 }
1075                 else {
1076                     memcpy(value, replyMsg->valueBuf, *len);
1077                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1078                         procId, (String)replyMsg->instanceName)
1079                     for (i = 0; i < *len/4; i++) {
1080                         LOG2("%s, value buffer content: 0x%x...\n",
1081                             (String)replyMsg->name, ((uint32_t *)value)[i])
1082                     }
1083                 }
1085                 goto exit;
1086             }
1087             else {
1088                 /* name is not found */
1089                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1090                      (String)replyMsg->instanceName, (String)replyMsg->name)
1092                 /* set status to not found */
1093                 status = NameServer_E_NOTFOUND;
1094             }
1095         }
1096         done= TRUE;
1097     }
1099 exit:
1100     return (status);
1103 /* Function to retrieve the value portion of a name/value pair from
1104  * local table.
1105  */
1106 Int NameServer_get(NameServer_Handle handle,
1107                String            name,
1108                Ptr               value,
1109                UInt32 *          len,
1110                UInt16            procId[])
1112     Int status = NameServer_S_SUCCESS;
1113     UInt16 numProcs;
1114     UInt32 i;
1115     UInt16 clusterId;
1116     UInt16 baseId;
1118     numProcs = MultiProc_getNumProcsInCluster();
1119     baseId = MultiProc_getBaseIdOfCluster();
1121     /*
1122      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1123      * since this goes in a daemon, it will not be necessary.
1124      */
1126     if (procId == NULL) {
1127         status = NameServer_getLocal(handle, name, value, len);
1128         if (status == NameServer_E_NOTFOUND) {
1129             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1131                 /* getLocal call already covers "self", keep going */
1132                 if ((baseId + clusterId) == MultiProc_self()) {
1133                     continue;
1134                 }
1136                 status = NameServer_getRemote(handle, name, value, len,
1137                         baseId + clusterId);
1139                 if ((status >= 0) ||
1140                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1141                                      (status != NameServer_E_RESOURCE))) {
1142                     break;
1143                 }
1144             }
1145         }
1146     }
1147     else {
1148         /*
1149          *  Search the query list. It might contain the local proc
1150          *  somewhere in the list.
1151          */
1152         i = 0;
1153         while (procId[i] != MultiProc_INVALIDID) {
1154             if (procId[i] == MultiProc_self()) {
1155                 status = NameServer_getLocal(handle, name, value, len);
1156             }
1157             else {
1158                 status = NameServer_getRemote(handle, name, value, len,
1159                         procId[i]);
1160             }
1162             if ((status >= 0) ||
1163                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1164                                  (status != NameServer_E_RESOURCE))) {
1165                 break;
1166             }
1168             i++;
1169         }
1170     }
1172     if (status == NameServer_E_RESOURCE) {
1173         status = NameServer_E_NOTFOUND;
1174     }
1176     return (status);
1179 /* Gets a 32-bit value by name */
1180 Int NameServer_getUInt32(NameServer_Handle handle,
1181                      String            name,
1182                      Ptr               value,
1183                      UInt16            procId[])
1185     Int  status;
1186     UInt32 len = sizeof(UInt32);
1188     assert(handle != NULL);
1189     assert(name   != NULL);
1190     assert(value  != NULL);
1191     assert(NameServer_module->refCount != 0);
1193     status = NameServer_get(handle, name, value, &len, procId);
1195     return (status);
1198 /* Function to Retrieve the value portion of a name/value pair from
1199  * local table.
1200  */
1201 Int NameServer_getLocal(NameServer_Handle handle,
1202                     String            name,
1203                     Ptr               value,
1204                     UInt32 *          len)
1206     Int status = NameServer_E_NOTFOUND;
1207     NameServer_TableEntry * node = NULL;
1208     NameServer_TableEntry * temp = NULL;
1209     Bool done   = FALSE;
1210     UInt32 length;
1211     UInt32 hash;
1213     assert(handle != NULL);
1214     assert(name   != NULL);
1215     assert(value  != NULL);
1216     assert(len    != NULL);
1217     assert(NameServer_module->refCount != 0);
1219     length = *len;
1221     /* Calculate the hash */
1222     hash = stringHash(name);
1224     pthread_mutex_lock(&handle->gate);
1226     /* Traverse the list to find duplicate check */
1227     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1228         if (node->hash == hash) {
1229             if (node->collide == TRUE) {
1230                 temp = node;
1231                 while (temp) {
1232                     if (strcmp(temp->name, name) == 0u){
1233                         if (length <= node->len) {
1234                             memcpy(value, node->value, length);
1235                             *len = length;
1236                         }
1237                         else {
1238                             memcpy(value, node->value, node->len);
1239                             *len = node->len;
1240                         }
1241                         done = TRUE;
1242                         break;
1243                     }
1244                     temp = temp->next;
1245                 }
1246                 break;
1247             }
1248             else {
1249                 if (length <= node->len) {
1250                     memcpy(value, node->value, length);
1251                     *len = length;
1252                 }
1253                 else {
1254                     memcpy(value, node->value, node->len);
1255                     *len = node->len;
1256                 }
1257                 done = TRUE;
1258                 break;
1259             }
1260         }
1261     }
1263     pthread_mutex_unlock(&handle->gate);
1265     if (done == FALSE) {
1266         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1267     }
1268     else {
1269         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1270              node->name, (UInt32)node->value)
1271         status = NameServer_S_SUCCESS;
1272     }
1274     return (status);
1277 /*
1278  *  Gets a 32-bit value by name from the local table
1279  *
1280  *  If the name is found, the 32-bit value is copied into the value
1281  *  argument and a success status is returned.
1282  *
1283  *  If the name is not found, zero is returned in len and the contents
1284  *  of value are not modified. Not finding a name is not considered
1285  *  an error.
1286  *
1287  *  This function only searches the local name/value table.
1288  *
1289  */
1290 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1292     Int                 status;
1293     UInt32              len    = sizeof(UInt32);
1295     assert(handle != NULL);
1296     assert(name   != NULL);
1297     assert(value  != NULL);
1298     assert(NameServer_module->refCount != 0);
1300     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1301     status = NameServer_getLocal(handle, name, value, &len);
1303     return (status);
1307 #if defined (__cplusplus)
1309 #endif /* defined (__cplusplus) */