6ec0d8182deea1798559d9268b68259461cc54d1
[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     /* finally, free the instance object */
687     free(obj);
689     /* set the caller's handle to null */
690     (*handle) = NULL;
692 leave:
693     pthread_mutex_unlock(&NameServer_module->modGate);
695     return (status);
698 /* Adds a variable length value into the local NameServer table */
699 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
701     Int                 status = NameServer_S_SUCCESS;
702     NameServer_TableEntry * node = NULL;
703     NameServer_TableEntry * new_node = NULL;
704     Bool                found = FALSE;
705     UInt32              hash;
707     assert(handle != NULL);
708     assert(name     != NULL);
709     assert(buf      != NULL);
710     assert(len      != 0);
711     assert(NameServer_module->refCount != 0);
713     /* Calculate the hash */
714     hash = stringHash(name);
716     pthread_mutex_lock(&handle->gate);
718     if (strlen(name) > handle->params.maxNameLen - 1) {
719         status = NameServer_E_INVALIDARG;
720         LOG0("NameServer_add: name length exceeded maximum!\n")
721         new_node = NULL;
722         goto exit;
723     }
725     if (len > handle->params.maxValueLen) {
726         status = NameServer_E_INVALIDARG;
727         LOG0("NameServer_add: value length exceeded maximum!\n")
728         new_node = NULL;
729         goto exit;
730     }
732     /* Traverse the list to find duplicate check */
733     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
734         /* Hash matches */
735         if (node->hash == hash) {
736             /* If the name matches, incase hash is duplicate */
737             if (strcmp(node->name, name) == 0) {
738                 if (handle->params.checkExisting == TRUE) {
739                     status = NameServer_E_INVALIDARG;
740                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
741                     break;
742                 }
743             }
744             else {
745                 found = TRUE;
746                 break;
747             } /* name does not match */
748         } /* hash does not match */
749     } /* CIRCLEQ_traverse */
751     if (status != NameServer_S_SUCCESS) {
752         new_node = NULL;
753         goto exit;
754     }
756     /* Now add the new entry. */
757     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
758     if (new_node == NULL) {
759         status = NameServer_E_MEMORY;
760         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
762         goto exit;
763     }
765     new_node->hash    = hash;
766     new_node->collide = found; /* Indicate if there is a collision*/
767     new_node->len     = len;
768     new_node->next    = NULL;
769     new_node->name = (String)malloc(strlen(name) + 1u);
770     new_node->value  = (Ptr)malloc(len);
771     strncpy(new_node->name, name, strlen(name) + 1u);
772     memcpy((Ptr)new_node->value, (Ptr)buf, len);
774     if (found == TRUE) {
775         /* If hash is found, need to stitch the list to link the
776          * new node to the existing node with the same hash.
777          */
778         new_node->next = node->next;
779         node->next = new_node;
780     }
781     else {
782         /* put the new node into the list */
783         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
784     }
786     handle->count++;
788     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
789          name, *(UInt32 *)buf)
791 exit:
792     pthread_mutex_unlock(&handle->gate);
794     return (new_node);
798 /* Function to add a UInt32 value into a name server. */
799 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
801     Ptr entry = NULL;
803     assert(handle != NULL);
804     assert(name   != NULL);
805     assert(NameServer_module->refCount != 0);
807     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
809     return (entry);
812 /* Function to remove a name/value pair from a name server. */
813 Int NameServer_remove(NameServer_Handle handle, String name)
815     Int                 status = NameServer_S_SUCCESS;
816     NameServer_TableEntry *prev = NULL;
817     NameServer_TableEntry *temp = NULL;
818     NameServer_TableEntry *node = NULL;
819     Bool                done   = FALSE;
820     UInt32              hash;
822     assert(handle != NULL);
823     assert(name   != NULL);
824     assert(NameServer_module->refCount != 0);
826     /* Calculate the hash */
827     hash = stringHash(name);
829     pthread_mutex_lock(&handle->gate);
831     /* Traverse the list to find duplicate check */
832     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
833         /* Hash matchs */
834         if (node->hash == hash) {
835             if (node->collide == TRUE) {
836                 if (strcmp(node->name, name) == 0){
837                     free(node->value);
838                     free(node->name);
839                     memcpy((Ptr)node, (Ptr) node->next,
840                            sizeof(NameServer_TableEntry));
841                     node->next = node->next->next;
842                     free(node->next);
843                     handle->count--;
844                     done = TRUE;
845                     break;
846                 }
847                 else {
848                     prev = node;
849                     temp = node->next;
850                     while (temp) {
851                         if (strcmp(temp->name, name) == 0){
852                             free(temp->value);
853                             free(temp->name);
854                             prev->next = temp->next;
855                             free(temp);
856                             handle->count--;
857                             done = TRUE;
858                             break;
859                         }
860                         temp = temp->next;
861                     }
862                     break;
863                 }
864             }
865             else {
866                 NameServer_removeEntry(handle, (Ptr)node);
868                 done = TRUE;
869                 break;
870             }
871         }
872     }
874     if (done == FALSE) {
875         status = NameServer_E_INVALIDARG;
876         LOG1("NameServer_remove %d Entry not found!\n", status)
877     }
879     pthread_mutex_unlock(&handle->gate);
881     return (status);
884 /* Function to remove a name/value pair from a name server. */
885 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
887     Int  status = NameServer_S_SUCCESS;
888     NameServer_TableEntry * node;
890     assert(handle != NULL);
891     assert(entry  != NULL);
892     assert(NameServer_module->refCount != 0);
894     pthread_mutex_lock(&handle->gate);
896     node = (NameServer_TableEntry *)entry;
898     free(node->value);
899     free(node->name);
900     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
901     free(node);
902     handle->count--;
904     pthread_mutex_unlock(&handle->gate);
906     return (status);
910 /* Initialize this config-params structure with supplier-specified
911  * defaults before instance creation.
912  */
913 Void NameServer_Params_init(NameServer_Params * params)
915     assert(params != NULL);
917     memcpy(params, &(NameServer_module->defInstParams),
918            sizeof (NameServer_Params));
922 Int NameServer_getRemote(NameServer_Handle handle,
923                      String            name,
924                      Ptr               value,
925                      UInt32 *          len,
926                      UInt16            procId)
928     Int status = NameServer_S_SUCCESS;
929     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
930     NameServerRemote_Msg nsMsg;
931     NameServerRemote_Msg *replyMsg;
932     fd_set rfds;
933     int ret = 0, sock, maxfd, waitFd;
934     struct timeval tv;
935     uint64_t buf = 1;
936     int err;
937     int i;
938     static int seqNum = 0;
939     Bool done = FALSE;
940     UInt16 clusterId;
942     if (strlen(name) >= MAXNAMEINCHAR) {
943         LOG0("Name is too long in remote query\n");
944         return NameServer_E_NAMETOOLONG;
945     }
947     if (strlen(obj->name) >= MAXNAMEINCHAR) {
948         LOG0("Instance name is too long for remote query\n");
949         return NameServer_E_NAMETOOLONG;
950     }
952     /* Set Timeout to wait: */
953     tv.tv_sec = 0;
954     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
956     /* Create request message and send to remote: */
957     clusterId = procId - MultiProc_getBaseIdOfCluster();
958     sock = NameServer_module->comm[clusterId].sendSock;
959     if (sock == INVALIDSOCKET) {
960         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
961              procId);
962         status = NameServer_E_RESOURCE;
963         goto exit;
964     }
966     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
968     /* Create request message and send to remote processor: */
969     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
970     nsMsg.request = NAMESERVER_REQUEST;
971     nsMsg.requestStatus = 0;
972     nsMsg.valueLen = *len;
973     nsMsg.seqNum = seqNum++;
975     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
976     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
978     LOG3("NameServer_getRemote: requesting from procId %d, %s: %s\n",
979             procId, (String)nsMsg.instanceName, (String)nsMsg.name);
981     err = send(sock, &nsMsg, sizeof(NameServerRemote_Msg), 0);
982     if (err < 0) {
983         LOG2("NameServer_getRemote: send failed: %d, %s\n",
984              errno, strerror(errno))
985         status = NameServer_E_FAIL;
986         goto exit;
987     }
989     while (!done) {
990         /* Block on waitFd for signal from listener thread: */
991         waitFd = NameServer_module->waitFd;
992         FD_ZERO(&rfds);
993         FD_SET(waitFd, &rfds);
994         maxfd = waitFd + 1;
995         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
997         ret = select(maxfd, &rfds, NULL, NULL, &tv);
999         if (ret == -1) {
1000             LOG0("NameServer_getRemote: select failed.")
1001             status = NameServer_E_FAIL;
1002             goto exit;
1003         }
1004         else if (!ret) {
1005             LOG0("NameServer_getRemote: select timed out.\n")
1006             status = NameServer_E_TIMEOUT;
1007             goto exit;
1008         }
1010         if (FD_ISSET(waitFd, &rfds)) {
1011             /* Read, just to balance the write: */
1012             read(waitFd, &buf, sizeof(uint64_t));
1014             /* Process response: */
1015             replyMsg = &NameServer_module->nsMsg;
1017             if (replyMsg->seqNum != seqNum - 1) {
1018                 /* Ignore responses without current sequence # */
1019                 continue;
1020             }
1022             if (replyMsg->requestStatus) {
1023                 /* name is found */
1025                 /* set length to amount of data that was copied */
1026                 *len = replyMsg->valueLen;
1028                 /* set the contents of value */
1029                 if (*len <= sizeof (Bits32)) {
1030                     *(UInt32 *)value = (UInt32)replyMsg->value;
1031                     LOG4("NameServer_getRemote: Reply from: %d, %s: "
1032                             "name: %s, value: 0x%x\n", procId,
1033                             (String)replyMsg->instanceName,
1034                             (String)replyMsg->name, *(UInt32 *)value);
1035                 }
1036                 else {
1037                     memcpy(value, replyMsg->valueBuf, *len);
1038                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1039                         procId, (String)replyMsg->instanceName)
1040                     for (i = 0; i < *len/4; i++) {
1041                         LOG2("%s, value buffer content: 0x%x...\n",
1042                             (String)replyMsg->name, ((uint32_t *)value)[i])
1043                     }
1044                 }
1046                 goto exit;
1047             }
1048             else {
1049                 /* name is not found */
1050                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1051                      (String)replyMsg->instanceName, (String)replyMsg->name)
1053                 /* set status to not found */
1054                 status = NameServer_E_NOTFOUND;
1055             }
1056         }
1057         done= TRUE;
1058     }
1060 exit:
1061     return (status);
1064 /* Function to retrieve the value portion of a name/value pair from
1065  * local table.
1066  */
1067 Int NameServer_get(NameServer_Handle handle,
1068                String            name,
1069                Ptr               value,
1070                UInt32 *          len,
1071                UInt16            procId[])
1073     Int status = NameServer_S_SUCCESS;
1074     UInt16 numProcs;
1075     UInt32 i;
1076     UInt16 clusterId;
1077     UInt16 baseId;
1079     numProcs = MultiProc_getNumProcsInCluster();
1080     baseId = MultiProc_getBaseIdOfCluster();
1082     /*
1083      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1084      * since this goes in a daemon, it will not be necessary.
1085      */
1087     if (procId == NULL) {
1088         status = NameServer_getLocal(handle, name, value, len);
1089         if (status == NameServer_E_NOTFOUND) {
1090             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1092                 /* getLocal call already covers "self", keep going */
1093                 if ((baseId + clusterId) == MultiProc_self()) {
1094                     continue;
1095                 }
1097                 status = NameServer_getRemote(handle, name, value, len,
1098                         baseId + clusterId);
1100                 if ((status >= 0) ||
1101                     ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1102                                      (status != NameServer_E_RESOURCE))) {
1103                     break;
1104                 }
1105             }
1106         }
1107     }
1108     else {
1109         /*
1110          *  Search the query list. It might contain the local proc
1111          *  somewhere in the list.
1112          */
1113         i = 0;
1114         while (procId[i] != MultiProc_INVALIDID) {
1115             if (procId[i] == MultiProc_self()) {
1116                 status = NameServer_getLocal(handle, name, value, len);
1117             }
1118             else {
1119                 status = NameServer_getRemote(handle, name, value, len,
1120                         procId[i]);
1121             }
1123             if ((status >= 0) ||
1124                 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1125                                  (status != NameServer_E_RESOURCE))) {
1126                 break;
1127             }
1129             i++;
1130         }
1131     }
1133     if (status == NameServer_E_RESOURCE) {
1134         status = NameServer_E_NOTFOUND;
1135     }
1137     return (status);
1140 /* Gets a 32-bit value by name */
1141 Int NameServer_getUInt32(NameServer_Handle handle,
1142                      String            name,
1143                      Ptr               value,
1144                      UInt16            procId[])
1146     Int  status;
1147     UInt32 len = sizeof(UInt32);
1149     assert(handle != NULL);
1150     assert(name   != NULL);
1151     assert(value  != NULL);
1152     assert(NameServer_module->refCount != 0);
1154     status = NameServer_get(handle, name, value, &len, procId);
1156     return (status);
1159 /* Function to Retrieve the value portion of a name/value pair from
1160  * local table.
1161  */
1162 Int NameServer_getLocal(NameServer_Handle handle,
1163                     String            name,
1164                     Ptr               value,
1165                     UInt32 *          len)
1167     Int status = NameServer_E_NOTFOUND;
1168     NameServer_TableEntry * node = NULL;
1169     NameServer_TableEntry * temp = NULL;
1170     Bool done   = FALSE;
1171     UInt32 length;
1172     UInt32 hash;
1174     assert(handle != NULL);
1175     assert(name   != NULL);
1176     assert(value  != NULL);
1177     assert(len    != NULL);
1178     assert(NameServer_module->refCount != 0);
1180     length = *len;
1182     /* Calculate the hash */
1183     hash = stringHash(name);
1185     pthread_mutex_lock(&handle->gate);
1187     /* Traverse the list to find duplicate check */
1188     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1189         if (node->hash == hash) {
1190             if (node->collide == TRUE) {
1191                 temp = node;
1192                 while (temp) {
1193                     if (strcmp(temp->name, name) == 0u){
1194                         if (length <= node->len) {
1195                             memcpy(value, node->value, length);
1196                             *len = length;
1197                         }
1198                         else {
1199                             memcpy(value, node->value, node->len);
1200                             *len = node->len;
1201                         }
1202                         done = TRUE;
1203                         break;
1204                     }
1205                     temp = temp->next;
1206                 }
1207                 break;
1208             }
1209             else {
1210                 if (length <= node->len) {
1211                     memcpy(value, node->value, length);
1212                     *len = length;
1213                 }
1214                 else {
1215                     memcpy(value, node->value, node->len);
1216                     *len = node->len;
1217                 }
1218                 done = TRUE;
1219                 break;
1220             }
1221         }
1222     }
1224     pthread_mutex_unlock(&handle->gate);
1226     if (done == FALSE) {
1227         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1228     }
1229     else {
1230         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1231              node->name, (UInt32)node->value)
1232         status = NameServer_S_SUCCESS;
1233     }
1235     return (status);
1238 /*
1239  *  Gets a 32-bit value by name from the local table
1240  *
1241  *  If the name is found, the 32-bit value is copied into the value
1242  *  argument and a success status is returned.
1243  *
1244  *  If the name is not found, zero is returned in len and the contents
1245  *  of value are not modified. Not finding a name is not considered
1246  *  an error.
1247  *
1248  *  This function only searches the local name/value table.
1249  *
1250  */
1251 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1253     Int                 status;
1254     UInt32              len    = sizeof(UInt32);
1256     assert(handle != NULL);
1257     assert(name   != NULL);
1258     assert(value  != NULL);
1259     assert(NameServer_module->refCount != 0);
1261     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1262     status = NameServer_getLocal(handle, name, value, &len);
1264     return (status);
1267 /*
1268  *  ======== NameServer_attach ========
1269  */
1270 Int NameServer_attach(UInt16 procId)
1272     Int status = NameServer_S_SUCCESS;
1273     int sock;
1274     int err;
1275     UInt16 clId;
1276     uint64_t event;
1278     /* procId already validated in API layer */
1279     clId = procId - MultiProc_getBaseIdOfCluster();
1281     LOG2("NameServer_attach: --> procId=%d, refCount=%d\n",
1282             procId, NameServer_module->comm[clId].refCount)
1284     /* must reference count because we have multiple clients */
1285     if (NameServer_module->comm[clId].refCount > 0) {
1286         NameServer_module->comm[clId].refCount++;
1287         goto done;
1288     }
1290     /* create socket for sending messages to remote processor */
1291     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1292     if (sock < 0) {
1293         status = NameServer_E_FAIL;
1294         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1295                 strerror(errno));
1296         goto done;
1297     }
1298     NameServer_module->comm[clId].sendSock = sock;
1299     LOG2("NameServer_attach: created send socket: %d, procId %d\n", sock,
1300             procId);
1302     err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
1303     if (err < 0) {
1304         status = NameServer_E_FAIL;
1305         LOG3("NameServer_attach: connect failed: procId=%d, errno=%d (%s)\n",
1306                 procId, errno, strerror(errno));
1307         goto done;
1308     }
1310     /* create socket for receiving messages from remote processor */
1311     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1312     if (sock < 0) {
1313         status = NameServer_E_FAIL;
1314         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1315                 strerror(errno));
1316         goto done;
1317     }
1318     NameServer_module->comm[clId].recvSock = sock;
1319     LOG2("NameServer_attach: created receive socket: %d, procId %d\n", sock,
1320             procId);
1322     err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
1323     if (err < 0) {
1324         status = NameServer_E_FAIL;
1325         LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
1326                 strerror(errno));
1327         goto done;
1328     }
1330     /* getting here means we have successfully attached */
1331     NameServer_module->comm[clId].refCount++;
1333     /* tell the listener thread to add new receive sockets */
1334     event = NameServer_Event_REFRESH;
1335     write(NameServer_module->unblockFd, &event, sizeof(event));
1337     /* wait for ACK event */
1338     read(NameServer_module->waitFd, &event, sizeof(event));
1340 done:
1341     if (status < 0) {
1342         sock = NameServer_module->comm[clId].recvSock;
1343         if (sock != INVALIDSOCKET) {
1344             LOG1("    closing receive socket: %d\n", sock)
1345             close(sock);
1346             NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1347         }
1349         sock = NameServer_module->comm[clId].sendSock;
1350         if (sock != INVALIDSOCKET) {
1351             LOG1("    closing send socket: %d\n", sock)
1352             close(sock);
1353             NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1354         }
1355     }
1357     LOG2("NameServer_attach: <-- refCount=%d, status=%d\n",
1358             NameServer_module->comm[clId].refCount, status)
1360     return (status);
1363 /*
1364  *  ======== NameServer_detach ========
1365  */
1366 Int NameServer_detach(UInt16 procId)
1368     Int status = NameServer_S_SUCCESS;
1369     UInt16 clId;
1370     int sendSock;
1371     int recvSock;
1372     uint64_t event;
1374     /* procId already validated in API layer */
1375     clId = procId - MultiProc_getBaseIdOfCluster();
1377     LOG2("NameServer_detach: --> procId=%d, refCount=%d\n",
1378             procId, NameServer_module->comm[clId].refCount)
1380     /* decrement reference count regardless of outcome below */
1381     if (--NameServer_module->comm[clId].refCount > 0) {
1382         goto done;
1383     }
1385     /* remove sockets from active list */
1386     sendSock = NameServer_module->comm[clId].sendSock;
1387     NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1389     recvSock = NameServer_module->comm[clId].recvSock;
1390     NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1392     /* tell the listener thread to remove old sockets */
1393     event = NameServer_Event_REFRESH;
1394     write(NameServer_module->unblockFd, &event, sizeof(event));
1396     /* wait for ACK event */
1397     read(NameServer_module->waitFd, &event, sizeof(event));
1399     /* close the sending socket */
1400     LOG1("NameServer_detach: closing socket: %d\n", sendSock)
1401     close(sendSock);
1403     /* close the receiving socket */
1404     LOG1("NameServer_detach: closing socket: %d\n", recvSock)
1405     close(recvSock);
1407 done:
1408     LOG2("NameServer_detach: <-- refCount=%d, status=%d\n",
1409             NameServer_module->comm[clId].refCount, status)
1410     return (status);
1413 #if defined (__cplusplus)
1415 #endif /* defined (__cplusplus) */