1c7c7072e7a506b7aded1c82b3b7701b5ba34422
[ipc/ipcdev.git] / linux / src / daemon / lad.c
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[])
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);
869 /*
870  *  ======== assignClientId ========
871  */
872 static LAD_ClientHandle assignClientId(Void)
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);
889 /*
890  *  ======== cleanupFifos ========
891  */
892 static void cleanupFifos(Void)
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);
922 /*
923  *  ======== cleanupDepartedClients ========
924  */
925 static Void cleanupDepartedClients(Void)
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     }
963 /*
964  *  ======== connectToLAD ========
965  */
966 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
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);
1091 /*
1092  *  ======== disconnectFromLAD ========
1093  */
1094 static Void disconnectFromLAD(Int clientId)
1096     LOG0("\nLAD_DISCONNECT: ")
1098     LOG1("\n    client handle = %x", clientId)
1099     doDisconnect(clientId);
1101     LOG0("DONE\n")
1103     return;
1107 /*
1108  *  ======== doDisconnect ========
1109  */
1110 static Void doDisconnect(Int clientId)
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]);