Ignore cluster members which are not running
[ipc/ipcdev.git] / linux / src / daemon / NameServer_daemon.c
1 /*
2  * Copyright (c) 2012-2015 Texas Instruments Incorporated - http://www.ti.com
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*!
33  *  @file       NameServer.c
34  *
35  *  @brief      NameServer Manager
36  */
38 /* Standard IPC headers */
39 #include <ti/ipc/Std.h>
41 /* POSIX thread support */
42 #include <pthread.h>
44 /* Socket Headers */
45 #include <sys/queue.h>
46 #include <sys/select.h>
47 #include <sys/time.h>
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/eventfd.h>
51 #include <sys/socket.h>
52 #include <errno.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <assert.h>
59 /* Socket Protocol Family */
60 #include <net/rpmsg.h>
62 /* Module level headers */
63 #include <ti/ipc/NameServer.h>
64 #include <ti/ipc/MultiProc.h>
65 #include <_MultiProc.h>
67 /* Internal stuff: */
68 #include <_NameServer.h>
69 #include <ti/ipc/namesrv/_NameServerRemoteRpmsg.h>
71 /* Socket utils: */
72 #include <SocketFxns.h>
74 #include <_lad.h>
76 #define MESSAGEQ_RPMSG_PORT       61
77 #define NAME_SERVER_RPMSG_ADDR    0
79 #define INVALIDSOCKET     (-1)
81 #define NameServer_Event_ACK            (1 << 0)
82 #define NameServer_Event_REFRESH        (1 << 1)
83 #define NameServer_Event_SHUTDOWN       (1 << 2)
85 #if defined (__cplusplus)
86 extern "C" {
87 #endif
90 /* =============================================================================
91  * Structures & Enums
92  * =============================================================================
93  */
95 /* Structure of entry in Name/Value table */
96 typedef struct NameServer_TableEntry_tag {
97     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
98     /* List element */
99     UInt32                    hash;
100     /* Hash value */
101     String                    name;
102     /* Name portion of the name/value pair. */
103     UInt                      len;
104     /* Length of the value field. */
105     Ptr                       value;
106     /* Value portion of the name/value entry. */
107     Bool                      collide;
108     /* Does the hash collide? */
109     struct NameServer_TableEntry_tag * next;
110     /* Pointer to the next entry, used incase of collision only */
111 } NameServer_TableEntry;
113 /* Structure defining object for the NameServer */
114 struct NameServer_Object {
115     CIRCLEQ_ENTRY(NameServer_Object) elem;
116     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
117     String             name;            /* name of the instance */
118     NameServer_Params  params;          /* the parameter structure */
119     UInt32             count;           /* count of entries */
120     UInt32             refCount;        /* reference count to this object */
121     pthread_mutex_t    gate;            /* crit sect gate */
122 } NameServer_Object;
124 /* structure for NameServer module state */
125 typedef struct NameServer_ModuleObject {
126     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
127     Int32                refCount;
128     struct {
129         Int refCount;           /* attached reference count */
130         int sendSock;           /* socket for sending */
131         int recvSock;           /* socket for receiving */
132     } comm[MultiProc_MAXPROCESSORS];
133     pthread_t            listener;
134     /* Listener thread for NameServer replies and requests. */
135     int                  unblockFd;
136     /* Event to wake up listener thread. */
137     int                  waitFd;
138     /* Event to post to NameServer_get. */
139     NameServerRemote_Msg nsMsg;
140     /* NameServer Message cache. */
141     NameServer_Params    defInstParams;
142     /* Default instance paramters */
143     pthread_mutex_t      modGate;
144 } NameServer_ModuleObject;
146 #define CIRCLEQ_destruct(head) { \
147         (head)->cqh_first = NULL; \
148         (head)->cqh_last = NULL; \
151 #define CIRCLEQ_elemClear(elem) { \
152         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
155 #define CIRCLEQ_traverse(x, y, tag) \
156         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
158 /* =============================================================================
159  *  Globals
160  * =============================================================================
161  */
162 /*
163  * NameServer_state
164  *
165  * Make the module gate "recursive" since NameServer_getHandle() needs to
166  * use it and NameServer_create() needs to hold it around its call to
167  * NameServer_getHandle().  Also, use the static initializer instead of a
168  * run-time init call, so we can use this gate immediately in _setup().
169  */
170 static NameServer_ModuleObject NameServer_state = {
171     .defInstParams.maxRuntimeEntries = 0u,
172     .defInstParams.tableHeap         = NULL,
173     .defInstParams.checkExisting     = TRUE,
174     .defInstParams.maxValueLen       = 0u,
175     .defInstParams.maxNameLen        = 16u,
176 #if defined(IPC_BUILDOS_ANDROID)
177     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
178 #else
179 // only _NP (non-portable) type available in CG tools which we're using
180     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
181 #endif
182     .refCount                        = 0
183 };
185 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
187 static const UInt32 stringCrcTab[256u] = {
188   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
189   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
190   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
191   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
192   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
193   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
194   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
195   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
196   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
197   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
198   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
199   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
200   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
201   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
202   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
203   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
204   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
205   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
206   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
207   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
208   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
209   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
210   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
211   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
212   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
213   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
214   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
215   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
216   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
217   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
218   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
219   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
220   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
221   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
222   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
223   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
224   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
225   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
226   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
227   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
228   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
229   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
230   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
231 };
233 static UInt32 stringHash(String s)
235     UInt32 hash = strlen(s);
236     UInt32 i;
238     for (i = 0; i < strlen(s); i++) {
239         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
240     }
242     return (hash);
245 static void NameServerRemote_processMessage(NameServerRemote_Msg *msg,
246         UInt16 procId)
248     NameServer_Handle handle;
249     Int               status = NameServer_E_FAIL;
250     int               err;
251     uint64_t          buf = 1;
252     UInt16            clusterId;
254     if (msg->request == NAMESERVER_REQUEST) {
255         LOG2("NameServer Request: instanceName: %s, name: %s\n",
256              (String)msg->instanceName, (String)msg->name)
258         assert(msg->valueLen <= MAXVALUELEN);
259         /*
260          *  Message is a request. Lookup name in NameServer table.
261          *  Send a response message back to source processor.
262          */
263         handle = NameServer_getHandle((String)msg->instanceName);
265         if (handle != NULL) {
266             /* Search for the NameServer entry */
267             if (msg->valueLen <= sizeof (Bits32)) {
268                 LOG0("Calling NameServer_getLocalUInt32...\n")
269                 status = NameServer_getLocalUInt32(handle,
270                      (String)msg->name, &msg->value);
271             }
272             else {
273                 LOG0("Calling NameServer_getLocal...\n")
274                 status = NameServer_getLocal(handle,
275                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
276             }
277         }
279         LOG2("NameServer Response: instanceName: %s, name: %s,",
280              (String)msg->instanceName, (String)msg->name)
281         /* set the request status */
282         if (status < 0) {
283             LOG1(" Value not found, status: %d\n", status)
284             msg->requestStatus = 0;
285         }
286         else {
287             msg->requestStatus = 1;
288             LOG1(" Value: 0x%x\n", msg->value)
289         }
291         /* specify message as a response */
292         msg->request = NAMESERVER_RESPONSE;
293         msg->reserved = NAMESERVER_MSG_TOKEN;
295         /* send response message to remote processor */
296         clusterId = procId - MultiProc_getBaseIdOfCluster();
297         err = send(NameServer_module->comm[clusterId].sendSock, msg,
298                    sizeof(NameServerRemote_Msg), 0);
299         if (err < 0) {
300             LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
301         }
302     }
303     else {
304         LOG3("NameServer Reply: instanceName: %s, name: %s, value: 0x%x\n",
305                 (String)msg->instanceName, (String)msg->name, msg->value);
307         /* Save the response message.  */
308         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerRemote_Msg));
310         /* Post the eventfd upon which NameServer_get() is waiting */
311         write(NameServer_module->waitFd, &buf, sizeof(uint64_t));
312     }
315 /*
316  *  ======== listener_cb ========
317  */
318 static void *listener_cb(void *arg)
320     fd_set rfds;
321     int ret = 0, maxfd;
322     int i;
323     UInt16 procId;
324     struct  sockaddr_rpmsg  fromAddr;
325     unsigned int len;
326     NameServerRemote_Msg msg;
327     int nbytes;
328     UInt16 numProcs = MultiProc_getNumProcsInCluster();
329     UInt16 baseId = MultiProc_getBaseIdOfCluster();
330     int sock;
331     uint64_t event;
332     Bool run = TRUE;
334     LOG0("listener_cb: Entered Listener thread.\n")
336     do {
337         /* Wait for NameServer messages or unblockFd notification */
338         FD_ZERO(&rfds);
339         FD_SET(NameServer_module->unblockFd, &rfds);
340         maxfd = NameServer_module->unblockFd;
342         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
343             if ((MultiProc_self() == procId)
344                 || (NameServer_module->comm[i].recvSock == INVALIDSOCKET)) {
345                 continue;
346             }
347             sock = NameServer_module->comm[i].recvSock;
348             FD_SET(sock, &rfds);
349             maxfd = sock > maxfd ? sock : maxfd;
350         }
352         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
353              NameServer_module->unblockFd, maxfd)
355         /* wait here until new data available */
356         ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
358         if (ret == -1) {
359             LOG0("listener_cb: select failed.")
360             break;
361         }
362         LOG0("NameServer: back from select()\n")
364         /* check all receive sockets for pending data */
365         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
366             if ((MultiProc_self() == procId)
367                 || (NameServer_module->comm[i].recvSock == INVALIDSOCKET)) {
368                 continue;
369             }
370             sock = NameServer_module->comm[i].recvSock;
372             if (FD_ISSET(sock, &rfds)) {
373                 LOG1("NameServer: Listener got NameServer message "
374                      "from sock: %d!\n", sock);
375                 /* Get NameServer message and process: */
376                 memset(&fromAddr, 0, sizeof(fromAddr));
377                 len = sizeof(fromAddr);
379                 nbytes = recvfrom(sock, &msg, sizeof(NameServerRemote_Msg), 0,
380                                 (struct sockaddr *)&fromAddr, &len);
381                 if (len != sizeof(fromAddr)) {
382                     LOG1("recvfrom: got bad addr len (%d)\n", len)
383                     break;
384                 }
385                 if (nbytes < 0) {
386                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
387                     break;
388                 }
389                 else {
390                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
391                     LOG2("\tReceived ns msg: nbytes: %d, from addr: %d, ",
392                          nbytes, fromAddr.addr)
393                     LOG1("from vproc: %d\n", fromAddr.vproc_id)
394                     NameServerRemote_processMessage(&msg, procId);
395                 }
396             }
397         }
399         /* check for events */
400         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
402             read(NameServer_module->unblockFd, &event, sizeof(event));
404             if (event & NameServer_Event_SHUTDOWN) {
405                 LOG0("NameServer: listener thread, event: SHUTDOWN\n")
406                 event &= ~NameServer_Event_SHUTDOWN;
407                 run = FALSE;
408             }
409             if (event & NameServer_Event_REFRESH) {
410                 LOG0("NameServer: listener thread, event: REFRESH\n")
411                 /* send ACK event */
412                 event = NameServer_Event_ACK;
413                 write(NameServer_module->waitFd, &event, sizeof(event));
414             }
415         }
417     } while (run);
419     return ((void *)ret);
422 /* =============================================================================
423  * APIS
424  * =============================================================================
425  */
427 /*
428  *  ======== NameServer_setup ========
429  *  Function to setup the name server module
430  */
431 Int NameServer_setup(Void)
433     Int    status = NameServer_S_SUCCESS;
434     int    ret;
435     Int    i;
437     pthread_mutex_lock(&NameServer_module->modGate);
439     LOG1("NameServer_setup: entered, refCount=%d\n",
440             NameServer_module->refCount)
442     NameServer_module->refCount++;
444     if (NameServer_module->refCount > 1) {
445         LOG0("NameServer_setup: already setup\n")
446         status = NameServer_S_ALREADYSETUP;
447         goto exit;
448     }
450     /* counter event object for passing commands to worker thread */
451     NameServer_module->unblockFd = eventfd(0, 0);
453     if (NameServer_module->unblockFd < 0) {
454         status = NameServer_E_FAIL;
455         LOG0("NameServer_setup: failed to create unblockFd.\n")
456         goto exit;
457     }
459     /* semaphore event object for acknowledging LAD command thread */
460     NameServer_module->waitFd = eventfd(0, EFD_SEMAPHORE);
462     if (NameServer_module->waitFd < 0) {
463         status = NameServer_E_FAIL;
464         LOG0("NameServer_setup: failed to create waitFd.\n")
465         goto exit;
466     }
468     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
469         NameServer_module->comm[i].refCount = 0;
470         NameServer_module->comm[i].sendSock = INVALIDSOCKET;
471         NameServer_module->comm[i].recvSock = INVALIDSOCKET;
472     }
474     /* Construct the list object */
475     CIRCLEQ_INIT(&NameServer_module->objList);
477     /* Create the listener thread: */
478     LOG0("NameServer_setup: creating listener thread\n")
479     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
480     if (ret) {
481         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
482         status = NameServer_E_FAIL;
483     }
485 exit:
486     LOG1("NameServer_setup: exiting, refCount=%d\n",
487             NameServer_module->refCount)
489     pthread_mutex_unlock(&NameServer_module->modGate);
491     return (status);
494 /*
495  *  ======== NameServer_destroy ========
496  *  Function to destroy the name server module
497  */
498 Int NameServer_destroy(void)
500     Int status = NameServer_S_SUCCESS;
501     uint64_t event;
503     pthread_mutex_lock(&NameServer_module->modGate);
505     LOG1("NameServer_destroy: entered, refCount=%d\n",
506             NameServer_module->refCount)
508     NameServer_module->refCount--;
510     if (NameServer_module->refCount > 0) {
511         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n",
512                 NameServer_module->refCount)
513         status = NameServer_S_SUCCESS;
514         goto exit;
515     }
517     CIRCLEQ_destruct(&NameServer_module->objList);
519     /* shutdown the NameServer listener thread */
520     LOG0("NameServer_destroy: shutdown listener...\n")
521     event = NameServer_Event_SHUTDOWN;
522     write(NameServer_module->unblockFd, &event, sizeof(event));
524     /* Join: */
525     LOG0("NameServer_destroy: joining listener thread...\n")
526     pthread_join(NameServer_module->listener, NULL);
528     close(NameServer_module->unblockFd);
529     close(NameServer_module->waitFd);
531 exit:
532     LOG1("NameServer_destroy: exiting, refCount=%d\n",
533             NameServer_module->refCount)
535     pthread_mutex_unlock(&NameServer_module->modGate);
537     return (status);
540 /* Function to retrieve a NameServer handle from name. */
541 NameServer_Handle NameServer_getHandle(String name)
543     NameServer_Handle handle = NULL;
544     Bool              found = FALSE;
545     struct NameServer_Object * elem;
547     assert(name != NULL);
548     assert(NameServer_module->refCount != 0);
550     pthread_mutex_lock(&NameServer_module->modGate);
552     /* Lookup handle from name: */
553     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
554         handle = (NameServer_Handle) elem;
555         if (strcmp(handle->name, name) == 0) {
556             found = TRUE;
557             break;
558         }
559     }
561     if (found == FALSE) {
562         handle = NULL;
563     }
565     pthread_mutex_unlock(&NameServer_module->modGate);
567     return (handle);
571 /* Function to create a name server. */
572 NameServer_Handle NameServer_create(String name,
573                                     const NameServer_Params * params)
575     NameServer_Handle handle = NULL;
576     pthread_mutexattr_t mutex_attr;
578     assert(params != NULL);
579     assert(name != NULL);
580     assert(NameServer_module->refCount != 0);
582     LOG1("NameServer_create(): '%s'\n", name)
584     pthread_mutex_lock(&NameServer_module->modGate);
586     /* check if the name is already created or not */
587     handle = NameServer_getHandle(name);
588     if (handle != NULL) {
589         if (memcmp((Ptr)&handle->params, (Ptr)params,
590             sizeof(NameServer_Params)) == 0) {
591             handle->refCount++;
592         }
593         else {
594             LOG0("NameServer_create: NameServer params mismatch\n")
595             handle = NULL;
596         }
597         goto leave;
598     }
599     else {
600         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
601     }
603     if (!handle) {
604         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
605         goto leave;
606     }
608     handle->refCount = 1;
609     handle->name = (String)malloc(strlen(name) + 1u);
610     if (!handle->name) {
611         LOG0("NameServer_create: instance name alloc failed\n")
612         goto cleanup;
613     }
614     strncpy(handle->name, name, strlen (name) + 1u);
615     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
617     if (params->maxValueLen < sizeof(UInt32)) {
618         handle->params.maxValueLen = sizeof(UInt32);
619     }
620     else {
621         handle->params.maxValueLen = params->maxValueLen;
622     }
624     CIRCLEQ_INIT(&handle->nameList);
625     handle->count = 0u;
627     /* Put in the local list */
628     CIRCLEQ_elemClear(&handle->elem);
629     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
631     /*
632      * NameServer_removeEntry() enters gate and is called by
633      * NameServer_remove() while holding the gate.
634      */
635     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
636     pthread_mutex_init(&handle->gate, &mutex_attr);
638     goto leave;
640 cleanup:
641     free(handle);
642     handle = NULL;
644 leave:
645     pthread_mutex_unlock(&NameServer_module->modGate);
647     return (handle);
651 /* Function to delete a name server. */
652 Int NameServer_delete(NameServer_Handle * handle)
654     Int status = NameServer_S_SUCCESS;
656     assert(handle != NULL);
657     assert(*handle != NULL);
658     assert((*handle)->count == 0);
659     assert(NameServer_module->refCount != 0);
661     pthread_mutex_lock(&NameServer_module->modGate);
663     (*handle)->refCount--;
664     if ((*handle)->refCount != 0) {
665         goto leave;
666     }
668     if ((*handle)->count == 0) {
669         CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
671         if ((*handle)->name != NULL) {
672             free((*handle)->name);
673             (*handle)->name = NULL;
674         }
676         CIRCLEQ_destruct(&(*handle)->nameList);
678         free((*handle));
679         (*handle) = NULL;
680     }
682 leave:
683     pthread_mutex_unlock(&NameServer_module->modGate);
685     return (status);
688 /* Adds a variable length value into the local NameServer table */
689 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
691     Int                 status = NameServer_S_SUCCESS;
692     NameServer_TableEntry * node = NULL;
693     NameServer_TableEntry * new_node = NULL;
694     Bool                found = FALSE;
695     UInt32              hash;
697     assert(handle != NULL);
698     assert(name     != NULL);
699     assert(buf      != NULL);
700     assert(len      != 0);
701     assert(NameServer_module->refCount != 0);
703     /* Calculate the hash */
704     hash = stringHash(name);
706     pthread_mutex_lock(&handle->gate);
708     if (strlen(name) > handle->params.maxNameLen - 1) {
709         status = NameServer_E_INVALIDARG;
710         LOG0("NameServer_add: name length exceeded maximum!\n")
711         new_node = NULL;
712         goto exit;
713     }
715     if (len > handle->params.maxValueLen) {
716         status = NameServer_E_INVALIDARG;
717         LOG0("NameServer_add: value length exceeded maximum!\n")
718         new_node = NULL;
719         goto exit;
720     }
722     /* Traverse the list to find duplicate check */
723     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
724         /* Hash matches */
725         if (node->hash == hash) {
726             /* If the name matches, incase hash is duplicate */
727             if (strcmp(node->name, name) == 0) {
728                 if (handle->params.checkExisting == TRUE) {
729                     status = NameServer_E_INVALIDARG;
730                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
731                     break;
732                 }
733             }
734             else {
735                 found = TRUE;
736                 break;
737             } /* name does not match */
738         } /* hash does not match */
739     } /* CIRCLEQ_traverse */
741     if (status != NameServer_S_SUCCESS) {
742         new_node = NULL;
743         goto exit;
744     }
746     /* Now add the new entry. */
747     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
748     if (new_node == NULL) {
749         status = NameServer_E_MEMORY;
750         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
752         goto exit;
753     }
755     new_node->hash    = hash;
756     new_node->collide = found; /* Indicate if there is a collision*/
757     new_node->len     = len;
758     new_node->next    = NULL;
759     new_node->name = (String)malloc(strlen(name) + 1u);
760     new_node->value  = (Ptr)malloc(len);
761     strncpy(new_node->name, name, strlen(name) + 1u);
762     memcpy((Ptr)new_node->value, (Ptr)buf, len);
764     if (found == TRUE) {
765         /* If hash is found, need to stitch the list to link the
766          * new node to the existing node with the same hash.
767          */
768         new_node->next = node->next;
769         node->next = new_node;
770     }
771     else {
772         /* put the new node into the list */
773         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
774     }
776     handle->count++;
778     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
779          name, *(UInt32 *)buf)
781 exit:
782     pthread_mutex_unlock(&handle->gate);
784     return (new_node);
788 /* Function to add a UInt32 value into a name server. */
789 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
791     Ptr entry = NULL;
793     assert(handle != NULL);
794     assert(name   != NULL);
795     assert(NameServer_module->refCount != 0);
797     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
799     return (entry);
802 /* Function to remove a name/value pair from a name server. */
803 Int NameServer_remove(NameServer_Handle handle, String name)
805     Int                 status = NameServer_S_SUCCESS;
806     NameServer_TableEntry *prev = NULL;
807     NameServer_TableEntry *temp = NULL;
808     NameServer_TableEntry *node = NULL;
809     Bool                done   = FALSE;
810     UInt32              hash;
812     assert(handle != NULL);
813     assert(name   != NULL);
814     assert(NameServer_module->refCount != 0);
816     /* Calculate the hash */
817     hash = stringHash(name);
819     pthread_mutex_lock(&handle->gate);
821     /* Traverse the list to find duplicate check */
822     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
823         /* Hash matchs */
824         if (node->hash == hash) {
825             if (node->collide == TRUE) {
826                 if (strcmp(node->name, name) == 0){
827                     free(node->value);
828                     free(node->name);
829                     memcpy((Ptr)node, (Ptr) node->next,
830                            sizeof(NameServer_TableEntry));
831                     node->next = node->next->next;
832                     free(node->next);
833                     handle->count--;
834                     done = TRUE;
835                     break;
836                 }
837                 else {
838                     prev = node;
839                     temp = node->next;
840                     while (temp) {
841                         if (strcmp(temp->name, name) == 0){
842                             free(temp->value);
843                             free(temp->name);
844                             prev->next = temp->next;
845                             free(temp);
846                             handle->count--;
847                             done = TRUE;
848                             break;
849                         }
850                         temp = temp->next;
851                     }
852                     break;
853                 }
854             }
855             else {
856                 NameServer_removeEntry(handle, (Ptr)node);
858                 done = TRUE;
859                 break;
860             }
861         }
862     }
864     if (done == FALSE) {
865         status = NameServer_E_INVALIDARG;
866         LOG1("NameServer_remove %d Entry not found!\n", status)
867     }
869     pthread_mutex_unlock(&handle->gate);
871     return (status);
874 /* Function to remove a name/value pair from a name server. */
875 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
877     Int  status = NameServer_S_SUCCESS;
878     NameServer_TableEntry * node;
880     assert(handle != NULL);
881     assert(entry  != NULL);
882     assert(NameServer_module->refCount != 0);
884     pthread_mutex_lock(&handle->gate);
886     node = (NameServer_TableEntry *)entry;
888     free(node->value);
889     free(node->name);
890     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
891     free(node);
892     handle->count--;
894     pthread_mutex_unlock(&handle->gate);
896     return (status);
900 /* Initialize this config-params structure with supplier-specified
901  * defaults before instance creation.
902  */
903 Void NameServer_Params_init(NameServer_Params * params)
905     assert(params != NULL);
907     memcpy(params, &(NameServer_module->defInstParams),
908            sizeof (NameServer_Params));
912 Int NameServer_getRemote(NameServer_Handle handle,
913                      String            name,
914                      Ptr               value,
915                      UInt32 *          len,
916                      UInt16            procId)
918     Int status = NameServer_S_SUCCESS;
919     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
920     NameServerRemote_Msg nsMsg;
921     NameServerRemote_Msg *replyMsg;
922     fd_set rfds;
923     int ret = 0, sock, maxfd, waitFd;
924     struct timeval tv;
925     uint64_t buf = 1;
926     int err;
927     int i;
928     static int seqNum = 0;
929     Bool done = FALSE;
930     UInt16 clusterId;
932     if (strlen(name) >= MAXNAMEINCHAR) {
933         LOG0("Name is too long in remote query\n");
934         return NameServer_E_NAMETOOLONG;
935     }
937     if (strlen(obj->name) >= MAXNAMEINCHAR) {
938         LOG0("Instance name is too long for remote query\n");
939         return NameServer_E_NAMETOOLONG;
940     }
942     /* Set Timeout to wait: */
943     tv.tv_sec = 0;
944     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
946     /* Create request message and send to remote: */
947     clusterId = procId - MultiProc_getBaseIdOfCluster();
948     sock = NameServer_module->comm[clusterId].sendSock;
949     if (sock == INVALIDSOCKET) {
950         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
951              procId);
952         status = NameServer_E_RESOURCE;
953         goto exit;
954     }
956     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
958     /* Create request message and send to remote processor: */
959     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
960     nsMsg.request = NAMESERVER_REQUEST;
961     nsMsg.requestStatus = 0;
962     nsMsg.valueLen = *len;
963     nsMsg.seqNum = seqNum++;
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(NameServerRemote_Msg), 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     while (!done) {
981         /* Block on waitFd for signal from listener thread: */
982         waitFd = NameServer_module->waitFd;
983         FD_ZERO(&rfds);
984         FD_SET(waitFd, &rfds);
985         maxfd = waitFd + 1;
986         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
988         ret = select(maxfd, &rfds, NULL, NULL, &tv);
990         if (ret == -1) {
991             LOG0("NameServer_getRemote: select failed.")
992             status = NameServer_E_FAIL;
993             goto exit;
994         }
995         else if (!ret) {
996             LOG0("NameServer_getRemote: select timed out.\n")
997             status = NameServer_E_TIMEOUT;
998             goto exit;
999         }
1001         if (FD_ISSET(waitFd, &rfds)) {
1002             /* Read, just to balance the write: */
1003             read(waitFd, &buf, sizeof(uint64_t));
1005             /* Process response: */
1006             replyMsg = &NameServer_module->nsMsg;
1008             if (replyMsg->seqNum != seqNum - 1) {
1009                 /* Ignore responses without current sequence # */
1010                 continue;
1011             }
1013             if (replyMsg->requestStatus) {
1014                 /* name is found */
1016                 /* set length to amount of data that was copied */
1017                 *len = replyMsg->valueLen;
1019                 /* set the contents of value */
1020                 if (*len <= sizeof (Bits32)) {
1021                     *(UInt32 *)value = (UInt32)replyMsg->value;
1022                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1023                         procId, (String)replyMsg->instanceName)
1024                     LOG2("%s, value: 0x%x...\n",
1025                         (String)replyMsg->name, *(UInt32 *)value)
1026                 }
1027                 else {
1028                     memcpy(value, replyMsg->valueBuf, *len);
1029                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1030                         procId, (String)replyMsg->instanceName)
1031                     for (i = 0; i < *len/4; i++) {
1032                         LOG2("%s, value buffer content: 0x%x...\n",
1033                             (String)replyMsg->name, ((uint32_t *)value)[i])
1034                     }
1035                 }
1037                 goto exit;
1038             }
1039             else {
1040                 /* name is not found */
1041                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1042                      (String)replyMsg->instanceName, (String)replyMsg->name)
1044                 /* set status to not found */
1045                 status = NameServer_E_NOTFOUND;
1046             }
1047         }
1048         done= TRUE;
1049     }
1051 exit:
1052     return (status);
1055 /* Function to retrieve the value portion of a name/value pair from
1056  * local table.
1057  */
1058 Int NameServer_get(NameServer_Handle handle,
1059                String            name,
1060                Ptr               value,
1061                UInt32 *          len,
1062                UInt16            procId[])
1064     Int status = NameServer_S_SUCCESS;
1065     UInt16 numProcs;
1066     UInt32 i;
1067     UInt16 clusterId;
1068     UInt16 baseId;
1070     numProcs = MultiProc_getNumProcsInCluster();
1071     baseId = MultiProc_getBaseIdOfCluster();
1073     /*
1074      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1075      * since this goes in a daemon, it will not be necessary.
1076      */
1078     if (procId == NULL) {
1079         status = NameServer_getLocal(handle, name, value, len);
1080         if (status == NameServer_E_NOTFOUND) {
1081             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1083                 /* getLocal call already covers "self", keep going */
1084                 if ((baseId + clusterId) == MultiProc_self()) {
1085                     continue;
1086                 }
1088                 status = NameServer_getRemote(handle, name, value, len,
1089                         baseId + clusterId);
1091                 if ((status >= 0) ||
1092                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1093                                      (status != NameServer_E_RESOURCE))) {
1094                     break;
1095                 }
1096             }
1097         }
1098     }
1099     else {
1100         /*
1101          *  Search the query list. It might contain the local proc
1102          *  somewhere in the list.
1103          */
1104         i = 0;
1105         while (procId[i] != MultiProc_INVALIDID) {
1106             if (procId[i] == MultiProc_self()) {
1107                 status = NameServer_getLocal(handle, name, value, len);
1108             }
1109             else {
1110                 status = NameServer_getRemote(handle, name, value, len,
1111                         procId[i]);
1112             }
1114             if ((status >= 0) ||
1115                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1116                                  (status != NameServer_E_RESOURCE))) {
1117                 break;
1118             }
1120             i++;
1121         }
1122     }
1124     if (status == NameServer_E_RESOURCE) {
1125         status = NameServer_E_NOTFOUND;
1126     }
1128     return (status);
1131 /* Gets a 32-bit value by name */
1132 Int NameServer_getUInt32(NameServer_Handle handle,
1133                      String            name,
1134                      Ptr               value,
1135                      UInt16            procId[])
1137     Int  status;
1138     UInt32 len = sizeof(UInt32);
1140     assert(handle != NULL);
1141     assert(name   != NULL);
1142     assert(value  != NULL);
1143     assert(NameServer_module->refCount != 0);
1145     status = NameServer_get(handle, name, value, &len, procId);
1147     return (status);
1150 /* Function to Retrieve the value portion of a name/value pair from
1151  * local table.
1152  */
1153 Int NameServer_getLocal(NameServer_Handle handle,
1154                     String            name,
1155                     Ptr               value,
1156                     UInt32 *          len)
1158     Int status = NameServer_E_NOTFOUND;
1159     NameServer_TableEntry * node = NULL;
1160     NameServer_TableEntry * temp = NULL;
1161     Bool done   = FALSE;
1162     UInt32 length;
1163     UInt32 hash;
1165     assert(handle != NULL);
1166     assert(name   != NULL);
1167     assert(value  != NULL);
1168     assert(len    != NULL);
1169     assert(NameServer_module->refCount != 0);
1171     length = *len;
1173     /* Calculate the hash */
1174     hash = stringHash(name);
1176     pthread_mutex_lock(&handle->gate);
1178     /* Traverse the list to find duplicate check */
1179     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1180         if (node->hash == hash) {
1181             if (node->collide == TRUE) {
1182                 temp = node;
1183                 while (temp) {
1184                     if (strcmp(temp->name, name) == 0u){
1185                         if (length <= node->len) {
1186                             memcpy(value, node->value, length);
1187                             *len = length;
1188                         }
1189                         else {
1190                             memcpy(value, node->value, node->len);
1191                             *len = node->len;
1192                         }
1193                         done = TRUE;
1194                         break;
1195                     }
1196                     temp = temp->next;
1197                 }
1198                 break;
1199             }
1200             else {
1201                 if (length <= node->len) {
1202                     memcpy(value, node->value, length);
1203                     *len = length;
1204                 }
1205                 else {
1206                     memcpy(value, node->value, node->len);
1207                     *len = node->len;
1208                 }
1209                 done = TRUE;
1210                 break;
1211             }
1212         }
1213     }
1215     pthread_mutex_unlock(&handle->gate);
1217     if (done == FALSE) {
1218         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1219     }
1220     else {
1221         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1222              node->name, (UInt32)node->value)
1223         status = NameServer_S_SUCCESS;
1224     }
1226     return (status);
1229 /*
1230  *  Gets a 32-bit value by name from the local table
1231  *
1232  *  If the name is found, the 32-bit value is copied into the value
1233  *  argument and a success status is returned.
1234  *
1235  *  If the name is not found, zero is returned in len and the contents
1236  *  of value are not modified. Not finding a name is not considered
1237  *  an error.
1238  *
1239  *  This function only searches the local name/value table.
1240  *
1241  */
1242 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1244     Int                 status;
1245     UInt32              len    = sizeof(UInt32);
1247     assert(handle != NULL);
1248     assert(name   != NULL);
1249     assert(value  != NULL);
1250     assert(NameServer_module->refCount != 0);
1252     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1253     status = NameServer_getLocal(handle, name, value, &len);
1255     return (status);
1258 /*
1259  *  ======== NameServer_attach ========
1260  */
1261 Int NameServer_attach(UInt16 procId)
1263     Int status = NameServer_S_SUCCESS;
1264     int sock;
1265     int err;
1266     UInt16 clId;
1267     uint64_t event;
1269     /* procId already validated in API layer */
1270     clId = procId - MultiProc_getBaseIdOfCluster();
1272     /* must reference count because we have multiple clients */
1273     if (NameServer_module->comm[clId].refCount > 0) {
1274         NameServer_module->comm[clId].refCount++;
1275         goto done;
1276     }
1278     /* create socket for sending messages to remote processor */
1279     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1280     if (sock < 0) {
1281         status = NameServer_E_FAIL;
1282         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1283                 strerror(errno));
1284         goto done;
1285     }
1286     NameServer_module->comm[clId].sendSock = sock;
1287     LOG2("NameServer_attach: created send socket: %d, procId %d\n", sock,
1288             procId);
1290     err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
1291     if (err < 0) {
1292         status = NameServer_E_FAIL;
1293         LOG3("NameServer_attach: connect failed: procId=%d, errno=%d (%s)\n",
1294                 procId, errno, strerror(errno));
1295         goto done;
1296     }
1298     /* create socket for receiving messages from remote processor */
1299     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1300     if (sock < 0) {
1301         status = NameServer_E_FAIL;
1302         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1303                 strerror(errno));
1304         goto done;
1305     }
1306     NameServer_module->comm[clId].recvSock = sock;
1307     LOG2("NameServer_attach: created receive socket: %d, procId %d\n", sock,
1308             procId);
1310     err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
1311     if (err < 0) {
1312         status = NameServer_E_FAIL;
1313         LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
1314                 strerror(errno));
1315         goto done;
1316     }
1318     /* getting here means we have successfully attached */
1319     NameServer_module->comm[clId].refCount++;
1321     /* tell the listener thread to add new receive sockets */
1322     event = NameServer_Event_REFRESH;
1323     write(NameServer_module->unblockFd, &event, sizeof(event));
1325     /* wait for ACK event */
1326     read(NameServer_module->waitFd, &event, sizeof(event));
1328 done:
1329     if (status < 0) {
1330         sock = NameServer_module->comm[clId].recvSock;
1331         if (sock != INVALIDSOCKET) {
1332             LOG1("    closing receive socket: %d\n", sock)
1333             close(sock);
1334             NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1335         }
1337         sock = NameServer_module->comm[clId].sendSock;
1338         if (sock != INVALIDSOCKET) {
1339             LOG1("    closing send socket: %d\n", sock)
1340             close(sock);
1341             NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1342         }
1343     }
1345     return (status);
1348 /*
1349  *  ======== NameServer_detach ========
1350  */
1351 Int NameServer_detach(UInt16 procId)
1353     Int status = NameServer_S_SUCCESS;
1354     UInt16 clId;
1355     int sendSock;
1356     int recvSock;
1357     uint64_t event;
1359     /* procId already validated in API layer */
1360     clId = procId - MultiProc_getBaseIdOfCluster();
1362     if (--NameServer_module->comm[clId].refCount > 0) {
1363         goto done;
1364     }
1366     /* remove sockets from active list */
1367     sendSock = NameServer_module->comm[clId].sendSock;
1368     NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1370     recvSock = NameServer_module->comm[clId].recvSock;
1371     NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1373     /* tell the listener thread to remove old sockets */
1374     event = NameServer_Event_REFRESH;
1375     write(NameServer_module->unblockFd, &event, sizeof(event));
1377     /* wait for ACK event */
1378     read(NameServer_module->waitFd, &event, sizeof(event));
1380     /* close the sending socket */
1381     LOG1("NameServer_destroy: closing socket: %d\n", sendSock)
1382     close(sendSock);
1384     /* close the receiving socket */
1385     LOG1("NameServer_destroy: closing socket: %d\n", recvSock)
1386     close(recvSock);
1388     /* decrement the reference count */
1389     NameServer_module->comm[clId].refCount--;
1391 done:
1392     return (status);
1395 #if defined (__cplusplus)
1397 #endif /* defined (__cplusplus) */