067bcd809a0630f3c2c2b432ead99a3b4f58e120
1 /*
2 * Copyright (c) 2012-2013, 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 pthread_mutex_t gate; /* crit sect gate */
117 } NameServer_Object;
119 /* structure for NameServer module state */
120 typedef struct NameServer_ModuleObject {
121 CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
122 Int32 refCount;
123 int sendSock[MultiProc_MAXPROCESSORS];
124 /* Sockets for sending to remote proc nameserver ports: */
125 int recvSock[MultiProc_MAXPROCESSORS];
126 /* Sockets for recving from remote proc nameserver ports: */
127 pthread_t listener;
128 /* Listener thread for NameServer replies and requests. */
129 int unblockFd;
130 /* Event to post to exit listener. */
131 int waitFd;
132 /* Event to post to NameServer_get. */
133 NameServerMsg nsMsg;
134 /* NameServer Message cache. */
135 NameServer_Params defInstParams;
136 /* Default instance paramters */
137 pthread_mutex_t modGate;
138 } NameServer_ModuleObject;
140 #define CIRCLEQ_destruct(head) { \
141 (head)->cqh_first = NULL; \
142 (head)->cqh_last = NULL; \
143 }
145 #define CIRCLEQ_elemClear(elem) { \
146 (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
147 }
149 #define CIRCLEQ_traverse(x, y, tag) \
150 for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
152 /* =============================================================================
153 * Globals
154 * =============================================================================
155 */
156 /*
157 * NameServer_state
158 *
159 * Make the module gate "recursive" since NameServer_getHandle() needs to
160 * use it and NameServer_create() needs to hold it around its call to
161 * NameServer_getHandle(). Also, use the static initializer instead of a
162 * run-time init call, so we can use this gate immediately in _setup().
163 */
164 static NameServer_ModuleObject NameServer_state = {
165 .defInstParams.maxRuntimeEntries = 0u,
166 .defInstParams.tableHeap = NULL,
167 .defInstParams.checkExisting = TRUE,
168 .defInstParams.maxValueLen = 0u,
169 .defInstParams.maxNameLen = 16u,
170 // only _NP (non-portable) type available in CG tools which we're using
171 .modGate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
172 // .modGate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER,
173 .refCount = 0
174 };
176 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
178 static const UInt32 stringCrcTab[256u] = {
179 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
180 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
181 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
182 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
183 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
184 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
185 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
186 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
187 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
188 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
189 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
190 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
191 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
192 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
193 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
194 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
195 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
196 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
197 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
198 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
199 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
200 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
201 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
202 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
203 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
204 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
205 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
206 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
207 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
208 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
209 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
210 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
211 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
212 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
213 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
214 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
215 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
216 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
217 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
218 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
219 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
220 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
221 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
222 };
224 static UInt32 stringHash(String s)
225 {
226 UInt32 hash = strlen(s);
227 UInt32 i;
229 for (i = 0; i < strlen(s); i++) {
230 hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
231 }
233 return (hash);
234 }
236 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
237 {
238 NameServer_Handle handle;
239 Int status = NameServer_E_FAIL;
240 int err;
241 uint64_t buf = 1;
242 int numBytes;
243 int waitFd = NameServer_module->waitFd;
245 if (msg->request == NAMESERVER_REQUEST) {
246 LOG2("NameServer Request: instanceName: %s, name: %s\n",
247 (String)msg->instanceName, (String)msg->name)
249 /*
250 * Message is a request. Lookup name in NameServer table.
251 * Send a response message back to source processor.
252 */
253 handle = NameServer_getHandle((String)msg->instanceName);
255 if (handle != NULL) {
256 /* Search for the NameServer entry */
257 LOG0("Calling NameServer_getLocalUInt32...\n")
258 status = NameServer_getLocalUInt32(handle,
259 (String)msg->name, &msg->value);
260 }
262 LOG2("NameServer Response: instanceName: %s, name: %s,",
263 (String)msg->instanceName, (String)msg->name)
264 /* set the request status */
265 if (status < 0) {
266 LOG1(" Value not found, status: %d\n", status)
267 msg->requestStatus = 0;
268 }
269 else {
270 msg->requestStatus = 1;
271 LOG1(" Value: 0x%x\n", msg->value)
272 }
274 /* specify message as a response */
275 msg->request = NAMESERVER_RESPONSE;
276 msg->reserved = NAMESERVER_MSG_TOKEN;
278 /* send response message to remote processor */
279 err = send(NameServer_module->sendSock[procId], msg,
280 sizeof(NameServerMsg), 0);
281 if (err < 0) {
282 LOG2("NameServer: send failed: %d, %s\n", errno, strerror(errno))
283 }
284 }
285 else {
286 LOG2("NameServer Reply: instanceName: %s, name: %s",
287 (String)msg->instanceName, (String)msg->name)
288 LOG1(", value: 0x%x\n", msg->value)
290 /* Save the response message. */
291 memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
293 /* Post the eventfd upon which NameServer_get() is waiting */
294 numBytes = write(waitFd, &buf, sizeof(uint64_t));
295 }
296 }
299 static void *listener_cb(void *arg)
300 {
301 fd_set rfds;
302 int ret = 0, maxfd;
303 UInt16 procId;
304 struct sockaddr_rpmsg fromAddr;
305 unsigned int len;
306 NameServerMsg msg;
307 int byteCount;
308 UInt16 numProcs = MultiProc_getNumProcessors();
309 int sock;
311 LOG0("listener_cb: Entered Listener thread.\n")
313 do {
314 /* Wait for NameServer messages or unblockFd notification */
315 FD_ZERO(&rfds);
316 FD_SET(NameServer_module->unblockFd, &rfds);
317 maxfd = NameServer_module->unblockFd;
318 for (procId = 0; procId < numProcs; procId++) {
319 if (procId == MultiProc_self() ||
320 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
321 continue;
322 }
323 sock = NameServer_module->recvSock[procId];
324 FD_SET(sock, &rfds);
325 maxfd = MAX(sock, maxfd);
326 }
328 maxfd = maxfd + 1;
329 LOG2("NameServer: waiting for unblockFd: %d, and socks: maxfd: %d\n",
330 NameServer_module->unblockFd, maxfd)
331 ret = select(maxfd, &rfds, NULL, NULL, NULL);
332 if (ret == -1) {
333 LOG0("listener_cb: select failed.")
334 break;
335 }
336 LOG0("NameServer: back from select()\n")
338 for (procId = 0; procId < numProcs; procId++) {
339 if (procId == MultiProc_self() ||
340 NameServer_module->recvSock[procId] == INVALIDSOCKET) {
341 continue;
342 }
343 sock = NameServer_module->recvSock[procId];
344 if (FD_ISSET(sock, &rfds)) {
345 LOG1("NameServer: Listener got NameServer message "
346 "from sock: %d!\n", sock);
347 /* Get NameServer message and process: */
348 memset(&fromAddr, 0, sizeof(fromAddr));
349 len = sizeof(fromAddr);
351 byteCount = recvfrom(sock, &msg, sizeof(NameServerMsg), 0,
352 (struct sockaddr *)&fromAddr, &len);
353 if (len != sizeof(fromAddr)) {
354 LOG1("recvfrom: got bad addr len (%d)\n", len)
355 break;
356 }
357 if (byteCount < 0) {
358 LOG2("recvfrom failed: %s (%d)\n", strerror(errno), errno)
359 break;
360 }
361 else {
362 LOG1("listener_cb: recvfrom socket: fd: %d\n", sock)
363 LOG2("\tReceived ns msg: byteCount: %d, from addr: %d, ",
364 byteCount, fromAddr.addr)
365 LOG1("from vproc: %d\n", fromAddr.vproc_id)
366 NameServerRemote_processMessage(&msg, procId);
367 }
368 }
369 }
370 if (FD_ISSET(NameServer_module->unblockFd, &rfds)) {
371 /* We are told to unblock and exit: */
372 LOG0("NameServer: Listener thread exiting\n")
373 break;
374 }
375 } while (1);
377 return ((void *)ret);
378 }
380 /* =============================================================================
381 * APIS
382 * =============================================================================
383 */
385 /* Function to setup the nameserver module. */
386 Int NameServer_setup(Void)
387 {
388 Int status = NameServer_S_SUCCESS;
389 int err;
390 int sock;
391 int ret;
392 UInt16 procId;
393 UInt16 numProcs;
395 pthread_mutex_lock(&NameServer_module->modGate);
397 LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
399 NameServer_module->refCount++;
401 if (NameServer_module->refCount > 1) {
402 LOG0("NameServer_setup: already setup\n")
403 status = NameServer_S_ALREADYSETUP;
404 goto exit;
405 }
407 numProcs = MultiProc_getNumProcessors();
409 NameServer_module->unblockFd = eventfd(0, 0);
410 if (NameServer_module->unblockFd < 0) {
411 status = NameServer_E_FAIL;
412 LOG0("NameServer_setup: failed to create unblockFd.\n")
413 goto exit;
414 }
416 NameServer_module->waitFd = eventfd(0, 0);
417 if (NameServer_module->waitFd < 0) {
418 status = NameServer_E_FAIL;
419 LOG0("NameServer_setup: failed to create waitFd.\n")
420 goto exit;
421 }
423 for (procId = 0; procId < numProcs; procId++) {
424 NameServer_module->sendSock[procId] = INVALIDSOCKET;
425 NameServer_module->recvSock[procId] = INVALIDSOCKET;
427 /* Only support NameServer to remote procs: */
428 if (procId == MultiProc_self()) {
429 continue;
430 }
432 /* Create the socket for sending messages to each remote proc: */
433 sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
434 if (sock < 0) {
435 status = NameServer_E_FAIL;
436 LOG2("NameServer_setup: socket failed: %d, %s\n",
437 errno, strerror(errno))
438 }
439 else {
440 LOG1("NameServer_setup: created send socket: %d\n", sock)
441 err = ConnectSocket(sock, procId, MESSAGEQ_RPMSG_PORT);
442 if (err < 0) {
443 status = NameServer_E_FAIL;
444 LOG2("NameServer_setup: connect failed: %d, %s\n",
445 errno, strerror(errno))
447 LOG1(" closing send socket: %d\n", sock)
448 close(sock);
449 }
450 else {
451 NameServer_module->sendSock[procId] = sock;
452 }
453 }
455 /* Create the socket for recving messages from each remote proc: */
456 sock = socket(AF_RPMSG, SOCK_SEQPACKET, 0);
457 if (sock < 0) {
458 status = NameServer_E_FAIL;
459 LOG2("NameServer_setup: socket failed: %d, %s\n",
460 errno, strerror(errno))
461 }
462 else {
463 LOG1("NameServer_setup: created recv socket: %d\n", sock)
465 err = SocketBindAddr(sock, procId, NAME_SERVER_RPMSG_ADDR);
466 if (err < 0) {
467 status = NameServer_E_FAIL;
468 LOG2("NameServer_setup: bind failed: %d, %s\n",
469 errno, strerror(errno))
471 LOG1(" closing recv socket: %d\n", sock)
472 close(sock);
473 }
474 else {
475 NameServer_module->recvSock[procId] = sock;
476 }
477 }
478 }
480 /* Construct the list object */
481 CIRCLEQ_INIT(&NameServer_module->objList);
483 /* Create the listener thread: */
484 LOG0("NameServer_setup: creating listener thread\n")
485 ret = pthread_create(&NameServer_module->listener, NULL, listener_cb, NULL);
486 if (ret) {
487 LOG1("NameServer_setup: can't spawn thread: %s\n", strerror(ret))
488 LOG0("NameServer_setup: eventfd failed");
490 status = NameServer_E_FAIL;
491 }
493 exit:
494 LOG1("NameServer_setup: exiting, refCount=%d\n", NameServer_module->refCount)
496 pthread_mutex_unlock(&NameServer_module->modGate);
498 return (status);
499 }
501 /*! Function to destroy the nameserver module. */
502 Int NameServer_destroy(void)
503 {
504 Int status = NameServer_S_SUCCESS;
505 UInt16 numProcs = MultiProc_getNumProcessors();
506 UInt16 procId;
507 int sock;
508 uint64_t buf = 1;
509 int numBytes;
511 pthread_mutex_lock(&NameServer_module->modGate);
513 LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
515 NameServer_module->refCount--;
517 if (NameServer_module->refCount > 0) {
518 LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
519 status = NameServer_S_SUCCESS;
521 goto exit;
522 }
524 for (procId = 0; procId < numProcs; procId++) {
525 /* Only support NameServer to remote procs: */
526 if (procId == MultiProc_self()) {
527 continue;
528 }
530 /* Close the socket: */
531 sock = NameServer_module->sendSock[procId];
532 if (sock != INVALIDSOCKET) {
533 LOG1("NameServer_destroy: closing socket: %d\n", sock)
534 close(sock);
535 NameServer_module->sendSock[procId] = INVALIDSOCKET;
536 }
537 /* Close the socket: */
538 sock = NameServer_module->recvSock[procId];
539 if (sock != INVALIDSOCKET) {
540 LOG1("NameServer_destroy: closing socket: %d\n", sock)
541 close(sock);
542 NameServer_module->recvSock[procId] = INVALIDSOCKET;
543 }
544 }
546 CIRCLEQ_destruct(&NameServer_module->objList);
548 /* Unblock the NameServer listener thread: */
549 LOG0("NameServer_destroy: unblocking listener...\n")
550 numBytes = write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
552 /* Join: */
553 LOG0("NameServer_destroy: joining listener thread...\n")
554 pthread_join(NameServer_module->listener, NULL);
556 close(NameServer_module->unblockFd);
557 close(NameServer_module->waitFd);
559 exit:
560 LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
562 pthread_mutex_unlock(&NameServer_module->modGate);
564 return (status);
565 }
567 /* Function to retrieve a NameServer handle from name. */
568 NameServer_Handle NameServer_getHandle(String name)
569 {
570 NameServer_Handle handle = NULL;
571 Bool found = FALSE;
572 struct NameServer_Object * elem;
574 assert(name != NULL);
575 assert(NameServer_module->refCount != 0);
577 pthread_mutex_lock(&NameServer_module->modGate);
579 /* Lookup handle from name: */
580 CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
581 handle = (NameServer_Handle) elem;
582 if (strcmp(handle->name, name) == 0) {
583 found = TRUE;
584 break;
585 }
586 }
588 if (found == FALSE) {
589 handle = NULL;
590 }
592 pthread_mutex_unlock(&NameServer_module->modGate);
594 return (handle);
595 }
598 /* Function to create a name server. */
599 NameServer_Handle NameServer_create(String name,
600 const NameServer_Params * params)
601 {
602 NameServer_Handle handle = NULL;
603 pthread_mutexattr_t mutex_attr;
605 assert(params != NULL);
606 assert(name != NULL);
607 assert(NameServer_module->refCount != 0);
609 LOG1("NameServer_create(): '%s'\n", name)
611 pthread_mutex_lock(&NameServer_module->modGate);
613 if (params->maxValueLen > sizeof(UInt32)) {
614 LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
615 /* Can't handle more than UInt32 at this time: */
616 goto leave;
617 }
619 /* check if the name is already created or not */
620 if (NameServer_getHandle(name)) {
621 LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
622 handle = NULL;
623 goto leave;
624 }
625 else {
626 handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
627 }
629 if (!handle) {
630 LOG0("NameServer_create: NameServer_Handle alloc failed\n")
631 goto leave;
632 }
634 handle->name = (String)malloc(strlen(name) + 1u);
635 if (!handle->name) {
636 LOG0("NameServer_create: instance name alloc failed\n")
637 goto cleanup;
638 }
639 strncpy(handle->name, name, strlen (name) + 1u);
640 memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
642 if (params->maxValueLen < sizeof(UInt32)) {
643 handle->params.maxValueLen = sizeof(UInt32);
644 }
645 else {
646 handle->params.maxValueLen = params->maxValueLen;
647 }
649 CIRCLEQ_INIT(&handle->nameList);
650 handle->count = 0u;
652 /* Put in the local list */
653 CIRCLEQ_elemClear(&handle->elem);
654 CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
656 /*
657 * NameServer_removeEntry() enters gate and is called by
658 * NameServer_remove() while holding the gate.
659 */
660 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
661 pthread_mutex_init(&handle->gate, &mutex_attr);
663 goto leave;
665 cleanup:
666 free(handle);
667 handle = NULL;
669 leave:
670 pthread_mutex_unlock(&NameServer_module->modGate);
672 return (handle);
673 }
676 /* Function to delete a name server. */
677 Int NameServer_delete(NameServer_Handle * handle)
678 {
679 Int status = NameServer_S_SUCCESS;
681 assert(handle != NULL);
682 assert(*handle != NULL);
683 assert((*handle)->count == 0);
684 assert(NameServer_module->refCount != 0);
686 pthread_mutex_lock(&NameServer_module->modGate);
688 if ((*handle)->count == 0) {
689 CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
691 if ((*handle)->name != NULL) {
692 free((*handle)->name);
693 (*handle)->name = NULL;
694 }
696 CIRCLEQ_destruct(&(*handle)->nameList);
698 free((*handle));
699 (*handle) = NULL;
700 }
702 pthread_mutex_unlock(&NameServer_module->modGate);
704 return (status);
705 }
707 /* Adds a variable length value into the local NameServer table */
708 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
709 {
710 Int status = NameServer_S_SUCCESS;
711 NameServer_TableEntry * node = NULL;
712 NameServer_TableEntry * new_node = NULL;
713 Bool found = FALSE;
714 UInt32 hash;
716 assert(handle != NULL);
717 assert(name != NULL);
718 assert(buf != NULL);
719 assert(len != 0);
720 assert(NameServer_module->refCount != 0);
722 /* Calculate the hash */
723 hash = stringHash(name);
725 pthread_mutex_lock(&handle->gate);
727 /* Traverse the list to find duplicate check */
728 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
729 /* Hash matches */
730 if (node->hash == hash) {
731 /* If the name matches, incase hash is duplicate */
732 if (strcmp(node->name, name) == 0) {
733 if (handle->params.checkExisting == TRUE) {
734 status = NameServer_E_INVALIDARG;
735 LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
736 break;
737 }
738 }
739 else {
740 found = TRUE;
741 break;
742 } /* name does not match */
743 } /* hash does not match */
744 } /* CIRCLEQ_traverse */
746 if (status != NameServer_S_SUCCESS) {
747 new_node = NULL;
748 goto exit;
749 }
751 /* Now add the new entry. */
752 new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
753 if (new_node == NULL) {
754 status = NameServer_E_MEMORY;
755 LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
757 goto exit;
758 }
760 new_node->hash = hash;
761 new_node->collide = found; /* Indicate if there is a collision*/
762 new_node->len = len;
763 new_node->next = NULL;
764 new_node->name = (String)malloc(strlen(name) + 1u);
765 new_node->value = (Ptr)malloc(len);
766 strncpy(new_node->name, name, strlen(name) + 1u);
767 memcpy((Ptr)new_node->value, (Ptr)buf, len);
769 if (found == TRUE) {
770 /* If hash is found, need to stitch the list to link the
771 * new node to the existing node with the same hash.
772 */
773 new_node->next = node->next;
774 node->next = new_node;
775 }
776 else {
777 /* put the new node into the list */
778 CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
779 }
781 handle->count++;
783 LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
784 name, *(UInt32 *)buf)
786 exit:
787 pthread_mutex_unlock(&handle->gate);
789 return (new_node);
790 }
793 /* Function to add a UInt32 value into a name server. */
794 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
795 {
796 Ptr entry = NULL;
798 assert(handle != NULL);
799 assert(name != NULL);
800 assert(NameServer_module->refCount != 0);
802 entry = NameServer_add(handle, name, &value, sizeof(UInt32));
804 return (entry);
805 }
807 /* Function to remove a name/value pair from a name server. */
808 Int NameServer_remove(NameServer_Handle handle, String name)
809 {
810 Int status = NameServer_S_SUCCESS;
811 NameServer_TableEntry *prev = NULL;
812 NameServer_TableEntry *temp = NULL;
813 NameServer_TableEntry *node = NULL;
814 Bool done = FALSE;
815 UInt32 hash;
817 assert(handle != NULL);
818 assert(name != NULL);
819 assert(NameServer_module->refCount != 0);
821 /* Calculate the hash */
822 hash = stringHash(name);
824 pthread_mutex_lock(&handle->gate);
826 /* Traverse the list to find duplicate check */
827 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
828 /* Hash matchs */
829 if (node->hash == hash) {
830 if (node->collide == TRUE) {
831 if (strcmp(node->name, name) == 0){
832 free(node->value);
833 free(node->name);
834 memcpy((Ptr)node, (Ptr) node->next,
835 sizeof(NameServer_TableEntry));
836 node->next = node->next->next;
837 free(node->next);
838 handle->count--;
839 done = TRUE;
840 break;
841 }
842 else {
843 prev = node;
844 temp = node->next;
845 while (temp) {
846 if (strcmp(temp->name, name) == 0){
847 free(temp->value);
848 free(temp->name);
849 prev->next = temp->next;
850 free(temp);
851 handle->count--;
852 done = TRUE;
853 break;
854 }
855 temp = temp->next;
856 }
857 break;
858 }
859 }
860 else {
861 NameServer_removeEntry(handle, (Ptr)node);
863 done = TRUE;
864 break;
865 }
866 }
867 }
869 if (done == FALSE) {
870 status = NameServer_E_INVALIDARG;
871 LOG1("NameServer_remove %d Entry not found!\n", status)
872 }
874 pthread_mutex_unlock(&handle->gate);
876 return (status);
877 }
879 /* Function to remove a name/value pair from a name server. */
880 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
881 {
882 Int status = NameServer_S_SUCCESS;
883 NameServer_TableEntry * node;
885 assert(handle != NULL);
886 assert(entry != NULL);
887 assert(NameServer_module->refCount != 0);
889 pthread_mutex_lock(&handle->gate);
891 node = (NameServer_TableEntry *)entry;
893 free(node->value);
894 free(node->name);
895 CIRCLEQ_REMOVE(&handle->nameList, node, elem);
896 free(node);
897 handle->count--;
899 pthread_mutex_unlock(&handle->gate);
901 return (status);
902 }
905 /* Initialize this config-params structure with supplier-specified
906 * defaults before instance creation.
907 */
908 Void NameServer_Params_init(NameServer_Params * params)
909 {
910 assert(params != NULL);
912 memcpy(params, &(NameServer_module->defInstParams),
913 sizeof (NameServer_Params));
914 }
917 Int NameServer_getRemote(NameServer_Handle handle,
918 String name,
919 Ptr value,
920 UInt32 * len,
921 UInt16 procId)
922 {
923 Int status = NameServer_S_SUCCESS;
924 struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
925 NameServerMsg nsMsg;
926 NameServerMsg *replyMsg;
927 fd_set rfds;
928 int ret = 0, sock, maxfd, waitFd;
929 struct timeval tv;
930 uint64_t buf = 1;
931 int numBytes;
932 int err;
934 /* Set Timeout to wait: */
935 tv.tv_sec = 0;
936 tv.tv_usec = NAMESERVER_GET_TIMEOUT;
938 /* Create request message and send to remote: */
939 sock = NameServer_module->sendSock[procId];
940 LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
942 /* Create request message and send to remote processor: */
943 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
944 nsMsg.request = NAMESERVER_REQUEST;
945 nsMsg.requestStatus = 0;
947 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
948 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
950 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
951 procId, (String)nsMsg.instanceName)
952 LOG1("%s...\n", (String)nsMsg.name)
954 err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
955 if (err < 0) {
956 LOG2("NameServer_getRemote: send failed: %d, %s\n",
957 errno, strerror(errno))
958 status = NameServer_E_FAIL;
959 goto exit;
960 }
962 /* Block on waitFd for signal from listener thread: */
963 waitFd = NameServer_module->waitFd;
964 FD_ZERO(&rfds);
965 FD_SET(waitFd, &rfds);
966 maxfd = waitFd + 1;
967 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
968 ret = select(maxfd, &rfds, NULL, NULL, &tv);
969 if (ret == -1) {
970 LOG0("NameServer_getRemote: select failed.")
971 status = NameServer_E_FAIL;
972 goto exit;
973 }
974 else if (!ret) {
975 LOG0("NameServer_getRemote: select timed out.\n")
976 status = NameServer_E_TIMEOUT;
977 goto exit;
978 }
980 if (FD_ISSET(waitFd, &rfds)) {
981 /* Read, just to balance the write: */
982 numBytes = read(waitFd, &buf, sizeof(uint64_t));
984 /* Process response: */
985 replyMsg = &NameServer_module->nsMsg;
987 if (replyMsg->requestStatus) {
988 /* name is found */
989 /* set the contents of value */
990 *(UInt32 *)value = (UInt32)replyMsg->value;
992 LOG2("NameServer_getRemote: Reply from: %d, %s:",
993 procId, (String)replyMsg->instanceName)
994 LOG2("%s, value: 0x%x...\n",
995 (String)replyMsg->name, *(UInt32 *)value)
996 goto exit;
997 }
998 else {
999 /* name is not found */
1000 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1001 (String)replyMsg->instanceName, (String)replyMsg->name)
1003 /* set status to not found */
1004 status = NameServer_E_NOTFOUND;
1005 }
1006 }
1008 exit:
1009 return (status);
1010 }
1012 /* Function to retrieve the value portion of a name/value pair from
1013 * local table.
1014 */
1015 Int NameServer_get(NameServer_Handle handle,
1016 String name,
1017 Ptr value,
1018 UInt32 * len,
1019 UInt16 procId[])
1020 {
1021 Int status = NameServer_S_SUCCESS;
1022 UInt16 numProcs = MultiProc_getNumProcessors();
1023 UInt32 i;
1025 /*
1026 * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1027 * since this goes in a daemon, it will not be necessary.
1028 */
1030 if (procId == NULL) {
1031 status = NameServer_getLocal(handle, name, value, len);
1032 if (status == NameServer_E_NOTFOUND) {
1033 for (i = 0; i < numProcs; i++) {
1034 /* getLocal call already covers "self", keep going */
1035 if (i == MultiProc_self()) {
1036 continue;
1037 }
1039 status = NameServer_getRemote(handle, name, value, len, i);
1041 if ((status >= 0) ||
1042 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
1043 break;
1044 }
1045 }
1046 }
1047 }
1048 else {
1049 /*
1050 * Search the query list. It might contain the local proc
1051 * somewhere in the list.
1052 */
1053 i = 0;
1054 while (procId[i] != MultiProc_INVALIDID) {
1055 if (procId[i] == MultiProc_self()) {
1056 status = NameServer_getLocal(handle, name, value, len);
1057 }
1058 else {
1059 status = NameServer_getRemote(handle, name, value, len, i);
1060 }
1062 if ((status >= 0) ||
1063 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
1064 break;
1065 }
1067 i++;
1068 }
1069 }
1071 return (status);
1072 }
1074 /* Gets a 32-bit value by name */
1075 Int NameServer_getUInt32(NameServer_Handle handle,
1076 String name,
1077 Ptr value,
1078 UInt16 procId[])
1079 {
1080 Int status;
1081 UInt32 len = sizeof(UInt32);
1083 assert(handle != NULL);
1084 assert(name != NULL);
1085 assert(value != NULL);
1086 assert(NameServer_module->refCount != 0);
1088 status = NameServer_get(handle, name, value, &len, procId);
1090 return (status);
1091 }
1093 /* Function to Retrieve the value portion of a name/value pair from
1094 * local table.
1095 */
1096 Int NameServer_getLocal(NameServer_Handle handle,
1097 String name,
1098 Ptr value,
1099 UInt32 * len)
1100 {
1101 Int status = NameServer_E_NOTFOUND;
1102 NameServer_TableEntry * node = NULL;
1103 NameServer_TableEntry * temp = NULL;
1104 Bool done = FALSE;
1105 UInt32 length;
1106 UInt32 hash;
1108 assert(handle != NULL);
1109 assert(name != NULL);
1110 assert(value != NULL);
1111 assert(len != NULL);
1112 assert(NameServer_module->refCount != 0);
1114 length = *len;
1116 /* Calculate the hash */
1117 hash = stringHash(name);
1119 pthread_mutex_lock(&handle->gate);
1121 /* Traverse the list to find duplicate check */
1122 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1123 if (node->hash == hash) {
1124 if (node->collide == TRUE) {
1125 temp = node;
1126 while (temp) {
1127 if (strcmp(temp->name, name) == 0u){
1128 if (length <= node->len) {
1129 memcpy(value, node->value, length);
1130 *len = length;
1131 }
1132 else {
1133 memcpy(value, node->value, node->len);
1134 *len = node->len;
1135 }
1136 done = TRUE;
1137 break;
1138 }
1139 temp = temp->next;
1140 }
1141 break;
1142 }
1143 else {
1144 if (length <= node->len) {
1145 memcpy(value, node->value, length);
1146 *len = length;
1147 }
1148 else {
1149 memcpy(value, node->value, node->len);
1150 *len = node->len;
1151 }
1152 done = TRUE;
1153 break;
1154 }
1155 }
1156 }
1158 pthread_mutex_unlock(&handle->gate);
1160 if (done == FALSE) {
1161 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1162 }
1163 else {
1164 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1165 node->name, (UInt32)node->value)
1166 status = NameServer_S_SUCCESS;
1167 }
1169 return (status);
1170 }
1172 /*
1173 * Gets a 32-bit value by name from the local table
1174 *
1175 * If the name is found, the 32-bit value is copied into the value
1176 * argument and a success status is returned.
1177 *
1178 * If the name is not found, zero is returned in len and the contents
1179 * of value are not modified. Not finding a name is not considered
1180 * an error.
1181 *
1182 * This function only searches the local name/value table.
1183 *
1184 */
1185 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1186 {
1187 Int status;
1188 UInt32 len = sizeof(UInt32);
1190 assert(handle != NULL);
1191 assert(name != NULL);
1192 assert(value != NULL);
1193 assert(NameServer_module->refCount != 0);
1195 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1196 status = NameServer_getLocal(handle, name, value, &len);
1198 return (status);
1199 }
1202 #if defined (__cplusplus)
1203 }
1204 #endif /* defined (__cplusplus) */