mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-06 15:26:58 +02:00
The include file <command.h> does not need anything from <env.h>. Furthermore, include/env.h itself includes other headers which can lead to longer indirect inclusion paths. To prepare to remove <env.h> from <command.h> fix all of the places which had relied on this indirect inclusion to instead include <env.h> directly. Reviewed-by: Mattijs Korpershoek <mkorpershoek@kernel.org> # android, bcb Reviewed-by: Jerome Forissier <jerome.forissier@linaro.org> # spawn Signed-off-by: Tom Rini <trini@konsulko.com>
189 lines
3.5 KiB
C
189 lines
3.5 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (c) 2011 The Chromium OS Authors.
|
|
*/
|
|
|
|
#include <command.h>
|
|
#include <console.h>
|
|
#include <env.h>
|
|
#include <malloc.h>
|
|
#include <vsprintf.h>
|
|
#include <uthread.h>
|
|
|
|
/* Spawn arguments and job index */
|
|
struct spa {
|
|
int argc;
|
|
char **argv;
|
|
unsigned int job_idx;
|
|
};
|
|
|
|
/*
|
|
* uthread group identifiers for each running job
|
|
* 0: job slot available, != 0: uthread group id
|
|
* Note that job[0] is job_id 1, job[1] is job_id 2 etc.
|
|
*/
|
|
static unsigned int job[CONFIG_CMD_SPAWN_NUM_JOBS];
|
|
/* Return values of the commands run as jobs */
|
|
static enum command_ret_t job_ret[CONFIG_CMD_SPAWN_NUM_JOBS];
|
|
|
|
static void spa_free(struct spa *spa)
|
|
{
|
|
int i;
|
|
|
|
if (!spa)
|
|
return;
|
|
|
|
for (i = 0; i < spa->argc; i++)
|
|
free(spa->argv[i]);
|
|
free(spa->argv);
|
|
free(spa);
|
|
}
|
|
|
|
static struct spa *spa_create(int argc, char *const argv[])
|
|
{
|
|
struct spa *spa;
|
|
int i;
|
|
|
|
spa = calloc(1, sizeof(*spa));
|
|
if (!spa)
|
|
return NULL;
|
|
spa->argc = argc;
|
|
spa->argv = malloc(argc * sizeof(char *));
|
|
if (!spa->argv)
|
|
goto err;
|
|
for (i = 0; i < argc; i++) {
|
|
spa->argv[i] = strdup(argv[i]);
|
|
if (!spa->argv[i])
|
|
goto err;
|
|
}
|
|
return spa;
|
|
err:
|
|
spa_free(spa);
|
|
return NULL;
|
|
}
|
|
|
|
static void spawn_thread(void *arg)
|
|
{
|
|
struct spa *spa = (struct spa *)arg;
|
|
ulong cycles = 0;
|
|
int repeatable = 0;
|
|
|
|
job_ret[spa->job_idx] = cmd_process(0, spa->argc, spa->argv,
|
|
&repeatable, &cycles);
|
|
spa_free(spa);
|
|
}
|
|
|
|
static unsigned int next_job_id(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < CONFIG_CMD_SPAWN_NUM_JOBS; i++)
|
|
if (!job[i])
|
|
return i + 1;
|
|
|
|
/* No job available */
|
|
return 0;
|
|
}
|
|
|
|
static void refresh_jobs(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < CONFIG_CMD_SPAWN_NUM_JOBS; i++)
|
|
if (job[i] && uthread_grp_done(job[i]))
|
|
job[i] = 0;
|
|
|
|
}
|
|
|
|
static int do_spawn(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
unsigned int id;
|
|
unsigned int idx;
|
|
struct spa *spa;
|
|
int ret;
|
|
|
|
if (argc == 1)
|
|
return CMD_RET_USAGE;
|
|
|
|
spa = spa_create(argc - 1, argv + 1);
|
|
if (!spa)
|
|
return CMD_RET_FAILURE;
|
|
|
|
refresh_jobs();
|
|
|
|
id = next_job_id();
|
|
if (!id)
|
|
return CMD_RET_FAILURE;
|
|
idx = id - 1;
|
|
|
|
job[idx] = uthread_grp_new_id();
|
|
|
|
ret = uthread_create(NULL, spawn_thread, spa, 0, job[idx]);
|
|
if (ret) {
|
|
job[idx] = 0;
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
|
|
ret = env_set_ulong("job_id", id);
|
|
if (ret)
|
|
return CMD_RET_FAILURE;
|
|
|
|
return CMD_RET_SUCCESS;
|
|
}
|
|
|
|
U_BOOT_CMD(spawn, CONFIG_SYS_MAXARGS, 0, do_spawn,
|
|
"run commands and summarize execution time",
|
|
"command [args...]\n");
|
|
|
|
static enum command_ret_t wait_job(unsigned int idx)
|
|
{
|
|
int prev = disable_ctrlc(false);
|
|
|
|
while (!uthread_grp_done(job[idx])) {
|
|
if (ctrlc()) {
|
|
puts("<INTERRUPT>\n");
|
|
disable_ctrlc(prev);
|
|
return CMD_RET_FAILURE;
|
|
}
|
|
uthread_schedule();
|
|
}
|
|
|
|
job[idx] = 0;
|
|
disable_ctrlc(prev);
|
|
|
|
return job_ret[idx];
|
|
}
|
|
|
|
static int do_wait(struct cmd_tbl *cmdtp, int flag, int argc,
|
|
char *const argv[])
|
|
{
|
|
enum command_ret_t ret = CMD_RET_SUCCESS;
|
|
unsigned long id;
|
|
unsigned int idx;
|
|
int i;
|
|
|
|
if (argc == 1) {
|
|
for (i = 0; i < CONFIG_CMD_SPAWN_NUM_JOBS; i++)
|
|
if (job[i])
|
|
ret = wait_job(i);
|
|
} else {
|
|
for (i = 1; i < argc; i++) {
|
|
id = dectoul(argv[i], NULL);
|
|
if (id < 1 || id > CONFIG_CMD_SPAWN_NUM_JOBS)
|
|
return CMD_RET_USAGE;
|
|
idx = (int)id - 1;
|
|
ret = wait_job(idx);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
U_BOOT_CMD(wait, CONFIG_SYS_MAXARGS, 0, do_wait,
|
|
"wait for one or more jobs to complete",
|
|
"[job_id ...]\n"
|
|
" - Wait until all specified jobs have exited and return the\n"
|
|
" exit status of the last job waited for. When no job_id is\n"
|
|
" given, wait for all the background jobs.\n");
|