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[])
114 {
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_IPC_GETCONFIG:
376 Ipc_getConfig(&rsp.ipcConfig);
377 break;
379 case LAD_NAMESERVER_SETUP:
380 LOG0("LAD_NAMESERVER_SETUP: calling NameServer_setup()...\n")
382 rsp.status = NameServer_setup();
384 LOG1(" status = %d\n", rsp.status)
385 LOG0("DONE\n")
387 break;
389 case LAD_NAMESERVER_DESTROY:
390 LOG0("LAD_NAMESERVER_DESTROY: calling NameServer_destroy()...\n")
392 rsp.status = NameServer_destroy();
394 LOG1(" status = %d\n", rsp.status)
395 LOG0("DONE\n")
397 break;
399 case LAD_NAMESERVER_PARAMS_INIT:
400 LOG0("LAD_NAMESERVER_PARAMS_INIT: calling NameServer_Params_init()...\n")
402 NameServer_Params_init(&rsp.params);
404 LOG0("DONE\n")
406 break;
408 case LAD_NAMESERVER_CREATE:
409 LOG1("LAD_NAMESERVER_CREATE: calling NameServer_create('%s')...\n", cmd.args.create.name)
411 rsp.handle = NameServer_create(cmd.args.create.name,
412 &cmd.args.create.params);
414 LOG1(" handle = %p\n", rsp.handle)
415 LOG0("DONE\n")
417 break;
419 case LAD_NAMESERVER_DELETE:
420 LOG1("LAD_NAMESERVER_DELETE: calling NameServer_delete(%p)...\n",
421 cmd.args.nsdelete.handle)
423 rsp.nsdelete.handle = cmd.args.nsdelete.handle;
424 rsp.nsdelete.status = NameServer_delete(&rsp.nsdelete.handle);
426 LOG1(" status = %d\n", rsp.nsdelete.status)
427 LOG0("DONE\n")
429 break;
431 case LAD_NAMESERVER_ADD:
432 LOG1("LAD_NAMESERVER_ADD: calling NameServer_add(%p, ", cmd.args.add.handle)
433 LOG2("'%s', %p,", cmd.args.add.name, cmd.args.add.buf)
434 LOG1(" 0x%x)...\n", cmd.args.add.len)
436 rsp.entryPtr = NameServer_add(
437 cmd.args.add.handle,
438 cmd.args.add.name,
439 cmd.args.add.buf,
440 cmd.args.add.len);
442 LOG1(" entryPtr = %p\n", rsp.entryPtr)
443 LOG0("DONE\n")
445 break;
447 case LAD_NAMESERVER_GET:
448 LOG2("LAD_NAMESERVER_GET: calling NameServer_get(%p, '%s'",
449 cmd.args.get.handle, cmd.args.get.name)
450 LOG0(")...\n")
452 if (cmd.args.get.procId[0] == (UInt16)-1) {
453 procIdPtr = NULL;
454 }
455 else {
456 procIdPtr = cmd.args.get.procId;
457 }
458 rsp.get.status = NameServer_get(
459 cmd.args.get.handle,
460 cmd.args.get.name,
461 rsp.get.buf,
462 &cmd.args.get.len,
463 procIdPtr);
464 rsp.get.len = cmd.args.get.len;
466 LOG1(" value = 0x%x\n", rsp.get.len)
467 LOG1(" status = %d\n", rsp.get.status)
468 LOG0("DONE\n")
470 break;
472 case LAD_NAMESERVER_ADDUINT32:
473 LOG3("LAD_NAMESERVER_ADDUINT32: calling NameServer_addUInt32"
474 "(%p, '%s', 0x%x)...\n", cmd.args.addUInt32.handle,
475 cmd.args.addUInt32.name, cmd.args.addUInt32.val)
477 rsp.entryPtr = NameServer_addUInt32(
478 cmd.args.addUInt32.handle,
479 cmd.args.addUInt32.name,
480 cmd.args.addUInt32.val);
482 LOG1(" entryPtr = %p\n", rsp.entryPtr)
483 LOG0("DONE\n")
485 break;
487 case LAD_NAMESERVER_GETUINT32:
488 LOG2("LAD_NAMESERVER_GETUINT32: calling NameServer_getUInt32"
489 "(%p, '%s')...\n", cmd.args.getUInt32.handle,
490 cmd.args.getUInt32.name)
492 if (cmd.args.getUInt32.procId[0] == (UInt16)-1) {
493 procIdPtr = NULL;
494 }
495 else {
496 procIdPtr = cmd.args.getUInt32.procId;
497 }
498 rsp.getUInt32.status = NameServer_getUInt32(
499 cmd.args.getUInt32.handle,
500 cmd.args.getUInt32.name,
501 &rsp.getUInt32.val,
502 procIdPtr);
504 LOG1(" value = 0x%x\n", rsp.getUInt32.val)
505 LOG1(" status = %d\n", rsp.getUInt32.status)
506 LOG0("DONE\n")
508 break;
510 case LAD_NAMESERVER_GETLOCAL:
511 rsp.get.status = NameServer_getLocal(cmd.args.getLocal.handle,
512 cmd.args.getLocal.name, &rsp.get.buf, &cmd.args.getLocal.len);
513 rsp.get.len = cmd.args.getLocal.len;
514 break;
516 case LAD_NAMESERVER_GETLOCALUINT32:
517 rsp.getUInt32.status = NameServer_getLocalUInt32(
518 cmd.args.getLocalUInt32.handle,
519 cmd.args.getLocalUInt32.name,
520 &rsp.getUInt32.val);
521 break;
523 case LAD_NAMESERVER_REMOVE:
524 LOG2("LAD_NAMESERVER_REMOVE: calling NameServer_remove(%p, '%s')...\n", cmd.args.remove.handle, cmd.args.remove.name)
526 rsp.status = NameServer_remove(cmd.args.remove.handle,
527 cmd.args.remove.name);
529 LOG1(" status = %d\n", rsp.status)
530 LOG0("DONE\n")
532 break;
534 case LAD_NAMESERVER_REMOVEENTRY:
535 LOG2("LAD_NAMESERVER_REMOVEENTRY: calling NameServer_removeEntry(%p, %p)...\n", cmd.args.removeEntry.handle, cmd.args.removeEntry.entryPtr)
537 rsp.status = NameServer_removeEntry(
538 cmd.args.removeEntry.handle,
539 cmd.args.removeEntry.entryPtr);
541 LOG1(" status = %d\n", rsp.status)
542 LOG0("DONE\n")
544 break;
546 case LAD_NAMESERVER_ATTACH:
547 rsp.status = NameServer_attach(cmd.args.attach.procId);
548 break;
550 case LAD_NAMESERVER_DETACH:
551 rsp.status = NameServer_detach(cmd.args.detach.procId);
552 break;
554 case LAD_MESSAGEQ_GETCONFIG:
555 LOG0("LAD_MESSAGEQ_GETCONFIG: calling MessageQ_getConfig()...\n")
557 MessageQ_getConfig(&rsp.messageQGetConfig.cfg);
558 rsp.messageQGetConfig.status = 0;
560 LOG1(" status = %d\n", rsp.messageQGetConfig.status)
561 LOG0("DONE\n")
563 break;
565 case LAD_MESSAGEQ_SETUP:
566 LOG0("LAD_MESSAGEQ_SETUP: calling MessageQ_setup()...\n")
568 rsp.setup.status = MessageQ_setup(&cmd.args.messageQSetup.cfg);
569 rsp.setup.nameServerHandle = MessageQ_getNameServerHandle();
571 LOG1(" status = %d\n", rsp.setup.status)
572 LOG0("DONE\n")
574 break;
576 case LAD_MESSAGEQ_DESTROY:
577 LOG0("LAD_MESSAGEQ_DESTROY: calling MessageQ_destroy()...\n")
579 rsp.status = MessageQ_destroy();
581 LOG1(" status = %d\n", rsp.status)
582 LOG0("DONE\n")
584 break;
586 case LAD_MESSAGEQ_CREATE:
587 LOG2("LAD_MESSAGEQ_CREATE: calling MessageQ_create(%p, %p)...\n",
588 cmd.args.messageQCreate.name,
589 &cmd.args.messageQCreate.params);
591 tmpString = (cmd.args.messageQCreate.name[0] == '\0') ? NULL :
592 cmd.args.messageQCreate.name;
594 handle = MessageQ_create(tmpString, &cmd.args.messageQCreate.params);
595 rsp.messageQCreate.serverHandle = handle;
597 if (handle) {
598 rsp.messageQCreate.queueId = MessageQ_getQueueId(handle);
599 MessageQ_setQueueOwner(handle, clientPID[clientId]);
600 rsp.messageQCreate.status = 0;
601 }
602 else {
603 rsp.messageQCreate.status = -1;
604 }
606 LOG1(" status = %d\n", rsp.messageQCreate.status)
607 LOG0("DONE\n")
609 break;
611 case LAD_MESSAGEQ_DELETE:
612 LOG1("LAD_MESSAGEQ_DELETE: calling MessageQ_delete(%p)...\n", cmd.args.messageQDelete.serverHandle)
614 rsp.messageQDelete.status =
615 MessageQ_delete((MessageQ_Handle *)&cmd.args.messageQDelete.serverHandle);
617 LOG1(" status = %d\n", rsp.messageQDelete.status)
618 LOG0("DONE\n")
620 break;
622 case LAD_MESSAGEQ_MSGINIT:
623 LOG1("LAD_MESSAGEQ_MSGINIT: calling MessageQ_msgInit(%p)...\n", &rsp.msgInit.msg);
625 MessageQ_msgInit(&rsp.msgInit.msg);
626 rsp.msgInit.status = 0;
628 LOG1(" status = %d\n", rsp.msgInit.status)
629 LOG0("DONE\n")
631 break;
633 case LAD_MULTIPROC_GETCONFIG:
634 LOG0("LAD_MULTIPROC_GETCONFIG: calling MultiProc_getConfig()...\n")
636 MultiProc_getConfig(&rsp.multiprocGetConfig.cfg);
637 rsp.multiprocGetConfig.status = 0;
639 LOG1(" status = %d\n", rsp.multiprocGetConfig.status)
640 LOG0("DONE\n")
642 break;
644 #if defined(GATEMP_SUPPORT)
645 case LAD_GATEMP_START:
646 LOG0("LAD_GATEMP_START: calling GateMP_start()...\n")
648 rsp.gateMPStart.nameServerHandle = GateMP_getNameServer();
649 rsp.gateMPStart.status = GateMP_S_SUCCESS;;
651 LOG1(" status = %d\n", rsp.gateMPStart.status)
652 LOG0("DONE\n")
654 break;
656 case LAD_GATEMP_GETNUMRESOURCES:
657 LOG0("LAD_GATEMP_GETNUMRESOURCES: calling GateMP_getNumResources()...\n")
659 rsp.gateMPGetNumResources.value = GateMP_getNumResources(
660 cmd.args.gateMPGetNumResources.type);
661 rsp.gateMPGetNumResources.status = GateMP_S_SUCCESS;;
663 LOG1(" status = %d\n", rsp.gateMPGetNumResources.status)
664 LOG0("DONE\n")
666 break;
668 case LAD_GATEMP_GETFREERESOURCE:
669 LOG0("LAD_GATEMP_GETFREERESOURCE: calling GateMP_getFreeResource()...\n")
671 rsp.gateMPGetFreeResource.id = GateMP_getFreeResource(
672 cmd.args.gateMPGetFreeResource.type);
673 rsp.gateMPGetFreeResource.status = GateMP_S_SUCCESS;;
675 LOG1(" status = %d\n", rsp.gateMPGetFreeResource.status)
676 LOG0("DONE\n")
678 break;
680 case LAD_GATEMP_RELEASERESOURCE:
681 LOG0("LAD_GATEMP_RELEASERESOURCE: calling GateMP_releaseResource()...\n")
683 rsp.gateMPReleaseResource.status = GateMP_releaseResource(
684 cmd.args.gateMPReleaseResource.id,
685 cmd.args.gateMPReleaseResource.type);
687 LOG1(" status = %d\n", rsp.gateMPReleaseResource.status)
688 LOG0("DONE\n")
690 break;
692 case LAD_GATEMP_ISSETUP:
693 LOG0("LAD_GATEMP_ISSETUP: calling GateMP_isSetup()...\n")
695 rsp.gateMPIsSetup.result = GateMP_isSetup();
696 rsp.gateMPIsSetup.status = GateMP_S_SUCCESS;
698 LOG1(" status = %d\n", rsp.gateMPIsSetup.status)
699 LOG0("DONE\n")
701 break;
703 case LAD_GATEHWSPINLOCK_GETCONFIG:
704 LOG0("LAD_GATEHWSPINLOCK_GETCONFIG: calling GateHWSpinlock_getConfig()...\n")
706 GateHWSpinlock_getConfig(&rsp.gateHWSpinlockGetConfig.cfgParams);
707 rsp.gateHWSpinlockGetConfig.status = 0;
709 LOG1(" status = %d\n", rsp.gateHWSpinlockGetConfig.status)
710 LOG0("DONE\n")
712 break;
713 #endif
715 case LAD_EXIT:
716 goto exitNow;
718 break;
720 default:
721 LOG1("\nUnrecognized command: 0x%x\n", command)
723 break;
724 }
726 switch (command) {
727 case LAD_CONNECT:
728 case LAD_DISCONNECT:
729 break;
731 case LAD_IPC_GETCONFIG:
732 case LAD_NAMESERVER_SETUP:
733 case LAD_NAMESERVER_DESTROY:
734 case LAD_NAMESERVER_PARAMS_INIT:
735 case LAD_NAMESERVER_CREATE:
736 case LAD_NAMESERVER_DELETE:
737 case LAD_NAMESERVER_ADD:
738 case LAD_NAMESERVER_GET:
739 case LAD_NAMESERVER_ADDUINT32:
740 case LAD_NAMESERVER_GETUINT32:
741 case LAD_NAMESERVER_GETLOCAL:
742 case LAD_NAMESERVER_GETLOCALUINT32:
743 case LAD_NAMESERVER_REMOVE:
744 case LAD_NAMESERVER_REMOVEENTRY:
745 case LAD_NAMESERVER_ATTACH:
746 case LAD_NAMESERVER_DETACH:
747 case LAD_MESSAGEQ_GETCONFIG:
748 case LAD_MESSAGEQ_SETUP:
749 case LAD_MESSAGEQ_DESTROY:
750 case LAD_MESSAGEQ_CREATE:
751 case LAD_MESSAGEQ_DELETE:
752 case LAD_MESSAGEQ_MSGINIT:
753 case LAD_MULTIPROC_GETCONFIG:
754 #if defined(GATEMP_SUPPORT)
755 case LAD_GATEMP_START:
756 case LAD_GATEMP_GETNUMRESOURCES:
757 case LAD_GATEMP_GETFREERESOURCE:
758 case LAD_GATEMP_RELEASERESOURCE:
759 case LAD_GATEMP_ISSETUP:
760 case LAD_GATEHWSPINLOCK_GETCONFIG:
761 #endif
763 LOG0("Sending response...\n");
765 fwrite(&rsp, LAD_RESPONSELENGTH, 1, responseFIFOFilePtr[clientId]);
766 fflush(responseFIFOFilePtr[clientId]);
768 break;
770 default:
771 break;
772 }
773 }
775 exitNow:
776 #if defined(GATEMP_SUPPORT)
777 if (gatempEnabled) {
778 GateMP_destroy();
779 NameServer_destroy();
780 }
781 #endif
782 if (logFile) {
783 LOG0("\n\nLAD IS SELF TERMINATING...\n\n")
784 fclose(logPtr);
785 }
786 unlink(commandFIFOFile);
788 return(0);
790 }
793 /*
794 * ======== assignClientId ========
795 */
796 static LAD_ClientHandle assignClientId(Void)
797 {
798 Int clientId = -1;
799 Int i;
801 /* scan connection status flags to acquire a clientId */
802 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
803 /* if slot open then provisionally select this clientId */
804 if (clientConnected[i] == FALSE) {
805 clientId = i;
806 break;
807 }
808 }
810 return(clientId);
811 }
814 /*
815 * ======== cleanupDepartedClients ========
816 */
817 static Void cleanupDepartedClients(Void)
818 {
819 Int killStat;
820 Int i;
822 /* scan all connections to verify client processes still exist... */
823 for (i = 0; i < LAD_MAXNUMCLIENTS; i++) {
825 /* if connected... */
826 if (clientConnected[i] == TRUE) {
828 /* check if the client process (PID) still exists */
829 /*
830 * NOTE - calling kill with signal value of 0 will perform
831 * error checking, but not actually send a signal. Will use this
832 * error check to see if PID still exists. An alternative was
833 * to call getpgid. This worked, but is apparently limited to
834 * USE_XOPEN_EXTENDED configurations.
835 */
836 killStat = kill(clientPID[i], 0);
837 if ((killStat == -1) && (errno == ESRCH)) {
839 LOG1("\nDETECTED CONNECTED CLIENT #%d HAS DEPARTED!", i)
841 /* will always need to do the disconnect... */
842 LOG0("\nDoing DISCONNECT on behalf of client...")
843 doDisconnect(i);
845 MessageQ_cleanupOwner(clientPID[i]);
846 // NameServer_cleanupOwner(clientPID[i]);
848 LOG0("DONE\n")
849 }
850 }
851 }
852 }
855 /*
856 * ======== connectToLAD ========
857 */
858 static Int connectToLAD(String clientName, Int pid, String clientProto, Int *clientIdPtr)
859 {
860 Int clientId = -1;
861 Bool connectDenied = FALSE;
862 Int status = LAD_SUCCESS;
863 FILE * filePtr;
864 Int statusIO;
866 /*
867 * TODO:L here, and everywhere parse FIFO strings: should
868 * add full error checking for incomplete or corrupted
869 * strings? Since LAD to ladclient comms are "closed", and
870 * tested, the likelihood of problems seems very low.
871 * But should still consider doing full error checking
872 * and, hopefully, recovery.
873 */
874 LOG0("\nLAD_CONNECT: \n")
875 LOG1(" client FIFO name = %s\n", clientName)
876 LOG1(" client PID = %d\n", pid)
878 /* first check for proper communication protocol */
879 if (strcmp(clientProto, LAD_PROTOCOLVERSION) != 0) {
881 /* if no match then reject the request */
882 LOG0(" ERROR: mismatch in communication protocol!\n")
883 LOG1(" LAD protocol = %s\n", LAD_PROTOCOLVERSION)
884 LOG1(" client protocol = %s\n", clientProto)
885 status = LAD_INVALIDVERSION;
887 /* set flag so know to close FIFO after response */
888 connectDenied = TRUE;
890 /* now jump forward a bit to send response */
891 goto openResponseFIFO;
892 }
894 /* determine this client's ID */
895 clientId = assignClientId();
897 /* if failed to acquire an ID then exit early */
898 if (clientId == -1) {
899 LOG0(" no free handle; too many connections!\n")
900 status = LAD_ACCESSDENIED;
902 /* set flag so know to close FIFO after response */
903 connectDenied = TRUE;
904 }
905 else {
906 LOG1(" assigned client handle = %d\n", clientId)
908 /* save the client's FIFO name for when disconnect */
909 strcpy(clientFIFOName[clientId], clientName);
910 }
912 openResponseFIFO:
914 /* if response FIFO exists from previous LAD session delete it now */
915 unlink(clientName);
917 /* create the dedicated response FIFO to the client */
918 statusIO = mkfifo(clientName, 0777);
919 if (statusIO != 0) {
921 LOG2("\nERROR: unable to mkfifo %s, errno = %x\n", clientName, errno)
923 status = LAD_IOFAILURE;
925 /* send no response; connection request will timeout */
926 goto doneconnect;
927 }
929 LOG1(" FIFO %s created\n", clientName)
931 /* set FIFO permissions to read/write */
932 chmod(clientName, 0666);
934 filePtr = fopen(clientName, "w");
935 if (filePtr == NULL) {
936 LOG1("\nERROR: unable to open response FIFO %s\n", clientName)
938 /* if failed open, still need to delete the FIFO */
939 unlink(clientName);
941 status = LAD_IOFAILURE;
943 /* send no response; connection request will timeout */
944 goto doneconnect;
945 }
947 LOG1(" FIFO %s opened for writing\n", clientName)
949 /*
950 * set "this client is connected" flag; this client ID is now "owned", and
951 * is no longer provisional
952 */
953 if (connectDenied == FALSE) {
954 responseFIFOFilePtr[clientId] = filePtr;
955 clientPID[clientId] = pid;
956 clientConnected[clientId] = TRUE;
957 }
959 rsp.connect.assignedId = clientId;
960 rsp.status = status;
962 /* put response to FIFO */
963 fwrite(&rsp, LAD_RESPONSELENGTH, 1, filePtr);
964 fflush(filePtr);
966 LOG0(" sent response\n")
968 /* if connection was denied, must now close FIFO */
969 if (connectDenied == TRUE) {
970 LOG1(" connect denied; closing FIFO %s\n", clientName)
971 fclose(filePtr);
972 unlink(clientName);
973 }
975 LOG0("DONE\n")
977 doneconnect:
978 if (clientIdPtr != NULL) {
979 *clientIdPtr = clientId;
980 }
982 return(status);
983 }
986 /*
987 * ======== disconnectFromLAD ========
988 */
989 static Void disconnectFromLAD(Int clientId)
990 {
991 LOG0("\nLAD_DISCONNECT: ")
993 LOG1("\n client handle = %x", clientId)
994 doDisconnect(clientId);
996 LOG0("DONE\n")
998 return;
999 }
1002 /*
1003 * ======== doDisconnect ========
1004 */
1005 static Void doDisconnect(Int clientId)
1006 {
1007 /* set "this client is not connected" flag */
1008 clientConnected[clientId] = FALSE;
1010 /* close and remove the response FIFO */
1011 LOG2("\n closing FIFO %s (filePtr=%p)\n",
1012 clientFIFOName[clientId], responseFIFOFilePtr[clientId])
1013 fclose(responseFIFOFilePtr[clientId]);
1015 LOG1(" done, unlinking %s\n", clientFIFOName[clientId]);
1016 unlink(clientFIFOName[clientId]);
1017 }