f7982c799642ac78a0b51ccaa5c7ca9686ef719e
[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;
683     Int status = 0;
685     assert(params != NULL);
686     assert(name != NULL);
687     assert(NameServer_module->refCount != 0);
689     LOG1("NameServer_create(): '%s'\n", name)
691     pthread_mutex_lock(&NameServer_module->modGate);
693     status = pthread_mutexattr_init(&mutex_attr);
694     assert(status == 0);
696     /* check if the name is already created or not */
697     handle = NameServer_getHandle(name);
698     if (handle != NULL) {
699         if (memcmp((Ptr)&handle->params, (Ptr)params,
700             sizeof(NameServer_Params)) == 0) {
701             handle->refCount++;
702         }
703         else {
704             LOG0("NameServer_create: NameServer params mismatch\n")
705             handle = NULL;
706         }
707         goto leave;
708     }
709     else {
710         handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
711     }
713     if (!handle) {
714         LOG0("NameServer_create: NameServer_Handle alloc failed\n")
715         goto leave;
716     }
718     handle->refCount = 1;
719     handle->name = (String)malloc(strlen(name) + 1u);
720     if (!handle->name) {
721         LOG0("NameServer_create: instance name alloc failed\n")
722         goto cleanup;
723     }
724     strncpy(handle->name, name, strlen (name) + 1u);
725     memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
727     if (params->maxValueLen < sizeof(UInt32)) {
728         handle->params.maxValueLen = sizeof(UInt32);
729     }
730     else {
731         handle->params.maxValueLen = params->maxValueLen;
732     }
734     CIRCLEQ_INIT(&handle->nameList);
735     handle->count = 0u;
737     /* Put in the local list */
738     CIRCLEQ_elemClear(&handle->elem);
739     CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
741     /*
742      * NameServer_removeEntry() enters gate and is called by
743      * NameServer_remove() while holding the gate.
744      */
745     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
746     pthread_mutex_init(&handle->gate, &mutex_attr);
748     goto leave;
750 cleanup:
751     free(handle);
752     handle = NULL;
754 leave:
755     pthread_mutexattr_destroy(&mutex_attr);
756     pthread_mutex_unlock(&NameServer_module->modGate);
758     return (handle);
761 /*
762  *  ======== NameServer_delete ========
763  *  Delete a name server instance
764  */
765 Int NameServer_delete(NameServer_Handle *handle)
767     Int status = NameServer_S_SUCCESS;
768     struct NameServer_Object *obj;
770     assert(handle != NULL);
771     assert(*handle != NULL);
772     assert(NameServer_module->refCount != 0);
774     obj = *(struct NameServer_Object **)handle;
776     pthread_mutex_lock(&NameServer_module->modGate);
778     obj->refCount--;
779     if (obj->refCount != 0) {
780         goto leave;
781     }
783     /* delete each entry on the name list */
784     while (obj->nameList.cqh_first != (void *)&obj->nameList) {
785         NameServer_removeEntry(*handle, (Ptr)(obj->nameList.cqh_first));
786     }
788     /* free the instance name */
789     if (obj->name != NULL) {
790         free(obj->name);
791         obj->name = NULL;
792     }
794     /* destroy the mutex */
795     pthread_mutex_destroy(&obj->gate);
797     /* remove from objList */
798     CIRCLEQ_REMOVE(&NameServer_module->objList, obj, elem);
800     /* finally, free the instance object */
801     free(obj);
803     /* set the caller's handle to null */
804     (*handle) = NULL;
806 leave:
807     pthread_mutex_unlock(&NameServer_module->modGate);
809     return (status);
812 /* Adds a variable length value into the local NameServer table */
813 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
815     Int                 status = NameServer_S_SUCCESS;
816     NameServer_TableEntry * node = NULL;
817     NameServer_TableEntry * new_node = NULL;
818     Bool                found = FALSE;
819     UInt32              hash;
821     assert(handle != NULL);
822     assert(name     != NULL);
823     assert(buf      != NULL);
824     assert(len      != 0);
825     assert(NameServer_module->refCount != 0);
827     /* Calculate the hash */
828     hash = stringHash(name);
830     pthread_mutex_lock(&handle->gate);
832     if (strlen(name) > handle->params.maxNameLen - 1) {
833         status = NameServer_E_INVALIDARG;
834         LOG0("NameServer_add: name length exceeded maximum!\n")
835         new_node = NULL;
836         goto exit;
837     }
839     if (len > handle->params.maxValueLen) {
840         status = NameServer_E_INVALIDARG;
841         LOG0("NameServer_add: value length exceeded maximum!\n")
842         new_node = NULL;
843         goto exit;
844     }
846     /* Traverse the list to find duplicate check */
847     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
848         /* Hash matches */
849         if (node->hash == hash) {
850             /* If the name matches, incase hash is duplicate */
851             if (strcmp(node->name, name) == 0) {
852                 if (handle->params.checkExisting == TRUE) {
853                     status = NameServer_E_INVALIDARG;
854                     LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
855                     break;
856                 }
857             }
858             else {
859                 found = TRUE;
860                 break;
861             } /* name does not match */
862         } /* hash does not match */
863     } /* CIRCLEQ_traverse */
865     if (status != NameServer_S_SUCCESS) {
866         new_node = NULL;
867         goto exit;
868     }
870     /* Now add the new entry. */
871     new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
872     if (new_node == NULL) {
873         status = NameServer_E_MEMORY;
874         LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
876         goto exit;
877     }
879     new_node->hash    = hash;
880     new_node->collide = found; /* Indicate if there is a collision*/
881     new_node->len     = len;
882     new_node->next    = NULL;
883     new_node->name = (String)malloc(strlen(name) + 1u);
884     new_node->value  = (Ptr)malloc(len);
885     strncpy(new_node->name, name, strlen(name) + 1u);
886     memcpy((Ptr)new_node->value, (Ptr)buf, len);
888     if (found == TRUE) {
889         /* If hash is found, need to stitch the list to link the
890          * new node to the existing node with the same hash.
891          */
892         new_node->next = node->next;
893         node->next = new_node;
894     }
895     else {
896         /* put the new node into the list */
897         CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
898     }
900     handle->count++;
902     LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
903          name, *(UInt32 *)buf)
905 exit:
906     pthread_mutex_unlock(&handle->gate);
908     return (new_node);
912 /* Function to add a UInt32 value into a name server. */
913 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
915     Ptr entry = NULL;
917     assert(handle != NULL);
918     assert(name   != NULL);
919     assert(NameServer_module->refCount != 0);
921     entry = NameServer_add(handle, name, &value, sizeof(UInt32));
923     return (entry);
926 /* Function to remove a name/value pair from a name server. */
927 Int NameServer_remove(NameServer_Handle handle, String name)
929     Int                 status = NameServer_S_SUCCESS;
930     NameServer_TableEntry *prev = NULL;
931     NameServer_TableEntry *temp = NULL;
932     NameServer_TableEntry *node = NULL;
933     Bool                done   = FALSE;
934     UInt32              hash;
936     assert(handle != NULL);
937     assert(name   != NULL);
938     assert(NameServer_module->refCount != 0);
940     /* Calculate the hash */
941     hash = stringHash(name);
943     pthread_mutex_lock(&handle->gate);
945     /* Traverse the list to find duplicate check */
946     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
947         /* Hash matchs */
948         if (node->hash == hash) {
949             if (node->collide == TRUE) {
950                 if (strcmp(node->name, name) == 0){
951                     free(node->value);
952                     free(node->name);
953                     memcpy((Ptr)node, (Ptr) node->next,
954                            sizeof(NameServer_TableEntry));
955                     node->next = node->next->next;
956                     free(node->next);
957                     handle->count--;
958                     done = TRUE;
959                     break;
960                 }
961                 else {
962                     prev = node;
963                     temp = node->next;
964                     while (temp) {
965                         if (strcmp(temp->name, name) == 0){
966                             free(temp->value);
967                             free(temp->name);
968                             prev->next = temp->next;
969                             free(temp);
970                             handle->count--;
971                             done = TRUE;
972                             break;
973                         }
974                         temp = temp->next;
975                     }
976                     break;
977                 }
978             }
979             else {
980                 NameServer_removeEntry(handle, (Ptr)node);
982                 done = TRUE;
983                 break;
984             }
985         }
986     }
988     if (done == FALSE) {
989         status = NameServer_E_INVALIDARG;
990         LOG1("NameServer_remove %d Entry not found!\n", status)
991     }
993     pthread_mutex_unlock(&handle->gate);
995     return (status);
998 /* Function to remove a name/value pair from a name server. */
999 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
1001     Int  status = NameServer_S_SUCCESS;
1002     NameServer_TableEntry * node;
1004     assert(handle != NULL);
1005     assert(entry  != NULL);
1006     assert(NameServer_module->refCount != 0);
1008     pthread_mutex_lock(&handle->gate);
1010     node = (NameServer_TableEntry *)entry;
1012     free(node->value);
1013     free(node->name);
1014     CIRCLEQ_REMOVE(&handle->nameList, node, elem);
1015     free(node);
1016     handle->count--;
1018     pthread_mutex_unlock(&handle->gate);
1020     return (status);
1024 /* Initialize this config-params structure with supplier-specified
1025  * defaults before instance creation.
1026  */
1027 Void NameServer_Params_init(NameServer_Params * params)
1029     assert(params != NULL);
1031     memcpy(params, &(NameServer_module->defInstParams),
1032            sizeof (NameServer_Params));
1036 Int NameServer_getRemote(NameServer_Handle handle,
1037                      String            name,
1038                      Ptr               value,
1039                      UInt32 *          len,
1040                      UInt16            procId)
1042     Int status = NameServer_S_SUCCESS;
1043     struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
1044     NameServerRemote_Msg nsMsg;
1045     NameServerRemote_Msg *replyMsg;
1046     fd_set rfds;
1047     int ret = 0, sock, maxfd, waitFd;
1048     struct timeval tv;
1049     uint64_t buf = 1;
1050     int err;
1051     int i;
1052     static int seqNum = 0;
1053     Bool done = FALSE;
1054     UInt16 clusterId;
1056     if (strlen(name) >= MAXNAMEINCHAR) {
1057         LOG0("Name is too long in remote query\n");
1058         return NameServer_E_NAMETOOLONG;
1059     }
1061     if (strlen(obj->name) >= MAXNAMEINCHAR) {
1062         LOG0("Instance name is too long for remote query\n");
1063         return NameServer_E_NAMETOOLONG;
1064     }
1066     /* Set Timeout to wait: */
1067     tv.tv_sec = 0;
1068     tv.tv_usec = NAMESERVER_GET_TIMEOUT;
1070     /* Create request message and send to remote: */
1071     clusterId = procId - MultiProc_getBaseIdOfCluster();
1072     sock = NameServer_module->comm[clusterId].sendSock;
1073     if (sock == INVALIDSOCKET) {
1074         LOG1("NameServer_getRemote: no socket connection to processor %d\n",
1075              procId);
1076         status = NameServer_E_RESOURCE;
1077         goto exit;
1078     }
1080     LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
1082     memset(&nsMsg, 0, sizeof(NameServerRemote_Msg));
1083     /* Create request message and send to remote processor: */
1084     nsMsg.reserved = NAMESERVER_MSG_TOKEN;
1085     nsMsg.request = NAMESERVER_REQUEST;
1086     nsMsg.requestStatus = 0;
1087     nsMsg.valueLen = *len;
1088     nsMsg.seqNum = seqNum++;
1090     strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
1091     strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1093     LOG3("NameServer_getRemote: requesting from procId %d, %s: %s\n",
1094             procId, (String)nsMsg.instanceName, (String)nsMsg.name);
1096     err = send(sock, &nsMsg, sizeof(NameServerRemote_Msg), 0);
1097     if (err < 0) {
1098         LOG2("NameServer_getRemote: send failed: %d, %s\n",
1099              errno, strerror(errno))
1100         status = NameServer_E_FAIL;
1101         goto exit;
1102     }
1104     while (!done) {
1105         /* Block on waitFd for signal from listener thread: */
1106         waitFd = NameServer_module->waitFd;
1107         FD_ZERO(&rfds);
1108         FD_SET(waitFd, &rfds);
1109         maxfd = waitFd + 1;
1110         LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1112         ret = select(maxfd, &rfds, NULL, NULL, &tv);
1114         if (ret == -1) {
1115             LOG0("NameServer_getRemote: select failed.")
1116             status = NameServer_E_FAIL;
1117             goto exit;
1118         }
1119         else if (!ret) {
1120             LOG0("NameServer_getRemote: select timed out.\n")
1121             status = NameServer_E_TIMEOUT;
1122             goto exit;
1123         }
1125         if (FD_ISSET(waitFd, &rfds)) {
1126             /* Read, just to balance the write: */
1127             read(waitFd, &buf, sizeof(uint64_t));
1129             /* Process response: */
1130             replyMsg = &NameServer_module->nsMsg;
1132             if (replyMsg->seqNum != seqNum - 1) {
1133                 /* Ignore responses without current sequence # */
1134                 continue;
1135             }
1137             if (replyMsg->requestStatus) {
1138                 /* name is found */
1140                 /* set length to amount of data that was copied */
1141                 *len = replyMsg->valueLen;
1143                 /* set the contents of value */
1144                 if (*len <= sizeof (Bits32)) {
1145                     *(UInt32 *)value = (UInt32)replyMsg->value;
1146                     LOG4("NameServer_getRemote: Reply from: %d, %s: "
1147                             "name: %s, value: 0x%x\n", procId,
1148                             (String)replyMsg->instanceName,
1149                             (String)replyMsg->name, *(UInt32 *)value);
1150                 }
1151                 else {
1152                     memcpy(value, replyMsg->valueBuf, *len);
1153                     LOG2("NameServer_getRemote: Reply from: %d, %s:",
1154                         procId, (String)replyMsg->instanceName)
1155                     for (i = 0; i < *len/4; i++) {
1156                         LOG2("%s, value buffer content: 0x%x...\n",
1157                             (String)replyMsg->name, ((uint32_t *)value)[i])
1158                     }
1159                 }
1161                 goto exit;
1162             }
1163             else {
1164                 /* name is not found */
1165                 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1166                      (String)replyMsg->instanceName, (String)replyMsg->name)
1168                 /* set status to not found */
1169                 status = NameServer_E_NOTFOUND;
1170             }
1171         }
1172         done= TRUE;
1173     }
1175 exit:
1176     return (status);
1179 /* Function to retrieve the value portion of a name/value pair from
1180  * local table.
1181  */
1182 Int NameServer_get(NameServer_Handle handle,
1183                String            name,
1184                Ptr               value,
1185                UInt32 *          len,
1186                UInt16            procId[])
1188     Int status = NameServer_S_SUCCESS;
1189     UInt16 numProcs;
1190     UInt32 i;
1191     UInt16 clusterId;
1192     UInt16 baseId;
1194     numProcs = MultiProc_getNumProcsInCluster();
1195     baseId = MultiProc_getBaseIdOfCluster();
1197     /*
1198      * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1199      * since this goes in a daemon, it will not be necessary.
1200      */
1202     if (procId == NULL) {
1203         status = NameServer_getLocal(handle, name, value, len);
1204         if (status == NameServer_E_NOTFOUND) {
1205             for (clusterId = 0; clusterId < numProcs; clusterId++) {
1207                 /* getLocal call already covers "self", keep going */
1208                 if ((baseId + clusterId) == MultiProc_self()) {
1209                     continue;
1210                 }
1212                 status = NameServer_getRemote(handle, name, value, len,
1213                         baseId + clusterId);
1215                 if (status >= 0) {
1216                     break;
1217                 }
1218             }
1219         }
1220     }
1221     else {
1222         /*
1223          *  Search the query list. It might contain the local proc
1224          *  somewhere in the list.
1225          */
1226         i = 0;
1227         while (procId[i] != MultiProc_INVALIDID) {
1228             if (procId[i] == MultiProc_self()) {
1229                 status = NameServer_getLocal(handle, name, value, len);
1230             }
1231             else {
1232                 status = NameServer_getRemote(handle, name, value, len,
1233                         procId[i]);
1234             }
1236             if (status >= 0) {
1237                 break;
1238             }
1240             i++;
1241         }
1242     }
1244     if (status == NameServer_E_RESOURCE) {
1245         status = NameServer_E_NOTFOUND;
1246     }
1248     return (status);
1251 /* Gets a 32-bit value by name */
1252 Int NameServer_getUInt32(NameServer_Handle handle,
1253                      String            name,
1254                      Ptr               value,
1255                      UInt16            procId[])
1257     Int  status;
1258     UInt32 len = sizeof(UInt32);
1260     assert(handle != NULL);
1261     assert(name   != NULL);
1262     assert(value  != NULL);
1263     assert(NameServer_module->refCount != 0);
1265     status = NameServer_get(handle, name, value, &len, procId);
1267     return (status);
1270 /* Function to Retrieve the value portion of a name/value pair from
1271  * local table.
1272  */
1273 Int NameServer_getLocal(NameServer_Handle handle,
1274                     String            name,
1275                     Ptr               value,
1276                     UInt32 *          len)
1278     Int status = NameServer_E_NOTFOUND;
1279     NameServer_TableEntry * node = NULL;
1280     NameServer_TableEntry * temp = NULL;
1281     Bool done   = FALSE;
1282     UInt32 length;
1283     UInt32 hash;
1285     assert(handle != NULL);
1286     assert(name   != NULL);
1287     assert(value  != NULL);
1288     assert(len    != NULL);
1289     assert(NameServer_module->refCount != 0);
1291     length = *len;
1293     /* Calculate the hash */
1294     hash = stringHash(name);
1296     pthread_mutex_lock(&handle->gate);
1298     /* Traverse the list to find duplicate check */
1299     CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1300         if (node->hash == hash) {
1301             if (node->collide == TRUE) {
1302                 temp = node;
1303                 while (temp) {
1304                     if (strcmp(temp->name, name) == 0u){
1305                         if (length <= node->len) {
1306                             memcpy(value, node->value, length);
1307                             *len = length;
1308                         }
1309                         else {
1310                             memcpy(value, node->value, node->len);
1311                             *len = node->len;
1312                         }
1313                         done = TRUE;
1314                         break;
1315                     }
1316                     temp = temp->next;
1317                 }
1318                 break;
1319             }
1320             else {
1321                 if (length <= node->len) {
1322                     memcpy(value, node->value, length);
1323                     *len = length;
1324                 }
1325                 else {
1326                     memcpy(value, node->value, node->len);
1327                     *len = node->len;
1328                 }
1329                 done = TRUE;
1330                 break;
1331             }
1332         }
1333     }
1335     pthread_mutex_unlock(&handle->gate);
1337     if (done == FALSE) {
1338         LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1339     }
1340     else {
1341         LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1342              node->name, (UInt32)node->value)
1343         status = NameServer_S_SUCCESS;
1344     }
1346     return (status);
1349 /*
1350  *  Gets a 32-bit value by name from the local table
1351  *
1352  *  If the name is found, the 32-bit value is copied into the value
1353  *  argument and a success status is returned.
1354  *
1355  *  If the name is not found, zero is returned in len and the contents
1356  *  of value are not modified. Not finding a name is not considered
1357  *  an error.
1358  *
1359  *  This function only searches the local name/value table.
1360  *
1361  */
1362 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1364     Int                 status;
1365     UInt32              len    = sizeof(UInt32);
1367     assert(handle != NULL);
1368     assert(name   != NULL);
1369     assert(value  != NULL);
1370     assert(NameServer_module->refCount != 0);
1372     LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1373     status = NameServer_getLocal(handle, name, value, &len);
1375     return (status);
1378 /*
1379  *  ======== NameServer_attach ========
1380  */
1381 Int NameServer_attach(UInt16 procId)
1383     Int status = NameServer_S_SUCCESS;
1384     int sock;
1385     int err;
1386     UInt16 clId;
1387     uint64_t event;
1389     /* procId already validated in API layer */
1390     clId = procId - MultiProc_getBaseIdOfCluster();
1392     pthread_mutex_lock(&NameServer_module->attachGate);
1394     LOG2("NameServer_attach: --> procId=%d, refCount=%d\n",
1395             procId, NameServer_module->comm[clId].refCount)
1397     /* must reference count because we have multiple clients */
1398     if (NameServer_module->comm[clId].refCount > 0) {
1399         NameServer_module->comm[clId].refCount++;
1400         goto done;
1401     }
1403     /* create socket for sending messages to remote processor */
1404     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1405     if (sock < 0) {
1406         status = NameServer_E_FAIL;
1407         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1408                 strerror(errno));
1409         goto done;
1410     }
1411     NameServer_module->comm[clId].sendSock = sock;
1412     LOG2("NameServer_attach: created send socket: %d, procId %d\n", sock,
1413             procId);
1415     err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
1416     if (err < 0) {
1417         status = NameServer_E_FAIL;
1418         LOG3("NameServer_attach: connect failed: procId=%d, errno=%d (%s)\n",
1419                 procId, errno, strerror(errno));
1420         goto done;
1421     }
1423     /* create socket for receiving messages from remote processor */
1424     sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
1425     if (sock < 0) {
1426         status = NameServer_E_FAIL;
1427         LOG2("NameServer_attach: socket failed: %d, %s\n", errno,
1428                 strerror(errno));
1429         goto done;
1430     }
1431     NameServer_module->comm[clId].recvSock = sock;
1432     LOG2("NameServer_attach: created receive socket: %d, procId %d\n", sock,
1433             procId);
1435     err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
1436     if (err < 0) {
1437         status = NameServer_E_FAIL;
1438         LOG2("NameServer_attach: bind failed: %d, %s\n", errno,
1439                 strerror(errno));
1440         goto done;
1441     }
1443     /* getting here means we have successfully attached */
1444     NameServer_module->comm[clId].refCount++;
1446     pthread_mutex_unlock(&NameServer_module->attachGate);
1448     /* tell the listener thread to add new receive sockets */
1449     event = NameServer_Event_REFRESH;
1450     write(NameServer_module->unblockFd, &event, sizeof(event));
1452     /* wait for ACK event */
1453     read(NameServer_module->waitFd, &event, sizeof(event));
1455     pthread_mutex_lock(&NameServer_module->attachGate);
1457 done:
1458     if (status < 0) {
1459         sock = NameServer_module->comm[clId].recvSock;
1460         if (sock != INVALIDSOCKET) {
1461             LOG1("    closing receive socket: %d\n", sock)
1462             close(sock);
1463             NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1464         }
1466         sock = NameServer_module->comm[clId].sendSock;
1467         if (sock != INVALIDSOCKET) {
1468             LOG1("    closing send socket: %d\n", sock)
1469             close(sock);
1470             NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1471         }
1472     }
1474     LOG2("NameServer_attach: <-- refCount=%d, status=%d\n",
1475             NameServer_module->comm[clId].refCount, status)
1477     pthread_mutex_unlock(&NameServer_module->attachGate);
1479     return (status);
1482 /*
1483  *  ======== NameServer_detach ========
1484  */
1485 Int NameServer_detach(UInt16 procId)
1487     Int status = NameServer_S_SUCCESS;
1488     UInt16 clId;
1489     int sendSock;
1490     int recvSock;
1491     uint64_t event;
1493     /* procId already validated in API layer */
1494     clId = procId - MultiProc_getBaseIdOfCluster();
1496     pthread_mutex_lock(&NameServer_module->attachGate);
1498     LOG2("NameServer_detach: --> procId=%d, refCount=%d\n",
1499             procId, NameServer_module->comm[clId].refCount)
1501     /* decrement reference count regardless of outcome below */
1502     if (--NameServer_module->comm[clId].refCount > 0) {
1503         pthread_mutex_unlock(&NameServer_module->attachGate);
1504         goto done;
1505     }
1507     /* remove sockets from active list */
1508     sendSock = NameServer_module->comm[clId].sendSock;
1509     NameServer_module->comm[clId].sendSock = INVALIDSOCKET;
1511     recvSock = NameServer_module->comm[clId].recvSock;
1512     NameServer_module->comm[clId].recvSock = INVALIDSOCKET;
1514     pthread_mutex_unlock(&NameServer_module->attachGate);
1516     /* tell the listener thread to remove old sockets */
1517     event = NameServer_Event_REFRESH;
1518     write(NameServer_module->unblockFd, &event, sizeof(event));
1520     /* wait for ACK event */
1521     read(NameServer_module->waitFd, &event, sizeof(event));
1523     /* close the sending socket */
1524     LOG1("NameServer_detach: closing socket: %d\n", sendSock)
1525     close(sendSock);
1527     /* close the receiving socket */
1528     LOG1("NameServer_detach: closing socket: %d\n", recvSock)
1529     close(recvSock);
1531 done:
1532     LOG2("NameServer_detach: <-- refCount=%d, status=%d\n",
1533             NameServer_module->comm[clId].refCount, status)
1534     return (status);
1537 #if defined (__cplusplus)
1539 #endif /* defined (__cplusplus) */