Compare commits

...

11 Commits
4.11.3 ... 4.11

Author SHA1 Message Date
Christian Mauderer
051778e9d6 imfs: Fix index underrun when extending empty file
Currently the following sequence causes a endless loop when extending an
IMFS file:

- Create a file with zero length and close it.
- Make sure nearly no allocatable memory is left.
- Open the file and write enough data into it that more than the
  remaining memory will be used.

In that case when extending the IMFS file, the file currently need zero
blocks. If allocating enough new blocks fails, the already allocated new
blocks will be freed again.

The comparison of block>=old_blocks that has been used prior to this
patch compared two unsigned numbers. If old_blocks was zero, the
comparison of these two numbers always evaluated to true.

This patch frees the last block in a separate step to avoid this
problem.

Note: This patch is a backport of
43119193ef from RTEMS master. It only
contains the bugfix. Adding a test case has been skipped because that
part of the patch didn't apply without problems and is not really
relevant for fixing the bug.

Fixes #2353
2022-04-07 10:45:12 +02:00
Thanassis Tsiodras
63c6b06fd1 bsps/sparc: Fix global construction/destruction
The

  KEEP (*(SORT(.ctors.*)))
  KEEP (*(.ctors))

cannot be simplified to

  KEEP (*(SORT(.ctors*)))

since

  .ctors < .ctors.*

in lexicographical order.

See spglobalcon02 test case.

Close #3319.
2021-08-12 14:47:59 +02:00
Daniel Hellstrom
a100457c7d leon,gr1553b: improve init check
Check in init3 not needed since same data is already checked in init2
stage. Adds an extra check that the APB register space is available before
accessing it.

Closes #2331
2020-10-01 11:35:03 +10:00
Chris Johns
55d9d8c552 libmisc/shell: Updating joel script handling fixes from RTEMS 5
Updates #3877
2020-04-14 18:48:32 +10:00
Chris Johns
4d906d6af1 libmisc/shell: Fix the handling of joel scripts in telnet
- Fix the passing of std[in/out] to child threads
- Fix deleting of managed memory in the key destructor
- Only set the key in the main loop thread
- Only allocate a shell env outside of the main loop
- Fix memory leak if the task start fails
- Remove error level from shell env, it cannot be returned this way. Add
  exit_code but the API is broken so it cannot be returned.

Closes #3877
2020-02-19 19:05:54 +11:00
Chris Johns
fe09d8d4d3 libcsupport/newlib: Call newlib's __sinit to force reent initialisation
- Newlib overtites any FILE pointers set in stdin, stdout or stderr.

Closes #3870
2020-02-19 19:01:08 +11:00
Jonathan Brandmeyer
33c82ddba1 shell: Correct argument order of mfill
Close #3722.

(cherry picked from commit 2e8a66d13f)
2019-03-14 09:57:40 -04:00
Sebastian Huber
dc6bd8bb66 score: Fix ISR enable in _Thread_Dispatch_enable()
This bug had probably no effect since the interrupt enable is idempotent
on all CPU ports.

Close #3497.
2018-08-20 08:40:24 +02:00
Sebastian Huber
3abc731b22 rfs: Remove erroneous call of rtems_disk_release()
The function rtems_rfs_buffer_sync() erroneously calls
rtems_disk_release(). This screws up the reference counting of the disk.

Close #3494.
2018-08-10 06:57:10 +02:00
Sebastian Huber
d4165e7173 sptests/sp36: Remove obsolete test program
It tests the (never really working) strict order mutex option.

Update #3406.
2018-06-19 07:58:13 +02:00
Chris Johns
c3353ae565 cpukit/mttpd: Add a callback to generate a per file HTTP etag.
Closes #3324
2018-03-08 15:34:15 +11:00
18 changed files with 440 additions and 355 deletions

View File

@@ -191,6 +191,8 @@ static int gr1553_init2(struct drvmgr_dev *dev)
return DRVMGR_FAIL;
}
pnpinfo = &ambadev->info;
if ( pnpinfo->apb_slv == NULL )
return DRVMGR_EIO;
regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
/* Stop IRQ */
@@ -227,9 +229,6 @@ static int gr1553_init3(struct drvmgr_dev *dev)
/* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)dev->businfo;
if ( ambadev == NULL ) {
return DRVMGR_FAIL;
}
pnpinfo = &ambadev->info;
regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start;
@@ -257,6 +256,12 @@ static int gr1553_init3(struct drvmgr_dev *dev)
gr1553_list_add(&gr1553_rt_root, feat);
}
if ( priv->features == 0 ) {
/* no features in HW should never happen.. an I/O error? */
free(priv);
return DRVMGR_EIO;
}
return DRVMGR_OK;
}

View File

@@ -87,11 +87,13 @@ SECTIONS
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors*)))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors*)))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
_rodata_start = . ;
*(.rodata*)

View File

@@ -44,7 +44,10 @@ bool newlib_create_hook(
}
#endif
_REENT_INIT_PTR((creating_task->libc_reent)); /* GCC extension: structure constants */
extern void __sinit (struct _reent *s);
struct _reent *reent = (struct _reent *) creating_task->libc_reent;
_REENT_INIT_PTR((reent)); /* GCC extension: structure constants */
__sinit( reent );
return true;
}

View File

@@ -188,9 +188,10 @@ static int IMFS_memfile_extend(
offset = 0;
}
} else {
for ( ; block>=old_blocks ; block-- ) {
for ( ; block>old_blocks ; block-- ) {
IMFS_memfile_remove_block( memfile, block );
}
IMFS_memfile_remove_block( memfile, old_blocks );
rtems_set_errno_and_return_minus_one( ENOSPC );
}
}

View File

@@ -397,7 +397,6 @@ rtems_rfs_buffer_sync (rtems_rfs_file_system* fs)
rtems_status_text (sc));
result = EIO;
}
rtems_disk_release (fs->disk);
#else
if (fsync (fs->device) < 0)
{

View File

@@ -60,7 +60,7 @@ static int rtems_shell_main_mfill(
/*
* Now fill the memory.
*/
memset(addr, size, value);
memset(addr, value, size);
return 0;
}

View File

@@ -40,22 +40,44 @@
#include <pthread.h>
#include <assert.h>
#define SHELL_STD_DEBUG 0
#if SHELL_STD_DEBUG
#include <rtems/bspIo.h>
#define shell_std_debug(...) \
do { printk("shell[%08x]: ", rtems_task_self()); printk(__VA_ARGS__); } while (0)
#else
#define shell_std_debug(...)
#endif
const rtems_shell_env_t rtems_global_shell_env = {
.magic = rtems_build_name('S', 'E', 'N', 'V'),
.managed = false,
.devname = CONSOLE_DEVICE_NAME,
.taskname = "SHGL",
.exit_shell = false,
.forever = true,
.errorlevel = -1,
.echo = false,
.cwd = "/",
.input = NULL,
.output = NULL,
.output_append = false,
.parent_stdin = NULL,
.parent_stdout = NULL,
.parent_stderr = NULL,
.wake_on_end = RTEMS_ID_NONE,
.login_check = NULL
.exit_code = NULL,
.login_check = NULL,
.uid = 0,
.gid = 0
};
typedef struct rtems_shell_env_key_handle
{
bool managed;
rtems_shell_env_t* env;
} rtems_shell_env_key_handle;
static pthread_once_t rtems_shell_once = PTHREAD_ONCE_INIT;
static pthread_key_t rtems_shell_current_env_key;
@@ -64,7 +86,7 @@ static pthread_key_t rtems_shell_current_env_key;
* Initialize the shell user/process environment information
*/
static rtems_shell_env_t *rtems_shell_init_env(
rtems_shell_env_t *shell_env_p
rtems_shell_env_t *shell_env_parent
)
{
rtems_shell_env_t *shell_env;
@@ -72,11 +94,16 @@ static rtems_shell_env_t *rtems_shell_init_env(
shell_env = malloc(sizeof(rtems_shell_env_t));
if ( !shell_env )
return NULL;
if ( !shell_env_p ) {
if ( shell_env_parent == NULL ) {
shell_env_parent = rtems_shell_get_current_env();
}
if ( shell_env_parent == NULL ) {
*shell_env = rtems_global_shell_env;
} else {
*shell_env = *shell_env_p;
*shell_env = *shell_env_parent;
}
shell_env->managed = true;
shell_env->taskname = NULL;
return shell_env;
@@ -89,17 +116,20 @@ static void rtems_shell_env_free(
void *ptr
)
{
rtems_shell_env_t *shell_env;
shell_env = (rtems_shell_env_t *) ptr;
if ( ptr != NULL ) {
rtems_shell_env_key_handle *handle = (rtems_shell_env_key_handle *) ptr;
rtems_shell_env_t *shell_env = handle->env;
if ( !ptr )
return;
if ( handle->managed ) {
if ( shell_env->input )
free((void *)shell_env->input);
if ( shell_env->output )
free((void *)shell_env->output);
free( shell_env );
}
if ( shell_env->input )
free((void *)shell_env->input);
if ( shell_env->output )
free((void *)shell_env->output);
free( ptr );
free( handle );
}
}
static void rtems_shell_create_file(const char *name, const char *content)
@@ -155,12 +185,73 @@ void rtems_shell_init_environment(void)
assert(pthread_once(&rtems_shell_once, rtems_shell_init_once) == 0);
}
/*
* Set the shell env into the current thread's shell key.
*/
static bool rtems_shell_set_shell_env(
rtems_shell_env_t* shell_env
)
{
/*
* The shell environment can be managed or it can be provided by a
* user. We need to create a handle to hold the env pointer.
*/
rtems_shell_env_key_handle *handle;
int eno;
handle = malloc(sizeof(rtems_shell_env_key_handle));
if (handle == NULL) {
rtems_error(0, "no memory for shell env key handle)");
return false;
}
handle->managed = shell_env->managed;
handle->env = shell_env;
eno = pthread_setspecific(rtems_shell_current_env_key, handle);
if (eno != 0) {
rtems_error(0, "pthread_setspecific(shell_current_env_key): set");
return false;
}
return true;
}
/*
* Clear the current thread's shell key.
*/
static void rtems_shell_clear_shell_env(void)
{
int eno;
/*
* Run the destructor manually.
*/
rtems_shell_env_free(pthread_getspecific(rtems_shell_current_env_key));
/*
* Clear the key
*/
eno = pthread_setspecific(rtems_shell_current_env_key, NULL);
if (eno != 0)
rtems_error(0, "pthread_setspecific(shell_current_env_key): clear");
/*
* Clear stdin and stdout file pointers of they will be closed
*/
stdin = NULL;
stdout = NULL;
}
/*
* Return the current shell environment
*/
rtems_shell_env_t *rtems_shell_get_current_env(void)
{
return (rtems_shell_env_t *) pthread_getspecific(rtems_shell_current_env_key);
rtems_shell_env_key_handle *handle;
handle = (rtems_shell_env_key_handle*)
pthread_getspecific(rtems_shell_current_env_key);
return handle == NULL ? NULL : handle->env;
}
/*
@@ -170,15 +261,27 @@ rtems_shell_env_t *rtems_shell_get_current_env(void)
void rtems_shell_dup_current_env(rtems_shell_env_t *copy)
{
rtems_shell_env_t *env = rtems_shell_get_current_env();
if (env) {
if (env != NULL) {
shell_std_debug("dup: existing parent\n");
*copy = *env;
}
else {
memset(copy, 0, sizeof(rtems_shell_env_t));
copy->magic = rtems_build_name('S', 'E', 'N', 'V');
copy->devname = CONSOLE_DEVICE_NAME;
copy->taskname = "RTSH";
*copy = rtems_global_shell_env;
copy->magic = rtems_build_name('S', 'E', 'N', 'V');
copy->devname = CONSOLE_DEVICE_NAME;
copy->taskname = "RTSH";
copy->parent_stdout = stdout;
copy->parent_stdin = stdin;
copy->parent_stderr = stderr;
shell_std_debug("dup: global: copy: %p out: %d (%p) in: %d (%p)\n",
copy,
fileno(copy->parent_stdout), copy->parent_stdout,
fileno(copy->parent_stdin), copy->parent_stdin);
}
/*
* Duplicated environments are not managed.
*/
copy->managed = false;
}
/*
@@ -203,14 +306,21 @@ static int rtems_shell_line_editor(
int up;
int cmd = -1;
int inserting = 1;
int in_fileno = fileno(in);
int out_fileno = fileno(out);
output = (out && isatty(fileno(in)));
/*
* Only this task can use this file descriptor because calling
* fileno will block if another thread call made a call on this
* descriptor.
*/
output = (out && isatty(in_fileno));
col = last_col = 0;
tcdrain(fileno(in));
tcdrain(in_fileno);
if (out)
tcdrain(fileno(out));
tcdrain(out_fileno);
if (output && prompt)
fprintf(out, "\r%s", prompt);
@@ -546,9 +656,9 @@ static int rtems_shell_line_editor(
static bool rtems_shell_login(rtems_shell_env_t *env, FILE * in,FILE * out)
{
FILE *fd;
int c;
time_t t;
FILE *fd;
int c;
time_t t;
if (out) {
if ((env->devname[5]!='p')||
@@ -556,9 +666,9 @@ static bool rtems_shell_login(rtems_shell_env_t *env, FILE * in,FILE * out)
(env->devname[7]!='y')) {
fd = fopen("/etc/issue","r");
if (fd) {
while ((c=fgetc(fd))!=EOF) {
while ((c = fgetc(fd)) != EOF) {
if (c=='@') {
switch(c=fgetc(fd)) {
switch (c = fgetc(fd)) {
case 'L':
fprintf(out,"%s", env->devname);
break;
@@ -707,106 +817,115 @@ static bool rtems_shell_init_user_env(void)
#define RTEMS_SHELL_PROMPT_SIZE (128)
bool rtems_shell_main_loop(
rtems_shell_env_t *shell_env_arg
rtems_shell_env_t *shell_env
)
{
rtems_shell_env_t *shell_env;
int eno;
struct termios term;
struct termios previous_term;
char *prompt = NULL;
int cmd;
int cmd_count = 1; /* assume a script and so only 1 command line */
char *cmds[RTEMS_SHELL_CMD_COUNT];
char *cmd_argv;
int argc;
char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
bool result = true;
bool input_file = false;
int line = 0;
FILE *stdinToClose = NULL;
FILE *stdoutToClose = NULL;
struct termios term;
struct termios previous_term;
char *prompt = NULL;
int cmd;
int cmd_count = 1; /* assume a script and so only 1 command line */
char *cmds[RTEMS_SHELL_CMD_COUNT];
char *cmd_argv;
int argc;
char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
bool result = true;
bool input_file = false;
int line = 0;
FILE *stdinToClose = NULL;
FILE *stdoutToClose = NULL;
rtems_shell_init_environment();
shell_env = rtems_shell_init_env(shell_env_arg);
if (shell_env == NULL) {
rtems_error(0, "rtems_shell_init_env");
if (shell_env->magic != rtems_build_name('S', 'E', 'N', 'V')) {
rtems_error(0, "invalid shell environment passed to the main loop)");
return false;
}
eno = pthread_setspecific(rtems_shell_current_env_key, shell_env);
if (eno != 0) {
rtems_error(0, "pthread_setspecific(shell_current_env_key)");
if (!rtems_shell_set_shell_env(shell_env))
return false;
}
if (!rtems_shell_init_user_env()) {
rtems_error(0, "rtems_shell_init_user_env");
rtems_shell_clear_shell_env();
return false;
}
fileno(stdout);
shell_std_debug("env: %p\n", shell_env);
/* fprintf( stderr,
"-%s-%s-\n", shell_env->input, shell_env->output );
*/
if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) {
if (strcmp(shell_env->output, "stderr") == 0) {
if (shell_env->output == NULL || strcmp(shell_env->output, "stdout") == 0) {
if (shell_env->parent_stdout != NULL)
stdout = shell_env->parent_stdout;
}
else if (strcmp(shell_env->output, "stderr") == 0) {
if (shell_env->parent_stderr != NULL)
stdout = shell_env->parent_stderr;
else
stdout = stderr;
} else if (strcmp(shell_env->output, "/dev/null") == 0) {
fclose (stdout);
} else {
FILE *output = fopen(shell_env_arg->output,
shell_env_arg->output_append ? "a" : "w");
if (!output) {
fprintf(stderr, "shell: open output %s failed: %s\n",
shell_env_arg->output, strerror(errno));
return false;
}
stdout = output;
stdoutToClose = output;
} else if (strcmp(shell_env->output, "/dev/null") == 0) {
fclose (stdout);
} else {
FILE *output = fopen(shell_env->output,
shell_env->output_append ? "a" : "w");
if (output == NULL) {
fprintf(stderr, "shell: open output %s failed: %s\n",
shell_env->output, strerror(errno));
rtems_shell_clear_shell_env();
return false;
}
stdout = output;
stdoutToClose = output;
}
if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) {
FILE *input = fopen(shell_env_arg->input, "r");
if (!input) {
if (shell_env->input == NULL || strcmp(shell_env->input, "stdin") == 0) {
if (shell_env->parent_stdin != NULL)
stdin = shell_env->parent_stdin;
} else {
FILE *input = fopen(shell_env->input, "r");
if (input == NULL) {
fprintf(stderr, "shell: open input %s failed: %s\n",
shell_env_arg->input, strerror(errno));
shell_env->input, strerror(errno));
if (stdoutToClose != NULL)
fclose(stdoutToClose);
rtems_shell_clear_shell_env();
return false;
}
stdin = input;
stdinToClose = input;
shell_env->forever = false;
input_file =true;
input_file = true;
}
else {
/* make a raw terminal,Linux Manuals */
if (!input_file) {
/* Make a raw terminal, Linux Manuals */
if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
term = previous_term;
term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
term.c_oflag &= ~OPOST;
term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
term.c_cflag |= CLOCAL | CREAD;
term.c_cflag |= CLOCAL | CREAD;
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;
if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
fprintf(stderr,
"shell:cannot set terminal attributes(%s)\n",shell_env->devname);
"shell: cannot set terminal attributes(%s)\n",shell_env->devname);
}
}
cmd_count = RTEMS_SHELL_CMD_COUNT;
prompt = malloc(RTEMS_SHELL_PROMPT_SIZE);
if (!prompt)
fprintf(stderr,
"shell:cannot allocate prompt memory\n");
"shell: cannot allocate prompt memory\n");
}
setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/
setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
shell_std_debug("child out: %d (%p)\n", fileno(stdout), stdout);
shell_std_debug("child in: %d (%p)\n", fileno(stdin), stdin);
/* Do not buffer if interactive else leave buffered */
if (!input_file)
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
/*
* Allocate the command line buffers.
@@ -869,8 +988,6 @@ bool rtems_shell_main_loop(
shell_env->exit_shell = false;
for (;;) {
int cmd;
/* Prompt section */
if (prompt) {
rtems_shell_get_prompt(shell_env, prompt,
@@ -885,8 +1002,10 @@ bool rtems_shell_main_loop(
if (cmd == -1)
continue; /* empty line */
if (cmd == -2)
if (cmd == -2) {
result = false;
break; /*EOF*/
}
line++;
@@ -924,7 +1043,11 @@ bool rtems_shell_main_loop(
memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE);
if (!rtems_shell_make_args(cmd_argv, &argc, argv,
RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {
shell_env->errorlevel = rtems_shell_execute_cmd(argv[0], argc, argv);
int exit_code = rtems_shell_execute_cmd(argv[0], argc, argv);
if (shell_env->exit_code != NULL)
*shell_env->exit_code = exit_code;
if (exit_code != 0 && shell_env->exit_on_error)
shell_env->exit_shell = true;
}
/* end exec cmd section */
@@ -935,6 +1058,7 @@ bool rtems_shell_main_loop(
fflush( stdout );
fflush( stderr );
}
shell_std_debug("end: %d %d\n", result, shell_env->forever);
} while (result && shell_env->forever);
}
@@ -946,6 +1070,9 @@ bool rtems_shell_main_loop(
if (prompt)
free (prompt);
shell_std_debug("child in-to-close: %p\n", stdinToClose);
shell_std_debug("child out-to-close: %p\n", stdoutToClose);
if (stdinToClose) {
fclose( stdinToClose );
} else {
@@ -959,6 +1086,7 @@ bool rtems_shell_main_loop(
}
if ( stdoutToClose )
fclose( stdoutToClose );
rtems_shell_clear_shell_env();
return result;
}
@@ -974,6 +1102,7 @@ static rtems_status_code rtems_shell_run (
const char *output,
bool output_append,
rtems_id wake_on_end,
int *exit_code,
bool echo,
rtems_shell_login_check_t login_check
)
@@ -983,6 +1112,8 @@ static rtems_status_code rtems_shell_run (
rtems_shell_env_t *shell_env;
rtems_name name;
rtems_shell_init_environment();
if ( task_name && strlen(task_name) >= 4)
name = rtems_build_name(
task_name[0], task_name[1], task_name[2], task_name[3]);
@@ -1008,25 +1139,41 @@ static rtems_status_code rtems_shell_run (
"allocating shell_env %s in shell_init()",task_name);
return RTEMS_NO_MEMORY;
}
shell_std_debug("run: env: %p\n", shell_env);
shell_env->devname = devname;
shell_env->taskname = task_name;
shell_env->exit_shell = false;
shell_env->forever = forever;
shell_env->echo = echo;
shell_env->input = strdup (input);
shell_env->output = strdup (output);
shell_env->input = input == NULL ? NULL : strdup (input);
shell_env->output = output == NULL ? NULL : strdup (output);
shell_env->output_append = output_append;
shell_env->parent_stdin = stdin;
shell_env->parent_stdout = stdout;
shell_env->parent_stderr = stderr;
shell_env->wake_on_end = wake_on_end;
shell_env->exit_code = exit_code;
shell_env->login_check = login_check;
shell_env->uid = getuid();
shell_env->gid = getgid();
getcwd(shell_env->cwd, sizeof(shell_env->cwd));
shell_std_debug("run out: %d (%p)\n",
fileno(shell_env->parent_stdout), shell_env->parent_stdout);
shell_std_debug("run in: %d (%p)\n",
fileno(shell_env->parent_stdin), shell_env->parent_stdin);
sc = rtems_task_start(task_id, rtems_shell_task,
(rtems_task_argument) shell_env);
(rtems_task_argument) shell_env);
if (sc != RTEMS_SUCCESSFUL) {
rtems_error(sc,"starting task %s in shell_init()",task_name);
free( (void*) shell_env->input );
free( (void*) shell_env->output );
free( shell_env );
return sc;
}
@@ -1035,7 +1182,9 @@ static rtems_status_code rtems_shell_run (
sc = rtems_event_receive (RTEMS_EVENT_1, RTEMS_WAIT, 0, &out);
}
return 0;
shell_std_debug("run: end: sc:%d ec:%d\n", sc, *exit_code);
return sc;
}
rtems_status_code rtems_shell_init(
@@ -1049,6 +1198,7 @@ rtems_status_code rtems_shell_init(
)
{
rtems_id to_wake = RTEMS_ID_NONE;
int exit_code = 0;
if ( wait )
to_wake = rtems_task_self();
@@ -1064,12 +1214,13 @@ rtems_status_code rtems_shell_init(
"stdout", /* output */
false, /* output_append */
to_wake, /* wake_on_end */
&exit_code, /* exit code of command */
false, /* echo */
login_check /* login check */
);
}
rtems_status_code rtems_shell_script (
rtems_status_code rtems_shell_script (
const char *task_name,
size_t task_stacksize,
rtems_task_priority task_priority,
@@ -1080,14 +1231,14 @@ rtems_status_code rtems_shell_script (
bool echo
)
{
rtems_id current_task = RTEMS_INVALID_ID;
rtems_id to_wake = RTEMS_ID_NONE;
int exit_code = 0;
rtems_status_code sc;
if (wait) {
sc = rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &current_task);
if (sc != RTEMS_SUCCESSFUL)
return sc;
}
shell_std_debug("script: in: %s out: %s\n", input, output);
if ( wait )
to_wake = rtems_task_self();
sc = rtems_shell_run(
task_name, /* task_name */
@@ -1099,12 +1250,19 @@ rtems_status_code rtems_shell_script (
input, /* input */
output, /* output */
output_append, /* output_append */
current_task, /* wake_on_end */
to_wake, /* wake_on_end */
&exit_code, /* exit_code */
echo, /* echo */
NULL /* login check */
);
if (sc != RTEMS_SUCCESSFUL)
return sc;
if (sc == RTEMS_SUCCESSFUL)
{
/* Place holder until RTEMS 5 is released then the interface for
* this call will change. */
}
shell_std_debug("script: end: %d\n", sc);
return sc;
}

View File

@@ -217,19 +217,24 @@ extern rtems_status_code rtems_shell_script(
/**
* Private environment associated with each shell instance.
*/
typedef struct {
typedef struct rtems_shell_env {
/** 'S','E','N','V': Shell Environment */
rtems_name magic;
bool managed;
const char *devname;
const char *taskname;
bool exit_shell; /* logout */
bool forever; /* repeat login */
int errorlevel;
int *exit_code;
bool exit_on_error;
bool echo;
char cwd[256];
const char *input;
const char *output;
bool output_append;
FILE *parent_stdin;
FILE *parent_stdout;
FILE *parent_stderr;
rtems_id wake_on_end;
rtems_shell_login_check_t login_check;

View File

@@ -2989,10 +2989,16 @@ static void gmt_time_string(char *buf, size_t buf_len, time_t *t) {
strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(t));
}
static void construct_etag(char *buf, size_t buf_len,
static void construct_etag(const struct mg_connection *conn, const char *path,
char *buf, size_t buf_len,
const struct file *filep) {
snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"",
(unsigned long) filep->modification_time, filep->size);
if (conn->ctx->callbacks.http_etag != NULL &&
conn->ctx->callbacks.http_etag(conn, path, buf, buf_len)) {
}
else {
snprintf(buf, buf_len, "\"%lx.%" INT64_FMT "\"",
(unsigned long) filep->modification_time, filep->size);
}
}
static void fclose_on_exec(struct file *filep) {
@@ -3061,7 +3067,7 @@ static void handle_file_request(struct mg_connection *conn, const char *path,
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
gmt_time_string(date, sizeof(date), &curtime);
gmt_time_string(lm, sizeof(lm), &filep->modification_time);
construct_etag(etag, sizeof(etag), filep);
construct_etag(conn, path, etag, sizeof(etag), filep);
(void) mg_printf(conn,
"HTTP/1.1 %d %s\r\n"
@@ -3221,11 +3227,12 @@ static int substitute_index_file(struct mg_connection *conn, char *path,
// Return True if we should reply 304 Not Modified.
static int is_not_modified(const struct mg_connection *conn,
const char *path,
const struct file *filep) {
char etag[64];
const char *ims = mg_get_header(conn, "If-Modified-Since");
const char *inm = mg_get_header(conn, "If-None-Match");
construct_etag(etag, sizeof(etag), filep);
construct_etag(conn, path, etag, sizeof(etag), filep);
return (inm != NULL && !mg_strcasecmp(etag, inm)) ||
(ims != NULL && filep->modification_time <= parse_date_string(ims));
}
@@ -4591,7 +4598,7 @@ static void handle_request(struct mg_connection *conn) {
strlen(conn->ctx->config[SSI_EXTENSIONS]),
path) > 0) {
handle_ssi_file_request(conn, path);
} else if (is_not_modified(conn, &file)) {
} else if (is_not_modified(conn, path, &file)) {
send_http_error(conn, 304, "Not Modified", "%s", "");
} else {
handle_file_request(conn, path, &file);

View File

@@ -124,6 +124,19 @@ struct mg_callbacks {
// Parameters:
// status: HTTP error status code.
int (*http_error)(struct mg_connection *, int status);
// Called when mongoose needs to generate an HTTP etag.
// Implementing this callback allows a custom etag to be generated. If
// not implemented the standard etag generator is used which is the
// modification time as a hex value and the file size.
// Use this callback if the modification time cannot be controlled.
// Parameters:
// path: path to the file being requested
// etag: buffer to write the etag into
// etag_len: the length of the etag buffer
// Return value:
int (*http_etag)(const struct mg_connection *,
const char *path, char *etag, size_t etag_len);
};
// Start web server.

View File

@@ -314,9 +314,8 @@ RTEMS_INLINE_ROUTINE void _Thread_Dispatch_enable( Per_CPU_Control *cpu_self )
} else {
cpu_self->thread_dispatch_disable_level = 0;
_Profiling_Thread_dispatch_enable( cpu_self, 0 );
_ISR_Enable_without_giant( level );
}
_ISR_Enable_without_giant( level );
} else {
cpu_self->thread_dispatch_disable_level = disable_level - 1;
}

View File

@@ -245,6 +245,10 @@ static void test(void)
int rv;
rtems_resource_snapshot snapshot;
rtems_test_assert(fileno(stdout) >= 0);
rtems_test_assert(fileno(stdin) >= 0);
rtems_test_assert(fileno(stderr) >= 0);
ctx->main_task_id = rtems_task_self();
rtems_resource_snapshot_take(&snapshot);
@@ -275,6 +279,10 @@ static void test(void)
sc = rtems_task_delete(ctx->worker_task_id);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
rtems_test_assert(fileno(stdout) >= 0);
rtems_test_assert(fileno(stdin) >= 0);
rtems_test_assert(fileno(stderr) >= 0);
rv = unlink(&file_path[0]);
rtems_test_assert(rv == 0);

View File

@@ -46,6 +46,122 @@ static void create_file(const char *name, const char *content)
rtems_test_assert(rv == 0);
}
static const char joel_in[] =
"#! joel\n"
"jtst hello world\n"
"jtst 1 2 3 4 5\n";
static const char joel_out_1[] =
" 3 'jtst hello world'\n"
" 6 'jtst 1 2 3 4 5'\n";
static const char joel_out_2[] =
"\n"
"RTEMS Shell on (null). Use 'help' to list commands.\n"
" 3 'jtst hello world'\n"
" 6 'jtst 1 2 3 4 5'\n";
static int joel_test_command(int argc, char** argv)
{
int i;
fprintf(stdout, "%2d '", argc);
for (i = 0; i < argc; ++i) {
fprintf(stdout, argv[i]);
if (i < (argc - 1))
fprintf(stdout, " ");
}
fprintf(stdout, "'\n");
return 0;
}
static void test_joel(void)
{
/*
* Running a joel script tests the shell main loop.
*/
char buf[sizeof(joel_out_2) + 1];
rtems_shell_cmd_t* cmd;
FILE *in;
FILE *out;
FILE *current_stdout = stdout;
FILE *current_stdin = stdin;
size_t len;
rtems_status_code sc;
/*
* Use a private command due to the way the testsuite maps printk onto printf.
*/
cmd = rtems_shell_add_cmd("jtst", "misc", "joel test", joel_test_command);
rtems_test_assert(cmd != NULL);
len = strlen(joel_in);
in = fopen("/jin", "w");
rtems_test_assert(in != NULL);
rtems_test_assert(fwrite(joel_in, sizeof(char), len, in) == len);
rtems_test_assert(fclose(in) == 0);
/*
* The shell opens the input and output files.
*/
sc = rtems_shell_script(
"JTST",
8 * 1024,
1,
"/jin",
"/jout",
false,
true,
false);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
out = fopen("/jout", "r");
rtems_test_assert(out != NULL);
rtems_test_assert(!feof(out));
memset(buf, 0, sizeof(buf));
len = fread(buf, sizeof(char), sizeof(buf), out);
rtems_test_assert(len > 0);
rtems_test_assert(strcmp(joel_out_1, buf) == 0);
rtems_test_assert(fclose(out) == 0);
/*
* The shell task inherits the parent stdin and stdout
*/
in = fopen("/jin", "r");
rtems_test_assert(in != NULL);
out = fopen("/jout", "w");
rtems_test_assert(out != NULL);
stdin = in;
stdout = out;
sc = rtems_shell_script(
"JTST",
8 * 1024,
1,
"stdin",
"stdout",
false,
true,
false);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
stdout = current_stdout;
stdin = current_stdin;
rtems_test_assert(fclose(in) == 0);
rtems_test_assert(fclose(out) == 0);
out = fopen("/jout", "r");
rtems_test_assert(out != NULL);
rtems_test_assert(!feof(out));
memset(buf, 0, sizeof(buf));
len = fread(buf, sizeof(char), sizeof(buf), out);
rtems_test_assert(len > 0);
rtems_test_assert(strcmp(joel_out_2, buf) == 0);
rtems_test_assert(fclose(out) == 0);
}
static void test(void)
{
rtems_user_env_t *uenv;
@@ -165,6 +281,7 @@ static void Init(rtems_task_argument arg)
TEST_BEGIN();
test();
test_joel();
TEST_END();
rtems_test_exit(0);
@@ -173,10 +290,10 @@ static void Init(rtems_task_argument arg)
#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 5
#define CONFIGURE_MAXIMUM_TASKS 1
#define CONFIGURE_MAXIMUM_POSIX_KEYS 1
#define CONFIGURE_MAXIMUM_TASKS 3
#define CONFIGURE_MAXIMUM_POSIX_KEYS 2
#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 2
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION

View File

@@ -104,7 +104,6 @@ sp32/Makefile
sp33/Makefile
sp34/Makefile
sp35/Makefile
sp36/Makefile
sp37/Makefile
sp38/Makefile
sp40/Makefile

View File

@@ -1,21 +0,0 @@
rtems_tests_PROGRAMS = sp36
sp36_SOURCES = strict_order_mut.c
dist_rtems_tests_DATA = sp36.scn
dist_rtems_tests_DATA += sp36.doc
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../automake/compile.am
include $(top_srcdir)/../automake/leaf.am
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
LINK_OBJS = $(sp36_OBJECTS)
LINK_LIBS = $(sp36_LDLIBS)
sp36$(EXEEXT): $(sp36_OBJECTS) $(sp36_DEPENDENCIES)
@rm -f sp36$(EXEEXT)
$(make-exe)
include $(top_srcdir)/../automake/local.am

View File

@@ -1,42 +0,0 @@
This is a simple test program to demonstrate strict order mutex.
1)What's strict order mutex ?
In rtems,when a task release a priority_inheritance or
priority ceiling semaphore,the kernel detect whether
this task holds priority_inheritance or priority
ceiling semaphore, if not, set the priority of task
back to real priority of task.
This method is right, but in theory, we would like
to reset the priority after releasing the mutex if
releasing it in LIFO order.Do it like this can decrease
the blocking time of a higher priority task .
2)How to enable "strict order mutex " ?
When configuring the rtems , add
ENABLE_STRICT_ORDER_MUTEX=1
to your configure parameter.
3)About this test program
T0,T1,S0,S1
T0,priority 4
T1,priority 1
S0,priority inheritance
S1,priority ceiling,priority ceiling 1
1,T0 obtain S0 then obtain S1, priority of T0 should be improved to 1
2,T0 try to release S0, but not in strict order, return error code
3,T0 release S1,the priority of T0 back to 4
4,T1 try to obtain S0
5,T1 should be blocked and the priority of T0 should be improved to 1
6,T0 release S0
7,T1 obtain S0
8,OVER.

View File

@@ -1,168 +0,0 @@
/*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#define CONFIGURE_INIT
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <bsp.h>
#include <stdio.h>
#include "tmacros.h"
#include <rtems/score/coremutex.h>
#define BACK_TYPE(_type_in_ptr,_type_out,_type_in_name) \
((_type_out *)((unsigned int)_type_in_ptr - \
(unsigned int)(&((_type_out *)0)->_type_in_name)))
/* configuration information */
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_EXTRA_TASK_STACKS (RTEMS_MINIMUM_STACK_SIZE * 3)
#define CONFIGURE_MAXIMUM_TASKS 10
#define CONFIGURE_MAXIMUM_SEMAPHORES 10
rtems_task Task0(rtems_task_argument ignored);
rtems_task Task1(rtems_task_argument ignored);
rtems_task Init(rtems_task_argument ignored);
rtems_task_priority Get_current_pri(void);
#include <rtems/confdefs.h>
rtems_id Task_id[4];
rtems_name Task_name[4];
rtems_id Mutex_id[4];
rtems_name Mutex_name[4];
rtems_task Init(rtems_task_argument ignored)
{
rtems_status_code status;
printf("\n----------------TEST 36 ------------\n");
Mutex_name[0] = rtems_build_name( 'S','0',' ',' ');
status = rtems_semaphore_create(
Mutex_name[0],
1,
RTEMS_LOCAL|
RTEMS_SIMPLE_BINARY_SEMAPHORE|
RTEMS_PRIORITY,
0,
&Mutex_id[0]
);
directive_failed( status, "rtems_semaphore_create of S0");
printf("Create S0, Inherit_priority\n");
Mutex_name[1] = rtems_build_name( 'S','1',' ',' ');
status = rtems_semaphore_create(
Mutex_name[1],
1,
RTEMS_LOCAL|
RTEMS_SIMPLE_BINARY_SEMAPHORE|
RTEMS_PRIORITY,
1,
&Mutex_id[1]
);
directive_failed( status, "rtems_semaphore_create of S1");
printf("Create S1, Priority_celling is 1\n");
Mutex_name[2] = rtems_build_name( 'S','Y','N','C');
Task_name[0] = rtems_build_name( 'T','0',' ',' ');
status = rtems_task_create(
Task_name[0],
4,
RTEMS_MINIMUM_STACK_SIZE *2,
RTEMS_DEFAULT_MODES,
RTEMS_DEFAULT_ATTRIBUTES,
&Task_id[0]
);
directive_failed( status,"rtems_task_create of T0");
printf("Create T0,priority is 4\n");
status = rtems_task_start( Task_id[0],Task0, 0);
directive_failed( status,"rtems_task_start of T0");
status = rtems_task_delete( RTEMS_SELF);
directive_failed( status,"rtems_task_delete of INIT");
}
rtems_task Task0(rtems_task_argument ignored)
{
rtems_status_code status;
status = rtems_semaphore_obtain( Mutex_id[0], RTEMS_WAIT, 0 );
printf("T0 rtems_semaphore_obtain - S0\n");
directive_failed( status,"rtems_semaphore_obtain of S0\n");
printf("The current priority of T0 is %d\n",Get_current_pri());
status = rtems_semaphore_obtain( Mutex_id[1], RTEMS_WAIT, 0 );
printf("T0 rtems_semaphore_obtain - S1\n");
directive_failed( status,"rtems_semaphore_obtain of S1");
printf("The current priority of T0 is %d\n",Get_current_pri());
#ifdef __RTEMS_STRICT_ORDER_MUTEX__
status = rtems_semaphore_release( Mutex_id[0] );
printf("T0 - rtems_semaphore_release - S0\n");
if(status == CORE_MUTEX_RELEASE_NOT_ORDER)
printf("T0 releasing S0 not in order\n");
#endif
status = rtems_semaphore_release(Mutex_id[1]);
printf("T0 - rtems_semaphore_release - S1\n");
directive_failed( status,"rtems_semaphore_release of S1\n");
printf("The current priority of T0 is %d\n",Get_current_pri());
Task_name[1] = rtems_build_name( 'T','1',' ',' ');
status = rtems_task_create(
Task_name[1],
1,
RTEMS_MINIMUM_STACK_SIZE *2,
RTEMS_DEFAULT_MODES,
RTEMS_DEFAULT_ATTRIBUTES,
&Task_id[1]
);
directive_failed( status , "rtems_task_create of T1\n");
printf("Create S1,priority is 1\n");
status = rtems_task_start( Task_id[1],Task1, 0);
directive_failed( status, "rtems_task_start of T1\n");
printf("The current priority of T0 is %d\n",Get_current_pri());
status = rtems_semaphore_release(Mutex_id[0]);
printf("T0 - rtems_semaphore_release - S0\n");
directive_failed( status, "rtems_semaphore_release of S0\n");
}
rtems_task Task1(rtems_task_argument ignored)
{
rtems_status_code status;
status = rtems_semaphore_obtain( Mutex_id[0], RTEMS_WAIT, 0 );
printf("T1 - rtems_semaphore_obtain - S0");
directive_failed( status," rtems_semaphore_obtain S0");
}
rtems_task_priority Get_current_pri(void)
{
rtems_status_code status;
rtems_task_priority pri;
status = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &pri);
directive_failed( status, " rtems_task_set_priority ");
return pri;
}