This is an automated email from Gerrit.

"Kautuk Consul <kcon...@ventanamicro.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7377

-- gerrit

commit 36aae95c5e277da89cea5b23f23d0c9dbff677c0
Author: Kautuk Consul <kcon...@ventanamicro.com>
Date:   Mon Oct 17 16:57:36 2022 +0530

    src/target/semihosting_common.c: add stdfd fd control command
    
    The semihosting->stdin_fd is initially in blocking mode.
    Due to this there is a possibility that the system software blocks
    waiting for a key-press from the user. This can adversely affect
    various housekeeping aspects of system software such as the
    scheduling of the system software tasks/processes/threads.
    
    Specifically, in my case I am booting the Linux kernel on RISCV
    that routes all console read and write character requests to the
    openSBI firmware. Since the openSBI firmware blocks waiting for a
    key-press and openocd is waiting in getchar() the entire Linux
    kernel scheduling is blocked due to which there are various stalls
    in the kernel.
    
    This patch introduces a new command called semihosting_stdfd that
    enables us to put any of the standard input/output/error fds into
    non-blocking mode. After applying this patch and running the
    semihosting_std command my scheduling and kernel thread stalls were
    removed and I could get the Linux bash prompt and could successfully
    run shell commands and observe their outputs in semihosting console.
    
    This same command can be extended if anyone wants to add more
    controls to the semihosting standard file descriptors.
    
    Also added documentation for this new command.
    
    Signed-off-by: Kautuk Consul <kcon...@ventanamicro.com>
    Change-Id: I5f0c62db3e1f2ea35d1a225e0ed02eeeddd52e53

diff --git a/doc/openocd.texi b/doc/openocd.texi
index e9f93614c9..a28ce30982 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9583,6 +9583,13 @@ Set the base directory for semihosting I/O, either an 
absolute path or a path re
 Use "." for the current directory.
 @end deffn
 
+@deffn {Command} {arm semihosting_stdfd} ['in'|'out'|'err'] 
['blocking'|'nonblocking']
+@cindex ARM semihosting
+Set/unset the O_NONBLOCK file status flag in the 
semihosting->std[in|out|err]_fd file descriptor. This file status
+flag affects the appropriate standard file descriptor's blocking/non-blocking 
status thus affecting the
+responsiveness of the semihosting console to inputs/outputs from/to standard 
input/output/error file descriptors.
+@end deffn
+
 @section ARMv4 and ARMv5 Architecture
 @cindex ARMv4
 @cindex ARMv5
diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c
index dc0dae2c87..94a4883f04 100644
--- a/src/target/semihosting_common.c
+++ b/src/target/semihosting_common.c
@@ -2038,6 +2038,57 @@ 
COMMAND_HANDLER(handle_common_semihosting_basedir_command)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(handle_common_semihosting_stdfd_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+
+       if (!target) {
+               LOG_ERROR("No target selected");
+               return ERROR_FAIL;
+       }
+
+       struct semihosting *semihosting = target->semihosting;
+       if (!semihosting) {
+               command_print(CMD, "semihosting not supported for current 
target");
+               return ERROR_FAIL;
+       }
+
+       if (!semihosting->is_active) {
+               command_print(CMD, "semihosting not yet enabled for current 
target");
+               return ERROR_FAIL;
+       }
+
+       int flags;
+       int fd;
+
+       if (CMD_ARGC < 2 || CMD_ARGC > 2)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (strcmp(CMD_ARGV[0], "in") == 0)
+               fd = semihosting->stdin_fd;
+       else if (strcmp(CMD_ARGV[0], "out") == 0)
+               fd = semihosting->stdout_fd;
+       else if (strcmp(CMD_ARGV[0], "err") == 0)
+               fd = semihosting->stderr_fd;
+       else
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (strcmp(CMD_ARGV[1], "blocking") == 0) {
+               flags = fcntl(fd, F_GETFL, 0);
+               flags & O_NONBLOCK ? fcntl(fd, F_SETFL, flags & (~O_NONBLOCK)) 
: 1;
+       } else if (strcmp(CMD_ARGV[1], "nonblocking") == 0) {
+               flags = fcntl(fd, F_GETFL, 0);
+               flags & O_NONBLOCK ? 1 : fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+       } else {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       command_print(CMD, "semihosting %s standard fd set to %s",
+               CMD_ARGV[0], CMD_ARGV[1]);
+
+       return ERROR_OK;
+}
+
 const struct command_registration semihosting_common_handlers[] = {
        {
                .name = "semihosting",
@@ -2088,5 +2139,12 @@ const struct command_registration 
semihosting_common_handlers[] = {
                .usage = "[dir]",
                .help = "set the base directory for semihosting I/O operations",
        },
+       {
+               .name = "semihosting_stdfd",
+               .handler = handle_common_semihosting_stdfd_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['in'|'out'|'err'] ['blocking'|'nonblocking']",
+               .help = "control the semihosting->std*_fd file descriptor 
flags",
+       },
        COMMAND_REGISTRATION_DONE
 };

-- 

Reply via email to