public inbox for ecos-devel@sourceware.org
 help / color / mirror / Atom feed
* thread2 test gets deadlocked... Is it possible or am I missing some config option?
@ 2013-08-13 13:59 David Fernandez
  2013-08-13 19:19 ` David Fernandez
  0 siblings, 1 reply; 2+ messages in thread
From: David Fernandez @ 2013-08-13 13:59 UTC (permalink / raw)
  To: eCos development list

[-- Attachment #1: Type: text/plain, Size: 2473 bytes --]

Hi there,

Testing my hal for Cortex-R4, I'm getting a funny behaviour for test
 kernel/.../thread2. It seems that when two threads have the same
 priority, there is no timeslicing working (interestingly, the
 timeslice tests also get deadlocked).

The problem seems to appear because thread#2 preempts thread #1,
(thread #1 seems to do more API calls than thread #2, but reducing the
unnecessary ones does not solve the problem), so thread #2 gets
waiting for thread #1 to increase "q", and thread #1 never gets
scheduled to realize that "q" has moved to 101, so it can move it to
102...

I've added lots of traces (see attached modified thread2.cxx, and the
trace output below).

Is this test expected to succeed without timeslicing?
Is it possible that the checks that thread#1 does at that critical
point might tip off the things to the wrong side?
Or is it that I might have some wrong configuration option set or unset?

If none of the above... Any idea on what could be wrong?

Regards.

These are the extra output that tries to show what is wrong:

INFO:<Main changing priority for thread #0 to 5.>
INFO:<Main changing priority for thread #1 to 6.>
INFO:<Main changing priority for thread #2 to 7.>
INFO:<Changing Priorities in main done.>
INFO:<Thread #0 Has q 0 => 1.>
INFO:<Thread #0 waiting on s0...>
INFO:<Thread #1 Has q 1 => 2.>
INFO:<Thread #1 waiting on s1...>
INFO:<Thread #2 Has q 2 => 3.>
INFO:<Thread #2 Posts s0.>
INFO:<Thread #0 waiting on s0 done.>
INFO:<Thread #0 Has q 3 => 4.>
INFO:<Thread #0 Posts s1.>
INFO:<Thread #0 Has q 4 => 5.>
INFO:<Thread #0 waiting on s0 (1/2)...>
INFO:<Thread #1 waiting on s1 done.>
INFO:<Thread #1 Has q 5 => 6.>
INFO:<Thread #1 changing priority for thread #0 to 9.>
INFO:<Thread #1 Posts s0.>
INFO:<Thread #1 Has q 6 => 7.>
INFO:<Thread #1 changing priority for thread #2 to 3.>
INFO:<Thread #2 Has q 7 => 8.>
INFO:<Thread #2 waiting on s2...>
INFO:<Thread #1 Has q 8 => 9.>
INFO:<Thread #1 Posts s2.>
INFO:<Thread #2 waiting on s2 done.>
INFO:<Thread #2 Has q 9 => 10.>
INFO:<Thread #2 changing priority for thread #1 to 6.>
INFO:<Thread #2 Has q 10 => 11.>
INFO:<Thread #2 changing its priority to 2.>
INFO:<Thread #2 Has q 11 => 12.>
INFO:<Thread #2 changing its priority to 7.>
INFO:<Thread #1 Has q 12 => 13.>
INFO:<Thread #1 Has q => 100.>
INFO:<Thread #1 changing priority for thread #2 to 6.>
INFO:<Thread #1 waiting for 'INFO:<Thread #2 Has q 100 => 101.>
INFO:<Thread #2 waiting for 'q' to be != 101...>

[-- Attachment #2: thread2.cxx --]
[-- Type: application/octet-stream, Size: 10479 bytes --]

//==========================================================================
//
//        thread2.cxx
//
//        Thread test 2
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
// -------------------------------------------                              
// This file is part of eCos, the Embedded Configurable Operating System.   
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, 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.,    
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 v2.                                               
//
// 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):     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++ );
    CYG_TEST_INFO("Thread #0 Has q 0 => 1.");
    CYG_TEST_INFO("Thread #0 waiting on s0...");
    s0.wait();
    CYG_TEST_INFO("Thread #0 waiting on s0 done.");
    CHECK(  3 == q++ );
    CYG_TEST_INFO("Thread #0 Has q 3 => 4.");
    CYG_TEST_INFO("Thread #0 Posts s1.");
    s1.post();
    CHECK(  4 == q++ );
    CYG_TEST_INFO("Thread #0 Has q 4 => 5.");
    CYG_TEST_INFO("Thread #0 waiting on s0 (1/2)...");
    s0.wait();
    CYG_TEST_INFO("Thread #0 waiting on s0 (1/2) done.");
    CYG_TEST_INFO("Thread #0 waiting on s0 (2/2)...");
    s0.wait();
    CYG_TEST_INFO("Thread #0 waiting on s0 (2/2) done.");
    CYG_TEST_PASS_FINISH("Thread 2 OK");
}

// ------------------------------------------------------------------------

static void entry1( CYG_ADDRWORD data )
{
    CHECK(  1 == q++ );
    CYG_TEST_INFO("Thread #1 Has q 1 => 2.");
    CYG_TEST_INFO("Thread #1 waiting on s1...");
    s1.wait();
    CYG_TEST_INFO("Thread #1 waiting on s1 done.");
    CHECK(  5 == q++ );
    CYG_TEST_INFO("Thread #1 Has q 5 => 6.");
    CYG_TEST_INFO("Thread #1 changing priority for thread #0 to 9.");
    thread0->set_priority(9);
    CYG_TEST_INFO("Thread #1 Posts s0.");
    s0.post();
    CHECK(  6 == q++ );
    CYG_TEST_INFO("Thread #1 Has q 6 => 7.");
    CYG_TEST_INFO("Thread #1 changing priority for thread #2 to 3.");
    thread2->set_priority(3);
    CHECK(  8 == q++ );
    CYG_TEST_INFO("Thread #1 Has q 8 => 9.");
    CYG_TEST_INFO("Thread #1 Posts s2.");
    s2.post();
    CHECK( 12 == q++ );
    CYG_TEST_INFO("Thread #1 Has q 12 => 13.");
    CHECK( 9 == thread0->get_priority() );
    CHECK( 6 == thread1->get_priority() );
    CHECK( 7 == thread2->get_priority() );
    q = 100;
    CYG_TEST_INFO("Thread #1 Has q => 100.");
#if !(CYGINT_KERNEL_SCHEDULER_UNIQUE_PRIORITIES) \
    && defined(CYGSEM_KERNEL_SCHED_TIMESLICE)
    CYG_TEST_INFO("Thread #1 changing priority for thread #2 to 6.");
    thread2->set_priority(6);
    CHECK( 6 == thread1->get_priority() );
    CHECK( 6 == thread2->get_priority() );

    CYG_TEST_INFO("Thread #1 waiting for 'q' to be != 100...");
    while ( 100 == q )
        ;
    CYG_TEST_INFO("Thread #1 waiting for 'q' to be != 100 done.");
    CHECK( 101 == q++ );
    CYG_TEST_INFO("Thread #1 Has q 101 => 102.");
    CYG_TEST_INFO("Thread #1 waiting on s1...");
    s1.wait();
    CYG_TEST_INFO("Thread #1 waiting on s1 done.");
    CHECK( 103 == q++ );
    CYG_TEST_INFO("Thread #1 Has q 103 => 104.");
#endif
    CYG_TEST_INFO("Thread #1 Posts s0.");
    s0.post();
    CYG_TEST_INFO("Thread #1 waiting on s1...");
    s1.wait();
    CYG_TEST_INFO("Thread #1 waiting on s1 done.");
}

// ------------------------------------------------------------------------

static void entry2( CYG_ADDRWORD data )
{
    CHECK(  2 == q++ );
    CYG_TEST_INFO("Thread #2 Has q 2 => 3.");
    CYG_TEST_INFO("Thread #2 Posts s0.");
    s0.post();
    CHECK(  7 == q++ );
    CYG_TEST_INFO("Thread #2 Has q 7 => 8.");
    CYG_TEST_INFO("Thread #2 waiting on s2...");
    s2.wait();
    CYG_TEST_INFO("Thread #2 waiting on s2 done.");
    CHECK(  9 == q++ );
    CYG_TEST_INFO("Thread #2 Has q 9 => 10.");
    CYG_TEST_INFO("Thread #2 changing priority for thread #1 to 6.");
    thread1->set_priority(6);
    CHECK( 10 == q++ );
    CYG_TEST_INFO("Thread #2 Has q 10 => 11.");
    CYG_TEST_INFO("Thread #2 changing its priority to 2.");
    thread2->set_priority(2);
    CHECK( 11 == q++ );
    CYG_TEST_INFO("Thread #2 Has q 11 => 12.");
    CYG_TEST_INFO("Thread #2 changing its priority to 7.");
    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++ );
    CYG_TEST_INFO("Thread #2 Has q 100 => 101.");
    CYG_TEST_INFO("Thread #2 waiting for 'q' to be != 101...");
    while ( 101 == q )
        ;
    CYG_TEST_INFO("Thread #2 waiting for 'q' to be != 101 done.");
    CHECK( 102 == q++ );
    CYG_TEST_INFO("Thread #2 Has q 102 => 103.");
    CYG_TEST_INFO("Thread #2 Posts s1.");
    s1.post();
#endif
    CYG_TEST_INFO("Thread #2 Posts s0.");
    s0.post();
    CYG_TEST_INFO("Thread #2 waiting on s2...");
    s2.wait();
    CYG_TEST_INFO("Thread #2 waiting on s2 done.");
}


// ------------------------------------------------------------------------

void thread2_main( void )
{
    CYG_TEST_INIT();
    
    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");

    thread0 = new_thread( entry0, 0 );
    thread1 = new_thread( entry1, 1 );
    thread2 = new_thread( entry2, 2 );

    thread0->resume();
    thread1->resume();
    thread2->resume();

    CYG_TEST_INFO("Main changing priority for thread #0 to 5.");
    thread0->set_priority(5);
    CYG_TEST_INFO("Main changing priority for thread #1 to 6.");
    thread1->set_priority(6);
    CYG_TEST_INFO("Main changing priority for thread #2 to 7.");
    thread2->set_priority(7);

    CYG_TEST_INFO("Changing Priorities in main done.");

    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_INFO("Thread2 test requires:\n"
                         "defined(CYGIMP_THREAD_PRIORITY) &&\n"
                         "!defined(CYGPKG_KERNEL_SMP_SUPPORT)\n");
    CYG_TEST_NA("Thread2 test requirements");
}

// ------------------------------------------------------------------------

#endif // CYGPKG_KERNEL_SMP_SUPPORT etc

// ------------------------------------------------------------------------
// EOF thread2.cxx

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-08-13 19:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-13 13:59 thread2 test gets deadlocked... Is it possible or am I missing some config option? David Fernandez
2013-08-13 19:19 ` David Fernandez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).