diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2010-01-19 08:55:18 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2010-01-19 08:55:18 +0000 |
commit | 64734fc14b1015c1568c2906c9aeab1c6a7db82d (patch) | |
tree | 853af83fb05c8fcf05e3d7c44308895377b0028d /testsuites | |
parent | 2010-01-18 Joel Sherrill <joel.sherrill@oarcorp.com> (diff) | |
download | rtems-64734fc14b1015c1568c2906c9aeab1c6a7db82d.tar.bz2 |
updates and new test cases
Diffstat (limited to 'testsuites')
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 |