summaryrefslogtreecommitdiffstats
path: root/testsuites/libtests/block08
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-19 08:55:18 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-19 08:55:18 +0000
commit64734fc14b1015c1568c2906c9aeab1c6a7db82d (patch)
tree853af83fb05c8fcf05e3d7c44308895377b0028d /testsuites/libtests/block08
parent2010-01-18 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-64734fc14b1015c1568c2906c9aeab1c6a7db82d.tar.bz2
updates and new test cases
Diffstat (limited to 'testsuites/libtests/block08')
-rw-r--r--testsuites/libtests/block08/Makefile.am50
-rw-r--r--testsuites/libtests/block08/bdbuf_test1_1.c146
-rw-r--r--testsuites/libtests/block08/bdbuf_test1_2.c161
-rw-r--r--testsuites/libtests/block08/bdbuf_test1_3.c177
-rw-r--r--testsuites/libtests/block08/bdbuf_test1_4.c179
-rw-r--r--testsuites/libtests/block08/bdbuf_test1_5.c146
-rw-r--r--testsuites/libtests/block08/bdbuf_test2_1.c195
-rw-r--r--testsuites/libtests/block08/bdbuf_test2_2.c196
-rw-r--r--testsuites/libtests/block08/bdbuf_test3_1.c184
-rw-r--r--testsuites/libtests/block08/bdbuf_test3_2.c197
-rw-r--r--testsuites/libtests/block08/bdbuf_test3_3.c208
-rw-r--r--testsuites/libtests/block08/bdbuf_test4_1.c176
-rw-r--r--testsuites/libtests/block08/bdbuf_test4_2.c161
-rw-r--r--testsuites/libtests/block08/bdbuf_test4_3.c155
-rw-r--r--testsuites/libtests/block08/bdbuf_tests.c271
-rw-r--r--testsuites/libtests/block08/bdbuf_tests.h504
-rw-r--r--testsuites/libtests/block08/block08.doc319
-rw-r--r--testsuites/libtests/block08/block08.scn86
-rw-r--r--testsuites/libtests/block08/init.c32
-rw-r--r--testsuites/libtests/block08/system.h56
-rw-r--r--testsuites/libtests/block08/test_disk.c154
21 files changed, 3753 insertions, 0 deletions
diff --git a/testsuites/libtests/block08/Makefile.am b/testsuites/libtests/block08/Makefile.am
new file mode 100644
index 0000000000..802c14f594
--- /dev/null
+++ b/testsuites/libtests/block08/Makefile.am
@@ -0,0 +1,50 @@
+##
+## Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+## Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+##
+## The license and distribution terms for this file may be
+## found in the file LICENSE in this distribution or at
+## http://www.rtems.com/license/LICENSE.
+## $Id$
+##
+
+MANAGERS = all
+
+rtems_tests_PROGRAMS = block08
+block08_SOURCES = init.c \
+ system.h \
+ bdbuf_tests.c \
+ bdbuf_tests.h \
+ test_disk.c \
+ bdbuf_test1_1.c \
+ bdbuf_test1_2.c \
+ bdbuf_test1_3.c \
+ bdbuf_test1_4.c \
+ bdbuf_test1_5.c \
+ bdbuf_test2_1.c \
+ bdbuf_test2_2.c \
+ bdbuf_test3_1.c \
+ bdbuf_test3_2.c \
+ bdbuf_test3_3.c \
+ bdbuf_test4_1.c \
+ bdbuf_test4_2.c \
+ bdbuf_test4_3.c
+
+dist_rtems_tests_DATA = block08.scn block08.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+block08_LDADD = $(MANAGERS_NOT_WANTED:%=$(PROJECT_LIB)/no-%.rel)
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(block08_OBJECTS) $(block08_LDADD)
+LINK_LIBS = $(block08_LDLIBS)
+
+block08$(EXEEXT): $(block08_OBJECTS) $(block08_DEPENDENCIES)
+ @rm -f block08$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/libtests/block08/bdbuf_test1_1.c b/testsuites/libtests/block08/bdbuf_test1_1.c
new file mode 100644
index 0000000000..1152af25b7
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test1_1.c
@@ -0,0 +1,146 @@
+/*! @file
+ * @brief Check the behaviour of rtems_bdbuf_read() function
+ * with different reports from disk device driver.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read() function and return 0 from disk device
+ * driver ioctl() function, and the result of asynchronous read
+ * complete notification is successful.
+ * -# Check that rtems_bdbuf_read() returns RTEMS_SUCCESSFUL and
+ * provides buffer descriptor.
+ * -# Call rtems_bdbuf_read() function and return -1 from disk device
+ * driver ioctl() function (there will be no asynchronous read
+ * complete notification).
+ * -# Check that rtems_bdbuf_read() returns RTEMS_IO_ERROR.
+ * -# Call rtems_bdbuf_read() function and return 0 from disk device
+ * driver ioctl() function, but the result of asynchronous read
+ * complete notification is faulty (with some erroneous status).
+ * -# Check that rtems_bdbuf_read() returns that status and does not
+ * return buffer descriptor.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test1_1_thread1(rtems_task_argument arg);
+
+#define TEST_BLK_NUM 10
+
+void
+bdbuf_test1_1_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 1.1");
+
+ /*
+ * Create working thread that will call rtems_bdbuf_read() function.
+ */
+ START_THREAD(1, bdbuf_test1_1_thread1);
+
+ /*
+ * Step 1:
+ * Check that rtems_bdbuf_read() returns RTEMS_SUCCESSFUL
+ * when device driver returns 0 from ioctl() call and
+ * return RTEMS_SUCCESSFUL status in asynchronous
+ * callback notification.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("2");
+
+ CONTINUE_THREAD(1);
+
+ /*
+ * Step 3:
+ * Check that rtems_bdbuf_read() returns RTEMS_IO_ERROR
+ * return code, when device driver returns -1 from ioctl() call.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(-1, EFAULT, RTEMS_SUCCESSFUL, 0);
+
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("4");
+
+ CONTINUE_THREAD(1);
+
+ /*
+ * Step 5:
+ * Check that rtems_bdbuf_read() returns status obtained
+ * from device driver via asynchonous notification.
+ * On this step device driver returns 0 from ioctl() call,
+ * but notification callback is called with RTEMS_NO_MEMORY status.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_NO_MEMORY, EFAULT);
+
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("6");
+
+ CONTINUE_THREAD(1);
+
+ TEST_END();
+}
+
+
+static rtems_task
+bdbuf_test1_1_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd1 = NULL;
+ rtems_bdbuf_buffer *bd2 = NULL;
+
+ /*
+ * Step 1-2:
+ * Successful read operation.
+ */
+ rc = rtems_bdbuf_read(test_dev, 0, &bd1);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ rc = rtems_bdbuf_release(bd1);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 3-4:
+ * Read operation fails with RTEMS_IO_ERROR code.
+ * The function shall not update user pointer.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd2);
+ if (rc != RTEMS_IO_ERROR || bd2 != NULL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 5-6:
+ * Read operation fails with RTEMS_NO_MEMORY code.
+ * The function shall not update user pointer.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd2);
+ if (rc != RTEMS_NO_MEMORY || bd2 != NULL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ THREAD_END();
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_test1_2.c b/testsuites/libtests/block08/bdbuf_test1_2.c
new file mode 100644
index 0000000000..255db3b321
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test1_2.c
@@ -0,0 +1,161 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_read() handles two readers waiting
+ * for a buffer with the same block number in cases when disk device
+ * driver reports failure in read complete notification.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read() function in thread #1 and block on
+ * waiting for read complete notification.
+ * -# Call rtems_bdbuf_read() function in thread #2 for the same
+ * block number. As the result it blocks on this read as well
+ * (but it will block on transfer semaphore).
+ * -# Disk device reports an error in read complete notification.
+ * As the result an error is returned from rtems_bdbuf_read() in
+ * thread #1.
+ * -# rtems_bdbuf_read() called in thread #2 should try to re-read
+ * data again so disk device ioctl() function is called again for
+ * this block number.
+ * -# Disk device reports an error in read complete notification.
+ * As the result an error is returned from rtems_bdbuf_read()
+ * in thread #2.
+ * .
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test1_2_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test1_2_thread2(rtems_task_argument arg);
+
+#define TEST_BLK_NUM 20
+
+void
+bdbuf_test1_2_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 1.2");
+
+ START_THREAD(1, bdbuf_test1_2_thread1);
+ START_THREAD(2, bdbuf_test1_2_thread2);
+
+ /*
+ * Step 1:
+ * Thread #1 calls rtems_bdbuf_read() and we block
+ * this thread on data transfer operation.
+ */
+ WAIT_DRV_MSG(&msg);
+
+ /*
+ * Step 2:
+ * Thread #2 calls rtems_bdbuf_read() for the same
+ * block number, as the result it shall block waiting
+ * on buffer state change.
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure thread #2 managed to block on the buffer. */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 3:
+ * Unblock thread #1 by reporting data transfer result.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_NO_MEMORY, EFAULT);
+
+ /*
+ * Wait for sync from thread #1.
+ */
+ WAIT_THREAD_SYNC(1);
+ CONTINUE_THREAD(1);
+ TEST_CHECK_RESULT("3");
+
+ /*
+ * Step 4:
+ * For thread #2 bdbuf shall try to re-read data.
+ * As the result we will get read call to device driver.
+ */
+ WAIT_DRV_MSG(&msg);
+
+ /* Check that thread #2 is still blocked */
+ CHECK_THREAD_BLOCKED(2);
+ /*
+ * Step 5:
+ * Report an error again from the driver.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_NO_MEMORY, EFAULT);
+
+ /*
+ * Wait for sync from thread #2.
+ */
+ WAIT_THREAD_SYNC(2);
+ CONTINUE_THREAD(2);
+ TEST_CHECK_RESULT("5");
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test1_2_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1 - 3:
+ * Try to read blk #N on thread #1
+ * We will block on this read and meanwhile
+ * thread #2 will try to read the same block.
+ * After blocking on read in thread #2, device
+ * driver will notify about an error, and as the
+ * result this call will return an error.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_NO_MEMORY || bd != NULL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test1_2_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * Try to read block #N. Right now thread #1 is waiting
+ * on data transfer operation, so we will block here as well.
+ *
+ * Step 4:
+ * Due to the fact that thread #1 failed to read required block
+ * number, bdbuf library should ask for re-read data again.
+ * But main test task will agin tell device driver to return
+ * RTEMS_NO_MEMORY data transfer result.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_NO_MEMORY || bd != NULL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(2);
+
+ THREAD_END();
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_test1_3.c b/testsuites/libtests/block08/bdbuf_test1_3.c
new file mode 100644
index 0000000000..bde277f617
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test1_3.c
@@ -0,0 +1,177 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_read() handles two readers waiting
+ * for a buffer with the same block number in cases when disk device
+ * driver reports failure in read complete notification.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read() function in thread #1 and block on
+ * waiting for read complete notification.
+ * -# Call rtems_bdbuf_read() function in thread #2 for the same block
+ * number. As the result it blocks on this read as well (but it will
+ * block on transfer semaphore).
+ * -# Disk device reports an error in read complete notification.
+ * As the result an error is returned from rtems_bdbuf_read()
+ * in thread #1.
+ * -# rtems_bdbuf_read() called in thread #2 should try to re-read data
+ * again so disk device ioctl() function is called again for this
+ * block number.
+ * -# This time disk device reports success in read complete notification.
+ * As the result rtems_bdbuf_read() in thread #2 shall return
+ * RTEMS_SUCCESSFUL and provide buffer descriptor.
+ * -# Call rtems_bdbuf_release() function in thread #2.
+ * .
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test1_3_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test1_3_thread2(rtems_task_argument arg);
+
+#define TEST_BLK_NUM 30
+
+void
+bdbuf_test1_3_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 1.3");
+
+ START_THREAD(1, bdbuf_test1_3_thread1);
+ START_THREAD(2, bdbuf_test1_3_thread2);
+
+ /*
+ * Step 1:
+ * Thread #1 calls rtems_bdbuf_read() and we block
+ * this thread on data transfer operation.
+ */
+ WAIT_DRV_MSG(&msg);
+
+ /*
+ * Step 2:
+ * Thread #2 calls rtems_bdbuf_read() for the same
+ * block number, as the result it shall block waiting
+ * on buffer state change.
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure thread #2 managed to block on the buffer. */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 3:
+ * Unblock thread #1 by reporting erroneous data transfer result.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_NO_MEMORY, EFAULT);
+
+ /*
+ * Wait for sync from thread #1.
+ */
+ WAIT_THREAD_SYNC(1);
+ CONTINUE_THREAD(1);
+ TEST_CHECK_RESULT("3");
+
+ /* Check thread #2 is still blocked */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 4:
+ * For thread #2 bdbuf shall try to re-read data.
+ * As the result we will get read call to device driver.
+ */
+ WAIT_DRV_MSG(&msg);
+
+ /*
+ * Step 5:
+ * This time report success from the driver and
+ * rtems_bdbuf_read() in thread #2 shall return
+ * RTEMS_SUCCESSFUL.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Wait for sync from thread #2.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("5");
+
+ /*
+ * Step 6:
+ * Release buffer in thread #2
+ */
+ CONTINUE_THREAD(2);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test1_3_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1 - 3:
+ * Try to read blk #N on thread #1
+ * We will block on this read and meanwhile
+ * thread #2 will try to read the same block.
+ * After blocking on read in thread #2, device
+ * driver will notify about an error, and as the
+ * result this call will return an error.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_NO_MEMORY || bd != NULL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test1_3_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * Try to read block #N. Right now thread #1 is waiting
+ * on data transfer operation, so we will block here as well.
+ *
+ * Step 4-5:
+ * Due to the fact that thread #1 failed to read required block
+ * number, bdbuf library should ask for re-read data again.
+ * Time time main task will tell driver to report success.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL || bd == NULL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(2);
+
+ /*
+ * Step 6:
+ * Release buffer.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_test1_4.c b/testsuites/libtests/block08/bdbuf_test1_4.c
new file mode 100644
index 0000000000..a3f4e69671
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test1_4.c
@@ -0,0 +1,179 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_read() handles two readers waiting
+ * for a buffer with the same block number in cases when disk device
+ * driver reports success in read complete notification.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read() function in thread #1 and block on
+ * waiting for read complete notification.
+ * -# Call rtems_bdbuf_read() function in thread #2 for the same
+ * block number. As the result it blocks on this read as well
+ * (but it will block on transfer semaphore).
+ * -# Disk device reports success in read complete notification.
+ * As the result rtems_bdbuf_read() function returns RTEMS_SUCCESSFUL
+ * in thread #1.
+ * -# Thread #1 releases buffer with rtems_bdbuf_release() function.
+ * -# rtems_bdbuf_read() function in thread #2 unlocks and
+ * returns RTEMS_SUCCESSFUL.
+ * -# Call rtems_bdbuf_release() function in thread #2.
+ * .
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test1_4_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test1_4_thread2(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM 40
+
+void
+bdbuf_test1_4_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 1.4");
+
+ START_THREAD(1, bdbuf_test1_4_thread1);
+ START_THREAD(2, bdbuf_test1_4_thread2);
+
+ /*
+ * Step 1:
+ * Thread #1 calls rtems_bdbuf_read() and we block
+ * this thread on data transfer operation.
+ */
+ WAIT_DRV_MSG(&msg);
+
+ /*
+ * Step 2:
+ * Thread #2 calls rtems_bdbuf_read() for the same
+ * block number, as the result it shall block waiting
+ * on buffer state change (waiting on TRANSFER state).
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure threads #1 and #2 managed blocked on the buffer. */
+ CHECK_THREAD_BLOCKED(1);
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 3:
+ * Unblock thread #1 by reporting successful data transfer result.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Wait for sync from thread #1.
+ */
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("3");
+
+ /*
+ * Check that thread #2 is still blocked.
+ */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 4:
+ * Thread #1 releases buffer with bdbuf_release() call.
+ */
+ CONTINUE_THREAD(1);
+
+ /*
+ * Step 5:
+ * On buffer release operation, we should have unblock
+ * of thread #2 that is wating on read buffer operation.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("5");
+
+ /*
+ * Step 6:
+ * Thread #2 release buffer.
+ */
+ CONTINUE_THREAD(2);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test1_4_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1 - 3:
+ * Try to read blk #N on thread #1
+ * We will block on this read and meanwhile
+ * thread #2 will try to read the same block.
+ * After blocking on read in thread #2, device
+ * driver will notify successful completion of
+ * date transfer, and as the result this call
+ * will return valid buffer.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 4:
+ * Release buffer returned on the previous step.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test1_4_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * Try to read block #N. Right now thread #1 is waiting
+ * on data transfer operation, so we will block here as well.
+ *
+ * Step 5:
+ * On step 4 thread #1 releases buffer and as the result
+ * our read operation should finish with success.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(2);
+
+ /*
+ * Step 6:
+ * Release buffer returned on the previous step.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+
diff --git a/testsuites/libtests/block08/bdbuf_test1_5.c b/testsuites/libtests/block08/bdbuf_test1_5.c
new file mode 100644
index 0000000000..f4a1156bd4
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test1_5.c
@@ -0,0 +1,146 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_read() handles read request
+ * for a buffer that is owned by an application.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read() function in thread #1 and
+ * provide successful read complete notification for this operation.
+ * As the result rtems_bdbuf_read() returns RTEMS_SUCCESSFUL
+ * in thread #1.
+ * -# In thread #2 call rtems_bdbuf_read() function for the same
+ * block number. A buffer for this block is owned by an application
+ * and as the result thread #2 block on this function.
+ * -# Call rtems_bdbuf_release() function in thread #1 in order to give
+ * it back under control of bdbuf library.
+ * -# Buffer now is ready to be returned for another application and
+ * as the result rtems_bdbuf_read() unblocks and returns
+ * RTEMS_SUCCESSFUL in thread #2.
+ * -# Call rtems_bdbuf_release() function in thread #2.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test1_5_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test1_5_thread2(rtems_task_argument arg);
+
+#define TEST_BLK_NUM 50
+
+void
+bdbuf_test1_5_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 1.5");
+
+ START_THREAD(1, bdbuf_test1_5_thread1);
+ START_THREAD(2, bdbuf_test1_5_thread2);
+
+ /*
+ * Step 1:
+ * Thread #1 calls rtems_bdbuf_read() and successfully
+ * get requested buffer.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("1");
+
+ /*
+ * Step 2:
+ * Thread #2 calls rtems_bdbuf_read() and blocks
+ * on this call because thread #1 owns a buffer.
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure thread #2 managed to block on a read request. */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 3:
+ * Now thread #1 releases a buffer.
+ */
+ CONTINUE_THREAD(1);
+
+ /*
+ * Step 4:
+ * Thread #2 should unblock now and get the buffer.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("4");
+
+ /*
+ * Step 5:
+ * Thread #2 release buffer.
+ */
+ CONTINUE_THREAD(2);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test1_5_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1:
+ * read blk #N on thread #1
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 3:
+ * Release buffer returned on step 1.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test1_5_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * Try to read block #N. Right now thread #1 owns
+ * this buffer, so we will block waiting for buffer.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(2);
+
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_test2_1.c b/testsuites/libtests/block08/bdbuf_test2_1.c
new file mode 100644
index 0000000000..33d5dd970f
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test2_1.c
@@ -0,0 +1,195 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_read() and rtems_bdbuf_release_modified()
+ * coexist. rtems_bdbuf_read() is blocked when required buffer is being
+ * transferred.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read() function in thread #1 and block on
+ * waiting for read complete notification.
+ * -# Call rtems_bdbuf_read() function in thread #2 for the same block
+ * number. As the result it blocks on this read as well
+ * (but it will block on transfer semaphore).
+ * -# Disk device reports success in read complete notification.
+ * As the result rtems_bdbuf_read() function retuens RTEMS_SUCCESSFUL
+ * in thread #1.
+ * -# Thread #1 releases buffer with rtems_bdbuf_release_modified() function.
+ * -# rtems_bdbuf_read() function in thread #2 unlocks and returns
+ * RTEMS_SUCCESSFUL.
+ * -# Wait swapout period and check that the buffer is not requested to
+ * be flushed to a disk.
+ * -# Call rtems_bdbuf_release() function in thread #2.
+ * -# Check that this block number is requested for a flush in swapout period.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test2_1_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test2_1_thread2(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM 60
+
+void
+bdbuf_test2_1_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 2.1");
+
+ /*
+ * Create two working threads that will call rtems_bdbuf_read() function.
+ */
+ START_THREAD(1, bdbuf_test2_1_thread1);
+ START_THREAD(2, bdbuf_test2_1_thread2);
+
+ /*
+ * Step 1:
+ * Thread #1 calls rtems_bdbuf_read() and we block
+ * this thread on data transfer operation.
+ */
+ WAIT_DRV_MSG(&msg);
+
+ /*
+ * Step 2:
+ * Thread #2 calls rtems_bdbuf_read() for the same
+ * block number, as the result it shall block waiting
+ * on buffer state change (waiting on TRANSFER state).
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure thread #2 managed to block on the buffer. */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 3:
+ * Unblock thread #1 by reporting successful data transfer result.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Wait for sync from thread #1.
+ */
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("3");
+
+ /* Check thread #2 is still blocked */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 4:
+ * Thread #1 releases buffer with bdbuf_release_modified() call.
+ */
+ CONTINUE_THREAD(1);
+
+ /*
+ * Step 5:
+ * On buffer release operation, we should have unblock
+ * of thread #2 that is waiting on read buffer operation.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("5");
+
+ /*
+ * Step 6:
+ * Wait swapout period and check that there is no
+ * request to flush buffer onto a disk.
+ */
+ CHECK_NO_DRV_MSG();
+
+ /*
+ * Step 7:
+ * Thread #2 releases buffer with bdbuf_release() call.
+ */
+ CONTINUE_THREAD(2);
+
+ /*
+ * Step 8:
+ * Check that in swapout interval disk device
+ * driver is requested to flush buffer.
+ */
+ WAIT_DRV_MSG_WR(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test2_1_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1 - 3:
+ * Try to read blk #N on thread #1
+ * We will block on this read and meanwhile
+ * thread #2 will try to read the same block.
+ * After blocking on read in thread #2, device
+ * driver will notify successful completion of
+ * date transfer, and as the result this call
+ * will return valid buffer.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 4:
+ * Release buffer returned on the previous step.
+ */
+ rc = rtems_bdbuf_release_modified(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test2_1_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * Try to read block #N. Right now thread #1 is waiting
+ * on data transfer operation, so we will block here as well.
+ *
+ * Step 5:
+ * On step 4 thread #1 releases buffer and as the result
+ * our read operation should finish with success.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(2);
+
+ /*
+ * Step 7:
+ * Release buffer.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_test2_2.c b/testsuites/libtests/block08/bdbuf_test2_2.c
new file mode 100644
index 0000000000..3e858708aa
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test2_2.c
@@ -0,0 +1,196 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_read() and rtems_bdbuf_release_modified()
+ * coexist. rtems_bdbuf_read() is blocked when required buffer is being
+ * transferred.
+ *
+ * The same as Test 2.1, but on step 7 thread #2 calls
+ * rtems_bdbuf_release_modified().
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read() function in thread #1 and block on
+ * waiting for read complete notification.
+ * -# Call rtems_bdbuf_read() function in thread #2 for
+ * the same block number. As the result it blocks on this read
+ * as well (but it will block on transfer semaphore).
+ * -# Disk device reports success in read complete notification.
+ * As the result rtems_bdbuf_read() function returns
+ * RTEMS_SUCCESSFUL in thread #1.
+ * -# Thread #1 releases buffer with rtems_bdbuf_release_modified() function.
+ * -# rtems_bdbuf_read() function in thread #2 unlocks and
+ * returns RTEMS_SUCCESSFUL.
+ * -# Wait swapout period and check that the buffer is not requested
+ * to be flushed to a disk.
+ * -# Call rtems_bdbuf_release_modified() function in thread #2.
+ * -# Check that this block number is requested for a flush in swapout period.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test2_2_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test2_2_thread2(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM 70
+
+void
+bdbuf_test2_2_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 2.2");
+
+ START_THREAD(1, bdbuf_test2_2_thread1);
+ START_THREAD(2, bdbuf_test2_2_thread2);
+
+ /*
+ * Step 1:
+ * Thread #1 calls rtems_bdbuf_read() and we block
+ * this thread on data transfer operation.
+ */
+ WAIT_DRV_MSG(&msg);
+
+ /*
+ * Step 2:
+ * Thread #2 calls rtems_bdbuf_read() for the same
+ * block number, as the result it shall block waiting
+ * on buffer state change (waiting on TRANSFER state).
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure thread #2 managed to block on the buffer. */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 3:
+ * Unblock thread #1 by reporting successful data transfer result.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Wait for sync from thread #1.
+ */
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("3");
+
+ /* Check thread #2 is still blocked */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 4:
+ * Thread #1 releases buffer with bdbuf_release_modified() call.
+ */
+ CONTINUE_THREAD(1);
+
+ /*
+ * Step 5:
+ * On buffer release operation, we should have unblock
+ * of thread #2 that is waiting on read buffer operation.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("5");
+
+ /*
+ * Step 6:
+ * Wait swapout period and check that there is no
+ * request to flush buffer onto a disk.
+ */
+ CHECK_NO_DRV_MSG();
+
+ /*
+ * Step 7:
+ * Thread #2 releases buffer with bdbuf_release_modified() call.
+ */
+ CONTINUE_THREAD(2);
+
+ /*
+ * Step 8:
+ * Check that in swapout interval disk device
+ * driver is requested to flush buffer.
+ */
+ WAIT_DRV_MSG_WR(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test2_2_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1 - 3:
+ * Try to read blk #N on thread #1
+ * We will block on this read and meanwhile
+ * thread #2 will try to read the same block.
+ * After blocking on read in thread #2, device
+ * driver will notify successful completion of
+ * date transfer, and as the result this call
+ * will return valid buffer.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 4:
+ * Release buffer returned on the previous step.
+ */
+ rc = rtems_bdbuf_release_modified(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test2_2_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * Try to read block #N. Right now thread #1 is waiting
+ * on data transfer operation, so we will block here as well.
+ *
+ * Step 5:
+ * On step 4 thread #1 releases buffer and as the result
+ * our read operation should finish with success.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ CONTINUE_MAIN(2);
+
+ /*
+ * Step 7:
+ * Release buffer.
+ */
+ rc = rtems_bdbuf_release_modified(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+
diff --git a/testsuites/libtests/block08/bdbuf_test3_1.c b/testsuites/libtests/block08/bdbuf_test3_1.c
new file mode 100644
index 0000000000..49141761ba
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test3_1.c
@@ -0,0 +1,184 @@
+/*! @file
+ * @brief Check how read/release work in case of only one buffer in ready list.
+ *
+ * Test sequence:
+ * -# In thread #1 call rtems_bdbuf_get(#N) to get an empty block #N.
+ * -# In thread #1 call rtems_bdbuf_release_modified() for previously
+ * got buffer.
+ * -# In thread #1 call rtems_bdbuf_read(#N) to get the same buffer
+ * (after this call a buffer is in AVL tree with ACCESS_MODIFIED state).
+ * -# In thread #2 call rtems_bdbuf_read/get(#M).
+ * -# In thread #1 call rtems_bdbuf_release(#N).
+ * -# Check that in thread #2 a buffer is obtained.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test3_1_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test3_1_thread2(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM_N 80
+#define TEST_BLK_NUM_M 85
+
+void
+bdbuf_test3_1_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 3.1");
+
+ START_THREAD(1, bdbuf_test3_1_thread1);
+ START_THREAD(2, bdbuf_test3_1_thread2);
+
+ /*
+ * Step 1-3:
+ * Wait for sync from thread #1.
+ * Thread #1 switch a buffer for #N into ACCESS_MODIFIED state.
+ */
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("3");
+
+ /*
+ * Step 4:
+ * Thread #2 calls get() function and blocks
+ * (there no buffers available in bdbuf library).
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure thread #2 managed to block on the buffer. */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 6:
+ * Thread #1 release buffer.
+ */
+ CONTINUE_THREAD(1);
+
+ /*
+ * Buffer released in thread #1 was in MODIFIED state, so
+ * there will be a request for disk write
+ */
+ WAIT_DRV_MSG_WR(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Check that thread #2 unblocked after this.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("5");
+
+ /*
+ * Release buffer in thread #2
+ */
+ CONTINUE_THREAD(2);
+
+ /*
+ * Buffer released in thread #2 switched to MODIFIED state, so
+ * there will be a request for disk write
+ */
+ WAIT_DRV_MSG_WR(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test3_1_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_get(#N) to get an empty block db;
+ * [this call will remove a buffer from ready list and insert
+ * it in AVL tree with ACCESS state.
+ * Step 2:
+ * Call release_modified(bd);
+ * [Now we have one entry in modified list and it is still
+ * in AVL tree with MODIFIED state]
+ * Step 3:
+ * Call read(#N) to get the same buffer.
+ * [An entry is found in AVL tree, removed from modified list and
+ * returned with state ACCESS_MODIFIED]
+ */
+ rc = rtems_bdbuf_get(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ rc = rtems_bdbuf_release_modified(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ /* Step 5:
+ * Call rtems_bdbuf_release(#N).
+ * As the result buffer will be used by bdbuf to get
+ * buffer #M for thread #2.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test3_1_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 4:
+ * In thread #2 call read/get(#M)
+ * [We ask for block number #M - there is no such entry in AVL,
+ * and all the lists are empty (ready, lru, modified), as a result
+ * this thread blocks on
+ * rtems_bdbuf_wait(pool, &pool->waiting, &pool->wait_waiters)]
+ */
+ rc = rtems_bdbuf_get(test_dev, TEST_BLK_NUM_M, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(2);
+
+ /*
+ * Release buffer.
+ */
+ rc = rtems_bdbuf_release_modified(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+
diff --git a/testsuites/libtests/block08/bdbuf_test3_2.c b/testsuites/libtests/block08/bdbuf_test3_2.c
new file mode 100644
index 0000000000..ddebce4e71
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test3_2.c
@@ -0,0 +1,197 @@
+/*! @file
+ * @brief Check that when there are some tasks waiting for an available
+ * buffer only one of them get a buffer after some other task releases one.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read(#N1) in thread #1.
+ * -# Call rtems_bdbuf_get(#N2) in thread #2.
+ * This thread blocks because we have no buffers available.
+ * -# Call rtems_bdbuf_get(#N3) in thread #3.
+ * This thread also blocks because we have no buffers available.
+ * -# Call rtems_bdbuf_release_modified(#N1) in thread #1.
+ * -# Check that only one thread (thread #2 or thread #3) got a buffer.
+ * Another thread shall still be blocked.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test3_2_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test3_2_thread2(rtems_task_argument arg);
+static rtems_task bdbuf_test3_2_thread3(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM_N1 90
+#define TEST_BLK_NUM_N2 92
+#define TEST_BLK_NUM_N3 94
+
+void
+bdbuf_test3_2_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 3.2");
+
+ /*
+ * Create working threads.
+ */
+ SET_THREAD_PRIORITY(2, LOW);
+ SET_THREAD_PRIORITY(3, HIGH);
+ START_THREAD(1, bdbuf_test3_2_thread1);
+ START_THREAD(2, bdbuf_test3_2_thread2);
+ START_THREAD(3, bdbuf_test3_2_thread3);
+
+ /*
+ * Start thread #1: it will read buffer #N1.
+ * Driver is asked to read this buffer.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ WAIT_THREAD_SYNC(1);
+
+ /*
+ * Block thread #2 and thread #3 on get buffers #N1 and #N2
+ * correspondingly.
+ */
+ CONTINUE_THREAD(2);
+ CONTINUE_THREAD(3);
+
+ /* Make sure threads managed to block on the buffers get. */
+ CHECK_THREAD_BLOCKED(2);
+ CHECK_THREAD_BLOCKED(3);
+
+ /*
+ * Step 4:
+ * Thread #1 release buffer.
+ */
+ CONTINUE_THREAD(1);
+
+ /*
+ * Check that thread #2 unblocked after this.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("5");
+
+ CHECK_THREAD_BLOCKED(3);
+
+ /* Release buffer in thread #2 */
+ CONTINUE_THREAD(2);
+
+ /* wait for driver message to flush it onto a disk */
+ WAIT_DRV_MSG_WR(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /* Wait for thread #3 to be unblocked */
+ WAIT_THREAD_SYNC(3);
+
+ /* Release buffer in thread #3 */
+ CONTINUE_THREAD(3);
+
+ /* wait for driver message to flush it onto a disk */
+ WAIT_DRV_MSG_WR(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test3_2_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) to get a buffer;
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N1, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 4:
+ * Call rtems_bdbuf_release(#N).
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test3_2_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * In thread #2 call get(#N2)
+ */
+ rc = rtems_bdbuf_get(test_dev, TEST_BLK_NUM_N2, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ printk("Thread #2 DEBLOCK\n");
+ CONTINUE_MAIN(2);
+
+ rc = rtems_bdbuf_release_modified(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test3_2_thread3(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(3);
+
+ /*
+ * Step 3:
+ * In thread #3 call get(#N3)
+ */
+ rc = rtems_bdbuf_get(test_dev, TEST_BLK_NUM_N3, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ printk("Thread #3 DEBLOCK\n");
+
+ CONTINUE_MAIN(3);
+
+ rc = rtems_bdbuf_release_modified(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ THREAD_END();
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_test3_3.c b/testsuites/libtests/block08/bdbuf_test3_3.c
new file mode 100644
index 0000000000..1ceee1e722
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test3_3.c
@@ -0,0 +1,208 @@
+/*! @file
+ * @brief Check how read/release work in case of only one buffer in ready list.
+ *
+ * The same as Test 3.2, but instead of calling rtems_bdbuf_get() in
+ * threads #1 and #2, it calls rtems_bdbuf_read().
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read(#N1) in thread #1.
+ * -# Call rtems_bdbuf_read(#N2) in thread #2.
+ * This thread blocks because we have no buffers available.
+ * -# Call rtems_bdbuf_read(#N3) in thread #3.
+ * This thread also blocks because we have no buffers available.
+ * -# Call rtems_bdbuf_release(#N1) in thread #1.
+ * -# Check that only one thread (thread #2 or thread #3) got a buffer.
+ * Another thread shall still be blocked.
+ * -# Call rtems_bdbuf_release(#N2) in thread #2 and check that
+ * thread #3 got a buffer as the result.
+ * .
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test3_3_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test3_3_thread2(rtems_task_argument arg);
+static rtems_task bdbuf_test3_3_thread3(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM_N1 96
+#define TEST_BLK_NUM_N2 98
+#define TEST_BLK_NUM_N3 100
+
+void
+bdbuf_test3_3_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 3.3");
+
+ /*
+ * Create working threads.
+ */
+ SET_THREAD_PRIORITY(2, LOW);
+ SET_THREAD_PRIORITY(3, HIGH);
+ START_THREAD(1, bdbuf_test3_3_thread1);
+ START_THREAD(2, bdbuf_test3_3_thread2);
+ START_THREAD(3, bdbuf_test3_3_thread3);
+
+ /*
+ * Start thread #1: it will read buffer #N1.
+ * Driver is asked to read this buffer.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ WAIT_THREAD_SYNC(1);
+
+ /*
+ * Block thread #2 and thread #3 on get buffers #N2 and #N3
+ * correspondingly (bdbuf librbary has no buffers available).
+ */
+ CONTINUE_THREAD(2);
+ CONTINUE_THREAD(3);
+
+ /* Make sure threads managed to block on the buffers get. */
+ CHECK_THREAD_BLOCKED(2);
+ CHECK_THREAD_BLOCKED(3);
+
+ /*
+ * Step 4:
+ * Thread #1 release buffer.
+ */
+ CONTINUE_THREAD(1);
+
+ /* Wait for read request in the driver (for thread #2) */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /* Check that there is no read request for another block */
+ CHECK_NO_DRV_MSG();
+
+ /*
+ * Check that thread #2 unblocked after this.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("5");
+
+ /* Thread #3 is still in blocked state */
+ CHECK_THREAD_BLOCKED(3);
+
+ /* Release buffer in thread #2 */
+ CONTINUE_THREAD(2);
+
+ /* Wait for read request in the driver (for thread #3) */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /* Wait for thread #3 to be unblocked */
+ WAIT_THREAD_SYNC(3);
+
+ /* Release buffer in thread #3 */
+ CONTINUE_THREAD(3);
+
+ CHECK_NO_DRV_MSG();
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test3_3_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) to get a buffer;
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N1, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 4:
+ * Call rtems_bdbuf_release(#N).
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test3_3_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * In thread #2 call read(#N2)
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N2, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ printk("Thread #2 DEBLOCK\n");
+ CONTINUE_MAIN(2);
+
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test3_3_thread3(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(3);
+
+ /*
+ * Step 3:
+ * In thread #3 call read(#N3)
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N3, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ printk("Thread #3 DEBLOCK\n");
+
+ CONTINUE_MAIN(3);
+
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ THREAD_END();
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_test4_1.c b/testsuites/libtests/block08/bdbuf_test4_1.c
new file mode 100644
index 0000000000..da6ff9561f
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test4_1.c
@@ -0,0 +1,176 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_sync() works.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read(#N) in thread #1.
+ * -# Call rtems_bdbuf_read(#N) from thread #2.
+ * -# Thread #2 blocks on this call.
+ * -# Call rtems_bdbuf_sync(#N) in thread #1.
+ * -# After a while disk driver gets write request for block #N.
+ * Notify bdbuf library about write complete event.
+ * -# Check that thread #1 unlocked after this.
+ * -# Check that thread #2 unblocks and get buffer #N.
+ * -# Release buffer in thread #2.
+ * .
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test4_1_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test4_1_thread2(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM_N 112
+
+void
+bdbuf_test4_1_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 4.1");
+
+ START_THREAD(1, bdbuf_test4_1_thread1);
+ START_THREAD(2, bdbuf_test4_1_thread2);
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) in thread #1.
+ * Wait for read request in disk driver.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /* Wait for return from rtems_bdbuf_read(#N) function. */
+ WAIT_THREAD_SYNC(1);
+
+ /*
+ * Step 2:
+ * Call rtems_bdbuf_read(#N) in thread #2.
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure that thread #2 blocks */
+ CHECK_THREAD_BLOCKED(2);
+ TEST_CHECK_RESULT("2");
+
+ /*
+ * Step 3:
+ * Call rtems_bdbuf_sync (#N) in thread #1.
+ */
+ CONTINUE_THREAD(1);
+
+ /*
+ * Setp 4:
+ * Wait for Write request to device driver.
+ */
+ WAIT_DRV_MSG_WR(&msg);
+
+ /* Check that both threads are blocked right now */
+ CHECK_THREAD_BLOCKED(1);
+ CHECK_THREAD_BLOCKED(2);
+
+ /* Send Write complete notification */
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Step 5:
+ * Check that rtems_bdbuf_sync(#N) call is unlocked.
+ */
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("5");
+
+ /*
+ * Step 6:
+ * Check that rtems_bdbuf_read(#N) call in thread #2 is unlocked.
+ */
+ WAIT_THREAD_SYNC(2);
+
+ /*
+ * Step 7:
+ * Release buffer in thread #2
+ */
+ CONTINUE_THREAD(2);
+
+ /*
+ * Exit from thread #1.
+ */
+ CONTINUE_THREAD(1);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test4_1_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) in thread #1;
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ /*
+ * Step 3:
+ * Call rtems_bdbuf_sync(#N)
+ */
+ rc = rtems_bdbuf_sync(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test4_1_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 2:
+ * In thread #2 call rtems_bdbuf_read(#N).
+ * We will block on this call.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(2);
+
+ /*
+ * Release buffer.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+
diff --git a/testsuites/libtests/block08/bdbuf_test4_2.c b/testsuites/libtests/block08/bdbuf_test4_2.c
new file mode 100644
index 0000000000..06587bccd1
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test4_2.c
@@ -0,0 +1,161 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_sync() works.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read(#N) in thread #1.
+ * -# Call rtems_bdbuf_sync(#N) in thread #1.
+ * -# After a while disk driver gets write request for block #N.
+ * -# Call rtems_bdbuf_read(#N) from thread #2 (before reply from the driver).
+ * Thread #2 blocks on this call.
+ * -# Notify bdbuf library about write complete event.
+ * -# Check that rtems_bdbuf_sync(#N) in thread #1 unlocked after this.
+ * (in fact a thread to unlock might be any).
+ * -# Check that thread #2 unblocks and get buffer #N.
+ * -# Release buffer in thread #2.
+ * .
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test4_2_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test4_2_thread2(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM_N 114
+
+void
+bdbuf_test4_2_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 4.2");
+
+ START_THREAD(1, bdbuf_test4_2_thread1);
+ START_THREAD(2, bdbuf_test4_2_thread2);
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) in thread #1.
+ * Wait for read request in disk driver.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Step 2, 3:
+ * Call rtems_bdbuf_sync(#N) in thread #1.
+ * As the result buffer is asked to be flashed onto the disk.
+ */
+ WAIT_DRV_MSG_WR(&msg);
+ TEST_CHECK_RESULT("3");
+
+ /*
+ * Step 4:
+ * Call rtems_bdbuf_read(#N) in thread #2
+ */
+ CONTINUE_THREAD(2);
+
+ /* Make sure that thread #2 blocks */
+ CHECK_THREAD_BLOCKED(2);
+
+ /*
+ * Step 5:
+ * Notify bdbuf library about write complete event.
+ */
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /* Check that rtems_bdbuf_sync() is unlocked in thread #1 */
+ WAIT_THREAD_SYNC(1);
+
+ /*
+ * Step 7:
+ * Check that rtems_bdbuf_read(#N) call is unlocked in thread #2.
+ */
+ WAIT_THREAD_SYNC(2);
+ TEST_CHECK_RESULT("7");
+
+ /*
+ * Step 8:
+ * Release buffer in thread #2
+ */
+ CONTINUE_THREAD(2);
+
+ /* Exit from thread #1 */
+ CONTINUE_THREAD(1);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test4_2_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) in thread #1;
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ /*
+ * Step 2:
+ * Call rtems_bdbuf_sync(#N)
+ */
+ rc = rtems_bdbuf_sync(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test4_2_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 4:
+ * In thread #2 call read(#N).
+ * We will block on this call.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(2);
+
+ /*
+ * Release buffer.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+
diff --git a/testsuites/libtests/block08/bdbuf_test4_3.c b/testsuites/libtests/block08/bdbuf_test4_3.c
new file mode 100644
index 0000000000..821333c71d
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_test4_3.c
@@ -0,0 +1,155 @@
+/*! @file
+ * @brief Check how rtems_bdbuf_sync() works.
+ *
+ * Test sequence:
+ * -# Call rtems_bdbuf_read(#N) in thread #1.
+ * -# Call rtems_bdbuf_sync(#N) in thread #1.
+ * -# After a while disk driver gets write request for block #N.
+ * Notify bdbuf about write complete event.
+ * -# Check that rtems_bdbuf_sync(#N) in thread #1 unlocked after this.
+ * -# Call rtems_bdbuf_read(#N) in thread #2.
+ * -# Check that buffer is successfully obtained in thread #2.
+ * -# Call rtems_bdbuf_release(#N) in thread #2.
+ * .
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <bdbuf_tests.h>
+
+static rtems_task bdbuf_test4_3_thread1(rtems_task_argument arg);
+static rtems_task bdbuf_test4_3_thread2(rtems_task_argument arg);
+
+/* Block number used in the test */
+#define TEST_BLK_NUM_N 116
+
+void
+bdbuf_test4_3_main()
+{
+ bdbuf_test_msg msg;
+
+ TEST_START("Test 4.3");
+
+ START_THREAD(1, bdbuf_test4_3_thread1);
+ START_THREAD(2, bdbuf_test4_3_thread2);
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) in thread #1.
+ * Wait for read request in disk driver.
+ */
+ WAIT_DRV_MSG(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Step 2:
+ * Call rtems_bdbuf_sync(#N) in thread #1.
+ * As the result buffer is asked to be flashed onto the disk.
+ */
+ WAIT_DRV_MSG_WR(&msg);
+ SEND_DRV_MSG(0, 0, RTEMS_SUCCESSFUL, 0);
+
+ /*
+ * Step 4:
+ * Check that rtems_bdbuf_sync(#N) call is unlocked.
+ */
+ WAIT_THREAD_SYNC(1);
+ TEST_CHECK_RESULT("4");
+
+ /*
+ * Step 5:
+ * Call rtems_bdbuf_read(#N) in thread #2.
+ */
+ CONTINUE_THREAD(2);
+
+ /*
+ * Step 6:
+ * Check that thread #2 successfully got the buffer.
+ */
+ WAIT_THREAD_SYNC(2);
+
+ /*
+ * Step 7:
+ * Release buffer in thread #2
+ */
+ CONTINUE_THREAD(2);
+
+ /*
+ * Exit from thread #1.
+ */
+ CONTINUE_THREAD(1);
+
+ TEST_END();
+}
+
+static rtems_task
+bdbuf_test4_3_thread1(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ /*
+ * Step 1:
+ * Call rtems_bdbuf_read(#N) in thread #1;
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ /*
+ * Step 2:
+ * Call rtems_bdbuf_sync(#N)
+ */
+ rc = rtems_bdbuf_sync(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(1);
+
+ THREAD_END();
+}
+
+static rtems_task
+bdbuf_test4_3_thread2(rtems_task_argument arg)
+{
+ rtems_status_code rc;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ WAIT_MAIN_SYNC(2);
+
+ /*
+ * Step 5:
+ * In thread #2 call rtems_bdbuf_read(#N).
+ * We will block on this call.
+ */
+ rc = rtems_bdbuf_read(test_dev, TEST_BLK_NUM_N, &bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+
+ CONTINUE_MAIN(2);
+
+ /*
+ * Release buffer.
+ */
+ rc = rtems_bdbuf_release(bd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ TEST_FAILED();
+ }
+ THREAD_END();
+}
+
+
diff --git a/testsuites/libtests/block08/bdbuf_tests.c b/testsuites/libtests/block08/bdbuf_tests.c
new file mode 100644
index 0000000000..642032a290
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_tests.c
@@ -0,0 +1,271 @@
+/*! @file
+ * @brief Implementation of auxiliary functions of bdbuf tests.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/io.h>
+#include <rtems/diskdevs.h>
+#include <rtems/bdbuf.h>
+#include "bdbuf_tests.h"
+
+
+struct bdbuf_test_descr {
+ void (* main)(void);
+} bdbuf_tests[] = {
+#if 0
+ { bdbuf_test1_1_main },
+ { bdbuf_test1_2_main },
+ { bdbuf_test1_3_main },
+#endif
+ { bdbuf_test1_4_main },
+ { bdbuf_test1_5_main },
+
+ { bdbuf_test2_1_main },
+ { bdbuf_test2_2_main },
+
+ { bdbuf_test3_1_main },
+ { bdbuf_test3_2_main },
+ { bdbuf_test3_3_main },
+
+ { bdbuf_test4_1_main },
+ { bdbuf_test4_2_main },
+ { bdbuf_test4_3_main },
+};
+
+#define TEST_SEM_ATTRIBS RTEMS_DEFAULT_ATTRIBUTES
+
+/** Device ID used for testing */
+dev_t test_dev = (dev_t)-1;
+
+/** Test result variable */
+bool good_test_result = true;
+
+test_ctx g_test_ctx;
+
+const char *test_name = "NO TEST";
+
+bdbuf_test_msg test_drv_msg;
+
+/** Count of messages in RX message queue used on disk driver side. */
+#define TEST_DRV_RX_MQUEUE_COUNT 10
+/** Name of disk driver RX message queue. */
+#define TEST_DRV_RX_MQUEUE_NAME (rtems_build_name( 'M', 'Q', 'D', ' ' ))
+
+/** Count of messages in Test task RX message queue */
+#define TEST_TASK_RX_MQUEUE_COUNT 10
+/** Name of Test task RX message queue */
+#define TEST_TASK_RX_MQUEUE_NAME (rtems_build_name( 'M', 'Q', 'T', ' ' ))
+
+rtems_status_code
+bdbuf_test_start_aux_task(rtems_name name,
+ rtems_task_entry entry_point,
+ rtems_task_argument arg,
+ Objects_Id *id)
+{
+ rtems_status_code rc;
+ Objects_Id task_id;
+
+ rc = rtems_task_create(name, BDBUF_TEST_THREAD_PRIO_NORMAL, 1024 * 2,
+ RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
+ RTEMS_LOCAL | RTEMS_NO_FLOATING_POINT,
+ &task_id);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ printf("Failed to create task\n");
+ return rc;
+ }
+
+ rc = rtems_task_start(task_id, entry_point, arg);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ printf("Failed to start task\n");
+ }
+ else
+ {
+ if (id != NULL)
+ *id = task_id;
+ }
+ return rc;
+}
+
+void
+run_bdbuf_tests()
+{
+ rtems_disk_device *disk;
+ rtems_status_code sc;
+ dev_t dev = -1;
+ unsigned int i;
+
+ rtems_device_major_number major;
+ rtems_driver_address_table testdisk = {
+ test_disk_initialize,
+ RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES
+ };
+
+ /* Create a message queue to get events from disk driver. */
+ sc = rtems_message_queue_create(TEST_TASK_RX_MQUEUE_NAME,
+ TEST_TASK_RX_MQUEUE_COUNT,
+ sizeof(bdbuf_test_msg),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &g_test_ctx.test_qid);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printk("Failed to create message queue for test task: %u\n", sc);
+ return;
+ }
+
+ /* Register a disk device that is used in tests */
+ sc = rtems_io_register_driver(0, &testdisk, &major);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printk("Failed to register TEST DEVICE: %d\n", sc);
+ return;
+ }
+
+ test_dev = -1;
+ while ((disk = rtems_disk_next(dev)) != NULL)
+ {
+ printk("DEV: %s [%lu]\n", disk->name, disk->size);
+ dev = disk->dev;
+ if (strcmp(disk->name, TEST_DISK_NAME) == 0)
+ test_dev = dev;
+ rtems_disk_release(disk);
+ }
+
+ if (test_dev == (dev_t)-1)
+ {
+ printf("Failed to find %s disk\n", TEST_DISK_NAME);
+ return;
+ }
+
+ /*
+ * On initialization test disk device driver registers
+ * its RX message queue, so we just need to locate it.
+ */
+ sc = rtems_message_queue_ident(TEST_DRV_RX_MQUEUE_NAME,
+ RTEMS_SEARCH_ALL_NODES,
+ &g_test_ctx.test_drv_qid);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printf("Failed to find Test Driver Queue: %u\n", sc);
+ return;
+ }
+
+ for (i = 0; i < ARRAY_NUM(g_test_ctx.test_sync_main); i++)
+ {
+ sc = rtems_semaphore_create(rtems_build_name('T', 'S', 'M', '0' + i),
+ 0, TEST_SEM_ATTRIBS, 0,
+ &g_test_ctx.test_sync_main[i]);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printk("Failed to create sync sem for test task: %u\n", sc);
+ return;
+ }
+ }
+
+ for (i = 0; i < ARRAY_NUM(g_test_ctx.test_sync); i++)
+ {
+ sc = rtems_semaphore_create(rtems_build_name('T', 'S', 'T', '0' + i),
+ 0, TEST_SEM_ATTRIBS, 0,
+ &g_test_ctx.test_sync[i]);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printk("Failed to create sync sem for test task #%d: %u\n", i + 1, sc);
+ return;
+ }
+ }
+
+ sc = rtems_semaphore_create(rtems_build_name('T', 'S', 'M', 'E'),
+ 0, TEST_SEM_ATTRIBS, 0,
+ &g_test_ctx.test_end_main);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printk("Failed to create end sync sem for test task: %u\n", sc);
+ return;
+ }
+
+ for (i = 0; i < ARRAY_NUM(g_test_ctx.test_task); i++)
+ g_test_ctx.test_task[i] = OBJECTS_ID_NONE;
+
+ for (i = 0; i < sizeof(bdbuf_tests) / sizeof(bdbuf_tests[0]); i++)
+ {
+ bdbuf_tests[i].main();
+ }
+}
+
+
+rtems_status_code
+bdbuf_test_create_drv_rx_queue(Objects_Id *id)
+{
+ return rtems_message_queue_create(TEST_DRV_RX_MQUEUE_NAME,
+ TEST_DRV_RX_MQUEUE_COUNT,
+ sizeof(bdbuf_test_msg),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ id);
+}
+
+rtems_status_code
+bdbuf_test_create_drv_tx_queue(Objects_Id *id)
+{
+ return rtems_message_queue_ident(TEST_TASK_RX_MQUEUE_NAME,
+ RTEMS_SEARCH_ALL_NODES,
+ id);
+}
+
+rtems_status_code
+bdbuf_test_start_thread(unsigned int idx, rtems_task_entry func)
+{
+ rtems_status_code sc;
+
+ if (g_test_ctx.test_task[idx] != OBJECTS_ID_NONE)
+ {
+ sc = rtems_task_delete(g_test_ctx.test_task[idx]);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printk("Failed to delete test thread %u in test %s\n",
+ idx + 1, g_test_ctx.test_name);
+ return sc;
+ }
+ }
+ sc = bdbuf_test_start_aux_task(
+ rtems_build_name('T', 'S', '.', '0' + idx),
+ func, (rtems_task_argument)(NULL),
+ &g_test_ctx.test_task[idx]);
+ return sc;
+}
+
+rtems_status_code
+bdbuf_test_end()
+{
+ rtems_status_code sc;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_NUM(g_test_ctx.test_task); i++)
+ {
+ if (g_test_ctx.test_task[i] != OBJECTS_ID_NONE)
+ {
+ sc = rtems_semaphore_obtain(g_test_ctx.test_end_main,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ printk("Failed to get a thread stopped\n");
+ }
+ g_test_ctx.test_task[i] = OBJECTS_ID_NONE;
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
diff --git a/testsuites/libtests/block08/bdbuf_tests.h b/testsuites/libtests/block08/bdbuf_tests.h
new file mode 100644
index 0000000000..e8affa1cbc
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_tests.h
@@ -0,0 +1,504 @@
+/*! @file
+ * @brief Common declarations of bdbuf tests.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef BDBUF_TESTS_H
+#define BDBUF_TESTS_H
+
+#include <stdio.h>
+#include <errno.h>
+#include <rtems/diskdevs.h>
+#include <rtems/bdbuf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void run_bdbuf_tests(void);
+
+extern void bdbuf_test1_1_main(void);
+extern void bdbuf_test1_2_main(void);
+extern void bdbuf_test1_3_main(void);
+extern void bdbuf_test1_4_main(void);
+extern void bdbuf_test1_5_main(void);
+
+extern void bdbuf_test2_1_main(void);
+extern void bdbuf_test2_2_main(void);
+extern void bdbuf_test2_3_main(void);
+extern void bdbuf_test2_4_main(void);
+extern void bdbuf_test2_5_main(void);
+
+extern void bdbuf_test3_1_main(void);
+extern void bdbuf_test3_2_main(void);
+extern void bdbuf_test3_3_main(void);
+
+extern void bdbuf_test4_1_main(void);
+extern void bdbuf_test4_2_main(void);
+extern void bdbuf_test4_3_main(void);
+
+extern rtems_device_driver
+test_disk_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg);
+
+#define ARRAY_NUM(a_) (sizeof(a_) / sizeof(a_[0]))
+
+/**
+ * Configuration parameters of Test disk device.
+ */
+#define TEST_DISK_BLOCK_SIZE 512
+#define TEST_DISK_BLOCK_NUM 1024
+#define TEST_DISK_NAME "/dev/testdisk"
+
+/** Type of messages between test disk driver and main test task */
+enum bdbuf_test_msg_type {
+ /** Message sent by disk driver to main test task */
+ BDBUF_TEST_MSG_TYPE_DRIVER_REQ,
+ /**
+ * Message sent main test task to disk driver
+ * in reply to request.
+ */
+ BDBUF_TEST_MSG_TYPE_DRIVER_REPLY,
+};
+
+/**
+ * Message used in communication between test disk driver
+ * and main test task.
+ * All R/W requests obtained by driver (from bdbuf library)
+ * are directed to main test task. Then main test task
+ * sends a reply after which test disk driver notifies
+ * bdbuf library about operation complete event.
+ */
+typedef struct bdbuf_test_msg {
+ /** Message type */
+ enum bdbuf_test_msg_type type;
+
+ union {
+ struct driver_req {
+ dev_t dev;
+ uint32_t req;
+ void *argp;
+ } driver_req;
+ struct driver_reply {
+ int ret_val;
+ int ret_errno;
+ rtems_status_code res_status;
+ int res_errno;
+ } driver_reply;
+ } val;
+} bdbuf_test_msg;
+
+
+typedef enum bdbuf_rest_thread_prio {
+ BDBUF_TEST_THREAD_PRIO_NORMAL = 3,
+ BDBUF_TEST_THREAD_PRIO_LOW = 7,
+ BDBUF_TEST_THREAD_PRIO_HIGH = 5,
+} bdbuf_rest_thread_prio;
+
+
+typedef struct test_ctx {
+ /**
+ * Message queue used by main task to get messages from
+ * disk device driver.
+ */
+ Objects_Id test_qid;
+
+ /**
+ * Object ID for disk driver queue.
+ * Test task will send messages to this queue in reply
+ * to messages received on @a test_qid.
+ */
+ Objects_Id test_drv_qid;
+
+ /** Test name */
+ const char *test_name;
+
+ /**
+ * Semaphore used for synchronization between test thread
+ * and main test task.
+ * Main test task blocks on one of these semaphores and an auxiliary thread
+ * releases it in order to pass control to main task again.
+ */
+ rtems_id test_sync_main[3];
+
+ /**
+ * This semaphore is used for synchornization between main test task
+ * and the END of auxiliary threads.
+ */
+ rtems_id test_end_main;
+
+ /**
+ * Semaphore used for synchronization between test thread
+ * and main test task.
+ * Thread #N blocks on this semaphore and the main task releases it
+ * when it wants to pass control to the auxiliary thread #N.
+ */
+ rtems_id test_sync[3];
+
+ /** Task Id values of auxiliary threads */
+ Objects_Id test_task[3];
+} test_ctx;
+
+extern test_ctx g_test_ctx;
+
+/** Device ID used for testing */
+extern dev_t test_dev;
+
+/**
+ * Create a message queue for test driver that is used for
+ * receiving messages from test task.
+ *
+ * @param[out] id RTEMS message queue identifier
+ *
+ * @return Status of the operation
+ */
+extern rtems_status_code bdbuf_test_create_drv_rx_queue(Objects_Id *id);
+
+/**
+ * Obtain a message queue for test driver that is used for
+ * sending messages to test task.
+ *
+ * @param[out] id RTEMS message queue identifier
+ *
+ * @return Status of the operation
+ */
+extern rtems_status_code bdbuf_test_create_drv_tx_queue(Objects_Id *id);
+
+/**
+ * Start a separate test task represented by function @p func
+ * and associated with task index @p idx.
+ *
+ * @param[in] idx Task index
+ * @param[in] func Test task function
+ */
+extern rtems_status_code bdbuf_test_start_thread(unsigned int idx,
+ rtems_task_entry func);
+
+/**
+ * Finalize test run.
+ */
+extern rtems_status_code bdbuf_test_end(void);
+
+/** Test result variable */
+extern bool good_test_result;
+
+#define BDBUF_TEST_BLOCK_TIMEOUT (2 * rtems_clock_get_ticks_per_second())
+
+#define SET_THREAD_PRIORITY(t_num_, prio_) \
+ do { \
+ rtems_task_priority old_prio; \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_task_set_priority( \
+ g_test_ctx.test_task[(t_num_) - 1], \
+ BDBUF_TEST_THREAD_PRIO_ ## prio_, &old_prio); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to change priority of test thread #" \
+ #t_num_ " in test %s\n", g_test_ctx.test_name); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Start thread number @p t_num_ with @p func_ function
+ * as an entry point of the thread.
+ *
+ * @param t_num_ thread number.
+ * @param func_ thread entry point.
+ */
+#define START_THREAD(t_num_, func_) \
+ do { \
+ if (bdbuf_test_start_thread((t_num_) - 1, func_) != \
+ RTEMS_SUCCESSFUL) \
+ { \
+ return; \
+ } \
+ printk("Thread #" #t_num_ " started\n"); \
+ } while (0)
+
+/**
+ * Wait for a message from device driver.
+ *
+ * @param[out] msg_ Pointer to a message data structure
+ */
+#define WAIT_DRV_MSG(msg_) \
+ do { \
+ rtems_status_code rc_; \
+ size_t msg_size_ = sizeof(*(msg_)); \
+ \
+ rc_ = rtems_message_queue_receive(g_test_ctx.test_qid, \
+ (msg_), &msg_size_, \
+ RTEMS_WAIT, \
+ RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL || \
+ msg_size_ != sizeof(*(msg_))) \
+ { \
+ printk("Error at %s:%d\n", __FILE__, __LINE__); \
+ return; \
+ } \
+ if ((msg_)->type != BDBUF_TEST_MSG_TYPE_DRIVER_REQ) \
+ { \
+ printk("Unexpected message received: %d\n", \
+ (msg_)->type); \
+ return; \
+ } \
+ } while (0)
+
+#define WAIT_DRV_MSG_WR(msg_) \
+ do { \
+ WAIT_DRV_MSG(msg_); \
+ if ((msg_)->val.driver_req.req != RTEMS_BLKIO_REQUEST || \
+ (msg_)->val.driver_req.dev != test_dev || \
+ ((rtems_blkdev_request *) \
+ ((msg_)->val.driver_req.argp))->req != \
+ RTEMS_BLKDEV_REQ_WRITE) \
+ { \
+ printk("Unexpected message received by disk driver: " \
+ "req - 0x%x (0x%x), dev - %d (%d)\n", \
+ (msg_)->val.driver_req.req, RTEMS_BLKIO_REQUEST, \
+ (msg_)->val.driver_req.dev, test_dev); \
+ return; \
+ } \
+ } while (0)
+
+#define CHECK_NO_DRV_MSG() \
+ do { \
+ rtems_status_code rc_; \
+ bdbuf_test_msg msg_; \
+ size_t msg_size_ = sizeof(msg_); \
+ \
+ rc_ = rtems_message_queue_receive(g_test_ctx.test_qid, \
+ (&msg_), &msg_size_, \
+ RTEMS_WAIT, \
+ BDBUF_TEST_BLOCK_TIMEOUT); \
+ if (rc_ != RTEMS_TIMEOUT) \
+ { \
+ printk("Error at %s:%d\n", __FILE__, __LINE__); \
+ return; \
+ } \
+ } while (0)
+
+extern bdbuf_test_msg test_drv_msg;
+
+/**
+ * Send a message to device driver (in order to complete
+ * blocked I/O operation).
+ *
+ * @param ret_val_ Return value to use when returning from
+ * ioctl() function.
+ * @param ret_errno_ errno value to set to errno variable.
+ * @param res_status_ In case return value from the ioctl()
+ * function is equal to 0, this value
+ * is used as status code in asynchronous
+ * notification.
+ * @param res_errno_ In case return value from the ioctl()
+ * function is equal to 0, this value
+ * is used as error value in asynchronous
+ * notification.
+ *
+ */
+#define SEND_DRV_MSG(ret_val_, ret_errno_, res_status_, res_errno_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ memset(&test_drv_msg, 0, sizeof(test_drv_msg)); \
+ test_drv_msg.type = BDBUF_TEST_MSG_TYPE_DRIVER_REPLY; \
+ test_drv_msg.val.driver_reply.ret_val = (ret_val_); \
+ test_drv_msg.val.driver_reply.ret_errno = (ret_errno_); \
+ test_drv_msg.val.driver_reply.res_status = (res_status_); \
+ test_drv_msg.val.driver_reply.res_errno = (res_errno_); \
+ \
+ rc_ = rtems_message_queue_send(g_test_ctx.test_drv_qid, \
+ &test_drv_msg, \
+ sizeof(test_drv_msg)); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Error while sending a message to " \
+ "disk driver: %u\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Block main test task until a thread passes back control
+ * with CONTINUE_MAIN().
+ *
+ * @param t_num_ thread number from which the main thread
+ * is waiting for a sync.
+ */
+#define WAIT_THREAD_SYNC(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync_main[(t_num_) - 1], \
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to get sync with a thread: %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Check that a particular thread is blocked.
+ *
+ * @param t_num_ thread number that we want to check for blocking
+ */
+#define CHECK_THREAD_BLOCKED(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync_main[(t_num_) - 1], \
+ RTEMS_WAIT, BDBUF_TEST_BLOCK_TIMEOUT); \
+ if (rc_ != RTEMS_TIMEOUT) \
+ { \
+ printk("Thread %d is not blocked at%s:%d\n", \
+ t_num_, __FILE__, __LINE__); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Main test task gives control to the particular thread.
+ *
+ * @param t_num_ thread number to which main test task wants
+ * to give control.
+ */
+#define CONTINUE_THREAD(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_release( \
+ g_test_ctx.test_sync[(t_num_) - 1]); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to give control to thread #" \
+ #t_num_ ": %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Passes control back to the main test task from a thread.
+ *
+ * @param t_num_ Current thread number
+ */
+#define CONTINUE_MAIN(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_release( \
+ g_test_ctx.test_sync_main[(t_num_) - 1]); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to give control to " \
+ "main task: %d", rc_); \
+ return; \
+ } \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync[(t_num_) - 1], \
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to block on thread #" \
+ #t_num_ ": %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+#define WAIT_MAIN_SYNC(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync[(t_num_) - 1], \
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to block on thread #" \
+ #t_num_ ": %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+
+#define TEST_START(test_name_) \
+ do { \
+ good_test_result = true; \
+ g_test_ctx.test_name = test_name_; \
+ printk("%s - STARTED\n", \
+ g_test_ctx.test_name); \
+ } while (0)
+
+#define TEST_CHECK_RESULT(step_) \
+ do { \
+ if (!good_test_result) \
+ { \
+ printk("TEST FAILED (Step %s)\n", \
+ step_); \
+ rtems_task_delete(RTEMS_SELF); \
+ } \
+ else \
+ { \
+ printk("%s: Step %s - OK\n", \
+ g_test_ctx.test_name, step_); \
+ } \
+ } while (0)
+
+#define TEST_END() \
+ do { \
+ bdbuf_test_end(); \
+ \
+ if (good_test_result) \
+ printk("TEST PASSED\n"); \
+ else \
+ printk("TEST FAILED (END)"); \
+ } while (0)
+
+#define THREAD_END() \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_release(g_test_ctx.test_end_main);\
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to give control to " \
+ "main task: %d", rc_); \
+ return; \
+ } \
+ rtems_task_delete(RTEMS_SELF); \
+ } while (0)
+
+#define TEST_FAILED() \
+ do { \
+ good_test_result = false; \
+ } while (0)
+
+#define SLEEP() \
+ rtems_task_wake_after(BDBUF_TEST_BLOCK_TIMEOUT)
+
+
+extern rtems_status_code
+bdbuf_test_start_aux_task(rtems_name name,
+ rtems_task_entry entry_point,
+ rtems_task_argument arg,
+ Objects_Id *id);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BDBUF_TESTS_H */
+
diff --git a/testsuites/libtests/block08/block08.doc b/testsuites/libtests/block08/block08.doc
new file mode 100644
index 0000000000..84c26188e3
--- /dev/null
+++ b/testsuites/libtests/block08/block08.doc
@@ -0,0 +1,319 @@
+bdbuf tests
+~~~~~~~~~~~
+
+Test 1
+~~~~~~
+
+Tests of this group check the behaviour of rtems_bdbuf_read() function
+in different situations.
+
+Test 1.1
+~~~~~~~~
+
+Check the behaviour of rtems_bdbuf_read function with different
+reports from disk device driver.
+
+1. Call rtems_bdbuf_read() function and disk device driver ioctl()
+ function returns 0, and the result of asynchronous read complete
+ notification is successful.
+ Check that rtems_bdbuf_read() returns RTEMS_SUCCESSFUL and
+ provides buffer descriptor.
+2. Call rtems_bdbuf_read() function and disk device driver ioctl()
+ function returns -1 (there will be no asynchronous read complete
+ notification).
+ Check that rtems_bdbuf_read() returns RTEMS_IO_ERROR.
+3. Call rtems_bdbuf_read() function and disk device driver ioctl()
+ function returns 0, but the result of asynchronous read complete
+ notification is faulty (with some erroneous status).
+ Check that rtems_bdbuf_read() returns that status and does not
+ return buffer descriptor.
+
+Test 1.2
+~~~~~~~~
+
+Check how rtems_bdbuf_read() handles two readers waiting for a buffer
+for the same block number in cases when disk device driver reports
+failure in read complete notification.
+
+1. Call rtems_bdbuf_read() function in thread #1 and block on
+ waiting for read complete notification.
+2. Call rtems_bdbuf_read() function in thread #2 for the same block
+ number. As the result it blocks on this read as well (but it will
+ block on transfer semaphore).
+3. Disk device reports an error in read complete notification.
+ As the result an error is returned from rtems_bdbuf_read() in
+ thread #1.
+4. rtems_bdbuf_read() called in thread #2 should try to re-read data
+ again so disk device ioctl() function is called again for this
+ block number.
+5. Disk device reports an error in read complete notification.
+ As the result an error is returned from rtems_bdbuf_read() in
+ thread #2.
+
+Test 1.3
+~~~~~~~~
+
+Check how rtems_bdbuf_read() handles two readers waiting for a buffer
+for the same block number in cases when disk device driver reports
+failure in read complete notification.
+
+1. Call rtems_bdbuf_read() function in thread #1 and block on
+ waiting for read complete notification.
+2. Call rtems_bdbuf_read() function in thread #2 for the same block
+ number. As the result it blocks on this read as well (but it will
+ block on transfer semaphore).
+3. Disk device reports an error in read complete notification.
+ As the result an error is returned from rtems_bdbuf_read() in
+ thread #1.
+4. rtems_bdbuf_read() called in thread #2 should try to re-read data
+ again so disk device ioctl() function is called again for this
+ block number.
+5. This time disk device reports success in read complete notification.
+ As the result rtems_bdbuf_read() in thread #2 shall return RTEMS_SUCCESSFUL
+ and provide buffer descriptor.
+6. Call rtems_bdbuf_release() function in thread #2.
+
+Test 1.4
+~~~~~~~~
+
+Check how rtems_bdbuf_read() handles two readers waiting for a buffer
+for the same block number in cases when disk device driver reports
+success in read complete notification.
+
+1. Call rtems_bdbuf_read() function in thread #1 and block on
+ waiting for read complete notification.
+2. Call rtems_bdbuf_read() function in thread #2 for the same block
+ number. As the result it blocks on this read as well (but it will
+ block on transfer semaphore).
+3. Disk device reports success in read complete notification.
+ As the result rtems_bdbuf_read() function retuens RTEMS_SUCCESSFUL
+ in thread #1.
+4. Thread #1 releases buffer with rtems_bdbuf_release() function.
+5. rtems_bdbuf_read() function in thread #2 unlocks and returns
+ RTEMS_SUCCESSFUL.
+6. Call rtems_bdbuf_release() function in thread #2.
+
+ISSUE (A)
+Due to implementation constrains of bdbuf library there is no way to
+handle such a situation according to task priority, but it is
+coded in such a way that task requested this buffer first will get it
+first (even though it is less priority task).
+
+Test 1.5
+~~~~~~~~
+
+Check how rtems_bdbuf_read() handles read request for a buffer that
+is owned by an application.
+
+1. Call rtems_bdbuf_read() function in thread #1 and provide successful
+ read complete notification for this operation.
+ As the result rtems_bdbuf_read() returns RTEMS_SUCCESSFUL in thread #1.
+2. In thread #2 call rtems_bdbuf_read() function for the same block number.
+ A buffer for this block is owned by an application and as the result
+ thread #2 block on this function.
+3. Call rtems_bdbuf_release() function in thread #1 in order to give
+ it back under control of bdbuf library.
+4. Buffer now is ready to be returned for another application and as
+ the result rtems_bdbuf_read() unblocks and returns RTEMS_SUCCESSFUL
+ in thread #2.
+5. Call rtems_bdbuf_release() function in thread #2.
+
+
+Test 2.1
+~~~~~~~~
+
+Check how rtems_bdbuf_read() and rtems_bdbuf_release_modified() coexist.
+rtems_bdbuf_read() is blocked when required buffer is being transferred.
+
+1. Call rtems_bdbuf_read() function in thread #1 and block on
+ waiting for read complete notification.
+2. Call rtems_bdbuf_read() function in thread #2 for the same block
+ number. As the result it blocks on this read as well (but it will
+ block on transfer semaphore).
+3. Disk device reports success in read complete notification.
+ As the result rtems_bdbuf_read() function retuens RTEMS_SUCCESSFUL
+ in thread #1.
+4. Thread #1 releases buffer with rtems_bdbuf_release_modified() function.
+5. rtems_bdbuf_read() function in thread #2 unlocks and returns
+ RTEMS_SUCCESSFUL.
+6. Wait swapout period and check that the buffer is not requested to be
+ flushed to a disk.
+7. Call rtems_bdbuf_release() function in thread #2.
+8. Check that this block number is requested for a flush in swapout period.
+
+ISSUE (A)
+
+Test 2.2
+~~~~~~~~
+
+The same as Test 2.1, but on step 7 thread #2 calls
+rtems_bdbuf_release_modified().
+Check how rtems_bdbuf_read() and rtems_bdbuf_release_modified() coexist.
+rtems_bdbuf_read() is blocked when required buffer is being transferred.
+
+1. Call rtems_bdbuf_read() function in thread #1 and block on
+ waiting for read complete notification.
+2. Call rtems_bdbuf_read() function in thread #2 for the same block
+ number. As the result it blocks on this read as well (but it will
+ block on transfer semaphore).
+3. Disk device reports success in read complete notification.
+ As the result rtems_bdbuf_read() function retuens RTEMS_SUCCESSFUL
+ in thread #1.
+4. Thread #1 releases buffer with rtems_bdbuf_release_modified() function.
+5. rtems_bdbuf_read() function in thread #2 unlocks and returns
+ RTEMS_SUCCESSFUL.
+6. Wait swapout period and check that the buffer is not requested to be
+ flushed to a disk.
+7. Call rtems_bdbuf_release_modified() function in thread #2.
+8. Check that this block number is requested for a flush in swapout period.
+
+Test 2.3
+~~~~~~~~
+
+Check how rtems_bdbuf_read() and rtems_bdbuf_release_modified() coexist.
+rtems_bdbuf_read() is blocked when required buffer is owned by another
+application.
+
+1. Call rtems_bdbuf_read() function in thread #1 and provide successful
+ read complete notification for this operation.
+ As the result rtems_bdbuf_read() returns RTEMS_SUCCESSFUL in thread #1.
+2. In thread #2 call rtems_bdbuf_read() function for the same block number.
+ A buffer for this block is owned by an application and as the result
+ thread #2 block on this function.
+3. Call rtems_bdbuf_release_modified() function in thread #1 in order
+ to give it back under control of bdbuf library.
+4. Buffer now is ready to be returned for another application and as
+ the result rtems_bdbuf_read() unblocks and returns RTEMS_SUCCESSFUL
+ in thread #2.
+5. Wait swapout period and check that the buffer is not requested to be
+ flushed to a disk.
+6. Call rtems_bdbuf_release() function in thread #2.
+7. Check that this block number is requested for a flush in swapout period.
+
+Test 2.4
+~~~~~~~~
+
+Check how rtems_bdbuf_read() and rtems_bdbuf_release_modified() coexist.
+rtems_bdbuf_read() is blocked when required buffer is owned by another
+application.
+The same as Test 2.3 but thread #2 releases buffer with
+rtems_bdbuf_release_modified() function.
+
+1. Call rtems_bdbuf_read() function in thread #1 and provide successful
+ read complete notification for this operation.
+ As the result rtems_bdbuf_read() returns RTEMS_SUCCESSFUL in thread #1.
+2. In thread #2 call rtems_bdbuf_read() function for the same block number.
+ A buffer for this block is owned by an application and as the result
+ thread #2 block on this function.
+3. Call rtems_bdbuf_release_modified() function in thread #1 in order
+ to give it back under control of bdbuf library.
+4. Buffer now is ready to be returned for another application and as
+ the result rtems_bdbuf_read() unblocks and returns RTEMS_SUCCESSFUL
+ in thread #2.
+5. Wait swapout period and check that the buffer is not requested to be
+ flushed to a disk.
+6. Call rtems_bdbuf_release_modified() function in thread #2.
+7. Check that this block number is requested for a flush in swapout period.
+
+
+
+Test 3
+~~~~~~
+
+Tests of this group check the behaviour of concurent reads from
+different tasks. Reads are done for different block numbers.
+
+Test 3.1
+~~~~~~~~
+
+Check how read/release work in case of only one buffer in ready list.
+
+1. In thread #1 call rtems_bdbuf_get(#N) to get an empty block #N.
+2. In thread #1 call rtems_bdbuf_release_modified() for previously got buffer.
+3. In thread #1 call rtems_bdbuf_read(#N) to get the same buffer
+ (after this call a buffer is in AVL tree with ACCESS_MODIFIED state).
+4. In thread #2 call rtems_bdbuf_read/get(#M).
+5. In thread #1 call rtems_bdbuf_release(#N).
+6. Check that in thread #2 a buffer is obtained.
+
+Test 3.2
+~~~~~~~~
+
+Check that when there are some tasks waiting for an available buffer only
+one of them get a buffer after some other task releases one.
+
+1. Call rtems_bdbuf_read(#N1) in thread #1.
+2. Call rtems_bdbuf_get(#N2) in thread #2.
+ This thread blocks because we have no buffers available.
+3. Call rtems_bdbuf_get(#N3) in thread #3.
+ This thread also blocks because we have no buffers available.
+4. Call rtems_bdbuf_release_modified(#N1) in thread #1.
+5. Check that only one thread (thread #2 or thread #3) got a buffer.
+ Another thread shall still be blocked.
+
+Test 3.3
+~~~~~~~~
+
+The same as Test 3.2, but instead of calling rtems_bdbuf_get() in
+threads #1 and #2, it calls rtems_bdbuf_read().
+
+1. Call rtems_bdbuf_read(#N1) in thread #1.
+2. Call rtems_bdbuf_read(#N2) in thread #2.
+ This thread blocks because we have no buffers available.
+3. Call rtems_bdbuf_read(#N3) in thread #3.
+ This thread also blocks because we have no buffers available.
+4. Call rtems_bdbuf_release(#N1) in thread #1.
+5. Check that only one thread (thread #2 or thread #3) got a buffer.
+ Another thread shall still be blocked.
+6. Call rtems_bdbuf_release(#N2) in thread #2 and check that thread #3
+ got a buffer as the result.
+
+Test 4
+~~~~~~
+
+Group of tests for sync buffer functionality.
+
+Test 4.1
+~~~~~~~~
+
+1. Call rtems_bdbuf_read(#N) in thread #1.
+2. Call rtems_bdbuf_read(#N) from thread #2.
+ Thread #2 blocks on this call.
+3. Call rtems_bdbuf_sync(#N) in thread #1.
+4. After a while disk driver gets write request for block #N.
+ Notify bdbuf library about write complete event.
+5. Check that thread #1 unlocked after this.
+6. Check that thread #2 unblocks and get buffer #N.
+7. Release buffer in thread #2.
+
+Test 4.2
+~~~~~~~~
+
+1. Call rtems_bdbuf_read(#N) in thread #1.
+2. Call rtems_bdbuf_sync(#N) in thread #1.
+3. After a while disk driver gets write request for block #N.
+4. Call rtems_bdbuf_read(#N) from thread #2 (before reply from the driver).
+ Thread #2 blocks on this call.
+5. Notify bdbuf library about write complete event.
+6. Check that rtems_bdbuf_sync(#N) in thread #1 unlocked after this.
+ (in fact a thread to unlock might be any).
+7. Check that thread #2 unblocks and get buffer #N.
+8. Release buffer in thread #2.
+
+Test 4.3
+~~~~~~~~
+
+1. Call rtems_bdbuf_read(#N) in thread #1.
+2. Call rtems_bdbuf_sync(#N) in thread #1.
+3. After a while disk driver gets write request for block #N.
+ Notify bdbuf about write complete event.
+4. Check that rtems_bdbuf_sync(#N) in thread #1 unlocked after this.
+5. Call rtems_bdbuf_read(#N) in thread #2.
+6. Check that buffer is successfully obtained in thread #2.
+7. Call rtems_bdbuf_release(#N) in thread #2.
+
+
+Test 4.4
+~~~~~~~~
+
+TODO: Two brances in sync() function should be tested.
diff --git a/testsuites/libtests/block08/block08.scn b/testsuites/libtests/block08/block08.scn
new file mode 100644
index 0000000000..75653cb999
--- /dev/null
+++ b/testsuites/libtests/block08/block08.scn
@@ -0,0 +1,86 @@
+test_disk_ioctl() Unexpected request comes 2
+TEST DISK - OK
+DEV: /dev/testdisk [1024]
+Test 1.4 - STARTED
+Thread #1 started
+Thread #2 started
+DISK_DRV: R [40]
+Test 1.4: Step 3 - OK
+Test 1.4: Step 5 - OK
+TEST PASSED
+Test 1.5 - STARTED
+Thread #1 started
+Thread #2 started
+DISK_DRV: R [50]
+Test 1.5: Step 1 - OK
+Test 1.5: Step 4 - OK
+TEST PASSED
+Test 2.1 - STARTED
+Thread #1 started
+Thread #2 started
+DISK_DRV: R [60]
+Test 2.1: Step 3 - OK
+Test 2.1: Step 5 - OK
+DISK_DRV: W [60]
+TEST PASSED
+Test 2.2 - STARTED
+Thread #1 started
+Thread #2 started
+DISK_DRV: R [70]
+Test 2.2: Step 3 - OK
+Test 2.2: Step 5 - OK
+DISK_DRV: W [70]
+TEST PASSED
+Test 3.1 - STARTED
+Thread #1 started
+Thread #2 started
+Test 3.1: Step 3 - OK
+DISK_DRV: W [80]
+Test 3.1: Step 5 - OK
+DISK_DRV: W [85]
+TEST PASSED
+Test 3.2 - STARTED
+Thread #1 started
+Thread #2 started
+Thread #3 started
+DISK_DRV: R [90]
+Thread #2 DEBLOCK
+Test 3.2: Step 5 - OK
+DISK_DRV: W [92]
+Thread #3 DEBLOCK
+DISK_DRV: W [94]
+TEST PASSED
+Test 3.3 - STARTED
+Thread #1 started
+Thread #2 started
+Thread #3 started
+DISK_DRV: R [96]
+DISK_DRV: R [98]
+Thread #2 DEBLOCK
+Test 3.3: Step 5 - OK
+DISK_DRV: R [100]
+Thread #3 DEBLOCK
+TEST PASSED
+Test 4.1 - STARTED
+Thread #1 started
+Thread #2 started
+DISK_DRV: R [112]
+Test 4.1: Step 2 - OK
+DISK_DRV: W [112]
+Test 4.1: Step 5 - OK
+TEST PASSED
+Test 4.2 - STARTED
+Thread #1 started
+Thread #2 started
+DISK_DRV: R [114]
+DISK_DRV: W [114]
+Test 4.2: Step 3 - OK
+Test 4.2: Step 7 - OK
+TEST PASSED
+Test 4.3 - STARTED
+Thread #1 started
+Thread #2 started
+DISK_DRV: R [116]
+DISK_DRV: W [116]
+Test 4.3: Step 4 - OK
+TEST PASSED
diff --git a/testsuites/libtests/block08/init.c b/testsuites/libtests/block08/init.c
new file mode 100644
index 0000000000..aad3ced4f4
--- /dev/null
+++ b/testsuites/libtests/block08/init.c
@@ -0,0 +1,32 @@
+/* Init
+ *
+ * This routine is the initialization task for this test program.
+ *
+ * Input parameters:
+ * argument - task argument
+ *
+ * Output parameters: NONE
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#define CONFIGURE_INIT
+#include "system.h"
+
+#include "bdbuf_tests.h"
+
+rtems_task Init(rtems_task_argument argument)
+{
+ rtems_status_code status;
+
+ run_bdbuf_tests();
+ exit(0);
+}
+
diff --git a/testsuites/libtests/block08/system.h b/testsuites/libtests/block08/system.h
new file mode 100644
index 0000000000..2d2f46c3da
--- /dev/null
+++ b/testsuites/libtests/block08/system.h
@@ -0,0 +1,56 @@
+/* system.h
+ *
+ * This include file contains information that is included in every
+ * function in the test set.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include "rtems/blkdev.h"
+
+rtems_task Init(
+ rtems_task_argument argument
+);
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS 28
+#define CONFIGURE_MAXIMUM_TIMERS 10
+#define CONFIGURE_MAXIMUM_SEMAPHORES 20
+#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 10
+#define CONFIGURE_MAXIMUM_PARTITIONS 1
+#define CONFIGURE_MAXIMUM_REGIONS 1
+#define CONFIGURE_MAXIMUM_PERIODS 1
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 0
+#define CONFIGURE_TICKS_PER_TIMESLICE 100
+
+#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
+#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 2
+#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (512)
+#define CONFIGURE_BDBUF_BUFFER_MIN_SIZE (512)
+#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE (512)
+
+/*
+ * Define it here in order to be able to register
+ * test driver after RTEMS initialization phase
+ * (on test start-up).
+ */
+#define CONFIGURE_MAXIMUM_DRIVERS 5
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_INIT_TASK_STACK_SIZE (4 * RTEMS_MINIMUM_STACK_SIZE)
+
+#define CONFIGURE_EXTRA_TASK_STACKS (13 * RTEMS_MINIMUM_STACK_SIZE)
+
+#include <rtems/confdefs.h>
+
+/* end of include file */
diff --git a/testsuites/libtests/block08/test_disk.c b/testsuites/libtests/block08/test_disk.c
new file mode 100644
index 0000000000..358b3614ae
--- /dev/null
+++ b/testsuites/libtests/block08/test_disk.c
@@ -0,0 +1,154 @@
+/*! @file
+ * @brief Test disk block device implementation.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "rtems/blkdev.h"
+#include "rtems/diskdevs.h"
+
+#include "bdbuf_tests.h"
+
+static Objects_Id drvq_id = OBJECTS_ID_NONE;
+static Objects_Id testq_id = OBJECTS_ID_NONE;
+
+static int
+test_disk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
+{
+ dev_t dev = rtems_disk_get_device_identifier(dd);
+ rtems_status_code rc;
+ bdbuf_test_msg msg;
+ size_t msg_size;
+
+ switch (req)
+ {
+ case RTEMS_BLKIO_REQUEST:
+ {
+ rtems_blkdev_request *r = argp;
+ rtems_blkdev_sg_buffer *sg;
+ unsigned int i;
+
+ printk("DISK_DRV: %s ",
+ r->req == RTEMS_BLKDEV_REQ_READ ? "R" :
+ r->req == RTEMS_BLKDEV_REQ_WRITE ? "W" : "?");
+ for (i = 0, sg = r->bufs; i < r->bufnum; i++, sg++)
+ {
+ printk("[%d] ", sg->block);
+ }
+ printk("\n");
+ break;
+ }
+
+ default:
+ printk("%s() Unexpected request comes %u\n",
+ __FUNCTION__, req);
+ return -1;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+ msg.type = BDBUF_TEST_MSG_TYPE_DRIVER_REQ;
+ msg.val.driver_req.dev = dev;
+ msg.val.driver_req.req = req;
+ msg.val.driver_req.argp = argp;
+
+ rc = rtems_message_queue_send(testq_id, &msg, sizeof(msg));
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ printf("Error while sending a message to Test task: %u\n", rc);
+ return -1;
+ }
+
+ /* Wait for a reply from the test task */
+ msg_size = sizeof(msg);
+ rc = rtems_message_queue_receive(drvq_id, &msg, &msg_size,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ printf("Error while reading a message from Test task: %u\n", rc);
+ return rc;
+ }
+ if (msg.type != BDBUF_TEST_MSG_TYPE_DRIVER_REPLY)
+ {
+ printf("Unexpected message comes to test disk driver: %d\n",
+ msg.type);
+ return -1;
+ }
+
+ if (msg.val.driver_reply.ret_val != 0)
+ {
+ errno = msg.val.driver_reply.ret_errno;
+ }
+ else
+ {
+ rtems_blkdev_request *r = (rtems_blkdev_request *)argp;
+
+ r->req_done(r->done_arg, msg.val.driver_reply.res_status);
+ }
+
+ return msg.val.driver_reply.ret_val;
+}
+
+rtems_device_driver
+test_disk_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_status_code rc;
+ dev_t dev;
+
+ rc = rtems_disk_io_initialize();
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+
+ dev = rtems_filesystem_make_dev_t(major, minor);
+ rc = rtems_disk_create_phys(dev,
+ TEST_DISK_BLOCK_SIZE, TEST_DISK_BLOCK_NUM,
+ test_disk_ioctl,
+ NULL,
+ TEST_DISK_NAME);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ printf("Failed to create %s disk\n", TEST_DISK_NAME);
+ return rc;
+ }
+
+ rc = bdbuf_test_create_drv_rx_queue(&drvq_id);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ printk("%s() Failed to create Msg Queue for RX: %u\n",
+ __FUNCTION__, rc);
+ return rc;
+ }
+
+ rc = bdbuf_test_create_drv_tx_queue(&testq_id);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ printf("%s() Failed to get Msg Queue for TX: %u\n",
+ __FUNCTION__, rc);
+ return rc;
+ }
+
+ printk("TEST DISK - OK\n");
+ return RTEMS_SUCCESSFUL;
+}
+