Remove NameServer instance from module list in NameServer_delete()
[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 #if !defined(EFD_SEMAPHORE)
77 #  define EFD_SEMAPHORE (1 << 0)
78 #endif
80 #define MESSAGEQ_RPMSG_PORT       61
81 #define NAME_SERVER_RPMSG_ADDR    0
83 #define INVALIDSOCKET     (-1)
85 #define NameServer_Event_ACK            (1 << 0)
86 #define NameServer_Event_REFRESH        (1 << 1)
87 #define NameServer_Event_SHUTDOWN       (1 << 2)
89 #if defined (__cplusplus)
90 extern "C" {
91 #endif
94 /* =============================================================================
95  * Structures & Enums
96  * =============================================================================
97  */
99 /* Structure of entry in Name/Value table */
100 typedef struct NameServer_TableEntry_tag {
101     CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
102     /* List element */
103     UInt32                    hash;
104     /* Hash value */
105     String                    name;
106     /* Name portion of the name/value pair. */
107     UInt                      len;
108     /* Length of the value field. */
109     Ptr                       value;
110     /* Value portion of the name/value entry. */
111     Bool                      collide;
112     /* Does the hash collide? */
113     struct NameServer_TableEntry_tag * next;
114     /* Pointer to the next entry, used incase of collision only */
115 } NameServer_TableEntry;
117 /* Structure defining object for the NameServer */
118 struct NameServer_Object {
119     CIRCLEQ_ENTRY(NameServer_Object) elem;
120     CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
121     String             name;            /* name of the instance */
122     NameServer_Params  params;          /* the parameter structure */
123     UInt32             count;           /* count of entries */
124     UInt32             refCount;        /* reference count to this object */
125     pthread_mutex_t    gate;            /* crit sect gate */
126 } NameServer_Object;
128 /* structure for NameServer module state */
129 typedef struct NameServer_ModuleObject {
130     CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
131     Int32                refCount;
132     struct {
133         Int refCount;           /* attached reference count */
134         int sendSock;           /* socket for sending */
135         int recvSock;           /* socket for receiving */
136     } comm[MultiProc_MAXPROCESSORS];
137     pthread_t            listener;
138     /* Listener thread for NameServer replies and requests. */
139     int                  unblockFd;
140     /* Event to wake up listener thread. */
141     int                  waitFd;
142     /* Event to post to NameServer_get. */
143     NameServerRemote_Msg nsMsg;
144     /* NameServer Message cache. */
145     NameServer_Params    defInstParams;
146     /* Default instance paramters */
147     pthread_mutex_t      modGate;
148 } NameServer_ModuleObject;
150 #define CIRCLEQ_elemClear(elem) { \
151         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
154 #define CIRCLEQ_traverse(x, y, tag) \
155         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
157 /* =============================================================================
158  *  Globals
159  * =============================================================================
160  */
161 /*
162  * NameServer_state
163  *
164  * Make the module gate "recursive" since NameServer_getHandle() needs to
165  * use it and NameServer_create() needs to hold it around its call to
166  * NameServer_getHandle().  Also, use the static initializer instead of a
167  * run-time init call, so we can use this gate immediately in _setup().
168  */
169 static NameServer_ModuleObject NameServer_state = {
170     .defInstParams.maxRuntimeEntries = 0u,
171     .defInstParams.tableHeap         = NULL,
172     .defInstParams.checkExisting     = TRUE,
173     .defInstParams.maxValueLen       = 0u,
174     .defInstParams.maxNameLen        = 16u,
175 #if defined(IPC_BUILDOS_ANDROID)
176     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
177 #else
178 // only _NP (non-portable) type available in CG tools which we're using
179     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
180 #endif
181     .refCount                        = 0
182 };
184 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
186 static const UInt32 stringCrcTab[256u] = {
187   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
188   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
189   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
190   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
191   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
192   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
193   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
194   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
195   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
196   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
197   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
198   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
199   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
200   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
201   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
202   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
203   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
204   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
205   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
206   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
207   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
208   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
209   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
210   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
211   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
212   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
213   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
214   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
215   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
216   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
217   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
218   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
219   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
220   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
221   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
222   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
223   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
224   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
225   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
226   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
227   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
228   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
229   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
230 };
232 static UInt32 stringHash(String s)
234     UInt32 hash = strlen(s);
235     UInt32 i;
237     for (i = 0; i < strlen(s); i++) {
238         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
239     }
241     return (hash);
244 static void NameServerRemote_processMessage(NameServerRemote_Msg *msg,
245         UInt16 procId)
247     NameServer_Handle handle;
248     Int               status = NameServer_E_FAIL;
249     int               err;
250     uint64_t          buf = 1;
251     UInt16            clusterId;
253     if (msg->request == NAMESERVER_REQUEST) {
254         LOG2("NameServer Request: instanceName: %s, name: %s\n",
255              (String)msg->instanceName, (String)msg->name)
257         assert(msg->valueLen <= MAXVALUELEN);
258         /*
259          *  Message is a request. Lookup name in NameServer table.
260          *  Send a response message back to source processor.
261          */
262         handle = NameServer_getHandle((String)msg->instanceName);
264         if (handle != NULL) {
265             /* Search for the NameServer entry */
266             if (msg->valueLen <= sizeof (Bits32)) {
267                 LOG0("Calling NameServer_getLocalUInt32...\n")
268                 status = NameServer_getLocalUInt32(handle,
269                      (String)msg->name, &msg->value);
270             }
271             else {
272                 LOG0("Calling NameServer_getLocal...\n")
273                 status = NameServer_getLocal(handle,
274                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
275             }
276         }
278         /* set the request status */
279         if (status < 0) {
280             LOG3("NameServer Response: instance: %s, name: %s, value not "
281                     "found, status: %d\n", (String)msg->instanceName,
282                     (String)msg->name, status);
283             msg->requestStatus = 0;
284         }
285         else {
286             LOG3("NameServer Response: instance: %s, name: %s, value: 0x%x\n",
287                     (String)msg->instanceName, (String)msg->name, msg->value);
288             msg->requestStatus = 1;
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                     LOG3("\tReceived ns msg: nbytes: %d, from addr: %d, "
392                             "from vproc: %d\n", nbytes, fromAddr.addr,
393                             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     /* TODO: delete any remaining instances */
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);
650 /*
651  *  ======== NameServer_delete ========
652  *  Delete a name server instance
653  */
654 Int NameServer_delete(NameServer_Handle *handle)
656     Int status = NameServer_S_SUCCESS;
657     struct NameServer_Object *obj;
659     assert(handle != NULL);
660     assert(*handle != NULL);
661     assert(NameServer_module->refCount != 0);
663     obj = *(struct NameServer_Object **)handle;
665     pthread_mutex_lock(&NameServer_module->modGate);
667     obj->refCount--;
668     if (obj->refCount != 0) {
669         goto leave;
670     }
672     /* delete each entry on the name list */
673     while (obj->nameList.cqh_first != (void *)&obj->nameList) {
674         NameServer_removeEntry(*handle, (Ptr)(obj->nameList.cqh_first));
675     }
677     /* free the instance name */
678     if (obj->name != NULL) {
679         free(obj->name);
680         obj->name = NULL;
681     }
683     /* destroy the mutex */
684     pthread_mutex_destroy(&obj->gate);
686     /* remove from objList */
687     CIRCLEQ_REMOVE(&NameServer_module->objList, obj, elem);
689     /* finally, free the instance object */
690     free(obj);
692     /* set the caller's handle to null */
693     (*handle) = NULL;
695 leave:
696     pthread_mutex_unlock(&NameServer_module->modGate);
698     return (status);
701 /* Adds a variable length value into the local NameServer table */
702 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
704     Int                 status = NameServer_S_SUCCESS;
705     NameServer_TableEntry * node = NULL;
706     NameServer_TableEntry * new_node = NULL;
707     Bool                found = FALSE;
708     UInt32              hash;
710     assert(handle != NULL);
711     assert(name     != NULL);
712     assert(buf      != NULL);
713     assert(len      != 0);
714     assert(NameServer_module->refCount != 0);
716     /* Calculate the hash */
717     hash = stringHash(name);
719     pthread_mutex_lock(&handle->gate);
721     if (strlen(name) > handle->params.maxNameLen - 1) {
722         status = NameServer_E_INVALIDARG;
723         LOG0("NameServer_add: name length exceeded maximum!\n")
724         new_node = NULL;
725         goto exit;
726     }
728     if (len > handle->params.maxValueLen) {
729         status = NameServer_E_INVALIDARG;
730         LOG0("NameServer_add: value length exceeded maximum!\n")
731         new_node = NULL;
732         goto exit;
733     }
735     /* Traverse the list to find duplicate check */
736     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
737         /* Hash matches */
738         if (node->hash == hash) {
739             /* If the name matches, incase hash is duplicate */
740             if (strcmp(node->name, name) == 0) {
741                 if (handle->params.checkExisting == TRUE) {
742                     status = NameServer_E_INVALIDARG;
743                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
744                     break;
745                 }
746             }
747             else {
748                 found = TRUE;
749                 break;
750             } /* name does not match */
751         } /* hash does not match */
752     } /* CIRCLEQ_traverse */
754     if (status != NameServer_S_SUCCESS) {
755         new_node = NULL;
756         goto exit;
757     }
759     /* Now add the new entry. */
760     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
761     if (new_node == NULL) {
762         status = NameServer_E_MEMORY;
763         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
765         goto exit;
766     }
768     new_node->hash    = hash;
769     new_node->collide = found; /* Indicate if there is a collision*/
770     new_node->len     = len;
771     new_node->next    = NULL;
772     new_node->name = (String)malloc(strlen(name) + 1u);
773     new_node->value  = (Ptr)malloc(len);
774     strncpy(new_node->name, name, strlen(name) + 1u);
775     memcpy((Ptr)new_node->value, (Ptr)buf, len);
777     if (found == TRUE) {
778         /* If hash is found, need to stitch the list to link the
779          * new node to the existing node with the same hash.
780          */
781         new_node->next = node->next;
782         node->next = new_node;
783     }
784     else {
785         /* put the new node into the list */
786         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
787     }
789     handle->count++;
791     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
792          name, *(UInt32 *)buf)
794 exit:
795     pthread_mutex_unlock(&handle->gate);
797     return (new_node);
801 /* Function to add a UInt32 value into a name server. */
802 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
804     Ptr entry = NULL;
806     assert(handle != NULL);
807     assert(name   != NULL);
808     assert(NameServer_module->refCount != 0);
810     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
812     return (entry);
815 /* Function to remove a name/value pair from a name server. */
816 Int NameServer_remove(NameServer_Handle handle, String name)
818     Int                 status = NameServer_S_SUCCESS;
819     NameServer_TableEntry *prev = NULL;
820     NameServer_TableEntry *temp = NULL;
821     NameServer_TableEntry *node = NULL;
822     Bool                done   = FALSE;
823     UInt32              hash;
825     assert(handle != NULL);
826     assert(name   != NULL);
827     assert(NameServer_module->refCount != 0);
829     /* Calculate the hash */
830     hash = stringHash(name);
832     pthread_mutex_lock(&handle->gate);
834     /* Traverse the list to find duplicate check */
835     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
836         /* Hash matchs */
837         if (node->hash == hash) {
838             if (node->collide == TRUE) {
839                 if (strcmp(node->name, name) == 0){
840                     free(node->value);
841                     free(node->name);
842                     memcpy((Ptr)node, (Ptr) node->next,
843                            sizeof(NameServer_TableEntry));
844                     node->next = node->next->next;
845                     free(node->next);
846                     handle->count--;
847                     done = TRUE;
848                     break;
849                 }
850                 else {
851                     prev = node;
852                     temp = node->next;
853                     while (temp) {
854                         if (strcmp(temp->name, name) == 0){
855                             free(temp->value);
856                             free(temp->name);
857                             prev->next = temp->next;
858                             free(temp);
859                             handle->count--;
860                             done = TRUE;
861                             break;
862                         }
863                         temp = temp->next;
864                     }
865                     break;
866                 }
867             }
868             else {
869                 NameServer_removeEntry(handle, (Ptr)node);
871                 done = TRUE;
872                 break;
873             }
874         }
875     }
877     if (done == FALSE) {
878         status = NameServer_E_INVALIDARG;
879         LOG1("NameServer_remove %d Entry not found!\n", status)
880     }
882     pthread_mutex_unlock(&handle->gate);
884     return (status);
887 /* Function to remove a name/value pair from a name server. */
888 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
890     Int  status = NameServer_S_SUCCESS;
891     NameServer_TableEntry * node;
893     assert(handle != NULL);
894     assert(entry  != NULL);
895     assert(NameServer_module->refCount != 0);
897     pthread_mutex_lock(&handle->gate);
899     node = (NameServer_TableEntry *)entry;
901     free(node->value);
902     free(node->name);
903     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
904     free(node);
905     handle->count--;
907     pthread_mutex_unlock(&handle->gate);
909     return (status);
913 /* Initialize this config-params structure with supplier-specified
914  * defaults before instance creation.
915  */
916 Void NameServer_Params_init(NameServer_Params * params)
918     assert(params != NULL);
920     memcpy(params, &(NameServer_module->defInstParams),
921            sizeof (NameServer_Params));
925 Int NameServer_getRemote(NameServer_Handle handle,
926                      String            name,
927                      Ptr               value,
928                      UInt32 *          len,
929                      UInt16            procId)
931     Int status = NameServer_S_SUCCESS;
932     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
933     NameServerRemote_Msg nsMsg;
934     NameServerRemote_Msg *replyMsg;
935     fd_set rfds;
936     int ret = 0, sock, maxfd, waitFd;
937     struct timeval tv;
938     uint64_t buf = 1;
939     int err;
940     int i;
941     static int seqNum = 0;
942     Bool done = FALSE;
943     UInt16 clusterId;
945     if (strlen(name) >= MAXNAMEINCHAR) {
946         LOG0("Name is too long in remote query\n");
947         return NameServer_E_NAMETOOLONG;
948     }
950     if (strlen(obj->name) >= MAXNAMEINCHAR) {
951         LOG0("Instance name is too long for remote query\n");
952         return NameServer_E_NAMETOOLONG;
953     }
955     /* Set Timeout to wait: */
956     tv.tv_sec = 0;
957     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
959     /* Create request message and send to remote: */
960     clusterId = procId - MultiProc_getBaseIdOfCluster();
961     sock = NameServer_module->comm[clusterId].sendSock;
962     if (sock == INVALIDSOCKET) {
963         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
964              procId);
965         status = NameServer_E_RESOURCE;
966         goto exit;
967     }
969     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
971     /* Create request message and send to remote processor: */
972     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
973     nsMsg.request = NAMESERVER_REQUEST;
974     nsMsg.requestStatus = 0;
975     nsMsg.valueLen = *len;
976     nsMsg.seqNum = seqNum++;
978     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
979     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
981     LOG3("NameServer_getRemote: requesting from procId %d, %s: %s\n",
982             procId, (String)nsMsg.instanceName, (String)nsMsg.name);
984     err = send(sock, &nsMsg, sizeof(NameServerRemote_Msg), 0);
985     if (err < 0) {
986         LOG2("NameServer_getRemote: send failed: %d, %s\n",
987              errno, strerror(errno))
988         status = NameServer_E_FAIL;
989         goto exit;
990     }
992     while (!done) {
993         /* Block on waitFd for signal from listener thread: */
994         waitFd = NameServer_module->waitFd;
995         FD_ZERO(&rfds);
996         FD_SET(waitFd, &rfds);
997         maxfd = waitFd + 1;
998         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1000         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1002         if (ret == -1) {
1003             LOG0("NameServer_getRemote: select failed.")
1004             status = NameServer_E_FAIL;
1005             goto exit;
1006         }
1007         else if (!ret) {
1008             LOG0("NameServer_getRemote: select timed out.\n")
1009             status = NameServer_E_TIMEOUT;
1010             goto exit;
1011         }
1013         if (FD_ISSET(waitFd, &rfds)) {
1014             /* Read, just to balance the write: */
1015             read(waitFd, &buf, sizeof(uint64_t));
1017             /* Process response: */
1018             replyMsg = &NameServer_module->nsMsg;
1020             if (replyMsg->seqNum != seqNum - 1) {
1021                 /* Ignore responses without current sequence # */
1022                 continue;
1023             }
1025             if (replyMsg->requestStatus) {
1026                 /* name is found */
1028                 /* set length to amount of data that was copied */
1029                 *len = replyMsg->valueLen;
1031                 /* set the contents of value */
1032                 if (*len <= sizeof (Bits32)) {
1033                     *(UInt32 *)value = (UInt32)replyMsg->value;
1034                     LOG4("NameServer_getRemote: Reply from: %d, %s: "
1035                             "name: %s, value: 0x%x\n", procId,
1036                             (String)replyMsg->instanceName,
1037                             (String)replyMsg->name, *(UInt32 *)value);
1038                 }
1039                 else {
1040                     memcpy(value, replyMsg->valueBuf, *len);
1041                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1042                         procId, (String)replyMsg->instanceName)
1043                     for (i = 0; i < *len/4; i++) {
1044                         LOG2("%s, value buffer content: 0x%x...\n",
1045                             (String)replyMsg->name, ((uint32_t *)value)[i])
1046                     }
1047                 }
1049                 goto exit;
1050             }
1051             else {
1052                 /* name is not found */
1053                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1054                      (String)replyMsg->instanceName, (String)replyMsg->name)
1056                 /* set status to not found */
1057                 status = NameServer_E_NOTFOUND;
1058             }
1059         }
1060         done= TRUE;
1061     }
1063 exit:
1064     return (status);
1067 /* Function to retrieve the value portion of a name/value pair from
1068  * local table.
1069  */
1070 Int NameServer_get(NameServer_Handle handle,
1071                String            name,
1072                Ptr               value,
1073                UInt32 *          len,
1074                UInt16            procId[])
1076     Int status = NameServer_S_SUCCESS;
1077     UInt16 numProcs;
1078     UInt32 i;
1079     UInt16 clusterId;
1080     UInt16 baseId;
1082     numProcs = MultiProc_getNumProcsInCluster();
1083     baseId = MultiProc_getBaseIdOfCluster();
1085     /*
1086      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1087      * since this goes in a daemon, it will not be necessary.
1088      */
1090     if (procId == NULL) {
1091         status = NameServer_getLocal(handle, name, value, len);
1092         if (status == NameServer_E_NOTFOUND) {
1093             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1095                 /* getLocal call already covers "self", keep going */
1096                 if ((baseId + clusterId) == MultiProc_self()) {
1097                     continue;
1098                 }
1100                 status = NameServer_getRemote(handle, name, value, len,
1101                         baseId + clusterId);
1103                 if ((status >= 0) ||
1104                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1105                                      (status != NameServer_E_RESOURCE))) {
1106                     break;
1107                 }
1108             }
1109         }
1110     }
1111     else {
1112         /*
1113          *  Search the query list. It might contain the local proc
1114          *  somewhere in the list.
1115          */
1116         i = 0;
1117         while (procId[i] != MultiProc_INVALIDID) {
1118             if (procId[i] == MultiProc_self()) {
1119                 status = NameServer_getLocal(handle, name, value, len);
1120             }
1121             else {
1122                 status = NameServer_getRemote(handle, name, value, len,
1123                         procId[i]);
1124             }
1126             if ((status >= 0) ||
1127                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1128                                  (status != NameServer_E_RESOURCE))) {
1129                 break;
1130             }
1132             i++;
1133         }
1134     }
1136     if (status == NameServer_E_RESOURCE) {
1137         status = NameServer_E_NOTFOUND;
1138     }
1140     return (status);
1143 /* Gets a 32-bit value by name */
1144 Int NameServer_getUInt32(NameServer_Handle handle,
1145                      String            name,
1146                      Ptr               value,
1147                      UInt16            procId[])
1149     Int  status;
1150     UInt32 len = sizeof(UInt32);
1152     assert(handle != NULL);
1153     assert(name   != NULL);
1154     assert(value  != NULL);
1155     assert(NameServer_module->refCount != 0);
1157     status = NameServer_get(handle, name, value, &len, procId);
1159     return (status);
1162 /* Function to Retrieve the value portion of a name/value pair from
1163  * local table.
1164  */
1165 Int NameServer_getLocal(NameServer_Handle handle,
1166                     String            name,
1167                     Ptr               value,
1168                     UInt32 *          len)
1170     Int status = NameServer_E_NOTFOUND;
1171     NameServer_TableEntry * node = NULL;
1172     NameServer_TableEntry * temp = NULL;
1173     Bool done   = FALSE;
1174     UInt32 length;
1175     UInt32 hash;
1177     assert(handle != NULL);
1178     assert(name   != NULL);
1179     assert(value  != NULL);
1180     assert(len    != NULL);
1181     assert(NameServer_module->refCount != 0);
1183     length = *len;
1185     /* Calculate the hash */
1186     hash = stringHash(name);
1188     pthread_mutex_lock(&handle->gate);
1190     /* Traverse the list to find duplicate check */
1191     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1192         if (node->hash == hash) {
1193             if (node->collide == TRUE) {
1194                 temp = node;
1195                 while (temp) {
1196                     if (strcmp(temp->name, name) == 0u){
1197                         if (length <= node->len) {
1198                             memcpy(value, node->value, length);
1199                             *len = length;
1200                         }
1201                         else {
1202                             memcpy(value, node->value, node->len);
1203                             *len = node->len;
1204                         }
1205                         done = TRUE;
1206                         break;
1207                     }
1208                     temp = temp->next;
1209                 }
1210                 break;
1211             }
1212             else {
1213                 if (length <= node->len) {
1214                     memcpy(value, node->value, length);
1215                     *len = length;
1216                 }
1217                 else {
1218                     memcpy(value, node->value, node->len);
1219                     *len = node->len;
1220                 }
1221                 done = TRUE;
1222                 break;
1223             }
1224         }
1225     }
1227     pthread_mutex_unlock(&handle->gate);
1229     if (done == FALSE) {
1230         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1231     }
1232     else {
1233         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1234              node->name, (UInt32)node->value)
1235         status = NameServer_S_SUCCESS;
1236     }
1238     return (status);
1241 /*
1242  *  Gets a 32-bit value by name from the local table
1243  *
1244  *  If the name is found, the 32-bit value is copied into the value
1245  *  argument and a success status is returned.
1246  *
1247  *  If the name is not found, zero is returned in len and the contents
1248  *  of value are not modified. Not finding a name is not considered
1249  *  an error.
1250  *
1251  *  This function only searches the local name/value table.
1252  *
1253  */
1254 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1256     Int                 status;
1257     UInt32              len    = sizeof(UInt32);
1259     assert(handle != NULL);
1260     assert(name   != NULL);
1261     assert(value  != NULL);
1262     assert(NameServer_module->refCount != 0);
1264     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1265     status = NameServer_getLocal(handle, name, value, &len);
1267     return (status);
1270 /*
1271  *  ======== NameServer_attach ========
1272  */
1273 Int NameServer_attach(UInt16 procId)
1275     Int status = NameServer_S_SUCCESS;
1276     int sock;
1277     int err;
1278     UInt16 clId;
1279     uint64_t event;
1281     /* procId already validated in API layer */
1282     clId = procId - MultiProc_getBaseIdOfCluster();
1284     LOG2("NameServer_attach: --> procId=%d, refCount=%d\n",
1285             procId, NameServer_module->comm[clId].refCount)
1287     /* must reference count because we have multiple clients */
1288     if (NameServer_module->comm[clId].refCount > 0) {
1289         NameServer_module->comm[clId].refCount++;
1290         goto done;
1291     }
1293     /* create socket for sending messages to remote processor */
1294     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1295     if (sock < 0) {
1296         status = NameServer_E_FAIL;
1297         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1298                 strerror(errno));
1299         goto done;
1300     }
1301     NameServer_module->comm[clId].sendSock = sock;
1302     LOG2("NameServer_attach: created send socket: %d, procId %d\n", sock,
1303             procId);
1305     err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
1306     if (err < 0) {
1307         status = NameServer_E_FAIL;
1308         LOG3("NameServer_attach: connect failed: procId=%d, errno=%d (%s)\n",
1309                 procId, errno, strerror(errno));
1310         goto done;
1311     }
1313     /* create socket for receiving messages from remote processor */
1314     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1315     if (sock < 0) {
1316         status = NameServer_E_FAIL;
1317         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1318                 strerror(errno));
1319         goto done;
1320     }
1321     NameServer_module->comm[clId].recvSock = sock;
1322     LOG2("NameServer_attach: created receive socket: %d, procId %d\n", sock,
1323             procId);
1325     err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
1326     if (err < 0) {
1327         status = NameServer_E_FAIL;
1328         LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
1329                 strerror(errno));
1330         goto done;
1331     }
1333     /* getting here means we have successfully attached */
1334     NameServer_module->comm[clId].refCount++;
1336     /* tell the listener thread to add new receive sockets */
1337     event = NameServer_Event_REFRESH;
1338     write(NameServer_module->unblockFd, &event, sizeof(event));
1340     /* wait for ACK event */
1341     read(NameServer_module->waitFd, &event, sizeof(event));
1343 done:
1344     if (status < 0) {
1345         sock = NameServer_module->comm[clId].recvSock;
1346         if (sock != INVALIDSOCKET) {
1347             LOG1("    closing receive socket: %d\n", sock)
1348             close(sock);
1349             NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1350         }
1352         sock = NameServer_module->comm[clId].sendSock;
1353         if (sock != INVALIDSOCKET) {
1354             LOG1("    closing send socket: %d\n", sock)
1355             close(sock);
1356             NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1357         }
1358     }
1360     LOG2("NameServer_attach: <-- refCount=%d, status=%d\n",
1361             NameServer_module->comm[clId].refCount, status)
1363     return (status);
1366 /*
1367  *  ======== NameServer_detach ========
1368  */
1369 Int NameServer_detach(UInt16 procId)
1371     Int status = NameServer_S_SUCCESS;
1372     UInt16 clId;
1373     int sendSock;
1374     int recvSock;
1375     uint64_t event;
1377     /* procId already validated in API layer */
1378     clId = procId - MultiProc_getBaseIdOfCluster();
1380     LOG2("NameServer_detach: --> procId=%d, refCount=%d\n",
1381             procId, NameServer_module->comm[clId].refCount)
1383     /* decrement reference count regardless of outcome below */
1384     if (--NameServer_module->comm[clId].refCount > 0) {
1385         goto done;
1386     }
1388     /* remove sockets from active list */
1389     sendSock = NameServer_module->comm[clId].sendSock;
1390     NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1392     recvSock = NameServer_module->comm[clId].recvSock;
1393     NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1395     /* tell the listener thread to remove old sockets */
1396     event = NameServer_Event_REFRESH;
1397     write(NameServer_module->unblockFd, &event, sizeof(event));
1399     /* wait for ACK event */
1400     read(NameServer_module->waitFd, &event, sizeof(event));
1402     /* close the sending socket */
1403     LOG1("NameServer_detach: closing socket: %d\n", sendSock)
1404     close(sendSock);
1406     /* close the receiving socket */
1407     LOG1("NameServer_detach: closing socket: %d\n", recvSock)
1408     close(recvSock);
1410 done:
1411     LOG2("NameServer_detach: <-- refCount=%d, status=%d\n",
1412             NameServer_module->comm[clId].refCount, status)
1413     return (status);
1416 #if defined (__cplusplus)
1418 #endif /* defined (__cplusplus) */