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
execute_parallel(Property line,Boolean waitflg,Boolean local)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
adjust_pmake_max_jobs(int pmake_max_jobs)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
m2_init()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
m2_fini()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
m2_acquire_job()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
m2_release_job()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
job_adjust_fini()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
job_adjust_error()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
job_adjust_init()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
distribute_process(char ** commands,Property line)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
doname_parallel(Name target,Boolean do_get,Boolean implicit)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
doname_subtree(Name target,Boolean do_get,Boolean implicit)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
finish_running(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
process_next(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 *
set_conditionals(int cnt,Name * targets)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
reset_conditionals(int cnt,Name * targets,Property * locals)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
dependency_conflict(Name target)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
await_parallel(Boolean waitflg)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
finish_children(Boolean docheck)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
dump_out_file(char * filename,Boolean err)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
finish_doname(Running rp)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 */
new_running_struct()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
add_running(Name target,Name true_target,Property command,int recursion_level,int auto_count,Name * automatics,Boolean do_get,Boolean implicit)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
add_pending(Name target,int recursion_level,Boolean do_get,Boolean implicit,Boolean redo)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
add_serial(Name target,int recursion_level,Boolean do_get,Boolean implicit)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
add_subtree(Name target,int recursion_level,Boolean do_get,Boolean implicit)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
store_conditionals(Running rp)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
parallel_ok(Name target,Boolean line_prop_must_exists)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
is_running(Name target)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
run_rule_commands(char * host,char ** commands)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
maybe_reread_make_state(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
delete_running_struct(Running rp)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