]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/make1.cpp
332b91cc5723967a1143786f5b260ed0412497d8
[ceph.git] / ceph / src / boost / tools / build / src / engine / make1.cpp
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3 *
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6
7 /* This file is ALSO:
8 * Copyright 2022 René Ferdinand Rivera Morell
9 * Copyright 2001-2004 David Abrahams.
10 * Distributed under the Boost Software License, Version 1.0.
11 * (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)
12 */
13
14 /*
15 * make1.c - execute commands to bring targets up to date
16 *
17 * This module contains make1(), the entry point called by make() to recursively
18 * descend the dependency graph executing update actions as marked by make0().
19 *
20 * External routines:
21 * make1() - execute commands to update a TARGET and all of its dependencies
22 *
23 * Internal routines, the recursive/asynchronous command executors:
24 * make1a() - recursively schedules dependency builds and then goes to
25 * MAKE1B
26 * make1b() - if nothing is blocking this target's build, proceed to
27 * MAKE1C
28 * make1c() - launch target's next command, or go to parents' MAKE1B
29 * if none
30 * make1c_closure() - handle command execution completion and go to MAKE1C
31 *
32 * Internal support routines:
33 * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc.
34 * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
35 * make1settings() - for vars with bound values, build up replacement lists
36 * make1bind() - bind targets that weren't bound in dependency analysis
37 */
38
39 #include "jam.h"
40 #include "make.h"
41
42 #include "command.h"
43 #include "compile.h"
44 #include "execcmd.h"
45 #include "headers.h"
46 #include "lists.h"
47 #include "object.h"
48 #include "output.h"
49 #include "parse.h"
50 #include "rules.h"
51 #include "search.h"
52 #include "variable.h"
53 #include "output.h"
54 #include "startup.h"
55
56 #include <assert.h>
57 #include <stdlib.h>
58
59 #if !defined( NT ) || defined( __GNUC__ )
60 #include <unistd.h> /* for unlink */
61 #endif
62
63 static CMD * make1cmds ( TARGET * );
64 static LIST * make1list ( LIST *, const targets_uptr &, int32_t flags );
65 static SETTINGS * make1settings ( struct module_t *, LIST * vars );
66 static void make1bind ( TARGET * );
67 static void push_cmds( CMDLIST * cmds, int32_t status );
68 static int32_t cmd_sem_lock( TARGET * t );
69 static void cmd_sem_unlock( TARGET * t );
70
71 static bool targets_contains( const targets_uptr & l, TARGET * t );
72 static bool targets_equal( const targets_uptr & l1, const targets_uptr & l2 );
73
74 /* Ugly static - it is too hard to carry it through the callbacks. */
75
76 static struct
77 {
78 int32_t failed;
79 int32_t skipped;
80 int32_t total;
81 int32_t made;
82 } counts[ 1 ];
83
84 /* Target state. */
85 #define T_STATE_MAKE1A 0 /* make1a() should be called */
86 #define T_STATE_MAKE1B 1 /* make1b() should be called */
87 #define T_STATE_MAKE1C 2 /* make1c() should be called */
88
89 typedef struct _state state;
90 struct _state
91 {
92 state * prev; /* previous state on stack */
93 TARGET * t; /* current target */
94 TARGET * parent; /* parent argument necessary for MAKE1A */
95 int32_t curstate; /* current state */
96 };
97
98 static void make1a( state * const );
99 static void make1b( state * const );
100 static void make1c( state const * const );
101
102 static void make1c_closure( void * const closure, int32_t status,
103 timing_info const * const, char const * const cmd_stdout,
104 char const * const cmd_stderr, int32_t const cmd_exit_reason );
105
106 typedef struct _stack
107 {
108 state * stack;
109 } stack;
110
111 static stack state_stack = { NULL };
112
113 static state * state_freelist = NULL;
114
115 /* Currently running command counter. */
116 static int32_t cmdsrunning;
117
118
119 static state * alloc_state()
120 {
121 if ( state_freelist )
122 {
123 state * const pState = state_freelist;
124 state_freelist = pState->prev;
125 memset( pState, 0, sizeof( state ) );
126 return pState;
127 }
128 return (state *)BJAM_MALLOC( sizeof( state ) );
129 }
130
131
132 static void free_state( state * const pState )
133 {
134 pState->prev = state_freelist;
135 state_freelist = pState;
136 }
137
138
139 static void clear_state_freelist()
140 {
141 while ( state_freelist )
142 {
143 state * const pState = state_freelist;
144 state_freelist = state_freelist->prev;
145 BJAM_FREE( pState );
146 }
147 }
148
149
150 static state * current_state( stack * const pStack )
151 {
152 return pStack->stack;
153 }
154
155
156 static void pop_state( stack * const pStack )
157 {
158 if ( pStack->stack )
159 {
160 state * const pState = pStack->stack->prev;
161 free_state( pStack->stack );
162 pStack->stack = pState;
163 }
164 }
165
166
167 static state * push_state( stack * const pStack, TARGET * const t,
168 TARGET * const parent, int32_t const curstate )
169 {
170 state * const pState = alloc_state();
171 pState->t = t;
172 pState->parent = parent;
173 pState->prev = pStack->stack;
174 pState->curstate = curstate;
175 return pStack->stack = pState;
176 }
177
178
179 /*
180 * Pushes a stack onto another stack, effectively reversing the order.
181 */
182
183 static void push_stack_on_stack( stack * const pDest, stack * const pSrc )
184 {
185 while ( pSrc->stack )
186 {
187 state * const pState = pSrc->stack;
188 pSrc->stack = pState->prev;
189 pState->prev = pDest->stack;
190 pDest->stack = pState;
191 }
192 }
193
194
195 /*
196 * make1() - execute commands to update a list of targets and all of their dependencies
197 */
198
199 static int32_t intr = 0;
200 static int32_t quit = 0;
201
202 int32_t make1( LIST * targets )
203 {
204 state * pState;
205 int32_t status = 0;
206
207 memset( (char *)counts, 0, sizeof( *counts ) );
208
209 {
210 LISTITER iter, end;
211 stack temp_stack = { NULL };
212 for ( iter = list_begin( targets ), end = list_end( targets );
213 iter != end; iter = list_next( iter ) )
214 push_state( &temp_stack, bindtarget( list_item( iter ) ), NULL, T_STATE_MAKE1A );
215 push_stack_on_stack( &state_stack, &temp_stack );
216 }
217
218 /* Clear any state left over from the past */
219 quit = 0;
220
221 /* Recursively make the target and its dependencies. */
222
223 while ( 1 )
224 {
225 while ( ( pState = current_state( &state_stack ) ) )
226 {
227 if ( quit )
228 pop_state( &state_stack );
229
230 switch ( pState->curstate )
231 {
232 case T_STATE_MAKE1A: make1a( pState ); break;
233 case T_STATE_MAKE1B: make1b( pState ); break;
234 case T_STATE_MAKE1C: make1c( pState ); break;
235 default:
236 assert( !"make1(): Invalid state detected." );
237 }
238 }
239 if ( !cmdsrunning )
240 break;
241 /* Wait for outstanding commands to finish running. */
242 exec_wait();
243 }
244
245 clear_state_freelist();
246
247 /* Talk about it. */
248 if ( counts->failed )
249 out_printf( "...failed updating %d target%s...\n", counts->failed,
250 counts->failed > 1 ? "s" : "" );
251 if ( DEBUG_MAKE && counts->skipped )
252 out_printf( "...skipped %d target%s...\n", counts->skipped,
253 counts->skipped > 1 ? "s" : "" );
254 if ( DEBUG_MAKE && counts->made )
255 out_printf( "...updated %d target%s...\n", counts->made,
256 counts->made > 1 ? "s" : "" );
257
258 /* If we were interrupted, exit now that all child processes
259 have finished. */
260 if ( intr )
261 b2::clean_exit( EXITBAD );
262
263 {
264 LISTITER iter, end;
265 for ( iter = list_begin( targets ), end = list_end( targets );
266 iter != end; iter = list_next( iter ) )
267 {
268 /* Check that the target was updated and that the
269 update succeeded. */
270 TARGET * t = bindtarget( list_item( iter ) );
271 if (t->progress == T_MAKE_DONE)
272 {
273 if (t->status != EXEC_CMD_OK)
274 status = 1;
275 }
276 else if ( ! ( t->progress == T_MAKE_NOEXEC_DONE && globs.noexec ) )
277 {
278 status = 1;
279 }
280 }
281 }
282 return status;
283 }
284
285
286 /*
287 * make1a() - recursively schedules dependency builds and then goes to MAKE1B
288 *
289 * Called to start processing a specified target. Does nothing if the target is
290 * already being processed or otherwise starts processing all of its
291 * dependencies.
292 */
293
294 static void make1a( state * const pState )
295 {
296 TARGET * t = pState->t;
297 TARGET * const scc_root = target_scc( t );
298
299 if ( !pState->parent || target_scc( pState->parent ) != scc_root )
300 pState->t = t = scc_root;
301
302 /* If the parent is the first to try to build this target or this target is
303 * in the MAKE1C quagmire, arrange for the parent to be notified when this
304 * target has been built.
305 */
306 if ( pState->parent && t->progress <= T_MAKE_RUNNING )
307 {
308 TARGET * const parent_scc = target_scc( pState->parent );
309 if ( t != parent_scc )
310 {
311 targetentry( t->parents, parent_scc );
312 ++parent_scc->asynccnt;
313 }
314 }
315
316 /* If the target has been previously updated with -n in effect, and we are
317 * now ignoring -n, update it for real. E.g. if the UPDATE_NOW rule was
318 * called for it twice - first with the -n option and then without.
319 */
320 if ( !globs.noexec && t->progress == T_MAKE_NOEXEC_DONE )
321 t->progress = T_MAKE_INIT;
322
323 /* If this target is already being processed then do nothing. There is no
324 * need to start processing the same target all over again.
325 */
326 if ( t->progress != T_MAKE_INIT )
327 {
328 pop_state( &state_stack );
329 return;
330 }
331
332 /* Guard against circular dependencies. */
333 t->progress = T_MAKE_ONSTACK;
334
335 /* 'asynccnt' counts the dependencies preventing this target from proceeding
336 * to MAKE1C for actual building. We start off with a count of 1 to prevent
337 * anything from happening until we can notify all dependencies that they
338 * are needed. This 1 is then accounted for when we enter MAKE1B ourselves,
339 * below. Without this if a dependency gets built before we finish
340 * processing all of our other dependencies our build might be triggered
341 * prematurely.
342 */
343 t->asynccnt = 1;
344
345 /* Push dependency build requests (to be executed in the natural order). */
346 {
347 stack temp_stack = { NULL };
348 targets_ptr c;
349 for ( c = t->depends.get(); c && !quit; c = c->next.get() )
350 push_state( &temp_stack, c->target, t, T_STATE_MAKE1A );
351 push_stack_on_stack( &state_stack, &temp_stack );
352 }
353
354 t->progress = T_MAKE_ACTIVE;
355
356 /* Once all of our dependencies have started getting processed we can move
357 * onto MAKE1B.
358 */
359 /* Implementation note:
360 * In theory this would be done by popping this state before pushing
361 * dependency target build requests but as a slight optimization we simply
362 * modify our current state and leave it on the stack instead.
363 */
364 pState->curstate = T_STATE_MAKE1B;
365 }
366
367
368 /*
369 * make1b() - if nothing is blocking this target's build, proceed to MAKE1C
370 *
371 * Called after something stops blocking this target's build, e.g. that all of
372 * its dependencies have started being processed, one of its dependencies has
373 * been built or a semaphore this target has been waiting for is free again.
374 */
375
376 static void make1b( state * const pState )
377 {
378 TARGET * const t = pState->t;
379 TARGET * failed = 0;
380 char const * failed_name = "dependencies";
381
382 pop_state( &state_stack );
383
384 /* If any dependencies are still outstanding, wait until they signal their
385 * completion by pushing this same state for their parent targets.
386 */
387 if ( --t->asynccnt )
388 {
389 return;
390 }
391
392 /* Now ready to build target 't', if dependencies built OK. */
393
394 /* Collect status from dependencies. If -n was passed then act as though all
395 * dependencies built correctly (the only way they can fail is if UPDATE_NOW
396 * was called). If the dependencies can not be found or we got an interrupt,
397 * we can not get here.
398 */
399 if ( !globs.noexec )
400 {
401 targets_ptr c;
402 for ( c = t->depends.get(); c; c = c->next.get() )
403 if ( c->target->status > t->status && !( c->target->flags &
404 T_FLAG_NOCARE ) )
405 {
406 failed = c->target;
407 t->status = c->target->status;
408 }
409 }
410
411 /* If an internal header node failed to build, we want to output the target
412 * that it failed on.
413 */
414 if ( failed )
415 failed_name = failed->flags & T_FLAG_INTERNAL
416 ? failed->failed
417 : object_str( failed->name );
418 t->failed = failed_name;
419
420 /* If actions for building any of the dependencies have failed, bail.
421 * Otherwise, execute all actions to make the current target.
422 */
423 if ( ( t->status == EXEC_CMD_FAIL ) && t->actions )
424 {
425 ++counts->skipped;
426 if ( ( t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD )
427 {
428 if ( !unlink( object_str( t->boundname ) ) )
429 out_printf( "...removing outdated %s\n", object_str( t->boundname )
430 );
431 }
432 else
433 out_printf( "...skipped %s for lack of %s...\n", object_str( t->name ),
434 failed_name );
435 }
436
437 if ( t->status == EXEC_CMD_OK )
438 switch ( t->fate )
439 {
440 case T_FATE_STABLE:
441 case T_FATE_NEWER:
442 break;
443
444 case T_FATE_CANTFIND:
445 case T_FATE_CANTMAKE:
446 t->status = EXEC_CMD_FAIL;
447 break;
448
449 case T_FATE_ISTMP:
450 if ( DEBUG_MAKE )
451 out_printf( "...using %s...\n", object_str( t->name ) );
452 break;
453
454 case T_FATE_TOUCHED:
455 case T_FATE_MISSING:
456 case T_FATE_NEEDTMP:
457 case T_FATE_OUTDATED:
458 case T_FATE_UPDATE:
459 case T_FATE_REBUILD:
460 /* Prepare commands for executing actions scheduled for this target.
461 * Commands have their embedded variables automatically expanded,
462 * including making use of any "on target" variables.
463 */
464 if ( t->actions )
465 {
466 ++counts->total;
467 if ( DEBUG_MAKE && !( counts->total % 100 ) )
468 out_printf( "...on %dth target...\n", counts->total );
469
470 t->cmds = (char *)make1cmds( t );
471 /* Update the target's "progress" so MAKE1C processing counts it
472 * among its successes/failures.
473 */
474 t->progress = T_MAKE_RUNNING;
475 }
476 break;
477
478 /* All valid fates should have been accounted for by now. */
479 default:
480 err_printf( "ERROR: %s has bad fate %d", object_str( t->name ),
481 t->fate );
482 b2::clean_exit( b2::exit_result::failure );
483 }
484
485 /* Proceed to MAKE1C to begin executing the chain of commands prepared for
486 * building the target. If we are not going to build the target (e.g. due to
487 * dependency failures or no commands needing to be run) the chain will be
488 * empty and MAKE1C processing will directly signal the target's completion.
489 */
490
491 if ( t->cmds == NULL || --( ( CMD * )t->cmds )->asynccnt == 0 )
492 push_state( &state_stack, t, NULL, T_STATE_MAKE1C );
493 else if ( DEBUG_EXECCMD )
494 {
495 CMD * cmd = ( CMD * )t->cmds;
496 out_printf( "Delaying %s %s: %d targets not ready\n", object_str( cmd->rule->name ), object_str( t->boundname ), cmd->asynccnt );
497 }
498 }
499
500
501 /*
502 * make1c() - launch target's next command, or go to parents' MAKE1B if none
503 *
504 * If there are (more) commands to run to build this target (and we have not hit
505 * an error running earlier comands) we launch the command using exec_cmd().
506 * Command execution signals its completion in exec_wait() by calling our
507 * make1c_closure() callback.
508 *
509 * If there are no more commands to run, we collect the status from all the
510 * actions and report our completion to all the parents.
511 */
512
513 static void make1c( state const * const pState )
514 {
515 TARGET * const t = pState->t;
516 CMD * const cmd = (CMD *)t->cmds;
517 int32_t exec_flags = 0;
518
519 if ( cmd )
520 {
521 /* Pop state first in case something below (e.g. exec_cmd(), exec_wait()
522 * or make1c_closure()) pushes a new state. Note that we must not access
523 * the popped state data after this as the same stack node might have
524 * been reused internally for some newly pushed state.
525 */
526 pop_state( &state_stack );
527
528 if ( cmd->status != EXEC_CMD_OK )
529 {
530 t->cmds = NULL;
531 push_cmds( cmd->next, cmd->status );
532 cmd_free( cmd );
533 return;
534 }
535
536 #ifdef OPT_SEMAPHORE
537 if ( ! cmd_sem_lock( t ) )
538 {
539 return;
540 }
541 #endif
542
543 /* Increment the jobs running counter. */
544 ++cmdsrunning;
545
546 if ( ( globs.jobs == 1 ) && ( DEBUG_MAKEQ ||
547 ( DEBUG_MAKE && !( cmd->rule->actions->flags & RULE_QUIETLY ) ) ) )
548 {
549 OBJECT * action = cmd->rule->name;
550 OBJECT * target = list_front( lol_get( (LOL *)&cmd->args, 0 ) );
551
552 out_printf( "%s %s\n", object_str( action ), object_str( target ) );
553
554 /* Print out the command executed if given -d+2. */
555 if ( DEBUG_EXEC )
556 {
557 out_puts( cmd->buf->value );
558 out_putc( '\n' );
559 }
560
561 /* We only need to flush the streams if there's likely to
562 * be a wait before it finishes.
563 */
564 if ( ! globs.noexec && ! cmd->noop )
565 {
566 out_flush();
567 err_flush();
568 }
569 }
570 else
571 {
572 exec_flags |= EXEC_CMD_QUIET;
573 }
574
575 /* Execute the actual build command or fake it if no-op. */
576 if ( globs.noexec || cmd->noop )
577 {
578 timing_info time_info = { 0 };
579 timestamp_current( &time_info.start );
580 timestamp_copy( &time_info.end, &time_info.start );
581 make1c_closure( t, EXEC_CMD_OK, &time_info, "", "", EXIT_OK );
582 }
583 else
584 {
585 exec_cmd( cmd->buf, exec_flags, make1c_closure, t, cmd->shell );
586
587 /* Wait until under the concurrent command count limit. */
588 /* FIXME: This wait could be skipped here and moved to just before
589 * trying to execute a command that would cross the command count
590 * limit. Note though that this might affect the order in which
591 * unrelated targets get built and would thus require that all
592 * affected Boost Build tests be updated.
593 */
594 assert( 0 < globs.jobs );
595 while ( cmdsrunning >= globs.jobs )
596 exec_wait();
597 }
598 }
599 else
600 {
601 /* Tally success/failure for those we tried to update. */
602 if ( t->progress == T_MAKE_RUNNING )
603 {
604 /* Invert OK/FAIL target status when FAIL_EXPECTED has been applied. */
605 if ( t->flags & T_FLAG_FAIL_EXPECTED && !globs.noexec )
606 {
607 switch ( t->status )
608 {
609 case EXEC_CMD_FAIL: t->status = EXEC_CMD_OK; break;
610 case EXEC_CMD_OK: t->status = EXEC_CMD_FAIL; break;
611 }
612
613 /* Printing failure has to be delayed until the last
614 * action is completed for FAIL_EXPECTED targets.
615 * Do it here.
616 */
617 if ( t->status == EXEC_CMD_FAIL )
618 {
619 out_printf( "...failed %s ", object_str( t->actions->action->rule->name ) );
620 out_printf( "%s", object_str( t->boundname ) );
621 out_printf( "...\n" );
622 }
623
624 /* Handle -q */
625 if ( t->status == EXEC_CMD_FAIL && globs.quitquick )
626 ++quit;
627
628 /* Delete the target on failure. */
629 if ( !( t->flags & ( T_FLAG_PRECIOUS | T_FLAG_NOTFILE ) ) &&
630 !unlink( object_str( t->boundname ) ) )
631 out_printf( "...removing %s\n", object_str( t->boundname ) );
632 }
633 switch ( t->status )
634 {
635 case EXEC_CMD_OK: ++counts->made; break;
636 case EXEC_CMD_FAIL: ++counts->failed; break;
637 }
638 }
639
640 /* Tell parents their dependency has been built. */
641 {
642 targets_ptr c;
643 stack temp_stack = { NULL };
644 TARGET * additional_includes = NULL;
645
646 t->progress = globs.noexec ? T_MAKE_NOEXEC_DONE : T_MAKE_DONE;
647
648 /* Target has been updated so rescan it for dependencies. */
649 if ( t->fate >= T_FATE_MISSING && t->status == EXEC_CMD_OK &&
650 !( t->flags & T_FLAG_INTERNAL ) )
651 {
652 TARGET * saved_includes;
653 SETTINGS * s;
654
655 /* Clean current includes. */
656 saved_includes = t->includes;
657 t->includes = 0;
658
659 s = copysettings( t->settings );
660 pushsettings( root_module(), s );
661 headers( t );
662 popsettings( root_module(), s );
663 freesettings( s );
664
665 if ( t->includes )
666 {
667 /* Tricky. The parents have already been processed, but they
668 * have not seen the internal node, because it was just
669 * created. We need to:
670 * - push MAKE1A states that would have been pushed by the
671 * parents here
672 * - make sure all unprocessed parents will pick up the
673 * new includes
674 * - make sure processing the additional MAKE1A states is
675 * done before processing the MAKE1B state for our
676 * current target (which would mean this target has
677 * already been built), otherwise the parent would be
678 * considered built before the additional MAKE1A state
679 * processing even got a chance to start.
680 */
681 make0( t->includes, t->parents->target, 0, 0, 0, t->includes
682 );
683 /* Link the old includes on to make sure that it gets
684 * cleaned up correctly.
685 */
686 t->includes->includes = saved_includes;
687 for ( c = t->dependants.get(); c; c = c->next.get() )
688 targetentry( c->target->depends, t->includes );
689 /* Will be processed below. */
690 additional_includes = t->includes;
691 }
692 else
693 {
694 t->includes = saved_includes;
695 }
696 }
697
698 if ( additional_includes )
699 for ( c = t->parents.get(); c; c = c->next.get() )
700 push_state( &temp_stack, additional_includes, c->target,
701 T_STATE_MAKE1A );
702
703 if ( t->scc_root )
704 {
705 TARGET * const scc_root = target_scc( t );
706 assert( scc_root->progress < T_MAKE_DONE );
707 for ( c = t->parents.get(); c; c = c->next.get() )
708 {
709 if ( target_scc( c->target ) == scc_root )
710 push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B
711 );
712 else
713 targetentry( scc_root->parents, c->target );
714 }
715 }
716 else
717 {
718 for ( c = t->parents.get(); c; c = c->next.get() )
719 push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B );
720 }
721
722 /* Must pop state before pushing any more. */
723 pop_state( &state_stack );
724
725 /* Using stacks reverses the order of execution. Reverse it back. */
726 push_stack_on_stack( &state_stack, &temp_stack );
727 }
728 }
729 }
730
731
732 /*
733 * call_timing_rule() - Look up the __TIMING_RULE__ variable on the given
734 * target, and if non-empty, invoke the rule it names, passing the given
735 * timing_info.
736 */
737
738 static void call_timing_rule( TARGET * target, timing_info const * const time )
739 {
740 LIST * timing_rule;
741
742 pushsettings( root_module(), target->settings );
743 timing_rule = var_get( root_module(), constant_TIMING_RULE );
744 popsettings( root_module(), target->settings );
745
746 if ( !list_empty( timing_rule ) )
747 {
748 /* rule timing-rule ( args * : target : start end user system clock ) */
749
750 /* Prepare the argument list. */
751 FRAME frame[ 1 ];
752 OBJECT * rulename = list_front( timing_rule );
753 frame_init( frame );
754
755 /* args * :: $(__TIMING_RULE__[2-]) */
756 lol_add( frame->args, list_copy_range( timing_rule, list_next(
757 list_begin( timing_rule ) ), list_end( timing_rule ) ) );
758
759 /* target :: the name of the target */
760 lol_add( frame->args, list_new( object_copy( target->name ) ) );
761
762 /* start end user system clock :: info about the action command */
763 lol_add( frame->args, list_push_back( list_push_back( list_push_back( list_push_back( list_new(
764 outf_time( &time->start ) ),
765 outf_time( &time->end ) ),
766 outf_double( time->user ) ),
767 outf_double( time->system ) ),
768 outf_double( timestamp_delta_seconds(&time->start, &time->end) ) )
769 );
770
771 /* Call the rule. */
772 evaluate_rule( bindrule( rulename , root_module() ), rulename, frame );
773
774 /* Clean up. */
775 frame_free( frame );
776 }
777 }
778
779
780 /*
781 * call_action_rule() - Look up the __ACTION_RULE__ variable on the given
782 * target, and if non-empty, invoke the rule it names, passing the given info,
783 * timing_info, executed command and command output.
784 */
785
786 static void call_action_rule
787 (
788 TARGET * target,
789 int32_t status,
790 timing_info const * time,
791 char const * executed_command,
792 char const * command_output
793 )
794 {
795 LIST * action_rule;
796
797 pushsettings( root_module(), target->settings );
798 action_rule = var_get( root_module(), constant_ACTION_RULE );
799 popsettings( root_module(), target->settings );
800
801 if ( !list_empty( action_rule ) )
802 {
803 /* rule action-rule (
804 args * :
805 target :
806 command status start end user system :
807 output ? ) */
808
809 /* Prepare the argument list. */
810 FRAME frame[ 1 ];
811 OBJECT * rulename = list_front( action_rule );
812 frame_init( frame );
813
814 /* args * :: $(__ACTION_RULE__[2-]) */
815 lol_add( frame->args, list_copy_range( action_rule, list_next(
816 list_begin( action_rule ) ), list_end( action_rule ) ) );
817
818 /* target :: the name of the target */
819 lol_add( frame->args, list_new( object_copy( target->name ) ) );
820
821 /* command status start end user system :: info about the action command
822 */
823 lol_add( frame->args,
824 list_push_back( list_push_back( list_push_back( list_push_back( list_push_back( list_new(
825 object_new( executed_command ) ),
826 outf_int( status ) ),
827 outf_time( &time->start ) ),
828 outf_time( &time->end ) ),
829 outf_double( time->user ) ),
830 outf_double( time->system ) ) );
831
832 /* output ? :: the output of the action command */
833 if ( command_output )
834 {
835 OBJECT * command_output_obj = object_new( command_output );
836 char * output_i = (char*)object_str(command_output_obj);
837 /* Clean the output of control characters. */
838 for (; *output_i; ++output_i)
839 {
840 if (iscntrl(*output_i) && !isspace(*output_i)) *output_i = '?';
841 }
842 lol_add( frame->args, list_new( command_output_obj ) );
843 }
844 else
845 lol_add( frame->args, L0 );
846
847 /* Call the rule. */
848 evaluate_rule( bindrule( rulename, root_module() ), rulename, frame );
849
850 /* Clean up. */
851 frame_free( frame );
852 }
853 }
854
855
856 /*
857 * make1c_closure() - handle command execution completion and go to MAKE1C.
858 *
859 * Internal function passed as a notification callback for when a command
860 * finishes getting executed by the OS or called directly when faking that a
861 * command had been executed by the OS.
862 *
863 * Now all we need to do is fiddle with the command exit status and push a new
864 * MAKE1C state to execute the next command scheduled for building this target
865 * or close up the target's build process in case there are no more commands
866 * scheduled for it. On interrupts, we bail heavily.
867 */
868
869 static void make1c_closure
870 (
871 void * const closure,
872 int32_t status_orig,
873 timing_info const * const time,
874 char const * const cmd_stdout,
875 char const * const cmd_stderr,
876 int32_t const cmd_exit_reason
877 )
878 {
879 TARGET * const t = (TARGET *)closure;
880 CMD * const cmd = (CMD *)t->cmds;
881 char const * rule_name = 0;
882 char const * target_name = 0;
883
884 assert( cmd );
885
886 --cmdsrunning;
887
888 /* Calculate the target's status from the cmd execution result. */
889 {
890 /* Store the target's status. */
891 t->status = status_orig;
892
893 /* Ignore failures for actions marked as 'ignore'. */
894 if ( t->status == EXEC_CMD_FAIL && cmd->rule->actions->flags &
895 RULE_IGNORE )
896 t->status = EXEC_CMD_OK;
897 }
898
899 if ( DEBUG_MAKEQ ||
900 ( DEBUG_MAKE && !( cmd->rule->actions->flags & RULE_QUIETLY ) ) )
901 {
902 rule_name = object_str( cmd->rule->name );
903 target_name = object_str( list_front( lol_get( (LOL *)&cmd->args, 0 ) )
904 );
905 }
906
907 if ( rule_name == NULL || globs.jobs > 1 )
908 out_action( rule_name, target_name, cmd->buf->value, cmd_stdout,
909 cmd_stderr, cmd_exit_reason );
910
911 /* If the process expired, make user aware with an explicit message, but do
912 * this only for non-quiet actions.
913 */
914 if ( cmd_exit_reason == EXIT_TIMEOUT && target_name )
915 out_printf( "%ld second time limit exceeded\n", globs.timeout );
916
917 out_flush();
918 err_flush();
919
920 if ( !globs.noexec )
921 {
922 call_timing_rule( t, time );
923 if ( DEBUG_EXECCMD )
924 out_printf( "%f sec system; %f sec user; %f sec clock\n",
925 time->system, time->user,
926 timestamp_delta_seconds(&time->start, &time->end) );
927
928 /* Assume -p0 is in effect, i.e. cmd_stdout contains merged output. */
929 call_action_rule( t, status_orig, time, cmd->buf->value, cmd_stdout );
930 }
931
932 /* Print command text on failure. */
933 if ( t->status == EXEC_CMD_FAIL && DEBUG_MAKE &&
934 ! ( t->flags & T_FLAG_FAIL_EXPECTED ) )
935 {
936 if ( !DEBUG_EXEC )
937 out_printf( "%s\n", cmd->buf->value );
938
939 out_printf( "...failed %s ", object_str( cmd->rule->name ) );
940 list_print( lol_get( (LOL *)&cmd->args, 0 ) );
941 out_printf( "...\n" );
942 }
943
944 /* On interrupt, set quit so _everything_ fails. Do the same for failed
945 * commands if we were asked to stop the build in case of any errors.
946 */
947 if ( t->status == EXEC_CMD_INTR )
948 {
949 ++intr;
950 ++quit;
951 }
952 if ( t->status == EXEC_CMD_FAIL && globs.quitquick &&
953 ! ( t->flags & T_FLAG_FAIL_EXPECTED ) )
954 ++quit;
955
956 /* If the command was not successful remove all of its targets not marked as
957 * "precious".
958 */
959 if ( t->status != EXEC_CMD_OK )
960 {
961 LIST * const targets = lol_get( (LOL *)&cmd->args, 0 );
962 LISTITER iter = list_begin( targets );
963 LISTITER const end = list_end( targets );
964 for ( ; iter != end; iter = list_next( iter ) )
965 {
966 char const * const filename = object_str( list_item( iter ) );
967 TARGET const * const t = bindtarget( list_item( iter ) );
968 if ( !( t->flags & T_FLAG_PRECIOUS ) && !unlink( filename ) )
969 out_printf( "...removing %s\n", filename );
970 }
971 }
972
973 #ifdef OPT_SEMAPHORE
974 /* Release any semaphores used by this action. */
975 cmd_sem_unlock( t );
976 #endif
977
978 /* Free this command and push the MAKE1C state to execute the next one
979 * scheduled for building this same target.
980 */
981 t->cmds = NULL;
982 push_cmds( cmd->next, t->status );
983 cmd_free( cmd );
984 }
985
986 /* push the next MAKE1C state after a command is run. */
987 static void push_cmds( CMDLIST * cmds, int32_t status )
988 {
989 CMDLIST * cmd_iter;
990 for( cmd_iter = cmds; cmd_iter; cmd_iter = cmd_iter->next )
991 {
992 if ( cmd_iter->iscmd )
993 {
994 CMD * next_cmd = cmd_iter->impl.cmd;
995 /* Propagate the command status. */
996 if ( next_cmd->status < status )
997 next_cmd->status = status;
998 if ( --next_cmd->asynccnt == 0 )
999 {
1000 /* Select the first target associated with the action.
1001 * This is safe because sibling CMDs cannot have targets
1002 * in common.
1003 */
1004 TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) );
1005 first_target->cmds = (char *)next_cmd;
1006 push_state( &state_stack, first_target, NULL, T_STATE_MAKE1C );
1007 }
1008 else if ( DEBUG_EXECCMD )
1009 {
1010 TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) );
1011 out_printf( "Delaying %s %s: %d targets not ready\n", object_str( next_cmd->rule->name ), object_str( first_target->boundname ), next_cmd->asynccnt );
1012 }
1013 }
1014 else
1015 {
1016 /* This is a target that we're finished updating */
1017 TARGET * updated_target = cmd_iter->impl.t;
1018 if ( updated_target->status < status )
1019 updated_target->status = status;
1020 updated_target->cmds = NULL;
1021 push_state( &state_stack, updated_target, NULL, T_STATE_MAKE1C );
1022 }
1023 }
1024 }
1025
1026
1027 /*
1028 * swap_settings() - replace the settings from the current module and target
1029 * with those from the new module and target
1030 */
1031
1032 static void swap_settings
1033 (
1034 module_t * * current_module,
1035 TARGET * * current_target,
1036 module_t * new_module,
1037 TARGET * new_target
1038 )
1039 {
1040 if ( ( new_target == *current_target ) &&
1041 ( new_module == *current_module ) )
1042 return;
1043
1044 if ( *current_target )
1045 popsettings( *current_module, (*current_target)->settings );
1046
1047 if ( new_target )
1048 pushsettings( new_module, new_target->settings );
1049
1050 *current_module = new_module;
1051 *current_target = new_target;
1052 }
1053
1054
1055 /*
1056 * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc.
1057 *
1058 * Essentially copies a chain of ACTIONs to a chain of CMDs, grouping
1059 * RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions, and handling
1060 * RULE_NEWSRCS actions. The result is a chain of CMDs which has already had all
1061 * of its embedded variable references expanded and can now be executed using
1062 * exec_cmd().
1063 */
1064
1065 static CMD * make1cmds( TARGET * t )
1066 {
1067 CMD * cmds = 0;
1068 CMD * last_cmd = 0;
1069 LIST * shell = L0;
1070 module_t * settings_module = 0;
1071 TARGET * settings_target = 0;
1072 ACTIONS * a0 = 0;
1073 int32_t const running_flag = globs.noexec ? A_RUNNING_NOEXEC : A_RUNNING;
1074
1075 /* Step through actions.
1076 */
1077 for ( a0 = t->actions; a0; a0 = a0->next )
1078 {
1079 RULE * rule = a0->action->rule;
1080 rule_actions_ptr actions = rule->actions;
1081 SETTINGS * boundvars;
1082 LIST * nt;
1083 LIST * ns;
1084 ACTIONS * a1;
1085
1086 /* Only do rules with commands to execute.
1087 */
1088 if ( !actions )
1089 continue;
1090
1091 if ( a0->action->running >= running_flag )
1092 {
1093 CMD * first;
1094 /* If this action was skipped either because it was
1095 * combined with another action by RULE_TOGETHER, or
1096 * because all of its sources were filtered out,
1097 * then we don't have anything to do here.
1098 */
1099 if ( a0->action->first_cmd == NULL )
1100 continue;
1101 /* This action has already been processed for another target.
1102 * Just set up the dependency graph correctly and move on.
1103 */
1104 first = (CMD *)a0->action->first_cmd;
1105 if( cmds )
1106 {
1107 last_cmd->next = cmdlist_append_cmd( last_cmd->next, first );
1108 }
1109 else
1110 {
1111 cmds = first;
1112 }
1113 last_cmd = (CMD *)a0->action->last_cmd;
1114 continue;
1115 }
1116
1117 a0->action->running = running_flag;
1118
1119 /* Make LISTS of targets and sources. If `execute together` has been
1120 * specified for this rule, tack on sources from each instance of this
1121 * rule for this target.
1122 */
1123 nt = make1list( L0, a0->action->targets, 0 );
1124 ns = make1list( L0, a0->action->sources, actions->flags );
1125 if ( actions->flags & RULE_TOGETHER )
1126 for ( a1 = a0->next; a1; a1 = a1->next )
1127 if ( a1->action->rule == rule &&
1128 a1->action->running < running_flag &&
1129 targets_equal( a0->action->targets, a1->action->targets ) )
1130 {
1131 ns = make1list( ns, a1->action->sources, actions->flags );
1132 a1->action->running = running_flag;
1133 }
1134
1135 /* If doing only updated (or existing) sources, but none have been
1136 * updated (or exist), skip this action.
1137 */
1138 if ( list_empty( ns ) &&
1139 ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) )
1140 {
1141 list_free( nt );
1142 continue;
1143 }
1144
1145 swap_settings( &settings_module, &settings_target, rule->module, t );
1146 if ( list_empty( shell ) )
1147 {
1148 /* shell is per-target */
1149 shell = var_get( rule->module, constant_JAMSHELL );
1150 }
1151
1152 /* If we had 'actions xxx bind vars' we bind the vars now. */
1153 boundvars = make1settings( rule->module, actions->bindlist );
1154 pushsettings( rule->module, boundvars );
1155
1156 /*
1157 * Build command, starting with all source args.
1158 *
1159 * For actions that allow PIECEMEAL commands, if the constructed command
1160 * string is too long, we retry constructing it with a reduced number of
1161 * source arguments presented.
1162 *
1163 * While reducing slowly takes a bit of compute time to get things just
1164 * right, it is worth it to get as close to maximum allowed command
1165 * string length as possible, because launching the commands we are
1166 * executing is likely to be much more compute intensive.
1167 *
1168 * Note that we loop through at least once, for sourceless actions.
1169 */
1170 {
1171 int32_t const length = list_length( ns );
1172 int32_t start = 0;
1173 int32_t chunk = length;
1174 int32_t cmd_count = 0;
1175 targets_uptr semaphores;
1176 targets_ptr targets_iter;
1177 int32_t unique_targets;
1178 do
1179 {
1180 CMD * cmd;
1181 int32_t cmd_check_result;
1182 int32_t cmd_error_length;
1183 int32_t cmd_error_max_length;
1184 int32_t retry = 0;
1185 int32_t accept_command = 0;
1186
1187 /* Build cmd: cmd_new() takes ownership of its lists. */
1188 cmd = cmd_new( rule, list_copy( nt ), list_sublist( ns, start,
1189 chunk ), list_copy( shell ) );
1190
1191 cmd_check_result = exec_check( cmd->buf, &cmd->shell,
1192 &cmd_error_length, &cmd_error_max_length );
1193
1194 if ( cmd_check_result == EXEC_CHECK_OK )
1195 {
1196 accept_command = 1;
1197 }
1198 else if ( cmd_check_result == EXEC_CHECK_NOOP )
1199 {
1200 accept_command = 1;
1201 cmd->noop = 1;
1202 }
1203 else if ( ( actions->flags & RULE_PIECEMEAL ) && ( chunk > 1 ) )
1204 {
1205 /* Too long but splittable. Reduce chunk size slowly and
1206 * retry.
1207 */
1208 assert( cmd_check_result == EXEC_CHECK_TOO_LONG ||
1209 cmd_check_result == EXEC_CHECK_LINE_TOO_LONG );
1210 chunk = chunk * 9 / 10;
1211 retry = 1;
1212 }
1213 else
1214 {
1215 /* Too long and not splittable. */
1216 char const * const error_message = cmd_check_result ==
1217 EXEC_CHECK_TOO_LONG
1218 ? "is too long"
1219 : "contains a line that is too long";
1220 assert( cmd_check_result == EXEC_CHECK_TOO_LONG ||
1221 cmd_check_result == EXEC_CHECK_LINE_TOO_LONG );
1222 out_printf(
1223 "%s action %s (%d, max %d):\n",
1224 object_str( rule->name ), error_message,
1225 cmd_error_length, cmd_error_max_length );
1226
1227 /* Tell the user what did not fit. */
1228 out_puts( cmd->buf->value );
1229 b2::clean_exit( EXITBAD );
1230 }
1231
1232 assert( !retry || !accept_command );
1233
1234 if ( accept_command )
1235 {
1236 /* Chain it up. */
1237 if ( cmds )
1238 {
1239 last_cmd->next = cmdlist_append_cmd( last_cmd->next, cmd );
1240 last_cmd = cmd;
1241 }
1242 else
1243 {
1244 cmds = last_cmd = cmd;
1245 }
1246
1247 if ( cmd_count++ == 0 )
1248 {
1249 a0->action->first_cmd = cmd;
1250 }
1251 }
1252 else
1253 {
1254 cmd_free( cmd );
1255 }
1256
1257 if ( !retry )
1258 start += chunk;
1259 }
1260 while ( start < length );
1261
1262 /* Record the end of the actions cmds */
1263 a0->action->last_cmd = last_cmd;
1264
1265 unique_targets = 0;
1266 for ( targets_iter = a0->action->targets.get(); targets_iter; targets_iter = targets_iter->next.get() )
1267 {
1268 if ( targets_contains( targets_iter->next, targets_iter->target ) )
1269 continue;
1270 /* Add all targets produced by the action to the update list. */
1271 push_state( &state_stack, targets_iter->target, NULL, T_STATE_MAKE1A );
1272 ++unique_targets;
1273 }
1274 /* We need to wait until all the targets agree that
1275 * it's okay to run this action.
1276 */
1277 ( ( CMD * )a0->action->first_cmd )->asynccnt = unique_targets;
1278
1279 #if OPT_SEMAPHORE
1280 /* Collect semaphores */
1281 for ( targets_iter = a0->action->targets.get(); targets_iter; targets_iter = targets_iter->next.get() )
1282 {
1283 TARGET * sem = targets_iter->target->semaphore;
1284 if ( sem )
1285 {
1286 if ( ! targets_contains( semaphores, sem ) )
1287 targetentry( semaphores, sem );
1288 }
1289 }
1290 ( ( CMD * )a0->action->first_cmd )->lock = semaphores.get();
1291 ( ( CMD * )a0->action->last_cmd )->unlock = std::move(semaphores);
1292 #endif
1293 }
1294
1295 /* These were always copied when used. */
1296 list_free( nt );
1297 list_free( ns );
1298
1299 /* Free variables with values bound by 'actions xxx bind vars'. */
1300 popsettings( rule->module, boundvars );
1301 freesettings( boundvars );
1302 }
1303
1304 if ( cmds )
1305 {
1306 last_cmd->next = cmdlist_append_target( last_cmd->next, t );
1307 }
1308
1309 swap_settings( &settings_module, &settings_target, 0, 0 );
1310 return cmds;
1311 }
1312
1313
1314 /*
1315 * make1list() - turn a list of targets into a LIST, for $(<) and $(>)
1316 */
1317
1318 static LIST * make1list( LIST * l, const targets_uptr & ts, int32_t flags )
1319 {
1320 targets_ptr targets = ts.get();
1321 for ( ; targets; targets = targets->next.get() )
1322 {
1323 TARGET * t = targets->target;
1324
1325 if ( t->binding == T_BIND_UNBOUND )
1326 make1bind( t );
1327
1328 if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) )
1329 {
1330 if ( ( t->binding != T_BIND_EXISTS ) &&
1331 ( t->fate <= T_FATE_STABLE ) )
1332 continue;
1333 }
1334 else if ( flags & RULE_EXISTING )
1335 {
1336 if ( t->binding != T_BIND_EXISTS )
1337 continue;
1338 }
1339 else if ( flags & RULE_NEWSRCS )
1340 {
1341 if ( t->fate <= T_FATE_STABLE )
1342 continue;
1343 }
1344
1345 /* Prohibit duplicates for RULE_TOGETHER. */
1346 if ( flags & RULE_TOGETHER )
1347 {
1348 LISTITER iter = list_begin( l );
1349 LISTITER const end = list_end( l );
1350 for ( ; iter != end; iter = list_next( iter ) )
1351 if ( object_equal( list_item( iter ), t->boundname ) )
1352 break;
1353 if ( iter != end )
1354 continue;
1355 }
1356
1357 /* Build new list. */
1358 l = list_push_back( l, object_copy( t->boundname ) );
1359 }
1360
1361 return l;
1362 }
1363
1364
1365 /*
1366 * make1settings() - for vars with bound values, build up replacement lists
1367 */
1368
1369 static SETTINGS * make1settings( struct module_t * module, LIST * vars )
1370 {
1371 SETTINGS * settings = 0;
1372
1373 LISTITER vars_iter = list_begin( vars );
1374 LISTITER const vars_end = list_end( vars );
1375 for ( ; vars_iter != vars_end; vars_iter = list_next( vars_iter ) )
1376 {
1377 LIST * const l = var_get( module, list_item( vars_iter ) );
1378 LIST * nl = L0;
1379 LISTITER iter = list_begin( l );
1380 LISTITER const end = list_end( l );
1381
1382 for ( ; iter != end; iter = list_next( iter ) )
1383 {
1384 TARGET * const t = bindtarget( list_item( iter ) );
1385
1386 /* Make sure the target is bound. */
1387 if ( t->binding == T_BIND_UNBOUND )
1388 make1bind( t );
1389
1390 /* Build a new list. */
1391 nl = list_push_back( nl, object_copy( t->boundname ) );
1392 }
1393
1394 /* Add to settings chain. */
1395 settings = addsettings( settings, VAR_SET, list_item( vars_iter ), nl );
1396 }
1397
1398 return settings;
1399 }
1400
1401
1402 /*
1403 * make1bind() - bind targets that were not bound during dependency analysis
1404 *
1405 * Spot the kludge! If a target is not in the dependency tree, it did not get
1406 * bound by make0(), so we have to do it here. Ugly.
1407 */
1408
1409 static void make1bind( TARGET * t )
1410 {
1411 if ( t->flags & T_FLAG_NOTFILE )
1412 return;
1413
1414 pushsettings( root_module(), t->settings );
1415 object_free( t->boundname );
1416 t->boundname = search( t->name, &t->time, 0, t->flags & T_FLAG_ISFILE );
1417 t->binding = timestamp_empty( &t->time ) ? T_BIND_MISSING : T_BIND_EXISTS;
1418 popsettings( root_module(), t->settings );
1419 }
1420
1421
1422 static bool targets_contains( const targets_uptr & ts, TARGET * t )
1423 {
1424 targets_ptr l = ts.get();
1425 for ( ; l; l = l->next.get() )
1426 {
1427 if ( t == l->target )
1428 {
1429 return true;
1430 }
1431 }
1432 return false;
1433 }
1434
1435 static bool targets_equal( const targets_uptr & ts1, const targets_uptr & ts2 )
1436 {
1437 targets_ptr l1 = ts1.get();
1438 targets_ptr l2 = ts2.get();
1439 for ( ; l1 && l2; l1 = l1->next.get(), l2 = l2->next.get() )
1440 {
1441 if ( l1->target != l2->target )
1442 return false;
1443 }
1444 return !l1 && !l2;
1445 }
1446
1447
1448 #ifdef OPT_SEMAPHORE
1449
1450 static int32_t cmd_sem_lock( TARGET * t )
1451 {
1452 CMD * cmd = (CMD *)t->cmds;
1453 targets_ptr iter;
1454 /* Check whether all the semaphores required for updating
1455 * this target are free.
1456 */
1457 for ( iter = cmd->lock; iter; iter = iter->next.get() )
1458 {
1459 if ( iter->target->asynccnt > 0 )
1460 {
1461 if ( DEBUG_EXECCMD )
1462 out_printf( "SEM: %s is busy, delaying launch of %s\n",
1463 object_str( iter->target->name ), object_str( t->name ) );
1464 targetentry( iter->target->parents, t );
1465 return 0;
1466 }
1467 }
1468 /* Lock the semaphores. */
1469 for ( iter = cmd->lock; iter; iter = iter->next.get() )
1470 {
1471 ++iter->target->asynccnt;
1472 if ( DEBUG_EXECCMD )
1473 out_printf( "SEM: %s now used by %s\n", object_str( iter->target->name
1474 ), object_str( t->name ) );
1475 }
1476 /* A cmd only needs to be locked around its execution.
1477 * clearing cmd->lock here makes it safe to call cmd_sem_lock
1478 * twice.
1479 */
1480 cmd->lock = NULL;
1481 return 1;
1482 }
1483
1484 static void cmd_sem_unlock( TARGET * t )
1485 {
1486 CMD * cmd = ( CMD * )t->cmds;
1487 targets_ptr iter;
1488 /* Release the semaphores. */
1489 for ( iter = cmd->unlock.get(); iter; iter = iter->next.get() )
1490 {
1491 if ( DEBUG_EXECCMD )
1492 out_printf( "SEM: %s is now free\n", object_str(
1493 iter->target->name ) );
1494 --iter->target->asynccnt;
1495 assert( iter->target->asynccnt <= 0 );
1496 }
1497 for ( iter = cmd->unlock.get(); iter; iter = iter->next.get() )
1498 {
1499 /* Find a waiting target that's ready */
1500 while ( iter->target->parents )
1501 {
1502 TARGET * t1 = iter->target->parents->target;
1503
1504 iter->target->parents = targets_pop(std::move(iter->target->parents));
1505
1506 if ( cmd_sem_lock( t1 ) )
1507 {
1508 push_state( &state_stack, t1, NULL, T_STATE_MAKE1C );
1509 break;
1510 }
1511 }
1512 }
1513 }
1514
1515 #endif