]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/NameServer_daemon.c
Android: Added support for MessageQ
[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     UInt32             refCount;        /* reference count to this object */
117     pthread_mutex_t    gate;            /* crit sect gate */
118 } NameServer_Object;
120 /* structure for NameServer module state */
121 typedef struct NameServer_ModuleObject {
122     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
123     Int32               refCount;
124     int                 sendSock[MultiProc_MAXPROCESSORS];
125     /* Sockets for sending to remote proc nameserver ports: */
126     int                 recvSock[MultiProc_MAXPROCESSORS];
127     /* Sockets for recving from remote proc nameserver ports: */
128     pthread_t           listener;
129     /* Listener thread for NameServer replies and requests. */
130     int                 unblockFd;
131     /* Event to post to exit listener. */
132     int                 waitFd;
133     /* Event to post to NameServer_get. */
134     NameServerMsg       nsMsg;
135     /* NameServer Message cache. */
136     NameServer_Params   defInstParams;
137     /* Default instance paramters */
138     pthread_mutex_t     modGate;
139 } NameServer_ModuleObject;
141 #define CIRCLEQ_destruct(head) { \
142         (head)->cqh_first = NULL; \
143         (head)->cqh_last = NULL; \
146 #define CIRCLEQ_elemClear(elem) { \
147         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
150 #define CIRCLEQ_traverse(x, y, tag) \
151         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
153 /* =============================================================================
154  *  Globals
155  * =============================================================================
156  */
157 /*
158  * NameServer_state
159  *
160  * Make the module gate "recursive" since NameServer_getHandle() needs to
161  * use it and NameServer_create() needs to hold it around its call to
162  * NameServer_getHandle().  Also, use the static initializer instead of a
163  * run-time init call, so we can use this gate immediately in _setup().
164  */
165 static NameServer_ModuleObject NameServer_state = {
166     .defInstParams.maxRuntimeEntries = 0u,
167     .defInstParams.tableHeap         = NULL,
168     .defInstParams.checkExisting     = TRUE,
169     .defInstParams.maxValueLen       = 0u,
170     .defInstParams.maxNameLen        = 16u,
171 #if defined(IPC_BUILDOS_ANDROID)
172     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
173 #else
174 // only _NP (non-portable) type available in CG tools which we're using
175     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
176 #endif
177     .refCount                        = 0
178 };
180 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
182 static const UInt32 stringCrcTab[256u] = {
183   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
184   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
185   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
186   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
187   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
188   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
189   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
190   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
191   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
192   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
193   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
194   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
195   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
196   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
197   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
198   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
199   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
200   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
201   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
202   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
203   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
204   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
205   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
206   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
207   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
208   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
209   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
210   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
211   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
212   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
213   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
214   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
215   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
216   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
217   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
218   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
219   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
220   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
221   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
222   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
223   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
224   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
225   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
226 };
228 static UInt32 stringHash(String s)
230     UInt32 hash = strlen(s);
231     UInt32 i;
233     for (i = 0; i < strlen(s); i++) {
234         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
235     }
237     return (hash);
240 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
242     NameServer_Handle handle;
243     Int               status = NameServer_E_FAIL;
244     int               err;
245     uint64_t          buf = 1;
246     int               numBytes;
247     int               waitFd = NameServer_module->waitFd;
249     if (msg->request == NAMESERVER_REQUEST) {
250         LOG2("NameServer Request: instanceName: %s, name: %s\n",
251              (String)msg->instanceName, (String)msg->name)
253         /*
254          *  Message is a request. Lookup name in NameServer table.
255          *  Send a response message back to source processor.
256          */
257         handle = NameServer_getHandle((String)msg->instanceName);
259         if (handle != NULL) {
260             /* Search for the NameServer entry */
261             LOG0("Calling NameServer_getLocalUInt32...\n")
262             status = NameServer_getLocalUInt32(handle,
263                      (String)msg->name, &msg->value);
264         }
266         LOG2("NameServer Response: instanceName: %s, name: %s,",
267              (String)msg->instanceName, (String)msg->name)
268         /* set the request status */
269         if (status < 0) {
270             LOG1(" Value not found, status: %d\n", status)
271             msg->requestStatus = 0;
272         }
273         else {
274             msg->requestStatus = 1;
275             LOG1(" Value: 0x%x\n", msg->value)
276         }
278         /* specify message as a response */
279         msg->request = NAMESERVER_RESPONSE;
280         msg->reserved = NAMESERVER_MSG_TOKEN;
282         /* send response message to remote processor */
283         err = send(NameServer_module->sendSock[procId], msg,
284                    sizeof(NameServerMsg), 0);
285         if (err < 0) {
286             LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
287         }
288     }
289     else {
290         LOG2("NameServer Reply: instanceName: %s, name: %s",
291              (String)msg->instanceName, (String)msg->name)
292         LOG1(", value: 0x%x\n", msg->value)
294         /* Save the response message.  */
295         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
297         /* Post the eventfd upon which NameServer_get() is waiting */
298         numBytes = write(waitFd, &buf, sizeof(uint64_t));
299     }
303 static void *listener_cb(void *arg)
305     fd_set rfds;
306     int ret = 0, maxfd;
307     UInt16 procId;
308     struct  sockaddr_rpmsg  fromAddr;
309     unsigned int len;
310     NameServerMsg msg;
311     int     byteCount;
312     UInt16  numProcs = MultiProc_getNumProcessors();
313     int     sock;
315     LOG0("listener_cb: Entered Listener thread.\n")
317     do {
318         /* Wait for NameServer messages or unblockFd notification */
319         FD_ZERO(&rfds);
320         FD_SET(NameServer_module->unblockFd, &rfds);
321         maxfd = NameServer_module->unblockFd;
322         for (procId = 0; procId < numProcs; procId++) {
323             if (procId == MultiProc_self() ||
324                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
325                 continue;
326             }
327             sock = NameServer_module->recvSock[procId];
328             FD_SET(sock, &rfds);
329             maxfd = MAX(sock, maxfd);
330         }
332         maxfd = maxfd + 1;
333         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
334              NameServer_module->unblockFd, maxfd)
335         ret = select(maxfd, &rfds, NULL, NULL, NULL);
336         if (ret == -1) {
337             LOG0("listener_cb: select failed.")
338             break;
339         }
340         LOG0("NameServer: back from select()\n")
342         for (procId = 0; procId < numProcs; procId++) {
343             if (procId == MultiProc_self() ||
344                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
345                 continue;
346             }
347             sock = NameServer_module->recvSock[procId];
348             if (FD_ISSET(sock, &rfds)) {
349                 LOG1("NameServer: Listener got NameServer message "
350                      "from sock: %d!\n", sock);
351                 /* Get NameServer message and process: */
352                 memset(&fromAddr, 0, sizeof(fromAddr));
353                 len = sizeof(fromAddr);
355                 byteCount = recvfrom(sock, &msg, sizeof(NameServerMsg), 0,
356                                 (struct sockaddr *)&fromAddr, &len);
357                 if (len != sizeof(fromAddr)) {
358                     LOG1("recvfrom: got bad addr len (%d)\n", len)
359                     break;
360                 }
361                 if (byteCount < 0) {
362                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
363                     break;
364                 }
365                 else {
366                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
367                     LOG2("\tReceived ns msg: byteCount: %d, from addr: %d, ",
368                          byteCount, fromAddr.addr)
369                     LOG1("from vproc: %d\n", fromAddr.vproc_id)
370                     NameServerRemote_processMessage(&msg, procId);
371                 }
372             }
373         }
374         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
375             /* We are told to unblock and exit: */
376             LOG0("NameServer: Listener thread exiting\n")
377             break;
378         }
379     } while (1);
381     return ((void *)ret);
384 /* =============================================================================
385  * APIS
386  * =============================================================================
387  */
389 /* Function to setup the nameserver module. */
390 Int NameServer_setup(Void)
392     Int    status = NameServer_S_SUCCESS;
393     int    err;
394     int    sock;
395     int    ret;
396     UInt16 procId;
397     UInt16 numProcs;
399     pthread_mutex_lock(&NameServer_module->modGate);
401     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
403     NameServer_module->refCount++;
405     if (NameServer_module->refCount > 1) {
406         LOG0("NameServer_setup: already setup\n")
407         status = NameServer_S_ALREADYSETUP;
408         goto exit;
409     }
411     numProcs = MultiProc_getNumProcessors();
413     NameServer_module->unblockFd = eventfd(0, 0);
414     if (NameServer_module->unblockFd < 0) {
415         status = NameServer_E_FAIL;
416         LOG0("NameServer_setup: failed to create unblockFd.\n")
417         goto exit;
418     }
420     NameServer_module->waitFd = eventfd(0, 0);
421     if (NameServer_module->waitFd < 0) {
422         status = NameServer_E_FAIL;
423         LOG0("NameServer_setup: failed to create waitFd.\n")
424         goto exit;
425     }
427     for (procId = 0; procId < numProcs; procId++) {
428         NameServer_module->sendSock[procId] = INVALIDSOCKET;
429         NameServer_module->recvSock[procId] = INVALIDSOCKET;
431         /* Only support NameServer to remote procs: */
432         if (procId == MultiProc_self()) {
433             continue;
434         }
436         /* Create the socket for sending messages to each remote proc: */
437         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
438         if (sock < 0) {
439             status = NameServer_E_FAIL;
440             LOG2("NameServer_setup: socket failed: %d, %s\n",
441                  errno, strerror(errno))
442         }
443         else  {
444             LOG1("NameServer_setup: created send socket: %d\n", sock)
445             err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
446             if (err < 0) {
447                 status = NameServer_E_FAIL;
448                 LOG2("NameServer_setup: connect failed: %d, %s\n",
449                      errno, strerror(errno))
451                 LOG1("    closing send socket: %d\n", sock)
452                 close(sock);
453             }
454             else {
455                 NameServer_module->sendSock[procId] = sock;
456             }
457         }
459         /* Create the socket for recving messages from each remote proc: */
460         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
461         if (sock < 0) {
462             status = NameServer_E_FAIL;
463             LOG2("NameServer_setup: socket failed: %d, %s\n",
464                  errno, strerror(errno))
465         }
466         else  {
467             LOG1("NameServer_setup: created recv socket: %d\n", sock)
469             err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
470             if (err < 0) {
471                 status = NameServer_E_FAIL;
472                 LOG2("NameServer_setup: bind failed: %d, %s\n",
473                     errno, strerror(errno))
475                 LOG1("    closing recv socket: %d\n", sock)
476                 close(sock);
477             }
478             else {
479                 NameServer_module->recvSock[procId] = sock;
480             }
481         }
482     }
484     /* Construct the list object */
485     CIRCLEQ_INIT(&NameServer_module->objList);
487     /* Create the listener thread: */
488     LOG0("NameServer_setup: creating listener thread\n")
489     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
490     if (ret) {
491         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
492         LOG0("NameServer_setup: eventfd failed");
494         status = NameServer_E_FAIL;
495     }
496     else {
497         /* look for at least one good send/recv pair to indicate success */
498         for (procId = 0; procId < numProcs; procId++) {
499             if (NameServer_module->sendSock[procId] != INVALIDSOCKET &&
500                 NameServer_module->recvSock[procId] != INVALIDSOCKET) {
501                 status = NameServer_S_SUCCESS;
503                 break;
504             }
505         }
506     }
508 exit:
509     LOG1("NameServer_setup: exiting, refCount=%d\n", NameServer_module->refCount)
511     pthread_mutex_unlock(&NameServer_module->modGate);
513     return (status);
516 /*! Function to destroy the nameserver module. */
517 Int NameServer_destroy(void)
519     Int      status    = NameServer_S_SUCCESS;
520     UInt16   numProcs = MultiProc_getNumProcessors();
521     UInt16   procId;
522     int      sock;
523     uint64_t buf = 1;
524     int      numBytes;
526     pthread_mutex_lock(&NameServer_module->modGate);
528     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
530     NameServer_module->refCount--;
532     if (NameServer_module->refCount > 0) {
533         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
534         status = NameServer_S_SUCCESS;
536         goto exit;
537     }
539     for (procId = 0; procId < numProcs; procId++) {
540         /* Only support NameServer to remote procs: */
541         if (procId == MultiProc_self()) {
542             continue;
543         }
545         /* Close the socket: */
546         sock = NameServer_module->sendSock[procId];
547         if (sock != INVALIDSOCKET) {
548             LOG1("NameServer_destroy: closing socket: %d\n", sock)
549             close(sock);
550             NameServer_module->sendSock[procId] = INVALIDSOCKET;
551         }
552         /* Close the socket: */
553         sock = NameServer_module->recvSock[procId];
554         if (sock != INVALIDSOCKET) {
555             LOG1("NameServer_destroy: closing socket: %d\n", sock)
556             close(sock);
557             NameServer_module->recvSock[procId] = INVALIDSOCKET;
558         }
559     }
561     CIRCLEQ_destruct(&NameServer_module->objList);
563     /* Unblock the NameServer listener thread: */
564     LOG0("NameServer_destroy: unblocking listener...\n")
565     numBytes = write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
567     /* Join: */
568     LOG0("NameServer_destroy: joining listener thread...\n")
569     pthread_join(NameServer_module->listener, NULL);
571     close(NameServer_module->unblockFd);
572     close(NameServer_module->waitFd);
574 exit:
575     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
577     pthread_mutex_unlock(&NameServer_module->modGate);
579     return (status);
582 /* Function to retrieve a NameServer handle from name. */
583 NameServer_Handle NameServer_getHandle(String name)
585     NameServer_Handle handle = NULL;
586     Bool              found = FALSE;
587     struct NameServer_Object * elem;
589     assert(name != NULL);
590     assert(NameServer_module->refCount != 0);
592     pthread_mutex_lock(&NameServer_module->modGate);
594     /* Lookup handle from name: */
595     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
596         handle = (NameServer_Handle) elem;
597         if (strcmp(handle->name, name) == 0) {
598             found = TRUE;
599             break;
600         }
601     }
603     if (found == FALSE) {
604         handle = NULL;
605     }
607     pthread_mutex_unlock(&NameServer_module->modGate);
609     return (handle);
613 /* Function to create a name server. */
614 NameServer_Handle NameServer_create(String name,
615                                     const NameServer_Params * params)
617     NameServer_Handle handle = NULL;
618     pthread_mutexattr_t mutex_attr;
620     assert(params != NULL);
621     assert(name != NULL);
622     assert(NameServer_module->refCount != 0);
624     LOG1("NameServer_create(): '%s'\n", name)
626     pthread_mutex_lock(&NameServer_module->modGate);
628     if (params->maxValueLen > sizeof(UInt32)) {
629         LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
630        /* Can't handle more than UInt32 at this time: */
631        goto leave;
632     }
634     /* check if the name is already created or not */
635     handle = NameServer_getHandle(name);
636     if (handle != NULL) {
637         if (memcmp((Ptr)&handle->params, (Ptr)params,
638             sizeof(NameServer_Params)) == 0) {
639             handle->refCount++;
640         }
641         else {
642             LOG0("NameServer_create: NameServer params mismatch\n")
643             handle = NULL;
644         }
645         goto leave;
646     }
647     else {
648         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
649     }
651     if (!handle) {
652         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
653         goto leave;
654     }
656     handle->refCount = 1;
657     handle->name = (String)malloc(strlen(name) + 1u);
658     if (!handle->name) {
659         LOG0("NameServer_create: instance name alloc failed\n")
660         goto cleanup;
661     }
662     strncpy(handle->name, name, strlen (name) + 1u);
663     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
665     if (params->maxValueLen < sizeof(UInt32)) {
666         handle->params.maxValueLen = sizeof(UInt32);
667     }
668     else {
669         handle->params.maxValueLen = params->maxValueLen;
670     }
672     CIRCLEQ_INIT(&handle->nameList);
673     handle->count = 0u;
675     /* Put in the local list */
676     CIRCLEQ_elemClear(&handle->elem);
677     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
679     /*
680      * NameServer_removeEntry() enters gate and is called by
681      * NameServer_remove() while holding the gate.
682      */
683     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
684     pthread_mutex_init(&handle->gate, &mutex_attr);
686     goto leave;
688 cleanup:
689     free(handle);
690     handle = NULL;
692 leave:
693     pthread_mutex_unlock(&NameServer_module->modGate);
695     return (handle);
699 /* Function to delete a name server. */
700 Int NameServer_delete(NameServer_Handle * handle)
702     Int status = NameServer_S_SUCCESS;
704     assert(handle != NULL);
705     assert(*handle != NULL);
706     assert((*handle)->count == 0);
707     assert(NameServer_module->refCount != 0);
709     pthread_mutex_lock(&NameServer_module->modGate);
711     (*handle)->refCount--;
712     if ((*handle)->refCount != 0) {
713         goto leave;
714     }
716     if ((*handle)->count == 0) {
717         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
719         if ((*handle)->name != NULL) {
720             free((*handle)->name);
721             (*handle)->name = NULL;
722         }
724         CIRCLEQ_destruct(&(*handle)->nameList);
726         free((*handle));
727         (*handle) = NULL;
728     }
730 leave:
731     pthread_mutex_unlock(&NameServer_module->modGate);
733     return (status);
736 /* Adds a variable length value into the local NameServer table */
737 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
739     Int                 status = NameServer_S_SUCCESS;
740     NameServer_TableEntry * node = NULL;
741     NameServer_TableEntry * new_node = NULL;
742     Bool                found = FALSE;
743     UInt32              hash;
745     assert(handle != NULL);
746     assert(name     != NULL);
747     assert(buf      != NULL);
748     assert(len      != 0);
749     assert(NameServer_module->refCount != 0);
751     /* Calculate the hash */
752     hash = stringHash(name);
754     pthread_mutex_lock(&handle->gate);
756     /* Traverse the list to find duplicate check */
757     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
758         /* Hash matches */
759         if (node->hash == hash) {
760             /* If the name matches, incase hash is duplicate */
761             if (strcmp(node->name, name) == 0) {
762                 if (handle->params.checkExisting == TRUE) {
763                     status = NameServer_E_INVALIDARG;
764                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
765                     break;
766                 }
767             }
768             else {
769                 found = TRUE;
770                 break;
771             } /* name does not match */
772         } /* hash does not match */
773     } /* CIRCLEQ_traverse */
775     if (status != NameServer_S_SUCCESS) {
776         new_node = NULL;
777         goto exit;
778     }
780     /* Now add the new entry. */
781     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
782     if (new_node == NULL) {
783         status = NameServer_E_MEMORY;
784         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
786         goto exit;
787     }
789     new_node->hash    = hash;
790     new_node->collide = found; /* Indicate if there is a collision*/
791     new_node->len     = len;
792     new_node->next    = NULL;
793     new_node->name = (String)malloc(strlen(name) + 1u);
794     new_node->value  = (Ptr)malloc(len);
795     strncpy(new_node->name, name, strlen(name) + 1u);
796     memcpy((Ptr)new_node->value, (Ptr)buf, len);
798     if (found == TRUE) {
799         /* If hash is found, need to stitch the list to link the
800          * new node to the existing node with the same hash.
801          */
802         new_node->next = node->next;
803         node->next = new_node;
804     }
805     else {
806         /* put the new node into the list */
807         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
808     }
810     handle->count++;
812     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
813          name, *(UInt32 *)buf)
815 exit:
816     pthread_mutex_unlock(&handle->gate);
818     return (new_node);
822 /* Function to add a UInt32 value into a name server. */
823 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
825     Ptr entry = NULL;
827     assert(handle != NULL);
828     assert(name   != NULL);
829     assert(NameServer_module->refCount != 0);
831     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
833     return (entry);
836 /* Function to remove a name/value pair from a name server. */
837 Int NameServer_remove(NameServer_Handle handle, String name)
839     Int                 status = NameServer_S_SUCCESS;
840     NameServer_TableEntry *prev = NULL;
841     NameServer_TableEntry *temp = NULL;
842     NameServer_TableEntry *node = NULL;
843     Bool                done   = FALSE;
844     UInt32              hash;
846     assert(handle != NULL);
847     assert(name   != NULL);
848     assert(NameServer_module->refCount != 0);
850     /* Calculate the hash */
851     hash = stringHash(name);
853     pthread_mutex_lock(&handle->gate);
855     /* Traverse the list to find duplicate check */
856     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
857         /* Hash matchs */
858         if (node->hash == hash) {
859             if (node->collide == TRUE) {
860                 if (strcmp(node->name, name) == 0){
861                     free(node->value);
862                     free(node->name);
863                     memcpy((Ptr)node, (Ptr) node->next,
864                            sizeof(NameServer_TableEntry));
865                     node->next = node->next->next;
866                     free(node->next);
867                     handle->count--;
868                     done = TRUE;
869                     break;
870                 }
871                 else {
872                     prev = node;
873                     temp = node->next;
874                     while (temp) {
875                         if (strcmp(temp->name, name) == 0){
876                             free(temp->value);
877                             free(temp->name);
878                             prev->next = temp->next;
879                             free(temp);
880                             handle->count--;
881                             done = TRUE;
882                             break;
883                         }
884                         temp = temp->next;
885                     }
886                     break;
887                 }
888             }
889             else {
890                 NameServer_removeEntry(handle, (Ptr)node);
892                 done = TRUE;
893                 break;
894             }
895         }
896     }
898     if (done == FALSE) {
899         status = NameServer_E_INVALIDARG;
900         LOG1("NameServer_remove %d Entry not found!\n", status)
901     }
903     pthread_mutex_unlock(&handle->gate);
905     return (status);
908 /* Function to remove a name/value pair from a name server. */
909 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
911     Int  status = NameServer_S_SUCCESS;
912     NameServer_TableEntry * node;
914     assert(handle != NULL);
915     assert(entry  != NULL);
916     assert(NameServer_module->refCount != 0);
918     pthread_mutex_lock(&handle->gate);
920     node = (NameServer_TableEntry *)entry;
922     free(node->value);
923     free(node->name);
924     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
925     free(node);
926     handle->count--;
928     pthread_mutex_unlock(&handle->gate);
930     return (status);
934 /* Initialize this config-params structure with supplier-specified
935  * defaults before instance creation.
936  */
937 Void NameServer_Params_init(NameServer_Params * params)
939     assert(params != NULL);
941     memcpy(params, &(NameServer_module->defInstParams),
942            sizeof (NameServer_Params));
946 Int NameServer_getRemote(NameServer_Handle handle,
947                      String            name,
948                      Ptr               value,
949                      UInt32 *          len,
950                      UInt16            procId)
952     Int status = NameServer_S_SUCCESS;
953     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
954     NameServerMsg nsMsg;
955     NameServerMsg *replyMsg;
956     fd_set rfds;
957     int ret = 0, sock, maxfd, waitFd;
958     struct timeval tv;
959     uint64_t buf = 1;
960     int numBytes;
961     int err;
963     /* Set Timeout to wait: */
964     tv.tv_sec = 0;
965     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
967     /* Create request message and send to remote: */
968     sock = NameServer_module->sendSock[procId];
969     if (sock == INVALIDSOCKET) {
970         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
971              procId);
972         status = NameServer_E_RESOURCE;
973         goto exit;
974     }
976     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
978     /* Create request message and send to remote processor: */
979     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
980     nsMsg.request = NAMESERVER_REQUEST;
981     nsMsg.requestStatus = 0;
982     nsMsg.valueLen = *len;
984     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
985     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
987     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
988            procId, (String)nsMsg.instanceName)
989     LOG1("%s...\n", (String)nsMsg.name)
991     err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
992     if (err < 0) {
993         LOG2("NameServer_getRemote: send failed: %d, %s\n",
994              errno, strerror(errno))
995         status = NameServer_E_FAIL;
996         goto exit;
997     }
999     /* Block on waitFd for signal from listener thread: */
1000     waitFd = NameServer_module->waitFd;
1001     FD_ZERO(&rfds);
1002     FD_SET(waitFd, &rfds);
1003     maxfd = waitFd + 1;
1004     LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1005     ret = select(maxfd, &rfds, NULL, NULL, &tv);
1006     if (ret == -1) {
1007         LOG0("NameServer_getRemote: select failed.")
1008         status = NameServer_E_FAIL;
1009         goto exit;
1010     }
1011     else if (!ret) {
1012         LOG0("NameServer_getRemote: select timed out.\n")
1013         status = NameServer_E_TIMEOUT;
1014         goto exit;
1015     }
1017     if (FD_ISSET(waitFd, &rfds)) {
1018         /* Read, just to balance the write: */
1019         numBytes = read(waitFd, &buf, sizeof(uint64_t));
1021         /* Process response: */
1022         replyMsg = &NameServer_module->nsMsg;
1024         if (replyMsg->requestStatus) {
1025             /* name is found */
1026             /* set the contents of value */
1027             *(UInt32 *)value = (UInt32)replyMsg->value;
1029             LOG2("NameServer_getRemote: Reply from: %d, %s:",
1030                  procId, (String)replyMsg->instanceName)
1031             LOG2("%s, value: 0x%x...\n",
1032                  (String)replyMsg->name, *(UInt32 *)value)
1033             goto exit;
1034         }
1035         else {
1036             /* name is not found */
1037             LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1038                  (String)replyMsg->instanceName, (String)replyMsg->name)
1040             /* set status to not found */
1041             status = NameServer_E_NOTFOUND;
1042         }
1043     }
1045 exit:
1046     return (status);
1049 /* Function to retrieve the value portion of a name/value pair from
1050  * local table.
1051  */
1052 Int NameServer_get(NameServer_Handle handle,
1053                String            name,
1054                Ptr               value,
1055                UInt32 *          len,
1056                UInt16            procId[])
1058     Int status = NameServer_S_SUCCESS;
1059     UInt16 numProcs = MultiProc_getNumProcessors();
1060     UInt32 i;
1062     /*
1063      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1064      * since this goes in a daemon, it will not be necessary.
1065      */
1067     if (procId == NULL) {
1068         status = NameServer_getLocal(handle, name, value, len);
1069         if (status == NameServer_E_NOTFOUND) {
1070             for (i = 0; i < numProcs; i++) {
1071                 /* getLocal call already covers "self", keep going */
1072                 if (i == MultiProc_self()) {
1073                     continue;
1074                 }
1076                 status = NameServer_getRemote(handle, name, value, len, i);
1078                 if ((status >= 0) ||
1079                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1080                                      (status != NameServer_E_RESOURCE))) {
1081                     break;
1082                 }
1083             }
1084         }
1085     }
1086     else {
1087         /*
1088          *  Search the query list. It might contain the local proc
1089          *  somewhere in the list.
1090          */
1091         i = 0;
1092         while (procId[i] != MultiProc_INVALIDID) {
1093             if (procId[i] == MultiProc_self()) {
1094                 status = NameServer_getLocal(handle, name, value, len);
1095             }
1096             else {
1097                 status = NameServer_getRemote(handle, name, value, len, i);
1098             }
1100             if ((status >= 0) ||
1101                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1102                                  (status != NameServer_E_RESOURCE))) {
1103                 break;
1104             }
1106             i++;
1107         }
1108     }
1110     if (status == NameServer_E_RESOURCE) {
1111         status = NameServer_E_NOTFOUND;
1112     }
1114     return (status);
1117 /* Gets a 32-bit value by name */
1118 Int NameServer_getUInt32(NameServer_Handle handle,
1119                      String            name,
1120                      Ptr               value,
1121                      UInt16            procId[])
1123     Int  status;
1124     UInt32 len = sizeof(UInt32);
1126     assert(handle != NULL);
1127     assert(name   != NULL);
1128     assert(value  != NULL);
1129     assert(NameServer_module->refCount != 0);
1131     status = NameServer_get(handle, name, value, &len, procId);
1133     return (status);
1136 /* Function to Retrieve the value portion of a name/value pair from
1137  * local table.
1138  */
1139 Int NameServer_getLocal(NameServer_Handle handle,
1140                     String            name,
1141                     Ptr               value,
1142                     UInt32 *          len)
1144     Int status = NameServer_E_NOTFOUND;
1145     NameServer_TableEntry * node = NULL;
1146     NameServer_TableEntry * temp = NULL;
1147     Bool done   = FALSE;
1148     UInt32 length;
1149     UInt32 hash;
1151     assert(handle != NULL);
1152     assert(name   != NULL);
1153     assert(value  != NULL);
1154     assert(len    != NULL);
1155     assert(NameServer_module->refCount != 0);
1157     length = *len;
1159     /* Calculate the hash */
1160     hash = stringHash(name);
1162     pthread_mutex_lock(&handle->gate);
1164     /* Traverse the list to find duplicate check */
1165     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1166         if (node->hash == hash) {
1167             if (node->collide == TRUE) {
1168                 temp = node;
1169                 while (temp) {
1170                     if (strcmp(temp->name, name) == 0u){
1171                         if (length <= node->len) {
1172                             memcpy(value, node->value, length);
1173                             *len = length;
1174                         }
1175                         else {
1176                             memcpy(value, node->value, node->len);
1177                             *len = node->len;
1178                         }
1179                         done = TRUE;
1180                         break;
1181                     }
1182                     temp = temp->next;
1183                 }
1184                 break;
1185             }
1186             else {
1187                 if (length <= node->len) {
1188                     memcpy(value, node->value, length);
1189                     *len = length;
1190                 }
1191                 else {
1192                     memcpy(value, node->value, node->len);
1193                     *len = node->len;
1194                 }
1195                 done = TRUE;
1196                 break;
1197             }
1198         }
1199     }
1201     pthread_mutex_unlock(&handle->gate);
1203     if (done == FALSE) {
1204         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1205     }
1206     else {
1207         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1208              node->name, (UInt32)node->value)
1209         status = NameServer_S_SUCCESS;
1210     }
1212     return (status);
1215 /*
1216  *  Gets a 32-bit value by name from the local table
1217  *
1218  *  If the name is found, the 32-bit value is copied into the value
1219  *  argument and a success status is returned.
1220  *
1221  *  If the name is not found, zero is returned in len and the contents
1222  *  of value are not modified. Not finding a name is not considered
1223  *  an error.
1224  *
1225  *  This function only searches the local name/value table.
1226  *
1227  */
1228 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1230     Int                 status;
1231     UInt32              len    = sizeof(UInt32);
1233     assert(handle != NULL);
1234     assert(name   != NULL);
1235     assert(value  != NULL);
1236     assert(NameServer_module->refCount != 0);
1238     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1239     status = NameServer_getLocal(handle, name, value, &len);
1241     return (status);
1245 #if defined (__cplusplus)
1247 #endif /* defined (__cplusplus) */