Compare commits

...

10 Commits

Author SHA1 Message Date
Jan Sommer
61ccb9c05d bsp/xilinx-zynq: Flush TX-Buffer before initializing uart
Closes #4055
Closes #4056
2020-08-22 17:30:12 +10:00
Sebastian Huber
7661402bc2 confdefs: Fix cyclic dependency
Close #4060.
2020-08-21 20:02:35 +02:00
Chris Johns
5284e812e2 powerpc/io: The eieio() function clashes with FreeBSD. Change.
Closes #4021
2020-08-12 13:02:14 +10:00
Kinsey Moore
e95c00a79e posix: Only check shm_unlink obj_err if necessary
In the nominal case checked by spsysinit01, obj_err is unmodified if
_POSIX_Shm_Get_by_name returns non-NULL. In the case of shm_unlink, this means
an uninitialized value is passed into the switch and it appears tests using it
were passing by virtue of the stack having the right value on it in most cases.
This now checks obj_err only if _POSIX_Shm_Get_by_name returns NULL.

Close #4016
2020-08-11 07:48:19 -05:00
Chris Johns
95036a4591 shell: Only clear std handles when the shell task exits
Clearing the std file handles when the main loop exited crashes
telnetd as it reuses its session threads.

Closes #3859
2020-08-08 18:07:32 +10:00
Sebastian Huber
534f9dbe13 arm/atsam: Make interrupt server configurable
The external UART over SPI device SC16IS752 uses the interrupt server
for interrupt processing. The interrupt server is also heavily used by
libbsd. The interrupt processing for the SC16IS752 is time critical and
doesn't work if network traffic is processed at the same priority.
With #4033 custom interrupt servers are available. Change
atsam_sc16is752_spi_create() to support user-defined interrupt servers.
Introduced atsam_sc16is752_spi_config to cut down the argument count of
this function.

Close #4038.
2020-08-05 06:59:10 +02:00
Christian Mauderer
4a2ac5ef8d dosfs: Fix memory leak on failed mounts.
Currently if mount fails, a converter isn't destroyed. We have to take
care of two cases:

1. The user doesn't provide a converter.

In this case mounting a dosfs creates a default converter. This patch
makes sure that the converter is destroyed again if mount failes for
this case.

2. The user provides a converter.

In this case it's not sure that the dosfs specific routines are reached
because mount can fail before that. Therefore the user has to destroy
the converter himself again. This patch adds a documentation for that
and implements it in the media server.

Closes #4041.
2020-08-04 08:26:58 +02:00
Sebastian Huber
5eb0773159 rtems: Add rtems_interrupt_server_create()
Add rtems_interrupt_server_destroy().

Before this patch, the only way to create interrupt servers was
rtems_interrupt_server_initialize(). This function creates the default
interrupt server and in SMP configurations additional interrupt servers
for the additional processors. The interrupt server is heavily used by
libbsd. This includes the epoch based reclamation which performs time
consuming resource and memory deallocation work. This does not work well
with time critical services, for example an UART over SPI or I2C. One
approach to address this problem is to allow the application to create
custom interrupt servers with the right priority and task properties.
The interrupt server API accounted for this, however, it was not
implemented before this patch.

Close #4033.
2020-08-03 08:43:45 +02:00
Jan Sommer
849d741832 i386: Fix possible race condition on first context restore
Make sure that the esp is restored before the eflags register.

When the init task is initially restored, system interrupts are activated when the
eflags register is loaded.
If the esp register still points to an address in the interrupt stack
area (from early system initlization) the ISR might overwrite its own
stack.

Closes #4030
2020-07-29 11:39:35 +02:00
Jan Sommer
a1f9265c03 bsps/pc386: Fix IPI for non-consecutive APICIDs
- properly use the cpu <-> apic maps for IPIs

Closes #4028.
2020-07-16 08:08:09 -05:00
15 changed files with 538 additions and 220 deletions

View File

@@ -24,44 +24,85 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
/**
* @brief The SC16IS752 device context.
*
* All members are private to the device driver.
*/
typedef struct { typedef struct {
sc16is752_spi_context base; sc16is752_spi_context base;
Pin irq_pin; Pin irq_pin;
rtems_interrupt_server_entry irqs_entry; /* Internal. Don't touch. */ rtems_interrupt_server_entry irqs_entry;
rtems_interrupt_server_action irqs_action; /* Internal. Don't touch. */ rtems_interrupt_server_action irqs_action;
uint32_t irqs_index;
} atsam_sc16is752_spi_context; } atsam_sc16is752_spi_context;
/**
* @brief The SC16IS752 device configuration.
*
* @see atsam_sc16is752_spi_create().
*/
typedef struct {
/**
* @brief The device file path for the new device.
*/
const char *device_path;
/**
* @brief The SC16IS752 mode.
*/
sc16is752_mode mode;
/**
* @brief The input frequency in Hertz of the SC16IS752 chip. See XTAL1 and
* XTAL2 pins.
*/
uint32_t input_frequency;
/**
* @brief The SPI bus device path.
*/
const char *spi_path;
/**
* @brief The SPI chip select (starts with 0, the SPI driver uses
* SPI_ChipSelect(1 << spi_chip_select)).
*/
uint8_t spi_chip_select;
/**
* @brief The SPI bus speed in Hertz.
*/
uint32_t spi_speed_hz;
/**
* @brief The interrupt pin, e.g. { PIO_PD28, PIOD, ID_PIOD, PIO_INPUT,
* PIO_IT_LOW_LEVEL }.
*/
const Pin irq_pin;
/**
* @brief The index to identify the interrupt server used for interrupt
* processing.
*/
uint32_t server_index;
} atsam_sc16is752_spi_config;
/** /**
* @brief Creates an SPI connected SC16IS752 device. * @brief Creates an SPI connected SC16IS752 device.
* *
* This devices uses the interrupt server, see * This devices uses the interrupt server, see rtems_interrupt_server_create().
* rtems_interrupt_server_initialize().
* *
* The device claims the interrupt of the PIO block. * The device claims the interrupt of the PIO block.
* *
* @param[in] ctx The device context. May have an arbitrary content. * @param[out] ctx is the device context. It may have an arbitrary content.
* @param[in] device_path The device file path for the new device. * @param config is the device configuration.
* @param[in] mode The SC16IS752 mode.
* @param[in] input_frequency The input frequency in Hertz of the SC16IS752
* chip. See XTAL1 and XTAL2 pins.
* @param[in] spi_path The SPI bus device path.
* @param[in] spi_chip_select The SPI chip select (starts with 0, the SPI
* driver uses SPI_ChipSelect(1 << spi_chip_select)).
* @param[in] spi_speed_hz The SPI bus speed in Hertz.
* @param[in] irq_pin The interrupt pin, e.g. { PIO_PD28, PIOD, ID_PIOD,
* PIO_INPUT, PIO_IT_LOW_LEVEL }.
* *
* @return See sc16is752_spi_create(). * @return See sc16is752_spi_create().
*/ */
int atsam_sc16is752_spi_create( int atsam_sc16is752_spi_create(
atsam_sc16is752_spi_context *ctx, atsam_sc16is752_spi_context *ctx,
const char *device_path, const atsam_sc16is752_spi_config *config
sc16is752_mode mode,
uint32_t input_frequency,
const char *spi_path,
uint8_t spi_chip_select,
uint32_t spi_speed_hz,
const Pin *irq_pin
); );
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -41,7 +41,7 @@ static bool atsam_sc16is752_install_interrupt(sc16is752_context *base)
rtems_status_code sc; rtems_status_code sc;
uint8_t rv; uint8_t rv;
sc = rtems_interrupt_server_entry_initialize(RTEMS_INTERRUPT_SERVER_DEFAULT, sc = rtems_interrupt_server_entry_initialize(ctx->irqs_index,
&ctx->irqs_entry); &ctx->irqs_entry);
rtems_interrupt_server_action_prepend(&ctx->irqs_entry, rtems_interrupt_server_action_prepend(&ctx->irqs_entry,
&ctx->irqs_action, atsam_sc16i752_irqs_handler, ctx); &ctx->irqs_action, atsam_sc16i752_irqs_handler, ctx);
@@ -64,24 +64,19 @@ static void atsam_sc16is752_remove_interrupt(sc16is752_context *base)
} }
int atsam_sc16is752_spi_create( int atsam_sc16is752_spi_create(
atsam_sc16is752_spi_context *ctx, atsam_sc16is752_spi_context *ctx,
const char *device_path, const atsam_sc16is752_spi_config *config
sc16is752_mode mode,
uint32_t input_frequency,
const char *spi_path,
uint8_t spi_chip_select,
uint32_t spi_speed_hz,
const Pin *irq_pin
) )
{ {
ctx->base.base.mode = mode; ctx->base.base.mode = config->mode;
ctx->base.base.input_frequency = input_frequency; ctx->base.base.input_frequency = config->input_frequency;
ctx->base.base.install_irq = atsam_sc16is752_install_interrupt; ctx->base.base.install_irq = atsam_sc16is752_install_interrupt;
ctx->base.base.remove_irq = atsam_sc16is752_remove_interrupt; ctx->base.base.remove_irq = atsam_sc16is752_remove_interrupt;
ctx->base.spi_path = spi_path; ctx->base.spi_path = config->spi_path;
ctx->base.cs = spi_chip_select; ctx->base.cs = config->spi_chip_select;
ctx->base.speed_hz = spi_speed_hz; ctx->base.speed_hz = config->spi_speed_hz;
ctx->irq_pin = *irq_pin; ctx->irq_pin = config->irq_pin;
ctx->irqs_index = config->server_index;
return sc16is752_spi_create(&ctx->base, device_path); return sc16is752_spi_create(&ctx->base, config->device_path);
} }

View File

@@ -122,6 +122,8 @@ void zynq_uart_initialize(rtems_termios_device_context *base)
uint32_t brgr = 0x3e; uint32_t brgr = 0x3e;
uint32_t bauddiv = 0x6; uint32_t bauddiv = 0x6;
zynq_uart_reset_tx_flush(ctx);
zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode); zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode);
regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN); regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);

View File

@@ -226,9 +226,11 @@ get_checksum(unsigned start, int length)
int int
send_ipi(unsigned int dst, unsigned int v) send_ipi(unsigned int dst, unsigned int v)
{ {
int to, send_status; int to, send_status, apicid;
IMPS_LAPIC_WRITE(LAPIC_ICR+0x10, (dst << 24)); apicid = imps_cpu_apic_map[dst];
IMPS_LAPIC_WRITE(LAPIC_ICR+0x10, (apicid << 24));
IMPS_LAPIC_WRITE(LAPIC_ICR, v); IMPS_LAPIC_WRITE(LAPIC_ICR, v);
/* Wait for send to finish */ /* Wait for send to finish */
@@ -251,9 +253,11 @@ static int
boot_cpu(imps_processor *proc) boot_cpu(imps_processor *proc)
{ {
int apicid = proc->apic_id, success = 1; int apicid = proc->apic_id, success = 1;
int cpuid;
unsigned bootaddr; unsigned bootaddr;
unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR); unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR);
cpuid = imps_apic_cpu_map[apicid];
/* /*
* Copy boot code for secondary CPUs here. Find it in between * Copy boot code for secondary CPUs here. Find it in between
* "patch_code_start" and "patch_code_end" symbols. The other CPUs * "patch_code_start" and "patch_code_end" symbols. The other CPUs
@@ -276,7 +280,7 @@ boot_cpu(imps_processor *proc)
/* Pass start function, stack region and gdtdescr to AP /* Pass start function, stack region and gdtdescr to AP
* see startAP.S for location */ * see startAP.S for location */
reset[1] = (uint32_t)secondary_cpu_initialize; reset[1] = (uint32_t)secondary_cpu_initialize;
reset[2] = (uint32_t)_Per_CPU_Get_by_index(apicid)->interrupt_stack_high; reset[2] = (uint32_t)_Per_CPU_Get_by_index(cpuid)->interrupt_stack_high;
memcpy( memcpy(
(char*) &reset[3], (char*) &reset[3],
&gdtdesc, &gdtdesc,
@@ -295,13 +299,13 @@ boot_cpu(imps_processor *proc)
/* assert INIT IPI */ /* assert INIT IPI */
send_ipi( send_ipi(
apicid, cpuid,
LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT
); );
UDELAY(10000); UDELAY(10000);
/* de-assert INIT IPI */ /* de-assert INIT IPI */
send_ipi(apicid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_DM_INIT); send_ipi(cpuid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_DM_INIT);
UDELAY(10000); UDELAY(10000);
@@ -312,7 +316,7 @@ boot_cpu(imps_processor *proc)
if (proc->apic_ver >= APIC_VER_NEW) { if (proc->apic_ver >= APIC_VER_NEW) {
int i; int i;
for (i = 1; i <= 2; i++) { for (i = 1; i <= 2; i++) {
send_ipi(apicid, LAPIC_ICR_DM_SIPI | ((bootaddr >> 12) & 0xFF)); send_ipi(cpuid, LAPIC_ICR_DM_SIPI | ((bootaddr >> 12) & 0xFF));
UDELAY(1000); UDELAY(1000);
} }
} }

View File

@@ -50,7 +50,7 @@
* Acts as a barrier to ensure all previous I/O accesses have * Acts as a barrier to ensure all previous I/O accesses have
* completed before any further ones are issued. * completed before any further ones are issued.
*/ */
static inline void eieio(void) static inline void io_eieio(void)
{ {
__asm__ __volatile__ ("eieio"); __asm__ __volatile__ ("eieio");
} }
@@ -59,9 +59,9 @@ static inline void eieio(void)
/* Enforce in-order execution of data I/O. /* Enforce in-order execution of data I/O.
* No distinction between read/write on PPC; use eieio for all three. * No distinction between read/write on PPC; use eieio for all three.
*/ */
#define iobarrier_rw() eieio() #define iobarrier_rw() io_eieio()
#define iobarrier_r() eieio() #define iobarrier_r() io_eieio()
#define iobarrier_w() eieio() #define iobarrier_w() io_eieio()
/* /*
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier. * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.

View File

@@ -7,13 +7,7 @@
*/ */
/* /*
* Copyright (c) 2009, 2019 embedded brains GmbH. All rights reserved. * Copyright (C) 2009, 2020 embedded brains GmbH (http://www.embedded-brains.de)
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
@@ -21,6 +15,7 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <rtems.h> #include <rtems.h>
#include <rtems/chain.h> #include <rtems/chain.h>
@@ -30,54 +25,43 @@
#define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1) #define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1)
typedef struct { static rtems_interrupt_server_control bsp_interrupt_server_default;
RTEMS_INTERRUPT_LOCK_MEMBER(lock);
rtems_chain_control entries;
rtems_id server;
unsigned errors;
} bsp_interrupt_server_context;
#if defined(RTEMS_SMP) static rtems_chain_control bsp_interrupt_server_chain =
static bsp_interrupt_server_context *bsp_interrupt_server_instances; RTEMS_CHAIN_INITIALIZER_EMPTY(bsp_interrupt_server_chain);
#else
static bsp_interrupt_server_context bsp_interrupt_server_instance;
#endif
static bsp_interrupt_server_context *bsp_interrupt_server_get_context( static rtems_interrupt_server_control *bsp_interrupt_server_get_context(
uint32_t server_index, uint32_t server_index,
rtems_status_code *sc rtems_status_code *sc
) )
{ {
#if defined(RTEMS_SMP) rtems_chain_node *node;
if (bsp_interrupt_server_instances == NULL) {
*sc = RTEMS_INCORRECT_STATE;
return NULL;
}
#else
if (bsp_interrupt_server_instance.server == RTEMS_ID_NONE) {
*sc = RTEMS_INCORRECT_STATE;
return NULL;
}
#endif
if (server_index >= rtems_scheduler_get_processor_maximum()) { bsp_interrupt_lock();
*sc = RTEMS_INVALID_ID; node = rtems_chain_first(&bsp_interrupt_server_chain);
return NULL;
while (node != rtems_chain_tail(&bsp_interrupt_server_chain)) {
rtems_interrupt_server_control *s;
s = RTEMS_CONTAINER_OF(node, rtems_interrupt_server_control, node);
if (s->index == server_index) {
bsp_interrupt_unlock();
return s;
}
node = rtems_chain_next(node);
} }
*sc = RTEMS_SUCCESSFUL; bsp_interrupt_unlock();
#if defined(RTEMS_SMP) *sc = RTEMS_INVALID_ID;
return &bsp_interrupt_server_instances[server_index]; return NULL;
#else
return &bsp_interrupt_server_instance;
#endif
} }
static void bsp_interrupt_server_trigger(void *arg) static void bsp_interrupt_server_trigger(void *arg)
{ {
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
rtems_interrupt_server_entry *e = arg; rtems_interrupt_server_entry *e = arg;
bsp_interrupt_server_context *s = e->server; rtems_interrupt_server_control *s = e->server;
if (bsp_interrupt_is_valid_vector(e->vector)) { if (bsp_interrupt_is_valid_vector(e->vector)) {
bsp_interrupt_vector_disable(e->vector); bsp_interrupt_vector_disable(e->vector);
@@ -137,7 +121,7 @@ static rtems_interrupt_server_entry *bsp_interrupt_server_query_entry(
} }
typedef struct { typedef struct {
bsp_interrupt_server_context *server; rtems_interrupt_server_control *server;
rtems_vector_number vector; rtems_vector_number vector;
rtems_option options; rtems_option options;
rtems_interrupt_handler handler; rtems_interrupt_handler handler;
@@ -281,7 +265,7 @@ static void bsp_interrupt_server_remove_helper(void *arg)
} }
static rtems_status_code bsp_interrupt_server_call_helper( static rtems_status_code bsp_interrupt_server_call_helper(
bsp_interrupt_server_context *s, rtems_interrupt_server_control *s,
rtems_vector_number vector, rtems_vector_number vector,
rtems_option options, rtems_option options,
rtems_interrupt_handler handler, rtems_interrupt_handler handler,
@@ -314,7 +298,7 @@ static rtems_status_code bsp_interrupt_server_call_helper(
} }
static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry( static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
bsp_interrupt_server_context *s rtems_interrupt_server_control *s
) )
{ {
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
@@ -337,7 +321,7 @@ static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
static void bsp_interrupt_server_task(rtems_task_argument arg) static void bsp_interrupt_server_task(rtems_task_argument arg)
{ {
bsp_interrupt_server_context *s = (bsp_interrupt_server_context *) arg; rtems_interrupt_server_control *s = (rtems_interrupt_server_control *) arg;
while (true) { while (true) {
rtems_event_set events; rtems_event_set events;
@@ -377,7 +361,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
) )
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -402,7 +386,7 @@ rtems_status_code rtems_interrupt_server_handler_remove(
) )
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -464,7 +448,7 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_handler_iterate_helper_data hihd; bsp_interrupt_server_handler_iterate_helper_data hihd;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -487,6 +471,86 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
); );
} }
/*
* The default server is statically allocated. Just clear the structure so
* that it can be re-initialized.
*/
static void bsp_interrupt_server_destroy_default(
rtems_interrupt_server_control *s
)
{
memset(s, 0, sizeof(*s));
}
#if defined(RTEMS_SMP)
static void bsp_interrupt_server_destroy_secondary(
rtems_interrupt_server_control *s
)
{
free(s);
}
#endif
static rtems_status_code bsp_interrupt_server_create(
rtems_interrupt_server_control *s,
rtems_task_priority priority,
size_t stack_size,
rtems_mode modes,
rtems_attribute attributes,
uint32_t cpu_index
)
{
rtems_status_code sc;
#if defined(RTEMS_SMP)
rtems_id scheduler;
cpu_set_t cpu;
#endif
rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
rtems_chain_initialize_empty(&s->entries);
sc = rtems_task_create(
rtems_build_name('I', 'R', 'Q', 'S'),
priority,
stack_size,
modes,
attributes,
&s->server
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
#if defined(RTEMS_SMP)
sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler);
if (sc != RTEMS_SUCCESSFUL) {
/* Do not start an interrupt server on a processor without a scheduler */
return RTEMS_SUCCESSFUL;
}
sc = rtems_task_set_scheduler(s->server, scheduler, priority);
_Assert(sc == RTEMS_SUCCESSFUL);
/* Set the task to processor affinity on a best-effort basis */
CPU_ZERO(&cpu);
CPU_SET(cpu_index, &cpu);
(void) rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
#else
(void) cpu_index;
#endif
rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
sc = rtems_task_start(
s->server,
bsp_interrupt_server_task,
(rtems_task_argument) s
);
_Assert(sc == RTEMS_SUCCESSFUL);
return sc;
}
rtems_status_code rtems_interrupt_server_initialize( rtems_status_code rtems_interrupt_server_initialize(
rtems_task_priority priority, rtems_task_priority priority,
size_t stack_size, size_t stack_size,
@@ -495,95 +559,164 @@ rtems_status_code rtems_interrupt_server_initialize(
uint32_t *server_count uint32_t *server_count
) )
{ {
rtems_status_code sc;
rtems_interrupt_server_control *s;
uint32_t cpu_index; uint32_t cpu_index;
#if defined(RTEMS_SMP)
uint32_t cpu_count; uint32_t cpu_count;
uint32_t dummy; #endif
bsp_interrupt_server_context *instances;
if (server_count == NULL) { cpu_index = 0;
server_count = &dummy; s = &bsp_interrupt_server_default;
bsp_interrupt_lock();
if (s->server != 0) {
sc = RTEMS_INCORRECT_STATE;
goto done;
} }
s->destroy = bsp_interrupt_server_destroy_default;
sc = bsp_interrupt_server_create(
s,
priority,
stack_size,
modes,
attributes,
cpu_index
);
if (sc != RTEMS_SUCCESSFUL) {
goto done;
}
cpu_index = 1;
#if defined(RTEMS_SMP)
cpu_count = rtems_scheduler_get_processor_maximum(); cpu_count = rtems_scheduler_get_processor_maximum();
#if defined(RTEMS_SMP) while (cpu_index < cpu_count) {
instances = calloc(cpu_count, sizeof(*instances)); s = calloc(1, sizeof(*s));
if (instances == NULL) {
return RTEMS_NO_MEMORY;
}
#else
instances = &bsp_interrupt_server_instance;
#endif
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { if (s == NULL) {
bsp_interrupt_server_context *s = &instances[cpu_index]; sc = RTEMS_NO_MEMORY;
rtems_status_code sc; goto done;
#if defined(RTEMS_SMP) }
rtems_id scheduler;
cpu_set_t cpu;
#endif
rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server"); s->destroy = bsp_interrupt_server_destroy_secondary;
rtems_chain_initialize_empty(&s->entries); s->index = cpu_index;
sc = bsp_interrupt_server_create(
sc = rtems_task_create( s,
rtems_build_name('I', 'R', 'Q', 'S'),
priority, priority,
stack_size, stack_size,
modes, modes,
attributes, attributes,
&s->server cpu_index
); );
if (sc != RTEMS_SUCCESSFUL) { if (sc != RTEMS_SUCCESSFUL) {
*server_count = cpu_index; goto done;
#if defined(RTEMS_SMP)
if (cpu_index > 0) {
bsp_interrupt_server_instances = instances;
return RTEMS_SUCCESSFUL;
}
free(instances);
#endif
return RTEMS_TOO_MANY;
} }
#if defined(RTEMS_SMP) ++cpu_index;
sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler); }
if (sc != RTEMS_SUCCESSFUL) {
/* Do not start an interrupt server on a processor without a scheduler */
continue;
}
sc = rtems_task_set_scheduler(s->server, scheduler, priority);
_Assert(sc == RTEMS_SUCCESSFUL);
/* Set the task to processor affinity on a best-effort basis */
CPU_ZERO(&cpu);
CPU_SET(cpu_index, &cpu);
(void) rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
#endif #endif
sc = rtems_task_start( done:
s->server, bsp_interrupt_unlock();
bsp_interrupt_server_task,
(rtems_task_argument) s if (server_count != NULL) {
); *server_count = cpu_index;
_Assert(sc == RTEMS_SUCCESSFUL);
} }
#if defined(RTEMS_SMP) return sc;
bsp_interrupt_server_instances = instances; }
#endif
*server_count = cpu_index;
rtems_status_code rtems_interrupt_server_create(
rtems_interrupt_server_control *s,
const rtems_interrupt_server_config *config,
uint32_t *server_index
)
{
rtems_status_code sc;
sc = rtems_task_create(
config->name,
config->priority,
config->storage_size,
config->modes,
config->attributes,
&s->server
);
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
rtems_chain_initialize_empty(&s->entries);
s->destroy = config->destroy;
s->index = rtems_object_id_get_index(s->server)
+ rtems_scheduler_get_processor_maximum();
*server_index = s->index;
bsp_interrupt_lock();
rtems_chain_initialize_node(&s->node);
rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
bsp_interrupt_unlock();
sc = rtems_task_start(
s->server,
bsp_interrupt_server_task,
(rtems_task_argument) s
);
_Assert(sc == RTEMS_SUCCESSFUL);
return sc;
}
static void bsp_interrupt_server_destroy_helper(void *arg)
{
bsp_interrupt_server_helper_data *hd = arg;
rtems_interrupt_server_control *s = hd->server;
rtems_status_code sc;
bsp_interrupt_lock();
rtems_chain_extract_unprotected(&s->node);
bsp_interrupt_unlock();
if (s->destroy != NULL) {
(*s->destroy)(s);
}
sc = rtems_event_transient_send(hd->task);
_Assert(sc == RTEMS_SUCCESSFUL);
(void) sc;
rtems_task_exit();
}
rtems_status_code rtems_interrupt_server_delete(uint32_t server_index)
{
rtems_status_code sc;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) {
return sc;
}
bsp_interrupt_server_call_helper(
s,
BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
0,
NULL,
NULL,
bsp_interrupt_server_destroy_helper
);
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
} }
static void bsp_interrupt_server_entry_initialize( static void bsp_interrupt_server_entry_initialize(
rtems_interrupt_server_entry *entry, rtems_interrupt_server_entry *entry,
bsp_interrupt_server_context *s rtems_interrupt_server_control *s
) )
{ {
rtems_chain_set_off_chain(&entry->node); rtems_chain_set_off_chain(&entry->node);
@@ -611,7 +744,7 @@ rtems_status_code rtems_interrupt_server_entry_initialize(
) )
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -645,7 +778,7 @@ rtems_status_code rtems_interrupt_server_entry_move(
) )
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(destination_server_index, &sc); s = bsp_interrupt_server_get_context(destination_server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -667,7 +800,7 @@ void rtems_interrupt_server_entry_destroy(
rtems_interrupt_server_entry *entry rtems_interrupt_server_entry *entry
) )
{ {
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
s = entry->server; s = entry->server;
@@ -698,7 +831,7 @@ rtems_status_code rtems_interrupt_server_request_initialize(
) )
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -727,8 +860,8 @@ static void bsp_interrupt_server_handler_move_helper(void *arg)
e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options); e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
if (e != NULL) { if (e != NULL) {
rtems_interrupt_lock_context lock_context; rtems_interrupt_lock_context lock_context;
bsp_interrupt_server_context *src = e->server; rtems_interrupt_server_control *src = e->server;
bsp_interrupt_server_context *dst = hihd->arg; rtems_interrupt_server_control *dst = hihd->arg;
bool pending; bool pending;
/* The source server is only used in SMP configurations for the lock */ /* The source server is only used in SMP configurations for the lock */
@@ -763,8 +896,8 @@ rtems_status_code rtems_interrupt_server_move(
) )
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *src; rtems_interrupt_server_control *src;
bsp_interrupt_server_context *dst; rtems_interrupt_server_control *dst;
bsp_interrupt_server_handler_iterate_helper_data hihd; bsp_interrupt_server_handler_iterate_helper_data hihd;
src = bsp_interrupt_server_get_context(source_server_index, &sc); src = bsp_interrupt_server_get_context(source_server_index, &sc);
@@ -810,7 +943,7 @@ static void bsp_interrupt_server_entry_suspend_helper(void *arg)
rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index) rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -831,7 +964,7 @@ rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
rtems_status_code rtems_interrupt_server_resume(uint32_t server_index) rtems_status_code rtems_interrupt_server_resume(uint32_t server_index)
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) { if (s == NULL) {
@@ -858,7 +991,7 @@ rtems_status_code rtems_interrupt_server_set_affinity(
) )
{ {
rtems_status_code sc; rtems_status_code sc;
bsp_interrupt_server_context *s; rtems_interrupt_server_control *s;
rtems_id scheduler; rtems_id scheduler;
s = bsp_interrupt_server_get_context(server_index, &sc); s = bsp_interrupt_server_get_context(server_index, &sc);

View File

@@ -6,9 +6,6 @@
* @ingroup RTEMSApplicationConfiguration * @ingroup RTEMSApplicationConfiguration
* *
* @brief Evaluate MPCI Configuration Options * @brief Evaluate MPCI Configuration Options
*
* This header file defines _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT for use by
* other configuration header files.
*/ */
/* /*
@@ -49,6 +46,8 @@
#ifdef CONFIGURE_MP_APPLICATION #ifdef CONFIGURE_MP_APPLICATION
#include <rtems/confdefs/threads.h>
#ifndef CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK #ifndef CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK
#define CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK 0 #define CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK 0
#endif #endif
@@ -83,8 +82,6 @@
#error "CONFIGURE_MP_NODE_NUMBER must be less than or equal to CONFIGURE_MP_MAXIMUM_NODES" #error "CONFIGURE_MP_NODE_NUMBER must be less than or equal to CONFIGURE_MP_MAXIMUM_NODES"
#endif #endif
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -126,10 +123,6 @@ RTEMS_SECTION( ".rtemsstack.mpci" );
} }
#endif #endif
#else /* CONFIGURE_MP_APPLICATION */
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
#endif /* CONFIGURE_MP_APPLICATION */ #endif /* CONFIGURE_MP_APPLICATION */
#else /* RTEMS_MULTIPROCESSING */ #else /* RTEMS_MULTIPROCESSING */
@@ -138,8 +131,6 @@ RTEMS_SECTION( ".rtemsstack.mpci" );
#error "CONFIGURE_MP_APPLICATION must not be defined if multiprocessing is disabled" #error "CONFIGURE_MP_APPLICATION must not be defined if multiprocessing is disabled"
#endif #endif
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
#endif /* RTEMS_MULTIPROCESSING */ #endif /* RTEMS_MULTIPROCESSING */
#endif /* CONFIGURE_INIT */ #endif /* CONFIGURE_INIT */

View File

@@ -44,7 +44,6 @@
#include <rtems/confdefs/bdbuf.h> #include <rtems/confdefs/bdbuf.h>
#include <rtems/confdefs/extensions.h> #include <rtems/confdefs/extensions.h>
#include <rtems/confdefs/mpci.h>
#include <rtems/confdefs/percpu.h> #include <rtems/confdefs/percpu.h>
#include <rtems/confdefs/scheduler.h> #include <rtems/confdefs/scheduler.h>
#include <rtems/confdefs/unlimited.h> #include <rtems/confdefs/unlimited.h>
@@ -197,6 +196,12 @@ const size_t _Thread_Initial_thread_count =
rtems_resource_maximum_per_allocation( _CONFIGURE_TASKS ) + rtems_resource_maximum_per_allocation( _CONFIGURE_TASKS ) +
rtems_resource_maximum_per_allocation( CONFIGURE_MAXIMUM_POSIX_THREADS ); rtems_resource_maximum_per_allocation( CONFIGURE_MAXIMUM_POSIX_THREADS );
#if defined(RTEMS_MULTIPROCESSING) && defined(CONFIGURE_MP_APPLICATION)
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 1
#else
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
#endif
THREAD_INFORMATION_DEFINE( THREAD_INFORMATION_DEFINE(
_Thread, _Thread,
OBJECTS_INTERNAL_API, OBJECTS_INTERNAL_API,

View File

@@ -214,6 +214,9 @@ typedef struct {
/** /**
* @brief Converter implementation for new file system instance. * @brief Converter implementation for new file system instance.
* *
* Note: If you pass a converter to mount, you have to destroy it yourself if
* mount failed. In a good case it is destroyed at unmount.
*
* Before converters have been added to the RTEMS implementation of the FAT * Before converters have been added to the RTEMS implementation of the FAT
* file system, the implementation was: * file system, the implementation was:
* - Short names were saved in code page format (as is still the case). * - Short names were saved in code page format (as is still the case).
@@ -270,6 +273,10 @@ typedef struct {
* RTEMS_FILESYSTEM_READ_WRITE, * RTEMS_FILESYSTEM_READ_WRITE,
* &mount_opts * &mount_opts
* ); * );
*
* if (rv != 0) {
* (*mount_opts.converter->handler->destroy)(mount_opts.converter);
* }
* } else { * } else {
* rv = -1; * rv = -1;
* errno = ENOMEM; * errno = ENOMEM;

View File

@@ -9,13 +9,7 @@
/* /*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette. * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
* *
* Copyright (C) 2008, 2019 embedded brains GmbH * Copyright (C) 2008, 2020 embedded brains GmbH (http://www.embedded-brains.de)
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
* *
* The license and distribution terms for this file may be * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
@@ -259,6 +253,76 @@ typedef struct rtems_interrupt_server_action {
*/ */
#define RTEMS_INTERRUPT_SERVER_DEFAULT 0 #define RTEMS_INTERRUPT_SERVER_DEFAULT 0
/**
* @brief An interrupt server control.
*
* This structure must be treated as an opaque data type. Members must not be
* accessed directly.
*
* @see rtems_interrupt_server_create()
*/
typedef struct rtems_interrupt_server_control {
RTEMS_INTERRUPT_LOCK_MEMBER( lock )
rtems_chain_control entries;
rtems_id server;
unsigned long errors;
uint32_t index;
rtems_chain_node node;
void ( *destroy )( struct rtems_interrupt_server_control * );
} rtems_interrupt_server_control;
/**
* @brief An interrupt server configuration.
*
* @see rtems_interrupt_server_create()
*/
typedef struct {
/**
* @brief The task name of the interrupt server.
*/
rtems_name name;
/**
* @brief The initial task priority of the interrupt server.
*/
rtems_task_priority priority;
/**
* @brief The task storage area of the interrupt server.
*
* It shall be NULL for interrupt servers created by
* rtems_interrupt_server_create().
*/
void *storage_area;
/**
* @brief The task storage size of the interrupt server.
*
* For interrupt servers created by rtems_interrupt_server_create() this is
* the task stack size.
*/
size_t storage_size;
/**
* @brief The initial task modes of the interrupt server.
*/
rtems_mode modes;
/**
* @brief The task attributes of the interrupt server.
*/
rtems_attribute attributes;
/**
* @brief An optional handler to destroy the interrupt server control handed
* over to rtems_interrupt_server_create().
*
* This handler is called in the context of the interrupt server to be
* deleted, see also rtems_interrupt_server_delete().
*/
void ( *destroy )( rtems_interrupt_server_control * );
} rtems_interrupt_server_config;
/** /**
* @brief An interrupt server entry. * @brief An interrupt server entry.
* *
@@ -309,16 +373,19 @@ typedef struct {
* *
* The server count pointer @a server_count may be @a NULL. * The server count pointer @a server_count may be @a NULL.
* *
* The task name of interrupt servers created by this function is
* rtems_build_name( 'I', 'R', 'Q', 'S' ).
*
* This function may block. * This function may block.
* *
* @see rtems_task_create(). * @retval RTEMS_SUCCESSFUL The operation was successful.
* *
* @retval RTEMS_SUCCESSFUL Successful operation. * @retval RTEMS_INCORRECT_STATE The interrupt servers were already initialized.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized. *
* @retval RTEMS_NO_MEMORY Not enough memory. * @return The function uses rtems_task_create(). If this operation is not
* @retval RTEMS_TOO_MANY No free task available to create at least one server task. * successful, then its status code is returned.
* @retval RTEMS_UNSATISFIED Task stack size too large. *
* @retval RTEMS_INVALID_PRIORITY Invalid task priority. * @see rtems_interrupt_server_create() and rtems_interrupt_server_delete().
*/ */
rtems_status_code rtems_interrupt_server_initialize( rtems_status_code rtems_interrupt_server_initialize(
rtems_task_priority priority, rtems_task_priority priority,
@@ -328,6 +395,54 @@ rtems_status_code rtems_interrupt_server_initialize(
uint32_t *server_count uint32_t *server_count
); );
/**
* @brief Creates an interrupt server.
*
* This function may block.
*
* @param[out] control is the interrupt server control. The ownership of this
* structure is transferred from the caller of this function to the interrupt
* server management.
*
* @param config is the interrupt server configuration.
*
* @param[out] server_index is the pointer to a server index variable. The
* index of the built interrupt server will be stored in the referenced
* variable if the operation was successful.
*
* @retval RTEMS_SUCCESSFUL The operation was successful.
*
* @return The function uses rtems_task_create(). If this operation is not
* successful, then its status code is returned.
*
* @see rtems_interrupt_server_initialize() and
* rtems_interrupt_server_delete().
*/
rtems_status_code rtems_interrupt_server_create(
rtems_interrupt_server_control *control,
const rtems_interrupt_server_config *config,
uint32_t *server_index
);
/**
* @brief Destroys the interrupt server.
*
* This function may block.
*
* The interrupt server deletes itself, so after the return of the function the
* interrupt server may be still in the termination process depending on the
* task priorities of the system.
*
* @param server_index is the index of the interrupt server to destroy. Use
* ::RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
*
* @retval RTEMS_SUCCESSFUL The operation was successful.
* @retval RTEMS_INVALID_ID The interrupt server index was invalid.
*
* @see rtems_interrupt_server_create()
*/
rtems_status_code rtems_interrupt_server_delete( uint32_t server_index );
/** /**
* @brief Installs the interrupt handler routine @a handler for the interrupt * @brief Installs the interrupt handler routine @a handler for the interrupt
* vector with number @a vector on the server @a server. * vector with number @a vector on the server @a server.

View File

@@ -504,6 +504,7 @@ static rtems_status_code mount_worker(
if (rv != 0) { if (rv != 0) {
rmdir(mount_path); rmdir(mount_path);
free(mount_path); free(mount_path);
(*mount_options.converter->handler->destroy)(mount_options.converter);
return RTEMS_IO_ERROR; return RTEMS_IO_ERROR;
} }

View File

@@ -103,10 +103,12 @@ int rtems_dosfs_initialize(
int rc = 0; int rc = 0;
const rtems_dosfs_mount_options *mount_options = data; const rtems_dosfs_mount_options *mount_options = data;
rtems_dosfs_convert_control *converter; rtems_dosfs_convert_control *converter;
bool converter_created = false;
if (mount_options == NULL || mount_options->converter == NULL) { if (mount_options == NULL || mount_options->converter == NULL) {
converter = rtems_dosfs_create_default_converter(); converter = rtems_dosfs_create_default_converter();
converter_created = true;
} else { } else {
converter = mount_options->converter; converter = mount_options->converter;
} }
@@ -117,6 +119,9 @@ int rtems_dosfs_initialize(
&msdos_file_handlers, &msdos_file_handlers,
&msdos_dir_handlers, &msdos_dir_handlers,
converter); converter);
if (rc != 0 && converter_created) {
(*converter->handler->destroy)(converter);
}
} else { } else {
errno = ENOMEM; errno = ENOMEM;
rc = -1; rc = -1;

View File

@@ -234,12 +234,16 @@ static void rtems_shell_clear_shell_env(void)
eno = pthread_setspecific(rtems_shell_current_env_key, NULL); eno = pthread_setspecific(rtems_shell_current_env_key, NULL);
if (eno != 0) if (eno != 0)
rtems_error(0, "pthread_setspecific(shell_current_env_key): clear"); rtems_error(0, "pthread_setspecific(shell_current_env_key): clear");
}
/* /*
* Clear stdin and stdout file pointers of they will be closed * Clear stdin, stdout and stderr file pointers so they will not be closed.
*/ */
static void rtems_shell_clear_shell_std_handles(void)
{
stdin = NULL; stdin = NULL;
stdout = NULL; stdout = NULL;
stderr = NULL;
} }
/* /*
@@ -775,6 +779,7 @@ void rtems_shell_print_env(
{ {
if ( !shell_env ) { if ( !shell_env ) {
printk( "shell_env is NULL\n" ); printk( "shell_env is NULL\n" );
return; return;
} }
printk( "shell_env=%p\n" printk( "shell_env=%p\n"
@@ -797,6 +802,7 @@ static rtems_task rtems_shell_task(rtems_task_argument task_argument)
rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument; rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;
rtems_id wake_on_end = shell_env->wake_on_end; rtems_id wake_on_end = shell_env->wake_on_end;
rtems_shell_main_loop( shell_env ); rtems_shell_main_loop( shell_env );
rtems_shell_clear_shell_std_handles();
if (wake_on_end != RTEMS_INVALID_ID) if (wake_on_end != RTEMS_INVALID_ID)
rtems_event_send (wake_on_end, RTEMS_EVENT_1); rtems_event_send (wake_on_end, RTEMS_EVENT_1);
rtems_task_exit(); rtems_task_exit();
@@ -872,6 +878,11 @@ bool rtems_shell_main_loop(
else else
stdout = stderr; stdout = stderr;
} else if (strcmp(shell_env->output, "/dev/null") == 0) { } else if (strcmp(shell_env->output, "/dev/null") == 0) {
if (stdout == NULL) {
fprintf(stderr, "shell: stdout is NULLs\n");
rtems_shell_clear_shell_env();
return false;
}
fclose (stdout); fclose (stdout);
} else { } else {
FILE *output = fopen(shell_env->output, FILE *output = fopen(shell_env->output,
@@ -906,6 +917,13 @@ bool rtems_shell_main_loop(
} }
if (!input_file) { if (!input_file) {
if (stdin == NULL) {
fprintf(stderr, "shell: stdin is NULLs\n");
if (stdoutToClose != NULL)
fclose(stdoutToClose);
rtems_shell_clear_shell_env();
return false;
}
/* Make a raw terminal, Linux Manuals */ /* Make a raw terminal, Linux Manuals */
if (tcgetattr(fileno(stdin), &previous_term) >= 0) { if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
term = previous_term; term = previous_term;
@@ -967,7 +985,7 @@ bool rtems_shell_main_loop(
* keep on trucking. * keep on trucking.
*/ */
if (shell_env->login_check != NULL) { if (shell_env->login_check != NULL) {
result = rtems_shell_login(shell_env, stdin,stdout); result = rtems_shell_login(shell_env, stdin, stdout);
} else { } else {
setuid(shell_env->uid); setuid(shell_env->uid);
setgid(shell_env->gid); setgid(shell_env->gid);

View File

@@ -29,28 +29,29 @@ int shm_unlink( const char *name )
_Objects_Allocator_lock(); _Objects_Allocator_lock();
shm = _POSIX_Shm_Get_by_name( name, 0, &obj_err ); shm = _POSIX_Shm_Get_by_name( name, 0, &obj_err );
switch ( obj_err ) { if ( shm ) {
case OBJECTS_GET_BY_NAME_INVALID_NAME: _Objects_Namespace_remove_string(
err = ENOENT; &_POSIX_Shm_Information,
break; &shm->Object
);
case OBJECTS_GET_BY_NAME_NAME_TOO_LONG: if ( shm->reference_count == 0 ) {
err = ENAMETOOLONG; /* Only remove the shm object if no references exist to it. Otherwise,
break; * the shm object will be freed later in _POSIX_Shm_Attempt_delete */
_POSIX_Shm_Free( shm );
}
} else {
switch ( obj_err ) {
case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
err = ENAMETOOLONG;
break;
case OBJECTS_GET_BY_NAME_NO_OBJECT: case OBJECTS_GET_BY_NAME_INVALID_NAME:
default: case OBJECTS_GET_BY_NAME_NO_OBJECT:
_Objects_Namespace_remove_string( default:
&_POSIX_Shm_Information, err = ENOENT;
&shm->Object break;
); }
if ( shm->reference_count == 0 ) {
/* Only remove the shm object if no references exist to it. Otherwise,
* the shm object will be freed later in _POSIX_Shm_Attempt_delete */
_POSIX_Shm_Free( shm );
}
break;
} }
_Objects_Allocator_unlock(); _Objects_Allocator_unlock();

View File

@@ -83,9 +83,9 @@ SYM (_CPU_Context_switch):
.L_restore: .L_restore:
movl I386_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE(eax),ecx movl I386_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE(eax),ecx
movl ecx,PER_CPU_ISR_DISPATCH_DISABLE(edx) movl ecx,PER_CPU_ISR_DISPATCH_DISABLE(edx)
movl REG_ESP(eax),esp /* restore stack pointer */
pushl REG_EFLAGS(eax) /* push eflags */ pushl REG_EFLAGS(eax) /* push eflags */
popf /* restore eflags */ popf /* restore eflags */
movl REG_ESP(eax),esp /* restore stack pointer */
movl REG_EBP(eax),ebp /* restore base pointer */ movl REG_EBP(eax),ebp /* restore base pointer */
movl REG_EBX(eax),ebx /* restore ebx */ movl REG_EBX(eax),ebx /* restore ebx */
movl REG_ESI(eax),esi /* restore source register */ movl REG_ESI(eax),esi /* restore source register */