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