1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * parallel.cc
29 *
30 * Deal with the parallel processing
31 */
32
33 /*
34 * Included files
35 */
36 #include <errno.h> /* errno */
37 #include <fcntl.h>
38 #include <mk/defs.h>
39 #include <mksh/dosys.h> /* redirect_io() */
40 #include <mksh/macro.h> /* expand_value() */
41 #include <mksh/misc.h> /* getmem() */
42 #include <sys/signal.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 #include <sys/utsname.h>
46 #include <sys/wait.h>
47 #include <unistd.h>
48 #include <netdb.h>
49 #include <libintl.h>
50
51
52
53 /*
54 * Defined macros
55 */
56 #define MAXRULES 100
57
58 /*
59 * This const should be in avo_dms/include/AvoDmakeCommand.h
60 */
61 const int local_host_mask = 0x20;
62
63
64 /*
65 * typedefs & structs
66 */
67
68
69 /*
70 * Static variables
71 */
72 static Boolean just_did_subtree = false;
73 static char local_host[MAXNAMELEN] = "";
74 static char user_name[MAXNAMELEN] = "";
75 static int pmake_max_jobs = 0;
76 static pid_t process_running = -1;
77 static Running *running_tail = &running_list;
78 static Name subtree_conflict;
79 static Name subtree_conflict2;
80
81
82 /*
83 * File table of contents
84 */
85 static void delete_running_struct(Running rp);
86 static Boolean dependency_conflict(Name target);
87 static Doname distribute_process(char **commands, Property line);
88 static void doname_subtree(Name target, Boolean do_get, Boolean implicit);
89 static void dump_out_file(char *filename, Boolean err);
90 static void finish_doname(Running rp);
91 static void maybe_reread_make_state(void);
92 static void process_next(void);
93 static void reset_conditionals(int cnt, Name *targets, Property *locals);
94 static pid_t run_rule_commands(char *host, char **commands);
95 static Property *set_conditionals(int cnt, Name *targets);
96 static void store_conditionals(Running rp);
97
98
99 /*
100 * execute_parallel(line, waitflg)
101 *
102 * DMake 2.x:
103 * parallel mode: spawns a parallel process to execute the command group.
104 *
105 * Return value:
106 * The result of the execution
107 *
108 * Parameters:
109 * line The command group to execute
110 */
111 Doname
112 execute_parallel(Property line, Boolean waitflg, Boolean local)
113 {
114 int argcnt;
115 int cmd_options = 0;
116 char *commands[MAXRULES + 5];
117 char *cp;
118 Name dmake_name;
119 Name dmake_value;
120 int ignore;
121 Name make_machines_name;
122 char **p;
123 Property prop;
124 Doname result = build_ok;
125 Cmd_line rule;
126 Boolean silent_flag;
127 Name target = line->body.line.target;
128 Boolean wrote_state_file = false;
129
130 if ((pmake_max_jobs == 0) &&
131 (dmake_mode_type == parallel_mode)) {
132 if (local_host[0] == '\0') {
133 (void) gethostname(local_host, MAXNAMELEN);
134 }
135 MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS");
136 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
137 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
138 ((dmake_value = prop->body.macro.value) != NULL)) {
139 pmake_max_jobs = atoi(dmake_value->string_mb);
140 if (pmake_max_jobs <= 0) {
141 warning(gettext("DMAKE_MAX_JOBS cannot be less than or equal to zero."));
142 warning(gettext("setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS);
143 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
144 }
145 } else {
146 /*
147 * For backwards compatibility w/ PMake 1.x, when
148 * DMake 2.x is being run in parallel mode, DMake
149 * should parse the PMake startup file
150 * $(HOME)/.make.machines to get the pmake_max_jobs.
151 */
152 MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE");
153 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
154 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
155 ((dmake_value = prop->body.macro.value) != NULL)) {
156 make_machines_name = dmake_value;
157 } else {
158 make_machines_name = NULL;
159 }
160 if ((pmake_max_jobs = read_make_machines(make_machines_name)) <= 0) {
161 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
162 }
163 }
164 }
165
166 if ((dmake_mode_type == serial_mode) ||
167 ((dmake_mode_type == parallel_mode) && (waitflg))) {
168 return (execute_serial(line));
169 }
170
171 {
172 p = commands;
173 }
174
175 argcnt = 0;
176 for (rule = line->body.line.command_used;
177 rule != NULL;
178 rule = rule->next) {
179 if (posix && (touch || quest) && !rule->always_exec) {
180 continue;
181 }
182 if (vpath_defined) {
183 rule->command_line =
184 vpath_translation(rule->command_line);
185 }
186
187 silent_flag = false;
188 ignore = 0;
189
190 if (rule->command_line->hash.length > 0) {
191 if (++argcnt == MAXRULES) {
192 return build_serial;
193 }
194 {
195 if (rule->silent && !silent) {
196 silent_flag = true;
197 }
198 if (rule->ignore_error) {
199 ignore++;
200 }
201 /* XXX - need to add support for + prefix */
202 if (silent_flag || ignore) {
203 *p = getmem((silent_flag ? 1 : 0) +
204 ignore +
205 (strlen(rule->
206 command_line->
207 string_mb)) +
208 1);
209 cp = *p++;
210 if (silent_flag) {
211 *cp++ = (int) at_char;
212 }
213 if (ignore) {
214 *cp++ = (int) hyphen_char;
215 }
216 (void) strcpy(cp, rule->command_line->string_mb);
217 } else {
218 *p++ = rule->command_line->string_mb;
219 }
220 }
221 }
222 }
223 if ((argcnt == 0) ||
224 (report_dependencies_level > 0)) {
225 return build_ok;
226 }
227 {
228 *p = NULL;
229
230 Doname res = distribute_process(commands, line);
231 if (res == build_running) {
232 parallel_process_cnt++;
233 }
234
235 /*
236 * Return only those memory that were specially allocated
237 * for part of commands.
238 */
239 for (int i = 0; commands[i] != NULL; i++) {
240 if ((commands[i][0] == (int) at_char) ||
241 (commands[i][0] == (int) hyphen_char)) {
242 retmem_mb(commands[i]);
243 }
244 }
245 return res;
246 }
247 }
248
249
250 #define MAXJOBS_ADJUST_RFE4694000
251
252 #ifdef MAXJOBS_ADJUST_RFE4694000
253
254 #include <unistd.h> /* sysconf(_SC_NPROCESSORS_ONLN) */
255 #include <sys/ipc.h> /* ftok() */
256 #include <sys/shm.h> /* shmget(), shmat(), shmdt(), shmctl() */
257 #include <semaphore.h> /* sem_init(), sem_trywait(), sem_post(), sem_destroy() */
258 #include <sys/loadavg.h> /* getloadavg() */
259
260 /*
261 * adjust_pmake_max_jobs (int pmake_max_jobs)
262 *
263 * Parameters:
264 * pmake_max_jobs - max jobs limit set by user
265 *
266 * External functions used:
267 * sysconf()
268 * getloadavg()
269 */
270 static int
271 adjust_pmake_max_jobs (int pmake_max_jobs)
272 {
273 static int ncpu = 0;
274 double loadavg[3];
275 int adjustment;
276 int adjusted_max_jobs;
277
278 if (ncpu <= 0) {
279 if ((ncpu = sysconf(_SC_NPROCESSORS_ONLN)) <= 0) {
280 ncpu = 1;
281 }
282 }
283 if (getloadavg(loadavg, 3) != 3) return(pmake_max_jobs);
284 adjustment = ((int)loadavg[LOADAVG_1MIN]);
285 if (adjustment < 2) return(pmake_max_jobs);
286 if (ncpu > 1) {
287 adjustment = adjustment / ncpu;
288 }
289 adjusted_max_jobs = pmake_max_jobs - adjustment;
290 if (adjusted_max_jobs < 1) adjusted_max_jobs = 1;
291 return(adjusted_max_jobs);
292 }
293
294 /*
295 * M2 adjust mode data and functions
296 *
297 * m2_init() - initializes M2 shared semaphore
298 * m2_acquire_job() - decrements M2 semaphore counter
299 * m2_release_job() - increments M2 semaphore counter
300 * m2_fini() - destroys M2 semaphore and shared memory*
301 *
302 * Environment variables:
303 * __DMAKE_M2_FILE__
304 *
305 * External functions:
306 * ftok(), shmget(), shmat(), shmdt(), shmctl()
307 * sem_init(), sem_trywait(), sem_post(), sem_destroy()
308 * creat(), close(), unlink()
309 * getenv(), putenv()
310 *
311 * Static variables:
312 * m2_file - tmp file name to create ipc key for shared memory
313 * m2_shm_id - shared memory id
314 * m2_shm_sem - shared memory semaphore
315 */
316
317 static char m2_file[MAXPATHLEN];
318 static int m2_shm_id = -1;
319 static sem_t* m2_shm_sem = 0;
320
321 static int
322 m2_init() {
323 char *var;
324 key_t key;
325
326 if ((var = getenv("__DMAKE_M2_FILE__")) == 0) {
327 /* compose tmp file name */
328 sprintf(m2_file, "%s/dmake.m2.%d.XXXXXX", tmpdir, getpid());
329
330 /* create tmp file */
331 int fd = mkstemp(m2_file);
332 if (fd < 0) {
333 return -1;
334 } else {
335 close(fd);
336 }
337 } else {
338 /* using existing semaphore */
339 strcpy(m2_file, var);
340 }
341
342 /* combine IPC key */
343 if ((key = ftok(m2_file, 38)) == (key_t) -1) {
344 return -1;
345 }
346
347 /* create shared memory */
348 if ((m2_shm_id = shmget(key, sizeof(*m2_shm_sem), 0666 | (var ? 0 : IPC_CREAT|IPC_EXCL))) == -1) {
349 return -1;
350 }
351
352 /* attach shared memory */
353 if ((m2_shm_sem = (sem_t*) shmat(m2_shm_id, 0, 0666)) == (sem_t*)-1) {
354 return -1;
355 }
356
357 /* root process */
358 if (var == 0) {
359 /* initialize semaphore */
360 if (sem_init(m2_shm_sem, 1, pmake_max_jobs)) {
361 return -1;
362 }
363
364 /* alloc memory for env variable */
365 if ((var = (char*) malloc(MAXPATHLEN)) == 0) {
366 return -1;
367 }
368
369 /* put key to env */
370 sprintf(var, "__DMAKE_M2_FILE__=%s", m2_file);
371 if (putenv(var)) {
372 return -1;
373 }
374 }
375 return 0;
376 }
377
378 static void
379 m2_fini() {
380 if (m2_shm_id >= 0) {
381 struct shmid_ds stat;
382
383 /* determine the number of attached processes */
384 if (shmctl(m2_shm_id, IPC_STAT, &stat) == 0) {
385 if (stat.shm_nattch <= 1) {
386 /* destroy semaphore */
387 if (m2_shm_sem != 0) {
388 (void) sem_destroy(m2_shm_sem);
389 }
390
391 /* destroy shared memory */
392 (void) shmctl(m2_shm_id, IPC_RMID, &stat);
393
394 /* remove tmp file created for the key */
395 (void) unlink(m2_file);
396 } else {
397 /* detach shared memory */
398 if (m2_shm_sem != 0) {
399 (void) shmdt((char*) m2_shm_sem);
400 }
401 }
402 }
403
404 m2_shm_id = -1;
405 m2_shm_sem = 0;
406 }
407 }
408
409 static int
410 m2_acquire_job() {
411 if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
412 if (sem_trywait(m2_shm_sem) == 0) {
413 return 1;
414 }
415 if (errno == EAGAIN) {
416 return 0;
417 }
418 }
419 return -1;
420 }
421
422 static int
423 m2_release_job() {
424 if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
425 if (sem_post(m2_shm_sem) == 0) {
426 return 0;
427 }
428 }
429 return -1;
430 }
431
432 /*
433 * job adjust mode
434 *
435 * Possible values:
436 * ADJUST_M1 - adjustment by system load (default)
437 * ADJUST_M2 - fixed limit of jobs for the group of nested dmakes
438 * ADJUST_NONE - no adjustment - fixed limit of jobs for the current dmake
439 */
440 static enum {
441 ADJUST_UNKNOWN,
442 ADJUST_M1,
443 ADJUST_M2,
444 ADJUST_NONE
445 } job_adjust_mode = ADJUST_UNKNOWN;
446
447 /*
448 * void job_adjust_fini()
449 *
450 * Description:
451 * Cleans up job adjust data.
452 *
453 * Static variables:
454 * job_adjust_mode Current job adjust mode
455 */
456 void
457 job_adjust_fini() {
458 if (job_adjust_mode == ADJUST_M2) {
459 m2_fini();
460 }
461 }
462
463 /*
464 * void job_adjust_error()
465 *
466 * Description:
467 * Prints warning message, cleans up job adjust data, and disables job adjustment
468 *
469 * Environment:
470 * DMAKE_ADJUST_MAX_JOBS
471 *
472 * External functions:
473 * putenv()
474 *
475 * Static variables:
476 * job_adjust_mode Current job adjust mode
477 */
478 static void
479 job_adjust_error() {
480 if (job_adjust_mode != ADJUST_NONE) {
481 /* cleanup internals */
482 job_adjust_fini();
483
484 /* warning message for the user */
485 warning(gettext("Encountered max jobs auto adjustment error - disabling auto adjustment."));
486
487 /* switch off job adjustment for the children */
488 putenv(strdup("DMAKE_ADJUST_MAX_JOBS=NO"));
489
490 /* and for this dmake */
491 job_adjust_mode = ADJUST_NONE;
492 }
493 }
494
495 /*
496 * void job_adjust_init()
497 *
498 * Description:
499 * Parses DMAKE_ADJUST_MAX_JOBS env variable
500 * and performs appropriate initializations.
501 *
502 * Environment:
503 * DMAKE_ADJUST_MAX_JOBS
504 * DMAKE_ADJUST_MAX_JOBS == "NO" - no adjustment
505 * DMAKE_ADJUST_MAX_JOBS == "M2" - M2 adjust mode
506 * other - M1 adjust mode
507 *
508 * External functions:
509 * getenv()
510 *
511 * Static variables:
512 * job_adjust_mode Current job adjust mode
513 */
514 static void
515 job_adjust_init() {
516 if (job_adjust_mode == ADJUST_UNKNOWN) {
517 /* default mode */
518 job_adjust_mode = ADJUST_M1;
519
520 /* determine adjust mode */
521 if (char *var = getenv("DMAKE_ADJUST_MAX_JOBS")) {
522 if (strcasecmp(var, "NO") == 0) {
523 job_adjust_mode = ADJUST_NONE;
524 } else if (strcasecmp(var, "M2") == 0) {
525 job_adjust_mode = ADJUST_M2;
526 }
527 }
528
529 /* M2 specific initialization */
530 if (job_adjust_mode == ADJUST_M2) {
531 if (m2_init()) {
532 job_adjust_error();
533 }
534 }
535 }
536 }
537
538 #endif /* MAXJOBS_ADJUST_RFE4694000 */
539
540 /*
541 * distribute_process(char **commands, Property line)
542 *
543 * Parameters:
544 * commands argv vector of commands to execute
545 *
546 * Return value:
547 * The result of the execution
548 *
549 * Static variables used:
550 * process_running Set to the pid of the process set running
551 * #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
552 * job_adjust_mode Current job adjust mode
553 * #endif
554 */
555 static Doname
556 distribute_process(char **commands, Property line)
557 {
558 static unsigned file_number = 0;
559 wchar_t string[MAXPATHLEN];
560 char mbstring[MAXPATHLEN];
561 int filed;
562 int res;
563 int tmp_index;
564 char *tmp_index_str_ptr;
565
566 #if !defined (TEAMWARE_MAKE_CMN) || !defined (MAXJOBS_ADJUST_RFE4694000)
567 while (parallel_process_cnt >= pmake_max_jobs) {
568 await_parallel(false);
569 finish_children(true);
570 }
571 #else /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */
572 /* initialize adjust mode, if not initialized */
573 if (job_adjust_mode == ADJUST_UNKNOWN) {
574 job_adjust_init();
575 }
576
577 /* actions depend on adjust mode */
578 switch (job_adjust_mode) {
579 case ADJUST_M1:
580 while (parallel_process_cnt >= adjust_pmake_max_jobs (pmake_max_jobs)) {
581 await_parallel(false);
582 finish_children(true);
583 }
584 break;
585 case ADJUST_M2:
586 if ((res = m2_acquire_job()) == 0) {
587 if (parallel_process_cnt > 0) {
588 await_parallel(false);
589 finish_children(true);
590
591 if ((res = m2_acquire_job()) == 0) {
592 return build_serial;
593 }
594 } else {
595 return build_serial;
596 }
597 }
598 if (res < 0) {
599 /* job adjustment error */
600 job_adjust_error();
601
602 /* no adjustment */
603 while (parallel_process_cnt >= pmake_max_jobs) {
604 await_parallel(false);
605 finish_children(true);
606 }
607 }
608 break;
609 default:
610 while (parallel_process_cnt >= pmake_max_jobs) {
611 await_parallel(false);
612 finish_children(true);
613 }
614 }
615 #endif /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */
616 setvar_envvar();
617 /*
618 * Tell the user what DMake is doing.
619 */
620 if (!silent && output_mode != txt2_mode) {
621 /*
622 * Print local_host --> x job(s).
623 */
624 (void) fprintf(stdout,
625 gettext("%s --> %d %s\n"),
626 local_host,
627 parallel_process_cnt + 1,
628 (parallel_process_cnt == 0) ? gettext("job") : gettext("jobs"));
629
630 /* Print command line(s). */
631 tmp_index = 0;
632 while (commands[tmp_index] != NULL) {
633 /* No @ char. */
634 /* XXX - need to add [2] when + prefix is added */
635 if ((commands[tmp_index][0] != (int) at_char) &&
636 (commands[tmp_index][1] != (int) at_char)) {
637 tmp_index_str_ptr = commands[tmp_index];
638 if (*tmp_index_str_ptr == (int) hyphen_char) {
639 tmp_index_str_ptr++;
640 }
641 (void) fprintf(stdout, "%s\n", tmp_index_str_ptr);
642 }
643 tmp_index++;
644 }
645 (void) fflush(stdout);
646 }
647
648 (void) sprintf(mbstring,
649 "%s/dmake.stdout.%d.%d.XXXXXX",
650 tmpdir,
651 getpid(),
652 file_number++);
653
654 mktemp(mbstring);
655
656 stdout_file = strdup(mbstring);
657 stderr_file = NULL;
658
659 if (!out_err_same) {
660 (void) sprintf(mbstring,
661 "%s/dmake.stderr.%d.%d.XXXXXX",
662 tmpdir,
663 getpid(),
664 file_number++);
665
666 mktemp(mbstring);
667
668 stderr_file = strdup(mbstring);
669 }
670
671 process_running = run_rule_commands(local_host, commands);
672
673 return build_running;
674 }
675
676 /*
677 * doname_parallel(target, do_get, implicit)
678 *
679 * Processes the given target and finishes up any parallel
680 * processes left running.
681 *
682 * Return value:
683 * Result of target build
684 *
685 * Parameters:
686 * target Target to build
687 * do_get True if sccs get to be done
688 * implicit True if this is an implicit target
689 */
690 Doname
691 doname_parallel(Name target, Boolean do_get, Boolean implicit)
692 {
693 Doname result;
694
695 result = doname_check(target, do_get, implicit, false);
696 if (result == build_ok || result == build_failed) {
697 return result;
698 }
699 finish_running();
700 return (Doname) target->state;
701 }
702
703 /*
704 * doname_subtree(target, do_get, implicit)
705 *
706 * Completely computes an object and its dependents for a
707 * serial subtree build.
708 *
709 * Parameters:
710 * target Target to build
711 * do_get True if sccs get to be done
712 * implicit True if this is an implicit target
713 *
714 * Static variables used:
715 * running_tail Tail of the list of running processes
716 *
717 * Global variables used:
718 * running_list The list of running processes
719 */
720 static void
721 doname_subtree(Name target, Boolean do_get, Boolean implicit)
722 {
723 Running save_running_list;
724 Running *save_running_tail;
725
726 save_running_list = running_list;
727 save_running_tail = running_tail;
728 running_list = NULL;
729 running_tail = &running_list;
730 target->state = build_subtree;
731 target->checking_subtree = true;
732 while(doname_check(target, do_get, implicit, false) == build_running) {
733 target->checking_subtree = false;
734 finish_running();
735 target->state = build_subtree;
736 }
737 target->checking_subtree = false;
738 running_list = save_running_list;
739 running_tail = save_running_tail;
740 }
741
742 /*
743 * finish_running()
744 *
745 * Keeps processing until the running_list is emptied out.
746 *
747 * Parameters:
748 *
749 * Global variables used:
750 * running_list The list of running processes
751 */
752 void
753 finish_running(void)
754 {
755 while (running_list != NULL) {
756 {
757 await_parallel(false);
758 finish_children(true);
759 }
760 if (running_list != NULL) {
761 process_next();
762 }
763 }
764 }
765
766 /*
767 * process_next()
768 *
769 * Searches the running list for any targets which can start processing.
770 * This can be a pending target, a serial target, or a subtree target.
771 *
772 * Parameters:
773 *
774 * Static variables used:
775 * running_tail The end of the list of running procs
776 * subtree_conflict A target which conflicts with a subtree
777 * subtree_conflict2 The other target which conflicts
778 *
779 * Global variables used:
780 * commands_done True if commands executed
781 * debug_level Controls debug output
782 * parallel_process_cnt Number of parallel process running
783 * recursion_level Indentation for debug output
784 * running_list List of running processes
785 */
786 static void
787 process_next(void)
788 {
789 Running rp;
790 Running *rp_prev;
791 Property line;
792 Chain target_group;
793 Dependency dep;
794 Boolean quiescent = true;
795 Running *subtree_target;
796 Boolean saved_commands_done;
797 Property *conditionals;
798
799 subtree_target = NULL;
800 subtree_conflict = NULL;
801 subtree_conflict2 = NULL;
802 /*
803 * If nothing currently running, build a serial target, if any.
804 */
805 start_loop_1:
806 for (rp_prev = &running_list, rp = running_list;
807 rp != NULL && parallel_process_cnt == 0;
808 rp = rp->next) {
809 if (rp->state == build_serial) {
810 *rp_prev = rp->next;
811 if (rp->next == NULL) {
812 running_tail = rp_prev;
813 }
814 recursion_level = rp->recursion_level;
815 rp->target->state = build_pending;
816 (void) doname_check(rp->target,
817 rp->do_get,
818 rp->implicit,
819 false);
820 quiescent = false;
821 delete_running_struct(rp);
822 goto start_loop_1;
823 } else {
824 rp_prev = &rp->next;
825 }
826 }
827 /*
828 * Find a target to build. The target must be pending, have all
829 * its dependencies built, and not be in a target group with a target
830 * currently building.
831 */
832 start_loop_2:
833 for (rp_prev = &running_list, rp = running_list;
834 rp != NULL;
835 rp = rp->next) {
836 if (!(rp->state == build_pending ||
837 rp->state == build_subtree)) {
838 quiescent = false;
839 rp_prev = &rp->next;
840 } else if (rp->state == build_pending) {
841 line = get_prop(rp->target->prop, line_prop);
842 for (dep = line->body.line.dependencies;
843 dep != NULL;
844 dep = dep->next) {
845 if (dep->name->state == build_running ||
846 dep->name->state == build_pending ||
847 dep->name->state == build_serial) {
848 break;
849 }
850 }
851 if (dep == NULL) {
852 for (target_group = line->body.line.target_group;
853 target_group != NULL;
854 target_group = target_group->next) {
855 if (is_running(target_group->name)) {
856 break;
857 }
858 }
859 if (target_group == NULL) {
860 *rp_prev = rp->next;
861 if (rp->next == NULL) {
862 running_tail = rp_prev;
863 }
864 recursion_level = rp->recursion_level;
865 rp->target->state = rp->redo ?
866 build_dont_know : build_pending;
867 saved_commands_done = commands_done;
868 conditionals =
869 set_conditionals
870 (rp->conditional_cnt,
871 rp->conditional_targets);
872 rp->target->dont_activate_cond_values = true;
873 if ((doname_check(rp->target,
874 rp->do_get,
875 rp->implicit,
876 rp->target->has_target_prop ? true : false) !=
877 build_running) &&
878 !commands_done) {
879 commands_done =
880 saved_commands_done;
881 }
882 rp->target->dont_activate_cond_values = false;
883 reset_conditionals
884 (rp->conditional_cnt,
885 rp->conditional_targets,
886 conditionals);
887 quiescent = false;
888 delete_running_struct(rp);
889 goto start_loop_2;
890 } else {
891 rp_prev = &rp->next;
892 }
893 } else {
894 rp_prev = &rp->next;
895 }
896 } else {
897 rp_prev = &rp->next;
898 }
899 }
900 /*
901 * If nothing has been found to build and there exists a subtree
902 * target with no dependency conflicts, build it.
903 */
904 if (quiescent) {
905 start_loop_3:
906 for (rp_prev = &running_list, rp = running_list;
907 rp != NULL;
908 rp = rp->next) {
909 if (rp->state == build_subtree) {
910 if (!dependency_conflict(rp->target)) {
911 *rp_prev = rp->next;
912 if (rp->next == NULL) {
913 running_tail = rp_prev;
914 }
915 recursion_level = rp->recursion_level;
916 doname_subtree(rp->target,
917 rp->do_get,
918 rp->implicit);
919 quiescent = false;
920 delete_running_struct(rp);
921 goto start_loop_3;
922 } else {
923 subtree_target = rp_prev;
924 rp_prev = &rp->next;
925 }
926 } else {
927 rp_prev = &rp->next;
928 }
929 }
930 }
931 /*
932 * If still nothing found to build, we either have a deadlock
933 * or a subtree with a dependency conflict with something waiting
934 * to build.
935 */
936 if (quiescent) {
937 if (subtree_target == NULL) {
938 fatal(gettext("Internal error: deadlock detected in process_next"));
939 } else {
940 rp = *subtree_target;
941 if (debug_level > 0) {
942 warning(gettext("Conditional macro conflict encountered for %s between %s and %s"),
943 subtree_conflict2->string_mb,
944 rp->target->string_mb,
945 subtree_conflict->string_mb);
946 }
947 *subtree_target = (*subtree_target)->next;
948 if (rp->next == NULL) {
949 running_tail = subtree_target;
950 }
951 recursion_level = rp->recursion_level;
952 doname_subtree(rp->target, rp->do_get, rp->implicit);
953 delete_running_struct(rp);
954 }
955 }
956 }
957
958 /*
959 * set_conditionals(cnt, targets)
960 *
961 * Sets the conditional macros for the targets given in the array of
962 * targets. The old macro values are returned in an array of
963 * Properties for later resetting.
964 *
965 * Return value:
966 * Array of conditional macro settings
967 *
968 * Parameters:
969 * cnt Number of targets
970 * targets Array of targets
971 */
972 static Property *
973 set_conditionals(int cnt, Name *targets)
974 {
975 Property *locals, *lp;
976 Name *tp;
977
978 locals = (Property *) getmem(cnt * sizeof(Property));
979 for (lp = locals, tp = targets;
980 cnt > 0;
981 cnt--, lp++, tp++) {
982 *lp = (Property) getmem((*tp)->conditional_cnt *
983 sizeof(struct _Property));
984 set_locals(*tp, *lp);
985 }
986 return locals;
987 }
988
989 /*
990 * reset_conditionals(cnt, targets, locals)
991 *
992 * Resets the conditional macros as saved in the given array of
993 * Properties. The resets are done in reverse order. Afterwards the
994 * data structures are freed.
995 *
996 * Parameters:
997 * cnt Number of targets
998 * targets Array of targets
999 * locals Array of dependency macro settings
1000 */
1001 static void
1002 reset_conditionals(int cnt, Name *targets, Property *locals)
1003 {
1004 Name *tp;
1005 Property *lp;
1006
1007 for (tp = targets + (cnt - 1), lp = locals + (cnt - 1);
1008 cnt > 0;
1009 cnt--, tp--, lp--) {
1010 reset_locals(*tp,
1011 *lp,
1012 get_prop((*tp)->prop, conditional_prop),
1013 0);
1014 retmem_mb((caddr_t) *lp);
1015 }
1016 retmem_mb((caddr_t) locals);
1017 }
1018
1019 /*
1020 * dependency_conflict(target)
1021 *
1022 * Returns true if there is an intersection between
1023 * the subtree of the target and any dependents of the pending targets.
1024 *
1025 * Return value:
1026 * True if conflict found
1027 *
1028 * Parameters:
1029 * target Subtree target to check
1030 *
1031 * Static variables used:
1032 * subtree_conflict Target conflict found
1033 * subtree_conflict2 Second conflict found
1034 *
1035 * Global variables used:
1036 * running_list List of running processes
1037 * wait_name .WAIT, not a real dependency
1038 */
1039 static Boolean
1040 dependency_conflict(Name target)
1041 {
1042 Property line;
1043 Property pending_line;
1044 Dependency dp;
1045 Dependency pending_dp;
1046 Running rp;
1047
1048 /* Return if we are already checking this target */
1049 if (target->checking_subtree) {
1050 return false;
1051 }
1052 target->checking_subtree = true;
1053 line = get_prop(target->prop, line_prop);
1054 if (line == NULL) {
1055 target->checking_subtree = false;
1056 return false;
1057 }
1058 /* Check each dependency of the target for conflicts */
1059 for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) {
1060 /* Ignore .WAIT dependency */
1061 if (dp->name == wait_name) {
1062 continue;
1063 }
1064 /*
1065 * For each pending target, look for a dependency which
1066 * is the same as a dependency of the subtree target. Since
1067 * we can't build the subtree until all pending targets have
1068 * finished which depend on the same dependency, this is
1069 * a conflict.
1070 */
1071 for (rp = running_list; rp != NULL; rp = rp->next) {
1072 if (rp->state == build_pending) {
1073 pending_line = get_prop(rp->target->prop,
1074 line_prop);
1075 if (pending_line == NULL) {
1076 continue;
1077 }
1078 for(pending_dp = pending_line->
1079 body.line.dependencies;
1080 pending_dp != NULL;
1081 pending_dp = pending_dp->next) {
1082 if (dp->name == pending_dp->name) {
1083 target->checking_subtree
1084 = false;
1085 subtree_conflict = rp->target;
1086 subtree_conflict2 = dp->name;
1087 return true;
1088 }
1089 }
1090 }
1091 }
1092 if (dependency_conflict(dp->name)) {
1093 target->checking_subtree = false;
1094 return true;
1095 }
1096 }
1097 target->checking_subtree = false;
1098 return false;
1099 }
1100
1101 /*
1102 * await_parallel(waitflg)
1103 *
1104 * Waits for parallel children to exit and finishes their processing.
1105 * If waitflg is false, the function returns after update_delay.
1106 *
1107 * Parameters:
1108 * waitflg dwight
1109 */
1110 void
1111 await_parallel(Boolean waitflg)
1112 {
1113 Boolean nohang;
1114 pid_t pid;
1115 int status;
1116 Running rp;
1117 int waiterr;
1118
1119 nohang = false;
1120 for ( ; ; ) {
1121 if (!nohang) {
1122 (void) alarm((int) update_delay);
1123 }
1124 pid = waitpid((pid_t)-1,
1125 &status,
1126 nohang ? WNOHANG : 0);
1127 waiterr = errno;
1128 if (!nohang) {
1129 (void) alarm(0);
1130 }
1131 if (pid <= 0) {
1132 if (waiterr == EINTR) {
1133 if (waitflg) {
1134 continue;
1135 } else {
1136 return;
1137 }
1138 } else {
1139 return;
1140 }
1141 }
1142 for (rp = running_list;
1143 (rp != NULL) && (rp->pid != pid);
1144 rp = rp->next) {
1145 ;
1146 }
1147 if (rp == NULL) {
1148 fatal(gettext("Internal error: returned child pid not in running_list"));
1149 } else {
1150 rp->state = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? build_ok : build_failed;
1151 }
1152 nohang = true;
1153 parallel_process_cnt--;
1154
1155 #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
1156 if (job_adjust_mode == ADJUST_M2) {
1157 if (m2_release_job()) {
1158 job_adjust_error();
1159 }
1160 }
1161 #endif
1162 }
1163 }
1164
1165 /*
1166 * finish_children(docheck)
1167 *
1168 * Finishes the processing for all targets which were running
1169 * and have now completed.
1170 *
1171 * Parameters:
1172 * docheck Completely check the finished target
1173 *
1174 * Static variables used:
1175 * running_tail The tail of the running list
1176 *
1177 * Global variables used:
1178 * continue_after_error -k flag
1179 * fatal_in_progress True if we are finishing up after fatal err
1180 * running_list List of running processes
1181 */
1182 void
1183 finish_children(Boolean docheck)
1184 {
1185 int cmds_length;
1186 Property line;
1187 Property line2;
1188 struct stat out_buf;
1189 Running rp;
1190 Running *rp_prev;
1191 Cmd_line rule;
1192 Boolean silent_flag;
1193
1194 for (rp_prev = &running_list, rp = running_list;
1195 rp != NULL;
1196 rp = rp->next) {
1197 bypass_for_loop_inc_4:
1198 /*
1199 * If the state is ok or failed, then this target has
1200 * finished building.
1201 * In parallel_mode, output the accumulated stdout/stderr.
1202 * Read the auto dependency stuff, handle a failed build,
1203 * update the target, then finish the doname process for
1204 * that target.
1205 */
1206 if (rp->state == build_ok || rp->state == build_failed) {
1207 *rp_prev = rp->next;
1208 if (rp->next == NULL) {
1209 running_tail = rp_prev;
1210 }
1211 if ((line2 = rp->command) == NULL) {
1212 line2 = get_prop(rp->target->prop, line_prop);
1213 }
1214
1215
1216 /*
1217 * Check if there were any job output
1218 * from the parallel build.
1219 */
1220 if (rp->stdout_file != NULL) {
1221 if (stat(rp->stdout_file, &out_buf) < 0) {
1222 fatal(gettext("stat of %s failed: %s"),
1223 rp->stdout_file,
1224 errmsg(errno));
1225 }
1226
1227 if ((line2 != NULL) &&
1228 (out_buf.st_size > 0)) {
1229 cmds_length = 0;
1230 for (rule = line2->body.line.command_used,
1231 silent_flag = silent;
1232 rule != NULL;
1233 rule = rule->next) {
1234 cmds_length += rule->command_line->hash.length + 1;
1235 silent_flag = BOOLEAN(silent_flag || rule->silent);
1236 }
1237 if (out_buf.st_size != cmds_length || silent_flag ||
1238 output_mode == txt2_mode) {
1239 dump_out_file(rp->stdout_file, false);
1240 }
1241 }
1242 (void) unlink(rp->stdout_file);
1243 retmem_mb(rp->stdout_file);
1244 rp->stdout_file = NULL;
1245 }
1246
1247 if (!out_err_same && (rp->stderr_file != NULL)) {
1248 if (stat(rp->stderr_file, &out_buf) < 0) {
1249 fatal(gettext("stat of %s failed: %s"),
1250 rp->stderr_file,
1251 errmsg(errno));
1252 }
1253 if ((line2 != NULL) &&
1254 (out_buf.st_size > 0)) {
1255 dump_out_file(rp->stderr_file, true);
1256 }
1257 (void) unlink(rp->stderr_file);
1258 retmem_mb(rp->stderr_file);
1259 rp->stderr_file = NULL;
1260 }
1261
1262 check_state(rp->temp_file);
1263 if (rp->temp_file != NULL) {
1264 free_name(rp->temp_file);
1265 }
1266 rp->temp_file = NULL;
1267 if (rp->state == build_failed) {
1268 line = get_prop(rp->target->prop, line_prop);
1269 if (line != NULL) {
1270 line->body.line.command_used = NULL;
1271 }
1272 if (continue_after_error ||
1273 fatal_in_progress ||
1274 !docheck) {
1275 warning(gettext("Command failed for target `%s'"),
1276 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1277 build_failed_seen = true;
1278 } else {
1279 /*
1280 * XXX??? - DMake needs to exit(),
1281 * but shouldn't call fatal().
1282 */
1283 #ifdef PRINT_EXIT_STATUS
1284 warning("I'm in finish_children. rp->state == build_failed.");
1285 #endif
1286
1287 fatal(gettext("Command failed for target `%s'"),
1288 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1289 }
1290 }
1291 if (!docheck) {
1292 delete_running_struct(rp);
1293 rp = *rp_prev;
1294 if (rp == NULL) {
1295 break;
1296 } else {
1297 goto bypass_for_loop_inc_4;
1298 }
1299 }
1300 update_target(get_prop(rp->target->prop, line_prop),
1301 rp->state);
1302 finish_doname(rp);
1303 delete_running_struct(rp);
1304 rp = *rp_prev;
1305 if (rp == NULL) {
1306 break;
1307 } else {
1308 goto bypass_for_loop_inc_4;
1309 }
1310 } else {
1311 rp_prev = &rp->next;
1312 }
1313 }
1314 }
1315
1316 /*
1317 * dump_out_file(filename, err)
1318 *
1319 * Write the contents of the file to stdout, then unlink the file.
1320 *
1321 * Parameters:
1322 * filename Name of temp file containing output
1323 *
1324 * Global variables used:
1325 */
1326 static void
1327 dump_out_file(char *filename, Boolean err)
1328 {
1329 int chars_read;
1330 char copybuf[BUFSIZ];
1331 int fd;
1332 int out_fd = (err ? 2 : 1);
1333
1334 if ((fd = open(filename, O_RDONLY)) < 0) {
1335 fatal(gettext("open failed for output file %s: %s"),
1336 filename,
1337 errmsg(errno));
1338 }
1339 if (!silent && output_mode != txt2_mode) {
1340 (void) fprintf(err ? stderr : stdout,
1341 err ?
1342 gettext("%s --> Job errors\n") :
1343 gettext("%s --> Job output\n"),
1344 local_host);
1345 (void) fflush(err ? stderr : stdout);
1346 }
1347 for (chars_read = read(fd, copybuf, BUFSIZ);
1348 chars_read > 0;
1349 chars_read = read(fd, copybuf, BUFSIZ)) {
1350 /*
1351 * Read buffers from the source file until end or error.
1352 */
1353 if (write(out_fd, copybuf, chars_read) < 0) {
1354 fatal(gettext("write failed for output file %s: %s"),
1355 filename,
1356 errmsg(errno));
1357 }
1358 }
1359 (void) close(fd);
1360 (void) unlink(filename);
1361 }
1362
1363 /*
1364 * finish_doname(rp)
1365 *
1366 * Completes the processing for a target which was left running.
1367 *
1368 * Parameters:
1369 * rp Running list entry for target
1370 *
1371 * Global variables used:
1372 * debug_level Debug flag
1373 * recursion_level Indentation for debug output
1374 */
1375 static void
1376 finish_doname(Running rp)
1377 {
1378 int auto_count = rp->auto_count;
1379 Name *automatics = rp->automatics;
1380 Doname result = rp->state;
1381 Name target = rp->target;
1382 Name true_target = rp->true_target;
1383 Property *conditionals;
1384
1385 recursion_level = rp->recursion_level;
1386 if (result == build_ok) {
1387 if (true_target == NULL) {
1388 (void) printf("Target = %s\n", target->string_mb);
1389 (void) printf(" State = %d\n", result);
1390 fatal("Internal error: NULL true_target in finish_doname");
1391 }
1392 /* If all went OK, set a nice timestamp */
1393 if (true_target->stat.time == file_doesnt_exist) {
1394 true_target->stat.time = file_max_time;
1395 }
1396 }
1397 target->state = result;
1398 if (target->is_member) {
1399 Property member;
1400
1401 /* Propagate the timestamp from the member file to the member */
1402 if ((target->stat.time != file_max_time) &&
1403 ((member = get_prop(target->prop, member_prop)) != NULL) &&
1404 (exists(member->body.member.member) > file_doesnt_exist)) {
1405 target->stat.time =
1406 /*
1407 exists(member->body.member.member);
1408 */
1409 member->body.member.member->stat.time;
1410 }
1411 }
1412 /*
1413 * Check if we found any new auto dependencies when we
1414 * built the target.
1415 */
1416 if ((result == build_ok) && check_auto_dependencies(target,
1417 auto_count,
1418 automatics)) {
1419 if (debug_level > 0) {
1420 (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"),
1421 recursion_level,
1422 "",
1423 true_target->string_mb);
1424 }
1425 target->rechecking_target = true;
1426 target->state = build_running;
1427
1428 /* [tolik, Tue Mar 25 1997]
1429 * Fix for bug 4038824:
1430 * command line options set by conditional macros get dropped
1431 * rp->conditional_cnt and rp->conditional_targets must be copied
1432 * to new 'rp' during add_pending(). Set_conditionals() stores
1433 * rp->conditional_targets to the global variable 'conditional_targets'
1434 * Add_pending() will use this variable to set up 'rp'.
1435 */
1436 conditionals = set_conditionals(rp->conditional_cnt, rp->conditional_targets);
1437 add_pending(target,
1438 recursion_level,
1439 rp->do_get,
1440 rp->implicit,
1441 true);
1442 reset_conditionals(rp->conditional_cnt, rp->conditional_targets, conditionals);
1443 }
1444 }
1445
1446 /*
1447 * new_running_struct()
1448 *
1449 * Constructor for Running struct. Creates a structure and initializes
1450 * its fields.
1451 *
1452 */
1453 static Running new_running_struct()
1454 {
1455 Running rp;
1456
1457 rp = ALLOC(Running);
1458 rp->target = NULL;
1459 rp->true_target = NULL;
1460 rp->command = NULL;
1461 rp->sprodep_value = NULL;
1462 rp->sprodep_env = NULL;
1463 rp->auto_count = 0;
1464 rp->automatics = NULL;
1465 rp->pid = -1;
1466 rp->job_msg_id = -1;
1467 rp->stdout_file = NULL;
1468 rp->stderr_file = NULL;
1469 rp->temp_file = NULL;
1470 rp->next = NULL;
1471 return rp;
1472 }
1473
1474 /*
1475 * add_running(target, true_target, command, recursion_level, auto_count,
1476 * automatics, do_get, implicit)
1477 *
1478 * Adds a record on the running list for this target, which
1479 * was just spawned and is running.
1480 *
1481 * Parameters:
1482 * target Target being built
1483 * true_target True target for target
1484 * command Running command.
1485 * recursion_level Debug indentation level
1486 * auto_count Count of automatic dependencies
1487 * automatics List of automatic dependencies
1488 * do_get Sccs get flag
1489 * implicit Implicit flag
1490 *
1491 * Static variables used:
1492 * running_tail Tail of running list
1493 * process_running PID of process
1494 *
1495 * Global variables used:
1496 * current_line Current line for target
1497 * current_target Current target being built
1498 * stderr_file Temporary file for stdout
1499 * stdout_file Temporary file for stdout
1500 * temp_file_name Temporary file for auto dependencies
1501 */
1502 void
1503 add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit)
1504 {
1505 Running rp;
1506 Name *p;
1507
1508 rp = new_running_struct();
1509 rp->state = build_running;
1510 rp->target = target;
1511 rp->true_target = true_target;
1512 rp->command = command;
1513 rp->recursion_level = recursion_level;
1514 rp->do_get = do_get;
1515 rp->implicit = implicit;
1516 rp->auto_count = auto_count;
1517 if (auto_count > 0) {
1518 rp->automatics = (Name *) getmem(auto_count * sizeof (Name));
1519 for (p = rp->automatics; auto_count > 0; auto_count--) {
1520 *p++ = *automatics++;
1521 }
1522 } else {
1523 rp->automatics = NULL;
1524 }
1525 {
1526 rp->pid = process_running;
1527 process_running = -1;
1528 childPid = -1;
1529 }
1530 rp->job_msg_id = job_msg_id;
1531 rp->stdout_file = stdout_file;
1532 rp->stderr_file = stderr_file;
1533 rp->temp_file = temp_file_name;
1534 rp->redo = false;
1535 rp->next = NULL;
1536 store_conditionals(rp);
1537 stdout_file = NULL;
1538 stderr_file = NULL;
1539 temp_file_name = NULL;
1540 current_target = NULL;
1541 current_line = NULL;
1542 *running_tail = rp;
1543 running_tail = &rp->next;
1544 }
1545
1546 /*
1547 * add_pending(target, recursion_level, do_get, implicit, redo)
1548 *
1549 * Adds a record on the running list for a pending target
1550 * (waiting for its dependents to finish running).
1551 *
1552 * Parameters:
1553 * target Target being built
1554 * recursion_level Debug indentation level
1555 * do_get Sccs get flag
1556 * implicit Implicit flag
1557 * redo True if this target is being redone
1558 *
1559 * Static variables used:
1560 * running_tail Tail of running list
1561 */
1562 void
1563 add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo)
1564 {
1565 Running rp;
1566 rp = new_running_struct();
1567 rp->state = build_pending;
1568 rp->target = target;
1569 rp->recursion_level = recursion_level;
1570 rp->do_get = do_get;
1571 rp->implicit = implicit;
1572 rp->redo = redo;
1573 store_conditionals(rp);
1574 *running_tail = rp;
1575 running_tail = &rp->next;
1576 }
1577
1578 /*
1579 * add_serial(target, recursion_level, do_get, implicit)
1580 *
1581 * Adds a record on the running list for a target which must be
1582 * executed in serial after others have finished.
1583 *
1584 * Parameters:
1585 * target Target being built
1586 * recursion_level Debug indentation level
1587 * do_get Sccs get flag
1588 * implicit Implicit flag
1589 *
1590 * Static variables used:
1591 * running_tail Tail of running list
1592 */
1593 void
1594 add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1595 {
1596 Running rp;
1597
1598 rp = new_running_struct();
1599 rp->target = target;
1600 rp->recursion_level = recursion_level;
1601 rp->do_get = do_get;
1602 rp->implicit = implicit;
1603 rp->state = build_serial;
1604 rp->redo = false;
1605 store_conditionals(rp);
1606 *running_tail = rp;
1607 running_tail = &rp->next;
1608 }
1609
1610 /*
1611 * add_subtree(target, recursion_level, do_get, implicit)
1612 *
1613 * Adds a record on the running list for a target which must be
1614 * executed in isolation after others have finished.
1615 *
1616 * Parameters:
1617 * target Target being built
1618 * recursion_level Debug indentation level
1619 * do_get Sccs get flag
1620 * implicit Implicit flag
1621 *
1622 * Static variables used:
1623 * running_tail Tail of running list
1624 */
1625 void
1626 add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1627 {
1628 Running rp;
1629
1630 rp = new_running_struct();
1631 rp->target = target;
1632 rp->recursion_level = recursion_level;
1633 rp->do_get = do_get;
1634 rp->implicit = implicit;
1635 rp->state = build_subtree;
1636 rp->redo = false;
1637 store_conditionals(rp);
1638 *running_tail = rp;
1639 running_tail = &rp->next;
1640 }
1641
1642 /*
1643 * store_conditionals(rp)
1644 *
1645 * Creates an array of the currently active targets with conditional
1646 * macros (found in the chain conditional_targets) and puts that
1647 * array in the Running struct.
1648 *
1649 * Parameters:
1650 * rp Running struct for storing chain
1651 *
1652 * Global variables used:
1653 * conditional_targets Chain of current dynamic conditionals
1654 */
1655 static void
1656 store_conditionals(Running rp)
1657 {
1658 int cnt;
1659 Chain cond_name;
1660
1661 if (conditional_targets == NULL) {
1662 rp->conditional_cnt = 0;
1663 rp->conditional_targets = NULL;
1664 return;
1665 }
1666 cnt = 0;
1667 for (cond_name = conditional_targets;
1668 cond_name != NULL;
1669 cond_name = cond_name->next) {
1670 cnt++;
1671 }
1672 rp->conditional_cnt = cnt;
1673 rp->conditional_targets = (Name *) getmem(cnt * sizeof(Name));
1674 for (cond_name = conditional_targets;
1675 cond_name != NULL;
1676 cond_name = cond_name->next) {
1677 rp->conditional_targets[--cnt] = cond_name->name;
1678 }
1679 }
1680
1681 /*
1682 * parallel_ok(target, line_prop_must_exists)
1683 *
1684 * Returns true if the target can be run in parallel
1685 *
1686 * Return value:
1687 * True if can run in parallel
1688 *
1689 * Parameters:
1690 * target Target being tested
1691 *
1692 * Global variables used:
1693 * all_parallel True if all targets default to parallel
1694 * only_parallel True if no targets default to parallel
1695 */
1696 Boolean
1697 parallel_ok(Name target, Boolean line_prop_must_exists)
1698 {
1699 Boolean assign;
1700 Boolean make_refd;
1701 Property line;
1702 Cmd_line rule;
1703
1704 assign = make_refd = false;
1705 if (((line = get_prop(target->prop, line_prop)) == NULL) &&
1706 line_prop_must_exists) {
1707 return false;
1708 }
1709 if (line != NULL) {
1710 for (rule = line->body.line.command_used;
1711 rule != NULL;
1712 rule = rule->next) {
1713 if (rule->assign) {
1714 assign = true;
1715 } else if (rule->make_refd) {
1716 make_refd = true;
1717 }
1718 }
1719 }
1720 if (assign) {
1721 return false;
1722 } else if (target->parallel) {
1723 return true;
1724 } else if (target->no_parallel) {
1725 return false;
1726 } else if (all_parallel) {
1727 return true;
1728 } else if (only_parallel) {
1729 return false;
1730 } else if (make_refd) {
1731 return false;
1732 } else {
1733 return true;
1734 }
1735 }
1736
1737 /*
1738 * is_running(target)
1739 *
1740 * Returns true if the target is running.
1741 *
1742 * Return value:
1743 * True if target is running
1744 *
1745 * Parameters:
1746 * target Target to check
1747 *
1748 * Global variables used:
1749 * running_list List of running processes
1750 */
1751 Boolean
1752 is_running(Name target)
1753 {
1754 Running rp;
1755
1756 if (target->state != build_running) {
1757 return false;
1758 }
1759 for (rp = running_list;
1760 rp != NULL && target != rp->target;
1761 rp = rp->next);
1762 if (rp == NULL) {
1763 return false;
1764 } else {
1765 return (rp->state == build_running) ? true : false;
1766 }
1767 }
1768
1769 /*
1770 * This function replaces the makesh binary.
1771 */
1772
1773
1774 static pid_t
1775 run_rule_commands(char *host, char **commands)
1776 {
1777 Boolean always_exec;
1778 Name command;
1779 Boolean ignore;
1780 int length;
1781 Doname result;
1782 Boolean silent_flag;
1783 wchar_t *tmp_wcs_buffer;
1784
1785 childPid = fork();
1786 switch (childPid) {
1787 case -1: /* Error */
1788 fatal(gettext("Could not fork child process for dmake job: %s"),
1789 errmsg(errno));
1790 break;
1791 case 0: /* Child */
1792 /* To control the processed targets list is not the child's business */
1793 running_list = NULL;
1794 if(out_err_same) {
1795 redirect_io(stdout_file, (char*)NULL);
1796 } else {
1797 redirect_io(stdout_file, stderr_file);
1798 }
1799 for (commands = commands;
1800 (*commands != (char *)NULL);
1801 commands++) {
1802 silent_flag = silent;
1803 ignore = false;
1804 always_exec = false;
1805 while ((**commands == (int) at_char) ||
1806 (**commands == (int) hyphen_char) ||
1807 (**commands == (int) plus_char)) {
1808 if (**commands == (int) at_char) {
1809 silent_flag = true;
1810 }
1811 if (**commands == (int) hyphen_char) {
1812 ignore = true;
1813 }
1814 if (**commands == (int) plus_char) {
1815 always_exec = true;
1816 }
1817 (*commands)++;
1818 }
1819 if ((length = strlen(*commands)) >= MAXPATHLEN) {
1820 tmp_wcs_buffer = ALLOC_WC(length + 1);
1821 (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
1822 command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
1823 retmem(tmp_wcs_buffer);
1824 } else {
1825 MBSTOWCS(wcs_buffer, *commands);
1826 command = GETNAME(wcs_buffer, FIND_LENGTH);
1827 }
1828 if ((command->hash.length > 0) &&
1829 !silent_flag) {
1830 (void) printf("%s\n", command->string_mb);
1831 }
1832 result = dosys(command,
1833 ignore,
1834 false,
1835 false, /* bugs #4085164 & #4990057 */
1836 /* BOOLEAN(silent_flag && ignore), */
1837 always_exec,
1838 (Name) NULL);
1839 if (result == build_failed) {
1840 if (silent_flag) {
1841 (void) printf(gettext("The following command caused the error:\n%s\n"), command->string_mb);
1842 }
1843 if (!ignore) {
1844 _exit(1);
1845 }
1846 }
1847 }
1848 _exit(0);
1849 break;
1850 default:
1851 break;
1852 }
1853 return childPid;
1854 }
1855
1856 static void
1857 maybe_reread_make_state(void)
1858 {
1859 /* Copying dosys()... */
1860 if (report_dependencies_level == 0) {
1861 make_state->stat.time = file_no_time;
1862 (void) exists(make_state);
1863 if (make_state_before == make_state->stat.time) {
1864 return;
1865 }
1866 makefile_type = reading_statefile;
1867 if (read_trace_level > 1) {
1868 trace_reader = true;
1869 }
1870 temp_file_number++;
1871 (void) read_simple_file(make_state,
1872 false,
1873 false,
1874 false,
1875 false,
1876 false,
1877 true);
1878 trace_reader = false;
1879 }
1880 }
1881
1882
1883 static void
1884 delete_running_struct(Running rp)
1885 {
1886 if ((rp->conditional_cnt > 0) &&
1887 (rp->conditional_targets != NULL)) {
1888 retmem_mb((char *) rp->conditional_targets);
1889 }
1890 /**/
1891 if ((rp->auto_count > 0) &&
1892 (rp->automatics != NULL)) {
1893 retmem_mb((char *) rp->automatics);
1894 }
1895 /**/
1896 if(rp->sprodep_value) {
1897 free_name(rp->sprodep_value);
1898 }
1899 if(rp->sprodep_env) {
1900 retmem_mb(rp->sprodep_env);
1901 }
1902 retmem_mb((char *) rp);
1903
1904 }
1905
1906