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