758e09892f51f97ac841085045d2cbee414cd488
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 #ifndef DAEMON
65 #define DAEMON 1 /* 1 = run as a daemon; 0 = run as app */
66 #endif
68 #define READ_BUF_SIZE 50
70 Bool logFile = FALSE;
71 FILE *logPtr = NULL;
72 struct timeval start_tv;
74 static String commandFIFOFile = LAD_COMMANDFIFO;
75 static FILE *commandFIFOFilePtr = NULL;
77 #if defined(GATEMP_SUPPORT)
78 static Bool gatempEnabled = FALSE;
79 #endif
81 /* LAD client info arrays */
82 static Bool clientConnected[LAD_MAXNUMCLIENTS];
83 static UInt clientPID[LAD_MAXNUMCLIENTS];
84 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
85 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
87 /* local internal routines */
88 static Bool isDaemonRunning(Char *pidName);
89 static LAD_ClientHandle assignClientId(Void);
90 static Void cleanupFifos(Void);
91 static Void cleanupDepartedClients(Void);
92 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
93 static Void disconnectFromLAD(Int clientId);
94 static Void doDisconnect(Int clientId);
96 struct LAD_CommandObj cmd;
97 union LAD_ResponseObj rsp;
99 #define LAD_USAGE "\
100 Usage:\n\
101 lad_<platform> [options] \n\
102 \n\
103 Options:\n\
104 h : print this help message\n\
105 g : enable GateMP support \n\
106 l <logfile> : name of logfile for LAD\n\
107 n <nprocs> : total number of processors in the system\n\
108 p <oct value>: set LAD's directory permissions\n\
109 r <nreserve> : number of reserved queues\n\
110 s <synctype> : type of Ipc_ProcSync (ALL|PAIR|NONE)\n\
111 b <value> : Processor's base cluster id \n\
112 \n\
113 Examples:\n\
114 lad_<platform> -h\n\
115 lad_<platform> -l log.txt\n\
116 lad_<platform> -l log.txt -p 777\n\
117 lad_<platform> -g -l log.txt\n\
118 lad_<platform> -l log.txt -b 10\n\
119 \n"
121 /*
122 * ======== main ========
123 */
124 int main(int argc, char * argv[])
125 {
126 MessageQ_Handle handle;
127 Ipc_Config ipcCfg;
128 UInt16 *procIdPtr;
129 Int statusIO;
130 Int clientId;
131 Int command;
132 Int flags;
133 Int i;
134 Int n;
135 Int c;
136 #if defined(GATEMP_SUPPORT)
137 Int status;
138 UInt16 procId;
139 #endif
140 String tmpString;
141 #if DAEMON
142 pid_t pid;
143 pid_t sid;
144 #endif
146 /* change to LAD's root directory */
147 if ((chdir(LAD_ROOTDIR)) < 0) {
148 /* if can't change directory assume it needs to be created, do it */
149 if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
150 fprintf(stderr,
151 "\nERROR: Failed to create LAD's root directory!\n");
152 exit(EXIT_FAILURE);
153 }
154 }
156 #ifndef IPC_BUILDOS_ANDROID
157 if (isDaemonRunning(argv[0])) {
158 printf("Multiple instances of LAD are not supported!\n");
159 exit(EXIT_FAILURE);
160 }
161 #endif
163 /* change to LAD's working directory */
164 if ((chdir(LAD_WORKINGDIR)) < 0) {
166 /* if can't change directory assume it needs to be created, do it */
167 if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
168 fprintf(stderr,
169 "\nERROR: Failed to create LAD's working directory!\n");
170 exit(EXIT_FAILURE);
171 }
172 /* now change to the new directory */
173 if ((chdir(LAD_WORKINGDIR)) < 0) {
174 fprintf(stderr,
175 "\nERROR: Failed to change to LAD's working directory!\n");
176 exit(EXIT_FAILURE);
177 }
178 } else {
179 cleanupFifos();
180 }
182 /* process command line args */
183 while (1) {
184 c = getopt(argc, argv, "b:ghl:n:p:r:s:");
185 if (c == -1) {
186 break;
187 }
189 switch (c) {
190 case 'g':
191 #if defined(GATEMP_SUPPORT)
192 printf("\nGateMP support enabled on host\n");
193 gatempEnabled = TRUE;
194 #else
195 printf("\nGateMP is not supported for this device\n");
196 #endif
197 break;
198 case 'b':
199 printf("\nSet LAD's base cluster id to %s\n", optarg);
200 _MultiProc_cfg.id = atoi(optarg);
201 _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
202 break;
203 case 'h':
204 printf("%s", LAD_USAGE);
205 exit(0);
206 break;
207 case 'l':
208 logPtr = fopen(optarg, "w");
209 if (logPtr == NULL) {
210 fprintf(stderr, "\nERROR: unable to open log file %s\n",
211 optarg);
212 exit(EXIT_FAILURE);
213 }
214 else {
215 logFile = TRUE;
216 gettimeofday(&start_tv, NULL);
217 printf("\nOpened log file: %s\n", optarg);
218 /* close log file upon LAD termination */
219 flags = fcntl(fileno(logPtr), F_GETFD);
220 if (flags != -1) {
221 fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
222 }
223 }
224 break;
225 case 'n':
226 printf("\nSet LAD's number of processors to %s\n", optarg);
227 _MultiProc_cfg.numProcessors = atoi(optarg);
228 break;
229 case 'p':
230 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
231 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
232 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
233 break;
234 case 'r':
235 printf("\nSet LAD's number of reserved queues to %s\n", optarg);
236 _MessageQ_setNumReservedEntries(atoi(optarg));
237 break;
238 case 's':
239 printf("\nSet LAD's synchronization scheme to ProcSync_%s\n",
240 optarg);
242 Ipc_getConfig(&ipcCfg);
244 if (!strcmp(optarg, "ALL")) {
245 ipcCfg.procSync = Ipc_ProcSync_ALL;
246 }
247 else if (!strcmp(optarg, "PAIR")) {
248 ipcCfg.procSync = Ipc_ProcSync_PAIR;
249 }
250 else if (!strcmp(optarg, "NONE")) {
251 ipcCfg.procSync = Ipc_ProcSync_NONE;
252 }
253 else {
254 fprintf(stderr,
255 "Error: bad synchronization specified, must be "
256 "ALL|PAIR|NONE\n");
257 exit(EXIT_FAILURE);
258 }
260 Ipc_setConfig(&ipcCfg);
261 break;
262 default:
263 fprintf (stderr, "\nUnrecognized argument\n");
264 exit(EXIT_FAILURE);
265 }
266 }
268 /* Check to ensure id and baseId are not invalid */
269 printf ("\nnumProcessors = %d id = %d baseId = %d\n",
270 _MultiProc_cfg.numProcessors, _MultiProc_cfg.id,
271 _MultiProc_cfg.baseIdOfCluster);
273 if (_MultiProc_cfg.id == 0xFFFF ||
274 _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
275 fprintf(stderr, "\nBase cluster id is set to an INVALID value\n");
276 fprintf(stderr,
277 "Use -b option to set value or modify the MultiProcCfg file\n"
278 );
279 exit(EXIT_FAILURE);
280 }
281 if ((_MultiProc_cfg.baseIdOfCluster + _MultiProc_cfg.numProcsInCluster) >
282 _MultiProc_cfg.numProcessors) {
283 fprintf(stderr,
284 "\nNumber of processors (%d) must be >= base cluster id + "
285 "number of processors in cluster (%d + %d)\n",
286 _MultiProc_cfg.numProcessors, _MultiProc_cfg.baseIdOfCluster,
287 _MultiProc_cfg.numProcsInCluster);
288 exit(EXIT_FAILURE);
289 }
292 #if DAEMON
293 /* fork off a child process */
294 pid = fork();
296 /* if fork of child failed then exit immediately; no child created */
297 if (pid < 0) {
298 fprintf(stderr, "\nERROR: Failed to fork child process!");
299 exit(EXIT_FAILURE);
300 }
302 /* if pid > 0 this is the parent; time to die ... */
303 if (pid > 0) {
304 printf("\nSpawned daemon: %s\n\n", argv[0]);
305 exit(EXIT_SUCCESS);
306 }
308 /* child continues from here (pid == 0) ... */
310 /* change file mode mask */
311 umask(0);
313 /* create new session ID for the child */
314 sid = setsid();
316 /* exit with failure code if failed to get session ID... */
317 if (sid < 0) {
318 fprintf(stderr, "\nERROR: Failed to acquire new session ID!");
319 exit(EXIT_FAILURE);
320 }
322 /* disassociate from the standard file descriptors */
323 close(STDIN_FILENO);
324 close(STDOUT_FILENO);
325 close(STDERR_FILENO);
327 #endif
329 LOG0("\nInitializing LAD... ")
331 /* TODO:L make sure LAD is not already running? */
333 /* initialize client info arrays */
334 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
335 clientConnected[i] = FALSE;
336 responseFIFOFilePtr[i] = NULL;
337 }
339 /* if command FIFO exists from previous LAD session delete it now */
340 unlink(commandFIFOFile);
342 /* create command FIFO */
343 statusIO = mkfifo(commandFIFOFile, 0777);
344 if (statusIO != 0) {
345 LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
346 errno)
347 return(0);
348 }
350 /* set FIFO permissions to read/write */
351 chmod(commandFIFOFile, 0666);
353 /* Setup modules relevant for GateMP if necessary */
354 #if defined(GATEMP_SUPPORT)
355 if (gatempEnabled) {
356 /* Set up NameServer for resource manager process */
357 status = NameServer_setup();
358 if (status < 0) {
359 LOG0("\nERROR: unable to setup NameServer\n")
360 return(0);
361 }
363 status = GateHWSpinlock_start();
364 if (status < 0) {
365 LOG0("\nERROR: unable to start GateHWSpinlock\n");
366 return(0);
367 }
369 /* Set up GateMP */
370 status = GateMP_setup();
371 if (status < 0) {
372 LOG0("\nERROR: unable to setup GateMP\n")
373 NameServer_destroy();
374 return(0);
375 }
376 }
377 #endif
379 opencommandFIFO:
381 /* now open file for FIFO - will block until writer arrives... */
382 LOG1("\n opening FIFO: %s\n", commandFIFOFile)
383 commandFIFOFilePtr = fopen(commandFIFOFile, "r");
384 if (commandFIFOFilePtr == NULL) {
385 LOG0("\nERROR: unable to open command FIFO\n")
386 unlink(commandFIFOFile);
387 #if defined(GATEMP_SUPPORT)
388 if (gatempEnabled) {
389 GateMP_destroy();
390 NameServer_destroy();
391 }
392 #endif
393 return(0);
394 }
396 /* COMMAND PROCESSING LOOP */
397 while (1) {
398 LOG0("Retrieving command...\n")
400 /* read the next command packet */
401 n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
403 /*
404 * if last client closes FIFO then it must be closed and reopened ...
405 */
406 if (!n) {
407 LOG1(" EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
408 fclose(commandFIFOFilePtr);
410 goto opencommandFIFO;
411 }
413 /* cleanup for any connected/started clients that have departed */
414 cleanupDepartedClients();
416 command = cmd.cmd;
417 clientId = cmd.clientId;
419 /* process individual commands */
420 switch (command) {
421 /*
422 * Since cmd is a union of rcv and snd structs, don't write
423 * any snd elements before all rcv elements have been referenced
424 * (either saved in separate variables or passed to a function).
425 *
426 * cmd.cmd has already been saved in 'command'
427 * cmd.clientId has already been saved in 'clientId'
428 */
429 case LAD_CONNECT:
430 connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
431 cmd.args.connect.protocol, NULL);
433 break;
435 case LAD_DISCONNECT:
436 disconnectFromLAD(clientId);
438 break;
440 case LAD_IPC_GETCONFIG:
441 Ipc_getConfig(&rsp.ipcConfig);
442 break;
444 case LAD_NAMESERVER_SETUP:
445 LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
447 rsp.status = NameServer_setup();
449 LOG1(" status = %d\n", rsp.status)
450 LOG0("DONE\n")
452 break;
454 case LAD_NAMESERVER_DESTROY:
455 LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
457 rsp.status = NameServer_destroy();
459 LOG1(" status = %d\n", rsp.status)
460 LOG0("DONE\n")
462 break;
464 case LAD_NAMESERVER_PARAMS_INIT:
465 LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
467 NameServer_Params_init(&rsp.params);
469 LOG0("DONE\n")
471 break;
473 case LAD_NAMESERVER_CREATE:
474 LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
476 rsp.handle = NameServer_create(cmd.args.create.name,
477 &cmd.args.create.params);
479 LOG1(" handle = %p\n", rsp.handle)
480 LOG0("DONE\n")
482 break;
484 case LAD_NAMESERVER_DELETE:
485 LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
486 cmd.args.nsdelete.handle)
488 rsp.nsdelete.handle = cmd.args.nsdelete.handle;
489 rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
491 LOG1(" status = %d\n", rsp.nsdelete.status)
492 LOG0("DONE\n")
494 break;
496 case LAD_NAMESERVER_ADD:
497 LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
498 LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
499 LOG1(" 0x%x)...\n", cmd.args.add.len)
501 rsp.entryPtr = NameServer_add(
502 cmd.args.add.handle,
503 cmd.args.add.name,
504 cmd.args.add.buf,
505 cmd.args.add.len);
507 LOG1(" entryPtr = %p\n", rsp.entryPtr)
508 LOG0("DONE\n")
510 break;
512 case LAD_NAMESERVER_GET:
513 LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
514 cmd.args.get.handle, cmd.args.get.name)
515 LOG0(")...\n")
517 if (cmd.args.get.procId[0] == (UInt16)-1) {
518 procIdPtr = NULL;
519 }
520 else {
521 procIdPtr = cmd.args.get.procId;
522 }
523 rsp.get.status = NameServer_get(
524 cmd.args.get.handle,
525 cmd.args.get.name,
526 rsp.get.buf,
527 &cmd.args.get.len,
528 procIdPtr);
529 rsp.get.len = cmd.args.get.len;
531 LOG1(" value = 0x%x\n", rsp.get.len)
532 LOG1(" status = %d\n", rsp.get.status)
533 LOG0("DONE\n")
535 break;
537 case LAD_NAMESERVER_ADDUINT32:
538 LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
539 "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
540 cmd.args.addUInt32.name, cmd.args.addUInt32.val)
542 rsp.entryPtr = NameServer_addUInt32(
543 cmd.args.addUInt32.handle,
544 cmd.args.addUInt32.name,
545 cmd.args.addUInt32.val);
547 LOG1(" entryPtr = %p\n", rsp.entryPtr)
548 LOG0("DONE\n")
550 break;
552 case LAD_NAMESERVER_GETUINT32:
553 LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
554 "(%p, '%s')...\n", cmd.args.getUInt32.handle,
555 cmd.args.getUInt32.name)
557 if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
558 procIdPtr = NULL;
559 }
560 else {
561 procIdPtr = cmd.args.getUInt32.procId;
562 }
563 rsp.getUInt32.status = NameServer_getUInt32(
564 cmd.args.getUInt32.handle,
565 cmd.args.getUInt32.name,
566 &rsp.getUInt32.val,
567 procIdPtr);
569 LOG1(" value = 0x%x\n", rsp.getUInt32.val)
570 LOG1(" status = %d\n", rsp.getUInt32.status)
571 LOG0("DONE\n")
573 break;
575 case LAD_NAMESERVER_GETLOCAL:
576 rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
577 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
578 rsp.get.len = cmd.args.getLocal.len;
579 break;
581 case LAD_NAMESERVER_GETLOCALUINT32:
582 rsp.getUInt32.status = NameServer_getLocalUInt32(
583 cmd.args.getLocalUInt32.handle,
584 cmd.args.getLocalUInt32.name,
585 &rsp.getUInt32.val);
586 break;
588 case LAD_NAMESERVER_REMOVE:
589 LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
591 rsp.status = NameServer_remove(cmd.args.remove.handle,
592 cmd.args.remove.name);
594 LOG1(" status = %d\n", rsp.status)
595 LOG0("DONE\n")
597 break;
599 case LAD_NAMESERVER_REMOVEENTRY:
600 LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
602 rsp.status = NameServer_removeEntry(
603 cmd.args.removeEntry.handle,
604 cmd.args.removeEntry.entryPtr);
606 LOG1(" status = %d\n", rsp.status)
607 LOG0("DONE\n")
609 break;
611 case LAD_NAMESERVER_ATTACH:
612 rsp.status = NameServer_attach(cmd.args.attach.procId);
613 break;
615 case LAD_NAMESERVER_DETACH:
616 rsp.status = NameServer_detach(cmd.args.detach.procId);
617 break;
619 case LAD_MESSAGEQ_GETCONFIG:
620 LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
622 MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
623 rsp.messageQGetConfig.status = 0;
625 LOG1(" status = %d\n", rsp.messageQGetConfig.status)
626 LOG0("DONE\n")
628 break;
630 case LAD_MESSAGEQ_SETUP:
631 LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
633 rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
634 rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
636 LOG1(" status = %d\n", rsp.setup.status)
637 LOG0("DONE\n")
639 break;
641 case LAD_MESSAGEQ_DESTROY:
642 LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
644 rsp.status = MessageQ_destroy();
646 LOG1(" status = %d\n", rsp.status)
647 LOG0("DONE\n")
649 break;
651 case LAD_MESSAGEQ_CREATE:
652 LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
653 cmd.args.messageQCreate.name,
654 &cmd.args.messageQCreate.params);
656 tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
657 cmd.args.messageQCreate.name;
659 handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
660 rsp.messageQCreate.serverHandle = handle;
662 if (handle) {
663 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
664 MessageQ_setQueueOwner(handle, clientPID[clientId]);
665 rsp.messageQCreate.status = 0;
666 }
667 else {
668 rsp.messageQCreate.status = -1;
669 }
671 LOG1(" status = %d\n", rsp.messageQCreate.status)
672 LOG0("DONE\n")
674 break;
676 case LAD_MESSAGEQ_ANNOUNCE:
677 LOG2("LAD_MESSAGEQ_ANNOUNCE: calling MessageQ_announce(%p, %p)...\n",
678 cmd.args.messageQAnnounce.name,
679 cmd.args.messageQAnnounce.serverHandle);
681 tmpString = (cmd.args.messageQAnnounce.name[0] == '\0') ? NULL :
682 cmd.args.messageQAnnounce.name;
684 rsp.messageQAnnounce.status =
685 MessageQ_announce(tmpString, (MessageQ_Handle *)&cmd.args.messageQAnnounce.serverHandle);
687 LOG1(" status = %d\n", rsp.messageQAnnounce.status)
688 LOG0("DONE\n")
690 break;
691 case LAD_MESSAGEQ_DELETE:
692 LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
694 rsp.messageQDelete.status =
695 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
697 LOG1(" status = %d\n", rsp.messageQDelete.status)
698 LOG0("DONE\n")
700 break;
702 case LAD_MESSAGEQ_MSGINIT:
703 LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
705 MessageQ_msgInit(&rsp.msgInit.msg);
706 rsp.msgInit.status = 0;
708 LOG1(" status = %d\n", rsp.msgInit.status)
709 LOG0("DONE\n")
711 break;
713 case LAD_MULTIPROC_GETCONFIG:
714 LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
716 MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
717 rsp.multiprocGetConfig.status = 0;
719 LOG1(" status = %d\n", rsp.multiprocGetConfig.status)
720 LOG0("DONE\n")
722 break;
724 #if defined(GATEMP_SUPPORT)
725 case LAD_GATEMP_ATTACH:
726 procId = cmd.args.attach.procId;
727 LOG1("LAD_GATEMP_ATTACH: calling GateMP_attach(%d)...\n", procId)
729 rsp.status = GateMP_attach(procId);
731 LOG1(" status = %d\n", rsp.status)
732 LOG0("DONE\n")
734 break;
736 case LAD_GATEMP_DETACH:
737 procId = cmd.args.detach.procId;
738 LOG1("LAD_GATEMP_DETACH: calling GateMP_detach(%d)...\n", procId)
740 rsp.status = GateMP_detach(procId);
742 LOG1(" status = %d\n", rsp.status)
743 LOG0("DONE\n")
745 break;
747 case LAD_GATEMP_START:
748 LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
750 rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
751 rsp.gateMPStart.status = GateMP_S_SUCCESS;
753 LOG1(" status = %d\n", rsp.gateMPStart.status)
754 LOG0("DONE\n")
756 break;
758 case LAD_GATEMP_GETNUMRESOURCES:
759 LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
761 rsp.gateMPGetNumResources.value = GateMP_getNumResources(
762 cmd.args.gateMPGetNumResources.type);
763 rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
765 LOG1(" status = %d\n", rsp.gateMPGetNumResources.status)
766 LOG0("DONE\n")
768 break;
770 case LAD_GATEMP_GETFREERESOURCE:
771 LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
773 rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
774 cmd.args.gateMPGetFreeResource.type);
775 rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
777 LOG1(" status = %d\n", rsp.gateMPGetFreeResource.status)
778 LOG0("DONE\n")
780 break;
782 case LAD_GATEMP_RELEASERESOURCE:
783 LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
785 rsp.gateMPReleaseResource.status = GateMP_releaseResource(
786 cmd.args.gateMPReleaseResource.id,
787 cmd.args.gateMPReleaseResource.type);
789 LOG1(" status = %d\n", rsp.gateMPReleaseResource.status)
790 LOG0("DONE\n")
792 break;
794 case LAD_GATEMP_ISSETUP:
795 LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
797 rsp.gateMPIsSetup.result = GateMP_isSetup();
798 rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
800 LOG1(" status = %d\n", rsp.gateMPIsSetup.status)
801 LOG0("DONE\n")
803 break;
805 case LAD_GATEHWSPINLOCK_GETCONFIG:
806 LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
808 GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
809 rsp.gateHWSpinlockGetConfig.status = 0;
811 LOG1(" status = %d\n", rsp.gateHWSpinlockGetConfig.status)
812 LOG0("DONE\n")
814 break;
815 #endif
817 case LAD_EXIT:
818 goto exitNow;
820 break;
822 default:
823 LOG1("\nUnrecognized command: 0x%x\n", command)
825 break;
826 }
828 switch (command) {
829 case LAD_CONNECT:
830 case LAD_DISCONNECT:
831 break;
833 case LAD_IPC_GETCONFIG:
834 case LAD_NAMESERVER_SETUP:
835 case LAD_NAMESERVER_DESTROY:
836 case LAD_NAMESERVER_PARAMS_INIT:
837 case LAD_NAMESERVER_CREATE:
838 case LAD_NAMESERVER_DELETE:
839 case LAD_NAMESERVER_ADD:
840 case LAD_NAMESERVER_GET:
841 case LAD_NAMESERVER_ADDUINT32:
842 case LAD_NAMESERVER_GETUINT32:
843 case LAD_NAMESERVER_GETLOCAL:
844 case LAD_NAMESERVER_GETLOCALUINT32:
845 case LAD_NAMESERVER_REMOVE:
846 case LAD_NAMESERVER_REMOVEENTRY:
847 case LAD_NAMESERVER_ATTACH:
848 case LAD_NAMESERVER_DETACH:
849 case LAD_MESSAGEQ_GETCONFIG:
850 case LAD_MESSAGEQ_SETUP:
851 case LAD_MESSAGEQ_DESTROY:
852 case LAD_MESSAGEQ_CREATE:
853 case LAD_MESSAGEQ_ANNOUNCE:
854 case LAD_MESSAGEQ_DELETE:
855 case LAD_MESSAGEQ_MSGINIT:
856 case LAD_MULTIPROC_GETCONFIG:
857 #if defined(GATEMP_SUPPORT)
858 case LAD_GATEMP_ATTACH:
859 case LAD_GATEMP_DETACH:
860 case LAD_GATEMP_START:
861 case LAD_GATEMP_GETNUMRESOURCES:
862 case LAD_GATEMP_GETFREERESOURCE:
863 case LAD_GATEMP_RELEASERESOURCE:
864 case LAD_GATEMP_ISSETUP:
865 case LAD_GATEHWSPINLOCK_GETCONFIG:
866 #endif
868 LOG0("Sending response...\n");
870 fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
871 fflush(responseFIFOFilePtr[clientId]);
873 break;
875 default:
876 break;
877 }
878 }
880 exitNow:
881 #if defined(GATEMP_SUPPORT)
882 if (gatempEnabled) {
883 GateMP_destroy();
884 NameServer_destroy();
885 }
886 #endif
887 if (logFile) {
888 LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
889 fclose(logPtr);
890 }
891 unlink(commandFIFOFile);
893 return(0);
895 }
898 /*
899 * ======== isDaemonRunning ========
900 */
901 static Bool isDaemonRunning(Char *pidName)
902 {
903 DIR *dir;
904 pid_t pid;
905 Int dirNum;
906 FILE *fp;
907 struct dirent * next;
908 Bool isRunning = FALSE;
909 Char filename [READ_BUF_SIZE];
910 Char buffer [READ_BUF_SIZE];
911 Char *bptr = buffer;
912 Char *name;
914 pid = getpid();
915 dir = opendir("/proc");
916 if (!dir) {
917 printf("Warning: Cannot open /proc filesystem\n");
918 return isRunning;
919 }
921 name = strrchr(pidName, '/');
922 if (name) {
923 pidName = (name + 1);
924 }
926 while ((next = readdir(dir)) != NULL) {
927 /* If it isn't a number, we don't want it */
928 if (!isdigit(*next->d_name)) {
929 continue;
930 }
932 dirNum = strtol(next->d_name, NULL, 10);
933 if (dirNum == pid) {
934 continue;
935 }
937 snprintf(filename, READ_BUF_SIZE, "/proc/%s/cmdline", next->d_name);
938 if (!(fp = fopen(filename, "r"))) {
939 continue;
940 }
941 if (fgets(buffer, READ_BUF_SIZE, fp) == NULL) {
942 fclose(fp);
943 continue;
944 }
945 fclose (fp);
947 name = strrchr(buffer, '/');
948 if (name && (name + 1)) {
949 bptr = name + 1;
950 }
951 else {
952 bptr = buffer;
953 }
955 /* Buffer should contain the entire command line */
956 if (strcmp(bptr, pidName) == 0) {
957 isRunning = TRUE;
958 break;
959 }
960 }
961 closedir (dir);
963 return isRunning;
964 }
966 /*
967 * ======== assignClientId ========
968 */
969 static LAD_ClientHandle assignClientId(Void)
970 {
971 Int clientId = -1;
972 Int i;
974 /* scan connection status flags to acquire a clientId */
975 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
976 /* if slot open then provisionally select this clientId */
977 if (clientConnected[i] == FALSE) {
978 clientId = i;
979 break;
980 }
981 }
983 return(clientId);
984 }
986 /*
987 * ======== cleanupFifos ========
988 */
989 static void cleanupFifos(Void)
990 {
991 DIR *dir;
992 struct dirent entry;
993 struct dirent *result;
994 size_t dirnamelen;
995 size_t maxcopy;
996 Char pathname[PATH_MAX];
997 Char *namep;
999 if ((dir = opendir(LAD_WORKINGDIR)) == NULL)
1000 return;
1002 dirnamelen = snprintf(pathname, sizeof(pathname), "%s/", LAD_WORKINGDIR);
1003 if (dirnamelen >= sizeof(pathname)) {
1004 closedir(dir);
1005 return;
1006 }
1007 namep = pathname + dirnamelen;
1008 maxcopy = PATH_MAX - dirnamelen;
1009 while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
1010 /* Delete old FIFOs left over */
1011 if ((entry.d_type == DT_FIFO) && (strlen(entry.d_name) < maxcopy)) {
1012 strncpy(namep, entry.d_name, maxcopy);
1013 unlink(pathname);
1014 }
1015 }
1016 closedir(dir);
1017 }
1019 /*
1020 * ======== cleanupDepartedClients ========
1021 */
1022 static Void cleanupDepartedClients(Void)
1023 {
1024 Int killStat;
1025 Int i;
1027 /* scan all connections to verify client processes still exist... */
1028 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
1030 /* if connected... */
1031 if (clientConnected[i] == TRUE) {
1033 /* check if the client process (PID) still exists */
1034 /*
1035 * NOTE - calling kill with signal value of 0 will perform
1036 * error checking, but not actually send a signal. Will use this
1037 * error check to see if PID still exists. An alternative was
1038 * to call getpgid. This worked, but is apparently limited to
1039 * USE_XOPEN_EXTENDED configurations.
1040 */
1041 killStat = kill(clientPID[i], 0);
1042 if ((killStat == -1) && (errno == ESRCH)) {
1044 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
1046 /* will always need to do the disconnect... */
1047 LOG0("\nDoing DISCONNECT on behalf of client...")
1048 doDisconnect(i);
1050 MessageQ_cleanupOwner(clientPID[i]);
1051 // NameServer_cleanupOwner(clientPID[i]);
1053 LOG0("DONE\n")
1054 }
1055 }
1056 }
1057 }
1060 /*
1061 * ======== connectToLAD ========
1062 */
1063 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
1064 {
1065 Int clientId = -1;
1066 Bool connectDenied = FALSE;
1067 Int status = LAD_SUCCESS;
1068 FILE * filePtr;
1069 Int statusIO;
1071 /*
1072 * TODO:L here, and everywhere parse FIFO strings: should
1073 * add full error checking for incomplete or corrupted
1074 * strings? Since LAD to ladclient comms are "closed", and
1075 * tested, the likelihood of problems seems very low.
1076 * But should still consider doing full error checking
1077 * and, hopefully, recovery.
1078 */
1079 LOG0("\nLAD_CONNECT: \n")
1080 LOG1(" client FIFO name = %s\n", clientName)
1081 LOG1(" client PID = %d\n", pid)
1083 /* first check for proper communication protocol */
1084 if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
1086 /* if no match then reject the request */
1087 LOG0(" ERROR: mismatch in communication protocol!\n")
1088 LOG1(" LAD protocol = %s\n", LAD_PROTOCOLVERSION)
1089 LOG1(" client protocol = %s\n", clientProto)
1090 status = LAD_INVALIDVERSION;
1092 /* set flag so know to close FIFO after response */
1093 connectDenied = TRUE;
1095 /* now jump forward a bit to send response */
1096 goto openResponseFIFO;
1097 }
1099 /* determine this client's ID */
1100 clientId = assignClientId();
1102 /* if failed to acquire an ID then exit early */
1103 if (clientId == -1) {
1104 LOG0(" no free handle; too many connections!\n")
1105 status = LAD_ACCESSDENIED;
1107 /* set flag so know to close FIFO after response */
1108 connectDenied = TRUE;
1109 }
1110 else {
1111 LOG1(" assigned client handle = %d\n", clientId)
1113 /* save the client's FIFO name for when disconnect */
1114 strcpy(clientFIFOName[clientId], clientName);
1115 }
1117 openResponseFIFO:
1119 /* create the dedicated response FIFO to the client */
1120 statusIO = mkfifo(clientName, 0777);
1121 if (statusIO != 0) {
1123 LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
1125 status = LAD_IOFAILURE;
1127 /* send no response; connection request will timeout */
1128 goto doneconnect;
1129 }
1131 LOG1(" FIFO %s created\n", clientName)
1133 /* set FIFO permissions to read/write */
1134 chmod(clientName, 0666);
1136 filePtr = fopen(clientName, "w");
1137 if (filePtr == NULL) {
1138 LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
1140 /* if failed open, still need to delete the FIFO */
1141 unlink(clientName);
1143 status = LAD_IOFAILURE;
1145 /* send no response; connection request will timeout */
1146 goto doneconnect;
1147 }
1149 LOG1(" FIFO %s opened for writing\n", clientName)
1151 /*
1152 * set "this client is connected" flag; this client ID is now "owned", and
1153 * is no longer provisional
1154 */
1155 if (connectDenied == FALSE) {
1156 responseFIFOFilePtr[clientId] = filePtr;
1157 clientPID[clientId] = pid;
1158 clientConnected[clientId] = TRUE;
1159 }
1161 rsp.connect.assignedId = clientId;
1162 rsp.status = status;
1164 /* put response to FIFO */
1165 fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
1166 fflush(filePtr);
1168 LOG0(" sent response\n")
1170 /* if connection was denied, must now close FIFO */
1171 if (connectDenied == TRUE) {
1172 LOG1(" connect denied; closing FIFO %s\n", clientName)
1173 fclose(filePtr);
1174 unlink(clientName);
1175 }
1177 LOG0("DONE\n")
1179 doneconnect:
1180 if (clientIdPtr != NULL) {
1181 *clientIdPtr = clientId;
1182 }
1184 return(status);
1185 }
1188 /*
1189 * ======== disconnectFromLAD ========
1190 */
1191 static Void disconnectFromLAD(Int clientId)
1192 {
1193 LOG0("\nLAD_DISCONNECT: ")
1195 LOG1("\n client handle = %x", clientId)
1196 doDisconnect(clientId);
1198 LOG0("DONE\n")
1200 return;
1201 }
1204 /*
1205 * ======== doDisconnect ========
1206 */
1207 static Void doDisconnect(Int clientId)
1208 {
1209 /* set "this client is not connected" flag */
1210 clientConnected[clientId] = FALSE;
1212 /* close and remove the response FIFO */
1213 LOG2("\n closing FIFO %s (filePtr=%p)\n",
1214 clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1215 fclose(responseFIFOFilePtr[clientId]);
1217 LOG1(" done, unlinking %s\n", clientFIFOName[clientId]);
1218 unlink(clientFIFOName[clientId]);
1219 }