view packages/kernel/current/tests/mqueue1.cxx @ 947:cf8d8ca2ed1d

* host/rawether.c (tap_init): Set the persistent flag on the tap device if requested by the user. This allows dhcpd and radvd to keep running on the tap device between invocations of the synth target. * doc/syntheth.sgml: Documentation for the persistent option.
author asl
date Tue, 15 Apr 2003 10:31:21 +0000
parents d2c90368aeef
children 74dbf4c3f2e1
line wrap: on
line source

/*========================================================================
//
//      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 */