mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-01-12 10:53:15 +01:00
interrupt request updated.
started multicore support.
This commit is contained in:
@@ -85,7 +85,7 @@ thread_shell (void)
|
||||
* is first restored.
|
||||
*/
|
||||
// sei();
|
||||
atomvmExitCritical (the_atomvm) ;
|
||||
atomvmExitCritical () ;
|
||||
|
||||
/* Call the thread entry point */
|
||||
if (curr_tcb && curr_tcb->entry_point)
|
||||
@@ -110,7 +110,7 @@ archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(u
|
||||
tcb_ptr->entry_param = entry_param ;
|
||||
tcb_ptr->entry_point = entry_point ;
|
||||
|
||||
atomvmContextCreate (the_atomvm, &tcb_ptr->context, (unsigned int )stack_top, (unsigned int )thread_shell) ;
|
||||
atomvmContextCreate (&tcb_ptr->context, (unsigned int )stack_top, (unsigned int )thread_shell) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(u
|
||||
void
|
||||
archFirstThreadRestore(ATOM_TCB * p_sp_new)
|
||||
{
|
||||
atomvmContextSwitch (the_atomvm, p_sp_new->context) ;
|
||||
atomvmContextSwitch (0, p_sp_new->context) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ archFirstThreadRestore(ATOM_TCB * p_sp_new)
|
||||
void
|
||||
archContextSwitch (ATOM_TCB * p_sp_old, ATOM_TCB * p_sp_new)
|
||||
{
|
||||
atomvmContextSwitch (the_atomvm, p_sp_new->context) ;
|
||||
atomvmContextSwitch (p_sp_old->context, p_sp_new->context) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -161,12 +161,12 @@ void archTimerTickIrqHandler ()
|
||||
unsigned int
|
||||
__enter_critical ()
|
||||
{
|
||||
return atomvmEnterCritical (the_atomvm) ;
|
||||
return atomvmEnterCritical () ;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__exit_critical (unsigned int isr)
|
||||
{
|
||||
atomvmExitCritical (the_atomvm) ;
|
||||
atomvmExitCritical () ;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,43 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Atom Virtual Machine.
|
||||
*
|
||||
*
|
||||
* This module implements the virtual machine.
|
||||
*
|
||||
*
|
||||
* \b Functions contained in this module:\n
|
||||
*
|
||||
* \b Function prototypes used for controlling the atom virtual machine: \n
|
||||
*
|
||||
* \li atomvmCtrlInit(): .
|
||||
* \li atomvmCtrlRun(): .
|
||||
* \li atomvmCtrlIntRequest(): .
|
||||
* \li atomvmCtrlClose(): .
|
||||
*
|
||||
* \b Function prototypes for use by the atom virtual machine: \n
|
||||
*
|
||||
* \li atomvmExitCritical(): .
|
||||
* \li atomvmEnterCritical(): .
|
||||
* \li atomvmContextCreate(): .
|
||||
* \li atomvmContextSwitch(): .
|
||||
* \li atomvmContextDesrtroy(): .
|
||||
*
|
||||
* \b Function prototypes to be implemted in the atom virtual machine: \n
|
||||
*
|
||||
* \li __atomvmReset(): .
|
||||
* \li __atomvmClose(): .
|
||||
*
|
||||
*/
|
||||
|
||||
#include "atomvm.h"
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
|
||||
#define CONTEXT_VM (CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS)
|
||||
|
||||
@@ -70,6 +105,31 @@ typedef struct ATOMVM_CALLBACK_CONTEXT_S {
|
||||
|
||||
} ATOMVM_CALLBACK_CONTEXT, *PATOMVM_CALLBACK_CONTEXT ;
|
||||
|
||||
|
||||
/* ATOMVM_CALLBACK_CONTEXT_SWITCH is the parameter for a ATOMVM_CALLBACK_F call
|
||||
that take as parameter a pointer to a ATOMVM_CONTEXT to operate on */
|
||||
typedef struct ATOMVM_CALLBACK_CONTEXT_SWITCH_S {
|
||||
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
/* Context the callback function will operate on */
|
||||
volatile PATOMVM_CONTEXT p_old_context ;
|
||||
volatile PATOMVM_CONTEXT p_new_context ;
|
||||
|
||||
} ATOMVM_CALLBACK_CONTEXT_SWITCH, *PATOMVM_CALLBACK_CONTEXT_SWITCH ;
|
||||
|
||||
/* ATOMVM_CALLBACK_IPI is the parameter for a ATOMVM_CALLBACK_F call
|
||||
that take as parameter a pointer to a ipi target and the isr to call */
|
||||
typedef struct ATOMVM_CALLBACK_IPI_S {
|
||||
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
/* Parameters the callback function will operate on */
|
||||
volatile uint32_t target ;
|
||||
volatile uint32_t isr ;
|
||||
|
||||
} ATOMVM_CALLBACK_IPI, *PATOMVM_CALLBACK_IPI ;
|
||||
|
||||
typedef struct ATOMVM_PERF_COUNTERS_S {
|
||||
|
||||
/* Number of interrupt requests */
|
||||
@@ -98,6 +158,7 @@ typedef struct ATOMVM_CONTEXT_S {
|
||||
and atomvmEnterCritical() will respectively decrement and
|
||||
increment the critical count */
|
||||
volatile uint32_t critical_count ;
|
||||
uint32_t thread_id ;
|
||||
|
||||
} ATOMVM_CONTEXT, *PATOMVM_CONTEXT ;
|
||||
|
||||
@@ -105,6 +166,8 @@ typedef struct ATOMVM_CONTEXT_S {
|
||||
by a call to atomvmCtrlInit(). */
|
||||
typedef struct ATOMVM_S {
|
||||
|
||||
uint32_t atomvm_id ;
|
||||
|
||||
/* Thread the virtual machine will run in */
|
||||
HANDLE vm_thread ;
|
||||
|
||||
@@ -138,11 +201,19 @@ typedef struct ATOMVM_S {
|
||||
} ATOMVM, *PATOMVM ;
|
||||
|
||||
|
||||
/* Global declarations */
|
||||
volatile uint32_t g_atomvm_counter = 0 ;
|
||||
HANDLE g_atomvm_event = 0 ;
|
||||
DWORD g_atomvm_tls_idx ;
|
||||
PATOMVM g_vms[ATOMVM_MAX_VM] ;
|
||||
|
||||
|
||||
/* Forward declaration for the atom virtual machine thread */
|
||||
static DWORD WINAPI vm_thread (LPVOID lpParameter) ;
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCtrlInit
|
||||
*
|
||||
* This is an atomvm controll function used by a controlling thread
|
||||
@@ -159,24 +230,41 @@ static DWORD WINAPI vm_thread (LPVOID lpParameter) ;
|
||||
uint32_t
|
||||
atomvmCtrlInit (HATOMVM *atomvm)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) malloc (sizeof(struct ATOMVM_S)) ;
|
||||
PATOMVM patomvm = 0 ;
|
||||
int32_t i ;
|
||||
|
||||
if (patomvm) {
|
||||
if (g_atomvm_counter < ATOMVM_MAX_VM) {
|
||||
|
||||
memset (patomvm, 0, sizeof(struct ATOMVM_S)) ;
|
||||
patomvm = (PATOMVM) malloc (sizeof(struct ATOMVM_S)) ;
|
||||
|
||||
patomvm->atomvm_call = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int_complete = CreateEvent (NULL, FALSE, TRUE, 0) ;
|
||||
patomvm->atomvm_close = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
if (patomvm) {
|
||||
|
||||
patomvm->vm_thread = CreateThread (NULL, 0, vm_thread, 0, CREATE_SUSPENDED, NULL) ;
|
||||
memset (patomvm, 0, sizeof(struct ATOMVM_S)) ;
|
||||
|
||||
patomvm->atom_init_context.critical_count = 1 ;
|
||||
patomvm->current_context = &patomvm->atom_init_context ;
|
||||
patomvm->atomvm_id = InterlockedIncrement(&g_atomvm_counter) - 1 ;
|
||||
|
||||
*atomvm = (HATOMVM)patomvm ;
|
||||
if (patomvm->atomvm_id == 0) {
|
||||
g_atomvm_event = CreateEvent (NULL, FALSE, FALSE, 0) ;
|
||||
g_atomvm_tls_idx = TlsAlloc () ;
|
||||
for (i=0; i<ATOMVM_MAX_VM; i++) {
|
||||
g_vms[i] = 0 ;
|
||||
}
|
||||
}
|
||||
g_vms[patomvm->atomvm_id] = patomvm ;
|
||||
|
||||
patomvm->atomvm_call = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
patomvm->atomvm_int_complete = CreateEvent (NULL, FALSE, TRUE, 0) ;
|
||||
patomvm->atomvm_close = CreateEvent (NULL, TRUE, FALSE, 0) ;
|
||||
|
||||
patomvm->vm_thread = CreateThread (NULL, 0, vm_thread, (void*)patomvm, CREATE_SUSPENDED, NULL) ;
|
||||
|
||||
patomvm->atom_init_context.critical_count = 1 ;
|
||||
patomvm->current_context = &patomvm->atom_init_context ;
|
||||
|
||||
*atomvm = (HATOMVM)patomvm ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return patomvm != 0 ;
|
||||
@@ -184,6 +272,7 @@ atomvmCtrlInit (HATOMVM *atomvm)
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCtrlRun
|
||||
*
|
||||
* This is an atomvm controll function used by a controlling thread
|
||||
@@ -207,6 +296,13 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
uint32_t res ;
|
||||
uint32_t wait_object ;
|
||||
PATOMVM_CALLBACK service_call ;
|
||||
#if defined DEBUG || defined _DEBUG
|
||||
BOOL tls_res =
|
||||
#endif
|
||||
TlsSetValue (g_atomvm_tls_idx, (void*) atomvm) ;
|
||||
|
||||
|
||||
ATOMVM_ASSERT(tls_res, _T("TlsSetValue failed")) ;
|
||||
|
||||
ResumeThread (patomvm->vm_thread) ;
|
||||
|
||||
@@ -240,6 +336,7 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
ResetEvent (patomvm->atomvm_call) ;
|
||||
res = ResumeThread (patomvm->vm_thread) ;
|
||||
ATOMVM_ASSERT(res == 1 , _T("ResumeThread failed")) ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -265,9 +362,10 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
|
||||
res = ResumeThread (patomvm->vm_thread) ;
|
||||
ATOMVM_ASSERT(res == 1 , _T("ResumeThread failed")) ;
|
||||
|
||||
ResetEvent (patomvm->atomvm_int) ;
|
||||
InterlockedExchange ((volatile uint32_t*)&patomvm->isr, 0) ;
|
||||
ResetEvent (patomvm->atomvm_int) ;
|
||||
SetEvent (patomvm->atomvm_int_complete) ;
|
||||
SetEvent (patomvm->atomvm_int_complete) ;
|
||||
|
||||
} else {
|
||||
|
||||
@@ -295,6 +393,7 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCtrlClose
|
||||
*
|
||||
* This is an atomvm controll function used by a controlling thread
|
||||
@@ -329,6 +428,8 @@ atomvmCtrlClose (HATOMVM atomvm)
|
||||
CloseHandle (patomvm->atomvm_close) ;
|
||||
CloseHandle (patomvm->vm_thread) ;
|
||||
|
||||
TlsFree (g_atomvm_tls_idx) ;
|
||||
|
||||
free (atomvm) ;
|
||||
}
|
||||
|
||||
@@ -375,7 +476,27 @@ invokeCallback (PATOMVM patomvm, ATOMVM_CALLBACK_F callback, PATOMVM_CALLBACK se
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* \b getAtomvm
|
||||
*
|
||||
* Get the atomvm instance for the calling thredd
|
||||
*
|
||||
* @return atomvm instance
|
||||
*/
|
||||
__inline PATOMVM
|
||||
getAtomvm ()
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) TlsGetValue (g_atomvm_tls_idx) ;
|
||||
|
||||
ATOMVM_ASSERT(patomvm , _T("TlsGetValue failed")) ;
|
||||
|
||||
return patomvm ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmExitCritical
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
@@ -384,14 +505,12 @@ invokeCallback (PATOMVM patomvm, ATOMVM_CALLBACK_F callback, PATOMVM_CALLBACK se
|
||||
* When the critical count reaches zero, interrupts will be enabled again. Calling
|
||||
* this function from inside an isr has no effect.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
*
|
||||
* @return Critical count before this function was called.
|
||||
* @return Critical count before the function call.
|
||||
*/
|
||||
int32_t
|
||||
atomvmExitCritical (HATOMVM atomvm)
|
||||
atomvmExitCritical ()
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
int32_t count = 0;
|
||||
|
||||
if (patomvm->status_isr == 0) {
|
||||
@@ -403,6 +522,7 @@ atomvmExitCritical (HATOMVM atomvm)
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmEnterCritical
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
@@ -413,14 +533,13 @@ atomvmExitCritical (HATOMVM atomvm)
|
||||
*
|
||||
* All threads are created with a critical count of 1.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
*
|
||||
* @return Critical count before this function was called.
|
||||
* @return Critical count before the function call.
|
||||
*/
|
||||
int32_t
|
||||
atomvmEnterCritical (HATOMVM atomvm)
|
||||
atomvmEnterCritical ()
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
int32_t count = 0 ;
|
||||
|
||||
if (patomvm->status_isr == 0) {
|
||||
@@ -432,6 +551,24 @@ atomvmEnterCritical (HATOMVM atomvm)
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCriticalCount
|
||||
*
|
||||
* Rerurns the critical cont of the current context.
|
||||
*
|
||||
* @return the critical cont of the current context.
|
||||
*/
|
||||
int32_t
|
||||
atomvmCriticalCount ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
return patomvm->current_context->critical_count ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmCtrlIntRequest
|
||||
*
|
||||
* This is an atomvm controll function used by a controlling thread(s)
|
||||
@@ -440,7 +577,7 @@ atomvmEnterCritical (HATOMVM atomvm)
|
||||
* This function requests an interrupt service routine to be called in the
|
||||
* context of the atom virtual machine.
|
||||
*
|
||||
* The call will block untill after the interrupt completes.
|
||||
* The call will block while a previously scheduled interrupt is in progress.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] isr The address of the interrupt service routine. The routine must use
|
||||
@@ -453,10 +590,11 @@ atomvmCtrlIntRequest (HATOMVM atomvm, uint32_t isr)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
|
||||
WaitForSingleObject (patomvm->atomvm_int_complete, INFINITE) ;
|
||||
while (InterlockedCompareExchange ((volatile uint32_t *)&patomvm->isr, isr, 0) == 0) {
|
||||
SwitchToThread() ;
|
||||
}
|
||||
SignalObjectAndWait(patomvm->atomvm_int, patomvm->atomvm_int_complete, INFINITE, FALSE) ;
|
||||
SetEvent (patomvm->atomvm_int) ;
|
||||
|
||||
}
|
||||
|
||||
@@ -486,6 +624,7 @@ callbackContextCreate (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmContextCreate
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
@@ -493,7 +632,6 @@ callbackContextCreate (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
* This function creates a atomvm thread context that can be scheduled
|
||||
* by atomvmContextSwitch.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[out] context Handle to the context of the thread that are allocated
|
||||
* by the caller.
|
||||
* @param[in] stack Stack top.
|
||||
@@ -502,10 +640,10 @@ callbackContextCreate (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
atomvmContextCreate (HATOMVM atomvm, HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t entry)
|
||||
atomvmContextCreate (HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t entry)
|
||||
{
|
||||
uint32_t res ;
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
PATOMVM_CONTEXT new_context = (PATOMVM_CONTEXT)malloc (sizeof(ATOMVM_CONTEXT)) ;
|
||||
CONTEXT* pcontext = &new_context->context ;
|
||||
ATOMVM_CALLBACK_CONTEXT context_init ;
|
||||
@@ -542,17 +680,20 @@ atomvmContextCreate (HATOMVM atomvm, HATOMVM_CONTEXT* atomvm_context, uint32_t s
|
||||
uint32_t
|
||||
callbackContextSwitch (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
uint32_t res1 ;
|
||||
uint32_t res1 = 1 ;
|
||||
uint32_t res2 ;
|
||||
PATOMVM_CALLBACK_CONTEXT context_switch = (PATOMVM_CALLBACK_CONTEXT)callback ;
|
||||
CONTEXT* pnew_context = &context_switch->pcontext->context ;
|
||||
PATOMVM_CALLBACK_CONTEXT_SWITCH context_switch = (PATOMVM_CALLBACK_CONTEXT_SWITCH)callback ;
|
||||
CONTEXT* p_old_context = &context_switch->p_old_context->context ;
|
||||
CONTEXT* p_new_context = &context_switch->p_new_context->context ;
|
||||
|
||||
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, context_switch) ;
|
||||
|
||||
res1 = GetThreadContext (patomvm->vm_thread, &patomvm->current_context->context) ;
|
||||
ATOMVM_ASSERT(res1 , _T("GetThreadContext failed")) ;
|
||||
if (p_old_context) {
|
||||
res1 = GetThreadContext (patomvm->vm_thread, p_old_context) ;
|
||||
ATOMVM_ASSERT(res1 , _T("GetThreadContext failed")) ;
|
||||
}
|
||||
|
||||
InterlockedExchange ((volatile uint32_t*)&patomvm->current_context, (uint32_t)pnew_context) ;
|
||||
InterlockedExchange ((volatile uint32_t*)&patomvm->current_context, (uint32_t)p_new_context) ;
|
||||
res2 = SetThreadContext (patomvm->vm_thread, &patomvm->current_context->context) ;
|
||||
ATOMVM_ASSERT(res2 , _T("SetThreadContext failed")) ;
|
||||
|
||||
@@ -561,44 +702,45 @@ callbackContextSwitch (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmContextSwitch
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function schedules a thread for the context created by atomvmContextCreate.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] new_context The context to schedule.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
atomvmContextSwitch (HATOMVM atomvm, HATOMVM_CONTEXT new_context)
|
||||
atomvmContextSwitch (HATOMVM_CONTEXT old_context, HATOMVM_CONTEXT new_context)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
ATOMVM_CALLBACK_CONTEXT context_switch ;
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK_CONTEXT_SWITCH context_switch ;
|
||||
|
||||
context_switch.pcontext = (PATOMVM_CONTEXT) new_context ;
|
||||
context_switch.p_old_context = (PATOMVM_CONTEXT) old_context ;
|
||||
context_switch.p_new_context = (PATOMVM_CONTEXT) new_context ;
|
||||
|
||||
return invokeCallback (patomvm, callbackContextSwitch, (PATOMVM_CALLBACK)&context_switch) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmContextDesrtroy
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This functiondestroyes a atomvm context created by atomvmContextCreate.
|
||||
*
|
||||
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[in] context The context to destroy.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void
|
||||
atomvmContextDesrtroy (HATOMVM atomvm, HATOMVM_CONTEXT context)
|
||||
atomvmContextDesrtroy (HATOMVM_CONTEXT context)
|
||||
{
|
||||
PATOMVM patomvm = (PATOMVM) atomvm ;
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
ATOMVM_ASSERT(patomvm->current_context != (PATOMVM_CONTEXT)context,
|
||||
_T("atomvmContextDesrtroy failed")) ;
|
||||
@@ -606,6 +748,240 @@ atomvmContextDesrtroy (HATOMVM atomvm, HATOMVM_CONTEXT context)
|
||||
free((void*)context) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmWriteThreadId
|
||||
*
|
||||
* Write a thread ID.
|
||||
*
|
||||
* Write a thread ID for the current context.
|
||||
*
|
||||
* @param[in] thread_id thread_id.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
void
|
||||
atomvmWriteThreadId (uint32_t thread_id)
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
patomvm->current_context->thread_id = thread_id ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmReadThreadId
|
||||
*
|
||||
* Write a thread ID.
|
||||
*
|
||||
* Read a thread ID for the current context.
|
||||
*
|
||||
* @return thread_id
|
||||
*/
|
||||
uint32_t
|
||||
atomvmReadThreadId ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
return patomvm->current_context->thread_id ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmGetVmId
|
||||
*
|
||||
* Returns an identifier for the virtual machine. This is zero for the first
|
||||
* virtual machine created with atomvmCtrlInit(), 1 for the second and so on.
|
||||
*
|
||||
* @return The atom vm ID
|
||||
*/
|
||||
uint32_t
|
||||
atomvmGetVmId ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
|
||||
return patomvm->atomvm_id ;
|
||||
}
|
||||
/**
|
||||
* \b callbackEventWait
|
||||
*
|
||||
* This function is invoked from the controll thread after a call to atomvmEventWait.
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[out] context Context to be scheduled.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackEventWait (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
return WaitForSingleObject (g_atomvm_event, INFINITE) == WAIT_OBJECT_0 ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmEventWait
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
*
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void
|
||||
atomvmEventWait ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
invokeCallback (patomvm, callbackEventWait, (PATOMVM_CALLBACK)&callback) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b callbackEventSend
|
||||
*
|
||||
* This function is invoked from the controll thread after a call to atomvmEventSend.
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[out] context Context to be scheduled.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackEventSend (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
return SetEvent (g_atomvm_event) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmEventSend
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
*
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void
|
||||
atomvmEventSend ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
invokeCallback (patomvm, callbackEventSend, (PATOMVM_CALLBACK)&callback) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \b callbackInterruptWait
|
||||
*
|
||||
* This function is invoked from the controll thread after a call to atomvmInterruptWait().
|
||||
*
|
||||
* The atom virtual machine is suspended while this function is called.
|
||||
*
|
||||
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
|
||||
* @param[out] callback Callback parameter.
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackInterruptWait (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
return WaitForSingleObject (patomvm->atomvm_int, INFINITE) == WAIT_OBJECT_0 ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmInterruptWait
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
*
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
void
|
||||
atomvmInterruptWait ()
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK callback ;
|
||||
|
||||
invokeCallback (patomvm, callbackInterruptWait, (PATOMVM_CALLBACK)&callback) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b callbackScheduleIpi
|
||||
*
|
||||
* This function is invoked from the controll thread after a call to atomvmScheduleIpi().
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
*
|
||||
* @param[in] target Target atomvm ID, less than ATOMVM_MAX_VM
|
||||
* @param[in] isr interrupt service routine
|
||||
*
|
||||
* @return Zero on failure, try to call GetLastError().
|
||||
*/
|
||||
uint32_t
|
||||
callbackScheduleIpi (PATOMVM patomvm, PATOMVM_CALLBACK callback)
|
||||
{
|
||||
PATOMVM_CALLBACK_IPI callback_ipi = (PATOMVM_CALLBACK_IPI)callback ;
|
||||
uint32_t res = 0 ;
|
||||
|
||||
if ((callback_ipi->target < ATOMVM_MAX_VM) &&
|
||||
(g_vms[callback_ipi->target] != patomvm) ) {
|
||||
|
||||
atomvmCtrlIntRequest ((HATOMVM)g_vms[callback_ipi->target], callback_ipi->isr) ;
|
||||
res = 1 ;
|
||||
|
||||
}
|
||||
|
||||
return res ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b atomvmScheduleIpi
|
||||
*
|
||||
* This function is to be used by the atom virtual machine.
|
||||
*
|
||||
* This function if for synchronization between multiple
|
||||
* atom vms.
|
||||
*
|
||||
* @param[in] target Target atomvm ID
|
||||
* @param[in] isr interrupt service routine
|
||||
*
|
||||
* @return Zero on failure, the vm is not running.
|
||||
*/
|
||||
uint32_t
|
||||
atomvmScheduleIpi (uint32_t target, uintptr_t isr)
|
||||
{
|
||||
PATOMVM patomvm = getAtomvm () ;
|
||||
ATOMVM_CALLBACK_IPI callback ;
|
||||
|
||||
callback.target = target ;
|
||||
callback.isr = isr ;
|
||||
|
||||
return invokeCallback (patomvm, callbackScheduleIpi, (PATOMVM_CALLBACK)&callback) ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \b vm_thread
|
||||
@@ -620,6 +996,9 @@ atomvmContextDesrtroy (HATOMVM atomvm, HATOMVM_CONTEXT context)
|
||||
DWORD WINAPI
|
||||
vm_thread (LPVOID lpParameter)
|
||||
{
|
||||
BOOL res = TlsSetValue (g_atomvm_tls_idx, lpParameter) ;
|
||||
|
||||
ATOMVM_ASSERT(res, _T("TlsSetValue failed")) ;
|
||||
__atomvmReset () ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,36 @@
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** \mainpage \ref atomvm
|
||||
* \defgroup atomvm Atomvm API
|
||||
*
|
||||
* @authors Natie van Rooyen
|
||||
*
|
||||
* @section intro Introduction
|
||||
* Atomvm is a tiny virtual machine that can run on Windows inside an IDE with a
|
||||
* debugger like Microsoft Visual C++ Express. The primary purpose of this virtual
|
||||
* machine is for the evaluation of Real Time Operating Systems (like atomthreads)
|
||||
* and the development and testing of modules for this Real Time Operating System
|
||||
* in a user friendly environment.:
|
||||
*
|
||||
* @section build Building The Source
|
||||
* To test this project, just add all the files from the "atomthreads/kernel"
|
||||
* directory and the "atomthreads/ports/atomvm" directory as well as the test
|
||||
* program main.c to your project. Add both the
|
||||
* before mentioned directories to the include paths of your project and compile. \n
|
||||
* Atomvm was designed for multi core systems but also runs fine on any single
|
||||
* core system.
|
||||
*
|
||||
* @section test Running The Test
|
||||
* The test, main.c, is intentioned to stress the virtual machine as opposed to
|
||||
* testing the Real Time Operating System. However, this test can also run the
|
||||
* unit tests of atomthreads by using the preprocessor directive "UNIT_TESTS" and
|
||||
* linking in the desired unit test into the project.
|
||||
* */
|
||||
|
||||
#ifndef __ATOMVM_H__
|
||||
#define __ATOMVM_H__
|
||||
|
||||
@@ -33,13 +63,15 @@
|
||||
#include "atomuser.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined _DEBUG || defined DEBUG
|
||||
#define ATOMVM_ASSERT(x, msg) _ASSERT(x)
|
||||
#else
|
||||
#define ATOMVM_ASSERT(x, msg)
|
||||
#endif
|
||||
|
||||
|
||||
#define ATOMVM_MAX_VM 8
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
/* This is an opaque handle to an instance of an atomvm created
|
||||
@@ -58,14 +90,42 @@ extern void atomvmCtrlIntRequest (HATOMVM atomvm, uintptr_t isr) ;
|
||||
extern void atomvmCtrlClose (HATOMVM atomvm) ;
|
||||
|
||||
/* Function prototypes for use by the atom virtual machine */
|
||||
extern int32_t atomvmExitCritical (HATOMVM atomvm) ;
|
||||
extern int32_t atomvmEnterCritical (HATOMVM atomvm) ;
|
||||
extern uint32_t atomvmContextCreate (HATOMVM atomvm, HATOMVM_CONTEXT* context, uint32_t stack, uint32_t entry) ;
|
||||
extern uint32_t atomvmContextSwitch (HATOMVM atomvm, HATOMVM_CONTEXT new_context) ;
|
||||
extern void atomvmContextDesrtroy (HATOMVM atomvm, HATOMVM_CONTEXT context) ;
|
||||
extern int32_t atomvmExitCritical () ;
|
||||
extern int32_t atomvmEnterCritical () ;
|
||||
extern int32_t atomvmCriticalCount () ;
|
||||
extern uint32_t atomvmContextCreate (HATOMVM_CONTEXT* context, uint32_t stack, uint32_t entry) ;
|
||||
extern uint32_t atomvmContextSwitch (HATOMVM_CONTEXT old_context, HATOMVM_CONTEXT new_context) ;
|
||||
extern void atomvmContextDesrtroy (HATOMVM_CONTEXT context) ;
|
||||
extern void atomvmWriteThreadId (uint32_t thread_id) ;
|
||||
extern uint32_t atomvmReadThreadId () ;
|
||||
/* Function prototypes for use by the atom virtual machine
|
||||
for synchronization with other running atom virtual machines */
|
||||
extern uint32_t atomvmGetVmId () ;
|
||||
extern void atomvmInterruptWait () ;
|
||||
extern void atomvmEventWait () ;
|
||||
extern void atomvmEventSend () ;
|
||||
extern uint32_t atomvmScheduleIpi (uint32_t target, uintptr_t isr) ;
|
||||
|
||||
/* Function prototypes to be implemted in the atom virtual machine */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b __atomvmReset
|
||||
*
|
||||
* Function prototype to be implemted in the atom virtual machine
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
extern void __atomvmReset (void) ;
|
||||
/**
|
||||
* \ingroup atomvm
|
||||
* \b __atomvmClose
|
||||
*
|
||||
* Function prototype to be implemted in the atom virtual machine
|
||||
*
|
||||
* @return void.
|
||||
*/
|
||||
extern void __atomvmClose (void) ;
|
||||
|
||||
#endif /* __ATOMVM_H__ */
|
||||
|
||||
@@ -91,8 +91,10 @@ monitor_thread (uint32_t parm)
|
||||
printf("\nIdle Threadd 1 Counter = %d\nIdle Theadrd 2 Counter = %d\nInterrupt Counter = %d",test2_counter,test3_counter,test_isr_count);
|
||||
printf ("\n\n") ;
|
||||
CRITICAL_END();
|
||||
|
||||
atomTimerDelay (300) ;
|
||||
//for (i=0; i<100;i++) {
|
||||
// atomvmInterruptWait () ;
|
||||
//}
|
||||
atomTimerDelay (150) ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user