Android: Fix compilation warnings
[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     socklen_t 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;
427     (Void)arg;
429     LOG0("listener_cb: Entered Listener thread.\n")
431     do {
432         /* Wait for NameServer messages or unblockFd notification */
433         FD_ZERO(&rfds);
434         FD_SET(NameServer_module->unblockFd, &rfds);
435         maxfd = NameServer_module->unblockFd;
437         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
438             if ((MultiProc_self() == procId)
439                 || (NameServer_module->comm[i].recvSock == INVALIDSOCKET)) {
440                 continue;
441             }
442             sock = NameServer_module->comm[i].recvSock;
443             FD_SET(sock, &rfds);
444             maxfd = sock > maxfd ? sock : maxfd;
445         }
447         LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
448              NameServer_module->unblockFd, maxfd)
450         /* wait here until new data available */
451         ret = select(maxfd + 1, &rfds, NULL, NULL, NULL);
453         if (ret == -1) {
454             LOG0("listener_cb: select failed.")
455             break;
456         }
457         LOG0("NameServer: back from select()\n")
459         /* check all receive sockets for pending data */
460         for (i = 0, procId = baseId; i < numProcs; i++, procId++) {
461             if ((MultiProc_self() == procId)
462                 || (NameServer_module->comm[i].recvSock == INVALIDSOCKET)) {
463                 continue;
464             }
465             sock = NameServer_module->comm[i].recvSock;
467             if (FD_ISSET(sock, &rfds)) {
468                 LOG1("NameServer: Listener got NameServer message "
469                      "from sock: %d!\n", sock);
470                 /* Get NameServer message and process: */
471                 memset(&fromAddr, 0, sizeof(fromAddr));
472                 len = sizeof(fromAddr);
474                 nbytes = recvfrom(sock, &msg, sizeof(NameServerRemote_Msg), 0,
475                                 (struct sockaddr *)&fromAddr, &len);
476                 if (len != sizeof(fromAddr)) {
477                     LOG1("recvfrom: got bad addr len (%d)\n", len)
478                     break;
479                 }
480                 if (nbytes < 0) {
481                     LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
482                     if (errno == ENOLINK) {
483                         LOG0("Socket is no longer valid, MUST re-attach!\n");
484                         reconnect = TRUE;
485                     }
486                     break;
487                 }
488                 else {
489                     LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
490                     LOG3("\tReceived ns msg: nbytes: %d, from addr: %d, "
491                             "from vproc: %d\n", nbytes, fromAddr.addr,
492                             fromAddr.vproc_id);
493                     NameServerRemote_processMessage(&msg, procId);
494                 }
495             }
496         }
498         /* check for events */
499         if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
501             read(NameServer_module->unblockFd, &event, sizeof(event));
503             if (event & NameServer_Event_SHUTDOWN) {
504                 LOG0("NameServer: listener thread, event: SHUTDOWN\n")
505                 event &= ~NameServer_Event_SHUTDOWN;
506                 run = FALSE;
507             }
508             if (event & NameServer_Event_REFRESH) {
509                 LOG0("NameServer: listener thread, event: REFRESH\n")
510                 /* send ACK event */
511                 event = NameServer_Event_ACK;
512                 write(NameServer_module->waitFd, &event, sizeof(event));
513             }
514         }
516         if (reconnect) {
517             reconnect = FALSE;
518             /* grab lock to prevent users from attach/deattach while recovering */
519             pthread_mutex_lock(&NameServer_module->attachGate);
520             NameServer_reattach(procId);
521             pthread_mutex_unlock(&NameServer_module->attachGate);
522         }
524     } while (run);
526     return ((void *)ret);
529 /* =============================================================================
530  * APIS
531  * =============================================================================
532  */
534 /*
535  *  ======== NameServer_setup ========
536  *  Function to setup the name server module
537  */
538 Int NameServer_setup(Void)
540     Int    status = NameServer_S_SUCCESS;
541     int    ret;
542     Int    i;
544     pthread_mutex_lock(&NameServer_module->modGate);
546     LOG1("NameServer_setup: entered, refCount=%d\n",
547             NameServer_module->refCount)
549     NameServer_module->refCount++;
551     if (NameServer_module->refCount > 1) {
552         LOG0("NameServer_setup: already setup\n")
553         status = NameServer_S_ALREADYSETUP;
554         goto exit;
555     }
557     /* counter event object for passing commands to worker thread */
558     NameServer_module->unblockFd = eventfd(0, 0);
560     if (NameServer_module->unblockFd < 0) {
561         status = NameServer_E_FAIL;
562         LOG0("NameServer_setup: failed to create unblockFd.\n")
563         goto exit;
564     }
566     /* semaphore event object for acknowledging LAD command thread */
567     NameServer_module->waitFd = eventfd(0, EFD_SEMAPHORE);
569     if (NameServer_module->waitFd < 0) {
570         status = NameServer_E_FAIL;
571         LOG0("NameServer_setup: failed to create waitFd.\n")
572         goto exit;
573     }
575     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
576         NameServer_module->comm[i].refCount = 0;
577         NameServer_module->comm[i].sendSock = INVALIDSOCKET;
578         NameServer_module->comm[i].recvSock = INVALIDSOCKET;
579     }
581     /* Construct the list object */
582     CIRCLEQ_INIT(&NameServer_module->objList);
584     /* Create the listener thread: */
585     LOG0("NameServer_setup: creating listener thread\n")
586     ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
587     if (ret) {
588         LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
589         status = NameServer_E_FAIL;
590     }
592 exit:
593     LOG1("NameServer_setup: exiting, refCount=%d\n",
594             NameServer_module->refCount)
596     pthread_mutex_unlock(&NameServer_module->modGate);
598     return (status);
601 /*
602  *  ======== NameServer_destroy ========
603  *  Function to destroy the name server module
604  */
605 Int NameServer_destroy(void)
607     Int status = NameServer_S_SUCCESS;
608     uint64_t event;
610     pthread_mutex_lock(&NameServer_module->modGate);
612     LOG1("NameServer_destroy: entered, refCount=%d\n",
613             NameServer_module->refCount)
615     NameServer_module->refCount--;
617     if (NameServer_module->refCount > 0) {
618         LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n",
619                 NameServer_module->refCount)
620         status = NameServer_S_SUCCESS;
621         goto exit;
622     }
624     /* TODO: delete any remaining instances */
626     /* shutdown the NameServer listener thread */
627     LOG0("NameServer_destroy: shutdown listener...\n")
628     event = NameServer_Event_SHUTDOWN;
629     write(NameServer_module->unblockFd, &event, sizeof(event));
631     /* Join: */
632     LOG0("NameServer_destroy: joining listener thread...\n")
633     pthread_join(NameServer_module->listener, NULL);
635     close(NameServer_module->unblockFd);
636     close(NameServer_module->waitFd);
638 exit:
639     LOG1("NameServer_destroy: exiting, refCount=%d\n",
640             NameServer_module->refCount)
642     pthread_mutex_unlock(&NameServer_module->modGate);
644     return (status);
647 /* Function to retrieve a NameServer handle from name. */
648 NameServer_Handle NameServer_getHandle(String name)
650     NameServer_Handle handle = NULL;
651     Bool              found = FALSE;
652     struct NameServer_Object * elem;
654     assert(name != NULL);
655     assert(NameServer_module->refCount != 0);
657     pthread_mutex_lock(&NameServer_module->modGate);
659     /* Lookup handle from name: */
660     CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
661         handle = (NameServer_Handle) elem;
662         if (strcmp(handle->name, name) == 0) {
663             found = TRUE;
664             break;
665         }
666     }
668     if (found == FALSE) {
669         handle = NULL;
670     }
672     pthread_mutex_unlock(&NameServer_module->modGate);
674     return (handle);
678 /* Function to create a name server. */
679 NameServer_Handle NameServer_create(String name,
680                                     const NameServer_Params * params)
682     NameServer_Handle handle = NULL;
683     pthread_mutexattr_t mutex_attr;
684     Int status = 0;
686     assert(params != NULL);
687     assert(name != NULL);
688     assert(NameServer_module->refCount != 0);
690     LOG1("NameServer_create(): '%s'\n", name)
692     pthread_mutex_lock(&NameServer_module->modGate);
694     status = pthread_mutexattr_init(&mutex_attr);
695     assert(status == 0);
697     /* check if the name is already created or not */
698     handle = NameServer_getHandle(name);
699     if (handle != NULL) {
700         if (memcmp((Ptr)&handle->params, (Ptr)params,
701             sizeof(NameServer_Params)) == 0) {
702             handle->refCount++;
703         }
704         else {
705             LOG0("NameServer_create: NameServer params mismatch\n")
706             handle = NULL;
707         }
708         goto leave;
709     }
710     else {
711         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
712     }
714     if (!handle) {
715         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
716         goto leave;
717     }
719     handle->refCount = 1;
720     handle->name = (String)malloc(strlen(name) + 1u);
721     if (!handle->name) {
722         LOG0("NameServer_create: instance name alloc failed\n")
723         goto cleanup;
724     }
725     strncpy(handle->name, name, strlen (name) + 1u);
726     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
728     if (params->maxValueLen < sizeof(UInt32)) {
729         handle->params.maxValueLen = sizeof(UInt32);
730     }
731     else {
732         handle->params.maxValueLen = params->maxValueLen;
733     }
735     CIRCLEQ_INIT(&handle->nameList);
736     handle->count = 0u;
738     /* Put in the local list */
739     CIRCLEQ_elemClear(&handle->elem);
740     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
742     /*
743      * NameServer_removeEntry() enters gate and is called by
744      * NameServer_remove() while holding the gate.
745      */
746     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
747     pthread_mutex_init(&handle->gate, &mutex_attr);
749     goto leave;
751 cleanup:
752     free(handle);
753     handle = NULL;
755 leave:
756     pthread_mutexattr_destroy(&mutex_attr);
757     pthread_mutex_unlock(&NameServer_module->modGate);
759     return (handle);
762 /*
763  *  ======== NameServer_delete ========
764  *  Delete a name server instance
765  */
766 Int NameServer_delete(NameServer_Handle *handle)
768     Int status = NameServer_S_SUCCESS;
769     struct NameServer_Object *obj;
771     assert(handle != NULL);
772     assert(*handle != NULL);
773     assert(NameServer_module->refCount != 0);
775     obj = *(struct NameServer_Object **)handle;
777     pthread_mutex_lock(&NameServer_module->modGate);
779     obj->refCount--;
780     if (obj->refCount != 0) {
781         goto leave;
782     }
784     /* delete each entry on the name list */
785     while (obj->nameList.cqh_first != (void *)&obj->nameList) {
786         NameServer_removeEntry(*handle, (Ptr)(obj->nameList.cqh_first));
787     }
789     /* free the instance name */
790     if (obj->name != NULL) {
791         free(obj->name);
792         obj->name = NULL;
793     }
795     /* destroy the mutex */
796     pthread_mutex_destroy(&obj->gate);
798     /* remove from objList */
799     CIRCLEQ_REMOVE(&NameServer_module->objList, obj, elem);
801     /* finally, free the instance object */
802     free(obj);
804     /* set the caller's handle to null */
805     (*handle) = NULL;
807 leave:
808     pthread_mutex_unlock(&NameServer_module->modGate);
810     return (status);
813 /* Adds a variable length value into the local NameServer table */
814 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
816     Int                 status = NameServer_S_SUCCESS;
817     NameServer_TableEntry * node = NULL;
818     NameServer_TableEntry * new_node = NULL;
819     Bool                found = FALSE;
820     UInt32              hash;
822     assert(handle != NULL);
823     assert(name     != NULL);
824     assert(buf      != NULL);
825     assert(len      != 0);
826     assert(NameServer_module->refCount != 0);
828     /* Calculate the hash */
829     hash = stringHash(name);
831     pthread_mutex_lock(&handle->gate);
833     if (strlen(name) > handle->params.maxNameLen - 1) {
834         status = NameServer_E_INVALIDARG;
835         LOG0("NameServer_add: name length exceeded maximum!\n")
836         new_node = NULL;
837         goto exit;
838     }
840     if (len > handle->params.maxValueLen) {
841         status = NameServer_E_INVALIDARG;
842         LOG0("NameServer_add: value length exceeded maximum!\n")
843         new_node = NULL;
844         goto exit;
845     }
847     /* Traverse the list to find duplicate check */
848     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
849         /* Hash matches */
850         if (node->hash == hash) {
851             /* If the name matches, incase hash is duplicate */
852             if (strcmp(node->name, name) == 0) {
853                 if (handle->params.checkExisting == TRUE) {
854                     status = NameServer_E_INVALIDARG;
855                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
856                     break;
857                 }
858             }
859             else {
860                 found = TRUE;
861                 break;
862             } /* name does not match */
863         } /* hash does not match */
864     } /* CIRCLEQ_traverse */
866     if (status != NameServer_S_SUCCESS) {
867         new_node = NULL;
868         goto exit;
869     }
871     /* Now add the new entry. */
872     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
873     if (new_node == NULL) {
874         status = NameServer_E_MEMORY;
875         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
877         goto exit;
878     }
880     new_node->hash    = hash;
881     new_node->collide = found; /* Indicate if there is a collision*/
882     new_node->len     = len;
883     new_node->next    = NULL;
884     new_node->name = (String)malloc(strlen(name) + 1u);
885     new_node->value  = (Ptr)malloc(len);
886     strncpy(new_node->name, name, strlen(name) + 1u);
887     memcpy((Ptr)new_node->value, (Ptr)buf, len);
889     if (found == TRUE) {
890         /* If hash is found, need to stitch the list to link the
891          * new node to the existing node with the same hash.
892          */
893         new_node->next = node->next;
894         node->next = new_node;
895     }
896     else {
897         /* put the new node into the list */
898         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
899     }
901     handle->count++;
903     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
904          name, *(UInt32 *)buf)
906 exit:
907     pthread_mutex_unlock(&handle->gate);
909     return (new_node);
913 /* Function to add a UInt32 value into a name server. */
914 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
916     Ptr entry = NULL;
918     assert(handle != NULL);
919     assert(name   != NULL);
920     assert(NameServer_module->refCount != 0);
922     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
924     return (entry);
927 /* Function to remove a name/value pair from a name server. */
928 Int NameServer_remove(NameServer_Handle handle, String name)
930     Int                 status = NameServer_S_SUCCESS;
931     NameServer_TableEntry *prev = NULL;
932     NameServer_TableEntry *temp = NULL;
933     NameServer_TableEntry *node = NULL;
934     Bool                done   = FALSE;
935     UInt32              hash;
937     assert(handle != NULL);
938     assert(name   != NULL);
939     assert(NameServer_module->refCount != 0);
941     /* Calculate the hash */
942     hash = stringHash(name);
944     pthread_mutex_lock(&handle->gate);
946     /* Traverse the list to find duplicate check */
947     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
948         /* Hash matchs */
949         if (node->hash == hash) {
950             if (node->collide == TRUE) {
951                 if (strcmp(node->name, name) == 0){
952                     free(node->value);
953                     free(node->name);
954                     memcpy((Ptr)node, (Ptr) node->next,
955                            sizeof(NameServer_TableEntry));
956                     node->next = node->next->next;
957                     free(node->next);
958                     handle->count--;
959                     done = TRUE;
960                     break;
961                 }
962                 else {
963                     prev = node;
964                     temp = node->next;
965                     while (temp) {
966                         if (strcmp(temp->name, name) == 0){
967                             free(temp->value);
968                             free(temp->name);
969                             prev->next = temp->next;
970                             free(temp);
971                             handle->count--;
972                             done = TRUE;
973                             break;
974                         }
975                         temp = temp->next;
976                     }
977                     break;
978                 }
979             }
980             else {
981                 NameServer_removeEntry(handle, (Ptr)node);
983                 done = TRUE;
984                 break;
985             }
986         }
987     }
989     if (done == FALSE) {
990         status = NameServer_E_INVALIDARG;
991         LOG1("NameServer_remove %d Entry not found!\n", status)
992     }
994     pthread_mutex_unlock(&handle->gate);
996     return (status);
999 /* Function to remove a name/value pair from a name server. */
1000 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
1002     Int  status = NameServer_S_SUCCESS;
1003     NameServer_TableEntry * node;
1005     assert(handle != NULL);
1006     assert(entry  != NULL);
1007     assert(NameServer_module->refCount != 0);
1009     pthread_mutex_lock(&handle->gate);
1011     node = (NameServer_TableEntry *)entry;
1013     free(node->value);
1014     free(node->name);
1015     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
1016     free(node);
1017     handle->count--;
1019     pthread_mutex_unlock(&handle->gate);
1021     return (status);
1025 /* Initialize this config-params structure with supplier-specified
1026  * defaults before instance creation.
1027  */
1028 Void NameServer_Params_init(NameServer_Params * params)
1030     assert(params != NULL);
1032     memcpy(params, &(NameServer_module->defInstParams),
1033            sizeof (NameServer_Params));
1037 Int NameServer_getRemote(NameServer_Handle handle,
1038                      String            name,
1039                      Ptr               value,
1040                      UInt32 *          len,
1041                      UInt16            procId)
1043     Int status = NameServer_S_SUCCESS;
1044     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
1045     NameServerRemote_Msg nsMsg;
1046     NameServerRemote_Msg *replyMsg;
1047     fd_set rfds;
1048     int ret = 0, sock, maxfd, waitFd;
1049     struct timeval tv;
1050     uint64_t buf = 1;
1051     int err;
1052     UInt i;
1053     static int seqNum = 0;
1054     Bool done = FALSE;
1055     UInt16 clusterId;
1057     if (strlen(name) >= MAXNAMEINCHAR) {
1058         LOG0("Name is too long in remote query\n");
1059         return NameServer_E_NAMETOOLONG;
1060     }
1062     if (strlen(obj->name) >= MAXNAMEINCHAR) {
1063         LOG0("Instance name is too long for remote query\n");
1064         return NameServer_E_NAMETOOLONG;
1065     }
1067     /* Set Timeout to wait: */
1068     tv.tv_sec = 0;
1069     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
1071     /* Create request message and send to remote: */
1072     clusterId = procId - MultiProc_getBaseIdOfCluster();
1073     sock = NameServer_module->comm[clusterId].sendSock;
1074     if (sock == INVALIDSOCKET) {
1075         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
1076              procId);
1077         status = NameServer_E_RESOURCE;
1078         goto exit;
1079     }
1081     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
1083     memset(&nsMsg, 0, sizeof(NameServerRemote_Msg));
1084     /* Create request message and send to remote processor: */
1085     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
1086     nsMsg.request = NAMESERVER_REQUEST;
1087     nsMsg.requestStatus = 0;
1088     nsMsg.valueLen = *len;
1089     nsMsg.seqNum = seqNum++;
1091     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
1092     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1094     LOG3("NameServer_getRemote: requesting from procId %d, %s: %s\n",
1095             procId, (String)nsMsg.instanceName, (String)nsMsg.name);
1097     err = send(sock, &nsMsg, sizeof(NameServerRemote_Msg), 0);
1098     if (err < 0) {
1099         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1100              errno, strerror(errno))
1101         status = NameServer_E_FAIL;
1102         goto exit;
1103     }
1105     while (!done) {
1106         /* Block on waitFd for signal from listener thread: */
1107         waitFd = NameServer_module->waitFd;
1108         FD_ZERO(&rfds);
1109         FD_SET(waitFd, &rfds);
1110         maxfd = waitFd + 1;
1111         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1113         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1115         if (ret == -1) {
1116             LOG0("NameServer_getRemote: select failed.")
1117             status = NameServer_E_FAIL;
1118             goto exit;
1119         }
1120         else if (!ret) {
1121             LOG0("NameServer_getRemote: select timed out.\n")
1122             status = NameServer_E_TIMEOUT;
1123             goto exit;
1124         }
1126         if (FD_ISSET(waitFd, &rfds)) {
1127             /* Read, just to balance the write: */
1128             read(waitFd, &buf, sizeof(uint64_t));
1130             /* Process response: */
1131             replyMsg = &NameServer_module->nsMsg;
1133             if ((int)(replyMsg->seqNum) != seqNum - 1) {
1134                 /* Ignore responses without current sequence # */
1135                 continue;
1136             }
1138             if (replyMsg->requestStatus) {
1139                 /* name is found */
1141                 /* set length to amount of data that was copied */
1142                 *len = replyMsg->valueLen;
1144                 /* set the contents of value */
1145                 if (*len <= sizeof (Bits32)) {
1146                     *(UInt32 *)value = (UInt32)replyMsg->value;
1147                     LOG4("NameServer_getRemote: Reply from: %d, %s: "
1148                             "name: %s, value: 0x%x\n", procId,
1149                             (String)replyMsg->instanceName,
1150                             (String)replyMsg->name, *(UInt32 *)value);
1151                 }
1152                 else {
1153                     memcpy(value, replyMsg->valueBuf, *len);
1154                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1155                         procId, (String)replyMsg->instanceName)
1156                     for (i = 0; i < *len/4; i++) {
1157                         LOG2("%s, value buffer content: 0x%x...\n",
1158                             (String)replyMsg->name, ((uint32_t *)value)[i])
1159                     }
1160                 }
1162                 goto exit;
1163             }
1164             else {
1165                 /* name is not found */
1166                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1167                      (String)replyMsg->instanceName, (String)replyMsg->name)
1169                 /* set status to not found */
1170                 status = NameServer_E_NOTFOUND;
1171             }
1172         }
1173         done= TRUE;
1174     }
1176 exit:
1177     return (status);
1180 /* Function to retrieve the value portion of a name/value pair from
1181  * local table.
1182  */
1183 Int NameServer_get(NameServer_Handle handle,
1184                String            name,
1185                Ptr               value,
1186                UInt32 *          len,
1187                UInt16            procId[])
1189     Int status = NameServer_S_SUCCESS;
1190     UInt16 numProcs;
1191     UInt32 i;
1192     UInt16 clusterId;
1193     UInt16 baseId;
1195     numProcs = MultiProc_getNumProcsInCluster();
1196     baseId = MultiProc_getBaseIdOfCluster();
1198     /*
1199      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1200      * since this goes in a daemon, it will not be necessary.
1201      */
1203     if (procId == NULL) {
1204         status = NameServer_getLocal(handle, name, value, len);
1205         if (status == NameServer_E_NOTFOUND) {
1206             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1208                 /* getLocal call already covers "self", keep going */
1209                 if ((baseId + clusterId) == MultiProc_self()) {
1210                     continue;
1211                 }
1213                 status = NameServer_getRemote(handle, name, value, len,
1214                         baseId + clusterId);
1216                 if (status >= 0) {
1217                     break;
1218                 }
1219             }
1220         }
1221     }
1222     else {
1223         /*
1224          *  Search the query list. It might contain the local proc
1225          *  somewhere in the list.
1226          */
1227         i = 0;
1228         while (procId[i] != MultiProc_INVALIDID) {
1229             if (procId[i] == MultiProc_self()) {
1230                 status = NameServer_getLocal(handle, name, value, len);
1231             }
1232             else {
1233                 status = NameServer_getRemote(handle, name, value, len,
1234                         procId[i]);
1235             }
1237             if (status >= 0) {
1238                 break;
1239             }
1241             i++;
1242         }
1243     }
1245     if (status == NameServer_E_RESOURCE) {
1246         status = NameServer_E_NOTFOUND;
1247     }
1249     return (status);
1252 /* Gets a 32-bit value by name */
1253 Int NameServer_getUInt32(NameServer_Handle handle,
1254                      String            name,
1255                      Ptr               value,
1256                      UInt16            procId[])
1258     Int  status;
1259     UInt32 len = sizeof(UInt32);
1261     assert(handle != NULL);
1262     assert(name   != NULL);
1263     assert(value  != NULL);
1264     assert(NameServer_module->refCount != 0);
1266     status = NameServer_get(handle, name, value, &len, procId);
1268     return (status);
1271 /* Function to Retrieve the value portion of a name/value pair from
1272  * local table.
1273  */
1274 Int NameServer_getLocal(NameServer_Handle handle,
1275                     String            name,
1276                     Ptr               value,
1277                     UInt32 *          len)
1279     Int status = NameServer_E_NOTFOUND;
1280     NameServer_TableEntry * node = NULL;
1281     NameServer_TableEntry * temp = NULL;
1282     Bool done   = FALSE;
1283     UInt32 length;
1284     UInt32 hash;
1286     assert(handle != NULL);
1287     assert(name   != NULL);
1288     assert(value  != NULL);
1289     assert(len    != NULL);
1290     assert(NameServer_module->refCount != 0);
1292     length = *len;
1294     /* Calculate the hash */
1295     hash = stringHash(name);
1297     pthread_mutex_lock(&handle->gate);
1299     /* Traverse the list to find duplicate check */
1300     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1301         if (node->hash == hash) {
1302             if (node->collide == TRUE) {
1303                 temp = node;
1304                 while (temp) {
1305                     if (strcmp(temp->name, name) == 0u){
1306                         if (length <= node->len) {
1307                             memcpy(value, node->value, length);
1308                             *len = length;
1309                         }
1310                         else {
1311                             memcpy(value, node->value, node->len);
1312                             *len = node->len;
1313                         }
1314                         done = TRUE;
1315                         break;
1316                     }
1317                     temp = temp->next;
1318                 }
1319                 break;
1320             }
1321             else {
1322                 if (length <= node->len) {
1323                     memcpy(value, node->value, length);
1324                     *len = length;
1325                 }
1326                 else {
1327                     memcpy(value, node->value, node->len);
1328                     *len = node->len;
1329                 }
1330                 done = TRUE;
1331                 break;
1332             }
1333         }
1334     }
1336     pthread_mutex_unlock(&handle->gate);
1338     if (done == FALSE) {
1339         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1340     }
1341     else {
1342         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1343              node->name, (UInt32)node->value)
1344         status = NameServer_S_SUCCESS;
1345     }
1347     return (status);
1350 /*
1351  *  Gets a 32-bit value by name from the local table
1352  *
1353  *  If the name is found, the 32-bit value is copied into the value
1354  *  argument and a success status is returned.
1355  *
1356  *  If the name is not found, zero is returned in len and the contents
1357  *  of value are not modified. Not finding a name is not considered
1358  *  an error.
1359  *
1360  *  This function only searches the local name/value table.
1361  *
1362  */
1363 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1365     Int                 status;
1366     UInt32              len    = sizeof(UInt32);
1368     assert(handle != NULL);
1369     assert(name   != NULL);
1370     assert(value  != NULL);
1371     assert(NameServer_module->refCount != 0);
1373     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1374     status = NameServer_getLocal(handle, name, value, &len);
1376     return (status);
1379 /*
1380  *  ======== NameServer_attach ========
1381  */
1382 Int NameServer_attach(UInt16 procId)
1384     Int status = NameServer_S_SUCCESS;
1385     int sock;
1386     int err;
1387     UInt16 clId;
1388     uint64_t event;
1390     /* procId already validated in API layer */
1391     clId = procId - MultiProc_getBaseIdOfCluster();
1393     pthread_mutex_lock(&NameServer_module->attachGate);
1395     LOG2("NameServer_attach: --> procId=%d, refCount=%d\n",
1396             procId, NameServer_module->comm[clId].refCount)
1398     /* must reference count because we have multiple clients */
1399     if (NameServer_module->comm[clId].refCount > 0) {
1400         NameServer_module->comm[clId].refCount++;
1401         goto done;
1402     }
1404     /* create socket for sending messages to remote processor */
1405     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1406     if (sock < 0) {
1407         status = NameServer_E_FAIL;
1408         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1409                 strerror(errno));
1410         goto done;
1411     }
1412     NameServer_module->comm[clId].sendSock = sock;
1413     LOG2("NameServer_attach: created send socket: %d, procId %d\n", sock,
1414             procId);
1416     err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
1417     if (err < 0) {
1418         status = NameServer_E_FAIL;
1419         LOG3("NameServer_attach: connect failed: procId=%d, errno=%d (%s)\n",
1420                 procId, errno, strerror(errno));
1421         goto done;
1422     }
1424     /* create socket for receiving messages from remote processor */
1425     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1426     if (sock < 0) {
1427         status = NameServer_E_FAIL;
1428         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1429                 strerror(errno));
1430         goto done;
1431     }
1432     NameServer_module->comm[clId].recvSock = sock;
1433     LOG2("NameServer_attach: created receive socket: %d, procId %d\n", sock,
1434             procId);
1436     err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
1437     if (err < 0) {
1438         status = NameServer_E_FAIL;
1439         LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
1440                 strerror(errno));
1441         goto done;
1442     }
1444     /* getting here means we have successfully attached */
1445     NameServer_module->comm[clId].refCount++;
1447     pthread_mutex_unlock(&NameServer_module->attachGate);
1449     /* tell the listener thread to add new receive sockets */
1450     event = NameServer_Event_REFRESH;
1451     write(NameServer_module->unblockFd, &event, sizeof(event));
1453     /* wait for ACK event */
1454     read(NameServer_module->waitFd, &event, sizeof(event));
1456     pthread_mutex_lock(&NameServer_module->attachGate);
1458 done:
1459     if (status < 0) {
1460         sock = NameServer_module->comm[clId].recvSock;
1461         if (sock != INVALIDSOCKET) {
1462             LOG1("    closing receive socket: %d\n", sock)
1463             close(sock);
1464             NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1465         }
1467         sock = NameServer_module->comm[clId].sendSock;
1468         if (sock != INVALIDSOCKET) {
1469             LOG1("    closing send socket: %d\n", sock)
1470             close(sock);
1471             NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1472         }
1473     }
1475     LOG2("NameServer_attach: <-- refCount=%d, status=%d\n",
1476             NameServer_module->comm[clId].refCount, status)
1478     pthread_mutex_unlock(&NameServer_module->attachGate);
1480     return (status);
1483 /*
1484  *  ======== NameServer_detach ========
1485  */
1486 Int NameServer_detach(UInt16 procId)
1488     Int status = NameServer_S_SUCCESS;
1489     UInt16 clId;
1490     int sendSock;
1491     int recvSock;
1492     uint64_t event;
1494     /* procId already validated in API layer */
1495     clId = procId - MultiProc_getBaseIdOfCluster();
1497     pthread_mutex_lock(&NameServer_module->attachGate);
1499     LOG2("NameServer_detach: --> procId=%d, refCount=%d\n",
1500             procId, NameServer_module->comm[clId].refCount)
1502     /* decrement reference count regardless of outcome below */
1503     if (--NameServer_module->comm[clId].refCount > 0) {
1504         pthread_mutex_unlock(&NameServer_module->attachGate);
1505         goto done;
1506     }
1508     /* remove sockets from active list */
1509     sendSock = NameServer_module->comm[clId].sendSock;
1510     NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1512     recvSock = NameServer_module->comm[clId].recvSock;
1513     NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1515     pthread_mutex_unlock(&NameServer_module->attachGate);
1517     /* tell the listener thread to remove old sockets */
1518     event = NameServer_Event_REFRESH;
1519     write(NameServer_module->unblockFd, &event, sizeof(event));
1521     /* wait for ACK event */
1522     read(NameServer_module->waitFd, &event, sizeof(event));
1524     /* close the sending socket */
1525     LOG1("NameServer_detach: closing socket: %d\n", sendSock)
1526     close(sendSock);
1528     /* close the receiving socket */
1529     LOG1("NameServer_detach: closing socket: %d\n", recvSock)
1530     close(recvSock);
1532 done:
1533     LOG2("NameServer_detach: <-- refCount=%d, status=%d\n",
1534             NameServer_module->comm[clId].refCount, status)
1535     return (status);
1538 #if defined (__cplusplus)
1540 #endif /* defined (__cplusplus) */