1 /*
2 * Copyright (c) 2013-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 /*
34 * ======== rms.c ========
35 */
37 /* This define must precede inclusion of any xdc header files */
38 #define Registry_CURDESC ti_sdo_ce_rms_desc
40 #include <xdc/std.h>
41 #include <xdc/runtime/Assert.h>
42 #include <xdc/runtime/Diags.h>
43 #include <xdc/runtime/Log.h>
44 #include <xdc/runtime/Registry.h>
46 #include <xdc/runtime/knl/Thread.h>
48 #include <string.h>
49 #include <assert.h>
50 #include <stdio.h>
51 #include <ctype.h>
53 #include <ti/sdo/ce/global/CESettings.h>
54 #include <ti/sdo/ce/osal/Global.h>
55 #include <ti/sdo/ce/osal/Memory.h>
56 #include <ti/sdo/ce/osal/Trace.h>
57 #include <ti/sdo/ce/ipc/Comm.h>
58 #include <ti/sdo/ce/ipc/Processor.h>
60 #include <ti/sdo/ce/rms.h>
61 #include <ti/sdo/ce/alg/Algorithm.h>
62 #include <ti/sdo/ce/node/node.h>
63 #include <ti/sdo/ce/node/_node.h> /* RMS is a "friend" of NODE */
64 #include <ti/sdo/ce/Server.h>
65 #include <ti/sdo/ce/_Server.h>
66 #include <ti/sdo/ce/skel.h>
68 #include <ti/xdais/ialg.h>
71 #define MAXNUMLEN 8
72 #define MAXNUMSEGS 1024 /* Maximum number of heaps checked for */
74 /*
75 * Heap must be large enough to hold HeapMem_Header. Don't allow heaps to
76 * be re-defined to a size of 0 to avoid extra maintenance. Will check that
77 * the size is at least MINHEAPSIZE.
78 */
79 #define MINHEAPSIZE 16
81 #define MODNAME "ti.sdo.ce.rms"
83 /*
84 * Maximum length of codec name (Should be the same as in visa.c)
85 */
86 #define MAXNAMELEN 127 /* Maximum length of codec name */
88 #define HEADERSIZE ( \
89 (Char *)&(((RMS_RmsMsg *)0)->cmdBuf) - (Char *)0 \
90 )
92 /* this function is for internal use only */
93 #define RMS_checkUuid(uuid1, uuid2) \
94 ( ((uuid1).data) == ((uuid2).data) )
96 /* internal description of a created node instance */
97 typedef struct RMS_Obj {
98 NODE_Handle node; /* NULL means free */
99 NODE_Desc *nodeDesc; /* ptr to entry in node database */
100 Comm_Handle nodeQueue; /* node's input message queue */
101 Comm_Id gppQueue; /* gpp's (client's) message queue */
102 Int instanceId; /* unique instance ID */
103 String name; /* node's instance name */
104 } RMS_Obj;
107 static Int initCount = 0;
109 static Comm_Handle rmsMsgQueue = Comm_INVALIDHANDLE;
110 static RMS_RmsMsg *rmsMsg = NULL;
111 static Thread_Handle rmsTsk = NULL;
112 static Bool traceTokenAvailable = TRUE;
114 /* default RMS configuration data set */
115 RMS_Config RMS_CONFIG = RMS_CONFIGDEFAULT;
117 Void RMS_run(IArg arg); /* RMS task entry function prototype */
119 static Void RMS_exec(Void);
121 static RMS_Status addAlg(RMS_CmdSetAddAlgIn *cmdIn,
122 RMS_CmdSetAddAlgOut *cmdOut);
123 static Char *formatNum(Char *ptr, UInt32 un);
124 static Void freeInst(RMS_Obj *inst);
125 static RMS_Status getAlg(RMS_CmdSetGetAlgIn *cmdIn,
126 RMS_CmdSetGetAlgOut *cmdOut);
127 static RMS_Status getMemRecs(RMS_CmdSetGetMemRecsIn *cmdIn,
128 RMS_CmdSetGetMemRecsOut *cmdOut);
129 static RMS_Status getNumAlgs(RMS_CmdSetGetNumAlgsOut *cmdOut);
130 static RMS_Status getNumRecs(RMS_CmdSetGetNumRecsIn *cmdIn,
131 RMS_CmdSetGetNumRecsOut *cmdOut);
132 static RMS_Status getSegStat(Int segId, RMS_CmdSetGetSegStatOut *out);
133 static RMS_Obj *mkInst(String nodeName, Int id);
135 static RMS_Status processRmsCmd(RMS_CmdBuf *cmdBuf, Int size);
136 static RMS_Status redefineHeap(String name, Int segId, Uint32 base,
137 Uint32 size);
138 static RMS_Status restoreHeap(String name);
140 extern Void IPC_threadGeneratedInit(Void);
141 extern Void IPC_threadGeneratedReset(Void);
143 Registry_Desc ti_sdo_ce_rms_desc;
145 static Int regInit = 0; /* Registry_addModule() called */
147 static Int detachFlag = 0; /* Set to 1 when we need to detatch */
148 static Int exitFlag = 0; /* Set to 1 when we need the rms thread to exit */
150 /*
151 * ======== RMS_init ========
152 * Calls to RMS_init() must be serialized.
153 */
154 Void RMS_init(Void)
155 {
156 #ifndef xdc_target__os_undefined
157 Thread_Priority threadPri;
158 Int pri;
159 #endif
160 Registry_Result result;
162 /*
163 * No need to reference count for Registry_addModule(), since there
164 * is no way to remove the module.
165 */
166 if (regInit == 0) {
167 /* Register this module for logging */
168 result = Registry_addModule(&ti_sdo_ce_rms_desc, MODNAME);
169 Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
171 if (result == Registry_SUCCESS) {
172 /* Set the diags mask to the CE default */
173 CESettings_init();
174 CESettings_setDiags(MODNAME);
175 }
176 regInit = 1;
177 }
179 if (initCount++ == 0) {
180 Thread_Params rmsTskAttrs;
181 Comm_Attrs commAttrs;
182 static char rmsCommName[32]; /* MessageQ_max length(?) */
184 NODE_init();
185 Comm_init();
188 /* HACK: we set callFxn in advance in case we run with an
189 * OSAL that does not support separate Thread threads
190 */
191 commAttrs = Comm_ATTRS;
192 commAttrs.callFxn = (Comm_CallFxn)RMS_exec;
194 /* create core-specific RMS's MSGQ for msg exchange with clients */
195 sprintf(rmsCommName, RMS_CMDQNAME ":%s",
196 Processor_getCoreName(Processor_myCoreId()));
197 rmsMsgQueue = Comm_create(rmsCommName, &commAttrs);
198 assert(rmsMsgQueue != NULL);
200 /* now, create the RMS task that acts on the server's behalf */
201 Thread_Params_init(&rmsTskAttrs);
202 #ifdef xdc_target__os_undefined
203 rmsTskAttrs.osPriority = RMS_config.tskPriority;
204 #else
205 pri = RMS_config.tskPriority;
206 threadPri = (pri <= RMS_LOWESTPRI) ? Thread_Priority_LOWEST :
207 (pri <= RMS_LOWPRI) ? Thread_Priority_BELOW_NORMAL :
208 (pri <= RMS_NORMALPRI) ? Thread_Priority_NORMAL :
209 (pri <= RMS_HIGHPRI) ? Thread_Priority_ABOVE_NORMAL :
210 Thread_Priority_HIGHEST;
212 rmsTskAttrs.priority = threadPri;
213 #endif
214 rmsTskAttrs.stackSize = RMS_config.tskStacksize;
215 rmsTsk = Thread_create((Thread_RunFxn)RMS_run, &rmsTskAttrs, NULL);
216 assert(rmsTsk != NULL);
217 }
218 Log_print0(Diags_USER5, "[+5] RMS_init> exit");
220 }
222 /*
223 * ======== RMS_exit ========
224 */
225 Void RMS_exit(Void)
226 {
227 Comm_Id rmsMsgQueueId;
228 RMS_RmsMsg msg;
230 if (initCount-- <= 1) {
231 initCount = 0;
233 if ((rmsTsk != NULL) && (rmsMsgQueue != Comm_INVALIDHANDLE)) {
234 rmsMsgQueueId = Comm_getId(rmsMsgQueue);
235 Comm_staticMsgInit((Comm_Msg)&msg, sizeof(RMS_RmsMsg));
236 msg.cmdBuf.cmd = RMS_QUIT;
238 Comm_put(rmsMsgQueueId, (Comm_Msg)&msg);
240 /* Wait for RMS thread to terminate */
241 Thread_join(rmsTsk, NULL);
242 }
244 if (rmsMsgQueue != NULL) {
245 Comm_delete(rmsMsgQueue);
246 rmsMsgQueue = NULL;
247 }
248 rmsMsgQueue = Comm_INVALIDHANDLE;
250 if (rmsTsk != NULL) {
251 Thread_delete(&rmsTsk);
252 rmsTsk = NULL;
253 }
255 traceTokenAvailable = TRUE;
256 }
257 }
260 /*
261 * ======== RMS_run ========
262 */
263 Void RMS_run(IArg arg)
264 {
265 for (;;) {
266 /* Note, we do any deferred thread level init here. */
268 /*
269 * When ipc.bios.Ipc.manageIpc = TRUE, this function calls
270 * Ipc_attach().
271 */
272 IPC_threadGeneratedInit();
274 /* and finally, the RMS_exec() loop can run */
275 for (;;) {
276 RMS_exec();
277 if (detachFlag) {
278 detachFlag = FALSE;
279 break;
280 }
281 if (exitFlag) {
282 /*
283 * CERuntime_exit has been called. We shouldn't get
284 * here unless IPC_threadGeneratedInit and exit are NOPs
285 * (ipc.bios.Ipc.manageIpc == FALSE, ie the app is
286 * responsible for calling Ipc_attach() / Ipc_detatch()).
287 */
288 exitFlag = FALSE;
289 return;
290 }
291 }
293 /*
294 * Calls Ipc_detatch(), Ipc_stop(), and Ipc_start(), when manageIpc
295 * is TRUE.
296 */
297 IPC_threadGeneratedReset();
298 }
299 }
301 /*
302 * ======== RMS_exec ========
303 */
304 static Void RMS_exec(Void)
305 {
306 RMS_CmdBuf *cmdBuf;
307 Int commStatus;
308 Comm_Id sendersMsgQueue;
309 RMS_Status status;
311 /* get something to do */
312 commStatus = Comm_get(rmsMsgQueue, (Comm_Msg *)&rmsMsg, Comm_FOREVER);
314 Log_print1(Diags_USER4, "[+4] RMS_exec> got msg. status = %d",
315 (IArg)commStatus);
317 if (commStatus == Comm_EOK) {
318 Int msgSize = Comm_getMsgSize((Comm_Msg)rmsMsg);
320 /* we assume message recieved is at least as large as we require */
321 assert(msgSize >= sizeof (RMS_RmsMsg));
323 /* do it */
324 cmdBuf = (RMS_CmdBuf *)&(rmsMsg->cmdBuf);
325 status = processRmsCmd(cmdBuf, msgSize - HEADERSIZE);
326 cmdBuf->status = status;
328 if (!exitFlag) {
329 /* find out who the sender was */
330 commStatus = Comm_getSendersId((Comm_Msg)rmsMsg, &sendersMsgQueue);
331 assert(commStatus == Comm_EOK);
333 /* then send the message back */
334 commStatus = Comm_put(sendersMsgQueue, (Comm_Msg)rmsMsg);
335 assert(commStatus == Comm_EOK);
336 }
337 }
338 else {
339 #if 0
340 /* In some cases (like shutdown) this is expected */
341 Log_print1(Diags_USER7, "[+7] RMS_exec> Comm_get failed (0x%x)",
342 (IArg)commStatus);
343 #endif
344 }
345 }
347 /*
348 * ======== addAlg ========
349 */
350 static RMS_Status addAlg(RMS_CmdSetAddAlgIn *cmdIn,
351 RMS_CmdSetAddAlgOut *cmdOut)
352 {
353 Server_AlgDesc algDesc;
354 Server_Status status;
356 /* Set fields to defaults */
357 Server_initAlgDesc(&algDesc);
359 /* Server will make a copy of the name */
360 algDesc.name = (String)cmdIn->name;
362 Log_print1(Diags_USER4, "[+4] RMS addAlg> Name: %s", (IArg)algDesc.name);
364 algDesc.fxns = (IALG_Fxns *)cmdIn->fxns;
365 algDesc.idmaFxns = (Ptr)cmdIn->idmaFxns;
366 algDesc.iresFxns = (Ptr)cmdIn->iresFxns;
367 algDesc.isLocal = TRUE;
368 algDesc.groupId = (Int)cmdIn->groupId;
369 algDesc.memType = (Engine_CachedMemType)cmdIn->memType;
371 algDesc.types = (String)cmdIn->typeTab;
372 algDesc.stubFxnsName = (String)cmdIn->stubFxnsName;
373 algDesc.skelFxns = (SKEL_Fxns *)cmdIn->skelFxns;
375 Log_print1(Diags_USER4, "[+4] RMS addAlg> fxns: 0x%x",
376 (IArg)algDesc.fxns);
377 Log_print1(Diags_USER6, "[+4] RMS addAlg> skel: 0x%x",
378 (IArg)algDesc.skelFxns);
380 Log_print1(Diags_USER4, "[+4] RMS addAlg> idmaFxns: 0x%x",
381 (IArg)algDesc.idmaFxns);
382 Log_print1(Diags_USER4, "[+4] RMS addAlg> iresFxns: 0x%x",
383 (IArg)algDesc.iresFxns);
384 Log_print1(Diags_USER4, "[+4] RMS addAlg> groupId: %d",
385 (IArg)algDesc.groupId);
386 Log_print1(Diags_USER4, "[+4] RMS addAlg> memType: %d",
387 (IArg)algDesc.memType);
389 Log_print1(Diags_USER4, "[+4] RMS addAlg> Types: %s", (IArg)algDesc.types);
390 Log_print1(Diags_USER4, "[+4] RMS addAlg> Stubs: %s",
391 (IArg)algDesc.stubFxnsName);
393 algDesc.priority = (Int)cmdIn->priority;
394 algDesc.stackSize = (UInt32)cmdIn->stackSize;
395 algDesc.stackSeg = (UInt32)cmdIn->stackSeg;
396 algDesc.codecClassConfig = (Void *)cmdIn->codecClassConfig;
398 Log_print1(Diags_USER4, "[+4] RMS addAlg> isLocal: %d",
399 (IArg)algDesc.isLocal);
400 Log_print1(Diags_USER4, "[+4] RMS addAlg> priority: %d",
401 (IArg)algDesc.priority);
402 Log_print1(Diags_USER4, "[+4] RMS addAlg> stackSize: 0x%x",
403 (IArg)algDesc.stackSize);
404 Log_print1(Diags_USER4, "[+4] RMS addAlg> codecClassConfig: 0x%x",
405 (IArg)algDesc.codecClassConfig);
407 status = Server_addAlg(NULL, NULL, &algDesc);
409 if (status != Server_EOK) {
410 Log_print1(Diags_USER7, "App-> ERROR: can't add Alg (0x%x)\n",
411 (IArg)status);
412 /* TODO: Convert Server_Status to RMS error */
413 cmdOut->serverError = (RMS_Word)status;
414 return (RMS_EFAIL);
415 }
417 /* Get the uuid assigned to the node to pass back to the host */
418 status = Server_getNodeUuid(algDesc.name, &(cmdOut->uuid));
420 if (status != Server_EOK) {
421 Log_print1(Diags_USER7, "App-> ERROR: can't find alg uuid (0x%x)\n",
422 (IArg)status);
423 /* TODO: Convert Server_Status to RMS error */
424 cmdOut->serverError = (RMS_Word)status;
426 return (RMS_EFAIL);
427 }
429 cmdOut->serverError = (RMS_Word)status;
430 return (RMS_EOK);
431 }
433 /*
434 * ======== checkStack ========
435 */
436 static Void checkStack(Void)
437 {
438 Bits16 classId = Diags_USER5;
439 Int headroom = 100;
440 Thread_Stat buf;
442 Thread_stat(Thread_self(NULL), &buf, NULL);
444 /* check stack size to see if we are close to overrun */
445 if (buf.stackSize != 0) {
446 headroom = (buf.stackSize > buf.stackUsed)
447 ? ((buf.stackSize - buf.stackUsed) * 100) / buf.stackSize : 0;
448 }
450 if (headroom < 10) {
451 classId |= Diags_USER6; /* less than 10%, generate warning */
452 }
453 Log_print3(classId, "RMS: stack size = %d, stack used = %d(%d%%)",
454 (IArg)(buf.stackSize), (IArg)(buf.stackUsed),
455 (IArg)(100 - headroom));
456 }
458 /*
459 * ======== createNode ========
460 */
461 static RMS_Status createNode(RMS_CmdSetCreateNodeIn *cmdIn,
462 RMS_CmdSetCreateNodeOut *cmdOut)
463 {
464 RMS_Obj *rmsInst;
465 NODE_Desc *nodeDesc = NULL;
466 NODE_Desc desc;
467 NODE_Attrs nodeAttrs;
468 NODE_Handle node;
469 Int numDynNodes;
470 Int i;
471 Int priority;
472 RMS_Status status;
473 Char tmpName[MAXNAMELEN + 1];
474 String createArgBuf;
475 Int createArgLen;
477 /* instance ID -- unique across all instances */
478 static Int instanceId = 0;
480 Log_print2(Diags_USER5, "[+5] RMS createNode> Enter(0x%x, 0x%x)",
481 (IArg)cmdIn, (IArg)cmdOut);
483 /* search the database of nodes for the given uuid */
484 for (nodeDesc = RMS_nodeTab; nodeDesc->name != NULL; nodeDesc++) {
485 if (RMS_checkUuid(cmdIn->uuid, nodeDesc->uuid)) {
486 break; /* found it */
487 }
488 }
489 numDynNodes = Server_getNumNodes();
490 Log_print1(Diags_USER5, "[+5]RMS createNode> Num dynamic nodes: %d",
491 (IArg)numDynNodes);
493 if (nodeDesc->name == NULL) {
494 /* Search in list of dynamically added nodes */
495 numDynNodes = Server_getNumNodes();
497 Log_print1(Diags_USER5, "[+5] RMS createNode> Searching dynamic "
498 "nodes. num nodes = %d",
499 (IArg)numDynNodes);
501 for (i = 0; i < numDynNodes; i++) {
502 nodeDesc = Server_getNode(i);
503 if ((nodeDesc != NULL) &&
504 (RMS_checkUuid(cmdIn->uuid, nodeDesc->uuid))) {
505 break; /* found it */
506 }
507 }
508 }
510 if ((nodeDesc == NULL) || (nodeDesc->name == NULL)) {
511 return (RMS_EINVUUID);
512 }
514 Log_print2(Diags_USER5, "[+5] RMS createNode> Found match: "
515 "name = %s, uuid = 0x%x",
516 (IArg)nodeDesc->name, (IArg)nodeDesc->uuid.data);
519 if (nodeDesc->rpcProtocolVersion != cmdIn->rpcProtocolVersion) {
520 return (RMS_EINVPROT);
521 }
523 /* create an RMS node instance */
524 rmsInst = mkInst(nodeDesc->name, instanceId);
525 if (rmsInst == NULL) {
526 return (RMS_ERESOURCE);
527 }
529 /* point to the args buffer of the in structure */
530 createArgLen = cmdIn->argLength;
531 if (createArgLen > 0) {
532 createArgBuf = (String)(cmdIn->argBuffer);
533 }
534 else {
535 createArgBuf = NULL;
536 }
538 /* Initilize desc with configured values. */
539 desc = *nodeDesc;
540 nodeAttrs = *(nodeDesc->nodeAttrs);
541 desc.nodeAttrs = &nodeAttrs;
543 /*
544 * If create parameters have priority set to -1, use configured priority,
545 * otherwise override the configured priority with the value passed in
546 * the create args.
547 */
548 priority = (Int)(cmdIn->nodePriority);
549 if (priority != -1) {
550 // TODO: (jeh) Thread_MINPRI and Thread_MAXPRI no longer exist.
551 //if ((priority < Thread_MINPRI) || (priority > Thread_MAXPRI)) {
552 // return (RMS_EINVAL);
553 //}
554 nodeAttrs.initPriority = priority;
555 }
557 /*
558 * Create new name combining nodeDesc->name and ::1 if cmdIn->useExtHeap
559 * is TRUE. We need to do this because NODE_create() calls the codec's
560 * create function (which only takes its own attributes arg).
561 */
562 if (cmdIn->useExtHeap) {
563 desc.name = tmpName;
564 strncpy(tmpName, nodeDesc->name, MAXNAMELEN - strlen("::1"));
565 tmpName[MAXNAMELEN - strlen("::1")] = '\0';
567 strcpy(tmpName + strlen(tmpName), "::1");
568 tmpName[MAXNAMELEN] = '\0';
569 }
571 status = NODE_create(
572 &desc, /* in: */
573 createArgLen, /* in: */
574 createArgBuf, /* in: */
575 cmdIn->gppQueue, /* in: sendQueue (to gpp msgq) */
576 rmsInst->name, /* in: node instance name */
577 &node /* out: node handle */
578 );
580 if (status != NODE_EOK) {
581 freeInst(rmsInst);
582 status = (status == NODE_EOUTOFMEMORY) ? RMS_EOUTOFMEMORY :
583 (status == NODE_ETASK) ? RMS_ETASK : RMS_EFAIL;
584 return (status);
585 }
587 /* record the node instance data */
588 rmsInst->node = node;
589 rmsInst->nodeDesc = nodeDesc;
590 rmsInst->nodeQueue = NODE_getRecvQueue(node);
591 rmsInst->gppQueue = cmdIn->gppQueue;
592 rmsInst->instanceId = instanceId;
593 instanceId++;
595 /* prepare command output */
596 cmdOut->node = (RMS_Word)rmsInst;
597 cmdOut->nodeQueue = Comm_getId(rmsInst->nodeQueue);
598 cmdOut->remoteVisa = (RMS_Word)NODE_getEnv(node);
600 return (RMS_EOK);
601 }
603 /*
604 * ======== deleteNode ========
605 */
606 static RMS_Status deleteNode(RMS_CmdSetDeleteNodeIn *cmdIn, RMS_CmdSetDeleteNodeOut *cmdOut)
607 {
608 RMS_Obj *rmsInst = (RMS_Obj *)cmdIn->node;
609 RMS_Status status = RMS_EOK;
610 NODE_Stat buf;
612 Log_print2(Diags_USER5, "[+5] RMS deleteNode> Enter(0x%x, 0x%x)",
613 (IArg)cmdIn, (IArg)cmdOut);
615 /* get current stack info before deleting node */
616 if (NODE_stat(rmsInst->node, &buf) == 0) {
617 cmdOut->stackSize = buf.stackSize;
618 cmdOut->stackUsed = buf.stackUsed;
619 }
620 else {
621 cmdOut->stackSize = 0;
622 cmdOut->stackUsed = 0;
623 }
625 /* delete the node object itself */
626 if (NODE_delete(rmsInst->node) != NODE_EOK) {
627 status = RMS_EFAIL;
628 }
630 freeInst(rmsInst);
632 return (status);
633 }
635 /*
636 * ======== startNode ========
637 */
638 static RMS_Status startNode(RMS_CmdSetExecuteNodeIn *cmdIn)
639 {
640 RMS_Obj *rmsInst = (RMS_Obj *)cmdIn->node;
641 RMS_Status status = RMS_EOK;
643 Log_print1(Diags_USER5, "[+5] RMS startNode> Enter(0x%x)", (IArg)cmdIn);
645 if (NODE_start(rmsInst->node) != NODE_EOK) {
646 status = RMS_EFAIL;
647 }
649 return (status);
650 }
652 /*
653 * ======== formatNum ========
654 */
655 static Char *formatNum(Char *ptr, UInt32 un)
656 {
657 Int i = 0;
658 UInt32 n = un;
659 static const Char digtohex[] = "0123456789abcdef";
661 /* compute digits in number from right to left */
662 do {
663 *(--ptr) = digtohex[n & 0xf];
664 n = n >> 4;
665 ++i;
666 } while (n);
668 return (ptr);
669 }
671 /*
672 * ======== freeInst ========
673 */
674 static Void freeInst(RMS_Obj *inst)
675 {
676 if (inst->name != NULL) {
677 Memory_free(inst->name, strlen(inst->name) + 1, NULL);
678 }
679 Memory_free(inst, sizeof (RMS_Obj), NULL);
680 }
682 /*
683 * ======== getAlg ========
684 */
685 static RMS_Status getAlg(RMS_CmdSetGetAlgIn *cmdIn,
686 RMS_CmdSetGetAlgOut *cmdOut)
687 {
688 NODE_Desc *desc;
689 Int len;
690 Int nodeTabLen = 0;
691 Int index = (Int)cmdIn->index;
693 Log_print2(Diags_USER5, "[+5] RMS getAlg> Enter(0x%x, 0x%x)",
694 (IArg)cmdIn, (IArg)cmdOut);
696 /* search the database of nodes for the given uuid */
697 for (desc = RMS_nodeTab, nodeTabLen = 0; desc->name != NULL;
698 desc++, nodeTabLen++) {
699 }
701 if (index < nodeTabLen) {
702 desc = RMS_nodeTab + index;
703 }
704 else {
705 desc = Server_getNode(index - nodeTabLen);
706 }
708 if (desc == NULL) {
709 /* Can't find node with this index */
710 Log_print3(Diags_USER6, "[+6] RMS getAlg> Failed to find node [%d]. "
711 "RMS_nodeTab len = [%d], number of dynamically added "
712 "nodes = [%d]", (IArg)index, (IArg)nodeTabLen,
713 (IArg)Server_getNumNodes());
714 return (RMS_EFAIL);
715 }
717 /* Copy alg name */
718 len = strlen(desc->name);
719 if (len >= RMS_MAXSTRLEN) {
720 /* Name is too big to copy */
721 Log_print1(Diags_USER7, "[+7] RMS getAlg> Length of alg name [%d] "
722 "is too big to copy!", len);
723 return (RMS_EFAIL);
724 }
725 strncpy((Char *)cmdOut->name, desc->name, RMS_MAXSTRLEN);
727 /* Copy stub functions name */
728 len = strlen(desc->stubFxnsName);
729 if (len >= RMS_MAXSTRLEN) {
730 /* Name is too big to copy */
731 Log_print1(Diags_USER7, "[+7] RMS getAlg> Length of alg's stub "
732 "functions name [%d] is too big to copy!", len);
733 return (RMS_EFAIL);
734 }
735 strncpy((Char *)cmdOut->stubFxns, desc->stubFxnsName, RMS_MAXSTRLEN);
737 /* Copy the typetab string */
738 len = strlen(desc->typeTab);
739 if (len >= RMS_MAXSTRLEN) {
740 /* Name is too big to copy */
741 Log_print1(Diags_USER7, "[+7] RMS getAlg> Length of alg's typeTab "
742 "string [%d] is too big to copy!", len);
743 return (RMS_EFAIL);
744 }
745 strncpy((Char *)cmdOut->typeTab, desc->typeTab, RMS_MAXSTRLEN);
747 /* Copy the rest of the stuff */
748 cmdOut->uuid = desc->uuid;
749 cmdOut->rpcProtocolVersion = desc->rpcProtocolVersion;
751 return (RMS_EOK);
752 }
755 /*
756 * ======== getMemStat ========
757 */
758 static RMS_Status getMemStat(RMS_CmdSetGetMemStatOut *out)
759 {
760 Int i;
761 ti_sdo_ce_osal_Memory_Stat statBuf;
762 UInt32 total = 0;
764 for (i = 0; i < MAXNUMSEGS; i++) {
765 if (Memory_segStat(i, &statBuf) != TRUE) {
766 break;
767 }
768 total += statBuf.used;
769 }
771 if (i == MAXNUMSEGS) {
772 /* Memory may be corrupted, print warning */
773 Log_print1(Diags_USER6, "[+6] RMS> getMemStat() finding > %d heaps!!!",
774 (IArg)MAXNUMSEGS);
775 }
776 out->used = total;
778 checkStack();
780 return (RMS_EOK);
781 }
783 /*
784 * ======== getMemRecs ========
785 */
786 static RMS_Status getMemRecs(RMS_CmdSetGetMemRecsIn *cmdIn,
787 RMS_CmdSetGetMemRecsOut *cmdOut)
788 {
789 RMS_Obj *rmsInst = (RMS_Obj *)cmdIn->node;
790 Algorithm_Handle alg;
791 VISA_Handle visa;
792 Int maxRecs = cmdIn->numRecs;
793 IALG_MemRec *memTab = (IALG_MemRec *)(cmdOut->memRecs);
794 RMS_Status status = RMS_EOK;
796 visa = (VISA_Handle)NODE_getEnv(rmsInst->node);
797 alg = (Algorithm_Handle)VISA_getAlgorithmHandle(visa);
799 cmdOut->numRecs = Algorithm_getMemRecs(alg, memTab, maxRecs);
801 return (status);
802 }
804 /*
805 * ======== getNumAlgs ========
806 */
807 static RMS_Status getNumAlgs(RMS_CmdSetGetNumAlgsOut *cmdOut)
808 {
809 NODE_Desc *desc;
810 Int numAlgs = 0;
812 Log_print1(Diags_USER5, "[+5] RMS getNumAlgs> Enter(0x%x)", (IArg)cmdOut);
814 /* Count the number of nodes in the database */
815 for (desc = RMS_nodeTab; desc->name != NULL; desc++, numAlgs++) {
816 }
818 /* Get the number of dynamically addes algs */
819 numAlgs += Server_getNumNodes();
821 cmdOut->numAlgs = numAlgs;
822 return (RMS_EOK);
823 }
825 /*
826 * ======== getNumRecs ========
827 */
828 static RMS_Status getNumRecs(RMS_CmdSetGetNumRecsIn *cmdIn,
829 RMS_CmdSetGetNumRecsOut *cmdOut)
830 {
831 RMS_Obj *rmsInst = (RMS_Obj *)cmdIn->node;
832 Algorithm_Handle alg;
833 VISA_Handle visa;
834 RMS_Status status = RMS_EOK;
836 visa = (VISA_Handle)NODE_getEnv(rmsInst->node);
837 alg = (Algorithm_Handle)VISA_getAlgorithmHandle(visa);
839 cmdOut->numRecs = Algorithm_getNumRecs(alg);
841 return (status);
842 }
844 /*
845 * ======== getSegStat ========
846 */
847 static RMS_Status getSegStat(Int segId, RMS_CmdSetGetSegStatOut *out)
848 {
849 Memory_Stat statBuf;
851 if (Memory_segStat(segId, &statBuf) != TRUE) {
852 /* segId is out of range */
853 Log_print1(Diags_USER6,
854 "[+6] RMS> getSegStat() segment [%d] not found", (IArg)segId);
855 return (RMS_ENOTFOUND);
856 }
857 else {
858 /* Copy to out */
859 out->base = statBuf.base;
860 out->size = statBuf.size;
861 out->used = statBuf.used;
862 out->maxBlockLen = statBuf.length;
864 /* Copy memory segment name */
865 // TODO: Find a way to get segment name.
866 if (statBuf.name != NULL) {
867 strncpy((Char *)out->name, statBuf.name, RMS_MAXSEGNAMELENGTH);
868 ((Char *)(out->name))[RMS_MAXSEGNAMELENGTH] = '\0';
869 }
870 else {
871 ((Char *)(out->name))[0] = 0;
872 }
873 }
875 return (RMS_EOK);
876 }
878 /*
879 * ======== getCpuStat ========
880 */
881 static RMS_Status getCpuStat(RMS_CmdSetGetCpuStatOut *out)
882 {
883 out->cpuLoad = Global_getCpuLoad();
884 return (RMS_EOK);
885 }
887 #if 0
888 /*
889 * ======== getTrace ========
890 */
891 static RMS_Status getTrace(RMS_CmdSetGetTraceOut *out, Int size)
892 {
893 UInt32 avail;
894 UInt32 lost;
896 Log_print2(Diags_USER5, "[+5] RMS getTrace> Enter(0x%x, 0x%x)",
897 (IArg)out, (IArg)size);
899 out->max = Trace_getSize();
900 out->size = Trace_fillBuf((Char *)out->buf, size, &avail, &lost);
901 out->avail = avail;
902 out->lost = lost;
904 return (RMS_EOK);
905 }
906 #endif
908 /*
909 * ======== setTraceMask ========
910 */
911 static RMS_Status setTraceMask(RMS_CmdSetSetTraceMaskIn *in)
912 {
913 String mask = (String)in->traceMask;
915 mask[RMS_MAXTRACEMASKSIZE + 1] = '\0';
917 Log_print1(Diags_ENTRY, "[+E] setting trace mask to %s", (IArg)mask);
919 Diags_setMask(mask);
921 Global_setSpecialTrace(mask);
923 return (RMS_EOK);
924 }
926 /*
927 * ======== getVers ========
928 */
929 static RMS_Status getVers(RMS_CmdSetGetVersOut *out)
930 {
931 extern String ti_sdo_ce__versionString;
933 if (ti_sdo_ce__versionString != NULL) {
934 /* The CE version */
935 strncpy((Char *)out->vers, ti_sdo_ce__versionString,
936 RMS_READBUFSIZE - 1);
937 ((Char *)out->vers)[RMS_READBUFSIZE - 1] = '\0';
939 /* The RMS Protocol version */
940 out->rpcMajor = RMS_VERSION_MAJOR;
941 out->rpcSource = RMS_VERSION_SOURCE;
942 out->rpcMinor = RMS_VERSION_MINOR;
944 return (RMS_EOK);
945 }
947 return (RMS_EFAIL);
948 }
950 /*
951 * ======== mkInst ========
952 */
953 static RMS_Obj *mkInst(String nodeName, Int id)
954 {
955 Char idBuf[MAXNUMLEN + 1]; /* +1 for terminating '\0' */
956 String idString;
957 Int len;
958 RMS_Obj *inst;
960 inst = Memory_alloc(sizeof (RMS_Obj), NULL);
961 if (inst == NULL) {
962 return (NULL);
963 }
965 idBuf[MAXNUMLEN] = '\0';
966 idString = formatNum(idBuf + MAXNUMLEN, id);
968 len = strlen(nodeName) + strlen(idString) + 2; /* +2 for '\0' and '#' */
969 inst->name = (String)Memory_alloc(len, NULL);
970 if (inst->name == NULL) {
971 freeInst(inst);
972 return (NULL);
973 }
975 strcpy(inst->name, nodeName);
976 strcat(inst->name, "#");
977 strcat(inst->name, idString);
979 return (inst);
980 }
982 /*
983 * ======== processRmsCmd ========
984 */
985 static RMS_Status processRmsCmd(RMS_CmdBuf *cmdBuf, Int cmdBufSize)
986 {
987 Log_print3(Diags_ENTRY, "[+E] processRmsCmd(0x%x, %d): cmd = %d",
988 (IArg)cmdBuf, (IArg)cmdBufSize, (IArg)(cmdBuf->cmd));
990 switch (cmdBuf->cmd) {
991 case RMS_CREATENODE:
992 return createNode(&cmdBuf->data.createNodeIn,
993 &cmdBuf->data.createNodeOut);
994 case RMS_STARTNODE:
995 return startNode(&cmdBuf->data.startNodeIn);
997 case RMS_DELETENODE:
998 return deleteNode(&cmdBuf->data.deleteNodeIn,
999 &cmdBuf->data.deleteNodeOut);
1001 case RMS_GETMEMSTAT:
1002 return getMemStat(&cmdBuf->data.getMemStatOut);
1004 case RMS_GETNUMSEGS:
1005 cmdBuf->data.getNumSegsOut.numSegs = Memory_getNumHeaps();
1006 return (RMS_EOK);
1008 case RMS_GETSEGSTAT:
1009 return getSegStat((Int)(cmdBuf->data.getSegStatIn.segId),
1010 &cmdBuf->data.getSegStatOut);
1012 case RMS_GETCPUSTAT:
1013 return getCpuStat(&cmdBuf->data.getCpuStatOut);
1015 #if 0
1016 case RMS_GETTRACE: {
1017 Int traceSize = cmdBufSize - (
1018 (Char *)cmdBuf->data.getTraceOut.buf - (Char *)cmdBuf
1019 );
1020 Log_print2(Diags_ENTRY,
1021 "[+E] remote time = 0x%x, trace buffer size = %d",
1022 (IArg)(cmdBuf->data.getTraceIn.curTime), (IArg)traceSize);
1023 return getTrace(&cmdBuf->data.getTraceOut, traceSize);
1024 }
1025 #endif
1027 case RMS_SETTRACEMASK:
1028 return setTraceMask(&cmdBuf->data.setTraceMaskIn);
1030 case RMS_GETVERS:
1031 return getVers(&cmdBuf->data.getVersOut);
1033 case RMS_REDEFINEHEAP:
1034 return redefineHeap((String)(cmdBuf->data.redefineHeapIn.name),
1035 -1, /* Redefine heap by name, not segid */
1036 cmdBuf->data.redefineHeapIn.base,
1037 cmdBuf->data.redefineHeapIn.size);
1039 case RMS_RELTRACETOKEN:
1040 traceTokenAvailable = TRUE;
1041 return (RMS_EOK);
1043 case RMS_REQTRACETOKEN:
1044 if (traceTokenAvailable == TRUE) {
1045 traceTokenAvailable = FALSE;
1046 return (RMS_EOK);
1047 }
1048 else {
1049 return (RMS_ERESOURCE);
1050 }
1052 case RMS_RESTOREHEAP:
1053 return restoreHeap((String)(cmdBuf->data.redefineHeapIn.name));
1055 case RMS_WRITEWORD:
1056 *(Int *)(cmdBuf->data.writeWordIn.addr) =
1057 (Int)cmdBuf->data.writeWordIn.value;
1058 return (RMS_EOK);
1060 case RMS_GETNUMMEMRECS:
1061 return getNumRecs(&cmdBuf->data.getNumRecsIn,
1062 &cmdBuf->data.getNumRecsOut);
1064 case RMS_GETMEMRECS:
1065 return getMemRecs(&cmdBuf->data.getMemRecsIn,
1066 &cmdBuf->data.getMemRecsOut);
1067 case RMS_GETALG:
1068 return (getAlg(&cmdBuf->data.getAlgIn, &cmdBuf->data.getAlgOut));
1070 case RMS_ADDALG:
1071 return (addAlg(&cmdBuf->data.addAlgIn, &cmdBuf->data.addAlgOut));
1073 case RMS_GETNUMALGS:
1074 return (getNumAlgs(&cmdBuf->data.getNumAlgsOut));
1076 case RMS_DETACH:
1077 detachFlag = 1;
1078 return (RMS_EOK);
1080 case RMS_QUIT:
1081 exitFlag = 1;
1082 return (RMS_EOK);
1084 default:
1085 return (RMS_EFAIL);
1086 }
1087 }
1089 /*
1090 * ======== redefineHeap ========
1091 * Redefine the heap defined by either name (if not NULL), or by segId
1092 * (if name is NULL).
1093 */
1094 static RMS_Status redefineHeap(String name, Int segId, UInt32 base,
1095 UInt32 size)
1096 {
1097 Memory_Stat stat;
1098 Uint32 end = base + size - 1;
1099 Int i;
1101 if (name != NULL) {
1102 if ((segId = Memory_getHeapId(name)) < 0) {
1103 Log_print1(Diags_USER6, "[+6] RMS> redefineHeap() heap %s not "
1104 "found.", (IArg)name);
1105 return (RMS_ENOTFOUND);
1106 }
1107 }
1109 Assert_isTrue(Memory_segStat(segId, &stat), (Assert_Id)NULL);
1111 /*
1112 * Check for memory overlap with another heap, if size > 0.
1113 * (This check still does not guarentee that [base, base + size - 1]
1114 * is a valid memory segment.)
1115 */
1116 if (size > MINHEAPSIZE) {
1117 for (i = 0; Memory_segStat(i, &stat); i++) {
1118 if (i == segId) {
1119 continue;
1120 }
1122 if (((stat.base <= base) && (base < stat.base + stat.size)) ||
1123 ((base <= stat.base) && (stat.base <= end))) {
1124 /* Memory overlap */
1125 Log_print2(Diags_USER6, "[+6] RMS> redefineHeap() cannot "
1126 "redefine heap %s, since this would cause overlap "
1127 "with heap %s", (IArg)name, (IArg)stat.name);
1128 return (RMS_EINVAL);
1129 }
1130 }
1131 }
1132 else {
1133 Log_print3(Diags_USER6, "[+6] RMS> redefineHeap() cannot redefine "
1134 "heap %s, since new size (0x%x) is too small. Size should "
1135 "be at least %d.",
1136 (IArg)name, (IArg)size, (IArg)MINHEAPSIZE);
1137 return (RMS_EINVAL);
1138 }
1140 if (!Memory_redefine(segId, base, size)) {
1141 /*
1142 * Should not get here unless memory is in use, since we've
1143 * already checked that segment exists.
1144 */
1145 return (RMS_EFREE);
1146 }
1148 return (RMS_EOK);
1149 }
1151 /*
1152 * ======== restoreHeap ========
1153 */
1154 static RMS_Status restoreHeap(String name)
1155 {
1156 Int segId;
1158 if ((segId = Memory_getHeapId(name)) < 0) {
1159 Log_print1(Diags_USER6, "[+6] RMS> restoreHeap() heap %s not found",
1160 (IArg)name);
1161 return (RMS_ENOTFOUND);
1162 }
1164 if (!Memory_restoreHeap(segId)) {
1165 /*
1166 * Should not get here unless memory is in use, since we've
1167 * already checked that segment exists.
1168 */
1169 return (RMS_EFREE);
1170 }
1172 return (RMS_EOK);
1173 }