110d63b7dSRichard Lowe /*
210d63b7dSRichard Lowe * CDDL HEADER START
310d63b7dSRichard Lowe *
410d63b7dSRichard Lowe * The contents of this file are subject to the terms of the
510d63b7dSRichard Lowe * Common Development and Distribution License (the "License").
610d63b7dSRichard Lowe * You may not use this file except in compliance with the License.
710d63b7dSRichard Lowe *
810d63b7dSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7dSRichard Lowe * or http://www.opensolaris.org/os/licensing.
1010d63b7dSRichard Lowe * See the License for the specific language governing permissions
1110d63b7dSRichard Lowe * and limitations under the License.
1210d63b7dSRichard Lowe *
1310d63b7dSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7dSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7dSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
1610d63b7dSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7dSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7dSRichard Lowe *
1910d63b7dSRichard Lowe * CDDL HEADER END
2010d63b7dSRichard Lowe */
2110d63b7dSRichard Lowe /*
2210d63b7dSRichard Lowe * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
2310d63b7dSRichard Lowe * Use is subject to license terms.
2410d63b7dSRichard Lowe */
2510d63b7dSRichard Lowe
2610d63b7dSRichard Lowe
2710d63b7dSRichard Lowe /*
2810d63b7dSRichard Lowe * parallel.cc
2910d63b7dSRichard Lowe *
3010d63b7dSRichard Lowe * Deal with the parallel processing
3110d63b7dSRichard Lowe */
3210d63b7dSRichard Lowe
3310d63b7dSRichard Lowe /*
3410d63b7dSRichard Lowe * Included files
3510d63b7dSRichard Lowe */
3610d63b7dSRichard Lowe #include <errno.h> /* errno */
3710d63b7dSRichard Lowe #include <fcntl.h>
3810d63b7dSRichard Lowe #include <mk/defs.h>
3910d63b7dSRichard Lowe #include <mksh/dosys.h> /* redirect_io() */
4010d63b7dSRichard Lowe #include <mksh/macro.h> /* expand_value() */
4110d63b7dSRichard Lowe #include <mksh/misc.h> /* getmem() */
4210d63b7dSRichard Lowe #include <sys/signal.h>
4310d63b7dSRichard Lowe #include <sys/stat.h>
4410d63b7dSRichard Lowe #include <sys/types.h>
4510d63b7dSRichard Lowe #include <sys/utsname.h>
4610d63b7dSRichard Lowe #include <sys/wait.h>
4710d63b7dSRichard Lowe #include <unistd.h>
4810d63b7dSRichard Lowe #include <netdb.h>
4910d63b7dSRichard Lowe #include <libintl.h>
5010d63b7dSRichard Lowe
5110d63b7dSRichard Lowe
5210d63b7dSRichard Lowe
5310d63b7dSRichard Lowe /*
5410d63b7dSRichard Lowe * Defined macros
5510d63b7dSRichard Lowe */
5610d63b7dSRichard Lowe #define MAXRULES 100
5710d63b7dSRichard Lowe
5810d63b7dSRichard Lowe /*
5910d63b7dSRichard Lowe * This const should be in avo_dms/include/AvoDmakeCommand.h
6010d63b7dSRichard Lowe */
6110d63b7dSRichard Lowe const int local_host_mask = 0x20;
6210d63b7dSRichard Lowe
6310d63b7dSRichard Lowe
6410d63b7dSRichard Lowe /*
6510d63b7dSRichard Lowe * typedefs & structs
6610d63b7dSRichard Lowe */
6710d63b7dSRichard Lowe
6810d63b7dSRichard Lowe
6910d63b7dSRichard Lowe /*
7010d63b7dSRichard Lowe * Static variables
7110d63b7dSRichard Lowe */
7210d63b7dSRichard Lowe static Boolean just_did_subtree = false;
7310d63b7dSRichard Lowe static char local_host[MAXNAMELEN] = "";
7410d63b7dSRichard Lowe static char user_name[MAXNAMELEN] = "";
7510d63b7dSRichard Lowe static int pmake_max_jobs = 0;
7610d63b7dSRichard Lowe static pid_t process_running = -1;
7710d63b7dSRichard Lowe static Running *running_tail = &running_list;
7810d63b7dSRichard Lowe static Name subtree_conflict;
7910d63b7dSRichard Lowe static Name subtree_conflict2;
8010d63b7dSRichard Lowe
8110d63b7dSRichard Lowe
8210d63b7dSRichard Lowe /*
8310d63b7dSRichard Lowe * File table of contents
8410d63b7dSRichard Lowe */
8510d63b7dSRichard Lowe static void delete_running_struct(Running rp);
8610d63b7dSRichard Lowe static Boolean dependency_conflict(Name target);
8710d63b7dSRichard Lowe static Doname distribute_process(char **commands, Property line);
8810d63b7dSRichard Lowe static void doname_subtree(Name target, Boolean do_get, Boolean implicit);
8910d63b7dSRichard Lowe static void dump_out_file(char *filename, Boolean err);
9010d63b7dSRichard Lowe static void finish_doname(Running rp);
9110d63b7dSRichard Lowe static void maybe_reread_make_state(void);
9210d63b7dSRichard Lowe static void process_next(void);
9310d63b7dSRichard Lowe static void reset_conditionals(int cnt, Name *targets, Property *locals);
9410d63b7dSRichard Lowe static pid_t run_rule_commands(char *host, char **commands);
9510d63b7dSRichard Lowe static Property *set_conditionals(int cnt, Name *targets);
9610d63b7dSRichard Lowe static void store_conditionals(Running rp);
9710d63b7dSRichard Lowe
9810d63b7dSRichard Lowe
9910d63b7dSRichard Lowe /*
10010d63b7dSRichard Lowe * execute_parallel(line, waitflg)
10110d63b7dSRichard Lowe *
10210d63b7dSRichard Lowe * DMake 2.x:
10310d63b7dSRichard Lowe * parallel mode: spawns a parallel process to execute the command group.
10410d63b7dSRichard Lowe *
10510d63b7dSRichard Lowe * Return value:
10610d63b7dSRichard Lowe * The result of the execution
10710d63b7dSRichard Lowe *
10810d63b7dSRichard Lowe * Parameters:
10910d63b7dSRichard Lowe * line The command group to execute
11010d63b7dSRichard Lowe */
11110d63b7dSRichard Lowe Doname
execute_parallel(Property line,Boolean waitflg,Boolean local)11210d63b7dSRichard Lowe execute_parallel(Property line, Boolean waitflg, Boolean local)
11310d63b7dSRichard Lowe {
11410d63b7dSRichard Lowe int argcnt;
11510d63b7dSRichard Lowe int cmd_options = 0;
11610d63b7dSRichard Lowe char *commands[MAXRULES + 5];
11710d63b7dSRichard Lowe char *cp;
11810d63b7dSRichard Lowe Name dmake_name;
11910d63b7dSRichard Lowe Name dmake_value;
12010d63b7dSRichard Lowe int ignore;
12110d63b7dSRichard Lowe Name make_machines_name;
12210d63b7dSRichard Lowe char **p;
12310d63b7dSRichard Lowe Property prop;
12410d63b7dSRichard Lowe Doname result = build_ok;
12510d63b7dSRichard Lowe Cmd_line rule;
12610d63b7dSRichard Lowe Boolean silent_flag;
12710d63b7dSRichard Lowe Name target = line->body.line.target;
12810d63b7dSRichard Lowe Boolean wrote_state_file = false;
12910d63b7dSRichard Lowe
13010d63b7dSRichard Lowe if ((pmake_max_jobs == 0) &&
13110d63b7dSRichard Lowe (dmake_mode_type == parallel_mode)) {
13210d63b7dSRichard Lowe if (local_host[0] == '\0') {
13310d63b7dSRichard Lowe (void) gethostname(local_host, MAXNAMELEN);
13410d63b7dSRichard Lowe }
13510d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS");
13610d63b7dSRichard Lowe dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
13710d63b7dSRichard Lowe if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
13810d63b7dSRichard Lowe ((dmake_value = prop->body.macro.value) != NULL)) {
13910d63b7dSRichard Lowe pmake_max_jobs = atoi(dmake_value->string_mb);
14010d63b7dSRichard Lowe if (pmake_max_jobs <= 0) {
14110d63b7dSRichard Lowe warning(gettext("DMAKE_MAX_JOBS cannot be less than or equal to zero."));
14210d63b7dSRichard Lowe warning(gettext("setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS);
14310d63b7dSRichard Lowe pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
14410d63b7dSRichard Lowe }
14510d63b7dSRichard Lowe } else {
14610d63b7dSRichard Lowe /*
14710d63b7dSRichard Lowe * For backwards compatibility w/ PMake 1.x, when
14810d63b7dSRichard Lowe * DMake 2.x is being run in parallel mode, DMake
14910d63b7dSRichard Lowe * should parse the PMake startup file
15010d63b7dSRichard Lowe * $(HOME)/.make.machines to get the pmake_max_jobs.
15110d63b7dSRichard Lowe */
15210d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE");
15310d63b7dSRichard Lowe dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
15410d63b7dSRichard Lowe if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
15510d63b7dSRichard Lowe ((dmake_value = prop->body.macro.value) != NULL)) {
15610d63b7dSRichard Lowe make_machines_name = dmake_value;
15710d63b7dSRichard Lowe } else {
15810d63b7dSRichard Lowe make_machines_name = NULL;
15910d63b7dSRichard Lowe }
16010d63b7dSRichard Lowe if ((pmake_max_jobs = read_make_machines(make_machines_name)) <= 0) {
16110d63b7dSRichard Lowe pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
16210d63b7dSRichard Lowe }
16310d63b7dSRichard Lowe }
16410d63b7dSRichard Lowe }
16510d63b7dSRichard Lowe
16610d63b7dSRichard Lowe if ((dmake_mode_type == serial_mode) ||
16710d63b7dSRichard Lowe ((dmake_mode_type == parallel_mode) && (waitflg))) {
16810d63b7dSRichard Lowe return (execute_serial(line));
16910d63b7dSRichard Lowe }
17010d63b7dSRichard Lowe
17110d63b7dSRichard Lowe {
17210d63b7dSRichard Lowe p = commands;
17310d63b7dSRichard Lowe }
17410d63b7dSRichard Lowe
17510d63b7dSRichard Lowe argcnt = 0;
17610d63b7dSRichard Lowe for (rule = line->body.line.command_used;
17710d63b7dSRichard Lowe rule != NULL;
17810d63b7dSRichard Lowe rule = rule->next) {
17910d63b7dSRichard Lowe if (posix && (touch || quest) && !rule->always_exec) {
18010d63b7dSRichard Lowe continue;
18110d63b7dSRichard Lowe }
18210d63b7dSRichard Lowe if (vpath_defined) {
18310d63b7dSRichard Lowe rule->command_line =
18410d63b7dSRichard Lowe vpath_translation(rule->command_line);
18510d63b7dSRichard Lowe }
186*ae389aa9SAndy Fiddaman
18710d63b7dSRichard Lowe silent_flag = false;
18810d63b7dSRichard Lowe ignore = 0;
18910d63b7dSRichard Lowe
19010d63b7dSRichard Lowe if (rule->command_line->hash.length > 0) {
19110d63b7dSRichard Lowe if (++argcnt == MAXRULES) {
19210d63b7dSRichard Lowe return build_serial;
19310d63b7dSRichard Lowe }
19410d63b7dSRichard Lowe {
19510d63b7dSRichard Lowe if (rule->silent && !silent) {
19610d63b7dSRichard Lowe silent_flag = true;
19710d63b7dSRichard Lowe }
19810d63b7dSRichard Lowe if (rule->ignore_error) {
19910d63b7dSRichard Lowe ignore++;
20010d63b7dSRichard Lowe }
20110d63b7dSRichard Lowe /* XXX - need to add support for + prefix */
20210d63b7dSRichard Lowe if (silent_flag || ignore) {
20310d63b7dSRichard Lowe *p = getmem((silent_flag ? 1 : 0) +
20410d63b7dSRichard Lowe ignore +
20510d63b7dSRichard Lowe (strlen(rule->
20610d63b7dSRichard Lowe command_line->
20710d63b7dSRichard Lowe string_mb)) +
20810d63b7dSRichard Lowe 1);
20910d63b7dSRichard Lowe cp = *p++;
21010d63b7dSRichard Lowe if (silent_flag) {
21110d63b7dSRichard Lowe *cp++ = (int) at_char;
21210d63b7dSRichard Lowe }
21310d63b7dSRichard Lowe if (ignore) {
21410d63b7dSRichard Lowe *cp++ = (int) hyphen_char;
21510d63b7dSRichard Lowe }
21610d63b7dSRichard Lowe (void) strcpy(cp, rule->command_line->string_mb);
21710d63b7dSRichard Lowe } else {
21810d63b7dSRichard Lowe *p++ = rule->command_line->string_mb;
21910d63b7dSRichard Lowe }
22010d63b7dSRichard Lowe }
22110d63b7dSRichard Lowe }
22210d63b7dSRichard Lowe }
22310d63b7dSRichard Lowe if ((argcnt == 0) ||
22410d63b7dSRichard Lowe (report_dependencies_level > 0)) {
22510d63b7dSRichard Lowe return build_ok;
22610d63b7dSRichard Lowe }
22710d63b7dSRichard Lowe {
22810d63b7dSRichard Lowe *p = NULL;
22910d63b7dSRichard Lowe
23010d63b7dSRichard Lowe Doname res = distribute_process(commands, line);
23110d63b7dSRichard Lowe if (res == build_running) {
23210d63b7dSRichard Lowe parallel_process_cnt++;
23310d63b7dSRichard Lowe }
23410d63b7dSRichard Lowe
23510d63b7dSRichard Lowe /*
23610d63b7dSRichard Lowe * Return only those memory that were specially allocated
23710d63b7dSRichard Lowe * for part of commands.
23810d63b7dSRichard Lowe */
23910d63b7dSRichard Lowe for (int i = 0; commands[i] != NULL; i++) {
24010d63b7dSRichard Lowe if ((commands[i][0] == (int) at_char) ||
24110d63b7dSRichard Lowe (commands[i][0] == (int) hyphen_char)) {
24210d63b7dSRichard Lowe retmem_mb(commands[i]);
24310d63b7dSRichard Lowe }
24410d63b7dSRichard Lowe }
24510d63b7dSRichard Lowe return res;
24610d63b7dSRichard Lowe }
24710d63b7dSRichard Lowe }
24810d63b7dSRichard Lowe
24910d63b7dSRichard Lowe
25010d63b7dSRichard Lowe
25110d63b7dSRichard Lowe #include <unistd.h> /* sysconf(_SC_NPROCESSORS_ONLN) */
25210d63b7dSRichard Lowe #include <sys/ipc.h> /* ftok() */
25310d63b7dSRichard Lowe #include <sys/shm.h> /* shmget(), shmat(), shmdt(), shmctl() */
25410d63b7dSRichard Lowe #include <semaphore.h> /* sem_init(), sem_trywait(), sem_post(), sem_destroy() */
25510d63b7dSRichard Lowe #include <sys/loadavg.h> /* getloadavg() */
25610d63b7dSRichard Lowe
25710d63b7dSRichard Lowe /*
25810d63b7dSRichard Lowe * adjust_pmake_max_jobs (int pmake_max_jobs)
25910d63b7dSRichard Lowe *
26010d63b7dSRichard Lowe * Parameters:
261*ae389aa9SAndy Fiddaman * pmake_max_jobs - max jobs limit set by user
26210d63b7dSRichard Lowe *
26310d63b7dSRichard Lowe * External functions used:
26410d63b7dSRichard Lowe * sysconf()
265*ae389aa9SAndy Fiddaman * getloadavg()
26610d63b7dSRichard Lowe */
26710d63b7dSRichard Lowe static int
adjust_pmake_max_jobs(int pmake_max_jobs)26810d63b7dSRichard Lowe adjust_pmake_max_jobs (int pmake_max_jobs)
26910d63b7dSRichard Lowe {
27010d63b7dSRichard Lowe static int ncpu = 0;
27110d63b7dSRichard Lowe double loadavg[3];
27210d63b7dSRichard Lowe int adjustment;
27310d63b7dSRichard Lowe int adjusted_max_jobs;
27410d63b7dSRichard Lowe
27510d63b7dSRichard Lowe if (ncpu <= 0) {
27610d63b7dSRichard Lowe if ((ncpu = sysconf(_SC_NPROCESSORS_ONLN)) <= 0) {
27710d63b7dSRichard Lowe ncpu = 1;
27810d63b7dSRichard Lowe }
27910d63b7dSRichard Lowe }
28010d63b7dSRichard Lowe if (getloadavg(loadavg, 3) != 3) return(pmake_max_jobs);
28110d63b7dSRichard Lowe adjustment = ((int)loadavg[LOADAVG_1MIN]);
28210d63b7dSRichard Lowe if (adjustment < 2) return(pmake_max_jobs);
28310d63b7dSRichard Lowe if (ncpu > 1) {
28410d63b7dSRichard Lowe adjustment = adjustment / ncpu;
28510d63b7dSRichard Lowe }
28610d63b7dSRichard Lowe adjusted_max_jobs = pmake_max_jobs - adjustment;
28710d63b7dSRichard Lowe if (adjusted_max_jobs < 1) adjusted_max_jobs = 1;
28810d63b7dSRichard Lowe return(adjusted_max_jobs);
28910d63b7dSRichard Lowe }
29010d63b7dSRichard Lowe
29110d63b7dSRichard Lowe /*
29210d63b7dSRichard Lowe * M2 adjust mode data and functions
29310d63b7dSRichard Lowe *
29410d63b7dSRichard Lowe * m2_init() - initializes M2 shared semaphore
29510d63b7dSRichard Lowe * m2_acquire_job() - decrements M2 semaphore counter
29610d63b7dSRichard Lowe * m2_release_job() - increments M2 semaphore counter
29710d63b7dSRichard Lowe * m2_fini() - destroys M2 semaphore and shared memory*
29810d63b7dSRichard Lowe *
29910d63b7dSRichard Lowe * Environment variables:
30010d63b7dSRichard Lowe * __DMAKE_M2_FILE__
30110d63b7dSRichard Lowe *
30210d63b7dSRichard Lowe * External functions:
30310d63b7dSRichard Lowe * ftok(), shmget(), shmat(), shmdt(), shmctl()
30410d63b7dSRichard Lowe * sem_init(), sem_trywait(), sem_post(), sem_destroy()
30510d63b7dSRichard Lowe * creat(), close(), unlink()
30610d63b7dSRichard Lowe * getenv(), putenv()
30710d63b7dSRichard Lowe *
30810d63b7dSRichard Lowe * Static variables:
30910d63b7dSRichard Lowe * m2_file - tmp file name to create ipc key for shared memory
31010d63b7dSRichard Lowe * m2_shm_id - shared memory id
31110d63b7dSRichard Lowe * m2_shm_sem - shared memory semaphore
31210d63b7dSRichard Lowe */
31310d63b7dSRichard Lowe
31410d63b7dSRichard Lowe static char m2_file[MAXPATHLEN];
31510d63b7dSRichard Lowe static int m2_shm_id = -1;
31610d63b7dSRichard Lowe static sem_t* m2_shm_sem = 0;
31710d63b7dSRichard Lowe
31810d63b7dSRichard Lowe static int
m2_init()31910d63b7dSRichard Lowe m2_init() {
32010d63b7dSRichard Lowe char *var;
32110d63b7dSRichard Lowe key_t key;
32210d63b7dSRichard Lowe
32310d63b7dSRichard Lowe if ((var = getenv("__DMAKE_M2_FILE__")) == 0) {
32410d63b7dSRichard Lowe /* compose tmp file name */
32510d63b7dSRichard Lowe sprintf(m2_file, "%s/dmake.m2.%d.XXXXXX", tmpdir, getpid());
32610d63b7dSRichard Lowe
32710d63b7dSRichard Lowe /* create tmp file */
32810d63b7dSRichard Lowe int fd = mkstemp(m2_file);
32910d63b7dSRichard Lowe if (fd < 0) {
33010d63b7dSRichard Lowe return -1;
33110d63b7dSRichard Lowe } else {
33210d63b7dSRichard Lowe close(fd);
33310d63b7dSRichard Lowe }
33410d63b7dSRichard Lowe } else {
33510d63b7dSRichard Lowe /* using existing semaphore */
33610d63b7dSRichard Lowe strcpy(m2_file, var);
33710d63b7dSRichard Lowe }
33810d63b7dSRichard Lowe
33910d63b7dSRichard Lowe /* combine IPC key */
34010d63b7dSRichard Lowe if ((key = ftok(m2_file, 38)) == (key_t) -1) {
34110d63b7dSRichard Lowe return -1;
34210d63b7dSRichard Lowe }
34310d63b7dSRichard Lowe
34410d63b7dSRichard Lowe /* create shared memory */
34510d63b7dSRichard Lowe if ((m2_shm_id = shmget(key, sizeof(*m2_shm_sem), 0666 | (var ? 0 : IPC_CREAT|IPC_EXCL))) == -1) {
34610d63b7dSRichard Lowe return -1;
34710d63b7dSRichard Lowe }
34810d63b7dSRichard Lowe
34910d63b7dSRichard Lowe /* attach shared memory */
35010d63b7dSRichard Lowe if ((m2_shm_sem = (sem_t*) shmat(m2_shm_id, 0, 0666)) == (sem_t*)-1) {
35110d63b7dSRichard Lowe return -1;
35210d63b7dSRichard Lowe }
35310d63b7dSRichard Lowe
35410d63b7dSRichard Lowe /* root process */
35510d63b7dSRichard Lowe if (var == 0) {
35610d63b7dSRichard Lowe /* initialize semaphore */
35710d63b7dSRichard Lowe if (sem_init(m2_shm_sem, 1, pmake_max_jobs)) {
35810d63b7dSRichard Lowe return -1;
35910d63b7dSRichard Lowe }
36010d63b7dSRichard Lowe
36110d63b7dSRichard Lowe /* alloc memory for env variable */
36210d63b7dSRichard Lowe if ((var = (char*) malloc(MAXPATHLEN)) == 0) {
36310d63b7dSRichard Lowe return -1;
36410d63b7dSRichard Lowe }
36510d63b7dSRichard Lowe
36610d63b7dSRichard Lowe /* put key to env */
36710d63b7dSRichard Lowe sprintf(var, "__DMAKE_M2_FILE__=%s", m2_file);
36810d63b7dSRichard Lowe if (putenv(var)) {
36910d63b7dSRichard Lowe return -1;
37010d63b7dSRichard Lowe }
37110d63b7dSRichard Lowe }
37210d63b7dSRichard Lowe return 0;
37310d63b7dSRichard Lowe }
37410d63b7dSRichard Lowe
37510d63b7dSRichard Lowe static void
m2_fini()37610d63b7dSRichard Lowe m2_fini() {
37710d63b7dSRichard Lowe if (m2_shm_id >= 0) {
37810d63b7dSRichard Lowe struct shmid_ds stat;
37910d63b7dSRichard Lowe
38010d63b7dSRichard Lowe /* determine the number of attached processes */
38110d63b7dSRichard Lowe if (shmctl(m2_shm_id, IPC_STAT, &stat) == 0) {
38210d63b7dSRichard Lowe if (stat.shm_nattch <= 1) {
38310d63b7dSRichard Lowe /* destroy semaphore */
38410d63b7dSRichard Lowe if (m2_shm_sem != 0) {
38510d63b7dSRichard Lowe (void) sem_destroy(m2_shm_sem);
38610d63b7dSRichard Lowe }
38710d63b7dSRichard Lowe
38810d63b7dSRichard Lowe /* destroy shared memory */
38910d63b7dSRichard Lowe (void) shmctl(m2_shm_id, IPC_RMID, &stat);
39010d63b7dSRichard Lowe
39110d63b7dSRichard Lowe /* remove tmp file created for the key */
39210d63b7dSRichard Lowe (void) unlink(m2_file);
39310d63b7dSRichard Lowe } else {
39410d63b7dSRichard Lowe /* detach shared memory */
39510d63b7dSRichard Lowe if (m2_shm_sem != 0) {
39610d63b7dSRichard Lowe (void) shmdt((char*) m2_shm_sem);
39710d63b7dSRichard Lowe }
39810d63b7dSRichard Lowe }
39910d63b7dSRichard Lowe }
40010d63b7dSRichard Lowe
40110d63b7dSRichard Lowe m2_shm_id = -1;
40210d63b7dSRichard Lowe m2_shm_sem = 0;
40310d63b7dSRichard Lowe }
40410d63b7dSRichard Lowe }
40510d63b7dSRichard Lowe
40610d63b7dSRichard Lowe static int
m2_acquire_job()40710d63b7dSRichard Lowe m2_acquire_job() {
40810d63b7dSRichard Lowe if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
40910d63b7dSRichard Lowe if (sem_trywait(m2_shm_sem) == 0) {
41010d63b7dSRichard Lowe return 1;
41110d63b7dSRichard Lowe }
41210d63b7dSRichard Lowe if (errno == EAGAIN) {
41310d63b7dSRichard Lowe return 0;
41410d63b7dSRichard Lowe }
41510d63b7dSRichard Lowe }
41610d63b7dSRichard Lowe return -1;
41710d63b7dSRichard Lowe }
41810d63b7dSRichard Lowe
41910d63b7dSRichard Lowe static int
m2_release_job()42010d63b7dSRichard Lowe m2_release_job() {
42110d63b7dSRichard Lowe if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
42210d63b7dSRichard Lowe if (sem_post(m2_shm_sem) == 0) {
42310d63b7dSRichard Lowe return 0;
42410d63b7dSRichard Lowe }
42510d63b7dSRichard Lowe }
42610d63b7dSRichard Lowe return -1;
42710d63b7dSRichard Lowe }
42810d63b7dSRichard Lowe
42910d63b7dSRichard Lowe /*
43010d63b7dSRichard Lowe * job adjust mode
43110d63b7dSRichard Lowe *
43210d63b7dSRichard Lowe * Possible values:
43310d63b7dSRichard Lowe * ADJUST_M1 - adjustment by system load (default)
43410d63b7dSRichard Lowe * ADJUST_M2 - fixed limit of jobs for the group of nested dmakes
43510d63b7dSRichard Lowe * ADJUST_NONE - no adjustment - fixed limit of jobs for the current dmake
43610d63b7dSRichard Lowe */
43710d63b7dSRichard Lowe static enum {
43810d63b7dSRichard Lowe ADJUST_UNKNOWN,
43910d63b7dSRichard Lowe ADJUST_M1,
44010d63b7dSRichard Lowe ADJUST_M2,
44110d63b7dSRichard Lowe ADJUST_NONE
44210d63b7dSRichard Lowe } job_adjust_mode = ADJUST_UNKNOWN;
44310d63b7dSRichard Lowe
44410d63b7dSRichard Lowe /*
44510d63b7dSRichard Lowe * void job_adjust_fini()
44610d63b7dSRichard Lowe *
44710d63b7dSRichard Lowe * Description:
44810d63b7dSRichard Lowe * Cleans up job adjust data.
44910d63b7dSRichard Lowe *
45010d63b7dSRichard Lowe * Static variables:
45110d63b7dSRichard Lowe * job_adjust_mode Current job adjust mode
45210d63b7dSRichard Lowe */
45310d63b7dSRichard Lowe void
job_adjust_fini()45410d63b7dSRichard Lowe job_adjust_fini() {
45510d63b7dSRichard Lowe if (job_adjust_mode == ADJUST_M2) {
45610d63b7dSRichard Lowe m2_fini();
45710d63b7dSRichard Lowe }
45810d63b7dSRichard Lowe }
45910d63b7dSRichard Lowe
46010d63b7dSRichard Lowe /*
46110d63b7dSRichard Lowe * void job_adjust_error()
46210d63b7dSRichard Lowe *
46310d63b7dSRichard Lowe * Description:
46410d63b7dSRichard Lowe * Prints warning message, cleans up job adjust data, and disables job adjustment
46510d63b7dSRichard Lowe *
46610d63b7dSRichard Lowe * Environment:
46710d63b7dSRichard Lowe * DMAKE_ADJUST_MAX_JOBS
46810d63b7dSRichard Lowe *
46910d63b7dSRichard Lowe * External functions:
47010d63b7dSRichard Lowe * putenv()
47110d63b7dSRichard Lowe *
47210d63b7dSRichard Lowe * Static variables:
47310d63b7dSRichard Lowe * job_adjust_mode Current job adjust mode
47410d63b7dSRichard Lowe */
47510d63b7dSRichard Lowe static void
job_adjust_error()47610d63b7dSRichard Lowe job_adjust_error() {
47710d63b7dSRichard Lowe if (job_adjust_mode != ADJUST_NONE) {
47810d63b7dSRichard Lowe /* cleanup internals */
47910d63b7dSRichard Lowe job_adjust_fini();
48010d63b7dSRichard Lowe
48110d63b7dSRichard Lowe /* warning message for the user */
48210d63b7dSRichard Lowe warning(gettext("Encountered max jobs auto adjustment error - disabling auto adjustment."));
48310d63b7dSRichard Lowe
48410d63b7dSRichard Lowe /* switch off job adjustment for the children */
48510d63b7dSRichard Lowe putenv(strdup("DMAKE_ADJUST_MAX_JOBS=NO"));
48610d63b7dSRichard Lowe
48710d63b7dSRichard Lowe /* and for this dmake */
48810d63b7dSRichard Lowe job_adjust_mode = ADJUST_NONE;
48910d63b7dSRichard Lowe }
49010d63b7dSRichard Lowe }
49110d63b7dSRichard Lowe
49210d63b7dSRichard Lowe /*
49310d63b7dSRichard Lowe * void job_adjust_init()
49410d63b7dSRichard Lowe *
49510d63b7dSRichard Lowe * Description:
49610d63b7dSRichard Lowe * Parses DMAKE_ADJUST_MAX_JOBS env variable
49710d63b7dSRichard Lowe * and performs appropriate initializations.
49810d63b7dSRichard Lowe *
49910d63b7dSRichard Lowe * Environment:
50010d63b7dSRichard Lowe * DMAKE_ADJUST_MAX_JOBS
50110d63b7dSRichard Lowe * DMAKE_ADJUST_MAX_JOBS == "NO" - no adjustment
50210d63b7dSRichard Lowe * DMAKE_ADJUST_MAX_JOBS == "M2" - M2 adjust mode
50310d63b7dSRichard Lowe * other - M1 adjust mode
50410d63b7dSRichard Lowe *
50510d63b7dSRichard Lowe * External functions:
50610d63b7dSRichard Lowe * getenv()
50710d63b7dSRichard Lowe *
50810d63b7dSRichard Lowe * Static variables:
50910d63b7dSRichard Lowe * job_adjust_mode Current job adjust mode
51010d63b7dSRichard Lowe */
51110d63b7dSRichard Lowe static void
job_adjust_init()51210d63b7dSRichard Lowe job_adjust_init() {
51310d63b7dSRichard Lowe if (job_adjust_mode == ADJUST_UNKNOWN) {
51410d63b7dSRichard Lowe /* default mode */
51510d63b7dSRichard Lowe job_adjust_mode = ADJUST_M1;
51610d63b7dSRichard Lowe
51710d63b7dSRichard Lowe /* determine adjust mode */
51810d63b7dSRichard Lowe if (char *var = getenv("DMAKE_ADJUST_MAX_JOBS")) {
51910d63b7dSRichard Lowe if (strcasecmp(var, "NO") == 0) {
52010d63b7dSRichard Lowe job_adjust_mode = ADJUST_NONE;
52110d63b7dSRichard Lowe } else if (strcasecmp(var, "M2") == 0) {
52210d63b7dSRichard Lowe job_adjust_mode = ADJUST_M2;
52310d63b7dSRichard Lowe }
52410d63b7dSRichard Lowe }
52510d63b7dSRichard Lowe
52610d63b7dSRichard Lowe /* M2 specific initialization */
52710d63b7dSRichard Lowe if (job_adjust_mode == ADJUST_M2) {
52810d63b7dSRichard Lowe if (m2_init()) {
52910d63b7dSRichard Lowe job_adjust_error();
53010d63b7dSRichard Lowe }
53110d63b7dSRichard Lowe }
53210d63b7dSRichard Lowe }
53310d63b7dSRichard Lowe }
53410d63b7dSRichard Lowe
53510d63b7dSRichard Lowe
53610d63b7dSRichard Lowe /*
53710d63b7dSRichard Lowe * distribute_process(char **commands, Property line)
53810d63b7dSRichard Lowe *
53910d63b7dSRichard Lowe * Parameters:
54010d63b7dSRichard Lowe * commands argv vector of commands to execute
54110d63b7dSRichard Lowe *
54210d63b7dSRichard Lowe * Return value:
54310d63b7dSRichard Lowe * The result of the execution
54410d63b7dSRichard Lowe *
54510d63b7dSRichard Lowe * Static variables used:
54610d63b7dSRichard Lowe * process_running Set to the pid of the process set running
54710d63b7dSRichard Lowe * job_adjust_mode Current job adjust mode
54810d63b7dSRichard Lowe */
54910d63b7dSRichard Lowe static Doname
distribute_process(char ** commands,Property line)55010d63b7dSRichard Lowe distribute_process(char **commands, Property line)
55110d63b7dSRichard Lowe {
55210d63b7dSRichard Lowe static unsigned file_number = 0;
55310d63b7dSRichard Lowe wchar_t string[MAXPATHLEN];
55410d63b7dSRichard Lowe char mbstring[MAXPATHLEN];
55510d63b7dSRichard Lowe int filed;
55610d63b7dSRichard Lowe int res;
55710d63b7dSRichard Lowe int tmp_index;
55810d63b7dSRichard Lowe char *tmp_index_str_ptr;
55910d63b7dSRichard Lowe
56010d63b7dSRichard Lowe /* initialize adjust mode, if not initialized */
56110d63b7dSRichard Lowe if (job_adjust_mode == ADJUST_UNKNOWN) {
56210d63b7dSRichard Lowe job_adjust_init();
56310d63b7dSRichard Lowe }
56410d63b7dSRichard Lowe
56510d63b7dSRichard Lowe /* actions depend on adjust mode */
56610d63b7dSRichard Lowe switch (job_adjust_mode) {
56710d63b7dSRichard Lowe case ADJUST_M1:
56810d63b7dSRichard Lowe while (parallel_process_cnt >= adjust_pmake_max_jobs (pmake_max_jobs)) {
56910d63b7dSRichard Lowe await_parallel(false);
57010d63b7dSRichard Lowe finish_children(true);
57110d63b7dSRichard Lowe }
57210d63b7dSRichard Lowe break;
57310d63b7dSRichard Lowe case ADJUST_M2:
57410d63b7dSRichard Lowe if ((res = m2_acquire_job()) == 0) {
57510d63b7dSRichard Lowe if (parallel_process_cnt > 0) {
57610d63b7dSRichard Lowe await_parallel(false);
57710d63b7dSRichard Lowe finish_children(true);
57810d63b7dSRichard Lowe
57910d63b7dSRichard Lowe if ((res = m2_acquire_job()) == 0) {
58010d63b7dSRichard Lowe return build_serial;
58110d63b7dSRichard Lowe }
58210d63b7dSRichard Lowe } else {
58310d63b7dSRichard Lowe return build_serial;
58410d63b7dSRichard Lowe }
58510d63b7dSRichard Lowe }
58610d63b7dSRichard Lowe if (res < 0) {
58710d63b7dSRichard Lowe /* job adjustment error */
58810d63b7dSRichard Lowe job_adjust_error();
58910d63b7dSRichard Lowe
59010d63b7dSRichard Lowe /* no adjustment */
59110d63b7dSRichard Lowe while (parallel_process_cnt >= pmake_max_jobs) {
59210d63b7dSRichard Lowe await_parallel(false);
59310d63b7dSRichard Lowe finish_children(true);
59410d63b7dSRichard Lowe }
59510d63b7dSRichard Lowe }
59610d63b7dSRichard Lowe break;
59710d63b7dSRichard Lowe default:
59810d63b7dSRichard Lowe while (parallel_process_cnt >= pmake_max_jobs) {
59910d63b7dSRichard Lowe await_parallel(false);
60010d63b7dSRichard Lowe finish_children(true);
60110d63b7dSRichard Lowe }
60210d63b7dSRichard Lowe }
60310d63b7dSRichard Lowe
60410d63b7dSRichard Lowe setvar_envvar();
60510d63b7dSRichard Lowe /*
60610d63b7dSRichard Lowe * Tell the user what DMake is doing.
60710d63b7dSRichard Lowe */
60810d63b7dSRichard Lowe if (!silent && output_mode != txt2_mode) {
60910d63b7dSRichard Lowe /*
61010d63b7dSRichard Lowe * Print local_host --> x job(s).
61110d63b7dSRichard Lowe */
61210d63b7dSRichard Lowe (void) fprintf(stdout,
61310d63b7dSRichard Lowe gettext("%s --> %d %s\n"),
61410d63b7dSRichard Lowe local_host,
61510d63b7dSRichard Lowe parallel_process_cnt + 1,
61610d63b7dSRichard Lowe (parallel_process_cnt == 0) ? gettext("job") : gettext("jobs"));
61710d63b7dSRichard Lowe
61810d63b7dSRichard Lowe /* Print command line(s). */
61910d63b7dSRichard Lowe tmp_index = 0;
62010d63b7dSRichard Lowe while (commands[tmp_index] != NULL) {
62110d63b7dSRichard Lowe /* No @ char. */
62210d63b7dSRichard Lowe /* XXX - need to add [2] when + prefix is added */
62310d63b7dSRichard Lowe if ((commands[tmp_index][0] != (int) at_char) &&
62410d63b7dSRichard Lowe (commands[tmp_index][1] != (int) at_char)) {
62510d63b7dSRichard Lowe tmp_index_str_ptr = commands[tmp_index];
62610d63b7dSRichard Lowe if (*tmp_index_str_ptr == (int) hyphen_char) {
62710d63b7dSRichard Lowe tmp_index_str_ptr++;
62810d63b7dSRichard Lowe }
62910d63b7dSRichard Lowe (void) fprintf(stdout, "%s\n", tmp_index_str_ptr);
63010d63b7dSRichard Lowe }
63110d63b7dSRichard Lowe tmp_index++;
63210d63b7dSRichard Lowe }
63310d63b7dSRichard Lowe (void) fflush(stdout);
63410d63b7dSRichard Lowe }
63510d63b7dSRichard Lowe
63610d63b7dSRichard Lowe (void) sprintf(mbstring,
63710d63b7dSRichard Lowe "%s/dmake.stdout.%d.%d.XXXXXX",
63810d63b7dSRichard Lowe tmpdir,
63910d63b7dSRichard Lowe getpid(),
64010d63b7dSRichard Lowe file_number++);
64110d63b7dSRichard Lowe
64210d63b7dSRichard Lowe mktemp(mbstring);
64310d63b7dSRichard Lowe
64410d63b7dSRichard Lowe stdout_file = strdup(mbstring);
64510d63b7dSRichard Lowe stderr_file = NULL;
64610d63b7dSRichard Lowe
64710d63b7dSRichard Lowe if (!out_err_same) {
64810d63b7dSRichard Lowe (void) sprintf(mbstring,
64910d63b7dSRichard Lowe "%s/dmake.stderr.%d.%d.XXXXXX",
65010d63b7dSRichard Lowe tmpdir,
65110d63b7dSRichard Lowe getpid(),
65210d63b7dSRichard Lowe file_number++);
65310d63b7dSRichard Lowe
65410d63b7dSRichard Lowe mktemp(mbstring);
65510d63b7dSRichard Lowe
65610d63b7dSRichard Lowe stderr_file = strdup(mbstring);
65710d63b7dSRichard Lowe }
65810d63b7dSRichard Lowe
65910d63b7dSRichard Lowe process_running = run_rule_commands(local_host, commands);
66010d63b7dSRichard Lowe
66110d63b7dSRichard Lowe return build_running;
66210d63b7dSRichard Lowe }
66310d63b7dSRichard Lowe
66410d63b7dSRichard Lowe /*
66510d63b7dSRichard Lowe * doname_parallel(target, do_get, implicit)
66610d63b7dSRichard Lowe *
66710d63b7dSRichard Lowe * Processes the given target and finishes up any parallel
66810d63b7dSRichard Lowe * processes left running.
66910d63b7dSRichard Lowe *
67010d63b7dSRichard Lowe * Return value:
67110d63b7dSRichard Lowe * Result of target build
67210d63b7dSRichard Lowe *
67310d63b7dSRichard Lowe * Parameters:
67410d63b7dSRichard Lowe * target Target to build
67510d63b7dSRichard Lowe * do_get True if sccs get to be done
67610d63b7dSRichard Lowe * implicit True if this is an implicit target
67710d63b7dSRichard Lowe */
67810d63b7dSRichard Lowe Doname
doname_parallel(Name target,Boolean do_get,Boolean implicit)67910d63b7dSRichard Lowe doname_parallel(Name target, Boolean do_get, Boolean implicit)
68010d63b7dSRichard Lowe {
68110d63b7dSRichard Lowe Doname result;
68210d63b7dSRichard Lowe
68310d63b7dSRichard Lowe result = doname_check(target, do_get, implicit, false);
68410d63b7dSRichard Lowe if (result == build_ok || result == build_failed) {
68510d63b7dSRichard Lowe return result;
68610d63b7dSRichard Lowe }
68710d63b7dSRichard Lowe finish_running();
68810d63b7dSRichard Lowe return (Doname) target->state;
68910d63b7dSRichard Lowe }
69010d63b7dSRichard Lowe
69110d63b7dSRichard Lowe /*
69210d63b7dSRichard Lowe * doname_subtree(target, do_get, implicit)
69310d63b7dSRichard Lowe *
69410d63b7dSRichard Lowe * Completely computes an object and its dependents for a
69510d63b7dSRichard Lowe * serial subtree build.
69610d63b7dSRichard Lowe *
69710d63b7dSRichard Lowe * Parameters:
69810d63b7dSRichard Lowe * target Target to build
69910d63b7dSRichard Lowe * do_get True if sccs get to be done
70010d63b7dSRichard Lowe * implicit True if this is an implicit target
70110d63b7dSRichard Lowe *
70210d63b7dSRichard Lowe * Static variables used:
70310d63b7dSRichard Lowe * running_tail Tail of the list of running processes
70410d63b7dSRichard Lowe *
70510d63b7dSRichard Lowe * Global variables used:
70610d63b7dSRichard Lowe * running_list The list of running processes
70710d63b7dSRichard Lowe */
70810d63b7dSRichard Lowe static void
doname_subtree(Name target,Boolean do_get,Boolean implicit)70910d63b7dSRichard Lowe doname_subtree(Name target, Boolean do_get, Boolean implicit)
71010d63b7dSRichard Lowe {
71110d63b7dSRichard Lowe Running save_running_list;
71210d63b7dSRichard Lowe Running *save_running_tail;
71310d63b7dSRichard Lowe
71410d63b7dSRichard Lowe save_running_list = running_list;
71510d63b7dSRichard Lowe save_running_tail = running_tail;
71610d63b7dSRichard Lowe running_list = NULL;
71710d63b7dSRichard Lowe running_tail = &running_list;
71810d63b7dSRichard Lowe target->state = build_subtree;
71910d63b7dSRichard Lowe target->checking_subtree = true;
72010d63b7dSRichard Lowe while(doname_check(target, do_get, implicit, false) == build_running) {
72110d63b7dSRichard Lowe target->checking_subtree = false;
72210d63b7dSRichard Lowe finish_running();
72310d63b7dSRichard Lowe target->state = build_subtree;
72410d63b7dSRichard Lowe }
72510d63b7dSRichard Lowe target->checking_subtree = false;
72610d63b7dSRichard Lowe running_list = save_running_list;
72710d63b7dSRichard Lowe running_tail = save_running_tail;
72810d63b7dSRichard Lowe }
72910d63b7dSRichard Lowe
73010d63b7dSRichard Lowe /*
73110d63b7dSRichard Lowe * finish_running()
73210d63b7dSRichard Lowe *
73310d63b7dSRichard Lowe * Keeps processing until the running_list is emptied out.
73410d63b7dSRichard Lowe *
73510d63b7dSRichard Lowe * Parameters:
73610d63b7dSRichard Lowe *
73710d63b7dSRichard Lowe * Global variables used:
73810d63b7dSRichard Lowe * running_list The list of running processes
73910d63b7dSRichard Lowe */
74010d63b7dSRichard Lowe void
finish_running(void)74110d63b7dSRichard Lowe finish_running(void)
74210d63b7dSRichard Lowe {
74310d63b7dSRichard Lowe while (running_list != NULL) {
74410d63b7dSRichard Lowe {
74510d63b7dSRichard Lowe await_parallel(false);
74610d63b7dSRichard Lowe finish_children(true);
74710d63b7dSRichard Lowe }
74810d63b7dSRichard Lowe if (running_list != NULL) {
74910d63b7dSRichard Lowe process_next();
75010d63b7dSRichard Lowe }
75110d63b7dSRichard Lowe }
75210d63b7dSRichard Lowe }
75310d63b7dSRichard Lowe
75410d63b7dSRichard Lowe /*
75510d63b7dSRichard Lowe * process_next()
75610d63b7dSRichard Lowe *
75710d63b7dSRichard Lowe * Searches the running list for any targets which can start processing.
75810d63b7dSRichard Lowe * This can be a pending target, a serial target, or a subtree target.
75910d63b7dSRichard Lowe *
76010d63b7dSRichard Lowe * Parameters:
76110d63b7dSRichard Lowe *
76210d63b7dSRichard Lowe * Static variables used:
76310d63b7dSRichard Lowe * running_tail The end of the list of running procs
76410d63b7dSRichard Lowe * subtree_conflict A target which conflicts with a subtree
76510d63b7dSRichard Lowe * subtree_conflict2 The other target which conflicts
76610d63b7dSRichard Lowe *
76710d63b7dSRichard Lowe * Global variables used:
76810d63b7dSRichard Lowe * commands_done True if commands executed
76910d63b7dSRichard Lowe * debug_level Controls debug output
77010d63b7dSRichard Lowe * parallel_process_cnt Number of parallel process running
77110d63b7dSRichard Lowe * recursion_level Indentation for debug output
77210d63b7dSRichard Lowe * running_list List of running processes
77310d63b7dSRichard Lowe */
77410d63b7dSRichard Lowe static void
process_next(void)77510d63b7dSRichard Lowe process_next(void)
77610d63b7dSRichard Lowe {
77710d63b7dSRichard Lowe Running rp;
77810d63b7dSRichard Lowe Running *rp_prev;
77910d63b7dSRichard Lowe Property line;
78010d63b7dSRichard Lowe Chain target_group;
78110d63b7dSRichard Lowe Dependency dep;
78210d63b7dSRichard Lowe Boolean quiescent = true;
78310d63b7dSRichard Lowe Running *subtree_target;
78410d63b7dSRichard Lowe Boolean saved_commands_done;
78510d63b7dSRichard Lowe Property *conditionals;
78610d63b7dSRichard Lowe
78710d63b7dSRichard Lowe subtree_target = NULL;
78810d63b7dSRichard Lowe subtree_conflict = NULL;
78910d63b7dSRichard Lowe subtree_conflict2 = NULL;
79010d63b7dSRichard Lowe /*
79110d63b7dSRichard Lowe * If nothing currently running, build a serial target, if any.
79210d63b7dSRichard Lowe */
79310d63b7dSRichard Lowe start_loop_1:
79410d63b7dSRichard Lowe for (rp_prev = &running_list, rp = running_list;
79510d63b7dSRichard Lowe rp != NULL && parallel_process_cnt == 0;
79610d63b7dSRichard Lowe rp = rp->next) {
79710d63b7dSRichard Lowe if (rp->state == build_serial) {
79810d63b7dSRichard Lowe *rp_prev = rp->next;
79910d63b7dSRichard Lowe if (rp->next == NULL) {
80010d63b7dSRichard Lowe running_tail = rp_prev;
80110d63b7dSRichard Lowe }
80210d63b7dSRichard Lowe recursion_level = rp->recursion_level;
80310d63b7dSRichard Lowe rp->target->state = build_pending;
80410d63b7dSRichard Lowe (void) doname_check(rp->target,
80510d63b7dSRichard Lowe rp->do_get,
80610d63b7dSRichard Lowe rp->implicit,
80710d63b7dSRichard Lowe false);
80810d63b7dSRichard Lowe quiescent = false;
80910d63b7dSRichard Lowe delete_running_struct(rp);
81010d63b7dSRichard Lowe goto start_loop_1;
81110d63b7dSRichard Lowe } else {
81210d63b7dSRichard Lowe rp_prev = &rp->next;
81310d63b7dSRichard Lowe }
81410d63b7dSRichard Lowe }
81510d63b7dSRichard Lowe /*
81610d63b7dSRichard Lowe * Find a target to build. The target must be pending, have all
81710d63b7dSRichard Lowe * its dependencies built, and not be in a target group with a target
81810d63b7dSRichard Lowe * currently building.
81910d63b7dSRichard Lowe */
82010d63b7dSRichard Lowe start_loop_2:
82110d63b7dSRichard Lowe for (rp_prev = &running_list, rp = running_list;
82210d63b7dSRichard Lowe rp != NULL;
82310d63b7dSRichard Lowe rp = rp->next) {
82410d63b7dSRichard Lowe if (!(rp->state == build_pending ||
82510d63b7dSRichard Lowe rp->state == build_subtree)) {
82610d63b7dSRichard Lowe quiescent = false;
82710d63b7dSRichard Lowe rp_prev = &rp->next;
82810d63b7dSRichard Lowe } else if (rp->state == build_pending) {
82910d63b7dSRichard Lowe line = get_prop(rp->target->prop, line_prop);
83010d63b7dSRichard Lowe for (dep = line->body.line.dependencies;
83110d63b7dSRichard Lowe dep != NULL;
83210d63b7dSRichard Lowe dep = dep->next) {
83310d63b7dSRichard Lowe if (dep->name->state == build_running ||
83410d63b7dSRichard Lowe dep->name->state == build_pending ||
83510d63b7dSRichard Lowe dep->name->state == build_serial) {
83610d63b7dSRichard Lowe break;
83710d63b7dSRichard Lowe }
83810d63b7dSRichard Lowe }
83910d63b7dSRichard Lowe if (dep == NULL) {
84010d63b7dSRichard Lowe for (target_group = line->body.line.target_group;
84110d63b7dSRichard Lowe target_group != NULL;
84210d63b7dSRichard Lowe target_group = target_group->next) {
84310d63b7dSRichard Lowe if (is_running(target_group->name)) {
84410d63b7dSRichard Lowe break;
84510d63b7dSRichard Lowe }
84610d63b7dSRichard Lowe }
84710d63b7dSRichard Lowe if (target_group == NULL) {
84810d63b7dSRichard Lowe *rp_prev = rp->next;
84910d63b7dSRichard Lowe if (rp->next == NULL) {
85010d63b7dSRichard Lowe running_tail = rp_prev;
85110d63b7dSRichard Lowe }
85210d63b7dSRichard Lowe recursion_level = rp->recursion_level;
85310d63b7dSRichard Lowe rp->target->state = rp->redo ?
85410d63b7dSRichard Lowe build_dont_know : build_pending;
85510d63b7dSRichard Lowe saved_commands_done = commands_done;
85610d63b7dSRichard Lowe conditionals =
85710d63b7dSRichard Lowe set_conditionals
85810d63b7dSRichard Lowe (rp->conditional_cnt,
85910d63b7dSRichard Lowe rp->conditional_targets);
86010d63b7dSRichard Lowe rp->target->dont_activate_cond_values = true;
86110d63b7dSRichard Lowe if ((doname_check(rp->target,
86210d63b7dSRichard Lowe rp->do_get,
86310d63b7dSRichard Lowe rp->implicit,
86410d63b7dSRichard Lowe rp->target->has_target_prop ? true : false) !=
86510d63b7dSRichard Lowe build_running) &&
86610d63b7dSRichard Lowe !commands_done) {
86710d63b7dSRichard Lowe commands_done =
86810d63b7dSRichard Lowe saved_commands_done;
86910d63b7dSRichard Lowe }
87010d63b7dSRichard Lowe rp->target->dont_activate_cond_values = false;
87110d63b7dSRichard Lowe reset_conditionals
87210d63b7dSRichard Lowe (rp->conditional_cnt,
87310d63b7dSRichard Lowe rp->conditional_targets,
87410d63b7dSRichard Lowe conditionals);
87510d63b7dSRichard Lowe quiescent = false;
87610d63b7dSRichard Lowe delete_running_struct(rp);
87710d63b7dSRichard Lowe goto start_loop_2;
87810d63b7dSRichard Lowe } else {
87910d63b7dSRichard Lowe rp_prev = &rp->next;
88010d63b7dSRichard Lowe }
88110d63b7dSRichard Lowe } else {
88210d63b7dSRichard Lowe rp_prev = &rp->next;
88310d63b7dSRichard Lowe }
88410d63b7dSRichard Lowe } else {
88510d63b7dSRichard Lowe rp_prev = &rp->next;
88610d63b7dSRichard Lowe }
88710d63b7dSRichard Lowe }
88810d63b7dSRichard Lowe /*
88910d63b7dSRichard Lowe * If nothing has been found to build and there exists a subtree
89010d63b7dSRichard Lowe * target with no dependency conflicts, build it.
89110d63b7dSRichard Lowe */
89210d63b7dSRichard Lowe if (quiescent) {
89310d63b7dSRichard Lowe start_loop_3:
89410d63b7dSRichard Lowe for (rp_prev = &running_list, rp = running_list;
89510d63b7dSRichard Lowe rp != NULL;
89610d63b7dSRichard Lowe rp = rp->next) {
89710d63b7dSRichard Lowe if (rp->state == build_subtree) {
89810d63b7dSRichard Lowe if (!dependency_conflict(rp->target)) {
89910d63b7dSRichard Lowe *rp_prev = rp->next;
90010d63b7dSRichard Lowe if (rp->next == NULL) {
90110d63b7dSRichard Lowe running_tail = rp_prev;
90210d63b7dSRichard Lowe }
90310d63b7dSRichard Lowe recursion_level = rp->recursion_level;
90410d63b7dSRichard Lowe doname_subtree(rp->target,
90510d63b7dSRichard Lowe rp->do_get,
90610d63b7dSRichard Lowe rp->implicit);
90710d63b7dSRichard Lowe quiescent = false;
90810d63b7dSRichard Lowe delete_running_struct(rp);
90910d63b7dSRichard Lowe goto start_loop_3;
91010d63b7dSRichard Lowe } else {
91110d63b7dSRichard Lowe subtree_target = rp_prev;
91210d63b7dSRichard Lowe rp_prev = &rp->next;
91310d63b7dSRichard Lowe }
91410d63b7dSRichard Lowe } else {
91510d63b7dSRichard Lowe rp_prev = &rp->next;
91610d63b7dSRichard Lowe }
91710d63b7dSRichard Lowe }
91810d63b7dSRichard Lowe }
91910d63b7dSRichard Lowe /*
92010d63b7dSRichard Lowe * If still nothing found to build, we either have a deadlock
92110d63b7dSRichard Lowe * or a subtree with a dependency conflict with something waiting
92210d63b7dSRichard Lowe * to build.
92310d63b7dSRichard Lowe */
92410d63b7dSRichard Lowe if (quiescent) {
92510d63b7dSRichard Lowe if (subtree_target == NULL) {
92610d63b7dSRichard Lowe fatal(gettext("Internal error: deadlock detected in process_next"));
92710d63b7dSRichard Lowe } else {
92810d63b7dSRichard Lowe rp = *subtree_target;
92910d63b7dSRichard Lowe if (debug_level > 0) {
93010d63b7dSRichard Lowe warning(gettext("Conditional macro conflict encountered for %s between %s and %s"),
93110d63b7dSRichard Lowe subtree_conflict2->string_mb,
93210d63b7dSRichard Lowe rp->target->string_mb,
93310d63b7dSRichard Lowe subtree_conflict->string_mb);
93410d63b7dSRichard Lowe }
93510d63b7dSRichard Lowe *subtree_target = (*subtree_target)->next;
93610d63b7dSRichard Lowe if (rp->next == NULL) {
93710d63b7dSRichard Lowe running_tail = subtree_target;
93810d63b7dSRichard Lowe }
93910d63b7dSRichard Lowe recursion_level = rp->recursion_level;
94010d63b7dSRichard Lowe doname_subtree(rp->target, rp->do_get, rp->implicit);
94110d63b7dSRichard Lowe delete_running_struct(rp);
94210d63b7dSRichard Lowe }
94310d63b7dSRichard Lowe }
94410d63b7dSRichard Lowe }
94510d63b7dSRichard Lowe
94610d63b7dSRichard Lowe /*
94710d63b7dSRichard Lowe * set_conditionals(cnt, targets)
94810d63b7dSRichard Lowe *
94910d63b7dSRichard Lowe * Sets the conditional macros for the targets given in the array of
95010d63b7dSRichard Lowe * targets. The old macro values are returned in an array of
95110d63b7dSRichard Lowe * Properties for later resetting.
95210d63b7dSRichard Lowe *
95310d63b7dSRichard Lowe * Return value:
95410d63b7dSRichard Lowe * Array of conditional macro settings
95510d63b7dSRichard Lowe *
95610d63b7dSRichard Lowe * Parameters:
95710d63b7dSRichard Lowe * cnt Number of targets
95810d63b7dSRichard Lowe * targets Array of targets
95910d63b7dSRichard Lowe */
96010d63b7dSRichard Lowe static Property *
set_conditionals(int cnt,Name * targets)96110d63b7dSRichard Lowe set_conditionals(int cnt, Name *targets)
96210d63b7dSRichard Lowe {
96310d63b7dSRichard Lowe Property *locals, *lp;
96410d63b7dSRichard Lowe Name *tp;
96510d63b7dSRichard Lowe
96610d63b7dSRichard Lowe locals = (Property *) getmem(cnt * sizeof(Property));
96710d63b7dSRichard Lowe for (lp = locals, tp = targets;
96810d63b7dSRichard Lowe cnt > 0;
96910d63b7dSRichard Lowe cnt--, lp++, tp++) {
97010d63b7dSRichard Lowe *lp = (Property) getmem((*tp)->conditional_cnt *
97110d63b7dSRichard Lowe sizeof(struct _Property));
97210d63b7dSRichard Lowe set_locals(*tp, *lp);
97310d63b7dSRichard Lowe }
97410d63b7dSRichard Lowe return locals;
97510d63b7dSRichard Lowe }
97610d63b7dSRichard Lowe
97710d63b7dSRichard Lowe /*
97810d63b7dSRichard Lowe * reset_conditionals(cnt, targets, locals)
97910d63b7dSRichard Lowe *
98010d63b7dSRichard Lowe * Resets the conditional macros as saved in the given array of
98110d63b7dSRichard Lowe * Properties. The resets are done in reverse order. Afterwards the
98210d63b7dSRichard Lowe * data structures are freed.
98310d63b7dSRichard Lowe *
98410d63b7dSRichard Lowe * Parameters:
98510d63b7dSRichard Lowe * cnt Number of targets
98610d63b7dSRichard Lowe * targets Array of targets
98710d63b7dSRichard Lowe * locals Array of dependency macro settings
98810d63b7dSRichard Lowe */
98910d63b7dSRichard Lowe static void
reset_conditionals(int cnt,Name * targets,Property * locals)99010d63b7dSRichard Lowe reset_conditionals(int cnt, Name *targets, Property *locals)
99110d63b7dSRichard Lowe {
99210d63b7dSRichard Lowe Name *tp;
99310d63b7dSRichard Lowe Property *lp;
99410d63b7dSRichard Lowe
99510d63b7dSRichard Lowe for (tp = targets + (cnt - 1), lp = locals + (cnt - 1);
99610d63b7dSRichard Lowe cnt > 0;
99710d63b7dSRichard Lowe cnt--, tp--, lp--) {
99810d63b7dSRichard Lowe reset_locals(*tp,
99910d63b7dSRichard Lowe *lp,
100010d63b7dSRichard Lowe get_prop((*tp)->prop, conditional_prop),
100110d63b7dSRichard Lowe 0);
100210d63b7dSRichard Lowe retmem_mb((caddr_t) *lp);
100310d63b7dSRichard Lowe }
100410d63b7dSRichard Lowe retmem_mb((caddr_t) locals);
100510d63b7dSRichard Lowe }
100610d63b7dSRichard Lowe
100710d63b7dSRichard Lowe /*
100810d63b7dSRichard Lowe * dependency_conflict(target)
100910d63b7dSRichard Lowe *
101010d63b7dSRichard Lowe * Returns true if there is an intersection between
101110d63b7dSRichard Lowe * the subtree of the target and any dependents of the pending targets.
101210d63b7dSRichard Lowe *
101310d63b7dSRichard Lowe * Return value:
101410d63b7dSRichard Lowe * True if conflict found
101510d63b7dSRichard Lowe *
101610d63b7dSRichard Lowe * Parameters:
101710d63b7dSRichard Lowe * target Subtree target to check
101810d63b7dSRichard Lowe *
101910d63b7dSRichard Lowe * Static variables used:
102010d63b7dSRichard Lowe * subtree_conflict Target conflict found
102110d63b7dSRichard Lowe * subtree_conflict2 Second conflict found
102210d63b7dSRichard Lowe *
102310d63b7dSRichard Lowe * Global variables used:
102410d63b7dSRichard Lowe * running_list List of running processes
102510d63b7dSRichard Lowe * wait_name .WAIT, not a real dependency
102610d63b7dSRichard Lowe */
102710d63b7dSRichard Lowe static Boolean
dependency_conflict(Name target)102810d63b7dSRichard Lowe dependency_conflict(Name target)
102910d63b7dSRichard Lowe {
103010d63b7dSRichard Lowe Property line;
103110d63b7dSRichard Lowe Property pending_line;
103210d63b7dSRichard Lowe Dependency dp;
103310d63b7dSRichard Lowe Dependency pending_dp;
103410d63b7dSRichard Lowe Running rp;
103510d63b7dSRichard Lowe
103610d63b7dSRichard Lowe /* Return if we are already checking this target */
103710d63b7dSRichard Lowe if (target->checking_subtree) {
103810d63b7dSRichard Lowe return false;
103910d63b7dSRichard Lowe }
104010d63b7dSRichard Lowe target->checking_subtree = true;
104110d63b7dSRichard Lowe line = get_prop(target->prop, line_prop);
104210d63b7dSRichard Lowe if (line == NULL) {
104310d63b7dSRichard Lowe target->checking_subtree = false;
104410d63b7dSRichard Lowe return false;
104510d63b7dSRichard Lowe }
104610d63b7dSRichard Lowe /* Check each dependency of the target for conflicts */
104710d63b7dSRichard Lowe for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) {
104810d63b7dSRichard Lowe /* Ignore .WAIT dependency */
104910d63b7dSRichard Lowe if (dp->name == wait_name) {
105010d63b7dSRichard Lowe continue;
105110d63b7dSRichard Lowe }
105210d63b7dSRichard Lowe /*
105310d63b7dSRichard Lowe * For each pending target, look for a dependency which
105410d63b7dSRichard Lowe * is the same as a dependency of the subtree target. Since
105510d63b7dSRichard Lowe * we can't build the subtree until all pending targets have
105610d63b7dSRichard Lowe * finished which depend on the same dependency, this is
105710d63b7dSRichard Lowe * a conflict.
105810d63b7dSRichard Lowe */
105910d63b7dSRichard Lowe for (rp = running_list; rp != NULL; rp = rp->next) {
106010d63b7dSRichard Lowe if (rp->state == build_pending) {
106110d63b7dSRichard Lowe pending_line = get_prop(rp->target->prop,
106210d63b7dSRichard Lowe line_prop);
106310d63b7dSRichard Lowe if (pending_line == NULL) {
106410d63b7dSRichard Lowe continue;
106510d63b7dSRichard Lowe }
106610d63b7dSRichard Lowe for(pending_dp = pending_line->
1067*ae389aa9SAndy Fiddaman body.line.dependencies;
106810d63b7dSRichard Lowe pending_dp != NULL;
106910d63b7dSRichard Lowe pending_dp = pending_dp->next) {
107010d63b7dSRichard Lowe if (dp->name == pending_dp->name) {
107110d63b7dSRichard Lowe target->checking_subtree
1072*ae389aa9SAndy Fiddaman = false;
107310d63b7dSRichard Lowe subtree_conflict = rp->target;
107410d63b7dSRichard Lowe subtree_conflict2 = dp->name;
107510d63b7dSRichard Lowe return true;
107610d63b7dSRichard Lowe }
107710d63b7dSRichard Lowe }
107810d63b7dSRichard Lowe }
107910d63b7dSRichard Lowe }
108010d63b7dSRichard Lowe if (dependency_conflict(dp->name)) {
108110d63b7dSRichard Lowe target->checking_subtree = false;
108210d63b7dSRichard Lowe return true;
108310d63b7dSRichard Lowe }
108410d63b7dSRichard Lowe }
108510d63b7dSRichard Lowe target->checking_subtree = false;
108610d63b7dSRichard Lowe return false;
108710d63b7dSRichard Lowe }
108810d63b7dSRichard Lowe
108910d63b7dSRichard Lowe /*
109010d63b7dSRichard Lowe * await_parallel(waitflg)
109110d63b7dSRichard Lowe *
109210d63b7dSRichard Lowe * Waits for parallel children to exit and finishes their processing.
109310d63b7dSRichard Lowe * If waitflg is false, the function returns after update_delay.
109410d63b7dSRichard Lowe *
109510d63b7dSRichard Lowe * Parameters:
109610d63b7dSRichard Lowe * waitflg dwight
109710d63b7dSRichard Lowe */
109810d63b7dSRichard Lowe void
await_parallel(Boolean waitflg)109910d63b7dSRichard Lowe await_parallel(Boolean waitflg)
110010d63b7dSRichard Lowe {
110110d63b7dSRichard Lowe Boolean nohang;
110210d63b7dSRichard Lowe pid_t pid;
110310d63b7dSRichard Lowe int status;
110410d63b7dSRichard Lowe Running rp;
110510d63b7dSRichard Lowe int waiterr;
110610d63b7dSRichard Lowe
110710d63b7dSRichard Lowe nohang = false;
110810d63b7dSRichard Lowe for ( ; ; ) {
110910d63b7dSRichard Lowe if (!nohang) {
111010d63b7dSRichard Lowe (void) alarm((int) update_delay);
111110d63b7dSRichard Lowe }
111210d63b7dSRichard Lowe pid = waitpid((pid_t)-1,
111310d63b7dSRichard Lowe &status,
111410d63b7dSRichard Lowe nohang ? WNOHANG : 0);
111510d63b7dSRichard Lowe waiterr = errno;
111610d63b7dSRichard Lowe if (!nohang) {
111710d63b7dSRichard Lowe (void) alarm(0);
111810d63b7dSRichard Lowe }
111910d63b7dSRichard Lowe if (pid <= 0) {
112010d63b7dSRichard Lowe if (waiterr == EINTR) {
112110d63b7dSRichard Lowe if (waitflg) {
112210d63b7dSRichard Lowe continue;
112310d63b7dSRichard Lowe } else {
112410d63b7dSRichard Lowe return;
112510d63b7dSRichard Lowe }
112610d63b7dSRichard Lowe } else {
112710d63b7dSRichard Lowe return;
112810d63b7dSRichard Lowe }
112910d63b7dSRichard Lowe }
113010d63b7dSRichard Lowe for (rp = running_list;
113110d63b7dSRichard Lowe (rp != NULL) && (rp->pid != pid);
113210d63b7dSRichard Lowe rp = rp->next) {
113310d63b7dSRichard Lowe ;
113410d63b7dSRichard Lowe }
113510d63b7dSRichard Lowe if (rp == NULL) {
113610d63b7dSRichard Lowe fatal(gettext("Internal error: returned child pid not in running_list"));
113710d63b7dSRichard Lowe } else {
113810d63b7dSRichard Lowe rp->state = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? build_ok : build_failed;
113910d63b7dSRichard Lowe }
114010d63b7dSRichard Lowe nohang = true;
114110d63b7dSRichard Lowe parallel_process_cnt--;
114210d63b7dSRichard Lowe
114310d63b7dSRichard Lowe if (job_adjust_mode == ADJUST_M2) {
114410d63b7dSRichard Lowe if (m2_release_job()) {
114510d63b7dSRichard Lowe job_adjust_error();
114610d63b7dSRichard Lowe }
114710d63b7dSRichard Lowe }
114810d63b7dSRichard Lowe }
114910d63b7dSRichard Lowe }
115010d63b7dSRichard Lowe
115110d63b7dSRichard Lowe /*
115210d63b7dSRichard Lowe * finish_children(docheck)
115310d63b7dSRichard Lowe *
115410d63b7dSRichard Lowe * Finishes the processing for all targets which were running
115510d63b7dSRichard Lowe * and have now completed.
115610d63b7dSRichard Lowe *
115710d63b7dSRichard Lowe * Parameters:
115810d63b7dSRichard Lowe * docheck Completely check the finished target
115910d63b7dSRichard Lowe *
116010d63b7dSRichard Lowe * Static variables used:
116110d63b7dSRichard Lowe * running_tail The tail of the running list
116210d63b7dSRichard Lowe *
116310d63b7dSRichard Lowe * Global variables used:
116410d63b7dSRichard Lowe * continue_after_error -k flag
116510d63b7dSRichard Lowe * fatal_in_progress True if we are finishing up after fatal err
116610d63b7dSRichard Lowe * running_list List of running processes
116710d63b7dSRichard Lowe */
116810d63b7dSRichard Lowe void
finish_children(Boolean docheck)116910d63b7dSRichard Lowe finish_children(Boolean docheck)
117010d63b7dSRichard Lowe {
117110d63b7dSRichard Lowe int cmds_length;
117210d63b7dSRichard Lowe Property line;
117310d63b7dSRichard Lowe Property line2;
117410d63b7dSRichard Lowe struct stat out_buf;
117510d63b7dSRichard Lowe Running rp;
117610d63b7dSRichard Lowe Running *rp_prev;
117710d63b7dSRichard Lowe Cmd_line rule;
117810d63b7dSRichard Lowe Boolean silent_flag;
117910d63b7dSRichard Lowe
118010d63b7dSRichard Lowe for (rp_prev = &running_list, rp = running_list;
118110d63b7dSRichard Lowe rp != NULL;
118210d63b7dSRichard Lowe rp = rp->next) {
118310d63b7dSRichard Lowe bypass_for_loop_inc_4:
118410d63b7dSRichard Lowe /*
118510d63b7dSRichard Lowe * If the state is ok or failed, then this target has
118610d63b7dSRichard Lowe * finished building.
118710d63b7dSRichard Lowe * In parallel_mode, output the accumulated stdout/stderr.
118810d63b7dSRichard Lowe * Read the auto dependency stuff, handle a failed build,
118910d63b7dSRichard Lowe * update the target, then finish the doname process for
119010d63b7dSRichard Lowe * that target.
119110d63b7dSRichard Lowe */
119210d63b7dSRichard Lowe if (rp->state == build_ok || rp->state == build_failed) {
119310d63b7dSRichard Lowe *rp_prev = rp->next;
119410d63b7dSRichard Lowe if (rp->next == NULL) {
119510d63b7dSRichard Lowe running_tail = rp_prev;
119610d63b7dSRichard Lowe }
119710d63b7dSRichard Lowe if ((line2 = rp->command) == NULL) {
119810d63b7dSRichard Lowe line2 = get_prop(rp->target->prop, line_prop);
119910d63b7dSRichard Lowe }
120010d63b7dSRichard Lowe
120110d63b7dSRichard Lowe
120210d63b7dSRichard Lowe /*
120310d63b7dSRichard Lowe * Check if there were any job output
120410d63b7dSRichard Lowe * from the parallel build.
120510d63b7dSRichard Lowe */
120610d63b7dSRichard Lowe if (rp->stdout_file != NULL) {
120710d63b7dSRichard Lowe if (stat(rp->stdout_file, &out_buf) < 0) {
120810d63b7dSRichard Lowe fatal(gettext("stat of %s failed: %s"),
120910d63b7dSRichard Lowe rp->stdout_file,
121010d63b7dSRichard Lowe errmsg(errno));
121110d63b7dSRichard Lowe }
121210d63b7dSRichard Lowe
121310d63b7dSRichard Lowe if ((line2 != NULL) &&
121410d63b7dSRichard Lowe (out_buf.st_size > 0)) {
121510d63b7dSRichard Lowe cmds_length = 0;
121610d63b7dSRichard Lowe for (rule = line2->body.line.command_used,
121710d63b7dSRichard Lowe silent_flag = silent;
121810d63b7dSRichard Lowe rule != NULL;
121910d63b7dSRichard Lowe rule = rule->next) {
122010d63b7dSRichard Lowe cmds_length += rule->command_line->hash.length + 1;
122110d63b7dSRichard Lowe silent_flag = BOOLEAN(silent_flag || rule->silent);
122210d63b7dSRichard Lowe }
122310d63b7dSRichard Lowe if (out_buf.st_size != cmds_length || silent_flag ||
122410d63b7dSRichard Lowe output_mode == txt2_mode) {
122510d63b7dSRichard Lowe dump_out_file(rp->stdout_file, false);
122610d63b7dSRichard Lowe }
122710d63b7dSRichard Lowe }
122810d63b7dSRichard Lowe (void) unlink(rp->stdout_file);
122910d63b7dSRichard Lowe retmem_mb(rp->stdout_file);
123010d63b7dSRichard Lowe rp->stdout_file = NULL;
123110d63b7dSRichard Lowe }
123210d63b7dSRichard Lowe
123310d63b7dSRichard Lowe if (!out_err_same && (rp->stderr_file != NULL)) {
123410d63b7dSRichard Lowe if (stat(rp->stderr_file, &out_buf) < 0) {
123510d63b7dSRichard Lowe fatal(gettext("stat of %s failed: %s"),
123610d63b7dSRichard Lowe rp->stderr_file,
123710d63b7dSRichard Lowe errmsg(errno));
123810d63b7dSRichard Lowe }
123910d63b7dSRichard Lowe if ((line2 != NULL) &&
124010d63b7dSRichard Lowe (out_buf.st_size > 0)) {
124110d63b7dSRichard Lowe dump_out_file(rp->stderr_file, true);
124210d63b7dSRichard Lowe }
124310d63b7dSRichard Lowe (void) unlink(rp->stderr_file);
124410d63b7dSRichard Lowe retmem_mb(rp->stderr_file);
124510d63b7dSRichard Lowe rp->stderr_file = NULL;
124610d63b7dSRichard Lowe }
1247*ae389aa9SAndy Fiddaman
124810d63b7dSRichard Lowe check_state(rp->temp_file);
124910d63b7dSRichard Lowe if (rp->temp_file != NULL) {
125010d63b7dSRichard Lowe free_name(rp->temp_file);
125110d63b7dSRichard Lowe }
125210d63b7dSRichard Lowe rp->temp_file = NULL;
125310d63b7dSRichard Lowe if (rp->state == build_failed) {
125410d63b7dSRichard Lowe line = get_prop(rp->target->prop, line_prop);
125510d63b7dSRichard Lowe if (line != NULL) {
125610d63b7dSRichard Lowe line->body.line.command_used = NULL;
125710d63b7dSRichard Lowe }
125810d63b7dSRichard Lowe if (continue_after_error ||
125910d63b7dSRichard Lowe fatal_in_progress ||
126010d63b7dSRichard Lowe !docheck) {
126110d63b7dSRichard Lowe warning(gettext("Command failed for target `%s'"),
126210d63b7dSRichard Lowe rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
126310d63b7dSRichard Lowe build_failed_seen = true;
126410d63b7dSRichard Lowe } else {
126510d63b7dSRichard Lowe /*
126610d63b7dSRichard Lowe * XXX??? - DMake needs to exit(),
126710d63b7dSRichard Lowe * but shouldn't call fatal().
126810d63b7dSRichard Lowe */
126910d63b7dSRichard Lowe #ifdef PRINT_EXIT_STATUS
127010d63b7dSRichard Lowe warning("I'm in finish_children. rp->state == build_failed.");
127110d63b7dSRichard Lowe #endif
127210d63b7dSRichard Lowe
127310d63b7dSRichard Lowe fatal(gettext("Command failed for target `%s'"),
127410d63b7dSRichard Lowe rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
127510d63b7dSRichard Lowe }
127610d63b7dSRichard Lowe }
127710d63b7dSRichard Lowe if (!docheck) {
127810d63b7dSRichard Lowe delete_running_struct(rp);
127910d63b7dSRichard Lowe rp = *rp_prev;
128010d63b7dSRichard Lowe if (rp == NULL) {
128110d63b7dSRichard Lowe break;
128210d63b7dSRichard Lowe } else {
128310d63b7dSRichard Lowe goto bypass_for_loop_inc_4;
128410d63b7dSRichard Lowe }
128510d63b7dSRichard Lowe }
128610d63b7dSRichard Lowe update_target(get_prop(rp->target->prop, line_prop),
128710d63b7dSRichard Lowe rp->state);
128810d63b7dSRichard Lowe finish_doname(rp);
128910d63b7dSRichard Lowe delete_running_struct(rp);
129010d63b7dSRichard Lowe rp = *rp_prev;
129110d63b7dSRichard Lowe if (rp == NULL) {
129210d63b7dSRichard Lowe break;
129310d63b7dSRichard Lowe } else {
129410d63b7dSRichard Lowe goto bypass_for_loop_inc_4;
129510d63b7dSRichard Lowe }
129610d63b7dSRichard Lowe } else {
129710d63b7dSRichard Lowe rp_prev = &rp->next;
129810d63b7dSRichard Lowe }
129910d63b7dSRichard Lowe }
130010d63b7dSRichard Lowe }
130110d63b7dSRichard Lowe
130210d63b7dSRichard Lowe /*
130310d63b7dSRichard Lowe * dump_out_file(filename, err)
130410d63b7dSRichard Lowe *
130510d63b7dSRichard Lowe * Write the contents of the file to stdout, then unlink the file.
130610d63b7dSRichard Lowe *
130710d63b7dSRichard Lowe * Parameters:
130810d63b7dSRichard Lowe * filename Name of temp file containing output
130910d63b7dSRichard Lowe *
131010d63b7dSRichard Lowe * Global variables used:
131110d63b7dSRichard Lowe */
131210d63b7dSRichard Lowe static void
dump_out_file(char * filename,Boolean err)131310d63b7dSRichard Lowe dump_out_file(char *filename, Boolean err)
131410d63b7dSRichard Lowe {
131510d63b7dSRichard Lowe int chars_read;
131610d63b7dSRichard Lowe char copybuf[BUFSIZ];
131710d63b7dSRichard Lowe int fd;
131810d63b7dSRichard Lowe int out_fd = (err ? 2 : 1);
131910d63b7dSRichard Lowe
132010d63b7dSRichard Lowe if ((fd = open(filename, O_RDONLY)) < 0) {
132110d63b7dSRichard Lowe fatal(gettext("open failed for output file %s: %s"),
132210d63b7dSRichard Lowe filename,
132310d63b7dSRichard Lowe errmsg(errno));
132410d63b7dSRichard Lowe }
132510d63b7dSRichard Lowe if (!silent && output_mode != txt2_mode) {
132610d63b7dSRichard Lowe (void) fprintf(err ? stderr : stdout,
132710d63b7dSRichard Lowe err ?
132810d63b7dSRichard Lowe gettext("%s --> Job errors\n") :
132910d63b7dSRichard Lowe gettext("%s --> Job output\n"),
133010d63b7dSRichard Lowe local_host);
133110d63b7dSRichard Lowe (void) fflush(err ? stderr : stdout);
133210d63b7dSRichard Lowe }
133310d63b7dSRichard Lowe for (chars_read = read(fd, copybuf, BUFSIZ);
133410d63b7dSRichard Lowe chars_read > 0;
133510d63b7dSRichard Lowe chars_read = read(fd, copybuf, BUFSIZ)) {
133610d63b7dSRichard Lowe /*
133710d63b7dSRichard Lowe * Read buffers from the source file until end or error.
133810d63b7dSRichard Lowe */
133910d63b7dSRichard Lowe if (write(out_fd, copybuf, chars_read) < 0) {
134010d63b7dSRichard Lowe fatal(gettext("write failed for output file %s: %s"),
134110d63b7dSRichard Lowe filename,
134210d63b7dSRichard Lowe errmsg(errno));
134310d63b7dSRichard Lowe }
134410d63b7dSRichard Lowe }
134510d63b7dSRichard Lowe (void) close(fd);
134610d63b7dSRichard Lowe (void) unlink(filename);
134710d63b7dSRichard Lowe }
134810d63b7dSRichard Lowe
134910d63b7dSRichard Lowe /*
135010d63b7dSRichard Lowe * finish_doname(rp)
135110d63b7dSRichard Lowe *
135210d63b7dSRichard Lowe * Completes the processing for a target which was left running.
135310d63b7dSRichard Lowe *
135410d63b7dSRichard Lowe * Parameters:
135510d63b7dSRichard Lowe * rp Running list entry for target
135610d63b7dSRichard Lowe *
135710d63b7dSRichard Lowe * Global variables used:
135810d63b7dSRichard Lowe * debug_level Debug flag
135910d63b7dSRichard Lowe * recursion_level Indentation for debug output
136010d63b7dSRichard Lowe */
136110d63b7dSRichard Lowe static void
finish_doname(Running rp)136210d63b7dSRichard Lowe finish_doname(Running rp)
136310d63b7dSRichard Lowe {
136410d63b7dSRichard Lowe int auto_count = rp->auto_count;
136510d63b7dSRichard Lowe Name *automatics = rp->automatics;
136610d63b7dSRichard Lowe Doname result = rp->state;
136710d63b7dSRichard Lowe Name target = rp->target;
136810d63b7dSRichard Lowe Name true_target = rp->true_target;
136910d63b7dSRichard Lowe Property *conditionals;
137010d63b7dSRichard Lowe
137110d63b7dSRichard Lowe recursion_level = rp->recursion_level;
137210d63b7dSRichard Lowe if (result == build_ok) {
137310d63b7dSRichard Lowe if (true_target == NULL) {
137410d63b7dSRichard Lowe (void) printf("Target = %s\n", target->string_mb);
137510d63b7dSRichard Lowe (void) printf(" State = %d\n", result);
137610d63b7dSRichard Lowe fatal("Internal error: NULL true_target in finish_doname");
137710d63b7dSRichard Lowe }
137810d63b7dSRichard Lowe /* If all went OK, set a nice timestamp */
137910d63b7dSRichard Lowe if (true_target->stat.time == file_doesnt_exist) {
138010d63b7dSRichard Lowe true_target->stat.time = file_max_time;
138110d63b7dSRichard Lowe }
138210d63b7dSRichard Lowe }
138310d63b7dSRichard Lowe target->state = result;
138410d63b7dSRichard Lowe if (target->is_member) {
138510d63b7dSRichard Lowe Property member;
138610d63b7dSRichard Lowe
138710d63b7dSRichard Lowe /* Propagate the timestamp from the member file to the member */
138810d63b7dSRichard Lowe if ((target->stat.time != file_max_time) &&
138910d63b7dSRichard Lowe ((member = get_prop(target->prop, member_prop)) != NULL) &&
139010d63b7dSRichard Lowe (exists(member->body.member.member) > file_doesnt_exist)) {
139110d63b7dSRichard Lowe target->stat.time =
139210d63b7dSRichard Lowe /*
139310d63b7dSRichard Lowe exists(member->body.member.member);
139410d63b7dSRichard Lowe */
139510d63b7dSRichard Lowe member->body.member.member->stat.time;
139610d63b7dSRichard Lowe }
139710d63b7dSRichard Lowe }
139810d63b7dSRichard Lowe /*
139910d63b7dSRichard Lowe * Check if we found any new auto dependencies when we
140010d63b7dSRichard Lowe * built the target.
140110d63b7dSRichard Lowe */
140210d63b7dSRichard Lowe if ((result == build_ok) && check_auto_dependencies(target,
140310d63b7dSRichard Lowe auto_count,
140410d63b7dSRichard Lowe automatics)) {
140510d63b7dSRichard Lowe if (debug_level > 0) {
140610d63b7dSRichard Lowe (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"),
140710d63b7dSRichard Lowe recursion_level,
140810d63b7dSRichard Lowe "",
140910d63b7dSRichard Lowe true_target->string_mb);
141010d63b7dSRichard Lowe }
141110d63b7dSRichard Lowe target->rechecking_target = true;
141210d63b7dSRichard Lowe target->state = build_running;
141310d63b7dSRichard Lowe
141410d63b7dSRichard Lowe /* [tolik, Tue Mar 25 1997]
141510d63b7dSRichard Lowe * Fix for bug 4038824:
141610d63b7dSRichard Lowe * command line options set by conditional macros get dropped
141710d63b7dSRichard Lowe * rp->conditional_cnt and rp->conditional_targets must be copied
141810d63b7dSRichard Lowe * to new 'rp' during add_pending(). Set_conditionals() stores
141910d63b7dSRichard Lowe * rp->conditional_targets to the global variable 'conditional_targets'
142010d63b7dSRichard Lowe * Add_pending() will use this variable to set up 'rp'.
142110d63b7dSRichard Lowe */
142210d63b7dSRichard Lowe conditionals = set_conditionals(rp->conditional_cnt, rp->conditional_targets);
142310d63b7dSRichard Lowe add_pending(target,
142410d63b7dSRichard Lowe recursion_level,
142510d63b7dSRichard Lowe rp->do_get,
142610d63b7dSRichard Lowe rp->implicit,
142710d63b7dSRichard Lowe true);
142810d63b7dSRichard Lowe reset_conditionals(rp->conditional_cnt, rp->conditional_targets, conditionals);
142910d63b7dSRichard Lowe }
143010d63b7dSRichard Lowe }
143110d63b7dSRichard Lowe
143210d63b7dSRichard Lowe /*
143310d63b7dSRichard Lowe * new_running_struct()
143410d63b7dSRichard Lowe *
143510d63b7dSRichard Lowe * Constructor for Running struct. Creates a structure and initializes
143610d63b7dSRichard Lowe * its fields.
143710d63b7dSRichard Lowe *
143810d63b7dSRichard Lowe */
new_running_struct()143910d63b7dSRichard Lowe static Running new_running_struct()
144010d63b7dSRichard Lowe {
144110d63b7dSRichard Lowe Running rp;
144210d63b7dSRichard Lowe
144310d63b7dSRichard Lowe rp = ALLOC(Running);
144410d63b7dSRichard Lowe rp->target = NULL;
144510d63b7dSRichard Lowe rp->true_target = NULL;
144610d63b7dSRichard Lowe rp->command = NULL;
144710d63b7dSRichard Lowe rp->sprodep_value = NULL;
144810d63b7dSRichard Lowe rp->sprodep_env = NULL;
144910d63b7dSRichard Lowe rp->auto_count = 0;
145010d63b7dSRichard Lowe rp->automatics = NULL;
145110d63b7dSRichard Lowe rp->pid = -1;
145210d63b7dSRichard Lowe rp->job_msg_id = -1;
145310d63b7dSRichard Lowe rp->stdout_file = NULL;
145410d63b7dSRichard Lowe rp->stderr_file = NULL;
145510d63b7dSRichard Lowe rp->temp_file = NULL;
145610d63b7dSRichard Lowe rp->next = NULL;
145710d63b7dSRichard Lowe return rp;
145810d63b7dSRichard Lowe }
145910d63b7dSRichard Lowe
146010d63b7dSRichard Lowe /*
146110d63b7dSRichard Lowe * add_running(target, true_target, command, recursion_level, auto_count,
146210d63b7dSRichard Lowe * automatics, do_get, implicit)
146310d63b7dSRichard Lowe *
146410d63b7dSRichard Lowe * Adds a record on the running list for this target, which
146510d63b7dSRichard Lowe * was just spawned and is running.
146610d63b7dSRichard Lowe *
146710d63b7dSRichard Lowe * Parameters:
146810d63b7dSRichard Lowe * target Target being built
146910d63b7dSRichard Lowe * true_target True target for target
147010d63b7dSRichard Lowe * command Running command.
147110d63b7dSRichard Lowe * recursion_level Debug indentation level
147210d63b7dSRichard Lowe * auto_count Count of automatic dependencies
147310d63b7dSRichard Lowe * automatics List of automatic dependencies
147410d63b7dSRichard Lowe * do_get Sccs get flag
147510d63b7dSRichard Lowe * implicit Implicit flag
147610d63b7dSRichard Lowe *
147710d63b7dSRichard Lowe * Static variables used:
147810d63b7dSRichard Lowe * running_tail Tail of running list
147910d63b7dSRichard Lowe * process_running PID of process
148010d63b7dSRichard Lowe *
148110d63b7dSRichard Lowe * Global variables used:
148210d63b7dSRichard Lowe * current_line Current line for target
148310d63b7dSRichard Lowe * current_target Current target being built
148410d63b7dSRichard Lowe * stderr_file Temporary file for stdout
148510d63b7dSRichard Lowe * stdout_file Temporary file for stdout
148610d63b7dSRichard Lowe * temp_file_name Temporary file for auto dependencies
148710d63b7dSRichard Lowe */
148810d63b7dSRichard Lowe void
add_running(Name target,Name true_target,Property command,int recursion_level,int auto_count,Name * automatics,Boolean do_get,Boolean implicit)148910d63b7dSRichard Lowe add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit)
149010d63b7dSRichard Lowe {
149110d63b7dSRichard Lowe Running rp;
149210d63b7dSRichard Lowe Name *p;
149310d63b7dSRichard Lowe
149410d63b7dSRichard Lowe rp = new_running_struct();
149510d63b7dSRichard Lowe rp->state = build_running;
149610d63b7dSRichard Lowe rp->target = target;
149710d63b7dSRichard Lowe rp->true_target = true_target;
149810d63b7dSRichard Lowe rp->command = command;
149910d63b7dSRichard Lowe rp->recursion_level = recursion_level;
150010d63b7dSRichard Lowe rp->do_get = do_get;
150110d63b7dSRichard Lowe rp->implicit = implicit;
150210d63b7dSRichard Lowe rp->auto_count = auto_count;
150310d63b7dSRichard Lowe if (auto_count > 0) {
150410d63b7dSRichard Lowe rp->automatics = (Name *) getmem(auto_count * sizeof (Name));
150510d63b7dSRichard Lowe for (p = rp->automatics; auto_count > 0; auto_count--) {
150610d63b7dSRichard Lowe *p++ = *automatics++;
150710d63b7dSRichard Lowe }
150810d63b7dSRichard Lowe } else {
150910d63b7dSRichard Lowe rp->automatics = NULL;
151010d63b7dSRichard Lowe }
151110d63b7dSRichard Lowe {
151210d63b7dSRichard Lowe rp->pid = process_running;
151310d63b7dSRichard Lowe process_running = -1;
151410d63b7dSRichard Lowe childPid = -1;
151510d63b7dSRichard Lowe }
151610d63b7dSRichard Lowe rp->job_msg_id = job_msg_id;
151710d63b7dSRichard Lowe rp->stdout_file = stdout_file;
151810d63b7dSRichard Lowe rp->stderr_file = stderr_file;
151910d63b7dSRichard Lowe rp->temp_file = temp_file_name;
152010d63b7dSRichard Lowe rp->redo = false;
152110d63b7dSRichard Lowe rp->next = NULL;
152210d63b7dSRichard Lowe store_conditionals(rp);
152310d63b7dSRichard Lowe stdout_file = NULL;
152410d63b7dSRichard Lowe stderr_file = NULL;
152510d63b7dSRichard Lowe temp_file_name = NULL;
152610d63b7dSRichard Lowe current_target = NULL;
152710d63b7dSRichard Lowe current_line = NULL;
152810d63b7dSRichard Lowe *running_tail = rp;
152910d63b7dSRichard Lowe running_tail = &rp->next;
153010d63b7dSRichard Lowe }
153110d63b7dSRichard Lowe
153210d63b7dSRichard Lowe /*
153310d63b7dSRichard Lowe * add_pending(target, recursion_level, do_get, implicit, redo)
153410d63b7dSRichard Lowe *
153510d63b7dSRichard Lowe * Adds a record on the running list for a pending target
153610d63b7dSRichard Lowe * (waiting for its dependents to finish running).
153710d63b7dSRichard Lowe *
153810d63b7dSRichard Lowe * Parameters:
153910d63b7dSRichard Lowe * target Target being built
154010d63b7dSRichard Lowe * recursion_level Debug indentation level
154110d63b7dSRichard Lowe * do_get Sccs get flag
154210d63b7dSRichard Lowe * implicit Implicit flag
154310d63b7dSRichard Lowe * redo True if this target is being redone
154410d63b7dSRichard Lowe *
154510d63b7dSRichard Lowe * Static variables used:
154610d63b7dSRichard Lowe * running_tail Tail of running list
154710d63b7dSRichard Lowe */
154810d63b7dSRichard Lowe void
add_pending(Name target,int recursion_level,Boolean do_get,Boolean implicit,Boolean redo)154910d63b7dSRichard Lowe add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo)
155010d63b7dSRichard Lowe {
155110d63b7dSRichard Lowe Running rp;
155210d63b7dSRichard Lowe rp = new_running_struct();
155310d63b7dSRichard Lowe rp->state = build_pending;
155410d63b7dSRichard Lowe rp->target = target;
155510d63b7dSRichard Lowe rp->recursion_level = recursion_level;
155610d63b7dSRichard Lowe rp->do_get = do_get;
155710d63b7dSRichard Lowe rp->implicit = implicit;
155810d63b7dSRichard Lowe rp->redo = redo;
155910d63b7dSRichard Lowe store_conditionals(rp);
156010d63b7dSRichard Lowe *running_tail = rp;
156110d63b7dSRichard Lowe running_tail = &rp->next;
156210d63b7dSRichard Lowe }
156310d63b7dSRichard Lowe
156410d63b7dSRichard Lowe /*
156510d63b7dSRichard Lowe * add_serial(target, recursion_level, do_get, implicit)
156610d63b7dSRichard Lowe *
156710d63b7dSRichard Lowe * Adds a record on the running list for a target which must be
156810d63b7dSRichard Lowe * executed in serial after others have finished.
156910d63b7dSRichard Lowe *
157010d63b7dSRichard Lowe * Parameters:
157110d63b7dSRichard Lowe * target Target being built
157210d63b7dSRichard Lowe * recursion_level Debug indentation level
157310d63b7dSRichard Lowe * do_get Sccs get flag
157410d63b7dSRichard Lowe * implicit Implicit flag
157510d63b7dSRichard Lowe *
157610d63b7dSRichard Lowe * Static variables used:
157710d63b7dSRichard Lowe * running_tail Tail of running list
157810d63b7dSRichard Lowe */
157910d63b7dSRichard Lowe void
add_serial(Name target,int recursion_level,Boolean do_get,Boolean implicit)158010d63b7dSRichard Lowe add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit)
158110d63b7dSRichard Lowe {
158210d63b7dSRichard Lowe Running rp;
158310d63b7dSRichard Lowe
158410d63b7dSRichard Lowe rp = new_running_struct();
158510d63b7dSRichard Lowe rp->target = target;
158610d63b7dSRichard Lowe rp->recursion_level = recursion_level;
158710d63b7dSRichard Lowe rp->do_get = do_get;
158810d63b7dSRichard Lowe rp->implicit = implicit;
158910d63b7dSRichard Lowe rp->state = build_serial;
159010d63b7dSRichard Lowe rp->redo = false;
159110d63b7dSRichard Lowe store_conditionals(rp);
159210d63b7dSRichard Lowe *running_tail = rp;
159310d63b7dSRichard Lowe running_tail = &rp->next;
159410d63b7dSRichard Lowe }
159510d63b7dSRichard Lowe
159610d63b7dSRichard Lowe /*
159710d63b7dSRichard Lowe * add_subtree(target, recursion_level, do_get, implicit)
159810d63b7dSRichard Lowe *
159910d63b7dSRichard Lowe * Adds a record on the running list for a target which must be
160010d63b7dSRichard Lowe * executed in isolation after others have finished.
160110d63b7dSRichard Lowe *
160210d63b7dSRichard Lowe * Parameters:
160310d63b7dSRichard Lowe * target Target being built
160410d63b7dSRichard Lowe * recursion_level Debug indentation level
160510d63b7dSRichard Lowe * do_get Sccs get flag
160610d63b7dSRichard Lowe * implicit Implicit flag
160710d63b7dSRichard Lowe *
160810d63b7dSRichard Lowe * Static variables used:
160910d63b7dSRichard Lowe * running_tail Tail of running list
161010d63b7dSRichard Lowe */
161110d63b7dSRichard Lowe void
add_subtree(Name target,int recursion_level,Boolean do_get,Boolean implicit)161210d63b7dSRichard Lowe add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit)
161310d63b7dSRichard Lowe {
161410d63b7dSRichard Lowe Running rp;
161510d63b7dSRichard Lowe
161610d63b7dSRichard Lowe rp = new_running_struct();
161710d63b7dSRichard Lowe rp->target = target;
161810d63b7dSRichard Lowe rp->recursion_level = recursion_level;
161910d63b7dSRichard Lowe rp->do_get = do_get;
162010d63b7dSRichard Lowe rp->implicit = implicit;
162110d63b7dSRichard Lowe rp->state = build_subtree;
162210d63b7dSRichard Lowe rp->redo = false;
162310d63b7dSRichard Lowe store_conditionals(rp);
162410d63b7dSRichard Lowe *running_tail = rp;
162510d63b7dSRichard Lowe running_tail = &rp->next;
162610d63b7dSRichard Lowe }
162710d63b7dSRichard Lowe
162810d63b7dSRichard Lowe /*
162910d63b7dSRichard Lowe * store_conditionals(rp)
163010d63b7dSRichard Lowe *
163110d63b7dSRichard Lowe * Creates an array of the currently active targets with conditional
163210d63b7dSRichard Lowe * macros (found in the chain conditional_targets) and puts that
163310d63b7dSRichard Lowe * array in the Running struct.
163410d63b7dSRichard Lowe *
163510d63b7dSRichard Lowe * Parameters:
163610d63b7dSRichard Lowe * rp Running struct for storing chain
163710d63b7dSRichard Lowe *
163810d63b7dSRichard Lowe * Global variables used:
163910d63b7dSRichard Lowe * conditional_targets Chain of current dynamic conditionals
164010d63b7dSRichard Lowe */
164110d63b7dSRichard Lowe static void
store_conditionals(Running rp)164210d63b7dSRichard Lowe store_conditionals(Running rp)
164310d63b7dSRichard Lowe {
164410d63b7dSRichard Lowe int cnt;
164510d63b7dSRichard Lowe Chain cond_name;
164610d63b7dSRichard Lowe
164710d63b7dSRichard Lowe if (conditional_targets == NULL) {
164810d63b7dSRichard Lowe rp->conditional_cnt = 0;
164910d63b7dSRichard Lowe rp->conditional_targets = NULL;
165010d63b7dSRichard Lowe return;
165110d63b7dSRichard Lowe }
165210d63b7dSRichard Lowe cnt = 0;
165310d63b7dSRichard Lowe for (cond_name = conditional_targets;
165410d63b7dSRichard Lowe cond_name != NULL;
165510d63b7dSRichard Lowe cond_name = cond_name->next) {
165610d63b7dSRichard Lowe cnt++;
165710d63b7dSRichard Lowe }
165810d63b7dSRichard Lowe rp->conditional_cnt = cnt;
165910d63b7dSRichard Lowe rp->conditional_targets = (Name *) getmem(cnt * sizeof(Name));
166010d63b7dSRichard Lowe for (cond_name = conditional_targets;
166110d63b7dSRichard Lowe cond_name != NULL;
166210d63b7dSRichard Lowe cond_name = cond_name->next) {
166310d63b7dSRichard Lowe rp->conditional_targets[--cnt] = cond_name->name;
166410d63b7dSRichard Lowe }
166510d63b7dSRichard Lowe }
166610d63b7dSRichard Lowe
166710d63b7dSRichard Lowe /*
166810d63b7dSRichard Lowe * parallel_ok(target, line_prop_must_exists)
166910d63b7dSRichard Lowe *
167010d63b7dSRichard Lowe * Returns true if the target can be run in parallel
167110d63b7dSRichard Lowe *
167210d63b7dSRichard Lowe * Return value:
167310d63b7dSRichard Lowe * True if can run in parallel
167410d63b7dSRichard Lowe *
167510d63b7dSRichard Lowe * Parameters:
167610d63b7dSRichard Lowe * target Target being tested
167710d63b7dSRichard Lowe *
167810d63b7dSRichard Lowe * Global variables used:
167910d63b7dSRichard Lowe * all_parallel True if all targets default to parallel
168010d63b7dSRichard Lowe * only_parallel True if no targets default to parallel
168110d63b7dSRichard Lowe */
168210d63b7dSRichard Lowe Boolean
parallel_ok(Name target,Boolean line_prop_must_exists)168310d63b7dSRichard Lowe parallel_ok(Name target, Boolean line_prop_must_exists)
168410d63b7dSRichard Lowe {
168510d63b7dSRichard Lowe Boolean assign;
168610d63b7dSRichard Lowe Boolean make_refd;
168710d63b7dSRichard Lowe Property line;
168810d63b7dSRichard Lowe Cmd_line rule;
168910d63b7dSRichard Lowe
169010d63b7dSRichard Lowe assign = make_refd = false;
169110d63b7dSRichard Lowe if (((line = get_prop(target->prop, line_prop)) == NULL) &&
169210d63b7dSRichard Lowe line_prop_must_exists) {
169310d63b7dSRichard Lowe return false;
169410d63b7dSRichard Lowe }
169510d63b7dSRichard Lowe if (line != NULL) {
169610d63b7dSRichard Lowe for (rule = line->body.line.command_used;
169710d63b7dSRichard Lowe rule != NULL;
169810d63b7dSRichard Lowe rule = rule->next) {
169910d63b7dSRichard Lowe if (rule->assign) {
170010d63b7dSRichard Lowe assign = true;
170110d63b7dSRichard Lowe } else if (rule->make_refd) {
170210d63b7dSRichard Lowe make_refd = true;
170310d63b7dSRichard Lowe }
170410d63b7dSRichard Lowe }
170510d63b7dSRichard Lowe }
170610d63b7dSRichard Lowe if (assign) {
170710d63b7dSRichard Lowe return false;
170810d63b7dSRichard Lowe } else if (target->parallel) {
170910d63b7dSRichard Lowe return true;
171010d63b7dSRichard Lowe } else if (target->no_parallel) {
171110d63b7dSRichard Lowe return false;
171210d63b7dSRichard Lowe } else if (all_parallel) {
171310d63b7dSRichard Lowe return true;
171410d63b7dSRichard Lowe } else if (only_parallel) {
171510d63b7dSRichard Lowe return false;
171610d63b7dSRichard Lowe } else if (make_refd) {
171710d63b7dSRichard Lowe return false;
171810d63b7dSRichard Lowe } else {
171910d63b7dSRichard Lowe return true;
172010d63b7dSRichard Lowe }
172110d63b7dSRichard Lowe }
172210d63b7dSRichard Lowe
172310d63b7dSRichard Lowe /*
172410d63b7dSRichard Lowe * is_running(target)
172510d63b7dSRichard Lowe *
172610d63b7dSRichard Lowe * Returns true if the target is running.
172710d63b7dSRichard Lowe *
172810d63b7dSRichard Lowe * Return value:
172910d63b7dSRichard Lowe * True if target is running
173010d63b7dSRichard Lowe *
173110d63b7dSRichard Lowe * Parameters:
173210d63b7dSRichard Lowe * target Target to check
173310d63b7dSRichard Lowe *
173410d63b7dSRichard Lowe * Global variables used:
173510d63b7dSRichard Lowe * running_list List of running processes
173610d63b7dSRichard Lowe */
173710d63b7dSRichard Lowe Boolean
is_running(Name target)173810d63b7dSRichard Lowe is_running(Name target)
173910d63b7dSRichard Lowe {
174010d63b7dSRichard Lowe Running rp;
174110d63b7dSRichard Lowe
174210d63b7dSRichard Lowe if (target->state != build_running) {
174310d63b7dSRichard Lowe return false;
174410d63b7dSRichard Lowe }
174510d63b7dSRichard Lowe for (rp = running_list;
174610d63b7dSRichard Lowe rp != NULL && target != rp->target;
174710d63b7dSRichard Lowe rp = rp->next);
174810d63b7dSRichard Lowe if (rp == NULL) {
174910d63b7dSRichard Lowe return false;
175010d63b7dSRichard Lowe } else {
175110d63b7dSRichard Lowe return (rp->state == build_running) ? true : false;
175210d63b7dSRichard Lowe }
175310d63b7dSRichard Lowe }
175410d63b7dSRichard Lowe
175510d63b7dSRichard Lowe /*
175610d63b7dSRichard Lowe * This function replaces the makesh binary.
175710d63b7dSRichard Lowe */
1758*ae389aa9SAndy Fiddaman
175910d63b7dSRichard Lowe
176010d63b7dSRichard Lowe static pid_t
run_rule_commands(char * host,char ** commands)176110d63b7dSRichard Lowe run_rule_commands(char *host, char **commands)
176210d63b7dSRichard Lowe {
176310d63b7dSRichard Lowe Boolean always_exec;
176410d63b7dSRichard Lowe Name command;
176510d63b7dSRichard Lowe Boolean ignore;
176610d63b7dSRichard Lowe int length;
176710d63b7dSRichard Lowe Doname result;
176810d63b7dSRichard Lowe Boolean silent_flag;
176910d63b7dSRichard Lowe wchar_t *tmp_wcs_buffer;
177010d63b7dSRichard Lowe
177110d63b7dSRichard Lowe childPid = fork();
177210d63b7dSRichard Lowe switch (childPid) {
177310d63b7dSRichard Lowe case -1: /* Error */
177410d63b7dSRichard Lowe fatal(gettext("Could not fork child process for dmake job: %s"),
177510d63b7dSRichard Lowe errmsg(errno));
177610d63b7dSRichard Lowe break;
177710d63b7dSRichard Lowe case 0: /* Child */
177810d63b7dSRichard Lowe /* To control the processed targets list is not the child's business */
177910d63b7dSRichard Lowe running_list = NULL;
178010d63b7dSRichard Lowe if(out_err_same) {
178110d63b7dSRichard Lowe redirect_io(stdout_file, (char*)NULL);
178210d63b7dSRichard Lowe } else {
178310d63b7dSRichard Lowe redirect_io(stdout_file, stderr_file);
178410d63b7dSRichard Lowe }
178510d63b7dSRichard Lowe for (commands = commands;
178610d63b7dSRichard Lowe (*commands != (char *)NULL);
178710d63b7dSRichard Lowe commands++) {
178810d63b7dSRichard Lowe silent_flag = silent;
178910d63b7dSRichard Lowe ignore = false;
179010d63b7dSRichard Lowe always_exec = false;
179110d63b7dSRichard Lowe while ((**commands == (int) at_char) ||
179210d63b7dSRichard Lowe (**commands == (int) hyphen_char) ||
179310d63b7dSRichard Lowe (**commands == (int) plus_char)) {
179410d63b7dSRichard Lowe if (**commands == (int) at_char) {
179510d63b7dSRichard Lowe silent_flag = true;
179610d63b7dSRichard Lowe }
179710d63b7dSRichard Lowe if (**commands == (int) hyphen_char) {
179810d63b7dSRichard Lowe ignore = true;
179910d63b7dSRichard Lowe }
180010d63b7dSRichard Lowe if (**commands == (int) plus_char) {
180110d63b7dSRichard Lowe always_exec = true;
180210d63b7dSRichard Lowe }
180310d63b7dSRichard Lowe (*commands)++;
180410d63b7dSRichard Lowe }
180510d63b7dSRichard Lowe if ((length = strlen(*commands)) >= MAXPATHLEN) {
180610d63b7dSRichard Lowe tmp_wcs_buffer = ALLOC_WC(length + 1);
180710d63b7dSRichard Lowe (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
180810d63b7dSRichard Lowe command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
180910d63b7dSRichard Lowe retmem(tmp_wcs_buffer);
181010d63b7dSRichard Lowe } else {
181110d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, *commands);
181210d63b7dSRichard Lowe command = GETNAME(wcs_buffer, FIND_LENGTH);
181310d63b7dSRichard Lowe }
181410d63b7dSRichard Lowe if ((command->hash.length > 0) &&
181510d63b7dSRichard Lowe !silent_flag) {
181610d63b7dSRichard Lowe (void) printf("%s\n", command->string_mb);
181710d63b7dSRichard Lowe }
181810d63b7dSRichard Lowe result = dosys(command,
181910d63b7dSRichard Lowe ignore,
182010d63b7dSRichard Lowe false,
182110d63b7dSRichard Lowe false, /* bugs #4085164 & #4990057 */
182210d63b7dSRichard Lowe /* BOOLEAN(silent_flag && ignore), */
1823*ae389aa9SAndy Fiddaman always_exec,
182410d63b7dSRichard Lowe (Name) NULL);
182510d63b7dSRichard Lowe if (result == build_failed) {
182610d63b7dSRichard Lowe if (silent_flag) {
182710d63b7dSRichard Lowe (void) printf(gettext("The following command caused the error:\n%s\n"), command->string_mb);
182810d63b7dSRichard Lowe }
182910d63b7dSRichard Lowe if (!ignore) {
183010d63b7dSRichard Lowe _exit(1);
183110d63b7dSRichard Lowe }
183210d63b7dSRichard Lowe }
183310d63b7dSRichard Lowe }
183410d63b7dSRichard Lowe _exit(0);
183510d63b7dSRichard Lowe break;
183610d63b7dSRichard Lowe default:
183710d63b7dSRichard Lowe break;
183810d63b7dSRichard Lowe }
183910d63b7dSRichard Lowe return childPid;
184010d63b7dSRichard Lowe }
184110d63b7dSRichard Lowe
184210d63b7dSRichard Lowe static void
maybe_reread_make_state(void)184310d63b7dSRichard Lowe maybe_reread_make_state(void)
184410d63b7dSRichard Lowe {
184510d63b7dSRichard Lowe /* Copying dosys()... */
184610d63b7dSRichard Lowe if (report_dependencies_level == 0) {
184710d63b7dSRichard Lowe make_state->stat.time = file_no_time;
184810d63b7dSRichard Lowe (void) exists(make_state);
184910d63b7dSRichard Lowe if (make_state_before == make_state->stat.time) {
185010d63b7dSRichard Lowe return;
185110d63b7dSRichard Lowe }
185210d63b7dSRichard Lowe makefile_type = reading_statefile;
185310d63b7dSRichard Lowe if (read_trace_level > 1) {
185410d63b7dSRichard Lowe trace_reader = true;
185510d63b7dSRichard Lowe }
185610d63b7dSRichard Lowe temp_file_number++;
185710d63b7dSRichard Lowe (void) read_simple_file(make_state,
185810d63b7dSRichard Lowe false,
185910d63b7dSRichard Lowe false,
186010d63b7dSRichard Lowe false,
186110d63b7dSRichard Lowe false,
186210d63b7dSRichard Lowe false,
186310d63b7dSRichard Lowe true);
186410d63b7dSRichard Lowe trace_reader = false;
186510d63b7dSRichard Lowe }
186610d63b7dSRichard Lowe }
186710d63b7dSRichard Lowe
186810d63b7dSRichard Lowe
186910d63b7dSRichard Lowe static void
delete_running_struct(Running rp)187010d63b7dSRichard Lowe delete_running_struct(Running rp)
187110d63b7dSRichard Lowe {
187210d63b7dSRichard Lowe if ((rp->conditional_cnt > 0) &&
187310d63b7dSRichard Lowe (rp->conditional_targets != NULL)) {
187410d63b7dSRichard Lowe retmem_mb((char *) rp->conditional_targets);
187510d63b7dSRichard Lowe }
187610d63b7dSRichard Lowe /**/
187710d63b7dSRichard Lowe if ((rp->auto_count > 0) &&
187810d63b7dSRichard Lowe (rp->automatics != NULL)) {
187910d63b7dSRichard Lowe retmem_mb((char *) rp->automatics);
188010d63b7dSRichard Lowe }
188110d63b7dSRichard Lowe /**/
188210d63b7dSRichard Lowe if(rp->sprodep_value) {
188310d63b7dSRichard Lowe free_name(rp->sprodep_value);
188410d63b7dSRichard Lowe }
188510d63b7dSRichard Lowe if(rp->sprodep_env) {
188610d63b7dSRichard Lowe retmem_mb(rp->sprodep_env);
188710d63b7dSRichard Lowe }
188810d63b7dSRichard Lowe retmem_mb((char *) rp);
188910d63b7dSRichard Lowe
189010d63b7dSRichard Lowe }
189110d63b7dSRichard Lowe
189210d63b7dSRichard Lowe
1893