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_daemon.c
34 *
35 * @brief NameServer Manager
36 *
37 */
40 /* Standard headers */
41 #include <ti/ipc/Std.h>
43 /* Qnx specific header files */
44 #include <pthread.h>
46 /* Socket Headers */
47 #include <sys/queue.h>
48 #include <sys/select.h>
49 #include <sys/time.h>
50 #include <sys/types.h>
51 #include <sys/param.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>
58 #include <fcntl.h>
60 /* Module level headers */
61 #include <ti/ipc/NameServer.h>
62 #include <ti/ipc/MultiProc.h>
63 #include <_MultiProc.h>
64 #include <ti/ipc/MessageQCopy.h>
66 /* Internal stuff: */
67 #include <_MessageQCopy.h>
68 #include <_NameServer.h>
69 #include <_NameServerRemoteRpmsg.h>
70 #include <_IpcLog.h>
72 /* TI Ipc utils: */
73 #include <TiIpcFxns.h>
75 #include "ti/ipc/ti_ipc.h"
77 #define MESSAGEQ_RPMSG_PORT 61
78 #define NAME_SERVER_RPMSG_ADDR 0
79 #define RPMSG_RESERVED_ADDRESSES (1024)
81 #define INVALIDSOCKET (-1)
83 #if defined (__cplusplus)
84 extern "C" {
85 #endif
88 /* =============================================================================
89 * Structures & Enums
90 * =============================================================================
91 */
93 /* Structure of entry in Name/Value table */
94 typedef struct NameServer_TableEntry_tag {
95 CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
96 /* List element */
97 UInt32 hash;
98 /* Hash value */
99 String name;
100 /* Name portion of the name/value pair. */
101 UInt len;
102 /* Length of the value field. */
103 Ptr value;
104 /* Value portion of the name/value entry. */
105 Bool collide;
106 /* Does the hash collide? */
107 struct NameServer_TableEntry_tag * next;
108 /* Pointer to the next entry, used incase of collision only */
109 } NameServer_TableEntry;
111 /* Structure defining object for the NameServer */
112 struct NameServer_Object {
113 CIRCLEQ_ENTRY(NameServer_Object) elem;
114 CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
115 String name; /* name of the instance */
116 NameServer_Params params; /* the parameter structure */
117 UInt32 count; /* count of entries */
118 pthread_mutex_t gate; /* crit sect gate */
119 } NameServer_Object;
121 /* structure for NameServer module state */
122 typedef struct NameServer_ModuleObject {
123 CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
124 Int32 refCount;
125 MessageQCopy_Handle mq;
126 /* MessageQCopy instance to receive from remote proc nameserver ports: */
127 UInt32 recvAddr;
128 /* Local endpoint for receiving from remote proc nameserver ports: */
129 pthread_t listener;
130 /* Listener thread for NameServer replies and requests. */
131 int waitFdW;
132 int waitFdR;
133 /* Pipe 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 // .modGate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
172 .modGate = PTHREAD_RMUTEX_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 char buf = 'n';
241 int numBytes;
242 int waitFd = NameServer_module->waitFdW;
244 if (msg->request == NAMESERVER_REQUEST) {
245 LOG2("NameServer Request: instanceName: %s, name: %s\n",
246 (String)msg->instanceName, (String)msg->name)
248 assert(msg->valueLen <= MAXVALUELEN);
250 /*
251 * Message is a request. Lookup name in NameServer table.
252 * Send a response message back to source processor.
253 */
254 handle = NameServer_getHandle((String)msg->instanceName);
256 if (handle != NULL) {
257 /* Search for the NameServer entry */
258 if (msg->valueLen <= sizeof (Bits32)) {
259 LOG0("Calling NameServer_getLocalUInt32...\n")
260 status = NameServer_getLocalUInt32(handle,
261 (String)msg->name, &msg->value);
262 }
263 else {
264 LOG0("Calling NameServer_getLocal...\n")
265 status = NameServer_getLocal(handle,
266 (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
267 }
268 }
270 LOG2("NameServer Response: instanceName: %s, name: %s,",
271 (String)msg->instanceName, (String)msg->name)
272 /* set the request status */
273 if (status < 0) {
274 LOG1(" Value not found, status: %d\n", status)
275 msg->requestStatus = 0;
276 }
277 else {
278 msg->requestStatus = 1;
279 LOG1(" Value: 0x%x\n", msg->value)
280 }
282 /* specify message as a response */
283 msg->request = NAMESERVER_RESPONSE;
284 msg->reserved = NAMESERVER_MSG_TOKEN;
286 /* send response message to remote processor */
287 status = MessageQCopy_send(procId, MultiProc_self(),
288 MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
289 sizeof(NameServerMsg), TRUE);
290 if (status < 0) {
291 LOG0("NameServer: MessageQCopy_send failed\n")
292 }
293 }
294 else {
295 LOG2("NameServer Reply: instanceName: %s, name: %s",
296 (String)msg->instanceName, (String)msg->name)
297 LOG1(", value: 0x%x\n", msg->value)
299 /* Save the response message. */
300 memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
302 /* Post the eventfd upon which NameServer_get() is waiting */
303 numBytes = write(waitFd, &buf, sizeof(buf));
304 }
305 }
307 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
308 void * priv, UInt32 src, UInt16 srcProc)
309 {
310 NameServerMsg msg;
312 LOG0("listener_cb: Entered Listener thread.\n")
314 LOG1("NameServer: Listener got NameServer message "
315 "from MessageQCopy: 0x%p!\n", handle);
316 /* Get NameServer message and process: */
317 memcpy(&msg, data, len);
319 if (len != sizeof(NameServerMsg)) {
320 LOG1("NameServer: got bad NameServerMsg len (%d)\n",
321 len)
322 }
323 else {
324 LOG1("listener_cb: read from MessageQCopy 0x%p\n", handle)
325 LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
326 len, src)
327 LOG1("from vproc: %d\n", srcProc)
328 NameServerRemote_processMessage(&msg, srcProc);
329 }
330 }
332 /* =============================================================================
333 * APIS
334 * =============================================================================
335 */
337 /* Function to setup the nameserver module. */
338 Int NameServer_setup(Void)
339 {
340 Int status = NameServer_S_SUCCESS;
341 UInt16 numProcs;
342 int fd[2];
344 pthread_mutex_lock(&NameServer_module->modGate);
346 LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
348 NameServer_module->refCount++;
350 if (NameServer_module->refCount > 1) {
351 LOG0("NameServer_setup: already setup\n")
352 status = NameServer_S_ALREADYSETUP;
353 goto exit;
354 }
356 numProcs = MultiProc_getNumProcessors();
358 if (pipe(fd) == -1) {
359 status = NameServer_E_FAIL;
360 LOG0("NameServer_setup: failed to create waitFd.\n")
361 goto exit;
362 }
363 NameServer_module->waitFdW = fd[1];
364 NameServer_module->waitFdR = fd[0];
366 /* Create the MessageQCopy for receiving messages from all remote proc */
367 NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
368 NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
370 if (NameServer_module->mq == NULL) {
371 status = NameServer_E_FAIL;
372 LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
373 goto exit;
374 }
376 /* Construct the list object */
377 CIRCLEQ_INIT(&NameServer_module->objList);
379 exit:
380 LOG1("NameServer_setup: exiting, refCount=%d\n", \
381 NameServer_module->refCount)
383 pthread_mutex_unlock(&NameServer_module->modGate);
385 return (status);
386 }
388 /*! Function to destroy the nameserver module. */
389 Int NameServer_destroy(void)
390 {
391 Int status = NameServer_S_SUCCESS;
393 pthread_mutex_lock(&NameServer_module->modGate);
395 LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
397 NameServer_module->refCount--;
399 if (NameServer_module->refCount > 0) {
400 LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
401 status = NameServer_S_SUCCESS;
403 goto exit;
404 }
406 /* Delete the MessageQCopy instances */
407 if (NameServer_module->mq != NULL) {
408 MessageQCopy_delete(&NameServer_module->mq);
409 }
411 CIRCLEQ_destruct(&NameServer_module->objList);
413 close(NameServer_module->waitFdW);
414 close(NameServer_module->waitFdR);
416 exit:
417 LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
419 pthread_mutex_unlock(&NameServer_module->modGate);
421 return (status);
422 }
424 /* Function to retrieve a NameServer handle from name. */
425 NameServer_Handle NameServer_getHandle(String name)
426 {
427 NameServer_Handle handle = NULL;
428 Bool found = FALSE;
429 struct NameServer_Object * elem;
431 assert(name != NULL);
432 assert(NameServer_module->refCount != 0);
434 pthread_mutex_lock(&NameServer_module->modGate);
436 /* Lookup handle from name: */
437 CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
438 handle = (NameServer_Handle) elem;
439 if (strcmp(handle->name, name) == 0) {
440 found = TRUE;
441 break;
442 }
443 }
445 if (found == FALSE) {
446 handle = NULL;
447 }
449 pthread_mutex_unlock(&NameServer_module->modGate);
451 return (handle);
452 }
455 /* Function to create a name server. */
456 NameServer_Handle NameServer_create(String name,
457 const NameServer_Params * params)
458 {
459 NameServer_Handle handle = NULL;
460 pthread_mutexattr_t mutex_attr;
462 assert(params != NULL);
463 assert(name != NULL);
464 assert(NameServer_module->refCount != 0);
466 LOG1("NameServer_create(): '%s'\n", name)
468 pthread_mutex_lock(&NameServer_module->modGate);
470 /* check if the name is already created or not */
471 if (NameServer_getHandle(name)) {
472 LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
473 handle = NULL;
474 goto leave;
475 }
476 else {
477 handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
478 }
480 if (!handle) {
481 LOG0("NameServer_create: NameServer_Handle alloc failed\n")
482 goto leave;
483 }
485 handle->name = (String)malloc(strlen(name) + 1u);
486 if (!handle->name) {
487 LOG0("NameServer_create: instance name alloc failed\n")
488 goto cleanup;
489 }
490 strncpy(handle->name, name, strlen (name) + 1u);
491 memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
493 assert(params.maxValueLen <= MAXVALUELEN);
495 if (params->maxValueLen < sizeof(UInt32)) {
496 handle->params.maxValueLen = sizeof(UInt32);
497 }
498 else {
499 handle->params.maxValueLen = params->maxValueLen;
500 }
502 CIRCLEQ_INIT(&handle->nameList);
503 handle->count = 0u;
505 /* Put in the local list */
506 CIRCLEQ_elemClear(&handle->elem);
507 CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
509 /*
510 * NameServer_removeEntry() enters gate and is called by
511 * NameServer_remove() while holding the gate.
512 */
513 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
514 pthread_mutex_init(&handle->gate, &mutex_attr);
516 goto leave;
518 cleanup:
519 free(handle);
520 handle = NULL;
522 leave:
523 pthread_mutex_unlock(&NameServer_module->modGate);
525 return (handle);
526 }
529 /* Function to delete a name server. */
530 Int NameServer_delete(NameServer_Handle * handle)
531 {
532 Int status = NameServer_S_SUCCESS;
534 assert(handle != NULL);
535 assert(*handle != NULL);
536 assert((*handle)->count == 0);
537 assert(NameServer_module->refCount != 0);
539 pthread_mutex_lock(&NameServer_module->modGate);
541 if ((*handle)->count == 0) {
542 CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
544 if ((*handle)->name != NULL) {
545 free((*handle)->name);
546 (*handle)->name = NULL;
547 }
549 CIRCLEQ_destruct(&(*handle)->nameList);
551 free((*handle));
552 (*handle) = NULL;
553 }
555 pthread_mutex_unlock(&NameServer_module->modGate);
557 return (status);
558 }
560 /* Adds a variable length value into the local NameServer table */
561 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
562 {
563 Int status = NameServer_S_SUCCESS;
564 NameServer_TableEntry * node = NULL;
565 NameServer_TableEntry * new_node = NULL;
566 Bool found = FALSE;
567 UInt32 hash;
569 assert(handle != NULL);
570 assert(name != NULL);
571 assert(buf != NULL);
572 assert(len != 0);
573 assert(NameServer_module->refCount != 0);
575 /* Calculate the hash */
576 hash = stringHash(name);
578 if (len > handle->params.maxValueLen) {
579 status = NameServer_E_INVALIDARG;
580 LOG0("NameServer_add: value length exceeded maximum!\n")
581 new_node = NULL;
582 goto exit;
583 }
585 pthread_mutex_lock(&handle->gate);
587 /* Traverse the list to find duplicate check */
588 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
589 /* Hash matches */
590 if (node->hash == hash) {
591 /* If the name matches, incase hash is duplicate */
592 if (strcmp(node->name, name) == 0) {
593 if (handle->params.checkExisting == TRUE) {
594 status = NameServer_E_INVALIDARG;
595 LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
596 break;
597 }
598 }
599 else {
600 found = TRUE;
601 break;
602 } /* name does not match */
603 } /* hash does not match */
604 } /* CIRCLEQ_traverse */
606 if (status != NameServer_S_SUCCESS) {
607 new_node = NULL;
608 goto exit;
609 }
611 /* Now add the new entry. */
612 new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
613 if (new_node == NULL) {
614 status = NameServer_E_MEMORY;
615 LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
617 goto exit;
618 }
620 new_node->hash = hash;
621 new_node->collide = found; /* Indicate if there is a collision*/
622 new_node->len = len;
623 new_node->next = NULL;
624 new_node->name = (String)malloc(strlen(name) + 1u);
625 new_node->value = (Ptr)malloc(len);
626 strncpy(new_node->name, name, strlen(name) + 1u);
627 memcpy((Ptr)new_node->value, (Ptr)buf, len);
629 if (found == TRUE) {
630 /* If hash is found, need to stitch the list to link the
631 * new node to the existing node with the same hash.
632 */
633 new_node->next = node->next;
634 node->next = new_node;
635 }
636 else {
637 /* put the new node into the list */
638 CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
639 }
641 handle->count++;
643 LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
644 name, *(UInt32 *)buf)
646 exit:
647 pthread_mutex_unlock(&handle->gate);
649 return (new_node);
650 }
653 /* Function to add a UInt32 value into a name server. */
654 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
655 {
656 Ptr entry = NULL;
658 assert(handle != NULL);
659 assert(name != NULL);
660 assert(NameServer_module->refCount != 0);
662 entry = NameServer_add(handle, name, &value, sizeof(UInt32));
664 return (entry);
665 }
667 /* Function to remove a name/value pair from a name server. */
668 Int NameServer_remove(NameServer_Handle handle, String name)
669 {
670 Int status = NameServer_S_SUCCESS;
671 NameServer_TableEntry *prev = NULL;
672 NameServer_TableEntry *temp = NULL;
673 NameServer_TableEntry *node = NULL;
674 Bool done = FALSE;
675 UInt32 hash;
677 assert(handle != NULL);
678 assert(name != NULL);
679 assert(NameServer_module->refCount != 0);
681 /* Calculate the hash */
682 hash = stringHash(name);
684 pthread_mutex_lock(&handle->gate);
686 /* Traverse the list to find duplicate check */
687 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
688 /* Hash matchs */
689 if (node->hash == hash) {
690 if (node->collide == TRUE) {
691 if (strcmp(node->name, name) == 0){
692 free(node->value);
693 free(node->name);
694 memcpy((Ptr)node, (Ptr) node->next,
695 sizeof(NameServer_TableEntry));
696 node->next = node->next->next;
697 free(node->next);
698 handle->count--;
699 done = TRUE;
700 break;
701 }
702 else {
703 prev = node;
704 temp = node->next;
705 while (temp) {
706 if (strcmp(temp->name, name) == 0){
707 free(temp->value);
708 free(temp->name);
709 prev->next = temp->next;
710 free(temp);
711 handle->count--;
712 done = TRUE;
713 break;
714 }
715 temp = temp->next;
716 }
717 break;
718 }
719 }
720 else {
721 NameServer_removeEntry(handle, (Ptr)node);
723 done = TRUE;
724 break;
725 }
726 }
727 }
729 if (done == FALSE) {
730 status = NameServer_E_INVALIDARG;
731 LOG1("NameServer_remove %d Entry not found!\n", status)
732 }
734 pthread_mutex_unlock(&handle->gate);
736 return (status);
737 }
739 /* Function to remove a name/value pair from a name server. */
740 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
741 {
742 Int status = NameServer_S_SUCCESS;
743 NameServer_TableEntry * node;
745 assert(handle != NULL);
746 assert(entry != NULL);
747 assert(NameServer_module->refCount != 0);
749 pthread_mutex_lock(&handle->gate);
751 node = (NameServer_TableEntry *)entry;
753 free(node->value);
754 free(node->name);
755 CIRCLEQ_REMOVE(&handle->nameList, node, elem);
756 free(node);
757 handle->count--;
759 pthread_mutex_unlock(&handle->gate);
761 return (status);
762 }
765 /* Initialize this config-params structure with supplier-specified
766 * defaults before instance creation.
767 */
768 Void NameServer_Params_init(NameServer_Params * params)
769 {
770 assert(params != NULL);
772 memcpy(params, &(NameServer_module->defInstParams),
773 sizeof (NameServer_Params));
774 }
777 Int NameServer_getRemote(NameServer_Handle handle,
778 String name,
779 Ptr value,
780 UInt32 * len,
781 UInt16 procId)
782 {
783 Int status = NameServer_S_SUCCESS;
784 Int mqcStatus = -1;
785 struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
786 NameServerMsg nsMsg;
787 NameServerMsg *replyMsg;
788 fd_set rfds;
789 int ret = 0, maxfd, waitFd;
790 struct timeval tv;
791 char buf = '1';
792 int numBytes;
794 pthread_mutex_lock(&NameServer_module->modGate);
796 /* Set Timeout to wait: */
797 tv.tv_sec = NAMESERVER_GET_TIMEOUT;
798 tv.tv_usec = 0;
800 /* Create request message and send to remote processor: */
801 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
802 nsMsg.request = NAMESERVER_REQUEST;
803 nsMsg.requestStatus = 0;
804 nsMsg.valueLen = *len;
806 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
807 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
809 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
810 procId, (String)nsMsg.instanceName)
811 LOG1("%s...\n", (String)nsMsg.name)
812 /* send message */
813 mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
814 RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
815 TRUE);
816 if (mqcStatus < 0) {
817 LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
818 status = NameServer_E_NOTFOUND;
819 goto exit;
820 }
822 /* Block on waitFd for signal from listener thread: */
823 waitFd = NameServer_module->waitFdR;
824 FD_ZERO(&rfds);
825 FD_SET(waitFd, &rfds);
826 maxfd = waitFd + 1;
827 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
828 ret = select(maxfd, &rfds, NULL, NULL, &tv);
829 if (ret == -1) {
830 LOG0("NameServer_getRemote: select failed.")
831 status = NameServer_E_FAIL;
832 goto exit;
833 }
834 else if (!ret) {
835 LOG0("NameServer_getRemote: select timed out.\n")
836 status = NameServer_E_TIMEOUT;
837 goto exit;
838 }
840 if (FD_ISSET(waitFd, &rfds)) {
841 /* Read, just to balance the write: */
842 numBytes = read(waitFd, &buf, sizeof(buf));
844 /* Process response: */
845 replyMsg = &NameServer_module->nsMsg;
847 if (replyMsg->requestStatus) {
848 /* name is found */
850 /* set length to amount of data that was copied */
851 *len = replyMsg->valueLen;
853 /* set the contents of value */
854 if (*len <= sizeof (Bits32)) {
855 *(UInt32 *)value = (UInt32)replyMsg->value;
856 LOG2("NameServer_getRemote: Reply from: %d, %s:",
857 procId, (String)replyMsg->instanceName)
858 LOG2("%s, value: 0x%x...\n",
859 (String)replyMsg->name, *(UInt32 *)value)
860 }
861 else {
862 memcpy(value, replyMsg->valueBuf, *len);
863 LOG2("NameServer_getRemote: Reply from: %d, %s:",
864 procId, (String)replyMsg->instanceName)
865 LOG2("%s, value buffer at address: 0x%p...\n",
866 (String)replyMsg->name, value)
867 }
869 goto exit;
870 }
871 else {
872 /* name is not found */
873 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
874 (String)replyMsg->instanceName, (String)replyMsg->name)
876 /* set status to not found */
877 status = NameServer_E_NOTFOUND;
878 }
879 }
881 exit:
882 pthread_mutex_unlock(&NameServer_module->modGate);
884 return (status);
885 }
887 /* Function to retrieve the value portion of a name/value pair from
888 * local table.
889 */
890 Int NameServer_get(NameServer_Handle handle,
891 String name,
892 Ptr value,
893 UInt32 * len,
894 UInt16 procId[])
895 {
896 Int status = NameServer_S_SUCCESS;
897 UInt16 numProcs = MultiProc_getNumProcessors();
898 UInt32 i;
900 if (procId == NULL) {
901 status = NameServer_getLocal(handle, name, value, len);
902 if (status == NameServer_E_NOTFOUND) {
903 for (i = 0; i < numProcs; i++) {
904 /* getLocal call already covers "self", keep going */
905 if (i == MultiProc_self()) {
906 continue;
907 }
909 status = NameServer_getRemote(handle, name, value, len, i);
911 if ((status >= 0) ||
912 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
913 break;
914 }
915 }
916 }
917 }
918 else {
919 /*
920 * Search the query list. It might contain the local proc
921 * somewhere in the list.
922 */
923 i = 0;
924 while (procId[i] != MultiProc_INVALIDID) {
925 if (procId[i] == MultiProc_self()) {
926 status = NameServer_getLocal(handle, name, value, len);
927 }
928 else {
929 status = NameServer_getRemote(handle, name, value, len, i);
930 }
932 if ((status >= 0) ||
933 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
934 break;
935 }
937 i++;
938 }
939 }
941 return (status);
942 }
944 /* Gets a 32-bit value by name */
945 Int NameServer_getUInt32(NameServer_Handle handle,
946 String name,
947 Ptr value,
948 UInt16 procId[])
949 {
950 Int status;
951 UInt32 len = sizeof(UInt32);
953 assert(handle != NULL);
954 assert(name != NULL);
955 assert(value != NULL);
956 assert(NameServer_module->refCount != 0);
958 status = NameServer_get(handle, name, value, &len, procId);
960 return (status);
961 }
963 /* Function to Retrieve the value portion of a name/value pair from
964 * local table.
965 */
966 Int NameServer_getLocal(NameServer_Handle handle,
967 String name,
968 Ptr value,
969 UInt32 * len)
970 {
971 Int status = NameServer_E_NOTFOUND;
972 NameServer_TableEntry * node = NULL;
973 NameServer_TableEntry * temp = NULL;
974 Bool done = FALSE;
975 UInt32 length;
976 UInt32 hash;
978 assert(handle != NULL);
979 assert(name != NULL);
980 assert(value != NULL);
981 assert(len != NULL);
982 assert(NameServer_module->refCount != 0);
984 length = *len;
986 /* Calculate the hash */
987 hash = stringHash(name);
989 pthread_mutex_lock(&handle->gate);
991 /* Traverse the list to find duplicate check */
992 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
993 if (node->hash == hash) {
994 if (node->collide == TRUE) {
995 temp = node;
996 while (temp) {
997 if (strcmp(temp->name, name) == 0u){
998 if (length <= node->len) {
999 memcpy(value, node->value, length);
1000 *len = length;
1001 }
1002 else {
1003 memcpy(value, node->value, node->len);
1004 *len = node->len;
1005 }
1006 done = TRUE;
1007 break;
1008 }
1009 temp = temp->next;
1010 }
1011 break;
1012 }
1013 else {
1014 if (length <= node->len) {
1015 memcpy(value, node->value, length);
1016 *len = length;
1017 }
1018 else {
1019 memcpy(value, node->value, node->len);
1020 *len = node->len;
1021 }
1022 done = TRUE;
1023 break;
1024 }
1025 }
1026 }
1028 pthread_mutex_unlock(&handle->gate);
1030 if (done == FALSE) {
1031 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1032 }
1033 else {
1034 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1035 node->name, (UInt32)node->value)
1036 status = NameServer_S_SUCCESS;
1037 }
1039 return (status);
1040 }
1042 /*
1043 * Gets a 32-bit value by name from the local table
1044 *
1045 * If the name is found, the 32-bit value is copied into the value
1046 * argument and a success status is returned.
1047 *
1048 * If the name is not found, zero is returned in len and the contents
1049 * of value are not modified. Not finding a name is not considered
1050 * an error.
1051 *
1052 * This function only searches the local name/value table.
1053 *
1054 */
1055 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1056 {
1057 Int status;
1058 UInt32 len = sizeof(UInt32);
1060 assert(handle != NULL);
1061 assert(name != NULL);
1062 assert(value != NULL);
1063 assert(NameServer_module->refCount != 0);
1065 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1066 status = NameServer_getLocal(handle, name, value, &len);
1068 return (status);
1069 }
1072 #if defined (__cplusplus)
1073 }
1074 #endif /* defined (__cplusplus) */