⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mutex3.cxx

📁 eCos1.31版
💻 CXX
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////        mutex3.cxx////        Mutex test 3 - priority inheritance////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):     hmt// Contributors:  hmt// Date:          2000-01-06// Description:   Tests mutex priority inheritance//####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>#include <cyg/infra/diag.h>             // diag_printf// ------------------------------------------------------------------------//// 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)// ------------------------------------------------------------------------// Management functions//// Stolen from testaux.hxx and copied in here because I want to be able to// reset the world also.#define NTHREADS 7static inline void *operator new(size_t size, void *ptr) { return ptr; };#define STACKSIZE CYGNUM_HAL_STACK_SIZE_TYPICALstatic 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 int nthreads = 0;static Cyg_Thread *new_thread( cyg_thread_entry *entry,                               CYG_ADDRWORD data,                               CYG_ADDRWORD priority,                               int do_resume ){    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 threadvolatile 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 CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE    CYG_TEST_INFO( "Checking for MUTEX_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 for NO mutex_priority_inheritance" );    CYG_TEST_CHECK( 0 == t3ran, "Thread 3 DID run" );    CYG_TEST_CHECK( 0 == got_it, "Thread 1 DID get the mutex" );#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();}// ------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -