]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - linux/src/daemon/NameServer_daemon.c
Implement reference counting in NameServer_create/delete (SDOCM00103730)
[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 // only _NP (non-portable) type available in CG tools which we're using
172     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
173 //    .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
174     .refCount                        = 0
175 };
177 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
179 static const UInt32 stringCrcTab[256u] = {
180   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
181   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
182   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
183   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
184   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
185   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
186   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
187   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
188   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
189   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
190   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
191   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
192   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
193   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
194   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
195   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
196   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
197   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
198   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
199   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
200   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
201   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
202   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
203   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
204   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
205   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
206   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
207   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
208   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
209   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
210   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
211   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
212   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
213   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
214   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
215   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
216   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
217   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
218   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
219   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
220   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
221   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
222   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
223 };
225 static UInt32 stringHash(String s)
227     UInt32 hash = strlen(s);
228     UInt32 i;
230     for (i = 0; i < strlen(s); i++) {
231         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
232     }
234     return (hash);
237 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
239     NameServer_Handle handle;
240     Int               status = NameServer_E_FAIL;
241     int               err;
242     uint64_t          buf = 1;
243     int               numBytes;
244     int               waitFd = NameServer_module->waitFd;
246     if (msg->request == NAMESERVER_REQUEST) {
247         LOG2("NameServer Request: instanceName: %s, name: %s\n",
248              (String)msg->instanceName, (String)msg->name)
250         /*
251          *  Message is a request. Lookup name in NameServer table.
252          *  Send a response message back to source processor.
253          */
254         handle = NameServer_getHandle((String)msg->instanceName);
256         if (handle != NULL) {
257             /* Search for the NameServer entry */
258             LOG0("Calling NameServer_getLocalUInt32...\n")
259             status = NameServer_getLocalUInt32(handle,
260                      (String)msg->name, &msg->value);
261         }
263         LOG2("NameServer Response: instanceName: %s, name: %s,",
264              (String)msg->instanceName, (String)msg->name)
265         /* set the request status */
266         if (status < 0) {
267             LOG1(" Value not found, status: %d\n", status)
268             msg->requestStatus = 0;
269         }
270         else {
271             msg->requestStatus = 1;
272             LOG1(" Value: 0x%x\n", msg->value)
273         }
275         /* specify message as a response */
276         msg->request = NAMESERVER_RESPONSE;
277         msg->reserved = NAMESERVER_MSG_TOKEN;
279         /* send response message to remote processor */
280         err = send(NameServer_module->sendSock[procId], msg,
281                    sizeof(NameServerMsg), 0);
282         if (err < 0) {
283             LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
284         }
285     }
286     else {
287         LOG2("NameServer Reply: instanceName: %s, name: %s",
288              (String)msg->instanceName, (String)msg->name)
289         LOG1(", value: 0x%x\n", msg->value)
291         /* Save the response message.  */
292         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
294         /* Post the eventfd upon which NameServer_get() is waiting */
295         numBytes = write(waitFd, &buf, sizeof(uint64_t));
296     }
300 static void *listener_cb(void *arg)
302     fd_set rfds;
303     int ret = 0, maxfd;
304     UInt16 procId;
305     struct  sockaddr_rpmsg  fromAddr;
306     unsigned int len;
307     NameServerMsg msg;
308     int     byteCount;
309     UInt16  numProcs = MultiProc_getNumProcessors();
310     int     sock;
312     LOG0("listener_cb: Entered Listener thread.\n")
314     do {
315         /* Wait for NameServer messages or unblockFd notification */
316         FD_ZERO(&rfds);
317         FD_SET(NameServer_module->unblockFd, &rfds);
318         maxfd = NameServer_module->unblockFd;
319         for (procId = 0; procId < numProcs; procId++) {
320             if (procId == MultiProc_self() ||
321                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
322                 continue;
323             }
324             sock = NameServer_module->recvSock[procId];
325             FD_SET(sock, &rfds);
326             maxfd = MAX(sock, maxfd);
327         }
329         maxfd = maxfd + 1;
330         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
331              NameServer_module->unblockFd, maxfd)
332         ret = select(maxfd, &rfds, NULL, NULL, NULL);
333         if (ret == -1) {
334             LOG0("listener_cb: select failed.")
335             break;
336         }
337         LOG0("NameServer: back from select()\n")
339         for (procId = 0; procId < numProcs; procId++) {
340             if (procId == MultiProc_self() ||
341                 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
342                 continue;
343             }
344             sock = NameServer_module->recvSock[procId];
345             if (FD_ISSET(sock, &rfds)) {
346                 LOG1("NameServer: Listener got NameServer message "
347                      "from sock: %d!\n", sock);
348                 /* Get NameServer message and process: */
349                 memset(&fromAddr, 0, sizeof(fromAddr));
350                 len = sizeof(fromAddr);
352                 byteCount = recvfrom(sock, &msg, sizeof(NameServerMsg), 0,
353                                 (struct sockaddr *)&fromAddr, &len);
354                 if (len != sizeof(fromAddr)) {
355                     LOG1("recvfrom: got bad addr len (%d)\n", len)
356                     break;
357                 }
358                 if (byteCount < 0) {
359                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
360                     break;
361                 }
362                 else {
363                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
364                     LOG2("\tReceived ns msg: byteCount: %d, from addr: %d, ",
365                          byteCount, fromAddr.addr)
366                     LOG1("from vproc: %d\n", fromAddr.vproc_id)
367                     NameServerRemote_processMessage(&msg, procId);
368                 }
369             }
370         }
371         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
372             /* We are told to unblock and exit: */
373             LOG0("NameServer: Listener thread exiting\n")
374             break;
375         }
376     } while (1);
378     return ((void *)ret);
381 /* =============================================================================
382  * APIS
383  * =============================================================================
384  */
386 /* Function to setup the nameserver module. */
387 Int NameServer_setup(Void)
389     Int    status = NameServer_S_SUCCESS;
390     int    err;
391     int    sock;
392     int    ret;
393     UInt16 procId;
394     UInt16 numProcs;
396     pthread_mutex_lock(&NameServer_module->modGate);
398     LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
400     NameServer_module->refCount++;
402     if (NameServer_module->refCount > 1) {
403         LOG0("NameServer_setup: already setup\n")
404         status = NameServer_S_ALREADYSETUP;
405         goto exit;
406     }
408     numProcs = MultiProc_getNumProcessors();
410     NameServer_module->unblockFd = eventfd(0, 0);
411     if (NameServer_module->unblockFd < 0) {
412         status = NameServer_E_FAIL;
413         LOG0("NameServer_setup: failed to create unblockFd.\n")
414         goto exit;
415     }
417     NameServer_module->waitFd = eventfd(0, 0);
418     if (NameServer_module->waitFd < 0) {
419         status = NameServer_E_FAIL;
420         LOG0("NameServer_setup: failed to create waitFd.\n")
421         goto exit;
422     }
424     for (procId = 0; procId < numProcs; procId++) {
425         NameServer_module->sendSock[procId] = INVALIDSOCKET;
426         NameServer_module->recvSock[procId] = INVALIDSOCKET;
428         /* Only support NameServer to remote procs: */
429         if (procId == MultiProc_self()) {
430             continue;
431         }
433         /* Create the socket for sending messages to each remote proc: */
434         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
435         if (sock < 0) {
436             status = NameServer_E_FAIL;
437             LOG2("NameServer_setup: socket failed: %d, %s\n",
438                  errno, strerror(errno))
439         }
440         else  {
441             LOG1("NameServer_setup: created send socket: %d\n", sock)
442             err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
443             if (err < 0) {
444                 status = NameServer_E_FAIL;
445                 LOG2("NameServer_setup: connect failed: %d, %s\n",
446                      errno, strerror(errno))
448                 LOG1("    closing send socket: %d\n", sock)
449                 close(sock);
450             }
451             else {
452                 NameServer_module->sendSock[procId] = sock;
453             }
454         }
456         /* Create the socket for recving messages from each remote proc: */
457         sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
458         if (sock < 0) {
459             status = NameServer_E_FAIL;
460             LOG2("NameServer_setup: socket failed: %d, %s\n",
461                  errno, strerror(errno))
462         }
463         else  {
464             LOG1("NameServer_setup: created recv socket: %d\n", sock)
466             err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
467             if (err < 0) {
468                 status = NameServer_E_FAIL;
469                 LOG2("NameServer_setup: bind failed: %d, %s\n",
470                     errno, strerror(errno))
472                 LOG1("    closing recv socket: %d\n", sock)
473                 close(sock);
474             }
475             else {
476                 NameServer_module->recvSock[procId] = sock;
477             }
478         }
479     }
481     /* Construct the list object */
482     CIRCLEQ_INIT(&NameServer_module->objList);
484     /* Create the listener thread: */
485     LOG0("NameServer_setup: creating listener thread\n")
486     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
487     if (ret) {
488         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
489         LOG0("NameServer_setup: eventfd failed");
491         status = NameServer_E_FAIL;
492     }
493     else {
494         /* look for at least one good send/recv pair to indicate success */
495         for (procId = 0; procId < numProcs; procId++) {
496             if (NameServer_module->sendSock[procId] != INVALIDSOCKET &&
497                 NameServer_module->recvSock[procId] != INVALIDSOCKET) {
498                 status = NameServer_S_SUCCESS;
500                 break;
501             }
502         }
503     }
505 exit:
506     LOG1("NameServer_setup: exiting, refCount=%d\n", NameServer_module->refCount)
508     pthread_mutex_unlock(&NameServer_module->modGate);
510     return (status);
513 /*! Function to destroy the nameserver module. */
514 Int NameServer_destroy(void)
516     Int      status    = NameServer_S_SUCCESS;
517     UInt16   numProcs = MultiProc_getNumProcessors();
518     UInt16   procId;
519     int      sock;
520     uint64_t buf = 1;
521     int      numBytes;
523     pthread_mutex_lock(&NameServer_module->modGate);
525     LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
527     NameServer_module->refCount--;
529     if (NameServer_module->refCount > 0) {
530         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
531         status = NameServer_S_SUCCESS;
533         goto exit;
534     }
536     for (procId = 0; procId < numProcs; procId++) {
537         /* Only support NameServer to remote procs: */
538         if (procId == MultiProc_self()) {
539             continue;
540         }
542         /* Close the socket: */
543         sock = NameServer_module->sendSock[procId];
544         if (sock != INVALIDSOCKET) {
545             LOG1("NameServer_destroy: closing socket: %d\n", sock)
546             close(sock);
547             NameServer_module->sendSock[procId] = INVALIDSOCKET;
548         }
549         /* Close the socket: */
550         sock = NameServer_module->recvSock[procId];
551         if (sock != INVALIDSOCKET) {
552             LOG1("NameServer_destroy: closing socket: %d\n", sock)
553             close(sock);
554             NameServer_module->recvSock[procId] = INVALIDSOCKET;
555         }
556     }
558     CIRCLEQ_destruct(&NameServer_module->objList);
560     /* Unblock the NameServer listener thread: */
561     LOG0("NameServer_destroy: unblocking listener...\n")
562     numBytes = write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
564     /* Join: */
565     LOG0("NameServer_destroy: joining listener thread...\n")
566     pthread_join(NameServer_module->listener, NULL);
568     close(NameServer_module->unblockFd);
569     close(NameServer_module->waitFd);
571 exit:
572     LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
574     pthread_mutex_unlock(&NameServer_module->modGate);
576     return (status);
579 /* Function to retrieve a NameServer handle from name. */
580 NameServer_Handle NameServer_getHandle(String name)
582     NameServer_Handle handle = NULL;
583     Bool              found = FALSE;
584     struct NameServer_Object * elem;
586     assert(name != NULL);
587     assert(NameServer_module->refCount != 0);
589     pthread_mutex_lock(&NameServer_module->modGate);
591     /* Lookup handle from name: */
592     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
593         handle = (NameServer_Handle) elem;
594         if (strcmp(handle->name, name) == 0) {
595             found = TRUE;
596             break;
597         }
598     }
600     if (found == FALSE) {
601         handle = NULL;
602     }
604     pthread_mutex_unlock(&NameServer_module->modGate);
606     return (handle);
610 /* Function to create a name server. */
611 NameServer_Handle NameServer_create(String name,
612                                     const NameServer_Params * params)
614     NameServer_Handle handle = NULL;
615     pthread_mutexattr_t mutex_attr;
617     assert(params != NULL);
618     assert(name != NULL);
619     assert(NameServer_module->refCount != 0);
621     LOG1("NameServer_create(): '%s'\n", name)
623     pthread_mutex_lock(&NameServer_module->modGate);
625     if (params->maxValueLen > sizeof(UInt32)) {
626         LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
627        /* Can't handle more than UInt32 at this time: */
628        goto leave;
629     }
631     /* check if the name is already created or not */
632     handle = NameServer_getHandle(name);
633     if (handle != NULL) {
634         if (memcmp((Ptr)&handle->params, (Ptr)params,
635             sizeof(NameServer_Params)) == 0) {
636             handle->refCount++;
637         }
638         else {
639             LOG0("NameServer_create: NameServer params mismatch\n")
640             handle = NULL;
641         }
642         goto leave;
643     }
644     else {
645         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
646     }
648     if (!handle) {
649         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
650         goto leave;
651     }
653     handle->refCount = 1;
654     handle->name = (String)malloc(strlen(name) + 1u);
655     if (!handle->name) {
656         LOG0("NameServer_create: instance name alloc failed\n")
657         goto cleanup;
658     }
659     strncpy(handle->name, name, strlen (name) + 1u);
660     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
662     if (params->maxValueLen < sizeof(UInt32)) {
663         handle->params.maxValueLen = sizeof(UInt32);
664     }
665     else {
666         handle->params.maxValueLen = params->maxValueLen;
667     }
669     CIRCLEQ_INIT(&handle->nameList);
670     handle->count = 0u;
672     /* Put in the local list */
673     CIRCLEQ_elemClear(&handle->elem);
674     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
676     /*
677      * NameServer_removeEntry() enters gate and is called by
678      * NameServer_remove() while holding the gate.
679      */
680     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
681     pthread_mutex_init(&handle->gate, &mutex_attr);
683     goto leave;
685 cleanup:
686     free(handle);
687     handle = NULL;
689 leave:
690     pthread_mutex_unlock(&NameServer_module->modGate);
692     return (handle);
696 /* Function to delete a name server. */
697 Int NameServer_delete(NameServer_Handle * handle)
699     Int status = NameServer_S_SUCCESS;
701     assert(handle != NULL);
702     assert(*handle != NULL);
703     assert((*handle)->count == 0);
704     assert(NameServer_module->refCount != 0);
706     pthread_mutex_lock(&NameServer_module->modGate);
708     (*handle)->refCount--;
709     if ((*handle)->refCount != 0) {
710         goto leave;
711     }
713     if ((*handle)->count == 0) {
714         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
716         if ((*handle)->name != NULL) {
717             free((*handle)->name);
718             (*handle)->name = NULL;
719         }
721         CIRCLEQ_destruct(&(*handle)->nameList);
723         free((*handle));
724         (*handle) = NULL;
725     }
727 leave:
728     pthread_mutex_unlock(&NameServer_module->modGate);
730     return (status);
733 /* Adds a variable length value into the local NameServer table */
734 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
736     Int                 status = NameServer_S_SUCCESS;
737     NameServer_TableEntry * node = NULL;
738     NameServer_TableEntry * new_node = NULL;
739     Bool                found = FALSE;
740     UInt32              hash;
742     assert(handle != NULL);
743     assert(name     != NULL);
744     assert(buf      != NULL);
745     assert(len      != 0);
746     assert(NameServer_module->refCount != 0);
748     /* Calculate the hash */
749     hash = stringHash(name);
751     pthread_mutex_lock(&handle->gate);
753     /* Traverse the list to find duplicate check */
754     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
755         /* Hash matches */
756         if (node->hash == hash) {
757             /* If the name matches, incase hash is duplicate */
758             if (strcmp(node->name, name) == 0) {
759                 if (handle->params.checkExisting == TRUE) {
760                     status = NameServer_E_INVALIDARG;
761                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
762                     break;
763                 }
764             }
765             else {
766                 found = TRUE;
767                 break;
768             } /* name does not match */
769         } /* hash does not match */
770     } /* CIRCLEQ_traverse */
772     if (status != NameServer_S_SUCCESS) {
773         new_node = NULL;
774         goto exit;
775     }
777     /* Now add the new entry. */
778     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
779     if (new_node == NULL) {
780         status = NameServer_E_MEMORY;
781         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
783         goto exit;
784     }
786     new_node->hash    = hash;
787     new_node->collide = found; /* Indicate if there is a collision*/
788     new_node->len     = len;
789     new_node->next    = NULL;
790     new_node->name = (String)malloc(strlen(name) + 1u);
791     new_node->value  = (Ptr)malloc(len);
792     strncpy(new_node->name, name, strlen(name) + 1u);
793     memcpy((Ptr)new_node->value, (Ptr)buf, len);
795     if (found == TRUE) {
796         /* If hash is found, need to stitch the list to link the
797          * new node to the existing node with the same hash.
798          */
799         new_node->next = node->next;
800         node->next = new_node;
801     }
802     else {
803         /* put the new node into the list */
804         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
805     }
807     handle->count++;
809     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
810          name, *(UInt32 *)buf)
812 exit:
813     pthread_mutex_unlock(&handle->gate);
815     return (new_node);
819 /* Function to add a UInt32 value into a name server. */
820 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
822     Ptr entry = NULL;
824     assert(handle != NULL);
825     assert(name   != NULL);
826     assert(NameServer_module->refCount != 0);
828     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
830     return (entry);
833 /* Function to remove a name/value pair from a name server. */
834 Int NameServer_remove(NameServer_Handle handle, String name)
836     Int                 status = NameServer_S_SUCCESS;
837     NameServer_TableEntry *prev = NULL;
838     NameServer_TableEntry *temp = NULL;
839     NameServer_TableEntry *node = NULL;
840     Bool                done   = FALSE;
841     UInt32              hash;
843     assert(handle != NULL);
844     assert(name   != NULL);
845     assert(NameServer_module->refCount != 0);
847     /* Calculate the hash */
848     hash = stringHash(name);
850     pthread_mutex_lock(&handle->gate);
852     /* Traverse the list to find duplicate check */
853     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
854         /* Hash matchs */
855         if (node->hash == hash) {
856             if (node->collide == TRUE) {
857                 if (strcmp(node->name, name) == 0){
858                     free(node->value);
859                     free(node->name);
860                     memcpy((Ptr)node, (Ptr) node->next,
861                            sizeof(NameServer_TableEntry));
862                     node->next = node->next->next;
863                     free(node->next);
864                     handle->count--;
865                     done = TRUE;
866                     break;
867                 }
868                 else {
869                     prev = node;
870                     temp = node->next;
871                     while (temp) {
872                         if (strcmp(temp->name, name) == 0){
873                             free(temp->value);
874                             free(temp->name);
875                             prev->next = temp->next;
876                             free(temp);
877                             handle->count--;
878                             done = TRUE;
879                             break;
880                         }
881                         temp = temp->next;
882                     }
883                     break;
884                 }
885             }
886             else {
887                 NameServer_removeEntry(handle, (Ptr)node);
889                 done = TRUE;
890                 break;
891             }
892         }
893     }
895     if (done == FALSE) {
896         status = NameServer_E_INVALIDARG;
897         LOG1("NameServer_remove %d Entry not found!\n", status)
898     }
900     pthread_mutex_unlock(&handle->gate);
902     return (status);
905 /* Function to remove a name/value pair from a name server. */
906 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
908     Int  status = NameServer_S_SUCCESS;
909     NameServer_TableEntry * node;
911     assert(handle != NULL);
912     assert(entry  != NULL);
913     assert(NameServer_module->refCount != 0);
915     pthread_mutex_lock(&handle->gate);
917     node = (NameServer_TableEntry *)entry;
919     free(node->value);
920     free(node->name);
921     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
922     free(node);
923     handle->count--;
925     pthread_mutex_unlock(&handle->gate);
927     return (status);
931 /* Initialize this config-params structure with supplier-specified
932  * defaults before instance creation.
933  */
934 Void NameServer_Params_init(NameServer_Params * params)
936     assert(params != NULL);
938     memcpy(params, &(NameServer_module->defInstParams),
939            sizeof (NameServer_Params));
943 Int NameServer_getRemote(NameServer_Handle handle,
944                      String            name,
945                      Ptr               value,
946                      UInt32 *          len,
947                      UInt16            procId)
949     Int status = NameServer_S_SUCCESS;
950     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
951     NameServerMsg nsMsg;
952     NameServerMsg *replyMsg;
953     fd_set rfds;
954     int ret = 0, sock, maxfd, waitFd;
955     struct timeval tv;
956     uint64_t buf = 1;
957     int numBytes;
958     int err;
960     /* Set Timeout to wait: */
961     tv.tv_sec = 0;
962     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
964     /* Create request message and send to remote: */
965     sock = NameServer_module->sendSock[procId];
966     if (sock == INVALIDSOCKET) {
967         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
968              procId);
969         status = NameServer_E_RESOURCE;
970         goto exit;
971     }
973     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
975     /* Create request message and send to remote processor: */
976     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
977     nsMsg.request = NAMESERVER_REQUEST;
978     nsMsg.requestStatus = 0;
979     nsMsg.valueLen = *len;
981     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
982     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
984     LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
985            procId, (String)nsMsg.instanceName)
986     LOG1("%s...\n", (String)nsMsg.name)
988     err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
989     if (err < 0) {
990         LOG2("NameServer_getRemote: send failed: %d, %s\n",
991              errno, strerror(errno))
992         status = NameServer_E_FAIL;
993         goto exit;
994     }
996     /* Block on waitFd for signal from listener thread: */
997     waitFd = NameServer_module->waitFd;
998     FD_ZERO(&rfds);
999     FD_SET(waitFd, &rfds);
1000     maxfd = waitFd + 1;
1001     LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1002     ret = select(maxfd, &rfds, NULL, NULL, &tv);
1003     if (ret == -1) {
1004         LOG0("NameServer_getRemote: select failed.")
1005         status = NameServer_E_FAIL;
1006         goto exit;
1007     }
1008     else if (!ret) {
1009         LOG0("NameServer_getRemote: select timed out.\n")
1010         status = NameServer_E_TIMEOUT;
1011         goto exit;
1012     }
1014     if (FD_ISSET(waitFd, &rfds)) {
1015         /* Read, just to balance the write: */
1016         numBytes = read(waitFd, &buf, sizeof(uint64_t));
1018         /* Process response: */
1019         replyMsg = &NameServer_module->nsMsg;
1021         if (replyMsg->requestStatus) {
1022             /* name is found */
1023             /* set the contents of value */
1024             *(UInt32 *)value = (UInt32)replyMsg->value;
1026             LOG2("NameServer_getRemote: Reply from: %d, %s:",
1027                  procId, (String)replyMsg->instanceName)
1028             LOG2("%s, value: 0x%x...\n",
1029                  (String)replyMsg->name, *(UInt32 *)value)
1030             goto exit;
1031         }
1032         else {
1033             /* name is not found */
1034             LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1035                  (String)replyMsg->instanceName, (String)replyMsg->name)
1037             /* set status to not found */
1038             status = NameServer_E_NOTFOUND;
1039         }
1040     }
1042 exit:
1043     return (status);
1046 /* Function to retrieve the value portion of a name/value pair from
1047  * local table.
1048  */
1049 Int NameServer_get(NameServer_Handle handle,
1050                String            name,
1051                Ptr               value,
1052                UInt32 *          len,
1053                UInt16            procId[])
1055     Int status = NameServer_S_SUCCESS;
1056     UInt16 numProcs = MultiProc_getNumProcessors();
1057     UInt32 i;
1059     /*
1060      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1061      * since this goes in a daemon, it will not be necessary.
1062      */
1064     if (procId == NULL) {
1065         status = NameServer_getLocal(handle, name, value, len);
1066         if (status == NameServer_E_NOTFOUND) {
1067             for (i = 0; i < numProcs; i++) {
1068                 /* getLocal call already covers "self", keep going */
1069                 if (i == MultiProc_self()) {
1070                     continue;
1071                 }
1073                 status = NameServer_getRemote(handle, name, value, len, i);
1075                 if ((status >= 0) ||
1076                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1077                                      (status != NameServer_E_RESOURCE))) {
1078                     break;
1079                 }
1080             }
1081         }
1082     }
1083     else {
1084         /*
1085          *  Search the query list. It might contain the local proc
1086          *  somewhere in the list.
1087          */
1088         i = 0;
1089         while (procId[i] != MultiProc_INVALIDID) {
1090             if (procId[i] == MultiProc_self()) {
1091                 status = NameServer_getLocal(handle, name, value, len);
1092             }
1093             else {
1094                 status = NameServer_getRemote(handle, name, value, len, i);
1095             }
1097             if ((status >= 0) ||
1098                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1099                                  (status != NameServer_E_RESOURCE))) {
1100                 break;
1101             }
1103             i++;
1104         }
1105     }
1107     if (status == NameServer_E_RESOURCE) {
1108         status = NameServer_E_NOTFOUND;
1109     }
1111     return (status);
1114 /* Gets a 32-bit value by name */
1115 Int NameServer_getUInt32(NameServer_Handle handle,
1116                      String            name,
1117                      Ptr               value,
1118                      UInt16            procId[])
1120     Int  status;
1121     UInt32 len = sizeof(UInt32);
1123     assert(handle != NULL);
1124     assert(name   != NULL);
1125     assert(value  != NULL);
1126     assert(NameServer_module->refCount != 0);
1128     status = NameServer_get(handle, name, value, &len, procId);
1130     return (status);
1133 /* Function to Retrieve the value portion of a name/value pair from
1134  * local table.
1135  */
1136 Int NameServer_getLocal(NameServer_Handle handle,
1137                     String            name,
1138                     Ptr               value,
1139                     UInt32 *          len)
1141     Int status = NameServer_E_NOTFOUND;
1142     NameServer_TableEntry * node = NULL;
1143     NameServer_TableEntry * temp = NULL;
1144     Bool done   = FALSE;
1145     UInt32 length;
1146     UInt32 hash;
1148     assert(handle != NULL);
1149     assert(name   != NULL);
1150     assert(value  != NULL);
1151     assert(len    != NULL);
1152     assert(NameServer_module->refCount != 0);
1154     length = *len;
1156     /* Calculate the hash */
1157     hash = stringHash(name);
1159     pthread_mutex_lock(&handle->gate);
1161     /* Traverse the list to find duplicate check */
1162     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1163         if (node->hash == hash) {
1164             if (node->collide == TRUE) {
1165                 temp = node;
1166                 while (temp) {
1167                     if (strcmp(temp->name, name) == 0u){
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                     temp = temp->next;
1180                 }
1181                 break;
1182             }
1183             else {
1184                 if (length <= node->len) {
1185                     memcpy(value, node->value, length);
1186                     *len = length;
1187                 }
1188                 else {
1189                     memcpy(value, node->value, node->len);
1190                     *len = node->len;
1191                 }
1192                 done = TRUE;
1193                 break;
1194             }
1195         }
1196     }
1198     pthread_mutex_unlock(&handle->gate);
1200     if (done == FALSE) {
1201         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1202     }
1203     else {
1204         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1205              node->name, (UInt32)node->value)
1206         status = NameServer_S_SUCCESS;
1207     }
1209     return (status);
1212 /*
1213  *  Gets a 32-bit value by name from the local table
1214  *
1215  *  If the name is found, the 32-bit value is copied into the value
1216  *  argument and a success status is returned.
1217  *
1218  *  If the name is not found, zero is returned in len and the contents
1219  *  of value are not modified. Not finding a name is not considered
1220  *  an error.
1221  *
1222  *  This function only searches the local name/value table.
1223  *
1224  */
1225 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1227     Int                 status;
1228     UInt32              len    = sizeof(UInt32);
1230     assert(handle != NULL);
1231     assert(name   != NULL);
1232     assert(value  != NULL);
1233     assert(NameServer_module->refCount != 0);
1235     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1236     status = NameServer_getLocal(handle, name, value, &len);
1238     return (status);
1242 #if defined (__cplusplus)
1244 #endif /* defined (__cplusplus) */