]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/NameServer_daemon.c
Merge branch '3.30' into ipc-next
[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 <ti/ipc/namesrv/_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     NameServerRemote_Msg 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(NameServerRemote_Msg * 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(NameServerRemote_Msg), 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(NameServerRemote_Msg));
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     NameServerRemote_Msg 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(NameServerRemote_Msg), 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             LOG2("NameServer_setup: created send socket: %d, procId %d\n",
461                     sock, procId)
462             err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
463             if (err < 0) {
464                 status = NameServer_E_FAIL;
465                 LOG3("NameServer_setup: connect failed: procId=%d, "
466                         "errno=%d (%s)\n", procId, errno, strerror(errno))
468                 LOG1("    closing send socket: %d\n", sock)
469                 close(sock);
470             }
471             else {
472                 NameServer_module->sendSock[clId] = sock;
473             }
474         }
476         /* Create the socket for recving messages from each remote proc: */
477         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
478         if (sock < 0) {
479             status = NameServer_E_FAIL;
480             LOG2("NameServer_setup: socket failed: %d, %s\n",
481                  errno, strerror(errno))
482         }
483         else  {
484             LOG2("NameServer_setup: created recv socket: %d, procId %d\n",
485                     sock, procId)
486             err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
487             if (err < 0) {
488                 status = NameServer_E_FAIL;
489                 LOG2("NameServer_setup: bind failed: %d, %s\n",
490                     errno, strerror(errno))
492                 LOG1("    closing recv socket: %d\n", sock)
493                 close(sock);
494             }
495             else {
496                 NameServer_module->recvSock[clId] = sock;
497             }
498         }
499     }
501     /* Construct the list object */
502     CIRCLEQ_INIT(&NameServer_module->objList);
504     /* Create the listener thread: */
505     LOG0("NameServer_setup: creating listener thread\n")
506     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
507     if (ret) {
508         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
509         LOG0("NameServer_setup: eventfd failed");
511         status = NameServer_E_FAIL;
512     }
513     else {
514         /* look for at least one good send/recv pair to indicate success */
515         for (clId = 0; clId < numProcs; clId++) {
516             if (NameServer_module->sendSock[clId] != INVALIDSOCKET &&
517                 NameServer_module->recvSock[clId] != INVALIDSOCKET) {
518                 status = NameServer_S_SUCCESS;
519                 break;
520             }
521         }
522     }
524 exit:
525     LOG1("NameServer_setup: exiting, refCount=%d\n",
526             NameServer_module->refCount)
528     pthread_mutex_unlock(&NameServer_module->modGate);
530     return (status);
533 /*! Function to destroy the nameserver module. */
534 Int NameServer_destroy(void)
536     Int      status = NameServer_S_SUCCESS;
537     UInt16   numProcs;
538     UInt16   baseId;
539     UInt16   procId;
540     int      clId;
541     int      sock;
542     uint64_t buf = 1;
544     pthread_mutex_lock(&NameServer_module->modGate);
546     LOG1("NameServer_destroy: entered, refCount=%d\n",
547             NameServer_module->refCount)
549     NameServer_module->refCount--;
551     if (NameServer_module->refCount > 0) {
552         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n",
553                 NameServer_module->refCount)
554         status = NameServer_S_SUCCESS;
555         goto exit;
556     }
558     numProcs = MultiProc_getNumProcsInCluster();
559     baseId = MultiProc_getBaseIdOfCluster();
561     LOG2("NameServer_destroy: numProcs=%d, baseId=%d\n", numProcs, baseId);
563     for (clId = 0, procId = baseId; clId < numProcs; clId++, procId++) {
565         /* Only support NameServer to remote procs: */
566         if (MultiProc_self() == procId) {
567             continue;
568         }
570         /* Close the socket: */
571         sock = NameServer_module->sendSock[clId];
572         if (sock != INVALIDSOCKET) {
573             LOG1("NameServer_destroy: closing socket: %d\n", sock)
574             close(sock);
575             NameServer_module->sendSock[clId] = INVALIDSOCKET;
576         }
577         /* Close the socket: */
578         sock = NameServer_module->recvSock[clId];
579         if (sock != INVALIDSOCKET) {
580             LOG1("NameServer_destroy: closing socket: %d\n", sock)
581             close(sock);
582             NameServer_module->recvSock[clId] = INVALIDSOCKET;
583         }
584     }
586     CIRCLEQ_destruct(&NameServer_module->objList);
588     /* Unblock the NameServer listener thread: */
589     LOG0("NameServer_destroy: unblocking listener...\n")
590     write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
592     /* Join: */
593     LOG0("NameServer_destroy: joining listener thread...\n")
594     pthread_join(NameServer_module->listener, NULL);
596     close(NameServer_module->unblockFd);
597     close(NameServer_module->waitFd);
599 exit:
600     LOG1("NameServer_destroy: exiting, refCount=%d\n",
601             NameServer_module->refCount)
603     pthread_mutex_unlock(&NameServer_module->modGate);
605     return (status);
608 /* Function to retrieve a NameServer handle from name. */
609 NameServer_Handle NameServer_getHandle(String name)
611     NameServer_Handle handle = NULL;
612     Bool              found = FALSE;
613     struct NameServer_Object * elem;
615     assert(name != NULL);
616     assert(NameServer_module->refCount != 0);
618     pthread_mutex_lock(&NameServer_module->modGate);
620     /* Lookup handle from name: */
621     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
622         handle = (NameServer_Handle) elem;
623         if (strcmp(handle->name, name) == 0) {
624             found = TRUE;
625             break;
626         }
627     }
629     if (found == FALSE) {
630         handle = NULL;
631     }
633     pthread_mutex_unlock(&NameServer_module->modGate);
635     return (handle);
639 /* Function to create a name server. */
640 NameServer_Handle NameServer_create(String name,
641                                     const NameServer_Params * params)
643     NameServer_Handle handle = NULL;
644     pthread_mutexattr_t mutex_attr;
646     assert(params != NULL);
647     assert(name != NULL);
648     assert(NameServer_module->refCount != 0);
650     LOG1("NameServer_create(): '%s'\n", name)
652     pthread_mutex_lock(&NameServer_module->modGate);
654     /* check if the name is already created or not */
655     handle = NameServer_getHandle(name);
656     if (handle != NULL) {
657         if (memcmp((Ptr)&handle->params, (Ptr)params,
658             sizeof(NameServer_Params)) == 0) {
659             handle->refCount++;
660         }
661         else {
662             LOG0("NameServer_create: NameServer params mismatch\n")
663             handle = NULL;
664         }
665         goto leave;
666     }
667     else {
668         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
669     }
671     if (!handle) {
672         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
673         goto leave;
674     }
676     handle->refCount = 1;
677     handle->name = (String)malloc(strlen(name) + 1u);
678     if (!handle->name) {
679         LOG0("NameServer_create: instance name alloc failed\n")
680         goto cleanup;
681     }
682     strncpy(handle->name, name, strlen (name) + 1u);
683     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
685     if (params->maxValueLen < sizeof(UInt32)) {
686         handle->params.maxValueLen = sizeof(UInt32);
687     }
688     else {
689         handle->params.maxValueLen = params->maxValueLen;
690     }
692     CIRCLEQ_INIT(&handle->nameList);
693     handle->count = 0u;
695     /* Put in the local list */
696     CIRCLEQ_elemClear(&handle->elem);
697     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
699     /*
700      * NameServer_removeEntry() enters gate and is called by
701      * NameServer_remove() while holding the gate.
702      */
703     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
704     pthread_mutex_init(&handle->gate, &mutex_attr);
706     goto leave;
708 cleanup:
709     free(handle);
710     handle = NULL;
712 leave:
713     pthread_mutex_unlock(&NameServer_module->modGate);
715     return (handle);
719 /* Function to delete a name server. */
720 Int NameServer_delete(NameServer_Handle * handle)
722     Int status = NameServer_S_SUCCESS;
724     assert(handle != NULL);
725     assert(*handle != NULL);
726     assert((*handle)->count == 0);
727     assert(NameServer_module->refCount != 0);
729     pthread_mutex_lock(&NameServer_module->modGate);
731     (*handle)->refCount--;
732     if ((*handle)->refCount != 0) {
733         goto leave;
734     }
736     if ((*handle)->count == 0) {
737         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
739         if ((*handle)->name != NULL) {
740             free((*handle)->name);
741             (*handle)->name = NULL;
742         }
744         CIRCLEQ_destruct(&(*handle)->nameList);
746         free((*handle));
747         (*handle) = NULL;
748     }
750 leave:
751     pthread_mutex_unlock(&NameServer_module->modGate);
753     return (status);
756 /* Adds a variable length value into the local NameServer table */
757 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
759     Int                 status = NameServer_S_SUCCESS;
760     NameServer_TableEntry * node = NULL;
761     NameServer_TableEntry * new_node = NULL;
762     Bool                found = FALSE;
763     UInt32              hash;
765     assert(handle != NULL);
766     assert(name     != NULL);
767     assert(buf      != NULL);
768     assert(len      != 0);
769     assert(NameServer_module->refCount != 0);
771     /* Calculate the hash */
772     hash = stringHash(name);
774     pthread_mutex_lock(&handle->gate);
776     if (strlen(name) > handle->params.maxNameLen - 1) {
777         status = NameServer_E_INVALIDARG;
778         LOG0("NameServer_add: name length exceeded maximum!\n")
779         new_node = NULL;
780         goto exit;
781     }
783     if (len > handle->params.maxValueLen) {
784         status = NameServer_E_INVALIDARG;
785         LOG0("NameServer_add: value length exceeded maximum!\n")
786         new_node = NULL;
787         goto exit;
788     }
790     /* Traverse the list to find duplicate check */
791     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
792         /* Hash matches */
793         if (node->hash == hash) {
794             /* If the name matches, incase hash is duplicate */
795             if (strcmp(node->name, name) == 0) {
796                 if (handle->params.checkExisting == TRUE) {
797                     status = NameServer_E_INVALIDARG;
798                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
799                     break;
800                 }
801             }
802             else {
803                 found = TRUE;
804                 break;
805             } /* name does not match */
806         } /* hash does not match */
807     } /* CIRCLEQ_traverse */
809     if (status != NameServer_S_SUCCESS) {
810         new_node = NULL;
811         goto exit;
812     }
814     /* Now add the new entry. */
815     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
816     if (new_node == NULL) {
817         status = NameServer_E_MEMORY;
818         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
820         goto exit;
821     }
823     new_node->hash    = hash;
824     new_node->collide = found; /* Indicate if there is a collision*/
825     new_node->len     = len;
826     new_node->next    = NULL;
827     new_node->name = (String)malloc(strlen(name) + 1u);
828     new_node->value  = (Ptr)malloc(len);
829     strncpy(new_node->name, name, strlen(name) + 1u);
830     memcpy((Ptr)new_node->value, (Ptr)buf, len);
832     if (found == TRUE) {
833         /* If hash is found, need to stitch the list to link the
834          * new node to the existing node with the same hash.
835          */
836         new_node->next = node->next;
837         node->next = new_node;
838     }
839     else {
840         /* put the new node into the list */
841         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
842     }
844     handle->count++;
846     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
847          name, *(UInt32 *)buf)
849 exit:
850     pthread_mutex_unlock(&handle->gate);
852     return (new_node);
856 /* Function to add a UInt32 value into a name server. */
857 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
859     Ptr entry = NULL;
861     assert(handle != NULL);
862     assert(name   != NULL);
863     assert(NameServer_module->refCount != 0);
865     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
867     return (entry);
870 /* Function to remove a name/value pair from a name server. */
871 Int NameServer_remove(NameServer_Handle handle, String name)
873     Int                 status = NameServer_S_SUCCESS;
874     NameServer_TableEntry *prev = NULL;
875     NameServer_TableEntry *temp = NULL;
876     NameServer_TableEntry *node = NULL;
877     Bool                done   = FALSE;
878     UInt32              hash;
880     assert(handle != NULL);
881     assert(name   != NULL);
882     assert(NameServer_module->refCount != 0);
884     /* Calculate the hash */
885     hash = stringHash(name);
887     pthread_mutex_lock(&handle->gate);
889     /* Traverse the list to find duplicate check */
890     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
891         /* Hash matchs */
892         if (node->hash == hash) {
893             if (node->collide == TRUE) {
894                 if (strcmp(node->name, name) == 0){
895                     free(node->value);
896                     free(node->name);
897                     memcpy((Ptr)node, (Ptr) node->next,
898                            sizeof(NameServer_TableEntry));
899                     node->next = node->next->next;
900                     free(node->next);
901                     handle->count--;
902                     done = TRUE;
903                     break;
904                 }
905                 else {
906                     prev = node;
907                     temp = node->next;
908                     while (temp) {
909                         if (strcmp(temp->name, name) == 0){
910                             free(temp->value);
911                             free(temp->name);
912                             prev->next = temp->next;
913                             free(temp);
914                             handle->count--;
915                             done = TRUE;
916                             break;
917                         }
918                         temp = temp->next;
919                     }
920                     break;
921                 }
922             }
923             else {
924                 NameServer_removeEntry(handle, (Ptr)node);
926                 done = TRUE;
927                 break;
928             }
929         }
930     }
932     if (done == FALSE) {
933         status = NameServer_E_INVALIDARG;
934         LOG1("NameServer_remove %d Entry not found!\n", status)
935     }
937     pthread_mutex_unlock(&handle->gate);
939     return (status);
942 /* Function to remove a name/value pair from a name server. */
943 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
945     Int  status = NameServer_S_SUCCESS;
946     NameServer_TableEntry * node;
948     assert(handle != NULL);
949     assert(entry  != NULL);
950     assert(NameServer_module->refCount != 0);
952     pthread_mutex_lock(&handle->gate);
954     node = (NameServer_TableEntry *)entry;
956     free(node->value);
957     free(node->name);
958     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
959     free(node);
960     handle->count--;
962     pthread_mutex_unlock(&handle->gate);
964     return (status);
968 /* Initialize this config-params structure with supplier-specified
969  * defaults before instance creation.
970  */
971 Void NameServer_Params_init(NameServer_Params * params)
973     assert(params != NULL);
975     memcpy(params, &(NameServer_module->defInstParams),
976            sizeof (NameServer_Params));
980 Int NameServer_getRemote(NameServer_Handle handle,
981                      String            name,
982                      Ptr               value,
983                      UInt32 *          len,
984                      UInt16            procId)
986     Int status = NameServer_S_SUCCESS;
987     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
988     NameServerRemote_Msg nsMsg;
989     NameServerRemote_Msg *replyMsg;
990     fd_set rfds;
991     int ret = 0, sock, maxfd, waitFd;
992     struct timeval tv;
993     uint64_t buf = 1;
994     int err;
995     int i;
996     static int seqNum = 0;
997     Bool done = FALSE;
998     UInt16 clusterId;
1000     if (strlen(name) >= MAXNAMEINCHAR) {
1001         LOG0("Name is too long in remote query\n");
1002         return NameServer_E_NAMETOOLONG;
1003     }
1005     if (strlen(obj->name) >= MAXNAMEINCHAR) {
1006         LOG0("Instance name is too long for remote query\n");
1007         return NameServer_E_NAMETOOLONG;
1008     }
1010     /* Set Timeout to wait: */
1011     tv.tv_sec = 0;
1012     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
1014     /* Create request message and send to remote: */
1015     clusterId = procId - MultiProc_getBaseIdOfCluster();
1016     sock = NameServer_module->sendSock[clusterId];
1017     if (sock == INVALIDSOCKET) {
1018         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
1019              procId);
1020         status = NameServer_E_RESOURCE;
1021         goto exit;
1022     }
1024     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
1026     /* Create request message and send to remote processor: */
1027     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
1028     nsMsg.request = NAMESERVER_REQUEST;
1029     nsMsg.requestStatus = 0;
1030     nsMsg.valueLen = *len;
1031     nsMsg.seqNum = seqNum++;
1033     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
1034     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1036     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
1037            procId, (String)nsMsg.instanceName)
1038     LOG1("%s...\n", (String)nsMsg.name)
1040     err = send(sock, &nsMsg, sizeof(NameServerRemote_Msg), 0);
1041     if (err < 0) {
1042         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1043              errno, strerror(errno))
1044         status = NameServer_E_FAIL;
1045         goto exit;
1046     }
1048     while (!done) {
1049         /* Block on waitFd for signal from listener thread: */
1050         waitFd = NameServer_module->waitFd;
1051         FD_ZERO(&rfds);
1052         FD_SET(waitFd, &rfds);
1053         maxfd = waitFd + 1;
1054         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1055         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1056         if (ret == -1) {
1057             LOG0("NameServer_getRemote: select failed.")
1058             status = NameServer_E_FAIL;
1059             goto exit;
1060         }
1061         else if (!ret) {
1062             LOG0("NameServer_getRemote: select timed out.\n")
1063             status = NameServer_E_TIMEOUT;
1064             goto exit;
1065         }
1067         if (FD_ISSET(waitFd, &rfds)) {
1068             /* Read, just to balance the write: */
1069             read(waitFd, &buf, sizeof(uint64_t));
1071             /* Process response: */
1072             replyMsg = &NameServer_module->nsMsg;
1074             if (replyMsg->seqNum != seqNum - 1) {
1075                 /* Ignore responses without current sequence # */
1076                 continue;
1077             }
1079             if (replyMsg->requestStatus) {
1080                 /* name is found */
1082                 /* set length to amount of data that was copied */
1083                 *len = replyMsg->valueLen;
1085                 /* set the contents of value */
1086                 if (*len <= sizeof (Bits32)) {
1087                     *(UInt32 *)value = (UInt32)replyMsg->value;
1088                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1089                         procId, (String)replyMsg->instanceName)
1090                     LOG2("%s, value: 0x%x...\n",
1091                         (String)replyMsg->name, *(UInt32 *)value)
1092                 }
1093                 else {
1094                     memcpy(value, replyMsg->valueBuf, *len);
1095                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1096                         procId, (String)replyMsg->instanceName)
1097                     for (i = 0; i < *len/4; i++) {
1098                         LOG2("%s, value buffer content: 0x%x...\n",
1099                             (String)replyMsg->name, ((uint32_t *)value)[i])
1100                     }
1101                 }
1103                 goto exit;
1104             }
1105             else {
1106                 /* name is not found */
1107                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1108                      (String)replyMsg->instanceName, (String)replyMsg->name)
1110                 /* set status to not found */
1111                 status = NameServer_E_NOTFOUND;
1112             }
1113         }
1114         done= TRUE;
1115     }
1117 exit:
1118     return (status);
1121 /* Function to retrieve the value portion of a name/value pair from
1122  * local table.
1123  */
1124 Int NameServer_get(NameServer_Handle handle,
1125                String            name,
1126                Ptr               value,
1127                UInt32 *          len,
1128                UInt16            procId[])
1130     Int status = NameServer_S_SUCCESS;
1131     UInt16 numProcs;
1132     UInt32 i;
1133     UInt16 clusterId;
1134     UInt16 baseId;
1136     numProcs = MultiProc_getNumProcsInCluster();
1137     baseId = MultiProc_getBaseIdOfCluster();
1139     /*
1140      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1141      * since this goes in a daemon, it will not be necessary.
1142      */
1144     if (procId == NULL) {
1145         status = NameServer_getLocal(handle, name, value, len);
1146         if (status == NameServer_E_NOTFOUND) {
1147             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1149                 /* getLocal call already covers "self", keep going */
1150                 if ((baseId + clusterId) == MultiProc_self()) {
1151                     continue;
1152                 }
1154                 status = NameServer_getRemote(handle, name, value, len,
1155                         baseId + clusterId);
1157                 if ((status >= 0) ||
1158                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1159                                      (status != NameServer_E_RESOURCE))) {
1160                     break;
1161                 }
1162             }
1163         }
1164     }
1165     else {
1166         /*
1167          *  Search the query list. It might contain the local proc
1168          *  somewhere in the list.
1169          */
1170         i = 0;
1171         while (procId[i] != MultiProc_INVALIDID) {
1172             if (procId[i] == MultiProc_self()) {
1173                 status = NameServer_getLocal(handle, name, value, len);
1174             }
1175             else {
1176                 status = NameServer_getRemote(handle, name, value, len,
1177                         procId[i]);
1178             }
1180             if ((status >= 0) ||
1181                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1182                                  (status != NameServer_E_RESOURCE))) {
1183                 break;
1184             }
1186             i++;
1187         }
1188     }
1190     if (status == NameServer_E_RESOURCE) {
1191         status = NameServer_E_NOTFOUND;
1192     }
1194     return (status);
1197 /* Gets a 32-bit value by name */
1198 Int NameServer_getUInt32(NameServer_Handle handle,
1199                      String            name,
1200                      Ptr               value,
1201                      UInt16            procId[])
1203     Int  status;
1204     UInt32 len = sizeof(UInt32);
1206     assert(handle != NULL);
1207     assert(name   != NULL);
1208     assert(value  != NULL);
1209     assert(NameServer_module->refCount != 0);
1211     status = NameServer_get(handle, name, value, &len, procId);
1213     return (status);
1216 /* Function to Retrieve the value portion of a name/value pair from
1217  * local table.
1218  */
1219 Int NameServer_getLocal(NameServer_Handle handle,
1220                     String            name,
1221                     Ptr               value,
1222                     UInt32 *          len)
1224     Int status = NameServer_E_NOTFOUND;
1225     NameServer_TableEntry * node = NULL;
1226     NameServer_TableEntry * temp = NULL;
1227     Bool done   = FALSE;
1228     UInt32 length;
1229     UInt32 hash;
1231     assert(handle != NULL);
1232     assert(name   != NULL);
1233     assert(value  != NULL);
1234     assert(len    != NULL);
1235     assert(NameServer_module->refCount != 0);
1237     length = *len;
1239     /* Calculate the hash */
1240     hash = stringHash(name);
1242     pthread_mutex_lock(&handle->gate);
1244     /* Traverse the list to find duplicate check */
1245     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1246         if (node->hash == hash) {
1247             if (node->collide == TRUE) {
1248                 temp = node;
1249                 while (temp) {
1250                     if (strcmp(temp->name, name) == 0u){
1251                         if (length <= node->len) {
1252                             memcpy(value, node->value, length);
1253                             *len = length;
1254                         }
1255                         else {
1256                             memcpy(value, node->value, node->len);
1257                             *len = node->len;
1258                         }
1259                         done = TRUE;
1260                         break;
1261                     }
1262                     temp = temp->next;
1263                 }
1264                 break;
1265             }
1266             else {
1267                 if (length <= node->len) {
1268                     memcpy(value, node->value, length);
1269                     *len = length;
1270                 }
1271                 else {
1272                     memcpy(value, node->value, node->len);
1273                     *len = node->len;
1274                 }
1275                 done = TRUE;
1276                 break;
1277             }
1278         }
1279     }
1281     pthread_mutex_unlock(&handle->gate);
1283     if (done == FALSE) {
1284         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1285     }
1286     else {
1287         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1288              node->name, (UInt32)node->value)
1289         status = NameServer_S_SUCCESS;
1290     }
1292     return (status);
1295 /*
1296  *  Gets a 32-bit value by name from the local table
1297  *
1298  *  If the name is found, the 32-bit value is copied into the value
1299  *  argument and a success status is returned.
1300  *
1301  *  If the name is not found, zero is returned in len and the contents
1302  *  of value are not modified. Not finding a name is not considered
1303  *  an error.
1304  *
1305  *  This function only searches the local name/value table.
1306  *
1307  */
1308 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1310     Int                 status;
1311     UInt32              len    = sizeof(UInt32);
1313     assert(handle != NULL);
1314     assert(name   != NULL);
1315     assert(value  != NULL);
1316     assert(NameServer_module->refCount != 0);
1318     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1319     status = NameServer_getLocal(handle, name, value, &len);
1321     return (status);
1325 #if defined (__cplusplus)
1327 #endif /* defined (__cplusplus) */