]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/NameServer_daemon.c
SDOCM00114730 Reserved message queues on Linux/Keystone II
[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             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     if (len > handle->params.maxValueLen) {
775         status = NameServer_E_INVALIDARG;
776         LOG0("NameServer_add: value length exceeded maximum!\n")
777         new_node = NULL;
778         goto exit;
779     }
781     pthread_mutex_lock(&handle->gate);
783     /* Traverse the list to find duplicate check */
784     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
785         /* Hash matches */
786         if (node->hash == hash) {
787             /* If the name matches, incase hash is duplicate */
788             if (strcmp(node->name, name) == 0) {
789                 if (handle->params.checkExisting == TRUE) {
790                     status = NameServer_E_INVALIDARG;
791                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
792                     break;
793                 }
794             }
795             else {
796                 found = TRUE;
797                 break;
798             } /* name does not match */
799         } /* hash does not match */
800     } /* CIRCLEQ_traverse */
802     if (status != NameServer_S_SUCCESS) {
803         new_node = NULL;
804         goto exit;
805     }
807     /* Now add the new entry. */
808     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
809     if (new_node == NULL) {
810         status = NameServer_E_MEMORY;
811         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
813         goto exit;
814     }
816     new_node->hash    = hash;
817     new_node->collide = found; /* Indicate if there is a collision*/
818     new_node->len     = len;
819     new_node->next    = NULL;
820     new_node->name = (String)malloc(strlen(name) + 1u);
821     new_node->value  = (Ptr)malloc(len);
822     strncpy(new_node->name, name, strlen(name) + 1u);
823     memcpy((Ptr)new_node->value, (Ptr)buf, len);
825     if (found == TRUE) {
826         /* If hash is found, need to stitch the list to link the
827          * new node to the existing node with the same hash.
828          */
829         new_node->next = node->next;
830         node->next = new_node;
831     }
832     else {
833         /* put the new node into the list */
834         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
835     }
837     handle->count++;
839     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
840          name, *(UInt32 *)buf)
842 exit:
843     pthread_mutex_unlock(&handle->gate);
845     return (new_node);
849 /* Function to add a UInt32 value into a name server. */
850 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
852     Ptr entry = NULL;
854     assert(handle != NULL);
855     assert(name   != NULL);
856     assert(NameServer_module->refCount != 0);
858     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
860     return (entry);
863 /* Function to remove a name/value pair from a name server. */
864 Int NameServer_remove(NameServer_Handle handle, String name)
866     Int                 status = NameServer_S_SUCCESS;
867     NameServer_TableEntry *prev = NULL;
868     NameServer_TableEntry *temp = NULL;
869     NameServer_TableEntry *node = NULL;
870     Bool                done   = FALSE;
871     UInt32              hash;
873     assert(handle != NULL);
874     assert(name   != NULL);
875     assert(NameServer_module->refCount != 0);
877     /* Calculate the hash */
878     hash = stringHash(name);
880     pthread_mutex_lock(&handle->gate);
882     /* Traverse the list to find duplicate check */
883     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
884         /* Hash matchs */
885         if (node->hash == hash) {
886             if (node->collide == TRUE) {
887                 if (strcmp(node->name, name) == 0){
888                     free(node->value);
889                     free(node->name);
890                     memcpy((Ptr)node, (Ptr) node->next,
891                            sizeof(NameServer_TableEntry));
892                     node->next = node->next->next;
893                     free(node->next);
894                     handle->count--;
895                     done = TRUE;
896                     break;
897                 }
898                 else {
899                     prev = node;
900                     temp = node->next;
901                     while (temp) {
902                         if (strcmp(temp->name, name) == 0){
903                             free(temp->value);
904                             free(temp->name);
905                             prev->next = temp->next;
906                             free(temp);
907                             handle->count--;
908                             done = TRUE;
909                             break;
910                         }
911                         temp = temp->next;
912                     }
913                     break;
914                 }
915             }
916             else {
917                 NameServer_removeEntry(handle, (Ptr)node);
919                 done = TRUE;
920                 break;
921             }
922         }
923     }
925     if (done == FALSE) {
926         status = NameServer_E_INVALIDARG;
927         LOG1("NameServer_remove %d Entry not found!\n", status)
928     }
930     pthread_mutex_unlock(&handle->gate);
932     return (status);
935 /* Function to remove a name/value pair from a name server. */
936 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
938     Int  status = NameServer_S_SUCCESS;
939     NameServer_TableEntry * node;
941     assert(handle != NULL);
942     assert(entry  != NULL);
943     assert(NameServer_module->refCount != 0);
945     pthread_mutex_lock(&handle->gate);
947     node = (NameServer_TableEntry *)entry;
949     free(node->value);
950     free(node->name);
951     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
952     free(node);
953     handle->count--;
955     pthread_mutex_unlock(&handle->gate);
957     return (status);
961 /* Initialize this config-params structure with supplier-specified
962  * defaults before instance creation.
963  */
964 Void NameServer_Params_init(NameServer_Params * params)
966     assert(params != NULL);
968     memcpy(params, &(NameServer_module->defInstParams),
969            sizeof (NameServer_Params));
973 Int NameServer_getRemote(NameServer_Handle handle,
974                      String            name,
975                      Ptr               value,
976                      UInt32 *          len,
977                      UInt16            procId)
979     Int status = NameServer_S_SUCCESS;
980     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
981     NameServerMsg nsMsg;
982     NameServerMsg *replyMsg;
983     fd_set rfds;
984     int ret = 0, sock, maxfd, waitFd;
985     struct timeval tv;
986     uint64_t buf = 1;
987     int err;
988     int i;
989     static int seqNum = 0;
990     Bool done = FALSE;
991     UInt16 clusterId;
993     /* Set Timeout to wait: */
994     tv.tv_sec = 0;
995     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
997     /* Create request message and send to remote: */
998     clusterId = procId - MultiProc_getBaseIdOfCluster();
999     sock = NameServer_module->sendSock[clusterId];
1000     if (sock == INVALIDSOCKET) {
1001         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
1002              procId);
1003         status = NameServer_E_RESOURCE;
1004         goto exit;
1005     }
1007     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
1009     /* Create request message and send to remote processor: */
1010     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
1011     nsMsg.request = NAMESERVER_REQUEST;
1012     nsMsg.requestStatus = 0;
1013     nsMsg.valueLen = *len;
1014     nsMsg.seqNum = seqNum++;
1016     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
1017     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1019     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
1020            procId, (String)nsMsg.instanceName)
1021     LOG1("%s...\n", (String)nsMsg.name)
1023     err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
1024     if (err < 0) {
1025         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1026              errno, strerror(errno))
1027         status = NameServer_E_FAIL;
1028         goto exit;
1029     }
1031     while (!done) {
1032         /* Block on waitFd for signal from listener thread: */
1033         waitFd = NameServer_module->waitFd;
1034         FD_ZERO(&rfds);
1035         FD_SET(waitFd, &rfds);
1036         maxfd = waitFd + 1;
1037         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1038         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1039         if (ret == -1) {
1040             LOG0("NameServer_getRemote: select failed.")
1041             status = NameServer_E_FAIL;
1042             goto exit;
1043         }
1044         else if (!ret) {
1045             LOG0("NameServer_getRemote: select timed out.\n")
1046             status = NameServer_E_TIMEOUT;
1047             goto exit;
1048         }
1050         if (FD_ISSET(waitFd, &rfds)) {
1051             /* Read, just to balance the write: */
1052             read(waitFd, &buf, sizeof(uint64_t));
1054             /* Process response: */
1055             replyMsg = &NameServer_module->nsMsg;
1057             if (replyMsg->seqNum != seqNum - 1) {
1058                 /* Ignore responses without current sequence # */
1059                 continue;
1060             }
1062             if (replyMsg->requestStatus) {
1063                 /* name is found */
1065                 /* set length to amount of data that was copied */
1066                 *len = replyMsg->valueLen;
1068                 /* set the contents of value */
1069                 if (*len <= sizeof (Bits32)) {
1070                     *(UInt32 *)value = (UInt32)replyMsg->value;
1071                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1072                         procId, (String)replyMsg->instanceName)
1073                     LOG2("%s, value: 0x%x...\n",
1074                         (String)replyMsg->name, *(UInt32 *)value)
1075                 }
1076                 else {
1077                     memcpy(value, replyMsg->valueBuf, *len);
1078                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1079                         procId, (String)replyMsg->instanceName)
1080                     for (i = 0; i < *len/4; i++) {
1081                         LOG2("%s, value buffer content: 0x%x...\n",
1082                             (String)replyMsg->name, ((uint32_t *)value)[i])
1083                     }
1084                 }
1086                 goto exit;
1087             }
1088             else {
1089                 /* name is not found */
1090                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1091                      (String)replyMsg->instanceName, (String)replyMsg->name)
1093                 /* set status to not found */
1094                 status = NameServer_E_NOTFOUND;
1095             }
1096         }
1097         done= TRUE;
1098     }
1100 exit:
1101     return (status);
1104 /* Function to retrieve the value portion of a name/value pair from
1105  * local table.
1106  */
1107 Int NameServer_get(NameServer_Handle handle,
1108                String            name,
1109                Ptr               value,
1110                UInt32 *          len,
1111                UInt16            procId[])
1113     Int status = NameServer_S_SUCCESS;
1114     UInt16 numProcs;
1115     UInt32 i;
1116     UInt16 clusterId;
1117     UInt16 baseId;
1119     numProcs = MultiProc_getNumProcsInCluster();
1120     baseId = MultiProc_getBaseIdOfCluster();
1122     /*
1123      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1124      * since this goes in a daemon, it will not be necessary.
1125      */
1127     if (procId == NULL) {
1128         status = NameServer_getLocal(handle, name, value, len);
1129         if (status == NameServer_E_NOTFOUND) {
1130             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1132                 /* getLocal call already covers "self", keep going */
1133                 if ((baseId + clusterId) == MultiProc_self()) {
1134                     continue;
1135                 }
1137                 status = NameServer_getRemote(handle, name, value, len,
1138                         baseId + clusterId);
1140                 if ((status >= 0) ||
1141                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1142                                      (status != NameServer_E_RESOURCE))) {
1143                     break;
1144                 }
1145             }
1146         }
1147     }
1148     else {
1149         /*
1150          *  Search the query list. It might contain the local proc
1151          *  somewhere in the list.
1152          */
1153         i = 0;
1154         while (procId[i] != MultiProc_INVALIDID) {
1155             if (procId[i] == MultiProc_self()) {
1156                 status = NameServer_getLocal(handle, name, value, len);
1157             }
1158             else {
1159                 status = NameServer_getRemote(handle, name, value, len,
1160                         procId[i]);
1161             }
1163             if ((status >= 0) ||
1164                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1165                                  (status != NameServer_E_RESOURCE))) {
1166                 break;
1167             }
1169             i++;
1170         }
1171     }
1173     if (status == NameServer_E_RESOURCE) {
1174         status = NameServer_E_NOTFOUND;
1175     }
1177     return (status);
1180 /* Gets a 32-bit value by name */
1181 Int NameServer_getUInt32(NameServer_Handle handle,
1182                      String            name,
1183                      Ptr               value,
1184                      UInt16            procId[])
1186     Int  status;
1187     UInt32 len = sizeof(UInt32);
1189     assert(handle != NULL);
1190     assert(name   != NULL);
1191     assert(value  != NULL);
1192     assert(NameServer_module->refCount != 0);
1194     status = NameServer_get(handle, name, value, &len, procId);
1196     return (status);
1199 /* Function to Retrieve the value portion of a name/value pair from
1200  * local table.
1201  */
1202 Int NameServer_getLocal(NameServer_Handle handle,
1203                     String            name,
1204                     Ptr               value,
1205                     UInt32 *          len)
1207     Int status = NameServer_E_NOTFOUND;
1208     NameServer_TableEntry * node = NULL;
1209     NameServer_TableEntry * temp = NULL;
1210     Bool done   = FALSE;
1211     UInt32 length;
1212     UInt32 hash;
1214     assert(handle != NULL);
1215     assert(name   != NULL);
1216     assert(value  != NULL);
1217     assert(len    != NULL);
1218     assert(NameServer_module->refCount != 0);
1220     length = *len;
1222     /* Calculate the hash */
1223     hash = stringHash(name);
1225     pthread_mutex_lock(&handle->gate);
1227     /* Traverse the list to find duplicate check */
1228     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1229         if (node->hash == hash) {
1230             if (node->collide == TRUE) {
1231                 temp = node;
1232                 while (temp) {
1233                     if (strcmp(temp->name, name) == 0u){
1234                         if (length <= node->len) {
1235                             memcpy(value, node->value, length);
1236                             *len = length;
1237                         }
1238                         else {
1239                             memcpy(value, node->value, node->len);
1240                             *len = node->len;
1241                         }
1242                         done = TRUE;
1243                         break;
1244                     }
1245                     temp = temp->next;
1246                 }
1247                 break;
1248             }
1249             else {
1250                 if (length <= node->len) {
1251                     memcpy(value, node->value, length);
1252                     *len = length;
1253                 }
1254                 else {
1255                     memcpy(value, node->value, node->len);
1256                     *len = node->len;
1257                 }
1258                 done = TRUE;
1259                 break;
1260             }
1261         }
1262     }
1264     pthread_mutex_unlock(&handle->gate);
1266     if (done == FALSE) {
1267         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1268     }
1269     else {
1270         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1271              node->name, (UInt32)node->value)
1272         status = NameServer_S_SUCCESS;
1273     }
1275     return (status);
1278 /*
1279  *  Gets a 32-bit value by name from the local table
1280  *
1281  *  If the name is found, the 32-bit value is copied into the value
1282  *  argument and a success status is returned.
1283  *
1284  *  If the name is not found, zero is returned in len and the contents
1285  *  of value are not modified. Not finding a name is not considered
1286  *  an error.
1287  *
1288  *  This function only searches the local name/value table.
1289  *
1290  */
1291 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1293     Int                 status;
1294     UInt32              len    = sizeof(UInt32);
1296     assert(handle != NULL);
1297     assert(name   != NULL);
1298     assert(value  != NULL);
1299     assert(NameServer_module->refCount != 0);
1301     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1302     status = NameServer_getLocal(handle, name, value, &len);
1304     return (status);
1308 #if defined (__cplusplus)
1310 #endif /* defined (__cplusplus) */