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); \
152 }
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)
233 {
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);
242 }
244 static void NameServerRemote_processMessage(NameServerRemote_Msg *msg,
245 UInt16 procId)
246 {
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 }
313 }
315 /*
316 * ======== listener_cb ========
317 */
318 static void *listener_cb(void *arg)
319 {
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);
420 }
422 /* =============================================================================
423 * APIS
424 * =============================================================================
425 */
427 /*
428 * ======== NameServer_setup ========
429 * Function to setup the name server module
430 */
431 Int NameServer_setup(Void)
432 {
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);
492 }
494 /*
495 * ======== NameServer_destroy ========
496 * Function to destroy the name server module
497 */
498 Int NameServer_destroy(void)
499 {
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);
538 }
540 /* Function to retrieve a NameServer handle from name. */
541 NameServer_Handle NameServer_getHandle(String name)
542 {
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);
568 }
571 /* Function to create a name server. */
572 NameServer_Handle NameServer_create(String name,
573 const NameServer_Params * params)
574 {
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);
648 }
650 /*
651 * ======== NameServer_delete ========
652 * Delete a name server instance
653 */
654 Int NameServer_delete(NameServer_Handle *handle)
655 {
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);
696 }
698 /* Adds a variable length value into the local NameServer table */
699 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
700 {
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);
795 }
798 /* Function to add a UInt32 value into a name server. */
799 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
800 {
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);
810 }
812 /* Function to remove a name/value pair from a name server. */
813 Int NameServer_remove(NameServer_Handle handle, String name)
814 {
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);
882 }
884 /* Function to remove a name/value pair from a name server. */
885 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
886 {
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);
907 }
910 /* Initialize this config-params structure with supplier-specified
911 * defaults before instance creation.
912 */
913 Void NameServer_Params_init(NameServer_Params * params)
914 {
915 assert(params != NULL);
917 memcpy(params, &(NameServer_module->defInstParams),
918 sizeof (NameServer_Params));
919 }
922 Int NameServer_getRemote(NameServer_Handle handle,
923 String name,
924 Ptr value,
925 UInt32 * len,
926 UInt16 procId)
927 {
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);
1062 }
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[])
1072 {
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);
1138 }
1140 /* Gets a 32-bit value by name */
1141 Int NameServer_getUInt32(NameServer_Handle handle,
1142 String name,
1143 Ptr value,
1144 UInt16 procId[])
1145 {
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);
1157 }
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)
1166 {
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);
1236 }
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)
1252 {
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);
1265 }
1267 /*
1268 * ======== NameServer_attach ========
1269 */
1270 Int NameServer_attach(UInt16 procId)
1271 {
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 /* must reference count because we have multiple clients */
1282 if (NameServer_module->comm[clId].refCount > 0) {
1283 NameServer_module->comm[clId].refCount++;
1284 goto done;
1285 }
1287 /* create socket for sending messages to remote processor */
1288 sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1289 if (sock < 0) {
1290 status = NameServer_E_FAIL;
1291 LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1292 strerror(errno));
1293 goto done;
1294 }
1295 NameServer_module->comm[clId].sendSock = sock;
1296 LOG2("NameServer_attach: created send socket: %d, procId %d\n", sock,
1297 procId);
1299 err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
1300 if (err < 0) {
1301 status = NameServer_E_FAIL;
1302 LOG3("NameServer_attach: connect failed: procId=%d, errno=%d (%s)\n",
1303 procId, errno, strerror(errno));
1304 goto done;
1305 }
1307 /* create socket for receiving messages from remote processor */
1308 sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1309 if (sock < 0) {
1310 status = NameServer_E_FAIL;
1311 LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1312 strerror(errno));
1313 goto done;
1314 }
1315 NameServer_module->comm[clId].recvSock = sock;
1316 LOG2("NameServer_attach: created receive socket: %d, procId %d\n", sock,
1317 procId);
1319 err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
1320 if (err < 0) {
1321 status = NameServer_E_FAIL;
1322 LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
1323 strerror(errno));
1324 goto done;
1325 }
1327 /* getting here means we have successfully attached */
1328 NameServer_module->comm[clId].refCount++;
1330 /* tell the listener thread to add new receive sockets */
1331 event = NameServer_Event_REFRESH;
1332 write(NameServer_module->unblockFd, &event, sizeof(event));
1334 /* wait for ACK event */
1335 read(NameServer_module->waitFd, &event, sizeof(event));
1337 done:
1338 if (status < 0) {
1339 sock = NameServer_module->comm[clId].recvSock;
1340 if (sock != INVALIDSOCKET) {
1341 LOG1(" closing receive socket: %d\n", sock)
1342 close(sock);
1343 NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1344 }
1346 sock = NameServer_module->comm[clId].sendSock;
1347 if (sock != INVALIDSOCKET) {
1348 LOG1(" closing send socket: %d\n", sock)
1349 close(sock);
1350 NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1351 }
1352 }
1354 return (status);
1355 }
1357 /*
1358 * ======== NameServer_detach ========
1359 */
1360 Int NameServer_detach(UInt16 procId)
1361 {
1362 Int status = NameServer_S_SUCCESS;
1363 UInt16 clId;
1364 int sendSock;
1365 int recvSock;
1366 uint64_t event;
1368 /* procId already validated in API layer */
1369 clId = procId - MultiProc_getBaseIdOfCluster();
1371 if (--NameServer_module->comm[clId].refCount > 0) {
1372 goto done;
1373 }
1375 /* remove sockets from active list */
1376 sendSock = NameServer_module->comm[clId].sendSock;
1377 NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1379 recvSock = NameServer_module->comm[clId].recvSock;
1380 NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1382 /* tell the listener thread to remove old sockets */
1383 event = NameServer_Event_REFRESH;
1384 write(NameServer_module->unblockFd, &event, sizeof(event));
1386 /* wait for ACK event */
1387 read(NameServer_module->waitFd, &event, sizeof(event));
1389 /* close the sending socket */
1390 LOG1("NameServer_destroy: closing socket: %d\n", sendSock)
1391 close(sendSock);
1393 /* close the receiving socket */
1394 LOG1("NameServer_destroy: closing socket: %d\n", recvSock)
1395 close(recvSock);
1397 /* decrement the reference count */
1398 NameServer_module->comm[clId].refCount--;
1400 done:
1401 return (status);
1402 }
1404 #if defined (__cplusplus)
1405 }
1406 #endif /* defined (__cplusplus) */