1 /*
2 * Copyright (c) 2012-2015, 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 * ======== lad.c ========
34 */
36 #include <ti/ipc/Std.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <sys/stat.h>
44 #include <sys/time.h>
45 #include <sys/types.h>
46 #include <signal.h>
47 #include <unistd.h>
48 #include <dirent.h>
50 #include <ti/ipc/MessageQ.h>
51 #include <_MessageQ.h>
52 #include <ti/ipc/NameServer.h>
53 #include <_NameServer.h>
54 #include <ti/ipc/GateMP.h>
55 #include <_GateMP_daemon.h>
56 #include <_MultiProc.h>
58 #include <GateHWSpinlock.h>
60 #include <ladclient.h>
61 #include <_lad.h>
63 #define DAEMON 1 /* 1 = run as a daemon; 0 = run as app */
65 Bool logFile = FALSE;
66 FILE *logPtr = NULL;
67 struct timeval start_tv;
69 static String commandFIFOFile = LAD_COMMANDFIFO;
70 static FILE *commandFIFOFilePtr = NULL;
72 #if defined(GATEMP_SUPPORT)
73 static Bool gatempEnabled = FALSE;
74 #endif
76 /* LAD client info arrays */
77 static Bool clientConnected[LAD_MAXNUMCLIENTS];
78 static UInt clientPID[LAD_MAXNUMCLIENTS];
79 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
80 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
82 /* local internal routines */
83 static LAD_ClientHandle assignClientId(Void);
84 static Void cleanupFifos(Void);
85 static Void cleanupDepartedClients(Void);
86 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
87 static Void disconnectFromLAD(Int clientId);
88 static Void doDisconnect(Int clientId);
90 struct LAD_CommandObj cmd;
91 union LAD_ResponseObj rsp;
93 #define LAD_USAGE "\
94 Usage:\n\
95 lad_<platform> [options] \n\
96 \n\
97 Options:\n\
98 h : print this help message\n\
99 g : enable GateMP support \n\
100 l <logfile> : name of logfile for LAD\n\
101 n <nprocs> : total number of processors in the system\n\
102 p <oct value>: set LAD's directory permissions\n\
103 r <nreserve> : number of reserved queues\n\
104 s <synctype> : type of Ipc_ProcSync (ALL|PAIR|NONE)\n\
105 b <value> : Processor's base cluster id \n\
106 \n\
107 Examples:\n\
108 lad_<platform> -h\n\
109 lad_<platform> -l log.txt\n\
110 lad_<platform> -l log.txt -p 777\n\
111 lad_<platform> -g -l log.txt\n\
112 lad_<platform> -l log.txt -b 10\n\
113 \n"
115 /*
116 * ======== main ========
117 */
118 int main(int argc, char * argv[])
119 {
120 MessageQ_Handle handle;
121 Ipc_Config ipcCfg;
122 UInt16 *procIdPtr;
123 Int statusIO;
124 Int clientId;
125 Int command;
126 Int flags;
127 Int i;
128 Int n;
129 Int c;
130 #if defined(GATEMP_SUPPORT)
131 Int status;
132 UInt16 procId;
133 #endif
134 String tmpString;
135 #if DAEMON
136 pid_t pid;
137 pid_t sid;
138 #endif
140 /* change to LAD's root directory */
141 if ((chdir(LAD_ROOTDIR)) < 0) {
142 /* if can't change directory assume it needs to be created, do it */
143 if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
144 fprintf(stderr,
145 "\nERROR: Failed to create LAD's root directory!\n");
146 exit(EXIT_FAILURE);
147 }
148 }
150 /* change to LAD's working directory */
151 if ((chdir(LAD_WORKINGDIR)) < 0) {
153 /* if can't change directory assume it needs to be created, do it */
154 if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
155 fprintf(stderr,
156 "\nERROR: Failed to create LAD's working directory!\n");
157 exit(EXIT_FAILURE);
158 }
159 /* now change to the new directory */
160 if ((chdir(LAD_WORKINGDIR)) < 0) {
161 fprintf(stderr,
162 "\nERROR: Failed to change to LAD's working directory!\n");
163 exit(EXIT_FAILURE);
164 }
165 } else {
166 cleanupFifos();
167 }
169 /* process command line args */
170 while (1) {
171 c = getopt(argc, argv, "b:ghl:n:p:r:s:");
172 if (c == -1) {
173 break;
174 }
176 switch (c) {
177 case 'g':
178 #if defined(GATEMP_SUPPORT)
179 printf("\nGateMP support enabled on host\n");
180 gatempEnabled = TRUE;
181 #else
182 printf("\nGateMP is not supported for this device\n");
183 #endif
184 break;
185 case 'b':
186 printf("\nSet LAD's base cluster id to %s\n", optarg);
187 _MultiProc_cfg.id = atoi(optarg);
188 _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
189 break;
190 case 'h':
191 printf("%s", LAD_USAGE);
192 exit(0);
193 break;
194 case 'l':
195 logPtr = fopen(optarg, "w");
196 if (logPtr == NULL) {
197 fprintf(stderr, "\nERROR: unable to open log file %s\n",
198 optarg);
199 exit(EXIT_FAILURE);
200 }
201 else {
202 logFile = TRUE;
203 gettimeofday(&start_tv, NULL);
204 printf("\nOpened log file: %s\n", optarg);
205 /* close log file upon LAD termination */
206 flags = fcntl(fileno(logPtr), F_GETFD);
207 if (flags != -1) {
208 fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
209 }
210 }
211 break;
212 case 'n':
213 printf("\nSet LAD's number of processors to %s\n", optarg);
214 _MultiProc_cfg.numProcessors = atoi(optarg);
215 break;
216 case 'p':
217 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
218 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
219 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
220 break;
221 case 'r':
222 printf("\nSet LAD's number of reserved queues to %s\n", optarg);
223 _MessageQ_setNumReservedEntries(atoi(optarg));
224 break;
225 case 's':
226 printf("\nSet LAD's synchronization scheme to ProcSync_%s\n",
227 optarg);
229 Ipc_getConfig(&ipcCfg);
231 if (!strcmp(optarg, "ALL")) {
232 ipcCfg.procSync = Ipc_ProcSync_ALL;
233 }
234 else if (!strcmp(optarg, "PAIR")) {
235 ipcCfg.procSync = Ipc_ProcSync_PAIR;
236 }
237 else if (!strcmp(optarg, "NONE")) {
238 ipcCfg.procSync = Ipc_ProcSync_NONE;
239 }
240 else {
241 fprintf(stderr,
242 "Error: bad synchronization specified, must be "
243 "ALL|PAIR|NONE\n");
244 exit(EXIT_FAILURE);
245 }
247 Ipc_setConfig(&ipcCfg);
248 break;
249 default:
250 fprintf (stderr, "\nUnrecognized argument\n");
251 exit(EXIT_FAILURE);
252 }
253 }
255 /* Check to ensure id and baseId are not invalid */
256 printf ("\nnumProcessors = %d id = %d baseId = %d\n",
257 _MultiProc_cfg.numProcessors, _MultiProc_cfg.id,
258 _MultiProc_cfg.baseIdOfCluster);
260 if (_MultiProc_cfg.id == 0xFFFF ||
261 _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
262 fprintf(stderr, "\nBase cluster id is set to an INVALID value\n");
263 fprintf(stderr,
264 "Use -b option to set value or modify the MultiProcCfg file\n"
265 );
266 exit(EXIT_FAILURE);
267 }
268 if ((_MultiProc_cfg.baseIdOfCluster + _MultiProc_cfg.numProcsInCluster) >
269 _MultiProc_cfg.numProcessors) {
270 fprintf(stderr,
271 "\nNumber of processors (%d) must be >= base cluster id + "
272 "number of processors in cluster (%d + %d)\n",
273 _MultiProc_cfg.numProcessors, _MultiProc_cfg.baseIdOfCluster,
274 _MultiProc_cfg.numProcsInCluster);
275 exit(EXIT_FAILURE);
276 }
279 #if DAEMON
280 /* fork off a child process */
281 pid = fork();
283 /* if fork of child failed then exit immediately; no child created */
284 if (pid < 0) {
285 fprintf(stderr, "\nERROR: Failed to fork child process!");
286 exit(EXIT_FAILURE);
287 }
289 /* if pid > 0 this is the parent; time to die ... */
290 if (pid > 0) {
291 printf("\nSpawned daemon: %s\n\n", argv[0]);
292 exit(EXIT_SUCCESS);
293 }
295 /* child continues from here (pid == 0) ... */
297 /* change file mode mask */
298 umask(0);
300 /* create new session ID for the child */
301 sid = setsid();
303 /* exit with failure code if failed to get session ID... */
304 if (sid < 0) {
305 fprintf(stderr, "\nERROR: Failed to acquire new session ID!");
306 exit(EXIT_FAILURE);
307 }
309 /* disassociate from the standard file descriptors */
310 close(STDIN_FILENO);
311 close(STDOUT_FILENO);
312 close(STDERR_FILENO);
314 #endif
316 LOG0("\nInitializing LAD... ")
318 /* TODO:L make sure LAD is not already running? */
320 /* initialize client info arrays */
321 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
322 clientConnected[i] = FALSE;
323 responseFIFOFilePtr[i] = NULL;
324 }
326 /* if command FIFO exists from previous LAD session delete it now */
327 unlink(commandFIFOFile);
329 /* create command FIFO */
330 statusIO = mkfifo(commandFIFOFile, 0777);
331 if (statusIO != 0) {
332 LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
333 errno)
334 return(0);
335 }
337 /* set FIFO permissions to read/write */
338 chmod(commandFIFOFile, 0666);
340 /* Setup modules relevant for GateMP if necessary */
341 #if defined(GATEMP_SUPPORT)
342 if (gatempEnabled) {
343 /* Set up NameServer for resource manager process */
344 status = NameServer_setup();
345 if (status < 0) {
346 LOG0("\nERROR: unable to setup NameServer\n")
347 return(0);
348 }
350 status = GateHWSpinlock_start();
351 if (status < 0) {
352 LOG0("\nERROR: unable to start GateHWSpinlock\n");
353 return(0);
354 }
356 /* Set up GateMP */
357 status = GateMP_setup();
358 if (status < 0) {
359 LOG0("\nERROR: unable to setup GateMP\n")
360 NameServer_destroy();
361 return(0);
362 }
363 }
364 #endif
366 opencommandFIFO:
368 /* now open file for FIFO - will block until writer arrives... */
369 LOG1("\n opening FIFO: %s\n", commandFIFOFile)
370 commandFIFOFilePtr = fopen(commandFIFOFile, "r");
371 if (commandFIFOFilePtr == NULL) {
372 LOG0("\nERROR: unable to open command FIFO\n")
373 unlink(commandFIFOFile);
374 #if defined(GATEMP_SUPPORT)
375 if (gatempEnabled) {
376 GateMP_destroy();
377 NameServer_destroy();
378 }
379 #endif
380 return(0);
381 }
383 /* COMMAND PROCESSING LOOP */
384 while (1) {
385 LOG0("Retrieving command...\n")
387 /* read the next command packet */
388 n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
390 /*
391 * if last client closes FIFO then it must be closed and reopened ...
392 */
393 if (!n) {
394 LOG1(" EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
395 fclose(commandFIFOFilePtr);
397 goto opencommandFIFO;
398 }
400 /* cleanup for any connected/started clients that have departed */
401 cleanupDepartedClients();
403 command = cmd.cmd;
404 clientId = cmd.clientId;
406 /* process individual commands */
407 switch (command) {
408 /*
409 * Since cmd is a union of rcv and snd structs, don't write
410 * any snd elements before all rcv elements have been referenced
411 * (either saved in separate variables or passed to a function).
412 *
413 * cmd.cmd has already been saved in 'command'
414 * cmd.clientId has already been saved in 'clientId'
415 */
416 case LAD_CONNECT:
417 connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
418 cmd.args.connect.protocol, NULL);
420 break;
422 case LAD_DISCONNECT:
423 disconnectFromLAD(clientId);
425 break;
427 case LAD_IPC_GETCONFIG:
428 Ipc_getConfig(&rsp.ipcConfig);
429 break;
431 case LAD_NAMESERVER_SETUP:
432 LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
434 rsp.status = NameServer_setup();
436 LOG1(" status = %d\n", rsp.status)
437 LOG0("DONE\n")
439 break;
441 case LAD_NAMESERVER_DESTROY:
442 LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
444 rsp.status = NameServer_destroy();
446 LOG1(" status = %d\n", rsp.status)
447 LOG0("DONE\n")
449 break;
451 case LAD_NAMESERVER_PARAMS_INIT:
452 LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
454 NameServer_Params_init(&rsp.params);
456 LOG0("DONE\n")
458 break;
460 case LAD_NAMESERVER_CREATE:
461 LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
463 rsp.handle = NameServer_create(cmd.args.create.name,
464 &cmd.args.create.params);
466 LOG1(" handle = %p\n", rsp.handle)
467 LOG0("DONE\n")
469 break;
471 case LAD_NAMESERVER_DELETE:
472 LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
473 cmd.args.nsdelete.handle)
475 rsp.nsdelete.handle = cmd.args.nsdelete.handle;
476 rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
478 LOG1(" status = %d\n", rsp.nsdelete.status)
479 LOG0("DONE\n")
481 break;
483 case LAD_NAMESERVER_ADD:
484 LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
485 LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
486 LOG1(" 0x%x)...\n", cmd.args.add.len)
488 rsp.entryPtr = NameServer_add(
489 cmd.args.add.handle,
490 cmd.args.add.name,
491 cmd.args.add.buf,
492 cmd.args.add.len);
494 LOG1(" entryPtr = %p\n", rsp.entryPtr)
495 LOG0("DONE\n")
497 break;
499 case LAD_NAMESERVER_GET:
500 LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
501 cmd.args.get.handle, cmd.args.get.name)
502 LOG0(")...\n")
504 if (cmd.args.get.procId[0] == (UInt16)-1) {
505 procIdPtr = NULL;
506 }
507 else {
508 procIdPtr = cmd.args.get.procId;
509 }
510 rsp.get.status = NameServer_get(
511 cmd.args.get.handle,
512 cmd.args.get.name,
513 rsp.get.buf,
514 &cmd.args.get.len,
515 procIdPtr);
516 rsp.get.len = cmd.args.get.len;
518 LOG1(" value = 0x%x\n", rsp.get.len)
519 LOG1(" status = %d\n", rsp.get.status)
520 LOG0("DONE\n")
522 break;
524 case LAD_NAMESERVER_ADDUINT32:
525 LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
526 "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
527 cmd.args.addUInt32.name, cmd.args.addUInt32.val)
529 rsp.entryPtr = NameServer_addUInt32(
530 cmd.args.addUInt32.handle,
531 cmd.args.addUInt32.name,
532 cmd.args.addUInt32.val);
534 LOG1(" entryPtr = %p\n", rsp.entryPtr)
535 LOG0("DONE\n")
537 break;
539 case LAD_NAMESERVER_GETUINT32:
540 LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
541 "(%p, '%s')...\n", cmd.args.getUInt32.handle,
542 cmd.args.getUInt32.name)
544 if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
545 procIdPtr = NULL;
546 }
547 else {
548 procIdPtr = cmd.args.getUInt32.procId;
549 }
550 rsp.getUInt32.status = NameServer_getUInt32(
551 cmd.args.getUInt32.handle,
552 cmd.args.getUInt32.name,
553 &rsp.getUInt32.val,
554 procIdPtr);
556 LOG1(" value = 0x%x\n", rsp.getUInt32.val)
557 LOG1(" status = %d\n", rsp.getUInt32.status)
558 LOG0("DONE\n")
560 break;
562 case LAD_NAMESERVER_GETLOCAL:
563 rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
564 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
565 rsp.get.len = cmd.args.getLocal.len;
566 break;
568 case LAD_NAMESERVER_GETLOCALUINT32:
569 rsp.getUInt32.status = NameServer_getLocalUInt32(
570 cmd.args.getLocalUInt32.handle,
571 cmd.args.getLocalUInt32.name,
572 &rsp.getUInt32.val);
573 break;
575 case LAD_NAMESERVER_REMOVE:
576 LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
578 rsp.status = NameServer_remove(cmd.args.remove.handle,
579 cmd.args.remove.name);
581 LOG1(" status = %d\n", rsp.status)
582 LOG0("DONE\n")
584 break;
586 case LAD_NAMESERVER_REMOVEENTRY:
587 LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
589 rsp.status = NameServer_removeEntry(
590 cmd.args.removeEntry.handle,
591 cmd.args.removeEntry.entryPtr);
593 LOG1(" status = %d\n", rsp.status)
594 LOG0("DONE\n")
596 break;
598 case LAD_NAMESERVER_ATTACH:
599 rsp.status = NameServer_attach(cmd.args.attach.procId);
600 break;
602 case LAD_NAMESERVER_DETACH:
603 rsp.status = NameServer_detach(cmd.args.detach.procId);
604 break;
606 case LAD_MESSAGEQ_GETCONFIG:
607 LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
609 MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
610 rsp.messageQGetConfig.status = 0;
612 LOG1(" status = %d\n", rsp.messageQGetConfig.status)
613 LOG0("DONE\n")
615 break;
617 case LAD_MESSAGEQ_SETUP:
618 LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
620 rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
621 rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
623 LOG1(" status = %d\n", rsp.setup.status)
624 LOG0("DONE\n")
626 break;
628 case LAD_MESSAGEQ_DESTROY:
629 LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
631 rsp.status = MessageQ_destroy();
633 LOG1(" status = %d\n", rsp.status)
634 LOG0("DONE\n")
636 break;
638 case LAD_MESSAGEQ_CREATE:
639 LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
640 cmd.args.messageQCreate.name,
641 &cmd.args.messageQCreate.params);
643 tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
644 cmd.args.messageQCreate.name;
646 handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
647 rsp.messageQCreate.serverHandle = handle;
649 if (handle) {
650 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
651 MessageQ_setQueueOwner(handle, clientPID[clientId]);
652 rsp.messageQCreate.status = 0;
653 }
654 else {
655 rsp.messageQCreate.status = -1;
656 }
658 LOG1(" status = %d\n", rsp.messageQCreate.status)
659 LOG0("DONE\n")
661 break;
663 case LAD_MESSAGEQ_DELETE:
664 LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
666 rsp.messageQDelete.status =
667 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
669 LOG1(" status = %d\n", rsp.messageQDelete.status)
670 LOG0("DONE\n")
672 break;
674 case LAD_MESSAGEQ_MSGINIT:
675 LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
677 MessageQ_msgInit(&rsp.msgInit.msg);
678 rsp.msgInit.status = 0;
680 LOG1(" status = %d\n", rsp.msgInit.status)
681 LOG0("DONE\n")
683 break;
685 case LAD_MULTIPROC_GETCONFIG:
686 LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
688 MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
689 rsp.multiprocGetConfig.status = 0;
691 LOG1(" status = %d\n", rsp.multiprocGetConfig.status)
692 LOG0("DONE\n")
694 break;
696 #if defined(GATEMP_SUPPORT)
697 case LAD_GATEMP_ATTACH:
698 procId = cmd.args.attach.procId;
699 LOG1("LAD_GATEMP_ATTACH: calling GateMP_attach(%d)...\n", procId)
701 rsp.status = GateMP_attach(procId);
703 LOG1(" status = %d\n", rsp.status)
704 LOG0("DONE\n")
706 break;
708 case LAD_GATEMP_DETACH:
709 procId = cmd.args.detach.procId;
710 LOG1("LAD_GATEMP_DETACH: calling GateMP_detach(%d)...\n", procId)
712 rsp.status = GateMP_detach(procId);
714 LOG1(" status = %d\n", rsp.status)
715 LOG0("DONE\n")
717 break;
719 case LAD_GATEMP_START:
720 LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
722 rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
723 rsp.gateMPStart.status = GateMP_S_SUCCESS;
725 LOG1(" status = %d\n", rsp.gateMPStart.status)
726 LOG0("DONE\n")
728 break;
730 case LAD_GATEMP_GETNUMRESOURCES:
731 LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
733 rsp.gateMPGetNumResources.value = GateMP_getNumResources(
734 cmd.args.gateMPGetNumResources.type);
735 rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
737 LOG1(" status = %d\n", rsp.gateMPGetNumResources.status)
738 LOG0("DONE\n")
740 break;
742 case LAD_GATEMP_GETFREERESOURCE:
743 LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
745 rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
746 cmd.args.gateMPGetFreeResource.type);
747 rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
749 LOG1(" status = %d\n", rsp.gateMPGetFreeResource.status)
750 LOG0("DONE\n")
752 break;
754 case LAD_GATEMP_RELEASERESOURCE:
755 LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
757 rsp.gateMPReleaseResource.status = GateMP_releaseResource(
758 cmd.args.gateMPReleaseResource.id,
759 cmd.args.gateMPReleaseResource.type);
761 LOG1(" status = %d\n", rsp.gateMPReleaseResource.status)
762 LOG0("DONE\n")
764 break;
766 case LAD_GATEMP_ISSETUP:
767 LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
769 rsp.gateMPIsSetup.result = GateMP_isSetup();
770 rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
772 LOG1(" status = %d\n", rsp.gateMPIsSetup.status)
773 LOG0("DONE\n")
775 break;
777 case LAD_GATEHWSPINLOCK_GETCONFIG:
778 LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
780 GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
781 rsp.gateHWSpinlockGetConfig.status = 0;
783 LOG1(" status = %d\n", rsp.gateHWSpinlockGetConfig.status)
784 LOG0("DONE\n")
786 break;
787 #endif
789 case LAD_EXIT:
790 goto exitNow;
792 break;
794 default:
795 LOG1("\nUnrecognized command: 0x%x\n", command)
797 break;
798 }
800 switch (command) {
801 case LAD_CONNECT:
802 case LAD_DISCONNECT:
803 break;
805 case LAD_IPC_GETCONFIG:
806 case LAD_NAMESERVER_SETUP:
807 case LAD_NAMESERVER_DESTROY:
808 case LAD_NAMESERVER_PARAMS_INIT:
809 case LAD_NAMESERVER_CREATE:
810 case LAD_NAMESERVER_DELETE:
811 case LAD_NAMESERVER_ADD:
812 case LAD_NAMESERVER_GET:
813 case LAD_NAMESERVER_ADDUINT32:
814 case LAD_NAMESERVER_GETUINT32:
815 case LAD_NAMESERVER_GETLOCAL:
816 case LAD_NAMESERVER_GETLOCALUINT32:
817 case LAD_NAMESERVER_REMOVE:
818 case LAD_NAMESERVER_REMOVEENTRY:
819 case LAD_NAMESERVER_ATTACH:
820 case LAD_NAMESERVER_DETACH:
821 case LAD_MESSAGEQ_GETCONFIG:
822 case LAD_MESSAGEQ_SETUP:
823 case LAD_MESSAGEQ_DESTROY:
824 case LAD_MESSAGEQ_CREATE:
825 case LAD_MESSAGEQ_DELETE:
826 case LAD_MESSAGEQ_MSGINIT:
827 case LAD_MULTIPROC_GETCONFIG:
828 #if defined(GATEMP_SUPPORT)
829 case LAD_GATEMP_ATTACH:
830 case LAD_GATEMP_DETACH:
831 case LAD_GATEMP_START:
832 case LAD_GATEMP_GETNUMRESOURCES:
833 case LAD_GATEMP_GETFREERESOURCE:
834 case LAD_GATEMP_RELEASERESOURCE:
835 case LAD_GATEMP_ISSETUP:
836 case LAD_GATEHWSPINLOCK_GETCONFIG:
837 #endif
839 LOG0("Sending response...\n");
841 fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
842 fflush(responseFIFOFilePtr[clientId]);
844 break;
846 default:
847 break;
848 }
849 }
851 exitNow:
852 #if defined(GATEMP_SUPPORT)
853 if (gatempEnabled) {
854 GateMP_destroy();
855 NameServer_destroy();
856 }
857 #endif
858 if (logFile) {
859 LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
860 fclose(logPtr);
861 }
862 unlink(commandFIFOFile);
864 return(0);
866 }
869 /*
870 * ======== assignClientId ========
871 */
872 static LAD_ClientHandle assignClientId(Void)
873 {
874 Int clientId = -1;
875 Int i;
877 /* scan connection status flags to acquire a clientId */
878 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
879 /* if slot open then provisionally select this clientId */
880 if (clientConnected[i] == FALSE) {
881 clientId = i;
882 break;
883 }
884 }
886 return(clientId);
887 }
889 /*
890 * ======== cleanupFifos ========
891 */
892 static void cleanupFifos(Void)
893 {
894 DIR *dir;
895 struct dirent entry;
896 struct dirent *result;
897 size_t dirnamelen;
898 size_t maxcopy;
899 Char pathname[PATH_MAX];
900 Char *namep;
902 if ((dir = opendir(LAD_WORKINGDIR)) == NULL)
903 return;
905 dirnamelen = snprintf(pathname, sizeof(pathname), "%s/", LAD_WORKINGDIR);
906 if (dirnamelen >= sizeof(pathname)) {
907 closedir(dir);
908 return;
909 }
910 namep = pathname + dirnamelen;
911 maxcopy = PATH_MAX - dirnamelen;
912 while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
913 /* Delete old FIFOs left over */
914 if ((entry.d_type == DT_FIFO) && (strlen(entry.d_name) < maxcopy)) {
915 strncpy(namep, entry.d_name, maxcopy);
916 unlink(pathname);
917 }
918 }
919 closedir(dir);
920 }
922 /*
923 * ======== cleanupDepartedClients ========
924 */
925 static Void cleanupDepartedClients(Void)
926 {
927 Int killStat;
928 Int i;
930 /* scan all connections to verify client processes still exist... */
931 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
933 /* if connected... */
934 if (clientConnected[i] == TRUE) {
936 /* check if the client process (PID) still exists */
937 /*
938 * NOTE - calling kill with signal value of 0 will perform
939 * error checking, but not actually send a signal. Will use this
940 * error check to see if PID still exists. An alternative was
941 * to call getpgid. This worked, but is apparently limited to
942 * USE_XOPEN_EXTENDED configurations.
943 */
944 killStat = kill(clientPID[i], 0);
945 if ((killStat == -1) && (errno == ESRCH)) {
947 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
949 /* will always need to do the disconnect... */
950 LOG0("\nDoing DISCONNECT on behalf of client...")
951 doDisconnect(i);
953 MessageQ_cleanupOwner(clientPID[i]);
954 // NameServer_cleanupOwner(clientPID[i]);
956 LOG0("DONE\n")
957 }
958 }
959 }
960 }
963 /*
964 * ======== connectToLAD ========
965 */
966 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
967 {
968 Int clientId = -1;
969 Bool connectDenied = FALSE;
970 Int status = LAD_SUCCESS;
971 FILE * filePtr;
972 Int statusIO;
974 /*
975 * TODO:L here, and everywhere parse FIFO strings: should
976 * add full error checking for incomplete or corrupted
977 * strings? Since LAD to ladclient comms are "closed", and
978 * tested, the likelihood of problems seems very low.
979 * But should still consider doing full error checking
980 * and, hopefully, recovery.
981 */
982 LOG0("\nLAD_CONNECT: \n")
983 LOG1(" client FIFO name = %s\n", clientName)
984 LOG1(" client PID = %d\n", pid)
986 /* first check for proper communication protocol */
987 if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
989 /* if no match then reject the request */
990 LOG0(" ERROR: mismatch in communication protocol!\n")
991 LOG1(" LAD protocol = %s\n", LAD_PROTOCOLVERSION)
992 LOG1(" client protocol = %s\n", clientProto)
993 status = LAD_INVALIDVERSION;
995 /* set flag so know to close FIFO after response */
996 connectDenied = TRUE;
998 /* now jump forward a bit to send response */
999 goto openResponseFIFO;
1000 }
1002 /* determine this client's ID */
1003 clientId = assignClientId();
1005 /* if failed to acquire an ID then exit early */
1006 if (clientId == -1) {
1007 LOG0(" no free handle; too many connections!\n")
1008 status = LAD_ACCESSDENIED;
1010 /* set flag so know to close FIFO after response */
1011 connectDenied = TRUE;
1012 }
1013 else {
1014 LOG1(" assigned client handle = %d\n", clientId)
1016 /* save the client's FIFO name for when disconnect */
1017 strcpy(clientFIFOName[clientId], clientName);
1018 }
1020 openResponseFIFO:
1022 /* create the dedicated response FIFO to the client */
1023 statusIO = mkfifo(clientName, 0777);
1024 if (statusIO != 0) {
1026 LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
1028 status = LAD_IOFAILURE;
1030 /* send no response; connection request will timeout */
1031 goto doneconnect;
1032 }
1034 LOG1(" FIFO %s created\n", clientName)
1036 /* set FIFO permissions to read/write */
1037 chmod(clientName, 0666);
1039 filePtr = fopen(clientName, "w");
1040 if (filePtr == NULL) {
1041 LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
1043 /* if failed open, still need to delete the FIFO */
1044 unlink(clientName);
1046 status = LAD_IOFAILURE;
1048 /* send no response; connection request will timeout */
1049 goto doneconnect;
1050 }
1052 LOG1(" FIFO %s opened for writing\n", clientName)
1054 /*
1055 * set "this client is connected" flag; this client ID is now "owned", and
1056 * is no longer provisional
1057 */
1058 if (connectDenied == FALSE) {
1059 responseFIFOFilePtr[clientId] = filePtr;
1060 clientPID[clientId] = pid;
1061 clientConnected[clientId] = TRUE;
1062 }
1064 rsp.connect.assignedId = clientId;
1065 rsp.status = status;
1067 /* put response to FIFO */
1068 fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
1069 fflush(filePtr);
1071 LOG0(" sent response\n")
1073 /* if connection was denied, must now close FIFO */
1074 if (connectDenied == TRUE) {
1075 LOG1(" connect denied; closing FIFO %s\n", clientName)
1076 fclose(filePtr);
1077 unlink(clientName);
1078 }
1080 LOG0("DONE\n")
1082 doneconnect:
1083 if (clientIdPtr != NULL) {
1084 *clientIdPtr = clientId;
1085 }
1087 return(status);
1088 }
1091 /*
1092 * ======== disconnectFromLAD ========
1093 */
1094 static Void disconnectFromLAD(Int clientId)
1095 {
1096 LOG0("\nLAD_DISCONNECT: ")
1098 LOG1("\n client handle = %x", clientId)
1099 doDisconnect(clientId);
1101 LOG0("DONE\n")
1103 return;
1104 }
1107 /*
1108 * ======== doDisconnect ========
1109 */
1110 static Void doDisconnect(Int clientId)
1111 {
1112 /* set "this client is not connected" flag */
1113 clientConnected[clientId] = FALSE;
1115 /* close and remove the response FIFO */
1116 LOG2("\n closing FIFO %s (filePtr=%p)\n",
1117 clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1118 fclose(responseFIFOFilePtr[clientId]);
1120 LOG1(" done, unlinking %s\n", clientFIFOName[clientId]);
1121 unlink(clientFIFOName[clientId]);
1122 }