70742765d97d434c1ce51265573d1b732dd4e904
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 }
492 else {
493 /* look for at least one good send/recv pair to indicate success */
494 for (procId = 0; procId < numProcs; procId++) {
495 if (NameServer_module->sendSock[procId] != INVALIDSOCKET &&
496 NameServer_module->recvSock[procId] != INVALIDSOCKET) {
497 status = NameServer_S_SUCCESS;
499 break;
500 }
501 }
502 }
504 exit:
505 LOG1("NameServer_setup: exiting, refCount=%d\n", NameServer_module->refCount)
507 pthread_mutex_unlock(&NameServer_module->modGate);
509 return (status);
510 }
512 /*! Function to destroy the nameserver module. */
513 Int NameServer_destroy(void)
514 {
515 Int status = NameServer_S_SUCCESS;
516 UInt16 numProcs = MultiProc_getNumProcessors();
517 UInt16 procId;
518 int sock;
519 uint64_t buf = 1;
520 int numBytes;
522 pthread_mutex_lock(&NameServer_module->modGate);
524 LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
526 NameServer_module->refCount--;
528 if (NameServer_module->refCount > 0) {
529 LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
530 status = NameServer_S_SUCCESS;
532 goto exit;
533 }
535 for (procId = 0; procId < numProcs; procId++) {
536 /* Only support NameServer to remote procs: */
537 if (procId == MultiProc_self()) {
538 continue;
539 }
541 /* Close the socket: */
542 sock = NameServer_module->sendSock[procId];
543 if (sock != INVALIDSOCKET) {
544 LOG1("NameServer_destroy: closing socket: %d\n", sock)
545 close(sock);
546 NameServer_module->sendSock[procId] = INVALIDSOCKET;
547 }
548 /* Close the socket: */
549 sock = NameServer_module->recvSock[procId];
550 if (sock != INVALIDSOCKET) {
551 LOG1("NameServer_destroy: closing socket: %d\n", sock)
552 close(sock);
553 NameServer_module->recvSock[procId] = INVALIDSOCKET;
554 }
555 }
557 CIRCLEQ_destruct(&NameServer_module->objList);
559 /* Unblock the NameServer listener thread: */
560 LOG0("NameServer_destroy: unblocking listener...\n")
561 numBytes = write(NameServer_module->unblockFd, &buf, sizeof(uint64_t));
563 /* Join: */
564 LOG0("NameServer_destroy: joining listener thread...\n")
565 pthread_join(NameServer_module->listener, NULL);
567 close(NameServer_module->unblockFd);
568 close(NameServer_module->waitFd);
570 exit:
571 LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
573 pthread_mutex_unlock(&NameServer_module->modGate);
575 return (status);
576 }
578 /* Function to retrieve a NameServer handle from name. */
579 NameServer_Handle NameServer_getHandle(String name)
580 {
581 NameServer_Handle handle = NULL;
582 Bool found = FALSE;
583 struct NameServer_Object * elem;
585 assert(name != NULL);
586 assert(NameServer_module->refCount != 0);
588 pthread_mutex_lock(&NameServer_module->modGate);
590 /* Lookup handle from name: */
591 CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
592 handle = (NameServer_Handle) elem;
593 if (strcmp(handle->name, name) == 0) {
594 found = TRUE;
595 break;
596 }
597 }
599 if (found == FALSE) {
600 handle = NULL;
601 }
603 pthread_mutex_unlock(&NameServer_module->modGate);
605 return (handle);
606 }
609 /* Function to create a name server. */
610 NameServer_Handle NameServer_create(String name,
611 const NameServer_Params * params)
612 {
613 NameServer_Handle handle = NULL;
614 pthread_mutexattr_t mutex_attr;
616 assert(params != NULL);
617 assert(name != NULL);
618 assert(NameServer_module->refCount != 0);
620 LOG1("NameServer_create(): '%s'\n", name)
622 pthread_mutex_lock(&NameServer_module->modGate);
624 if (params->maxValueLen > sizeof(UInt32)) {
625 LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
626 /* Can't handle more than UInt32 at this time: */
627 goto leave;
628 }
630 /* check if the name is already created or not */
631 if (NameServer_getHandle(name)) {
632 LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
633 handle = NULL;
634 goto leave;
635 }
636 else {
637 handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
638 }
640 if (!handle) {
641 LOG0("NameServer_create: NameServer_Handle alloc failed\n")
642 goto leave;
643 }
645 handle->name = (String)malloc(strlen(name) + 1u);
646 if (!handle->name) {
647 LOG0("NameServer_create: instance name alloc failed\n")
648 goto cleanup;
649 }
650 strncpy(handle->name, name, strlen (name) + 1u);
651 memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
653 if (params->maxValueLen < sizeof(UInt32)) {
654 handle->params.maxValueLen = sizeof(UInt32);
655 }
656 else {
657 handle->params.maxValueLen = params->maxValueLen;
658 }
660 CIRCLEQ_INIT(&handle->nameList);
661 handle->count = 0u;
663 /* Put in the local list */
664 CIRCLEQ_elemClear(&handle->elem);
665 CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
667 /*
668 * NameServer_removeEntry() enters gate and is called by
669 * NameServer_remove() while holding the gate.
670 */
671 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
672 pthread_mutex_init(&handle->gate, &mutex_attr);
674 goto leave;
676 cleanup:
677 free(handle);
678 handle = NULL;
680 leave:
681 pthread_mutex_unlock(&NameServer_module->modGate);
683 return (handle);
684 }
687 /* Function to delete a name server. */
688 Int NameServer_delete(NameServer_Handle * handle)
689 {
690 Int status = NameServer_S_SUCCESS;
692 assert(handle != NULL);
693 assert(*handle != NULL);
694 assert((*handle)->count == 0);
695 assert(NameServer_module->refCount != 0);
697 pthread_mutex_lock(&NameServer_module->modGate);
699 if ((*handle)->count == 0) {
700 CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
702 if ((*handle)->name != NULL) {
703 free((*handle)->name);
704 (*handle)->name = NULL;
705 }
707 CIRCLEQ_destruct(&(*handle)->nameList);
709 free((*handle));
710 (*handle) = NULL;
711 }
713 pthread_mutex_unlock(&NameServer_module->modGate);
715 return (status);
716 }
718 /* Adds a variable length value into the local NameServer table */
719 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
720 {
721 Int status = NameServer_S_SUCCESS;
722 NameServer_TableEntry * node = NULL;
723 NameServer_TableEntry * new_node = NULL;
724 Bool found = FALSE;
725 UInt32 hash;
727 assert(handle != NULL);
728 assert(name != NULL);
729 assert(buf != NULL);
730 assert(len != 0);
731 assert(NameServer_module->refCount != 0);
733 /* Calculate the hash */
734 hash = stringHash(name);
736 pthread_mutex_lock(&handle->gate);
738 /* Traverse the list to find duplicate check */
739 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
740 /* Hash matches */
741 if (node->hash == hash) {
742 /* If the name matches, incase hash is duplicate */
743 if (strcmp(node->name, name) == 0) {
744 if (handle->params.checkExisting == TRUE) {
745 status = NameServer_E_INVALIDARG;
746 LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
747 break;
748 }
749 }
750 else {
751 found = TRUE;
752 break;
753 } /* name does not match */
754 } /* hash does not match */
755 } /* CIRCLEQ_traverse */
757 if (status != NameServer_S_SUCCESS) {
758 new_node = NULL;
759 goto exit;
760 }
762 /* Now add the new entry. */
763 new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
764 if (new_node == NULL) {
765 status = NameServer_E_MEMORY;
766 LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
768 goto exit;
769 }
771 new_node->hash = hash;
772 new_node->collide = found; /* Indicate if there is a collision*/
773 new_node->len = len;
774 new_node->next = NULL;
775 new_node->name = (String)malloc(strlen(name) + 1u);
776 new_node->value = (Ptr)malloc(len);
777 strncpy(new_node->name, name, strlen(name) + 1u);
778 memcpy((Ptr)new_node->value, (Ptr)buf, len);
780 if (found == TRUE) {
781 /* If hash is found, need to stitch the list to link the
782 * new node to the existing node with the same hash.
783 */
784 new_node->next = node->next;
785 node->next = new_node;
786 }
787 else {
788 /* put the new node into the list */
789 CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
790 }
792 handle->count++;
794 LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
795 name, *(UInt32 *)buf)
797 exit:
798 pthread_mutex_unlock(&handle->gate);
800 return (new_node);
801 }
804 /* Function to add a UInt32 value into a name server. */
805 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
806 {
807 Ptr entry = NULL;
809 assert(handle != NULL);
810 assert(name != NULL);
811 assert(NameServer_module->refCount != 0);
813 entry = NameServer_add(handle, name, &value, sizeof(UInt32));
815 return (entry);
816 }
818 /* Function to remove a name/value pair from a name server. */
819 Int NameServer_remove(NameServer_Handle handle, String name)
820 {
821 Int status = NameServer_S_SUCCESS;
822 NameServer_TableEntry *prev = NULL;
823 NameServer_TableEntry *temp = NULL;
824 NameServer_TableEntry *node = NULL;
825 Bool done = FALSE;
826 UInt32 hash;
828 assert(handle != NULL);
829 assert(name != NULL);
830 assert(NameServer_module->refCount != 0);
832 /* Calculate the hash */
833 hash = stringHash(name);
835 pthread_mutex_lock(&handle->gate);
837 /* Traverse the list to find duplicate check */
838 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
839 /* Hash matchs */
840 if (node->hash == hash) {
841 if (node->collide == TRUE) {
842 if (strcmp(node->name, name) == 0){
843 free(node->value);
844 free(node->name);
845 memcpy((Ptr)node, (Ptr) node->next,
846 sizeof(NameServer_TableEntry));
847 node->next = node->next->next;
848 free(node->next);
849 handle->count--;
850 done = TRUE;
851 break;
852 }
853 else {
854 prev = node;
855 temp = node->next;
856 while (temp) {
857 if (strcmp(temp->name, name) == 0){
858 free(temp->value);
859 free(temp->name);
860 prev->next = temp->next;
861 free(temp);
862 handle->count--;
863 done = TRUE;
864 break;
865 }
866 temp = temp->next;
867 }
868 break;
869 }
870 }
871 else {
872 NameServer_removeEntry(handle, (Ptr)node);
874 done = TRUE;
875 break;
876 }
877 }
878 }
880 if (done == FALSE) {
881 status = NameServer_E_INVALIDARG;
882 LOG1("NameServer_remove %d Entry not found!\n", status)
883 }
885 pthread_mutex_unlock(&handle->gate);
887 return (status);
888 }
890 /* Function to remove a name/value pair from a name server. */
891 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
892 {
893 Int status = NameServer_S_SUCCESS;
894 NameServer_TableEntry * node;
896 assert(handle != NULL);
897 assert(entry != NULL);
898 assert(NameServer_module->refCount != 0);
900 pthread_mutex_lock(&handle->gate);
902 node = (NameServer_TableEntry *)entry;
904 free(node->value);
905 free(node->name);
906 CIRCLEQ_REMOVE(&handle->nameList, node, elem);
907 free(node);
908 handle->count--;
910 pthread_mutex_unlock(&handle->gate);
912 return (status);
913 }
916 /* Initialize this config-params structure with supplier-specified
917 * defaults before instance creation.
918 */
919 Void NameServer_Params_init(NameServer_Params * params)
920 {
921 assert(params != NULL);
923 memcpy(params, &(NameServer_module->defInstParams),
924 sizeof (NameServer_Params));
925 }
928 Int NameServer_getRemote(NameServer_Handle handle,
929 String name,
930 Ptr value,
931 UInt32 * len,
932 UInt16 procId)
933 {
934 Int status = NameServer_S_SUCCESS;
935 struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
936 NameServerMsg nsMsg;
937 NameServerMsg *replyMsg;
938 fd_set rfds;
939 int ret = 0, sock, maxfd, waitFd;
940 struct timeval tv;
941 uint64_t buf = 1;
942 int numBytes;
943 int err;
945 /* Set Timeout to wait: */
946 tv.tv_sec = 0;
947 tv.tv_usec = NAMESERVER_GET_TIMEOUT;
949 /* Create request message and send to remote: */
950 sock = NameServer_module->sendSock[procId];
951 if (sock == INVALIDSOCKET) {
952 LOG1("NameServer_getRemote: no socket connection to processor %d\n",
953 procId);
954 status = NameServer_E_RESOURCE;
955 goto exit;
956 }
958 LOG1("NameServer_getRemote: Sending request via sock: %d\n", sock)
960 /* Create request message and send to remote processor: */
961 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
962 nsMsg.request = NAMESERVER_REQUEST;
963 nsMsg.requestStatus = 0;
965 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
966 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
968 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
969 procId, (String)nsMsg.instanceName)
970 LOG1("%s...\n", (String)nsMsg.name)
972 err = send(sock, &nsMsg, sizeof(NameServerMsg), 0);
973 if (err < 0) {
974 LOG2("NameServer_getRemote: send failed: %d, %s\n",
975 errno, strerror(errno))
976 status = NameServer_E_FAIL;
977 goto exit;
978 }
980 /* Block on waitFd for signal from listener thread: */
981 waitFd = NameServer_module->waitFd;
982 FD_ZERO(&rfds);
983 FD_SET(waitFd, &rfds);
984 maxfd = waitFd + 1;
985 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
986 ret = select(maxfd, &rfds, NULL, NULL, &tv);
987 if (ret == -1) {
988 LOG0("NameServer_getRemote: select failed.")
989 status = NameServer_E_FAIL;
990 goto exit;
991 }
992 else if (!ret) {
993 LOG0("NameServer_getRemote: select timed out.\n")
994 status = NameServer_E_TIMEOUT;
995 goto exit;
996 }
998 if (FD_ISSET(waitFd, &rfds)) {
999 /* Read, just to balance the write: */
1000 numBytes = read(waitFd, &buf, sizeof(uint64_t));
1002 /* Process response: */
1003 replyMsg = &NameServer_module->nsMsg;
1005 if (replyMsg->requestStatus) {
1006 /* name is found */
1007 /* set the contents of value */
1008 *(UInt32 *)value = (UInt32)replyMsg->value;
1010 LOG2("NameServer_getRemote: Reply from: %d, %s:",
1011 procId, (String)replyMsg->instanceName)
1012 LOG2("%s, value: 0x%x...\n",
1013 (String)replyMsg->name, *(UInt32 *)value)
1014 goto exit;
1015 }
1016 else {
1017 /* name is not found */
1018 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
1019 (String)replyMsg->instanceName, (String)replyMsg->name)
1021 /* set status to not found */
1022 status = NameServer_E_NOTFOUND;
1023 }
1024 }
1026 exit:
1027 return (status);
1028 }
1030 /* Function to retrieve the value portion of a name/value pair from
1031 * local table.
1032 */
1033 Int NameServer_get(NameServer_Handle handle,
1034 String name,
1035 Ptr value,
1036 UInt32 * len,
1037 UInt16 procId[])
1038 {
1039 Int status = NameServer_S_SUCCESS;
1040 UInt16 numProcs = MultiProc_getNumProcessors();
1041 UInt32 i;
1043 /*
1044 * BIOS side uses a gate (mutex) to protect NameServer_module->nsMsg, but
1045 * since this goes in a daemon, it will not be necessary.
1046 */
1048 if (procId == NULL) {
1049 status = NameServer_getLocal(handle, name, value, len);
1050 if (status == NameServer_E_NOTFOUND) {
1051 for (i = 0; i < numProcs; i++) {
1052 /* getLocal call already covers "self", keep going */
1053 if (i == MultiProc_self()) {
1054 continue;
1055 }
1057 status = NameServer_getRemote(handle, name, value, len, i);
1059 if ((status >= 0) ||
1060 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1061 (status != NameServer_E_RESOURCE))) {
1062 break;
1063 }
1064 }
1065 }
1066 }
1067 else {
1068 /*
1069 * Search the query list. It might contain the local proc
1070 * somewhere in the list.
1071 */
1072 i = 0;
1073 while (procId[i] != MultiProc_INVALIDID) {
1074 if (procId[i] == MultiProc_self()) {
1075 status = NameServer_getLocal(handle, name, value, len);
1076 }
1077 else {
1078 status = NameServer_getRemote(handle, name, value, len, i);
1079 }
1081 if ((status >= 0) ||
1082 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
1083 (status != NameServer_E_RESOURCE))) {
1084 break;
1085 }
1087 i++;
1088 }
1089 }
1091 if (status == NameServer_E_RESOURCE) {
1092 status = NameServer_E_NOTFOUND;
1093 }
1095 return (status);
1096 }
1098 /* Gets a 32-bit value by name */
1099 Int NameServer_getUInt32(NameServer_Handle handle,
1100 String name,
1101 Ptr value,
1102 UInt16 procId[])
1103 {
1104 Int status;
1105 UInt32 len = sizeof(UInt32);
1107 assert(handle != NULL);
1108 assert(name != NULL);
1109 assert(value != NULL);
1110 assert(NameServer_module->refCount != 0);
1112 status = NameServer_get(handle, name, value, &len, procId);
1114 return (status);
1115 }
1117 /* Function to Retrieve the value portion of a name/value pair from
1118 * local table.
1119 */
1120 Int NameServer_getLocal(NameServer_Handle handle,
1121 String name,
1122 Ptr value,
1123 UInt32 * len)
1124 {
1125 Int status = NameServer_E_NOTFOUND;
1126 NameServer_TableEntry * node = NULL;
1127 NameServer_TableEntry * temp = NULL;
1128 Bool done = FALSE;
1129 UInt32 length;
1130 UInt32 hash;
1132 assert(handle != NULL);
1133 assert(name != NULL);
1134 assert(value != NULL);
1135 assert(len != NULL);
1136 assert(NameServer_module->refCount != 0);
1138 length = *len;
1140 /* Calculate the hash */
1141 hash = stringHash(name);
1143 pthread_mutex_lock(&handle->gate);
1145 /* Traverse the list to find duplicate check */
1146 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1147 if (node->hash == hash) {
1148 if (node->collide == TRUE) {
1149 temp = node;
1150 while (temp) {
1151 if (strcmp(temp->name, name) == 0u){
1152 if (length <= node->len) {
1153 memcpy(value, node->value, length);
1154 *len = length;
1155 }
1156 else {
1157 memcpy(value, node->value, node->len);
1158 *len = node->len;
1159 }
1160 done = TRUE;
1161 break;
1162 }
1163 temp = temp->next;
1164 }
1165 break;
1166 }
1167 else {
1168 if (length <= node->len) {
1169 memcpy(value, node->value, length);
1170 *len = length;
1171 }
1172 else {
1173 memcpy(value, node->value, node->len);
1174 *len = node->len;
1175 }
1176 done = TRUE;
1177 break;
1178 }
1179 }
1180 }
1182 pthread_mutex_unlock(&handle->gate);
1184 if (done == FALSE) {
1185 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1186 }
1187 else {
1188 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1189 node->name, (UInt32)node->value)
1190 status = NameServer_S_SUCCESS;
1191 }
1193 return (status);
1194 }
1196 /*
1197 * Gets a 32-bit value by name from the local table
1198 *
1199 * If the name is found, the 32-bit value is copied into the value
1200 * argument and a success status is returned.
1201 *
1202 * If the name is not found, zero is returned in len and the contents
1203 * of value are not modified. Not finding a name is not considered
1204 * an error.
1205 *
1206 * This function only searches the local name/value table.
1207 *
1208 */
1209 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1210 {
1211 Int status;
1212 UInt32 len = sizeof(UInt32);
1214 assert(handle != NULL);
1215 assert(name != NULL);
1216 assert(value != NULL);
1217 assert(NameServer_module->refCount != 0);
1219 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1220 status = NameServer_getLocal(handle, name, value, &len);
1222 return (status);
1223 }
1226 #if defined (__cplusplus)
1227 }
1228 #endif /* defined (__cplusplus) */