1 /*
2 * Copyright (c) 2012-2014, Texas Instruments Incorporated
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 <_NameServerRemoteRpmsg.h>
71 /* Socket utils: */
72 #include <SocketFxns.h>
74 #include <_lad.h>
76 #define MESSAGEQ_RPMSG_PORT 61
77 #define NAME_SERVER_RPMSG_ADDR 0
79 #define INVALIDSOCKET (-1)
81 #if defined (__cplusplus)
82 extern "C" {
83 #endif
86 /* =============================================================================
87 * Structures & Enums
88 * =============================================================================
89 */
91 /* Structure of entry in Name/Value table */
92 typedef struct NameServer_TableEntry_tag {
93 CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
94 /* List element */
95 UInt32 hash;
96 /* Hash value */
97 String name;
98 /* Name portion of the name/value pair. */
99 UInt len;
100 /* Length of the value field. */
101 Ptr value;
102 /* Value portion of the name/value entry. */
103 Bool collide;
104 /* Does the hash collide? */
105 struct NameServer_TableEntry_tag * next;
106 /* Pointer to the next entry, used incase of collision only */
107 } NameServer_TableEntry;
109 /* Structure defining object for the NameServer */
110 struct NameServer_Object {
111 CIRCLEQ_ENTRY(NameServer_Object) elem;
112 CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
113 String name; /* name of the instance */
114 NameServer_Params params; /* the parameter structure */
115 UInt32 count; /* count of entries */
116 UInt32 refCount; /* reference count to this object */
117 pthread_mutex_t gate; /* crit sect gate */
118 } NameServer_Object;
120 /* structure for NameServer module state */
121 typedef struct NameServer_ModuleObject {
122 CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
123 Int32 refCount;
124 int sendSock[MultiProc_MAXPROCESSORS];
125 /* Sockets for sending to remote proc nameserver ports: */
126 int recvSock[MultiProc_MAXPROCESSORS];
127 /* Sockets for recving from remote proc nameserver ports: */
128 pthread_t listener;
129 /* Listener thread for NameServer replies and requests. */
130 int unblockFd;
131 /* Event to post to exit listener. */
132 int waitFd;
133 /* Event to post to NameServer_get. */
134 NameServerMsg nsMsg;
135 /* NameServer Message cache. */
136 NameServer_Params defInstParams;
137 /* Default instance paramters */
138 pthread_mutex_t modGate;
139 } NameServer_ModuleObject;
141 #define CIRCLEQ_destruct(head) { \
142 (head)->cqh_first = NULL; \
143 (head)->cqh_last = NULL; \
144 }
146 #define CIRCLEQ_elemClear(elem) { \
147 (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
148 }
150 #define CIRCLEQ_traverse(x, y, tag) \
151 for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
153 /* =============================================================================
154 * Globals
155 * =============================================================================
156 */
157 /*
158 * NameServer_state
159 *
160 * Make the module gate "recursive" since NameServer_getHandle() needs to
161 * use it and NameServer_create() needs to hold it around its call to
162 * NameServer_getHandle(). Also, use the static initializer instead of a
163 * run-time init call, so we can use this gate immediately in _setup().
164 */
165 static NameServer_ModuleObject NameServer_state = {
166 .defInstParams.maxRuntimeEntries = 0u,
167 .defInstParams.tableHeap = NULL,
168 .defInstParams.checkExisting = TRUE,
169 .defInstParams.maxValueLen = 0u,
170 .defInstParams.maxNameLen = 16u,
171 #if defined(IPC_BUILDOS_ANDROID)
172 .modGate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
173 #else
174 // only _NP (non-portable) type available in CG tools which we're using
175 .modGate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
176 #endif
177 .refCount = 0
178 };
180 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
182 static const UInt32 stringCrcTab[256u] = {
183 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
184 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
185 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
186 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
187 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
188 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
189 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
190 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
191 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
192 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
193 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
194 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
195 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
196 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
197 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
198 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
199 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
200 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
201 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
202 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
203 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
204 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
205 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
206 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
207 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
208 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
209 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
210 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
211 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
212 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
213 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
214 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
215 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
216 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
217 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
218 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
219 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
220 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
221 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
222 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
223 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
224 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
225 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
226 };
228 static UInt32 stringHash(String s)
229 {
230 UInt32 hash = strlen(s);
231 UInt32 i;
233 for (i = 0; i < strlen(s); i++) {
234 hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
235 }
237 return (hash);
238 }
240 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
241 {
242 NameServer_Handle handle;
243 Int status = NameServer_E_FAIL;
244 int err;
245 uint64_t buf = 1;
246 int numBytes;
247 int waitFd = NameServer_module->waitFd;
249 if (msg->request == NAMESERVER_REQUEST) {
250 LOG2("NameServer Request: instanceName: %s, name: %s\n",
251 (String)msg->instanceName, (String)msg->name)
253 assert(msg->valueLen <= MAXVALUELEN);
254 /*
255 * Message is a request. Lookup name in NameServer table.
256 * Send a response message back to source processor.
257 */
258 handle = NameServer_getHandle((String)msg->instanceName);
260 if (handle != NULL) {
261 /* Search for the NameServer entry */
262 if (msg->valueLen <= sizeof (Bits32)) {
263 LOG0("Calling NameServer_getLocalUInt32...\n")
264 status = NameServer_getLocalUInt32(handle,
265 (String)msg->name, &msg->value);
266 }
267 else {
268 LOG0("Calling NameServer_getLocal...\n")
269 status = NameServer_getLocal(handle,
270 (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
271 }
272 }
274 LOG2("NameServer Response: instanceName: %s, name: %s,",
275 (String)msg->instanceName, (String)msg->name)
276 /* set the request status */
277 if (status < 0) {
278 LOG1(" Value not found, status: %d\n", status)
279 msg->requestStatus = 0;
280 }
281 else {
282 msg->requestStatus = 1;
283 LOG1(" Value: 0x%x\n", msg->value)
284 }
286 /* specify message as a response */
287 msg->request = NAMESERVER_RESPONSE;
288 msg->reserved = NAMESERVER_MSG_TOKEN;
290 /* send response message to remote processor */
291 err = send(NameServer_module->sendSock[procId], msg,
292 sizeof(NameServerMsg), 0);
293 if (err < 0) {
294 LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
295 }
296 }
297 else {
298 LOG2("NameServer Reply: instanceName: %s, name: %s",
299 (String)msg->instanceName, (String)msg->name)
300 LOG1(", value: 0x%x\n", msg->value)
302 /* Save the response message. */
303 memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
305 /* Post the eventfd upon which NameServer_get() is waiting */
306 numBytes = write(waitFd, &buf, sizeof(uint64_t));
307 }
308 }
311 static void *listener_cb(void *arg)
312 {
313 fd_set rfds;
314 int ret = 0, maxfd;
315 UInt16 procId;
316 struct sockaddr_rpmsg fromAddr;
317 unsigned int len;
318 NameServerMsg msg;
319 int byteCount;
320 UInt16 numProcs = MultiProc_getNumProcessors();
321 int sock;
323 LOG0("listener_cb: Entered Listener thread.\n")
325 do {
326 /* Wait for NameServer messages or unblockFd notification */
327 FD_ZERO(&rfds);
328 FD_SET(NameServer_module->unblockFd, &rfds);
329 maxfd = NameServer_module->unblockFd;
330 for (procId = 0; procId < numProcs; procId++) {
331 if (procId == MultiProc_self() ||
332 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
333 continue;
334 }
335 sock = NameServer_module->recvSock[procId];
336 FD_SET(sock, &rfds);
337 maxfd = MAX(sock, maxfd);
338 }
340 maxfd = maxfd + 1;
341 LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
342 NameServer_module->unblockFd, maxfd)
343 ret = select(maxfd, &rfds, NULL, NULL, NULL);
344 if (ret == -1) {
345 LOG0("listener_cb: select failed.")
346 break;
347 }
348 LOG0("NameServer: back from select()\n")
350 for (procId = 0; procId < numProcs; procId++) {
351 if (procId == MultiProc_self() ||
352 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
353 continue;
354 }
355 sock = NameServer_module->recvSock[procId];
356 if (FD_ISSET(sock, &rfds)) {
357 LOG1("NameServer: Listener got NameServer message "
358 "from sock: %d!\n", sock);
359 /* Get NameServer message and process: */
360 memset(&fromAddr, 0, sizeof(fromAddr));
361 len = sizeof(fromAddr);
363 byteCount = recvfrom(sock, &msg, sizeof(NameServerMsg), 0,
364 (struct sockaddr *)&fromAddr, &len);
365 if (len != sizeof(fromAddr)) {
366 LOG1("recvfrom: got bad addr len (%d)\n", len)
367 break;
368 }
369 if (byteCount < 0) {
370 LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
371 break;
372 }
373 else {
374 LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
375 LOG2("\tReceived ns msg: byteCount: %d, from addr: %d, ",
376 byteCount, fromAddr.addr)
377 LOG1("from vproc: %d\n", fromAddr.vproc_id)
378 NameServerRemote_processMessage(&msg, procId);
379 }
380 }
381 }
382 if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
383 /* We are told to unblock and exit: */
384 LOG0("NameServer: Listener thread exiting\n")
385 break;
386 }
387 } while (1);
389 return ((void *)ret);
390 }
392 /* =============================================================================
393 * APIS
394 * =============================================================================
395 */
397 /* Function to setup the nameserver module. */
398 Int NameServer_setup(Void)
399 {
400 Int status = NameServer_S_SUCCESS;
401 int err;
402 int sock;
403 int ret;
404 UInt16 procId;
405 UInt16 numProcs;
407 pthread_mutex_lock(&NameServer_module->modGate);
409 LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
411 NameServer_module->refCount++;
413 if (NameServer_module->refCount > 1) {
414 LOG0("NameServer_setup: already setup\n")
415 status = NameServer_S_ALREADYSETUP;
416 goto exit;
417 }
419 numProcs = MultiProc_getNumProcessors();
421 NameServer_module->unblockFd = eventfd(0, 0);
422 if (NameServer_module->unblockFd < 0) {
423 status = NameServer_E_FAIL;
424 LOG0("NameServer_setup: failed to create unblockFd.\n")
425 goto exit;
426 }
428 NameServer_module->waitFd = eventfd(0, 0);
429 if (NameServer_module->waitFd < 0) {
430 status = NameServer_E_FAIL;
431 LOG0("NameServer_setup: failed to create waitFd.\n")
432 goto exit;
433 }
435 for (procId = 0; procId < numProcs; procId++) {
436 NameServer_module->sendSock[procId] = INVALIDSOCKET;
437 NameServer_module->recvSock[procId] = INVALIDSOCKET;
439 /* Only support NameServer to remote procs: */
440 if (procId == MultiProc_self()) {
441 continue;
442 }
444 /* Create the socket for sending messages to each remote proc: */
445 sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
446 if (sock < 0) {
447 status = NameServer_E_FAIL;
448 LOG2("NameServer_setup: socket failed: %d, %s\n",
449 errno, strerror(errno))
450 }
451 else {
452 LOG1("NameServer_setup: created send socket: %d\n", sock)
453 err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
454 if (err < 0) {
455 status = NameServer_E_FAIL;
456 LOG2("NameServer_setup: connect failed: %d, %s\n",
457 errno, strerror(errno))
459 LOG1(" closing send socket: %d\n", sock)
460 close(sock);
461 }
462 else {
463 NameServer_module->sendSock[procId] = sock;
464 }
465 }
467 /* Create the socket for recving messages from each remote proc: */
468 sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
469 if (sock < 0) {
470 status = NameServer_E_FAIL;
471 LOG2("NameServer_setup: socket failed: %d, %s\n",
472 errno, strerror(errno))
473 }
474 else {
475 LOG1("NameServer_setup: created recv socket: %d\n", sock)
477 err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
478 if (err < 0) {
479 status = NameServer_E_FAIL;
480 LOG2("NameServer_setup: bind failed: %d, %s\n",
481 errno, strerror(errno))
483 LOG1(" closing recv socket: %d\n", sock)
484 close(sock);
485 }
486 else {
487 NameServer_module->recvSock[procId] = sock;
488 }
489 }
490 }
492 /* Construct the list object */
493 CIRCLEQ_INIT(&NameServer_module->objList);
495 /* Create the listener thread: */
496 LOG0("NameServer_setup: creating listener thread\n")
497 ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
498 if (ret) {
499 LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
500 LOG0("NameServer_setup: eventfd failed");
502 status = NameServer_E_FAIL;
503 }
504 else {
505 /* look for at least one good send/recv pair to indicate success */
506 for (procId = 0; procId < numProcs; procId++) {
507 if (NameServer_module->sendSock[procId] != INVALIDSOCKET &&
508 NameServer_module->recvSock[procId] != INVALIDSOCKET) {
509 status = NameServer_S_SUCCESS;
511 break;
512 }
513 }
514 }
516 exit:
517 LOG1("NameServer_setup: exiting, refCount=%d\n", NameServer_module->refCount)
519 pthread_mutex_unlock(&NameServer_module->modGate);
521 return (status);
522 }
524 /*! Function to destroy the nameserver module. */
525 Int NameServer_destroy(void)
526 {
527 Int status = NameServer_S_SUCCESS;
528 UInt16 numProcs = MultiProc_getNumProcessors();
529 UInt16 procId;
530 int sock;
531 uint64_t buf = 1;
532 int numBytes;
534 pthread_mutex_lock(&NameServer_module->modGate);
536 LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
538 NameServer_module->refCount--;
540 if (NameServer_module->refCount > 0) {
541 LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
542 status = NameServer_S_SUCCESS;
544 goto exit;
545 }
547 for (procId = 0; procId < numProcs; procId++) {
548 /* Only support NameServer to remote procs: */
549 if (procId == MultiProc_self()) {
550 continue;
551 }
553 /* Close the socket: */
554 sock = NameServer_module->sendSock[procId];
555 if (sock != INVALIDSOCKET) {
556 LOG1("NameServer_destroy: closing socket: %d\n", sock)
557 close(sock);
558 NameServer_module->sendSock[procId] = INVALIDSOCKET;
559 }
560 /* Close the socket: */
561 sock = NameServer_module->recvSock[procId];
562 if (sock != INVALIDSOCKET) {
563 LOG1("NameServer_destroy: closing socket: %d\n", sock)
564 close(sock);
565 NameServer_module->recvSock[procId] = INVALIDSOCKET;
566 }
567 }
569 CIRCLEQ_destruct(&NameServer_module->objList);
571 /* Unblock the NameServer listener thread: */
572 LOG0("NameServer_destroy: unblocking listener...\n")
573 numBytes = write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
575 /* Join: */
576 LOG0("NameServer_destroy: joining listener thread...\n")
577 pthread_join(NameServer_module->listener, NULL);
579 close(NameServer_module->unblockFd);
580 close(NameServer_module->waitFd);
582 exit:
583 LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
585 pthread_mutex_unlock(&NameServer_module->modGate);
587 return (status);
588 }
590 /* Function to retrieve a NameServer handle from name. */
591 NameServer_Handle NameServer_getHandle(String name)
592 {
593 NameServer_Handle handle = NULL;
594 Bool found = FALSE;
595 struct NameServer_Object * elem;
597 assert(name != NULL);
598 assert(NameServer_module->refCount != 0);
600 pthread_mutex_lock(&NameServer_module->modGate);
602 /* Lookup handle from name: */
603 CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
604 handle = (NameServer_Handle) elem;
605 if (strcmp(handle->name, name) == 0) {
606 found = TRUE;
607 break;
608 }
609 }
611 if (found == FALSE) {
612 handle = NULL;
613 }
615 pthread_mutex_unlock(&NameServer_module->modGate);
617 return (handle);
618 }
621 /* Function to create a name server. */
622 NameServer_Handle NameServer_create(String name,
623 const NameServer_Params * params)
624 {
625 NameServer_Handle handle = NULL;
626 pthread_mutexattr_t mutex_attr;
628 assert(params != NULL);
629 assert(name != NULL);
630 assert(NameServer_module->refCount != 0);
632 LOG1("NameServer_create(): '%s'\n", name)
634 pthread_mutex_lock(&NameServer_module->modGate);
636 /* check if the name is already created or not */
637 handle = NameServer_getHandle(name);
638 if (handle != NULL) {
639 if (memcmp((Ptr)&handle->params, (Ptr)params,
640 sizeof(NameServer_Params)) == 0) {
641 handle->refCount++;
642 }
643 else {
644 LOG0("NameServer_create: NameServer params mismatch\n")
645 handle = NULL;
646 }
647 goto leave;
648 }
649 else {
650 handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
651 }
653 if (!handle) {
654 LOG0("NameServer_create: NameServer_Handle alloc failed\n")
655 goto leave;
656 }
658 handle->refCount = 1;
659 handle->name = (String)malloc(strlen(name) + 1u);
660 if (!handle->name) {
661 LOG0("NameServer_create: instance name alloc failed\n")
662 goto cleanup;
663 }
664 strncpy(handle->name, name, strlen (name) + 1u);
665 memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
667 if (params->maxValueLen < sizeof(UInt32)) {
668 handle->params.maxValueLen = sizeof(UInt32);
669 }
670 else {
671 handle->params.maxValueLen = params->maxValueLen;
672 }
674 CIRCLEQ_INIT(&handle->nameList);
675 handle->count = 0u;
677 /* Put in the local list */
678 CIRCLEQ_elemClear(&handle->elem);
679 CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
681 /*
682 * NameServer_removeEntry() enters gate and is called by
683 * NameServer_remove() while holding the gate.
684 */
685 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
686 pthread_mutex_init(&handle->gate, &mutex_attr);
688 goto leave;
690 cleanup:
691 free(handle);
692 handle = NULL;
694 leave:
695 pthread_mutex_unlock(&NameServer_module->modGate);
697 return (handle);
698 }
701 /* Function to delete a name server. */
702 Int NameServer_delete(NameServer_Handle * handle)
703 {
704 Int status = NameServer_S_SUCCESS;
706 assert(handle != NULL);
707 assert(*handle != NULL);
708 assert((*handle)->count == 0);
709 assert(NameServer_module->refCount != 0);
711 pthread_mutex_lock(&NameServer_module->modGate);
713 (*handle)->refCount--;
714 if ((*handle)->refCount != 0) {
715 goto leave;
716 }
718 if ((*handle)->count == 0) {
719 CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
721 if ((*handle)->name != NULL) {
722 free((*handle)->name);
723 (*handle)->name = NULL;
724 }
726 CIRCLEQ_destruct(&(*handle)->nameList);
728 free((*handle));
729 (*handle) = NULL;
730 }
732 leave:
733 pthread_mutex_unlock(&NameServer_module->modGate);
735 return (status);
736 }
738 /* Adds a variable length value into the local NameServer table */
739 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
740 {
741 Int status = NameServer_S_SUCCESS;
742 NameServer_TableEntry * node = NULL;
743 NameServer_TableEntry * new_node = NULL;
744 Bool found = FALSE;
745 UInt32 hash;
747 assert(handle != NULL);
748 assert(name != NULL);
749 assert(buf != NULL);
750 assert(len != 0);
751 assert(NameServer_module->refCount != 0);
753 /* Calculate the hash */
754 hash = stringHash(name);
756 if (len > handle->params.maxValueLen) {
757 status = NameServer_E_INVALIDARG;
758 LOG0("NameServer_add: value length exceeded maximum!\n")
759 new_node = NULL;
760 goto exit;
761 }
763 pthread_mutex_lock(&handle->gate);
765 /* Traverse the list to find duplicate check */
766 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
767 /* Hash matches */
768 if (node->hash == hash) {
769 /* If the name matches, incase hash is duplicate */
770 if (strcmp(node->name, name) == 0) {
771 if (handle->params.checkExisting == TRUE) {
772 status = NameServer_E_INVALIDARG;
773 LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
774 break;
775 }
776 }
777 else {
778 found = TRUE;
779 break;
780 } /* name does not match */
781 } /* hash does not match */
782 } /* CIRCLEQ_traverse */
784 if (status != NameServer_S_SUCCESS) {
785 new_node = NULL;
786 goto exit;
787 }
789 /* Now add the new entry. */
790 new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
791 if (new_node == NULL) {
792 status = NameServer_E_MEMORY;
793 LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
795 goto exit;
796 }
798 new_node->hash = hash;
799 new_node->collide = found; /* Indicate if there is a collision*/
800 new_node->len = len;
801 new_node->next = NULL;
802 new_node->name = (String)malloc(strlen(name) + 1u);
803 new_node->value = (Ptr)malloc(len);
804 strncpy(new_node->name, name, strlen(name) + 1u);
805 memcpy((Ptr)new_node->value, (Ptr)buf, len);
807 if (found == TRUE) {
808 /* If hash is found, need to stitch the list to link the
809 * new node to the existing node with the same hash.
810 */
811 new_node->next = node->next;
812 node->next = new_node;
813 }
814 else {
815 /* put the new node into the list */
816 CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
817 }
819 handle->count++;
821 LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
822 name, *(UInt32 *)buf)
824 exit:
825 pthread_mutex_unlock(&handle->gate);
827 return (new_node);
828 }
831 /* Function to add a UInt32 value into a name server. */
832 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
833 {
834 Ptr entry = NULL;
836 assert(handle != NULL);
837 assert(name != NULL);
838 assert(NameServer_module->refCount != 0);
840 entry = NameServer_add(handle, name, &value, sizeof(UInt32));
842 return (entry);
843 }
845 /* Function to remove a name/value pair from a name server. */
846 Int NameServer_remove(NameServer_Handle handle, String name)
847 {
848 Int status = NameServer_S_SUCCESS;
849 NameServer_TableEntry *prev = NULL;
850 NameServer_TableEntry *temp = NULL;
851 NameServer_TableEntry *node = NULL;
852 Bool done = FALSE;
853 UInt32 hash;
855 assert(handle != NULL);
856 assert(name != NULL);
857 assert(NameServer_module->refCount != 0);
859 /* Calculate the hash */
860 hash = stringHash(name);
862 pthread_mutex_lock(&handle->gate);
864 /* Traverse the list to find duplicate check */
865 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
866 /* Hash matchs */
867 if (node->hash == hash) {
868 if (node->collide == TRUE) {
869 if (strcmp(node->name, name) == 0){
870 free(node->value);
871 free(node->name);
872 memcpy((Ptr)node, (Ptr) node->next,
873 sizeof(NameServer_TableEntry));
874 node->next = node->next->next;
875 free(node->next);
876 handle->count--;
877 done = TRUE;
878 break;
879 }
880 else {
881 prev = node;
882 temp = node->next;
883 while (temp) {
884 if (strcmp(temp->name, name) == 0){
885 free(temp->value);
886 free(temp->name);
887 prev->next = temp->next;
888 free(temp);
889 handle->count--;
890 done = TRUE;
891 break;
892 }
893 temp = temp->next;
894 }
895 break;
896 }
897 }
898 else {
899 NameServer_removeEntry(handle, (Ptr)node);
901 done = TRUE;
902 break;
903 }
904 }
905 }
907 if (done == FALSE) {
908 status = NameServer_E_INVALIDARG;
909 LOG1("NameServer_remove %d Entry not found!\n", status)
910 }
912 pthread_mutex_unlock(&handle->gate);
914 return (status);
915 }
917 /* Function to remove a name/value pair from a name server. */
918 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
919 {
920 Int status = NameServer_S_SUCCESS;
921 NameServer_TableEntry * node;
923 assert(handle != NULL);
924 assert(entry != NULL);
925 assert(NameServer_module->refCount != 0);
927 pthread_mutex_lock(&handle->gate);
929 node = (NameServer_TableEntry *)entry;
931 free(node->value);
932 free(node->name);
933 CIRCLEQ_REMOVE(&handle->nameList, node, elem);
934 free(node);
935 handle->count--;
937 pthread_mutex_unlock(&handle->gate);
939 return (status);
940 }
943 /* Initialize this config-params structure with supplier-specified
944 * defaults before instance creation.
945 */
946 Void NameServer_Params_init(NameServer_Params * params)
947 {
948 assert(params != NULL);
950 memcpy(params, &(NameServer_module->defInstParams),
951 sizeof (NameServer_Params));
952 }
955 Int NameServer_getRemote(NameServer_Handle handle,
956 String name,
957 Ptr value,
958 UInt32 * len,
959 UInt16 procId)
960 {
961 Int status = NameServer_S_SUCCESS;
962 struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
963 NameServerMsg nsMsg;
964 NameServerMsg *replyMsg;
965 fd_set rfds;
966 int ret = 0, sock, maxfd, waitFd;
967 struct timeval tv;
968 uint64_t buf = 1;
969 int numBytes;
970 int err;
971 int i;
972 static int seqNum = 0;
973 Bool done = FALSE;
975 /* Set Timeout to wait: */
976 tv.tv_sec = 0;
977 tv.tv_usec = NAMESERVER_GET_TIMEOUT;
979 /* Create request message and send to remote: */
980 sock = NameServer_module->sendSock[procId];
981 if (sock == INVALIDSOCKET) {
982 LOG1("NameServer_getRemote: no socket connection to processor %d\n",
983 procId);
984 status = NameServer_E_RESOURCE;
985 goto exit;
986 }
988 LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
990 /* Create request message and send to remote processor: */
991 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
992 nsMsg.request = NAMESERVER_REQUEST;
993 nsMsg.requestStatus = 0;
994 nsMsg.valueLen = *len;
995 nsMsg.seqNum = seqNum++;
997 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
998 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
1000 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
1001 procId, (String)nsMsg.instanceName)
1002 LOG1("%s...\n", (String)nsMsg.name)
1004 err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
1005 if (err < 0) {
1006 LOG2("NameServer_getRemote: send failed: %d, %s\n",
1007 errno, strerror(errno))
1008 status = NameServer_E_FAIL;
1009 goto exit;
1010 }
1012 while (!done) {
1013 /* Block on waitFd for signal from listener thread: */
1014 waitFd = NameServer_module->waitFd;
1015 FD_ZERO(&rfds);
1016 FD_SET(waitFd, &rfds);
1017 maxfd = waitFd + 1;
1018 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
1019 ret = select(maxfd, &rfds, NULL, NULL, &tv);
1020 if (ret == -1) {
1021 LOG0("NameServer_getRemote: select failed.")
1022 status = NameServer_E_FAIL;
1023 goto exit;
1024 }
1025 else if (!ret) {
1026 LOG0("NameServer_getRemote: select timed out.\n")
1027 status = NameServer_E_TIMEOUT;
1028 goto exit;
1029 }
1031 if (FD_ISSET(waitFd, &rfds)) {
1032 /* Read, just to balance the write: */
1033 numBytes = read(waitFd, &buf, sizeof(uint64_t));
1035 /* Process response: */
1036 replyMsg = &NameServer_module->nsMsg;
1038 if (replyMsg->seqNum != seqNum - 1) {
1039 /* Ignore responses without current sequence # */
1040 continue;
1041 }
1043 if (replyMsg->requestStatus) {
1044 /* name is found */
1046 /* set length to amount of data that was copied */
1047 *len = replyMsg->valueLen;
1049 /* set the contents of value */
1050 if (*len <= sizeof (Bits32)) {
1051 *(UInt32 *)value = (UInt32)replyMsg->value;
1052 LOG2("NameServer_getRemote: Reply from: %d, %s:",
1053 procId, (String)replyMsg->instanceName)
1054 LOG2("%s, value: 0x%x...\n",
1055 (String)replyMsg->name, *(UInt32 *)value)
1056 }
1057 else {
1058 memcpy(value, replyMsg->valueBuf, *len);
1059 LOG2("NameServer_getRemote: Reply from: %d, %s:",
1060 procId, (String)replyMsg->instanceName)
1061 for (i = 0; i < *len/4; i++) {
1062 LOG2("%s, value buffer content: 0x%x...\n",
1063 (String)replyMsg->name, ((uint32_t *)value)[i])
1064 }
1065 }
1067 goto exit;
1068 }
1069 else {
1070 /* name is not found */
1071 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1072 (String)replyMsg->instanceName, (String)replyMsg->name)
1074 /* set status to not found */
1075 status = NameServer_E_NOTFOUND;
1076 }
1077 }
1078 done= TRUE;
1079 }
1081 exit:
1082 return (status);
1083 }
1085 /* Function to retrieve the value portion of a name/value pair from
1086 * local table.
1087 */
1088 Int NameServer_get(NameServer_Handle handle,
1089 String name,
1090 Ptr value,
1091 UInt32 * len,
1092 UInt16 procId[])
1093 {
1094 Int status = NameServer_S_SUCCESS;
1095 UInt16 numProcs = MultiProc_getNumProcessors();
1096 UInt32 i;
1098 /*
1099 * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1100 * since this goes in a daemon, it will not be necessary.
1101 */
1103 if (procId == NULL) {
1104 status = NameServer_getLocal(handle, name, value, len);
1105 if (status == NameServer_E_NOTFOUND) {
1106 for (i = 0; i < numProcs; i++) {
1107 /* getLocal call already covers "self", keep going */
1108 if (i == MultiProc_self()) {
1109 continue;
1110 }
1112 status = NameServer_getRemote(handle, name, value, len, i);
1114 if ((status >= 0) ||
1115 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1116 (status != NameServer_E_RESOURCE))) {
1117 break;
1118 }
1119 }
1120 }
1121 }
1122 else {
1123 /*
1124 * Search the query list. It might contain the local proc
1125 * somewhere in the list.
1126 */
1127 i = 0;
1128 while (procId[i] != MultiProc_INVALIDID) {
1129 if (procId[i] == MultiProc_self()) {
1130 status = NameServer_getLocal(handle, name, value, len);
1131 }
1132 else {
1133 status = NameServer_getRemote(handle, name, value, len, i);
1134 }
1136 if ((status >= 0) ||
1137 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1138 (status != NameServer_E_RESOURCE))) {
1139 break;
1140 }
1142 i++;
1143 }
1144 }
1146 if (status == NameServer_E_RESOURCE) {
1147 status = NameServer_E_NOTFOUND;
1148 }
1150 return (status);
1151 }
1153 /* Gets a 32-bit value by name */
1154 Int NameServer_getUInt32(NameServer_Handle handle,
1155 String name,
1156 Ptr value,
1157 UInt16 procId[])
1158 {
1159 Int status;
1160 UInt32 len = sizeof(UInt32);
1162 assert(handle != NULL);
1163 assert(name != NULL);
1164 assert(value != NULL);
1165 assert(NameServer_module->refCount != 0);
1167 status = NameServer_get(handle, name, value, &len, procId);
1169 return (status);
1170 }
1172 /* Function to Retrieve the value portion of a name/value pair from
1173 * local table.
1174 */
1175 Int NameServer_getLocal(NameServer_Handle handle,
1176 String name,
1177 Ptr value,
1178 UInt32 * len)
1179 {
1180 Int status = NameServer_E_NOTFOUND;
1181 NameServer_TableEntry * node = NULL;
1182 NameServer_TableEntry * temp = NULL;
1183 Bool done = FALSE;
1184 UInt32 length;
1185 UInt32 hash;
1187 assert(handle != NULL);
1188 assert(name != NULL);
1189 assert(value != NULL);
1190 assert(len != NULL);
1191 assert(NameServer_module->refCount != 0);
1193 length = *len;
1195 /* Calculate the hash */
1196 hash = stringHash(name);
1198 pthread_mutex_lock(&handle->gate);
1200 /* Traverse the list to find duplicate check */
1201 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1202 if (node->hash == hash) {
1203 if (node->collide == TRUE) {
1204 temp = node;
1205 while (temp) {
1206 if (strcmp(temp->name, name) == 0u){
1207 if (length <= node->len) {
1208 memcpy(value, node->value, length);
1209 *len = length;
1210 }
1211 else {
1212 memcpy(value, node->value, node->len);
1213 *len = node->len;
1214 }
1215 done = TRUE;
1216 break;
1217 }
1218 temp = temp->next;
1219 }
1220 break;
1221 }
1222 else {
1223 if (length <= node->len) {
1224 memcpy(value, node->value, length);
1225 *len = length;
1226 }
1227 else {
1228 memcpy(value, node->value, node->len);
1229 *len = node->len;
1230 }
1231 done = TRUE;
1232 break;
1233 }
1234 }
1235 }
1237 pthread_mutex_unlock(&handle->gate);
1239 if (done == FALSE) {
1240 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1241 }
1242 else {
1243 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1244 node->name, (UInt32)node->value)
1245 status = NameServer_S_SUCCESS;
1246 }
1248 return (status);
1249 }
1251 /*
1252 * Gets a 32-bit value by name from the local table
1253 *
1254 * If the name is found, the 32-bit value is copied into the value
1255 * argument and a success status is returned.
1256 *
1257 * If the name is not found, zero is returned in len and the contents
1258 * of value are not modified. Not finding a name is not considered
1259 * an error.
1260 *
1261 * This function only searches the local name/value table.
1262 *
1263 */
1264 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1265 {
1266 Int status;
1267 UInt32 len = sizeof(UInt32);
1269 assert(handle != NULL);
1270 assert(name != NULL);
1271 assert(value != NULL);
1272 assert(NameServer_module->refCount != 0);
1274 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1275 status = NameServer_getLocal(handle, name, value, &len);
1277 return (status);
1278 }
1281 #if defined (__cplusplus)
1282 }
1283 #endif /* defined (__cplusplus) */