void psi_memstall_tick(struct task_struct *task, int cpu) { struct psi_group *group; void *iter = NULL; while ((group = iterate_groups(task, &iter))) { struct psi_group_cpu *groupc; groupc = per_cpu_ptr(group->pcpu, cpu); write_seqcount_begin(&groupc->seq); record_times(groupc, cpu, true); write_seqcount_end(&groupc->seq); } }
inline typename property_traits<Components>::value_type connected_components(Graph& G, DFSVisitor v, Components c, DiscoverTime d, FinishTime f, Color color, directed_tag) { typedef typename graph_traits<Graph>::vertex_descriptor Vertex; typename property_traits<Color>::value_type cc = get(color, Vertex()); int time = 0; depth_first_search(G, record_times(d, f, time, v), color); Graph G_T(num_vertices(G)); transpose_graph(G, G_T); typedef typename property_traits<Components>::value_type count_type; count_type c_count(0); components_recorder<Components, dfs_visitor<> > vis(c, c_count, dfs_visitor<>()); // initialize G_T typename graph_traits<Graph>::vertex_iterator ui, ui_end; for (tie(ui, ui_end) = vertices(G_T); ui != ui_end; ++ui) put(color, *ui, white(cc)); typedef typename property_traits<FinishTime>::value_type D; typedef indirect_cmp< FinishTime, std::less<D> > Compare; Compare fl(f); priority_queue<Vertex, std::vector<Vertex>, Compare > Q(fl); typename graph_traits<Graph>::vertex_iterator i, j, iend, jend; tie(i, iend) = vertices(G_T); tie(j, jend) = vertices(G); for ( ; i != iend; ++i, ++j) { put(f, *i, get(f, *j)); Q.push(*i); } while ( !Q.empty() ) { Vertex u = Q.top(); Q.pop(); if (get(color, u) == white(cc)) { depth_first_visit(G_T, u, vis, color); ++c_count; } } return c_count; }
static void psi_group_change(struct psi_group *group, int cpu, unsigned int clear, unsigned int set) { struct psi_group_cpu *groupc; unsigned int t, m; groupc = per_cpu_ptr(group->pcpu, cpu); /* * First we assess the aggregate resource states this CPU's * tasks have been in since the last change, and account any * SOME and FULL time these may have resulted in. * * Then we update the task counts according to the state * change requested through the @clear and @set bits. */ write_seqcount_begin(&groupc->seq); record_times(groupc, cpu, false); for (t = 0, m = clear; m; m &= ~(1 << t), t++) { if (!(m & (1 << t))) continue; if (groupc->tasks[t] == 0 && !psi_bug) { printk_deferred(KERN_ERR "psi: task underflow! cpu=%d t=%d tasks=[%u %u %u] clear=%x set=%x\n", cpu, t, groupc->tasks[0], groupc->tasks[1], groupc->tasks[2], clear, set); psi_bug = 1; } groupc->tasks[t]--; } for (t = 0; set; set &= ~(1 << t), t++) if (set & (1 << t)) groupc->tasks[t]++; write_seqcount_end(&groupc->seq); }
void exec_wait() { int i = -1; int exit_reason; /* reason why a command completed */ /* Wait for a command to complete, while snarfing up any output. */ while ( 1 ) { /* Check for a complete command, briefly. */ i = try_wait( 500 ); /* Read in the output of all running commands. */ read_output(); /* Close out pending debug style dialogs. */ close_alerts(); /* Process the completed command we found. */ if ( i >= 0 ) { exit_reason = EXIT_OK; break; } /* Check if a command ran out of time. */ i = try_kill_one(); if ( i >= 0 ) { exit_reason = EXIT_TIMEOUT; break; } } /* We have a command... process it. */ { DWORD exit_code; timing_info time; int rstat; /* The time data for the command. */ record_times( cmdtab[ i ].pi.hProcess, &time ); /* Removed the used temporary command file. */ if ( cmdtab[ i ].command_file->size ) unlink( cmdtab[ i ].command_file->value ); /* Find out the process exit code. */ GetExitCodeProcess( cmdtab[ i ].pi.hProcess, &exit_code ); /* The dispossition of the command. */ if ( interrupted() ) rstat = EXEC_CMD_INTR; else if ( exit_code ) rstat = EXEC_CMD_FAIL; else rstat = EXEC_CMD_OK; /* Call the callback, may call back to jam rule land. */ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time, cmdtab[ i ].buffer_out->value, cmdtab[ i ].buffer_err->value, exit_reason ); /* Clean up our child process tracking data. No need to clear the * temporary command file name as it gets reused. */ closeWinHandle( &cmdtab[ i ].pi.hProcess ); closeWinHandle( &cmdtab[ i ].pi.hThread ); closeWinHandle( &cmdtab[ i ].pipe_out[ EXECCMD_PIPE_READ ] ); closeWinHandle( &cmdtab[ i ].pipe_out[ EXECCMD_PIPE_WRITE ] ); closeWinHandle( &cmdtab[ i ].pipe_err[ EXECCMD_PIPE_READ ] ); closeWinHandle( &cmdtab[ i ].pipe_err[ EXECCMD_PIPE_WRITE ] ); string_renew( cmdtab[ i ].buffer_out ); string_renew( cmdtab[ i ].buffer_err ); } }
int exec_wait() { int i = -1; /* Handle naive make1() which does not know if cmds are running. */ if ( !cmdsrunning ) return 0; /* Wait for a command to complete, while snarfing up any output. */ do { /* Check for a complete command, briefly. */ i = try_wait(500); /* Read in the output of all running commands. */ read_output(); /* Close out pending debug style dialogs. */ close_alerts(); /* Check if a command ran out of time. */ if ( i < 0 ) i = try_kill_one(); } while ( i < 0 ); /* We have a command... process it. */ --cmdsrunning; { timing_info time; int rstat; /* The time data for the command. */ record_times( cmdtab[ i ].pi.hProcess, &time ); /* Clear the temp file. */ if ( cmdtab[ i ].tempfile_bat ) { unlink( cmdtab[ i ].tempfile_bat ); BJAM_FREE( cmdtab[ i ].tempfile_bat ); cmdtab[ i ].tempfile_bat = NULL; } /* Find out the process exit code. */ GetExitCodeProcess( cmdtab[ i ].pi.hProcess, &cmdtab[ i ].exit_code ); /* The dispossition of the command. */ if ( intr ) rstat = EXEC_CMD_INTR; else if ( cmdtab[ i ].exit_code != 0 ) rstat = EXEC_CMD_FAIL; else rstat = EXEC_CMD_OK; /* Output the action block. */ out_action( cmdtab[ i ].action.size > 0 ? cmdtab[ i ].action.value : 0, cmdtab[ i ].target.size > 0 ? cmdtab[ i ].target.value : 0, cmdtab[ i ].command.size > 0 ? cmdtab[ i ].command.value : 0, cmdtab[ i ].buffer_out.size > 0 ? cmdtab[ i ].buffer_out.value : 0, cmdtab[ i ].buffer_err.size > 0 ? cmdtab[ i ].buffer_err.value : 0, cmdtab[ i ].exit_reason ); /* Call the callback, may call back to jam rule land. Assume -p0 in * effect so only pass buffer containing merged output. */ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time, cmdtab[ i ].command.value, cmdtab[ i ].buffer_out.value ); /* Clean up the command data, process, etc. */ string_free( &cmdtab[ i ].action ); string_new( &cmdtab[ i ].action ); string_free( &cmdtab[ i ].target ); string_new( &cmdtab[ i ].target ); string_free( &cmdtab[ i ].command ); string_new( &cmdtab[ i ].command ); if ( cmdtab[ i ].pi.hProcess ) { CloseHandle( cmdtab[ i ].pi.hProcess ); cmdtab[ i ].pi.hProcess = 0; } if ( cmdtab[ i ].pi.hThread ) { CloseHandle( cmdtab[ i ].pi.hThread ); cmdtab[ i ].pi.hThread = 0; } if ( cmdtab[ i ].pipe_out[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 0 ] ); cmdtab[ i ].pipe_out[ 0 ] = 0; } if ( cmdtab[ i ].pipe_out[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 1 ] ); cmdtab[ i ].pipe_out[ 1 ] = 0; } if ( cmdtab[ i ].pipe_err[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 0 ] ); cmdtab[ i ].pipe_err[ 0 ] = 0; } if ( cmdtab[ i ].pipe_err[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 1 ] ); cmdtab[ i ].pipe_err[ 1 ] = 0; } string_free( &cmdtab[ i ].buffer_out ); string_new( &cmdtab[ i ].buffer_out ); string_free( &cmdtab[ i ].buffer_err ); string_new( &cmdtab[ i ].buffer_err ); cmdtab[ i ].exit_code = 0; cmdtab[ i ].exit_reason = EXIT_OK; } return 1; }
int execwait() { int i; int status, w; int rstat; timing_info time; /* Handle naive make1() which doesn't know if cmds are running. */ if( !cmdsrunning ) return 0; if ( is_win95 ) return 0; /* Pick up process pid and status */ while( ( w = wait( &status ) ) == -1 && errno == EINTR ) ; if( w == -1 ) { printf( "child process(es) lost!\n" ); perror("wait"); exit( EXITBAD ); } /* Find the process in the cmdtab. */ for( i = 0; i < MAXJOBS; i++ ) if( w == cmdtab[ i ].pid ) break; if( i == MAXJOBS ) { printf( "waif child found!\n" ); exit( EXITBAD ); } record_times(cmdtab[i].pid, &time); /* Clear the temp file */ if ( cmdtab[i].tempfile ) unlink( cmdtab[ i ].tempfile ); /* Drive the completion */ if( !--cmdsrunning ) signal( SIGINT, istat ); if( intr ) rstat = EXEC_CMD_INTR; else if( w == -1 || status != 0 ) rstat = EXEC_CMD_FAIL; else rstat = EXEC_CMD_OK; cmdtab[ i ].pid = 0; /* SVA don't leak temp files */ if(cmdtab[i].tempfile != NULL) { free(cmdtab[i].tempfile); cmdtab[i].tempfile = NULL; } (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time ); return 1; }
void execcmd( char *string, void (*func)( void *closure, int status, timing_info* ), void *closure, LIST *shell ) { int pid; int slot; int raw_cmd = 0 ; char *argv_static[ MAXARGC + 1 ]; /* +1 for NULL */ char **argv = argv_static; char *p; /* Check to see if we need to hack around the line-length limitation. */ /* Look for a JAMSHELL setting of "%", indicating that the command * should be invoked directly */ if ( shell && !strcmp(shell->string,"%") && !list_next(shell) ) { raw_cmd = 1; shell = 0; } if ( !is_win95_defined ) set_is_win95(); /* Find a slot in the running commands table for this one. */ if ( is_win95 ) { /* only synchronous spans are supported on Windows 95/98 */ slot = 0; } else { for( slot = 0; slot < MAXJOBS; slot++ ) if( !cmdtab[ slot ].pid ) break; } if( slot == MAXJOBS ) { printf( "no slots for child!\n" ); exit( EXITBAD ); } if( !cmdtab[ slot ].tempfile ) { const char *tempdir = path_tmpdir(); DWORD procID = GetCurrentProcessId(); /* SVA - allocate 64 other just to be safe */ cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 64 ); if ( DEBUG_PROFILE ) profile_memory( strlen( tempdir ) + 64 ); sprintf( cmdtab[ slot ].tempfile, "%s\\jam%d-%02d.bat", tempdir, procID, slot ); } /* Trim leading, ending white space */ while( isspace( *string ) ) ++string; /* Write to .BAT file unless the line would be too long and it * meets the other spawnability criteria. */ if( raw_cmd && can_spawn( string ) >= MAXLINE ) { if( DEBUG_EXECCMD ) printf("Executing raw command directly\n"); } else { FILE *f = 0; int tries = 0; raw_cmd = 0; /* Write command to bat file. For some reason this open can fails intermitently. But doing some retries works. Most likely this is due to a previously existing file of the same name that happens to be opened by an active virus scanner. Pointed out, and fix by Bronek Kozicki. */ for (; !f && tries < 4; ++tries) { f = fopen( cmdtab[ slot ].tempfile, "w" ); if ( !f && tries < 4 ) Sleep( 250 ); } if (!f) { printf( "failed to write command file!\n" ); exit( EXITBAD ); } fputs( string, f ); fclose( f ); string = cmdtab[ slot ].tempfile; if( DEBUG_EXECCMD ) { if (shell) printf("using user-specified shell: %s", shell->string); else printf("Executing through .bat file\n"); } } /* Forumulate argv */ /* If shell was defined, be prepared for % and ! subs. */ /* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */ if( shell ) { int i; char jobno[4]; int gotpercent = 0; sprintf( jobno, "%d", slot + 1 ); for( i = 0; shell && i < MAXARGC; i++, shell = list_next( shell ) ) { switch( shell->string[0] ) { case '%': argv[i] = string; gotpercent++; break; case '!': argv[i] = jobno; break; default: argv[i] = shell->string; } if( DEBUG_EXECCMD ) printf( "argv[%d] = '%s'\n", i, argv[i] ); } if( !gotpercent ) argv[i++] = string; argv[i] = 0; } else if (raw_cmd) { argv = string_to_args(string); } else { /* don't worry, this is ignored on Win95/98, see later.. */ argv[0] = "cmd.exe"; argv[1] = "/Q/C"; /* anything more is non-portable */ argv[2] = string; argv[3] = 0; } /* Catch interrupts whenever commands are running. */ if( !cmdsrunning++ ) istat = signal( SIGINT, onintr ); /* Start the command */ /* on Win95, we only do a synchronous call */ if ( is_win95 ) { static const char* hard_coded[] = { "del", "erase", "copy", "mkdir", "rmdir", "cls", "dir", "ren", "rename", "move", 0 }; const char** keyword; int len, spawn = 1; int result; timing_info time = {0,0}; for ( keyword = hard_coded; keyword[0]; keyword++ ) { len = strlen( keyword[0] ); if ( strnicmp( string, keyword[0], len ) == 0 && !isalnum(string[len]) ) { /* this is one of the hard coded symbols, use 'system' to run */ /* them.. except for "del"/"erase" */ if ( keyword - hard_coded < 2 ) result = process_del( string ); else result = system( string ); spawn = 0; break; } } if (spawn) { char** args; /* convert the string into an array of arguments */ /* we need to take care of double quotes !! */ args = string_to_args( string ); if ( args ) { #if 0 char** arg; fprintf( stderr, "%s: ", args[0] ); arg = args+1; while ( arg[0] ) { fprintf( stderr, " {%s}", arg[0] ); arg++; } fprintf( stderr, "\n" ); #endif result = spawnvp( P_WAIT, args[0], args ); record_times(result, &time); free_argv( args ); } else result = 1; } func( closure, result ? EXEC_CMD_FAIL : EXEC_CMD_OK, &time ); return; } if( DEBUG_EXECCMD ) { char **argp = argv; printf("Executing command"); while(*argp != 0) { printf(" [%s]", *argp); argp++; } printf("\n"); } /* the rest is for Windows NT only */ /* spawn doesn't like quotes around the command name */ if ( argv[0][0] == '"') { int l = strlen(argv[0]); /* Clobber any closing quote, shortening the string by one * element */ if (argv[0][l-1] == '"') argv[0][l-1] = '\0'; /* Move everything *including* the original terminating zero * back one place in memory, covering up the opening quote */ memmove(argv[0],argv[0]+1,l); } if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) == -1 ) { perror( "spawn" ); exit( EXITBAD ); } /* Save the operation for execwait() to find. */ cmdtab[ slot ].pid = pid; cmdtab[ slot ].func = func; cmdtab[ slot ].closure = closure; /* Wait until we're under the limit of concurrent commands. */ /* Don't trust globs.jobs alone. */ while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs ) if( !execwait() ) break; if (argv != argv_static) { free_argv(argv); } }