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 <ctype.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include <sys/time.h>
46 #include <sys/types.h>
47 #include <signal.h>
48 #include <unistd.h>
49 #include <dirent.h>
51 #include <ti/ipc/MessageQ.h>
52 #include <_MessageQ.h>
53 #include <ti/ipc/NameServer.h>
54 #include <_NameServer.h>
55 #include <ti/ipc/GateMP.h>
56 #include <_GateMP_daemon.h>
57 #include <_MultiProc.h>
59 #include <GateHWSpinlock.h>
61 #include <ladclient.h>
62 #include <_lad.h>
64 #define DAEMON 1 /* 1 = run as a daemon; 0 = run as app */
66 #define READ_BUF_SIZE 50
68 Bool logFile = FALSE;
69 FILE *logPtr = NULL;
70 struct timeval start_tv;
72 static String commandFIFOFile = LAD_COMMANDFIFO;
73 static FILE *commandFIFOFilePtr = NULL;
75 #if defined(GATEMP_SUPPORT)
76 static Bool gatempEnabled = FALSE;
77 #endif
79 /* LAD client info arrays */
80 static Bool clientConnected[LAD_MAXNUMCLIENTS];
81 static UInt clientPID[LAD_MAXNUMCLIENTS];
82 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
83 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
85 /* local internal routines */
86 static Bool isDaemonRunning(Char *pidName);
87 static LAD_ClientHandle assignClientId(Void);
88 static Void cleanupFifos(Void);
89 static Void cleanupDepartedClients(Void);
90 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
91 static Void disconnectFromLAD(Int clientId);
92 static Void doDisconnect(Int clientId);
94 struct LAD_CommandObj cmd;
95 union LAD_ResponseObj rsp;
97 #define LAD_USAGE "\
98 Usage:\n\
99 lad_<platform> [options] \n\
100 \n\
101 Options:\n\
102 h : print this help message\n\
103 g : enable GateMP support \n\
104 l <logfile> : name of logfile for LAD\n\
105 n <nprocs> : total number of processors in the system\n\
106 p <oct value>: set LAD's directory permissions\n\
107 r <nreserve> : number of reserved queues\n\
108 s <synctype> : type of Ipc_ProcSync (ALL|PAIR|NONE)\n\
109 b <value> : Processor's base cluster id \n\
110 \n\
111 Examples:\n\
112 lad_<platform> -h\n\
113 lad_<platform> -l log.txt\n\
114 lad_<platform> -l log.txt -p 777\n\
115 lad_<platform> -g -l log.txt\n\
116 lad_<platform> -l log.txt -b 10\n\
117 \n"
119 /*
120 * ======== main ========
121 */
122 int main(int argc, char * argv[])
123 {
124 MessageQ_Handle handle;
125 Ipc_Config ipcCfg;
126 UInt16 *procIdPtr;
127 Int statusIO;
128 Int clientId;
129 Int command;
130 Int flags;
131 Int i;
132 Int n;
133 Int c;
134 #if defined(GATEMP_SUPPORT)
135 Int status;
136 UInt16 procId;
137 #endif
138 String tmpString;
139 #if DAEMON
140 pid_t pid;
141 pid_t sid;
142 #endif
144 /* change to LAD's root directory */
145 if ((chdir(LAD_ROOTDIR)) < 0) {
146 /* if can't change directory assume it needs to be created, do it */
147 if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
148 fprintf(stderr,
149 "\nERROR: Failed to create LAD's root directory!\n");
150 exit(EXIT_FAILURE);
151 }
152 }
154 if (isDaemonRunning(argv[0])) {
155 printf("Multiple instances of LAD are not supported!\n");
156 exit(EXIT_FAILURE);
157 }
159 /* change to LAD's working directory */
160 if ((chdir(LAD_WORKINGDIR)) < 0) {
162 /* if can't change directory assume it needs to be created, do it */
163 if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
164 fprintf(stderr,
165 "\nERROR: Failed to create LAD's working directory!\n");
166 exit(EXIT_FAILURE);
167 }
168 /* now change to the new directory */
169 if ((chdir(LAD_WORKINGDIR)) < 0) {
170 fprintf(stderr,
171 "\nERROR: Failed to change to LAD's working directory!\n");
172 exit(EXIT_FAILURE);
173 }
174 } else {
175 cleanupFifos();
176 }
178 /* process command line args */
179 while (1) {
180 c = getopt(argc, argv, "b:ghl:n:p:r:s:");
181 if (c == -1) {
182 break;
183 }
185 switch (c) {
186 case 'g':
187 #if defined(GATEMP_SUPPORT)
188 printf("\nGateMP support enabled on host\n");
189 gatempEnabled = TRUE;
190 #else
191 printf("\nGateMP is not supported for this device\n");
192 #endif
193 break;
194 case 'b':
195 printf("\nSet LAD's base cluster id to %s\n", optarg);
196 _MultiProc_cfg.id = atoi(optarg);
197 _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
198 break;
199 case 'h':
200 printf("%s", LAD_USAGE);
201 exit(0);
202 break;
203 case 'l':
204 logPtr = fopen(optarg, "w");
205 if (logPtr == NULL) {
206 fprintf(stderr, "\nERROR: unable to open log file %s\n",
207 optarg);
208 exit(EXIT_FAILURE);
209 }
210 else {
211 logFile = TRUE;
212 gettimeofday(&start_tv, NULL);
213 printf("\nOpened log file: %s\n", optarg);
214 /* close log file upon LAD termination */
215 flags = fcntl(fileno(logPtr), F_GETFD);
216 if (flags != -1) {
217 fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
218 }
219 }
220 break;
221 case 'n':
222 printf("\nSet LAD's number of processors to %s\n", optarg);
223 _MultiProc_cfg.numProcessors = atoi(optarg);
224 break;
225 case 'p':
226 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
227 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
228 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
229 break;
230 case 'r':
231 printf("\nSet LAD's number of reserved queues to %s\n", optarg);
232 _MessageQ_setNumReservedEntries(atoi(optarg));
233 break;
234 case 's':
235 printf("\nSet LAD's synchronization scheme to ProcSync_%s\n",
236 optarg);
238 Ipc_getConfig(&ipcCfg);
240 if (!strcmp(optarg, "ALL")) {
241 ipcCfg.procSync = Ipc_ProcSync_ALL;
242 }
243 else if (!strcmp(optarg, "PAIR")) {
244 ipcCfg.procSync = Ipc_ProcSync_PAIR;
245 }
246 else if (!strcmp(optarg, "NONE")) {
247 ipcCfg.procSync = Ipc_ProcSync_NONE;
248 }
249 else {
250 fprintf(stderr,
251 "Error: bad synchronization specified, must be "
252 "ALL|PAIR|NONE\n");
253 exit(EXIT_FAILURE);
254 }
256 Ipc_setConfig(&ipcCfg);
257 break;
258 default:
259 fprintf (stderr, "\nUnrecognized argument\n");
260 exit(EXIT_FAILURE);
261 }
262 }
264 /* Check to ensure id and baseId are not invalid */
265 printf ("\nnumProcessors = %d id = %d baseId = %d\n",
266 _MultiProc_cfg.numProcessors, _MultiProc_cfg.id,
267 _MultiProc_cfg.baseIdOfCluster);
269 if (_MultiProc_cfg.id == 0xFFFF ||
270 _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
271 fprintf(stderr, "\nBase cluster id is set to an INVALID value\n");
272 fprintf(stderr,
273 "Use -b option to set value or modify the MultiProcCfg file\n"
274 );
275 exit(EXIT_FAILURE);
276 }
277 if ((_MultiProc_cfg.baseIdOfCluster + _MultiProc_cfg.numProcsInCluster) >
278 _MultiProc_cfg.numProcessors) {
279 fprintf(stderr,
280 "\nNumber of processors (%d) must be >= base cluster id + "
281 "number of processors in cluster (%d + %d)\n",
282 _MultiProc_cfg.numProcessors, _MultiProc_cfg.baseIdOfCluster,
283 _MultiProc_cfg.numProcsInCluster);
284 exit(EXIT_FAILURE);
285 }
288 #if DAEMON
289 /* fork off a child process */
290 pid = fork();
292 /* if fork of child failed then exit immediately; no child created */
293 if (pid < 0) {
294 fprintf(stderr, "\nERROR: Failed to fork child process!");
295 exit(EXIT_FAILURE);
296 }
298 /* if pid > 0 this is the parent; time to die ... */
299 if (pid > 0) {
300 printf("\nSpawned daemon: %s\n\n", argv[0]);
301 exit(EXIT_SUCCESS);
302 }
304 /* child continues from here (pid == 0) ... */
306 /* change file mode mask */
307 umask(0);
309 /* create new session ID for the child */
310 sid = setsid();
312 /* exit with failure code if failed to get session ID... */
313 if (sid < 0) {
314 fprintf(stderr, "\nERROR: Failed to acquire new session ID!");
315 exit(EXIT_FAILURE);
316 }
318 /* disassociate from the standard file descriptors */
319 close(STDIN_FILENO);
320 close(STDOUT_FILENO);
321 close(STDERR_FILENO);
323 #endif
325 LOG0("\nInitializing LAD... ")
327 /* TODO:L make sure LAD is not already running? */
329 /* initialize client info arrays */
330 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
331 clientConnected[i] = FALSE;
332 responseFIFOFilePtr[i] = NULL;
333 }
335 /* if command FIFO exists from previous LAD session delete it now */
336 unlink(commandFIFOFile);
338 /* create command FIFO */
339 statusIO = mkfifo(commandFIFOFile, 0777);
340 if (statusIO != 0) {
341 LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
342 errno)
343 return(0);
344 }
346 /* set FIFO permissions to read/write */
347 chmod(commandFIFOFile, 0666);
349 /* Setup modules relevant for GateMP if necessary */
350 #if defined(GATEMP_SUPPORT)
351 if (gatempEnabled) {
352 /* Set up NameServer for resource manager process */
353 status = NameServer_setup();
354 if (status < 0) {
355 LOG0("\nERROR: unable to setup NameServer\n")
356 return(0);
357 }
359 status = GateHWSpinlock_start();
360 if (status < 0) {
361 LOG0("\nERROR: unable to start GateHWSpinlock\n");
362 return(0);
363 }
365 /* Set up GateMP */
366 status = GateMP_setup();
367 if (status < 0) {
368 LOG0("\nERROR: unable to setup GateMP\n")
369 NameServer_destroy();
370 return(0);
371 }
372 }
373 #endif
375 opencommandFIFO:
377 /* now open file for FIFO - will block until writer arrives... */
378 LOG1("\n opening FIFO: %s\n", commandFIFOFile)
379 commandFIFOFilePtr = fopen(commandFIFOFile, "r");
380 if (commandFIFOFilePtr == NULL) {
381 LOG0("\nERROR: unable to open command FIFO\n")
382 unlink(commandFIFOFile);
383 #if defined(GATEMP_SUPPORT)
384 if (gatempEnabled) {
385 GateMP_destroy();
386 NameServer_destroy();
387 }
388 #endif
389 return(0);
390 }
392 /* COMMAND PROCESSING LOOP */
393 while (1) {
394 LOG0("Retrieving command...\n")
396 /* read the next command packet */
397 n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
399 /*
400 * if last client closes FIFO then it must be closed and reopened ...
401 */
402 if (!n) {
403 LOG1(" EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
404 fclose(commandFIFOFilePtr);
406 goto opencommandFIFO;
407 }
409 /* cleanup for any connected/started clients that have departed */
410 cleanupDepartedClients();
412 command = cmd.cmd;
413 clientId = cmd.clientId;
415 /* process individual commands */
416 switch (command) {
417 /*
418 * Since cmd is a union of rcv and snd structs, don't write
419 * any snd elements before all rcv elements have been referenced
420 * (either saved in separate variables or passed to a function).
421 *
422 * cmd.cmd has already been saved in 'command'
423 * cmd.clientId has already been saved in 'clientId'
424 */
425 case LAD_CONNECT:
426 connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
427 cmd.args.connect.protocol, NULL);
429 break;
431 case LAD_DISCONNECT:
432 disconnectFromLAD(clientId);
434 break;
436 case LAD_IPC_GETCONFIG:
437 Ipc_getConfig(&rsp.ipcConfig);
438 break;
440 case LAD_NAMESERVER_SETUP:
441 LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
443 rsp.status = NameServer_setup();
445 LOG1(" status = %d\n", rsp.status)
446 LOG0("DONE\n")
448 break;
450 case LAD_NAMESERVER_DESTROY:
451 LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
453 rsp.status = NameServer_destroy();
455 LOG1(" status = %d\n", rsp.status)
456 LOG0("DONE\n")
458 break;
460 case LAD_NAMESERVER_PARAMS_INIT:
461 LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
463 NameServer_Params_init(&rsp.params);
465 LOG0("DONE\n")
467 break;
469 case LAD_NAMESERVER_CREATE:
470 LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
472 rsp.handle = NameServer_create(cmd.args.create.name,
473 &cmd.args.create.params);
475 LOG1(" handle = %p\n", rsp.handle)
476 LOG0("DONE\n")
478 break;
480 case LAD_NAMESERVER_DELETE:
481 LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
482 cmd.args.nsdelete.handle)
484 rsp.nsdelete.handle = cmd.args.nsdelete.handle;
485 rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
487 LOG1(" status = %d\n", rsp.nsdelete.status)
488 LOG0("DONE\n")
490 break;
492 case LAD_NAMESERVER_ADD:
493 LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
494 LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
495 LOG1(" 0x%x)...\n", cmd.args.add.len)
497 rsp.entryPtr = NameServer_add(
498 cmd.args.add.handle,
499 cmd.args.add.name,
500 cmd.args.add.buf,
501 cmd.args.add.len);
503 LOG1(" entryPtr = %p\n", rsp.entryPtr)
504 LOG0("DONE\n")
506 break;
508 case LAD_NAMESERVER_GET:
509 LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
510 cmd.args.get.handle, cmd.args.get.name)
511 LOG0(")...\n")
513 if (cmd.args.get.procId[0] == (UInt16)-1) {
514 procIdPtr = NULL;
515 }
516 else {
517 procIdPtr = cmd.args.get.procId;
518 }
519 rsp.get.status = NameServer_get(
520 cmd.args.get.handle,
521 cmd.args.get.name,
522 rsp.get.buf,
523 &cmd.args.get.len,
524 procIdPtr);
525 rsp.get.len = cmd.args.get.len;
527 LOG1(" value = 0x%x\n", rsp.get.len)
528 LOG1(" status = %d\n", rsp.get.status)
529 LOG0("DONE\n")
531 break;
533 case LAD_NAMESERVER_ADDUINT32:
534 LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
535 "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
536 cmd.args.addUInt32.name, cmd.args.addUInt32.val)
538 rsp.entryPtr = NameServer_addUInt32(
539 cmd.args.addUInt32.handle,
540 cmd.args.addUInt32.name,
541 cmd.args.addUInt32.val);
543 LOG1(" entryPtr = %p\n", rsp.entryPtr)
544 LOG0("DONE\n")
546 break;
548 case LAD_NAMESERVER_GETUINT32:
549 LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
550 "(%p, '%s')...\n", cmd.args.getUInt32.handle,
551 cmd.args.getUInt32.name)
553 if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
554 procIdPtr = NULL;
555 }
556 else {
557 procIdPtr = cmd.args.getUInt32.procId;
558 }
559 rsp.getUInt32.status = NameServer_getUInt32(
560 cmd.args.getUInt32.handle,
561 cmd.args.getUInt32.name,
562 &rsp.getUInt32.val,
563 procIdPtr);
565 LOG1(" value = 0x%x\n", rsp.getUInt32.val)
566 LOG1(" status = %d\n", rsp.getUInt32.status)
567 LOG0("DONE\n")
569 break;
571 case LAD_NAMESERVER_GETLOCAL:
572 rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
573 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
574 rsp.get.len = cmd.args.getLocal.len;
575 break;
577 case LAD_NAMESERVER_GETLOCALUINT32:
578 rsp.getUInt32.status = NameServer_getLocalUInt32(
579 cmd.args.getLocalUInt32.handle,
580 cmd.args.getLocalUInt32.name,
581 &rsp.getUInt32.val);
582 break;
584 case LAD_NAMESERVER_REMOVE:
585 LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
587 rsp.status = NameServer_remove(cmd.args.remove.handle,
588 cmd.args.remove.name);
590 LOG1(" status = %d\n", rsp.status)
591 LOG0("DONE\n")
593 break;
595 case LAD_NAMESERVER_REMOVEENTRY:
596 LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
598 rsp.status = NameServer_removeEntry(
599 cmd.args.removeEntry.handle,
600 cmd.args.removeEntry.entryPtr);
602 LOG1(" status = %d\n", rsp.status)
603 LOG0("DONE\n")
605 break;
607 case LAD_NAMESERVER_ATTACH:
608 rsp.status = NameServer_attach(cmd.args.attach.procId);
609 break;
611 case LAD_NAMESERVER_DETACH:
612 rsp.status = NameServer_detach(cmd.args.detach.procId);
613 break;
615 case LAD_MESSAGEQ_GETCONFIG:
616 LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
618 MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
619 rsp.messageQGetConfig.status = 0;
621 LOG1(" status = %d\n", rsp.messageQGetConfig.status)
622 LOG0("DONE\n")
624 break;
626 case LAD_MESSAGEQ_SETUP:
627 LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
629 rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
630 rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
632 LOG1(" status = %d\n", rsp.setup.status)
633 LOG0("DONE\n")
635 break;
637 case LAD_MESSAGEQ_DESTROY:
638 LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
640 rsp.status = MessageQ_destroy();
642 LOG1(" status = %d\n", rsp.status)
643 LOG0("DONE\n")
645 break;
647 case LAD_MESSAGEQ_CREATE:
648 LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
649 cmd.args.messageQCreate.name,
650 &cmd.args.messageQCreate.params);
652 tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
653 cmd.args.messageQCreate.name;
655 handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
656 rsp.messageQCreate.serverHandle = handle;
658 if (handle) {
659 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
660 MessageQ_setQueueOwner(handle, clientPID[clientId]);
661 rsp.messageQCreate.status = 0;
662 }
663 else {
664 rsp.messageQCreate.status = -1;
665 }
667 LOG1(" status = %d\n", rsp.messageQCreate.status)
668 LOG0("DONE\n")
670 break;
672 case LAD_MESSAGEQ_DELETE:
673 LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
675 rsp.messageQDelete.status =
676 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
678 LOG1(" status = %d\n", rsp.messageQDelete.status)
679 LOG0("DONE\n")
681 break;
683 case LAD_MESSAGEQ_MSGINIT:
684 LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
686 MessageQ_msgInit(&rsp.msgInit.msg);
687 rsp.msgInit.status = 0;
689 LOG1(" status = %d\n", rsp.msgInit.status)
690 LOG0("DONE\n")
692 break;
694 case LAD_MULTIPROC_GETCONFIG:
695 LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
697 MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
698 rsp.multiprocGetConfig.status = 0;
700 LOG1(" status = %d\n", rsp.multiprocGetConfig.status)
701 LOG0("DONE\n")
703 break;
705 #if defined(GATEMP_SUPPORT)
706 case LAD_GATEMP_ATTACH:
707 procId = cmd.args.attach.procId;
708 LOG1("LAD_GATEMP_ATTACH: calling GateMP_attach(%d)...\n", procId)
710 rsp.status = GateMP_attach(procId);
712 LOG1(" status = %d\n", rsp.status)
713 LOG0("DONE\n")
715 break;
717 case LAD_GATEMP_DETACH:
718 procId = cmd.args.detach.procId;
719 LOG1("LAD_GATEMP_DETACH: calling GateMP_detach(%d)...\n", procId)
721 rsp.status = GateMP_detach(procId);
723 LOG1(" status = %d\n", rsp.status)
724 LOG0("DONE\n")
726 break;
728 case LAD_GATEMP_START:
729 LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
731 rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
732 rsp.gateMPStart.status = GateMP_S_SUCCESS;
734 LOG1(" status = %d\n", rsp.gateMPStart.status)
735 LOG0("DONE\n")
737 break;
739 case LAD_GATEMP_GETNUMRESOURCES:
740 LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
742 rsp.gateMPGetNumResources.value = GateMP_getNumResources(
743 cmd.args.gateMPGetNumResources.type);
744 rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
746 LOG1(" status = %d\n", rsp.gateMPGetNumResources.status)
747 LOG0("DONE\n")
749 break;
751 case LAD_GATEMP_GETFREERESOURCE:
752 LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
754 rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
755 cmd.args.gateMPGetFreeResource.type);
756 rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
758 LOG1(" status = %d\n", rsp.gateMPGetFreeResource.status)
759 LOG0("DONE\n")
761 break;
763 case LAD_GATEMP_RELEASERESOURCE:
764 LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
766 rsp.gateMPReleaseResource.status = GateMP_releaseResource(
767 cmd.args.gateMPReleaseResource.id,
768 cmd.args.gateMPReleaseResource.type);
770 LOG1(" status = %d\n", rsp.gateMPReleaseResource.status)
771 LOG0("DONE\n")
773 break;
775 case LAD_GATEMP_ISSETUP:
776 LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
778 rsp.gateMPIsSetup.result = GateMP_isSetup();
779 rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
781 LOG1(" status = %d\n", rsp.gateMPIsSetup.status)
782 LOG0("DONE\n")
784 break;
786 case LAD_GATEHWSPINLOCK_GETCONFIG:
787 LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
789 GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
790 rsp.gateHWSpinlockGetConfig.status = 0;
792 LOG1(" status = %d\n", rsp.gateHWSpinlockGetConfig.status)
793 LOG0("DONE\n")
795 break;
796 #endif
798 case LAD_EXIT:
799 goto exitNow;
801 break;
803 default:
804 LOG1("\nUnrecognized command: 0x%x\n", command)
806 break;
807 }
809 switch (command) {
810 case LAD_CONNECT:
811 case LAD_DISCONNECT:
812 break;
814 case LAD_IPC_GETCONFIG:
815 case LAD_NAMESERVER_SETUP:
816 case LAD_NAMESERVER_DESTROY:
817 case LAD_NAMESERVER_PARAMS_INIT:
818 case LAD_NAMESERVER_CREATE:
819 case LAD_NAMESERVER_DELETE:
820 case LAD_NAMESERVER_ADD:
821 case LAD_NAMESERVER_GET:
822 case LAD_NAMESERVER_ADDUINT32:
823 case LAD_NAMESERVER_GETUINT32:
824 case LAD_NAMESERVER_GETLOCAL:
825 case LAD_NAMESERVER_GETLOCALUINT32:
826 case LAD_NAMESERVER_REMOVE:
827 case LAD_NAMESERVER_REMOVEENTRY:
828 case LAD_NAMESERVER_ATTACH:
829 case LAD_NAMESERVER_DETACH:
830 case LAD_MESSAGEQ_GETCONFIG:
831 case LAD_MESSAGEQ_SETUP:
832 case LAD_MESSAGEQ_DESTROY:
833 case LAD_MESSAGEQ_CREATE:
834 case LAD_MESSAGEQ_DELETE:
835 case LAD_MESSAGEQ_MSGINIT:
836 case LAD_MULTIPROC_GETCONFIG:
837 #if defined(GATEMP_SUPPORT)
838 case LAD_GATEMP_ATTACH:
839 case LAD_GATEMP_DETACH:
840 case LAD_GATEMP_START:
841 case LAD_GATEMP_GETNUMRESOURCES:
842 case LAD_GATEMP_GETFREERESOURCE:
843 case LAD_GATEMP_RELEASERESOURCE:
844 case LAD_GATEMP_ISSETUP:
845 case LAD_GATEHWSPINLOCK_GETCONFIG:
846 #endif
848 LOG0("Sending response...\n");
850 fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
851 fflush(responseFIFOFilePtr[clientId]);
853 break;
855 default:
856 break;
857 }
858 }
860 exitNow:
861 #if defined(GATEMP_SUPPORT)
862 if (gatempEnabled) {
863 GateMP_destroy();
864 NameServer_destroy();
865 }
866 #endif
867 if (logFile) {
868 LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
869 fclose(logPtr);
870 }
871 unlink(commandFIFOFile);
873 return(0);
875 }
878 /*
879 * ======== isDaemonRunning ========
880 */
881 static Bool isDaemonRunning(Char *pidName)
882 {
883 DIR *dir;
884 pid_t pid;
885 Int dirNum;
886 FILE *fp;
887 struct dirent * next;
888 Bool isRunning = FALSE;
889 Char filename [READ_BUF_SIZE];
890 Char buffer [READ_BUF_SIZE];
891 Char *bptr = buffer;
892 Char *name;
894 pid = getpid();
895 dir = opendir("/proc");
896 if (!dir) {
897 printf("Warning: Cannot open /proc filesystem\n");
898 return isRunning;
899 }
901 name = strrchr(pidName, '/');
902 if (name) {
903 pidName = (name + 1);
904 }
906 while ((next = readdir(dir)) != NULL) {
907 /* If it isn't a number, we don't want it */
908 if (!isdigit(*next->d_name)) {
909 continue;
910 }
912 dirNum = strtol(next->d_name, NULL, 10);
913 if (dirNum == pid) {
914 continue;
915 }
917 snprintf(filename, READ_BUF_SIZE, "/proc/%s/cmdline", next->d_name);
918 if (!(fp = fopen(filename, "r"))) {
919 continue;
920 }
921 if (fgets(buffer, READ_BUF_SIZE, fp) == NULL) {
922 fclose(fp);
923 continue;
924 }
925 fclose (fp);
927 name = strrchr(buffer, '/');
928 if (name && (name + 1)) {
929 bptr = name + 1;
930 }
931 else {
932 bptr = buffer;
933 }
935 /* Buffer should contain the entire command line */
936 if (strcmp(bptr, pidName) == 0) {
937 isRunning = TRUE;
938 break;
939 }
940 }
941 closedir (dir);
943 return isRunning;
944 }
946 /*
947 * ======== assignClientId ========
948 */
949 static LAD_ClientHandle assignClientId(Void)
950 {
951 Int clientId = -1;
952 Int i;
954 /* scan connection status flags to acquire a clientId */
955 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
956 /* if slot open then provisionally select this clientId */
957 if (clientConnected[i] == FALSE) {
958 clientId = i;
959 break;
960 }
961 }
963 return(clientId);
964 }
966 /*
967 * ======== cleanupFifos ========
968 */
969 static void cleanupFifos(Void)
970 {
971 DIR *dir;
972 struct dirent entry;
973 struct dirent *result;
974 size_t dirnamelen;
975 size_t maxcopy;
976 Char pathname[PATH_MAX];
977 Char *namep;
979 if ((dir = opendir(LAD_WORKINGDIR)) == NULL)
980 return;
982 dirnamelen = snprintf(pathname, sizeof(pathname), "%s/", LAD_WORKINGDIR);
983 if (dirnamelen >= sizeof(pathname)) {
984 closedir(dir);
985 return;
986 }
987 namep = pathname + dirnamelen;
988 maxcopy = PATH_MAX - dirnamelen;
989 while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
990 /* Delete old FIFOs left over */
991 if ((entry.d_type == DT_FIFO) && (strlen(entry.d_name) < maxcopy)) {
992 strncpy(namep, entry.d_name, maxcopy);
993 unlink(pathname);
994 }
995 }
996 closedir(dir);
997 }
999 /*
1000 * ======== cleanupDepartedClients ========
1001 */
1002 static Void cleanupDepartedClients(Void)
1003 {
1004 Int killStat;
1005 Int i;
1007 /* scan all connections to verify client processes still exist... */
1008 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
1010 /* if connected... */
1011 if (clientConnected[i] == TRUE) {
1013 /* check if the client process (PID) still exists */
1014 /*
1015 * NOTE - calling kill with signal value of 0 will perform
1016 * error checking, but not actually send a signal. Will use this
1017 * error check to see if PID still exists. An alternative was
1018 * to call getpgid. This worked, but is apparently limited to
1019 * USE_XOPEN_EXTENDED configurations.
1020 */
1021 killStat = kill(clientPID[i], 0);
1022 if ((killStat == -1) && (errno == ESRCH)) {
1024 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
1026 /* will always need to do the disconnect... */
1027 LOG0("\nDoing DISCONNECT on behalf of client...")
1028 doDisconnect(i);
1030 MessageQ_cleanupOwner(clientPID[i]);
1031 // NameServer_cleanupOwner(clientPID[i]);
1033 LOG0("DONE\n")
1034 }
1035 }
1036 }
1037 }
1040 /*
1041 * ======== connectToLAD ========
1042 */
1043 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
1044 {
1045 Int clientId = -1;
1046 Bool connectDenied = FALSE;
1047 Int status = LAD_SUCCESS;
1048 FILE * filePtr;
1049 Int statusIO;
1051 /*
1052 * TODO:L here, and everywhere parse FIFO strings: should
1053 * add full error checking for incomplete or corrupted
1054 * strings? Since LAD to ladclient comms are "closed", and
1055 * tested, the likelihood of problems seems very low.
1056 * But should still consider doing full error checking
1057 * and, hopefully, recovery.
1058 */
1059 LOG0("\nLAD_CONNECT: \n")
1060 LOG1(" client FIFO name = %s\n", clientName)
1061 LOG1(" client PID = %d\n", pid)
1063 /* first check for proper communication protocol */
1064 if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
1066 /* if no match then reject the request */
1067 LOG0(" ERROR: mismatch in communication protocol!\n")
1068 LOG1(" LAD protocol = %s\n", LAD_PROTOCOLVERSION)
1069 LOG1(" client protocol = %s\n", clientProto)
1070 status = LAD_INVALIDVERSION;
1072 /* set flag so know to close FIFO after response */
1073 connectDenied = TRUE;
1075 /* now jump forward a bit to send response */
1076 goto openResponseFIFO;
1077 }
1079 /* determine this client's ID */
1080 clientId = assignClientId();
1082 /* if failed to acquire an ID then exit early */
1083 if (clientId == -1) {
1084 LOG0(" no free handle; too many connections!\n")
1085 status = LAD_ACCESSDENIED;
1087 /* set flag so know to close FIFO after response */
1088 connectDenied = TRUE;
1089 }
1090 else {
1091 LOG1(" assigned client handle = %d\n", clientId)
1093 /* save the client's FIFO name for when disconnect */
1094 strcpy(clientFIFOName[clientId], clientName);
1095 }
1097 openResponseFIFO:
1099 /* create the dedicated response FIFO to the client */
1100 statusIO = mkfifo(clientName, 0777);
1101 if (statusIO != 0) {
1103 LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
1105 status = LAD_IOFAILURE;
1107 /* send no response; connection request will timeout */
1108 goto doneconnect;
1109 }
1111 LOG1(" FIFO %s created\n", clientName)
1113 /* set FIFO permissions to read/write */
1114 chmod(clientName, 0666);
1116 filePtr = fopen(clientName, "w");
1117 if (filePtr == NULL) {
1118 LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
1120 /* if failed open, still need to delete the FIFO */
1121 unlink(clientName);
1123 status = LAD_IOFAILURE;
1125 /* send no response; connection request will timeout */
1126 goto doneconnect;
1127 }
1129 LOG1(" FIFO %s opened for writing\n", clientName)
1131 /*
1132 * set "this client is connected" flag; this client ID is now "owned", and
1133 * is no longer provisional
1134 */
1135 if (connectDenied == FALSE) {
1136 responseFIFOFilePtr[clientId] = filePtr;
1137 clientPID[clientId] = pid;
1138 clientConnected[clientId] = TRUE;
1139 }
1141 rsp.connect.assignedId = clientId;
1142 rsp.status = status;
1144 /* put response to FIFO */
1145 fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
1146 fflush(filePtr);
1148 LOG0(" sent response\n")
1150 /* if connection was denied, must now close FIFO */
1151 if (connectDenied == TRUE) {
1152 LOG1(" connect denied; closing FIFO %s\n", clientName)
1153 fclose(filePtr);
1154 unlink(clientName);
1155 }
1157 LOG0("DONE\n")
1159 doneconnect:
1160 if (clientIdPtr != NULL) {
1161 *clientIdPtr = clientId;
1162 }
1164 return(status);
1165 }
1168 /*
1169 * ======== disconnectFromLAD ========
1170 */
1171 static Void disconnectFromLAD(Int clientId)
1172 {
1173 LOG0("\nLAD_DISCONNECT: ")
1175 LOG1("\n client handle = %x", clientId)
1176 doDisconnect(clientId);
1178 LOG0("DONE\n")
1180 return;
1181 }
1184 /*
1185 * ======== doDisconnect ========
1186 */
1187 static Void doDisconnect(Int clientId)
1188 {
1189 /* set "this client is not connected" flag */
1190 clientConnected[clientId] = FALSE;
1192 /* close and remove the response FIFO */
1193 LOG2("\n closing FIFO %s (filePtr=%p)\n",
1194 clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1195 fclose(responseFIFOFilePtr[clientId]);
1197 LOG1(" done, unlinking %s\n", clientFIFOName[clientId]);
1198 unlink(clientFIFOName[clientId]);
1199 }