mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-02-26 00:23:16 +01:00
ARM port: Support newlib thread reentrancy with thread-specific struct _reent. Tested on qemu_integratorcp.
This commit is contained in:
@@ -43,6 +43,10 @@
|
||||
|
||||
.extern __interrupt_dispatcher
|
||||
|
||||
/* When using newlib, reentrancy context needs to be updated on task switch */
|
||||
.extern _impure_ptr
|
||||
|
||||
|
||||
/**/
|
||||
.equ USR_MODE, 0x10
|
||||
.equ FIQ_MODE, 0x11
|
||||
@@ -80,6 +84,10 @@
|
||||
archContextSwitch:
|
||||
STMFD sp!, {r4 - r11, lr} /* Save registers */
|
||||
|
||||
ADD r4, r1, #4 /* Add offset to get address of new_tcb_ptr->reent context (second TCB element) */
|
||||
LDR r5, = _impure_ptr /* Get address of _impure_ptr into r5 */
|
||||
STR r4, [r5] /* Store new_tcb_ptr->reent context in _impure_ptr */
|
||||
|
||||
STR sp, [r0] /* Save old SP in old_tcb_ptr->sp_save_ptr (first TCB element) */
|
||||
LDR r1, [r1] /* Load new SP from new_tcb_ptr->sp_save_ptr (first TCB element) */
|
||||
MOV sp, r1
|
||||
@@ -120,6 +128,11 @@ archContextSwitch:
|
||||
* void archFirstThreadRestore (ATOM_TCB *new_tcb_ptr)
|
||||
*/
|
||||
archFirstThreadRestore:
|
||||
|
||||
ADD r4, r0, #4 /* Add offset to get address of new_tcb_ptr->reent context (second TCB element) */
|
||||
LDR r5, = _impure_ptr /* Get address of _impure_ptr into r5 */
|
||||
STR r4, [r5] /* Store new_tcb_ptr->reent context in _impure_ptr */
|
||||
|
||||
LDR r0, [r0] /* Get SP (sp_save_ptr is conveniently first element of TCB) */
|
||||
MOV sp, r0 /* Load new stack pointer */
|
||||
LDMFD sp!, {r4 - r11, pc} /* Load new registers */
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/reent.h>
|
||||
|
||||
#include "atom.h"
|
||||
#include "atomport.h"
|
||||
|
||||
@@ -68,6 +72,13 @@ static void thread_shell (void)
|
||||
/* Get the TCB of the thread being started */
|
||||
curr_tcb = atomCurrentContext();
|
||||
|
||||
/**
|
||||
* Open a stdout file descriptor so that the thread has its own stdout.
|
||||
* In theory threads could open stdout to different output drivers
|
||||
* if syscalls.s supported different output write functions.
|
||||
*/
|
||||
stdout = fopen ("/debuguart", "w");
|
||||
|
||||
/**
|
||||
* Enable interrupts - these will not be enabled when a thread
|
||||
* is first restored.
|
||||
@@ -80,6 +91,9 @@ static void thread_shell (void)
|
||||
curr_tcb->entry_point(curr_tcb->entry_param);
|
||||
}
|
||||
|
||||
/* Clean up after thread completion */
|
||||
_reclaim_reent (&(curr_tcb->port_priv.reent));
|
||||
|
||||
/* Thread has run to completion: remove it from the ready list */
|
||||
curr_tcb->suspended = TRUE;
|
||||
atomSched (FALSE);
|
||||
@@ -153,5 +167,10 @@ void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_poi
|
||||
*/
|
||||
tcb_ptr->sp_save_ptr = stack_ptr;
|
||||
|
||||
/**
|
||||
* At thread startup (and every time we switch back to a thread)
|
||||
* we set the global reentrancy pointer to this thread's reent struct
|
||||
*/
|
||||
_REENT_INIT_PTR (&(tcb_ptr->port_priv.reent));
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
/* Definition of NULL is available from stddef.h on this platform */
|
||||
#include <stddef.h>
|
||||
|
||||
/* Reentrancy structure */
|
||||
#include <sys/reent.h>
|
||||
|
||||
/* Required number of system ticks per second (normally 100 for 10ms tick) */
|
||||
#define SYSTEM_TICKS_PER_SEC 100
|
||||
|
||||
@@ -83,6 +86,15 @@ extern void contextExitCritical (uint32_t posture) ;
|
||||
#define CRITICAL_START() __atom_critical = contextEnterCritical()
|
||||
#define CRITICAL_END() contextExitCritical(__atom_critical)
|
||||
|
||||
/**
|
||||
* When using newlib, define port private field in atom_tcb to be a
|
||||
* struct _reent.
|
||||
*/
|
||||
struct arm_port_priv {
|
||||
struct _reent reent;
|
||||
};
|
||||
#define THREAD_PORT_PRIV struct arm_port_priv port_priv
|
||||
|
||||
/* Uncomment to enable stack-checking */
|
||||
/* #define ATOM_STACK_CHECKING */
|
||||
|
||||
|
||||
@@ -123,10 +123,17 @@ int _lseek(int file, int ptr, int dir)
|
||||
*
|
||||
* Simple stub implementation with no file table. All parameters ignored.
|
||||
*
|
||||
* We only support reading/writing to the UART, so we don't bother inspecting
|
||||
* the filename to decide which underlying device to use, _read() and _write()
|
||||
* only access the UART driver.
|
||||
*
|
||||
* This is currently only called once (each thread opens its own stdout when
|
||||
* it starts executing).
|
||||
*
|
||||
*/
|
||||
int _open(const char *name, int flags, int mode)
|
||||
{
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user