New MultiProc API to update processor mapping
[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>
49 #include <ti/ipc/MessageQ.h>
50 #include <_MessageQ.h>
51 #include <ti/ipc/NameServer.h>
52 #include <_NameServer.h>
53 #include <ti/ipc/GateMP.h>
54 #include <_GateMP_daemon.h>
55 #include <_MultiProc.h>
57 #include <GateHWSpinlock.h>
59 #include <ladclient.h>
60 #include <_lad.h>
62 #define DAEMON        1           /* 1 = run as a daemon; 0 = run as app */
64 Bool logFile = FALSE;
65 FILE *logPtr = NULL;
66 struct timeval start_tv;
68 static String commandFIFOFile = LAD_COMMANDFIFO;
69 static FILE *commandFIFOFilePtr = NULL;
71 #if defined(GATEMP_SUPPORT)
72 static Bool gatempEnabled = FALSE;
73 #endif
75 /* LAD client info arrays */
76 static Bool clientConnected[LAD_MAXNUMCLIENTS];
77 static UInt clientPID[LAD_MAXNUMCLIENTS];
78 static Char clientFIFOName[LAD_MAXNUMCLIENTS][LAD_MAXLENGTHFIFONAME];
79 static FILE * responseFIFOFilePtr[LAD_MAXNUMCLIENTS];
81 /* local internal routines */
82 static LAD_ClientHandle assignClientId(Void);
83 static Void cleanupDepartedClients(Void);
84 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr);
85 static Void disconnectFromLAD(Int clientId);
86 static Void doDisconnect(Int clientId);
88 struct LAD_CommandObj cmd;
89 union LAD_ResponseObj rsp;
91 #define LAD_USAGE "\
92 Usage:\n\
93     lad_<platform> [options] \n\
94 \n\
95 Options:\n\
96     h            : print this help message\n\
97     g            : enable GateMP support \n\
98     l <logfile>  : name of logfile for LAD\n\
99     p <oct value>: set LAD's directory permissions\n\
100     b <value>    : Processor's base cluster id \n\
101 \n\
102 Examples:\n\
103     lad_<platform> -h\n\
104     lad_<platform> -l log.txt\n\
105     lad_<platform> -l log.txt -p 777\n\
106     lad_<platform> -g -l log.txt\n\
107     lad_<platform> -l log.txt -b 10\n\
108 \n"
110 /*
111  *  ======== main ========
112  */
113 int main(int argc, char * argv[])
115     MessageQ_Handle handle;
116     UInt16 *procIdPtr;
117     Int statusIO;
118     Int clientId;
119     Int command;
120     Int flags;
121     Int i;
122     Int n;
123     Int c;
124 #if defined(GATEMP_SUPPORT)
125     Int status;
126 #endif
127     String tmpString;
128 #if DAEMON
129     pid_t pid;
130     pid_t sid;
131 #endif
133     /* change to LAD's root directory */
134     if ((chdir(LAD_ROOTDIR)) < 0) {
135         /* if can't change directory assume it needs to be created, do it */
136         if ((mkdir(LAD_ROOTDIR, 0666)) < 0) {
137             printf("\nERROR: Failed to create LAD's root directory!\n");
138             exit(EXIT_FAILURE);
139         }
140     }
142     /* change to LAD's working directory */
143     if ((chdir(LAD_WORKINGDIR)) < 0) {
145         /* if can't change directory assume it needs to be created, do it */
146         if ((mkdir(LAD_WORKINGDIR, 0666)) < 0) {
147             printf("\nERROR: Failed to create LAD's working directory!\n");
148             exit(EXIT_FAILURE);
149         }
150         /* now change to the new directory */
151         if ((chdir(LAD_WORKINGDIR)) < 0) {
152             printf("\nERROR: Failed to change to LAD's working directory!\n");
153             exit(EXIT_FAILURE);
154         }
155     }
157     /* process command line args */
158     while (1) {
159         c = getopt(argc, argv, "b:ghl:p:");
160         if (c == -1) {
161             break;
162         }
164         switch (c) {
165             case 'g':
166 #if defined(GATEMP_SUPPORT)
167                 printf("\nGateMP support enabled on host\n");
168                 gatempEnabled = TRUE;
169 #else
170                 printf("\nGateMP is not supported for this device\n");
171 #endif
172                 break;
173             case 'b':
174                 if (_MultiProc_cfg.id == 0xFFFF &&
175                     _MultiProc_cfg.baseIdOfCluster == 0xFFFF) {
176                     printf("\nSetting base cluster id to %s\n", optarg);
177                     _MultiProc_cfg.id = atoi(optarg);
178                     _MultiProc_cfg.baseIdOfCluster = atoi(optarg);
179                 }
180                 else {
181                    printf("\nBase cluster id in the MultiProcCfg file must be\n"
182                     "set to MultiProc_INVALIDID(0xFFFF) when using -b option\n");
183                    exit(EXIT_FAILURE);
184                 }
185                 break;
186             case 'h':
187                 printf("%s", LAD_USAGE);
188                 exit(0);
189                 break;
190             case 'l':
191                 logPtr = fopen(optarg, "w");
192                 if (logPtr == NULL) {
193                     printf("\nERROR: unable to open log file %s\n", optarg);
194                     exit(EXIT_FAILURE);
195                 }
196                 else {
197                     logFile = TRUE;
198                     gettimeofday(&start_tv, NULL);
199                     printf("\nOpened log file: %s\n", optarg);
200                     /* close log file upon LAD termination */
201                     flags = fcntl(fileno(logPtr), F_GETFD);
202                     if (flags != -1) {
203                         fcntl(fileno(logPtr), F_SETFD, flags | FD_CLOEXEC);
204                     }
205                 }
206                 break;
207             case 'p':
208                 printf("\nSet LAD's directory permissions to '%s'\n", optarg);
209                 chmod(LAD_ROOTDIR, strtol(optarg, NULL, 8));
210                 chmod(LAD_WORKINGDIR, strtol(optarg, NULL, 8));
211                 break;
212             default:
213                 fprintf (stderr, "\nUnrecognized argument\n");
214                 exit(EXIT_FAILURE);
215         }
216     }
218     /* Check to ensure id and baseId are not invalid */
219     printf ("id = %d baseId= %d\n", _MultiProc_cfg.id, _MultiProc_cfg.baseIdOfCluster);
220     if (_MultiProc_cfg.id == 0xFFFF || _MultiProc_cfg.baseIdOfCluster == 0xFFFF){
221          printf("\nBase cluster id is set to an INVALID value\n");
222          printf("Use -b option to set value or modify the MultiProcCfg file\n");
223          exit(EXIT_FAILURE);
224     }
227 #if DAEMON
228     /* fork off a child process */
229     pid = fork();
231     /* if fork of child failed then exit immediately; no child created */
232     if (pid < 0) {
233         printf("\nERROR: Failed to fork child process!");
234         exit(EXIT_FAILURE);
235     }
237     /* if pid > 0 this is the parent; time to die ... */
238     if (pid > 0) {
239         printf("\nSpawned daemon: %s\n\n", argv[0]);
240         exit(EXIT_SUCCESS);
241     }
243     /* child continues from here (pid == 0) ... */
245     /* change file mode mask */
246     umask(0);
248     /* create new session ID for the child */
249     sid = setsid();
251     /* exit with failure code if failed to get session ID... */
252     if (sid < 0) {
253         printf("\nERROR: Failed to acquire new session ID!");
254         exit(EXIT_FAILURE);
255     }
257     /* disassociate from the standard file descriptors */
258     close(STDIN_FILENO);
259     close(STDOUT_FILENO);
260     close(STDERR_FILENO);
262 #endif
264     LOG0("\nInitializing LAD... ")
266     /* TODO:L make sure LAD is not already running? */
268     /* initialize client info arrays */
269     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
270         clientConnected[i] = FALSE;
271         responseFIFOFilePtr[i] = NULL;
272     }
274     /* if command FIFO exists from previous LAD session delete it now */
275     unlink(commandFIFOFile);
277     /* create command FIFO */
278     statusIO = mkfifo(commandFIFOFile, 0777);
279     if (statusIO != 0) {
280         LOG2("\nERROR: unable to create %s, errno = %x\n", commandFIFOFile,
281             errno)
282         return(0);
283     }
285     /* set FIFO permissions to read/write */
286     chmod(commandFIFOFile, 0666);
288     /* Setup modules relevant for GateMP if necessary */
289 #if defined(GATEMP_SUPPORT)
290     if (gatempEnabled) {
291         /* Set up NameServer for resource manager process */
292         status = NameServer_setup();
293         if (status < 0) {
294             LOG0("\nERROR: unable to setup NameServer\n")
295             return(0);
296         }
298         status = GateHWSpinlock_start();
299         if (status < 0) {
300             LOG0("\nERROR: unable to start GateHWSpinlock\n");
301             return(0);
302         }
304         /* Set up GateMP */
305         status = GateMP_setup();
306         if (status < 0) {
307             LOG0("\nERROR: unable to setup GateMP\n")
308             NameServer_destroy();
309             return(0);
310         }
311     }
312 #endif
314 opencommandFIFO:
316     /* now open file for FIFO - will block until writer arrives... */
317     LOG1("\n    opening FIFO: %s\n", commandFIFOFile)
318     commandFIFOFilePtr = fopen(commandFIFOFile, "r");
319     if (commandFIFOFilePtr == NULL) {
320         LOG0("\nERROR: unable to open command FIFO\n")
321         unlink(commandFIFOFile);
322 #if defined(GATEMP_SUPPORT)
323         if (gatempEnabled) {
324             GateMP_destroy();
325             NameServer_destroy();
326         }
327 #endif
328         return(0);
329     }
331     /* COMMAND PROCESSING LOOP */
332     while (1) {
333         LOG0("Retrieving command...\n")
335         /* read the next command packet */
336         n = fread(&cmd, LAD_COMMANDLENGTH, 1, commandFIFOFilePtr);
338         /*
339          * if last client closes FIFO then it must be closed and reopened ...
340          */
341         if (!n) {
342             LOG1("   EOF detected on FIFO, closing FIFO: %s\n", commandFIFOFile)
343             fclose(commandFIFOFilePtr);
345             goto opencommandFIFO;
346         }
348         /* cleanup for any connected/started clients that have departed */
349         cleanupDepartedClients();
351         command = cmd.cmd;
352         clientId = cmd.clientId;
354         /* process individual commands */
355         switch (command) {
356           /*
357            * Since cmd is a union of rcv and snd structs, don't write
358            * any snd elements before all rcv elements have been referenced
359            * (either saved in separate variables or passed to a function).
360            *
361            * cmd.cmd has already been saved in 'command'
362            * cmd.clientId has already been saved in 'clientId'
363            */
364           case LAD_CONNECT:
365             connectToLAD(cmd.args.connect.name, cmd.args.connect.pid,
366                          cmd.args.connect.protocol, NULL);
368             break;
370           case LAD_DISCONNECT:
371             disconnectFromLAD(clientId);
373             break;
375           case LAD_RPROC_SETID:
376             rsp.status = MultiProc_rprocSetId(cmd.args.rprocSetId.procId,
377                     cmd.args.rprocSetId.rprocId);
378             break;
380           case LAD_IPC_GETCONFIG:
381             Ipc_getConfig(&rsp.ipcConfig);
382             break;
384           case LAD_NAMESERVER_SETUP:
385             LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
387             rsp.status = NameServer_setup();
389             LOG1("    status = %d\n", rsp.status)
390             LOG0("DONE\n")
392             break;
394           case LAD_NAMESERVER_DESTROY:
395             LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
397             rsp.status = NameServer_destroy();
399             LOG1("    status = %d\n", rsp.status)
400             LOG0("DONE\n")
402             break;
404           case LAD_NAMESERVER_PARAMS_INIT:
405             LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
407             NameServer_Params_init(&rsp.params);
409             LOG0("DONE\n")
411             break;
413           case LAD_NAMESERVER_CREATE:
414             LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
416             rsp.handle = NameServer_create(cmd.args.create.name,
417                                                &cmd.args.create.params);
419             LOG1("    handle = %p\n", rsp.handle)
420             LOG0("DONE\n")
422             break;
424           case LAD_NAMESERVER_DELETE:
425             LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
426                     cmd.args.nsdelete.handle)
428             rsp.nsdelete.handle = cmd.args.nsdelete.handle;
429             rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
431             LOG1("    status = %d\n", rsp.nsdelete.status)
432             LOG0("DONE\n")
434             break;
436           case LAD_NAMESERVER_ADD:
437             LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
438             LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
439             LOG1(" 0x%x)...\n", cmd.args.add.len)
441             rsp.entryPtr = NameServer_add(
442                 cmd.args.add.handle,
443                 cmd.args.add.name,
444                 cmd.args.add.buf,
445                 cmd.args.add.len);
447             LOG1("    entryPtr = %p\n", rsp.entryPtr)
448             LOG0("DONE\n")
450             break;
452           case LAD_NAMESERVER_GET:
453             LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
454                     cmd.args.get.handle, cmd.args.get.name)
455             LOG0(")...\n")
457             if (cmd.args.get.procId[0] == (UInt16)-1) {
458                 procIdPtr = NULL;
459             }
460             else {
461                 procIdPtr = cmd.args.get.procId;
462             }
463             rsp.get.status = NameServer_get(
464                 cmd.args.get.handle,
465                 cmd.args.get.name,
466                 rsp.get.buf,
467                 &cmd.args.get.len,
468                 procIdPtr);
469             rsp.get.len = cmd.args.get.len;
471             LOG1("    value = 0x%x\n", rsp.get.len)
472             LOG1("    status = %d\n", rsp.get.status)
473             LOG0("DONE\n")
475             break;
477           case LAD_NAMESERVER_ADDUINT32:
478             LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
479                     "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
480                     cmd.args.addUInt32.name, cmd.args.addUInt32.val)
482             rsp.entryPtr = NameServer_addUInt32(
483                 cmd.args.addUInt32.handle,
484                 cmd.args.addUInt32.name,
485                 cmd.args.addUInt32.val);
487             LOG1("    entryPtr = %p\n", rsp.entryPtr)
488             LOG0("DONE\n")
490             break;
492           case LAD_NAMESERVER_GETUINT32:
493             LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
494                     "(%p, '%s')...\n", cmd.args.getUInt32.handle,
495                     cmd.args.getUInt32.name)
497             if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
498                 procIdPtr = NULL;
499             }
500             else {
501                 procIdPtr = cmd.args.getUInt32.procId;
502             }
503             rsp.getUInt32.status = NameServer_getUInt32(
504                 cmd.args.getUInt32.handle,
505                 cmd.args.getUInt32.name,
506                 &rsp.getUInt32.val,
507                 procIdPtr);
509             LOG1("    value = 0x%x\n", rsp.getUInt32.val)
510             LOG1("    status = %d\n", rsp.getUInt32.status)
511             LOG0("DONE\n")
513             break;
515           case LAD_NAMESERVER_GETLOCAL:
516             rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
517                 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
518             rsp.get.len = cmd.args.getLocal.len;
519             break;
521           case LAD_NAMESERVER_GETLOCALUINT32:
522             rsp.getUInt32.status = NameServer_getLocalUInt32(
523                 cmd.args.getLocalUInt32.handle,
524                 cmd.args.getLocalUInt32.name,
525                 &rsp.getUInt32.val);
526             break;
528           case LAD_NAMESERVER_REMOVE:
529             LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
531             rsp.status = NameServer_remove(cmd.args.remove.handle,
532                                                cmd.args.remove.name);
534             LOG1("    status = %d\n", rsp.status)
535             LOG0("DONE\n")
537             break;
539           case LAD_NAMESERVER_REMOVEENTRY:
540             LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
542             rsp.status = NameServer_removeEntry(
543                 cmd.args.removeEntry.handle,
544                 cmd.args.removeEntry.entryPtr);
546             LOG1("    status = %d\n", rsp.status)
547             LOG0("DONE\n")
549             break;
551           case LAD_NAMESERVER_ATTACH:
552             rsp.status = NameServer_attach(cmd.args.attach.procId);
553             break;
555           case LAD_NAMESERVER_DETACH:
556             rsp.status = NameServer_detach(cmd.args.detach.procId);
557             break;
559           case LAD_MESSAGEQ_GETCONFIG:
560             LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
562             MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
563             rsp.messageQGetConfig.status = 0;
565             LOG1("    status = %d\n", rsp.messageQGetConfig.status)
566             LOG0("DONE\n")
568             break;
570           case LAD_MESSAGEQ_SETUP:
571             LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
573             rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
574             rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
576             LOG1("    status = %d\n", rsp.setup.status)
577             LOG0("DONE\n")
579             break;
581           case LAD_MESSAGEQ_DESTROY:
582             LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
584             rsp.status = MessageQ_destroy();
586             LOG1("    status = %d\n", rsp.status)
587             LOG0("DONE\n")
589             break;
591           case LAD_MESSAGEQ_CREATE:
592             LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
593                     cmd.args.messageQCreate.name,
594                     &cmd.args.messageQCreate.params);
596             tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
597                 cmd.args.messageQCreate.name;
599             handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
600             rsp.messageQCreate.serverHandle = handle;
602             if (handle) {
603                 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
604                 MessageQ_setQueueOwner(handle, clientPID[clientId]);
605                 rsp.messageQCreate.status = 0;
606             }
607             else {
608                 rsp.messageQCreate.status = -1;
609             }
611             LOG1("    status = %d\n", rsp.messageQCreate.status)
612             LOG0("DONE\n")
614             break;
616           case LAD_MESSAGEQ_DELETE:
617             LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
619             rsp.messageQDelete.status =
620                 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
622             LOG1("    status = %d\n", rsp.messageQDelete.status)
623             LOG0("DONE\n")
625             break;
627           case LAD_MESSAGEQ_MSGINIT:
628             LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
630             MessageQ_msgInit(&rsp.msgInit.msg);
631             rsp.msgInit.status = 0;
633             LOG1("    status = %d\n", rsp.msgInit.status)
634             LOG0("DONE\n")
636             break;
638           case LAD_MULTIPROC_GETCONFIG:
639             LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
641             MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
642             rsp.multiprocGetConfig.status = 0;
644             LOG1("    status = %d\n", rsp.multiprocGetConfig.status)
645             LOG0("DONE\n")
647             break;
649 #if defined(GATEMP_SUPPORT)
650           case LAD_GATEMP_START:
651             LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
653             rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
654             rsp.gateMPStart.status = GateMP_S_SUCCESS;;
656             LOG1("    status = %d\n", rsp.gateMPStart.status)
657             LOG0("DONE\n")
659             break;
661           case LAD_GATEMP_GETNUMRESOURCES:
662             LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
664             rsp.gateMPGetNumResources.value = GateMP_getNumResources(
665                                           cmd.args.gateMPGetNumResources.type);
666             rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
668             LOG1("    status = %d\n", rsp.gateMPGetNumResources.status)
669             LOG0("DONE\n")
671             break;
673           case LAD_GATEMP_GETFREERESOURCE:
674             LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
676             rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
677                                           cmd.args.gateMPGetFreeResource.type);
678             rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
680             LOG1("    status = %d\n", rsp.gateMPGetFreeResource.status)
681             LOG0("DONE\n")
683             break;
685           case LAD_GATEMP_RELEASERESOURCE:
686             LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
688             rsp.gateMPReleaseResource.status = GateMP_releaseResource(
689                                           cmd.args.gateMPReleaseResource.id,
690                                           cmd.args.gateMPReleaseResource.type);
692             LOG1("    status = %d\n", rsp.gateMPReleaseResource.status)
693             LOG0("DONE\n")
695             break;
697           case LAD_GATEMP_ISSETUP:
698             LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
700             rsp.gateMPIsSetup.result = GateMP_isSetup();
701             rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
703             LOG1("    status = %d\n", rsp.gateMPIsSetup.status)
704             LOG0("DONE\n")
706             break;
708           case LAD_GATEHWSPINLOCK_GETCONFIG:
709             LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
711             GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
712             rsp.gateHWSpinlockGetConfig.status = 0;
714             LOG1("    status = %d\n", rsp.gateHWSpinlockGetConfig.status)
715             LOG0("DONE\n")
717             break;
718 #endif
720           case LAD_EXIT:
721             goto exitNow;
723             break;
725           default:
726             LOG1("\nUnrecognized command: 0x%x\n", command)
728             break;
729         }
731         switch (command) {
732           case LAD_CONNECT:
733           case LAD_DISCONNECT:
734             break;
736           case LAD_RPROC_SETID:
737           case LAD_IPC_GETCONFIG:
738           case LAD_NAMESERVER_SETUP:
739           case LAD_NAMESERVER_DESTROY:
740           case LAD_NAMESERVER_PARAMS_INIT:
741           case LAD_NAMESERVER_CREATE:
742           case LAD_NAMESERVER_DELETE:
743           case LAD_NAMESERVER_ADD:
744           case LAD_NAMESERVER_GET:
745           case LAD_NAMESERVER_ADDUINT32:
746           case LAD_NAMESERVER_GETUINT32:
747           case LAD_NAMESERVER_GETLOCAL:
748           case LAD_NAMESERVER_GETLOCALUINT32:
749           case LAD_NAMESERVER_REMOVE:
750           case LAD_NAMESERVER_REMOVEENTRY:
751           case LAD_NAMESERVER_ATTACH:
752           case LAD_NAMESERVER_DETACH:
753           case LAD_MESSAGEQ_GETCONFIG:
754           case LAD_MESSAGEQ_SETUP:
755           case LAD_MESSAGEQ_DESTROY:
756           case LAD_MESSAGEQ_CREATE:
757           case LAD_MESSAGEQ_DELETE:
758           case LAD_MESSAGEQ_MSGINIT:
759           case LAD_MULTIPROC_GETCONFIG:
760 #if defined(GATEMP_SUPPORT)
761           case LAD_GATEMP_START:
762           case LAD_GATEMP_GETNUMRESOURCES:
763           case LAD_GATEMP_GETFREERESOURCE:
764           case LAD_GATEMP_RELEASERESOURCE:
765           case LAD_GATEMP_ISSETUP:
766           case LAD_GATEHWSPINLOCK_GETCONFIG:
767 #endif
769             LOG0("Sending response...\n");
771             fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
772             fflush(responseFIFOFilePtr[clientId]);
774             break;
776           default:
777             break;
778         }
779     }
781 exitNow:
782 #if defined(GATEMP_SUPPORT)
783     if (gatempEnabled) {
784         GateMP_destroy();
785         NameServer_destroy();
786     }
787 #endif
788     if (logFile) {
789         LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
790         fclose(logPtr);
791     }
792     unlink(commandFIFOFile);
794     return(0);
799 /*
800  *  ======== assignClientId ========
801  */
802 static LAD_ClientHandle assignClientId(Void)
804     Int clientId = -1;
805     Int i;
807     /* scan connection status flags to acquire a clientId */
808     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
809         /* if slot open then provisionally select this clientId */
810         if (clientConnected[i] == FALSE) {
811              clientId = i;
812              break;
813         }
814     }
816     return(clientId);
820 /*
821  *  ======== cleanupDepartedClients ========
822  */
823 static Void cleanupDepartedClients(Void)
825     Int killStat;
826     Int i;
828     /* scan all connections to verify client processes still exist... */
829     for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
831         /* if connected... */
832         if (clientConnected[i] == TRUE) {
834             /* check if the client process (PID) still exists */
835             /*
836              * NOTE - calling kill with signal value of 0 will perform
837              * error checking, but not actually send a signal.  Will use this
838              * error check to see if PID still exists.  An alternative was
839              * to call getpgid.  This worked, but is apparently limited to
840              * USE_XOPEN_EXTENDED configurations.
841              */
842             killStat = kill(clientPID[i], 0);
843             if ((killStat == -1) && (errno == ESRCH)) {
845                 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
847                 /* will always need to do the disconnect... */
848                 LOG0("\nDoing DISCONNECT on behalf of client...")
849                 doDisconnect(i);
851                 MessageQ_cleanupOwner(clientPID[i]);
852 //                NameServer_cleanupOwner(clientPID[i]);
854                 LOG0("DONE\n")
855             }
856         }
857     }
861 /*
862  *  ======== connectToLAD ========
863  */
864 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
866     Int clientId = -1;
867     Bool connectDenied = FALSE;
868     Int status = LAD_SUCCESS;
869     FILE * filePtr;
870     Int statusIO;
872     /*
873      * TODO:L here, and everywhere parse FIFO strings: should
874      * add full error checking for incomplete or corrupted
875      * strings? Since LAD to ladclient comms are "closed", and
876      * tested, the likelihood of problems seems very low.
877      * But should still consider doing full error checking
878      * and, hopefully, recovery.
879      */
880     LOG0("\nLAD_CONNECT: \n")
881     LOG1("    client FIFO name = %s\n", clientName)
882     LOG1("    client PID = %d\n", pid)
884     /* first check for proper communication protocol */
885     if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
887         /* if no match then reject the request */
888         LOG0("    ERROR: mismatch in communication protocol!\n")
889         LOG1("        LAD protocol = %s\n", LAD_PROTOCOLVERSION)
890         LOG1("        client protocol = %s\n", clientProto)
891         status = LAD_INVALIDVERSION;
893         /* set flag so know to close FIFO after response */
894         connectDenied = TRUE;
896         /* now jump forward a bit to send response */
897         goto openResponseFIFO;
898     }
900     /* determine this client's ID */
901     clientId = assignClientId();
903     /* if failed to acquire an ID then exit early */
904     if (clientId == -1) {
905         LOG0("    no free handle; too many connections!\n")
906         status = LAD_ACCESSDENIED;
908         /* set flag so know to close FIFO after response */
909         connectDenied = TRUE;
910     }
911     else {
912         LOG1("    assigned client handle = %d\n", clientId)
914         /* save the client's FIFO name for when disconnect */
915         strcpy(clientFIFOName[clientId], clientName);
916     }
918 openResponseFIFO:
920     /* if response FIFO exists from previous LAD session delete it now */
921     unlink(clientName);
923     /* create the dedicated response FIFO to the client */
924     statusIO = mkfifo(clientName, 0777);
925     if (statusIO != 0) {
927         LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
929         status = LAD_IOFAILURE;
931         /* send no response; connection request will timeout */
932         goto doneconnect;
933     }
935     LOG1("    FIFO %s created\n", clientName)
937     /* set FIFO permissions to read/write */
938     chmod(clientName, 0666);
940     filePtr = fopen(clientName, "w");
941     if (filePtr == NULL) {
942         LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
944         /* if failed open, still need to delete the FIFO */
945         unlink(clientName);
947         status = LAD_IOFAILURE;
949         /* send no response; connection request will timeout */
950         goto doneconnect;
951     }
953     LOG1("    FIFO %s opened for writing\n", clientName)
955     /*
956      * set "this client is connected" flag; this client ID is now "owned", and
957      * is no longer provisional
958      */
959     if (connectDenied == FALSE) {
960         responseFIFOFilePtr[clientId] = filePtr;
961         clientPID[clientId] = pid;
962         clientConnected[clientId] = TRUE;
963     }
965     rsp.connect.assignedId = clientId;
966     rsp.status = status;
968     /* put response to FIFO */
969     fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
970     fflush(filePtr);
972     LOG0("    sent response\n")
974     /* if connection was denied, must now close FIFO */
975     if (connectDenied == TRUE) {
976         LOG1("    connect denied; closing FIFO %s\n", clientName)
977         fclose(filePtr);
978         unlink(clientName);
979     }
981     LOG0("DONE\n")
983 doneconnect:
984     if (clientIdPtr != NULL) {
985         *clientIdPtr = clientId;
986     }
988     return(status);
992 /*
993  *  ======== disconnectFromLAD ========
994  */
995 static Void disconnectFromLAD(Int clientId)
997     LOG0("\nLAD_DISCONNECT: ")
999     LOG1("\n    client handle = %x", clientId)
1000     doDisconnect(clientId);
1002     LOG0("DONE\n")
1004     return;
1008 /*
1009  *  ======== doDisconnect ========
1010  */
1011 static Void doDisconnect(Int clientId)
1013     /* set "this client is not connected" flag */
1014     clientConnected[clientId] = FALSE;
1016     /* close and remove the response FIFO */
1017     LOG2("\n    closing FIFO %s (filePtr=%p)\n",
1018         clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1019     fclose(responseFIFOFilePtr[clientId]);
1021     LOG1("    done, unlinking %s\n", clientFIFOName[clientId]);
1022     unlink(clientFIFOName[clientId]);