Updates to the atomvm port.

This commit is contained in:
Natie van Rooyen
2012-10-03 21:19:44 +02:00
parent c016f54ad0
commit 6f34e08e2f
11 changed files with 646 additions and 734 deletions

View File

@@ -6,11 +6,18 @@ License: BSD Revised
---------------------------------------------------------------------------
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.
Atomvm is a tiny virtual machine that runs on Windows and can be debugged
from an IDE 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 programs for it on a Windows
machine.
Atomvm makes use of the Windows API functions GetThreadContext() and
SetThreadContext() to create multiple virtual contexts or threads inside a
single Windows thread. Atomvm also simulates interrupts with an interrupt
mask accessible from the Atomvm threads. External events can be queued as
interrupts to Atomvm, for example a timer loop generating system timer tick
interrupts for a Real Time Operating System ported to Atomvm.
---------------------------------------------------------------------------
@@ -28,9 +35,6 @@ core system.
RUNNING THE TESTS
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.
The test, main.c, is intentioned to stress the virtual machine.

View File

@@ -27,8 +27,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ATOM_PORT_TESTS_H
#define __ATOM_PORT_TESTS_H
#ifndef __ATOMPORT_TEST_H__
#define __ATOMPORT_TEST_H__
/* Include Atomthreads kernel API */
#include "atom.h"
@@ -56,3 +56,4 @@
#endif /* __ATOM_PORT_TESTS_H */
#endif /* __ATOMPORT_TEST_H__ */

View File

@@ -53,7 +53,7 @@ static HANDLE cntrl_thread ;
void
atomvmRun ()
{
atomvmCtrlInit (&the_atomvm) ;
atomvmCtrlCreate (&the_atomvm) ;
cntrl_thread = CreateThread (NULL, 0, cntrl_thread_proc, (uint32_t*)the_atomvm, CREATE_SUSPENDED, NULL) ;
ResumeThread (cntrl_thread) ;
}
@@ -85,7 +85,8 @@ thread_shell (void)
* is first restored.
*/
// sei();
atomvmExitCritical () ;
//atomvmExitCritical () ;
atomvmInterruptMask (0) ;
/* Call the thread entry point */
if (curr_tcb && curr_tcb->entry_point)
@@ -156,17 +157,3 @@ void archTimerTickIrqHandler ()
/* Call the interrupt exit routine */
atomIntExit(TRUE);
}
unsigned int
__enter_critical ()
{
return atomvmEnterCritical () ;
}
void
__exit_critical (unsigned int isr)
{
atomvmExitCritical () ;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, Kelvin Lawson. All rights reserved.
* Copyright (c) 2012, Natie van Rooyen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,19 +32,9 @@
#include "atomvm.h"
#define SYSTEM_MEMALIGN sizeof (unsigned int)
#define SYSTEM_TICKS_PER_SEC 100
typedef unsigned int uintptr_t ;
typedef int intptr_t ;
typedef unsigned int uint32_t ;
typedef unsigned short uint16_t ;
typedef unsigned char uint8_t ;
typedef int int32_t ;
typedef short int16_t ;
typedef char int8_t ;
/* Size of each stack entry / stack alignment size (e.g. 32 bits) */
#define STACK_ALIGN_SIZE sizeof(unsigned int)
/**
* Architecture-specific types.
@@ -52,15 +42,13 @@ typedef char int8_t ;
* included above.
*/
#define POINTER void *
#define ATOM_TLS HATOMVM_CONTEXT context ;
/* Critical region protection */
extern unsigned int __enter_critical() ;
extern void __exit_critical(unsigned int) ;
#define CRITICAL_STORE unsigned int __atom
#define CRITICAL_START() __atom = __enter_critical()
#define CRITICAL_END() __exit_critical(__atom)
#define CRITICAL_STORE unsigned int __atom_int_mask
#define CRITICAL_START() __atom_int_mask = atomvmInterruptMask(1)
#define CRITICAL_END() atomvmInterruptMask(__atom_int_mask)
#define ATOM_TLS HATOMVM_CONTEXT context ;
@@ -71,4 +59,4 @@ extern void archTimerTickIrqHandler () ;
/* The instance of the atomvm for this port */
extern HATOMVM the_atomvm ;
#endif /* __ATOM_PORT_H */
#endif /* __ATOM_PORT_H__ */

View File

@@ -39,18 +39,21 @@
*
* \b Function prototypes used for controlling the atom virtual machine: \n
*
* \li atomvmCtrlInit(): .
* \li atomvmCtrlCreate(): .
* \li atomvmCtrlRun(): .
* \li atomvmCtrlIntRequest(): .
* \li atomvmCtrlClose(): .
*
* \b Function prototypes for use by the atom virtual machine: \n
*
* \li atomvmExitCritical(): .
* \li atomvmEnterCritical(): .
* \li atomvmInterruptMask(): .
* \li atomvmContextCreate(): .
* \li atomvmContextSwitch(): .
* \li atomvmContextDesrtroy(): .
* \li atomvmWriteThreadId(): .
* \li atomvmReadThreadId(): .
* \li atomvmInterruptWait(): .
* \li atomvmGetVmId(): .
*
* \b Function prototypes to be implemted in the atom virtual machine: \n
*
@@ -67,8 +70,6 @@
#define CONTEXT_VM (CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS)
#define ATOMVM_ATOMVM_PERF_COUNTER(patomvm, counter) (InterlockedIncrement(&patomvm->perf_counters.counter))
/* Data types */
/* Forward declarations */
@@ -118,32 +119,6 @@ typedef struct ATOMVM_CALLBACK_CONTEXT_SWITCH_S {
} 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 */
uint32_t int_request ;
/* Number of service calls (context switches and
context init from atom virtual machime) */
uint32_t service_call ;
/* Total number of context switches */
uint32_t context_switch ;
} ATOMVM_PERF_COUNTERS, *PATOMVM_PERF_COUNTERS ;
/* ATOMVM_CONTEXT saves the state of a context created by
atomvmContextCreate() and sheduled by atomvmContextSwitch(). */
typedef struct ATOMVM_CONTEXT_S {
@@ -152,18 +127,16 @@ typedef struct ATOMVM_CONTEXT_S {
during context initialization and context switches */
CONTEXT context ;
/* When entering a critical section the critical_count is
incremented for the context. Interrupts will only occur while
the critical_count is zero. The functions atomvmExitCritical()
and atomvmEnterCritical() will respectively decrement and
increment the critical count */
volatile uint32_t critical_count ;
/* When entering a critical section the interrupt_mask is
set for the context. Interrupts will only occur while
the interrupt_mask is zero. */
volatile uint32_t interrupt_mask ;
uint32_t thread_id ;
} ATOMVM_CONTEXT, *PATOMVM_CONTEXT ;
/* ATOMVM defines the state of an instance to an atomvm. It is created
by a call to atomvmCtrlInit(). */
by a call to atomvmCtrlCreate(). */
typedef struct ATOMVM_S {
uint32_t atomvm_id ;
@@ -176,7 +149,6 @@ typedef struct ATOMVM_S {
HANDLE atomvm_int ;
HANDLE atomvm_int_complete ;
HANDLE atomvm_close ;
HANDLE atomvm_event ;
/* next ISR */
volatile void (*isr)(void) ;
@@ -191,21 +163,15 @@ typedef struct ATOMVM_S {
and, return value for the current service call */
PATOMVM_CALLBACK service_call ;
/* Context for startup, before any context was scheduled
(workaround to not check everytime if the first context
was already started) */
/* Context for startup, before any context was scheduled */
ATOMVM_CONTEXT atom_init_context ;
/* Performance counters */
volatile ATOMVM_PERF_COUNTERS perf_counters ;
} ATOMVM, *PATOMVM ;
/* Global declarations */
volatile uint32_t g_atomvm_counter = 0 ;
volatile DWORD g_atomvm_tls_idx ;
PATOMVM g_vms[ATOMVM_MAX_VM] ;
volatile uint32_t g_atomvm_id = 0 ;
volatile DWORD g_atomvm_tls_idx ;
/* Forward declaration for the atom virtual machine thread */
@@ -214,57 +180,52 @@ static DWORD WINAPI vm_thread (LPVOID lpParameter) ;
/**
* \ingroup atomvm
* \b atomvmCtrlInit
* \b atomvmCtrlCreate
*
* This is an atomvm controll function used by a controlling thread
* and must not be called from the atom virtual machine.
*
* Initializes the virtual machine.
*
* ToDo: More Error checking.
*
* @param[out] atomvm Handle to the virtual machine created.
*
* @return Zero on failure.
*/
uint32_t
atomvmCtrlInit (HATOMVM *atomvm)
atomvmCtrlCreate (HATOMVM *atomvm)
{
PATOMVM patomvm = 0 ;
int32_t i ;
if (g_atomvm_counter < ATOMVM_MAX_VM) {
patomvm = (PATOMVM) malloc (sizeof(struct ATOMVM_S)) ;
patomvm = (PATOMVM) malloc (sizeof(struct ATOMVM_S)) ;
if (patomvm) {
if (patomvm) {
memset (patomvm, 0, sizeof(struct ATOMVM_S)) ;
memset (patomvm, 0, sizeof(struct ATOMVM_S)) ;
patomvm->atomvm_id = InterlockedIncrement(&g_atomvm_counter) - 1 ;
if (patomvm->atomvm_id == 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->atomvm_event = CreateEvent (NULL, FALSE, 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 ;
patomvm->atomvm_id = InterlockedIncrement(&g_atomvm_id) - 1 ;
if (patomvm->atomvm_id == 0) {
g_atomvm_tls_idx = TlsAlloc () ;
}
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) ;
ATOMVM_ASSERT(patomvm->atomvm_call && patomvm->atomvm_int && patomvm->atomvm_int_complete &&
patomvm->atomvm_close, _T("ResumeThread failed")) ;
patomvm->vm_thread = CreateThread (NULL, 0, vm_thread, (void*)patomvm, CREATE_SUSPENDED, NULL) ;
ATOMVM_ASSERT(patomvm->vm_thread, _T("CreateThread failed")) ;
patomvm->atom_init_context.interrupt_mask = 1 ;
patomvm->current_context = &patomvm->atom_init_context ;
*atomvm = (HATOMVM)patomvm ;
}
return patomvm != 0 ;
@@ -275,16 +236,13 @@ atomvmCtrlInit (HATOMVM *atomvm)
* \ingroup atomvm
* \b atomvmCtrlRun
*
* This is an atomvm controll function used by a controlling thread
* and must not be called from the atom virtual machine.
*
* After a call to atomvmCtrlInit this function start the atom virtual machine.
* After a call to atomvmCtrlCreate this function start the atom virtual machine.
* The calling thread will be used to manage interrupts and service calls in
* the virtual machine. This function will not return untill atomvmCtrlClose
* is called.
*
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
* @param[in] flags Reserved for later use.
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlCreate.
* @param[in] flags not used.
*
* @return None
*/
@@ -299,9 +257,7 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
#if defined DEBUG || defined _DEBUG
BOOL tls_res =
#endif
TlsSetValue (g_atomvm_tls_idx, (void*) atomvm) ;
TlsSetValue (g_atomvm_tls_idx, (void*) atomvm) ;
ATOMVM_ASSERT(tls_res, _T("TlsSetValue failed")) ;
ResumeThread (patomvm->vm_thread) ;
@@ -316,8 +272,6 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
if (wait_object == WAIT_OBJECT_0) {
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, service_call) ;
service_call = patomvm->service_call ;
while (!service_call->lock) {
SwitchToThread () ;
@@ -336,25 +290,23 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
ResetEvent (patomvm->atomvm_call) ;
res = ResumeThread (patomvm->vm_thread) ;
ATOMVM_ASSERT(res == 1 , _T("ResumeThread failed")) ;
}
else if (wait_object == WAIT_OBJECT_0 + 1) {
if (patomvm->current_context->critical_count == 0) {
if (patomvm->current_context->interrupt_mask == 0) {
while ((res = SuspendThread (patomvm->vm_thread)) == (DWORD)-1) ;
ATOMVM_ASSERT(res == 0 , _T("SuspendThread failed")) ;
#if (_WIN32_WINNT >= 0x0600)
/*
This is used for multi processor machines to ensure the thread
is stopped before executing the next instruction. */
is stopped before executing the next instruction. Set
_WIN32_WINNT < 0x0600 if you are running Windows XP */
FlushProcessWriteBuffers ();
#endif
if (patomvm->current_context->critical_count == 0) {
ATOMVM_ATOMVM_PERF_COUNTER(patomvm, int_request) ;
if (patomvm->current_context->interrupt_mask == 0) {
patomvm->status_isr++ ;
patomvm->isr () ;
@@ -404,11 +356,11 @@ atomvmCtrlRun (HATOMVM atomvm, uint32_t flags)
* and must not be called from the atom virtual machine.
*
* Closes the virtual machine and release all memory and handles created
* in atomvmCtrlInit.
* in atomvmCtrlCreate.
*
* ToDo: this function was never tested.
*
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlInit.
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlCreate.
*
* @return None
*/
@@ -432,7 +384,7 @@ atomvmCtrlClose (HATOMVM atomvm)
CloseHandle (patomvm->atomvm_close) ;
CloseHandle (patomvm->vm_thread) ;
TlsFree (g_atomvm_tls_idx) ;
// TlsFree (g_atomvm_tls_idx) ;
free (atomvm) ;
}
@@ -446,9 +398,9 @@ atomvmCtrlClose (HATOMVM atomvm)
* an isr it is already in the conrtext of the controll thread and the callback
* routine is called directly.
*
* The atom virtual machine is suspended during the callback.
* The atom virtual machine thread is suspended during the callback.
*
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
* @param[in] callback Callback function.
* @param[in/out] context Context the function will operate on.
*
@@ -483,12 +435,12 @@ invokeCallback (PATOMVM patomvm, ATOMVM_CALLBACK_F callback, PATOMVM_CALLBACK se
/*
* \b getAtomvm
*
* Get the atomvm instance for the calling thredd
* Get the atomvm instance for the calling thread
*
* @return atomvm instance
*/
__inline PATOMVM
getAtomvm ()
getAtomvm (void)
{
PATOMVM patomvm = (PATOMVM) TlsGetValue (g_atomvm_tls_idx) ;
@@ -498,76 +450,29 @@ getAtomvm ()
}
/**
* \ingroup atomvm
* \b atomvmExitCritical
* \b atomvmInterruptMask
*
* This function is to be used by the atom virtual machine.
*
* This function will decrement the critical count for the current atomvm context.
* When the critical count reaches zero, interrupts will be enabled again. Calling
* this function from inside an isr has no effect.
* This function will mask interrupts for the current atomvm context.
*
* @return Critical count before the function call.
* @param[in] mask zero enables interrupts any other value masks interrupts.
*
* @return Interrupt mask before the function call.
*/
int32_t
atomvmExitCritical ()
atomvmInterruptMask (uint32_t mask)
{
PATOMVM patomvm = getAtomvm () ;
int32_t count = 0;
int32_t interrupts = 0;
if (patomvm->status_isr == 0) {
count = InterlockedDecrement (&patomvm->current_context->critical_count) ;
interrupts = InterlockedExchange (&patomvm->current_context->interrupt_mask, mask) ;
}
return count ;
}
/**
* \ingroup atomvm
* \b atomvmEnterCritical
*
* This function is to be used by the atom virtual machine.
*
* This function will increment the critical count for the current atomvm
* context. Interrupts will be disabled when the critical count is not zero.
* Calling this function from inside an isr has no effect.
*
* All threads are created with a critical count of 1.
*
*
* @return Critical count before the function call.
*/
int32_t
atomvmEnterCritical ()
{
PATOMVM patomvm = getAtomvm () ;
int32_t count = 0 ;
if (patomvm->status_isr == 0) {
count = InterlockedIncrement (&patomvm->current_context->critical_count) ;
}
return count ;
}
/**
* \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 ;
return interrupts ;
}
@@ -575,17 +480,17 @@ atomvmCriticalCount ()
* \ingroup atomvm
* \b atomvmCtrlIntRequest
*
* This is an atomvm controll function used by a controlling thread(s)
* This is an atomvm controll function used by external threads
* and must not be called from the atom virtual machine.
*
* This function requests an interrupt service routine to be called in the
* context of the atom virtual machine.
*
* The call will return immediately after the interrupt was scheduled.
* 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
* the default calling convention of the compiler.
* @param[in] atomvm Handle to the virtual machine created by atomvmCtrlCreate.
* @param[in] isr The address of the interrupt service routine.
*
* @return None
*/
@@ -610,7 +515,7 @@ atomvmCtrlIntRequest (HATOMVM atomvm, uint32_t isr)
*
* The atom virtual machine is suspended while this function is called.
*
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
* @param[out] context Context to be initialized.
*
* @return Zero on failure, try to call GetLastError().
@@ -654,7 +559,7 @@ atomvmContextCreate (HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t e
context_init.pcontext = new_context ;
new_context->critical_count = 1 ;
new_context->interrupt_mask = 1 ;
res = invokeCallback (patomvm, callbackContextCreate, (PATOMVM_CALLBACK)&context_init) ;
@@ -676,7 +581,7 @@ atomvmContextCreate (HATOMVM_CONTEXT* atomvm_context, uint32_t stack, uint32_t e
*
* The atom virtual machine is suspended while this function is called.
*
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
* @param[out] context Context to be scheduled.
*
* @return Zero on failure, try to call GetLastError().
@@ -690,8 +595,6 @@ callbackContextSwitch (PATOMVM patomvm, PATOMVM_CALLBACK 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) ;
if (p_old_context) {
res1 = GetThreadContext (patomvm->vm_thread, p_old_context) ;
ATOMVM_ASSERT(res1 , _T("GetThreadContext failed")) ;
@@ -783,7 +686,7 @@ atomvmWriteThreadId (uint32_t thread_id)
* @return thread_id
*/
uint32_t
atomvmReadThreadId ()
atomvmReadThreadId (void)
{
PATOMVM patomvm = getAtomvm () ;
@@ -796,103 +699,18 @@ atomvmReadThreadId ()
* \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.
* virtual machine created with atomvmCtrlCreate(), 1 for the second and so on.
*
* @return The atom vm ID
*/
uint32_t
atomvmGetVmId ()
atomvmGetVmId (void)
{
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 (patomvm->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)
{
int32_t i ;
for (i=0; i<ATOMVM_MAX_VM; i++) {
if (g_vms[i] && (g_vms[i] != patomvm)) {
SetEvent (g_vms[i]->atomvm_event) ;
}
}
return 1 ;
}
/**
* \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
@@ -901,7 +719,7 @@ atomvmEventSend ()
*
* The atom virtual machine is suspended while this function is called.
*
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlInit.
* @param[in] patomvm Pointer to the virtual machine created by atomvmCtrlCreate.
* @param[out] callback Callback parameter.
*
* @return Zero on failure, try to call GetLastError().
@@ -926,7 +744,7 @@ callbackInterruptWait (PATOMVM patomvm, PATOMVM_CALLBACK callback)
* @return void.
*/
void
atomvmInterruptWait ()
atomvmInterruptWait (void)
{
PATOMVM patomvm = getAtomvm () ;
ATOMVM_CALLBACK callback ;
@@ -934,66 +752,6 @@ atomvmInterruptWait ()
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

View File

@@ -35,32 +35,26 @@
* @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.:
* Atomvm is a tiny virtual machine that runs on Windows and can be debugged
* from an IDE 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 on a Windows machine.
*
* Atomvm makes use of the Windows API functions GetThreadContext() and
* SetThreadContext() to create multiple virtual contexts or threads inside a
* single Windows thread. Atomvm also simulates interrupts with an interrupt
* mask accessible from the Atomvm threads. External events can be queued as
* interrupts to Atomvm, for example a timer loop generating system timer tick
* interrupts for a Real Time Operating System ported to Atomvm.
*
* @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__
#include <crtdbg.h>
#include "atomuser.h"
#include "types.h"
#if defined _DEBUG || defined DEBUG
@@ -75,7 +69,7 @@
/* Forward declarations */
/* This is an opaque handle to an instance of an atomvm created
by a call to atomvmCtrlInit() */
by a call to atomvmCtrlCreate() */
typedef struct ATOMVM* HATOMVM ;
/* This is an opaque handle to an atomvm context created
@@ -84,40 +78,33 @@ typedef struct ATOMVM_CONTEXT* HATOMVM_CONTEXT ;
/* Function prototypes used for controlling the atom virtual machine */
extern uint32_t atomvmCtrlInit (HATOMVM* atomvm) ;
extern uint32_t atomvmCtrlCreate (HATOMVM* atomvm) ;
extern void atomvmCtrlRun (HATOMVM atomvm, uint32_t flags) ;
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 () ;
extern int32_t atomvmEnterCritical () ;
extern int32_t atomvmCriticalCount () ;
/* Function prototypes for use by the atom virtual machine from within the
call to __atomvmReset(). */
extern int32_t atomvmInterruptMask (uint32_t mask) ;
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) ;
extern uint32_t atomvmReadThreadId (void) ;
extern void atomvmInterruptWait (void) ;
extern uint32_t atomvmGetVmId (void) ;
/**
* \ingroup atomvm
* \b __atomvmReset
*
* Function prototype to be implemted in the atom virtual machine
* Function prototype to be implemted as entry point for the atom virtual machine.
*
* @return void.
*/
extern void __atomvmReset (void) ;
/**
* \ingroup atomvm
* \b __atomvmClose

View File

@@ -1,270 +1,270 @@
#include <stdio.h>
#include <windows.h>
#include "atom.h"
#include "atomvm.h"
#include "atomport.h"
// #define UNIT_TESTS
#ifdef UNIT_TESTS
extern uint32_t test_start (void) ;
#endif
#define TEST_THREADS 47
#define TEST_STACK_BYTE_SIZE 0x10000
#define IDLE_STACK_BYTE_SIZE 0x10000
#define MONITOR_STACK_BYTE_SIZE 0x10000
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
static unsigned char monitor_stack[MONITOR_STACK_BYTE_SIZE] ;
static unsigned char test_stack[TEST_THREADS+1][TEST_STACK_BYTE_SIZE] ;
static unsigned int test_counter[TEST_THREADS+1] = {0} ;
static unsigned int test2_counter = 0 ;
static unsigned int test3_counter = 0 ;
static unsigned int test_isr_count = 0 ;
static unsigned char test2_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char test3_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char test_idle_stack[TEST_STACK_BYTE_SIZE] ;
static uint8_t test_prio[60] = {
001,010,100,200,250, 200,200,200,200,200,
150,150,150,150,150, 250,250,250,250,250,
101,102,103,104,105, 202,204,206,208,210,
150,150,150,150,150, 250,250,250,250,250,
121,122,123,124,125, 061,063,065,067,061,
150,150,150,150,150, 250,250,250,250,250
};
static uint32_t test_interv[60] = {
001,001,001,001,001, 002,003,004,005,006,
015,015,015,015,015, 025,024,023,022,021,
905,005,005,005,805, 050,051,052,053,054,
015,015,015,015,015, 025,024,023,022,021,
030,030,030,030,030, 070,071,072,073,474,
005,006,007,007,001, 001,001,003,003,005
};
ATOM_TCB test_tcb[TEST_THREADS+1] ;
ATOM_TCB monitor_tcb ;
ATOM_TCB test2_tcb ;
ATOM_TCB test3_tcb ;
ATOM_TCB test_idle_tcb ;
DWORD WINAPI isr_thread_proc (LPVOID lpParameter) ;
static HANDLE isr_thread_1 ;
static HANDLE isr_thread_2 ;
static HANDLE isr_thread_3 ;
static HANDLE isr_thread_4 ;
void
ipi_sr()
{
printf("ipi\r\n") ;
}
void
monitor_thread (uint32_t parm)
{
CRITICAL_STORE;
int i ;
int c = 0 ;
ATOM_TCB *tcb ;
static unsigned int idle_1 = 0, idle_2 = 0, int_count = 0 ;
unsigned int delta_idle_1 , delta_idle_2 , delta_int_count ;
tcb = atomCurrentContext() ;
for (;;)
{
CRITICAL_START();
printf("Monitor # %04d (%08d)\n", c++, atomTimeGet()) ;
printf("-------------------------\n") ;
for (i=0; i<TEST_THREADS/3; i++) {
printf("Thr %.2d cnt %08d\t",i,test_counter[i]);
printf("Thr %.2d cnt %08d\t",i+TEST_THREADS/3,test_counter[i+TEST_THREADS/3]);
printf("Thr %.2d cnt %08d\n",i+TEST_THREADS*2/3,test_counter[i+TEST_THREADS*2/3]);
}
delta_idle_1 = test2_counter - idle_1 ;
delta_idle_2 = test3_counter - idle_2 ;
delta_int_count = test_isr_count - int_count ;
printf("\nIdle Threadd 1 Counter = %d %d %d\nIdle Theadrd 2 Counter = %d %d %d\nInterrupt Counter = %d %d %d",
test2_counter, delta_idle_1, (unsigned int)(test2_counter / c),
test3_counter, delta_idle_2, (unsigned int)(test3_counter / c),
test_isr_count, delta_int_count, (unsigned int)(test_isr_count / c));
printf ("\n\n") ;
idle_1 = test2_counter ;
idle_2 = test3_counter ;
int_count = test_isr_count ;
CRITICAL_END();
//for (i=0; i<100;i++) {
// atomvmInterruptWait () ;
//}
atomTimerDelay (150) ;
//atomvmScheduleIpi (atomvmGetVmId(), (uint32_t) ipi_sr) ;
}
}
void
test_thread (uint32_t parm)
{
CRITICAL_STORE;
for (;;) {
atomTimerDelay (test_interv[parm]) ;
CRITICAL_START();
test_counter[parm]++ ;
CRITICAL_END();
}
}
void
test2_thread (uint32_t parm)
{
CRITICAL_STORE;
for (;;) {
CRITICAL_START();
test2_counter++ ;
CRITICAL_END();
}
}
void test3_thread(uint32_t parm)
{
CRITICAL_STORE;
for (;;) {
CRITICAL_START();
test3_counter++ ;
CRITICAL_END();
}
}
#ifdef UNIT_TESTS
void unit_test_thread(uint32_t parm)
{
unsigned int failures ;
failures = test_start () ;
printf ("test_start %d failures\n", failures) ;
while(1) {
atomTimerDelay (100);
}
}
#endif
void
__atomvmReset ()
{
unsigned int i ;
atomOSInit(&idle_stack[IDLE_STACK_BYTE_SIZE - sizeof(unsigned int)], IDLE_STACK_BYTE_SIZE - sizeof(unsigned int)) ;
#ifndef UNIT_TESTS
for (i=0; i< TEST_THREADS;i++) {
atomThreadCreate ((ATOM_TCB *)&test_tcb[i], test_prio[i], test_thread, i, &test_stack[i][TEST_STACK_BYTE_SIZE - sizeof(unsigned int)], TEST_STACK_BYTE_SIZE - sizeof(unsigned int));
}
atomThreadCreate ((ATOM_TCB *)&monitor_tcb, 50, monitor_thread, 0, &monitor_stack[(MONITOR_STACK_BYTE_SIZE) - sizeof(unsigned int)], MONITOR_STACK_BYTE_SIZE - sizeof(unsigned int));
atomThreadCreate ((ATOM_TCB *)&test2_tcb, 253, test2_thread, 0, &test2_stack[(TEST_STACK_BYTE_SIZE) - sizeof(unsigned int)], (TEST_STACK_BYTE_SIZE) - sizeof(unsigned int));
atomThreadCreate ((ATOM_TCB *)&test3_tcb, 253, test3_thread, 0, &test3_stack[(TEST_STACK_BYTE_SIZE) - sizeof(unsigned int)], (TEST_STACK_BYTE_SIZE) - sizeof(unsigned int));
#else
atomThreadCreate ((ATOM_TCB *)&test2_tcb, 16, unit_test_thread, 0, &test2_stack[(TEST_STACK_BYTE_SIZE) - sizeof(unsigned int)], (TEST_STACK_BYTE_SIZE) - sizeof(unsigned int));
#endif
atomOSStart() ;
}
void
__atomvmClose ()
{
}
void
test_isr ()
{
static int i = 0 ;
test_isr_count++ ;
if (i++==25) {
//Sleep(3) ;
i = 0;
}
}
DWORD WINAPI
isr_thread_proc (LPVOID lpParameter)
{
int i = 0 ;
int x ;
int y = rand() % 100 ;
while (1) {
atomvmCtrlIntRequest (the_atomvm, (uintptr_t)test_isr) ;
if (i++==y) {
x = rand() % 50 ;
Sleep (x) ;
y = rand() % 100 ;
i = 0 ;
}
}
return 0 ;
}
void
main ()
{
atomvmRun () ;
#ifndef UNIT_TESTS
isr_thread_1 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
isr_thread_2 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
isr_thread_3 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
isr_thread_4 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
ResumeThread (isr_thread_1) ;
ResumeThread (isr_thread_2) ;
ResumeThread (isr_thread_3) ;
ResumeThread (isr_thread_4) ;
#endif
while (1) {
Sleep(1) ;
atomvmCtrlIntRequest (the_atomvm, (uintptr_t)archTimerTickIrqHandler) ;
}
}
#include <stdio.h>
#include <windows.h>
#include "atom.h"
#include "atomvm.h"
#include "atomport.h"
// #define UNIT_TESTS
#ifdef UNIT_TESTS
extern uint32_t test_start (void) ;
#endif
#define TEST_THREADS 47
#define TEST_STACK_BYTE_SIZE 0x10000
#define IDLE_STACK_BYTE_SIZE 0x10000
#define MONITOR_STACK_BYTE_SIZE 0x10000
static unsigned char idle_stack[IDLE_STACK_BYTE_SIZE] ;
static unsigned char monitor_stack[MONITOR_STACK_BYTE_SIZE] ;
static unsigned char test_stack[TEST_THREADS+1][TEST_STACK_BYTE_SIZE] ;
static unsigned int test_counter[TEST_THREADS+1] = {0} ;
static unsigned int test2_counter = 0 ;
static unsigned int test3_counter = 0 ;
static unsigned int test_isr_count = 0 ;
static unsigned char test2_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char test3_stack[TEST_STACK_BYTE_SIZE] ;
static unsigned char test_idle_stack[TEST_STACK_BYTE_SIZE] ;
static uint8_t test_prio[60] = {
001,010,100,200,250, 200,200,200,200,200,
150,150,150,150,150, 250,250,250,250,250,
101,102,103,104,105, 202,204,206,208,210,
150,150,150,150,150, 250,250,250,250,250,
121,122,123,124,125, 061,063,065,067,061,
150,150,150,150,150, 250,250,250,250,250
};
static uint32_t test_interv[60] = {
001,001,001,001,001, 002,003,004,005,006,
015,015,015,015,015, 025,024,023,022,021,
905,005,005,005,805, 050,051,052,053,054,
015,015,015,015,015, 025,024,023,022,021,
030,030,030,030,030, 070,071,072,073,474,
005,006,007,007,001, 001,001,003,003,005
};
ATOM_TCB test_tcb[TEST_THREADS+1] ;
ATOM_TCB monitor_tcb ;
ATOM_TCB test2_tcb ;
ATOM_TCB test3_tcb ;
ATOM_TCB test_idle_tcb ;
DWORD WINAPI isr_thread_proc (LPVOID lpParameter) ;
static HANDLE isr_thread_1 ;
static HANDLE isr_thread_2 ;
static HANDLE isr_thread_3 ;
static HANDLE isr_thread_4 ;
void
ipi_sr()
{
printf("ipi\r\n") ;
}
void
monitor_thread (uint32_t parm)
{
CRITICAL_STORE;
int i ;
int c = 0 ;
ATOM_TCB *tcb ;
static unsigned int idle_1 = 0, idle_2 = 0, int_count = 0 ;
unsigned int delta_idle_1 , delta_idle_2 , delta_int_count ;
tcb = atomCurrentContext() ;
for (;;)
{
CRITICAL_START();
printf("Monitor # %04d (%08d)\n", c++, atomTimeGet()) ;
printf("-------------------------\n") ;
for (i=0; i<TEST_THREADS/3; i++) {
printf("Thr %.2d cnt %08d\t",i,test_counter[i]);
printf("Thr %.2d cnt %08d\t",i+TEST_THREADS/3,test_counter[i+TEST_THREADS/3]);
printf("Thr %.2d cnt %08d\n",i+TEST_THREADS*2/3,test_counter[i+TEST_THREADS*2/3]);
}
delta_idle_1 = test2_counter - idle_1 ;
delta_idle_2 = test3_counter - idle_2 ;
delta_int_count = test_isr_count - int_count ;
printf("\nIdle Threadd 1 Counter = %d %d %d\nIdle Theadrd 2 Counter = %d %d %d\nInterrupt Counter = %d %d %d",
test2_counter, delta_idle_1, (unsigned int)(test2_counter / c),
test3_counter, delta_idle_2, (unsigned int)(test3_counter / c),
test_isr_count, delta_int_count, (unsigned int)(test_isr_count / c));
printf ("\n\n") ;
idle_1 = test2_counter ;
idle_2 = test3_counter ;
int_count = test_isr_count ;
CRITICAL_END();
//for (i=0; i<100;i++) {
// atomvmInterruptWait () ;
//}
atomTimerDelay (450) ;
//atomvmScheduleIpi (atomvmGetVmId(), (uint32_t) ipi_sr) ;
}
}
void
test_thread (uint32_t parm)
{
CRITICAL_STORE;
for (;;) {
atomTimerDelay (test_interv[parm]) ;
CRITICAL_START();
test_counter[parm]++ ;
CRITICAL_END();
}
}
void
test2_thread (uint32_t parm)
{
CRITICAL_STORE;
for (;;) {
CRITICAL_START();
test2_counter++ ;
CRITICAL_END();
}
}
void test3_thread(uint32_t parm)
{
CRITICAL_STORE;
for (;;) {
CRITICAL_START();
test3_counter++ ;
CRITICAL_END();
}
}
#ifdef UNIT_TESTS
void unit_test_thread(uint32_t parm)
{
unsigned int failures ;
failures = test_start () ;
printf ("test_start %d failures\n", failures) ;
while(1) {
atomTimerDelay (100);
}
}
#endif
void
__atomvmReset ()
{
unsigned int i ;
atomOSInit(&idle_stack[0], IDLE_STACK_BYTE_SIZE, 1) ;
#ifndef UNIT_TESTS
for (i=0; i< TEST_THREADS;i++) {
atomThreadCreate ((ATOM_TCB *)&test_tcb[i], test_prio[i], test_thread, i, &test_stack[i][0], TEST_STACK_BYTE_SIZE, 1);
}
atomThreadCreate ((ATOM_TCB *)&monitor_tcb, 50, monitor_thread, 0, &monitor_stack[0], MONITOR_STACK_BYTE_SIZE, 1);
atomThreadCreate ((ATOM_TCB *)&test2_tcb, 253, test2_thread, 0, &test2_stack[0], TEST_STACK_BYTE_SIZE, 1);
atomThreadCreate ((ATOM_TCB *)&test3_tcb, 253, test3_thread, 0, &test3_stack[0], TEST_STACK_BYTE_SIZE, 1);
#else
atomThreadCreate ((ATOM_TCB *)&test2_tcb, 16, unit_test_thread, 0, &test2_stack[], TEST_STACK_BYTE_SIZE, 1);
#endif
atomOSStart() ;
}
void
__atomvmClose ()
{
}
void
test_isr ()
{
static int i = 0 ;
test_isr_count++ ;
if (i++==25) {
//Sleep(3) ;
i = 0;
}
}
DWORD WINAPI
isr_thread_proc (LPVOID lpParameter)
{
int i = 0 ;
int x ;
int y = rand() % 100 ;
while (1) {
atomvmCtrlIntRequest (the_atomvm, (uintptr_t)test_isr) ;
if (i++==y) {
x = rand() % 50 ;
Sleep (x) ;
y = rand() % 100 ;
i = 0 ;
}
}
return 0 ;
}
void
main ()
{
atomvmRun () ;
#ifndef UNIT_TESTS
isr_thread_1 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
isr_thread_2 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
isr_thread_3 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
isr_thread_4 = CreateThread (NULL, 0, isr_thread_proc, 0, CREATE_SUSPENDED, NULL) ;
ResumeThread (isr_thread_1) ;
ResumeThread (isr_thread_2) ;
ResumeThread (isr_thread_3) ;
ResumeThread (isr_thread_4) ;
#endif
while (1) {
Sleep(1) ;
atomvmCtrlIntRequest (the_atomvm, (uintptr_t)archTimerTickIrqHandler) ;
}
}

View File

@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C++ Express 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc", "msvc.vcxproj", "{77095EB1-4988-4A04-8751-69C63C7C541B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{77095EB1-4988-4A04-8751-69C63C7C541B}.Debug|Win32.ActiveCfg = Debug|Win32
{77095EB1-4988-4A04-8751-69C63C7C541B}.Debug|Win32.Build.0 = Debug|Win32
{77095EB1-4988-4A04-8751-69C63C7C541B}.Release|Win32.ActiveCfg = Release|Win32
{77095EB1-4988-4A04-8751-69C63C7C541B}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{77095EB1-4988-4A04-8751-69C63C7C541B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>msvc</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(MSBuildProjectDirectory)/../../../kernel;$(MSBuildProjectDirectory)/..;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(MSBuildProjectDirectory)/..;$(MSBuildProjectDirectory)/../../../kernel;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\kernel\atom.h" />
<ClInclude Include="..\..\..\kernel\atommutex.h" />
<ClInclude Include="..\..\..\kernel\atomqueue.h" />
<ClInclude Include="..\..\..\kernel\atomsem.h" />
<ClInclude Include="..\..\..\kernel\atomtimer.h" />
<ClInclude Include="..\atomport-tests.h" />
<ClInclude Include="..\atomport.h" />
<ClInclude Include="..\atomuser.h" />
<ClInclude Include="..\atomvm.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\kernel\atomkernel.c" />
<ClCompile Include="..\..\..\kernel\atommutex.c" />
<ClCompile Include="..\..\..\kernel\atomqueue.c" />
<ClCompile Include="..\..\..\kernel\atomsem.c" />
<ClCompile Include="..\..\..\kernel\atomtimer.c" />
<ClCompile Include="..\atomport.c" />
<ClCompile Include="..\atomvm.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="atomthreads">
<UniqueIdentifier>{d05cbb5a-256f-4127-bd5b-c3bd69b3672c}</UniqueIdentifier>
</Filter>
<Filter Include="port">
<UniqueIdentifier>{f30700d8-652d-477c-a4f2-d23e7784de50}</UniqueIdentifier>
</Filter>
<Filter Include="atomvm">
<UniqueIdentifier>{a4f641bc-296d-4546-a831-2e1d0d7e9242}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\kernel\atom.h">
<Filter>atomthreads</Filter>
</ClInclude>
<ClInclude Include="..\..\..\kernel\atommutex.h">
<Filter>atomthreads</Filter>
</ClInclude>
<ClInclude Include="..\..\..\kernel\atomqueue.h">
<Filter>atomthreads</Filter>
</ClInclude>
<ClInclude Include="..\..\..\kernel\atomsem.h">
<Filter>atomthreads</Filter>
</ClInclude>
<ClInclude Include="..\..\..\kernel\atomtimer.h">
<Filter>atomthreads</Filter>
</ClInclude>
<ClInclude Include="..\atomport.h">
<Filter>port</Filter>
</ClInclude>
<ClInclude Include="..\atomport-tests.h">
<Filter>port</Filter>
</ClInclude>
<ClInclude Include="..\atomuser.h">
<Filter>port</Filter>
</ClInclude>
<ClInclude Include="..\atomvm.h">
<Filter>atomvm</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\kernel\atomkernel.c">
<Filter>atomthreads</Filter>
</ClCompile>
<ClCompile Include="..\..\..\kernel\atommutex.c">
<Filter>atomthreads</Filter>
</ClCompile>
<ClCompile Include="..\..\..\kernel\atomqueue.c">
<Filter>atomthreads</Filter>
</ClCompile>
<ClCompile Include="..\..\..\kernel\atomsem.c">
<Filter>atomthreads</Filter>
</ClCompile>
<ClCompile Include="..\..\..\kernel\atomtimer.c">
<Filter>atomthreads</Filter>
</ClCompile>
<ClCompile Include="..\atomport.c">
<Filter>port</Filter>
</ClCompile>
<ClCompile Include="main.c" />
<ClCompile Include="..\atomvm.c">
<Filter>atomvm</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -1,63 +1,61 @@
/*
* Copyright (c) 2010,Kelvin Lawson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. No personal names or organizations' names associated with the
* Atomthreads project may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#if 1
#ifndef __ATOM_USER_H__
#define __ATOM_USER_H__
/* Portable uint8_t and friends not available from stdint.h on this platform */
#include <windows.h>
#define SYSTEM_MEMALIGN sizeof (unsigned int)
typedef unsigned int uintptr_t ;
typedef int intptr_t ;
typedef unsigned int uint32_t ;
typedef unsigned short uint16_t ;
typedef unsigned char uint8_t ;
typedef int int32_t ;
typedef short int16_t ;
typedef char int8_t ;
/**
* Architecture-specific types.
* Most of these are available from stdint.h on this platform, which is
* included above.
*/
#define POINTER void *
#define ATOM_TLS HATOMVM_CONTEXT context ;
#endif /* __ATOM_USER_H__ */
#endif
/*
* Copyright (c) 2010,Kelvin Lawson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. No personal names or organizations' names associated with the
* Atomthreads project may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ATOM_USER_H__
#define __ATOM_USER_H__
/* Portable uint8_t and friends not available from stdint.h on this platform */
#include <windows.h>
#define SYSTEM_MEMALIGN sizeof (unsigned int)
typedef unsigned int uintptr_t ;
typedef int intptr_t ;
typedef unsigned int uint32_t ;
typedef unsigned short uint16_t ;
typedef unsigned char uint8_t ;
typedef int int32_t ;
typedef short int16_t ;
typedef char int8_t ;
/**
* Architecture-specific types.
* Most of these are available from stdint.h on this platform, which is
* included above.
*/
#define POINTER void *
#define ATOM_TLS HATOMVM_CONTEXT context ;
#endif /* __ATOM_USER_H__ */