Changes to support non-NameServer-capable slaves on Linux
[ipc/ipcdev.git] / linux / src / daemon / NameServer_daemon.c
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*!
33  *  @file       NameServer.c
34  *
35  *  @brief      NameServer Manager
36  */
38 /* Standard IPC headers */
39 #include <ti/ipc/Std.h>
41 /* POSIX thread support */
42 #include <pthread.h>
44 /* Socket Headers */
45 #include <sys/queue.h>
46 #include <sys/select.h>
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/eventfd.h>
51 #include <sys/socket.h>
52 #include <errno.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <assert.h>
59 /* Socket Protocol Family */
60 #include <net/rpmsg.h>
62 /* Module level headers */
63 #include <ti/ipc/NameServer.h>
64 #include <ti/ipc/MultiProc.h>
65 #include <_MultiProc.h>
67 /* Internal stuff: */
68 #include <_NameServer.h>
69 #include <_NameServerRemoteRpmsg.h>
71 /* Socket utils: */
72 #include <SocketFxns.h>
74 #include <_lad.h>
76 #define MESSAGEQ_RPMSG_PORT       61
77 #define NAME_SERVER_RPMSG_ADDR    0
79 #define INVALIDSOCKET     (-1)
81 #if defined (__cplusplus)
82 extern "C" {
83 #endif
86 /* =============================================================================
87  * Structures & Enums
88  * =============================================================================
89  */
91 /* Structure of entry in Name/Value table */
92 typedef struct NameServer_TableEntry_tag {
93     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
94     /* List element */
95     UInt32                    hash;
96     /* Hash value */
97     String                    name;
98     /* Name portion of the name/value pair. */
99     UInt                      len;
100     /* Length of the value field. */
101     Ptr                       value;
102     /* Value portion of the name/value entry. */
103     Bool                      collide;
104     /* Does the hash collide? */
105     struct NameServer_TableEntry_tag * next;
106     /* Pointer to the next entry, used incase of collision only */
107 } NameServer_TableEntry;
109 /* Structure defining object for the NameServer */
110 struct NameServer_Object {
111     CIRCLEQ_ENTRY(NameServer_Object) elem;
112     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
113     String             name;            /* name of the instance */
114     NameServer_Params  params;          /* the parameter structure */
115     UInt32             count;           /* count of entries */
116     pthread_mutex_t    gate;            /* crit sect gate */
117 } NameServer_Object;
119 /* structure for NameServer module state */
120 typedef struct NameServer_ModuleObject {
121     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
122     Int32               refCount;
123     int                 sendSock[MultiProc_MAXPROCESSORS];
124     /* Sockets for sending to remote proc nameserver ports: */
125     int                 recvSock[MultiProc_MAXPROCESSORS];
126     /* Sockets for recving from remote proc nameserver ports: */
127     pthread_t           listener;
128     /* Listener thread for NameServer replies and requests. */
129     int                 unblockFd;
130     /* Event to post to exit listener. */
131     int                 waitFd;
132     /* Event to post to NameServer_get. */
133     NameServerMsg       nsMsg;
134     /* NameServer Message cache. */
135     NameServer_Params   defInstParams;
136     /* Default instance paramters */
137     pthread_mutex_t     modGate;
138 } NameServer_ModuleObject;
140 #define CIRCLEQ_destruct(head) { \
141         (head)->cqh_first = NULL; \
142         (head)->cqh_last = NULL; \
145 #define CIRCLEQ_elemClear(elem) { \
146         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
149 #define CIRCLEQ_traverse(x, y, tag) \
150         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
152 /* =============================================================================
153  *  Globals
154  * =============================================================================
155  */
156 /*
157  * NameServer_state
158  *
159  * Make the module gate "recursive" since NameServer_getHandle() needs to
160  * use it and NameServer_create() needs to hold it around its call to
161  * NameServer_getHandle().  Also, use the static initializer instead of a
162  * run-time init call, so we can use this gate immediately in _setup().
163  */
164 static NameServer_ModuleObject NameServer_state = {
165     .defInstParams.maxRuntimeEntries = 0u,
166     .defInstParams.tableHeap         = NULL,
167     .defInstParams.checkExisting     = TRUE,
168     .defInstParams.maxValueLen       = 0u,
169     .defInstParams.maxNameLen        = 16u,
170 // only _NP (non-portable) type available in CG tools which we're using
171     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
172 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
173     .refCount                        = 0
174 };
176 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
178 static const UInt32 stringCrcTab[256u] = {
179   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
180   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
181   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
182   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
183   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
184   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
185   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
186   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
187   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
188   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
189   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
190   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
191   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
192   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
193   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
194   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
195   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
196   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
197   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
198   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
199   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
200   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
201   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
202   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
203   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
204   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
205   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
206   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
207   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
208   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
209   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
210   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
211   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
212   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
213   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
214   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
215   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
216   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
217   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
218   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
219   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
220   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
221   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
222 };
224 static UInt32 stringHash(String s)
226     UInt32 hash = strlen(s);
227     UInt32 i;
229     for (i = 0; i < strlen(s); i++) {
230         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
231     }
233     return (hash);
236 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
238     NameServer_Handle handle;
239     Int               status = NameServer_E_FAIL;
240     int               err;
241     uint64_t          buf = 1;
242     int               numBytes;
243     int               waitFd = NameServer_module->waitFd;
245     if (msg->request == NAMESERVER_REQUEST) {
246         LOG2("NameServer Request: instanceName: %s, name: %s\n",
247              (String)msg->instanceName, (String)msg->name)
249         /*
250          *  Message is a request. Lookup name in NameServer table.
251          *  Send a response message back to source processor.
252          */
253         handle = NameServer_getHandle((String)msg->instanceName);
255         if (handle != NULL) {
256             /* Search for the NameServer entry */
257             LOG0("Calling NameServer_getLocalUInt32...\n")
258             status = NameServer_getLocalUInt32(handle,
259                      (String)msg->name, &msg->value);
260         }
262         LOG2("NameServer Response: instanceName: %s, name: %s,",
263              (String)msg->instanceName, (String)msg->name)
264         /* set the request status */
265         if (status < 0) {
266             LOG1(" Value not found, status: %d\n", status)
267             msg->requestStatus = 0;
268         }
269         else {
270             msg->requestStatus = 1;
271             LOG1(" Value: 0x%x\n", msg->value)
272         }
274         /* specify message as a response */
275         msg->request = NAMESERVER_RESPONSE;
276         msg->reserved = NAMESERVER_MSG_TOKEN;
278         /* send response message to remote processor */
279         err = send(NameServer_module->sendSock[procId], msg,
280                    sizeof(NameServerMsg), 0);
281         if (err < 0) {
282             LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
283         }
284     }
285     else {
286         LOG2("NameServer Reply: instanceName: %s, name: %s",
287              (String)msg->instanceName, (String)msg->name)
288         LOG1(", value: 0x%x\n", msg->value)
290         /* Save the response message.  */
291         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
293         /* Post the eventfd upon which NameServer_get() is waiting */
294         numBytes = write(waitFd, &buf, sizeof(uint64_t));
295     }
299 static void *listener_cb(void *arg)
301     fd_set rfds;
302     int ret = 0, maxfd;
303     UInt16 procId;
304     struct  sockaddr_rpmsg  fromAddr;
305     unsigned int len;
306     NameServerMsg msg;
307     int     byteCount;
308     UInt16  numProcs = MultiProc_getNumProcessors();
309     int     sock;
311     LOG0("listener_cb: Entered Listener thread.\n")
313     do {
314         /* Wait for NameServer messages or unblockFd notification */
315         FD_ZERO(&rfds);
316         FD_SET(NameServer_module->unblockFd, &rfds);
317         maxfd = NameServer_module->unblockFd;
318         for (procId = 0; procId < numProcs; procId++) {
319             if (procId == MultiProc_self() ||
320                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
321                 continue;
322             }
323             sock = NameServer_module->recvSock[procId];
324             FD_SET(sock, &rfds);
325             maxfd = MAX(sock, maxfd);
326         }
328         maxfd = maxfd + 1;
329         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
330              NameServer_module->unblockFd, maxfd)
331         ret = select(maxfd, &rfds, NULL, NULL, NULL);
332         if (ret == -1) {
333             LOG0("listener_cb: select failed.")
334             break;
335         }
336         LOG0("NameServer: back from select()\n")
338         for (procId = 0; procId < numProcs; procId++) {
339             if (procId == MultiProc_self() ||
340                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
341                 continue;
342             }
343             sock = NameServer_module->recvSock[procId];
344             if (FD_ISSET(sock, &rfds)) {
345                 LOG1("NameServer: Listener got NameServer message "
346                      "from sock: %d!\n", sock);
347                 /* Get NameServer message and process: */
348                 memset(&fromAddr, 0, sizeof(fromAddr));
349                 len = sizeof(fromAddr);
351                 byteCount = recvfrom(sock, &msg, sizeof(NameServerMsg), 0,
352                                 (struct sockaddr *)&fromAddr, &len);
353                 if (len != sizeof(fromAddr)) {
354                     LOG1("recvfrom: got bad addr len (%d)\n", len)
355                     break;
356                 }
357                 if (byteCount < 0) {
358                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
359                     break;
360                 }
361                 else {
362                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
363                     LOG2("\tReceived ns msg: byteCount: %d, from addr: %d, ",
364                          byteCount, fromAddr.addr)
365                     LOG1("from vproc: %d\n", fromAddr.vproc_id)
366                     NameServerRemote_processMessage(&msg, procId);
367                 }
368             }
369         }
370         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
371             /* We are told to unblock and exit: */
372             LOG0("NameServer: Listener thread exiting\n")
373             break;
374         }
375     } while (1);
377     return ((void *)ret);
380 /* =============================================================================
381  * APIS
382  * =============================================================================
383  */
385 /* Function to setup the nameserver module. */
386 Int NameServer_setup(Void)
388     Int    status = NameServer_S_SUCCESS;
389     int    err;
390     int    sock;
391     int    ret;
392     UInt16 procId;
393     UInt16 numProcs;
395     pthread_mutex_lock(&NameServer_module->modGate);
397     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
399     NameServer_module->refCount++;
401     if (NameServer_module->refCount > 1) {
402         LOG0("NameServer_setup: already setup\n")
403         status = NameServer_S_ALREADYSETUP;
404         goto exit;
405     }
407     numProcs = MultiProc_getNumProcessors();
409     NameServer_module->unblockFd = eventfd(0, 0);
410     if (NameServer_module->unblockFd < 0) {
411         status = NameServer_E_FAIL;
412         LOG0("NameServer_setup: failed to create unblockFd.\n")
413         goto exit;
414     }
416     NameServer_module->waitFd = eventfd(0, 0);
417     if (NameServer_module->waitFd < 0) {
418         status = NameServer_E_FAIL;
419         LOG0("NameServer_setup: failed to create waitFd.\n")
420         goto exit;
421     }
423     for (procId = 0; procId < numProcs; procId++) {
424         NameServer_module->sendSock[procId] = INVALIDSOCKET;
425         NameServer_module->recvSock[procId] = INVALIDSOCKET;
427         /* Only support NameServer to remote procs: */
428         if (procId == MultiProc_self()) {
429             continue;
430         }
432         /* Create the socket for sending messages to each remote proc: */
433         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
434         if (sock < 0) {
435             status = NameServer_E_FAIL;
436             LOG2("NameServer_setup: socket failed: %d, %s\n",
437                  errno, strerror(errno))
438         }
439         else  {
440             LOG1("NameServer_setup: created send socket: %d\n", sock)
441             err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
442             if (err < 0) {
443                 status = NameServer_E_FAIL;
444                 LOG2("NameServer_setup: connect failed: %d, %s\n",
445                      errno, strerror(errno))
447                 LOG1("    closing send socket: %d\n", sock)
448                 close(sock);
449             }
450             else {
451                 NameServer_module->sendSock[procId] = sock;
452             }
453         }
455         /* Create the socket for recving messages from each remote proc: */
456         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
457         if (sock < 0) {
458             status = NameServer_E_FAIL;
459             LOG2("NameServer_setup: socket failed: %d, %s\n",
460                  errno, strerror(errno))
461         }
462         else  {
463             LOG1("NameServer_setup: created recv socket: %d\n", sock)
465             err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
466             if (err < 0) {
467                 status = NameServer_E_FAIL;
468                 LOG2("NameServer_setup: bind failed: %d, %s\n",
469                     errno, strerror(errno))
471                 LOG1("    closing recv socket: %d\n", sock)
472                 close(sock);
473             }
474             else {
475                 NameServer_module->recvSock[procId] = sock;
476             }
477         }
478     }
480     /* Construct the list object */
481     CIRCLEQ_INIT(&NameServer_module->objList);
483     /* Create the listener thread: */
484     LOG0("NameServer_setup: creating listener thread\n")
485     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
486     if (ret) {
487         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
488         LOG0("NameServer_setup: eventfd failed");
490         status = NameServer_E_FAIL;
491     }
492     else {
493         /* look for at least one good send/recv pair to indicate success */
494         for (procId = 0; procId < numProcs; procId++) {
495             if (NameServer_module->sendSock[procId] != INVALIDSOCKET &&
496                 NameServer_module->recvSock[procId] != INVALIDSOCKET) {
497                 status = NameServer_S_SUCCESS;
499                 break;
500             }
501         }
502     }
504 exit:
505     LOG1("NameServer_setup: exiting, refCount=%d\n", NameServer_module->refCount)
507     pthread_mutex_unlock(&NameServer_module->modGate);
509     return (status);
512 /*! Function to destroy the nameserver module. */
513 Int NameServer_destroy(void)
515     Int      status    = NameServer_S_SUCCESS;
516     UInt16   numProcs = MultiProc_getNumProcessors();
517     UInt16   procId;
518     int      sock;
519     uint64_t buf = 1;
520     int      numBytes;
522     pthread_mutex_lock(&NameServer_module->modGate);
524     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
526     NameServer_module->refCount--;
528     if (NameServer_module->refCount > 0) {
529         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
530         status = NameServer_S_SUCCESS;
532         goto exit;
533     }
535     for (procId = 0; procId < numProcs; procId++) {
536         /* Only support NameServer to remote procs: */
537         if (procId == MultiProc_self()) {
538             continue;
539         }
541         /* Close the socket: */
542         sock = NameServer_module->sendSock[procId];
543         if (sock != INVALIDSOCKET) {
544             LOG1("NameServer_destroy: closing socket: %d\n", sock)
545             close(sock);
546             NameServer_module->sendSock[procId] = INVALIDSOCKET;
547         }
548         /* Close the socket: */
549         sock = NameServer_module->recvSock[procId];
550         if (sock != INVALIDSOCKET) {
551             LOG1("NameServer_destroy: closing socket: %d\n", sock)
552             close(sock);
553             NameServer_module->recvSock[procId] = INVALIDSOCKET;
554         }
555     }
557     CIRCLEQ_destruct(&NameServer_module->objList);
559     /* Unblock the NameServer listener thread: */
560     LOG0("NameServer_destroy: unblocking listener...\n")
561     numBytes = write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
563     /* Join: */
564     LOG0("NameServer_destroy: joining listener thread...\n")
565     pthread_join(NameServer_module->listener, NULL);
567     close(NameServer_module->unblockFd);
568     close(NameServer_module->waitFd);
570 exit:
571     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
573     pthread_mutex_unlock(&NameServer_module->modGate);
575     return (status);
578 /* Function to retrieve a NameServer handle from name. */
579 NameServer_Handle NameServer_getHandle(String name)
581     NameServer_Handle handle = NULL;
582     Bool              found = FALSE;
583     struct NameServer_Object * elem;
585     assert(name != NULL);
586     assert(NameServer_module->refCount != 0);
588     pthread_mutex_lock(&NameServer_module->modGate);
590     /* Lookup handle from name: */
591     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
592         handle = (NameServer_Handle) elem;
593         if (strcmp(handle->name, name) == 0) {
594             found = TRUE;
595             break;
596         }
597     }
599     if (found == FALSE) {
600         handle = NULL;
601     }
603     pthread_mutex_unlock(&NameServer_module->modGate);
605     return (handle);
609 /* Function to create a name server. */
610 NameServer_Handle NameServer_create(String name,
611                                     const NameServer_Params * params)
613     NameServer_Handle handle = NULL;
614     pthread_mutexattr_t mutex_attr;
616     assert(params != NULL);
617     assert(name != NULL);
618     assert(NameServer_module->refCount != 0);
620     LOG1("NameServer_create(): '%s'\n", name)
622     pthread_mutex_lock(&NameServer_module->modGate);
624     if (params->maxValueLen > sizeof(UInt32)) {
625         LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
626        /* Can't handle more than UInt32 at this time: */
627        goto leave;
628     }
630     /* check if the name is already created or not */
631     if (NameServer_getHandle(name)) {
632         LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
633         handle = NULL;
634         goto leave;
635     }
636     else {
637         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
638     }
640     if (!handle) {
641         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
642         goto leave;
643     }
645     handle->name = (String)malloc(strlen(name) + 1u);
646     if (!handle->name) {
647         LOG0("NameServer_create: instance name alloc failed\n")
648         goto cleanup;
649     }
650     strncpy(handle->name, name, strlen (name) + 1u);
651     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
653     if (params->maxValueLen < sizeof(UInt32)) {
654         handle->params.maxValueLen = sizeof(UInt32);
655     }
656     else {
657         handle->params.maxValueLen = params->maxValueLen;
658     }
660     CIRCLEQ_INIT(&handle->nameList);
661     handle->count = 0u;
663     /* Put in the local list */
664     CIRCLEQ_elemClear(&handle->elem);
665     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
667     /*
668      * NameServer_removeEntry() enters gate and is called by
669      * NameServer_remove() while holding the gate.
670      */
671     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
672     pthread_mutex_init(&handle->gate, &mutex_attr);
674     goto leave;
676 cleanup:
677     free(handle);
678     handle = NULL;
680 leave:
681     pthread_mutex_unlock(&NameServer_module->modGate);
683     return (handle);
687 /* Function to delete a name server. */
688 Int NameServer_delete(NameServer_Handle * handle)
690     Int status = NameServer_S_SUCCESS;
692     assert(handle != NULL);
693     assert(*handle != NULL);
694     assert((*handle)->count == 0);
695     assert(NameServer_module->refCount != 0);
697     pthread_mutex_lock(&NameServer_module->modGate);
699     if ((*handle)->count == 0) {
700         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
702         if ((*handle)->name != NULL) {
703             free((*handle)->name);
704             (*handle)->name = NULL;
705         }
707         CIRCLEQ_destruct(&(*handle)->nameList);
709         free((*handle));
710         (*handle) = NULL;
711     }
713     pthread_mutex_unlock(&NameServer_module->modGate);
715     return (status);
718 /* Adds a variable length value into the local NameServer table */
719 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
721     Int                 status = NameServer_S_SUCCESS;
722     NameServer_TableEntry * node = NULL;
723     NameServer_TableEntry * new_node = NULL;
724     Bool                found = FALSE;
725     UInt32              hash;
727     assert(handle != NULL);
728     assert(name     != NULL);
729     assert(buf      != NULL);
730     assert(len      != 0);
731     assert(NameServer_module->refCount != 0);
733     /* Calculate the hash */
734     hash = stringHash(name);
736     pthread_mutex_lock(&handle->gate);
738     /* Traverse the list to find duplicate check */
739     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
740         /* Hash matches */
741         if (node->hash == hash) {
742             /* If the name matches, incase hash is duplicate */
743             if (strcmp(node->name, name) == 0) {
744                 if (handle->params.checkExisting == TRUE) {
745                     status = NameServer_E_INVALIDARG;
746                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
747                     break;
748                 }
749             }
750             else {
751                 found = TRUE;
752                 break;
753             } /* name does not match */
754         } /* hash does not match */
755     } /* CIRCLEQ_traverse */
757     if (status != NameServer_S_SUCCESS) {
758         new_node = NULL;
759         goto exit;
760     }
762     /* Now add the new entry. */
763     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
764     if (new_node == NULL) {
765         status = NameServer_E_MEMORY;
766         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
768         goto exit;
769     }
771     new_node->hash    = hash;
772     new_node->collide = found; /* Indicate if there is a collision*/
773     new_node->len     = len;
774     new_node->next    = NULL;
775     new_node->name = (String)malloc(strlen(name) + 1u);
776     new_node->value  = (Ptr)malloc(len);
777     strncpy(new_node->name, name, strlen(name) + 1u);
778     memcpy((Ptr)new_node->value, (Ptr)buf, len);
780     if (found == TRUE) {
781         /* If hash is found, need to stitch the list to link the
782          * new node to the existing node with the same hash.
783          */
784         new_node->next = node->next;
785         node->next = new_node;
786     }
787     else {
788         /* put the new node into the list */
789         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
790     }
792     handle->count++;
794     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
795          name, *(UInt32 *)buf)
797 exit:
798     pthread_mutex_unlock(&handle->gate);
800     return (new_node);
804 /* Function to add a UInt32 value into a name server. */
805 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
807     Ptr entry = NULL;
809     assert(handle != NULL);
810     assert(name   != NULL);
811     assert(NameServer_module->refCount != 0);
813     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
815     return (entry);
818 /* Function to remove a name/value pair from a name server. */
819 Int NameServer_remove(NameServer_Handle handle, String name)
821     Int                 status = NameServer_S_SUCCESS;
822     NameServer_TableEntry *prev = NULL;
823     NameServer_TableEntry *temp = NULL;
824     NameServer_TableEntry *node = NULL;
825     Bool                done   = FALSE;
826     UInt32              hash;
828     assert(handle != NULL);
829     assert(name   != NULL);
830     assert(NameServer_module->refCount != 0);
832     /* Calculate the hash */
833     hash = stringHash(name);
835     pthread_mutex_lock(&handle->gate);
837     /* Traverse the list to find duplicate check */
838     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
839         /* Hash matchs */
840         if (node->hash == hash) {
841             if (node->collide == TRUE) {
842                 if (strcmp(node->name, name) == 0){
843                     free(node->value);
844                     free(node->name);
845                     memcpy((Ptr)node, (Ptr) node->next,
846                            sizeof(NameServer_TableEntry));
847                     node->next = node->next->next;
848                     free(node->next);
849                     handle->count--;
850                     done = TRUE;
851                     break;
852                 }
853                 else {
854                     prev = node;
855                     temp = node->next;
856                     while (temp) {
857                         if (strcmp(temp->name, name) == 0){
858                             free(temp->value);
859                             free(temp->name);
860                             prev->next = temp->next;
861                             free(temp);
862                             handle->count--;
863                             done = TRUE;
864                             break;
865                         }
866                         temp = temp->next;
867                     }
868                     break;
869                 }
870             }
871             else {
872                 NameServer_removeEntry(handle, (Ptr)node);
874                 done = TRUE;
875                 break;
876             }
877         }
878     }
880     if (done == FALSE) {
881         status = NameServer_E_INVALIDARG;
882         LOG1("NameServer_remove %d Entry not found!\n", status)
883     }
885     pthread_mutex_unlock(&handle->gate);
887     return (status);
890 /* Function to remove a name/value pair from a name server. */
891 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
893     Int  status = NameServer_S_SUCCESS;
894     NameServer_TableEntry * node;
896     assert(handle != NULL);
897     assert(entry  != NULL);
898     assert(NameServer_module->refCount != 0);
900     pthread_mutex_lock(&handle->gate);
902     node = (NameServer_TableEntry *)entry;
904     free(node->value);
905     free(node->name);
906     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
907     free(node);
908     handle->count--;
910     pthread_mutex_unlock(&handle->gate);
912     return (status);
916 /* Initialize this config-params structure with supplier-specified
917  * defaults before instance creation.
918  */
919 Void NameServer_Params_init(NameServer_Params * params)
921     assert(params != NULL);
923     memcpy(params, &(NameServer_module->defInstParams),
924            sizeof (NameServer_Params));
928 Int NameServer_getRemote(NameServer_Handle handle,
929                      String            name,
930                      Ptr               value,
931                      UInt32 *          len,
932                      UInt16            procId)
934     Int status = NameServer_S_SUCCESS;
935     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
936     NameServerMsg nsMsg;
937     NameServerMsg *replyMsg;
938     fd_set rfds;
939     int ret = 0, sock, maxfd, waitFd;
940     struct timeval tv;
941     uint64_t buf = 1;
942     int numBytes;
943     int err;
945     /* Set Timeout to wait: */
946     tv.tv_sec = 0;
947     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
949     /* Create request message and send to remote: */
950     sock = NameServer_module->sendSock[procId];
951     if (sock == INVALIDSOCKET) {
952         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
953              procId);
954         status = NameServer_E_RESOURCE;
955         goto exit;
956     }
958     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
960     /* Create request message and send to remote processor: */
961     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
962     nsMsg.request = NAMESERVER_REQUEST;
963     nsMsg.requestStatus = 0;
965     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
966     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
968     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
969            procId, (String)nsMsg.instanceName)
970     LOG1("%s...\n", (String)nsMsg.name)
972     err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
973     if (err < 0) {
974         LOG2("NameServer_getRemote: send failed: %d, %s\n",
975              errno, strerror(errno))
976         status = NameServer_E_FAIL;
977         goto exit;
978     }
980     /* Block on waitFd for signal from listener thread: */
981     waitFd = NameServer_module->waitFd;
982     FD_ZERO(&rfds);
983     FD_SET(waitFd, &rfds);
984     maxfd = waitFd + 1;
985     LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
986     ret = select(maxfd, &rfds, NULL, NULL, &tv);
987     if (ret == -1) {
988         LOG0("NameServer_getRemote: select failed.")
989         status = NameServer_E_FAIL;
990         goto exit;
991     }
992     else if (!ret) {
993         LOG0("NameServer_getRemote: select timed out.\n")
994         status = NameServer_E_TIMEOUT;
995         goto exit;
996     }
998     if (FD_ISSET(waitFd, &rfds)) {
999         /* Read, just to balance the write: */
1000         numBytes = read(waitFd, &buf, sizeof(uint64_t));
1002         /* Process response: */
1003         replyMsg = &NameServer_module->nsMsg;
1005         if (replyMsg->requestStatus) {
1006             /* name is found */
1007             /* set the contents of value */
1008             *(UInt32 *)value = (UInt32)replyMsg->value;
1010             LOG2("NameServer_getRemote: Reply from: %d, %s:",
1011                  procId, (String)replyMsg->instanceName)
1012             LOG2("%s, value: 0x%x...\n",
1013                  (String)replyMsg->name, *(UInt32 *)value)
1014             goto exit;
1015         }
1016         else {
1017             /* name is not found */
1018             LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1019                  (String)replyMsg->instanceName, (String)replyMsg->name)
1021             /* set status to not found */
1022             status = NameServer_E_NOTFOUND;
1023         }
1024     }
1026 exit:
1027     return (status);
1030 /* Function to retrieve the value portion of a name/value pair from
1031  * local table.
1032  */
1033 Int NameServer_get(NameServer_Handle handle,
1034                String            name,
1035                Ptr               value,
1036                UInt32 *          len,
1037                UInt16            procId[])
1039     Int status = NameServer_S_SUCCESS;
1040     UInt16 numProcs = MultiProc_getNumProcessors();
1041     UInt32 i;
1043     /*
1044      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1045      * since this goes in a daemon, it will not be necessary.
1046      */
1048     if (procId == NULL) {
1049         status = NameServer_getLocal(handle, name, value, len);
1050         if (status == NameServer_E_NOTFOUND) {
1051             for (i = 0; i < numProcs; i++) {
1052                 /* getLocal call already covers "self", keep going */
1053                 if (i == MultiProc_self()) {
1054                     continue;
1055                 }
1057                 status = NameServer_getRemote(handle, name, value, len, i);
1059                 if ((status >= 0) ||
1060                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1061                                      (status != NameServer_E_RESOURCE))) {
1062                     break;
1063                 }
1064             }
1065         }
1066     }
1067     else {
1068         /*
1069          *  Search the query list. It might contain the local proc
1070          *  somewhere in the list.
1071          */
1072         i = 0;
1073         while (procId[i] != MultiProc_INVALIDID) {
1074             if (procId[i] == MultiProc_self()) {
1075                 status = NameServer_getLocal(handle, name, value, len);
1076             }
1077             else {
1078                 status = NameServer_getRemote(handle, name, value, len, i);
1079             }
1081             if ((status >= 0) ||
1082                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1083                                  (status != NameServer_E_RESOURCE))) {
1084                 break;
1085             }
1087             i++;
1088         }
1089     }
1091     if (status == NameServer_E_RESOURCE) {
1092         status = NameServer_E_NOTFOUND;
1093     }
1095     return (status);
1098 /* Gets a 32-bit value by name */
1099 Int NameServer_getUInt32(NameServer_Handle handle,
1100                      String            name,
1101                      Ptr               value,
1102                      UInt16            procId[])
1104     Int  status;
1105     UInt32 len = sizeof(UInt32);
1107     assert(handle != NULL);
1108     assert(name   != NULL);
1109     assert(value  != NULL);
1110     assert(NameServer_module->refCount != 0);
1112     status = NameServer_get(handle, name, value, &len, procId);
1114     return (status);
1117 /* Function to Retrieve the value portion of a name/value pair from
1118  * local table.
1119  */
1120 Int NameServer_getLocal(NameServer_Handle handle,
1121                     String            name,
1122                     Ptr               value,
1123                     UInt32 *          len)
1125     Int status = NameServer_E_NOTFOUND;
1126     NameServer_TableEntry * node = NULL;
1127     NameServer_TableEntry * temp = NULL;
1128     Bool done   = FALSE;
1129     UInt32 length;
1130     UInt32 hash;
1132     assert(handle != NULL);
1133     assert(name   != NULL);
1134     assert(value  != NULL);
1135     assert(len    != NULL);
1136     assert(NameServer_module->refCount != 0);
1138     length = *len;
1140     /* Calculate the hash */
1141     hash = stringHash(name);
1143     pthread_mutex_lock(&handle->gate);
1145     /* Traverse the list to find duplicate check */
1146     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1147         if (node->hash == hash) {
1148             if (node->collide == TRUE) {
1149                 temp = node;
1150                 while (temp) {
1151                     if (strcmp(temp->name, name) == 0u){
1152                         if (length <= node->len) {
1153                             memcpy(value, node->value, length);
1154                             *len = length;
1155                         }
1156                         else {
1157                             memcpy(value, node->value, node->len);
1158                             *len = node->len;
1159                         }
1160                         done = TRUE;
1161                         break;
1162                     }
1163                     temp = temp->next;
1164                 }
1165                 break;
1166             }
1167             else {
1168                 if (length <= node->len) {
1169                     memcpy(value, node->value, length);
1170                     *len = length;
1171                 }
1172                 else {
1173                     memcpy(value, node->value, node->len);
1174                     *len = node->len;
1175                 }
1176                 done = TRUE;
1177                 break;
1178             }
1179         }
1180     }
1182     pthread_mutex_unlock(&handle->gate);
1184     if (done == FALSE) {
1185         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1186     }
1187     else {
1188         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1189              node->name, (UInt32)node->value)
1190         status = NameServer_S_SUCCESS;
1191     }
1193     return (status);
1196 /*
1197  *  Gets a 32-bit value by name from the local table
1198  *
1199  *  If the name is found, the 32-bit value is copied into the value
1200  *  argument and a success status is returned.
1201  *
1202  *  If the name is not found, zero is returned in len and the contents
1203  *  of value are not modified. Not finding a name is not considered
1204  *  an error.
1205  *
1206  *  This function only searches the local name/value table.
1207  *
1208  */
1209 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1211     Int                 status;
1212     UInt32              len    = sizeof(UInt32);
1214     assert(handle != NULL);
1215     assert(name   != NULL);
1216     assert(value  != NULL);
1217     assert(NameServer_module->refCount != 0);
1219     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1220     status = NameServer_getLocal(handle, name, value, &len);
1222     return (status);
1226 #if defined (__cplusplus)
1228 #endif /* defined (__cplusplus) */