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" {
#endif /* __cplusplus */
/**
* @brief The SC16IS752 device context.
*
* All members are private to the device driver.
*/
typedef struct {
sc16is752_spi_context base;
Pin irq_pin;
rtems_interrupt_server_entry irqs_entry; /* Internal. Don't touch. */
rtems_interrupt_server_action irqs_action; /* Internal. Don't touch. */
rtems_interrupt_server_entry irqs_entry;
rtems_interrupt_server_action irqs_action;
uint32_t irqs_index;
} 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.
*
* This devices uses the interrupt server, see
* rtems_interrupt_server_initialize().
* This devices uses the interrupt server, see rtems_interrupt_server_create().
*
* The device claims the interrupt of the PIO block.
*
* @param[in] ctx The device context. May have an arbitrary content.
* @param[in] device_path The device file path for the new device.
* @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 }.
* @param[out] ctx is the device context. It may have an arbitrary content.
* @param config is the device configuration.
*
* @return See sc16is752_spi_create().
*/
int atsam_sc16is752_spi_create(
atsam_sc16is752_spi_context *ctx,
const char *device_path,
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
const atsam_sc16is752_spi_config *config
);
#ifdef __cplusplus

View File

@@ -41,7 +41,7 @@ static bool atsam_sc16is752_install_interrupt(sc16is752_context *base)
rtems_status_code sc;
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);
rtems_interrupt_server_action_prepend(&ctx->irqs_entry,
&ctx->irqs_action, atsam_sc16i752_irqs_handler, ctx);
@@ -65,23 +65,18 @@ static void atsam_sc16is752_remove_interrupt(sc16is752_context *base)
int atsam_sc16is752_spi_create(
atsam_sc16is752_spi_context *ctx,
const char *device_path,
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
const atsam_sc16is752_spi_config *config
)
{
ctx->base.base.mode = mode;
ctx->base.base.input_frequency = input_frequency;
ctx->base.base.mode = config->mode;
ctx->base.base.input_frequency = config->input_frequency;
ctx->base.base.install_irq = atsam_sc16is752_install_interrupt;
ctx->base.base.remove_irq = atsam_sc16is752_remove_interrupt;
ctx->base.spi_path = spi_path;
ctx->base.cs = spi_chip_select;
ctx->base.speed_hz = spi_speed_hz;
ctx->irq_pin = *irq_pin;
ctx->base.spi_path = config->spi_path;
ctx->base.cs = config->spi_chip_select;
ctx->base.speed_hz = config->spi_speed_hz;
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 bauddiv = 0x6;
zynq_uart_reset_tx_flush(ctx);
zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode);
regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);

View File

@@ -226,9 +226,11 @@ get_checksum(unsigned start, int length)
int
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);
/* Wait for send to finish */
@@ -251,9 +253,11 @@ static int
boot_cpu(imps_processor *proc)
{
int apicid = proc->apic_id, success = 1;
int cpuid;
unsigned bootaddr;
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
* "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
* see startAP.S for location */
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(
(char*) &reset[3],
&gdtdesc,
@@ -295,13 +299,13 @@ boot_cpu(imps_processor *proc)
/* assert INIT IPI */
send_ipi(
apicid,
cpuid,
LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT
);
UDELAY(10000);
/* 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);
@@ -312,7 +316,7 @@ boot_cpu(imps_processor *proc)
if (proc->apic_ver >= APIC_VER_NEW) {
int 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);
}
}

View File

@@ -50,7 +50,7 @@
* Acts as a barrier to ensure all previous I/O accesses have
* completed before any further ones are issued.
*/
static inline void eieio(void)
static inline void io_eieio(void)
{
__asm__ __volatile__ ("eieio");
}
@@ -59,9 +59,9 @@ static inline void eieio(void)
/* Enforce in-order execution of data I/O.
* No distinction between read/write on PPC; use eieio for all three.
*/
#define iobarrier_rw() eieio()
#define iobarrier_r() eieio()
#define iobarrier_w() eieio()
#define iobarrier_rw() io_eieio()
#define iobarrier_r() io_eieio()
#define iobarrier_w() io_eieio()
/*
* 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.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
* Copyright (C) 2009, 2020 embedded brains GmbH (http://www.embedded-brains.de)
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -21,6 +15,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include <rtems.h>
#include <rtems/chain.h>
@@ -30,54 +25,43 @@
#define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1)
typedef struct {
RTEMS_INTERRUPT_LOCK_MEMBER(lock);
rtems_chain_control entries;
rtems_id server;
unsigned errors;
} bsp_interrupt_server_context;
static rtems_interrupt_server_control bsp_interrupt_server_default;
#if defined(RTEMS_SMP)
static bsp_interrupt_server_context *bsp_interrupt_server_instances;
#else
static bsp_interrupt_server_context bsp_interrupt_server_instance;
#endif
static rtems_chain_control bsp_interrupt_server_chain =
RTEMS_CHAIN_INITIALIZER_EMPTY(bsp_interrupt_server_chain);
static bsp_interrupt_server_context *bsp_interrupt_server_get_context(
static rtems_interrupt_server_control *bsp_interrupt_server_get_context(
uint32_t server_index,
rtems_status_code *sc
)
{
#if defined(RTEMS_SMP)
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
rtems_chain_node *node;
if (server_index >= rtems_scheduler_get_processor_maximum()) {
bsp_interrupt_lock();
node = rtems_chain_first(&bsp_interrupt_server_chain);
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);
}
bsp_interrupt_unlock();
*sc = RTEMS_INVALID_ID;
return NULL;
}
*sc = RTEMS_SUCCESSFUL;
#if defined(RTEMS_SMP)
return &bsp_interrupt_server_instances[server_index];
#else
return &bsp_interrupt_server_instance;
#endif
}
static void bsp_interrupt_server_trigger(void *arg)
{
rtems_interrupt_lock_context lock_context;
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)) {
bsp_interrupt_vector_disable(e->vector);
@@ -137,7 +121,7 @@ static rtems_interrupt_server_entry *bsp_interrupt_server_query_entry(
}
typedef struct {
bsp_interrupt_server_context *server;
rtems_interrupt_server_control *server;
rtems_vector_number vector;
rtems_option options;
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(
bsp_interrupt_server_context *s,
rtems_interrupt_server_control *s,
rtems_vector_number vector,
rtems_option options,
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(
bsp_interrupt_server_context *s
rtems_interrupt_server_control *s
)
{
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)
{
bsp_interrupt_server_context *s = (bsp_interrupt_server_context *) arg;
rtems_interrupt_server_control *s = (rtems_interrupt_server_control *) arg;
while (true) {
rtems_event_set events;
@@ -377,7 +361,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
)
{
rtems_status_code sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) {
@@ -402,7 +386,7 @@ rtems_status_code rtems_interrupt_server_handler_remove(
)
{
rtems_status_code sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) {
@@ -464,7 +448,7 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
{
rtems_status_code sc;
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);
if (s == NULL) {
@@ -487,36 +471,35 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
);
}
rtems_status_code rtems_interrupt_server_initialize(
/*
* 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 *server_count
uint32_t cpu_index
)
{
uint32_t cpu_index;
uint32_t cpu_count;
uint32_t dummy;
bsp_interrupt_server_context *instances;
if (server_count == NULL) {
server_count = &dummy;
}
cpu_count = rtems_scheduler_get_processor_maximum();
#if defined(RTEMS_SMP)
instances = calloc(cpu_count, sizeof(*instances));
if (instances == NULL) {
return RTEMS_NO_MEMORY;
}
#else
instances = &bsp_interrupt_server_instance;
#endif
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
bsp_interrupt_server_context *s = &instances[cpu_index];
rtems_status_code sc;
#if defined(RTEMS_SMP)
rtems_id scheduler;
@@ -535,25 +518,14 @@ rtems_status_code rtems_interrupt_server_initialize(
&s->server
);
if (sc != RTEMS_SUCCESSFUL) {
*server_count = cpu_index;
#if defined(RTEMS_SMP)
if (cpu_index > 0) {
bsp_interrupt_server_instances = instances;
return RTEMS_SUCCESSFUL;
}
free(instances);
#endif
return RTEMS_TOO_MANY;
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 */
continue;
return RTEMS_SUCCESSFUL;
}
sc = rtems_task_set_scheduler(s->server, scheduler, priority);
@@ -563,27 +535,188 @@ rtems_status_code rtems_interrupt_server_initialize(
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_task_priority priority,
size_t stack_size,
rtems_mode modes,
rtems_attribute attributes,
uint32_t *server_count
)
{
rtems_status_code sc;
rtems_interrupt_server_control *s;
uint32_t cpu_index;
#if defined(RTEMS_SMP)
bsp_interrupt_server_instances = instances;
uint32_t cpu_count;
#endif
*server_count = cpu_index;
cpu_index = 0;
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();
while (cpu_index < cpu_count) {
s = calloc(1, sizeof(*s));
if (s == NULL) {
sc = RTEMS_NO_MEMORY;
goto done;
}
s->destroy = bsp_interrupt_server_destroy_secondary;
s->index = cpu_index;
sc = bsp_interrupt_server_create(
s,
priority,
stack_size,
modes,
attributes,
cpu_index
);
if (sc != RTEMS_SUCCESSFUL) {
goto done;
}
++cpu_index;
}
#endif
done:
bsp_interrupt_unlock();
if (server_count != NULL) {
*server_count = cpu_index;
}
return sc;
}
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;
}
static void bsp_interrupt_server_entry_initialize(
rtems_interrupt_server_entry *entry,
bsp_interrupt_server_context *s
rtems_interrupt_server_control *s
)
{
rtems_chain_set_off_chain(&entry->node);
@@ -611,7 +744,7 @@ rtems_status_code rtems_interrupt_server_entry_initialize(
)
{
rtems_status_code sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) {
@@ -645,7 +778,7 @@ rtems_status_code rtems_interrupt_server_entry_move(
)
{
rtems_status_code sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(destination_server_index, &sc);
if (s == NULL) {
@@ -667,7 +800,7 @@ void rtems_interrupt_server_entry_destroy(
rtems_interrupt_server_entry *entry
)
{
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
rtems_interrupt_lock_context lock_context;
s = entry->server;
@@ -698,7 +831,7 @@ rtems_status_code rtems_interrupt_server_request_initialize(
)
{
rtems_status_code sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc);
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);
if (e != NULL) {
rtems_interrupt_lock_context lock_context;
bsp_interrupt_server_context *src = e->server;
bsp_interrupt_server_context *dst = hihd->arg;
rtems_interrupt_server_control *src = e->server;
rtems_interrupt_server_control *dst = hihd->arg;
bool pending;
/* 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;
bsp_interrupt_server_context *src;
bsp_interrupt_server_context *dst;
rtems_interrupt_server_control *src;
rtems_interrupt_server_control *dst;
bsp_interrupt_server_handler_iterate_helper_data hihd;
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 sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc);
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 sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
s = bsp_interrupt_server_get_context(server_index, &sc);
if (s == NULL) {
@@ -858,7 +991,7 @@ rtems_status_code rtems_interrupt_server_set_affinity(
)
{
rtems_status_code sc;
bsp_interrupt_server_context *s;
rtems_interrupt_server_control *s;
rtems_id scheduler;
s = bsp_interrupt_server_get_context(server_index, &sc);

View File

@@ -6,9 +6,6 @@
* @ingroup RTEMSApplicationConfiguration
*
* @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
#include <rtems/confdefs/threads.h>
#ifndef CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK
#define CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK 0
#endif
@@ -83,8 +82,6 @@
#error "CONFIGURE_MP_NODE_NUMBER must be less than or equal to CONFIGURE_MP_MAXIMUM_NODES"
#endif
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 1
#ifdef __cplusplus
extern "C" {
#endif
@@ -126,10 +123,6 @@ RTEMS_SECTION( ".rtemsstack.mpci" );
}
#endif
#else /* CONFIGURE_MP_APPLICATION */
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
#endif /* CONFIGURE_MP_APPLICATION */
#else /* RTEMS_MULTIPROCESSING */
@@ -138,8 +131,6 @@ RTEMS_SECTION( ".rtemsstack.mpci" );
#error "CONFIGURE_MP_APPLICATION must not be defined if multiprocessing is disabled"
#endif
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
#endif /* RTEMS_MULTIPROCESSING */
#endif /* CONFIGURE_INIT */

View File

@@ -44,7 +44,6 @@
#include <rtems/confdefs/bdbuf.h>
#include <rtems/confdefs/extensions.h>
#include <rtems/confdefs/mpci.h>
#include <rtems/confdefs/percpu.h>
#include <rtems/confdefs/scheduler.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_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,
OBJECTS_INTERNAL_API,

View File

@@ -214,6 +214,9 @@ typedef struct {
/**
* @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
* file system, the implementation was:
* - Short names were saved in code page format (as is still the case).
@@ -270,6 +273,10 @@ typedef struct {
* RTEMS_FILESYSTEM_READ_WRITE,
* &mount_opts
* );
*
* if (rv != 0) {
* (*mount_opts.converter->handler->destroy)(mount_opts.converter);
* }
* } else {
* rv = -1;
* errno = ENOMEM;

View File

@@ -9,13 +9,7 @@
/*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
*
* Copyright (C) 2008, 2019 embedded brains GmbH
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
* Copyright (C) 2008, 2020 embedded brains GmbH (http://www.embedded-brains.de)
*
* The license and distribution terms for this file may be
* 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
/**
* @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.
*
@@ -309,16 +373,19 @@ typedef struct {
*
* 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.
*
* @see rtems_task_create().
* @retval RTEMS_SUCCESSFUL The operation was successful.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_NO_MEMORY Not enough memory.
* @retval RTEMS_TOO_MANY No free task available to create at least one server task.
* @retval RTEMS_UNSATISFIED Task stack size too large.
* @retval RTEMS_INVALID_PRIORITY Invalid task priority.
* @retval RTEMS_INCORRECT_STATE The interrupt servers were already initialized.
*
* @return The function uses rtems_task_create(). If this operation is not
* successful, then its status code is returned.
*
* @see rtems_interrupt_server_create() and rtems_interrupt_server_delete().
*/
rtems_status_code rtems_interrupt_server_initialize(
rtems_task_priority priority,
@@ -328,6 +395,54 @@ rtems_status_code rtems_interrupt_server_initialize(
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
* 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) {
rmdir(mount_path);
free(mount_path);
(*mount_options.converter->handler->destroy)(mount_options.converter);
return RTEMS_IO_ERROR;
}

View File

@@ -103,10 +103,12 @@ int rtems_dosfs_initialize(
int rc = 0;
const rtems_dosfs_mount_options *mount_options = data;
rtems_dosfs_convert_control *converter;
bool converter_created = false;
if (mount_options == NULL || mount_options->converter == NULL) {
converter = rtems_dosfs_create_default_converter();
converter_created = true;
} else {
converter = mount_options->converter;
}
@@ -117,6 +119,9 @@ int rtems_dosfs_initialize(
&msdos_file_handlers,
&msdos_dir_handlers,
converter);
if (rc != 0 && converter_created) {
(*converter->handler->destroy)(converter);
}
} else {
errno = ENOMEM;
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);
if (eno != 0)
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;
stdout = NULL;
stderr = NULL;
}
/*
@@ -775,6 +779,7 @@ void rtems_shell_print_env(
{
if ( !shell_env ) {
printk( "shell_env is NULL\n" );
return;
}
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_id wake_on_end = shell_env->wake_on_end;
rtems_shell_main_loop( shell_env );
rtems_shell_clear_shell_std_handles();
if (wake_on_end != RTEMS_INVALID_ID)
rtems_event_send (wake_on_end, RTEMS_EVENT_1);
rtems_task_exit();
@@ -872,6 +878,11 @@ bool rtems_shell_main_loop(
else
stdout = stderr;
} 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);
} else {
FILE *output = fopen(shell_env->output,
@@ -906,6 +917,13 @@ bool rtems_shell_main_loop(
}
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 */
if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
term = previous_term;

View File

@@ -29,17 +29,7 @@ int shm_unlink( const char *name )
_Objects_Allocator_lock();
shm = _POSIX_Shm_Get_by_name( name, 0, &obj_err );
switch ( obj_err ) {
case OBJECTS_GET_BY_NAME_INVALID_NAME:
err = ENOENT;
break;
case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
err = ENAMETOOLONG;
break;
case OBJECTS_GET_BY_NAME_NO_OBJECT:
default:
if ( shm ) {
_Objects_Namespace_remove_string(
&_POSIX_Shm_Information,
&shm->Object
@@ -50,7 +40,18 @@ int shm_unlink( const char *name )
* 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_INVALID_NAME:
case OBJECTS_GET_BY_NAME_NO_OBJECT:
default:
err = ENOENT;
break;
}
}
_Objects_Allocator_unlock();

View File

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