summaryrefslogtreecommitdiffstats
path: root/testsuites
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
parent2010-01-18 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-64734fc14b1015c1568c2906c9aeab1c6a7db82d.tar.bz2
updates and new test cases
Diffstat (limited to 'testsuites')
-rw-r--r--testsuites/libtests/ChangeLog21
-rw-r--r--testsuites/libtests/Makefile.am2
-rw-r--r--testsuites/libtests/block05/block05.doc21
-rw-r--r--testsuites/libtests/block05/init.c2
-rw-r--r--testsuites/libtests/block06/init.c4
-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
-rw-r--r--testsuites/libtests/block09/Makefile.am27
-rw-r--r--testsuites/libtests/block09/block09.doc27
-rw-r--r--testsuites/libtests/block09/block09.scn2
-rw-r--r--testsuites/libtests/block09/init.c226
-rw-r--r--testsuites/libtests/configure.ac2
31 files changed, 4073 insertions, 14 deletions
diff --git a/testsuites/libtests/ChangeLog b/testsuites/libtests/ChangeLog
index e1cd9e1ad5..e3366c519e 100644
--- a/testsuites/libtests/ChangeLog
+++ b/testsuites/libtests/ChangeLog
@@ -1,3 +1,24 @@
+2010-01-18 Sebastian Huber <Sebastian.Huber@embedded-brains.de>
+
+ * block09/block09.doc, block09/init.c, block09/.cvsignore,
+ block09/block09.scn, block09/Makefile.am: New files.
+ * configure.ac, Makefile.am: Update for new files.
+ * block05/block05.doc: Update for new state transitions.
+ * block05/init.c, block06/init.c: Update for block device API change.
+
+2010-01-18 Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+
+ * block08/bdbuf_test1_1.c, block08/bdbuf_test1_2.c,
+ block08/bdbuf_test1_3.c, block08/bdbuf_test1_4.c,
+ block08/bdbuf_test1_5.c, block08/bdbuf_test2_1.c,
+ block08/bdbuf_test2_2.c, block08/bdbuf_test3_1.c,
+ block08/bdbuf_test3_2.c, block08/bdbuf_test3_3.c,
+ block08/bdbuf_test4_1.c, block08/bdbuf_test4_2.c,
+ block08/bdbuf_test4_3.c, block08/bdbuf_tests.c, block08/bdbuf_tests.h,
+ block08/block08.doc, block08/block08.scn, block08/.cvsignore,
+ block08/init.c, block08/Makefile.am, block08/system.h,
+ block08/test_disk.c: New files.
+
2009-12-28 Aanjhan Ranganathan <aanjhan@gmail.com>
* bspcmdline01/init.c, bspcmdline01/bspcmdline01.scn: Added test case
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index a5958e5443..cc51b4970b 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -7,7 +7,7 @@ ACLOCAL_AMFLAGS = -I ../aclocal
SUBDIRS = bspcmdline01 cpuuse malloctest heapwalk putenvtest monitor \
monitor02 rtmonuse stackchk stackchk01 termios termios01 termios02 \
rtems++ tztest block01 block02 block03 block04 block05 block06 block07 \
- stringto01
+ block08 block09 stringto01
SUBDIRS += POSIX
include $(top_srcdir)/../automake/subdirs.am
diff --git a/testsuites/libtests/block05/block05.doc b/testsuites/libtests/block05/block05.doc
index 29ec114656..819701f250 100644
--- a/testsuites/libtests/block05/block05.doc
+++ b/testsuites/libtests/block05/block05.doc
@@ -32,13 +32,14 @@ concepts:
State changes count during this test:
| PREVIOUS STATE
-------+-------------------------------------------------------------------
- | EM FR CA AC AM MO SY TR
- | EM 6480 0 5040 0 0 0 0 0
- | FR 5041 0 23040 0 0 0 0 0
- | CA 0 0 0 22212 0 0 0 31608
-NEW | AC 0 17569 25739 0 0 0 0 0
-STATE | AM 0 0 0 0 0 3348 0 0
- | MO 0 0 0 10548 2232 0 0 0
- | SY 0 0 0 10548 1116 0 0 0
- | TR 0 10512 0 0 0 9432 11664 0
+ | FR EM CA AC AM AE MO SY TR
+------+------------------------------------------------------------------
+ | FR 7470 0 4050 0 0 11368 0 0 0
+ | EM 15419 0 17389 0 0 523 0 0 0
+ | CA 0 0 0 10301 0 0 0 0 33886
+ | AC 0 0 22747 0 0 0 0 0 0
+NEW | AM 0 0 0 0 0 0 3424 0 0
+STATE | AE 0 20485 0 0 0 0 0 0 0
+ | MO 0 0 0 6226 2280 4294 0 0 0
+ | SY 0 0 0 6220 1144 4300 0 0 0
+ | TR 0 12846 0 0 0 0 9376 11664 0
diff --git a/testsuites/libtests/block05/init.c b/testsuites/libtests/block05/init.c
index f26f3cb269..2cdc17774c 100644
--- a/testsuites/libtests/block05/init.c
+++ b/testsuites/libtests/block05/init.c
@@ -368,7 +368,7 @@ static int disk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
switch (r->req) {
case RTEMS_BLKDEV_REQ_READ:
case RTEMS_BLKDEV_REQ_WRITE:
- r->req_done(r->done_arg, RTEMS_SUCCESSFUL, 0);
+ r->req_done(r->done_arg, RTEMS_SUCCESSFUL);
return 0;
default:
errno = EINVAL;
diff --git a/testsuites/libtests/block06/init.c b/testsuites/libtests/block06/init.c
index 0a07708b19..92ef0cd8ee 100644
--- a/testsuites/libtests/block06/init.c
+++ b/testsuites/libtests/block06/init.c
@@ -501,7 +501,7 @@ bdbuf_disk_ioctl (rtems_disk_device *dd, uint32_t req, void* argp)
remains -= length;
}
- r->req_done (r->done_arg, RTEMS_SUCCESSFUL, 0);
+ r->req_done (r->done_arg, RTEMS_SUCCESSFUL);
}
bdbuf_disk_ioctl_leave (bdd, r->bufnum);
break;
@@ -509,7 +509,7 @@ bdbuf_disk_ioctl (rtems_disk_device *dd, uint32_t req, void* argp)
case RTEMS_BLKDEV_REQ_WRITE:
if (!bdbuf_disk_ioctl_process (bdd, r))
errno = EIO;
- r->req_done (r->done_arg, RTEMS_SUCCESSFUL, 0);
+ r->req_done (r->done_arg, RTEMS_SUCCESSFUL);
bdbuf_disk_ioctl_leave (bdd, r->bufnum);
break;
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;
+}
+
diff --git a/testsuites/libtests/block09/Makefile.am b/testsuites/libtests/block09/Makefile.am
new file mode 100644
index 0000000000..a59029463e
--- /dev/null
+++ b/testsuites/libtests/block09/Makefile.am
@@ -0,0 +1,27 @@
+##
+## $Id$
+##
+
+MANAGERS = io semaphore event
+
+rtems_tests_PROGRAMS = block09
+block09_SOURCES = init.c
+
+dist_rtems_tests_DATA = block09.scn block09.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+block09_LDADD = $(MANAGERS_NOT_WANTED:%=$(PROJECT_LIB)/no-%.rel)
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(block09_OBJECTS) $(block09_LDADD)
+LINK_LIBS = $(block09_LDLIBS)
+
+block09$(EXEEXT): $(block09_OBJECTS) $(block09_DEPENDENCIES)
+ @rm -f block09$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/libtests/block09/block09.doc b/testsuites/libtests/block09/block09.doc
new file mode 100644
index 0000000000..ec118a86a5
--- /dev/null
+++ b/testsuites/libtests/block09/block09.doc
@@ -0,0 +1,27 @@
+#
+# $Id$
+#
+# Copyright (c) 2010
+# embedded brains GmbH
+# Obere Lagerstr. 30
+# D-82178 Puchheim
+# Germany
+# <rtems@embedded-brains.de>
+#
+# 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.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: block09
+
+directives:
+
+ rtems_bdbuf_read
+ rtems_bdbuf_sync
+
+concepts:
+
++ Disk driver error handling..
diff --git a/testsuites/libtests/block09/block09.scn b/testsuites/libtests/block09/block09.scn
new file mode 100644
index 0000000000..c9fd1d459b
--- /dev/null
+++ b/testsuites/libtests/block09/block09.scn
@@ -0,0 +1,2 @@
+*** TEST BLOCK 9 ***
+*** END OF TEST BLOCK 9 ***
diff --git a/testsuites/libtests/block09/init.c b/testsuites/libtests/block09/init.c
new file mode 100644
index 0000000000..e413a1f748
--- /dev/null
+++ b/testsuites/libtests/block09/init.c
@@ -0,0 +1,226 @@
+/**
+ * @file
+ *
+ * @ingroup test_bdbuf
+ *
+ * @brief Bdbuf test for disk driver error handling..
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/bdbuf.h>
+#include <rtems/diskdevs.h>
+
+#define ASSERT_SC(sc) assert((sc) == RTEMS_SUCCESSFUL)
+
+#define BLOCK_SIZE sizeof(char)
+
+#define BLOCK_COUNT 4
+
+#define BLOCK_READ_IO_ERROR 0
+#define BLOCK_READ_UNSATISFIED 1
+#define BLOCK_READ_SUCCESSFUL 2
+#define BLOCK_WRITE_IO_ERROR 3
+
+static char disk_data [BLOCK_COUNT];
+
+static const rtems_driver_address_table disk_ops = {
+ .initialization_entry = NULL,
+ RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES
+};
+
+static int disk_ioctl(rtems_disk_device *dd, uint32_t req, void *arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (req == RTEMS_BLKIO_REQUEST) {
+ rtems_blkdev_request *r = arg;
+ uint32_t i = 0;
+
+ for (i = 0; i < r->bufnum; ++i) {
+ rtems_blkdev_sg_buffer *sg = &r->bufs [i];
+ char *buf = sg->buffer;
+
+ if (sg->length != 1) {
+ return -1;
+ }
+
+ switch (r->req) {
+ case RTEMS_BLKDEV_REQ_READ:
+ switch (sg->block) {
+ case BLOCK_READ_IO_ERROR:
+ sc = RTEMS_IO_ERROR;
+ break;
+ case BLOCK_READ_UNSATISFIED:
+ sc = RTEMS_UNSATISFIED;
+ break;
+ case BLOCK_READ_SUCCESSFUL:
+ case BLOCK_WRITE_IO_ERROR:
+ *buf = disk_data [sg->block];
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case RTEMS_BLKDEV_REQ_WRITE:
+ switch (sg->block) {
+ case BLOCK_READ_IO_ERROR:
+ case BLOCK_READ_UNSATISFIED:
+ case BLOCK_READ_SUCCESSFUL:
+ disk_data [sg->block] = *buf;
+ break;
+ case BLOCK_WRITE_IO_ERROR:
+ sc = RTEMS_IO_ERROR;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ r->req_done(r->done_arg, sc);
+
+ return 0;
+ } else {
+ return rtems_blkdev_ioctl(dd, req, arg);
+ }
+}
+
+rtems_status_code disk_register(
+ uint32_t block_size,
+ rtems_blkdev_bnum block_count,
+ dev_t *dev_ptr
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_device_major_number major = 0;
+ dev_t dev = 0;
+
+ sc = rtems_io_register_driver(0, &disk_ops, &major);
+ ASSERT_SC(sc);
+
+ dev = rtems_filesystem_make_dev_t(major, 0);
+
+ sc = rtems_disk_create_phys(
+ dev,
+ block_size,
+ block_count,
+ disk_ioctl,
+ NULL,
+ NULL
+ );
+ ASSERT_SC(sc);
+
+ *dev_ptr = dev;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+static void check_read(
+ dev_t dev,
+ rtems_blkdev_bnum block,
+ rtems_status_code expected_sc
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_bdbuf_buffer *bd = NULL;
+
+ sc = rtems_bdbuf_read(dev, block, &bd);
+ assert(sc == expected_sc);
+
+ if (sc == RTEMS_SUCCESSFUL) {
+ sc = rtems_bdbuf_release(bd);
+ ASSERT_SC(sc);
+ }
+}
+
+static rtems_task Init(rtems_task_argument argument)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_bdbuf_buffer *bd = NULL;
+ dev_t dev = 0;
+
+ printk("\n\n*** TEST BLOCK 9 ***\n");
+
+ sc = rtems_disk_io_initialize();
+ ASSERT_SC(sc);
+
+ sc = disk_register(BLOCK_SIZE, BLOCK_COUNT, &dev);
+ ASSERT_SC(sc);
+
+ check_read(dev, BLOCK_READ_IO_ERROR, RTEMS_IO_ERROR);
+ check_read(dev, BLOCK_READ_UNSATISFIED, RTEMS_UNSATISFIED);
+ check_read(dev, BLOCK_READ_SUCCESSFUL, RTEMS_SUCCESSFUL);
+ check_read(dev, BLOCK_WRITE_IO_ERROR, RTEMS_SUCCESSFUL);
+
+ /* Check write IO error */
+
+ sc = rtems_bdbuf_read(dev, BLOCK_WRITE_IO_ERROR, &bd);
+ ASSERT_SC(sc);
+
+ bd->buffer [0] = 1;
+
+ sc = rtems_bdbuf_sync(bd);
+ ASSERT_SC(sc);
+
+ sc = rtems_bdbuf_read(dev, BLOCK_WRITE_IO_ERROR, &bd);
+ ASSERT_SC(sc);
+
+ assert(bd->buffer [0] == 0);
+
+ sc = rtems_bdbuf_release(bd);
+ ASSERT_SC(sc);
+
+ /* Check write to deleted disk */
+
+ sc = rtems_bdbuf_read(dev, BLOCK_READ_SUCCESSFUL, &bd);
+ ASSERT_SC(sc);
+
+ sc = rtems_disk_delete(dev);
+ ASSERT_SC(sc);
+
+ sc = rtems_bdbuf_sync(bd);
+ ASSERT_SC(sc);
+
+ printk("*** END OF TEST BLOCK 9 ***\n");
+
+ exit(0);
+}
+
+#define CONFIGURE_INIT
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+
+#define CONFIGURE_MAXIMUM_TASKS 3
+#define CONFIGURE_MAXIMUM_DRIVERS 4
+#define CONFIGURE_MAXIMUM_SEMAPHORES 5
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_BDBUF_BUFFER_MIN_SIZE BLOCK_SIZE
+#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE BLOCK_SIZE
+#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (BLOCK_SIZE * BLOCK_COUNT)
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index 4fd8da82f9..a93ba4ccda 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -40,6 +40,8 @@ block04/Makefile
block05/Makefile
block06/Makefile
block07/Makefile
+block08/Makefile
+block09/Makefile
bspcmdline01/Makefile
cpuuse/Makefile
heapwalk/Makefile