mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-11-30 20:55:41 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a79813c96e | ||
|
|
0cf6de01df | ||
|
|
1240e8f81b | ||
|
|
b1dbd9eeae | ||
|
|
84d4c11c30 | ||
|
|
e7fa90ab0c | ||
|
|
dd490c5c2d | ||
|
|
d010f6ae8b | ||
|
|
3d8b56f10c | ||
|
|
cb3fba0447 | ||
|
|
6335d7e48a | ||
|
|
f769b20c98 | ||
|
|
9dae9f5fe8 | ||
|
|
b4149b2282 | ||
|
|
87bf49b715 | ||
|
|
e421c922a8 | ||
|
|
e36ba91110 | ||
|
|
a0e4be53f4 | ||
|
|
9641e1e97d | ||
|
|
f1c201c508 | ||
|
|
603c168a0b | ||
|
|
84c2cf3da9 |
4
.gitlab/gitlab-ci.yml
Normal file
4
.gitlab/gitlab-ci.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
include:
|
||||
- project: 'administration/integration'
|
||||
file:
|
||||
- 'ci/config/rtems.yml'
|
||||
@@ -30,6 +30,10 @@
|
||||
|
||||
#include <bsp/utility.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t config;
|
||||
#define CADENCE_SPI_CONFIG_MODEFAIL_EN BSP_BIT32(17)
|
||||
@@ -82,4 +86,8 @@ typedef struct {
|
||||
uint32_t moduleid;
|
||||
} cadence_spi;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBBSP_ARM_XILINX_ZYNQ_CADENCE_SPI_REGS_H */
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
|
||||
#include <bsp/utility.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t reserved1[7];
|
||||
uint32_t globalirq;
|
||||
@@ -85,4 +89,8 @@ typedef struct {
|
||||
uint32_t rx_fifo_len;
|
||||
} xilinx_axi_spi;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBBSP_ARM_XILINX_AXI_SPI_REGS_H */
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#include <dev/flash/flashdev.h>
|
||||
#include <dev/spi/xqspipsu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XQSPI_FLASH_MAX_REGIONS ((size_t)32)
|
||||
|
||||
/*
|
||||
@@ -65,4 +69,8 @@ typedef struct xqspi_flash_region_table {
|
||||
uint32_t xqspi_flash_bit_allocator;
|
||||
} xqspi_flash_region_table;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XILINX_XQSPI_FLASH_H */
|
||||
|
||||
@@ -3,8 +3,27 @@
|
||||
* SPDX-License-Identifier: MIT
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @file xqspipsu_flash_helper.h
|
||||
*
|
||||
* This file contains flash helper function prototypes for the QSPIPSU driver.
|
||||
* It consists of modified functions from Xilinx's flash example in
|
||||
* examples/xqspipsu_generic_flash_interrupt_example.c of the qspipsu driver.
|
||||
*
|
||||
* Since the comment blocks and general form of the functions has not changed,
|
||||
* the Xilinx copyright above is maintained, but this file is not part of the
|
||||
* upstream embeddedsw distribution.
|
||||
*/
|
||||
|
||||
#ifndef LIBBSP_DEV_SPI_XQSPIPSU_HELPER_H
|
||||
#define LIBBSP_DEV_SPI_XQSPIPSU_HELPER_H
|
||||
|
||||
#include "xqspipsu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int QspiPsu_NOR_Initialize(
|
||||
XQspiPsu *QspiPsuInstancePtr,
|
||||
u16 QspiPsuIntrId
|
||||
@@ -231,3 +250,9 @@ u32 QspiPsu_NOR_Get_Page_Size(XQspiPsu *QspiPsuPtr);
|
||||
* @return The JEDEC ID of attached flash in bytes.
|
||||
******************************************************************************/
|
||||
u32 QspiPsu_NOR_Get_JEDEC_ID(XQspiPsu *QspiPsuPtr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBBSP_DEV_SPI_XQSPIPSU_HELPER_H */
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010, 2017 embedded brains GmbH & Co. KG
|
||||
* Copyright (C) 2010, 2024 embedded brains GmbH & Co. KG
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -162,8 +162,6 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
|
||||
|
||||
void bsp_interrupt_dispatch(uintptr_t exception_number)
|
||||
{
|
||||
unsigned int vector;
|
||||
|
||||
if (exception_number == 10) {
|
||||
qoriq_decrementer_dispatch();
|
||||
return;
|
||||
@@ -176,22 +174,25 @@ void bsp_interrupt_dispatch(uintptr_t exception_number)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This works only if the "has-external-proxy" property is present in the
|
||||
* "epapr,hv-pic" device tree node.
|
||||
*/
|
||||
PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR, vector);
|
||||
|
||||
if (vector != SPURIOUS) {
|
||||
while (true) {
|
||||
unsigned int vector;
|
||||
uint32_t msr;
|
||||
|
||||
/*
|
||||
* This works only if the "has-external-proxy" property is present in the
|
||||
* "epapr,hv-pic" device tree node.
|
||||
*/
|
||||
PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR, vector);
|
||||
|
||||
if (vector == SPURIOUS) {
|
||||
return;
|
||||
}
|
||||
|
||||
msr = ppc_external_exceptions_enable();
|
||||
bsp_interrupt_handler_dispatch(vector);
|
||||
ppc_external_exceptions_disable(msr);
|
||||
|
||||
ev_int_eoi(vector);
|
||||
} else {
|
||||
bsp_interrupt_handler_default(vector);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,19 +587,20 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
|
||||
|
||||
void bsp_interrupt_dispatch(uintptr_t exception_number)
|
||||
{
|
||||
rtems_vector_number vector = qoriq.pic.iack;
|
||||
while (true) {
|
||||
rtems_vector_number vector = qoriq.pic.iack;
|
||||
uint32_t msr;
|
||||
|
||||
if (vector != SPURIOUS) {
|
||||
uint32_t msr = ppc_external_exceptions_enable();
|
||||
if (vector == SPURIOUS) {
|
||||
return;
|
||||
}
|
||||
|
||||
msr = ppc_external_exceptions_enable();
|
||||
bsp_interrupt_handler_dispatch(vector);
|
||||
|
||||
ppc_external_exceptions_disable(msr);
|
||||
|
||||
qoriq.pic.eoi = 0;
|
||||
qoriq.pic.whoami;
|
||||
} else {
|
||||
bsp_interrupt_handler_default(vector);
|
||||
ppc_enforce_in_order_execution_of_io();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,11 +181,14 @@ rtems_status_code console_initialize(
|
||||
|
||||
rtems_termios_initialize();
|
||||
|
||||
const rtems_termios_device_handler *handler = &apbuart_handler_polled;
|
||||
const rtems_termios_device_handler *handler;
|
||||
|
||||
if (BSP_CONSOLE_USE_INTERRUPTS) {
|
||||
#ifdef BSP_CONSOLE_USE_INTERRUPTS
|
||||
handler = &apbuart_handler_interrupt;
|
||||
}
|
||||
#else
|
||||
handler = &apbuart_handler_polled;
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < apbuart_devices; ++i) {
|
||||
struct apbuart_context *ctx;
|
||||
|
||||
|
||||
@@ -225,6 +225,7 @@ ata_io_data_request(ata_ide_dev_t *ata_dev, rtems_blkdev_request *req)
|
||||
areq->breq->bufnum * (areq->breq->bufs[0].length / ATA_SECTOR_SIZE);
|
||||
|
||||
/* add request to the queue of awaiting requests to the controller */
|
||||
rtems_chain_set_off_chain(&areq->link);
|
||||
ata_add_to_controller_queue(ctrl_minor, areq);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@@ -1249,6 +1250,7 @@ rtems_ata_initialize(rtems_device_major_number major,
|
||||
rtems_message_queue_delete(ata_queue_id);
|
||||
return status;
|
||||
}
|
||||
rtems_chain_set_off_chain(&int_st->link);
|
||||
#if CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE
|
||||
rtems_chain_append(
|
||||
&ata_int_vec[IDE_Controller_Table[ctrl_minor].int_vec],
|
||||
|
||||
@@ -590,7 +590,7 @@ int ns16550_set_attributes(
|
||||
* turn into the LSB and MSB divisor latch registers.
|
||||
*/
|
||||
|
||||
(*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
|
||||
(*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB | ucLineControl);
|
||||
(*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
|
||||
(*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
* consists of modified functions from Xilinx's flash example in
|
||||
* examples/xqspipsu_generic_flash_interrupt_example.c of the qspipsu driver.
|
||||
*
|
||||
* Since the comment blocks and general form of the functions has not changed,
|
||||
* the Xilinx copyright above is maintained, but this file is not part of the
|
||||
* upstream embeddedsw distribution.
|
||||
*/
|
||||
|
||||
#include "xqspipsu_flash_config.h"
|
||||
|
||||
@@ -62,7 +62,8 @@ int grlib_canbtrs_calc_timing(
|
||||
tseg++) {
|
||||
/* calculate scaler */
|
||||
tmp = ((br->divfactor + tseg) * baud);
|
||||
sc = (core_hz * 2)/ tmp - core_hz / tmp;
|
||||
/* Core frequency is always divided by 2 before scaler */
|
||||
sc = core_hz / (2 * tmp);
|
||||
if (sc <= 0 || sc > br->max_scaler)
|
||||
continue;
|
||||
if (br->has_bpr &&
|
||||
@@ -71,7 +72,7 @@ int grlib_canbtrs_calc_timing(
|
||||
((sc > 256 * 4) && (sc <= 256 * 8) && (sc & 0x7))))
|
||||
continue;
|
||||
|
||||
error = baud - core_hz / (sc * (br->divfactor + tseg));
|
||||
error = baud - core_hz / (2 * sc * (br->divfactor + tseg));
|
||||
#ifdef GRLIB_CANBTRS_DEBUG
|
||||
printf(" baud=%d, tseg=%d, sc=%d, error=%d\n",
|
||||
baud, tseg, sc, error);
|
||||
|
||||
@@ -1019,7 +1019,9 @@ static void convert_timing_to_btrs(
|
||||
{
|
||||
btrs->btr0 = (t->rsj << OCCAN_BUSTIM_SJW_BIT) |
|
||||
(t->scaler & OCCAN_BUSTIM_BRP);
|
||||
btrs->btr1 = (0<<7) | (t->ps2 << OCCAN_BUSTIM_TSEG2_BIT) | t->ps1;
|
||||
|
||||
/* Core adds +1 to the register values, so compensate here by decrementing */
|
||||
btrs->btr1 = (0<<7) | ((t->ps2-1) << OCCAN_BUSTIM_TSEG2_BIT) | (t->ps1-1);
|
||||
}
|
||||
|
||||
static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing)
|
||||
|
||||
@@ -21,14 +21,6 @@
|
||||
#include <leon.h>
|
||||
#include <rtems/btimer.h>
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
#define LEON3_TIMER_INDEX \
|
||||
((rtems_configuration_get_user_multiprocessing_table()) ? \
|
||||
(rtems_configuration_get_user_multiprocessing_table()->node) - 1 : 1)
|
||||
#else
|
||||
#define LEON3_TIMER_INDEX 0
|
||||
#endif
|
||||
|
||||
bool benchmark_timer_find_average_overhead;
|
||||
|
||||
bool benchmark_timer_is_initialized = false;
|
||||
@@ -39,7 +31,7 @@ void benchmark_timer_initialize(void)
|
||||
* Timer runs long and accurate enough not to require an interrupt.
|
||||
*/
|
||||
if (LEON3_Timer_Regs) {
|
||||
gptimer_timer *timer = &LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX];
|
||||
gptimer_timer *timer = &LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX];
|
||||
if ( benchmark_timer_is_initialized == false ) {
|
||||
/* approximately 1 us per countdown */
|
||||
grlib_store_32( &timer->trldval, 0xffffff );
|
||||
@@ -61,7 +53,7 @@ benchmark_timer_t benchmark_timer_read(void)
|
||||
|
||||
if (LEON3_Timer_Regs) {
|
||||
total =
|
||||
grlib_load_32( &LEON3_Timer_Regs->timer[LEON3_TIMER_INDEX].tcntval );
|
||||
grlib_load_32( &LEON3_Timer_Regs->timer[LEON3_CLOCK_INDEX].tcntval );
|
||||
|
||||
total = 0xffffff - total;
|
||||
|
||||
|
||||
@@ -216,11 +216,12 @@ extern unsigned int leon3_timer_prescaler;
|
||||
* @brief This constant defines the index of the GPTIMER timer used by the
|
||||
* clock driver.
|
||||
*/
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
#define LEON3_CLOCK_INDEX \
|
||||
( leon3_timer_core_index != 0 ? 0 : 2 * LEON3_Cpu_Index )
|
||||
#else
|
||||
#if !defined(RTEMS_MULTIPROCESSING)
|
||||
#define LEON3_CLOCK_INDEX 0
|
||||
#elif defined(LEON3_GPTIMER_BASE)
|
||||
#define LEON3_CLOCK_INDEX ( 2 * LEON3_Cpu_Index )
|
||||
#else
|
||||
#define LEON3_CLOCK_INDEX ( leon3_timer_core_index != 0 ? 0 : 2 * LEON3_Cpu_Index )
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,8 @@ void _Timecounter_Getmicrouptime(struct timeval *);
|
||||
void _Timecounter_Getbintime(struct bintime *);
|
||||
void _Timecounter_Getnanotime(struct timespec *);
|
||||
void _Timecounter_Getmicrotime(struct timeval *);
|
||||
void _Timecounter_Getboottime(struct timeval *);
|
||||
void _Timecounter_Getboottimebin(struct bintime *);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _MACHINE__TIMECOUNTER_H_ */
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
* Modifications to support reference counting in the file system are
|
||||
* Copyright (C) 2012 embedded brains GmbH & Co. KG
|
||||
*
|
||||
* Copyright (C) 2025 Contemporary Software
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@@ -1378,18 +1380,23 @@ typedef struct {
|
||||
} rtems_libio_ioctl_args_t;
|
||||
|
||||
/**
|
||||
* @name Flag Values
|
||||
* @name Flag Values and Masks
|
||||
*/
|
||||
/**@{**/
|
||||
|
||||
#define LIBIO_FLAGS_NO_DELAY 0x0001U /* return immediately if no data */
|
||||
#define LIBIO_FLAGS_READ 0x0002U /* reading */
|
||||
#define LIBIO_FLAGS_WRITE 0x0004U /* writing */
|
||||
#define LIBIO_FLAGS_OPEN 0x0100U /* device is open */
|
||||
#define LIBIO_FLAGS_APPEND 0x0200U /* all writes append */
|
||||
#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800U /* close on process exec() */
|
||||
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
|
||||
#define LIBIO_FLAGS_REFERENCE_INC 0x1000U
|
||||
#define LIBIO_FLAGS_FREE 0x0001U /* on the free list */
|
||||
#define LIBIO_FLAGS_NO_DELAY 0x0002U /* return immediately if no data */
|
||||
#define LIBIO_FLAGS_READ 0x0004U /* reading */
|
||||
#define LIBIO_FLAGS_WRITE 0x0008U /* writing */
|
||||
#define LIBIO_FLAGS_OPEN 0x0100U /* device is open */
|
||||
#define LIBIO_FLAGS_APPEND 0x0200U /* all writes append */
|
||||
#define LIBIO_FLAGS_CLOSE_BUSY 0x0400U /* close with refs held */
|
||||
#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800U /* close on process exec() */
|
||||
#define LIBIO_FLAGS_REFERENCE_INC 0x1000U
|
||||
/* masks */
|
||||
#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
|
||||
#define LIBIO_FLAGS_FLAGS_MASK (LIBIO_FLAGS_REFERENCE_INC - 1U)
|
||||
#define LIBIO_FLAGS_REFERENCE_MASK (~LIBIO_FLAGS_FLAGS_MASK)
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -1398,6 +1405,20 @@ static inline unsigned int rtems_libio_iop_flags( const rtems_libio_t *iop )
|
||||
return _Atomic_Load_uint( &iop->flags, ATOMIC_ORDER_RELAXED );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the iop is a bad file descriptor, otherwise
|
||||
* returns false. A bad file descriptor means free or not open.
|
||||
*
|
||||
* @param[in] flags The flags.
|
||||
*/
|
||||
static inline unsigned int rtems_libio_iop_flags_bad_fd(
|
||||
const unsigned int flags
|
||||
)
|
||||
{
|
||||
return ( ( flags & LIBIO_FLAGS_FREE ) != 0 )
|
||||
|| ( ( flags & LIBIO_FLAGS_OPEN ) == 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if this is a no delay iop, otherwise returns false.
|
||||
*
|
||||
@@ -1428,6 +1449,16 @@ static inline bool rtems_libio_iop_is_writeable( const rtems_libio_t *iop )
|
||||
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_WRITE ) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the iop is open, otherwise returns false.
|
||||
*
|
||||
* @param[in] iop The iop.
|
||||
*/
|
||||
static inline bool rtems_libio_iop_is_open( const rtems_libio_t *iop )
|
||||
{
|
||||
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_OPEN ) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if this is an append iop, otherwise returns false.
|
||||
*
|
||||
@@ -1438,6 +1469,28 @@ static inline bool rtems_libio_iop_is_append( const rtems_libio_t *iop )
|
||||
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_APPEND ) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the iop is held, otherwise returns false.
|
||||
*
|
||||
* @param[in] iop The iop.
|
||||
*/
|
||||
static inline bool rtems_libio_iop_is_held( const rtems_libio_t *iop )
|
||||
{
|
||||
const unsigned int ref_count =
|
||||
rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_REFERENCE_MASK;
|
||||
return ref_count != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the iop is free, otherwise returns false.
|
||||
*
|
||||
* @param[in] iop The iop.
|
||||
*/
|
||||
static inline bool rtems_libio_iop_is_free( const rtems_libio_t *iop )
|
||||
{
|
||||
return ( rtems_libio_iop_flags( iop ) & LIBIO_FLAGS_FREE ) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name External I/O Handlers
|
||||
*/
|
||||
|
||||
@@ -103,6 +103,63 @@ extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
|
||||
*/
|
||||
extern rtems_filesystem_global_location_t rtems_filesystem_global_location_null;
|
||||
|
||||
/*
|
||||
* File Descriptor Routine Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* This routine searches the IOP Table for an unused entry. If it
|
||||
* finds one, it returns it. Otherwise, it returns NULL.
|
||||
*/
|
||||
rtems_libio_t *rtems_libio_allocate(void);
|
||||
|
||||
/**
|
||||
* Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
|
||||
*/
|
||||
unsigned int rtems_libio_from_fcntl_flags( int fcntl_flags );
|
||||
|
||||
/**
|
||||
* Convert RTEMS internal flags to UNIX fnctl(2) flags
|
||||
*/
|
||||
int rtems_libio_to_fcntl_flags( unsigned int flags );
|
||||
|
||||
/**
|
||||
* This routine frees the resources associated with an IOP (file
|
||||
* descriptor) and clears the slot in the IOP Table. No checks are
|
||||
* made on the state of the IOP.
|
||||
*/
|
||||
void rtems_libio_free_iop(
|
||||
rtems_libio_t *iop
|
||||
);
|
||||
|
||||
/**
|
||||
* This routine frees the resources associated with an IOP (file
|
||||
* descriptor) and clears the slot in the IOP Table. The IOP has to
|
||||
* close (open flag not set) and no references held or the call will
|
||||
* ignore the request.
|
||||
*/
|
||||
static inline void rtems_libio_free(
|
||||
rtems_libio_t *iop
|
||||
)
|
||||
{
|
||||
/*
|
||||
* The IOP cannot be open and there can be no references held for it
|
||||
* to be returned to the free list.
|
||||
*
|
||||
* Note, the open flag indicates the user owns the fd that indexes
|
||||
* the iop so consider it an indirect reference. We cannot return
|
||||
* the iop to the free list while the user owns the fd.
|
||||
*
|
||||
* Read the flags once as it is an atomic and we need to test 2
|
||||
* flags. No convenience call as this is the only case we have.
|
||||
*/
|
||||
const unsigned int flags = rtems_libio_iop_flags( iop );
|
||||
if ( ( ( flags & LIBIO_FLAGS_OPEN ) == 0 )
|
||||
&& ( ( flags & LIBIO_FLAGS_REFERENCE_MASK ) == 0 ) ) {
|
||||
rtems_libio_free_iop( iop );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the specified flags in the iop.
|
||||
*
|
||||
@@ -184,6 +241,7 @@ static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
|
||||
_Assert( flags >= LIBIO_FLAGS_REFERENCE_INC );
|
||||
|
||||
desired = flags - LIBIO_FLAGS_REFERENCE_INC;
|
||||
|
||||
success = _Atomic_Compare_exchange_uint(
|
||||
&iop->flags,
|
||||
&flags,
|
||||
@@ -199,6 +257,8 @@ static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
|
||||
ATOMIC_ORDER_RELEASE
|
||||
);
|
||||
#endif
|
||||
/* free the IOP is not open or held */
|
||||
rtems_libio_free( iop );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -218,56 +278,83 @@ static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
|
||||
*/
|
||||
|
||||
#define rtems_libio_check_is_open(_iop) \
|
||||
do { \
|
||||
if ((rtems_libio_iop_flags(_iop) & LIBIO_FLAGS_OPEN) == 0) { \
|
||||
errno = EBADF; \
|
||||
return -1; \
|
||||
} \
|
||||
do { \
|
||||
if (rtems_libio_iop_is_open(_iop)) { \
|
||||
errno = EBADF; \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Macro to get the iop for the specified file descriptor.
|
||||
* @brief Function to get the iop for the specified file descriptor.
|
||||
*
|
||||
* Checks that the file descriptor is in the valid range and open.
|
||||
*/
|
||||
static inline int rtems_libio_get_iop( int fd, rtems_libio_t **iop )
|
||||
{
|
||||
unsigned int flags;
|
||||
if ( (uint32_t) ( fd ) >= rtems_libio_number_iops ) {
|
||||
return EBADF;
|
||||
}
|
||||
*iop = rtems_libio_iop( fd );
|
||||
flags = rtems_libio_iop_hold( *iop );
|
||||
if ( rtems_libio_iop_flags_bad_fd( flags ) ) {
|
||||
rtems_libio_iop_drop( *iop );
|
||||
return EBADF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro to get the iop for the specified file descriptor.
|
||||
*/
|
||||
#define LIBIO_GET_IOP( _fd, _iop ) \
|
||||
do { \
|
||||
unsigned int _flags; \
|
||||
if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
|
||||
rtems_set_errno_and_return_minus_one( EBADF ); \
|
||||
} \
|
||||
_iop = rtems_libio_iop( _fd ); \
|
||||
_flags = rtems_libio_iop_hold( _iop ); \
|
||||
if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
|
||||
rtems_libio_iop_drop( _iop ); \
|
||||
rtems_set_errno_and_return_minus_one( EBADF ); \
|
||||
int _error = rtems_libio_get_iop( _fd, &_iop ); \
|
||||
if ( _error != 0 ) { \
|
||||
rtems_set_errno_and_return_minus_one( _error ); \
|
||||
} \
|
||||
} while ( 0 )
|
||||
|
||||
/**
|
||||
* @brief Macro to get the iop for the specified file descriptor with access
|
||||
* flags and error.
|
||||
* @brief Function to get the iop for the specified file descriptor
|
||||
* with access flags and error.
|
||||
*
|
||||
* Checks that the file descriptor is in the valid range and open.
|
||||
*/
|
||||
static inline int rtems_libio_get_iop_with_access(
|
||||
int fd, rtems_libio_t **iop, unsigned int access_flags, int access_error
|
||||
)
|
||||
{
|
||||
const unsigned int mandatory = LIBIO_FLAGS_OPEN | access_flags ;
|
||||
unsigned int flags;
|
||||
if ( (uint32_t) ( fd ) >= rtems_libio_number_iops ) {
|
||||
return EBADF;
|
||||
}
|
||||
*iop = rtems_libio_iop( fd );
|
||||
flags = rtems_libio_iop_hold( *iop );
|
||||
if ( ( flags & mandatory ) != mandatory ) {
|
||||
rtems_libio_iop_drop( *iop );
|
||||
*iop = NULL;
|
||||
if ( ( flags & LIBIO_FLAGS_OPEN ) == 0 ) {
|
||||
return EBADF;
|
||||
} else {
|
||||
return access_error;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Macro to wrap the function to allow returning the IOP and
|
||||
* using the error set and return macro.
|
||||
*/
|
||||
#define LIBIO_GET_IOP_WITH_ACCESS( _fd, _iop, _access_flags, _access_error ) \
|
||||
do { \
|
||||
unsigned int _flags; \
|
||||
unsigned int _mandatory; \
|
||||
if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
|
||||
rtems_set_errno_and_return_minus_one( EBADF ); \
|
||||
} \
|
||||
_iop = rtems_libio_iop( _fd ); \
|
||||
_flags = rtems_libio_iop_hold( _iop ); \
|
||||
_mandatory = LIBIO_FLAGS_OPEN | ( _access_flags ); \
|
||||
if ( ( _flags & _mandatory ) != _mandatory ) { \
|
||||
int _error; \
|
||||
rtems_libio_iop_drop( _iop ); \
|
||||
if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
|
||||
_error = EBADF; \
|
||||
} else { \
|
||||
_error = _access_error; \
|
||||
} \
|
||||
int _error = rtems_libio_get_iop_with_access( \
|
||||
_fd, &_iop, _access_flags, _access_error \
|
||||
); \
|
||||
if ( _error != 0 ) { \
|
||||
rtems_set_errno_and_return_minus_one( _error ); \
|
||||
} \
|
||||
} while ( 0 )
|
||||
@@ -435,34 +522,6 @@ int rtems_filesystem_utime_update(
|
||||
struct timespec new_times[2]
|
||||
);
|
||||
|
||||
/*
|
||||
* File Descriptor Routine Prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
* This routine searches the IOP Table for an unused entry. If it
|
||||
* finds one, it returns it. Otherwise, it returns NULL.
|
||||
*/
|
||||
rtems_libio_t *rtems_libio_allocate(void);
|
||||
|
||||
/**
|
||||
* Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
|
||||
*/
|
||||
unsigned int rtems_libio_fcntl_flags( int fcntl_flags );
|
||||
|
||||
/**
|
||||
* Convert RTEMS internal flags to UNIX fnctl(2) flags
|
||||
*/
|
||||
int rtems_libio_to_fcntl_flags( unsigned int flags );
|
||||
|
||||
/**
|
||||
* This routine frees the resources associated with an IOP (file descriptor)
|
||||
* and clears the slot in the IOP Table.
|
||||
*/
|
||||
void rtems_libio_free(
|
||||
rtems_libio_t *iop
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the number of open iop descriptors
|
||||
*/
|
||||
|
||||
@@ -374,7 +374,7 @@ static inline size_t rtems_rtl_obj_align (size_t offset,
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the symbol in this object's files globa symbol table?
|
||||
* Is the symbol in this object's files global symbol table?
|
||||
*
|
||||
* @param obj The object file's descriptor to search.
|
||||
* @param sym The symbol to check.
|
||||
|
||||
@@ -97,6 +97,15 @@ bool rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
|
||||
*/
|
||||
void rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols);
|
||||
|
||||
/**
|
||||
* Insert a symbol into a symbol table.
|
||||
*
|
||||
* @param symbols Symbol table
|
||||
* @param symbols Symbol to add
|
||||
*/
|
||||
void rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
|
||||
rtems_rtl_obj_sym* symbol);
|
||||
|
||||
/**
|
||||
* Add a table of exported symbols to the symbol table.
|
||||
*
|
||||
|
||||
@@ -63,8 +63,11 @@ int close(
|
||||
rtems_set_errno_and_return_minus_one( EBADF );
|
||||
}
|
||||
|
||||
/* The expected flags */
|
||||
flags &= LIBIO_FLAGS_REFERENCE_INC - 1U;
|
||||
/* The expected flags depends on close when busy flag. If set
|
||||
* there can be references held when calling the close handler */
|
||||
if ( ( flags & LIBIO_FLAGS_CLOSE_BUSY ) == 0 ) {
|
||||
flags &= LIBIO_FLAGS_FLAGS_MASK;
|
||||
}
|
||||
|
||||
desired = flags & ~LIBIO_FLAGS_OPEN;
|
||||
success = _Atomic_Compare_exchange_uint(
|
||||
@@ -79,7 +82,7 @@ int close(
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ( flags & ~( LIBIO_FLAGS_REFERENCE_INC - 1U ) ) != 0 ) {
|
||||
if ( ( flags & LIBIO_FLAGS_REFERENCE_MASK ) != 0 ) {
|
||||
rtems_set_errno_and_return_minus_one( EBUSY );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ static int duplicate_iop( rtems_libio_t *iop )
|
||||
rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo );
|
||||
rtems_filesystem_instance_unlock( &iop->pathinfo );
|
||||
|
||||
rtems_libio_iop_flags_set( diop, rtems_libio_fcntl_flags( oflag ) );
|
||||
rtems_libio_iop_flags_set( diop, rtems_libio_from_fcntl_flags( oflag ) );
|
||||
/*
|
||||
* XXX: We call the open handler here to have a proper open and close pair.
|
||||
*
|
||||
@@ -99,7 +99,7 @@ static int duplicate2_iop( rtems_libio_t *iop, int fd2 )
|
||||
|
||||
if (rv == 0) {
|
||||
oflag = rtems_libio_to_fcntl_flags( rtems_libio_iop_flags( iop ) );
|
||||
rtems_libio_iop_flags_set( iop2, rtems_libio_fcntl_flags( oflag ) );
|
||||
rtems_libio_iop_flags_set( iop2, rtems_libio_from_fcntl_flags( oflag ) );
|
||||
|
||||
rtems_filesystem_instance_lock( &iop->pathinfo );
|
||||
rtems_filesystem_location_clone( &iop2->pathinfo, &iop->pathinfo );
|
||||
@@ -177,7 +177,7 @@ static int vfcntl(
|
||||
break;
|
||||
|
||||
case F_SETFL:
|
||||
flags = rtems_libio_fcntl_flags( va_arg( ap, int ) );
|
||||
flags = rtems_libio_from_fcntl_flags( va_arg( ap, int ) );
|
||||
mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND;
|
||||
|
||||
/*
|
||||
@@ -226,7 +226,10 @@ static int vfcntl(
|
||||
|
||||
if (ret >= 0) {
|
||||
int err = (*iop->pathinfo.handlers->fcntl_h)( iop, cmd );
|
||||
if (err) {
|
||||
if (err == 0 && !rtems_libio_iop_is_open( iop ) ) {
|
||||
err = EBADF;
|
||||
}
|
||||
if (err != 0) {
|
||||
errno = err;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
@@ -43,8 +43,10 @@
|
||||
|
||||
void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc )
|
||||
{
|
||||
rtems_filesystem_instance_lock( loc );
|
||||
(*loc->mt_entry->ops->freenod_h)( loc );
|
||||
rtems_filesystem_instance_unlock( loc );
|
||||
rtems_filesystem_location_remove_from_mt_entry( loc );
|
||||
if ( loc->mt_entry != NULL ) {
|
||||
rtems_filesystem_instance_lock( loc );
|
||||
(*loc->mt_entry->ops->freenod_h)( loc );
|
||||
rtems_filesystem_instance_unlock( loc );
|
||||
rtems_filesystem_location_remove_from_mt_entry( loc );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,10 @@ int fstat(
|
||||
memset( sbuf, 0, sizeof(struct stat) );
|
||||
|
||||
rv = (*iop->pathinfo.handlers->fstat_h)( &iop->pathinfo, sbuf );
|
||||
if (rv == 0 && !rtems_libio_iop_is_open( iop ) ) {
|
||||
errno = EBADF;
|
||||
rv = -1;
|
||||
}
|
||||
rtems_libio_iop_drop( iop );
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ static const rtems_assoc_t status_flags_assoc[] = {
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
unsigned int rtems_libio_fcntl_flags( int fcntl_flags )
|
||||
unsigned int rtems_libio_from_fcntl_flags( int fcntl_flags )
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
uint32_t access_modes;
|
||||
@@ -136,6 +136,8 @@ rtems_libio_t *rtems_libio_allocate( void )
|
||||
if ( iop != NULL ) {
|
||||
void *next;
|
||||
|
||||
rtems_libio_iop_flags_clear( iop, LIBIO_FLAGS_FREE );
|
||||
|
||||
next = iop->data1;
|
||||
rtems_libio_iop_free_head = next;
|
||||
|
||||
@@ -149,30 +151,32 @@ rtems_libio_t *rtems_libio_allocate( void )
|
||||
return iop;
|
||||
}
|
||||
|
||||
void rtems_libio_free(
|
||||
void rtems_libio_free_iop(
|
||||
rtems_libio_t *iop
|
||||
)
|
||||
{
|
||||
size_t zero;
|
||||
|
||||
rtems_filesystem_location_free( &iop->pathinfo );
|
||||
|
||||
rtems_libio_lock();
|
||||
|
||||
/*
|
||||
* Clear everything except the reference count part. At this point in time
|
||||
* there may be still some holders of this file descriptor.
|
||||
*/
|
||||
rtems_libio_iop_flags_clear( iop, LIBIO_FLAGS_REFERENCE_INC - 1U );
|
||||
zero = offsetof( rtems_libio_t, offset );
|
||||
memset( (char *) iop + zero, 0, sizeof( *iop ) - zero );
|
||||
if ( !rtems_libio_iop_is_free( iop ) ) {
|
||||
/*
|
||||
* Clear the flags. All references should have been dropped.
|
||||
*/
|
||||
_Atomic_Store_uint( &iop->flags, LIBIO_FLAGS_FREE, ATOMIC_ORDER_RELAXED );
|
||||
|
||||
/*
|
||||
* Append it to the free list. This increases the likelihood that a use
|
||||
* after close is detected.
|
||||
*/
|
||||
*rtems_libio_iop_free_tail = iop;
|
||||
rtems_libio_iop_free_tail = &iop->data1;
|
||||
rtems_filesystem_location_free( &iop->pathinfo );
|
||||
|
||||
zero = offsetof( rtems_libio_t, offset );
|
||||
memset( (char *) iop + zero, 0, sizeof( *iop ) - zero );
|
||||
|
||||
/*
|
||||
* Append it to the free list. This increases the likelihood that
|
||||
* a use after close is detected.
|
||||
*/
|
||||
*rtems_libio_iop_free_tail = iop;
|
||||
rtems_libio_iop_free_tail = &iop->data1;
|
||||
}
|
||||
|
||||
rtems_libio_unlock();
|
||||
}
|
||||
|
||||
@@ -72,8 +72,10 @@ static void rtems_libio_init( void )
|
||||
if (rtems_libio_number_iops > 0)
|
||||
{
|
||||
iop = rtems_libio_iop_free_head = &rtems_libio_iops[0];
|
||||
for (i = 0 ; (i + 1) < rtems_libio_number_iops ; i++, iop++)
|
||||
for (i = 0 ; (i + 1) < rtems_libio_number_iops ; i++, iop++) {
|
||||
rtems_libio_iop_flags_set( iop, LIBIO_FLAGS_FREE );
|
||||
iop->data1 = iop + 1;
|
||||
}
|
||||
iop->data1 = NULL;
|
||||
rtems_libio_iop_free_tail = &iop->data1;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ static int do_open(
|
||||
rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo );
|
||||
rtems_filesystem_eval_path_cleanup( &ctx );
|
||||
|
||||
rtems_libio_iop_flags_set( iop, rtems_libio_fcntl_flags( oflag ) );
|
||||
rtems_libio_iop_flags_set( iop, rtems_libio_from_fcntl_flags( oflag ) );
|
||||
|
||||
rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode );
|
||||
|
||||
@@ -168,10 +168,6 @@ static int do_open(
|
||||
}
|
||||
}
|
||||
|
||||
if ( rv < 0 ) {
|
||||
rtems_libio_free( iop );
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -192,6 +188,9 @@ int open( const char *path, int oflag, ... )
|
||||
iop = rtems_libio_allocate();
|
||||
if ( iop != NULL ) {
|
||||
rv = do_open( iop, path, oflag, mode );
|
||||
if ( rv < 0 ) {
|
||||
rtems_libio_free( iop );
|
||||
}
|
||||
} else {
|
||||
errno = ENFILE;
|
||||
rv = -1;
|
||||
|
||||
@@ -53,11 +53,11 @@ const rtems_assoc_t rtems_termios_baud_table [] = {
|
||||
{ "B1800", 1800, B1800 },
|
||||
{ "B2400", 2400, B2400 },
|
||||
{ "B4800", 4800, B4800 },
|
||||
{ "B7200", 7200, B7200 },
|
||||
{ "B9600", 9600, B9600 },
|
||||
{ "B14400", 14400, B14400 },
|
||||
{ "B19200", 19200, B19200 },
|
||||
{ "B38400", 38400, B38400 },
|
||||
{ "B7200", 7200, B7200 },
|
||||
{ "B14400", 14400, B14400 },
|
||||
{ "B28800", 28800, B28800 },
|
||||
{ "B57600", 57600, B57600 },
|
||||
{ "B76800", 76800, B76800 },
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/score/smp.h>
|
||||
#include <rtems/score/tls.h>
|
||||
|
||||
#include <rtems/rtems-debugger.h>
|
||||
#include <rtems/debugger/rtems-debugger-server.h>
|
||||
@@ -696,6 +697,25 @@ remote_packet_out_append_hex(const uint8_t* data, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* output data in big-endian instead of little-endian */
|
||||
static int
|
||||
remote_packet_out_append_hex_be(const uint8_t* data, size_t size)
|
||||
{
|
||||
size_t ol = rtems_debugger->output_level;
|
||||
size_t i = size;
|
||||
while (i > 0) {
|
||||
uint8_t byte = data[--i];
|
||||
if (rtems_debugger->output_level >= (RTEMS_DEBUGGER_BUFFER_SIZE - 2)) {
|
||||
rtems_debugger->output_level = ol;
|
||||
rtems_debugger_printf("rtems-db: output overflow\n");
|
||||
return -1;
|
||||
}
|
||||
rtems_debugger->output[rtems_debugger->output_level++] = hex_encode(byte >> 4);
|
||||
rtems_debugger->output[rtems_debugger->output_level++] = hex_encode(byte);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_packet_out_append_str(const char* str)
|
||||
{
|
||||
@@ -1019,6 +1039,116 @@ remote_gq_attached(uint8_t* buffer, int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rtems_debugger_thread* get_debugger_thread_from_id(const char* thread_id)
|
||||
{
|
||||
int r;
|
||||
DB_UINT pid = 0;
|
||||
DB_UINT tid = 0;
|
||||
bool extended;
|
||||
rtems_debugger_threads* threads = rtems_debugger->threads;
|
||||
rtems_debugger_thread* current;
|
||||
|
||||
extended = thread_id_decode(thread_id, &pid, &tid);
|
||||
if (!extended && !check_pid(pid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = rtems_debugger_thread_find_index(tid);
|
||||
if (r < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
current = rtems_debugger_thread_current(threads);
|
||||
return ¤t[r];
|
||||
}
|
||||
|
||||
static int
|
||||
parse_get_tls_addr(
|
||||
uint8_t* buffer,
|
||||
int size,
|
||||
const char** thread_id_str,
|
||||
const char** offset_str,
|
||||
const char** lm_str
|
||||
)
|
||||
{
|
||||
if (thread_id_str == NULL || offset_str == NULL || lm_str == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
*thread_id_str = strchr((const char*) buffer, ':') + 1;
|
||||
if (*thread_id_str == NULL || *thread_id_str - (char*)buffer > size) {
|
||||
/* malformed packet */
|
||||
return 1;
|
||||
}
|
||||
|
||||
*offset_str = strchr(*thread_id_str, ',') + 1;
|
||||
if (*offset_str == NULL || *offset_str - (char*)buffer > size) {
|
||||
/* malformed packet */
|
||||
return 1;
|
||||
}
|
||||
|
||||
*lm_str = strchr(*offset_str, ',') + 1;
|
||||
if (*lm_str == NULL || *lm_str - (char*)buffer > size) {
|
||||
/* malformed packet */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remote_gq_get_tls_addr(uint8_t* buffer, int size)
|
||||
{
|
||||
const char* thread_id_str;
|
||||
const char* offset_str;
|
||||
const char* lm_str;
|
||||
uint64_t target_address;
|
||||
int r;
|
||||
rtems_debugger_thread* thread;
|
||||
DB_UINT offset;
|
||||
DB_UINT lm;
|
||||
|
||||
if (parse_get_tls_addr(buffer, size, &thread_id_str, &offset_str, &lm_str)) {
|
||||
/* malformed packet */
|
||||
remote_packet_out_str(r_E01);
|
||||
remote_packet_out_send();
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = hex_decode_uint((const uint8_t*) offset_str);
|
||||
lm = hex_decode_uint((const uint8_t*) lm_str);
|
||||
if (lm != 0) {
|
||||
/*
|
||||
* TODO(kmoore) lm is the load module identifier. It is ignored and expected
|
||||
* to be 0 until TLS support for dynamically loaded modules is added.
|
||||
*/
|
||||
remote_packet_out_str(r_E01);
|
||||
remote_packet_out_send();
|
||||
return 0;
|
||||
}
|
||||
|
||||
thread = get_debugger_thread_from_id(thread_id_str);
|
||||
if (thread == NULL) {
|
||||
remote_packet_out_str(r_E01);
|
||||
remote_packet_out_send();
|
||||
return 0;
|
||||
}
|
||||
|
||||
target_address =
|
||||
(uintptr_t)_CPU_Get_TLS_thread_pointer(&thread->tcb->Registers);
|
||||
target_address += sizeof(TLS_Thread_control_block) + offset;
|
||||
|
||||
remote_packet_out_reset();
|
||||
r = remote_packet_out_append_hex_be((const uint8_t*) &target_address,
|
||||
sizeof(target_address));
|
||||
|
||||
if (r < 0) {
|
||||
remote_packet_out_str(r_E01);
|
||||
}
|
||||
remote_packet_out_send();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const rtems_debugger_packet general_query[] = {
|
||||
{ .label = "qfThreadInfo",
|
||||
.command = remote_gq_thread_info_first },
|
||||
@@ -1032,6 +1162,8 @@ static const rtems_debugger_packet general_query[] = {
|
||||
.command = remote_gq_attached },
|
||||
{ .label = "qXfer",
|
||||
.command = remote_gq_uninterpreted_transfer },
|
||||
{ .label = "qGetTLSAddr",
|
||||
.command = remote_gq_get_tls_addr },
|
||||
};
|
||||
|
||||
#define REMOTE_GENERAL_QUERIES RTEMS_DEBUGGER_NUMOF(general_query)
|
||||
|
||||
@@ -601,14 +601,6 @@ rtems_debugger_target_exception_thread_resume(rtems_debugger_thread* thread)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rtems_debugger_target_start_memory_access(void)
|
||||
{
|
||||
rtems_debugger_target* target = rtems_debugger->target;
|
||||
target->memory_access = true;
|
||||
return setjmp(target->access_return);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_debugger_target_end_memory_access(void)
|
||||
{
|
||||
|
||||
@@ -284,8 +284,20 @@ extern int rtems_debugger_target_cache_sync(rtems_debugger_target_swbreak* swbre
|
||||
/**
|
||||
* Start a target memory access. If 0 is return the access can proceed and if
|
||||
* -1 is return the access has failed.
|
||||
*
|
||||
* The call to setjmp() must not reside inside a stack frame relative to the
|
||||
* expected location of the possible failure. If the debugger is already
|
||||
* executing in exception context and setjmp is called with its own stack frame,
|
||||
* that stack frame will be released before the failure. The failure causes an
|
||||
* exception which will continue using the same stack and is highly likely to
|
||||
* overwrite stack information which is critical for the debugger to continue
|
||||
* execution.
|
||||
*/
|
||||
extern int rtems_debugger_target_start_memory_access(void);
|
||||
#define rtems_debugger_target_start_memory_access() \
|
||||
({ \
|
||||
rtems_debugger->target->memory_access = true, \
|
||||
setjmp(rtems_debugger->target->access_return); \
|
||||
})
|
||||
|
||||
/**
|
||||
* End a target memory access.
|
||||
|
||||
@@ -557,6 +557,8 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
|
||||
resolved = rtems_rtl_elf_find_symbol (obj,
|
||||
&sym, symname,
|
||||
&symbol, &symvalue);
|
||||
if (symname != NULL && strlen(symname) == 0)
|
||||
resolved = true;
|
||||
|
||||
if (!handler (obj,
|
||||
is_rela, relbuf, targetsect,
|
||||
|
||||
@@ -315,6 +315,10 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
|
||||
return rtems_rtl_elf_rel_failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Align tramp_brk as necessary.
|
||||
*/
|
||||
obj->tramp_brk = (void *)RTEMS_ALIGN_UP((uintptr_t)obj->tramp_brk, 4);
|
||||
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
|
||||
obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
|
||||
|
||||
@@ -519,6 +523,10 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
|
||||
return rtems_rtl_elf_rel_failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Align tramp_brk as necessary.
|
||||
*/
|
||||
obj->tramp_brk = (void *)RTEMS_ALIGN_UP((uintptr_t)obj->tramp_brk, 4);
|
||||
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
|
||||
tmp = tramp_addr + addend;
|
||||
if (isThumb(symvalue)) {
|
||||
@@ -526,11 +534,9 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
|
||||
tmp = tmp - (Elf_Addr)where;
|
||||
} else {
|
||||
/*
|
||||
* The B[L]X expects ARM code at the target. Align tramp_brk as
|
||||
* necessary.
|
||||
*/
|
||||
obj->tramp_brk = (void *)RTEMS_ALIGN_UP((uintptr_t)obj->tramp_brk, 4);
|
||||
tramp_addr = (Elf_Addr) obj->tramp_brk;
|
||||
* The B[L]X expects ARM code at the target.
|
||||
*/
|
||||
tramp_addr = (Elf_Addr) obj->tramp_brk;
|
||||
obj->tramp_brk = set_arm_veneer(obj->tramp_brk, symvalue);
|
||||
/*
|
||||
* where[1:0] are set to 0 for ARM-targeted relocations because the jump
|
||||
|
||||
@@ -48,16 +48,6 @@
|
||||
#include <rtems/rtl/rtl-sym.h>
|
||||
#include <rtems/rtl/rtl-trace.h>
|
||||
|
||||
/**
|
||||
* The single symbol forced into the global symbol table that is used to load a
|
||||
* symbol table from an object file.
|
||||
*/
|
||||
static rtems_rtl_obj_sym global_sym_add =
|
||||
{
|
||||
.name = "rtems_rtl_base_sym_global_add",
|
||||
.value = (void*) rtems_rtl_base_sym_global_add
|
||||
};
|
||||
|
||||
static uint_fast32_t
|
||||
rtems_rtl_symbol_hash (const char *s)
|
||||
{
|
||||
@@ -68,15 +58,6 @@ rtems_rtl_symbol_hash (const char *s)
|
||||
return h & 0xffffffff;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
|
||||
rtems_rtl_obj_sym* symbol)
|
||||
{
|
||||
uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
|
||||
rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
|
||||
&symbol->node);
|
||||
}
|
||||
|
||||
static const rtems_rtl_tls_offset*
|
||||
rtems_rtl_symbol_find_tls_offset (size_t index,
|
||||
const rtems_rtl_tls_offset* tls_offsets,
|
||||
@@ -108,7 +89,6 @@ rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
|
||||
symbols->nbuckets = buckets;
|
||||
for (buckets = 0; buckets < symbols->nbuckets; ++buckets)
|
||||
rtems_chain_initialize_empty (&symbols->buckets[buckets]);
|
||||
rtems_rtl_symbol_global_insert (symbols, &global_sym_add);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -118,6 +98,15 @@ rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols)
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, symbols->buckets);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
|
||||
rtems_rtl_obj_sym* symbol)
|
||||
{
|
||||
uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
|
||||
rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
|
||||
&symbol->node);
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
|
||||
const unsigned char* esyms,
|
||||
|
||||
@@ -562,10 +562,18 @@ rtems_rtl_unresolved_add (rtems_rtl_obj* obj,
|
||||
rtems_rtl_unresolv_block* block;
|
||||
rtems_rtl_unresolv_rec* rec;
|
||||
int name_index;
|
||||
const int name_len = (int) strlen(name);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
|
||||
rtems_rtl_obj_oname (obj), sect, name);
|
||||
printf ("rtl: unresolv: add: %s(s:%d) -> '%s' (len: %i)\n",
|
||||
rtems_rtl_obj_oname (obj), sect, name, name_len);
|
||||
|
||||
/*
|
||||
* No name or an empty name is not able to resolved?
|
||||
*/
|
||||
if (name_len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unresolved = rtems_rtl_unresolved_unprotected ();
|
||||
if (!unresolved)
|
||||
|
||||
@@ -78,17 +78,47 @@
|
||||
static rtems_rtl_data* rtl;
|
||||
static bool rtl_data_init;
|
||||
|
||||
/**
|
||||
* The single symbol forced into the global symbol table that is used to load a
|
||||
* symbol table from an object file.
|
||||
*/
|
||||
static rtems_rtl_obj_sym default_global_syms =
|
||||
{
|
||||
.name = "rtems_rtl_base_sym_global_add",
|
||||
.value = (void*) rtems_rtl_base_sym_global_add
|
||||
};
|
||||
|
||||
/**
|
||||
* Define a default base global symbol loader function that is weak
|
||||
* so a real table can be linked in when the user wants one.
|
||||
*
|
||||
* The default init handler add the one symbol used when loading
|
||||
* symbols with an object file. It is an unresolved external in that
|
||||
* object file.
|
||||
*/
|
||||
void rtems_rtl_base_global_syms_init (void) __attribute__ ((weak));
|
||||
void
|
||||
rtems_rtl_base_global_syms_init (void)
|
||||
{
|
||||
/*
|
||||
* Do nothing.
|
||||
*/
|
||||
rtems_rtl_symbols* symbols;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
|
||||
printf ("rtl: adding default global symbol\n");
|
||||
|
||||
if (!rtems_rtl_lock ())
|
||||
{
|
||||
rtems_rtl_set_error (EINVAL, "global add cannot lock rtl");
|
||||
return;
|
||||
}
|
||||
|
||||
symbols = rtems_rtl_global_symbols ();
|
||||
|
||||
rtl->base->global_table = &default_global_syms;
|
||||
rtl->base->global_syms = 1;
|
||||
|
||||
rtems_rtl_symbol_global_insert (symbols, &default_global_syms);
|
||||
|
||||
rtems_rtl_unlock ();
|
||||
}
|
||||
|
||||
static bool
|
||||
|
||||
@@ -801,9 +801,7 @@ rtems_capture_flush (bool prime)
|
||||
_Thread_Iterate (rtems_capture_flush_tcb, NULL);
|
||||
|
||||
if (prime)
|
||||
capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
|
||||
else
|
||||
capture_flags_global &= ~RTEMS_CAPTURE_OVERFLOW;
|
||||
capture_flags_global &= ~RTEMS_CAPTURE_TRIGGERED;
|
||||
|
||||
for (cpu=0; cpu < rtems_scheduler_get_processor_maximum(); cpu++) {
|
||||
RTEMS_INTERRUPT_LOCK_REFERENCE( lock, &(capture_lock_on_cpu( cpu )) )
|
||||
@@ -811,6 +809,7 @@ rtems_capture_flush (bool prime)
|
||||
|
||||
rtems_interrupt_lock_acquire (lock, &lock_context_per_cpu);
|
||||
capture_count_on_cpu(cpu) = 0;
|
||||
capture_flags_on_cpu(cpu) &= ~RTEMS_CAPTURE_OVERFLOW;
|
||||
if (capture_records_on_cpu(cpu).buffer)
|
||||
rtems_capture_buffer_flush( &capture_records_on_cpu(cpu) );
|
||||
rtems_interrupt_lock_release (lock, &lock_context_per_cpu);
|
||||
|
||||
@@ -45,6 +45,8 @@ extern "C" {
|
||||
#include <rtems/score/riscv.h>
|
||||
|
||||
#define RISCV_MSTATUS_MIE 0x8
|
||||
#define RISCV_MSTATUS_MDT 0x40000000000
|
||||
#define RISCV_MSTATUSH_MDT 0x400
|
||||
|
||||
#define CPU_ISR_PASSES_FRAME_POINTER FALSE
|
||||
|
||||
|
||||
@@ -106,6 +106,20 @@ SYM(_RISCV_Exception_handler):
|
||||
/* Check if this is a synchronous or interrupt exception */
|
||||
bgez a0, .Lsynchronous_exception
|
||||
|
||||
/*
|
||||
* Interrupt exception, clear MDT bit.
|
||||
* This is only necessary if the Smdbltrp extension is implemented.
|
||||
* In that case not clearing the MDT bit would prevent us from setting
|
||||
* the MIE bit later.
|
||||
*/
|
||||
#if __riscv_xlen == 64
|
||||
li t0, RISCV_MSTATUS_MDT
|
||||
csrrc zero, mstatus, t0
|
||||
#elif __riscv_xlen == 32
|
||||
li t0, RISCV_MSTATUSH_MDT
|
||||
csrrc zero, mstatush, t0
|
||||
#endif
|
||||
|
||||
/* Increment interrupt nest and thread dispatch disable level */
|
||||
lw t0, PER_CPU_ISR_NEST_LEVEL(s0)
|
||||
lw t1, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(s0)
|
||||
@@ -185,7 +199,6 @@ SYM(_RISCV_Exception_handler):
|
||||
/* Restore */
|
||||
LREG a0, RISCV_INTERRUPT_FRAME_MSTATUS(sp)
|
||||
LREG a1, RISCV_INTERRUPT_FRAME_MEPC(sp)
|
||||
LREG a2, RISCV_INTERRUPT_FRAME_A2(sp)
|
||||
LREG s0, RISCV_INTERRUPT_FRAME_S0(sp)
|
||||
LREG s1, RISCV_INTERRUPT_FRAME_S1(sp)
|
||||
LREG ra, RISCV_INTERRUPT_FRAME_RA(sp)
|
||||
@@ -201,6 +214,20 @@ SYM(_RISCV_Exception_handler):
|
||||
LREG t4, RISCV_INTERRUPT_FRAME_T4(sp)
|
||||
LREG t5, RISCV_INTERRUPT_FRAME_T5(sp)
|
||||
LREG t6, RISCV_INTERRUPT_FRAME_T6(sp)
|
||||
|
||||
/*
|
||||
* Clear MDT bit before restoring mstatus register.
|
||||
* This is only necessary if the Smdbltrp extension is implemented.
|
||||
* In that case, writing to mstatus with MDT set would clear the MIE
|
||||
* bit, regardless of the MIE value written.
|
||||
* On RV32, the MDT bit is in the mstatush CSR which is not restored.
|
||||
*/
|
||||
#if __riscv_xlen == 64
|
||||
li a2, RISCV_MSTATUS_MDT
|
||||
not a2, a2
|
||||
and a0, a0, a2
|
||||
#endif
|
||||
|
||||
csrw mstatus, a0
|
||||
csrw mepc, a1
|
||||
#if __riscv_flen > 0
|
||||
@@ -229,6 +256,7 @@ SYM(_RISCV_Exception_handler):
|
||||
#endif
|
||||
LREG a0, RISCV_INTERRUPT_FRAME_A0(sp)
|
||||
LREG a1, RISCV_INTERRUPT_FRAME_A1(sp)
|
||||
LREG a2, RISCV_INTERRUPT_FRAME_A2(sp)
|
||||
|
||||
addi sp, sp, CPU_INTERRUPT_FRAME_SIZE
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ install:
|
||||
- bsps/include/grlib/ambapp_bus_grlib.h
|
||||
- bsps/include/grlib/ambapp_ids.h
|
||||
- bsps/include/grlib/apbuart.h
|
||||
- bsps/include/grlib/apbuart-regs.h
|
||||
- bsps/include/grlib/apbuart_cons.h
|
||||
- bsps/include/grlib/apbuart_termios.h
|
||||
- bsps/include/grlib/b1553brm.h
|
||||
@@ -28,6 +29,7 @@ install:
|
||||
- bsps/include/grlib/genirq.h
|
||||
- bsps/include/grlib/gpiolib.h
|
||||
- bsps/include/grlib/gptimer.h
|
||||
- bsps/include/grlib/gptimer-regs.h
|
||||
- bsps/include/grlib/gr1553b.h
|
||||
- bsps/include/grlib/gr1553bc.h
|
||||
- bsps/include/grlib/gr1553bc_list.h
|
||||
@@ -59,6 +61,7 @@ install:
|
||||
- bsps/include/grlib/grtc.h
|
||||
- bsps/include/grlib/grtm.h
|
||||
- bsps/include/grlib/i2cmst.h
|
||||
- bsps/include/grlib/irqamp-regs.h
|
||||
- bsps/include/grlib/l2c.h
|
||||
- bsps/include/grlib/l4stat.h
|
||||
- bsps/include/grlib/mctrl.h
|
||||
|
||||
@@ -15,6 +15,9 @@ install:
|
||||
- destination: ${BSP_INCLUDEDIR}/drvmgr
|
||||
source:
|
||||
- bsps/sparc/include/drvmgr/leon2_amba_bus.h
|
||||
- destination: ${BSP_INCLUDEDIR}/grlib
|
||||
source:
|
||||
- bsps/sparc/include/grlib/io.h
|
||||
ldflags: []
|
||||
links:
|
||||
- role: build-dependency
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2012, 2020 embedded brains GmbH & Co. KG
|
||||
*
|
||||
* Copyright (C) 2025 Contemporary Software
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@@ -44,6 +46,7 @@ const char rtems_test_name[] = "FSCLOSE 1";
|
||||
|
||||
typedef enum {
|
||||
ACTION_CLOSE,
|
||||
ACTION_CLOSE_BUSY,
|
||||
ACTION_FCNTL,
|
||||
ACTION_FDATASYNC,
|
||||
ACTION_FCHDIR,
|
||||
@@ -67,6 +70,7 @@ typedef struct {
|
||||
test_action action;
|
||||
bool wait_in_close;
|
||||
bool wait_in_fstat;
|
||||
bool test_close_busy;
|
||||
int close_count;
|
||||
int fcntl_count;
|
||||
int fdatasync_count;
|
||||
@@ -84,6 +88,16 @@ typedef struct {
|
||||
|
||||
static test_context test_instance;
|
||||
|
||||
static size_t free_iops(void) {
|
||||
size_t count = 0;
|
||||
rtems_libio_t *iop = rtems_libio_iop_free_head;
|
||||
while (iop != NULL) {
|
||||
++count;
|
||||
iop = iop->data1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void wait(void)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
@@ -112,6 +126,10 @@ static int handler_open(
|
||||
ctx = IMFS_generic_get_context_by_iop(iop);
|
||||
++ctx->open_count;
|
||||
|
||||
if (ctx->action == ACTION_CLOSE_BUSY) {
|
||||
iop->flags |= LIBIO_FLAGS_CLOSE_BUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -344,6 +362,12 @@ static void worker_task(rtems_task_argument arg)
|
||||
rv = close(ctx->fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
break;
|
||||
case ACTION_CLOSE_BUSY:
|
||||
ctx->wait_in_fstat = true;
|
||||
rv = fstat(ctx->fd, &st);
|
||||
rtems_test_assert(rv == -1);
|
||||
rtems_test_assert(errno == EBADF);
|
||||
break;
|
||||
case ACTION_FCNTL:
|
||||
rv = fcntl(ctx->fd, F_GETFD);
|
||||
rtems_test_assert(rv >= 0);
|
||||
@@ -418,6 +442,7 @@ static void worker_task(rtems_task_argument arg)
|
||||
|
||||
static void test_fd_free_fifo(const char *path)
|
||||
{
|
||||
const size_t iops_free = free_iops();
|
||||
int a;
|
||||
int b;
|
||||
int rv;
|
||||
@@ -435,10 +460,13 @@ static void test_fd_free_fifo(const char *path)
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rtems_test_assert(a != b);
|
||||
|
||||
rtems_test_assert(iops_free == free_iops());
|
||||
}
|
||||
|
||||
static void test_close(test_context *ctx)
|
||||
{
|
||||
const size_t iops_free = free_iops();
|
||||
const char *path = "generic";
|
||||
int rv;
|
||||
rtems_status_code sc;
|
||||
@@ -483,40 +511,47 @@ static void test_close(test_context *ctx)
|
||||
|
||||
wakeup_worker(ctx);
|
||||
rv = close(ctx->fd);
|
||||
rtems_test_assert(rv == -1);
|
||||
|
||||
if (ac == ACTION_CLOSE) {
|
||||
rtems_test_assert(errno == EBADF);
|
||||
|
||||
flags = rtems_libio_iop_hold(iop);
|
||||
expected_flags = LIBIO_FLAGS_READ_WRITE;
|
||||
rtems_test_assert(flags == expected_flags);
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
expected_flags = LIBIO_FLAGS_REFERENCE_INC | LIBIO_FLAGS_READ_WRITE;
|
||||
rtems_test_assert(flags == expected_flags);
|
||||
} else {
|
||||
rtems_test_assert(errno == EBUSY);
|
||||
switch (ac) {
|
||||
case ACTION_CLOSE:
|
||||
rtems_test_assert(rv == -1);
|
||||
rtems_test_assert(errno == EBADF);
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
expected_flags = LIBIO_FLAGS_READ_WRITE;
|
||||
rtems_test_assert(flags == expected_flags);
|
||||
rtems_test_assert((iops_free - 1) == free_iops());
|
||||
break;
|
||||
case ACTION_CLOSE_BUSY:
|
||||
rtems_test_assert(rv == 0);
|
||||
break;
|
||||
default:
|
||||
rtems_test_assert(rv == -1);
|
||||
rtems_test_assert(errno == EBUSY);
|
||||
break;
|
||||
}
|
||||
|
||||
wakeup_worker(ctx);
|
||||
|
||||
if (ac == ACTION_CLOSE) {
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
expected_flags = LIBIO_FLAGS_REFERENCE_INC;
|
||||
rtems_test_assert(flags == expected_flags);
|
||||
rtems_libio_iop_drop(iop);
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
expected_flags = 0;
|
||||
rtems_test_assert(flags == expected_flags);
|
||||
switch (ac) {
|
||||
case ACTION_CLOSE:
|
||||
rtems_test_assert(rtems_libio_iop_is_free(iop));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rv = close(ctx->fd);
|
||||
|
||||
if (ac == ACTION_CLOSE) {
|
||||
rtems_test_assert(rv == -1);
|
||||
rtems_test_assert(errno == EBADF);
|
||||
} else {
|
||||
rtems_test_assert(rv == 0);
|
||||
rtems_test_assert(iops_free == free_iops());
|
||||
|
||||
switch (ac) {
|
||||
case ACTION_CLOSE:
|
||||
case ACTION_CLOSE_BUSY:
|
||||
rtems_test_assert(rv == -1);
|
||||
rtems_test_assert(errno == EBADF);
|
||||
break;
|
||||
default:
|
||||
rtems_test_assert(rv == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,21 +561,81 @@ static void test_close(test_context *ctx)
|
||||
rv = unlink(path);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rtems_test_assert(ctx->close_count == 17);
|
||||
rtems_test_assert(ctx->close_count == 18);
|
||||
rtems_test_assert(ctx->fcntl_count == 1);
|
||||
rtems_test_assert(ctx->fdatasync_count == 1);
|
||||
rtems_test_assert(ctx->fstat_count == 42);
|
||||
rtems_test_assert(ctx->fstat_count == 45);
|
||||
rtems_test_assert(ctx->fsync_count == 1);
|
||||
rtems_test_assert(ctx->ftruncate_count == 1);
|
||||
rtems_test_assert(ctx->ioctl_count == 1);
|
||||
rtems_test_assert(ctx->lseek_count == 1);
|
||||
rtems_test_assert(ctx->open_count == 17);
|
||||
rtems_test_assert(ctx->open_count == 18);
|
||||
rtems_test_assert(ctx->read_count == 1);
|
||||
rtems_test_assert(ctx->readv_count == 1);
|
||||
rtems_test_assert(ctx->write_count == 1);
|
||||
rtems_test_assert(ctx->writev_count == 1);
|
||||
}
|
||||
|
||||
static void test_iop(test_context *ctx) {
|
||||
const size_t iops_free = free_iops();
|
||||
rtems_libio_t *iop;
|
||||
rtems_libio_t *iop2;
|
||||
unsigned int flags;
|
||||
unsigned int expected;
|
||||
/* test allocatior */
|
||||
iop = rtems_libio_allocate();
|
||||
rtems_test_assert(iop != NULL);
|
||||
rtems_test_assert(iop->flags == 0);
|
||||
iop2 = rtems_libio_allocate();
|
||||
rtems_test_assert(iop2 != NULL);
|
||||
rtems_test_assert(rtems_libio_allocate() == NULL);
|
||||
rtems_libio_free(iop2);
|
||||
rtems_test_assert(iop2->flags == LIBIO_FLAGS_FREE);
|
||||
/* test flags, flag set/clear and bit tests */
|
||||
rtems_test_assert(!rtems_libio_iop_is_open(iop));
|
||||
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_OPEN);
|
||||
rtems_test_assert(rtems_libio_iop_is_open(iop));
|
||||
rtems_test_assert(!rtems_libio_iop_is_no_delay(iop));
|
||||
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_NO_DELAY);
|
||||
rtems_test_assert(rtems_libio_iop_is_no_delay(iop));
|
||||
rtems_test_assert(!rtems_libio_iop_is_readable(iop));
|
||||
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_READ);
|
||||
rtems_test_assert(rtems_libio_iop_is_readable(iop));
|
||||
rtems_test_assert(!rtems_libio_iop_is_writeable(iop));
|
||||
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_WRITE);
|
||||
rtems_test_assert(rtems_libio_iop_is_writeable(iop));
|
||||
rtems_test_assert(!rtems_libio_iop_is_append(iop));
|
||||
rtems_libio_iop_flags_set(iop, LIBIO_FLAGS_APPEND);
|
||||
rtems_test_assert(rtems_libio_iop_is_append(iop));
|
||||
/* test hold and drop and if drop frees the iop */
|
||||
expected =
|
||||
LIBIO_FLAGS_OPEN | LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_READ |
|
||||
LIBIO_FLAGS_WRITE | LIBIO_FLAGS_APPEND;
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
|
||||
rtems_test_assert((flags & LIBIO_FLAGS_REFERENCE_MASK) == 0);
|
||||
flags = rtems_libio_iop_hold(iop);
|
||||
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
rtems_test_assert(
|
||||
(flags & LIBIO_FLAGS_REFERENCE_MASK) == LIBIO_FLAGS_REFERENCE_INC);
|
||||
rtems_libio_free(iop);
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
|
||||
rtems_test_assert(
|
||||
(flags & LIBIO_FLAGS_REFERENCE_MASK) == LIBIO_FLAGS_REFERENCE_INC);
|
||||
rtems_libio_iop_drop(iop);
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
rtems_test_assert((flags & LIBIO_FLAGS_FLAGS_MASK) == expected);
|
||||
rtems_libio_iop_flags_clear(iop, LIBIO_FLAGS_OPEN);
|
||||
rtems_libio_iop_hold(iop);
|
||||
rtems_libio_iop_drop(iop);
|
||||
flags = rtems_libio_iop_flags(iop);
|
||||
rtems_test_assert(flags == LIBIO_FLAGS_FREE);
|
||||
rtems_test_assert(iops_free == free_iops());
|
||||
}
|
||||
|
||||
|
||||
static void test_tmpfile(test_context *ctx)
|
||||
{
|
||||
rtems_resource_snapshot before;
|
||||
@@ -566,6 +661,7 @@ static void test_tmpfile(test_context *ctx)
|
||||
static void Init(rtems_task_argument arg)
|
||||
{
|
||||
TEST_BEGIN();
|
||||
test_iop(&test_instance);
|
||||
test_close(&test_instance);
|
||||
test_tmpfile(&test_instance);
|
||||
TEST_END();
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#define FS_PASS() do {puts("PASS");} while (0)
|
||||
#define FS_FAIL() do {\
|
||||
printf( "FAIL %s: %d \n", __FILE__, __LINE__ );\
|
||||
printf( "FAIL errno=%s %s: %d \n", strerror(errno), __FILE__, __LINE__ );\
|
||||
fs_test_notify_failure(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user