From 8dbb1250f587484774752e8610f04a98157ca10a Mon Sep 17 00:00:00 2001 From: Evgeniy Naydanov Date: Wed, 22 Nov 2023 18:10:27 +0300 Subject: [PATCH] break from long loops on shutdown request In loops that typically take longer time to complete, check if there is a pending shutdown request. If so, terminate the loop. This allows to respond to a signal requesting a shutdown during some loops which do not return control to main OpenOCD loop. Change-Id: Iace0b58eddde1237832d0f9333a7c7b930565674 Signed-off-by: Evgeniy Naydanov --- src/server/server.h | 1 + src/target/image.c | 3 +++ src/target/riscv/batch.c | 3 +++ src/target/riscv/program.c | 3 +++ src/target/riscv/riscv-013.c | 6 ++++++ src/target/riscv/riscv.c | 6 ++++++ src/target/target.c | 20 +++++++++++++++++++- 7 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/server/server.h b/src/server/server.h index c9d4698af8..ea1e94ec5f 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -118,5 +118,6 @@ COMMAND_HELPER(server_port_command, unsigned short *out); #define ERROR_SERVER_REMOTE_CLOSED (-400) #define ERROR_CONNECTION_REJECTED (-401) +#define ERROR_SERVER_INTERRUPTED (-402) #endif /* OPENOCD_SERVER_SERVER_H */ diff --git a/src/target/image.c b/src/target/image.c index 9175c200af..440fe17d18 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -24,6 +24,7 @@ #include "image.h" #include "target.h" #include +#include /* convert ELF header field to host endianness */ #define field16(elf, field) \ @@ -1295,6 +1296,8 @@ int image_calculate_checksum(const uint8_t *buffer, uint32_t nbytes, uint32_t *c crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buffer++) & 255]; } keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; } LOG_DEBUG("Calculating checksum done; checksum=0x%" PRIx32, crc); diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index 290ce371be..7abe8ade3f 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -111,6 +111,9 @@ int riscv_batch_run(struct riscv_batch *batch) keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + if (bscan_tunnel_ir_width != 0) { /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */ for (size_t i = 0; i < batch->used_scans; ++i) { diff --git a/src/target/riscv/program.c b/src/target/riscv/program.c index 22962fab4e..4543495192 100644 --- a/src/target/riscv/program.c +++ b/src/target/riscv/program.c @@ -47,6 +47,9 @@ int riscv_program_exec(struct riscv_program *p, struct target *t) { keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + p->execution_result = RISCV_PROGBUF_EXEC_RESULT_UNKNOWN; riscv_reg_t saved_registers[GDB_REGNO_XPR31 + 1]; for (size_t i = GDB_REGNO_ZERO + 1; i <= GDB_REGNO_XPR31; ++i) { diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 2b8d381515..651342acd0 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -595,6 +595,9 @@ static int dmi_op_timeout(struct target *target, uint32_t *data_in, keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + time_t start = time(NULL); /* This first loop performs the request. Note that if for some reason this * stays busy, it is actually due to the previous access. */ @@ -3241,6 +3244,9 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, return ERROR_FAIL; } keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + dmi_status_t status = dmi_scan(target, NULL, &sbvalue[next_read_j], DMI_OP_READ, sbdata[j], 0, false); /* By reading from sbdata0, we have just initiated another system bus read. diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index dd9ee43e8b..47674ad01b 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -5141,6 +5141,9 @@ static int riscv_set_or_write_register(struct target *target, keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + if (regid == GDB_REGNO_PC) { return riscv_set_or_write_register(target, GDB_REGNO_DPC, value, write_through); } else if (regid == GDB_REGNO_PRIV) { @@ -5238,6 +5241,9 @@ int riscv_get_register(struct target *target, riscv_reg_t *value, keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + if (regid == GDB_REGNO_PC) { return riscv_get_register(target, value, GDB_REGNO_DPC); } else if (regid == GDB_REGNO_PRIV) { diff --git a/src/target/target.c b/src/target/target.c index 216dcb2eae..5e93c78734 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1214,6 +1214,10 @@ int target_run_read_async_algorithm(struct target *target, /* Avoid GDB timeouts */ keep_alive(); + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + break; + } } if (retval != ERROR_OK) { @@ -3225,8 +3229,11 @@ int target_wait_state(struct target *target, enum target_state state, unsigned i nvp_value2name(nvp_target_state, state)->name); } - if (cur-then > 500) + if (cur - then > 500) { keep_alive(); + if (openocd_is_shutdown_pending()) + return ERROR_SERVER_INTERRUPTED; + } if ((cur-then) > ms) { LOG_ERROR("timed out while waiting for target %s", @@ -3509,6 +3516,11 @@ static int target_fill_mem(struct target *target, break; /* avoid GDB timeouts */ keep_alive(); + + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + break; + } } free(target_buf); @@ -3851,6 +3863,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver } } keep_alive(); + if (openocd_is_shutdown_pending()) { + retval = ERROR_SERVER_INTERRUPTED; + free(data); + free(buffer); + goto done; + } } } free(data);