Linux: NameServer_daemon: Check All Remote Cores Even if One Core is in Bad State
[ipc/ipcdev.git] / linux / src / daemon / NameServer_daemon.c
1 /*
2  * Copyright (c) 2012-2016 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     pthread_mutex_t      attachGate;
149 } NameServer_ModuleObject;
151 #define CIRCLEQ_elemClear(elem) { \
152         (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
155 #define CIRCLEQ_traverse(x, y, tag) \
156         for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
158 /* =============================================================================
159  *  Globals
160  * =============================================================================
161  */
162 /*
163  * NameServer_state
164  *
165  * Make the module gate "recursive" since NameServer_getHandle() needs to
166  * use it and NameServer_create() needs to hold it around its call to
167  * NameServer_getHandle().  Also, use the static initializer instead of a
168  * run-time init call, so we can use this gate immediately in _setup().
169  */
170 static NameServer_ModuleObject NameServer_state = {
171     .defInstParams.maxRuntimeEntries = 0u,
172     .defInstParams.tableHeap         = NULL,
173     .defInstParams.checkExisting     = TRUE,
174     .defInstParams.maxValueLen       = 0u,
175     .defInstParams.maxNameLen        = 16u,
176 #if defined(IPC_BUILDOS_ANDROID) && (PLATFORM_SDK_VERSION < 23)
177     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
178 #else
179 // only _NP (non-portable) type available in CG tools which we're using
180     .modGate                         = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
181 #endif
182     .attachGate                      = PTHREAD_MUTEX_INITIALIZER,
183     .refCount                        = 0
184 };
186 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
188 static const UInt32 stringCrcTab[256u] = {
189   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
190   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
191   0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
192   0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
193   0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
194   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
195   0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
196   0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
197   0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
198   0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
199   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
200   0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
201   0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
202   0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
203   0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
204   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
205   0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
206   0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
207   0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
208   0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
209   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
210   0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
211   0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
212   0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
213   0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
214   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
215   0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
216   0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
217   0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
218   0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
219   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
220   0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
221   0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
222   0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
223   0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
224   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
225   0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
226   0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
227   0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
228   0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
229   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
230   0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
231   0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
232 };
234 static UInt32 stringHash(String s)
236     UInt32 hash = strlen(s);
237     UInt32 i;
239     for (i = 0; i < strlen(s); i++) {
240         hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
241     }
243     return (hash);
246 static Int NameServer_reattach(UInt16 procId)
248     Int status = NameServer_S_SUCCESS;
249     UInt16 clId;
250     int sendSock = INVALIDSOCKET;
251     int recvSock = INVALIDSOCKET;
252     int err;
254     /* procId already validated in API layer */
255     clId = procId - MultiProc_getBaseIdOfCluster();
257     if (NameServer_module->comm[clId].refCount == 0) {
258         goto done;
259     }
261     LOG2("NameServer_reattach: --> procId=%d, refCount=%d\n",
262             procId, NameServer_module->comm[clId].refCount)
264     /* first create new sockets */
265     sendSock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
266     if (sendSock < 0) {
267         status = NameServer_E_FAIL;
268         LOG2("NameServer_reattach: socket failed: %d, %s\n", errno,
269                 strerror(errno));
270         goto done;
271     }
272     LOG2("NameServer_reattach: created send socket: %d, procId %d\n", sendSock,
273             procId);
275     err = ConnectSocket(sendSock, procId, MESSAGEQ_RPMSG_PORT);
276     if (err < 0) {
277         status = NameServer_E_FAIL;
278         LOG3("NameServer_reattach: connect failed: procId=%d, errno=%d (%s)\n",
279                 procId, errno, strerror(errno));
280         goto done;
281     }
283     /* create socket for receiving messages from remote processor */
284     recvSock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
285     if (recvSock < 0) {
286         status = NameServer_E_FAIL;
287         LOG2("NameServer_reattach: socket failed: %d, %s\n", errno,
288                 strerror(errno));
289         goto done;
290     }
292     LOG2("NameServer_attach: created receive socket: %d, procId %d\n", recvSock,
293             procId);
295     err = SocketBindAddr(recvSock, procId, NAME_SERVER_RPMSG_ADDR);
296     if (err < 0) {
297         status = NameServer_E_FAIL;
298         LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
299                 strerror(errno));
300         goto done;
301     }
303     /* then close old sockets */
304     /* close the sending socket */
305     LOG1("NameServer_reattach: closing socket: %d\n",
306          NameServer_module->comm[clId].sendSock)
307     close(NameServer_module->comm[clId].sendSock);
309     /* close the receiving socket */
310     LOG1("NameServer_reattach: closing socket: %d\n",
311          NameServer_module->comm[clId].recvSock)
312     close(NameServer_module->comm[clId].recvSock);
314     /* assign new sockets */
315     NameServer_module->comm[clId].sendSock = sendSock;
316     NameServer_module->comm[clId].recvSock = recvSock;
318 done:
319     if (status < 0) {
320         if (recvSock >= 0) {
321             LOG1("    closing receive socket: %d\n", recvSock)
322             close(recvSock);
323         }
325         if (sendSock >= 0) {
326             LOG1("    closing send socket: %d\n", sendSock)
327             close(sendSock);
328         }
329     }
331     LOG2("NameServer_reattach: <-- refCount=%d, status=%d\n",
332             NameServer_module->comm[clId].refCount, status)
334     return (status);
337 static void NameServerRemote_processMessage(NameServerRemote_Msg *msg,
338         UInt16 procId)
340     NameServer_Handle handle;
341     Int               status = NameServer_E_FAIL;
342     int               err;
343     uint64_t          buf = 1;
344     UInt16            clusterId;
346     if (msg->request == NAMESERVER_REQUEST) {
347         LOG2("NameServer Request: instanceName: %s, name: %s\n",
348              (String)msg->instanceName, (String)msg->name)
350         assert(msg->valueLen <= MAXVALUELEN);
351         /*
352          *  Message is a request. Lookup name in NameServer table.
353          *  Send a response message back to source processor.
354          */
355         handle = NameServer_getHandle((String)msg->instanceName);
357         if (handle != NULL) {
358             /* Search for the NameServer entry */
359             if (msg->valueLen <= sizeof (Bits32)) {
360                 LOG0("Calling NameServer_getLocalUInt32...\n")
361                 status = NameServer_getLocalUInt32(handle,
362                      (String)msg->name, &msg->value);
363             }
364             else {
365                 LOG0("Calling NameServer_getLocal...\n")
366                 status = NameServer_getLocal(handle,
367                      (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
368             }
369         }
371         /* set the request status */
372         if (status < 0) {
373             LOG3("NameServer Response: instance: %s, name: %s, value not "
374                     "found, status: %d\n", (String)msg->instanceName,
375                     (String)msg->name, status);
376             msg->requestStatus = 0;
377         }
378         else {
379             LOG3("NameServer Response: instance: %s, name: %s, value: 0x%x\n",
380                     (String)msg->instanceName, (String)msg->name, msg->value);
381             msg->requestStatus = 1;
382         }
384         /* specify message as a response */
385         msg->request = NAMESERVER_RESPONSE;
386         msg->reserved = NAMESERVER_MSG_TOKEN;
388         /* send response message to remote processor */
389         clusterId = procId - MultiProc_getBaseIdOfCluster();
390         err = send(NameServer_module->comm[clusterId].sendSock, msg,
391                    sizeof(NameServerRemote_Msg), 0);
392         if (err < 0) {
393             LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
394         }
395     }
396     else {
397         LOG3("NameServer Reply: instanceName: %s, name: %s, value: 0x%x\n",
398                 (String)msg->instanceName, (String)msg->name, msg->value);
400         /* Save the response message.  */
401         memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerRemote_Msg));
403         /* Post the eventfd upon which NameServer_get() is waiting */
404         write(NameServer_module->waitFd, &buf, sizeof(uint64_t));
405     }
408 /*
409  *  ======== listener_cb ========
410  */
411 static void *listener_cb(void *arg)
413     fd_set rfds;
414     int ret = 0, maxfd;
415     int i;
416     UInt16 procId;
417     struct  sockaddr_rpmsg  fromAddr;
418     unsigned int len;
419     NameServerRemote_Msg msg;
420     int nbytes;
421     UInt16 numProcs = MultiProc_getNumProcsInCluster();
422     UInt16 baseId = MultiProc_getBaseIdOfCluster();
423     int sock;
424     uint64_t event;
425     Bool run = TRUE;
426     Bool reconnect = FALSE;
428     LOG0("listener_cb: Entered Listener thread.\n")
430     do {
431         /* Wait for NameServer messages or unblockFd notification */
432         FD_ZERO(&rfds);
433         FD_SET(NameServer_module->unblockFd, &rfds);
434         maxfd = NameServer_module->unblockFd;
436         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
437             if ((MultiProc_self() == procId)
438                 || (NameServer_module->comm[i].recvSock == INVALIDSOCKET)) {
439                 continue;
440             }
441             sock = NameServer_module->comm[i].recvSock;
442             FD_SET(sock, &rfds);
443             maxfd = sock > maxfd ? sock : maxfd;
444         }
446         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
447              NameServer_module->unblockFd, maxfd)
449         /* wait here until new data available */
450         ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
452         if (ret == -1) {
453             LOG0("listener_cb: select failed.")
454             break;
455         }
456         LOG0("NameServer: back from select()\n")
458         /* check all receive sockets for pending data */
459         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
460             if ((MultiProc_self() == procId)
461                 || (NameServer_module->comm[i].recvSock == INVALIDSOCKET)) {
462                 continue;
463             }
464             sock = NameServer_module->comm[i].recvSock;
466             if (FD_ISSET(sock, &rfds)) {
467                 LOG1("NameServer: Listener got NameServer message "
468                      "from sock: %d!\n", sock);
469                 /* Get NameServer message and process: */
470                 memset(&fromAddr, 0, sizeof(fromAddr));
471                 len = sizeof(fromAddr);
473                 nbytes = recvfrom(sock, &msg, sizeof(NameServerRemote_Msg), 0,
474                                 (struct sockaddr *)&fromAddr, &len);
475                 if (len != sizeof(fromAddr)) {
476                     LOG1("recvfrom: got bad addr len (%d)\n", len)
477                     break;
478                 }
479                 if (nbytes < 0) {
480                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
481                     if (errno == ENOLINK) {
482                         LOG0("Socket is no longer valid, MUST re-attach!\n");
483                         reconnect = TRUE;
484                     }
485                     break;
486                 }
487                 else {
488                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
489                     LOG3("\tReceived ns msg: nbytes: %d, from addr: %d, "
490                             "from vproc: %d\n", nbytes, fromAddr.addr,
491                             fromAddr.vproc_id);
492                     NameServerRemote_processMessage(&msg, procId);
493                 }
494             }
495         }
497         /* check for events */
498         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
500             read(NameServer_module->unblockFd, &event, sizeof(event));
502             if (event & NameServer_Event_SHUTDOWN) {
503                 LOG0("NameServer: listener thread, event: SHUTDOWN\n")
504                 event &= ~NameServer_Event_SHUTDOWN;
505                 run = FALSE;
506             }
507             if (event & NameServer_Event_REFRESH) {
508                 LOG0("NameServer: listener thread, event: REFRESH\n")
509                 /* send ACK event */
510                 event = NameServer_Event_ACK;
511                 write(NameServer_module->waitFd, &event, sizeof(event));
512             }
513         }
515         if (reconnect) {
516             reconnect = FALSE;
517             /* grab lock to prevent users from attach/deattach while recovering */
518             pthread_mutex_lock(&NameServer_module->attachGate);
519             NameServer_reattach(procId);
520             pthread_mutex_unlock(&NameServer_module->attachGate);
521         }
523     } while (run);
525     return ((void *)ret);
528 /* =============================================================================
529  * APIS
530  * =============================================================================
531  */
533 /*
534  *  ======== NameServer_setup ========
535  *  Function to setup the name server module
536  */
537 Int NameServer_setup(Void)
539     Int    status = NameServer_S_SUCCESS;
540     int    ret;
541     Int    i;
543     pthread_mutex_lock(&NameServer_module->modGate);
545     LOG1("NameServer_setup: entered, refCount=%d\n",
546             NameServer_module->refCount)
548     NameServer_module->refCount++;
550     if (NameServer_module->refCount > 1) {
551         LOG0("NameServer_setup: already setup\n")
552         status = NameServer_S_ALREADYSETUP;
553         goto exit;
554     }
556     /* counter event object for passing commands to worker thread */
557     NameServer_module->unblockFd = eventfd(0, 0);
559     if (NameServer_module->unblockFd < 0) {
560         status = NameServer_E_FAIL;
561         LOG0("NameServer_setup: failed to create unblockFd.\n")
562         goto exit;
563     }
565     /* semaphore event object for acknowledging LAD command thread */
566     NameServer_module->waitFd = eventfd(0, EFD_SEMAPHORE);
568     if (NameServer_module->waitFd < 0) {
569         status = NameServer_E_FAIL;
570         LOG0("NameServer_setup: failed to create waitFd.\n")
571         goto exit;
572     }
574     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
575         NameServer_module->comm[i].refCount = 0;
576         NameServer_module->comm[i].sendSock = INVALIDSOCKET;
577         NameServer_module->comm[i].recvSock = INVALIDSOCKET;
578     }
580     /* Construct the list object */
581     CIRCLEQ_INIT(&NameServer_module->objList);
583     /* Create the listener thread: */
584     LOG0("NameServer_setup: creating listener thread\n")
585     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
586     if (ret) {
587         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
588         status = NameServer_E_FAIL;
589     }
591 exit:
592     LOG1("NameServer_setup: exiting, refCount=%d\n",
593             NameServer_module->refCount)
595     pthread_mutex_unlock(&NameServer_module->modGate);
597     return (status);
600 /*
601  *  ======== NameServer_destroy ========
602  *  Function to destroy the name server module
603  */
604 Int NameServer_destroy(void)
606     Int status = NameServer_S_SUCCESS;
607     uint64_t event;
609     pthread_mutex_lock(&NameServer_module->modGate);
611     LOG1("NameServer_destroy: entered, refCount=%d\n",
612             NameServer_module->refCount)
614     NameServer_module->refCount--;
616     if (NameServer_module->refCount > 0) {
617         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n",
618                 NameServer_module->refCount)
619         status = NameServer_S_SUCCESS;
620         goto exit;
621     }
623     /* TODO: delete any remaining instances */
625     /* shutdown the NameServer listener thread */
626     LOG0("NameServer_destroy: shutdown listener...\n")
627     event = NameServer_Event_SHUTDOWN;
628     write(NameServer_module->unblockFd, &event, sizeof(event));
630     /* Join: */
631     LOG0("NameServer_destroy: joining listener thread...\n")
632     pthread_join(NameServer_module->listener, NULL);
634     close(NameServer_module->unblockFd);
635     close(NameServer_module->waitFd);
637 exit:
638     LOG1("NameServer_destroy: exiting, refCount=%d\n",
639             NameServer_module->refCount)
641     pthread_mutex_unlock(&NameServer_module->modGate);
643     return (status);
646 /* Function to retrieve a NameServer handle from name. */
647 NameServer_Handle NameServer_getHandle(String name)
649     NameServer_Handle handle = NULL;
650     Bool              found = FALSE;
651     struct NameServer_Object * elem;
653     assert(name != NULL);
654     assert(NameServer_module->refCount != 0);
656     pthread_mutex_lock(&NameServer_module->modGate);
658     /* Lookup handle from name: */
659     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
660         handle = (NameServer_Handle) elem;
661         if (strcmp(handle->name, name) == 0) {
662             found = TRUE;
663             break;
664         }
665     }
667     if (found == FALSE) {
668         handle = NULL;
669     }
671     pthread_mutex_unlock(&NameServer_module->modGate);
673     return (handle);
677 /* Function to create a name server. */
678 NameServer_Handle NameServer_create(String name,
679                                     const NameServer_Params * params)
681     NameServer_Handle handle = NULL;
682     pthread_mutexattr_t mutex_attr;
684     assert(params != NULL);
685     assert(name != NULL);
686     assert(NameServer_module->refCount != 0);
688     LOG1("NameServer_create(): '%s'\n", name)
690     pthread_mutex_lock(&NameServer_module->modGate);
692     /* check if the name is already created or not */
693     handle = NameServer_getHandle(name);
694     if (handle != NULL) {
695         if (memcmp((Ptr)&handle->params, (Ptr)params,
696             sizeof(NameServer_Params)) == 0) {
697             handle->refCount++;
698         }
699         else {
700             LOG0("NameServer_create: NameServer params mismatch\n")
701             handle = NULL;
702         }
703         goto leave;
704     }
705     else {
706         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
707     }
709     if (!handle) {
710         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
711         goto leave;
712     }
714     handle->refCount = 1;
715     handle->name = (String)malloc(strlen(name) + 1u);
716     if (!handle->name) {
717         LOG0("NameServer_create: instance name alloc failed\n")
718         goto cleanup;
719     }
720     strncpy(handle->name, name, strlen (name) + 1u);
721     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
723     if (params->maxValueLen < sizeof(UInt32)) {
724         handle->params.maxValueLen = sizeof(UInt32);
725     }
726     else {
727         handle->params.maxValueLen = params->maxValueLen;
728     }
730     CIRCLEQ_INIT(&handle->nameList);
731     handle->count = 0u;
733     /* Put in the local list */
734     CIRCLEQ_elemClear(&handle->elem);
735     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
737     /*
738      * NameServer_removeEntry() enters gate and is called by
739      * NameServer_remove() while holding the gate.
740      */
741     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
742     pthread_mutex_init(&handle->gate, &mutex_attr);
744     goto leave;
746 cleanup:
747     free(handle);
748     handle = NULL;
750 leave:
751     pthread_mutex_unlock(&NameServer_module->modGate);
753     return (handle);
756 /*
757  *  ======== NameServer_delete ========
758  *  Delete a name server instance
759  */
760 Int NameServer_delete(NameServer_Handle *handle)
762     Int status = NameServer_S_SUCCESS;
763     struct NameServer_Object *obj;
765     assert(handle != NULL);
766     assert(*handle != NULL);
767     assert(NameServer_module->refCount != 0);
769     obj = *(struct NameServer_Object **)handle;
771     pthread_mutex_lock(&NameServer_module->modGate);
773     obj->refCount--;
774     if (obj->refCount != 0) {
775         goto leave;
776     }
778     /* delete each entry on the name list */
779     while (obj->nameList.cqh_first != (void *)&obj->nameList) {
780         NameServer_removeEntry(*handle, (Ptr)(obj->nameList.cqh_first));
781     }
783     /* free the instance name */
784     if (obj->name != NULL) {
785         free(obj->name);
786         obj->name = NULL;
787     }
789     /* destroy the mutex */
790     pthread_mutex_destroy(&obj->gate);
792     /* remove from objList */
793     CIRCLEQ_REMOVE(&NameServer_module->objList, obj, elem);
795     /* finally, free the instance object */
796     free(obj);
798     /* set the caller's handle to null */
799     (*handle) = NULL;
801 leave:
802     pthread_mutex_unlock(&NameServer_module->modGate);
804     return (status);
807 /* Adds a variable length value into the local NameServer table */
808 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
810     Int                 status = NameServer_S_SUCCESS;
811     NameServer_TableEntry * node = NULL;
812     NameServer_TableEntry * new_node = NULL;
813     Bool                found = FALSE;
814     UInt32              hash;
816     assert(handle != NULL);
817     assert(name     != NULL);
818     assert(buf      != NULL);
819     assert(len      != 0);
820     assert(NameServer_module->refCount != 0);
822     /* Calculate the hash */
823     hash = stringHash(name);
825     pthread_mutex_lock(&handle->gate);
827     if (strlen(name) > handle->params.maxNameLen - 1) {
828         status = NameServer_E_INVALIDARG;
829         LOG0("NameServer_add: name length exceeded maximum!\n")
830         new_node = NULL;
831         goto exit;
832     }
834     if (len > handle->params.maxValueLen) {
835         status = NameServer_E_INVALIDARG;
836         LOG0("NameServer_add: value length exceeded maximum!\n")
837         new_node = NULL;
838         goto exit;
839     }
841     /* Traverse the list to find duplicate check */
842     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
843         /* Hash matches */
844         if (node->hash == hash) {
845             /* If the name matches, incase hash is duplicate */
846             if (strcmp(node->name, name) == 0) {
847                 if (handle->params.checkExisting == TRUE) {
848                     status = NameServer_E_INVALIDARG;
849                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
850                     break;
851                 }
852             }
853             else {
854                 found = TRUE;
855                 break;
856             } /* name does not match */
857         } /* hash does not match */
858     } /* CIRCLEQ_traverse */
860     if (status != NameServer_S_SUCCESS) {
861         new_node = NULL;
862         goto exit;
863     }
865     /* Now add the new entry. */
866     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
867     if (new_node == NULL) {
868         status = NameServer_E_MEMORY;
869         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
871         goto exit;
872     }
874     new_node->hash    = hash;
875     new_node->collide = found; /* Indicate if there is a collision*/
876     new_node->len     = len;
877     new_node->next    = NULL;
878     new_node->name = (String)malloc(strlen(name) + 1u);
879     new_node->value  = (Ptr)malloc(len);
880     strncpy(new_node->name, name, strlen(name) + 1u);
881     memcpy((Ptr)new_node->value, (Ptr)buf, len);
883     if (found == TRUE) {
884         /* If hash is found, need to stitch the list to link the
885          * new node to the existing node with the same hash.
886          */
887         new_node->next = node->next;
888         node->next = new_node;
889     }
890     else {
891         /* put the new node into the list */
892         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
893     }
895     handle->count++;
897     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
898          name, *(UInt32 *)buf)
900 exit:
901     pthread_mutex_unlock(&handle->gate);
903     return (new_node);
907 /* Function to add a UInt32 value into a name server. */
908 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
910     Ptr entry = NULL;
912     assert(handle != NULL);
913     assert(name   != NULL);
914     assert(NameServer_module->refCount != 0);
916     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
918     return (entry);
921 /* Function to remove a name/value pair from a name server. */
922 Int NameServer_remove(NameServer_Handle handle, String name)
924     Int                 status = NameServer_S_SUCCESS;
925     NameServer_TableEntry *prev = NULL;
926     NameServer_TableEntry *temp = NULL;
927     NameServer_TableEntry *node = NULL;
928     Bool                done   = FALSE;
929     UInt32              hash;
931     assert(handle != NULL);
932     assert(name   != NULL);
933     assert(NameServer_module->refCount != 0);
935     /* Calculate the hash */
936     hash = stringHash(name);
938     pthread_mutex_lock(&handle->gate);
940     /* Traverse the list to find duplicate check */
941     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
942         /* Hash matchs */
943         if (node->hash == hash) {
944             if (node->collide == TRUE) {
945                 if (strcmp(node->name, name) == 0){
946                     free(node->value);
947                     free(node->name);
948                     memcpy((Ptr)node, (Ptr) node->next,
949                            sizeof(NameServer_TableEntry));
950                     node->next = node->next->next;
951                     free(node->next);
952                     handle->count--;
953                     done = TRUE;
954                     break;
955                 }
956                 else {
957                     prev = node;
958                     temp = node->next;
959                     while (temp) {
960                         if (strcmp(temp->name, name) == 0){
961                             free(temp->value);
962                             free(temp->name);
963                             prev->next = temp->next;
964                             free(temp);
965                             handle->count--;
966                             done = TRUE;
967                             break;
968                         }
969                         temp = temp->next;
970                     }
971                     break;
972                 }
973             }
974             else {
975                 NameServer_removeEntry(handle, (Ptr)node);
977                 done = TRUE;
978                 break;
979             }
980         }
981     }
983     if (done == FALSE) {
984         status = NameServer_E_INVALIDARG;
985         LOG1("NameServer_remove %d Entry not found!\n", status)
986     }
988     pthread_mutex_unlock(&handle->gate);
990     return (status);
993 /* Function to remove a name/value pair from a name server. */
994 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
996     Int  status = NameServer_S_SUCCESS;
997     NameServer_TableEntry * node;
999     assert(handle != NULL);
1000     assert(entry  != NULL);
1001     assert(NameServer_module->refCount != 0);
1003     pthread_mutex_lock(&handle->gate);
1005     node = (NameServer_TableEntry *)entry;
1007     free(node->value);
1008     free(node->name);
1009     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
1010     free(node);
1011     handle->count--;
1013     pthread_mutex_unlock(&handle->gate);
1015     return (status);
1019 /* Initialize this config-params structure with supplier-specified
1020  * defaults before instance creation.
1021  */
1022 Void NameServer_Params_init(NameServer_Params * params)
1024     assert(params != NULL);
1026     memcpy(params, &(NameServer_module->defInstParams),
1027            sizeof (NameServer_Params));
1031 Int NameServer_getRemote(NameServer_Handle handle,
1032                      String            name,
1033                      Ptr               value,
1034                      UInt32 *          len,
1035                      UInt16            procId)
1037     Int status = NameServer_S_SUCCESS;
1038     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
1039     NameServerRemote_Msg nsMsg;
1040     NameServerRemote_Msg *replyMsg;
1041     fd_set rfds;
1042     int ret = 0, sock, maxfd, waitFd;
1043     struct timeval tv;
1044     uint64_t buf = 1;
1045     int err;
1046     int i;
1047     static int seqNum = 0;
1048     Bool done = FALSE;
1049     UInt16 clusterId;
1051     if (strlen(name) >= MAXNAMEINCHAR) {
1052         LOG0("Name is too long in remote query\n");
1053         return NameServer_E_NAMETOOLONG;
1054     }
1056     if (strlen(obj->name) >= MAXNAMEINCHAR) {
1057         LOG0("Instance name is too long for remote query\n");
1058         return NameServer_E_NAMETOOLONG;
1059     }
1061     /* Set Timeout to wait: */
1062     tv.tv_sec = 0;
1063     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
1065     /* Create request message and send to remote: */
1066     clusterId = procId - MultiProc_getBaseIdOfCluster();
1067     sock = NameServer_module->comm[clusterId].sendSock;
1068     if (sock == INVALIDSOCKET) {
1069         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
1070              procId);
1071         status = NameServer_E_RESOURCE;
1072         goto exit;
1073     }
1075     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
1077     /* Create request message and send to remote processor: */
1078     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
1079     nsMsg.request = NAMESERVER_REQUEST;
1080     nsMsg.requestStatus = 0;
1081     nsMsg.valueLen = *len;
1082     nsMsg.seqNum = seqNum++;
1084     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
1085     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1087     LOG3("NameServer_getRemote: requesting from procId %d, %s: %s\n",
1088             procId, (String)nsMsg.instanceName, (String)nsMsg.name);
1090     err = send(sock, &nsMsg, sizeof(NameServerRemote_Msg), 0);
1091     if (err < 0) {
1092         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1093              errno, strerror(errno))
1094         status = NameServer_E_FAIL;
1095         goto exit;
1096     }
1098     while (!done) {
1099         /* Block on waitFd for signal from listener thread: */
1100         waitFd = NameServer_module->waitFd;
1101         FD_ZERO(&rfds);
1102         FD_SET(waitFd, &rfds);
1103         maxfd = waitFd + 1;
1104         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1106         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1108         if (ret == -1) {
1109             LOG0("NameServer_getRemote: select failed.")
1110             status = NameServer_E_FAIL;
1111             goto exit;
1112         }
1113         else if (!ret) {
1114             LOG0("NameServer_getRemote: select timed out.\n")
1115             status = NameServer_E_TIMEOUT;
1116             goto exit;
1117         }
1119         if (FD_ISSET(waitFd, &rfds)) {
1120             /* Read, just to balance the write: */
1121             read(waitFd, &buf, sizeof(uint64_t));
1123             /* Process response: */
1124             replyMsg = &NameServer_module->nsMsg;
1126             if (replyMsg->seqNum != seqNum - 1) {
1127                 /* Ignore responses without current sequence # */
1128                 continue;
1129             }
1131             if (replyMsg->requestStatus) {
1132                 /* name is found */
1134                 /* set length to amount of data that was copied */
1135                 *len = replyMsg->valueLen;
1137                 /* set the contents of value */
1138                 if (*len <= sizeof (Bits32)) {
1139                     *(UInt32 *)value = (UInt32)replyMsg->value;
1140                     LOG4("NameServer_getRemote: Reply from: %d, %s: "
1141                             "name: %s, value: 0x%x\n", procId,
1142                             (String)replyMsg->instanceName,
1143                             (String)replyMsg->name, *(UInt32 *)value);
1144                 }
1145                 else {
1146                     memcpy(value, replyMsg->valueBuf, *len);
1147                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1148                         procId, (String)replyMsg->instanceName)
1149                     for (i = 0; i < *len/4; i++) {
1150                         LOG2("%s, value buffer content: 0x%x...\n",
1151                             (String)replyMsg->name, ((uint32_t *)value)[i])
1152                     }
1153                 }
1155                 goto exit;
1156             }
1157             else {
1158                 /* name is not found */
1159                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1160                      (String)replyMsg->instanceName, (String)replyMsg->name)
1162                 /* set status to not found */
1163                 status = NameServer_E_NOTFOUND;
1164             }
1165         }
1166         done= TRUE;
1167     }
1169 exit:
1170     return (status);
1173 /* Function to retrieve the value portion of a name/value pair from
1174  * local table.
1175  */
1176 Int NameServer_get(NameServer_Handle handle,
1177                String            name,
1178                Ptr               value,
1179                UInt32 *          len,
1180                UInt16            procId[])
1182     Int status = NameServer_S_SUCCESS;
1183     UInt16 numProcs;
1184     UInt32 i;
1185     UInt16 clusterId;
1186     UInt16 baseId;
1188     numProcs = MultiProc_getNumProcsInCluster();
1189     baseId = MultiProc_getBaseIdOfCluster();
1191     /*
1192      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1193      * since this goes in a daemon, it will not be necessary.
1194      */
1196     if (procId == NULL) {
1197         status = NameServer_getLocal(handle, name, value, len);
1198         if (status == NameServer_E_NOTFOUND) {
1199             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1201                 /* getLocal call already covers "self", keep going */
1202                 if ((baseId + clusterId) == MultiProc_self()) {
1203                     continue;
1204                 }
1206                 status = NameServer_getRemote(handle, name, value, len,
1207                         baseId + clusterId);
1209                 if (status >= 0) {
1210                     break;
1211                 }
1212             }
1213         }
1214     }
1215     else {
1216         /*
1217          *  Search the query list. It might contain the local proc
1218          *  somewhere in the list.
1219          */
1220         i = 0;
1221         while (procId[i] != MultiProc_INVALIDID) {
1222             if (procId[i] == MultiProc_self()) {
1223                 status = NameServer_getLocal(handle, name, value, len);
1224             }
1225             else {
1226                 status = NameServer_getRemote(handle, name, value, len,
1227                         procId[i]);
1228             }
1230             if (status >= 0) {
1231                 break;
1232             }
1234             i++;
1235         }
1236     }
1238     if (status == NameServer_E_RESOURCE) {
1239         status = NameServer_E_NOTFOUND;
1240     }
1242     return (status);
1245 /* Gets a 32-bit value by name */
1246 Int NameServer_getUInt32(NameServer_Handle handle,
1247                      String            name,
1248                      Ptr               value,
1249                      UInt16            procId[])
1251     Int  status;
1252     UInt32 len = sizeof(UInt32);
1254     assert(handle != NULL);
1255     assert(name   != NULL);
1256     assert(value  != NULL);
1257     assert(NameServer_module->refCount != 0);
1259     status = NameServer_get(handle, name, value, &len, procId);
1261     return (status);
1264 /* Function to Retrieve the value portion of a name/value pair from
1265  * local table.
1266  */
1267 Int NameServer_getLocal(NameServer_Handle handle,
1268                     String            name,
1269                     Ptr               value,
1270                     UInt32 *          len)
1272     Int status = NameServer_E_NOTFOUND;
1273     NameServer_TableEntry * node = NULL;
1274     NameServer_TableEntry * temp = NULL;
1275     Bool done   = FALSE;
1276     UInt32 length;
1277     UInt32 hash;
1279     assert(handle != NULL);
1280     assert(name   != NULL);
1281     assert(value  != NULL);
1282     assert(len    != NULL);
1283     assert(NameServer_module->refCount != 0);
1285     length = *len;
1287     /* Calculate the hash */
1288     hash = stringHash(name);
1290     pthread_mutex_lock(&handle->gate);
1292     /* Traverse the list to find duplicate check */
1293     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1294         if (node->hash == hash) {
1295             if (node->collide == TRUE) {
1296                 temp = node;
1297                 while (temp) {
1298                     if (strcmp(temp->name, name) == 0u){
1299                         if (length <= node->len) {
1300                             memcpy(value, node->value, length);
1301                             *len = length;
1302                         }
1303                         else {
1304                             memcpy(value, node->value, node->len);
1305                             *len = node->len;
1306                         }
1307                         done = TRUE;
1308                         break;
1309                     }
1310                     temp = temp->next;
1311                 }
1312                 break;
1313             }
1314             else {
1315                 if (length <= node->len) {
1316                     memcpy(value, node->value, length);
1317                     *len = length;
1318                 }
1319                 else {
1320                     memcpy(value, node->value, node->len);
1321                     *len = node->len;
1322                 }
1323                 done = TRUE;
1324                 break;
1325             }
1326         }
1327     }
1329     pthread_mutex_unlock(&handle->gate);
1331     if (done == FALSE) {
1332         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1333     }
1334     else {
1335         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1336              node->name, (UInt32)node->value)
1337         status = NameServer_S_SUCCESS;
1338     }
1340     return (status);
1343 /*
1344  *  Gets a 32-bit value by name from the local table
1345  *
1346  *  If the name is found, the 32-bit value is copied into the value
1347  *  argument and a success status is returned.
1348  *
1349  *  If the name is not found, zero is returned in len and the contents
1350  *  of value are not modified. Not finding a name is not considered
1351  *  an error.
1352  *
1353  *  This function only searches the local name/value table.
1354  *
1355  */
1356 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1358     Int                 status;
1359     UInt32              len    = sizeof(UInt32);
1361     assert(handle != NULL);
1362     assert(name   != NULL);
1363     assert(value  != NULL);
1364     assert(NameServer_module->refCount != 0);
1366     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1367     status = NameServer_getLocal(handle, name, value, &len);
1369     return (status);
1372 /*
1373  *  ======== NameServer_attach ========
1374  */
1375 Int NameServer_attach(UInt16 procId)
1377     Int status = NameServer_S_SUCCESS;
1378     int sock;
1379     int err;
1380     UInt16 clId;
1381     uint64_t event;
1383     /* procId already validated in API layer */
1384     clId = procId - MultiProc_getBaseIdOfCluster();
1386     pthread_mutex_lock(&NameServer_module->attachGate);
1388     LOG2("NameServer_attach: --> procId=%d, refCount=%d\n",
1389             procId, NameServer_module->comm[clId].refCount)
1391     /* must reference count because we have multiple clients */
1392     if (NameServer_module->comm[clId].refCount > 0) {
1393         NameServer_module->comm[clId].refCount++;
1394         goto done;
1395     }
1397     /* create socket for sending messages to remote processor */
1398     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1399     if (sock < 0) {
1400         status = NameServer_E_FAIL;
1401         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1402                 strerror(errno));
1403         goto done;
1404     }
1405     NameServer_module->comm[clId].sendSock = sock;
1406     LOG2("NameServer_attach: created send socket: %d, procId %d\n", sock,
1407             procId);
1409     err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
1410     if (err < 0) {
1411         status = NameServer_E_FAIL;
1412         LOG3("NameServer_attach: connect failed: procId=%d, errno=%d (%s)\n",
1413                 procId, errno, strerror(errno));
1414         goto done;
1415     }
1417     /* create socket for receiving messages from remote processor */
1418     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1419     if (sock < 0) {
1420         status = NameServer_E_FAIL;
1421         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1422                 strerror(errno));
1423         goto done;
1424     }
1425     NameServer_module->comm[clId].recvSock = sock;
1426     LOG2("NameServer_attach: created receive socket: %d, procId %d\n", sock,
1427             procId);
1429     err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
1430     if (err < 0) {
1431         status = NameServer_E_FAIL;
1432         LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
1433                 strerror(errno));
1434         goto done;
1435     }
1437     /* getting here means we have successfully attached */
1438     NameServer_module->comm[clId].refCount++;
1440     pthread_mutex_unlock(&NameServer_module->attachGate);
1442     /* tell the listener thread to add new receive sockets */
1443     event = NameServer_Event_REFRESH;
1444     write(NameServer_module->unblockFd, &event, sizeof(event));
1446     /* wait for ACK event */
1447     read(NameServer_module->waitFd, &event, sizeof(event));
1449     pthread_mutex_lock(&NameServer_module->attachGate);
1451 done:
1452     if (status < 0) {
1453         sock = NameServer_module->comm[clId].recvSock;
1454         if (sock != INVALIDSOCKET) {
1455             LOG1("    closing receive socket: %d\n", sock)
1456             close(sock);
1457             NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1458         }
1460         sock = NameServer_module->comm[clId].sendSock;
1461         if (sock != INVALIDSOCKET) {
1462             LOG1("    closing send socket: %d\n", sock)
1463             close(sock);
1464             NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1465         }
1466     }
1468     LOG2("NameServer_attach: <-- refCount=%d, status=%d\n",
1469             NameServer_module->comm[clId].refCount, status)
1471     pthread_mutex_unlock(&NameServer_module->attachGate);
1473     return (status);
1476 /*
1477  *  ======== NameServer_detach ========
1478  */
1479 Int NameServer_detach(UInt16 procId)
1481     Int status = NameServer_S_SUCCESS;
1482     UInt16 clId;
1483     int sendSock;
1484     int recvSock;
1485     uint64_t event;
1487     /* procId already validated in API layer */
1488     clId = procId - MultiProc_getBaseIdOfCluster();
1490     pthread_mutex_lock(&NameServer_module->attachGate);
1492     LOG2("NameServer_detach: --> procId=%d, refCount=%d\n",
1493             procId, NameServer_module->comm[clId].refCount)
1495     /* decrement reference count regardless of outcome below */
1496     if (--NameServer_module->comm[clId].refCount > 0) {
1497         pthread_mutex_unlock(&NameServer_module->attachGate);
1498         goto done;
1499     }
1501     /* remove sockets from active list */
1502     sendSock = NameServer_module->comm[clId].sendSock;
1503     NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1505     recvSock = NameServer_module->comm[clId].recvSock;
1506     NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1508     pthread_mutex_unlock(&NameServer_module->attachGate);
1510     /* tell the listener thread to remove old sockets */
1511     event = NameServer_Event_REFRESH;
1512     write(NameServer_module->unblockFd, &event, sizeof(event));
1514     /* wait for ACK event */
1515     read(NameServer_module->waitFd, &event, sizeof(event));
1517     /* close the sending socket */
1518     LOG1("NameServer_detach: closing socket: %d\n", sendSock)
1519     close(sendSock);
1521     /* close the receiving socket */
1522     LOG1("NameServer_detach: closing socket: %d\n", recvSock)
1523     close(recvSock);
1525 done:
1526     LOG2("NameServer_detach: <-- refCount=%d, status=%d\n",
1527             NameServer_module->comm[clId].refCount, status)
1528     return (status);
1531 #if defined (__cplusplus)
1533 #endif /* defined (__cplusplus) */