summaryrefslogtreecommitdiffstats
path: root/testsuites/sptests
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-05 14:36:30 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-04-06 09:08:20 +0200
commit97312fcc6da163d76b69bf8ce68fd791cf014c2a (patch)
tree6599b770a1587356b02b92b4003489f2e9bf8bc5 /testsuites/sptests
parentbsp/atsam: Fix mbuf allocation (diff)
downloadrtems-97312fcc6da163d76b69bf8ce68fd791cf014c2a.tar.bz2
score: Delete Thread_Wait_information::id
This field was only by the monitor in non-multiprocessing configurations. Add new field Thread_Wait_information::remote_id in multiprocessing configurations and use it for the remote procedure call thread queue. Add _Thread_Wait_get_id() to obtain the object identifier for debug and system information tools. Ensure the object layout via static asserts. Add test cases to sptests/spthreadq01.
Diffstat (limited to 'testsuites/sptests')
-rw-r--r--testsuites/sptests/spthreadq01/init.c367
-rw-r--r--testsuites/sptests/spthreadq01/spthreadq01.doc12
2 files changed, 373 insertions, 6 deletions
diff --git a/testsuites/sptests/spthreadq01/init.c b/testsuites/sptests/spthreadq01/init.c
index 6eef0c7454..c1812f6eaa 100644
--- a/testsuites/sptests/spthreadq01/init.c
+++ b/testsuites/sptests/spthreadq01/init.c
@@ -2,6 +2,8 @@
* COPYRIGHT (c) 1989-2009.
* On-Line Applications Research Corporation (OAR).
*
+ * Copyright (c) 2016 embedded brains GmbH.
+ *
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
@@ -13,17 +15,354 @@
#include <tmacros.h>
-#include <sys/types.h>
-#include <rtems/score/threadqimpl.h>
+#include <rtems.h>
+
+#include <rtems/score/threadimpl.h>
+
+#if defined(RTEMS_POSIX_API)
+ #include <fcntl.h>
+ #include <mqueue.h>
+ #include <semaphore.h>
+ #include <string.h>
+ #include <pthread.h>
+
+ #include <rtems/posix/mqueueimpl.h>
+#endif
const char rtems_test_name[] = "SPTHREADQ 1";
static Thread_queue_Control queue = THREAD_QUEUE_INITIALIZER( "Queue" );
+typedef struct {
+ Thread_Control *master;
+ rtems_id master_id;
+ rtems_id worker_id;
+ rtems_id sem;
+ rtems_id mtx;
+ rtems_id mq;
+ rtems_id br;
+#if defined(RTEMS_POSIX_API)
+ sem_t psem;
+ pthread_mutex_t pmtx;
+ pthread_cond_t pcv;
+ pthread_rwlock_t prw;
+ mqd_t pmq;
+#endif
+} test_context;
+
+static test_context test_instance;
+
+static void wait_for_worker(test_context *ctx)
+{
+ rtems_status_code sc;
+
+ sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void wake_up_master(test_context *ctx)
+{
+ rtems_status_code sc;
+
+ sc = rtems_event_transient_send(ctx->master_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static rtems_id get_wait_id(test_context *ctx)
+{
+ ISR_lock_Context lock_context;
+ void *lock;
+ rtems_id id;
+
+ lock = _Thread_Lock_acquire(ctx->master, &lock_context);
+ id = _Thread_Wait_get_id(ctx->master);
+ _Thread_Lock_release(lock, &lock_context);
+
+ return id;
+}
+
+static void classic_worker(test_context *ctx)
+{
+ rtems_status_code sc;
+ char buf[1];
+
+ wake_up_master(ctx);
+ rtems_test_assert(get_wait_id(ctx) == ctx->sem);
+
+ sc = rtems_semaphore_release(ctx->sem);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ wake_up_master(ctx);
+ rtems_test_assert(get_wait_id(ctx) == ctx->mtx);
+
+ sc = rtems_semaphore_release(ctx->mtx);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ wake_up_master(ctx);
+ rtems_test_assert(get_wait_id(ctx) == ctx->mq);
+
+ buf[0] = 'X';
+ sc = rtems_message_queue_send(ctx->mq, &buf[0], sizeof(buf));
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ wake_up_master(ctx);
+ rtems_test_assert(get_wait_id(ctx) == ctx->br);
+
+ sc = rtems_barrier_wait(ctx->br, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void posix_worker(test_context *ctx)
+{
+#if defined(RTEMS_POSIX_API)
+ int rv;
+ int eno;
+ char buf[1];
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ Objects_Locations location;
+ ISR_lock_Context lock_context;
+
+ wake_up_master(ctx);
+ rtems_test_assert(get_wait_id(ctx) == ctx->psem);
+
+ rv = sem_post(&ctx->psem);
+ rtems_test_assert(rv == 0);
+
+ eno = pthread_mutex_lock(&ctx->pmtx);
+ rtems_test_assert(eno == 0);
+
+ wake_up_master(ctx);
+ rtems_test_assert(get_wait_id(ctx) == ctx->pmtx);
+
+ eno = pthread_mutex_unlock(&ctx->pmtx);
+ rtems_test_assert(eno == 0);
+
+ eno = pthread_mutex_lock(&ctx->pmtx);
+ rtems_test_assert(eno == 0);
+
+ rtems_test_assert(get_wait_id(ctx) == ctx->pcv);
+
+ eno = pthread_cond_signal(&ctx->pcv);
+ rtems_test_assert(eno == 0);
+
+ eno = pthread_mutex_unlock(&ctx->pmtx);
+ rtems_test_assert(eno == 0);
+
+ eno = pthread_rwlock_wrlock(&ctx->prw);
+ rtems_test_assert(eno == 0);
+
+ wake_up_master(ctx);
+ rtems_test_assert(get_wait_id(ctx) == ctx->prw);
+
+ eno = pthread_rwlock_unlock(&ctx->prw);
+ rtems_test_assert(eno == 0);
+
+ wake_up_master(ctx);
+ the_mq_fd = _POSIX_Message_queue_Get_fd_interrupt_disable(
+ ctx->pmq,
+ &location,
+ &lock_context
+ );
+ _ISR_lock_ISR_enable(&lock_context);
+ rtems_test_assert(the_mq_fd != NULL);
+ rtems_test_assert(location == OBJECTS_LOCAL);
+ rtems_test_assert(get_wait_id(ctx) == the_mq_fd->Queue->Object.id);
+
+ buf[0] = 'x';
+ rv = mq_send(ctx->pmq, &buf[0], sizeof(buf), 0);
+ rtems_test_assert(rv == 0);
+#endif
+}
+
+static rtems_task worker(rtems_task_argument arg)
+{
+ test_context *ctx = (test_context *) arg;
+
+ rtems_test_assert(get_wait_id(ctx) == 0);
+
+ classic_worker(ctx);
+ posix_worker(ctx);
+}
+
+static void test_classic_init(test_context *ctx)
+{
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('S', 'E', 'M', ' '),
+ 0,
+ RTEMS_COUNTING_SEMAPHORE,
+ 0,
+ &ctx->sem
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('M', 'T', 'X', ' '),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
+ 0,
+ &ctx->mtx
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_message_queue_create(
+ rtems_build_name('M', 'Q', ' ', ' '),
+ 1,
+ 1,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->mq
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_barrier_create(
+ rtems_build_name('B', 'R', ' ', ' '),
+ RTEMS_BARRIER_AUTOMATIC_RELEASE,
+ 2,
+ &ctx->br
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test_posix_init(test_context *ctx)
+{
+#if defined(RTEMS_POSIX_API)
+ int rv;
+ int eno;
+ struct mq_attr attr;
+
+ rv = sem_init(&ctx->psem, 0, 0);
+ rtems_test_assert(rv == 0);
+
+ eno = pthread_mutex_init(&ctx->pmtx, NULL);
+ rtems_test_assert(eno == 0);
+
+ eno = pthread_cond_init(&ctx->pcv, NULL);
+ rtems_test_assert(eno == 0);
+
+ eno = pthread_rwlock_init(&ctx->prw, NULL);
+ rtems_test_assert(eno == 0);
+
+ memset(&attr, 0, sizeof(attr));
+ attr.mq_maxmsg = 1;
+ attr.mq_msgsize = sizeof(char);
+
+ ctx->pmq = mq_open("mq", O_CREAT | O_RDWR, 0x777, &attr);
+ rtems_test_assert(ctx->mq != -1);
+#endif
+}
+
+static void test_context_init(test_context *ctx)
+{
+ rtems_status_code sc;
+
+ ctx->master = _Thread_Get_executing();
+ ctx->master_id = rtems_task_self();
+
+ test_classic_init(ctx);
+ test_posix_init(ctx);
+
+ sc = rtems_task_create(
+ rtems_build_name('W', 'O', 'R', 'K'),
+ 2,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &ctx->worker_id
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(ctx->worker_id, worker, (rtems_task_argument) ctx);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test_classic_obj(test_context *ctx)
+{
+ rtems_status_code sc;
+ char buf[1];
+ size_t n;
+
+ wait_for_worker(ctx);
+
+ sc = rtems_semaphore_obtain(ctx->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ wait_for_worker(ctx);
+
+ sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ wait_for_worker(ctx);
+
+ buf[0] = 'Y';
+ n = 123;
+ sc = rtems_message_queue_receive(
+ ctx->mq,
+ &buf[0],
+ &n,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+ rtems_test_assert(buf[0] == 'X');
+ rtems_test_assert(n == sizeof(buf));
+
+ wait_for_worker(ctx);
+
+ sc = rtems_barrier_wait(ctx->br, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void test_posix_obj(test_context *ctx)
+{
+#if defined(RTEMS_POSIX_API)
+ int rv;
+ int eno;
+ char buf[1];
+ unsigned prio;
+ ssize_t n;
+
+ wait_for_worker(ctx);
+
+ rv = sem_wait(&ctx->psem);
+ rtems_test_assert(rv == 0);
+
+ wait_for_worker(ctx);
+
+ eno = pthread_mutex_lock(&ctx->pmtx);
+ rtems_test_assert(eno == 0);
+
+ eno = pthread_cond_wait(&ctx->pcv, &ctx->pmtx);
+ rtems_test_assert(eno == 0);
+
+ eno = pthread_mutex_unlock(&ctx->pmtx);
+ rtems_test_assert(eno == 0);
+
+ wait_for_worker(ctx);
+
+ eno = pthread_rwlock_wrlock(&ctx->prw);
+ rtems_test_assert(eno == 0);
+
+ wait_for_worker(ctx);
+
+ buf[0] = 'y';
+ prio = 1;
+ n = mq_receive(ctx->pmq, &buf[0], sizeof(buf), &prio);
+ rtems_test_assert(n == (ssize_t) sizeof(buf));
+ rtems_test_assert(buf[0] == 'x');
+ rtems_test_assert(prio == 0);
+#endif
+}
+
static rtems_task Init(
rtems_task_argument ignored
)
{
+ test_context *ctx = &test_instance;
+
TEST_BEGIN();
puts( "Init - _Thread_queue_Extract - thread not blocked on a thread queue" );
@@ -32,6 +371,10 @@ static rtems_task Init(
_Thread_Enable_dispatch();
/* is there more to check? */
+ test_context_init(ctx);
+ test_classic_obj(ctx);
+ test_posix_obj(ctx);
+
rtems_test_assert( queue.Queue.heads == NULL );
TEST_END();
@@ -43,7 +386,25 @@ static rtems_task Init(
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
-#define CONFIGURE_MAXIMUM_TASKS 1
+#define CONFIGURE_MAXIMUM_TASKS 2
+#define CONFIGURE_MAXIMUM_SEMAPHORES 2
+#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 1
+#define CONFIGURE_MAXIMUM_BARRIERS 1
+
+#if defined(RTEMS_POSIX_API)
+ #define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1
+ #define CONFIGURE_MAXIMUM_POSIX_MUTEXES 1
+ #define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 1
+ #define CONFIGURE_MAXIMUM_POSIX_RWLOCKS 1
+ #define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 1
+ #define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUE_DESCRIPTORS 1
+ #define CONFIGURE_MESSAGE_BUFFER_MEMORY \
+ (2 * CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(1, 1))
+#else
+ #define CONFIGURE_MESSAGE_BUFFER_MEMORY \
+ CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(1, 1)
+#endif
+
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
diff --git a/testsuites/sptests/spthreadq01/spthreadq01.doc b/testsuites/sptests/spthreadq01/spthreadq01.doc
index cf80f5dd6a..c3837af168 100644
--- a/testsuites/sptests/spthreadq01/spthreadq01.doc
+++ b/testsuites/sptests/spthreadq01/spthreadq01.doc
@@ -12,9 +12,15 @@ test set name: spthreadq01
directives:
- _Threadq_Extract
+ - THREAD_QUEUE_INITIALIZER()
+ - _Thread_queue_Extract()
+ - _Thread_Wait_get_id()
concepts:
-+ Ensure that when an attempt is made to extract a thread which is not blocked
- on a thread queue, that the behavior is as expected.
+ - Ensure that the thread queue initializer correctly initializes the thread
+ queue.
+ - Ensure that when an attempt is made to extract a thread which is not blocked
+ on a thread queue, that the behavior is as expected.
+ - Ensure that _Thread_Wait_get_id() returns the right object identifier for
+ various high-level objects.