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