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 *
37 */
40 /* Standard headers */
41 #include <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 <_MessageQCopyDefs.h>
69 #include <_NameServer.h>
70 #include <_NameServerRemoteRpmsg.h>
71 #include <_IpcLog.h>
73 /* TI Ipc utils: */
74 #include <TiIpcFxns.h>
76 #include "ti/ipc/ti_ipc.h"
78 #define MESSAGEQ_RPMSG_PORT 61
79 #define NAME_SERVER_RPMSG_ADDR 0
80 #define RPMSG_RESERVED_ADDRESSES (1024)
82 #define INVALIDSOCKET (-1)
84 #if defined (__cplusplus)
85 extern "C" {
86 #endif
89 /* =============================================================================
90 * Structures & Enums
91 * =============================================================================
92 */
94 /* Structure of entry in Name/Value table */
95 typedef struct NameServer_TableEntry_tag {
96 CIRCLEQ_ENTRY(NameServer_TableEntry_tag) elem;
97 /* List element */
98 UInt32 hash;
99 /* Hash value */
100 String name;
101 /* Name portion of the name/value pair. */
102 UInt len;
103 /* Length of the value field. */
104 Ptr value;
105 /* Value portion of the name/value entry. */
106 Bool collide;
107 /* Does the hash collide? */
108 struct NameServer_TableEntry_tag * next;
109 /* Pointer to the next entry, used incase of collision only */
110 } NameServer_TableEntry;
112 /* Structure defining object for the NameServer */
113 struct NameServer_Object {
114 CIRCLEQ_ENTRY(NameServer_Object) elem;
115 CIRCLEQ_HEAD(dummy2, NameServer_TableEntry_tag) nameList;
116 String name; /* name of the instance */
117 NameServer_Params params; /* the parameter structure */
118 UInt32 count; /* count of entries */
119 pthread_mutex_t gate; /* crit sect gate */
120 } NameServer_Object;
122 /* structure for NameServer module state */
123 typedef struct NameServer_ModuleObject {
124 CIRCLEQ_HEAD(dummy1, NameServer_Object) objList;
125 Int32 refCount;
126 MessageQCopy_Handle mq;
127 /* MessageQCopy instance to receive from remote proc nameserver ports: */
128 UInt32 recvAddr;
129 /* Local endpoint for receiving from remote proc nameserver ports: */
130 pthread_t listener;
131 /* Listener thread for NameServer replies and requests. */
132 int waitFdW;
133 int waitFdR;
134 /* Pipe to post to NameServer_get. */
135 NameServerMsg nsMsg;
136 /* NameServer Message cache. */
137 NameServer_Params defInstParams;
138 /* Default instance paramters */
139 pthread_mutex_t modGate;
140 } NameServer_ModuleObject;
142 #define CIRCLEQ_destruct(head) { \
143 (head)->cqh_first = NULL; \
144 (head)->cqh_last = NULL; \
145 }
147 #define CIRCLEQ_elemClear(elem) { \
148 (elem)->cqe_next = (elem)->cqe_prev = (Void *)(elem); \
149 }
151 #define CIRCLEQ_traverse(x, y, tag) \
152 for (x = (y)->cqh_first; x != (struct tag *)(y); x = x->elem.cqe_next)
154 /* =============================================================================
155 * Globals
156 * =============================================================================
157 */
158 /*
159 * NameServer_state
160 *
161 * Make the module gate "recursive" since NameServer_getHandle() needs to
162 * use it and NameServer_create() needs to hold it around its call to
163 * NameServer_getHandle(). Also, use the static initializer instead of a
164 * run-time init call, so we can use this gate immediately in _setup().
165 */
166 static NameServer_ModuleObject NameServer_state = {
167 .defInstParams.maxRuntimeEntries = 0u,
168 .defInstParams.tableHeap = NULL,
169 .defInstParams.checkExisting = TRUE,
170 .defInstParams.maxValueLen = 0u,
171 .defInstParams.maxNameLen = 16u,
172 // .modGate = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
173 .modGate = PTHREAD_RMUTEX_INITIALIZER,
174 .refCount = 0
175 };
177 static NameServer_ModuleObject * NameServer_module = &NameServer_state;
179 static const UInt32 stringCrcTab[256u] = {
180 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
181 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
182 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
183 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
184 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
185 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
186 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
187 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
188 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
189 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
190 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
191 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
192 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
193 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
194 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
195 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
196 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
197 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
198 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
199 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
200 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
201 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
202 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
203 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
204 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
205 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
206 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
207 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
208 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
209 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
210 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
211 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
212 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
213 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
214 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
215 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
216 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
217 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
218 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
219 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
220 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
221 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
222 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
223 };
225 static UInt32 stringHash(String s)
226 {
227 UInt32 hash = strlen(s);
228 UInt32 i;
230 for (i = 0; i < strlen(s); i++) {
231 hash = (hash >> 8u) ^ stringCrcTab[(hash & 0xff)] ^ s[i];
232 }
234 return (hash);
235 }
237 static void NameServerRemote_processMessage(NameServerMsg * msg, UInt16 procId)
238 {
239 NameServer_Handle handle;
240 Int status = NameServer_E_FAIL;
241 char buf = 'n';
242 int numBytes;
243 int waitFd = NameServer_module->waitFdW;
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 status = MessageQCopy_send(procId, MultiProc_self(),
280 MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
281 sizeof(NameServerMsg), TRUE);
282 if (status < 0) {
283 LOG0("NameServer: MessageQCopy_send failed\n")
284 }
285 }
286 else {
287 LOG2("NameServer Reply: instanceName: %s, name: %s",
288 (String)msg->instanceName, (String)msg->name)
289 LOG1(", value: 0x%x\n", msg->value)
291 /* Save the response message. */
292 memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
294 /* Post the eventfd upon which NameServer_get() is waiting */
295 numBytes = write(waitFd, &buf, sizeof(buf));
296 }
297 }
299 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
300 void * priv, UInt32 src, UInt16 srcProc)
301 {
302 NameServerMsg msg;
304 LOG0("listener_cb: Entered Listener thread.\n")
306 LOG1("NameServer: Listener got NameServer message "
307 "from MessageQCopy: 0x%x!\n", handle);
308 /* Get NameServer message and process: */
309 memcpy(&msg, data, len);
311 if (len != sizeof(NameServerMsg)) {
312 LOG1("NameServer: got bad NameServerMsg len (%d)\n",
313 len)
314 }
315 else {
316 LOG1("listener_cb: read from MessageQCopy 0x%x\n", handle)
317 LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
318 len, src)
319 LOG1("from vproc: %d\n", srcProc)
320 NameServerRemote_processMessage(&msg, srcProc);
321 }
322 }
324 /* =============================================================================
325 * APIS
326 * =============================================================================
327 */
329 /* Function to setup the nameserver module. */
330 Int NameServer_setup(Void)
331 {
332 Int status = NameServer_S_SUCCESS;
333 UInt16 numProcs;
334 int fd[2];
336 pthread_mutex_lock(&NameServer_module->modGate);
338 LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
340 NameServer_module->refCount++;
342 if (NameServer_module->refCount > 1) {
343 LOG0("NameServer_setup: already setup\n")
344 status = NameServer_S_ALREADYSETUP;
345 goto exit;
346 }
348 numProcs = MultiProc_getNumProcessors();
350 if (pipe(fd) == -1) {
351 status = NameServer_E_FAIL;
352 LOG0("NameServer_setup: failed to create waitFd.\n")
353 goto exit;
354 }
355 NameServer_module->waitFdW = fd[1];
356 NameServer_module->waitFdR = fd[0];
358 /* Create the MessageQCopy for receiving messages from all remote proc */
359 NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
360 NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
362 if (NameServer_module->mq == NULL) {
363 status = NameServer_E_FAIL;
364 LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
365 goto exit;
366 }
368 /* Construct the list object */
369 CIRCLEQ_INIT(&NameServer_module->objList);
371 exit:
372 LOG1("NameServer_setup: exiting, refCount=%d\n", \
373 NameServer_module->refCount)
375 pthread_mutex_unlock(&NameServer_module->modGate);
377 return (status);
378 }
380 /*! Function to destroy the nameserver module. */
381 Int NameServer_destroy(void)
382 {
383 Int status = NameServer_S_SUCCESS;
385 pthread_mutex_lock(&NameServer_module->modGate);
387 LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
389 NameServer_module->refCount--;
391 if (NameServer_module->refCount > 0) {
392 LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
393 status = NameServer_S_SUCCESS;
395 goto exit;
396 }
398 /* Delete the MessageQCopy instances */
399 if (NameServer_module->mq != NULL) {
400 MessageQCopy_delete(&NameServer_module->mq);
401 }
403 CIRCLEQ_destruct(&NameServer_module->objList);
405 close(NameServer_module->waitFdW);
406 close(NameServer_module->waitFdR);
408 exit:
409 LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
411 pthread_mutex_unlock(&NameServer_module->modGate);
413 return (status);
414 }
416 /* Function to retrieve a NameServer handle from name. */
417 NameServer_Handle NameServer_getHandle(String name)
418 {
419 NameServer_Handle handle = NULL;
420 Bool found = FALSE;
421 struct NameServer_Object * elem;
423 assert(name != NULL);
424 assert(NameServer_module->refCount != 0);
426 pthread_mutex_lock(&NameServer_module->modGate);
428 /* Lookup handle from name: */
429 CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
430 handle = (NameServer_Handle) elem;
431 if (strcmp(handle->name, name) == 0) {
432 found = TRUE;
433 break;
434 }
435 }
437 if (found == FALSE) {
438 handle = NULL;
439 }
441 pthread_mutex_unlock(&NameServer_module->modGate);
443 return (handle);
444 }
447 /* Function to create a name server. */
448 NameServer_Handle NameServer_create(String name,
449 const NameServer_Params * params)
450 {
451 NameServer_Handle handle = NULL;
452 pthread_mutexattr_t mutex_attr;
454 assert(params != NULL);
455 assert(name != NULL);
456 assert(NameServer_module->refCount != 0);
458 LOG1("NameServer_create(): '%s'\n", name)
460 pthread_mutex_lock(&NameServer_module->modGate);
462 if (params->maxValueLen > sizeof(UInt32)) {
463 LOG1("NameServer_create: params->maxValueLen (%d) too big for now\n", params->maxValueLen)
464 /* Can't handle more than UInt32 at this time: */
465 goto leave;
466 }
468 /* check if the name is already created or not */
469 if (NameServer_getHandle(name)) {
470 LOG0("NameServer_create NameServer_E_INVALIDARG Name is in use!\n")
471 handle = NULL;
472 goto leave;
473 }
474 else {
475 handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
476 }
478 if (!handle) {
479 LOG0("NameServer_create: NameServer_Handle alloc failed\n")
480 goto leave;
481 }
483 handle->name = (String)malloc(strlen(name) + 1u);
484 if (!handle->name) {
485 LOG0("NameServer_create: instance name alloc failed\n")
486 goto cleanup;
487 }
488 strncpy(handle->name, name, strlen (name) + 1u);
489 memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
491 if (params->maxValueLen < sizeof(UInt32)) {
492 handle->params.maxValueLen = sizeof(UInt32);
493 }
494 else {
495 handle->params.maxValueLen = params->maxValueLen;
496 }
498 CIRCLEQ_INIT(&handle->nameList);
499 handle->count = 0u;
501 /* Put in the local list */
502 CIRCLEQ_elemClear(&handle->elem);
503 CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
505 /*
506 * NameServer_removeEntry() enters gate and is called by
507 * NameServer_remove() while holding the gate.
508 */
509 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
510 pthread_mutex_init(&handle->gate, &mutex_attr);
512 goto leave;
514 cleanup:
515 free(handle);
516 handle = NULL;
518 leave:
519 pthread_mutex_unlock(&NameServer_module->modGate);
521 return (handle);
522 }
525 /* Function to delete a name server. */
526 Int NameServer_delete(NameServer_Handle * handle)
527 {
528 Int status = NameServer_S_SUCCESS;
530 assert(handle != NULL);
531 assert(*handle != NULL);
532 assert((*handle)->count == 0);
533 assert(NameServer_module->refCount != 0);
535 pthread_mutex_lock(&NameServer_module->modGate);
537 if ((*handle)->count == 0) {
538 CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
540 if ((*handle)->name != NULL) {
541 free((*handle)->name);
542 (*handle)->name = NULL;
543 }
545 CIRCLEQ_destruct(&(*handle)->nameList);
547 free((*handle));
548 (*handle) = NULL;
549 }
551 pthread_mutex_unlock(&NameServer_module->modGate);
553 return (status);
554 }
556 /* Adds a variable length value into the local NameServer table */
557 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
558 {
559 Int status = NameServer_S_SUCCESS;
560 NameServer_TableEntry * node = NULL;
561 NameServer_TableEntry * new_node = NULL;
562 Bool found = FALSE;
563 UInt32 hash;
565 assert(handle != NULL);
566 assert(name != NULL);
567 assert(buf != NULL);
568 assert(len != 0);
569 assert(NameServer_module->refCount != 0);
571 /* Calculate the hash */
572 hash = stringHash(name);
574 pthread_mutex_lock(&handle->gate);
576 /* Traverse the list to find duplicate check */
577 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
578 /* Hash matches */
579 if (node->hash == hash) {
580 /* If the name matches, incase hash is duplicate */
581 if (strcmp(node->name, name) == 0) {
582 if (handle->params.checkExisting == TRUE) {
583 status = NameServer_E_INVALIDARG;
584 LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
585 break;
586 }
587 }
588 else {
589 found = TRUE;
590 break;
591 } /* name does not match */
592 } /* hash does not match */
593 } /* CIRCLEQ_traverse */
595 if (status != NameServer_S_SUCCESS) {
596 new_node = NULL;
597 goto exit;
598 }
600 /* Now add the new entry. */
601 new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
602 if (new_node == NULL) {
603 status = NameServer_E_MEMORY;
604 LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
606 goto exit;
607 }
609 new_node->hash = hash;
610 new_node->collide = found; /* Indicate if there is a collision*/
611 new_node->len = len;
612 new_node->next = NULL;
613 new_node->name = (String)malloc(strlen(name) + 1u);
614 new_node->value = (Ptr)malloc(len);
615 strncpy(new_node->name, name, strlen(name) + 1u);
616 memcpy((Ptr)new_node->value, (Ptr)buf, len);
618 if (found == TRUE) {
619 /* If hash is found, need to stitch the list to link the
620 * new node to the existing node with the same hash.
621 */
622 new_node->next = node->next;
623 node->next = new_node;
624 }
625 else {
626 /* put the new node into the list */
627 CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
628 }
630 handle->count++;
632 LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
633 name, *(UInt32 *)buf)
635 exit:
636 pthread_mutex_unlock(&handle->gate);
638 return (new_node);
639 }
642 /* Function to add a UInt32 value into a name server. */
643 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
644 {
645 Ptr entry = NULL;
647 assert(handle != NULL);
648 assert(name != NULL);
649 assert(NameServer_module->refCount != 0);
651 entry = NameServer_add(handle, name, &value, sizeof(UInt32));
653 return (entry);
654 }
656 /* Function to remove a name/value pair from a name server. */
657 Int NameServer_remove(NameServer_Handle handle, String name)
658 {
659 Int status = NameServer_S_SUCCESS;
660 NameServer_TableEntry *prev = NULL;
661 NameServer_TableEntry *temp = NULL;
662 NameServer_TableEntry *node = NULL;
663 Bool done = FALSE;
664 UInt32 hash;
666 assert(handle != NULL);
667 assert(name != NULL);
668 assert(NameServer_module->refCount != 0);
670 /* Calculate the hash */
671 hash = stringHash(name);
673 pthread_mutex_lock(&handle->gate);
675 /* Traverse the list to find duplicate check */
676 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
677 /* Hash matchs */
678 if (node->hash == hash) {
679 if (node->collide == TRUE) {
680 if (strcmp(node->name, name) == 0){
681 free(node->value);
682 free(node->name);
683 memcpy((Ptr)node, (Ptr) node->next,
684 sizeof(NameServer_TableEntry));
685 node->next = node->next->next;
686 free(node->next);
687 handle->count--;
688 done = TRUE;
689 break;
690 }
691 else {
692 prev = node;
693 temp = node->next;
694 while (temp) {
695 if (strcmp(temp->name, name) == 0){
696 free(temp->value);
697 free(temp->name);
698 prev->next = temp->next;
699 free(temp);
700 handle->count--;
701 done = TRUE;
702 break;
703 }
704 temp = temp->next;
705 }
706 break;
707 }
708 }
709 else {
710 NameServer_removeEntry(handle, (Ptr)node);
712 done = TRUE;
713 break;
714 }
715 }
716 }
718 if (done == FALSE) {
719 status = NameServer_E_INVALIDARG;
720 LOG1("NameServer_remove %d Entry not found!\n", status)
721 }
723 pthread_mutex_unlock(&handle->gate);
725 return (status);
726 }
728 /* Function to remove a name/value pair from a name server. */
729 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
730 {
731 Int status = NameServer_S_SUCCESS;
732 NameServer_TableEntry * node;
734 assert(handle != NULL);
735 assert(entry != NULL);
736 assert(NameServer_module->refCount != 0);
738 pthread_mutex_lock(&handle->gate);
740 node = (NameServer_TableEntry *)entry;
742 free(node->value);
743 free(node->name);
744 CIRCLEQ_REMOVE(&handle->nameList, node, elem);
745 free(node);
746 handle->count--;
748 pthread_mutex_unlock(&handle->gate);
750 return (status);
751 }
754 /* Initialize this config-params structure with supplier-specified
755 * defaults before instance creation.
756 */
757 Void NameServer_Params_init(NameServer_Params * params)
758 {
759 assert(params != NULL);
761 memcpy(params, &(NameServer_module->defInstParams),
762 sizeof (NameServer_Params));
763 }
766 Int NameServer_getRemote(NameServer_Handle handle,
767 String name,
768 Ptr value,
769 UInt32 * len,
770 UInt16 procId)
771 {
772 Int status = NameServer_S_SUCCESS;
773 Int mqcStatus = -1;
774 struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
775 NameServerMsg nsMsg;
776 NameServerMsg *replyMsg;
777 fd_set rfds;
778 int ret = 0, maxfd, waitFd;
779 struct timeval tv;
780 char buf = '1';
781 int numBytes;
783 pthread_mutex_lock(&NameServer_module->modGate);
785 /* Set Timeout to wait: */
786 tv.tv_sec = NAMESERVER_GET_TIMEOUT;
787 tv.tv_usec = 0;
789 /* Create request message and send to remote processor: */
790 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
791 nsMsg.request = NAMESERVER_REQUEST;
792 nsMsg.requestStatus = 0;
794 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
795 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
797 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
798 procId, (String)nsMsg.instanceName)
799 LOG1("%s...\n", (String)nsMsg.name)
800 /* send message */
801 mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
802 RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
803 TRUE);
804 if (mqcStatus < 0) {
805 LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
806 status = NameServer_E_NOTFOUND;
807 goto exit;
808 }
810 /* Block on waitFd for signal from listener thread: */
811 waitFd = NameServer_module->waitFdR;
812 FD_ZERO(&rfds);
813 FD_SET(waitFd, &rfds);
814 maxfd = waitFd + 1;
815 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
816 ret = select(maxfd, &rfds, NULL, NULL, &tv);
817 if (ret == -1) {
818 LOG0("NameServer_getRemote: select failed.")
819 status = NameServer_E_FAIL;
820 goto exit;
821 }
822 else if (!ret) {
823 LOG0("NameServer_getRemote: select timed out.\n")
824 status = NameServer_E_TIMEOUT;
825 goto exit;
826 }
828 if (FD_ISSET(waitFd, &rfds)) {
829 /* Read, just to balance the write: */
830 numBytes = read(waitFd, &buf, sizeof(buf));
832 /* Process response: */
833 replyMsg = &NameServer_module->nsMsg;
835 if (replyMsg->requestStatus) {
836 /* name is found */
837 /* set the contents of value */
838 *(UInt32 *)value = (UInt32)replyMsg->value;
840 LOG2("NameServer_getRemote: Reply from: %d, %s:",
841 procId, (String)replyMsg->instanceName)
842 LOG2("%s, value: 0x%x...\n",
843 (String)replyMsg->name, *(UInt32 *)value)
844 goto exit;
845 }
846 else {
847 /* name is not found */
848 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
849 (String)replyMsg->instanceName, (String)replyMsg->name)
851 /* set status to not found */
852 status = NameServer_E_NOTFOUND;
853 }
854 }
856 exit:
857 pthread_mutex_unlock(&NameServer_module->modGate);
859 return (status);
860 }
862 /* Function to retrieve the value portion of a name/value pair from
863 * local table.
864 */
865 Int NameServer_get(NameServer_Handle handle,
866 String name,
867 Ptr value,
868 UInt32 * len,
869 UInt16 procId[])
870 {
871 Int status = NameServer_S_SUCCESS;
872 UInt16 numProcs = MultiProc_getNumProcessors();
873 UInt32 i;
875 if (procId == NULL) {
876 status = NameServer_getLocal(handle, name, value, len);
877 if (status == NameServer_E_NOTFOUND) {
878 for (i = 0; i < numProcs; i++) {
879 /* getLocal call already covers "self", keep going */
880 if (i == MultiProc_self()) {
881 continue;
882 }
884 status = NameServer_getRemote(handle, name, value, len, i);
886 if ((status >= 0) ||
887 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
888 break;
889 }
890 }
891 }
892 }
893 else {
894 /*
895 * Search the query list. It might contain the local proc
896 * somewhere in the list.
897 */
898 i = 0;
899 while (procId[i] != MultiProc_INVALIDID) {
900 if (procId[i] == MultiProc_self()) {
901 status = NameServer_getLocal(handle, name, value, len);
902 }
903 else {
904 status = NameServer_getRemote(handle, name, value, len, i);
905 }
907 if ((status >= 0) ||
908 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
909 break;
910 }
912 i++;
913 }
914 }
916 return (status);
917 }
919 /* Gets a 32-bit value by name */
920 Int NameServer_getUInt32(NameServer_Handle handle,
921 String name,
922 Ptr value,
923 UInt16 procId[])
924 {
925 Int status;
926 UInt32 len = sizeof(UInt32);
928 assert(handle != NULL);
929 assert(name != NULL);
930 assert(value != NULL);
931 assert(NameServer_module->refCount != 0);
933 status = NameServer_get(handle, name, value, &len, procId);
935 return (status);
936 }
938 /* Function to Retrieve the value portion of a name/value pair from
939 * local table.
940 */
941 Int NameServer_getLocal(NameServer_Handle handle,
942 String name,
943 Ptr value,
944 UInt32 * len)
945 {
946 Int status = NameServer_E_NOTFOUND;
947 NameServer_TableEntry * node = NULL;
948 NameServer_TableEntry * temp = NULL;
949 Bool done = FALSE;
950 UInt32 length;
951 UInt32 hash;
953 assert(handle != NULL);
954 assert(name != NULL);
955 assert(value != NULL);
956 assert(len != NULL);
957 assert(NameServer_module->refCount != 0);
959 length = *len;
961 /* Calculate the hash */
962 hash = stringHash(name);
964 pthread_mutex_lock(&handle->gate);
966 /* Traverse the list to find duplicate check */
967 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
968 if (node->hash == hash) {
969 if (node->collide == TRUE) {
970 temp = node;
971 while (temp) {
972 if (strcmp(temp->name, name) == 0u){
973 if (length <= node->len) {
974 memcpy(value, node->value, length);
975 *len = length;
976 }
977 else {
978 memcpy(value, node->value, node->len);
979 *len = node->len;
980 }
981 done = TRUE;
982 break;
983 }
984 temp = temp->next;
985 }
986 break;
987 }
988 else {
989 if (length <= node->len) {
990 memcpy(value, node->value, length);
991 *len = length;
992 }
993 else {
994 memcpy(value, node->value, node->len);
995 *len = node->len;
996 }
997 done = TRUE;
998 break;
999 }
1000 }
1001 }
1003 pthread_mutex_unlock(&handle->gate);
1005 if (done == FALSE) {
1006 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1007 }
1008 else {
1009 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1010 node->name, (UInt32)node->value)
1011 status = NameServer_S_SUCCESS;
1012 }
1014 return (status);
1015 }
1017 /*
1018 * Gets a 32-bit value by name from the local table
1019 *
1020 * If the name is found, the 32-bit value is copied into the value
1021 * argument and a success status is returned.
1022 *
1023 * If the name is not found, zero is returned in len and the contents
1024 * of value are not modified. Not finding a name is not considered
1025 * an error.
1026 *
1027 * This function only searches the local name/value table.
1028 *
1029 */
1030 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1031 {
1032 Int status;
1033 UInt32 len = sizeof(UInt32);
1035 assert(handle != NULL);
1036 assert(name != NULL);
1037 assert(value != NULL);
1038 assert(NameServer_module->refCount != 0);
1040 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1041 status = NameServer_getLocal(handle, name, value, &len);
1043 return (status);
1044 }
1047 #if defined (__cplusplus)
1048 }
1049 #endif /* defined (__cplusplus) */