OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/rtos/ecos-2.0/packages/kernel/v2_0/tests
    from Rev 27 to Rev 174
    Reverse comparison

Rev 27 → Rev 174

/kmutex1.c
0,0 → 1,188
/*=================================================================
//
// kmutex1.c
//
// Kernel C API Mutex test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-23
// Description: Tests basic mutex functionality.
// Omissions: Timed wait.
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
#define NTHREADS 3
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
 
static cyg_mutex_t m0, m1;
static cyg_cond_t cvar0, cvar1, cvar2;
 
static cyg_ucount8 m0d=0, m1d=0;
 
static void finish( cyg_ucount8 t )
{
cyg_mutex_lock( &m1 ); {
m1d |= 1<<t;
if( 0x7 == m1d )
CYG_TEST_PASS_FINISH("Kernel C API Mutex 1 OK");
cyg_cond_wait( &cvar2 );
} /* cyg_mutex_unlock( &m1 ); */
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry0( cyg_addrword_t data )
{
cyg_mutex_lock( &m0 ); {
CHECK( ! cyg_mutex_trylock( &m0 ) );
cyg_mutex_lock( &m1 ); {
CHECK( ! cyg_mutex_trylock( &m0 ) );
} cyg_mutex_unlock( &m1 );
} cyg_mutex_unlock( &m0 );
 
cyg_mutex_lock( &m0 ); {
while ( 0 == m0d )
cyg_cond_wait( &cvar0 );
CHECK( 1 == m0d++ );
cyg_cond_signal( &cvar0 );
while ( 4 != m0d )
cyg_cond_wait( &cvar1 );
CHECK( 4 == m0d );
} cyg_mutex_unlock( &m0 );
 
finish( (cyg_ucount8)data );
}
 
static void entry1( cyg_addrword_t data )
{
cyg_mutex_lock( &m0 ); {
CHECK( cyg_mutex_trylock( &m1 ) ); {
} cyg_mutex_unlock( &m1 );
} cyg_mutex_unlock( &m0 );
 
cyg_mutex_lock( &m0 ); {
CHECK( 0 == m0d++ );
cyg_cond_broadcast( &cvar0 );
} cyg_mutex_unlock( &m0 );
cyg_mutex_lock( &m0 ); {
while( 1 == m0d )
cyg_cond_wait( &cvar0 );
CHECK( 2 == m0d++ );
cyg_cond_signal( &cvar0 );
while( 3 == m0d )
cyg_cond_wait( &cvar1 );
} cyg_mutex_unlock( &m0 );
 
finish( (cyg_ucount8)data );
}
 
static void entry2( cyg_addrword_t data )
{
cyg_mutex_lock( &m0 ); {
while( 3 != m0d ) {
cyg_cond_wait( &cvar0 );
}
CHECK( 3 == m0d++ );
cyg_cond_broadcast( &cvar1 );
} cyg_mutex_unlock( &m0 );
 
finish( (cyg_ucount8)data );
}
 
void kmutex1_main( void )
{
CYG_TEST_INIT();
 
cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kmutex1-0",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_thread_create(4, entry1 , (cyg_addrword_t)1, "kmutex1-1",
(void *)stack[1], STACKSIZE, &thread[1], &thread_obj[1]);
cyg_thread_resume(thread[1]);
 
cyg_thread_create(4, entry2 , (cyg_addrword_t)2, "kmutex1-2",
(void *)stack[2], STACKSIZE, &thread[2], &thread_obj[2]);
cyg_thread_resume(thread[2]);
 
cyg_mutex_init( &m0 );
cyg_mutex_init( &m1 );
 
cyg_cond_init( &cvar0, &m0 );
cyg_cond_init( &cvar1, &m0 );
cyg_cond_init( &cvar2, &m1 );
 
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
kmutex1_main();
}
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF kmutex1.c */
/kcache1.c
0,0 → 1,422
/*=================================================================
//
// kcache1.c
//
// Cache timing test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm, nickg
// Date: 1998-06-18
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/hal/hal_cache.h>
 
#if defined(HAL_DCACHE_SIZE) || defined(HAL_UCACHE_SIZE)
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
#ifdef CYGFUN_KERNEL_API_C
 
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_intr.h>
 
// -------------------------------------------------------------------------
// If the HAL does not supply this, we supply our own version
 
#ifndef HAL_DCACHE_PURGE_ALL
# ifdef HAL_DCACHE_SYNC
 
#define HAL_DCACHE_PURGE_ALL() HAL_DCACHE_SYNC()
 
# else
 
static cyg_uint8 dca[HAL_DCACHE_SIZE + HAL_DCACHE_LINE_SIZE*2];
 
#define HAL_DCACHE_PURGE_ALL() \
CYG_MACRO_START \
volatile cyg_uint8 *addr = &dca[HAL_DCACHE_LINE_SIZE]; \
volatile cyg_uint8 tmp = 0; \
int i; \
for( i = 0; i < HAL_DCACHE_SIZE; i += HAL_DCACHE_LINE_SIZE ) \
{ \
tmp = addr[i]; \
} \
CYG_MACRO_END
 
# endif
#endif
 
// -------------------------------------------------------------------------
 
#define NTHREADS 1
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
#ifndef MAX_STRIDE
#define MAX_STRIDE 64
#endif
 
volatile char m[(HAL_DCACHE_SIZE/HAL_DCACHE_LINE_SIZE)*MAX_STRIDE];
 
// -------------------------------------------------------------------------
 
static void time0(register cyg_uint32 stride)
{
register cyg_uint32 j,k;
cyg_tick_count_t count0, count1;
cyg_ucount32 t;
register char c;
 
count0 = cyg_current_time();
 
k = 0;
if ( cyg_test_is_simulator )
k = 3960;
 
for(; k<4000;k++) {
for(j=0; j<(HAL_DCACHE_SIZE/HAL_DCACHE_LINE_SIZE); j++) {
c=m[stride*j];
}
}
 
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("stride=%d, time=%d\n", stride, t);
}
 
// -------------------------------------------------------------------------
 
void time1(void)
{
cyg_uint32 i;
 
for(i=1; i<=MAX_STRIDE; i+=i) {
time0(i);
}
}
 
// -------------------------------------------------------------------------
// With an ICache invalidate in the middle:
#ifdef HAL_ICACHE_INVALIDATE_ALL
static void time0II(register cyg_uint32 stride)
{
register cyg_uint32 j,k;
cyg_tick_count_t count0, count1;
cyg_ucount32 t;
register char c;
 
count0 = cyg_current_time();
 
k = 0;
if ( cyg_test_is_simulator )
k = 3960;
 
for(; k<4000;k++) {
for(j=0; j<(HAL_DCACHE_SIZE/HAL_DCACHE_LINE_SIZE); j++) {
HAL_ICACHE_INVALIDATE_ALL();
c=m[stride*j];
}
}
 
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("stride=%d, time=%d\n", stride, t);
}
 
// -------------------------------------------------------------------------
 
void time1II(void)
{
cyg_uint32 i;
 
for(i=1; i<=MAX_STRIDE; i+=i) {
time0II(i);
}
}
#endif
// -------------------------------------------------------------------------
// With a DCache invalidate in the middle:
// This is guaranteed to produce bogus timing results since interrupts
// have to be disabled to prevent accidental loss of state.
#ifdef HAL_DCACHE_INVALIDATE_ALL
static void time0DI(register cyg_uint32 stride)
{
register cyg_uint32 j,k;
volatile cyg_tick_count_t count0;
cyg_tick_count_t count1;
cyg_ucount32 t;
register char c;
register CYG_INTERRUPT_STATE oldints;
 
count0 = cyg_current_time();
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
 
k = 0;
if ( cyg_test_is_simulator )
k = 3960;
 
for(; k<4000;k++) {
for(j=0; j<(HAL_DCACHE_SIZE/HAL_DCACHE_LINE_SIZE); j++) {
HAL_DCACHE_INVALIDATE_ALL();
c=m[stride*j];
}
}
HAL_RESTORE_INTERRUPTS(oldints);
 
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("stride=%d, time=%d\n", stride, t);
}
 
// -------------------------------------------------------------------------
 
void time1DI(void)
{
cyg_uint32 i;
 
for(i=1; i<=MAX_STRIDE; i+=i) {
time0DI(i);
}
}
#endif
// -------------------------------------------------------------------------
// This test could be improved by counting number of passes possible
// in a given number of ticks.
 
static void entry0( cyg_addrword_t data )
{
register CYG_INTERRUPT_STATE oldints;
 
#ifdef HAL_CACHE_UNIFIED
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL(); // rely on above definition
HAL_UCACHE_INVALIDATE_ALL();
HAL_UCACHE_DISABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Cache off");
time1();
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL(); // rely on above definition
HAL_UCACHE_INVALIDATE_ALL();
HAL_UCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Cache on");
time1();
 
#ifdef HAL_DCACHE_INVALIDATE_ALL
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_UCACHE_INVALIDATE_ALL();
HAL_UCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Cache on: invalidate Cache (expect bogus timing)");
time1DI();
#endif
 
#else // HAL_CACHE_UNIFIED
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_DISABLE();
HAL_DCACHE_DISABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache off Icache off");
time1();
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_DISABLE();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache on Icache off");
time1();
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_ENABLE();
HAL_DCACHE_DISABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache off Icache on");
time1();
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_ENABLE();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache on Icache on");
time1();
 
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_DISABLE();
HAL_DCACHE_DISABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache off Icache off (again)");
time1();
 
#if defined(HAL_DCACHE_INVALIDATE_ALL) || defined(HAL_ICACHE_INVALIDATE_ALL)
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_ENABLE();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache on Icache on (again)");
time1();
 
#if defined(CYGPKG_HAL_MIPS)
// In some architectures, the time taken for the next two tests is
// very long, partly because HAL_XCACHE_INVALIDATE_ALL() is implemented
// with a loop over the cache. Hence these tests take longer than the
// testing infrastructure is prepared to wait. The simplest way to get
// these tests to run quickly is to make them think they are running
// under a simulator.
// If the target actually is a simulator, skip the below - it's very
// slow on the simulator, even with reduced loop counts.
if (cyg_test_is_simulator)
CYG_TEST_PASS_FINISH("End of test");
 
#if defined(CYGPKG_HAL_MIPS_TX49)
// The TX49 has a large cache, and even with reduced loop count,
// 90+ seconds elapses between each INFO output.
CYG_TEST_PASS_FINISH("End of test");
#endif
 
cyg_test_is_simulator = 1;
#endif
 
#ifdef HAL_ICACHE_INVALIDATE_ALL
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_ENABLE();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache on Icache on: invalidate ICache each time");
time1II();
#endif
#ifdef HAL_DCACHE_INVALIDATE_ALL
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_PURGE_ALL();
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_INVALIDATE_ALL();
HAL_ICACHE_ENABLE();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
CYG_TEST_INFO("Dcache on Icache on: invalidate DCache (expect bogus times)");
time1DI();
#endif
#endif // either INVALIDATE_ALL macro
 
#endif // HAL_CACHE_UNIFIED
 
CYG_TEST_PASS_FINISH("End of test");
}
 
// -------------------------------------------------------------------------
 
void kcache2_main( void )
{
CYG_TEST_INIT();
 
cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kcache1",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_scheduler_start();
}
 
// -------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
kcache2_main();
}
 
// -------------------------------------------------------------------------
 
#else // def CYGFUN_KERNEL_API_C
#define N_A_MSG "Kernel C API layer disabled"
#endif // def CYGFUN_KERNEL_API_C
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
#define N_A_MSG "Kernel real-time clock disabled"
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
#else // def HAL_DCACHE_SIZE
#define N_A_MSG "No caches defined"
#endif // def HAL_DCACHE_SIZE
 
#ifdef N_A_MSG
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( N_A_MSG );
}
#endif // N_A_MSG
 
// -------------------------------------------------------------------------
/* EOF kcache1.c */
/release.cxx
0,0 → 1,129
//==========================================================================
//
// release.cxx
//
// Thread release test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 1998-04-24
// Description: Tests the functionality of thread release().
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
#define NTHREADS 2
 
#include "testaux.hxx"
 
static Cyg_Binary_Semaphore s0, s1;
 
static void entry0( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
if (!s0.wait() )
{
if( self->get_wake_reason() != Cyg_Thread::BREAK )
CYG_TEST_FAIL_FINISH("Wake reason not BREAK");
}
else
{
CYG_TEST_FAIL_FINISH("Thread not released");
}
 
s1.post();
self->exit();
}
 
 
static void entry1( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
 
// Give the other thread a chance to wait in SMP systems.
for( int i = 0; i < 100; i++ )
self->yield();
thread[0]->release();
 
s1.wait();
CYG_TEST_PASS_FINISH("Release OK");
Cyg_Thread::self()->exit();
}
 
void release_main(void)
{
CYG_TEST_INIT();
 
new_thread( entry0, 0);
new_thread( entry1, 1);
 
thread[0]->set_priority(5);
thread[1]->set_priority(6);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
 
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
release_main();
}
// EOF release.cxx
/kcache2.c
0,0 → 1,920
/*=================================================================
//
// kcache2.c
//
// Cache feature/timing tests
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jskov, based on kcache1.c by dsm
// Contributors: jskov, gthomas
// Date: 1998-12-10
// Description: Tests some of the more exotic cache macros.
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
#ifdef CYGFUN_KERNEL_API_C
 
#include <cyg/infra/diag.h>
#include <cyg/hal/hal_cache.h>
 
// -------------------------------------------------------------------------
 
#define NTHREADS 1
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
// The following are defaults for loop variables. Note they will be overriden
// on simulator targets, where detected - there is no point testing a cache
// which doesn't exist :-).
 
#define TEST_DZERO_LOOPS 5000 // default number of loops for test_dzero()
#define TIME_ILOCK_LOOPS 10000 // default number of loops for time_ilock()
#define TIME_DLOCK_LOOPS 10000 // default number of loops for time_dlock()
 
// Define this to enable a simple, but hopefully useful, data cache
// test. It may help discover if the cache support has been defined
// properly (in terms of size and shape)
#ifdef HAL_DCACHE_LINE_SIZE
#define _TEST_DCACHE_OPERATION
#endif
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
#define MAXSIZE 1<<18
 
volatile char m[MAXSIZE];
 
// -------------------------------------------------------------------------
// Test of data cache zero.
// o Timing comparison with instructions doing the same amount of work.
// o Check that area cleared with the DCACHE_ZERO macro contains zeros.
#ifdef HAL_DCACHE_ZERO
static void test_dzero(void)
{
register cyg_uint32 k, i;
cyg_tick_count_t count0, count1;
cyg_ucount32 t;
volatile cyg_uint32* aligned_p;
volatile cyg_uint32* p;
register CYG_INTERRUPT_STATE oldints;
cyg_ucount32 test_dzero_loops = TEST_DZERO_LOOPS;
 
CYG_TEST_INFO("Data cache zero");
 
if (cyg_test_is_simulator)
test_dzero_loops=10;
 
aligned_p = (volatile cyg_uint32*)
(((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
& ~(HAL_DCACHE_LINE_SIZE-1));
 
// Time with conventional instructions.
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
count0 = cyg_current_time();
for (k = 0; k < test_dzero_loops; k++) {
p = aligned_p;
for (i = 0; i < HAL_DCACHE_SETS; i++) {
#if (16 == HAL_DCACHE_LINE_SIZE)
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
#elif (32 == HAL_DCACHE_LINE_SIZE)
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
*p++ = 0;
#else
#error "Not defined for this cache line size."
#endif
}
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
}
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("time with instructions: %d\n", t);
 
// Initialize the area with non-zero so we can check whether
// the macro cleared the area properly.
p = aligned_p;
for (i = 0;
i < HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE/sizeof(cyg_uint32);
i++) {
*p++ = 0xdeadbeef;
}
 
// Time with DCACHE_ZERO.
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
count0 = cyg_current_time();
for (k = 0; k < test_dzero_loops; k++) {
HAL_DCACHE_ZERO(aligned_p, HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE);
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
}
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("time with HAL_DCACHE_ZERO: %d\n", t);
 
// Verify that the area was actually cleared.
{
cyg_uint32 d;
 
d = 0;
p = aligned_p;
for (i = 0;
i < HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE/sizeof(cyg_uint32);
i++) {
d |= *p++;
}
 
CYG_TEST_CHECK(0 == d, "region not properly cleared");
}
 
}
#endif
 
// -------------------------------------------------------------------------
// Test of data cache write hint.
// Just check that the macro compiles.
#ifdef HAL_DCACHE_WRITE_HINT
static void test_dwrite_hint(void)
{
register cyg_uint32 k;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache write hint");
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
 
HAL_DCACHE_WRITE_HINT(&m[HAL_DCACHE_LINE_SIZE*2], 2*HAL_DCACHE_LINE_SIZE);
for (k = 0; k < 20; k++);
m[HAL_DCACHE_LINE_SIZE*2] = 42;
}
#endif
 
// -------------------------------------------------------------------------
// Test of data cache read hint.
// Just check that the macro compiles.
#ifdef HAL_DCACHE_READ_HINT
static void test_dread_hint(void)
{
register char c;
register cyg_uint32 k;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache read hint");
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
 
HAL_DCACHE_READ_HINT(&m[HAL_DCACHE_LINE_SIZE*2], 2*HAL_DCACHE_LINE_SIZE);
for (k = 0; k < 20; k++);
c = m[HAL_DCACHE_LINE_SIZE*2];
}
#endif
 
// -------------------------------------------------------------------------
// Test of data cache line store
// o No semantic requirement.
// o Check that flushed data is written to memory.
// o Simple invocation check of macro.
#ifdef HAL_DCACHE_STORE
static void test_dstore(void)
{
volatile cyg_uint8* aligned_p;
cyg_int32 i;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache store region");
 
for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
m[i] = 0;
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
 
aligned_p = (volatile cyg_uint8*)
(((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
& ~(HAL_DCACHE_LINE_SIZE-1));
 
aligned_p[0] = 42 + aligned_p[1]; // Load causes cache to be used!
 
HAL_DCACHE_STORE(aligned_p, HAL_DCACHE_LINE_SIZE);
 
CYG_TEST_CHECK(42 == aligned_p[0],
"memory didn't contain flushed data");
 
HAL_DCACHE_INVALIDATE_ALL(); // Discard...
 
CYG_TEST_CHECK(42 == aligned_p[0],
"memory didn't contain flushed data after invalidate all");
 
HAL_RESTORE_INTERRUPTS(oldints);
}
#endif
 
// -------------------------------------------------------------------------
// Test of data cache total flush (sync).
// o No semantic requirement.
// o Check that flushed data is written to memory.
// o Simple invocation check of macro.
#ifdef HAL_DCACHE_LINE_SIZE // So we can find our way around memory
 
#ifdef _TEST_DCACHE_OPERATION
static void
test_dcache_operation(void)
{
long *lp = (long *)m;
int i, errs;
cyg_uint32 oldints;
 
CYG_TEST_INFO("Data cache basic");
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
// Fill test buffer
for (i = 0; i < sizeof(m)/sizeof(*lp); i++) {
lp[i] = i;
}
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
// Now push data through the cache
// Note: 256 seems like a reasonable offset. It may be useful to actually
// compute this (and the size of the test region) based on cache geometry
for (i = 256; i < 256+HAL_DCACHE_SIZE/sizeof(*lp); i++) {
lp[i] = 0xFF000000 + i;
}
// Now force cache clean and off
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
// Verify the data
diag_printf("Verify data with cache off\n");
errs = 0;
for (i = 0; i < sizeof(m)/sizeof(*lp); i++) {
if ((i >= 256) && (i < 256+HAL_DCACHE_SIZE/sizeof(*lp))) {
if (lp[i] != (0xFF000000 + i)) {
if (++errs < 16) {
diag_printf("Data inside test range changed - was: %x, is %x, index: %x\n",
0xFF000000+i, lp[i], i);
}
}
} else {
if (lp[i] != i) {
if (++errs < 16) {
diag_printf("Data outside test range changed - was: %x, is %x, index: %x\n",
i, lp[i], i);
}
}
}
}
CYG_TEST_CHECK(0 == errs, "dcache basic failed");
#if 0 // Additional information
diag_printf("%d total errors during compare\n", errs);
diag_dump_buf(&lp[240], 128);
#endif
HAL_RESTORE_INTERRUPTS(oldints);
}
#endif
 
static void test_dsync(void)
{
volatile cyg_uint8* aligned_p;
cyg_int32 i;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache sync all");
 
for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
m[i] = 0;
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
 
aligned_p = (volatile cyg_uint8*)
(((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
& ~(HAL_DCACHE_LINE_SIZE-1));
 
aligned_p[0] = 42 + aligned_p[1]; // Load causes cache to be used!
aligned_p[HAL_DCACHE_LINE_SIZE] = 43 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
 
HAL_DCACHE_SYNC();
 
CYG_TEST_CHECK(42 == aligned_p[0],
"memory didn't contain flushed data");
CYG_TEST_CHECK(43 == aligned_p[HAL_DCACHE_LINE_SIZE],
"memory didn't contain flushed data next block");
 
HAL_DCACHE_INVALIDATE_ALL();
 
CYG_TEST_CHECK(42 == aligned_p[0],
"memory didn't contain flushed data after invalidate");
CYG_TEST_CHECK(43 == aligned_p[HAL_DCACHE_LINE_SIZE],
"memory didn't contain flushed data next block after invalidate");
 
HAL_RESTORE_INTERRUPTS(oldints);
 
HAL_ICACHE_INVALIDATE_ALL();
HAL_DCACHE_DISABLE();
 
CYG_TEST_CHECK(42 == aligned_p[0],
"memory didn't contain flushed data after disable");
CYG_TEST_CHECK(43 == aligned_p[HAL_DCACHE_LINE_SIZE],
"memory didn't contain flushed data next block after disable");
 
HAL_DCACHE_ENABLE();
}
#endif // HAL_DCACHE_LINE_SIZE
 
// -------------------------------------------------------------------------
// Test of data cache line flush.
// o Requires write-back cache.
// o Check that flushed data is written to memory.
// o Simple range check of macro.
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
#ifdef HAL_DCACHE_FLUSH
static void test_dflush(void)
{
volatile cyg_uint8* aligned_p;
cyg_int32 i;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache flush region");
 
for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
m[i] = 0;
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
 
aligned_p = (volatile cyg_uint8*)
(((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
& ~(HAL_DCACHE_LINE_SIZE-1));
 
HAL_DISABLE_INTERRUPTS(oldints);
 
aligned_p[0] = 42 + aligned_p[1]; // Load causes cache to be used!
aligned_p[HAL_DCACHE_LINE_SIZE] = 43 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
 
HAL_DCACHE_FLUSH(aligned_p, HAL_DCACHE_LINE_SIZE);
 
HAL_DCACHE_DISABLE();
 
HAL_RESTORE_INTERRUPTS(oldints);
 
CYG_TEST_CHECK(42 == aligned_p[0],
"memory didn't contain flushed data");
CYG_TEST_CHECK(0 == aligned_p[HAL_DCACHE_LINE_SIZE],
"flushed beyond region");
 
HAL_DCACHE_ENABLE();
}
#endif
#endif
 
// -------------------------------------------------------------------------
// Test of data cache disable (which does NOT force contents out to RAM)
// o Requires write-back cache [so NOT invoked unconditionally]
// o Check that dirty data is not written to memory and is invalidated
// in the cache.
// o Simple invocation check of macro.
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
static void test_ddisable(void)
{
volatile cyg_uint8* aligned_p;
cyg_int32 i;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache gross disable");
 
for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
m[i] = 0;
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
 
aligned_p = (volatile cyg_uint8*)
(((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
& ~(HAL_DCACHE_LINE_SIZE-1));
 
HAL_DISABLE_INTERRUPTS(oldints);
 
aligned_p[0] = 43 + aligned_p[1]; // Load causes cache to be used!
aligned_p[HAL_DCACHE_LINE_SIZE-1] = 43;
 
aligned_p[HAL_DCACHE_LINE_SIZE] = 42 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
 
HAL_DCACHE_DISABLE();
 
HAL_RESTORE_INTERRUPTS(oldints);
 
CYG_TEST_CHECK(0 == aligned_p[0] &&
0 == aligned_p[HAL_DCACHE_LINE_SIZE-1],
"cache/memory contained invalidated data");
CYG_TEST_CHECK(0 == aligned_p[HAL_DCACHE_LINE_SIZE],
"next block contained invalidated data");
 
HAL_DCACHE_ENABLE();
}
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
 
// -------------------------------------------------------------------------
// Test of data cache total invalidate.
// o Requires write-back cache.
// o Check that invalidated data is not written to memory and is invalidated
// in the cache.
// o Simple invocation check of macro.
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
#ifdef HAL_DCACHE_INVALIDATE_ALL
static void test_dinvalidate_all(void)
{
volatile cyg_uint8* aligned_p;
cyg_int32 i;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache invalidate all");
 
for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
m[i] = 0;
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
 
aligned_p = (volatile cyg_uint8*)
(((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
& ~(HAL_DCACHE_LINE_SIZE-1));
 
aligned_p[0] = 43 + aligned_p[1]; // Load causes cache to be used!
aligned_p[HAL_DCACHE_LINE_SIZE-1] = 43;
 
aligned_p[HAL_DCACHE_LINE_SIZE] = 42 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
 
HAL_DCACHE_INVALIDATE_ALL();
 
HAL_RESTORE_INTERRUPTS(oldints);
 
CYG_TEST_CHECK(0 == aligned_p[0] &&
0 == aligned_p[HAL_DCACHE_LINE_SIZE-1],
"cache/memory contained invalidated data");
CYG_TEST_CHECK(0 == aligned_p[HAL_DCACHE_LINE_SIZE],
"next block contained invalidated data");
}
#endif
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
 
// -------------------------------------------------------------------------
// Test of data cache line invalidate.
// o Requires write-back cache.
// o Check that invalidated data is not written to memory and is invalidated
// in the cache.
// o Simple range check of macro.
#ifdef HAL_DCACHE_QUERY_WRITE_MODE // only if we know this, can we test:
#ifdef HAL_DCACHE_INVALIDATE
static void test_dinvalidate(void)
{
volatile cyg_uint8* aligned_p;
cyg_int32 i;
register CYG_INTERRUPT_STATE oldints;
 
CYG_TEST_INFO("Data cache invalidate region");
 
for (i = 0; i < HAL_DCACHE_LINE_SIZE*16; i++)
m[i] = 0;
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
 
aligned_p = (volatile cyg_uint8*)
(((unsigned long) &m[HAL_DCACHE_LINE_SIZE*2])
& ~(HAL_DCACHE_LINE_SIZE-1));
 
HAL_DISABLE_INTERRUPTS(oldints);
 
aligned_p[0] = 43 + aligned_p[1]; // Load causes cache to be used!
aligned_p[HAL_DCACHE_LINE_SIZE-1] = 43;
 
aligned_p[HAL_DCACHE_LINE_SIZE] = 42 + aligned_p[HAL_DCACHE_LINE_SIZE + 1];
 
HAL_DCACHE_INVALIDATE(aligned_p, HAL_DCACHE_LINE_SIZE);
 
HAL_RESTORE_INTERRUPTS(oldints);
 
CYG_TEST_CHECK(0 == aligned_p[0] &&
0 == aligned_p[HAL_DCACHE_LINE_SIZE-1],
"cache/memory contained invalidated data");
CYG_TEST_CHECK(42 == aligned_p[HAL_DCACHE_LINE_SIZE],
"invalidated beyond range");
 
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
 
CYG_TEST_CHECK(0 == aligned_p[0] &&
0 == aligned_p[HAL_DCACHE_LINE_SIZE-1],
"cache/memory contained invalidated data after SYNC/DIS");
CYG_TEST_CHECK(42 == aligned_p[HAL_DCACHE_LINE_SIZE],
"invalidated beyond range after SYNC/DIS");
 
HAL_DCACHE_ENABLE();
}
#endif
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
 
// -------------------------------------------------------------------------
// Test of instruction cache locking.
// o Time difference between repeatedly executing a bunch of instructions
// with and without locking.
#ifdef HAL_ICACHE_LOCK
static void iloop(unsigned long* start, unsigned long* end, int dummy)
{
// dummy is just used to fool the compiler to not move the labels
// around. All callers should call with dummy=0;
 
register char c;
register CYG_INTERRUPT_STATE oldints;
 
if (1 == dummy) goto label_end;
 
label_start:
// Invalidating shouldn't affect locked lines.
HAL_DISABLE_INTERRUPTS(oldints);
HAL_ICACHE_DISABLE();
HAL_ICACHE_INVALIDATE_ALL();
HAL_ICACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
 
c = m[HAL_DCACHE_LINE_SIZE*0];
c = m[HAL_DCACHE_LINE_SIZE*1];
c = m[HAL_DCACHE_LINE_SIZE*2];
c = m[HAL_DCACHE_LINE_SIZE*3];
c = m[HAL_DCACHE_LINE_SIZE*4];
c = m[HAL_DCACHE_LINE_SIZE*5];
c = m[HAL_DCACHE_LINE_SIZE*6];
c = m[HAL_DCACHE_LINE_SIZE*7];
c = m[HAL_DCACHE_LINE_SIZE*8];
c = m[HAL_DCACHE_LINE_SIZE*9];
c = m[HAL_DCACHE_LINE_SIZE*10];
c = m[HAL_DCACHE_LINE_SIZE*11];
c = m[HAL_DCACHE_LINE_SIZE*12];
c = m[HAL_DCACHE_LINE_SIZE*13];
c = m[HAL_DCACHE_LINE_SIZE*14];
c = m[HAL_DCACHE_LINE_SIZE*15];
c = m[HAL_DCACHE_LINE_SIZE*16];
c = m[HAL_DCACHE_LINE_SIZE*17];
c = m[HAL_DCACHE_LINE_SIZE*18];
c = m[HAL_DCACHE_LINE_SIZE*19];
c = m[HAL_DCACHE_LINE_SIZE*20];
c = m[HAL_DCACHE_LINE_SIZE*21];
c = m[HAL_DCACHE_LINE_SIZE*22];
c = m[HAL_DCACHE_LINE_SIZE*23];
c = m[HAL_DCACHE_LINE_SIZE*24];
c = m[HAL_DCACHE_LINE_SIZE*25];
c = m[HAL_DCACHE_LINE_SIZE*26];
c = m[HAL_DCACHE_LINE_SIZE*27];
c = m[HAL_DCACHE_LINE_SIZE*28];
c = m[HAL_DCACHE_LINE_SIZE*29];
c = m[HAL_DCACHE_LINE_SIZE*30];
c = m[HAL_DCACHE_LINE_SIZE*31];
c = m[HAL_DCACHE_LINE_SIZE*32];
c = m[HAL_DCACHE_LINE_SIZE*33];
c = m[HAL_DCACHE_LINE_SIZE*34];
c = m[HAL_DCACHE_LINE_SIZE*35];
c = m[HAL_DCACHE_LINE_SIZE*36];
c = m[HAL_DCACHE_LINE_SIZE*37];
c = m[HAL_DCACHE_LINE_SIZE*38];
c = m[HAL_DCACHE_LINE_SIZE*39];
c = m[HAL_DCACHE_LINE_SIZE*40];
c = m[HAL_DCACHE_LINE_SIZE*41];
c = m[HAL_DCACHE_LINE_SIZE*42];
c = m[HAL_DCACHE_LINE_SIZE*43];
c = m[HAL_DCACHE_LINE_SIZE*44];
c = m[HAL_DCACHE_LINE_SIZE*45];
c = m[HAL_DCACHE_LINE_SIZE*46];
c = m[HAL_DCACHE_LINE_SIZE*47];
c = m[HAL_DCACHE_LINE_SIZE*48];
c = m[HAL_DCACHE_LINE_SIZE*49];
c = m[HAL_DCACHE_LINE_SIZE*50];
c = m[HAL_DCACHE_LINE_SIZE*51];
c = m[HAL_DCACHE_LINE_SIZE*52];
c = m[HAL_DCACHE_LINE_SIZE*53];
c = m[HAL_DCACHE_LINE_SIZE*54];
c = m[HAL_DCACHE_LINE_SIZE*55];
c = m[HAL_DCACHE_LINE_SIZE*56];
c = m[HAL_DCACHE_LINE_SIZE*57];
c = m[HAL_DCACHE_LINE_SIZE*58];
c = m[HAL_DCACHE_LINE_SIZE*59];
c = m[HAL_DCACHE_LINE_SIZE*60];
c = m[HAL_DCACHE_LINE_SIZE*61];
c = m[HAL_DCACHE_LINE_SIZE*62];
c = m[HAL_DCACHE_LINE_SIZE*63];
 
label_end:
 
*start = (unsigned long) &&label_start;
*end = (unsigned long) &&label_end;
 
if (1 == dummy) goto label_start;
}
 
static void time_ilock(void)
{
register cyg_ucount32 k;
cyg_tick_count_t count0, count1;
cyg_ucount32 t;
unsigned long start, end;
register cyg_ucount32 time_ilock_loops = TIME_ILOCK_LOOPS;
 
CYG_TEST_INFO("Instruction cache lock");
 
if (cyg_test_is_simulator)
time_ilock_loops = 10;
 
count0 = cyg_current_time();
for (k = 0; k < time_ilock_loops; k++) {
iloop(&start, &end, 0);
}
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("time without lock: %d\n", t);
 
HAL_ICACHE_LOCK(start, end-start);
 
count0 = cyg_current_time();
for (k = 0; k < time_ilock_loops; k++) {
iloop(&start, &end, 0);
}
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("time with lock: %d\n", t);
 
HAL_ICACHE_UNLOCK(start, end-start);
}
#endif // ifdef HAL_ICACHE_LOCK
 
// -------------------------------------------------------------------------
// Test of data cache locking.
// o Time difference between repeatedly accessing a memory region
// with and without locking.
#ifdef HAL_DCACHE_LOCK
static void dloop(void)
{
register cyg_uint32 j;
register char c;
register CYG_INTERRUPT_STATE oldints;
 
HAL_DISABLE_INTERRUPTS(oldints);
HAL_DCACHE_SYNC();
HAL_DCACHE_DISABLE();
HAL_DCACHE_SYNC();
HAL_DCACHE_INVALIDATE_ALL();
HAL_DCACHE_ENABLE();
HAL_RESTORE_INTERRUPTS(oldints);
for (j = 0; j < HAL_DCACHE_SETS; j++) {
c = m[HAL_DCACHE_LINE_SIZE*j];
}
}
 
static void time_dlock(void)
{
register cyg_ucount32 k;
cyg_tick_count_t count0, count1;
cyg_ucount32 t;
register cyg_ucount32 time_dlock_loops = TIME_DLOCK_LOOPS;
 
CYG_TEST_INFO("Data cache lock");
 
if (cyg_test_is_simulator)
time_dlock_loops = 10;
 
count0 = cyg_current_time();
for (k = 0; k < time_dlock_loops; k++) {
dloop();
}
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("time without lock: %d\n", t);
 
HAL_DCACHE_LOCK(&m[0], HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE);
 
count0 = cyg_current_time();
for (k = 0; k < time_dlock_loops; k++) {
dloop();
}
count1 = cyg_current_time();
t = count1 - count0;
diag_printf("time with lock: %d\n", t);
 
HAL_DCACHE_UNLOCK(&m[0], HAL_DCACHE_SETS*HAL_DCACHE_LINE_SIZE);
}
#endif // ifdef HAL_DCACHE_LOCK
 
// -------------------------------------------------------------------------
static void entry0( cyg_addrword_t data )
{
int numtests = 0;
#ifdef HAL_DCACHE_QUERY_WRITE_MODE
int wmode;
#endif
#ifdef HAL_DCACHE_LOCK
time_dlock(); numtests++;
#endif
#ifdef HAL_ICACHE_LOCK
time_ilock(); numtests++;
#endif
#ifdef HAL_DCACHE_LINE_SIZE // So we can find our way around memory
test_dsync(); numtests++;
#endif
#ifdef HAL_DCACHE_STORE
test_dstore(); numtests++;
#endif
#ifdef _TEST_DCACHE_OPERATION
test_dcache_operation(); numtests++;
#endif
#ifdef HAL_DCACHE_READ_HINT
test_dread_hint(); numtests++;
#endif
#ifdef HAL_DCACHE_WRITE_HINT
test_dwrite_hint(); numtests++;
#endif
#ifdef HAL_DCACHE_ZERO
test_dzero(); numtests++;
#endif
 
// The below tests only work on a copy-back cache.
#ifdef HAL_DCACHE_QUERY_WRITE_MODE
HAL_DCACHE_QUERY_WRITE_MODE( wmode );
if ( HAL_DCACHE_WRITEBACK_MODE == wmode ) {
test_ddisable(); numtests++;
#ifdef HAL_DCACHE_INVALIDATE
test_dinvalidate_all(); numtests++;
#endif
#ifdef HAL_DCACHE_FLUSH
test_dflush(); numtests++;
#endif
#ifdef HAL_DCACHE_INVALIDATE
test_dinvalidate(); numtests++;
#endif
}
#endif // def HAL_DCACHE_QUERY_WRITE_MODE
if ( numtests ) {
CYG_TEST_PASS_FINISH("End of test");
}
else {
CYG_TEST_NA( "No applicable cache tests" );
}
}
 
// -------------------------------------------------------------------------
 
void kcache2_main( void )
{
CYG_TEST_INIT();
 
cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kcache2",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_scheduler_start();
}
 
// -------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
kcache2_main();
}
 
// -------------------------------------------------------------------------
 
#else // def CYGFUN_KERNEL_API_C
#define N_A_MSG "Kernel C API layer disabled"
#endif // def CYGFUN_KERNEL_API_C
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
#define N_A_MSG "Kernel real-time clock disabled"
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
#ifdef N_A_MSG
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( N_A_MSG );
}
#endif // N_A_MSG
 
// -------------------------------------------------------------------------
/* EOF kcache2.c */
/kmutex3.c
0,0 → 1,638
//==========================================================================
//
// kmutex3.c
//
// Mutex test 3 - priority inheritance
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors: hmt
// Date: 2000-01-06, 2001-08-10
// Description: Tests mutex priority inheritance. This is simply a
// translation of the similarly named kernel test to the
// KAPI, with the intention of also testing the new
// "set the protocol at run-time" extensions.
//####DESCRIPTIONEND####
 
#include <pkgconf/hal.h>
#include <pkgconf/kernel.h>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/infra/diag.h> // diag_printf
 
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
// ------------------------------------------------------------------------
//
// These checks should be enough; any other scheduler which has priorities
// should manifest as having no priority inheritance, but otherwise fine,
// so the test should work correctly.
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) && \
defined(CYGFUN_KERNEL_API_C) && \
!defined(CYGPKG_KERNEL_SMP_SUPPORT)
 
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/cyg_trac.h>
#include <cyg/infra/diag.h> // diag_printf
 
 
// ------------------------------------------------------------------------
// manufacture a simpler feature test macro for priority inheritance than
// the configuration gives us. We have priority inheritance if it is configured
// as the only protocol, or if it is the default protocol for dynamic protocol
// choice.
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_INHERIT
# define PRIORITY_INHERITANCE "dynamic-default-inherit"
# endif
# else
# define PRIORITY_INHERITANCE "static-inherit"
# endif
#endif
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_CEILING
# if CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY <= 5
# define PRIORITY_INHERITANCE "dynamic-default-ceiling-high"
# elif CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY >= 15
# define NO_PRIORITY_INHERITANCE "dynamic-default-ceiling-low"
# else
# define PRIORITY_UNKNOWN "dynamic-default-ceiling-mid"
# endif
# endif
# else
# if CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY <= 5
# define PRIORITY_INHERITANCE "static-ceiling-high"
# elif CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY >= 15
# define NO_PRIORITY_INHERITANCE "static-ceiling-low"
# else
# define PRIORITY_UNKNOWN "static-ceiling-mid"
# endif
# endif
#endif
 
#ifndef PRIORITY_INHERITANCE
# ifndef NO_PRIORITY_INHERITANCE
# define NO_PRIORITY_INHERITANCE "no scheme selected"
# endif
#endif
 
// ------------------------------------------------------------------------
// Management functions
//
// Stolen from testaux.hxx and copied in here because I want to be able to
// reset the world also.
//
// Translated into KAPI also.
 
#define NTHREADS 7
 
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS] = { 0 };
 
typedef cyg_uint64 CYG_ALIGNMENT_TYPE;
 
static cyg_thread thread_obj[NTHREADS];
 
static CYG_ALIGNMENT_TYPE stack[NTHREADS] [
(STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1)
/ sizeof(CYG_ALIGNMENT_TYPE) ];
 
static volatile int nthreads = 0;
 
#undef NULL
#define NULL (0)
 
static cyg_handle_t new_thread( cyg_thread_entry_t *entry,
cyg_addrword_t data,
cyg_addrword_t priority,
int do_resume )
{
int _nthreads = nthreads++;
 
CYG_ASSERT(_nthreads < NTHREADS,
"Attempt to create more than NTHREADS threads");
 
cyg_thread_create( priority,
entry,
data,
NULL, // no name
(void *)(stack[_nthreads]),
STACKSIZE,
&thread[_nthreads],
&thread_obj[_nthreads] );
 
if ( do_resume )
cyg_thread_resume( thread[_nthreads] );
 
return thread[_nthreads];
}
 
 
static void kill_threads( void )
{
CYG_ASSERT(nthreads <= NTHREADS,
"More than NTHREADS threads");
CYG_ASSERT( cyg_thread_self() == thread[0],
"kill_threads() not called from thread 0");
while ( nthreads > 1 ) {
nthreads--;
if ( NULL != thread[nthreads] ) {
do
cyg_thread_kill( thread[nthreads] );
while ( ! cyg_thread_delete ( thread[nthreads] ) );
thread[nthreads] = NULL;
}
}
CYG_ASSERT(nthreads == 1,
"No threads left");
}
 
// ------------------------------------------------------------------------
 
#define DELAYFACTOR 1 // for debugging
 
// ------------------------------------------------------------------------
 
static cyg_mutex_t mutex_obj;
static cyg_mutex_t *mutex;
 
// These are for reporting back to the master thread
volatile int got_it = 0;
volatile int t3ran = 0;
volatile int t3ended = 0;
volatile int extras[4] = {0,0,0,0};
volatile int go_flag = 0; // but this one controls thread 3 from thread 2
 
// ------------------------------------------------------------------------
// 0 to 3 of these run generally to interfere with the other processing,
// to cause multiple prio inheritances, and clashes in any orders.
 
static void extra_thread( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
 
#define XINFO( z ) \
do { z[13] = '0' + data; CYG_TEST_INFO( z ); } while ( 0 )
 
static char running[] = "Extra thread Xa running";
static char exiting[] = "Extra thread Xa exiting";
static char resumed[] = "Extra thread Xa resumed";
static char locked[] = "Extra thread Xa locked";
static char unlocked[] = "Extra thread Xa unlocked";
 
XINFO( running );
 
cyg_thread_suspend( self );
 
XINFO( resumed );
 
cyg_mutex_lock( mutex );
 
XINFO( locked );
 
cyg_mutex_unlock( mutex );
 
XINFO( unlocked );
 
extras[ data ] ++;
 
XINFO( exiting );
 
}
 
// ------------------------------------------------------------------------
 
static void t1( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
 
CYG_TEST_INFO( "Thread 1 running" );
 
cyg_thread_suspend( self );
 
cyg_mutex_lock( mutex );
 
got_it++;
 
CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,1]" );
 
cyg_mutex_unlock( mutex );
 
CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,2]" );
 
// That's all.
 
CYG_TEST_INFO( "Thread 1 exit" );
}
 
// ------------------------------------------------------------------------
 
static void t2( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
int i;
cyg_tick_count_t then, now;
 
CYG_TEST_INFO( "Thread 2 running" );
 
CYG_TEST_CHECK( 0 == (data & ~0x77), "Bad T2 arg: extra bits" );
CYG_TEST_CHECK( 0 == (data & (data >> 4)), "Bad T2 arg: overlap" );
 
cyg_thread_suspend( self );
 
// depending on our config argument, optionally restart some of the
// extra threads to throw noise into the scheduler:
for ( i = 0; i < 3; i++ )
if ( (1 << i) & data ) // bits 0-2 control
cyg_thread_resume( thread[i+4] ); // extras are thread[4-6]
 
cyg_thread_delay( DELAYFACTOR * 10 ); // let those threads run
 
cyg_scheduler_lock(); // do this next lot atomically
 
go_flag = 1; // unleash thread 3
cyg_thread_resume( thread[1] ); // resume thread 1
 
// depending on our config argument, optionally restart some of the
// extra threads to throw noise into the scheduler at this later point:
for ( i = 4; i < 7; i++ )
if ( (1 << i) & data ) // bits 4-6 control
cyg_thread_resume( thread[i] ); // extras are thread[4-6]
 
cyg_scheduler_unlock(); // let scheduling proceed
 
// Need a delay (but not a CPU yield) to allow t3 to awaken and act on
// the go_flag, otherwise we check these details below too soon.
// Actually, waiting for the clock to tick a couple of times would be
// better, so that is what we will do. Must be a busy-wait.
then = cyg_current_time();
do {
now = cyg_current_time();
// Wait longer than the delay in t3 waiting on go_flag
} while ( now < (then + 3) );
 
#ifdef PRIORITY_UNKNOWN
CYG_TEST_INFO( "Not checking: " PRIORITY_UNKNOWN );
#else
#ifdef PRIORITY_INHERITANCE
CYG_TEST_INFO( "Checking priority scheme: " PRIORITY_INHERITANCE );
CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
#else
CYG_TEST_INFO( "Checking NO priority scheme: " NO_PRIORITY_INHERITANCE );
CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" );
CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" );
#endif
#endif
 
CYG_TEST_CHECK( 0 == t3ended, "Thread 3 ended prematurely [T2,1]" );
 
cyg_thread_delay( DELAYFACTOR * 20 ); // let those threads run
 
CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
CYG_TEST_CHECK( 1 == t3ended, "Thread 3 has not ended" );
 
for ( i = 0; i < 3; i++ )
if ( (1 << i) & (data | data >> 4) ) // bits 0-2 and 4-6 control
CYG_TEST_CHECK( 1 == extras[i+1], "Extra thread did not run" );
else
CYG_TEST_CHECK( 0 == extras[i+1], "Extra thread ran" );
 
CYG_TEST_PASS( "Thread 2 exiting, AOK" );
// That's all: restart the control thread.
cyg_thread_resume( thread[0] );
}
 
// ------------------------------------------------------------------------
 
static void t3( cyg_addrword_t data )
{
CYG_TEST_INFO( "Thread 3 running" );
 
cyg_mutex_lock( mutex );
 
cyg_thread_delay( DELAYFACTOR * 5 ); // let thread 3a run
 
cyg_thread_resume( thread[2] ); // resume thread 2
 
while ( 0 == go_flag )
cyg_thread_delay(1); // wait until we are told to go
 
t3ran ++; // record the fact
 
CYG_TEST_CHECK( 0 == got_it, "Thread 1 claims to have got my mutex" );
cyg_mutex_unlock( mutex );
t3ended ++; // record that we came back
 
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
 
CYG_TEST_INFO( "Thread 3 exit" );
}
 
// ------------------------------------------------------------------------
 
static void control_thread( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
int i, z;
 
CYG_TEST_INIT();
CYG_TEST_INFO( "Control Thread running" );
 
// Go through the 27 possibilities of resuming the extra threads
// 0: not at all
// 1: early in the process
// 2: later on
// which are represented by bits 0-3 and 4-6 resp in the argument to
// thread 2 (none set means no resume at all).
for ( i = 0; i < 27; i++ ) {
static int xx[] = { 0, 1, 16 };
int j = i % 3;
int k = (i / 3) % 3;
int l = (i / 9) % 3;
 
int d = xx[j] | (xx[k]<<1) | (xx[l]<<2) ;
 
if ( cyg_test_is_simulator && (0 != i && 13 != i && 26 != i) )
continue; // 13 is 111 base 3, 26 is 222 base 3
 
#ifdef PRIORITY_INHERITANCE
// If the simple scheme plus relay enhancement, or any other
// *complete* scheme, we can run all three ancillary threads no
// problem, so no special action here.
 
#else
// If no priority inheritance at all, running threads 1a and 2a is
// OK, but not thread 3a; it blocks the world.
if ( l ) // Cannot run thread 3a if no
break; // priority inheritance at all.
#endif
 
mutex = &mutex_obj;
cyg_mutex_init( mutex );
 
got_it = 0;
t3ran = 0;
t3ended = 0;
for ( z = 0; z < 4; z++ ) extras[z] = 0;
go_flag = 0;
new_thread( t1, 0, 5, 1 ); // Slot 1
new_thread( t2, d, 10, 1 ); // Slot 2
new_thread( t3, 0, 15, 1 ); // Slot 3
new_thread( extra_thread, 1, 8, j ); // Slot 4
new_thread( extra_thread, 2, 12, k ); // Slot 5
new_thread( extra_thread, 3, 17, l ); // Slot 6
{
static char *a[] = { "inactive", "run early", "run late" };
diag_printf( "\n----- [%2d] New Cycle: 0x%02x, Threads 1a %s, 2a %s, 3a %s -----\n",
i, d, a[j], a[k], a[l] );
}
 
cyg_thread_suspend( self );
kill_threads();
cyg_mutex_destroy( mutex );
}
CYG_TEST_EXIT( "Control Thread exit" );
}
 
// ------------------------------------------------------------------------
 
externC void
cyg_user_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
new_thread( control_thread, 0, 2, 1 );
}
 
#else // CYGVAR_KERNEL_COUNTERS_CLOCK &c
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_PASS_FINISH("KMutex3 test requires:\n"
"CYGFUN_KERNEL_API_C &&\n"
"CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
"(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) &&\n"
"!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
}
#endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c
 
 
// ------------------------------------------------------------------------
// Documentation: enclosed is the design of this test.
//
// It has been carefully constructed so that it does NOT use other kernel
// facilities (aside from delay-task) to test that priority inheritance is
// working, or not, as intended by the configuration.
//
// These notes describe the flow of control in one run of the test with the
// ancillary tasks optionally interspersed. The details of how those extra
// tasks are or are not allowed to run are not described.
//
//
//
// The only change in the test that depends on whether there is inheritance or
// not is the check in thread 2 on "3-ran" and "got it" flags marked ****
//
//
// volatile &c booleans:
// "got it" = FALSE
// "3-ran" = FALSE
// "3-ended" = FALSE
// "extras"[3] = FALSE
//
// thread 1. prio 5, self-suspend.
//
// thread 1a, prio 8, self-suspend.
//
// thread 2. prio 10, self-suspend.
//
// thread 2a, prio 12, self-suspend.
//
// thread 3. prio 15, runs, lock mutex, resume(2)
//
// thread 3a, prio 17, self-suspend.
//
// 2. runs,
// 2. resume(3a) +++OPTIONAL
// 2. resume(2a) +++OPTIONAL
// 2. resume(1a) +++OPTIONAL
// [1a lock-fail] thread 3->prio := 8
//
// [3. runs maybe, does the looping thing]
//
// 2. sleep a while...
//
// [2a lock-fail] thread 3->prio := 12
//
// [3. runs maybe, does the looping thing]
//
// [3a lock-fail] thread 3->prio unchanged
//
// [3. runs maybe, does the looping thing]
//
// 2. lock scheduler
// 2. set "go-flag"
// 2. resume(1)
// 2. resume(1a) +++OPTIONAL
// 2. resume(2a) +++OPTIONAL
// 2. resume(3a) +++OPTIONAL
// 2. unlock scheduler
//
// 1. runs, lock mutex - thread 3 has it locked
//
// 2. busy-waits a bit for thread 3 to come out of its delay() loop.
// This must be a *busy*wait so that 3 can only run via the
// inherited raised priority.
//
// [xa. all do the same: lock mutex, ]
// [xa. unlock mutex ]
// [xa. set a flag "extras"[x] to say we are done. ]
// [xa. exit ]
//
//
//
// INHERIT
// -------
//
// thread 3->prio := 5
//
// 3. runs,
// 3. set a flag to say "3-ran",
// 3. loop with a sleep(1) until "go-flag" is set.
// 3. check "got it" is false,
// 3. then unlock mutex,
//
// thread 3->prio := 15
//
// 1. runs, set a flag to say "got it",
// 1. check "3-ended" flag is false
// 1. unlock mutex,
// 1. check "3-ended" flag is still false
// 1. exit.
//
// [1a locks, unlocks, exits]
//
// 2. runs, check "3-ran" and "got it" flags are TRUE ****
// 2. check "3-ended" flag is false
// 2. sleeps for a while so that...
//
// [2a locks, unlocks, exits]
//
// 3. runs, set "3-ended" flag,
// 3. check "3-ran" and "got it" flags
// 3. exit
//
// [3a locks, unlocks, exits]
//
// 2. awakens, checks all flags true,
// 2. check that all "extra" threads that we started have indeed run
// 2. end of test.
//
//
//
//
// NO-INHERIT
// ----------
// thread 1 is waiting on the mutex
//
// [1a lock-fail]
//
// 2. runs, checks that "3-ran" and "got it" flags are FALSE ****
// 2. check "3-ended" flag is false
// 2. sleeps for a while so that...
//
// [2a. lock-fail]
//
// 3. runs, set a flag to say "3-ran",
// 3. check "got it" is false,
// 3. then unlock mutex,
//
// 1. runs, set a flag to say "got it",
// 1. check "3-ended" flag is false
// 1. unlock mutex,
// 1. check "3-ended" flag is still false
// 1. exit.
//
// [1a locks, unlocks, exits]
// [2a locks, unlocks, exits]
//
// 3. runs, set "3-ended" flag,
// 3. check "3-ran" and "got it" flags
// 3. exit
//
// [3a locks, unlocks, exits]
//
// 2. awakens, checks all flags true,
// 2. check that all "extra" threads that we started have indeed run
// 2. end of test.
//
//
// (the end)
//
//
// ------------------------------------------------------------------------
 
// EOF mutex3.c
/kmutex4.c
0,0 → 1,525
//==========================================================================
//
// kmutex4.c
//
// Mutex test 4 - dynamic priority inheritance protocol
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors: hmt
// Date: 2000-01-06, 2001-08-10, 2001-08-21
// Description: Tests mutex priority inheritance. This is an extension of
// kmutex3.c, to test the new "set the protocol at run-time"
// extensions.
//####DESCRIPTIONEND####
 
#include <pkgconf/hal.h>
#include <pkgconf/kernel.h>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/infra/diag.h> // diag_printf
 
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
// ------------------------------------------------------------------------
//
// These checks should be enough; any other scheduler which has priorities
// should manifest as having no priority inheritance, but otherwise fine,
// so the test should work correctly.
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) && \
defined(CYGFUN_KERNEL_API_C) && \
!defined(CYGPKG_KERNEL_SMP_SUPPORT) && \
defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC) \
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/cyg_trac.h>
#include <cyg/infra/diag.h> // diag_printf
 
// ------------------------------------------------------------------------
 
#define nVERBOSE
 
// ------------------------------------------------------------------------
// We have dynamic protocol choice, so we can set the protocol to whatever
// we want. We'll do these combinations:
// NONE
// INHERIT
// CEILING = 4 = higher than any thread === INHERIT in behaviour
// CEILING = 11 = mixed in with threads === cannot check anything
// CEILING = 17 = lower than any threads === NONE in behaviour
 
#define PROTO_NONE (0)
#define PROTO_INHERIT (1)
#define PROTO_CEILING_HIGH (2)
#define PROTO_CEILING_MID (3)
#define PROTO_CEILING_LOW (4)
 
int proto;
 
static char * protnames[] = {
"none",
"inherit",
"high ceiling",
"medium ceiling",
"low ceiling",
};
 
// ------------------------------------------------------------------------
// Management functions
//
// Stolen from testaux.hxx and copied in here because I want to be able to
// reset the world also.
//
// Translated into KAPI also.
 
#define NTHREADS 7
 
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS] = { 0 };
 
typedef cyg_uint64 CYG_ALIGNMENT_TYPE;
 
static cyg_thread thread_obj[NTHREADS];
 
static CYG_ALIGNMENT_TYPE stack[NTHREADS] [
(STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1)
/ sizeof(CYG_ALIGNMENT_TYPE) ];
 
static volatile int nthreads = 0;
 
#undef NULL
#define NULL (0)
 
static cyg_handle_t new_thread( cyg_thread_entry_t *entry,
cyg_addrword_t data,
cyg_addrword_t priority,
int do_resume,
char *name )
{
int _nthreads = nthreads++;
 
CYG_ASSERT(_nthreads < NTHREADS,
"Attempt to create more than NTHREADS threads");
 
cyg_thread_create( priority,
entry,
data,
name,
(void *)(stack[_nthreads]),
STACKSIZE,
&thread[_nthreads],
&thread_obj[_nthreads] );
 
if ( do_resume )
cyg_thread_resume( thread[_nthreads] );
 
return thread[_nthreads];
}
 
 
static void kill_threads( void )
{
CYG_ASSERT(nthreads <= NTHREADS,
"More than NTHREADS threads");
CYG_ASSERT( cyg_thread_self() == thread[0],
"kill_threads() not called from thread 0");
while ( nthreads > 1 ) {
nthreads--;
if ( NULL != thread[nthreads] ) {
do
cyg_thread_kill( thread[nthreads] );
while ( ! cyg_thread_delete ( thread[nthreads] ) );
thread[nthreads] = NULL;
}
}
CYG_ASSERT(nthreads == 1,
"No threads left");
}
 
// ------------------------------------------------------------------------
 
#define DELAYFACTOR 1 // for debugging
 
// ------------------------------------------------------------------------
 
static cyg_mutex_t mutex_obj;
static cyg_mutex_t *mutex;
 
// These are for reporting back to the master thread
volatile int got_it = 0;
volatile int t3ran = 0;
volatile int t3ended = 0;
volatile int extras[4] = {0,0,0,0};
volatile int go_flag = 0; // but this one controls thread 3 from thread 2
 
// ------------------------------------------------------------------------
// 0 to 3 of these run generally to interfere with the other processing,
// to cause multiple prio inheritances, and clashes in any orders.
 
static void extra_thread( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
 
 
#ifdef VERBOSE
#define xXINFO( z ) \
do { z[13] = '0' + data; CYG_TEST_INFO( z ); } while ( 0 )
 
static char running[] = "Extra thread Xa running";
static char exiting[] = "Extra thread Xa exiting";
static char resumed[] = "Extra thread Xa resumed";
static char locked[] = "Extra thread Xa locked";
static char unlocked[] = "Extra thread Xa unlocked";
#else
#define XINFO( z ) /* nothing */
#endif
 
XINFO( running );
 
cyg_thread_suspend( self );
 
XINFO( resumed );
 
cyg_mutex_lock( mutex );
 
XINFO( locked );
 
cyg_mutex_unlock( mutex );
 
XINFO( unlocked );
 
extras[ data ] ++;
 
XINFO( exiting );
 
}
 
// ------------------------------------------------------------------------
 
static void t1( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
#ifdef VERBOSE
CYG_TEST_INFO( "Thread 1 running" );
#endif
cyg_thread_suspend( self );
 
cyg_mutex_lock( mutex );
 
got_it++;
 
CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,1]" );
 
cyg_mutex_unlock( mutex );
 
CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,2]" );
 
// That's all.
#ifdef VERBOSE
CYG_TEST_INFO( "Thread 1 exit" );
#endif
}
 
// ------------------------------------------------------------------------
 
static void t2( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
int i;
cyg_tick_count_t then, now;
#ifdef VERBOSE
CYG_TEST_INFO( "Thread 2 running" );
#endif
CYG_TEST_CHECK( 0 == (data & ~0x77), "Bad T2 arg: extra bits" );
CYG_TEST_CHECK( 0 == (data & (data >> 4)), "Bad T2 arg: overlap" );
 
cyg_thread_suspend( self );
 
// depending on our config argument, optionally restart some of the
// extra threads to throw noise into the scheduler:
for ( i = 0; i < 3; i++ )
if ( (1 << i) & data ) // bits 0-2 control
cyg_thread_resume( thread[i+4] ); // extras are thread[4-6]
 
cyg_thread_delay( DELAYFACTOR * 10 ); // let those threads run
 
cyg_scheduler_lock(); // do this next lot atomically
 
go_flag = 1; // unleash thread 3
cyg_thread_resume( thread[1] ); // resume thread 1
 
// depending on our config argument, optionally restart some of the
// extra threads to throw noise into the scheduler at this later point:
for ( i = 4; i < 7; i++ )
if ( (1 << i) & data ) // bits 4-6 control
cyg_thread_resume( thread[i] ); // extras are thread[4-6]
 
cyg_scheduler_unlock(); // let scheduling proceed
 
// Need a delay (but not a CPU yield) to allow t3 to awaken and act on
// the go_flag, otherwise we check these details below too soon.
// Actually, waiting for the clock to tick a couple of times would be
// better, so that is what we will do. Must be a busy-wait.
then = cyg_current_time();
do {
now = cyg_current_time();
// Wait longer than the delay in t3 waiting on go_flag
} while ( now < (then + 3) );
 
// Check for whatever result we expect from the protocol selected:
// This mirrors what is done in configury in kmutex3.c and mutex3.cxx
if ( PROTO_CEILING_MID == proto ) {
CYG_TEST_INFO( "Not checking: ceiling mid value" );
}
else if ( PROTO_INHERIT == proto ||
PROTO_CEILING_HIGH == proto ) {
CYG_TEST_INFO( "Checking priority scheme operating" );
CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
}
else {
CYG_TEST_INFO( "Checking NO priority scheme operating" );
CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" );
CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" );
}
 
CYG_TEST_CHECK( 0 == t3ended, "Thread 3 ended prematurely [T2,1]" );
 
cyg_thread_delay( DELAYFACTOR * 20 ); // let those threads run
 
CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
CYG_TEST_CHECK( 1 == t3ended, "Thread 3 has not ended" );
 
for ( i = 0; i < 3; i++ )
if ( (1 << i) & (data | data >> 4) ) // bits 0-2 and 4-6 control
CYG_TEST_CHECK( 1 == extras[i+1], "Extra thread did not run" );
else
CYG_TEST_CHECK( 0 == extras[i+1], "Extra thread ran" );
 
CYG_TEST_PASS( "Thread 2 exiting, AOK" );
// That's all: restart the control thread.
cyg_thread_resume( thread[0] );
}
 
// ------------------------------------------------------------------------
 
static void t3( cyg_addrword_t data )
{
#ifdef VERBOSE
CYG_TEST_INFO( "Thread 3 running" );
#endif
cyg_mutex_lock( mutex );
 
cyg_thread_delay( DELAYFACTOR * 5 ); // let thread 3a run
 
cyg_thread_resume( thread[2] ); // resume thread 2
 
while ( 0 == go_flag )
cyg_thread_delay(1); // wait until we are told to go
 
t3ran ++; // record the fact
 
CYG_TEST_CHECK( 0 == got_it, "Thread 1 claims to have got my mutex" );
cyg_mutex_unlock( mutex );
t3ended ++; // record that we came back
 
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
#ifdef VERBOSE
CYG_TEST_INFO( "Thread 3 exit" );
#endif
}
 
// ------------------------------------------------------------------------
 
static void control_thread( cyg_addrword_t data )
{
cyg_handle_t self = cyg_thread_self();
int i, z;
 
CYG_TEST_INIT();
CYG_TEST_INFO( "Control Thread running" );
 
// Go through the 27 possibilities of resuming the extra threads
// 0: not at all
// 1: early in the process
// 2: later on
// which are represented by bits 0-3 and 4-6 resp in the argument to
// thread 2 (none set means no resume at all).
for ( i = 0; i < 27; i++ ) {
static int xx[] = { 0, 1, 16 };
int j = i % 3;
int k = (i / 3) % 3;
int l = (i / 9) % 3;
 
int d = xx[j] | (xx[k]<<1) | (xx[l]<<2) ;
 
if ( cyg_test_is_simulator && (0 != i && 13 != i && 26 != i) )
continue; // 13 is 111 base 3, 26 is 222 base 3
 
// Go through all these priority inversion prevention protocols:
// (if supported in this configuration)
// PROTO_NONE (0)
// PROTO_INHERIT (1)
// PROTO_CEILING_HIGH (2)
// PROTO_CEILING_MID (3)
// PROTO_CEILING_LOW (4)
for ( proto = PROTO_NONE; proto <= PROTO_CEILING_LOW; proto++ ) {
 
// If no priority inheritance at all, running threads 1a and 2a is
// OK, but not thread 3a; it blocks the world.
if ( PROTO_NONE == proto ||
PROTO_CEILING_MID == proto ||
PROTO_CEILING_LOW == proto )
if ( l ) // Cannot run thread 3a if no
continue; // priority inheritance at all.
 
mutex = &mutex_obj;
switch ( proto ) {
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_NONE
case PROTO_NONE:
cyg_mutex_init( mutex );
cyg_mutex_set_protocol( mutex, CYG_MUTEX_NONE );
break;
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
case PROTO_INHERIT:
cyg_mutex_init( mutex );
cyg_mutex_set_protocol( mutex, CYG_MUTEX_INHERIT );
break;
#endif
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
case PROTO_CEILING_HIGH:
cyg_mutex_init( mutex );
cyg_mutex_set_protocol( mutex, CYG_MUTEX_CEILING );
cyg_mutex_set_ceiling( mutex, (cyg_priority_t) 4 );
break;
case PROTO_CEILING_MID:
cyg_mutex_init( mutex );
cyg_mutex_set_protocol( mutex, CYG_MUTEX_CEILING );
cyg_mutex_set_ceiling( mutex, (cyg_priority_t) 11 );
break;
case PROTO_CEILING_LOW:
cyg_mutex_init( mutex );
cyg_mutex_set_protocol( mutex, CYG_MUTEX_CEILING );
cyg_mutex_set_ceiling( mutex, (cyg_priority_t) 17 );
break;
#endif
default:
continue; // Break out of the prio for loop - do nothing
}
 
got_it = 0;
t3ran = 0;
t3ended = 0;
for ( z = 0; z < 4; z++ ) extras[z] = 0;
go_flag = 0;
new_thread( t1, 0, 5, 1, "test 1" ); // Slot 1
new_thread( t2, d, 10, 1, "test 2" ); // Slot 2
new_thread( t3, 0, 15, 1, "test 3" ); // Slot 3
new_thread( extra_thread, 1, 8, j, "extra 1" ); // Slot 4
new_thread( extra_thread, 2, 12, k, "extra 2" ); // Slot 5
new_thread( extra_thread, 3, 17, l, "extra 3" ); // Slot 6
{
static char *a[] = { "inactive", "run early", "run late" };
diag_printf( "\n----- %s [%2d] New Cycle: 0x%02x, Threads 1a %s, 2a %s, 3a %s -----\n",
protnames[proto], i, d, a[j], a[k], a[l] );
}
 
cyg_thread_suspend( self );
kill_threads();
cyg_mutex_destroy( mutex );
}
}
CYG_TEST_EXIT( "Control Thread exit" );
}
 
// ------------------------------------------------------------------------
 
externC void
cyg_user_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
new_thread( control_thread, 0, 2, 1, "control thread" );
}
 
#else // CYGVAR_KERNEL_COUNTERS_CLOCK &c
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_PASS_FINISH("KMutex4 test requires:\n"
"CYGFUN_KERNEL_API_C &&\n"
"CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
"(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) &&\n"
"!defined(CYGPKG_KERNEL_SMP_SUPPORT) &&\n"
"defined(CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC)\n"
);
}
#endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c
 
 
// ------------------------------------------------------------------------
// Documentation: enclosed is the design of this test.
//
// See mutex3.cxx or kmutex3.c
 
// ------------------------------------------------------------------------
// EOF mutex4.c
/kmbox1.c
0,0 → 1,217
/*==========================================================================
//
// kmbox1.cxx
//
// Kernel Mbox test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author: dsm
// Contributors: dsm
// Date: 1998-06-02
// Description: Tests basic mbox functionality.
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
#define NTHREADS 2
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
static cyg_handle_t m0, m1, m2;
static cyg_mbox mbox0, mbox1, mbox2;
 
static cyg_atomic q = 0;
 
#ifndef CYGMTH_MBOX_PUT_CAN_WAIT
#define cyg_mbox_PUT cyg_mbox_tryput
#endif
 
static void entry0( cyg_addrword_t data )
{
cyg_count8 u,i,j;
 
CYG_TEST_INFO("Testing put() and tryput() without wakeup");
CYG_TEST_CHECK(!cyg_mbox_waiting_to_get(m0), "mbox not initialized properly");
CYG_TEST_CHECK(0==cyg_mbox_peek(m0), "mbox not initialized properly");
CYG_TEST_CHECK(NULL==cyg_mbox_peek_item(m0), "mbox not initialized properly");
cyg_mbox_PUT(m0, (void *)55);
CYG_TEST_CHECK(1==cyg_mbox_peek(m0), "peek() wrong");
CYG_TEST_CHECK(55==(cyg_count8)cyg_mbox_peek_item(m0), "peek_item() wrong");
for(u=1; cyg_mbox_tryput(m0, (void*)u); u++) {
CYG_TEST_CHECK(55==(cyg_count8)cyg_mbox_peek_item(m0), "peek_item() wrong");
CYG_TEST_CHECK(u+1==cyg_mbox_peek(m0), "peek() wrong");
}
CYG_TEST_CHECK(u == CYGNUM_KERNEL_SYNCH_MBOX_QUEUE_SIZE, "mbox not configured size");
 
// m0 now contains ( 55 1 2 .. u-1 )
CYG_TEST_CHECK(u==cyg_mbox_peek(m0), "peek() wrong");
CYG_TEST_CHECK(55==(cyg_count8)cyg_mbox_peek_item(m0), "peek_item() wrong");
 
CYG_TEST_INFO("Testing get(), tryget()");
i = (cyg_count8)cyg_mbox_tryget(m0);
CYG_TEST_CHECK( 55 == i, "Got wrong message" );
for(j=1; j<u;j++) {
CYG_TEST_CHECK( j == (cyg_count8)cyg_mbox_peek_item(m0), "peek_item()" );
CYG_TEST_CHECK( cyg_mbox_peek(m0) == u - j, "peek() wrong" );
i = (cyg_count8)cyg_mbox_get(m0);
CYG_TEST_CHECK( j == i, "Got wrong message" );
}
CYG_TEST_CHECK( NULL == cyg_mbox_peek_item(m0), "peek_item()" );
CYG_TEST_CHECK( 0 == cyg_mbox_peek(m0), "peek()");
// m0 now empty
 
CYG_TEST_CHECK(!cyg_mbox_waiting_to_put(m0), "waiting_to_put()");
CYG_TEST_CHECK(!cyg_mbox_waiting_to_get(m0), "waiting_to_get()");
 
CYG_TEST_INFO("Testing get(), blocking");
CYG_TEST_CHECK(0==q++, "bad synchronization");
cyg_mbox_PUT(m1, (void*)99); // wakes t1
i = (cyg_count8)cyg_mbox_get(m0); // sent by t1
CYG_TEST_CHECK(3==i, "Recieved wrong message");
CYG_TEST_CHECK(2==q++, "bad synchronization");
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
CYG_TEST_CHECK(NULL==cyg_mbox_timed_get(m0, cyg_current_time()+10),
"unexpectedly found message");
CYG_TEST_CHECK(3==q++, "bad synchronization");
// Allow t1 to run as this get times out
// t1 must not be waiting...
CYG_TEST_CHECK(cyg_mbox_waiting_to_get(m0), "waiting_to_get()");
 
cyg_mbox_PUT(m0, (void*)7); // wake t1 from timed get
#ifdef CYGMTH_MBOX_PUT_CAN_WAIT
q=10;
while(cyg_mbox_tryput(m0, (void*)6)) // fill m0's queue
;
// m0 now contains ( 6 ... 6 )
CYG_TEST_CHECK(10==q++, "bad synchronization");
cyg_mbox_put(m1, (void*)4); // wake t1
CYG_TEST_CHECK(!cyg_mbox_timed_put(m0, (void*)8, cyg_current_time()+10),
"timed put() unexpectedly worked");
CYG_TEST_CHECK(12==q++, "bad synchronization");
// m0 still contains ( 6 ... 6 )
cyg_mbox_put(m0, (void*)9);
CYG_TEST_CHECK(13==q++, "bad synchronization");
#endif
#endif
i=(cyg_count8)cyg_mbox_get(m2);
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry1( cyg_addrword_t data )
{
cyg_count8 i;
i = (cyg_count8)cyg_mbox_get(m1);
CYG_TEST_CHECK(1==q++, "bad synchronization");
cyg_mbox_PUT(m0, (void *)3); // wake t0
 
#if defined(CYGFUN_KERNEL_THREADS_TIMER)
CYG_TEST_INFO("Testing timed functions");
CYG_TEST_CHECK(7==(cyg_count8)cyg_mbox_timed_get(m0,cyg_current_time()+20),
"timed get()");
CYG_TEST_CHECK(4==q++, "bad synchronization");
#ifdef CYGMTH_MBOX_PUT_CAN_WAIT
CYG_TEST_CHECK(4==(cyg_count8)cyg_mbox_get(m1));
 
CYG_TEST_CHECK(11==q++, "bad synchronization");
thread[0]->delay(20); // allow t0 to reach put on m1
CYG_TEST_CHECK(14==q++, "bad synchronization");
CYG_TEST_CHECK(cyg_mbox_waiting_to_put(m0), "waiting_to_put()");
do {
// after first get m0 contains ( 6 .. 6 9 )
i=(cyg_count8)cyg_mbox_tryget(m0);
} while(6==i);
CYG_TEST_CHECK(9==i,"put gone awry");
#endif
#endif
CYG_TEST_PASS_FINISH("Kernel C API Mbox 1 OK");
}
 
void kmbox1_main( void )
{
CYG_TEST_INIT();
 
cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kmbox1-0",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_thread_create(4, entry1 , (cyg_addrword_t)1, "kmbox1-1",
(void *)stack[1], STACKSIZE, &thread[1], &thread_obj[1]);
cyg_thread_resume(thread[1]);
 
cyg_mbox_create( &m0, &mbox0 );
cyg_mbox_create( &m1, &mbox1 );
cyg_mbox_create( &m2, &mbox2 );
 
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
kmbox1_main();
}
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF kmbox1.c */
/mutex0.cxx
0,0 → 1,96
//==========================================================================
//
// mutex0.cxx
//
// Mutex and condition variable test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: Limited to checking constructors/destructors
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/mutex.hxx>
 
#include <cyg/infra/testcase.h>
 
#include "testaux.hxx"
 
static Cyg_Mutex mutex0;
 
static Cyg_Condition_Variable cvar0( mutex0 );
 
static bool flash( void )
{
Cyg_Mutex m0;
 
CYG_ASSERTCLASSO(m0, "error");
 
Cyg_Condition_Variable cv0( m0 );
 
CYG_ASSERTCLASSO(cv0, "error");
 
return true;
}
 
void mutex0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_ASSERTCLASSO(mutex0, "error");
CYG_ASSERTCLASSO(cvar0, "error");
CYG_TEST_PASS_FINISH("Mutex 0 OK");
 
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
mutex0_main();
}
// EOF mutex0.cxx
/klock.c
0,0 → 1,318
/*=================================================================
//
// klock.c
//
// Kernel lock test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-18
// Description: Tests some basic thread functions.
//####DESCRIPTIONEND####
*/
//==========================================================================
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
//==========================================================================
 
#ifdef CYGFUN_KERNEL_API_C
 
#if (CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES == 0)
 
//==========================================================================
 
#include "testaux.h"
 
#include <cyg/hal/hal_arch.h> // for CYGNUM_HAL_STACK_SIZE_TYPICAL
 
//==========================================================================
 
#ifdef CYGNUM_HAL_STACK_SIZE_TYPICAL
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
#else
#define STACKSIZE 2000
#endif
 
//==========================================================================
 
static char stack[2][STACKSIZE];
 
static cyg_thread thread[2];
 
static cyg_handle_t pt0,pt1;
 
static cyg_mutex_t mx;
static cyg_cond_t cv;
static cyg_sem_t sem;
static cyg_flag_t fl;
static cyg_mbox mbox;
static cyg_handle_t mbh;
 
volatile static int thread0_state = 0;
volatile static int thread1_state = 0;
 
//==========================================================================
 
static void entry0( cyg_addrword_t data )
{
CHECK( 222 == (int)data );
 
// Do everything with the scheduler locked.
cyg_scheduler_lock();
 
// --------------------------------------------------
// Mutex test
cyg_mutex_lock( &mx );
thread0_state = 1;
// Get thread 2 running.
cyg_thread_resume(pt1);
thread0_state = 2;
 
#ifdef CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT
cyg_cond_wait( &cv );
thread0_state = 3;
 
while( thread1_state < 2 ) cyg_thread_yield();
cyg_cond_broadcast( &cv );
thread0_state = 4;
#endif
 
cyg_mutex_unlock( &mx );
thread0_state = 5;
 
 
// --------------------------------------------------
// Semaphore test
cyg_semaphore_wait( &sem );
thread0_state = 6;
 
cyg_semaphore_post( &sem );
thread0_state = 7;
 
while( thread1_state < 7 ) cyg_thread_yield();
// --------------------------------------------------
// Flags test
 
cyg_flag_wait( &fl, 1, CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR);
thread0_state = 8;
 
cyg_flag_setbits( &fl, 2 );
thread0_state = 9;
// --------------------------------------------------
// Message box test
 
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
{
void *mbret;
 
mbret = cyg_mbox_get( mbh );
CYG_TEST_CHECK( mbret == (void *)0xAAAAAAAA , "bad result from cyg_mbox_timed_get()");
thread0_state = 10;
cyg_mbox_put( mbh, (void *)0xBBBBBBBB );
thread0_state = 11;
}
#endif
// --------------------------------------------------
thread0_state = 999;
 
cyg_thread_yield();
cyg_thread_yield();
cyg_thread_yield();
CYG_TEST_CHECK( thread0_state == 999, "thread 0 not in exit state");
CYG_TEST_CHECK( thread1_state == 999, "thread 1 not in exit state");
CYG_TEST_PASS_FINISH("Kernel lock test OK");
}
 
//==========================================================================
 
static void entry1( cyg_addrword_t data )
{
cyg_bool res;
CHECK( 333 == (int)data );
 
// Do everything with the scheduler locked.
cyg_scheduler_lock();
 
// --------------------------------------------------
// Mutex test
#ifdef CYGMFN_KERNEL_SYNCH_CONDVAR_TIMED_WAIT
cyg_mutex_lock( &mx );
thread1_state = 1;
 
while( thread0_state < 2 ) cyg_thread_yield();
cyg_cond_signal( &cv );
thread1_state = 2;
 
res = cyg_cond_timed_wait( &cv, cyg_current_time()+10 );
CYG_TEST_CHECK( res , "FALSE result from cyg_cond_timed_wait()" );
thread1_state = 3;
 
cyg_mutex_unlock( &mx );
thread1_state = 4;
#endif
 
// --------------------------------------------------
// Semaphore test
while( thread0_state < 5 ) cyg_thread_yield();
cyg_semaphore_post( &sem );
thread1_state = 5;
 
while( thread0_state < 6 ) cyg_thread_yield();
thread1_state = 6;
#ifdef CYGFUN_KERNEL_THREADS_TIMER
res = cyg_semaphore_timed_wait( &sem, cyg_current_time()+10 );
#else
res = cyg_semaphore_wait( &sem );
#endif
CYG_TEST_CHECK( res , "FALSE result from cyg_semaphore[_timed]_wait()" );
thread1_state = 7;
 
// --------------------------------------------------
// Flags test
 
cyg_flag_setbits( &fl, 1 );
thread1_state = 8;
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
cyg_flag_timed_wait( &fl, 2, CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR,
cyg_current_time()+10 );
#else
cyg_flag_wait( &fl, 2, CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR );
#endif
thread1_state = 9;
// --------------------------------------------------
// Message box test
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
{
void *mbret;
#ifdef CYGFUN_KERNEL_THREADS_TIMER
cyg_mbox_timed_put( mbh, (void *)0xAAAAAAAA, cyg_current_time()+10 );
#else
cyg_mbox_put( mbh, (void *)0xAAAAAAAA );
#endif
thread1_state = 10;
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
mbret = cyg_mbox_timed_get( mbh, cyg_current_time()+10);
#else
mbret = cyg_mbox_get( mbh );
#endif
CYG_TEST_CHECK( mbret == (void *)0xBBBBBBBB , "bad result from cyg_mbox[_timed]_get()");
thread1_state = 9;
}
#endif
// --------------------------------------------------
thread1_state = 999;
cyg_thread_exit();
}
 
//==========================================================================
 
void kthread1_main( void )
{
CYG_TEST_INIT();
 
cyg_thread_create(4, entry0, (cyg_addrword_t)222, "kthread1-0",
(void *)stack[0], STACKSIZE, &pt0, &thread[0] );
cyg_thread_create(4, entry1, (cyg_addrword_t)333, "kthread1-1",
(void *)stack[1], STACKSIZE, &pt1, &thread[1] );
 
// Init all the objects
 
cyg_mutex_init( &mx );
cyg_cond_init( &cv, &mx );
cyg_semaphore_init( &sem, 0 );
cyg_flag_init( &fl );
cyg_mbox_create( &mbh, &mbox );
cyg_thread_resume(pt0);
 
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
//==========================================================================
 
externC void
cyg_start( void )
{
kthread1_main();
}
 
//==========================================================================
 
#else /* CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES == 0 */
# define NA_MSG "Schedule has unique priorities"
#endif
 
#else /* def CYGFUN_KERNEL_API_C */
# define NA_MSG "Kernel C API layer disabled"
#endif
 
#ifdef NA_MSG
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA(NA_MSG);
}
#endif
 
//==========================================================================
/* EOF klock.c */
/mutex1.cxx
0,0 → 1,162
//==========================================================================
//
// mutex1.cxx
//
// Mutex test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: Tests basic mutex functionality.
// Omissions: Timed wait.
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
#include <cyg/kernel/thread.hxx> // Cyg_Thread
 
#include <cyg/kernel/mutex.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/thread.inl>
 
 
#define NTHREADS 3
#include "testaux.hxx"
 
static Cyg_Mutex m0, m1;
static Cyg_Condition_Variable cvar0( m0 ), cvar1( m0 ), cvar2( m1 );
 
static cyg_ucount8 m0d=0, m1d=0;
 
static void finish( cyg_ucount8 t )
{
m1.lock(); {
m1d |= 1<<t;
if( 0x7 == m1d )
CYG_TEST_PASS_FINISH("Mutex 1 OK");
cvar2.wait();
}
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry0( CYG_ADDRWORD data )
{
m0.lock(); {
CHECK( ! m0.trylock() );
m1.lock(); {
CHECK( ! m0.trylock() );
} m1.unlock();
} m0.unlock();
 
m0.lock(); {
while ( 0 == m0d )
cvar0.wait();
CHECK( 1 == m0d++ );
cvar0.signal();
while ( 4 != m0d )
cvar1.wait();
CHECK( 4 == m0d );
} m0.unlock();
 
finish( data );
}
 
static void entry1( CYG_ADDRWORD data )
{
m0.lock(); {
CHECK( m1.trylock() ); {
} m1.unlock();
} m0.unlock();
 
m0.lock(); {
CHECK( 0 == m0d++ );
cvar0.broadcast();
} m0.unlock();
m0.lock(); {
while( 1 == m0d )
cvar0.wait();
CHECK( 2 == m0d++ );
cvar0.signal();
while (3 == m0d )
cvar1.wait();
} m0.unlock();
 
finish( data ); // At most 1 finish inside m0 lock
}
 
static void entry2( CYG_ADDRWORD data )
{
m0.lock(); {
while( 3 != m0d ) {
cvar0.wait();
}
CHECK( 3 == m0d++ );
cvar1.broadcast();
} m0.unlock();
 
finish( data );
}
 
void mutex1_main( void )
{
CYG_TEST_INIT();
 
new_thread(entry0, 0);
new_thread(entry1, 1);
new_thread(entry2, 2);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
mutex1_main();
}
// EOF mutex1.cxx
/kflag0.c
0,0 → 1,99
/*==========================================================================
//
// kflag0.cxx
//
// Kernel C API Flag test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: hmt
// Date: 1998-10-19
// Description: Limited to checking constructors/destructors
//####DESCRIPTIONEND####
*/
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
cyg_flag_t f0, f1, f2;
 
static bool flash( void )
{
cyg_flag_init( &f0 );
cyg_flag_init( &f1 );
cyg_flag_init( &f2 );
 
cyg_flag_destroy( &f0 );
cyg_flag_destroy( &f1 );
cyg_flag_destroy( &f2 );
 
return true;
}
 
void kflag0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Kernel C API Flag 0 OK");
}
 
externC void
cyg_start( void )
{
kflag0_main();
}
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
// EOF kflag0.cxx
/mutex2.cxx
0,0 → 1,273
//==========================================================================
//
// mutex1.cxx
//
// Mutex test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 1999-02-19
// Description: Tests mutex release functionality
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
#include <cyg/kernel/thread.hxx> // Cyg_Thread
 
#include <cyg/kernel/mutex.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/thread.inl>
 
// ------------------------------------------------------------------------
 
#if !defined(CYGPKG_KERNEL_SMP_SUPPORT)
 
// ------------------------------------------------------------------------
 
#define NTHREADS 4
#include "testaux.hxx"
#include "testaux.h"
 
// ------------------------------------------------------------------------
 
static Cyg_Mutex m0, m1;
static Cyg_Condition_Variable cvar0( m0 ), cvar1( m0 ), cvar2( m1 );
 
volatile int thread_state[NTHREADS];
 
// ------------------------------------------------------------------------
// This thread is meant to get hung up trying to re-acquire m0
// after waiting on the cv.
 
static void entry0( CYG_ADDRWORD data )
{
CYG_TEST_INFO( "thread0: lock mutex 0");
m0.lock();
 
CYG_TEST_INFO( "thread0: wait cvar 0");
 
thread_state[data] = 1;
cvar0.wait();
 
thread_state[data] = 2;
CYG_TEST_INFO( "thread0: woke from cvar 0");
 
CYG_TEST_INFO( "thread0: unlock mutex 0");
m0.unlock();
 
thread_state[data] = 3;
CYG_TEST_INFO( "thread0: exit");
 
thread[data]->exit();
}
 
// ------------------------------------------------------------------------
// This thread is meant to claim and keep m0.
 
static void entry1( CYG_ADDRWORD data )
{
CYG_TEST_INFO( "thread1: lock mutex 0");
m0.lock();
 
CYG_TEST_INFO( "thread1: lock mutex 1");
 
thread_state[data] = 1;
m1.lock();
 
thread_state[data] = 2;
CYG_TEST_INFO( "thread1: wait cvar 2");
 
cvar2.wait();
 
thread_state[data] = 3;
CYG_TEST_INFO( "thread1: woke from cvar 2");
 
CYG_TEST_INFO( "thread1: unlock mutex 1");
 
m1.unlock();
 
thread_state[data] = 4;
CYG_TEST_INFO( "thread1: unlock m0");
 
m0.unlock();
 
thread_state[data] = 5;
CYG_TEST_INFO( "thread1: exit");
 
thread[data]->exit();
}
 
// ------------------------------------------------------------------------
// This thread is meant to get hung trying to acquire m0, and then get
// released out of it by thread3.
 
static void entry2( CYG_ADDRWORD data )
{
CYG_TEST_INFO( "thread2: lock mutex 0");
 
thread_state[data] = 1;
if( m0.lock() )
{
thread_state[data] = 2;
CYG_TEST_INFO( "thread2: lock mutex 0 - returned TRUE");
CYG_TEST_FAIL_FINISH(" m0.lock() returned TRUE" );
}
else
{
thread_state[data] = 3;
CYG_TEST_INFO( "thread2: lock mutex 0 - returned FALSE");
}
 
CYG_TEST_INFO( "thread2: exit");
thread[data]->exit();
}
 
// ------------------------------------------------------------------------
 
static void entry3( CYG_ADDRWORD data )
{
 
CHECK( thread_state[0] == 1 );
CHECK( thread_state[1] == 2 );
CHECK( thread_state[2] == 1 );
CYG_TEST_INFO( "thread3: signal cvar 0");
cvar0.signal();
 
CHECK( thread_state[0] == 1 );
CHECK( thread_state[1] == 2 );
CHECK( thread_state[2] == 1 );
 
CYG_TEST_INFO( "thread3: release mutex 0");
 
m0.release();
 
CHECK( thread_state[0] == 1 );
CHECK( thread_state[1] == 2 );
CHECK( thread_state[2] == 3 );
 
CYG_TEST_INFO( "thread3: signal cvar 2");
cvar2.signal();
 
CHECK( thread_state[0] == 3 );
CHECK( thread_state[1] == 5 );
CHECK( thread_state[2] == 3 );
 
CYG_TEST_PASS_FINISH( "mutex2 finished OK");
CYG_TEST_INFO( "thread3: exit");
 
thread[data]->exit();
}
 
// ------------------------------------------------------------------------
 
void mutex2_main( void )
{
CYG_TEST_INIT();
 
new_thread(entry0, 0);
new_thread(entry1, 1);
new_thread(entry2, 2);
new_thread(entry3, 3);
 
// Set priorities from the top to prevent two threads getting
// the same priority: this causes an ASSERT on some configurations.
thread[3]->set_priority( 5 );
thread[2]->set_priority( 4 );
thread[1]->set_priority( 3 );
thread[0]->set_priority( 2 );
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
// ------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
mutex2_main();
}
 
// ------------------------------------------------------------------------
 
#else // CYGPKG_KERNEL_SMP_SUPPORT
 
// ------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_PASS_FINISH("Mutex2 test requires:\n"
"!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
 
}
 
// ------------------------------------------------------------------------
 
#endif // CYGPKG_KERNEL_SMP_SUPPORT
 
// ------------------------------------------------------------------------
// EOF mutex2.cxx
/mutex3.cxx
0,0 → 1,630
//==========================================================================
//
// mutex3.cxx
//
// Mutex test 3 - priority inheritance
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors: hmt
// Date: 2000-01-06
// Description: Tests mutex priority inheritance
//####DESCRIPTIONEND####
 
#include <pkgconf/hal.h>
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
#include <cyg/kernel/thread.hxx> // Cyg_Thread
 
#include <cyg/kernel/mutex.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/thread.inl>
 
#include <cyg/infra/diag.h> // diag_printf
 
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
// ------------------------------------------------------------------------
//
// These checks should be enough; any other scheduler which has priorities
// should manifest as having no priority inheritance, but otherwise fine,
// so the test should work correctly.
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) && \
!defined(CYGPKG_KERNEL_SMP_SUPPORT)
 
// ------------------------------------------------------------------------
// Manufacture a simpler feature test macro for priority inheritance than
// the configuration gives us. We have priority inheritance if it is configured
// as the only protocol, or if it is the default protocol for dynamic protocol
// choice.
// FIXME: If we have dynamic protocol choice, we can also set priority inheritance
// as the protocol to be used on the mutexes we are interested in. At present we
// do not do this.
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_INHERIT
# define PRIORITY_INHERITANCE "dynamic-default-inherit"
# endif
# else
# define PRIORITY_INHERITANCE "static-inherit"
# endif
#endif
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_CEILING
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_CEILING
# if CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY <= 5
# define PRIORITY_INHERITANCE "dynamic-default-ceiling-high"
# elif CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY >= 15
# define NO_PRIORITY_INHERITANCE "dynamic-default-ceiling-low"
# else
# define PRIORITY_UNKNOWN "dynamic-default-ceiling-mid"
# endif
# endif
# else
# if CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY <= 5
# define PRIORITY_INHERITANCE "static-ceiling-high"
# elif CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_PRIORITY >= 15
# define NO_PRIORITY_INHERITANCE "static-ceiling-low"
# else
# define PRIORITY_UNKNOWN "static-ceiling-mid"
# endif
# endif
#endif
 
#ifndef PRIORITY_INHERITANCE
# ifndef NO_PRIORITY_INHERITANCE
# define NO_PRIORITY_INHERITANCE "no scheme selected"
# endif
#endif
 
// ------------------------------------------------------------------------
// Management functions
//
// Stolen from testaux.hxx and copied in here because I want to be able to
// reset the world also.
 
#define NTHREADS 7
 
static inline void *operator new(size_t size, void *ptr) { return ptr; };
 
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static Cyg_Thread *thread[NTHREADS] = { 0 };
 
typedef CYG_WORD64 CYG_ALIGNMENT_TYPE;
 
static CYG_ALIGNMENT_TYPE thread_obj[NTHREADS] [
(sizeof(Cyg_Thread)+sizeof(CYG_ALIGNMENT_TYPE)-1)
/ sizeof(CYG_ALIGNMENT_TYPE) ];
 
static CYG_ALIGNMENT_TYPE stack[NTHREADS] [
(STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1)
/ sizeof(CYG_ALIGNMENT_TYPE) ];
 
static volatile int nthreads = 0;
 
static Cyg_Thread *new_thread( cyg_thread_entry *entry,
CYG_ADDRWORD data,
CYG_ADDRWORD priority,
int do_resume )
{
int _nthreads = nthreads++;
 
CYG_ASSERT(_nthreads < NTHREADS,
"Attempt to create more than NTHREADS threads");
 
thread[_nthreads] = new( (void *)&thread_obj[_nthreads] )
Cyg_Thread(priority,
entry, data,
NULL, // no name
(CYG_ADDRESS)stack[_nthreads], STACKSIZE );
 
if ( do_resume )
thread[_nthreads]->resume();
 
return thread[_nthreads];
}
 
 
static void kill_threads( void )
{
CYG_ASSERT(nthreads <= NTHREADS,
"More than NTHREADS threads");
CYG_ASSERT( Cyg_Thread::self() == thread[0],
"kill_threads() not called from thread 0");
while ( nthreads > 1 ) {
nthreads--;
if ( NULL != thread[nthreads] ) {
thread[nthreads]->kill();
thread[nthreads]->~Cyg_Thread();
thread[nthreads] = NULL;
}
}
CYG_ASSERT(nthreads == 1,
"No threads left");
}
 
// ------------------------------------------------------------------------
 
#define DELAYFACTOR 1 // for debugging
 
// ------------------------------------------------------------------------
 
static Cyg_Mutex mutex;
 
// These are for reporting back to the master thread
volatile int got_it = 0;
volatile int t3ran = 0;
volatile int t3ended = 0;
volatile int extras[4] = {0,0,0,0};
volatile int go_flag = 0; // but this one controls thread 3 from thread 2
 
// ------------------------------------------------------------------------
// 0 to 3 of these run generally to interfere with the other processing,
// to cause multiple prio inheritances, and clashes in any orders.
 
static void extra_thread( CYG_ADDRWORD data )
{
#define XINFO( z ) \
do { z[13] = '0' + data; CYG_TEST_INFO( z ); } while ( 0 )
 
static char running[] = "Extra thread Xa running";
static char exiting[] = "Extra thread Xa exiting";
static char resumed[] = "Extra thread Xa resumed";
static char locked[] = "Extra thread Xa locked";
static char unlocked[] = "Extra thread Xa unlocked";
 
XINFO( running );
 
Cyg_Thread *self = Cyg_Thread::self();
 
self->suspend();
 
XINFO( resumed );
 
mutex.lock();
 
XINFO( locked );
 
mutex.unlock();
 
XINFO( unlocked );
 
extras[ data ] ++;
 
XINFO( exiting );
 
}
 
// ------------------------------------------------------------------------
 
static void t1( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
 
CYG_TEST_INFO( "Thread 1 running" );
 
self->suspend();
 
mutex.lock();
 
got_it++;
 
CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,1]" );
 
mutex.unlock();
 
CYG_TEST_CHECK( 0 == t3ended, "T3 ended prematurely [T1,2]" );
 
// That's all.
 
CYG_TEST_INFO( "Thread 1 exit" );
}
 
// ------------------------------------------------------------------------
 
static void t2( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
int i;
cyg_tick_count then, now;
 
 
CYG_TEST_INFO( "Thread 2 running" );
 
CYG_TEST_CHECK( 0 == (data & ~0x77), "Bad T2 arg: extra bits" );
CYG_TEST_CHECK( 0 == (data & (data >> 4)), "Bad T2 arg: overlap" );
 
self->suspend();
 
// depending on our config argument, optionally restart some of the
// extra threads to throw noise into the scheduler:
for ( i = 0; i < 3; i++ )
if ( (1 << i) & data ) // bits 0-2 control
thread[i+4]->resume(); // made sure extras are thread[4-6]
 
self->delay( DELAYFACTOR * 10 ); // let those threads run
 
Cyg_Scheduler::lock(); // do this next lot atomically
 
go_flag = 1; // unleash thread 3
thread[1]->resume(); // resume thread 1
 
// depending on our config argument, optionally restart some of the
// extra threads to throw noise into the scheduler at this later point:
for ( i = 4; i < 7; i++ )
if ( (1 << i) & data ) // bits 4-6 control
thread[i]->resume(); // made sure extras are thread[4-6]
 
Cyg_Scheduler::unlock(); // let scheduling proceed
 
// Need a delay (but not a CPU yield) to allow t3 to awaken and act on
// the go_flag, otherwise we check these details below too soon.
// Actually, waiting for the clock to tick a couple of times would be
// better, so that is what we will do. Must be a busy-wait.
then = Cyg_Clock::real_time_clock->current_value();
do {
now = Cyg_Clock::real_time_clock->current_value();
// Wait longer than the delay in t3 waiting on go_flag
} while ( now < (then + 3) );
 
#ifdef PRIORITY_UNKNOWN
CYG_TEST_INFO( "Not checking: " PRIORITY_UNKNOWN );
#else
#ifdef PRIORITY_INHERITANCE
CYG_TEST_INFO( "Checking priority scheme: " PRIORITY_INHERITANCE );
CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
#else
CYG_TEST_INFO( "Checking NO priority scheme: " NO_PRIORITY_INHERITANCE );
CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" );
CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" );
#endif
#endif
 
CYG_TEST_CHECK( 0 == t3ended, "Thread 3 ended prematurely [T2,1]" );
 
self->delay( DELAYFACTOR * 20 ); // let those threads run
 
CYG_TEST_CHECK( 1 == t3ran, "Thread 3 did not run" );
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
CYG_TEST_CHECK( 1 == t3ended, "Thread 3 has not ended" );
 
for ( i = 0; i < 3; i++ )
if ( (1 << i) & (data | data >> 4) ) // bits 0-2 and 4-6 control
CYG_TEST_CHECK( 1 == extras[i+1], "Extra thread did not run" );
else
CYG_TEST_CHECK( 0 == extras[i+1], "Extra thread ran" );
 
CYG_TEST_PASS( "Thread 2 exiting, AOK" );
// That's all: restart the control thread.
thread[0]->resume();
}
 
// ------------------------------------------------------------------------
 
static void t3( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
 
CYG_TEST_INFO( "Thread 3 running" );
 
mutex.lock();
 
self->delay( DELAYFACTOR * 5 ); // let thread 3a run
 
thread[2]->resume(); // resume thread 2
 
while ( 0 == go_flag )
self->delay(1); // wait until we are told to go
 
t3ran ++; // record the fact
 
CYG_TEST_CHECK( 0 == got_it, "Thread 1 claims to have got my mutex" );
mutex.unlock();
t3ended ++; // record that we came back
 
CYG_TEST_CHECK( 1 == got_it, "Thread 1 did not get the mutex" );
 
CYG_TEST_INFO( "Thread 3 exit" );
}
 
// ------------------------------------------------------------------------
 
static void control_thread( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
int i;
 
CYG_TEST_INIT();
CYG_TEST_INFO( "Control Thread running" );
 
// Go through the 27 possibilitied of resuming the extra threads
// 0: not at all
// 1: early in the process
// 2: later on
// which are represented by bits 0-3 and 4-6 resp in the argument to
// thread 2 (none set means no resume at all).
for ( i = 0; i < 27; i++ ) {
static int xx[] = { 0, 1, 16 };
int j = i % 3;
int k = (i / 3) % 3;
int l = (i / 9) % 3;
 
int d = xx[j] | (xx[k]<<1) | (xx[l]<<2) ;
 
if ( cyg_test_is_simulator && (0 != i && 13 != i && 26 != i) )
continue; // 13 is 111 base 3, 26 is 222 base 3
 
#ifdef PRIORITY_INHERITANCE
// If the simple scheme plus relay enhancement, or any other
// *complete* scheme, we can run all three ancillary threads no
// problem, so no special action here.
 
#else
// If no priority inheritance at all, running threads 1a and 2a is
// OK, but not thread 3a; it blocks the world.
if ( l ) // Cannot run thread 3a if no
break; // priority inheritance at all.
#endif
 
mutex = Cyg_Mutex(); // Reinitialize this
 
got_it = 0;
t3ran = 0;
t3ended = 0;
for ( int z = 0; z < 4; z++ ) extras[z] = 0;
go_flag = 0;
new_thread( t1, 0, 5, 1 ); // Slot 1
new_thread( t2, d, 10, 1 ); // Slot 2
new_thread( t3, 0, 15, 1 ); // Slot 3
new_thread( extra_thread, 1, 8, j ); // Slot 4
new_thread( extra_thread, 2, 12, k ); // Slot 5
new_thread( extra_thread, 3, 17, l ); // Slot 6
{
static char *a[] = { "inactive", "run early", "run late" };
diag_printf( "\n----- [%2d] New Cycle: 0x%02x, Threads 1a %s, 2a %s, 3a %s -----\n",
i, d, a[j], a[k], a[l] );
}
 
self->suspend();
kill_threads();
mutex.~Cyg_Mutex();
}
CYG_TEST_EXIT( "Control Thread exit" );
}
 
// ------------------------------------------------------------------------
 
externC void
cyg_user_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
new_thread( control_thread, 0, 2, 1 );
}
 
#else // CYGVAR_KERNEL_COUNTERS_CLOCK &c
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_PASS_FINISH("Mutex3 test requires:\n"
"CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
"(CYGNUM_KERNEL_SCHED_PRIORITIES > 20) &&\n"
"!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
}
#endif // CYGVAR_KERNEL_COUNTERS_CLOCK &c
 
 
// ------------------------------------------------------------------------
// Documentation: enclosed is the design of this test.
//
// It has been carefully constructed so that it does NOT use other kernel
// facilities (aside from delay-task) to test that priority inheritance is
// working, or not, as intended by the configuration.
//
// These notes describe the flow of control in one run of the test with the
// ancillary tasks optionally interspersed. The details of how those extra
// tasks are or are not allowed to run are not described.
//
//
//
// The only change in the test that depends on whether there is inheritance or
// not is the check in thread 2 on "3-ran" and "got it" flags marked ****
//
//
// volatile &c booleans:
// "got it" = FALSE
// "3-ran" = FALSE
// "3-ended" = FALSE
// "extras"[3] = FALSE
//
// thread 1. prio 5, self-suspend.
//
// thread 1a, prio 8, self-suspend.
//
// thread 2. prio 10, self-suspend.
//
// thread 2a, prio 12, self-suspend.
//
// thread 3. prio 15, runs, lock mutex, resume(2)
//
// thread 3a, prio 17, self-suspend.
//
// 2. runs,
// 2. resume(3a) +++OPTIONAL
// 2. resume(2a) +++OPTIONAL
// 2. resume(1a) +++OPTIONAL
// [1a lock-fail] thread 3->prio := 8
//
// [3. runs maybe, does the looping thing]
//
// 2. sleep a while...
//
// [2a lock-fail] thread 3->prio := 12
//
// [3. runs maybe, does the looping thing]
//
// [3a lock-fail] thread 3->prio unchanged
//
// [3. runs maybe, does the looping thing]
//
// 2. lock scheduler
// 2. set "go-flag"
// 2. resume(1)
// 2. resume(1a) +++OPTIONAL
// 2. resume(2a) +++OPTIONAL
// 2. resume(3a) +++OPTIONAL
// 2. unlock scheduler
//
// 1. runs, lock mutex - thread 3 has it locked
//
// 2. busy-waits a bit for thread 3 to come out of its delay() loop.
// This must be a *busy*wait so that 3 can only run via the
// inherited raised priority.
//
// [xa. all do the same: lock mutex, ]
// [xa. unlock mutex ]
// [xa. set a flag "extras"[x] to say we are done. ]
// [xa. exit ]
//
//
//
// INHERIT
// -------
//
// thread 3->prio := 5
//
// 3. runs,
// 3. set a flag to say "3-ran",
// 3. loop with a sleep(1) until "go-flag" is set.
// 3. check "got it" is false,
// 3. then unlock mutex,
//
// thread 3->prio := 15
//
// 1. runs, set a flag to say "got it",
// 1. check "3-ended" flag is false
// 1. unlock mutex,
// 1. check "3-ended" flag is still false
// 1. exit.
//
// [1a locks, unlocks, exits]
//
// 2. runs, check "3-ran" and "got it" flags are TRUE ****
// 2. check "3-ended" flag is false
// 2. sleeps for a while so that...
//
// [2a locks, unlocks, exits]
//
// 3. runs, set "3-ended" flag,
// 3. check "3-ran" and "got it" flags
// 3. exit
//
// [3a locks, unlocks, exits]
//
// 2. awakens, checks all flags true,
// 2. check that all "extra" threads that we started have indeed run
// 2. end of test.
//
//
//
//
// NO-INHERIT
// ----------
// thread 1 is waiting on the mutex
//
// [1a lock-fail]
//
// 2. runs, checks that "3-ran" and "got it" flags are FALSE ****
// 2. check "3-ended" flag is false
// 2. sleeps for a while so that...
//
// [2a. lock-fail]
//
// 3. runs, set a flag to say "3-ran",
// 3. check "got it" is false,
// 3. then unlock mutex,
//
// 1. runs, set a flag to say "got it",
// 1. check "3-ended" flag is false
// 1. unlock mutex,
// 1. check "3-ended" flag is still false
// 1. exit.
//
// [1a locks, unlocks, exits]
// [2a locks, unlocks, exits]
//
// 3. runs, set "3-ended" flag,
// 3. check "3-ran" and "got it" flags
// 3. exit
//
// [3a locks, unlocks, exits]
//
// 2. awakens, checks all flags true,
// 2. check that all "extra" threads that we started have indeed run
// 2. end of test.
//
//
// (the end)
//
//
// ------------------------------------------------------------------------
 
// EOF mutex3.cxx
/kflag1.c
0,0 → 1,244
/*==========================================================================
//
// kflag1.cxx
//
// Kernel C API Flag test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author: dsm
// Contributors: hmt
// Date: 1998-10-19
// Description: Tests basic flag functionality.
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
 
#define NTHREADS 3
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
static cyg_flag_t f0, f1;
#ifdef CYGFUN_KERNEL_THREADS_TIMER
static cyg_flag_t f2;
#endif
 
static volatile cyg_ucount8 q = 0;
#define FIRST_THREAD_WAIT_TIME 5
#define SECOND_THREAD_WAIT_TIME 10
#define THIRD_THREAD_WAIT_TIME 20
 
static void entry0( cyg_addrword_t data )
{
CYG_TEST_INFO("Testing cyg_flag_setbits() and cyg_flag_maskbits()");
CYG_TEST_CHECK(0==cyg_flag_peek( &f0 ), "flag not initialized properly");
cyg_flag_setbits( &f0, 0x1);
CYG_TEST_CHECK(1==cyg_flag_peek( &f0 ), "setbits");
cyg_flag_setbits( &f0, 0x3);
CYG_TEST_CHECK(3==cyg_flag_peek( &f0 ), "setbits");
cyg_flag_maskbits( &f0, ~0x5);
CYG_TEST_CHECK(2==cyg_flag_peek( &f0 ), "maskbits");
cyg_flag_setbits( &f0, ~0 );
CYG_TEST_CHECK(~0u==cyg_flag_peek( &f0 ), "setbits all set");
cyg_flag_maskbits( &f0, 0 );
CYG_TEST_CHECK(0==cyg_flag_peek( &f0 ), "maskbits all clear");
CYG_TEST_CHECK(0==q++, "bad synchronization");
 
CYG_TEST_INFO("Testing cyg_flag_wait()");
cyg_flag_setbits( &f1, 0x4);
CYG_TEST_CHECK(0x4==cyg_flag_peek( &f1 ), "setbits");
CYG_TEST_CHECK(1==q++, "bad synchronization");
cyg_flag_setbits( &f1, 0x18); // wake t1
cyg_flag_wait( &f1, 0x11, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR);
CYG_TEST_CHECK(0==cyg_flag_peek( &f1 ), "flag value wrong");
CYG_TEST_CHECK(3==q++, "bad synchronization");
cyg_flag_setbits( &f0, 0x2); // wake t1
cyg_flag_wait( &f1, 0x10, CYG_FLAG_WAITMODE_AND );
cyg_flag_setbits( &f0, 0x1); // wake t1
 
cyg_flag_wait( &f1, 0x11, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR);
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
cyg_flag_wait( &f2, 0x2, CYG_FLAG_WAITMODE_OR);
CYG_TEST_CHECK(20==q,"bad synchronization");
cyg_flag_timed_wait( &f2, 0x10, CYG_FLAG_WAITMODE_AND,
cyg_current_time()+THIRD_THREAD_WAIT_TIME);
CYG_TEST_CHECK(21==q++,"bad synchronization");
#endif
cyg_flag_wait( &f0, 1, CYG_FLAG_WAITMODE_OR);
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry1( cyg_addrword_t data )
{
cyg_flag_wait( &f1, 0xc, CYG_FLAG_WAITMODE_AND);
CYG_TEST_CHECK(2==q++, "bad synchronization");
CYG_TEST_CHECK(0x1c==cyg_flag_peek( &f1 ), "flag value wrong");
cyg_flag_setbits( &f1, 0x1); // wake t0
cyg_flag_wait( &f0, 0x3, CYG_FLAG_WAITMODE_OR);
CYG_TEST_CHECK(4==q++, "bad synchronization");
CYG_TEST_CHECK(2==cyg_flag_peek( &f0 ), "flag value wrong");
cyg_flag_setbits( &f1, 0xf0); // wake t0,t2
cyg_flag_wait( &f0, 0x5, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR);
CYG_TEST_CHECK(0==cyg_flag_peek( &f0 ), "flag value wrong");
CYG_TEST_CHECK(0xf0==cyg_flag_peek( &f1 ), "flag value wrong");
CYG_TEST_CHECK(5==q++, "bad synchronization");
cyg_flag_maskbits( &f1, 0 );
CYG_TEST_CHECK(0==cyg_flag_peek( &f1 ), "flag value wrong");
CYG_TEST_INFO("Testing cyg_flag_poll()");
cyg_flag_setbits( &f0, 0x55);
CYG_TEST_CHECK(0x55==cyg_flag_peek( &f0 ), "flag value wrong");
CYG_TEST_CHECK(0x55==cyg_flag_poll( &f0, 0x3, CYG_FLAG_WAITMODE_OR),"bad poll() return");
CYG_TEST_CHECK(0==cyg_flag_poll( &f0, 0xf, CYG_FLAG_WAITMODE_AND),"poll()");
CYG_TEST_CHECK(0==cyg_flag_poll( &f0, 0xa, CYG_FLAG_WAITMODE_OR),"poll()");
CYG_TEST_CHECK(0x55==cyg_flag_peek( &f0 ), "flag value wrong");
CYG_TEST_CHECK(0x55==cyg_flag_poll( &f0, 0xf, CYG_FLAG_WAITMODE_OR | CYG_FLAG_WAITMODE_CLR),"poll");
CYG_TEST_CHECK(0x0==cyg_flag_peek( &f0 ), "flag value wrong");
cyg_flag_setbits( &f0, 0x50);
CYG_TEST_CHECK(0x50==cyg_flag_poll( &f0, 0x10, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR),"poll");
CYG_TEST_CHECK(0x0==cyg_flag_peek( &f0 ), "flag value wrong");
 
CYG_TEST_INFO("Testing cyg_flag_waiting()");
cyg_flag_maskbits( &f0, 0 );
CYG_TEST_CHECK(!cyg_flag_waiting( &f0 ), "waiting()");
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
cyg_thread_delay( 10 ); // allow other threads to reach wait on f1
CYG_TEST_CHECK(cyg_flag_waiting( &f1 ), "waiting() not true");
cyg_flag_setbits( &f1, ~0 ); // wake one of t0,t2
CYG_TEST_CHECK(cyg_flag_waiting( &f1 ),"waiting() not true");
#else
cyg_flag_setbits( &f1, 0x11); // wake one of t0,t2
#endif
cyg_flag_setbits( &f1, 0x11); // wake other of t0,t2
CYG_TEST_CHECK(!cyg_flag_waiting( &f1 ),"waiting not false");
CYG_TEST_CHECK(0x0==cyg_flag_peek( &f1 ), "flag value wrong");
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
CYG_TEST_INFO("Testing cyg_flag_timed_wait()");
q=20;
cyg_flag_setbits( &f2, 0x2); // synchronize with t0,t2
CYG_TEST_CHECK(20==q,"bad synchronization");
cyg_flag_timed_wait( &f2, 0x20, CYG_FLAG_WAITMODE_AND,
cyg_current_time()+SECOND_THREAD_WAIT_TIME);
CYG_TEST_CHECK(22==q++,"bad synchronization");
#endif
 
CYG_TEST_PASS_FINISH("Kernel C API Flag 1 OK");
}
 
static void entry2( cyg_addrword_t data )
{
cyg_flag_wait( &f1, 0x60, CYG_FLAG_WAITMODE_OR);
cyg_flag_setbits( &f0, 0x4);
 
cyg_flag_wait( &f1, 0x11, CYG_FLAG_WAITMODE_AND | CYG_FLAG_WAITMODE_CLR);
#ifdef CYGFUN_KERNEL_THREADS_TIMER
cyg_flag_wait( &f2, 0x2, CYG_FLAG_WAITMODE_OR);
CYG_TEST_CHECK(20==q,"bad synchronization");
CYG_TEST_CHECK(0==cyg_flag_timed_wait( &f2, 0x40, CYG_FLAG_WAITMODE_AND,
cyg_current_time()+FIRST_THREAD_WAIT_TIME),
"timed wait() wrong");
CYG_TEST_CHECK(20==q++,"bad synchronization");
// Now wake t0 before it times out
cyg_flag_setbits( &f2, 0x10);
#endif
cyg_flag_wait( &f0, 1, CYG_FLAG_WAITMODE_OR);
CYG_TEST_FAIL_FINISH("Not reached");
}
 
void kflag1_main( void )
{
CYG_TEST_INIT();
 
cyg_flag_init( &f0 );
cyg_flag_init( &f1 );
#ifdef CYGFUN_KERNEL_THREADS_TIMER
cyg_flag_init( &f2 );
#endif
 
cyg_thread_create( 1, entry0 , (cyg_addrword_t)0, "kflag1-0",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_thread_create( 1, entry1 , (cyg_addrword_t)1, "kflag1-1",
(void *)stack[1], STACKSIZE, &thread[1], &thread_obj[1]);
cyg_thread_resume(thread[1]);
 
cyg_thread_create( 1, entry2 , (cyg_addrword_t)2, "kflag1-2",
(void *)stack[2], STACKSIZE, &thread[2], &thread_obj[2]);
cyg_thread_resume(thread[2]);
 
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
kflag1_main();
}
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
// EOF flag1.cxx
/fptest.c
0,0 → 1,354
//==========================================================================
//
// fptest.cxx
//
// Basic FPU test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 2003 Nick Garnett
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg@calivar.com
// Contributors: nickg@calivar.com
// Date: 2003-01-27
// Description: Simple FPU test. This is not very sophisticated as far
// as checking FPU performance or accuracy. It is more
// concerned with checking that several threads doing FP
// operations do not interfere with eachother's use of the
// FPU.
//
//####DESCRIPTIONEND####
//==========================================================================
 
#include <pkgconf/kernel.h>
#include <pkgconf/hal.h>
 
#include <cyg/hal/hal_arch.h>
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
#include <cyg/infra/diag.h>
 
//#include <cyg/kernel/test/stackmon.h>
//#include CYGHWR_MEMORY_LAYOUT_H
 
//==========================================================================
 
#if defined(CYGFUN_KERNEL_API_C) && \
defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
 
//==========================================================================
// Base priority for all threads.
 
#define BASE_PRI 5
 
//==========================================================================
// Runtime
//
// This is the number of ticks that the program will run for. 3000
// ticks is equal to 30 seconds in the default configuration. For
// simulators we reduce the run time to 3 simulated seconds.
 
#define RUN_TICKS 3000
#define RUN_TICKS_SIM 300
 
//==========================================================================
// Thread parameters
 
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM)
 
static cyg_uint8 stacks[3][STACK_SIZE];
static cyg_handle_t thread[3];
static cyg_thread thread_struct[3];
 
//==========================================================================
// Alarm parameters.
 
static cyg_alarm alarm_struct;
static cyg_handle_t alarm;
 
static cyg_count8 cur_thread = 0;
static cyg_count32 alarm_ticks = 0;
static cyg_count32 run_ticks = RUN_TICKS;
 
//==========================================================================
 
static int errors = 0;
 
//==========================================================================
// Random number generator. Ripped out of the C library.
 
static int rand( unsigned int *seed )
{
// This is the code supplied in Knuth Vol 2 section 3.6 p.185 bottom
 
#define RAND_MAX 0x7fffffff
#define MM 2147483647 // a Mersenne prime
#define AA 48271 // this does well in the spectral test
#define QQ 44488 // (long)(MM/AA)
#define RR 3399 // MM % AA; it is important that RR<QQ
 
*seed = AA*(*seed % QQ) - RR*(unsigned int)(*seed/QQ);
if (*seed < 0)
*seed += MM;
 
return (int)( *seed & RAND_MAX );
}
 
//==========================================================================
// Test calculation.
//
// Generates an array of random FP values and then repeatedly applies
// a calculation to them and checks that the same result is reached
// each time. The calculation, in the macro CALC, is intended to make
// maximum use of the FPU registers. However, the i386 compiler
// doesn't let this expression get very complex before it starts
// spilling values out to memory.
 
static void do_test( double *values,
int count,
int loops,
int test,
const char *name)
{
unsigned int i, j;
// volatiles necessary to force
// values to 64 bits for comparison
volatile double sum = 1.0;
volatile double last_sum;
unsigned int seed;
#define V(__i) (values[(__i)%count])
#define CALC ((V(i-1)*V(i+1))*(V(i-2)*V(i+2))*(V(i-3)*sum))
 
seed = ((unsigned int)&i)*count;
 
// Set up an array of values...
for( i = 0; i < count; i++ )
values[i] = (double)rand( &seed )/(double)0x7fffffff;
 
// Now calculate something from them...
for( i = 0; i < count; i++ )
sum += CALC;
last_sum = sum;
// Now recalculate the sum in a loop and look for errors
for( j = 0; j < loops ; j++ )
{
sum = 1.0;
for( i = 0; i < count; i++ )
sum += CALC;
 
if( sum != last_sum )
{
errors++;
diag_printf("%s: Sum mismatch! %d sum=[%08x:%08x] last_sum=[%08x:%08x]\n",
name,j,
((cyg_uint32 *)&sum)[0],((cyg_uint32 *)&sum)[1],
((cyg_uint32 *)&last_sum)[0],((cyg_uint32 *)&last_sum)[1]
);
}
#if 0
if( ((j*count)%1000000) == 0 )
diag_printf("INFO:<%s: %2d calculations done>\n",name,j*count);
#endif
}
 
}
 
//==========================================================================
// Alarm handler
//
// This is called every tick. It lowers the priority of the currently
// running thread and raises the priority of the next. Thus we
// implement a form of timelslicing between the threads at one tick
// granularity.
 
static void alarm_fn(cyg_handle_t alarm, cyg_addrword_t data)
{
alarm_ticks++;
 
if( alarm_ticks >= run_ticks )
{
if( errors )
CYG_TEST_FAIL("Errors detected");
else
CYG_TEST_PASS("OK");
CYG_TEST_FINISH("FP Test done");
}
else
{
cyg_thread_set_priority( thread[cur_thread], BASE_PRI );
 
cur_thread = (cur_thread+1)%3;
 
cyg_thread_set_priority( thread[cur_thread], BASE_PRI-1 );
}
}
 
 
//==========================================================================
 
#define FP1_COUNT 1000
 
static double fpt1_values[FP1_COUNT];
 
void fptest1( CYG_ADDRWORD id )
{
while(1)
do_test( fpt1_values, FP1_COUNT, 2000000000, id, "fptest1" );
}
 
//==========================================================================
 
#define FP2_COUNT 10000
 
static double fpt2_values[FP2_COUNT];
 
void fptest2( CYG_ADDRWORD id )
{
while(1)
do_test( fpt2_values, FP2_COUNT, 2000000000, id, "fptest2" );
}
 
//==========================================================================
 
#define FP3_COUNT 100
 
static double fpt3_values[FP3_COUNT];
 
void fptest3( CYG_ADDRWORD id )
{
while(1)
do_test( fpt3_values, FP3_COUNT, 2000000000, id, "fptest3" );
}
 
//==========================================================================
 
void fptest_main( void )
{
CYG_TEST_INIT();
 
if( cyg_test_is_simulator )
{
run_ticks = RUN_TICKS_SIM;
}
 
CYG_TEST_INFO("Run fptest in cyg_start");
do_test( fpt3_values, FP3_COUNT, 1000, 0, "start" );
CYG_TEST_INFO( "cyg_start run done");
cyg_thread_create( BASE_PRI-1,
fptest1,
0,
"fptest1",
&stacks[0][0],
STACK_SIZE,
&thread[0],
&thread_struct[0]);
 
cyg_thread_resume( thread[0] );
 
cyg_thread_create( BASE_PRI,
fptest2,
1,
"fptest2",
&stacks[1][0],
STACK_SIZE,
&thread[1],
&thread_struct[1]);
 
cyg_thread_resume( thread[1] );
 
cyg_thread_create( BASE_PRI,
fptest3,
2,
"fptest3",
&stacks[2][0],
STACK_SIZE,
&thread[2],
&thread_struct[2]);
 
cyg_thread_resume( thread[2] );
 
cyg_alarm_create( cyg_real_time_clock(),
alarm_fn,
0,
&alarm,
&alarm_struct );
 
cyg_alarm_initialize( alarm, cyg_current_time()+1, 1 );
cyg_scheduler_start();
 
}
 
//==========================================================================
 
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
fptest_main();
}
 
//==========================================================================
 
#else // CYGFUN_KERNEL_API_C...
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("FP test requires:\n"
"CYGFUN_KERNEL_API_C && \n"
"CYGSEM_KERNEL_SCHED_MLQUEUE && \n"
"(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n");
}
 
#endif // CYGFUN_KERNEL_API_C, etc.
 
//==========================================================================
// EOF fptest.cxx
/thread0.cxx
0,0 → 1,114
//==========================================================================
//
// thread0.cxx
//
// Thread test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-11
// Description: Limited to checking constructors/destructors
// Omissions:
// Thread constructors with 2 or 3 args are not supported at time
// of writing test.
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/thread.inl>
 
#include "testaux.hxx"
 
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static char stack[STACKSIZE];
 
static cyg_thread_entry entry;
 
static void entry( CYG_ADDRWORD data )
{
}
 
static int *p;
 
static bool flash( void )
{
#if 0 // no facility to allocate stack exists yet.
Cyg_Thread t0( entry, 0x111 );
 
CYG_ASSERTCLASS(&t0, "error");
 
Cyg_Thread t1( entry, (CYG_ADDRWORD)&t0, STACKSIZE );
 
CYG_ASSERTCLASS(&t1, "error");
#endif
Cyg_Thread t2( CYG_SCHED_DEFAULT_INFO,
entry, (CYG_ADDRWORD)p,
"thread t2",
(CYG_ADDRESS)stack, STACKSIZE );
 
CYG_ASSERTCLASS(&t2, "error");
 
return true;
}
 
void thread0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Thread 0 OK");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
thread0_main();
}
// EOF thread0.cxx
/kintr0.c
0,0 → 1,230
/*=================================================================
//
// kintr0.c
//
// Kernel C API Intr test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm, jlarmour
// Date: 1999-02-16
// Description: Very basic test of interrupt objects
// Options:
// CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
// CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE_MAX
// CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
//####DESCRIPTIONEND####
*/
 
#include <cyg/kernel/kapi.h>
#include <cyg/hal/hal_intr.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
static cyg_interrupt intr_obj[2];
 
static cyg_handle_t intr0, intr1;
 
 
static cyg_ISR_t isr0, isr1;
static cyg_DSR_t dsr0, dsr1;
 
static cyg_uint32 isr0(cyg_vector_t vector, cyg_addrword_t data)
{
CYG_UNUSED_PARAM(cyg_addrword_t, data);
 
cyg_interrupt_acknowledge(vector);
return 0;
}
 
static void dsr0(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
CYG_UNUSED_PARAM(cyg_vector_t, vector);
CYG_UNUSED_PARAM(cyg_ucount32, count);
CYG_UNUSED_PARAM(cyg_addrword_t, data);
}
 
static cyg_uint32 isr1(cyg_vector_t vector, cyg_addrword_t data)
{
CYG_UNUSED_PARAM(cyg_vector_t, vector);
CYG_UNUSED_PARAM(cyg_addrword_t, data);
return 0;
}
 
static void dsr1(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
CYG_UNUSED_PARAM(cyg_vector_t, vector);
CYG_UNUSED_PARAM(cyg_ucount32, count);
CYG_UNUSED_PARAM(cyg_addrword_t, data);
}
 
static bool flash( void )
{
cyg_handle_t handle;
cyg_interrupt intr;
 
cyg_interrupt_create(CYGNUM_HAL_ISR_MIN, 0, (cyg_addrword_t)333,
isr0, dsr0, &handle, &intr );
cyg_interrupt_delete(handle);
 
return true;
}
 
/* IMPORTANT: The calling convention for VSRs is target dependent. It is
* unlikely that a plain C or C++ routine would function correctly on any
* particular platform, even if it could correctly access the system
* resources necessary to handle the event that caused it to be called.
* VSRs usually must be written in assembly language.
*
* This is just a test program. The routine vsr0() below is defined simply
* to define an address that will be in executable memory. If an event
* causes this VSR to be called, all bets are off. If it is accidentally
* installed in the vector for the realtime clock, the system will likely
* freeze.
*/
 
static cyg_VSR_t vsr0;
 
static void vsr0()
{
}
 
void kintr0_main( void )
{
cyg_vector_t v = (CYGNUM_HAL_VSR_MIN + 11) % CYGNUM_HAL_VSR_COUNT;
cyg_vector_t v1;
cyg_vector_t lvl1 = CYGNUM_HAL_ISR_MIN + (1 % CYGNUM_HAL_ISR_COUNT);
cyg_vector_t lvl2 = CYGNUM_HAL_ISR_MIN + (15 % CYGNUM_HAL_ISR_COUNT);
int in_use;
 
cyg_VSR_t *old_vsr, *new_vsr;
 
CYG_TEST_INIT();
#ifdef CYGPKG_HAL_MIPS_TX39
// This can be removed when PR 17831 is fixed
if ( cyg_test_is_simulator )
v1 = 12 % CYGNUM_HAL_ISR_COUNT;
else /* NOTE TRAILING ELSE... */
#endif
v1 = CYGNUM_HAL_ISR_MIN + ( 6 % CYGNUM_HAL_ISR_COUNT);
 
CHECK(flash());
CHECK(flash());
 
// Make sure the chosen levels are not already in use.
HAL_INTERRUPT_IN_USE( lvl1, in_use );
intr0 = 0;
if (!in_use)
cyg_interrupt_create(lvl1, 1, (cyg_addrword_t)777, isr0, dsr0,
&intr0, &intr_obj[0]);
HAL_INTERRUPT_IN_USE( lvl2, in_use );
intr1 = 0;
if (!in_use && lvl1 != lvl2)
cyg_interrupt_create(lvl2, 1, 888, isr1, dsr1, &intr1, &intr_obj[1]);
 
// Check these functions at least exist
 
cyg_interrupt_disable();
cyg_interrupt_enable();
 
if (intr0)
cyg_interrupt_attach(intr0);
if (intr1)
cyg_interrupt_attach(intr1);
if (intr0)
cyg_interrupt_detach(intr0);
if (intr1)
cyg_interrupt_detach(intr1);
 
// If this attaching interrupt replaces the previous interrupt
// instead of adding to it we could be in a big mess if the
// vector is being used by something important.
cyg_interrupt_get_vsr( v, &old_vsr );
cyg_interrupt_set_vsr( v, vsr0 );
cyg_interrupt_get_vsr( v, &new_vsr );
CHECK( vsr0 == new_vsr );
 
new_vsr = NULL;
cyg_interrupt_get_vsr( v, &new_vsr );
cyg_interrupt_set_vsr( v, old_vsr );
CHECK( new_vsr == vsr0 );
 
cyg_interrupt_set_vsr( v, new_vsr );
new_vsr = NULL;
cyg_interrupt_get_vsr( v, &new_vsr );
CHECK( vsr0 == new_vsr );
 
cyg_interrupt_set_vsr( v, old_vsr );
CHECK( vsr0 == new_vsr );
new_vsr = NULL;
cyg_interrupt_get_vsr( v, &new_vsr );
CHECK( old_vsr == new_vsr );
CHECK( NULL != vsr0 );
 
cyg_interrupt_mask(v1);
cyg_interrupt_unmask(v1);
cyg_interrupt_configure(v1, true, true);
 
CYG_TEST_PASS_FINISH("Kernel C API Intr 0 OK");
}
 
externC void
cyg_start( void )
{
kintr0_main();
}
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF kintr0.c */
/thread1.cxx
0,0 → 1,172
//==========================================================================
//
// thread1.cxx
//
// Thread test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-11
// Description: Tests some basic thread functions.
// Omissions: Cyg_ThreadTimer
// Cyg_Thread
// exit -- not necessarily called
// yield
// set_priority
// get_priority
// get/set_sleep_reason
// get/set_wake_reason
// set/clear_timer
// Cyg_ThreadQueue
//
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/thread.hxx>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
 
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/thread.inl>
 
#include "testaux.hxx"
 
#ifdef CYGNUM_HAL_STACK_SIZE_TYPICAL
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
#else
#define STACKSIZE 2000
#endif
 
static char stack[2][STACKSIZE];
 
static char thread[2][sizeof(Cyg_Thread)];
 
static Cyg_Thread *pt0,*pt1;
static cyg_uint16 uid0,uid1;
 
 
static void entry0( CYG_ADDRWORD data )
{
CHECK( 222 == data );
 
uid0 = pt0->get_unique_id();
 
pt1->suspend();
pt1->resume();
 
do {
pt0->delay(1);
} while( Cyg_Thread::RUNNING == pt1->get_state() );
CHECK( Cyg_Thread::SLEEPING == pt1->get_state() );
 
pt1->wake();
 
CHECK( uid0 != uid1 );
 
CYG_TEST_PASS_FINISH("Thread 1 OK");
}
 
static void entry1( CYG_ADDRWORD data )
{
CHECK( 333 == data );
 
uid1 = pt1->get_unique_id();
 
Cyg_Thread *self = Cyg_Thread::self();
CHECK( self == pt1 );
 
pt1->sleep();
pt1->suspend();
 
Cyg_Thread::exit(); // no guarantee this will be called
}
 
void thread1_main( void )
{
CYG_TEST_INIT();
 
pt0 = new((void *)&thread[0])
Cyg_Thread(CYG_SCHED_DEFAULT_INFO,
entry0, 222,
"thread 0",
(CYG_ADDRESS)stack[0], STACKSIZE );
pt1 = new((void *)&thread[1])
Cyg_Thread(CYG_SCHED_DEFAULT_INFO,
entry1, 333,
"thread 1",
(CYG_ADDRESS)stack[1], STACKSIZE );
 
CYG_ASSERTCLASS( pt0, "error" );
CYG_ASSERTCLASS( pt1, "error" );
 
pt0->resume();
pt1->resume();
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
thread1_main();
}
 
#else // ifdef CYGFUN_KERNEL_THREADS_TIMER
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel threads timer disabled");
}
 
#endif // ifdef CYGFUN_KERNEL_THREADS_TIMER
 
// EOF thread1.cxx
/thread2.cxx
0,0 → 1,236
//==========================================================================
//
// thread2.cxx
//
// Thread test 2
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-19
// Description:
// tests scheduler & threads & priorities
// + create multiple threads with various priorities
// + check highest priority running thread is always running
// + check next highest runs when highest suspended
// + check several threads of equal priority share time
// (only !CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES)
// + check other threads are starved
// + check setting priority dynamically causes a thread to
// become/stay current/non-current
// Omissions:
// check yield
// check can set threads with min and max priority
// Options:
// CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES
// CYGIMP_THREAD_PRIORITY
// CYGNUM_KERNEL_SCHED_PRIORITIES
// CYGSEM_KERNEL_SCHED_BITMAP
// CYGSEM_KERNEL_SCHED_MLQUEUE
//####DESCRIPTIONEND####
//==========================================================================
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
// ------------------------------------------------------------------------
 
#if defined(CYGIMP_THREAD_PRIORITY) && \
!defined(CYGPKG_KERNEL_SMP_SUPPORT)
 
// ------------------------------------------------------------------------
 
static Cyg_Counting_Semaphore s0, s1, s2;
 
static volatile cyg_ucount8 q = 0;
 
static Cyg_Thread *thread0, *thread1, *thread2;
 
#define NTHREADS 3
#include "testaux.hxx"
 
// ------------------------------------------------------------------------
 
static void entry0( CYG_ADDRWORD data )
{
CHECK( 0 == q++ );
s0.wait();
CHECK( 3 == q++ );
s1.post();
CHECK( 4 == q++ );
s0.wait();
s0.wait();
CYG_TEST_PASS_FINISH("Thread 2 OK");
}
 
// ------------------------------------------------------------------------
 
static void entry1( CYG_ADDRWORD data )
{
CHECK( 1 == q++ );
s1.wait();
CHECK( 5 == q++ );
thread0->set_priority(9);
s0.post();
CHECK( 6 == q++ );
thread2->set_priority(3);
CHECK( 8 == q++ );
s2.post();
CHECK( 12 == q++ );
CHECK( 9 == thread0->get_priority() );
CHECK( 6 == thread1->get_priority() );
CHECK( 7 == thread2->get_priority() );
q = 100;
#if !(CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES) \
&& defined(CYGSEM_KERNEL_SCHED_TIMESLICE)
thread2->set_priority(6);
CHECK( 6 == thread1->get_priority() );
CHECK( 6 == thread2->get_priority() );
 
while ( 100 == q )
;
CHECK( 101 == q++ );
s1.wait();
CHECK( 103 == q++ );
#endif
s0.post();
s1.wait();
}
 
// ------------------------------------------------------------------------
 
static void entry2( CYG_ADDRWORD data )
{
CHECK( 2 == q++ );
s0.post();
CHECK( 7 == q++ );
s2.wait();
CHECK( 9 == q++ );
thread1->set_priority(6);
CHECK( 10 == q++ );
thread2->set_priority(2);
CHECK( 11 == q++ );
thread2->set_priority(7);
 
#if !(CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES) \
&& defined(CYGSEM_KERNEL_SCHED_TIMESLICE)
CHECK( 6 == thread1->get_priority() );
CHECK( 6 == thread2->get_priority() );
 
CHECK( 100 == q++ );
while ( 101 == q )
;
CHECK( 102 == q++ );
s1.post();
#endif
s0.post();
s2.wait();
}
 
 
// ------------------------------------------------------------------------
 
void thread2_main( void )
{
CYG_TEST_INIT();
thread0 = new_thread( entry0, 0 );
thread1 = new_thread( entry1, 1 );
thread2 = new_thread( entry2, 2 );
 
thread0->resume();
thread1->resume();
thread2->resume();
 
thread0->set_priority(5);
thread1->set_priority(6);
thread2->set_priority(7);
 
if( 9 >= CYG_THREAD_MIN_PRIORITY )
CYG_TEST_FAIL_FINISH("Test requires priorities up to 9");
 
if( 2 <= CYG_THREAD_MAX_PRIORITY )
CYG_TEST_FAIL_FINISH("Test requires priorities as low as 2");
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Unresolved");
}
 
// ------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
thread2_main();
}
// ------------------------------------------------------------------------
 
 
#else // CYGPKG_KERNEL_SMP_SUPPORT etc
 
// ------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_PASS_FINISH("Thread2 test requires:\n"
"defined(CYGIMP_THREAD_PRIORITY) &&\n"
"!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
 
}
 
// ------------------------------------------------------------------------
 
#endif // CYGPKG_KERNEL_SMP_SUPPORT etc
 
// ------------------------------------------------------------------------
// EOF thread2.cxx
/kill.cxx
0,0 → 1,199
//==========================================================================
//
// kill.cxx
//
// Thread kill test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 1998-04-24
// Description: Tests the functionality of thread kill() and
// reinitalize().
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
 
#include <cyg/kernel/sched.inl>
 
#define NTHREADS 3
 
#include "testaux.hxx"
 
// In general, this delay has to be long enough to account for slow targets
// and potential problems on e.g. the linux synthetic target to avoid
// potential problems due to timing inaccuracy and scheduling of Linux
// tasks. It is decreased further below for simulators.
int delay_ticks = 5;
 
 
static Cyg_Binary_Semaphore s0, s1;
 
volatile cyg_atomic thread0_state;
volatile cyg_atomic thread1_state;
volatile cyg_atomic thread2_state;
 
static void entry0( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
 
thread0_state = 1;
s0.wait();
 
thread0_state = 2;
CYG_TEST_FAIL_FINISH("Thread not killed");
 
self->exit();
}
 
 
static void entry1( CYG_ADDRWORD data )
{
Cyg_Thread *self = Cyg_Thread::self();
 
thread1_state = 1;
self->delay(delay_ticks);
 
if( thread2_state != 1 )
CYG_TEST_FAIL_FINISH("Thread2 in wrong state");
thread1_state = 2;
thread[0]->kill();
 
thread1_state = 3;
thread[2]->kill();
 
thread1_state = 4;
self->delay(delay_ticks);
 
thread1_state = 5;
thread2_state = 0;
thread[2]->reinitialize();
thread[2]->resume();
 
self->delay(delay_ticks);
 
if( thread2_state != 1 )
CYG_TEST_FAIL_FINISH("Thread2 in wrong state");
thread1_state = 6;
 
self->delay(delay_ticks);
 
if( thread2_state != 2 )
CYG_TEST_FAIL_FINISH("Thread2 in wrong state");
thread[2]->kill();
 
thread1_state = 7;
CYG_TEST_PASS_FINISH("Kill OK");
Cyg_Thread::self()->exit();
}
 
static void entry2( CYG_ADDRWORD data )
{
thread2_state = 1;
 
while( thread1_state != 6 ) continue;
 
thread2_state = 2;
for(;;) continue;
}
 
void release_main(void)
{
CYG_TEST_INIT();
 
if (cyg_test_is_simulator)
delay_ticks = 2;
 
new_thread( entry0, 0);
new_thread( entry1, 1);
new_thread( entry2, 2);
 
thread[0]->set_priority(5);
thread[1]->set_priority(6);
thread[2]->set_priority(7);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
release_main();
}
 
#else // ifdef CYGFUN_KERNEL_THREADS_TIMER
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel threads timer disabled");
}
 
#endif // ifdef CYGFUN_KERNEL_THREADS_TIMER
// EOF kill.cxx
/tcdiag.cxx
0,0 → 1,97
//==========================================================================
//
// tcdiag.cxx
//
// Kernel diag test harness.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-17
// Description: Test harness implementation that uses the kernel's
// diag channel. This is intended for manual testing
// of the kernel.
//####DESCRIPTIONEND####
 
#include <testcase.h>
#include <diag.h>
 
bool cyg_test_is_simulator=false; // infrastructure changes as necessary
 
void cyg_test_init()
{
diag_init();
}
 
void cyg_test_output(int status, char *msg, int line, char *file)
{
char *st;
 
switch (status) {
case 0:
st = "FAIL:";
break;
case 1:
st = "PASS:";
break;
case 2:
st = "EXIT:";
break;
case 3:
st = "INFO:";
break;
}
 
diag_write_string(st);
diag_write_char('<');
diag_write_string(msg);
diag_write_string("> Line: ");
diag_write_dec(line);
diag_write_string(", File: ");
diag_write_string(file);
diag_write_char('\n');
 
}
 
// This is an appropriate function to set a breakpoint on
void cyg_test_exit()
{
for(;;)
;
}
// EOF tcdiag.cxx
/bin_sem0.cxx
0,0 → 1,89
//==========================================================================
//
// bin_sem0.cxx
//
// Binary semaphore test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: Limited to checking constructors/destructors
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include "testaux.hxx"
 
static Cyg_Binary_Semaphore sema0, sema1(false), sema2(true);
 
 
static bool flash( void )
{
Cyg_Binary_Semaphore s0;
 
Cyg_Binary_Semaphore s1(true);
 
Cyg_Binary_Semaphore s2(false);
 
return true;
}
 
void bin_sem0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Binary Semaphore 0 OK");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
bin_sem0_main();
}
// EOF bin_sem0.cxx
/bin_sem1.cxx
0,0 → 1,130
//==========================================================================
//
// bin_sem1.cxx
//
// Binary semaphore test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: Tests basic binary semaphore functionality.
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
#include <cyg/kernel/thread.hxx> // Cyg_Thread
#include <cyg/kernel/thread.inl>
 
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
#define NTHREADS 2
 
#include "testaux.hxx"
 
static Cyg_Binary_Semaphore s0(true), s1(false), s2;
 
static volatile cyg_ucount8 q = 0;
 
static void entry0( CYG_ADDRWORD data )
{
s0.wait();
CHECK( 0 == q++ );
s1.post();
s0.wait();
CHECK( 2 == q++ );
CHECK( ! s0.posted() );
CHECK( ! s0.trywait() );
s0.post();
CHECK( 3 == q++ );
CHECK( s0.posted() );
s1.post();
CHECK( ! s2.posted() );
s2.wait();
CHECK( 5 == q++ );
CYG_TEST_PASS_FINISH("Binary Semaphore 1 OK");
}
 
static void entry1( CYG_ADDRWORD data )
{
CHECK( s1.posted() );
s1.wait();
CHECK( 1 == q++ );
CHECK( ! s0.posted() );
s0.post();
s1.wait();
CHECK( 4 == q++ );
CHECK( s0.posted() );
CHECK( s0.trywait() );
CHECK( ! s0.posted() );
s2.post();
s0.wait();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
void bin_sem1_main( void )
{
CYG_TEST_INIT();
 
new_thread( entry0, 0);
new_thread( entry1, 1);
#ifdef CYGIMP_THREAD_PRIORITY
thread[0]->set_priority( 4 );
thread[1]->set_priority( 5 ); // make sure the threads execute as intended
#endif
 
Cyg_Scheduler::start();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
bin_sem1_main();
}
// EOF bin_sem1.cxx
/bin_sem2.cxx
0,0 → 1,224
//==========================================================================
//
// bin_sem2.cxx
//
// Binary semaphore test 2
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg,dsm
// Contributors: dsm
// Date: 1998-03-10
// Description:
// Dining philosophers test. Based on philo.cxx
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/mutex.hxx>
 
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
static cyg_ucount16 PHILO_LOOPS = 1000;
 
#define PHILOSOPHERS 15
#define NTHREADS PHILOSOPHERS
#include "testaux.hxx"
 
static Cyg_Binary_Semaphore chopstick[PHILOSOPHERS];
 
static char pstate[PHILOSOPHERS+1]; // state of each philosopher
 
static cyg_ucount16 state_changes = 0;
// state_changes keep track of number of changes to pstate so
// we can exit after we've seen enough.
 
 
static Cyg_Mutex pstate_mutex;
static Cyg_Mutex cycle_mutex;
 
static inline int left(cyg_count8 i)
{
return (0 == i) ? PHILOSOPHERS-1 : i-1 ;
}
static inline int right(cyg_count8 i)
{
return (PHILOSOPHERS == i+1) ? 0 : i+1 ;
}
 
void change_state(int id, char newstate)
{
if (PHILO_LOOPS == state_changes++)
CYG_TEST_PASS_FINISH("Binary Semaphore 2 OK");
 
pstate_mutex.lock(); {
pstate[id] = newstate;
bool all_hungry = true; // until proved otherwise
for(cyg_ucount8 i=0; i < PHILOSOPHERS; i++) {
if('E' == pstate[i]) {
CHECK('E' != pstate[left(i)]);
CHECK('E' != pstate[right(i)]);
}
if('H' != pstate[i]) {
all_hungry = false;
}
}
// Theoretically it is possible for all the philosophers to be
// hungry but not waiting on semaphores. But in practice this
// means something is wrong.
CHECK(false == all_hungry);
} pstate_mutex.unlock();
}
 
char get_state(int id)
{
pstate_mutex.lock();
char s = pstate[id];
 
pstate_mutex.unlock();
 
return s;
}
 
// -------------------------------------------------------------------------
// Thread to behave like a philosopher
 
void Philosopher( CYG_ADDRESS id )
{
Cyg_Thread *self = Cyg_Thread::self();
Cyg_Binary_Semaphore *first_stick = &chopstick[id];
Cyg_Binary_Semaphore *second_stick = &chopstick[(id+1)%PHILOSOPHERS];
CHECK( id >= 0 && id < PHILOSOPHERS);
 
// Deadlock avoidance. The easiest way to make the philosophers
// behave is to make each pick up the lowest numbered stick
// first. This is how it works out anyway for all the philosophers
// except the last, who must have his sticks swapped.
if( id == PHILOSOPHERS-1 )
{
Cyg_Binary_Semaphore *t = first_stick;
first_stick = second_stick;
second_stick = t;
}
// The following variable is shared by all philosophers.
// It is incremented unprotected, but this does not matter
// since it is only present to introduce a little variability
// into the think and eat times.
static int cycle = 0;
for(;;)
{
// Think for a bit
 
self->delay((id+cycle++)%12); // Cogito ergo sum...
 
// I am now hungry, try to get the chopsticks
change_state(id,'H');
 
// Get the sticks
first_stick->wait();
second_stick->wait();
 
// Got them, now eat
change_state(id,'E');
// Check that the world is as I think it is...
CYG_TEST_CHECK( !first_stick->posted(),
"Not got first stick");
CYG_TEST_CHECK( !second_stick->posted(),
"Not got second stick");
CYG_TEST_CHECK( get_state(left(id)) != 'E',
"Left neighbour also eating!!");
CYG_TEST_CHECK( get_state(right(id)) != 'E',
"Right neighbour also eating!!");
self->delay((id+cycle++)%6); // munch munch
 
// Finished eating, put down sticks.
 
change_state(id,'T');
 
// put sticks back on table
first_stick->post();
second_stick->post();
}
}
 
// -------------------------------------------------------------------------
 
void bin_sem2_main( void )
{
CYG_TEST_INIT();
 
if (cyg_test_is_simulator)
PHILO_LOOPS = 100;
 
for( int i = 0; i < PHILOSOPHERS; i++ )
{
pstate[i] = 'T'; // starting state
new_thread(Philosopher, i);
 
// make the matching chopstick present
chopstick[i].post();
}
Cyg_Scheduler::scheduler.start();
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
bin_sem2_main();
}
// EOF bin_sem2.cxx
/dhrystone.c
0,0 → 1,1176
//=============================================================================
//####UNSUPPORTEDBEGIN####
//
// -------------------------------------------
// This source file has been contributed to eCos/Red Hat. It may have been
// changed slightly to provide an interface consistent with those of other
// files.
//
// The functionality and contents of this file is supplied "AS IS"
// without any form of support and will not necessarily be kept up
// to date by Red Hat.
//
// The style of programming used in this file may not comply with the
// eCos programming guidelines. Please do not use as a base for other
// files.
//
// All inquiries about this file, or the functionality provided by it,
// should be directed to the 'ecos-discuss' mailing list (see
// http://sourceware.cygnus.com/ecos/intouch.html for details).
//
// -------------------------------------------
//
//####UNSUPPORTEDEND####
//=============================================================================
// Originally three different files, dhry.h, dhry21a.c and dhry21b.c
// Merged into one file and changed a little to avoid compilation warnings.
// The files were found at:
// FTP ftp.nosc.mil/pub/aburto/dhrystone
//=============================================================================
 
#include <pkgconf/system.h>
#include <pkgconf/infra.h>
#include <pkgconf/kernel.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/testcase.h>
 
#if !defined(CYGPKG_ISOINFRA)
# define NA_MSG "Requires CYGPKG_ISOINFRA"
#else
# include <pkgconf/isoinfra.h>
 
# if !defined(CYGFUN_KERNEL_API_C) \
|| !defined(CYGINT_ISO_STDIO_FORMATTED_IO) \
|| CYGINT_ISO_MALLOC == 0 \
|| !defined(CYGINT_ISO_STRING_STRFUNCS)
 
# define NA_MSG "Requires CYGFUN_KERNEL_API_C && CYGINT_ISO_STDIO_FORMATTED_IO && CYGINT_ISO_MALLOC && CYGINT_ISO_STRING_STRFUNCS"
 
# elif !defined(__OPTIMIZE__) \
|| defined(CYGPKG_INFRA_DEBUG) \
|| defined(CYGPKG_KERNEL_INSTRUMENT)
# define NA_MSG "Only runs with optimized code, no tracing and no asserts"
# elif defined(CYGDBG_INFRA_DIAG_USE_DEVICE)
# define NA_MSG "Must use HAL diag output to avoid background DSR activity"
# endif
#endif
 
#ifndef NA_MSG
 
#include <cyg/hal/hal_cache.h>
#include <cyg/kernel/kapi.h>
#include <stdlib.h>
#include <string.h>
 
// Time in seconds.
double
dtime(void)
{
return (double) cyg_current_time() / 100;
}
 
// Number of loops to run.
#if defined(CYGPRI_KERNEL_TESTS_DHRYSTONE_PASSES)
# define PASSES CYGPRI_KERNEL_TESTS_DHRYSTONE_PASSES
#else
# define PASSES 400000
#endif
 
// Used in the code below to mark changes to the code.
#define __ECOS__
 
#undef true
#undef false
 
 
/*
*************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry.h (part 1 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
* Siemens Nixdorf Inf. Syst.
* STM OS 32
* Otto-Hahn-Ring 6
* W-8000 Muenchen 83
* Germany
* Phone: [+49]-89-636-42436
* (8-17 Central European Time)
* UUCP: weicker@ztivax.uucp@unido.uucp
* Internet: weicker@ztivax.siemens.com
*
* Original Version (in Ada) published in
* "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
* pp. 1013 - 1030, together with the statistics
* on which the distribution of statements etc. is based.
*
* In this C version, the following C library functions are
* used:
* - strcpy, strcmp (inside the measurement loop)
* - printf, scanf (outside the measurement loop)
*
* Collection of Results:
* Reinhold Weicker (address see above) and
*
* Rick Richardson
* PC Research. Inc.
* 94 Apple Orchard Drive
* Tinton Falls, NJ 07724
* Phone: (201) 834-1378 (9-17 EST)
* UUCP: ...!uunet!pcrat!rick
*
* Please send results to Rick Richardson and/or Reinhold Weicker.
* Complete information should be given on hardware and software
* used. Hardware information includes: Machine type, CPU, type and
* size of caches; for microprocessors: clock frequency, memory speed
* (number of wait states). Software information includes: Compiler
* (and runtime library) manufacturer and version, compilation
* switches, OS version. The Operating System version may give an
* indication about the compiler; Dhrystone itself performs no OS
* calls in the measurement loop.
*
* The complete output generated by the program should be mailed
* such that at least some checks for correctness can be made.
*
*************************************************************************
*
* History: This version C/2.1 has been made for two reasons:
*
* 1) There is an obvious need for a common C version of
* Dhrystone, since C is at present the most popular system
* programming language for the class of processors
* (microcomputers, minicomputers) where Dhrystone is used
* most. There should be, as far as possible, only one C
* version of Dhrystone such that results can be compared
* without restrictions. In the past, the C versions
* distributed by Rick Richardson (Version 1.1) and by
* Reinhold Weicker had small (though not significant)
* differences.
*
* 2) As far as it is possible without changes to the
* Dhrystone statistics, optimizing compilers should be
* prevented from removing significant statements.
*
* This C version has been developed in cooperation with
* Rick Richardson (Tinton Falls, NJ), it incorporates many
* ideas from the "Version 1.1" distributed previously by
* him over the UNIX network Usenet.
* I also thank Chaim Benedelac (National Semiconductor),
* David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
* Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
* for their help with comments on earlier versions of the
* benchmark.
*
* Changes: In the initialization part, this version follows mostly
* Rick Richardson's version distributed via Usenet, not the
* version distributed earlier via floppy disk by Reinhold
* Weicker. As a concession to older compilers, names have
* been made unique within the first 8 characters. Inside the
* measurement loop, this version follows the version
* previously distributed by Reinhold Weicker.
*
* At several places in the benchmark, code has been added,
* but within the measurement loop only in branches that
* are not executed. The intention is that optimizing
* compilers should be prevented from moving code out of the
* measurement loop, or from removing code altogether. Since
* the statements that are executed within the measurement
* loop have NOT been changed, the numbers defining the
* "Dhrystone distribution" (distribution of statements,
* operand types and locality) still hold. Except for
* sophisticated optimizing compilers, execution times for
* this version should be the same as for previous versions.
*
* Since it has proven difficult to subtract the time for the
* measurement loop overhead in a correct way, the loop check
* has been made a part of the benchmark. This does have
* an impact - though a very minor one - on the distribution
* statistics which have been updated for this version.
*
* All changes within the measurement loop are described
* and discussed in the companion paper "Rationale for
* Dhrystone version 2".
*
* Because of the self-imposed limitation that the order and
* distribution of the executed statements should not be
* changed, there are still cases where optimizing compilers
* may not generate code for some statements. To a certain
* degree, this is unavoidable for small synthetic
* benchmarks. Users of the benchmark are advised to check
* code listings whether code is generated for all statements
* of Dhrystone.
*
* Version 2.1 is identical to version 2.0 distributed via
* the UNIX network Usenet in March 1988 except that it
* corrects some minor deficiencies that were found by users
* of version 2.0. The only change within the measurement
* loop is that a non-executed "else" part was added to the
* "if" statement in Func_3, and a non-executed "else" part
* removed from Proc_3.
*
*************************************************************************
*
* Defines: The following "Defines" are possible:
* -DROPT (default: Not defined)
* As an approximation to what an average C
* programmer might do, the "register" storage class
* is applied (if enabled by -DROPT)
* - for local variables, if they are used
* (dynamically) five or more times
* - for parameters if they are used (dynamically)
* six or more times
* Note that an optimal "register" strategy is
* compiler-dependent, and that "register"
* declarations do not necessarily lead to faster
* execution.
* -DNOSTRUCTASSIGN (default: Not defined)
* Define if the C compiler does not support
* assignment of structures.
* -DNOENUMS (default: Not defined)
* Define if the C compiler does not support
* enumeration types.
*
*************************************************************************
*
* Compilation model and measurement (IMPORTANT):
*
* This C version of Dhrystone consists of three files:
* - dhry.h (this file, containing global definitions and comments)
* - dhry_1.c (containing the code corresponding to Ada package Pack_1)
* - dhry_2.c (containing the code corresponding to Ada package Pack_2)
*
* The following "ground rules" apply for measurements:
* - Separate compilation
* - No procedure merging
* - Otherwise, compiler optimizations are allowed but should be
* indicated
* - Default results are those without register declarations
* See the companion paper "Rationale for Dhrystone Version 2" for a more
* detailed discussion of these ground rules.
*
* For 16-Bit processors (e.g. 80186, 80286), times for all compilation
* models ("small", "medium", "large" etc.) should be given if possible,
* together with a definition of these models for the compiler system
* used.
*
*************************************************************************
*
* Dhrystone (C version) statistics:
*
* [Comment from the first distribution, updated for version 2.
* Note that because of language differences, the numbers are slightly
* different from the Ada version.]
*
* The following program contains statements of a high level programming
* language (here: C) in a distribution considered representative:
*
* assignments 52 (51.0 %)
* control statements 33 (32.4 %)
* procedure, function calls 17 (16.7 %)
*
* 103 statements are dynamically executed. The program is balanced with
* respect to the three aspects:
*
* - statement type
* - operand type
* - operand locality
* operand global, local, parameter, or constant.
*
* The combination of these three aspects is balanced only approximately.
*
* 1. Statement Type:
* ----------------- number
*
* V1 = V2 9
* (incl. V1 = F(..)
* V = Constant 12
* Assignment, 7
* with array element
* Assignment, 6
* with record component
* --
* 34 34
*
* X = Y +|-|"&&"|"|" Z 5
* X = Y +|-|"==" Constant 6
* X = X +|- 1 3
* X = Y *|/ Z 2
* X = Expression, 1
* two operators
* X = Expression, 1
* three operators
* --
* 18 18
*
* if .... 14
* with "else" 7
* without "else" 7
* executed 3
* not executed 4
* for ... 7 | counted every time
* while ... 4 | the loop condition
* do ... while 1 | is evaluated
* switch ... 1
* break 1
* declaration with 1
* initialization
* --
* 34 34
*
* P (...) procedure call 11
* user procedure 10
* library procedure 1
* X = F (...)
* function call 6
* user function 5
* library function 1
* --
* 17 17
* ---
* 103
*
* The average number of parameters in procedure or function calls
* is 1.82 (not counting the function values as implicit parameters).
*
*
* 2. Operators
* ------------
* number approximate
* percentage
*
* Arithmetic 32 50.8
*
* + 21 33.3
* - 7 11.1
* * 3 4.8
* / (int div) 1 1.6
*
* Comparison 27 42.8
*
* == 9 14.3
* /= 4 6.3
* > 1 1.6
* < 3 4.8
* >= 1 1.6
* <= 9 14.3
*
* Logic 4 6.3
*
* && (AND-THEN) 1 1.6
* | (OR) 1 1.6
* ! (NOT) 2 3.2
*
* -- -----
* 63 100.1
*
*
* 3. Operand Type (counted once per operand reference):
* ---------------
* number approximate
* percentage
*
* Integer 175 72.3 %
* Character 45 18.6 %
* Pointer 12 5.0 %
* String30 6 2.5 %
* Array 2 0.8 %
* Record 2 0.8 %
* --- -------
* 242 100.0 %
*
* When there is an access path leading to the final operand (e.g. a
* record component), only the final data type on the access path is
* counted.
*
*
* 4. Operand Locality:
* -------------------
* number approximate
* percentage
*
* local variable 114 47.1 %
* global variable 22 9.1 %
* parameter 45 18.6 %
* value 23 9.5 %
* reference 22 9.1 %
* function result 6 2.5 %
* constant 55 22.7 %
* --- -------
* 242 100.0 %
*
*
* The program does not compute anything meaningful, but it is
* syntactically and semantically correct. All variables have a value
* assigned to them before they are used as a source operand.
*
* There has been no explicit effort to account for the effects of a
* cache, or to balance the use of long or short displacements for code
* or data.
*
*************************************************************************
*/
 
/* Compiler and system dependent definitions: */
 
#define Mic_secs_Per_Second 1000000.0
/* Berkeley UNIX C returns process times in seconds/HZ */
 
#ifdef NOSTRUCTASSIGN
#define structassign(d, s) memcpy(&(d), &(s), sizeof(d))
#else
#define structassign(d, s) d = s
#endif
 
#ifdef NOENUM
#define Ident_1 0
#define Ident_2 1
#define Ident_3 2
#define Ident_4 3
#define Ident_5 4
typedef int Enumeration;
#else
typedef enum {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
Enumeration;
#endif
/* for boolean and enumeration types in Ada, Pascal */
 
/* General definitions: */
 
#include <stdio.h>
/* for strcpy, strcmp */
 
#define Null 0
/* Value of a Null pointer */
#define true 1
#define false 0
 
typedef int One_Thirty;
typedef int One_Fifty;
typedef char Capital_Letter;
typedef int Boolean;
typedef char Str_30 [31];
typedef int Arr_1_Dim [50];
typedef int Arr_2_Dim [50] [50];
 
typedef struct record
{
struct record *Ptr_Comp;
Enumeration Discr;
union {
struct {
Enumeration Enum_Comp;
int Int_Comp;
char Str_Comp [31];
} var_1;
struct {
Enumeration E_Comp_2;
char Str_2_Comp [31];
} var_2;
struct {
char Ch_1_Comp;
char Ch_2_Comp;
} var_3;
} variant;
} Rec_Type, *Rec_Pointer;
 
#ifdef __ECOS__
 
#ifndef ROPT
#define REG
/* REG becomes defined as empty */
/* i.e. no register variables */
#else
#define REG register
#endif
 
Boolean Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
Boolean Func_3 (Enumeration Enum_Par_Val);
 
void Proc_1 (REG Rec_Pointer Ptr_Val_Par);
void Proc_2 (One_Fifty* Int_Par_Ref);
void Proc_3 (Rec_Pointer *Ptr_Ref_Par);
void Proc_4 (void);
void Proc_5 (void);
void Proc_6 (Enumeration Enum_Val_Par, Enumeration* Enum_Ref_Par);
void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val,
One_Fifty* Int_Par_Ref);
void Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref,
int Int_1_Par_Val, int Int_2_Par_Val);
Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
 
#endif // __ECOS__
 
/*
*************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry_1.c (part 2 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
*
*************************************************************************
*/
 
#include <stdio.h>
#ifndef __ECOS__
#include "dhry.h"
#endif // __ECOS__
 
/* Global Variables: */
 
Rec_Pointer Ptr_Glob,
Next_Ptr_Glob;
int Int_Glob;
Boolean Bool_Glob;
char Ch_1_Glob,
Ch_2_Glob;
int Arr_1_Glob [50];
int Arr_2_Glob [50] [50];
 
char Reg_Define[] = "Register option selected.";
 
#ifndef __ECOS__
extern char *malloc ();
Enumeration Func_1 ();
#endif
/*
forward declaration necessary since Enumeration may not simply be int
*/
 
#ifndef __ECOS__
#ifndef ROPT
#define REG
/* REG becomes defined as empty */
/* i.e. no register variables */
#else
#define REG register
#endif
#endif
 
/* variables for time measurement: */
 
#define Too_Small_Time 2
/* Measurements should last at least 2 seconds */
 
double Begin_Time,
End_Time,
User_Time;
 
double Microseconds,
Dhrystones_Per_Second,
Vax_Mips;
 
/* end of variables for time measurement */
 
 
#ifndef __ECOS__
void main ()
#else // __ECOS__
int main (void)
#endif // __ECOS__
/*****/
 
/* main program, corresponds to procedures */
/* Main and Proc_0 in the Ada version */
{
#ifndef __ECOS__
double dtime();
#endif // __ECOS__
 
One_Fifty Int_1_Loc;
REG One_Fifty Int_2_Loc;
One_Fifty Int_3_Loc;
REG char Ch_Index;
Enumeration Enum_Loc;
Str_30 Str_1_Loc;
Str_30 Str_2_Loc;
REG int Run_Index;
REG int Number_Of_Runs;
 
 
#ifdef __ECOS__
 
CYG_TEST_INIT();
 
#ifdef CYG_HAL_I386_LINUX
CYG_TEST_NA("Only runs on hardware...");
#else
if (cyg_test_is_simulator)
CYG_TEST_NA("Only runs on hardware...");
#endif
 
#else // __ECOS__
FILE *Ap;
 
/* Initializations */
 
if ((Ap = fopen("dhry.res","a+")) == NULL)
{
printf("Can not open dhry.res\n\n");
exit(1);
}
#endif // __ECOS__
 
Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
 
Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
Ptr_Glob->Discr = Ident_1;
Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
Ptr_Glob->variant.var_1.Int_Comp = 40;
strcpy (Ptr_Glob->variant.var_1.Str_Comp,
"DHRYSTONE PROGRAM, SOME STRING");
strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
 
Arr_2_Glob [8][7] = 10;
/* Was missing in published program. Without this statement, */
/* Arr_2_Glob [8][7] would have an undefined value. */
/* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
/* overflow may occur for this array element. */
 
printf ("\n");
printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
printf ("\n");
/*
if (Reg)
{
printf ("Program compiled with 'register' attribute\n");
printf ("\n");
}
else
{
printf ("Program compiled without 'register' attribute\n");
printf ("\n");
}
*/
#ifdef __ECOS__
Number_Of_Runs = PASSES;
#else // __ECOS__
printf ("Please give the number of runs through the benchmark: ");
{
int n;
scanf ("%d", &n);
Number_Of_Runs = n;
}
printf ("\n");
#endif // __ECOS__
 
printf ("Execution starts, %d runs through Dhrystone\n",Number_Of_Runs);
 
/***************/
/* Start timer */
/***************/
Begin_Time = dtime();
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
{
 
Proc_5();
Proc_4();
/* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
Int_1_Loc = 2;
Int_2_Loc = 3;
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
Enum_Loc = Ident_2;
Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
/* Bool_Glob == 1 */
while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
{
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
/* Int_3_Loc == 7 */
Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
/* Int_3_Loc == 7 */
Int_1_Loc += 1;
} /* while */
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
/* Int_Glob == 5 */
Proc_1 (Ptr_Glob);
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
/* loop body executed twice */
{
if (Enum_Loc == Func_1 (Ch_Index, 'C'))
/* then, not executed */
{
Proc_6 (Ident_1, &Enum_Loc);
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
Int_2_Loc = Run_Index;
Int_Glob = Run_Index;
}
}
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Int_2_Loc = Int_2_Loc * Int_1_Loc;
Int_1_Loc = Int_2_Loc / Int_3_Loc;
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
/* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
Proc_2 (&Int_1_Loc);
/* Int_1_Loc == 5 */
 
} /* loop "for Run_Index" */
 
/**************/
/* Stop timer */
/**************/
 
End_Time = dtime();
 
printf ("Execution ends\n");
printf ("\n");
printf ("Final values of the variables used in the benchmark:\n");
printf ("\n");
printf ("Int_Glob: %d\n", Int_Glob);
printf (" should be: %d\n", 5);
printf ("Bool_Glob: %d\n", Bool_Glob);
printf (" should be: %d\n", 1);
printf ("Ch_1_Glob: %c\n", Ch_1_Glob);
printf (" should be: %c\n", 'A');
printf ("Ch_2_Glob: %c\n", Ch_2_Glob);
printf (" should be: %c\n", 'B');
printf ("Arr_1_Glob[8]: %d\n", Arr_1_Glob[8]);
printf (" should be: %d\n", 7);
printf ("Arr_2_Glob[8][7]: %d\n", Arr_2_Glob[8][7]);
printf (" should be: Number_Of_Runs + 10\n");
printf ("Ptr_Glob->\n");
printf (" Ptr_Comp: %d\n", (int) Ptr_Glob->Ptr_Comp);
printf (" should be: (implementation-dependent)\n");
printf (" Discr: %d\n", Ptr_Glob->Discr);
printf (" should be: %d\n", 0);
printf (" Enum_Comp: %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
printf (" should be: %d\n", 2);
printf (" Int_Comp: %d\n", Ptr_Glob->variant.var_1.Int_Comp);
printf (" should be: %d\n", 17);
printf (" Str_Comp: %s\n", Ptr_Glob->variant.var_1.Str_Comp);
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf ("Next_Ptr_Glob->\n");
printf (" Ptr_Comp: %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
printf (" should be: (implementation-dependent), same as above\n");
printf (" Discr: %d\n", Next_Ptr_Glob->Discr);
printf (" should be: %d\n", 0);
printf (" Enum_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
printf (" should be: %d\n", 1);
printf (" Int_Comp: %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
printf (" should be: %d\n", 18);
printf (" Str_Comp: %s\n", Next_Ptr_Glob->variant.var_1.Str_Comp);
printf (" should be: DHRYSTONE PROGRAM, SOME STRING\n");
printf ("Int_1_Loc: %d\n", Int_1_Loc);
printf (" should be: %d\n", 5);
printf ("Int_2_Loc: %d\n", Int_2_Loc);
printf (" should be: %d\n", 13);
printf ("Int_3_Loc: %d\n", Int_3_Loc);
printf (" should be: %d\n", 7);
printf ("Enum_Loc: %d\n", Enum_Loc);
printf (" should be: %d\n", 1);
printf ("Str_1_Loc: %s\n", Str_1_Loc);
printf (" should be: DHRYSTONE PROGRAM, 1'ST STRING\n");
printf ("Str_2_Loc: %s\n", Str_2_Loc);
printf (" should be: DHRYSTONE PROGRAM, 2'ND STRING\n");
printf ("\n");
 
User_Time = End_Time - Begin_Time;
 
if (User_Time < Too_Small_Time)
{
printf ("Measured time too small to obtain meaningful results\n");
printf ("Please increase number of runs\n");
printf ("\n");
}
else
{
Microseconds = User_Time * Mic_secs_Per_Second
/ (double) Number_Of_Runs;
Dhrystones_Per_Second = (double) Number_Of_Runs / User_Time;
Vax_Mips = Dhrystones_Per_Second / 1757.0;
 
#ifdef ROPT
printf ("Register option selected? YES\n");
#else
printf ("Register option selected? NO\n");
#ifndef __ECOS__
strcpy(Reg_Define, "Register option not selected.");
#endif // __ECOS__
#endif
printf ("Microseconds for one run through Dhrystone: ");
#ifdef __ECOS__
printf ("%7.1f \n", Microseconds);
printf ("Dhrystones per Second: ");
printf ("%10.1f \n", Dhrystones_Per_Second);
printf ("VAX MIPS rating = %10.3f \n",Vax_Mips);
printf ("\n");
#else // __ECOS__
printf ("%7.1lf \n", Microseconds);
printf ("Dhrystones per Second: ");
printf ("%10.1lf \n", Dhrystones_Per_Second);
printf ("VAX MIPS rating = %10.3lf \n",Vax_Mips);
printf ("\n");
 
fprintf(Ap,"\n");
fprintf(Ap,"Dhrystone Benchmark, Version 2.1 (Language: C)\n");
fprintf(Ap,"%s\n",Reg_Define);
fprintf(Ap,"Microseconds for one loop: %7.1lf\n",Microseconds);
fprintf(Ap,"Dhrystones per second: %10.1lf\n",Dhrystones_Per_Second);
fprintf(Ap,"VAX MIPS rating: %10.3lf\n",Vax_Mips);
fclose(Ap);
#endif // __ECOS__
}
#ifdef __ECOS__
CYG_TEST_PASS_FINISH("Dhrystone test");
#endif // __ECOS__
}
 
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_1 (Ptr_Val_Par)
/******************/
 
REG Rec_Pointer Ptr_Val_Par;
/* executed once */
{
REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
/* == Ptr_Glob_Next */
/* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
/* corresponds to "rename" in Ada, "with" in Pascal */
structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
Ptr_Val_Par->variant.var_1.Int_Comp = 5;
Next_Record->variant.var_1.Int_Comp
= Ptr_Val_Par->variant.var_1.Int_Comp;
Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
Proc_3 (&Next_Record->Ptr_Comp);
/* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
== Ptr_Glob->Ptr_Comp */
if (Next_Record->Discr == Ident_1)
/* then, executed */
{
Next_Record->variant.var_1.Int_Comp = 6;
Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
&Next_Record->variant.var_1.Enum_Comp);
Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
&Next_Record->variant.var_1.Int_Comp);
}
else /* not executed */
structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
} /* Proc_1 */
 
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_2 (Int_Par_Ref)
/******************/
/* executed once */
/* *Int_Par_Ref == 1, becomes 4 */
 
One_Fifty *Int_Par_Ref;
{
One_Fifty Int_Loc;
#ifdef __ECOS__
Enumeration Enum_Loc = Ident_1;
#else // __ECOS__
Enumeration Enum_Loc;
#endif // __ECOS__
 
Int_Loc = *Int_Par_Ref + 10;
do /* executed once */
if (Ch_1_Glob == 'A')
/* then, executed */
{
Int_Loc -= 1;
*Int_Par_Ref = Int_Loc - Int_Glob;
Enum_Loc = Ident_1;
} /* if */
while (Enum_Loc != Ident_1); /* true */
} /* Proc_2 */
 
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_3 (Ptr_Ref_Par)
/******************/
/* executed once */
/* Ptr_Ref_Par becomes Ptr_Glob */
 
Rec_Pointer *Ptr_Ref_Par;
 
{
if (Ptr_Glob != Null)
/* then, executed */
*Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
} /* Proc_3 */
 
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_4 () /* without parameters */
/*******/
/* executed once */
{
Boolean Bool_Loc;
 
Bool_Loc = Ch_1_Glob == 'A';
Bool_Glob = Bool_Loc | Bool_Glob;
Ch_2_Glob = 'B';
} /* Proc_4 */
 
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_5 () /* without parameters */
/*******/
/* executed once */
{
Ch_1_Glob = 'A';
Bool_Glob = false;
} /* Proc_5 */
 
 
/* Procedure for the assignment of structures, */
/* if the C compiler doesn't support this feature */
#ifdef NOSTRUCTASSIGN
memcpy (d, s, l)
register char *d;
register char *s;
register int l;
{
while (l--) *d++ = *s++;
}
#endif
 
/*
*************************************************************************
*
* "DHRYSTONE" Benchmark Program
* -----------------------------
*
* Version: C, Version 2.1
*
* File: dhry_2.c (part 3 of 3)
*
* Date: May 25, 1988
*
* Author: Reinhold P. Weicker
*
*************************************************************************
*/
 
#ifndef __ECOS__
#include "dhry.h"
 
#ifndef REG
#define REG
/* REG becomes defined as empty */
/* i.e. no register variables */
#else
#define REG register
#endif
#endif // __ECOS__
 
extern int Int_Glob;
extern char Ch_1_Glob;
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_6 (Enum_Val_Par, Enum_Ref_Par)
/*********************************/
/* executed once */
/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
 
Enumeration Enum_Val_Par;
Enumeration *Enum_Ref_Par;
{
*Enum_Ref_Par = Enum_Val_Par;
if (! Func_3 (Enum_Val_Par))
/* then, not executed */
*Enum_Ref_Par = Ident_4;
switch (Enum_Val_Par)
{
case Ident_1:
*Enum_Ref_Par = Ident_1;
break;
case Ident_2:
if (Int_Glob > 100)
/* then */
*Enum_Ref_Par = Ident_1;
else *Enum_Ref_Par = Ident_4;
break;
case Ident_3: /* executed */
*Enum_Ref_Par = Ident_2;
break;
case Ident_4: break;
case Ident_5:
*Enum_Ref_Par = Ident_3;
break;
} /* switch */
} /* Proc_6 */
 
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_7 (Int_1_Par_Val, Int_2_Par_Val, Int_Par_Ref)
/**********************************************/
/* executed three times */
/* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
/* Int_Par_Ref becomes 7 */
/* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
/* Int_Par_Ref becomes 17 */
/* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
/* Int_Par_Ref becomes 18 */
One_Fifty Int_1_Par_Val;
One_Fifty Int_2_Par_Val;
One_Fifty *Int_Par_Ref;
{
One_Fifty Int_Loc;
 
Int_Loc = Int_1_Par_Val + 2;
*Int_Par_Ref = Int_2_Par_Val + Int_Loc;
} /* Proc_7 */
 
 
#ifdef __ECOS__
void
#endif // __ECOS__
Proc_8 (Arr_1_Par_Ref, Arr_2_Par_Ref, Int_1_Par_Val, Int_2_Par_Val)
/*********************************************************************/
/* executed once */
/* Int_Par_Val_1 == 3 */
/* Int_Par_Val_2 == 7 */
Arr_1_Dim Arr_1_Par_Ref;
Arr_2_Dim Arr_2_Par_Ref;
int Int_1_Par_Val;
int Int_2_Par_Val;
{
REG One_Fifty Int_Index;
REG One_Fifty Int_Loc;
 
Int_Loc = Int_1_Par_Val + 5;
Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
Int_Glob = 5;
} /* Proc_8 */
 
 
Enumeration Func_1 (Ch_1_Par_Val, Ch_2_Par_Val)
/*************************************************/
/* executed three times */
/* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
/* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
/* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
 
Capital_Letter Ch_1_Par_Val;
Capital_Letter Ch_2_Par_Val;
{
Capital_Letter Ch_1_Loc;
Capital_Letter Ch_2_Loc;
 
Ch_1_Loc = Ch_1_Par_Val;
Ch_2_Loc = Ch_1_Loc;
if (Ch_2_Loc != Ch_2_Par_Val)
/* then, executed */
return (Ident_1);
else /* not executed */
{
Ch_1_Glob = Ch_1_Loc;
return (Ident_2);
}
} /* Func_1 */
 
 
Boolean Func_2 (Str_1_Par_Ref, Str_2_Par_Ref)
/*************************************************/
/* executed once */
/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
 
Str_30 Str_1_Par_Ref;
Str_30 Str_2_Par_Ref;
{
REG One_Thirty Int_Loc;
#ifdef __ECOS__
Capital_Letter Ch_Loc = 'A';
#else // __ECOS__
Capital_Letter Ch_Loc;
#endif // __ECOS__
 
Int_Loc = 2;
while (Int_Loc <= 2) /* loop body executed once */
if (Func_1 (Str_1_Par_Ref[Int_Loc],
Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
/* then, executed */
{
Ch_Loc = 'A';
Int_Loc += 1;
} /* if, while */
if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
/* then, not executed */
Int_Loc = 7;
if (Ch_Loc == 'R')
/* then, not executed */
return (true);
else /* executed */
{
if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
/* then, not executed */
{
Int_Loc += 7;
Int_Glob = Int_Loc;
return (true);
}
else /* executed */
return (false);
} /* if Ch_Loc */
} /* Func_2 */
 
 
Boolean Func_3 (Enum_Par_Val)
/***************************/
/* executed once */
/* Enum_Par_Val == Ident_3 */
Enumeration Enum_Par_Val;
{
Enumeration Enum_Loc;
 
Enum_Loc = Enum_Par_Val;
if (Enum_Loc == Ident_3)
/* then, executed */
return (true);
else /* not executed */
return (false);
} /* Func_3 */
 
#else /* ifndef NA_MSG */
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA(NA_MSG);
}
#endif
/testaux.hxx
0,0 → 1,110
#ifndef CYGONCE_KERNEL_TESTS_TESTAUX_HXX
#define CYGONCE_KERNEL_TESTS_TESTAUX_HXX
 
//==========================================================================
//
// testaux.hxx
//
// Auxiliary test header file
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-09
// Description:
// Defines some convenience functions to get us going. In
// particular this file reserves space for NTHREADS threads,
// which can be created by calls to aux_new_thread()
// It also defines a CHECK function.
//
//####DESCRIPTIONEND####
 
 
static inline void *operator new(size_t size, void *ptr) { return ptr; };
 
 
#include <pkgconf/hal.h>
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
#ifdef NTHREADS
 
#ifndef STACKSIZE
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
#endif
 
static Cyg_Thread *thread[NTHREADS];
 
typedef CYG_WORD64 CYG_ALIGNMENT_TYPE;
 
static CYG_ALIGNMENT_TYPE thread_obj[NTHREADS] [
(sizeof(Cyg_Thread)+sizeof(CYG_ALIGNMENT_TYPE)-1)
/ sizeof(CYG_ALIGNMENT_TYPE) ];
 
static CYG_ALIGNMENT_TYPE stack[NTHREADS] [
(STACKSIZE+sizeof(CYG_ALIGNMENT_TYPE)-1)
/ sizeof(CYG_ALIGNMENT_TYPE) ];
 
static volatile int nthreads = 0;
 
static Cyg_Thread *new_thread(cyg_thread_entry *entry, CYG_ADDRWORD data)
{
int _nthreads = nthreads++;
 
CYG_ASSERT(_nthreads < NTHREADS,
"Attempt to create more than NTHREADS threads");
 
thread[_nthreads] = new( (void *)&thread_obj[_nthreads] )
Cyg_Thread(CYG_SCHED_DEFAULT_INFO,
entry, data,
NULL, // no name
(CYG_ADDRESS)stack[_nthreads], STACKSIZE );
 
thread[_nthreads]->resume();
 
return thread[_nthreads];
}
#endif // defined(NTHREADS)
 
#define CHECK(b) CYG_TEST_CHECK(b,#b)
 
#endif // ifndef CYGONCE_KERNEL_TESTS_TESTAUX_HXX
 
// End of testaux.hxx
/ksched1.c
0,0 → 1,103
/*=================================================================
//
// ksched1.c
//
// Kernel C API Sched test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-23
// Description: Simply checks the world starts
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
#define NTHREADS 2
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
 
static void entry0( cyg_addrword_t data )
{
CHECK( 222 == (int)data );
CYG_TEST_PASS_FINISH( "Kernel C API Sched 1 OK");
}
 
void ksched1_main(void)
{
CYG_TEST_INIT();
 
cyg_thread_create( 4, entry0 , (cyg_addrword_t)222, "ksched1",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_scheduler_start();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
ksched1_main();
}
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF ksched1.c */
/thread_gdb.c
0,0 → 1,413
//==========================================================================
//
// thread_gdb.c
//
// A test for thread support in GDB
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 1998-09-21
// Description: GDB thread support test.
//####DESCRIPTIONEND####
//
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/cyg_ass.h>
 
#include <cyg/infra/testcase.h>
 
#if defined(CYGFUN_KERNEL_API_C) && defined(CYGSEM_KERNEL_SCHED_MLQUEUE) &&\
(CYGNUM_KERNEL_SCHED_PRIORITIES > 26)
 
#include <cyg/hal/hal_arch.h> // for CYGNUM_HAL_STACK_SIZE_TYPICAL
 
// -------------------------------------------------------------------------
 
#define THREADS 10
 
#ifdef CYGNUM_HAL_STACK_SIZE_TYPICAL
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
#else
#define STACKSIZE (2*1024)
#endif
 
#define CONTROLLER_PRI_HI 0
#define CONTROLLER_PRI_LO 25
 
#define WORKER_PRI 3
#define WORKER_PRI_RANGE 20
 
 
// -------------------------------------------------------------------------
 
// array of stacks for threads
char thread_stack[THREADS][STACKSIZE];
 
// array of threads.
cyg_thread thread[THREADS];
 
cyg_handle_t thread_handle[THREADS];
 
volatile cyg_uint8 worker_state;
 
#define WORKER_STATE_WAIT 1
#define WORKER_STATE_BREAK 2
#define WORKER_STATE_EXIT 9
 
cyg_mutex_t worker_mutex;
cyg_cond_t worker_cv;
 
cyg_count32 workers_asleep = 0;
 
cyg_count32 thread_count[THREADS];
 
cyg_priority_t thread_pri[THREADS];
 
 
 
// -------------------------------------------------------------------------
 
extern void breakme(void)
{
}
 
// -------------------------------------------------------------------------
 
void worker( cyg_addrword_t id )
{
for(;;)
{
thread_count[id]++;
thread_pri[id] = cyg_thread_get_priority( cyg_thread_self() );
switch( worker_state )
{
case WORKER_STATE_BREAK:
if( 0 == (id % 4) )
breakme();
case WORKER_STATE_WAIT:
cyg_mutex_lock( &worker_mutex );
workers_asleep++;
cyg_cond_wait( &worker_cv );
workers_asleep--;
cyg_mutex_unlock( &worker_mutex );
break;
 
case WORKER_STATE_EXIT:
cyg_thread_exit();
}
}
}
 
// -------------------------------------------------------------------------
 
void controller( cyg_addrword_t id )
{
cyg_priority_t pri;
int i;
 
cyg_mutex_init( &worker_mutex );
cyg_cond_init( &worker_cv, &worker_mutex );
// 1 thread, it is running, it calls BREAKME();
// +++ Thread status returned:
// +++ 1 thread, running, is the current one
breakme();
 
// Create N more threads; they are all suspended after creation. Adjust
// the priorities of all the threads to lower than the controlling thread.
// Make them all be distinct priorities as far as possible. BREAKME();
// +++ 1 thread, running, + N suspended ones of different prios.
 
for( i = 1; i < THREADS; i++ )
{
pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
 
cyg_thread_create(pri, worker, (cyg_addrword_t)i, "worker",
(void *)(&thread_stack[i]), STACKSIZE,
&thread_handle[i], &thread[i]);
 
}
 
breakme();
 
// Adjust the priorities of all the threads to lower than the controlling
// thread. Make them all be THE SAME priority. BREAKME();
// +++ 1 thread, running, + N suspended ones of same prio.
 
for( i = 1; i < THREADS; i++ )
{
cyg_thread_set_priority( thread_handle[i], WORKER_PRI );
}
 
breakme();
// Release all the N threads, BREAKME();
// +++ 1 thread, running, + N ready ones of same prio.
 
for( i = 1; i < THREADS; i++ )
{
cyg_thread_resume( thread_handle[i] );
}
 
breakme();
 
// Adjust the priorities of all the threads, lower than the controlling
// thread. Make them all be distinct priorities as far as possible.
// BREAKME();
// +++ 1 thread, running, + N ready ones of different prios.
 
for( i = 1; i < THREADS; i++ )
{
pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
cyg_thread_set_priority( thread_handle[i], pri );
}
 
breakme();
// Command all the N threads to sleep; switch my own priority to lower
// than theirs so that they all run and sleep, then I get back in and
// BREAKME();
// +++ 1 thread, running, + N sleeping ones of different prios.
 
worker_state = WORKER_STATE_WAIT;
 
cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_LO );
 
breakme();
// Make them all be THE SAME priority; BREAKME();
// +++ 1 thread, running, + N sleeping ones of same prio.
 
for( i = 1; i < THREADS; i++ )
{
cyg_thread_set_priority( thread_handle[i], WORKER_PRI );
}
 
breakme();
 
// Wake them all up, they'll loop once and sleep again; I get in and
// BREAKME();
// +++ 1 thread, running, + N sleeping ones of same prio.
 
cyg_cond_broadcast( &worker_cv );
 
breakme();
 
// Adjust the priorities of all the threads, higher than the controlling
// thread. Make them all be distinct priorities as far as possible.
// BREAKME();
// +++ 1 thread, running, + N sleeping ones of different prios.
 
for( i = 1; i < THREADS; i++ )
{
pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
cyg_thread_set_priority( thread_handle[i], pri );
}
 
breakme();
 
// Wake them all up, they'll loop once and sleep again; I get in and
// BREAKME();
// +++ 1 thread, running, + N sleeping ones of different prios.
 
cyg_cond_broadcast( &worker_cv );
 
breakme();
 
// Set them all the same prio, set me to the same prio, BREAKME();
// +++ 1 running, + N sleeping, *all* the same prio.
 
for( i = 0; i < THREADS; i++ )
{
cyg_thread_set_priority( thread_handle[i], WORKER_PRI );
}
 
breakme();
 
// Wake them all up, they'll loop once and sleep again; I get in and
// BREAKME(); repeatedly until they have all slept again.
// +++ 1 running, + some sleeping, some ready, *all* the same prio.
 
cyg_cond_broadcast( &worker_cv );
 
// cyg_thread_yield();
do
{
breakme();
} while( workers_asleep != THREADS-1 );
 
breakme();
// Suspend some of the threads, BREAKME();
// +++ 1 running, + some sleeping, some suspended, *all* the same prio.
 
for( i = 1; i < THREADS; i++ )
{
// suspend every 3rd thread
if( 0 == (i % 3) ) cyg_thread_suspend( thread_handle[i] );
}
 
breakme();
 
 
// Change the prios all different, change my prio to highest , BREAKME();
// +++ 1 running, + some sleeping, some suspended, different prios.
 
cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_HI );
for( i = 1; i < THREADS; i++ )
{
pri = CONTROLLER_PRI_HI + 1 + i % WORKER_PRI_RANGE;
cyg_thread_set_priority( thread_handle[i], pri );
}
 
breakme();
// Wake up all the threads, BREAKME();
// +++ 1 running, + some ready, some suspended/ready, different prios.
 
cyg_cond_broadcast( &worker_cv );
 
breakme();
 
 
// Change my prio to lowest, let all the threads run, BREAKME().
// +++ 1 running + some sleeping, some suspended/ready, different prios.
 
cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_LO );
breakme();
// Resume all the threads, BREAKME();
// +++ 1 running, + N ready, different prios.
 
for( i = 1; i < THREADS; i++ )
{
cyg_thread_resume( thread_handle[i] );
}
breakme();
// Command some of the N threads to call BREAKME(); themselves (then sleep
// again). Change my prio to low, so that they all get to run and hit the
// breakpoint.
// +++ A different one running every time, others in a mixture of
// ready and sleeping states.
worker_state = WORKER_STATE_BREAK;
 
cyg_cond_broadcast( &worker_cv );
cyg_thread_set_priority( thread_handle[0], CONTROLLER_PRI_LO );
breakme();
// Command all the threads to exit; switch my own priority to lower
// than theirs so that they all run and exit, then I get back in and
// BREAKME();
// +++ 1 thread, running, + N dormant ones.
 
worker_state = WORKER_STATE_EXIT;
 
cyg_cond_broadcast( &worker_cv );
breakme();
 
#if 0
 
// Cannot do this yet...
// Destroy some of the N threads to invalidate their IDs. Re-create them
// with new IDs, so that we get IDs 1,2,4,6,8,11,12,13,14,15 in use instead
// of 1,2,3,4,5,6,7,8,9, if you see what I mean. Do all the above again.
// Loop forever, or whatever...
 
#endif
 
breakme();
CYG_TEST_PASS_FINISH("GDB Thread test OK");
}
 
// -------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
 
CYG_TEST_INIT();
cyg_thread_create(CONTROLLER_PRI_HI, controller, (cyg_addrword_t)0, "controller",
(void *)(&thread_stack[0]), STACKSIZE,
&thread_handle[0], &thread[0]);
// resume it
cyg_thread_resume(thread_handle[0]);
 
// Get the world going
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
#else /* def CYGFUN_KERNEL_API_C */
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_PASS_FINISH("Incorrect configuration for this test");
}
#endif /* def CYGFUN_KERNEL_API_C && ... */
 
// -------------------------------------------------------------------------
// EOF thread_gdb.c
/kclock0.c
0,0 → 1,274
/*=================================================================
//
// kclock0.c
//
// Kernel C API Clock test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-20
// Description: Tests some basic clock functions.
//####DESCRIPTIONEND####
*/
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
cyg_alarm_t call_me;
 
cyg_counter counter0o, counter1o;
cyg_handle_t counter0, counter1;
 
cyg_alarm alarmo[3];
cyg_handle_t alarm0, alarm1, alarm2;
 
cyg_resolution_t res, res0, res1;
 
cyg_clock clock0o;
cyg_handle_t clock0;
 
const cyg_uint32 big_number = 3333222111u;
 
cyg_bool_t flash( void )
{
cyg_counter_create( &counter0, &counter0o );
cyg_counter_create( &counter1, &counter1o );
cyg_alarm_create( counter0,
call_me,
(cyg_addrword_t)12,
&alarm0,
&alarmo[0]);
 
res.dividend = 1;
res.divisor = 2;
 
cyg_clock_create( res, &clock0, &clock0o );
cyg_clock_delete( clock0 );
 
cyg_alarm_delete( alarm0 );
 
cyg_counter_delete( counter0 );
cyg_counter_delete( counter1 );
 
return true;
}
 
/* Testing alarms
//
// call_me is a function that will be called when an alarm is
// triggered. It updates a global variable called which is CHECKed
// explicitly to see if the approriate alarms have been called.
*/
 
cyg_uint16 called = 0x0;
 
void call_me(cyg_handle_t alarm, cyg_addrword_t data)
{
called ^= (int)data;
}
 
void call_me2(cyg_handle_t alarm, cyg_addrword_t data)
{
call_me(alarm, (cyg_addrword_t)((int)data^0x10));
}
 
 
void kclock0_main(void)
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
 
cyg_counter_create( &counter0, &counter0o);
 
CHECK( 0 == cyg_counter_current_value( counter0 ) );
 
cyg_counter_tick(counter0);
 
CHECK( 1 == cyg_counter_current_value(counter0) );
 
cyg_counter_tick(counter0);
 
CHECK( 2 == cyg_counter_current_value(counter0) );
 
cyg_counter_set_value( counter0, 0xffffffff );
 
CHECK( 0xffffffff == cyg_counter_current_value(counter0) );
 
cyg_counter_tick(counter0); // Overflows 32 bits
CHECK( 0x100000000ULL == cyg_counter_current_value(counter0) );
 
cyg_counter_set_value(counter0, 11);
CHECK( 11 == cyg_counter_current_value(counter0) );
/* the call_me functions cause the "called" bits to toggle
// checking the value of called checks the parity of # of calls
// made by each alarm.
*/
 
cyg_alarm_create(counter0,
call_me, (cyg_addrword_t)0x1, &alarm0, &alarmo[0]);
cyg_alarm_create(counter0,
call_me, (cyg_addrword_t)0x2, &alarm1, &alarmo[1]);
cyg_alarm_create(counter0,
call_me2, (cyg_addrword_t)0x4, &alarm2, &alarmo[2]);
CHECK( 0x00 == called );
cyg_alarm_initialize(alarm0, 12,3);
cyg_alarm_initialize(alarm2, 21,2);
CHECK( 0x00 == called );
 
cyg_counter_tick(counter0); /* 12 a0 */
CHECK( 0x01 == called );
 
cyg_alarm_initialize(alarm1, 13,0);
cyg_counter_tick(counter0); /* 13 a1 */
CHECK( 0x03 == called );
 
cyg_alarm_initialize(alarm1, 17,0);
cyg_counter_tick(counter0); /* 14 */
CHECK( 0x03 == called );
 
cyg_counter_tick(counter0); /* 15 a0 */
CHECK( 0x02 == called );
 
cyg_counter_tick(counter0); /* 16 */
cyg_counter_tick(counter0); /* 17 a1 */
CHECK( 0x00 == called );
 
cyg_counter_tick(counter0); /* 18 a0 */
CHECK( 0x01 == called );
 
cyg_counter_tick(counter0); /* 19 */
cyg_counter_tick(counter0); /* 20 */
cyg_counter_tick(counter0); /* 21 a0 a2 */
CHECK( 0x14 == called );
 
cyg_counter_tick(counter0); /* 22 */
cyg_counter_tick(counter0); /* 23 a2 */
CHECK( 0x00 == called );
cyg_alarm_disable(alarm2);
 
cyg_counter_tick(counter0); /* 24 a0 */
cyg_counter_tick(counter0); /* 25 */
CHECK( 0x01 == called );
cyg_alarm_enable(alarm2); /* a2 (enabled at 25) */
CHECK( 0x15 == called );
 
cyg_counter_tick(counter0); /* 26 */
CHECK( 0x15 == called );
cyg_counter_tick(counter0); /* 27 a0 a2 */
cyg_counter_tick(counter0); /* 28 */
CHECK( 0x00 == called );
cyg_counter_tick(counter0); /* 29 a2 */
cyg_counter_tick(counter0); /* 30 a0 */
cyg_counter_tick(counter0); /* 31 a2 */
CHECK( 0x01 == called );
 
res0.dividend = 100;
res0.divisor = 3;
 
cyg_clock_create( res0, &clock0, &clock0o );
 
res1 = cyg_clock_get_resolution(clock0);
CHECK( res0.dividend == res1.dividend );
CHECK( res0.divisor == res1.divisor );
 
res1.dividend = 12;
res1.divisor = 25;
 
cyg_clock_set_resolution(clock0, res1);
res0 = cyg_clock_get_resolution(clock0);
CHECK( res0.dividend == res1.dividend );
CHECK( res0.divisor == res1.divisor );
 
cyg_clock_to_counter(clock0, &counter1);
 
CHECK( 0 == cyg_counter_current_value( counter1 ) );
CHECK( 0 == cyg_current_time() );
 
cyg_counter_tick(counter1);
 
CHECK( 1 == cyg_counter_current_value(counter1) );
 
res0 = cyg_clock_get_resolution(cyg_real_time_clock());
 
/* Current time should be 0 as interrupts will still be disabled */
CHECK( 0 == cyg_current_time() );
 
CYG_TEST_PASS_FINISH("Kernel C API Clock 0 OK");
}
 
externC void
cyg_start( void )
{
kclock0_main();
}
 
#else // def CYGFUN_KERNEL_API_C
#define N_A_MSG "Kernel C API layer disabled"
#endif // def CYGFUN_KERNEL_API_C
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
#define N_A_MSG "Kernel real-time clock disabled"
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
#ifdef N_A_MSG
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( N_A_MSG );
}
#endif // N_A_MSG
 
// EOF kclock0.c
/kclock1.c
0,0 → 1,153
/*=================================================================
//
// kclock1.c
//
// Kernel C API Clock test 1 - Real Time Clock
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-20
// Description: Tests the Kernel Real Time Clock
// This test creates a thread, starts the scheduler and
// delays for a time of about 5 seconds. This test should
// be expected to run for about this length of time.
// Omissions:
// Doesn't test alarms attached to RTC.
// Assumptions:
// CYGVAR_KERNEL_COUNTERS_CLOCK must be set.
// Resolution of clock small compared with 5s.
// Overhead small compared with 5s.
// Options:
// CYGIMP_KERNEL_COUNTERS_SINGLE_LIST
// CYGIMP_KERNEL_COUNTERS_MULTI_LIST
// CYGVAR_KERNEL_COUNTERS_CLOCK
// CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
 
static cyg_uint64 TEST_DELAY;
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
#define NTHREADS 1
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
static void entry0( cyg_addrword_t data )
{
cyg_resolution_t res;
cyg_uint32 ticks;
cyg_tick_count_t count0, count1;
cyg_handle_t rtclock, rtcounter;
 
rtclock = cyg_real_time_clock();
cyg_clock_to_counter(rtclock, &rtcounter);
 
res = cyg_clock_get_resolution (rtclock);
 
/* RTC takes res.dividend/res.divisor ns/tick */
ticks = ((cyg_uint64)TEST_DELAY * res.divisor) / res.dividend;
 
count0 = cyg_counter_current_value(rtcounter);
cyg_thread_delay(ticks);
count1 = cyg_counter_current_value(rtcounter);
 
CYG_TEST_CHECK(count0+ticks <= count1,
"real time clock's counter not counting");
 
CYG_TEST_CHECK(count1 <= cyg_current_time(),"cyg_current_time()");
 
CYG_TEST_PASS_FINISH("Kernel C API Clock 1 OK");
}
 
void kclock1_main( void )
{
CYG_TEST_INIT();
 
if (cyg_test_is_simulator) {
TEST_DELAY = 100000000ll;
} else {
TEST_DELAY = 3000000000ll;
}
 
cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kclock1",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_scheduler_start();
}
 
externC void
cyg_start( void )
{
kclock1_main();
}
 
#else // def CYGFUN_KERNEL_API_C
#define N_A_MSG "Kernel C API layer disabled"
#endif // def CYGFUN_KERNEL_API_C
#else // def CYGFUN_KERNEL_THREADS_TIMER
#define N_A_MSG "Kernel threads timer disabled"
#endif // def CYGFUN_KERNEL_THREADS_TIMER
 
#ifdef N_A_MSG
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( N_A_MSG );
}
#endif // N_A_MSG
 
// EOF kclock1.c
/sched1.cxx
0,0 → 1,111
//==========================================================================
//
// sched1.cxx
//
// Sched test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-26
// Description: Tests some basic sched functions.
// Omissions:
// Doesn't test Cyg_Scheduler::get_thread_switches() very well
// Cyg_SchedThread
// inherit_priority
// disinherit_priority
// Options:
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
#include <cyg/kernel/thread.hxx> // Cyg_Thread
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/thread.inl>
 
#define NTHREADS 2
 
#include "testaux.hxx"
 
static void entry0( CYG_ADDRWORD data )
{
CHECK( 0 == Cyg_Scheduler::get_sched_lock() );
Cyg_Scheduler::lock(); {
CHECK( 1 == Cyg_Scheduler::get_sched_lock() );
Cyg_Scheduler::lock(); {
CHECK( 2 == Cyg_Scheduler::get_sched_lock() );
} Cyg_Scheduler::unlock();
} Cyg_Scheduler::unlock();
cyg_ucount32 t0=Cyg_Scheduler::get_thread_switches();
cyg_ucount32 t1=Cyg_Scheduler::get_thread_switches();
CHECK( t1 >= t0 );
CHECK( Cyg_Scheduler::get_current_thread() ==
Cyg_Thread::self() );
CYG_TEST_PASS_FINISH( "Sched 1 OK");
}
 
static void entry1( CYG_ADDRWORD data )
{
Cyg_Thread::self()->sleep();
}
 
void sched1_main(void)
{
CYG_TEST_INIT();
 
new_thread(entry0, 222);
new_thread(entry1, 333);
 
Cyg_Scheduler::start();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
sched1_main();
}
// EOF sched1.cxx
/except1.cxx
0,0 → 1,271
//=================================================================
//
// except1.cxx
//
// Exception test 1
//
//=================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm, jlarmour
// Date: 1999-02-16
// Description: Test basic exception functionality
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGPKG_KERNEL_EXCEPTIONS
 
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
#include <cyg/kernel/thread.hxx> // Cyg_Thread
#include <cyg/kernel/intr.hxx> // cyg_VSR
 
#include <cyg/hal/hal_intr.h> // exception ranges
 
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/thread.inl>
 
#define NTHREADS 1
#include "testaux.hxx"
 
#ifndef CYGPKG_HAL_ARM_PID
#define EXCEPTION_DATA_ACCESS
#endif
 
static int d0;
#ifdef EXCEPTION_DATA_ACCESS
static cyg_exception_handler handler0;
 
static void handler0(CYG_ADDRWORD data, cyg_code number, CYG_ADDRWORD info)
{
CYG_TEST_INFO("handler 0 called");
CYG_TEST_CHECK((CYG_ADDRWORD)123 == data, "handler given wrong data");
// ignore machine specific stuff
CYG_UNUSED_PARAM(cyg_code, number);
CYG_UNUSED_PARAM(CYG_ADDRWORD, info);
 
CYG_TEST_PASS_FINISH("Except 1 OK");
}
#endif
 
static void handler1(CYG_ADDRWORD data, cyg_code number, CYG_ADDRWORD info)
{
CYG_TEST_INFO("handler 1 called");
 
CYG_TEST_CHECK((CYG_ADDRWORD)&d0 == data, "handler given wrong data");
 
#ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
CYG_TEST_CHECK(number == CYGNUM_HAL_EXCEPTION_MAX, "handler given wrong number");
#else
CYG_UNUSED_PARAM(cyg_code, number);
#endif
 
CYG_TEST_CHECK((CYG_ADDRWORD)99 == info, "handler given wrong info");
}
 
#ifdef EXCEPTION_DATA_ACCESS
// The following function attempts to cause an exception in various
// hacky ways. It is machine dependent what exception is generated.
// It does reads rather than writes hoping not to corrupt anything
// important.
static int
cause_fpe(int num)
{
double a;
 
a = 1.0/num; // Depending on FPU emulation and/or
// the FPU architecture, this may
// cause an exception.
// (float division by zero)
 
return ((int)a)/num; // This may cause an exception if
// the architecture supports it.
// (integer division by zero).
} // cause_fpe()
 
void cause_exception(void)
{
int x;
unsigned int p=0;
 
// First try for an address exception (unaligned access exception
// or SEGV/BUS exceptions)
do {
x=*(volatile int *)(p-1);
p+=0x100000;
} while(p != 0);
 
// Next try an integer or floating point divide-by-zero exception.
cause_fpe(0);
}
#endif
 
static void entry0( CYG_ADDRWORD data )
{
#ifdef EXCEPTION_DATA_ACCESS
cyg_code n;
#endif
cyg_exception_handler *old_handler, *old_handler1;
CYG_ADDRWORD old_data, old_data1;
Cyg_Thread *p=Cyg_Thread::self();
 
CYG_UNUSED_PARAM(CYG_ADDRESS, data);
 
p->register_exception(
CYGNUM_HAL_EXCEPTION_MAX,
&handler1,
(CYG_ADDRWORD)&d0,
&old_handler,
&old_data);
 
p->register_exception(
CYGNUM_HAL_EXCEPTION_MAX,
&handler1,
(CYG_ADDRWORD)&d0,
&old_handler1,
&old_data1);
CYG_TEST_CHECK(old_handler1 == &handler1,
"register exception: old_handler not the one previously registered");
CYG_TEST_CHECK(old_data1 == (CYG_ADDRWORD)&d0,
"register exception: old_data not those previously registered");
 
p->deliver_exception(CYGNUM_HAL_EXCEPTION_MAX, (CYG_ADDRWORD)99);
 
CYG_TEST_INFO("handler 1 returned");
 
p->deregister_exception(CYGNUM_HAL_EXCEPTION_MAX);
p->deregister_exception(CYGNUM_HAL_EXCEPTION_MAX);
 
#ifdef EXCEPTION_DATA_ACCESS
 
#if 0
#elif defined(CYGPKG_HAL_POWERPC_SIM)
// The exception generated by the SIM is not recognized by GDB.
// PR 19945 workaround.
CYG_TEST_NA("Not applicable to PowerPC SIM");
#endif
 
for(n = CYGNUM_HAL_EXCEPTION_MIN; n <= CYGNUM_HAL_EXCEPTION_MAX; n++) {
p->register_exception(
n,
handler0,
(CYG_ADDRWORD)123,
&old_handler1,
&old_data1);
}
 
CYG_TEST_PASS("Attempting to provoke exception");
 
cause_exception();
 
CYG_TEST_FAIL_FINISH("Couldn't cause exception");
#else // EXCEPTION_DATA_ACCESS
CYG_TEST_NA("Platform does not support data exceptions");
#endif
 
}
 
#ifdef CYG_HAL_MIPS_TX39_JMR3904
 
externC cyg_VSR __default_exception_vsr;
cyg_VSR *old_vsr;
 
#endif
 
void except0_main( void )
{
// Use CYG_TEST_GDBCMD _before_ CYG_TEST_INIT()
CYG_TEST_GDBCMD("handle SIGBUS nostop");
CYG_TEST_GDBCMD("handle SIGSEGV nostop");
CYG_TEST_GDBCMD("handle SIGFPE nostop");
 
CYG_TEST_INIT();
 
#ifdef HAL_VSR_SET_TO_ECOS_HANDLER
// Reclaim the VSR off CygMon possibly
#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_ACCESS, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_FPU, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, NULL );
#endif
#endif
 
new_thread(entry0, 0);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
except0_main();
}
#else // def CYGPKG_KERNEL_EXCEPTIONS
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Exceptions disabled");
}
#endif // def CYGPKG_KERNEL_EXCEPTIONS
 
// EOF except1.cxx
/clock0.cxx
0,0 → 1,286
//==========================================================================
//
// clock0.cxx
//
// Clock test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-13
// Description: Tests some basic clock functions.
// Omissions: Doesn't test likely boundary conditions for
// CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE
// Real Time Clock Testing is limited
// Options:
// CYGIMP_KERNEL_COUNTERS_SINGLE_LIST
// CYGIMP_KERNEL_COUNTERS_MULTI_LIST
// CYGVAR_KERNEL_COUNTERS_CLOCK
// CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE
// Assumptions: This assumes we have long long support and
// that counters are 64 bits.
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/clock.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/clock.inl>
 
#include "testaux.hxx"
 
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
 
cyg_alarm_fn call_me;
 
bool flash( void )
{
Cyg_Counter counter0 = Cyg_Counter();
Cyg_Counter counter1 = Cyg_Counter(723);
CYG_ASSERTCLASSO( counter0, "error" );
CYG_ASSERTCLASSO( counter1, "error" );
 
Cyg_Alarm alarm0 = Cyg_Alarm(&counter0, call_me, 12);
 
CYG_ASSERTCLASSO( alarm0, "error" );
 
Cyg_Clock::cyg_resolution res = {1,2};
 
Cyg_Clock clock0(res);
 
CYG_ASSERTCLASSO( clock0, "error" );
 
return true;
}
 
// Testing alarms
//
// call_me is a function that will be called when an alarm is
// triggered. It updates a global variable called which is CHECKed
// explicitly to see if the approriate alarms have been called.
 
cyg_uint16 called = 0x0;
 
void call_me(Cyg_Alarm *alarm, CYG_ADDRWORD data)
{
called ^= data;
}
 
void call_me2(Cyg_Alarm *alarm, CYG_ADDRWORD data)
{
call_me(alarm, data^0x10);
}
 
 
void clock0_main(void)
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
 
const cyg_uint32 big_number = 3333222111u;
Cyg_Counter counter0 = Cyg_Counter();
 
CHECK( 0 == counter0.current_value() );
CHECK( 0 == counter0.current_value_lo() );
CHECK( 0 == counter0.current_value_hi() );
 
counter0.tick();
 
CHECK( 1 == counter0.current_value() );
CHECK( 1 == counter0.current_value_lo() );
CHECK( 0 == counter0.current_value_hi() );
 
counter0.tick(6);
 
CHECK( 7 == counter0.current_value() );
CHECK( 7 == counter0.current_value_lo() );
CHECK( 0 == counter0.current_value_hi() );
 
counter0.set_value( 0xfffffffc );
 
CHECK( 0xfffffffc == counter0.current_value() );
CHECK( 0xfffffffc == counter0.current_value_lo() );
CHECK( 0 == counter0.current_value_hi() );
 
counter0.tick( 0x13 ); // Overflows 32 bits
CHECK( 0x10000000fULL == counter0.current_value() );
CHECK( 0xf == counter0.current_value_lo() );
CHECK( 0x1 == counter0.current_value_hi() );
 
Cyg_Counter counter1 = Cyg_Counter(big_number);
 
CHECK( 0 == counter1.current_value() );
CHECK( 0 == counter1.current_value_lo() );
CHECK( 0 == counter1.current_value_hi() );
 
counter1.tick(2);
CHECK( 2ll*big_number == counter1.current_value() );
CHECK( ((2ll*big_number) & 0xffffffff) ==
counter1.current_value_lo() );
CHECK( ((2ll*big_number) >> 32) == counter1.current_value_hi() );
 
counter1.tick();
CHECK( 3ll*big_number == counter1.current_value() );
CHECK( ((3ll*big_number) & 0xffffffff) ==
counter1.current_value_lo() );
CHECK( ((3ll*big_number) >> 32) == counter1.current_value_hi() );
 
counter1.tick();
CHECK( 4ll*big_number == counter1.current_value() );
CHECK( ((4ll*big_number) & 0xffffffff) ==
counter1.current_value_lo() );
CHECK( ((4ll*big_number) >> 32) == counter1.current_value_hi() );
 
counter1.set_value(1222333444555ll);
CHECK( 1222333444555ll == counter1.current_value() );
 
counter0.set_value(11);
CHECK( 11 == counter0.current_value() );
// the call_me functions cause the "called" bits to toggle
// CHECKing the value of called TEST_CHECKs the parity of # of calls
// made by each alarm.
 
Cyg_Alarm alarm0 = Cyg_Alarm(&counter0, call_me, 0x1);
Cyg_Alarm alarm1 = Cyg_Alarm(&counter0, call_me, 0x2);
Cyg_Alarm alarm2 = Cyg_Alarm(&counter0, call_me2, 0x4);
CHECK( 0x00 == called );
alarm0.initialize(12,3);
alarm2.initialize(21,2);
CHECK( 0x00 == called );
 
counter0.tick(); // 12 a0
CHECK( 0x01 == called );
 
alarm1.initialize(13,0);
counter0.tick(); // 13 a1
CHECK( 0x03 == called );
 
alarm1.initialize(17,0);
counter0.tick(); // 14
CHECK( 0x03 == called );
 
counter0.tick(); // 15 a0
CHECK( 0x02 == called );
 
counter0.tick(2); // 17 a1
CHECK( 0x00 == called );
 
counter0.tick(); // 18 a0
CHECK( 0x01 == called );
 
counter0.tick(3); // 21 a0 a2
CHECK( 0x14 == called );
 
counter0.tick(2); // 23 a2
CHECK( 0x00 == called );
alarm2.disable();
 
counter0.tick(2); // 25 a0(24)
CHECK( 0x01 == called );
alarm2.enable(); // a2 (enabled at 25)
CHECK( 0x15 == called );
 
counter0.tick(); // 26
CHECK( 0x15 == called );
counter0.tick(2); // 28 a0(27) a2(27)
CHECK( 0x00 == called );
counter0.tick(3); // 31 a0(30) a2(29 31)
CHECK( 0x01 == called );
 
Cyg_Clock::cyg_resolution res0;
 
res0.dividend = 100;
res0.divisor = 3;
 
Cyg_Clock::cyg_resolution res1;
 
Cyg_Clock clock0 = Cyg_Clock(res0);
 
res1 = clock0.get_resolution();
CHECK( res0.dividend == res1.dividend );
CHECK( res0.divisor == res1.divisor );
 
res1.dividend = 12;
res1.divisor = 25;
 
clock0.set_resolution(res1);
res0 = clock0.get_resolution();
CHECK( res0.dividend == res1.dividend );
CHECK( res0.divisor == res1.divisor );
 
res0 = Cyg_Clock::real_time_clock->get_resolution();
 
CYG_TEST_PASS_FINISH("Clock 0 OK");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
clock0_main();
}
 
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( "Kernel real-time clock disabled");
}
 
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
// EOF clock0.cxx
/philo.cxx
0,0 → 1,241
//==========================================================================
//
// philo.cxx
//
// A test of the dining philosophers problem
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: A test of the dining philosophers problem
//####DESCRIPTIONEND####
//
 
#include <cyg/kernel/kernel.hxx>
 
#include <cyg/hal/hal_io.h>
 
// -------------------------------------------------------------------------
// Data for the philosophers problem
 
#define PHILOSOPHERS 15 // number of philosophers
#define STACKSIZE (2*1024) // size of thread stack
 
#define NTHREADS PHILOSOPHERS
#include "testaux.hxx"
 
// array of chopsticks
Cyg_Binary_Semaphore chopstick[PHILOSOPHERS];
 
 
//cyg_thread_entry Philosopher;
 
// -------------------------------------------------------------------------
// State recording and display
 
static char pstate[PHILOSOPHERS+1]; // state vector showing what each
// philosopher is doing
 
Cyg_Mutex state_mutex;
 
#ifdef CYG_HAL_MN10300_MN103002
static cyg_count8 eaters = 0;
#endif
 
void change_state(int id, char newstate)
{
CYG_INSTRUMENT_USER( 1, 0, 0);
state_mutex.lock();
CYG_INSTRUMENT_USER( 2, 0, 0);
 
#ifdef CYG_HAL_MN10300_MN103002
if( pstate[id] == 'E' ) eaters--;
if( newstate == 'E' ) eaters++;
// led(eaters);
#endif
pstate[id] = newstate;
 
diag_write_string(pstate);
#if 0
diag_write_char(' ');
diag_write_dec(Cyg_Scheduler::get_thread_switches());
#endif
diag_write_char('\n');
 
CYG_INSTRUMENT_USER( 3, 0, 0);
state_mutex.unlock();
CYG_INSTRUMENT_USER( 4, 0, 0);
}
 
char get_state( int id)
{
state_mutex.lock();
char s = pstate[id];
 
state_mutex.unlock();
 
return s;
}
 
// -------------------------------------------------------------------------
// Thread to behave like a philosopher
 
void Philosopher( CYG_ADDRESS id )
{
Cyg_Thread *self = Cyg_Thread::self();
Cyg_Binary_Semaphore *first_stick = &chopstick[id];
Cyg_Binary_Semaphore *second_stick = &chopstick[(id+1)%PHILOSOPHERS];
#ifdef CYGPKG_INFRA_DEBUG
int left_philo = ((id==0)?PHILOSOPHERS:id)-1;
int right_philo = (id==PHILOSOPHERS-1)?0:(id+1);
#endif
CYG_ASSERT( id >= 0 && id < PHILOSOPHERS, "Bad id");
 
// Deadlock avoidance. The easiest way to make the philosophers
// behave is to make each pick up the lowest numbered stick
// first. This is how it works out anyway for all the philosophers
// except the last, who must have his sticks swapped.
if( id == PHILOSOPHERS-1 )
{
Cyg_Binary_Semaphore *t = first_stick;
first_stick = second_stick;
second_stick = t;
}
// The following variable is shared by all philosophers.
// It is incremented unprotected, but this does not matter
// since it is only present to introduce a little variability
// into the think and eat times.
static int cycle = 0;
for(;;)
{
// Think for a bit
 
self->delay((id+cycle++)%12); // Cogito ergo sum...
 
// I am now hungry, try to get the chopsticks
 
change_state(id,'H');
// Get the first stick
CYG_INSTRUMENT_USER( 5, 0, 0);
first_stick->wait();
CYG_INSTRUMENT_USER( 6, 0, 0);
// Get the second stick
CYG_INSTRUMENT_USER( 7, 0, 0);
second_stick->wait();
CYG_INSTRUMENT_USER( 8, 0, 0);
// Got them, now eat
 
change_state(id,'E');
// Check that the world is as I think it is...
CYG_ASSERT( !first_stick->posted(), "Not got first stick");
CYG_ASSERT( !second_stick->posted(), "Not got second stick");
CYG_ASSERT( get_state(left_philo) != 'E', "Left neighbour also eating!!");
CYG_ASSERT( get_state(right_philo) != 'E', "Right neighbour also eating!!");
self->delay((id+cycle++)%6); // munch munch
 
// Finished eating, put down sticks.
 
change_state(id,'T');
 
CYG_INSTRUMENT_USER( 9, 0, 0);
first_stick->post();
CYG_INSTRUMENT_USER( 10, 0, 0);
second_stick->post();
CYG_INSTRUMENT_USER( 11, 0, 0);
 
// Cyg_Scheduler::lock();
// Cyg_Scheduler::unlock();
CYG_INSTRUMENT_USER( 12, 0, 0);
}
}
 
// -------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
diag_init();
 
diag_write_string("Philosophers\n");
diag_write_string("Started\n");
 
// Zero last element in state so it acts like
// a string.
pstate[PHILOSOPHERS] = 0;
 
#if 1
for( int i = 0; i < PHILOSOPHERS; i++ )
{
change_state(i,'T'); // starting state
 
// Start the philosopher
Cyg_Thread *t = new_thread( Philosopher, i );
 
// resume it
t->resume();
 
// and make the matching chopstick present
chopstick[i].post();
}
#endif
// Get the world going
Cyg_Scheduler::scheduler.start();
 
}
 
// -------------------------------------------------------------------------
// EOF philo.cxx
/clock1.cxx
0,0 → 1,132
//==========================================================================
//
// clock1.cxx
//
// Clock test 1 - Real Time Clock
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-16
// Description: Tests the Kernel Real Time Clock
// This test creates a thread, starts the scheduler and
// delays for a time of about 5 seconds. This test should
// be expected to run for about this length of time.
// Omissions:
// Doesn't test alarms attached to RTC.
// Assumptions:
// CYGVAR_KERNEL_COUNTERS_CLOCK must be set.
// Resolution of clock small compared with 5s.
// Overhead small compared with 5s.
// Options:
// CYGIMP_KERNEL_COUNTERS_SINGLE_LIST
// CYGIMP_KERNEL_COUNTERS_MULTI_LIST
// CYGVAR_KERNEL_COUNTERS_CLOCK
// CYGNUM_KERNEL_COUNTERS_MULTI_LIST_SIZE
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/clock.hxx>
#include <cyg/kernel/thread.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/clock.inl>
#include <cyg/kernel/thread.inl>
 
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
 
 
#define NTHREADS 1
#include "testaux.hxx"
 
static cyg_uint32 ticks; // Number of ticks thread[0] will delay for
 
static cyg_uint64 TEST_DELAY;
 
static void entry0( CYG_ADDRWORD data )
{
((Cyg_Thread *)data)->delay(ticks);
 
CYG_TEST_PASS_FINISH("Clock 1 OK");
}
 
void clock1_main( void )
{
CYG_TEST_INIT();
 
if (cyg_test_is_simulator) {
TEST_DELAY = 100000000ll;
} else {
TEST_DELAY = 3000000000ll;
}
 
new_thread(entry0, (CYG_ADDRWORD)&thread_obj[0]);
 
Cyg_Clock::cyg_resolution res;
 
res = Cyg_Clock::real_time_clock->get_resolution ();
 
// RTC takes res.dividend/res.divisor ns/tick
ticks = ((cyg_uint64)TEST_DELAY * res.divisor) / res.dividend;
 
Cyg_Scheduler::start();
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
clock1_main();
}
 
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( "Kernel real-time clock disabled");
}
 
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
// EOF clock1.cxx
/tm_basic.cxx
0,0 → 1,1868
//==========================================================================
//
// tm_basic.cxx
//
// Basic timing test / scaffolding
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2002 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
// Contributors: gthomas
// Date: 1998-10-19
// Description: Very simple kernel timing test
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
#include <pkgconf/hal.h>
 
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/sema.hxx>
#include <cyg/kernel/flag.hxx>
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/clock.hxx>
#include <cyg/kernel/clock.inl>
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
#include <cyg/infra/diag.h>
 
#include <cyg/kernel/test/stackmon.h>
#include CYGHWR_MEMORY_LAYOUT_H
 
// Define this to see the statistics with the first sample datum removed.
// This can expose the effects of caches on the speed of operations.
#undef STATS_WITHOUT_FIRST_SAMPLE
 
#if defined(CYGFUN_KERNEL_API_C) && \
defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \
defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \
!defined(CYGDBG_INFRA_DIAG_USE_DEVICE) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
 
#define NTHREADS 1
#include "testaux.hxx"
 
// Structure used to keep track of times
typedef struct fun_times {
cyg_uint32 start;
cyg_uint32 end;
} fun_times;
 
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM
 
#ifdef CYGMEM_REGION_ram_SIZE
#define CYG_THREAD_OVERHEAD (STACK_SIZE+sizeof(cyg_thread)+(sizeof(fun_times)*2))
#define NTEST_THREADS ((CYGMEM_REGION_ram_SIZE/16)/CYG_THREAD_OVERHEAD)
#define CYG_MUTEX_OVERHEAD (sizeof(cyg_mutex_t)+sizeof(fun_times))
#define NMUTEXES ((CYGMEM_REGION_ram_SIZE/16)/CYG_MUTEX_OVERHEAD)
#define CYG_MBOX_OVERHEAD (sizeof(cyg_mbox)+sizeof(fun_times))
#define NMBOXES ((CYGMEM_REGION_ram_SIZE/24)/CYG_MBOX_OVERHEAD)
#define CYG_SEMAPHORE_OVERHEAD (sizeof(cyg_sem_t)+sizeof(fun_times))
#define NSEMAPHORES ((CYGMEM_REGION_ram_SIZE/16)/CYG_SEMAPHORE_OVERHEAD)
#define CYG_COUNTER_OVERHEAD (sizeof(cyg_counter)+sizeof(fun_times))
#define NCOUNTERS ((CYGMEM_REGION_ram_SIZE/24)/CYG_COUNTER_OVERHEAD)
#define CYG_FLAG_OVERHEAD (sizeof(cyg_flag_t)+sizeof(fun_times))
#define NFLAGS ((CYGMEM_REGION_ram_SIZE/24)/CYG_FLAG_OVERHEAD)
#define CYG_ALARM_OVERHEAD (sizeof(cyg_alarm)+sizeof(fun_times))
#define NALARMS ((CYGMEM_REGION_ram_SIZE/16)/CYG_ALARM_OVERHEAD)
#else
// Defaults
#define NTEST_THREADS 16
#define NMUTEXES 32
#define NMBOXES 32
#define NSEMAPHORES 32
#define NFLAGS 32
#define NCOUNTERS 32
#define NALARMS 32
#endif
 
#define NSAMPLES 32
#define NTHREAD_SWITCHES 128
#define NSCHEDS 128
 
#define NSAMPLES_SIM 2
#define NTEST_THREADS_SIM 2
#define NTHREAD_SWITCHES_SIM 4
#define NMUTEXES_SIM 2
#define NMBOXES_SIM 2
#define NSEMAPHORES_SIM 2
#define NSCHEDS_SIM 4
#define NFLAGS_SIM 2
#define NCOUNTERS_SIM 2
#define NALARMS_SIM 2
 
static int nsamples;
static int ntest_threads;
static int nthread_switches;
static int nmutexes;
static int nmboxes;
static int nsemaphores;
static int nscheds;
static int nflags;
static int ncounters;
static int nalarms;
 
static char stacks[NTEST_THREADS][STACK_SIZE];
static cyg_thread test_threads[NTEST_THREADS];
static cyg_handle_t threads[NTEST_THREADS];
static int overhead;
static cyg_sem_t synchro;
static fun_times thread_ft[NTEST_THREADS];
 
static fun_times test2_ft[NTHREAD_SWITCHES];
 
static cyg_mutex_t test_mutexes[NMUTEXES];
static fun_times mutex_ft[NMUTEXES];
static cyg_thread mutex_test_thread;
static cyg_handle_t mutex_test_thread_handle;
 
static cyg_mbox test_mboxes[NMBOXES];
static cyg_handle_t test_mbox_handles[NMBOXES];
static fun_times mbox_ft[NMBOXES];
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
static cyg_thread mbox_test_thread;
static cyg_handle_t mbox_test_thread_handle;
#endif
 
static cyg_sem_t test_semaphores[NSEMAPHORES];
static fun_times semaphore_ft[NSEMAPHORES];
static cyg_thread semaphore_test_thread;
static cyg_handle_t semaphore_test_thread_handle;
 
static fun_times sched_ft[NSCHEDS];
 
static cyg_counter test_counters[NCOUNTERS];
static cyg_handle_t counters[NCOUNTERS];
static fun_times counter_ft[NCOUNTERS];
 
static cyg_flag_t test_flags[NFLAGS];
static fun_times flag_ft[NFLAGS];
 
static cyg_alarm test_alarms[NALARMS];
static cyg_handle_t alarms[NALARMS];
static fun_times alarm_ft[NALARMS];
 
static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
static long ns_per_system_clock;
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)
// Data kept by kernel real time clock measuring clock interrupt latency
extern cyg_tick_count total_clock_latency, total_clock_interrupts;
extern cyg_int32 min_clock_latency, max_clock_latency;
extern bool measure_clock_latency;
#endif
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY) && defined(HAL_CLOCK_LATENCY)
extern cyg_tick_count total_clock_dsr_latency, total_clock_dsr_calls;
extern cyg_int32 min_clock_dsr_latency, max_clock_dsr_latency;
extern bool measure_clock_latency;
#endif
 
void run_sched_tests(void);
void run_thread_tests(void);
void run_thread_switch_test(void);
void run_mutex_tests(void);
void run_mutex_circuit_test(void);
void run_mbox_tests(void);
void run_mbox_circuit_test(void);
void run_semaphore_tests(void);
void run_semaphore_circuit_test(void);
void run_counter_tests(void);
void run_flag_tests(void);
void run_alarm_tests(void);
 
#ifndef max
#define max(n,m) (m > n ? n : m)
#endif
 
// Wait until a clock tick [real time clock] has passed. This should keep it
// from happening again during a measurement, thus minimizing any fluctuations
void
wait_for_tick(void)
{
cyg_tick_count_t tv0, tv1;
tv0 = cyg_current_time();
while (true) {
tv1 = cyg_current_time();
if (tv1 != tv0) break;
}
}
 
// Display a number of ticks as microseconds
// Note: for improved calculation significance, values are kept in ticks*1000
void
show_ticks_in_us(cyg_uint32 ticks)
{
long long ns;
ns = (ns_per_system_clock * (long long)ticks) / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
ns += 5; // for rounding to .01us
diag_printf("%5d.%02d", (int)(ns/1000), (int)((ns%1000)/10));
}
 
//
// If the kernel is instrumented to measure clock interrupt latency, these
// measurements can be drastically perturbed by printing via "diag_printf()"
// since that code may run with interrupts disabled for long periods.
//
// In order to get accurate/reasonable latency figures _for the kernel
// primitive functions beint tested_, the kernel's latency measurements
// are suspended while the printing actually takes place.
//
// The measurements are reenabled after the printing, thus allowing for
// fair measurements of the kernel primitives, which are not distorted
// by the printing mechanisms.
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)
void
disable_clock_latency_measurement(void)
{
wait_for_tick();
measure_clock_latency = false;
}
 
void
enable_clock_latency_measurement(void)
{
wait_for_tick();
measure_clock_latency = true;
}
 
// Ensure that the measurements are reasonable (no startup anomalies)
void
reset_clock_latency_measurement(void)
{
disable_clock_latency_measurement();
total_clock_latency = 0;
total_clock_interrupts = 0;
min_clock_latency = 0x7FFFFFFF;
max_clock_latency = 0;
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY) && defined(HAL_CLOCK_LATENCY)
total_clock_dsr_latency = 0;
total_clock_dsr_calls = 0;
min_clock_dsr_latency = 0x7FFFFFFF;
max_clock_dsr_latency = 0;
#endif
enable_clock_latency_measurement();
}
#else
#define disable_clock_latency_measurement()
#define enable_clock_latency_measurement()
#define reset_clock_latency_measurement()
#endif
 
void
show_times_hdr(void)
{
disable_clock_latency_measurement();
diag_printf("\n");
diag_printf(" Confidence\n");
diag_printf(" Ave Min Max Var Ave Min Function\n");
diag_printf(" ====== ====== ====== ====== ========== ========\n");
enable_clock_latency_measurement();
}
 
void
show_times_detail(fun_times ft[], int nsamples, char *title, bool ignore_first)
{
int i, delta, min, max, con_ave, con_min, ave_dev;
int start_sample, total_samples;
cyg_int32 total, ave;
 
if (ignore_first) {
start_sample = 1;
total_samples = nsamples-1;
} else {
start_sample = 0;
total_samples = nsamples;
}
total = 0;
min = 0x7FFFFFFF;
max = 0;
for (i = start_sample; i < nsamples; i++) {
if (ft[i].end < ft[i].start) {
// Clock wrapped around (timer tick)
delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start;
} else {
delta = ft[i].end - ft[i].start;
}
delta -= overhead;
if (delta < 0) delta = 0;
delta *= 1000;
total += delta;
if (delta < min) min = delta;
if (delta > max) max = delta;
}
ave = total / total_samples;
total = 0;
ave_dev = 0;
for (i = start_sample; i < nsamples; i++) {
if (ft[i].end < ft[i].start) {
// Clock wrapped around (timer tick)
delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start;
} else {
delta = ft[i].end - ft[i].start;
}
delta -= overhead;
if (delta < 0) delta = 0;
delta *= 1000;
delta = delta - ave;
if (delta < 0) delta = -delta;
ave_dev += delta;
}
ave_dev /= total_samples;
con_ave = 0;
con_min = 0;
for (i = start_sample; i < nsamples; i++) {
if (ft[i].end < ft[i].start) {
// Clock wrapped around (timer tick)
delta = (ft[i].end+CYGNUM_KERNEL_COUNTERS_RTC_PERIOD) - ft[i].start;
} else {
delta = ft[i].end - ft[i].start;
}
delta -= overhead;
if (delta < 0) delta = 0;
delta *= 1000;
if ((delta <= (ave+ave_dev)) && (delta >= (ave-ave_dev))) con_ave++;
if ((delta <= (min+ave_dev)) && (delta >= (min-ave_dev))) con_min++;
}
con_ave = (con_ave * 100) / total_samples;
con_min = (con_min * 100) / total_samples;
show_ticks_in_us(ave);
show_ticks_in_us(min);
show_ticks_in_us(max);
show_ticks_in_us(ave_dev);
disable_clock_latency_measurement();
diag_printf(" %3d%% %3d%%", con_ave, con_min);
diag_printf(" %s\n", title);
enable_clock_latency_measurement();
}
 
void
show_times(fun_times ft[], int nsamples, char *title)
{
show_times_detail(ft, nsamples, title, false);
#ifdef STATS_WITHOUT_FIRST_SAMPLE
show_times_detail(ft, nsamples, "", true);
#endif
}
 
void
show_test_parameters(void)
{
disable_clock_latency_measurement();
diag_printf("\nTesting parameters:\n");
diag_printf(" Clock samples: %5d\n", nsamples);
diag_printf(" Threads: %5d\n", ntest_threads);
diag_printf(" Thread switches: %5d\n", nthread_switches);
diag_printf(" Mutexes: %5d\n", nmutexes);
diag_printf(" Mailboxes: %5d\n", nmboxes);
diag_printf(" Semaphores: %5d\n", nsemaphores);
diag_printf(" Scheduler operations: %5d\n", nscheds);
diag_printf(" Counters: %5d\n", ncounters);
diag_printf(" Flags: %5d\n", nflags);
diag_printf(" Alarms: %5d\n", nalarms);
diag_printf("\n");
enable_clock_latency_measurement();
}
 
void
end_of_test_group(void)
{
disable_clock_latency_measurement();
diag_printf("\n");
enable_clock_latency_measurement();
}
 
// Compute a name for a thread
char *
thread_name(char *basename, int indx) {
return "<<NULL>>"; // Not currently used
}
 
// test0 - null test, never executed
void
test0(cyg_uint32 indx)
{
#ifndef CYGPKG_KERNEL_SMP_SUPPORT
// In SMP, somw of these threads will execute
diag_printf("test0.%d executed?\n", indx);
#endif
cyg_thread_exit();
}
 
// test1 - empty test, simply exit. Last thread signals parent.
void
test1(cyg_uint32 indx)
{
if (indx == (cyg_uint32)(ntest_threads-1)) {
cyg_semaphore_post(&synchro); // Signal that last thread is dying
}
cyg_thread_exit();
}
 
// test2 - measure thread switch times
void
test2(cyg_uint32 indx)
{
int i;
for (i = 0; i < nthread_switches; i++) {
if (indx == 0) {
HAL_CLOCK_READ(&test2_ft[i].start);
} else {
HAL_CLOCK_READ(&test2_ft[i].end);
}
cyg_thread_yield();
}
if (indx == 1) {
cyg_semaphore_post(&synchro);
}
cyg_thread_exit();
}
 
// Full-circuit mutex unlock/lock test
void
mutex_test(cyg_uint32 indx)
{
int i;
cyg_mutex_lock(&test_mutexes[0]);
for (i = 0; i < nmutexes; i++) {
cyg_semaphore_wait(&synchro);
wait_for_tick(); // Wait until the next clock tick to minimize aberations
HAL_CLOCK_READ(&mutex_ft[i].start);
cyg_mutex_unlock(&test_mutexes[0]);
cyg_mutex_lock(&test_mutexes[0]);
cyg_semaphore_post(&synchro);
}
cyg_thread_exit();
}
 
// Full-circuit mbox put/get test
void
mbox_test(cyg_uint32 indx)
{
void *item;
do {
item = cyg_mbox_get(test_mbox_handles[0]);
HAL_CLOCK_READ(&mbox_ft[(int)item].end);
cyg_semaphore_post(&synchro);
} while ((int)item != (nmboxes-1));
cyg_thread_exit();
}
 
// Full-circuit semaphore post/wait test
void
semaphore_test(cyg_uint32 indx)
{
int i;
for (i = 0; i < nsemaphores; i++) {
cyg_semaphore_wait(&test_semaphores[0]);
HAL_CLOCK_READ(&semaphore_ft[i].end);
cyg_semaphore_post(&synchro);
}
cyg_thread_exit();
}
 
//
// This set of tests is used to measure kernel primitives that deal with threads
//
void
run_thread_tests(void)
{
int i;
cyg_priority_t prio;
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_create(10, // Priority - just a number
test0, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Create thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_yield();
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Yield thread [all suspended]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_suspend(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Suspend [suspended] thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_resume(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Resume thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_set_priority(threads[i], 11);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Set priority");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
prio = cyg_thread_get_priority(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Get priority");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_kill(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Kill [suspended] thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_yield();
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Yield [no other] thread");
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
 
// Recreate the test set
for (i = 0; i < ntest_threads; i++) {
cyg_thread_create(10, // Priority - just a number
test0, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
}
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_resume(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Resume [suspended low prio] thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_resume(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Resume [runnable low prio] thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_suspend(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Suspend [runnable] thread");
 
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_yield();
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Yield [only low prio] thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_suspend(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Suspend [runnable->not runnable]");
for (i = 0; i < ntest_threads; i++) {
cyg_thread_resume(threads[i]);
}
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_kill(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Kill [runnable] thread");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_delete(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Destroy [dead] thread");
 
// Recreate the test set
for (i = 0; i < ntest_threads; i++) {
cyg_thread_create(10, // Priority - just a number
test0, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume(threads[i]);
}
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_delete(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Destroy [runnable] thread");
 
// Set my priority lower than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 3);
 
// Set up the end-of-threads synchronizer
cyg_semaphore_init(&synchro, 0);
 
// Recreate the test set
for (i = 0; i < ntest_threads; i++) {
cyg_thread_create(2, // Priority - just a number
test1, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
}
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ntest_threads; i++) {
HAL_CLOCK_READ(&thread_ft[i].start);
cyg_thread_resume(threads[i]);
HAL_CLOCK_READ(&thread_ft[i].end);
}
show_times(thread_ft, ntest_threads, "Resume [high priority] thread");
cyg_semaphore_wait(&synchro); // Wait for all threads to finish
// Make sure they are all dead
for (i = 0; i < ntest_threads; i++) {
cyg_thread_delete(threads[i]);
}
 
run_thread_switch_test();
end_of_test_group();
}
 
void
run_thread_switch_test(void)
{
int i;
 
// Set up for thread context switch
for (i = 0; i < 2; i++) {
cyg_thread_create(10, // Priority - just a number
test2, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume(threads[i]);
}
// Set up the end-of-threads synchronizer
cyg_semaphore_init(&synchro, 0);
cyg_semaphore_wait(&synchro);
wait_for_tick(); // Wait until the next clock tick to minimize aberations
show_times(test2_ft, nthread_switches, "Thread switch");
// Clean up
for (i = 0; i < 2; i++) {
cyg_thread_delete(threads[i]);
}
}
 
void
run_mutex_tests(void)
{
int i;
 
// Mutex primitives
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmutexes; i++) {
HAL_CLOCK_READ(&mutex_ft[i].start);
cyg_mutex_init(&test_mutexes[i]);
HAL_CLOCK_READ(&mutex_ft[i].end);
}
show_times(mutex_ft, nmutexes, "Init mutex");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmutexes; i++) {
HAL_CLOCK_READ(&mutex_ft[i].start);
cyg_mutex_lock(&test_mutexes[i]);
HAL_CLOCK_READ(&mutex_ft[i].end);
}
show_times(mutex_ft, nmutexes, "Lock [unlocked] mutex");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmutexes; i++) {
HAL_CLOCK_READ(&mutex_ft[i].start);
cyg_mutex_unlock(&test_mutexes[i]);
HAL_CLOCK_READ(&mutex_ft[i].end);
}
show_times(mutex_ft, nmutexes, "Unlock [locked] mutex");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmutexes; i++) {
HAL_CLOCK_READ(&mutex_ft[i].start);
cyg_mutex_trylock(&test_mutexes[i]);
HAL_CLOCK_READ(&mutex_ft[i].end);
}
show_times(mutex_ft, nmutexes, "Trylock [unlocked] mutex");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmutexes; i++) {
HAL_CLOCK_READ(&mutex_ft[i].start);
cyg_mutex_trylock(&test_mutexes[i]);
HAL_CLOCK_READ(&mutex_ft[i].end);
}
show_times(mutex_ft, nmutexes, "Trylock [locked] mutex");
 
// Must unlock mutices before destroying them.
for (i = 0; i < nmutexes; i++) {
cyg_mutex_unlock(&test_mutexes[i]);
}
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmutexes; i++) {
HAL_CLOCK_READ(&mutex_ft[i].start);
cyg_mutex_destroy(&test_mutexes[i]);
HAL_CLOCK_READ(&mutex_ft[i].end);
}
show_times(mutex_ft, nmutexes, "Destroy mutex");
run_mutex_circuit_test();
end_of_test_group();
}
 
void
run_mutex_circuit_test(void)
{
int i;
// Set my priority lower than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 4);
// Set up for full mutex unlock/lock test
cyg_mutex_init(&test_mutexes[0]);
cyg_semaphore_init(&synchro, 0);
cyg_thread_create(3, // Priority - just a number
mutex_test, // entry
0, // index
thread_name("thread", 0), // Name
&stacks[0][0], // Stack
STACK_SIZE, // Size
&mutex_test_thread_handle, // Handle
&mutex_test_thread // Thread data structure
);
cyg_thread_resume(mutex_test_thread_handle);
// Need to raise priority so that this thread will block on the "lock"
cyg_thread_set_priority(cyg_thread_self(), 2);
for (i = 0; i < nmutexes; i++) {
cyg_semaphore_post(&synchro);
cyg_mutex_lock(&test_mutexes[0]);
HAL_CLOCK_READ(&mutex_ft[i].end);
cyg_mutex_unlock(&test_mutexes[0]);
cyg_semaphore_wait(&synchro);
}
cyg_thread_delete(mutex_test_thread_handle);
show_times(mutex_ft, nmutexes, "Unlock/Lock mutex");
}
 
void
run_mbox_tests(void)
{
int i, cnt;
void *item;
// Mailbox primitives
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_create(&test_mbox_handles[i], &test_mboxes[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Create mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cnt = cyg_mbox_peek(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Peek [empty] mbox");
 
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_put(test_mbox_handles[i], (void *)i);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Put [first] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cnt = cyg_mbox_peek(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Peek [1 msg] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_put(test_mbox_handles[i], (void *)i);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Put [second] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cnt = cyg_mbox_peek(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Peek [2 msgs] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
item = cyg_mbox_get(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Get [first] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
item = cyg_mbox_get(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Get [second] mbox");
#endif // ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_tryput(test_mbox_handles[i], (void *)i);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Tryput [first] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
item = cyg_mbox_peek_item(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Peek item [non-empty] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
item = cyg_mbox_tryget(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Tryget [non-empty] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
item = cyg_mbox_peek_item(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Peek item [empty] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
item = cyg_mbox_tryget(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Tryget [empty] mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_waiting_to_get(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Waiting to get mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_waiting_to_put(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Waiting to put mbox");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nmboxes; i++) {
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_delete(test_mbox_handles[i]);
HAL_CLOCK_READ(&mbox_ft[i].end);
}
show_times(mbox_ft, nmboxes, "Delete mbox");
 
run_mbox_circuit_test();
end_of_test_group();
}
 
void
run_mbox_circuit_test(void)
{
#ifdef CYGMFN_KERNEL_SYNCH_MBOXT_PUT_CAN_WAIT
int i;
// Set my priority lower than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 3);
// Set up for full mbox put/get test
cyg_mbox_create(&test_mbox_handles[0], &test_mboxes[0]);
cyg_semaphore_init(&synchro, 0);
cyg_thread_create(2, // Priority - just a number
mbox_test, // entry
0, // index
thread_name("thread", 0), // Name
&stacks[0][0], // Stack
STACK_SIZE, // Size
&mbox_test_thread_handle, // Handle
&mbox_test_thread // Thread data structure
);
cyg_thread_resume(mbox_test_thread_handle);
for (i = 0; i < nmboxes; i++) {
wait_for_tick(); // Wait until the next clock tick to minimize aberations
HAL_CLOCK_READ(&mbox_ft[i].start);
cyg_mbox_put(test_mbox_handles[0], (void *)i);
cyg_semaphore_wait(&synchro);
}
cyg_thread_delete(mbox_test_thread_handle);
show_times(mbox_ft, nmboxes, "Put/Get mbox");
#endif
}
 
void
run_semaphore_tests(void)
{
int i;
cyg_count32 sem_val;
// Semaphore primitives
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nsemaphores; i++) {
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_init(&test_semaphores[i], 0);
HAL_CLOCK_READ(&semaphore_ft[i].end);
}
show_times(semaphore_ft, nsemaphores, "Init semaphore");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nsemaphores; i++) {
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_post(&test_semaphores[i]);
HAL_CLOCK_READ(&semaphore_ft[i].end);
}
show_times(semaphore_ft, nsemaphores, "Post [0] semaphore");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nsemaphores; i++) {
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_wait(&test_semaphores[i]);
HAL_CLOCK_READ(&semaphore_ft[i].end);
}
show_times(semaphore_ft, nsemaphores, "Wait [1] semaphore");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nsemaphores; i++) {
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_trywait(&test_semaphores[i]);
HAL_CLOCK_READ(&semaphore_ft[i].end);
}
show_times(semaphore_ft, nsemaphores, "Trywait [0] semaphore");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nsemaphores; i++) {
cyg_semaphore_post(&test_semaphores[i]);
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_trywait(&test_semaphores[i]);
HAL_CLOCK_READ(&semaphore_ft[i].end);
}
show_times(semaphore_ft, nsemaphores, "Trywait [1] semaphore");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nsemaphores; i++) {
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_peek(&test_semaphores[i], &sem_val);
HAL_CLOCK_READ(&semaphore_ft[i].end);
}
show_times(semaphore_ft, nsemaphores, "Peek semaphore");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nsemaphores; i++) {
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_destroy(&test_semaphores[i]);
HAL_CLOCK_READ(&semaphore_ft[i].end);
}
show_times(semaphore_ft, nsemaphores, "Destroy semaphore");
 
run_semaphore_circuit_test();
end_of_test_group();
}
 
void
run_semaphore_circuit_test(void)
{
int i;
// Set my priority lower than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 3);
// Set up for full semaphore post/wait test
cyg_semaphore_init(&test_semaphores[0], 0);
cyg_semaphore_init(&synchro, 0);
cyg_thread_create(2, // Priority - just a number
semaphore_test, // entry
0, // index
thread_name("thread", 0), // Name
&stacks[0][0], // Stack
STACK_SIZE, // Size
&semaphore_test_thread_handle, // Handle
&semaphore_test_thread // Thread data structure
);
cyg_thread_resume(semaphore_test_thread_handle);
for (i = 0; i < nsemaphores; i++) {
wait_for_tick(); // Wait until the next clock tick to minimize aberations
HAL_CLOCK_READ(&semaphore_ft[i].start);
cyg_semaphore_post(&test_semaphores[0]);
cyg_semaphore_wait(&synchro);
}
cyg_thread_delete(semaphore_test_thread_handle);
show_times(semaphore_ft, nsemaphores, "Post/Wait semaphore");
}
 
void
run_counter_tests(void)
{
int i;
cyg_tick_count_t val=0;
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
cyg_counter_create(&counters[i], &test_counters[i]);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Create counter");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
val = cyg_counter_current_value(counters[i]);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Get counter value");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
cyg_counter_set_value(counters[i], val);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Set counter value");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
cyg_counter_tick(counters[i]);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Tick counter");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
cyg_counter_delete(counters[i]);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Delete counter");
end_of_test_group();
}
 
void
run_flag_tests(void)
{
int i;
cyg_flag_value_t val;
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_init(&test_flags[i]);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Init flag");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_destroy(&test_flags[i]);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Destroy flag");
 
// Recreate the flags - reused in the remaining tests
for (i = 0; i < nflags; i++) {
cyg_flag_init(&test_flags[i]);
}
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_maskbits(&test_flags[i], 0);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Mask bits in flag");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_setbits(&test_flags[i], 0x11);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Set bits in flag [no waiters]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
cyg_flag_setbits(&test_flags[i], 0x11);
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_wait(&test_flags[i], 0x11, CYG_FLAG_WAITMODE_AND);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Wait for flag [AND]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
cyg_flag_setbits(&test_flags[i], 0x11);
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_wait(&test_flags[i], 0x11, CYG_FLAG_WAITMODE_OR);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Wait for flag [OR]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
cyg_flag_setbits(&test_flags[i], 0x11);
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_wait(&test_flags[i], 0x11, CYG_FLAG_WAITMODE_AND|CYG_FLAG_WAITMODE_CLR);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Wait for flag [AND/CLR]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
cyg_flag_setbits(&test_flags[i], 0x11);
HAL_CLOCK_READ(&flag_ft[i].start);
cyg_flag_wait(&test_flags[i], 0x11, CYG_FLAG_WAITMODE_OR|CYG_FLAG_WAITMODE_CLR);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Wait for flag [OR/CLR]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nflags; i++) {
cyg_flag_setbits(&test_flags[i], 0x11);
HAL_CLOCK_READ(&flag_ft[i].start);
val = cyg_flag_peek(&test_flags[i]);
HAL_CLOCK_READ(&flag_ft[i].end);
}
show_times(flag_ft, nflags, "Peek on flag");
 
// Destroy flags - no longer needed
for (i = 0; i < nflags; i++) {
cyg_flag_destroy(&test_flags[i]);
}
end_of_test_group();
}
 
// Alarm callback function
void
alarm_cb(cyg_handle_t alarm, cyg_addrword_t val)
{
// empty call back
}
 
// Callback used to test determinancy
static volatile int alarm_cnt;
void
alarm_cb2(cyg_handle_t alarm, cyg_addrword_t indx)
{
if (alarm_cnt == nscheds) return;
sched_ft[alarm_cnt].start = 0;
HAL_CLOCK_READ(&sched_ft[alarm_cnt++].end);
if (alarm_cnt == nscheds) {
cyg_semaphore_post(&synchro);
}
}
 
static void
alarm_cb3(cyg_handle_t alarm, cyg_addrword_t indx)
{
if (alarm_cnt == nscheds) {
cyg_semaphore_post(&synchro);
} else {
sched_ft[alarm_cnt].start = 0;
cyg_thread_resume((cyg_handle_t)indx);
}
}
 
// Null thread, used to keep scheduler busy
void
alarm_test(cyg_uint32 id)
{
while (true) {
cyg_thread_yield();
}
}
 
// Thread that suspends itself at the first opportunity
void
alarm_test2(cyg_uint32 id)
{
cyg_handle_t me = cyg_thread_self();
while (true) {
HAL_CLOCK_READ(&sched_ft[alarm_cnt++].end);
cyg_thread_suspend(me);
}
}
 
void
run_alarm_tests(void)
{
int i;
cyg_tick_count_t init_val, step_val;
cyg_handle_t rtc_handle;
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < ncounters; i++) {
cyg_counter_create(&counters[i], &test_counters[i]);
}
for (i = 0; i < nalarms; i++) {
HAL_CLOCK_READ(&alarm_ft[i].start);
cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[i], &test_alarms[i]);
HAL_CLOCK_READ(&alarm_ft[i].end);
}
show_times(alarm_ft, nalarms, "Create alarm");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
init_val = 0; step_val = 0;
for (i = 0; i < nalarms; i++) {
HAL_CLOCK_READ(&alarm_ft[i].start);
cyg_alarm_initialize(alarms[i], init_val, step_val);
HAL_CLOCK_READ(&alarm_ft[i].end);
}
show_times(alarm_ft, nalarms, "Initialize alarm");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
init_val = 0; step_val = 0;
for (i = 0; i < nalarms; i++) {
HAL_CLOCK_READ(&alarm_ft[i].start);
cyg_alarm_disable(alarms[i]);
HAL_CLOCK_READ(&alarm_ft[i].end);
}
show_times(alarm_ft, nalarms, "Disable alarm");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
init_val = 0; step_val = 0;
for (i = 0; i < nalarms; i++) {
HAL_CLOCK_READ(&alarm_ft[i].start);
cyg_alarm_enable(alarms[i]);
HAL_CLOCK_READ(&alarm_ft[i].end);
}
show_times(alarm_ft, nalarms, "Enable alarm");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nalarms; i++) {
HAL_CLOCK_READ(&alarm_ft[i].start);
cyg_alarm_delete(alarms[i]);
HAL_CLOCK_READ(&alarm_ft[i].end);
}
show_times(alarm_ft, nalarms, "Delete alarm");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_counter_create(&counters[0], &test_counters[0]);
cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[0], &test_alarms[0]);
init_val = 9999; step_val = 9999;
cyg_alarm_initialize(alarms[0], init_val, step_val);
cyg_alarm_enable(alarms[0]);
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
cyg_counter_tick(counters[0]);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Tick counter [1 alarm]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_counter_create(&counters[0], &test_counters[0]);
for (i = 0; i < nalarms; i++) {
cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[i], &test_alarms[i]);
init_val = 9999; step_val = 9999;
cyg_alarm_initialize(alarms[i], init_val, step_val);
cyg_alarm_enable(alarms[i]);
}
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
cyg_counter_tick(counters[0]);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Tick counter [many alarms]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_counter_create(&counters[0], &test_counters[0]);
cyg_alarm_create(counters[0], alarm_cb, 0, &alarms[0], &test_alarms[0]);
init_val = 1; step_val = 1;
cyg_alarm_initialize(alarms[0], init_val, step_val);
cyg_alarm_enable(alarms[0]);
for (i = 0; i < ncounters; i++) {
HAL_CLOCK_READ(&counter_ft[i].start);
cyg_counter_tick(counters[0]);
HAL_CLOCK_READ(&counter_ft[i].end);
}
show_times(counter_ft, ncounters, "Tick & fire counter [1 alarm]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_counter_create(&counters[0], &test_counters[0]);
for (i = 0; i < nalarms; i++) {
cyg_alarm_create(counters[0], alarm_cb, i, &alarms[i], &test_alarms[i]);
init_val = 1; step_val = 1;
cyg_alarm_initialize(alarms[i], init_val, step_val);
cyg_alarm_enable(alarms[i]);
}
for (i = 0; i < nalarms; i++) {
HAL_CLOCK_READ(&alarm_ft[i].start);
cyg_counter_tick(counters[0]);
HAL_CLOCK_READ(&alarm_ft[i].end);
}
for (i = 0; i < nalarms; i++) {
cyg_alarm_delete(alarms[i]);
}
show_times(alarm_ft, nalarms, "Tick & fire counters [>1 together]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_counter_create(&counters[0], &test_counters[0]);
for (i = 0; i < nalarms; i++) {
cyg_alarm_create(counters[0], alarm_cb, i, &alarms[i], &test_alarms[i]);
init_val = i+1; step_val = nalarms+1;
cyg_alarm_initialize(alarms[i], init_val, step_val);
cyg_alarm_enable(alarms[i]);
}
for (i = 0; i < nalarms; i++) {
HAL_CLOCK_READ(&alarm_ft[i].start);
cyg_counter_tick(counters[0]);
HAL_CLOCK_READ(&alarm_ft[i].end);
}
for (i = 0; i < nalarms; i++) {
cyg_alarm_delete(alarms[i]);
}
show_times(alarm_ft, nalarms, "Tick & fire counters [>1 separately]");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_clock_to_counter(cyg_real_time_clock(), &rtc_handle);
cyg_alarm_create(rtc_handle, alarm_cb2, 0, &alarms[0], &test_alarms[0]);
init_val = 5; step_val = 5; alarm_cnt = 0;
cyg_alarm_initialize(alarms[0], init_val, step_val);
cyg_semaphore_init(&synchro, 0);
cyg_alarm_enable(alarms[0]);
cyg_semaphore_wait(&synchro);
cyg_alarm_disable(alarms[0]);
cyg_alarm_delete(alarms[0]);
show_times(sched_ft, nscheds, "Alarm latency [0 threads]");
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
for (i = 0; i < 2; i++) {
cyg_thread_create(10, // Priority - just a number
alarm_test, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume(threads[i]);
}
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_clock_to_counter(cyg_real_time_clock(), &rtc_handle);
cyg_alarm_create(rtc_handle, alarm_cb2, 0, &alarms[0], &test_alarms[0]);
init_val = 5; step_val = 5; alarm_cnt = 0;
cyg_alarm_initialize(alarms[0], init_val, step_val);
cyg_semaphore_init(&synchro, 0);
cyg_alarm_enable(alarms[0]);
cyg_semaphore_wait(&synchro);
cyg_alarm_disable(alarms[0]);
cyg_alarm_delete(alarms[0]);
show_times(sched_ft, nscheds, "Alarm latency [2 threads]");
for (i = 0; i < 2; i++) {
cyg_thread_suspend(threads[i]);
cyg_thread_delete(threads[i]);
}
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
for (i = 0; i < ntest_threads; i++) {
cyg_thread_create(10, // Priority - just a number
alarm_test, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume(threads[i]);
}
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_clock_to_counter(cyg_real_time_clock(), &rtc_handle);
cyg_alarm_create(rtc_handle, alarm_cb2, 0, &alarms[0], &test_alarms[0]);
init_val = 5; step_val = 5; alarm_cnt = 0;
cyg_alarm_initialize(alarms[0], init_val, step_val);
cyg_semaphore_init(&synchro, 0);
cyg_alarm_enable(alarms[0]);
cyg_semaphore_wait(&synchro);
cyg_alarm_disable(alarms[0]);
cyg_alarm_delete(alarms[0]);
show_times(sched_ft, nscheds, "Alarm latency [many threads]");
for (i = 0; i < ntest_threads; i++) {
cyg_thread_suspend(threads[i]);
cyg_thread_delete(threads[i]);
}
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
cyg_thread_create(10, // Priority - just a number
alarm_test2, // entry
i, // index
thread_name("thread", 0), // Name
&stacks[0][0], // Stack
STACK_SIZE, // Size
&threads[0], // Handle
&test_threads[0] // Thread data structure
);
wait_for_tick(); // Wait until the next clock tick to minimize aberations
cyg_clock_to_counter(cyg_real_time_clock(), &rtc_handle);
cyg_alarm_create(rtc_handle, alarm_cb3, threads[0], &alarms[0],
&test_alarms[0]);
init_val = 5; step_val = 5; alarm_cnt = 0;
cyg_alarm_initialize(alarms[0], init_val, step_val);
cyg_semaphore_init(&synchro, 0);
cyg_alarm_enable(alarms[0]);
cyg_semaphore_wait(&synchro);
cyg_alarm_disable(alarms[0]);
cyg_alarm_delete(alarms[0]);
show_times(sched_ft, nscheds, "Alarm -> thread resume latency");
cyg_thread_suspend(threads[0]);
cyg_thread_delete(threads[0]);
end_of_test_group();
}
 
void
run_sched_tests(void)
{
int i;
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nscheds; i++) {
HAL_CLOCK_READ(&sched_ft[i].start);
cyg_scheduler_lock();
HAL_CLOCK_READ(&sched_ft[i].end);
cyg_scheduler_unlock();
}
show_times(sched_ft, nscheds, "Scheduler lock");
 
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nscheds; i++) {
cyg_scheduler_lock();
HAL_CLOCK_READ(&sched_ft[i].start);
cyg_scheduler_unlock();
HAL_CLOCK_READ(&sched_ft[i].end);
}
show_times(sched_ft, nscheds, "Scheduler unlock [0 threads]");
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
for (i = 0; i < 1; i++) {
cyg_thread_create(10, // Priority - just a number
test0, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
}
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nscheds; i++) {
cyg_scheduler_lock();
HAL_CLOCK_READ(&sched_ft[i].start);
cyg_scheduler_unlock();
HAL_CLOCK_READ(&sched_ft[i].end);
}
show_times(sched_ft, nscheds, "Scheduler unlock [1 suspended]");
for (i = 0; i < 1; i++) {
cyg_thread_delete(threads[i]);
}
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
for (i = 0; i < ntest_threads; i++) {
cyg_thread_create(10, // Priority - just a number
test0, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
}
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nscheds; i++) {
cyg_scheduler_lock();
HAL_CLOCK_READ(&sched_ft[i].start);
cyg_scheduler_unlock();
HAL_CLOCK_READ(&sched_ft[i].end);
}
show_times(sched_ft, nscheds, "Scheduler unlock [many suspended]");
for (i = 0; i < ntest_threads; i++) {
cyg_thread_delete(threads[i]);
}
 
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
for (i = 0; i < ntest_threads; i++) {
cyg_thread_create(10, // Priority - just a number
test0, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume(threads[i]);
}
wait_for_tick(); // Wait until the next clock tick to minimize aberations
for (i = 0; i < nscheds; i++) {
cyg_scheduler_lock();
HAL_CLOCK_READ(&sched_ft[i].start);
cyg_scheduler_unlock();
HAL_CLOCK_READ(&sched_ft[i].end);
}
show_times(sched_ft, nscheds, "Scheduler unlock [many low prio]");
for (i = 0; i < ntest_threads; i++) {
cyg_thread_delete(threads[i]);
}
end_of_test_group();
}
 
void
run_all_tests(CYG_ADDRESS id)
{
int i, j;
cyg_uint32 tv[nsamples], tv0, tv1;
cyg_uint32 min_stack, max_stack, total_stack, actual_stack;
cyg_tick_count_t ticks, tick0, tick1;
#ifdef CYG_SCHEDULER_LOCK_TIMINGS
cyg_uint32 lock_ave, lock_max;
#endif
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)
cyg_int32 clock_ave;
#endif
 
disable_clock_latency_measurement();
 
#ifndef CYGPKG_KERNEL_SMP_SUPPORT
cyg_test_dump_thread_stack_stats( "Startup, main stack", thread[0] );
cyg_test_dump_interrupt_stack_stats( "Startup" );
cyg_test_dump_idlethread_stack_stats( "Startup" );
cyg_test_clear_interrupt_stack();
#endif
diag_printf("\neCos Kernel Timings\n");
diag_printf("Notes: all times are in microseconds (.000001) unless otherwise stated\n");
#ifdef STATS_WITHOUT_FIRST_SAMPLE
diag_printf(" second line of results have first sample removed\n");
#endif
 
cyg_thread_delay(2); // Make sure the clock is actually running
 
ns_per_system_clock = 1000000/rtc_resolution[1];
 
wait_for_tick();
for (i = 0; i < nsamples; i++) {
HAL_CLOCK_READ(&tv[i]);
}
tv0 = 0;
for (i = 1; i < nsamples; i++) {
tv0 += tv[i] - tv[i-1];
}
end_of_test_group();
overhead = tv0 / (nsamples-1);
diag_printf("Reading the hardware clock takes %d 'ticks' overhead\n", overhead);
diag_printf("... this value will be factored out of all other measurements\n");
 
// Try and measure how long the clock interrupt handling takes
for (i = 0; i < nsamples; i++) {
tick0 = cyg_current_time();
while (true) {
tick1 = cyg_current_time();
if (tick0 != tick1) break;
}
HAL_CLOCK_READ(&tv[i]);
}
tv1 = 0;
for (i = 0; i < nsamples; i++) {
tv1 += tv[i] * 1000;
}
tv1 = tv1 / nsamples;
tv1 -= overhead; // Adjust out the cost of getting the timer value
diag_printf("Clock interrupt took");
show_ticks_in_us(tv1);
diag_printf(" microseconds (%d raw clock ticks)\n", tv1/1000);
enable_clock_latency_measurement();
 
ticks = cyg_current_time();
 
show_test_parameters();
show_times_hdr();
 
reset_clock_latency_measurement();
 
run_thread_tests();
run_sched_tests();
run_mutex_tests();
run_mbox_tests();
run_semaphore_tests();
run_counter_tests();
run_flag_tests();
run_alarm_tests();
 
#ifdef CYG_SCHEDULER_LOCK_TIMINGS
Cyg_Scheduler::get_lock_times(&lock_ave, &lock_max);
diag_printf("\nMax lock:");
show_ticks_in_us(lock_max);
diag_printf(", Ave lock:");
show_ticks_in_us(lock_ave);
diag_printf("\n");
#endif
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY) && defined(HAL_CLOCK_LATENCY)
// Display latency figures in same format as all other numbers
disable_clock_latency_measurement();
clock_ave = (total_clock_latency*1000) / total_clock_interrupts;
show_ticks_in_us(clock_ave);
show_ticks_in_us(min_clock_latency*1000);
show_ticks_in_us(max_clock_latency*1000);
show_ticks_in_us(0);
diag_printf(" Clock/interrupt latency\n\n");
enable_clock_latency_measurement();
#endif
 
#if defined(CYGVAR_KERNEL_COUNTERS_CLOCK_DSR_LATENCY) && defined(HAL_CLOCK_LATENCY)
disable_clock_latency_measurement();
clock_ave = (total_clock_dsr_latency*1000) / total_clock_dsr_calls;
show_ticks_in_us(clock_ave);
show_ticks_in_us(min_clock_dsr_latency*1000);
show_ticks_in_us(max_clock_dsr_latency*1000);
show_ticks_in_us(0);
diag_printf(" Clock DSR latency\n\n");
enable_clock_latency_measurement();
#endif
 
#ifndef CYGPKG_KERNEL_SMP_SUPPORT
disable_clock_latency_measurement();
min_stack = STACK_SIZE;
max_stack = 0;
total_stack = 0;
for (i = 0; i < (int)NTEST_THREADS; i++) {
for (j = 0; j < STACK_SIZE; j++) {
if (stacks[i][j]) break;
}
actual_stack = STACK_SIZE-j;
if (actual_stack < min_stack) min_stack = actual_stack;
if (actual_stack > max_stack) max_stack = actual_stack;
total_stack += actual_stack;
}
for (j = 0; j < STACKSIZE; j++) {
if (((char *)stack[0])[j]) break;
}
diag_printf("%5d %5d %5d (main stack: %5d) Thread stack used (%d total)\n",
total_stack/NTEST_THREADS, min_stack, max_stack,
STACKSIZE - j, STACK_SIZE);
 
cyg_test_dump_thread_stack_stats( "All done, main stack", thread[0] );
cyg_test_dump_interrupt_stack_stats( "All done" );
cyg_test_dump_idlethread_stack_stats( "All done" );
#endif
enable_clock_latency_measurement();
 
ticks = cyg_current_time();
diag_printf("\nTiming complete - %d ms total\n\n", (int)((ticks*ns_per_system_clock)/1000));
 
CYG_TEST_PASS_FINISH("Basic timing OK");
}
 
void tm_basic_main( void )
{
CYG_TEST_INIT();
 
if (cyg_test_is_simulator) {
nsamples = NSAMPLES_SIM;
ntest_threads = NTEST_THREADS_SIM;
nthread_switches = NTHREAD_SWITCHES_SIM;
nmutexes = NMUTEXES_SIM;
nmboxes = NMBOXES_SIM;
nsemaphores = NSEMAPHORES_SIM;
nscheds = NSCHEDS_SIM;
nflags = NFLAGS_SIM;
ncounters = NCOUNTERS_SIM;
nalarms = NALARMS_SIM;
} else {
nsamples = NSAMPLES;
ntest_threads = NTEST_THREADS;
nthread_switches = NTHREAD_SWITCHES;
nmutexes = NMUTEXES;
nmboxes = NMBOXES;
nsemaphores = NSEMAPHORES;
nscheds = NSCHEDS;
nflags = NFLAGS;
ncounters = NCOUNTERS;
nalarms = NALARMS;
}
 
// Sanity
#ifdef WORKHORSE_TEST
ntest_threads = max(512, ntest_threads);
nmutexes = max(1024, nmutexes);
nsemaphores = max(1024, nsemaphores);
nmboxes = max(1024, nmboxes);
ncounters = max(1024, ncounters);
nalarms = max(1024, nalarms);
#else
ntest_threads = max(64, ntest_threads);
nmutexes = max(32, nmutexes);
nsemaphores = max(32, nsemaphores);
nmboxes = max(32, nmboxes);
ncounters = max(32, ncounters);
nflags = max(32, nflags);
nalarms = max(32, nalarms);
#endif
 
new_thread(run_all_tests, 0);
Cyg_Scheduler::scheduler.start();
 
}
 
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
tm_basic_main();
}
 
#else // CYGFUN_KERNEL_API_C
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Timing tests require:\n"
"CYGFUN_KERNEL_API_C && \n"
"CYGSEM_KERNEL_SCHED_MLQUEUE &&\n"
"CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
"!CYGDBG_INFRA_DIAG_USE_DEVICE &&\n"
"(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n");
}
#endif // CYGFUN_KERNEL_API_C, etc.
 
// EOF tm_basic.cxx
/mqueue1.cxx
0,0 → 1,411
/*========================================================================
//
// mqueue1.cxx
//
// Message queues tests
//
//========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jlarmour
// Contributors:
// Date: 2000-05-12
// Purpose: This file provides tests for eCos mqueues
// Description:
// Usage:
//
//####DESCRIPTIONEND####
//
//======================================================================
*/
 
/* CONFIGURATION */
 
#include <pkgconf/kernel.h>
 
/* INCLUDES */
 
#include <cyg/infra/cyg_type.h> // common types and externC
#include <cyg/kernel/thread.hxx> // Cyg_Thread
#include <cyg/kernel/thread.inl>
// Specially avoid inlining here due to the way we abuse the mqueue
// implementation by making lots and lots of calls.
#define CYGPRI_KERNEL_SYNCH_MQUEUE_INLINE
#include <cyg/kernel/mqueue.hxx> // Mqueue Header
#include <cyg/kernel/sema.hxx> // semaphores
#include <cyg/infra/testcase.h> // test API
 
// use the common kernel test magic to define 2 threads
#define NTHREADS 2
#include "testaux.hxx"
 
/* GLOBALS */
 
static char mempool[500];
static size_t storedmempoollen;
Cyg_Mqueue *mq;
static Cyg_Binary_Semaphore t0sem, t1sem;
static int calledback;
 
 
/* FUNCTIONS */
 
static int
my_memcmp(const void *m1, const void *m2, size_t n)
{
char *s1 = (char *)m1;
char *s2 = (char *)m2;
 
while (n--) {
if (*s1 != *s2)
return *s1 - *s2;
s1++;
s2++;
}
return 0;
} // my_memcmp()
 
static void *
my_alloc( size_t len )
{
if ( len > sizeof(mempool) )
return NULL;
 
storedmempoollen = len;
return &mempool[0];
}
 
static void
my_free( void *ptr, size_t len )
{
CYG_TEST_PASS_FAIL( (ptr == &mempool[0]) && (len == storedmempoollen),
"Freed pool correctly");
mq = NULL; // invalidate
}
 
static void
callback(Cyg_Mqueue &mq, CYG_ADDRWORD data)
{
calledback += (int)data;
}
 
//************************************************************************
//************************************************************************
 
static void
t0( CYG_ADDRWORD data )
{
Cyg_Mqueue::qerr_t err;
char buf[35];
size_t len;
unsigned int prio;
bool b;
 
Cyg_Mqueue the_mq(4, 32, &my_alloc, &my_free, &err );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err,
"Create queue" );
mq = &the_mq;
 
//------------------------------------------------------------------------
 
err = mq->put( "Peter piper picked", sizeof("Peter piper picked"),
5, true );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err, "Simple (put)");
 
t1sem.post();
 
//------------------------------------------------------------------------
 
t0sem.wait();
 
err = mq->get( buf, &len, &prio, true );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == sizeof("a peck of"));
if (b)
b = (prio == 100);
if (b)
b = (0 ==
my_memcmp(buf, "a peck of", sizeof("a peck of"))
);
CYG_TEST_PASS_FAIL( b, "Blocking get");
 
//------------------------------------------------------------------------
 
t0sem.wait();
CYG_TEST_PASS_FAIL( 4 == mq->count(), "mq count" );
err = mq->get( buf, &len, &prio, false );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == sizeof("pickled peppers"));
if (b)
b = (prio == 300);
if (b)
b = (0 ==
my_memcmp(buf, "pickled peppers", sizeof("pickled peppers"))
);
if (b)
b = (3 == mq->count());
CYG_TEST_PASS_FAIL( b, "Prioritized (get 1)");
 
err = mq->get( buf, &len, &prio, false );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == sizeof("."));
if (b)
b = (prio == 250);
if (b)
b = (0 ==
my_memcmp(buf, ".", sizeof("."))
);
if (b)
b = (2 == mq->count());
CYG_TEST_PASS_FAIL( b, "Prioritized (get 2)");
 
err = mq->get( buf, &len, &prio, false );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == 1);
if (b)
b = (prio == 225);
if (b)
b = (0 ==
my_memcmp(buf, "", 1)
);
if (b)
b = (1 == mq->count());
CYG_TEST_PASS_FAIL( b, "Prioritized (get 3)");
 
err = mq->get( buf, &len, &prio, false );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == sizeof("If Peter"));
if (b)
b = (prio == 200);
if (b)
b = (0 ==
my_memcmp(buf, "If Peter", sizeof("If Peter"))
);
if (b)
b = (0 == mq->count());
CYG_TEST_PASS_FAIL( b, "Prioritized (get 4)");
 
//------------------------------------------------------------------------
 
err = mq->get( buf, &len, &prio, false );
 
CYG_TEST_PASS_FAIL( Cyg_Mqueue::WOULDBLOCK == err,
"Non-blocking get of empty queue" );
 
//------------------------------------------------------------------------
Cyg_Mqueue::callback_fn_t oldcallback;
oldcallback = mq->setnotify( &callback, (CYG_ADDRWORD) 42 );
err = mq->put( "If Peter", sizeof("If Peter"),
200, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err,
"Prioritized (put in empty queue)");
CYG_TEST_PASS_FAIL( 42 == calledback, "callback" );
CYG_TEST_PASS_FAIL( NULL == oldcallback, "oldcallback" );
 
err = mq->get( buf, &len, &prio, false );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == sizeof("If Peter"));
if (b)
b = (prio == 200);
if (b)
b = (0 ==
my_memcmp(buf, "If Peter", sizeof("If Peter"))
);
CYG_TEST_PASS_FAIL( b, "Prioritized (get 2)");
 
t1sem.post();
 
err = mq->get( buf, &len, &prio, true );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == 32);
if (b)
b = (42 == calledback);
if (b)
b = (prio == 250);
if (b)
b = (0 ==
my_memcmp(buf, "12345678901234567890123456789012", 32)
);
CYG_TEST_PASS_FAIL( b, "callback (blocked wait)");
 
//------------------------------------------------------------------------
t1sem.post();
t0sem.wait();
 
} // t0()
 
 
//************************************************************************
//************************************************************************
 
 
static void
t1( CYG_ADDRWORD data )
{
Cyg_Mqueue::qerr_t err;
char buf[35];
size_t len;
unsigned int prio;
bool b;
 
//------------------------------------------------------------------------
 
// wait till t0 says we can go
t1sem.wait();
 
err = mq->get( buf, &len, &prio, true );
b = (err == Cyg_Mqueue::OK);
if (b)
b = (len == sizeof("Peter piper picked"));
if (b)
b = (prio == 5);
if (b)
b = (0 ==
my_memcmp(buf, "Peter piper picked", sizeof("Peter piper picked"))
);
 
CYG_TEST_PASS_FAIL( b, "Simple");
 
//------------------------------------------------------------------------
t0sem.post(); // t0 should run straight away
Cyg_Thread::yield(); // but just in case we have a funny sched
 
// by now t0 is blocked in mq->get
 
err = mq->put( "a peck of", sizeof("a peck of"),
100, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err, "Block (put in empty queue)");
 
//------------------------------------------------------------------------
err = mq->put( "If Peter", sizeof("If Peter"),
200, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err,
"Prioritized (put in empty queue)");
 
err = mq->put( "pickled peppers", sizeof("pickled peppers"),
300, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err,
"Prioritized (put in queue w/1)");
 
err = mq->put( ".", sizeof("."), 250, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err,
"Prioritized (put in queue w/2)");
 
err = mq->put( "", 1, 225, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err,
"Prioritized (put in queue w/3)");
 
err = mq->put( "foobar", 6, 1, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::WOULDBLOCK == err,
"Prioritized (full queue)");
 
t0sem.post();
 
//------------------------------------------------------------------------
t1sem.wait();
Cyg_Thread::yield(); // but just in case we have a funny sched
err = mq->put( "12345678901234567890123456789012xxxx", 32,
250, false );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::OK == err,
"callback (put in queue)");
 
//------------------------------------------------------------------------
t1sem.wait();
 
// Create an oversized queue
{
Cyg_Mqueue huge_mq(99999, 99999, &my_alloc, &my_free, &err );
CYG_TEST_PASS_FAIL( Cyg_Mqueue::NOMEM == err,
"Oversized queue rejected" );
// and it now gets destructed - but that shouldn't call free
// to be called
}
 
//------------------------------------------------------------------------
t0sem.post(); // t0 should run straight away
Cyg_Thread::yield(); // but just in case we have a funny sched
 
// check that mq was destroyed when t0 dropped off the end
CYG_TEST_PASS_FAIL( NULL == mq, "queue destroyed correctly" );
CYG_TEST_EXIT("kernel mqueue test 1");
 
} // t1()
 
 
//************************************************************************
//************************************************************************
 
externC void
cyg_user_start(void)
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
CYG_TEST_INIT();
 
CYG_TEST_INFO( "Starting kernel mqueue test 1" );
new_thread( t0, 0);
new_thread( t1, 1);
 
#ifdef CYGIMP_THREAD_PRIORITY
thread[0]->set_priority( 4 );
thread[1]->set_priority( 5 ); // make sure the threads execute as intended
#endif
} // cyg_user_start()
 
//------------------------------------------------------------------------
 
 
/* EOF mqueue1.cxx */
/kthread0.c
0,0 → 1,120
/*=================================================================
//
// kthread0.c
//
// Kernel C API Thread test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-18
// Description: Limited to checking constructors/destructors
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static char stack[STACKSIZE];
 
static cyg_thread_entry_t entry;
 
static void entry( cyg_addrword_t data )
{
}
 
static int *p;
 
#if 0
static cyg_handle_t t0,t1;
static cyg_thread thread0, thread1;
#endif
 
static cyg_handle_t t2;
static cyg_thread thread2;
 
static bool flash( void )
{
#if 0 // no facility to allocate stack exists yet.
cyg_thread_create( entry, 0x111, NULL, 0, &t0, &thread0 );
 
cyg_thread_create( entry, (cyg_addrword_t)&t0, STACKSIZE, 0, &t1, &thread0 );
#endif
 
cyg_thread_create(4, entry, (cyg_addrword_t)p, "kthread0",
(void *)stack, STACKSIZE, &t2, &thread2 );
 
return true;
}
 
void kthread0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Kernel C API Thread 0 OK");
}
 
externC void
cyg_start( void )
{
kthread0_main();
}
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF kthread0.c */
/testaux.h
0,0 → 1,62
#ifndef CYGONCE_KERNEL_TESTS_TESTAUX_H
#define CYGONCE_KERNEL_TESTS_TESTAUX_H
 
/*=================================================================
//
// testaux.h
//
// Auxiliary test header file
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-09
// Description:
// Defines some convenience functions to get us going. In
// particular this file reserves space for NTHREADS threads,
// which can be created by calls to aux_new_thread()
// It also defines a CHECK function.
//
//####DESCRIPTIONEND####
*/
 
#define CHECK(b) CYG_TEST_CHECK(b,#b)
 
#endif /* ifndef CYGONCE_KERNEL_TESTS_TESTAUX_H */
 
/* EOF testaux.h */
/clocktruth.cxx
0,0 → 1,155
//==========================================================================
//
// clocktruth.cxx
//
// Clock Converter test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors: hmt
// Date: 2001-06-05
// Description: Tests the Kernel Real Time Clock for accuracy using a human
//
//####DESCRIPTIONEND####
 
 
// This is for a human to watch to sanity check the clock rate.
// It's easier to see what's happening if you enable this:
#define nRUNFOREVER
 
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/clock.hxx>
#include <cyg/kernel/sema.hxx>
#include <cyg/kernel/thread.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/clock.inl>
#include <cyg/kernel/thread.inl>
 
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
 
#include <cyg/infra/diag.h>
 
#define NTHREADS 1
#include "testaux.hxx"
 
#ifdef RUNFOREVER
#define ENDPOINT 8192
#else
#define ENDPOINT 20
#endif
 
static cyg_alarm_fn alarmfunc;
static void alarmfunc( Cyg_Alarm *alarm, CYG_ADDRWORD data )
{
Cyg_Binary_Semaphore *sp = (Cyg_Binary_Semaphore *)data;
sp->post();
}
 
 
static void entry0( CYG_ADDRWORD data )
{
cyg_uint32 now, then;
int i;
 
Cyg_Clock *rtc = Cyg_Clock::real_time_clock;
 
Cyg_Binary_Semaphore sema;
 
Cyg_Alarm alarm( rtc, &alarmfunc, (CYG_ADDRWORD)&sema );
 
// First, print 100 lines as fast as you can, of distinct ticks.
for ( i = 0; i < 100; i++ ) {
now = rtc->current_value_lo();
then = now;
while ( then == now )
now = rtc->current_value_lo();
 
diag_printf( "INFO<time now %8d>\n", now );
}
 
diag_printf( "INFO<per-second times are: %8d>\n", rtc->current_value_lo() );
for ( i = 0; i < 20; i++ ) {
Cyg_Thread::counted_sleep( 100 );
diag_printf( "INFO<per-second time %2d is %8d>\n",
i, rtc->current_value_lo() );
}
 
alarm.initialize( rtc->current_value() + 100, 100 );
alarm.enable();
for ( i = 0; i < ENDPOINT; i++ ) {
sema.wait();
diag_printf( "INFO<alarm time %2d is %8d>\n",
i, rtc->current_value_lo() );
}
 
CYG_TEST_PASS_FINISH("Clock truth OK");
}
 
void clocktruth_main( void )
{
CYG_TEST_INIT();
new_thread(entry0, (CYG_ADDRWORD)&thread_obj[0]);
Cyg_Scheduler::start();
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
clocktruth_main();
}
 
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( "Kernel real-time clock disabled");
}
 
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
// EOF clocktruth.cxx
/kthread1.c
0,0 → 1,136
/*=================================================================
//
// kthread1.c
//
// Kernel C API Thread test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-18
// Description: Tests some basic thread functions.
//####DESCRIPTIONEND####
*/
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
#include <cyg/hal/hal_arch.h> // for CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#ifdef CYGNUM_HAL_STACK_SIZE_TYPICAL
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
#else
#define STACKSIZE 2000
#endif
 
static char stack[2][STACKSIZE];
 
static cyg_thread thread[2];
 
static cyg_handle_t pt0,pt1;
 
 
static void entry0( cyg_addrword_t data )
{
CHECK( 222 == (int)data );
 
cyg_thread_suspend(pt1);
cyg_thread_resume(pt1);
 
cyg_thread_delay(1);
 
cyg_thread_resume(pt1);
 
cyg_thread_delay(1);
 
CYG_TEST_PASS_FINISH("Kernel C API Thread 1 OK");
}
 
static void entry1( cyg_addrword_t data )
{
cyg_handle_t self;
CHECK( 333 == (int)data );
 
self = cyg_thread_self();
CHECK( self == pt1 );
 
cyg_thread_suspend(pt1);
 
cyg_thread_exit(); // no guarantee this will be called
}
 
void kthread1_main( void )
{
CYG_TEST_INIT();
 
cyg_thread_create(4, entry0, (cyg_addrword_t)222, "kthread1-0",
(void *)stack[0], STACKSIZE, &pt0, &thread[0] );
cyg_thread_create(4, entry1, (cyg_addrword_t)333, "kthread1-1",
(void *)stack[1], STACKSIZE, &pt1, &thread[1] );
 
cyg_thread_resume(pt0);
cyg_thread_resume(pt1);
 
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
kthread1_main();
}
 
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF kthread1.c */
/mbox1.cxx
0,0 → 1,201
//==========================================================================
//
// mbox1.cxx
//
// Mbox test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author: dsm
// Contributors: dsm
// Date: 1998-05-19
// Description: Tests basic mbox functionality.
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx> // Cyg_Thread
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
 
#include <cyg/kernel/mbox.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
#include <cyg/kernel/timer.hxx> // Cyg_Timer
#include <cyg/kernel/clock.inl> // Cyg_Clock
 
#define NTHREADS 2
#include "testaux.hxx"
 
static Cyg_Mbox m0, m1, m2;
 
static volatile cyg_atomic q = 0;
 
#ifndef CYGMTH_MBOX_PUT_CAN_WAIT
#define PUT tryput
#endif
 
static void entry0( CYG_ADDRWORD data )
{
cyg_count8 u,i;
 
CYG_TEST_INFO("Testing put() and tryput() without wakeup");
CYG_TEST_CHECK(!m0.waiting_to_get(), "mbox not initialized properly");
CYG_TEST_CHECK(0==m0.peek(), "mbox not initialized properly");
CYG_TEST_CHECK(NULL==m0.peek_item(), "mbox not initialized properly");
m0.PUT((void *)55);
CYG_TEST_CHECK(1==m0.peek(), "peek() wrong");
CYG_TEST_CHECK(55==(cyg_count8)m0.peek_item(), "peek_item() wrong");
for(u=1; m0.tryput((void*)u); u++) {
CYG_TEST_CHECK(55==(cyg_count8)m0.peek_item(), "peek_item() wrong");
CYG_TEST_CHECK(u+1==m0.peek(), "peek() wrong");
}
CYG_TEST_CHECK(u == CYGNUM_KERNEL_SYNCH_MBOX_QUEUE_SIZE, "mbox not configured size");
 
// m0 now contains ( 55 1 2 .. u-1 )
CYG_TEST_CHECK(u==m0.peek(), "peek() wrong");
CYG_TEST_CHECK(55==(cyg_count8)m0.peek_item(), "peek_item() wrong");
 
CYG_TEST_INFO("Testing get(), tryget()");
i = (cyg_count8)m0.tryget();
CYG_TEST_CHECK( 55 == i, "Got wrong message" );
for(cyg_count8 j=1; j<u;j++) {
CYG_TEST_CHECK( j == (cyg_count8)m0.peek_item(), "peek_item()" );
CYG_TEST_CHECK( m0.peek() == u - j, "peek() wrong" );
i = (cyg_count8)m0.get();
CYG_TEST_CHECK( j == i, "Got wrong message" );
}
CYG_TEST_CHECK( NULL == m0.peek_item(), "peek_item()" );
CYG_TEST_CHECK( 0 == m0.peek(), "peek()");
// m0 now empty
 
CYG_TEST_CHECK(!m0.waiting_to_put(), "waiting_to_put()");
CYG_TEST_CHECK(!m0.waiting_to_get(), "waiting_to_get()");
 
CYG_TEST_INFO("Testing get(), blocking");
CYG_TEST_CHECK(0==q++, "bad synchronization");
m1.PUT((void*)99); // wakes t1
i = (cyg_count8)m0.get(); // sent by t1
CYG_TEST_CHECK(3==i, "Recieved wrong message");
CYG_TEST_CHECK(2==q++, "bad synchronization");
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
CYG_TEST_CHECK(NULL==m0.get(
Cyg_Clock::real_time_clock->current_value() + 10),
"unexpectedly found message");
CYG_TEST_CHECK(3==q++, "bad synchronization");
// Allow t1 to run as this get times out
// t1 must not be waiting...
CYG_TEST_CHECK(m0.waiting_to_get(), "waiting_to_get()");
 
m0.PUT((void*)7); // wake t1 from timed get
#ifdef CYGMTH_MBOX_PUT_CAN_WAIT
q=10;
while(m0.tryput((void*)6)) // fill m0's queue
;
// m0 now contains ( 6 ... 6 )
CYG_TEST_CHECK(10==q++, "bad synchronization");
m1.put((void*)4); // wake t1
CYG_TEST_CHECK(!m0.put((void*)8, 2), "timed put() unexpectedly worked");
CYG_TEST_CHECK(12==q++, "bad synchronization");
// m0 still contains ( 6 ... 6 )
m0.put((void*)9);
CYG_TEST_CHECK(13==q++, "bad synchronization");
#endif
#endif
i=(cyg_count8)m2.get();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry1( CYG_ADDRWORD data )
{
cyg_count8 i;
i = (cyg_count8)m1.get();
CYG_TEST_CHECK(1==q++, "bad synchronization");
m0.PUT((void *)3); // wake t0
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
CYG_TEST_INFO("Testing timed functions");
CYG_TEST_CHECK(7==(cyg_count8)m0.get(
Cyg_Clock::real_time_clock->current_value() + 20), "timed get()");
CYG_TEST_CHECK(4==q++, "bad synchronization");
#ifdef CYGMTH_MBOX_PUT_CAN_WAIT
CYG_TEST_CHECK(4==(cyg_count8)m1.get());
 
CYG_TEST_CHECK(11==q++, "bad synchronization");
thread[0]->delay(20); // allow t0 to reach put on m1
CYG_TEST_CHECK(14==q++, "bad synchronization");
CYG_TEST_CHECK(m0.waiting_to_put(), "waiting_to_put()");
do {
// after first get m0 contains ( 6 .. 6 9 )
i=(cyg_count8)m0.tryget();
} while(6==i);
CYG_TEST_CHECK(9==i,"put gone awry");
#endif
#endif
CYG_TEST_PASS_FINISH("Mbox 1 OK");
}
 
void mbox1_main( void )
{
CYG_TEST_INIT();
 
new_thread(entry0, 0);
new_thread(entry1, 1);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
mbox1_main();
}
 
// EOF mbox1.cxx
/flag0.cxx
0,0 → 1,88
//==========================================================================
//
// flag0.cxx
//
// Flag test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-05-11
// Description: Limited to checking constructors/destructors
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/flag.hxx>
 
#include <cyg/infra/testcase.h>
 
#include "testaux.hxx"
 
static Cyg_Flag f0, f1;
 
 
static bool flash( void )
{
Cyg_Flag f0;
 
Cyg_Flag f1;
 
return true;
}
 
void flag0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Flag 0 OK");
 
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
flag0_main();
}
// EOF flag0.cxx
/flag1.cxx
0,0 → 1,219
//==========================================================================
//
// flag1.cxx
//
// Flag test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author: dsm
// Contributors: dsm
// Date: 1998-05-11
// Description: Tests basic flag functionality.
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx> // Cyg_Thread
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
 
#include <cyg/kernel/flag.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
 
#define NTHREADS 3
#include "testaux.hxx"
 
static Cyg_Flag f0, f1;
#ifdef CYGFUN_KERNEL_THREADS_TIMER
static Cyg_Flag f2;
#endif
 
static volatile cyg_atomic q = 0;
#define FIRST_THREAD_WAIT_TIME 5
#define SECOND_THREAD_WAIT_TIME 10
#define THIRD_THREAD_WAIT_TIME 20
 
static void entry0( CYG_ADDRWORD data )
{
CYG_TEST_INFO("Testing setbits() and maskbits()");
CYG_TEST_CHECK(0==f0.peek(), "flag not initialized properly");
f0.setbits(0x1);
CYG_TEST_CHECK(1==f0.peek(), "setbits");
f0.setbits(0x3);
CYG_TEST_CHECK(3==f0.peek(), "setbits");
f0.maskbits(~0x5);
CYG_TEST_CHECK(2==f0.peek(), "maskbits");
f0.setbits();
CYG_TEST_CHECK(~0u==f0.peek(), "setbits no arg");
f0.maskbits();
CYG_TEST_CHECK(0==f0.peek(), "maskbits no arg");
CYG_TEST_CHECK(0==q++, "bad synchronization");
 
CYG_TEST_INFO("Testing wait()");
f1.setbits(0x4);
CYG_TEST_CHECK(0x4==f1.peek(), "maskbits no arg");
CYG_TEST_CHECK(1==q++, "bad synchronization");
f1.setbits(0x18); // wake t1
f1.wait(0x11, Cyg_Flag::AND | Cyg_Flag::CLR);
CYG_TEST_CHECK(0==f1.peek(), "flag value wrong");
CYG_TEST_CHECK(3==q++, "bad synchronization");
f0.setbits(0x2); // wake t1
f1.wait(0x10, Cyg_Flag::AND );
f0.setbits(0x1); // wake t1
 
f1.wait(0x11, Cyg_Flag::AND | Cyg_Flag::CLR);
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
f2.wait(0x2, Cyg_Flag::OR);
CYG_TEST_CHECK(20==q,"bad synchronization");
f2.wait(0x10, Cyg_Flag::AND,
Cyg_Clock::real_time_clock->current_value()+THIRD_THREAD_WAIT_TIME);
CYG_TEST_CHECK(21==q++,"bad synchronization");
#endif
f0.wait(1, Cyg_Flag::OR);
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry1( CYG_ADDRWORD data )
{
f1.wait(0xc, Cyg_Flag::AND);
CYG_TEST_CHECK(2==q++, "bad synchronization");
CYG_TEST_CHECK(0x1c==f1.peek(), "flag value wrong");
f1.setbits(0x1); // wake t0
f0.wait(0x3, Cyg_Flag::OR);
CYG_TEST_CHECK(4==q++, "bad synchronization");
CYG_TEST_CHECK(2==f0.peek(), "flag value wrong");
f1.setbits(0xf0); // wake t0,t2
f0.wait(0x5, Cyg_Flag::AND | Cyg_Flag::CLR); // wait for t0 & t2
CYG_TEST_CHECK(0==f0.peek(), "flag value wrong");
CYG_TEST_CHECK(0xf0==f1.peek(), "flag value wrong");
CYG_TEST_CHECK(5==q++, "bad synchronization");
f1.maskbits();
CYG_TEST_CHECK(0==f1.peek(), "flag value wrong");
CYG_TEST_INFO("Testing poll()");
f0.setbits(0x55);
CYG_TEST_CHECK(0x55==f0.peek(), "flag value wrong");
CYG_TEST_CHECK(0x55==f0.poll(0x3, Cyg_Flag::OR),"bad poll() return");
CYG_TEST_CHECK(0==f0.poll(0xf, Cyg_Flag::AND),"poll()");
CYG_TEST_CHECK(0==f0.poll(0xa, Cyg_Flag::OR),"poll()");
CYG_TEST_CHECK(0x55==f0.peek(), "flag value wrong");
CYG_TEST_CHECK(0x55==f0.poll(0xf, Cyg_Flag::OR | Cyg_Flag::CLR),"poll");
CYG_TEST_CHECK(0x0==f0.peek(), "flag value wrong");
f0.setbits(0x50);
CYG_TEST_CHECK(0x50==f0.poll(0x10, Cyg_Flag::AND | Cyg_Flag::CLR),"poll");
CYG_TEST_CHECK(0x0==f0.peek(), "flag value wrong");
 
CYG_TEST_INFO("Testing waiting()");
f0.maskbits();
CYG_TEST_CHECK(!f0.waiting(), "waiting()");
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
thread[1]->delay( 10 ); // allow other threads to reach wait on f1
CYG_TEST_CHECK(f1.waiting(), "waiting() not true");
f1.setbits(); // wake one of t0,t2
CYG_TEST_CHECK(f1.waiting(), "waiting() not true");
#else
f1.setbits(0x11); // wake one of t0,t2
#endif
f1.setbits(0x11); // wake other of t0,t2
CYG_TEST_CHECK(!f1.waiting(), "waiting not false");
 
#ifdef CYGFUN_KERNEL_THREADS_TIMER
CYG_TEST_INFO("Testing wait() with timeout");
q=20;
f2.setbits(0x2); // synchronize with t0,t2
CYG_TEST_CHECK(20==q,"bad synchronization");
f2.wait(0x20, Cyg_Flag::AND,
Cyg_Clock::real_time_clock->current_value()+SECOND_THREAD_WAIT_TIME);
CYG_TEST_CHECK(22==q++,"bad synchronization");
#endif
 
CYG_TEST_PASS_FINISH("Flag 1 OK");
}
 
static void entry2( CYG_ADDRWORD data )
{
f1.wait(0x60, Cyg_Flag::OR);
f0.setbits(0x4);
 
f1.wait(0x11, Cyg_Flag::AND | Cyg_Flag::CLR);
#ifdef CYGFUN_KERNEL_THREADS_TIMER
f2.wait(0x2, Cyg_Flag::OR);
CYG_TEST_CHECK(20==q,"bad synchronization");
CYG_TEST_CHECK(0==f2.wait(0x40, Cyg_Flag::AND,
Cyg_Clock::real_time_clock->current_value()+FIRST_THREAD_WAIT_TIME),
"timed wait() wrong");
CYG_TEST_CHECK(20==q++,"bad synchronization");
// Now wake t0 before it times out
f2.setbits(0x10);
#endif
f0.wait(1, Cyg_Flag::OR);
CYG_TEST_FAIL_FINISH("Not reached");
}
 
void flag1_main( void )
{
CYG_TEST_INIT();
 
new_thread(entry0, 0);
new_thread(entry1, 1);
new_thread(entry2, 2);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
flag1_main();
}
 
// EOF flag1.cxx
/intr0.cxx
0,0 → 1,209
//=================================================================
//
// intr0.cxx
//
// Interrupt test 0
//
//=================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm, jlarmour
// Date: 1999-02-16
// Description: Very basic test of interrupt objects
// Options:
// CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
// CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE
// CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/intr.hxx>
#include <cyg/hal/hal_intr.h>
 
#include <cyg/infra/testcase.h>
 
#include "testaux.hxx"
 
static cyg_ISR isr0, isr1;
static cyg_DSR dsr0, dsr1;
 
static char intr0_obj[sizeof(Cyg_Interrupt)];
static char intr1_obj[sizeof(Cyg_Interrupt)];
 
static cyg_uint32 isr0(cyg_vector vector, CYG_ADDRWORD data)
{
CYG_UNUSED_PARAM(CYG_ADDRWORD, data);
 
Cyg_Interrupt::acknowledge_interrupt(vector);
return 0;
}
 
static void dsr0(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data)
{
CYG_UNUSED_PARAM(cyg_vector, vector);
CYG_UNUSED_PARAM(cyg_ucount32, count);
CYG_UNUSED_PARAM(CYG_ADDRWORD, data);
}
 
static cyg_uint32 isr1(cyg_vector vector, CYG_ADDRWORD data)
{
CYG_UNUSED_PARAM(cyg_vector, vector);
CYG_UNUSED_PARAM(CYG_ADDRWORD, data);
return 0;
}
 
static void dsr1(cyg_vector vector, cyg_ucount32 count, CYG_ADDRWORD data)
{
CYG_UNUSED_PARAM(cyg_vector, vector);
CYG_UNUSED_PARAM(cyg_ucount32, count);
CYG_UNUSED_PARAM(CYG_ADDRWORD, data);
}
 
static bool flash( void )
{
Cyg_Interrupt intr0 = Cyg_Interrupt(CYGNUM_HAL_ISR_MIN, 0, (CYG_ADDRWORD)333, isr0, dsr0 );
 
return true;
}
 
/* IMPORTANT: The calling convention for VSRs is target dependent. It is
* unlikely that a plain C or C++ routine would function correctly on any
* particular platform, even if it could correctly access the system
* resources necessary to handle the event that caused it to be called.
* VSRs usually must be written in assembly language.
*
* This is just a test program. The routine vsr0() below is defined simply
* to define an address that will be in executable memory. If an event
* causes this VSR to be called, all bets are off. If it is accidentally
* installed in the vector for the realtime clock, the system will likely
* freeze.
*/
 
static cyg_VSR vsr0;
 
static void vsr0()
{
}
 
void intr0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
 
// Make sure the chosen levels are not already in use.
int in_use;
cyg_vector lvl1 = CYGNUM_HAL_ISR_MIN + (1 % CYGNUM_HAL_ISR_COUNT);
HAL_INTERRUPT_IN_USE( lvl1, in_use );
Cyg_Interrupt* intr0 = NULL;
if (!in_use)
intr0 = new((void *)&intr0_obj[0]) Cyg_Interrupt( lvl1, 1, (CYG_ADDRWORD)777, isr0, dsr0 );
cyg_vector lvl2 = CYGNUM_HAL_ISR_MIN + ( 15 % CYGNUM_HAL_ISR_COUNT);
HAL_INTERRUPT_IN_USE( lvl2, in_use );
Cyg_Interrupt* intr1 = NULL;
if (!in_use && lvl1 != lvl2)
intr1 = new((void *)&intr1_obj[0]) Cyg_Interrupt( lvl2, 1, 888, isr1, dsr1 );
 
// Check these functions at least exist
Cyg_Interrupt::disable_interrupts();
Cyg_Interrupt::enable_interrupts();
 
if (intr0)
intr0->attach();
if (intr1)
intr1->attach();
if (intr0)
intr0->detach();
if (intr1)
intr1->detach();
 
// If this attaching interrupt replaces the previous interrupt
// instead of adding to it we could be in a big mess if the
// vector is being used by something important.
cyg_vector v = (CYGNUM_HAL_VSR_MIN + 11) % CYGNUM_HAL_VSR_COUNT;
cyg_VSR *old_vsr, *new_vsr;
Cyg_Interrupt::set_vsr( v, vsr0, &old_vsr );
Cyg_Interrupt::get_vsr( v, &new_vsr );
CHECK( vsr0 == new_vsr );
 
new_vsr = NULL;
Cyg_Interrupt::set_vsr( v, old_vsr, &new_vsr );
CHECK( new_vsr == vsr0 );
 
Cyg_Interrupt::set_vsr( v, new_vsr );
new_vsr = NULL;
Cyg_Interrupt::get_vsr( v, &new_vsr );
CHECK( vsr0 == new_vsr );
 
Cyg_Interrupt::set_vsr( v, old_vsr );
CHECK( vsr0 == new_vsr );
new_vsr = NULL;
Cyg_Interrupt::get_vsr( v, &new_vsr );
CHECK( old_vsr == new_vsr );
CHECK( NULL != vsr0 );
 
cyg_vector v1;
#ifdef CYGPKG_HAL_MIPS_TX39
// This can be removed when PR 17831 is fixed
if ( cyg_test_is_simulator )
v1 = 12 % CYGNUM_HAL_ISR_COUNT;
else /* NOTE TRAILING ELSE... */
#endif
v1 = CYGNUM_HAL_ISR_MIN + (6 % CYGNUM_HAL_ISR_COUNT);
 
Cyg_Interrupt::mask_interrupt(v1);
Cyg_Interrupt::unmask_interrupt(v1);
 
Cyg_Interrupt::configure_interrupt(v1, true, true);
 
CYG_TEST_PASS_FINISH("Intr 0 OK");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
intr0_main();
}
// EOF intr0.cxx
/sync2.cxx
0,0 → 1,201
//==========================================================================
//
// sync2.cxx
//
// Sync test 2 -- test of different locking mechanisms
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-18
// Description:
// Creates some threads and tests the various synchronization
// mechanisms. Four threads are created t0..t3. t0 and t3 grab a
// mutex and check they have exclusive access to shared variable.
// t0,t1,t2 post each other in a loop with a semaphore so that
// only one is running at any time. t1,t2,t3 do a similar thing
// with counting semaphores, except that there are two active
// threads.
// Omissions:
// Doesn't test condition variables
//
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
#define NTHREADS 4
 
#include "testaux.hxx"
 
static Cyg_Mutex m0;
static Cyg_Binary_Semaphore s0, s1, s2(1);
static Cyg_Counting_Semaphore cs0, cs1, cs2, cs3;
 
static const cyg_ucount16 n = 1000;
static cyg_ucount8 m0d=99, sd=2, cd0=99, cd1=99;
 
static void entry0( CYG_ADDRWORD data )
{
for(cyg_ucount16 i=0; i<n; i++) {
s2.wait();
CHECK( 2 == sd );
sd = 0;
m0.lock(); {
m0d = 0;
s0.post();
CHECK( 0 == m0d );
} m0.unlock();
}
// wait for 3 explicit posts to indicate threads have stopped.
for(cyg_ucount8 i=0; i<3; i++)
cs3.wait();
 
CHECK( ! s0.posted() );
CHECK( ! s1.posted() );
CHECK( s2.posted() );
 
CHECK( 0 == cs0.peek() );
CHECK( 0 == cs1.peek() );
CHECK( 0 == cs2.peek() );
CHECK( 0 == cs3.peek() );
 
CHECK( 0 == cd0 );
CHECK( 0 == cd1 );
CYG_TEST_PASS_FINISH("Sync 2 OK");
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry1( CYG_ADDRWORD data )
{
for(cyg_ucount16 i=0; i<n; i++) {
s0.wait();
CHECK( 0 == sd );
sd = 1;
cd0 = 1;
cs1.post();
cd1 = 1;
cs1.post();
s1.post();
cs0.wait();
CHECK( 0 == cd0 );
cs0.wait();
CHECK( 0 == cd1 );
}
cs3.post();
s0.wait();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry2( CYG_ADDRWORD data )
{
for(cyg_ucount16 i=0; i<n; i++) {
s1.wait();
CHECK( 1 == sd );
sd = 2;
cs1.wait();
CHECK( 1 == cd0 );
cd0 = 2;
cs2.post();
s2.post();
cs1.wait();
CHECK( 1 == cd1 );
cd1 = 2;
cs2.post();
}
cs3.post();
s1.wait();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
static void entry3( CYG_ADDRWORD data )
{
for(cyg_ucount16 i=0; i < n*2; i++) {
cs2.wait();
CHECK( 2 == cd0 || 2 == cd1 );
m0.lock(); {
m0d = 3;
if( 2 == cd0 )
cd0 = 0;
else {
CHECK( 2 == cd1 );
cd1 = 0;
}
cs0.post();
CHECK( 3 == m0d );
} m0.unlock();
}
cs3.post();
cs1.wait();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
 
void sync2_main(void)
{
CYG_TEST_INIT();
 
new_thread(entry0, 0);
new_thread(entry1, 1);
new_thread(entry2, 2);
new_thread(entry3, 3);
 
Cyg_Scheduler::start();
 
CYG_TEST_PASS_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
sync2_main();
}
 
// EOF sync2.cxx
/timeslice.c
0,0 → 1,281
//==========================================================================
//
// timeslice.c
//
// Timeslice test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 2001-06-18
// Description: A basic timeslicing test.
//
//####DESCRIPTIONEND####
//==========================================================================
 
#include <pkgconf/kernel.h>
#include <pkgconf/hal.h>
 
#include <cyg/hal/hal_arch.h>
 
#include <cyg/kernel/smp.hxx>
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
#include <cyg/infra/diag.h>
 
//==========================================================================
 
#if defined(CYGSEM_KERNEL_SCHED_TIMESLICE) && \
defined(CYGFUN_KERNEL_API_C) && \
defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \
defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \
!defined(CYGDBG_INFRA_DIAG_USE_DEVICE) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
 
//==========================================================================
 
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL*5
 
#define NTHREADS_MAX (CYGNUM_KERNEL_CPU_MAX*6)
 
static int ncpus = CYGNUM_KERNEL_CPU_MAX;
 
static char test_stack[STACK_SIZE];
static cyg_thread test_thread;
static cyg_handle_t main_thread;
 
static char stacks[NTHREADS_MAX][STACK_SIZE];
static cyg_thread test_threads[NTHREADS_MAX];
static cyg_handle_t threads[NTHREADS_MAX];
 
static volatile int failed = false;
 
static volatile cyg_uint32 slicerun[NTHREADS_MAX][CYGNUM_KERNEL_CPU_MAX];
 
//==========================================================================
 
void
test_thread_timeslice(CYG_ADDRESS id)
{
for(;;)
slicerun[id][CYG_KERNEL_CPU_THIS()]++;
}
 
//==========================================================================
 
void run_test_timeslice(int nthread)
{
int i,j;
cyg_uint32 cpu_total[CYGNUM_KERNEL_CPU_MAX];
cyg_uint32 cpu_threads[CYGNUM_KERNEL_CPU_MAX];
cyg_uint32 thread_total[NTHREADS_MAX];
 
CYG_TEST_INFO( "Timeslice Test: Check timeslicing works");
// Init flags.
for (i = 0; i < nthread; i++)
for( j = 0; j < ncpus; j++ )
slicerun[i][j] = 0;
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
 
for (i = 0; i < nthread; i++) {
cyg_thread_create(10, // Priority - just a number
test_thread_timeslice, // entry
i, // index
"test_thread", // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume( threads[i]);
}
 
// Just wait a while, until the threads have all run for a bit.
cyg_thread_delay( CYGNUM_KERNEL_SCHED_TIMESLICE_TICKS*100 );
 
// Suspend all the threads
for (i = 0; i < nthread; i++) {
cyg_thread_suspend(threads[i]);
}
 
// And check that a thread ran on each CPU, and that each thread
// ran.
diag_printf(" Thread ");
for( j = 0; j < ncpus; j++ )
{
cpu_total[j] = 0;
cpu_threads[j] = 0;
// " %11d" __123456789ab"
diag_printf(" CPU %2d",j);
}
// " %11d" __123456789ab"
diag_printf(" Total\n");
for (i = 0; i < nthread; i++)
{
thread_total[i] = 0;
diag_printf(" %2d ",i);
for( j = 0; j < ncpus; j++ )
{
thread_total[i] += slicerun[i][j];
cpu_total[j] += slicerun[i][j];
if( slicerun[i][j] > 0 )
cpu_threads[j]++;
diag_printf(" %11d",slicerun[i][j]);
}
diag_printf(" %11d\n",thread_total[i]);
if( thread_total[i] == 0 )
failed++;
}
diag_printf(" Total ");
for( j = 0; j < ncpus; j++ )
diag_printf(" %11d",cpu_total[j]);
diag_printf("\n");
diag_printf("Threads ");
for( j = 0; j < ncpus; j++ )
{
diag_printf(" %11d",cpu_threads[j]);
if( cpu_threads[j] < 2 )
failed++;
}
diag_printf("\n");
 
// Delete all the threads
for (i = 0; i < nthread; i++) {
cyg_thread_delete(threads[i]);
}
 
CYG_TEST_INFO( "Timeslice Test: done");
}
 
 
//==========================================================================
 
void
run_tests(CYG_ADDRESS id)
{
int step;
int nthread;
// Try to run about 10 times in total, with varying numbers of threads
// from only one extra up to the full set:
 
step = (NTHREADS_MAX - (1 + CYG_KERNEL_CPU_COUNT()))/10;
if( step == 0 ) step = 1;
for( nthread = 1 + CYG_KERNEL_CPU_COUNT() ;
nthread <= NTHREADS_MAX ;
nthread += step )
run_test_timeslice(nthread);
 
if( failed )
CYG_TEST_FAIL_FINISH("Timeslice test failed\n");
CYG_TEST_PASS_FINISH("Timeslice test OK");
}
 
//==========================================================================
 
void timeslice_main( void )
{
CYG_TEST_INIT();
 
// Work out how many CPUs we actually have.
ncpus = CYG_KERNEL_CPU_COUNT();
 
cyg_thread_create(0, // Priority - just a number
run_tests, // entry
0, // index
"run_tests", // Name
test_stack, // Stack
STACK_SIZE, // Size
&main_thread, // Handle
&test_thread // Thread data structure
);
cyg_thread_resume( main_thread);
cyg_scheduler_start();
}
 
//==========================================================================
 
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
timeslice_main();
}
 
//==========================================================================
 
#else // CYGSEM_KERNEL_SCHED_TIMESLICE etc
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("SMP test requires:\n"
"CYGSEM_KERNEL_SCHED_TIMESLICE &&\n"
"CYGPKG_KERNEL_SMP_SUPPORT &&\n"
"CYGFUN_KERNEL_API_C && \n"
"CYGSEM_KERNEL_SCHED_MLQUEUE &&\n"
"CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
"!CYGPKG_HAL_I386_LINUX &&\n"
"!CYGDBG_INFRA_DIAG_USE_DEVICE &&\n"
"(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n");
}
 
#endif // CYGSEM_KERNEL_SCHED_TIMESLICE etc.
 
//==========================================================================
// EOF timeslice.c
/smp.cxx
0,0 → 1,473
//==========================================================================
//
// smp.cxx
//
// SMP tests
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 2001-06-18
// Description: Some basic SMP tests.
//
//####DESCRIPTIONEND####
//==========================================================================
 
#include <pkgconf/kernel.h>
#include <pkgconf/hal.h>
 
#if 1
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/sema.hxx>
#include <cyg/kernel/sched.inl>
#include <cyg/kernel/clock.hxx>
#include <cyg/kernel/clock.inl>
#endif
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
#include <cyg/infra/diag.h>
 
//==========================================================================
 
#if defined(CYGPKG_KERNEL_SMP_SUPPORT) && \
defined(CYGFUN_KERNEL_API_C) && \
defined(CYGSEM_KERNEL_SCHED_MLQUEUE) && \
defined(CYGVAR_KERNEL_COUNTERS_CLOCK) && \
!defined(CYGPKG_HAL_I386_LINUX) && \
!defined(CYGDBG_INFRA_DIAG_USE_DEVICE) && \
(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)
 
//==========================================================================
 
#define NTHREADS 1
#include "testaux.hxx"
 
#define STACK_SIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#define NTHREADS_MAX (CYGNUM_KERNEL_CPU_MAX*3)
 
static int ncpus = CYGNUM_KERNEL_CPU_MAX;
static int nthread = NTHREADS_MAX;
 
static char stacks[NTHREADS_MAX][STACK_SIZE];
static cyg_thread test_threads[NTHREADS_MAX];
static cyg_handle_t threads[NTHREADS_MAX];
 
static volatile cyg_uint32 cpu_run[CYGNUM_KERNEL_CPU_MAX];
static volatile int failed = false;
static volatile cyg_uint32 cpu_thread[CYGNUM_KERNEL_CPU_MAX];
 
static volatile cyg_uint32 slicerun[NTHREADS_MAX][CYGNUM_KERNEL_CPU_MAX];
 
 
static cyg_mutex_t mx;
 
 
//==========================================================================
// Compute a name for a thread
char *
thread_name(char *basename, int indx) {
return "<<NULL>>"; // Not currently used
}
 
//==========================================================================
 
void
test_thread_cpu(CYG_ADDRESS id)
{
for(;;)
cpu_run[CYG_KERNEL_CPU_THIS()] = true;
}
 
//==========================================================================
// First test: just run as many threads as CPUs and check that we
// get to run on each CPU.
 
void run_smp_test_cpus()
{
int i;
 
CYG_TEST_INFO( "CPU Test: Check CPUs functional");
// Init flags.
for (i = 0; i < ncpus; i++)
cpu_run[i] = false;
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
 
for (i = 0; i < ncpus; i++) {
cyg_thread_create(10, // Priority - just a number
test_thread_cpu, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume( threads[i]);
}
 
// Just wait a while, until the threads have all run for a bit.
cyg_thread_delay( 10 );
 
// Delete all the threads
for (i = 0; i < ncpus; i++) {
cyg_thread_delete(threads[i]);
}
 
// And check that a thread ran on each CPU
for (i = 0; i < ncpus; i++) {
// CYG_TEST_CHECK( cpu_run[i], "CPU didn't run");
if( !cpu_run[i] )
{
CYG_TEST_INFO( "CPU didn't run" );
failed++;
}
}
 
CYG_TEST_INFO( "CPU Test: done");
}
 
 
//==========================================================================
 
void
test_thread_pri(CYG_ADDRESS id)
{
for(;;)
{
cpu_thread[CYG_KERNEL_CPU_THIS()] = id;
}
}
 
//==========================================================================
// Second test: Run a thread on each CPU and then by manipulating the
// priorities, get the current thread to migrate to each CPU in turn.
 
 
void run_smp_test_pri()
{
int i;
 
CYG_TEST_INFO( "Pri Test: Check set_priority functionality");
// Init flags.
for (i = 0; i < ncpus; i++)
cpu_run[i] = false;
 
// Set my priority higher than any I plan to creat
cyg_thread_set_priority(cyg_thread_self(), 2);
 
for (i = 0; i < ncpus; i++) {
cyg_thread_create(10, // Priority - just a number
test_thread_pri, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume( threads[i]);
}
 
cyg_thread_delay( 2 );
cyg_handle_t cthread = threads[0];
cyg_thread_set_priority(cthread, 25);
// Just wait a while, until the threads have all run for a bit.
cyg_thread_delay( 2 );
 
for (i = 0; i < ncpus*500; i++)
{
HAL_SMP_CPU_TYPE cpu = i % CYG_KERNEL_CPU_COUNT();
if( cpu != CYG_KERNEL_CPU_THIS() )
{
// At this point we have the current thread running on a
// CPU at priority 2, ncpus-1 threads running at priority
// 10 and the last thread (cthread) in the run queue at
// priority 25.
// Pick a thread on a different CPU
cyg_handle_t dthread;
 
do
{
dthread = threads[cpu_thread[cpu]];
} while( dthread == cthread );
 
// Change the priority of the victim thread to 20. It is
// still higher priority than cthread so it will continue
// running.
 
cyg_thread_set_priority(dthread, 20);
 
// Now change our priority to 15. We are still higher
// priority that cthread so we will still run.
cyg_thread_set_priority(cyg_thread_self(), 15);
 
// Finally change the priority of cthread to 10. This will
// cause it to preempt us on the current CPU. In turn we
// will preempt dthread on its CPU.
 
// NOTE: This relies somewhat on the SMP scheduler doing
// what we expect here. Specifically, that it will preempt
// the current thread with cthread locally. A more
// sophisticated scheduler might decide that the most
// efficient thing to do is to preempt dthread with
// cthread remotely, leaving the current thread where it
// is. If we ever bother to implement this, then this test
// will need to change.
cyg_thread_set_priority(cthread, 10);
 
// Spin here a while until the scheduler sorts itself out.
for( int j = 0; j < 100000; j++ );
 
// Indicate that we have run on this CPU
cpu_run[CYG_KERNEL_CPU_THIS()]++;
 
// Restore our priority to 2 and depress dthread to 25 and
// make it the new cthread.
cyg_thread_set_priority(cyg_thread_self(), 2);
cyg_thread_set_priority(dthread, 25);
cthread = dthread;
}
}
 
// Delete all the threads
for (i = 0; i < ncpus; i++) {
cyg_thread_delete(threads[i]);
}
 
// And check that a thread ran on each CPU
for (i = 0; i < ncpus; i++) {
// CYG_TEST_CHECK( cpu_run[i], "CPU didn't run");
if( !cpu_run[i] )
{
CYG_TEST_INFO( "CPU didn't run" );
failed++;
}
}
 
CYG_TEST_INFO( "PRI Test: done");
}
 
//==========================================================================
 
void
test_thread_timeslice(CYG_ADDRESS id)
{
for(;;)
slicerun[id][CYG_KERNEL_CPU_THIS()]++;
}
 
//==========================================================================
// First test: just run as many threads as CPUs and check that we
// get to run on each CPU.
 
void run_smp_test_timeslice()
{
int i;
 
CYG_TEST_INFO( "Timeslice Test: Check timeslicing works");
// Init flags.
for (i = 0; i < nthread; i++)
for( int j = 0; j < ncpus; j++ )
slicerun[i][j] = 0;
// Set my priority higher than any I plan to create
cyg_thread_set_priority(cyg_thread_self(), 2);
 
for (i = 0; i < nthread; i++) {
cyg_thread_create(10, // Priority - just a number
test_thread_timeslice, // entry
i, // index
thread_name("thread", i), // Name
&stacks[i][0], // Stack
STACK_SIZE, // Size
&threads[i], // Handle
&test_threads[i] // Thread data structure
);
cyg_thread_resume( threads[i]);
}
 
// Just wait a while, until the threads have all run for a bit.
cyg_thread_delay( 200 );
 
// Delete all the threads
for (i = 0; i < nthread; i++) {
cyg_thread_suspend(threads[i]);
}
 
// And check that a thread ran on each CPU
 
cyg_uint32 cpu_total[ncpus];
cyg_uint32 cpu_threads[ncpus];
cyg_uint32 thread_total[nthread];
diag_printf(" Thread ");
for( int j = 0; j < ncpus; j++ )
{
cpu_total[j] = 0;
cpu_threads[j] = 0;
diag_printf(" CPU %2d",j);
}
diag_printf(" Total\n");
for (i = 0; i < nthread; i++)
{
thread_total[i] = 0;
diag_printf(" %2d ",i);
for( int j = 0; j < ncpus; j++ )
{
thread_total[i] += slicerun[i][j];
cpu_total[j] += slicerun[i][j];
if( slicerun[i][j] > 0 )
cpu_threads[j]++;
diag_printf(" %8d",slicerun[i][j]);
}
diag_printf("%8d\n",thread_total[i]);
}
diag_printf(" Total ");
for( int j = 0; j < ncpus; j++ )
diag_printf(" %8d",cpu_total[j]);
diag_printf("\n");
diag_printf("Threads ");
for( int j = 0; j < ncpus; j++ )
{
diag_printf(" %8d",cpu_threads[j]);
if( cpu_threads[j] < 2 )
failed++;
}
diag_printf("\n");
 
// Delete all the threads
for (i = 0; i < nthread; i++) {
cyg_thread_delete(threads[i]);
}
 
CYG_TEST_INFO( "Timeslice Test: done");
}
 
 
//==========================================================================
 
void
run_smp_tests(CYG_ADDRESS id)
{
cyg_mutex_init( &mx );
 
for( int i = 0; i < 100; i++ )
{
run_smp_test_cpus();
run_smp_test_pri();
run_smp_test_timeslice();
}
 
if( failed )
CYG_TEST_FAIL_FINISH("SMP tests failed\n");
CYG_TEST_PASS_FINISH("SMP tests OK");
}
 
//==========================================================================
 
void smp_main( void )
{
CYG_TEST_INIT();
 
// Work out how many CPUs we actually have.
ncpus = CYG_KERNEL_CPU_COUNT();
 
new_thread(run_smp_tests, 0);
 
cyg_scheduler_start();
}
 
//==========================================================================
 
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
externC void
cyg_hal_invoke_constructors();
#endif
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
smp_main();
}
 
//==========================================================================
 
#else // CYGPKG_KERNEL_SMP_SUPPORT etc.
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("SMP test requires:\n"
"CYGPKG_KERNEL_SMP_SUPPORT &&\n"
"CYGFUN_KERNEL_API_C && \n"
"CYGSEM_KERNEL_SCHED_MLQUEUE &&\n"
"CYGVAR_KERNEL_COUNTERS_CLOCK &&\n"
"!CYGPKG_HAL_I386_LINUX &&\n"
"!CYGDBG_INFRA_DIAG_USE_DEVICE &&\n"
"(CYGNUM_KERNEL_SCHED_PRIORITIES > 12)\n");
}
#endif // CYGPKG_KERNEL_SMP_SUPPORT etc.
 
//==========================================================================
// EOF tm_basic.cxx
/ksem0.c
0,0 → 1,100
/*=================================================================
//
// ksem0.c
//
// Kernel C API Semaphore test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-20
// Description: Limited to checking initialisation/destruction
//####DESCRIPTIONEND####
*/
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
cyg_sem_t s0, s1, s2;
 
static bool flash( void )
{
cyg_semaphore_init( &s0, 0 );
cyg_semaphore_init( &s1, 1 );
cyg_semaphore_init( &s2, 17 );
 
cyg_semaphore_destroy( &s0 );
cyg_semaphore_destroy( &s1 );
cyg_semaphore_destroy( &s2 );
 
return true;
}
 
void ksem0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Kernel C API Semaphore 0 OK");
}
 
externC void
cyg_start( void )
{
ksem0_main();
}
 
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF ksem0.c */
/sync3.cxx
0,0 → 1,231
//==========================================================================
//
// sync3.cxx
//
// Sync test 3 -- tests priorities and priority inheritance
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-18
// Description:
// Creates mutexes and threads to set up starvation condition.
// Checks simple priority inheritance cures this.
//
// The starvation condition is caused by the highest priority
// thread, t0 waiting on a mutex which is never released because
// it is held by t2. t2 never releases it because t1 will be
// running at a priority level higher than t2 (but lower than t0).
//
// With priority inheritance enabled, t2 will inherit its priority
// from t0 when t0 tries to grab the mutex.
//
// Options:
// CYGIMP_THREAD_PRIORITY
// CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
// CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_SIMPLE
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx>
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx>
#include <cyg/kernel/mutex.hxx>
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
#if defined(CYGIMP_THREAD_PRIORITY) && \
!defined(CYGPKG_KERNEL_SMP_SUPPORT)
 
// ------------------------------------------------------------------------
// Manufacture a simpler feature test macro for priority inheritance than
// the configuration gives us. We have priority inheritance if it is configured
// as the only protocol, or if it is the default protocol for dynamic protocol
// choice.
// FIXME: If we have dynamic protocol choice, we can also set priority inheritance
// as the protocol to be used on the mutexes we are interested in. At present we
// do not do this.
 
#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_INHERIT
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DYNAMIC
# ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INVERSION_PROTOCOL_DEFAULT_INHERIT
# define PRIORITY_INHERITANCE
# else
# undef PRIORITY_INHERITANCE
# endif
# else
# define PRIORITY_INHERITANCE
# endif
#else
# undef PRIORITY_INHERITANCE
#endif
 
// ------------------------------------------------------------------------
 
#define NTHREADS 3
 
#include "testaux.hxx"
 
static Cyg_Mutex m0;
static Cyg_Binary_Semaphore s0, s1, s2;
 
static cyg_ucount8 m0d = 9;
 
static void check_priorities_normal()
{
CHECK( 5 == thread[0]->get_priority());
CHECK( 6 == thread[1]->get_priority());
CHECK( 7 == thread[2]->get_priority());
}
 
static void check_priorities_inherited()
{
CHECK( 5 == thread[0]->get_priority());
CHECK( 6 == thread[1]->get_priority());
#ifdef PRIORITY_INHERITANCE
CHECK( 5 == thread[2]->get_current_priority());
#endif
CHECK( 7 == thread[2]->get_priority());
 
}
 
static void entry0( CYG_ADDRWORD data )
{
s0.wait(); // wait until t2 has gained m0.lock
check_priorities_normal();
m0.lock(); {
check_priorities_normal();
CHECK( 2 == m0d );
m0d = 0;
} m0.unlock();
check_priorities_normal();
#ifdef PRIORITY_INHERITANCE
CYG_TEST_PASS_FINISH("Sync 3 OK -- priority inheritance worked");
#else
CYG_TEST_FAIL_FINISH("Sync 3: thread not starved");
#endif
// NOT REACHED
}
 
static void entry1( CYG_ADDRWORD data )
{
s1.wait();
// The delay below will allow testing of the priority inheritance
// mechanism when scheduler does not guarantee to schedule threads
// in strict priority order.
for ( volatile cyg_ucount32 i=0; i < 100000; i++ )
; // math is hard
 
#ifdef PRIORITY_INHERITANCE
// thread0 should have stopped by this point
CYG_TEST_FAIL_FINISH("Sync 3: priority inheritance mechanism failed");
#else
// With strict priority scheduling and no priority inheritance
// this is expected to happen.
CYG_TEST_PASS_FINISH("Sync 3 OK");
#endif
CYG_TEST_FAIL_FINISH("Not reached");
}
 
void entry2( CYG_ADDRWORD data )
{
m0.lock(); {
CHECK( 9 == m0d );
check_priorities_normal();
s0.post(); // Now I have lock on m0, wake t0 then t1
check_priorities_inherited();
s1.post();
check_priorities_inherited();
m0d = 2;
} m0.unlock();
check_priorities_normal();
m0.lock(); {
check_priorities_normal();
CHECK( 0 == m0d );
m0d = 21;
s2.wait(); // never posted
} m0.unlock();
}
 
 
 
void sync3_main(void)
{
CYG_TEST_INIT();
 
new_thread( entry0, 0);
new_thread( entry1, 1);
new_thread( entry2, 2);
 
thread[0]->set_priority(5);
thread[1]->set_priority(6);
thread[2]->set_priority(7);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
sync3_main();
}
 
#else // defined(CYGIMP_THREAD_PRIORITY) etc
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_PASS_FINISH("Sync3 test requires:\n"
"defined(CYGIMP_THREAD_PRIORITY) &&\n"
"!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
 
}
 
#endif // defined(CYGIMP_THREAD_PRIORITY) etc
 
// EOF sync3.cxx
/ksem1.c
0,0 → 1,169
/*=================================================================
//
// ksem1.c
//
// C API semaphore test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-20
// Description: Tests basic semaphore functionality.
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
#define NTHREADS 2
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
 
static cyg_sem_t s0, s1, s2;
 
static volatile cyg_ucount8 q = 0;
 
static void entry0( cyg_addrword_t data )
{
cyg_ucount32 val;
 
cyg_semaphore_wait(&s0);
CHECK( 1 == q++ );
cyg_semaphore_post(&s1);
cyg_semaphore_wait(&s0);
CHECK( 3 == q++ );
cyg_semaphore_peek(&s0, &val);
CHECK( 0 == val);
CHECK( ! cyg_semaphore_trywait(&s0) );
cyg_semaphore_post(&s0);
CHECK( 4 == q++ );
cyg_semaphore_peek(&s0, &val);
CHECK( 1 == val);
cyg_semaphore_post(&s0);
cyg_semaphore_peek(&s0, &val);
CHECK( 2 == val);
cyg_semaphore_post(&s1);
cyg_semaphore_peek(&s2, &val);
CHECK( 0 == val);
cyg_semaphore_wait(&s2);
CHECK( 6 == q++ );
CYG_TEST_PASS_FINISH("Kernel C API Semaphore 1 OK");
}
 
static void entry1( cyg_addrword_t data )
{
cyg_count32 val;
 
cyg_semaphore_peek(&s1, &val);
CHECK( 2 == val);
cyg_semaphore_wait(&s1);
cyg_semaphore_peek(&s1, &val);
CHECK( 1 == val);
cyg_semaphore_wait(&s1);
CHECK( 0 == q++ );
cyg_semaphore_peek(&s0, &val);
CHECK( 0 == val);
cyg_semaphore_post(&s0);
cyg_semaphore_wait(&s1);
CHECK( 2 == q++ );
cyg_semaphore_post(&s0);
cyg_semaphore_wait(&s1);
CHECK( 5 == q++ );
cyg_semaphore_peek(&s0, &val);
CHECK( 2 == val);
CHECK( cyg_semaphore_trywait(&s0) );
cyg_semaphore_peek(&s0, &val);
CHECK( 1 == val);
CHECK( cyg_semaphore_trywait(&s0) );
cyg_semaphore_peek(&s0, &val);
CHECK( 0 == val);
cyg_semaphore_post(&s2);
cyg_semaphore_wait(&s0);
CYG_TEST_FAIL_FINISH("Not reached");
}
 
void ksem1_main( void )
{
CYG_TEST_INIT();
 
cyg_semaphore_init( &s0, 0);
cyg_semaphore_init( &s1, 2);
cyg_semaphore_init( &s2, 0);
 
cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "ksem1-0",
(void *)stack[0], STACKSIZE,&thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_thread_create(4, entry1 , (cyg_addrword_t)1, "ksem1-1",
(void *)stack[1], STACKSIZE, &thread[1], &thread_obj[1]);
cyg_thread_resume(thread[1]);
 
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
ksem1_main();
}
 
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF ksem1.c */
/clockcnv.cxx
0,0 → 1,287
//==========================================================================
//
// clockcnv.cxx
//
// Clock Converter test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): hmt
// Contributors: hmt
// Date: 2000-01-24
// Description: Tests the Kernel Real Time Clock Converter subsystem
//
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/clock.hxx>
#include <cyg/kernel/thread.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/clock.inl>
#include <cyg/kernel/thread.inl>
 
#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK
 
#include <cyg/infra/diag.h>
 
static void null_printf(const char *, ...)
{ /* nothing */ }
 
#define PRINTF0 diag_printf
#define nPRINTF0 null_printf
 
#define nPRINTF1 diag_printf
#define PRINTF1 null_printf
 
#define nPRINTF2 diag_printf
#define PRINTF2 null_printf
 
 
#define NTHREADS 1
#include "testaux.hxx"
 
static struct { cyg_uint32 ns; double scale; } ns_tickers[] = {
{ 70000000, 7.0 }, // 7cS
{ 50000000, 5.0 }, // 5cS
{ 45000000, 4.5 }, // 4.5cS
{ 30000000, 3.0 }, // 3cS
{ 20000000, 2.0 }, // 2cS
{ 10000000, 1.0 }, // 1cS - no change
{ 5000000, 0.5 }, // 1/2 a cS
{ 4900000, 0.49 }, // a bit below
{ 3333333, 0.3333333 }, // 1/3 cS
{ 1250000, 0.125 }, // 800Hz
{ 1000000, 0.1 }, // 1000Hz
{ 909090, 0.0909090 }, // 1100Hz
{ 490000, 0.049 }, // 490uS
{ 333333, 0.0333333 }, // 1/30 cS, 1/3mS
{ 49000, 0.0049 }, // 49uS
{ 33333, 0.0033333 }, // 1/30 mS
{ 4900, 0.00049 }, // 4.9uS
// now some outlandish ones
{ 170, 0.000017 }, // 170nS
{ 11, 0.0000011 }, // 11nS
{ 1000000000u, 100.0 }, // one second
{ 1234567777u, 123.4567777 }, // 1.234... seconds
{ 4294967291u, 429.4967291 }, // 4.3 seconds, nearly maxint.
// now some which are prime in the nS per tick field
{ 909091, 0.0909091 }, // also 1100Hz - but 909091 is a prime!
// and some eye-pleasing primes from the www - if they're not actually
// prime, don't blame me. http://www.rsok.com/~jrm/printprimes.html
{ 1000003, 0.1000003 },
{ 1477771, 0.1477771 },
{ 2000003, 0.2000003 },
{ 2382001, 0.2382001 },
{ 3333133, 0.3333133 },
{ 3999971, 0.3999971 },
{ 5555591, 0.5555591 },
{ 6013919, 0.6013919 },
// That's enough
};
 
static void entry0( CYG_ADDRWORD data )
{
// First just try it with the clock as default:
Cyg_Clock *rtc = Cyg_Clock::real_time_clock;
 
Cyg_Clock::converter cv, rcv;
Cyg_Clock::cyg_resolution res;
 
unsigned int counter = 0;
unsigned int skipped = 0;
 
unsigned int i;
for ( i = 0; i < sizeof( ns_tickers )/sizeof( ns_tickers[0] ); i++ ) {
 
unsigned int lcounter = 0;
unsigned int lskipped = 0;
 
rtc->get_other_to_clock_converter( ns_tickers[i].ns, &cv );
rtc->get_clock_to_other_converter( ns_tickers[i].ns, &rcv );
PRINTF1( "ns per tick: %d\n", ns_tickers[i].ns );
PRINTF1( " converter: * %d / %d * %d / %d\n",
(int)cv.mul1, (int)cv.div1, (int)cv.mul2,(int) cv.div2 );
PRINTF1( " reverser: * %d / %d * %d / %d\n",
(int)rcv.mul1, (int)rcv.div1, (int)rcv.mul2, (int)rcv.div2 );
 
double d = 1.0;
d *= (double)cv.mul1;
d /= (double)cv.div1;
d *= (double)cv.mul2;
d /= (double)cv.div2;
d *= (double)rcv.mul1;
d /= (double)rcv.div1;
d *= (double)rcv.mul2;
d /= (double)rcv.div2;
PRINTF1( " composite product %d.%d\n",
(int)d, ((int)(d * 1000000) % 1000000 ) );
d -= 1.0;
CYG_TEST_CHECK( d < +0.0001, "Overflow in composite product" );
CYG_TEST_CHECK( d > -0.0001, "Underflow in composite product" );
 
res = rtc->get_resolution();
 
double factor_other_to_clock;
double factor_clock_to_other;
 
// res.dividend/res.divisor is the number of nS in a system
// clock tick. So:
d = (double)res.dividend/(double)res.divisor;
 
factor_other_to_clock = ns_tickers[i].scale * 1.0e7 / d ;
factor_clock_to_other = d / (ns_tickers[i].scale * 1.0e7);
 
unsigned int j;
for ( j = 1; j < 100; j++ ) {
cyg_uint64 delay;
if (cyg_test_is_simulator)
j += 30; // test fewer values
/* tr.b..m..k.. */
 
#ifdef CYGPKG_HAL_V85X_V850_CEB
j += 30; // test fewer values
#endif
 
for ( delay = j; delay < 1000000000000ll; delay *= 10 ) {
// get the converted result
cyg_uint64 result = Cyg_Clock::convert( delay, &cv );
 
counter++; lcounter++;
if ( (double)delay * (double)cv.mul1 > 1.6e+19 ||
(double)delay * (double)rcv.mul1 > 1.6e+19 ) {
// in silly territory now, give up.
// (that's MAXINT squared, approx.)
skipped++; lskipped++;
continue; // so the counter is accurate
}
 
PRINTF2( "delay %x%08x to result %x%08x\n",
(int)(delay >> 32), (int)delay,
(int)(result >> 32), (int)result );
 
// get what it should be in double maths
double delta = factor_other_to_clock * (double)delay;
if ( delta > 1000.0 ) {
delta = (double)result - delta;
delta /= (double)result;
CYG_TEST_CHECK( delta <= +0.01,
"Proportional overflow in conversion to" );
CYG_TEST_CHECK( delta >= -0.01,
"Proportional underflow in conversion to" );
}
else {
cyg_uint64 lo = (cyg_uint64)(delta); // assume TRUNCATION
cyg_uint64 hi = lo + 1;
CYG_TEST_CHECK( hi >= result,
"Range overflow in conversion to" );
CYG_TEST_CHECK( lo <= result,
"Range underflow in conversion to" );
}
 
// get the converted result
result = Cyg_Clock::convert( delay, &rcv );
 
PRINTF2( "delay %x%08x from result %x%08x\n",
(int)(delay >> 32), (int)delay,
(int)(result >> 32), (int)result );
 
// get what it should be in double maths
delta = factor_clock_to_other * (double)delay;
if ( delta > 1000.0 ) {
delta = (double)result - delta;
delta /= (double)result;
CYG_TEST_CHECK( delta <= +0.01,
"Proportional overflow in conversion from" );
CYG_TEST_CHECK( delta >= -0.01,
"Proportional underflow in conversion from" );
}
else {
cyg_uint64 lo = (cyg_uint64)(delta); // assume TRUNCATION
cyg_uint64 hi = lo + 1;
CYG_TEST_CHECK( hi >= result,
"Range overflow in conversion from" );
CYG_TEST_CHECK( lo <= result,
"Range underflow in conversion from" );
}
 
if (cyg_test_is_simulator)
break;
}
}
PRINTF0( "INFO:<%d nS/tick: tested %d values, skipped %d because of overflow>\n",
ns_tickers[i].ns, lcounter, lskipped );
}
 
PRINTF0( "INFO:<tested %d values, total skipped %d because of overflow>\n",
counter, skipped );
 
CYG_TEST_PASS_FINISH("ClockCnv OK");
}
 
void clockcnv_main( void )
{
CYG_TEST_INIT();
new_thread(entry0, (CYG_ADDRWORD)&thread_obj[0]);
Cyg_Scheduler::start();
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
clockcnv_main();
}
 
#else // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( "Kernel real-time clock disabled");
}
 
#endif // def CYGVAR_KERNEL_COUNTERS_CLOCK
 
// EOF clockcnv.cxx
/kexcept1.c
0,0 → 1,288
/*=================================================================
//
// kexcept1.cxx
//
// Kernel C API Exception test 1
//
//=================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm, jlarmour
// Date: 1999-02-16
// Description: Test basic exception functionality
//####DESCRIPTIONEND####
*/
 
#include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGPKG_KERNEL_EXCEPTIONS
 
#ifdef CYGFUN_KERNEL_API_C
 
#include <cyg/hal/hal_intr.h> // exception ranges
 
#include "testaux.h"
 
#ifndef CYGPKG_HAL_ARM_PID
#define EXCEPTION_DATA_ACCESS
#endif
 
#define NTHREADS 1
#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICAL
 
static cyg_handle_t thread[NTHREADS];
 
static cyg_thread thread_obj[NTHREADS];
static char stack[NTHREADS][STACKSIZE];
 
 
 
#ifdef EXCEPTION_DATA_ACCESS
static cyg_exception_handler_t handler0;
 
static void handler0(cyg_addrword_t data, cyg_code_t number, cyg_addrword_t info)
{
CYG_TEST_INFO("handler 0 called");
CYG_TEST_CHECK((cyg_addrword_t)123 == data, "handler given wrong data");
// ignore machine specific stuff
CYG_UNUSED_PARAM(cyg_code_t, number);
CYG_UNUSED_PARAM(cyg_addrword_t, info);
 
CYG_TEST_PASS_FINISH("Except 1 OK");
}
#endif
 
static int d0;
 
static void handler1(cyg_addrword_t data, cyg_code_t number, cyg_addrword_t info)
{
CYG_TEST_INFO("handler 1 called");
 
CYG_TEST_CHECK((cyg_addrword_t)&d0 == data, "handler given wrong data");
 
#ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
CYG_TEST_CHECK(number == CYGNUM_HAL_EXCEPTION_MAX, "handler given wrong number");
#else
CYG_UNUSED_PARAM(cyg_code_t, number);
#endif
 
CYG_TEST_CHECK((cyg_addrword_t)99 == info, "handler given wrong info");
}
 
 
#ifdef EXCEPTION_DATA_ACCESS
// The following function attempts to cause an exception in various
// hacky ways. It is machine dependent what exception is generated.
// It does reads rather than writes hoping not to corrupt anything
// important.
static int
cause_fpe(int num)
{
double a;
 
a = 1.0/num; // Depending on FPU emulation and/or
// the FPU architecture, this may
// cause an exception.
// (float division by zero)
 
return ((int)a)/num; // This may cause an exception if
// the architecture supports it.
// (integer division by zero).
} // cause_fpe()
 
void cause_exception(void)
{
int x;
unsigned int p=0;
 
// First try for an address exception (unaligned access exception
// or SEGV/BUS exceptions)
do {
x=*(volatile int *)(p-1);
p+=0x100000;
} while(p != 0);
 
// Next try an integer or floating point divide-by-zero exception.
cause_fpe(0);
}
#endif
 
static void entry0( CYG_ADDRWORD data )
{
#ifdef EXCEPTION_DATA_ACCESS
cyg_code_t n;
#endif
cyg_exception_handler_t *old_handler, *old_handler1;
cyg_addrword_t old_data, old_data1;
 
CYG_UNUSED_PARAM(CYG_ADDRESS, data);
 
cyg_exception_set_handler(
CYGNUM_HAL_EXCEPTION_MAX,
&handler1,
(cyg_addrword_t)&d0,
&old_handler,
&old_data);
 
cyg_exception_set_handler(
CYGNUM_HAL_EXCEPTION_MAX,
&handler1,
(cyg_addrword_t)&d0,
&old_handler1,
&old_data1);
CYG_TEST_CHECK(old_handler1 == &handler1,
"register exception: old_handler not the one previously registered");
CYG_TEST_CHECK(old_data1 == (cyg_addrword_t)&d0,
"register exception: old_data not those previously registered");
 
cyg_exception_call_handler(
cyg_thread_self(),
CYGNUM_HAL_EXCEPTION_MAX,
(cyg_addrword_t)99);
 
CYG_TEST_INFO("handler 1 returned");
 
cyg_exception_clear_handler(CYGNUM_HAL_EXCEPTION_MAX);
cyg_exception_clear_handler(CYGNUM_HAL_EXCEPTION_MAX);
 
#ifdef EXCEPTION_DATA_ACCESS
 
#if 0
#elif defined(CYGPKG_HAL_POWERPC_SIM)
// The exception generated by the SIM is not recognized by GDB.
// PR 19945 workaround.
CYG_TEST_NA("Not applicable to PowerPC SIM");
#endif
 
for(n = CYGNUM_HAL_EXCEPTION_MIN; n <= CYGNUM_HAL_EXCEPTION_MAX; n++) {
cyg_exception_set_handler(
n,
handler0,
(cyg_addrword_t)123,
&old_handler1,
&old_data1);
}
 
CYG_TEST_PASS("Attempting to provoke exception");
 
cause_exception();
 
CYG_TEST_FAIL_FINISH("Couldn't cause exception");
#else // EXCEPTION_DATA_ACCESS
CYG_TEST_NA("Platform does not support data exceptions");
#endif
}
 
#ifdef CYG_HAL_MIPS_TX39_JMR3904
 
extern void __default_exception_vsr(void);
 
#endif
 
void except0_main( void )
{
// Use CYG_TEST_GDBCMD _before_ CYG_TEST_INIT()
CYG_TEST_GDBCMD("handle SIGBUS nostop");
CYG_TEST_GDBCMD("handle SIGSEGV nostop");
CYG_TEST_GDBCMD("handle SIGFPE nostop");
 
CYG_TEST_INIT();
 
#ifdef HAL_VSR_SET_TO_ECOS_HANDLER
// Reclaim the VSR off CygMon possibly
#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_ACCESS, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_FPU, NULL );
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, NULL );
#endif
#endif
 
cyg_thread_create(4, entry0 , (cyg_addrword_t)0, "kexcept1",
(void *)stack[0], STACKSIZE, &thread[0], &thread_obj[0]);
cyg_thread_resume(thread[0]);
 
cyg_scheduler_start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
except0_main();
}
 
#else // def CYGFUN_KERNEL_API_C
#define N_A_MSG "Kernel C API layer disabled"
#endif // def CYGFUN_KERNEL_API_C
#else // def CYGPKG_KERNEL_EXCEPTIONS
#define N_A_MSG "Exceptions disabled"
#endif // def CYGPKG_KERNEL_EXCEPTIONS
 
#ifdef N_A_MSG
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( N_A_MSG);
}
#endif // N_A_MSG
 
/* EOF kexcept1.c */
/kphilo.c
0,0 → 1,236
//==========================================================================
//
// kphilo.c
//
// A test of the dining philosophers problem
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: A test of the dining philosophers problem
//####DESCRIPTIONEND####
//
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/cyg_ass.h>
#include <cyg/kernel/diag.h>
 
// -------------------------------------------------------------------------
// Data for the philosophers problem
 
#define PHILOSOPHERS 15 // number of philosophers
#define STACKSIZE (2*1024) // size of thread stack
 
// array of stacks for philosopher threads
char thread_stack[PHILOSOPHERS][STACKSIZE];
 
// array of threads.
cyg_thread thread[PHILOSOPHERS];
 
cyg_handle_t thread_handle[PHILOSOPHERS];
 
// array of chopsticks
cyg_sem_t chopstick[PHILOSOPHERS];
 
cyg_ucount32 data_index;
 
// -------------------------------------------------------------------------
// State recording and display
 
static char pstate[PHILOSOPHERS+1]; // state vector showing what each
// philosopher is doing
 
cyg_mutex_t state_mutex;
 
#ifdef CYG_HAL_MN10300_MN103002
static cyg_count8 eaters = 0;
#endif
 
void change_state(int id, char newstate)
{
cyg_mutex_lock(&state_mutex);
 
#ifdef CYG_HAL_MN10300_MN103002
if( pstate[id] == 'E' ) eaters--;
if( newstate == 'E' ) eaters++;
// led(eaters);
#endif
pstate[id] = newstate;
 
diag_write_string(pstate);
#if 0
diag_write_char(' ');
diag_write_dec(Cyg_Scheduler::get_thread_switches());
#endif
diag_write_char('\n');
 
cyg_mutex_unlock(&state_mutex);
}
 
char get_state( int id)
{
char s;
cyg_mutex_lock(&state_mutex);
s = pstate[id];
 
cyg_mutex_unlock(&state_mutex);
 
return s;
}
 
// -------------------------------------------------------------------------
// Thread to behave like a philosopher
 
void Philosopher( cyg_addrword_t vid )
{
cyg_uint32 id = (cyg_uint32)vid;
cyg_sem_t *first_stick = &chopstick[id];
cyg_sem_t *second_stick = &chopstick[(id+1)%PHILOSOPHERS];
#ifdef CYGPKG_INFRA_DEBUG
int left_philo = ((id==0)?PHILOSOPHERS:id)-1;
int right_philo = (id==PHILOSOPHERS-1)?0:(id+1);
#endif
CYG_ASSERT( id >= 0 && id < PHILOSOPHERS, "Bad id");
 
// Deadlock avoidance. The easiest way to make the philosophers
// behave is to make each pick up the lowest numbered stick
// first. This is how it works out anyway for all the philosophers
// except the last, who must have his sticks swapped.
if( id == PHILOSOPHERS-1 )
{
cyg_sem_t *t = first_stick;
first_stick = second_stick;
second_stick = t;
}
for(;;)
{
cyg_ucount32 val;
// The following variable is shared by all philosophers.
// It is incremented unprotected, but this does not matter
// since it is only present to introduce a little variability
// into the think and eat times.
static volatile int cycle = 0;
// Think for a bit
 
cyg_thread_delay((id+cycle++)%12); // Cogito ergo sum...
 
// I am now hungry, try to get the chopsticks
 
change_state(id,'H');
// Get the first stick
cyg_semaphore_wait(first_stick);
// Get the second stick
cyg_semaphore_wait(second_stick);
// Got them, now eat
 
change_state(id,'E');
// Check that the world is as I think it is...
cyg_semaphore_peek( first_stick, &val);
CYG_ASSERT( val == 0, "Not got first stick");
cyg_semaphore_peek( second_stick, &val);
CYG_ASSERT( val == 0, "Not got second stick");
CYG_ASSERT( get_state(left_philo) != 'E', "Left neighbour also eating!!");
CYG_ASSERT( get_state(right_philo) != 'E', "Right neighbour also eating!!");
cyg_thread_delay((id+cycle++)%6); // munch munch
 
// Finished eating, put down sticks.
 
change_state(id,'T');
 
cyg_semaphore_post( first_stick );
cyg_semaphore_post( second_stick );
 
}
}
 
// -------------------------------------------------------------------------
 
externC void
cyg_start( void )
{
int i;
diag_init();
 
diag_write_string("Philosophers\n");
diag_write_string("Started\n");
 
// Zero last element in state so it acts like
// a string.
pstate[PHILOSOPHERS] = 0;
 
#if 1
for( i = 0; i < PHILOSOPHERS; i++ )
{
change_state(i,'T'); // starting state
 
cyg_thread_create(4, Philosopher, (cyg_addrword_t)i, "philosopher",
(void *)(&thread_stack[i]), STACKSIZE,
&thread_handle[i], &thread[i]);
 
// resume it
cyg_thread_resume(thread_handle[i]);
 
// and make the matching chopstick present
cyg_semaphore_init( &chopstick[i], 1);
}
#endif
// Get the world going
cyg_scheduler_start();
 
}
 
// -------------------------------------------------------------------------
// EOF kphilo.c
/cnt_sem0.cxx
0,0 → 1,89
//==========================================================================
//
// cnt_sem0.cxx
//
// Counting semaphore test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: Limited to checking constructors/destructors
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
static Cyg_Counting_Semaphore sema0, sema1(0), sema2(1);
 
#include "testaux.hxx"
 
static bool flash( void )
{
Cyg_Counting_Semaphore s0;
 
Cyg_Counting_Semaphore s1(97);
 
Cyg_Counting_Semaphore s2(0);
 
return true;
}
 
void cnt_sem0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Counting Semaphore 0 OK");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
cnt_sem0_main();
}
 
// EOF cnt_sem0.cxx
/cnt_sem1.cxx
0,0 → 1,135
//==========================================================================
//
// cnt_sem1.cxx
//
// Counting semaphore test 1
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-02-24
// Description: Tests basic counting semaphore functionality.
//####DESCRIPTIONEND####
 
#include <pkgconf/kernel.h>
 
#include <cyg/kernel/thread.hxx> // Cyg_Thread
#include <cyg/kernel/thread.inl>
#include <cyg/kernel/sched.hxx> // Cyg_Scheduler::start()
 
#include <cyg/kernel/sema.hxx>
 
#include <cyg/infra/testcase.h>
 
#include <cyg/kernel/sched.inl>
 
 
#define NTHREADS 2
#include "testaux.hxx"
 
static Cyg_Counting_Semaphore s0(0), s1(2), s2;
 
static volatile cyg_ucount8 q = 0;
 
static void entry0( CYG_ADDRWORD data )
{
s0.wait();
CHECK( 1 == q++ );
s1.post();
s0.wait();
CHECK( 3 == q++ );
CHECK( 0 == s0.peek() );
CHECK( ! s0.trywait() );
s0.post();
CHECK( 4 == q++ );
CHECK( 1 == s0.peek() );
s0.post();
CHECK( 2 == s0.peek() );
s1.post();
CHECK( 0 == s2.peek() );
s2.wait();
CHECK( 6 == q++ );
CYG_TEST_PASS_FINISH("Counting Semaphore 1 OK");
}
 
static void entry1( CYG_ADDRWORD data )
{
CHECK( 2 == s1.peek() );
s1.wait();
CHECK( 1 == s1.peek() );
s1.wait();
CHECK( 0 == q++ );
CHECK( 0 == s0.peek() );
s0.post();
s1.wait();
CHECK( 2 == q++ );
s0.post();
s1.wait();
CHECK( 5 == q++ );
CHECK( 2 == s0.peek() );
CHECK( s0.trywait() );
CHECK( 1 == s0.peek() );
CHECK( s0.trywait() );
CHECK( 0 == s0.peek() );
s2.post();
s0.wait();
CYG_TEST_FAIL_FINISH("Not reached");
}
 
void cnt_sem1_main( void )
{
CYG_TEST_INIT();
 
new_thread(entry0, 0);
new_thread(entry1, 1);
 
Cyg_Scheduler::start();
 
CYG_TEST_FAIL_FINISH("Not reached");
}
 
externC void
cyg_start( void )
{
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
cyg_hal_invoke_constructors();
#endif
cnt_sem1_main();
}
 
// EOF cnt_sem1.cxx
/kmutex0.c
0,0 → 1,98
/*=================================================================
//
// kmutex0.c
//
// Kernel C API Mutex and condition variable test 0
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): dsm
// Contributors: dsm
// Date: 1998-03-23
// Description: Limited to checking constructors/destructors
//####DESCRIPTIONEND####
*/
 
#include <cyg/kernel/kapi.h>
 
#include <cyg/infra/testcase.h>
 
#ifdef CYGFUN_KERNEL_API_C
 
#include "testaux.h"
 
static cyg_mutex_t mutex0;
 
static cyg_cond_t cvar0;
 
static bool flash( void )
{
cyg_mutex_init( &mutex0 );
cyg_cond_init( &cvar0, &mutex0 );
 
cyg_cond_destroy( &cvar0 );
cyg_mutex_destroy( &mutex0 );
 
return true;
}
 
void kmutex0_main( void )
{
CYG_TEST_INIT();
 
CHECK(flash());
CHECK(flash());
CYG_TEST_PASS_FINISH("Kernel C API Mutex 0 OK");
}
 
externC void
cyg_start( void )
{
kmutex0_main();
}
 
#else /* def CYGFUN_KERNEL_API_C */
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA("Kernel C API layer disabled");
}
#endif /* def CYGFUN_KERNEL_API_C */
 
/* EOF kmutex0.c */
/stress_threads.c
0,0 → 1,859
//==========================================================================
//
// stress_threads.cxx
//
// Basic thread stress test
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): rosalia
// Contributors: rosalia, jskov
// Date: 1999-04-13
// Description: Very simple thread stress test, with some memory
// allocation and alarm handling.
//
// Notes:
// If client_makes_request is big, it means that there are made many more
// client requests than can be serviced. Consequently, clients are wasting
// CPU time and should be sleeping more.
//
// The list of handler invocations show how many threads are running
// at the same time. The more powerful the CPU, the more the numbers
// should spread out.
//####DESCRIPTIONEND####
 
#include <pkgconf/system.h>
#include <cyg/infra/testcase.h>
 
#include <cyg/hal/hal_arch.h>
 
#if defined(CYGPKG_KERNEL) && defined(CYGPKG_IO) && defined(CYGPKG_ISOINFRA)
 
#include <pkgconf/kernel.h>
#include <pkgconf/isoinfra.h>
#include CYGHWR_MEMORY_LAYOUT_H
 
#if defined(CYGFUN_KERNEL_API_C)
 
#include <cyg/kernel/kapi.h>
 
#ifdef CYGINT_ISO_STDIO_FORMATTED_IO
 
#include <stdio.h>
#include <stdlib.h>
 
#if defined(CYGPKG_LIBM)
 
#include <math.h>
#include <assert.h>
 
#include <cyg/kernel/test/stackmon.h>
 
#if defined(CYGFUN_KERNEL_THREADS_TIMER)
#if CYGINT_ISO_MALLOC
 
/* if TIME_LIMIT is defined, it represents the number of seconds this
test should last; if it is undefined the test will go forever */
#define DEATH_TIME_LIMIT 20
/* #undef DEATH_TIME_LIMIT */
 
// STACK_SIZE is typical +2kB for printf family calls which use big
// auto variables. Add more for handler which calls perform_stressful_tasks()
#define STACK_SIZE (2*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL)
#define STACK_SIZE_HANDLER (STACK_SIZE + 30*CYGNUM_HAL_STACK_FRAME_SIZE)
 
#define N_MAIN 1
 
// If we have instrumentation enabled, make the execution time in the
// simulator even shorter that we were going to anyway.
#ifdef CYGPKG_KERNEL_INSTRUMENT
#define SIM_DELAY_DIVISOR 100
#else
#define SIM_DELAY_DIVISOR 10
#endif
 
//-----------------------------------------------------------------------
// Some targets need to define a smaller number of handlers due to
// memory restrictions.
#if defined(CYGMEM_REGION_ram_SIZE) && (CYGMEM_REGION_ram_SIZE < 0x80000)
#define MAX_HANDLERS 4
#define N_LISTENERS 1
#define N_CLIENTS 1
 
#undef STACK_SIZE
#undef STACK_SIZE_HANDLER
#define STACK_SIZE (1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL)
#define STACK_SIZE_HANDLER (STACK_SIZE + 10*CYGNUM_HAL_STACK_FRAME_SIZE)
#endif
 
//-----------------------------------------------------------------------
// If no target specific definitions, use defaults
#ifndef MAX_HANDLERS
#define MAX_HANDLERS 19
#define N_LISTENERS 4
#define N_CLIENTS 4
#endif
 
/* Allocate priorities in this order. This ensures that handlers
(which are the ones using the CPU) get enough CPU time to actually
complete their tasks.
 
The empty space ensures that if libc main() thread should happen to
be in the priority range of the handlers, no handlers are
accidently reduced so much in priority to get below
listeners/clients. */
 
#define P_MAIN_PROGRAM 1
#define P_MAIN_PROGRAM_E (P_MAIN_PROGRAM+N_MAIN)
 
#define P_BASE_HANDLER (P_MAIN_PROGRAM_E)
#define P_BASE_HANDLER_E (P_BASE_HANDLER+MAX_HANDLERS)
 
#define P_BASE_EMPTY (P_BASE_HANDLER_E)
#define P_BASE_EMPTY_E (P_BASE_EMPTY+2)
 
#define P_BASE_LISTENER (P_BASE_EMPTY_E)
#define P_BASE_LISTENER_E (P_BASE_LISTENER+N_LISTENERS)
 
#define P_BASE_CLIENT (P_BASE_LISTENER_E)
#define P_BASE_CLIENT_E (P_BASE_CLIENT+N_CLIENTS)
 
#define P_MAX (P_BASE_CLIENT_E)
 
/* Ensure there's room for what we request */
#if (CYGNUM_KERNEL_SCHED_PRIORITIES >= P_MAX)
 
/* if we use the bitmap scheduler we must make sure we don't use the
same priority more than once, so we must store those already in use */
static volatile char priority_in_use[P_MAX];
 
/* We may not get the priority we ask for (scheduler may decide to ignore
schedule hint). So keep a table of priorities actually assigned to
the threads. This information may come in handy for debugging - it's
not actively used by the code. */
static volatile int priority_translation[P_MAX];
 
/* now declare (and allocate space for) some kernel objects, like the
threads we will use */
cyg_thread main_thread_s;
cyg_thread handler_thread_s[MAX_HANDLERS];
cyg_thread listener_thread_s[N_LISTENERS];
cyg_thread client_thread_s[N_CLIENTS];
 
/* space for stacks for all threads */
char main_stack[STACK_SIZE];
char handler_stack[MAX_HANDLERS][STACK_SIZE_HANDLER];
char listener_stack[N_LISTENERS][STACK_SIZE];
char client_stack[N_CLIENTS][STACK_SIZE];
 
/* now the handles for the threads */
cyg_handle_t mainH;
cyg_handle_t handlerH[MAX_HANDLERS];
cyg_handle_t listenerH[N_LISTENERS];
cyg_handle_t clientH[N_CLIENTS];
 
/* space for thread names */
char thread_name[P_MAX][20];
 
/* and now variables for the procedure which is the thread */
cyg_thread_entry_t main_program, client_program, listener_program,
handler_program;
 
/* a few mutexes used in the code */
cyg_mutex_t client_request_lock, handler_slot_lock, statistics_print_lock,
free_handler_lock;
 
/* global variables with which the handler IDs and thread priorities
to free are communicated from handlers to main_program. Access to
these are protected by free_handler_lock. An id of -1 means the
that the variables are empty. */
volatile int free_handler_pri = 0;
volatile int free_handler_id = -1;
 
/* a global variable with which the client and server coordinate */
volatile int client_makes_request = 0;
 
/* if this is true, clients will not make requests */
volatile int clients_paused = 0;
 
 
/* indicates that it's time to print out a report */
volatile int time_to_report = 0;
/* print status after a delay of this many secs. */
int time_report_delay;
 
/*** now application-specific variables ***/
/* an array that stores whether the handler threads are in use */
volatile int handler_thread_in_use[MAX_HANDLERS];
/* total count of active handlers */
volatile int handler_thread_in_use_count;
 
 
/***** statistics-gathering variables *****/
struct s_statistics {
/* store the number of times each handler has been invoked */
unsigned long handler_invocation_histogram[MAX_HANDLERS];
 
/* store how many times malloc has been attempted and how many times
it has failed */
unsigned long malloc_tries, malloc_failures;
 
/* how many threads have been created */
unsigned long thread_creations, thread_exits;
};
 
struct s_statistics statistics;
 
/* some function prototypes; those with the sc_ prefix are
"statistics-collecting" versions of the cyg_ primitives */
cyg_addrword_t sc_thread_create(
cyg_addrword_t sched_info, /* scheduling info (eg pri) */
cyg_thread_entry_t *entry, /* entry point function */
cyg_addrword_t entry_data, /* entry data */
char *name, /* optional thread name */
void *stack_base, /* stack base, NULL = alloc */
cyg_ucount32 stack_size, /* stack size, 0 = default */
cyg_handle_t *handle, /* returned thread handle */
cyg_thread *thread /* put thread here */
);
 
void start_handler(void);
void stop_handler(int handler_id, int handler_pri);
void perform_stressful_tasks(void);
void permute_array(char a[], int size, int seed);
void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp,
cyg_alarm *death_alarm_p, int *killed_p);
void print_statistics(int print_full);
 
/* we need to declare the alarm handling function (which is defined
below), so that we can pass it to cyg_alarm_initialize() */
cyg_alarm_t report_alarm_func, death_alarm_func;
 
/* handle and alarm for the report alarm */
cyg_handle_t report_alarmH, counterH, system_clockH;
cyg_alarm report_alarm;
 
/* main launches all the threads of the test */
int
main(void)
{
int i;
 
CYG_TEST_INIT();
CYG_TEST_INFO("Stress threads test compiled on " __DATE__);
 
cyg_mutex_init(&client_request_lock);
cyg_mutex_init(&statistics_print_lock);
cyg_mutex_init(&free_handler_lock);
 
/* initialize statistics */
memset(&statistics, 0, sizeof(statistics));
 
/* clear priority table */
for (i = 0; i < sizeof(priority_in_use); i++)
priority_in_use[i] = 0;
 
/* initialize main thread */
{
priority_translation[P_MAIN_PROGRAM] =
sc_thread_create(P_MAIN_PROGRAM, main_program, (cyg_addrword_t) 0,
"main_program", (void *) main_stack, STACK_SIZE,
&mainH, &main_thread_s);
priority_in_use[P_MAIN_PROGRAM]++;
}
 
/* initialize all handler threads to not be in use */
for (i = 0; i < MAX_HANDLERS; ++i) {
handler_thread_in_use[i] = 0;
}
handler_thread_in_use_count = 0;
for (i = 0; i < N_LISTENERS; ++i) {
int prio = P_BASE_LISTENER + i;
char* name = &thread_name[prio][0];
sprintf(name, "listener-%02d", i);
priority_translation[prio] =
sc_thread_create(prio, listener_program, (cyg_addrword_t) i,
name, (void *) listener_stack[i], STACK_SIZE,
&listenerH[i], &listener_thread_s[i]);
CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");
priority_in_use[prio]++;
}
for (i = 0; i < N_CLIENTS; ++i) {
int prio = P_BASE_CLIENT + i;
char* name = &thread_name[prio][0];
sprintf(name, "client-%02d", i);
priority_translation[prio] =
sc_thread_create(prio, client_program, (cyg_addrword_t) i,
name, (void *) client_stack[i], STACK_SIZE,
&(clientH[i]), &client_thread_s[i]);
CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");
priority_in_use[prio]++;
}
 
cyg_thread_resume(mainH);
for (i = 0; i < N_CLIENTS; ++i) {
cyg_thread_resume(clientH[i]);
}
for (i = 0; i < N_LISTENERS; ++i) {
cyg_thread_resume(listenerH[i]);
}
 
/* set up the alarm which gives periodic wakeups to say "time to
print a report */
system_clockH = cyg_real_time_clock();
cyg_clock_to_counter(system_clockH, &counterH);
 
cyg_alarm_create(counterH, report_alarm_func,
(cyg_addrword_t) 4000,
&report_alarmH, &report_alarm);
if (cyg_test_is_simulator) {
time_report_delay = 2;
} else {
time_report_delay = 60;
}
 
cyg_alarm_initialize(report_alarmH, cyg_current_time()+200,
time_report_delay*100);
 
return 0;
}
 
/* main_program() -- frees resources and prints status. */
void main_program(cyg_addrword_t data)
{
#ifdef DEATH_TIME_LIMIT
cyg_handle_t deathH;
cyg_alarm death_alarm;
int is_dead = 0;
 
setup_death_alarm(0, &deathH, &death_alarm, &is_dead);
#endif /* DEATH_TIME_LIMIT */
 
for (;;) {
int handler_id = -1;
int handler_pri = 0;
 
cyg_mutex_lock(&free_handler_lock); {
// If any handler has left its ID, copy the ID and
// priority values to local variables, and free up the
// global communication variables again.
if (-1 != free_handler_id) {
handler_id = free_handler_id;
handler_pri = free_handler_pri;
free_handler_id = -1;
}
} cyg_mutex_unlock(&free_handler_lock);
 
if (-1 != handler_id) {
stop_handler(handler_id, handler_pri);
}
 
// If it's time to report status or quit, set pause flag and
// keep looping until all handlers have stopped.
if (time_to_report) {
// Pause clients
cyg_mutex_lock(&client_request_lock); {
clients_paused = 1;
} cyg_mutex_unlock(&client_request_lock);
 
// When all handlers have stopped, we can print statistics
// knowing that all (handler allocated) resources should have
// been freed. That is, we should be able to determine leaks.
if (0 == handler_thread_in_use_count) {
print_statistics(0);
 
// We've done the printing now. Resume the system.
time_to_report = 0;
cyg_mutex_lock(&client_request_lock); {
clients_paused = 0;
} cyg_mutex_unlock(&client_request_lock);
}
}
 
#ifdef DEATH_TIME_LIMIT
// Stop test if time.
if (is_dead) {
// Pause clients
cyg_mutex_lock(&client_request_lock); {
clients_paused = 1;
} cyg_mutex_unlock(&client_request_lock);
 
// When all handlers have stopped, we can print statistics
// knowing that all (handler allocated) resources should have
// been freed. That is, we should be able to determine leaks.
if (0 == handler_thread_in_use_count) {
print_statistics(1);
CYG_TEST_PASS_FINISH("Kernel thread stress test OK");
}
}
#endif /* DEATH_TIME_LIMIT */
 
cyg_thread_delay(3);
}
}
 
/* client_program() -- an obnoxious client which makes a lot of requests */
void client_program(cyg_addrword_t data)
{
int delay;
 
system_clockH = cyg_real_time_clock();
cyg_clock_to_counter(system_clockH, &counterH);
 
for (;;) {
delay = (rand() % 20);
 
/* now send a request to the server */
cyg_mutex_lock(&client_request_lock); {
if (0 == clients_paused)
client_makes_request++;
} cyg_mutex_unlock(&client_request_lock);
 
cyg_thread_delay(10+delay);
}
}
 
/* listener_program() -- listens for a request and spawns a handler to
take care of the request */
void listener_program(cyg_addrword_t data)
{
for (;;) {
int make_request = 0;
cyg_mutex_lock(&client_request_lock); {
if (client_makes_request > 0) {
--client_makes_request;
make_request = 1;
}
} cyg_mutex_unlock(&client_request_lock);
if (make_request)
start_handler();
cyg_thread_delay(2 + (rand() % 10));
}
}
 
/* handler_program() -- is spawned to handle each incoming request */
void handler_program(cyg_addrword_t data)
{
/* here is where we perform specific stressful tasks */
perform_stressful_tasks();
 
cyg_thread_delay(4 + (int) (0.5*log(1.0 + fabs((rand() % 1000000)))));
 
{
// Loop until the handler id and priority can be communicated to
// the main_program.
int freed = 0;
do {
cyg_mutex_lock(&free_handler_lock); {
if (-1 == free_handler_id) {
free_handler_id = data;
free_handler_pri = P_BASE_HANDLER+(int) data;
freed = 1;
}
} cyg_mutex_unlock(&free_handler_lock);
if (!freed)
cyg_thread_delay(2);
} while (!freed);
}
 
// Then exit.
cyg_thread_exit();
}
 
/* start a new handler */
void start_handler(void)
{
int prio;
char* name;
int handler_slot = 0;
int found = 0;
 
while (!found) {
cyg_mutex_lock(&handler_slot_lock); {
for (handler_slot = 0; handler_slot < MAX_HANDLERS;++handler_slot){
if (!handler_thread_in_use[handler_slot]) {
found = 1;
handler_thread_in_use[handler_slot]++;
handler_thread_in_use_count++;
break;
}
}
} cyg_mutex_unlock(&handler_slot_lock);
if (!found)
cyg_thread_delay(1);
}
 
CYG_ASSERT(1 == handler_thread_in_use[handler_slot],
"Handler usage count wrong!");
 
prio = P_BASE_HANDLER+handler_slot;
CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");
priority_in_use[prio]++;
 
name = &thread_name[prio][0];
sprintf(name, "handler-%02d/%02d", handler_slot, prio);
 
priority_translation[prio] =
sc_thread_create(prio, handler_program,
(cyg_addrword_t) handler_slot,
name, (void *) handler_stack[handler_slot],
STACK_SIZE_HANDLER, &handlerH[handler_slot],
&handler_thread_s[handler_slot]);
cyg_thread_resume(handlerH[handler_slot]);
++statistics.handler_invocation_histogram[handler_slot];
}
 
/* free a locked handler thread */
void stop_handler(int handler_id, int handler_pri)
{
// Finally delete the handler thread. This must be done in a
// loop, waiting for the call to return true. If it returns
// false, go to sleep for a bit, so the killed thread gets a
// chance to run and complete its business.
while (!cyg_thread_delete(handlerH[handler_id])) {
cyg_thread_delay(1);
}
++statistics.thread_exits;
// Free the handler resources.
cyg_mutex_lock(&handler_slot_lock); {
handler_thread_in_use[handler_id]--;
handler_thread_in_use_count--;
priority_in_use[handler_pri]--;
CYG_ASSERT(0 == priority_in_use[handler_pri],
"Priority not in use!");
CYG_ASSERT(0 == handler_thread_in_use[handler_id],
"Handler not in use!");
CYG_ASSERT(0 <= handler_thread_in_use_count,
"Stopped more handlers than was started!");
} cyg_mutex_unlock(&handler_slot_lock);
}
 
 
/* do things which will stress the system */
void perform_stressful_tasks()
{
#define MAX_MALLOCED_SPACES 100 /* do this many mallocs at most */
#define MALLOCED_BASE_SIZE 1 /* basic size in bytes */
char *spaces[MAX_MALLOCED_SPACES];
int sizes[MAX_MALLOCED_SPACES];
unsigned int i, j, size;
 
cyg_uint8 pool_space[10][100];
cyg_handle_t mempool_handles[10];
cyg_mempool_fix mempool_objects[10];
 
/* here I use malloc, which uses the kernel's variable memory pools.
note that malloc/free is a bit simple-minded here: it does not
try to really fragment things, and it does not try to make the
allocation/deallocation concurrent with other thread execution
(although I'm about to throw in a yield()) */
for (i = 0; i < MAX_MALLOCED_SPACES; ++i) {
++statistics.malloc_tries;
size = (i*2+1)*MALLOCED_BASE_SIZE;
spaces[i] = (char *) malloc(size);
sizes[i] = size;
 
if (spaces[i] != NULL) {
// Fill with a known value (differs between chunk).
for (j = 0; j < size; ++j) {
spaces[i][j] = 0x50 | ((j+i) & 0x0f);
}
}
 
if (i % (MAX_MALLOCED_SPACES/10) == 0) {
cyg_thread_yield();
}
if (i % (MAX_MALLOCED_SPACES/15) == 0) {
cyg_thread_delay(i % 5);
}
}
 
cyg_thread_delay(5);
 
/* now free it all up */
for (i = 0; i < MAX_MALLOCED_SPACES; ++i) {
if (spaces[i] != NULL) {
size = sizes[i];
for (j = 0; j < size; ++j) {
// Validate chunk data.
if ((0x50 | ((j+i) & 0x0f)) != spaces[i][j]) {
printf("Bad byte in chunk\n");
}
spaces[i][j] = 0xAA; /* write a bit pattern */
}
free(spaces[i]);
} else {
++statistics.malloc_failures;
}
}
 
/* now allocate and then free some fixed-size memory pools; for
now this is simple-minded because it does not have many threads
sharing the memory pools and racing for memory. */
for (i = 0; i < 10; ++i) {
cyg_mempool_fix_create(pool_space[i], 100, (i+1)*3,
&mempool_handles[i], &mempool_objects[i]);
}
 
for (i = 0; i < 10; ++i) {
spaces[i] = cyg_mempool_fix_try_alloc(mempool_handles[i]);
}
 
for (i = 0; i < 10; ++i) {
if (spaces[i]) {
cyg_mempool_fix_delete(mempool_handles[i]);
}
}
}
 
/* report_alarm_func() is invoked as an alarm handler, so it should be
quick and simple. in this case it sets a global flag which is
checked by main_program. */
void report_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data)
{
time_to_report = 1;
}
 
#ifdef DEATH_TIME_LIMIT
/* this sets up death alarms. it gets the handle and alarm from the
caller, since they must persist for the life of the alarm */
void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp,
cyg_alarm *death_alarm_p, int *killed_p)
{
cyg_handle_t system_clockH, counterH;
cyg_resolution_t rtc_res;
 
system_clockH = cyg_real_time_clock();
cyg_clock_to_counter(system_clockH, &counterH);
 
cyg_alarm_create(counterH, death_alarm_func,
(cyg_addrword_t) killed_p,
deathHp, death_alarm_p);
rtc_res = cyg_clock_get_resolution(system_clockH);
{
cyg_tick_count_t tick_delay;
tick_delay = (long long)
((1000000000.0*rtc_res.divisor)
*((double)DEATH_TIME_LIMIT)/((double)rtc_res.dividend));
if ( cyg_test_is_simulator )
tick_delay /= SIM_DELAY_DIVISOR;
#ifdef CYGPKG_HAL_SYNTH
// 20 seconds is a long time compared to the run time of other tests.
// Reduce to 10 seconds, allowing more tests to get run.
tick_delay /= 2;
#endif
 
cyg_alarm_initialize(*deathHp, cyg_current_time() + tick_delay, 0);
}
}
#endif
 
/* death_alarm_func() is the alarm handler that kills the current
thread after a specified timeout. It does so by setting a flag the
thread is constantly checking. */
void death_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data)
{
int *killed_p;
killed_p = (int *) data;
*killed_p = 1;
}
 
/* now I write the sc_ versions of the cyg_functions */
cyg_addrword_t sc_thread_create(
cyg_addrword_t sched_info, /* scheduling info (eg pri) */
cyg_thread_entry_t *entry, /* entry point function */
cyg_addrword_t entry_data, /* entry data */
char *name, /* optional thread name */
void *stack_base, /* stack base, NULL = alloc */
cyg_ucount32 stack_size, /* stack size, 0 = default */
cyg_handle_t *handle, /* returned thread handle */
cyg_thread *thread /* put thread here */
)
{
++statistics.thread_creations;
 
cyg_thread_create(sched_info, entry, entry_data, name,
stack_base, stack_size, handle, thread);
 
return cyg_thread_get_priority(*handle);
}
 
 
#define MINS_HOUR (60)
#define MINS_DAY (60*24)
 
void print_statistics(int print_full)
{
int i;
static int stat_dumps = 0;
static int print_count = 0;
static int shift_count = 0;
int minutes;
 
stat_dumps++;
 
// Find number of minutes.
minutes = time_report_delay*stat_dumps / 60;
 
if (!print_full) {
// Return if time/minutes not integer.
if ((time_report_delay*stat_dumps % 60) != 0)
return;
 
// After the first day, only dump stat once per day. Do print
// a . on the hour though.
if ((minutes > MINS_DAY) && ((minutes % MINS_DAY) != 0)) {
if ((minutes % MINS_HOUR) == 0) {
printf(".");
fflush(stdout);
}
return;
}
 
// After the first hour of the first day, only dump stat once
// per hour. Do print . each minute though.
if ((minutes < MINS_DAY) && (minutes > MINS_HOUR)
&& ((minutes % MINS_HOUR) != 0)) {
printf(".");
fflush(stdout);
return;
}
}
 
printf("\nState dump %d (%d hours, %d minutes) [numbers >>%d]\n",
++print_count, minutes / MINS_HOUR, minutes % MINS_HOUR,
shift_count);
 
cyg_mutex_lock(&statistics_print_lock); {
//--------------------------------
// Information private to this test:
printf(" Handler-invocations: ");
for (i = 0; i < MAX_HANDLERS; ++i) {
printf("%4lu ", statistics.handler_invocation_histogram[i]);
}
printf("\n");
printf(" malloc()-tries/failures: -- %7lu %7lu\n",
statistics.malloc_tries, statistics.malloc_failures);
printf(" client_makes_request: %d\n", client_makes_request);
 
// Check for big numbers and reduce if getting close to overflow
if (statistics.malloc_tries > 0x40000000) {
shift_count++;
for (i = 0; i < MAX_HANDLERS; ++i) {
statistics.handler_invocation_histogram[i] >>= 1;
}
statistics.malloc_tries >>= 1;
statistics.malloc_failures >>= 1;
}
} cyg_mutex_unlock(&statistics_print_lock);
 
#if CYGINT_ISO_MALLINFO
//--------------------------------
// System information
{
struct mallinfo mem_info;
mem_info = mallinfo();
printf(" Memory system: Total=0x%08x Free=0x%08x Max=0x%08x\n",
mem_info.arena, mem_info.fordblks, mem_info.maxfree);
}
#endif
 
// Dump stack status
printf(" Stack usage:\n");
cyg_test_dump_interrupt_stack_stats( " Interrupt" );
cyg_test_dump_idlethread_stack_stats( " Idle" );
 
cyg_test_dump_stack_stats(" Main", main_stack,
main_stack + sizeof(main_stack));
for (i = 0; i < MAX_HANDLERS; i++) {
cyg_test_dump_stack_stats(" Handler", handler_stack[i],
handler_stack[i] + sizeof(handler_stack[i]));
}
for (i = 0; i < N_LISTENERS; i++) {
cyg_test_dump_stack_stats(" Listener", listener_stack[i],
listener_stack[i] + sizeof(listener_stack[i]));
}
for (i = 0; i < N_CLIENTS; i++) {
cyg_test_dump_stack_stats(" Client", client_stack[i],
client_stack[i] + sizeof(client_stack[i]));
}
}
 
#else /* (CYGNUM_KERNEL_SCHED_PRIORITIES >= */
/* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */
#define N_A_MSG "not enough priorities available"
#endif /* (CYGNUM_KERNEL_SCHED_PRIORITIES >= */
/* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */
 
#else /* CYGINT_ISO_MALLOC */
# define N_A_MSG "this test needs malloc"
#endif /* CYGINT_ISO_MALLOC */
 
#else /* CYGFUN_KERNEL_THREADS_TIMER */
# define N_A_MSG "this test needs kernel threads timer"
#endif /* CYGFUN_KERNEL_THREADS_TIMER */
 
#else /* CYGPKG_LIBM */
# define N_A_MSG "this test needs libm"
#endif /* CYGPKG_LIBM */
 
#else /* CYGINT_ISO_STDIO_FORMATTED_IO */
# define N_A_MSG "this test needs stdio formatted I/O"
#endif /* CYGINT_ISO_STDIO_FORMATTED_IO */
 
#else // def CYGFUN_KERNEL_API_C
# define N_A_MSG "this test needs Kernel C API"
#endif
 
#else // def CYGPKG_KERNEL && CYGPKG_IO && CYGPKG_ISOINFRA
# define N_A_MSG "this tests needs Kernel, isoinfra and IO"
#endif
 
#ifdef N_A_MSG
externC void
cyg_start( void )
{
CYG_TEST_INIT();
CYG_TEST_NA( N_A_MSG);
}
#endif // N_A_MSG

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.