[PATCH 1/2] psxmsgq05: Added priority unblocking mq tests
Lou Woods
irnhorse4 at gmail.com
Thu Aug 29 18:11:25 UTC 2019
From: Lou Woods <Lou.Woods at OARCorp.com>
This test exercises the unblocking order of a POSIX
message queue
-Added psxmsgq05 test to the make structure.
-Added tests, doc, and scn output.
updates #3791.
---
testsuites/psxtests/Makefile.am | 10 +
testsuites/psxtests/configure.ac | 1 +
testsuites/psxtests/psxmsgq05/init.c | 440 ++++++++++++++++++++++++++++
testsuites/psxtests/psxmsgq05/psxmsgq05.doc | 42 +++
testsuites/psxtests/psxmsgq05/psxmsgq05.scn | 4 +
testsuites/psxtests/psxmsgq05/system.h | 56 ++++
6 files changed, 553 insertions(+)
mode change 100755 => 100644 testsuites/psxtests/Makefile.am
create mode 100644 testsuites/psxtests/psxmsgq05/init.c
create mode 100644 testsuites/psxtests/psxmsgq05/psxmsgq05.doc
create mode 100644 testsuites/psxtests/psxmsgq05/psxmsgq05.scn
create mode 100644 testsuites/psxtests/psxmsgq05/system.h
diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am
old mode 100755
new mode 100644
index c12b036..52c9644
--- a/testsuites/psxtests/Makefile.am
+++ b/testsuites/psxtests/Makefile.am
@@ -685,6 +685,16 @@ psxmsgq04_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_psxmsgq04) \
$(support_includes) -I$(top_srcdir)/include
endif
+if TEST_psxmsgq05
+psx_tests += psxmsgq05
+psx_screens += psxmsgq05/psxmsgq05.scn
+psx_docs += psxmsgq05/psxmsgq05.doc
+psxmsgq05_SOURCES = psxmsgq05/init.c psxmsgq05/system.h \
+ include/pmacros.h ../support/src/test_support.c
+psxmsgq05_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_psxmsgq05) \
+ $(support_includes) -I$(top_srcdir)/include
+endif
+
if TEST_psxmutexattr01
psx_tests += psxmutexattr01
psx_screens += psxmutexattr01/psxmutexattr01.scn
diff --git a/testsuites/psxtests/configure.ac b/testsuites/psxtests/configure.ac
index bb44bb8..32d143a 100644
--- a/testsuites/psxtests/configure.ac
+++ b/testsuites/psxtests/configure.ac
@@ -112,6 +112,7 @@ RTEMS_TEST_CHECK([psxmsgq01])
RTEMS_TEST_CHECK([psxmsgq02])
RTEMS_TEST_CHECK([psxmsgq03])
RTEMS_TEST_CHECK([psxmsgq04])
+RTEMS_TEST_CHECK([psxmsgq05])
RTEMS_TEST_CHECK([psxmutexattr01])
RTEMS_TEST_CHECK([psxndbm01])
RTEMS_TEST_CHECK([psxobj01])
diff --git a/testsuites/psxtests/psxmsgq05/init.c b/testsuites/psxtests/psxmsgq05/init.c
new file mode 100644
index 0000000..ab06156
--- /dev/null
+++ b/testsuites/psxtests/psxmsgq05/init.c
@@ -0,0 +1,440 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2019 On-Line Applications Research. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define CONFIGURE_INIT
+#include "system.h"
+
+#include <fcntl.h> /* For O_* constants */
+#include <pthread.h>
+#include <semaphore.h>
+#include <mqueue.h>
+#include <sched.h>
+
+#include "test_support.h"
+
+const char rtems_test_name[] = "PSXMSGQ 5";
+
+#define DEFAULT_WAIT 5
+#define DEFAULT_BUFFER_SIZE 4
+#define TASKS 2
+
+struct task_args {
+ mqd_t *p_main_msgQ;
+ sem_t *p_task_sem;
+ int wait_timeout;
+ bool receive_test;
+};
+
+/* forward declarations to avoid warnings */
+static int test_msgQ_unblock_order(
+ bool receive_test, /* true to test receive order, false for
+ send order */
+ bool *task1_released, /* set by function to indicate task1 was
+ released */
+ bool *task2_released /* set by function to indicate task2 was
+ released */
+);
+static void *taskEntry( void *arg );
+
+/* The taskEntry function calls send or receive on the provided message queue
+ * and will block waiting to receive or send a message depending on the
+ * receive_test flag. Once the tasked is unblocked it will post the provided
+ * semaphore.
+ */
+static void *taskEntry( void *arg )
+{
+ char buffer[ DEFAULT_BUFFER_SIZE ];
+ struct timespec timeout;
+ int retval;
+ struct task_args *args = arg;
+
+ if ( args == NULL ) {
+ fprintf( stderr, "NULL argument passed to task, exiting\n" );
+
+ return NULL;
+ }
+
+#if 0
+ fprintf( stderr,
+ "task id %x with sem %x about to block\n",
+ pthread_self(),
+ (unsigned int) ( args->p_task_sem ) );
+#endif
+
+ if ( args->receive_test == true ) {
+ if ( args->wait_timeout != 0 ) {
+ retval = clock_gettime( CLOCK_REALTIME, &timeout );
+
+ if ( retval == ( -1 ) ) {
+ perror( "clock gettime failed" );
+
+ return NULL;
+ }
+
+ timeout.tv_sec += args->wait_timeout;
+ retval = mq_timedreceive( *( args->p_main_msgQ ),
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ NULL,
+ &timeout );
+
+ if ( retval == ( -1 ) ) {
+ perror( "time mq_receive returned unexpectedly." );
+
+ return NULL;
+ }
+ } else {
+ retval = mq_receive( *( args->p_main_msgQ ),
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ NULL );
+
+ if ( retval == ( -1 ) ) {
+ perror( "time mq_receive returned unexpectedly." );
+
+ return NULL;
+ }
+ }
+ } else {
+ if ( args->wait_timeout != 0 ) {
+ retval = clock_gettime( CLOCK_REALTIME, &timeout );
+
+ if ( retval == ( -1 ) ) {
+ perror( "clock gettime failed" );
+
+ return NULL;
+ }
+
+ timeout.tv_sec += args->wait_timeout;
+ retval = mq_timedsend( *( args->p_main_msgQ ),
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ 1,
+ &timeout );
+
+ if ( retval == ( -1 ) ) {
+ perror( "time mq_send returned unexpectedly." );
+
+ return NULL;
+ }
+ } else {
+ retval = mq_send( *( args->p_main_msgQ ),
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ 1 );
+
+ if ( retval == ( -1 ) ) {
+ perror( "time mq_send returned unexpectedly." );
+
+ return NULL;
+ }
+ }
+ }
+
+ retval = sem_post( args->p_task_sem );
+
+ if ( retval == ( -1 ) ) {
+ perror( "sem_post failed from the task" );
+ }
+
+#if 0
+ fprintf( stderr,
+ "given task sem %x\n",
+ (unsigned int) args->p_task_sem );
+ fflush( stderr );
+#endif
+
+ return NULL;
+}
+
+/* The theory of operation for test_msgQ_unblock_order is to get two
+ * tasks to block on a message queue in FIFO order and demonstrate that they
+ * are released in priority order. This will test blocking on message queue
+ * receive when receive_test is set to true otherwise it will test blocking
+ * on a message queue send call. A message queue of size of 1 is created and
+ * shared between the main thread and two worker threads. For the receive
+ * blocking case the main thread will wait for the two threads to come up and
+ * call receive on the queue. The lower priority task is allowed to come up
+ * first and call receive before the higher priority task. The main task will
+ * now send a message to the shared queue and see which thread posts its
+ * semaphore indicating which task was woken up. If the higher priority task
+ * posts its semaphore then the test is a success. The send unblock order works
+ * similarly but the main task must fill the message queue first and call
+ * receive once the two threads are blocked on their send call.
+ */
+static int test_msgQ_unblock_order(
+ bool receive_test,
+ bool *task1_released,
+ bool *task2_released
+)
+{
+ pthread_t task_id[ TASKS ];
+ const int task_priority[ TASKS ] = { 50, 60 };
+ struct sched_param task_params[ TASKS ];
+ pthread_attr_t task_attr[ TASKS ];
+ struct task_args task_args[ TASKS ];
+ sem_t task_sem[ TASKS ];
+ const int task_self_priority = 40;
+ pthread_t task_self;
+ struct sched_param self_params;
+ mqd_t main_msgQ;
+ struct mq_attr mq_attribs;
+ struct timespec no_wait_tmo;
+ int retval;
+ int success = 0;
+ size_t lcv;
+ char buffer[] = { '1', '2', '3', '4' };
+ const char mq_name[] = "/psxmq5";
+
+ if ( task1_released != NULL )
+ *task1_released = false;
+ else
+ return -1;
+
+ if ( task2_released != NULL )
+ *task2_released = false;
+ else
+ return -1;
+
+ memset( &no_wait_tmo, 0, sizeof( no_wait_tmo ) );
+
+ task_self = pthread_self();
+ mq_attribs.mq_maxmsg = 1;
+ mq_attribs.mq_msgsize = DEFAULT_BUFFER_SIZE;
+
+ main_msgQ = mq_open( mq_name,
+ O_CREAT | O_RDWR | O_EXCL,
+ 0666,
+ &mq_attribs );
+
+ if ( main_msgQ == ( -1 ) ) {
+ perror( "mq_open failed" );
+
+ return -1;
+ }
+
+ for ( lcv = 0; lcv < TASKS; lcv++ ) {
+ retval = sem_init( &task_sem[ lcv ], 0, 0 );
+
+ if ( retval == ( -1 ) ) {
+ perror( "semaphore creation failed" );
+
+ return -1;
+ }
+ }
+
+ self_params.sched_priority = task_self_priority;
+ retval = pthread_setschedparam( task_self, SCHED_FIFO, &self_params );
+
+ if ( retval == ( -1 ) ) {
+ perror( "failed to set main task priority" );
+
+ return -1;
+ }
+
+ if ( receive_test == false ) {
+ /* fill up the queue */
+ retval = mq_send( main_msgQ, buffer, DEFAULT_BUFFER_SIZE, 1 );
+
+ if ( retval == ( -1 ) ) {
+ perror( "mq_send failed to fill queue" );
+
+ return -1;
+ }
+ }
+
+ for ( lcv = 0; lcv < TASKS; lcv++ ) {
+ /* Task are put into the wait state in FIFO order */
+ task_params[ lcv ].sched_priority = task_priority[ lcv ];
+ pthread_attr_init( &task_attr[ lcv ] );
+ pthread_attr_setinheritsched( &task_attr[ lcv ], PTHREAD_EXPLICIT_SCHED );
+ pthread_attr_setschedpolicy( &task_attr[ lcv ], SCHED_FIFO );
+ pthread_attr_setschedparam( &task_attr[ lcv ], &task_params[ lcv ] );
+ pthread_attr_setdetachstate( &task_attr[ lcv ], PTHREAD_CREATE_DETACHED );
+
+ task_args[ lcv ].p_main_msgQ = &main_msgQ;
+ task_args[ lcv ].p_task_sem = &task_sem[ lcv ];
+ task_args[ lcv ].wait_timeout = DEFAULT_WAIT;
+ task_args[ lcv ].receive_test = receive_test;
+
+ retval = pthread_create( &task_id[ lcv ],
+ &task_attr[ lcv ],
+ &taskEntry,
+ (void *) &task_args[ lcv ] );
+
+ if ( retval == ( -1 ) ) {
+ perror( "pthread_create failed for task" );
+
+ return -1;
+ }
+
+ sched_yield();
+ }
+
+ sleep( 1 );
+#if 0
+ fprintf( stderr,
+ "task1 id %x sem %x; task2 id %x sem %x\n",
+ task_id[ 0 ],
+ (unsigned int) &task_sem[ 0 ],
+ task_id[ 1 ],
+ (unsigned int) &task_sem[ 1 ] );
+#endif
+
+ if ( receive_test == true ) {
+ retval = mq_timedsend( main_msgQ,
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ 1,
+ &no_wait_tmo );
+
+ if ( retval == ( -1 ) ) {
+ perror( "mq_send failed to add item" );
+
+ return -1;
+ }
+ } else {
+ retval = mq_timedreceive( main_msgQ,
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ NULL,
+ &no_wait_tmo );
+
+ if ( retval == ( -1 ) ) {
+ perror( "mq_receive failed to retrieve item" );
+
+ return -1;
+ }
+ }
+
+ sched_yield();
+
+ retval = sem_timedwait( &task_sem[ 0 ], &no_wait_tmo );
+
+ if ( retval == ( -1 ) && errno == ETIMEDOUT )
+ *task1_released = false;
+ else if ( retval == 0 )
+ *task1_released = true;
+ else
+ success = -1;
+
+ retval = sem_timedwait( &task_sem[ 1 ], &no_wait_tmo );
+
+ if ( retval == ( -1 ) && errno == ETIMEDOUT )
+ *task2_released = false;
+ else if ( retval == ( 0 ) )
+ *task2_released = true;
+ else
+ success = -1;
+
+ /* clean up the remaining thread */
+ if ( receive_test == true ) {
+ mq_timedsend( main_msgQ,
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ 1,
+ &no_wait_tmo );
+ } else {
+ mq_timedreceive( main_msgQ,
+ buffer,
+ DEFAULT_BUFFER_SIZE,
+ NULL,
+ &no_wait_tmo );
+ }
+
+ sched_yield();
+
+ for ( lcv = 0; lcv < TASKS; lcv++ ) {
+ retval = pthread_cancel( task_id[ lcv ] );
+
+ if ( retval == ( -1 ) )
+ perror( "failed to cancel task" );
+
+ retval = sem_destroy( &task_sem[ lcv ] );
+
+ if ( retval == ( -1 ) )
+ perror( "failed to delete semaphore" );
+ }
+
+ retval = mq_close( main_msgQ );
+
+ if ( retval == ( -1 ) )
+ perror( "failed to close message queue" );
+
+ retval = mq_unlink( mq_name );
+
+ if ( retval == ( -1 ) )
+ perror( "failed to unlink message queue" );
+
+ return success;
+}
+
+/* This test demonstrates the unblock order of the POSIX message queue
+ * when two threads are forced to block on the same message queue call. The
+ * expected behavior is for the higher priority thread to be unblocked and
+ * receive a message ahead of a lower priority thread also blocked on a receive
+ * call. The behavior is expected to be the same when two or more threads
+ * attempt to send at the same time and have to block. This test does not
+ * address message priority
+ */
+void *POSIX_Init( void *argument )
+{
+ int success;
+ bool task1_released;
+ bool task2_released;
+
+ TEST_BEGIN();
+
+ puts( "Init - send priority unblock order" );
+
+ success = test_msgQ_unblock_order(
+ false,
+ &task1_released,
+ &task2_released );
+ rtems_test_assert( success == ( 0 ) );
+
+ rtems_test_assert( task2_released == true && task1_released == false );
+
+ puts( "Init - receive priority unblock order" );
+
+ success = test_msgQ_unblock_order(
+ true,
+ &task1_released,
+ &task2_released );
+ rtems_test_assert( success == ( 0 ) );
+
+ rtems_test_assert( task2_released == true && task1_released == false );
+
+ TEST_END();
+ rtems_test_exit( 0 );
+
+ return NULL; /* just so the compiler thinks we returned something */
+}
diff --git a/testsuites/psxtests/psxmsgq05/psxmsgq05.doc b/testsuites/psxtests/psxmsgq05/psxmsgq05.doc
new file mode 100644
index 0000000..e9eae49
--- /dev/null
+++ b/testsuites/psxtests/psxmsgq05/psxmsgq05.doc
@@ -0,0 +1,42 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (C) 2019 On-Line Applications Research. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxmsgq05
+
+directives:
+
+ mq_send
+ mq_timedsend
+ mq_receive
+ mq_timedreceive
+
+concepts:
+
++ Ensure that threads are unblocked in priority order while waiting to send or
+ receive a queued message.
diff --git a/testsuites/psxtests/psxmsgq05/psxmsgq05.scn b/testsuites/psxtests/psxmsgq05/psxmsgq05.scn
new file mode 100644
index 0000000..9c43710
--- /dev/null
+++ b/testsuites/psxtests/psxmsgq05/psxmsgq05.scn
@@ -0,0 +1,4 @@
+*** POSIX MESSAGE QUEUE TEST 5 ***
+Init - send priority unblock order
+Init - receive priority unblock order
+*** END OF POSIX MESSAGE QUEUE TEST 5 ***
diff --git a/testsuites/psxtests/psxmsgq05/system.h b/testsuites/psxtests/psxmsgq05/system.h
new file mode 100644
index 0000000..28e68f9
--- /dev/null
+++ b/testsuites/psxtests/psxmsgq05/system.h
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2019 On-Line Applications Research. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* functions */
+
+#include <pmacros.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+#include <tmacros.h>
+
+void *POSIX_Init(
+ void *argument
+);
+
+/* configuration information */
+
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 3
+#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 1
+#define CONFIGURE_MAXIMUM_TIMERS 1
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#include <rtems/confdefs.h>
+/* end of include file */
--
1.8.3.1
More information about the devel
mailing list