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