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 UInt32 refCount; /* reference count to this object */
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 assert(msg->valueLen <= MAXVALUELEN);
251 /*
252 * Message is a request. Lookup name in NameServer table.
253 * Send a response message back to source processor.
254 */
255 handle = NameServer_getHandle((String)msg->instanceName);
257 if (handle != NULL) {
258 /* Search for the NameServer entry */
259 if (msg->valueLen <= sizeof (Bits32)) {
260 LOG0("Calling NameServer_getLocalUInt32...\n")
261 status = NameServer_getLocalUInt32(handle,
262 (String)msg->name, &msg->value);
263 }
264 else {
265 LOG0("Calling NameServer_getLocal...\n")
266 status = NameServer_getLocal(handle,
267 (String)msg->name, (Ptr)msg->valueBuf, &msg->valueLen);
268 }
269 }
271 LOG2("NameServer Response: instanceName: %s, name: %s,",
272 (String)msg->instanceName, (String)msg->name)
273 /* set the request status */
274 if (status < 0) {
275 LOG1(" Value not found, status: %d\n", status)
276 msg->requestStatus = 0;
277 }
278 else {
279 msg->requestStatus = 1;
280 LOG1(" Value: 0x%x\n", msg->value)
281 }
283 /* specify message as a response */
284 msg->request = NAMESERVER_RESPONSE;
285 msg->reserved = NAMESERVER_MSG_TOKEN;
287 /* send response message to remote processor */
288 status = MessageQCopy_send(procId, MultiProc_self(),
289 MESSAGEQ_RPMSG_PORT, RPMSG_RESERVED_ADDRESSES, msg,
290 sizeof(NameServerMsg), TRUE);
291 if (status < 0) {
292 LOG0("NameServer: MessageQCopy_send failed\n")
293 }
294 }
295 else {
296 LOG2("NameServer Reply: instanceName: %s, name: %s",
297 (String)msg->instanceName, (String)msg->name)
298 LOG1(", value: 0x%x\n", msg->value)
300 /* Save the response message. */
301 memcpy(&NameServer_module->nsMsg, msg, sizeof(NameServerMsg));
303 /* Post the eventfd upon which NameServer_get() is waiting */
304 numBytes = write(waitFd, &buf, sizeof(buf));
305 }
306 }
308 static Void _listener_cb(MessageQCopy_Handle handle, void * data, int len,
309 void * priv, UInt32 src, UInt16 srcProc)
310 {
311 NameServerMsg msg;
313 LOG0("listener_cb: Entered Listener thread.\n")
315 LOG1("NameServer: Listener got NameServer message "
316 "from MessageQCopy: 0x%p!\n", handle);
317 /* Get NameServer message and process: */
318 memcpy(&msg, data, len);
320 if (len != sizeof(NameServerMsg)) {
321 LOG1("NameServer: got bad NameServerMsg len (%d)\n",
322 len)
323 }
324 else {
325 LOG1("listener_cb: read from MessageQCopy 0x%p\n", handle)
326 LOG2("\tReceived ns msg: byte count: %d, from addr: %d, ",
327 len, src)
328 LOG1("from vproc: %d\n", srcProc)
329 NameServerRemote_processMessage(&msg, srcProc);
330 }
331 }
333 /* =============================================================================
334 * APIS
335 * =============================================================================
336 */
338 /* Function to setup the nameserver module. */
339 Int NameServer_setup(Void)
340 {
341 Int status = NameServer_S_SUCCESS;
342 UInt16 numProcs;
343 int fd[2];
345 pthread_mutex_lock(&NameServer_module->modGate);
347 LOG1("NameServer_setup: entered, refCount=%d\n", NameServer_module->refCount)
349 NameServer_module->refCount++;
351 if (NameServer_module->refCount > 1) {
352 LOG0("NameServer_setup: already setup\n")
353 status = NameServer_S_ALREADYSETUP;
354 goto exit;
355 }
357 numProcs = MultiProc_getNumProcessors();
359 if (pipe(fd) == -1) {
360 status = NameServer_E_FAIL;
361 LOG0("NameServer_setup: failed to create waitFd.\n")
362 goto exit;
363 }
364 NameServer_module->waitFdW = fd[1];
365 NameServer_module->waitFdR = fd[0];
367 /* Create the MessageQCopy for receiving messages from all remote proc */
368 NameServer_module->mq = MessageQCopy_create(NAME_SERVER_RPMSG_ADDR,
369 NULL, _listener_cb, NULL, &NameServer_module->recvAddr);
371 if (NameServer_module->mq == NULL) {
372 status = NameServer_E_FAIL;
373 LOG0("NameServer_setup: failed to create MessageQCopy instance.\n")
374 goto exit;
375 }
377 /* Construct the list object */
378 CIRCLEQ_INIT(&NameServer_module->objList);
380 exit:
381 LOG1("NameServer_setup: exiting, refCount=%d\n", \
382 NameServer_module->refCount)
384 pthread_mutex_unlock(&NameServer_module->modGate);
386 return (status);
387 }
389 /*! Function to destroy the nameserver module. */
390 Int NameServer_destroy(void)
391 {
392 Int status = NameServer_S_SUCCESS;
394 pthread_mutex_lock(&NameServer_module->modGate);
396 LOG1("NameServer_destroy: entered, refCount=%d\n", NameServer_module->refCount)
398 NameServer_module->refCount--;
400 if (NameServer_module->refCount > 0) {
401 LOG1("NameServer_destroy(): refCount(%d) > 0, exiting\n", NameServer_module->refCount)
402 status = NameServer_S_SUCCESS;
404 goto exit;
405 }
407 /* Delete the MessageQCopy instances */
408 if (NameServer_module->mq != NULL) {
409 MessageQCopy_delete(&NameServer_module->mq);
410 }
412 CIRCLEQ_destruct(&NameServer_module->objList);
414 close(NameServer_module->waitFdW);
415 close(NameServer_module->waitFdR);
417 exit:
418 LOG1("NameServer_destroy: exiting, refCount=%d\n", NameServer_module->refCount)
420 pthread_mutex_unlock(&NameServer_module->modGate);
422 return (status);
423 }
425 /* Function to retrieve a NameServer handle from name. */
426 NameServer_Handle NameServer_getHandle(String name)
427 {
428 NameServer_Handle handle = NULL;
429 Bool found = FALSE;
430 struct NameServer_Object * elem;
432 assert(name != NULL);
433 assert(NameServer_module->refCount != 0);
435 pthread_mutex_lock(&NameServer_module->modGate);
437 /* Lookup handle from name: */
438 CIRCLEQ_traverse(elem, &NameServer_module->objList, NameServer_Object) {
439 handle = (NameServer_Handle) elem;
440 if (strcmp(handle->name, name) == 0) {
441 found = TRUE;
442 break;
443 }
444 }
446 if (found == FALSE) {
447 handle = NULL;
448 }
450 pthread_mutex_unlock(&NameServer_module->modGate);
452 return (handle);
453 }
456 /* Function to create a name server. */
457 NameServer_Handle NameServer_create(String name,
458 const NameServer_Params * params)
459 {
460 NameServer_Handle handle = NULL;
461 pthread_mutexattr_t mutex_attr;
463 assert(params != NULL);
464 assert(name != NULL);
465 assert(NameServer_module->refCount != 0);
467 LOG1("NameServer_create(): '%s'\n", name)
469 pthread_mutex_lock(&NameServer_module->modGate);
471 /* check if the name is already created or not */
472 handle = NameServer_getHandle(name);
473 if (handle != NULL) {
474 if (memcmp((Ptr)&handle->params, (Ptr)params,
475 sizeof(NameServer_Params)) == 0) {
476 handle->refCount++;
477 }
478 else {
479 LOG0("NameServer_create: NameServer params mismatch\n")
480 handle = NULL;
481 }
482 goto leave;
483 }
484 else {
485 handle = (NameServer_Handle)calloc(1, sizeof(NameServer_Object));
486 }
488 if (!handle) {
489 LOG0("NameServer_create: NameServer_Handle alloc failed\n")
490 goto leave;
491 }
493 handle->refCount = 1;
494 handle->name = (String)malloc(strlen(name) + 1u);
495 if (!handle->name) {
496 LOG0("NameServer_create: instance name alloc failed\n")
497 goto cleanup;
498 }
499 strncpy(handle->name, name, strlen (name) + 1u);
500 memcpy((Ptr) &handle->params, (Ptr) params, sizeof(NameServer_Params));
502 assert(params.maxValueLen <= MAXVALUELEN);
504 if (params->maxValueLen < sizeof(UInt32)) {
505 handle->params.maxValueLen = sizeof(UInt32);
506 }
507 else {
508 handle->params.maxValueLen = params->maxValueLen;
509 }
511 CIRCLEQ_INIT(&handle->nameList);
512 handle->count = 0u;
514 /* Put in the local list */
515 CIRCLEQ_elemClear(&handle->elem);
516 CIRCLEQ_INSERT_HEAD(&NameServer_module->objList, handle, elem);
518 /*
519 * NameServer_removeEntry() enters gate and is called by
520 * NameServer_remove() while holding the gate.
521 */
522 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
523 pthread_mutex_init(&handle->gate, &mutex_attr);
525 goto leave;
527 cleanup:
528 free(handle);
529 handle = NULL;
531 leave:
532 pthread_mutex_unlock(&NameServer_module->modGate);
534 return (handle);
535 }
538 /* Function to delete a name server. */
539 Int NameServer_delete(NameServer_Handle * handle)
540 {
541 Int status = NameServer_S_SUCCESS;
543 assert(handle != NULL);
544 assert(*handle != NULL);
545 assert((*handle)->count == 0);
546 assert(NameServer_module->refCount != 0);
548 pthread_mutex_lock(&NameServer_module->modGate);
550 (*handle)->refCount--;
551 if ((*handle)->refCount != 0) {
552 goto leave;
553 }
555 if ((*handle)->count == 0) {
556 CIRCLEQ_REMOVE(&NameServer_module->objList, *handle, elem);
558 if ((*handle)->name != NULL) {
559 free((*handle)->name);
560 (*handle)->name = NULL;
561 }
563 CIRCLEQ_destruct(&(*handle)->nameList);
565 free((*handle));
566 (*handle) = NULL;
567 }
569 leave:
570 pthread_mutex_unlock(&NameServer_module->modGate);
572 return (status);
573 }
575 /* Adds a variable length value into the local NameServer table */
576 Ptr NameServer_add(NameServer_Handle handle, String name, Ptr buf, UInt len)
577 {
578 Int status = NameServer_S_SUCCESS;
579 NameServer_TableEntry * node = NULL;
580 NameServer_TableEntry * new_node = NULL;
581 Bool found = FALSE;
582 UInt32 hash;
584 assert(handle != NULL);
585 assert(name != NULL);
586 assert(buf != NULL);
587 assert(len != 0);
588 assert(NameServer_module->refCount != 0);
590 /* Calculate the hash */
591 hash = stringHash(name);
593 if (len > handle->params.maxValueLen) {
594 status = NameServer_E_INVALIDARG;
595 LOG0("NameServer_add: value length exceeded maximum!\n")
596 new_node = NULL;
597 goto exit;
598 }
600 pthread_mutex_lock(&handle->gate);
602 /* Traverse the list to find duplicate check */
603 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
604 /* Hash matches */
605 if (node->hash == hash) {
606 /* If the name matches, incase hash is duplicate */
607 if (strcmp(node->name, name) == 0) {
608 if (handle->params.checkExisting == TRUE) {
609 status = NameServer_E_INVALIDARG;
610 LOG1("NameServer_add: '%s' - duplicate entry found!\n", name)
611 break;
612 }
613 }
614 else {
615 found = TRUE;
616 break;
617 } /* name does not match */
618 } /* hash does not match */
619 } /* CIRCLEQ_traverse */
621 if (status != NameServer_S_SUCCESS) {
622 new_node = NULL;
623 goto exit;
624 }
626 /* Now add the new entry. */
627 new_node = (NameServer_TableEntry *)malloc(sizeof(NameServer_TableEntry));
628 if (new_node == NULL) {
629 status = NameServer_E_MEMORY;
630 LOG1("NameServer_add: %d - malloc new_node failed!\n", status)
632 goto exit;
633 }
635 new_node->hash = hash;
636 new_node->collide = found; /* Indicate if there is a collision*/
637 new_node->len = len;
638 new_node->next = NULL;
639 new_node->name = (String)malloc(strlen(name) + 1u);
640 new_node->value = (Ptr)malloc(len);
641 strncpy(new_node->name, name, strlen(name) + 1u);
642 memcpy((Ptr)new_node->value, (Ptr)buf, len);
644 if (found == TRUE) {
645 /* If hash is found, need to stitch the list to link the
646 * new node to the existing node with the same hash.
647 */
648 new_node->next = node->next;
649 node->next = new_node;
650 }
651 else {
652 /* put the new node into the list */
653 CIRCLEQ_INSERT_HEAD(&handle->nameList, new_node, elem);
654 }
656 handle->count++;
658 LOG2("NameServer_add: Entered key: '%s', data: 0x%x\n",
659 name, *(UInt32 *)buf)
661 exit:
662 pthread_mutex_unlock(&handle->gate);
664 return (new_node);
665 }
668 /* Function to add a UInt32 value into a name server. */
669 Ptr NameServer_addUInt32(NameServer_Handle handle, String name, UInt32 value)
670 {
671 Ptr entry = NULL;
673 assert(handle != NULL);
674 assert(name != NULL);
675 assert(NameServer_module->refCount != 0);
677 entry = NameServer_add(handle, name, &value, sizeof(UInt32));
679 return (entry);
680 }
682 /* Function to remove a name/value pair from a name server. */
683 Int NameServer_remove(NameServer_Handle handle, String name)
684 {
685 Int status = NameServer_S_SUCCESS;
686 NameServer_TableEntry *prev = NULL;
687 NameServer_TableEntry *temp = NULL;
688 NameServer_TableEntry *node = NULL;
689 Bool done = FALSE;
690 UInt32 hash;
692 assert(handle != NULL);
693 assert(name != NULL);
694 assert(NameServer_module->refCount != 0);
696 /* Calculate the hash */
697 hash = stringHash(name);
699 pthread_mutex_lock(&handle->gate);
701 /* Traverse the list to find duplicate check */
702 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
703 /* Hash matchs */
704 if (node->hash == hash) {
705 if (node->collide == TRUE) {
706 if (strcmp(node->name, name) == 0){
707 free(node->value);
708 free(node->name);
709 memcpy((Ptr)node, (Ptr) node->next,
710 sizeof(NameServer_TableEntry));
711 node->next = node->next->next;
712 free(node->next);
713 handle->count--;
714 done = TRUE;
715 break;
716 }
717 else {
718 prev = node;
719 temp = node->next;
720 while (temp) {
721 if (strcmp(temp->name, name) == 0){
722 free(temp->value);
723 free(temp->name);
724 prev->next = temp->next;
725 free(temp);
726 handle->count--;
727 done = TRUE;
728 break;
729 }
730 temp = temp->next;
731 }
732 break;
733 }
734 }
735 else {
736 NameServer_removeEntry(handle, (Ptr)node);
738 done = TRUE;
739 break;
740 }
741 }
742 }
744 if (done == FALSE) {
745 status = NameServer_E_INVALIDARG;
746 LOG1("NameServer_remove %d Entry not found!\n", status)
747 }
749 pthread_mutex_unlock(&handle->gate);
751 return (status);
752 }
754 /* Function to remove a name/value pair from a name server. */
755 Int NameServer_removeEntry(NameServer_Handle handle, Ptr entry)
756 {
757 Int status = NameServer_S_SUCCESS;
758 NameServer_TableEntry * node;
760 assert(handle != NULL);
761 assert(entry != NULL);
762 assert(NameServer_module->refCount != 0);
764 pthread_mutex_lock(&handle->gate);
766 node = (NameServer_TableEntry *)entry;
768 free(node->value);
769 free(node->name);
770 CIRCLEQ_REMOVE(&handle->nameList, node, elem);
771 free(node);
772 handle->count--;
774 pthread_mutex_unlock(&handle->gate);
776 return (status);
777 }
780 /* Initialize this config-params structure with supplier-specified
781 * defaults before instance creation.
782 */
783 Void NameServer_Params_init(NameServer_Params * params)
784 {
785 assert(params != NULL);
787 memcpy(params, &(NameServer_module->defInstParams),
788 sizeof (NameServer_Params));
789 }
792 Int NameServer_getRemote(NameServer_Handle handle,
793 String name,
794 Ptr value,
795 UInt32 * len,
796 UInt16 procId)
797 {
798 Int status = NameServer_S_SUCCESS;
799 Int mqcStatus = -1;
800 struct NameServer_Object *obj = (struct NameServer_Object *)(handle);
801 NameServerMsg nsMsg;
802 NameServerMsg *replyMsg;
803 fd_set rfds;
804 int ret = 0, maxfd, waitFd;
805 struct timeval tv;
806 char buf = '1';
807 int numBytes;
809 pthread_mutex_lock(&NameServer_module->modGate);
811 /* Set Timeout to wait: */
812 tv.tv_sec = 0;
813 tv.tv_usec = NAMESERVER_GET_TIMEOUT;
815 /* Create request message and send to remote processor: */
816 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
817 nsMsg.request = NAMESERVER_REQUEST;
818 nsMsg.requestStatus = 0;
819 nsMsg.valueLen = *len;
821 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
822 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
824 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
825 procId, (String)nsMsg.instanceName)
826 LOG1("%s...\n", (String)nsMsg.name)
827 /* send message */
828 mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
829 RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
830 TRUE);
831 if (mqcStatus < 0) {
832 LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
833 status = NameServer_E_NOTFOUND;
834 goto exit;
835 }
837 /* Block on waitFd for signal from listener thread: */
838 waitFd = NameServer_module->waitFdR;
839 FD_ZERO(&rfds);
840 FD_SET(waitFd, &rfds);
841 maxfd = waitFd + 1;
842 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
843 ret = select(maxfd, &rfds, NULL, NULL, &tv);
844 if (ret == -1) {
845 LOG0("NameServer_getRemote: select failed.")
846 status = NameServer_E_FAIL;
847 goto exit;
848 }
849 else if (!ret) {
850 LOG0("NameServer_getRemote: select timed out.\n")
851 status = NameServer_E_TIMEOUT;
852 goto exit;
853 }
855 if (FD_ISSET(waitFd, &rfds)) {
856 /* Read, just to balance the write: */
857 numBytes = read(waitFd, &buf, sizeof(buf));
859 /* Process response: */
860 replyMsg = &NameServer_module->nsMsg;
862 if (replyMsg->requestStatus) {
863 /* name is found */
865 /* set length to amount of data that was copied */
866 *len = replyMsg->valueLen;
868 /* set the contents of value */
869 if (*len <= sizeof (Bits32)) {
870 *(UInt32 *)value = (UInt32)replyMsg->value;
871 LOG2("NameServer_getRemote: Reply from: %d, %s:",
872 procId, (String)replyMsg->instanceName)
873 LOG2("%s, value: 0x%x...\n",
874 (String)replyMsg->name, *(UInt32 *)value)
875 }
876 else {
877 memcpy(value, replyMsg->valueBuf, *len);
878 LOG2("NameServer_getRemote: Reply from: %d, %s:",
879 procId, (String)replyMsg->instanceName)
880 LOG2("%s, value buffer at address: 0x%p...\n",
881 (String)replyMsg->name, value)
882 }
884 goto exit;
885 }
886 else {
887 /* name is not found */
888 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
889 (String)replyMsg->instanceName, (String)replyMsg->name)
891 /* set status to not found */
892 status = NameServer_E_NOTFOUND;
893 }
894 }
896 exit:
897 pthread_mutex_unlock(&NameServer_module->modGate);
899 return (status);
900 }
902 /* Function to retrieve the value portion of a name/value pair from
903 * local table.
904 */
905 Int NameServer_get(NameServer_Handle handle,
906 String name,
907 Ptr value,
908 UInt32 * len,
909 UInt16 procId[])
910 {
911 Int status = NameServer_S_SUCCESS;
912 UInt16 numProcs = MultiProc_getNumProcessors();
913 UInt32 i;
915 if (procId == NULL) {
916 status = NameServer_getLocal(handle, name, value, len);
917 if (status == NameServer_E_NOTFOUND) {
918 for (i = 0; i < numProcs; i++) {
919 /* getLocal call already covers "self", keep going */
920 if (i == MultiProc_self()) {
921 continue;
922 }
924 status = NameServer_getRemote(handle, name, value, len, i);
926 if ((status >= 0) ||
927 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
928 (status != NameServer_E_TIMEOUT))) {
929 break;
930 }
931 }
932 }
933 }
934 else {
935 /*
936 * Search the query list. It might contain the local proc
937 * somewhere in the list.
938 */
939 i = 0;
940 while (procId[i] != MultiProc_INVALIDID) {
941 if (procId[i] == MultiProc_self()) {
942 status = NameServer_getLocal(handle, name, value, len);
943 }
944 else {
945 status = NameServer_getRemote(handle, name, value, len, i);
946 }
948 if ((status >= 0) ||
949 ((status < 0) && (status != NameServer_E_NOTFOUND))) {
950 break;
951 }
953 i++;
954 }
955 }
957 return (status);
958 }
960 /* Gets a 32-bit value by name */
961 Int NameServer_getUInt32(NameServer_Handle handle,
962 String name,
963 Ptr value,
964 UInt16 procId[])
965 {
966 Int status;
967 UInt32 len = sizeof(UInt32);
969 assert(handle != NULL);
970 assert(name != NULL);
971 assert(value != NULL);
972 assert(NameServer_module->refCount != 0);
974 status = NameServer_get(handle, name, value, &len, procId);
976 return (status);
977 }
979 /* Function to Retrieve the value portion of a name/value pair from
980 * local table.
981 */
982 Int NameServer_getLocal(NameServer_Handle handle,
983 String name,
984 Ptr value,
985 UInt32 * len)
986 {
987 Int status = NameServer_E_NOTFOUND;
988 NameServer_TableEntry * node = NULL;
989 NameServer_TableEntry * temp = NULL;
990 Bool done = FALSE;
991 UInt32 length;
992 UInt32 hash;
994 assert(handle != NULL);
995 assert(name != NULL);
996 assert(value != NULL);
997 assert(len != NULL);
998 assert(NameServer_module->refCount != 0);
1000 length = *len;
1002 /* Calculate the hash */
1003 hash = stringHash(name);
1005 pthread_mutex_lock(&handle->gate);
1007 /* Traverse the list to find duplicate check */
1008 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1009 if (node->hash == hash) {
1010 if (node->collide == TRUE) {
1011 temp = node;
1012 while (temp) {
1013 if (strcmp(temp->name, name) == 0u){
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 temp = temp->next;
1026 }
1027 break;
1028 }
1029 else {
1030 if (length <= node->len) {
1031 memcpy(value, node->value, length);
1032 *len = length;
1033 }
1034 else {
1035 memcpy(value, node->value, node->len);
1036 *len = node->len;
1037 }
1038 done = TRUE;
1039 break;
1040 }
1041 }
1042 }
1044 pthread_mutex_unlock(&handle->gate);
1046 if (done == FALSE) {
1047 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1048 }
1049 else {
1050 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1051 node->name, (UInt32)node->value)
1052 status = NameServer_S_SUCCESS;
1053 }
1055 return (status);
1056 }
1058 /*
1059 * Gets a 32-bit value by name from the local table
1060 *
1061 * If the name is found, the 32-bit value is copied into the value
1062 * argument and a success status is returned.
1063 *
1064 * If the name is not found, zero is returned in len and the contents
1065 * of value are not modified. Not finding a name is not considered
1066 * an error.
1067 *
1068 * This function only searches the local name/value table.
1069 *
1070 */
1071 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1072 {
1073 Int status;
1074 UInt32 len = sizeof(UInt32);
1076 assert(handle != NULL);
1077 assert(name != NULL);
1078 assert(value != NULL);
1079 assert(NameServer_module->refCount != 0);
1081 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1082 status = NameServer_getLocal(handle, name, value, &len);
1084 return (status);
1085 }
1088 #if defined (__cplusplus)
1089 }
1090 #endif /* defined (__cplusplus) */