1 /*
2 * Copyright (c) 2012-2014, 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;
808 static int seqNum = 0;
809 Bool done = FALSE;
811 pthread_mutex_lock(&NameServer_module->modGate);
813 /* Set Timeout to wait: */
814 tv.tv_sec = 0;
815 tv.tv_usec = NAMESERVER_GET_TIMEOUT;
817 /* Create request message and send to remote processor: */
818 nsMsg.reserved = NAMESERVER_MSG_TOKEN;
819 nsMsg.request = NAMESERVER_REQUEST;
820 nsMsg.requestStatus = 0;
821 nsMsg.valueLen = *len;
822 nsMsg.seqNum = seqNum++;
824 strncpy((char *)nsMsg.instanceName, obj->name, strlen(obj->name) + 1);
825 strncpy((char *)nsMsg.name, name, strlen(name) + 1);
827 LOG2("NameServer_getRemote: Requesting from procId %d, %s:",
828 procId, (String)nsMsg.instanceName)
829 LOG1("%s...\n", (String)nsMsg.name)
831 /* send message */
832 mqcStatus = MessageQCopy_send(procId, MultiProc_self(), MESSAGEQ_RPMSG_PORT,
833 RPMSG_RESERVED_ADDRESSES, &nsMsg, sizeof(NameServerMsg),
834 TRUE);
835 if (mqcStatus < 0) {
836 LOG0("NameServer_getRemote: Can't send to remote endpoint\n")
837 status = NameServer_E_NOTFOUND;
838 goto exit;
839 }
841 while (!done) {
842 /* Block on waitFd for signal from listener thread: */
843 waitFd = NameServer_module->waitFdR;
844 FD_ZERO(&rfds);
845 FD_SET(waitFd, &rfds);
846 maxfd = waitFd + 1;
847 LOG1("NameServer_getRemote: pending on waitFd: %d\n", waitFd)
848 ret = select(maxfd, &rfds, NULL, NULL, &tv);
849 if (ret == -1) {
850 LOG0("NameServer_getRemote: select failed.")
851 status = NameServer_E_FAIL;
852 goto exit;
853 }
854 else if (!ret) {
855 LOG0("NameServer_getRemote: select timed out.\n")
856 status = NameServer_E_TIMEOUT;
857 goto exit;
858 }
860 if (FD_ISSET(waitFd, &rfds)) {
861 /* Read, just to balance the write: */
862 numBytes = read(waitFd, &buf, sizeof(buf));
864 /* Process response: */
865 replyMsg = &NameServer_module->nsMsg;
867 if (replyMsg->seqNum != seqNum - 1) {
868 /* Ignore responses without current sequence # */
869 continue;
870 }
872 if (replyMsg->requestStatus) {
873 /* name is found */
875 /* set length to amount of data that was copied */
876 *len = replyMsg->valueLen;
878 /* set the contents of value */
879 if (*len <= sizeof (Bits32)) {
880 *(UInt32 *)value = (UInt32)replyMsg->value;
881 LOG2("NameServer_getRemote: Reply from: %d, %s:",
882 procId, (String)replyMsg->instanceName)
883 LOG2("%s, value: 0x%x...\n",
884 (String)replyMsg->name, *(UInt32 *)value)
885 }
886 else {
887 memcpy(value, replyMsg->valueBuf, *len);
888 LOG2("NameServer_getRemote: Reply from: %d, %s:",
889 procId, (String)replyMsg->instanceName)
890 LOG2("%s, value buffer at address: 0x%p...\n",
891 (String)replyMsg->name, value)
892 }
894 goto exit;
895 }
896 else {
897 /* name is not found */
898 LOG2("NameServer_getRemote: value for %s:%s not found.\n",
899 (String)replyMsg->instanceName, (String)replyMsg->name)
901 /* set status to not found */
902 status = NameServer_E_NOTFOUND;
903 }
904 }
905 done = TRUE;
906 }
907 exit:
908 pthread_mutex_unlock(&NameServer_module->modGate);
910 return (status);
911 }
913 /* Function to retrieve the value portion of a name/value pair from
914 * local table.
915 */
916 Int NameServer_get(NameServer_Handle handle,
917 String name,
918 Ptr value,
919 UInt32 * len,
920 UInt16 procId[])
921 {
922 Int status = NameServer_S_SUCCESS;
923 UInt16 numProcs = MultiProc_getNumProcessors();
924 UInt32 i;
926 if (procId == NULL) {
927 status = NameServer_getLocal(handle, name, value, len);
928 if (status == NameServer_E_NOTFOUND) {
929 for (i = 0; i < numProcs; i++) {
930 /* getLocal call already covers "self", keep going */
931 if (i == MultiProc_self()) {
932 continue;
933 }
935 status = NameServer_getRemote(handle, name, value, len, i);
937 if ((status >= 0) ||
938 ((status < 0) && (status != NameServer_E_NOTFOUND) &&
939 (status != NameServer_E_TIMEOUT))) {
940 break;
941 }
942 }
943 }
944 }
945 else {
946 /*
947 * Search the query list. It might contain the local proc
948 * somewhere in the list.
949 */
950 i = 0;
951 while (procId[i] != MultiProc_INVALIDID) {
952 if (procId[i] == MultiProc_self()) {
953 status = NameServer_getLocal(handle, name, value, len);
954 }
955 else {
956 status = NameServer_getRemote(handle, name, value, len, i);
957 }
959 if ((status >= 0) ||
960 ((status < 0) && (status != NameServer_E_NOTFOUND)
961 && (status != NameServer_E_TIMEOUT))) {
962 break;
963 }
965 i++;
966 }
967 }
969 return (status);
970 }
972 /* Gets a 32-bit value by name */
973 Int NameServer_getUInt32(NameServer_Handle handle,
974 String name,
975 Ptr value,
976 UInt16 procId[])
977 {
978 Int status;
979 UInt32 len = sizeof(UInt32);
981 assert(handle != NULL);
982 assert(name != NULL);
983 assert(value != NULL);
984 assert(NameServer_module->refCount != 0);
986 status = NameServer_get(handle, name, value, &len, procId);
988 return (status);
989 }
991 /* Function to Retrieve the value portion of a name/value pair from
992 * local table.
993 */
994 Int NameServer_getLocal(NameServer_Handle handle,
995 String name,
996 Ptr value,
997 UInt32 * len)
998 {
999 Int status = NameServer_E_NOTFOUND;
1000 NameServer_TableEntry * node = NULL;
1001 NameServer_TableEntry * temp = NULL;
1002 Bool done = FALSE;
1003 UInt32 length;
1004 UInt32 hash;
1006 assert(handle != NULL);
1007 assert(name != NULL);
1008 assert(value != NULL);
1009 assert(len != NULL);
1010 assert(NameServer_module->refCount != 0);
1012 length = *len;
1014 /* Calculate the hash */
1015 hash = stringHash(name);
1017 pthread_mutex_lock(&handle->gate);
1019 /* Traverse the list to find duplicate check */
1020 CIRCLEQ_traverse(node, &handle->nameList, NameServer_TableEntry_tag) {
1021 if (node->hash == hash) {
1022 if (node->collide == TRUE) {
1023 temp = node;
1024 while (temp) {
1025 if (strcmp(temp->name, name) == 0u){
1026 if (length <= node->len) {
1027 memcpy(value, node->value, length);
1028 *len = length;
1029 }
1030 else {
1031 memcpy(value, node->value, node->len);
1032 *len = node->len;
1033 }
1034 done = TRUE;
1035 break;
1036 }
1037 temp = temp->next;
1038 }
1039 break;
1040 }
1041 else {
1042 if (length <= node->len) {
1043 memcpy(value, node->value, length);
1044 *len = length;
1045 }
1046 else {
1047 memcpy(value, node->value, node->len);
1048 *len = node->len;
1049 }
1050 done = TRUE;
1051 break;
1052 }
1053 }
1054 }
1056 pthread_mutex_unlock(&handle->gate);
1058 if (done == FALSE) {
1059 LOG1("NameServer_getLocal: entry key: '%s' not found!\n", name)
1060 }
1061 else {
1062 LOG2("NameServer_getLocal: Found entry key: '%s', data: 0x%x\n",
1063 node->name, (UInt32)node->value)
1064 status = NameServer_S_SUCCESS;
1065 }
1067 return (status);
1068 }
1070 /*
1071 * Gets a 32-bit value by name from the local table
1072 *
1073 * If the name is found, the 32-bit value is copied into the value
1074 * argument and a success status is returned.
1075 *
1076 * If the name is not found, zero is returned in len and the contents
1077 * of value are not modified. Not finding a name is not considered
1078 * an error.
1079 *
1080 * This function only searches the local name/value table.
1081 *
1082 */
1083 Int NameServer_getLocalUInt32(NameServer_Handle handle, String name, Ptr value)
1084 {
1085 Int status;
1086 UInt32 len = sizeof(UInt32);
1088 assert(handle != NULL);
1089 assert(name != NULL);
1090 assert(value != NULL);
1091 assert(NameServer_module->refCount != 0);
1093 LOG0("NameServer_getLocalUInt32: calling NameServer_getLocal()...\n")
1094 status = NameServer_getLocal(handle, name, value, &len);
1096 return (status);
1097 }
1100 #if defined (__cplusplus)
1101 }
1102 #endif /* defined (__cplusplus) */