From e7fb54eb0593f80966502ca9b3cc2159e5e4a863 Mon Sep 17 00:00:00 2001 From: Thomas Doerfler Date: Tue, 26 Jan 2010 15:09:03 +0000 Subject: add purge capability to libblock, add proper test case --- testsuites/libtests/block10/Makefile.am | 27 ++ testsuites/libtests/block10/block10.doc | 47 ++++ testsuites/libtests/block10/block10.png | Bin 0 -> 70224 bytes testsuites/libtests/block10/block10.scn | 226 +++++++++++++++ testsuites/libtests/block10/init.c | 481 ++++++++++++++++++++++++++++++++ 5 files changed, 781 insertions(+) create mode 100644 testsuites/libtests/block10/Makefile.am create mode 100644 testsuites/libtests/block10/block10.doc create mode 100644 testsuites/libtests/block10/block10.png create mode 100644 testsuites/libtests/block10/block10.scn create mode 100644 testsuites/libtests/block10/init.c (limited to 'testsuites/libtests/block10') diff --git a/testsuites/libtests/block10/Makefile.am b/testsuites/libtests/block10/Makefile.am new file mode 100644 index 0000000000..2df0bb48c5 --- /dev/null +++ b/testsuites/libtests/block10/Makefile.am @@ -0,0 +1,27 @@ +## +## $Id$ +## + +MANAGERS = io semaphore event + +rtems_tests_PROGRAMS = block10 +block10_SOURCES = init.c + +dist_rtems_tests_DATA = block10.scn block10.doc block10.png + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +block10_LDADD = $(MANAGERS_NOT_WANTED:%=$(PROJECT_LIB)/no-%.rel) + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(block10_OBJECTS) $(block10_LDADD) +LINK_LIBS = $(block10_LDLIBS) + +block10$(EXEEXT): $(block10_OBJECTS) $(block10_DEPENDENCIES) + @rm -f block10$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/libtests/block10/block10.doc b/testsuites/libtests/block10/block10.doc new file mode 100644 index 0000000000..de1f9057e9 --- /dev/null +++ b/testsuites/libtests/block10/block10.doc @@ -0,0 +1,47 @@ +# +# $Id$ +# +# Copyright (c) 2010 +# embedded brains GmbH +# Obere Lagerstr. 30 +# D-82178 Puchheim +# Germany +# +# +# 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: block10 + +directives: + + rtems_bdbuf_get + rtems_bdbuf_read + rtems_bdbuf_release + rtems_bdbuf_release_modified + rtems_bdbuf_sync + +concepts: + ++ Purge functions test in various states + +State changes count during this test: + + | PREVIOUS STATE + | FR EM CA AC AM AE AP MO SY TF TP +---------+--------------------------------- + FR | 0 28 0 0 0 0 0 0 0 0 0 + EM | 28 0 4 0 0 14 18 2 2 0 2 + CA | 0 0 0 2 0 0 0 0 0 18 0 + AC | 0 0 16 0 0 0 0 0 0 0 0 +NEW AM | 0 0 0 0 0 0 0 6 0 0 0 +STATE AE | 0 26 0 0 0 0 0 0 0 0 0 + AP | 0 0 0 6 6 6 0 0 0 0 0 + MO | 0 0 0 2 0 6 0 0 0 0 0 + SY | 0 0 0 6 0 0 0 0 0 0 0 + TF | 0 16 0 0 0 0 0 0 4 0 0 + TP | 0 0 0 0 0 0 0 0 0 2 0 diff --git a/testsuites/libtests/block10/block10.png b/testsuites/libtests/block10/block10.png new file mode 100644 index 0000000000..6ff93dadc1 Binary files /dev/null and b/testsuites/libtests/block10/block10.png differ diff --git a/testsuites/libtests/block10/block10.scn b/testsuites/libtests/block10/block10.scn new file mode 100644 index 0000000000..dc5ab15784 --- /dev/null +++ b/testsuites/libtests/block10/block10.scn @@ -0,0 +1,226 @@ +*** TEST BLOCK 10 *** +test case [access]: get and release with waiter +I: try get +I: get +W: try get +I: purge +I: release +I: release done +W: get +W: release +W: release done +test case [access]: get and release without waiter +I: try get +I: get +I: purge +I: release +I: release done +test case [access]: get and release modified with waiter +I: try get +I: get +W: try get +I: purge +I: release modified +I: release modified done +W: get +W: release +W: release done +test case [access]: get and release modified without waiter +I: try get +I: get +I: purge +I: release modified +I: release modified done +test case [access]: get and sync with waiter +I: try get +I: get +W: try get +I: purge +I: sync +I: sync done +W: get +W: release +W: release done +test case [access]: get and sync without waiter +I: try get +I: get +I: purge +I: sync +I: sync done +test case [access]: access modified and release with waiter +I: try get modified +I: get modified +W: try get +I: purge +I: release +I: release done +W: get +W: release +W: release done +test case [access]: access modified and release without waiter +I: try get modified +I: get modified +I: purge +I: release +I: release done +test case [access]: access modified and release modified with waiter +I: try get modified +I: get modified +W: try get +I: purge +I: release modified +I: release modified done +W: get +W: release +W: release done +test case [access]: access modified and release modified without waiter +I: try get modified +I: get modified +I: purge +I: release modified +I: release modified done +test case [access]: access modified and sync with waiter +I: try get modified +I: get modified +W: try get +I: purge +I: sync +I: sync done +W: get +W: release +W: release done +test case [access]: access modified and sync without waiter +I: try get modified +I: get modified +I: purge +I: sync +I: sync done +test case [access]: read and release with waiter +I: try read +I: read +W: try get +I: purge +I: release +I: release done +W: get +W: release +W: release done +test case [access]: read and release without waiter +I: try read +I: read +I: purge +I: release +I: release done +test case [access]: read and release modified with waiter +I: try read +I: read +W: try get +I: purge +I: release modified +I: release modified done +W: get +W: release +W: release done +test case [access]: read and release modified without waiter +I: try read +I: read +I: purge +I: release modified +I: release modified done +test case [access]: read and sync with waiter +I: try read +I: read +W: try get +I: purge +I: sync +I: sync done +W: get +W: release +W: release done +test case [access]: read and sync without waiter +I: try read +I: read +I: purge +I: sync +I: sync done +test case [intermediate]: release with waiter +I: try read +I: read +W: try get +I: release +I: release done +I: purge +W: get +W: release +W: release done +test case [intermediate]: release without waiter +I: try read +I: read +I: release +I: release done +I: purge +test case [intermediate]: release modified with waiter +I: try read +I: read +W: try get +I: release modified +I: release modified done +I: purge +W: get +W: release +W: release done +test case [intermediate]: release modified without waiter +I: try read +I: read +I: release modified +I: release modified done +I: purge +test case [intermediate]: sync with waiter +I: try read +I: read +W: try get +I: sync +I: sync done +I: purge +W: get +W: release +W: release done +test case [intermediate]: sync without waiter +I: try read +I: read +I: sync +I: sync done +I: purge +test case [transfer]: sync with waiter +I: try read +I: read +W: try get +I: sync +P: purge +I: sync done +W: get +W: release +W: release done +test case [transfer]: sync without waiter +I: try read +I: read +I: sync +P: purge +I: sync done +test case [transfer]: transfer with waiter +I: try read +I: read +W: try get +I: sync +P: purge +I: sync done +W: get +W: release +W: release done +test case [transfer]: transfer without waiter +I: try read +I: read +I: sync +P: purge +I: sync done +*** END OF TEST BLOCK 10 *** diff --git a/testsuites/libtests/block10/init.c b/testsuites/libtests/block10/init.c new file mode 100644 index 0000000000..add29768e4 --- /dev/null +++ b/testsuites/libtests/block10/init.c @@ -0,0 +1,481 @@ +/** + * @file + * + * @ingroup test_bdbuf + * + * @brief Bdbuf test for purge. + */ + +/* + * Copyright (c) 2010 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * + * + * 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 +#include + +#include +#include +#include + +#define ASSERT_SC(sc) assert((sc) == RTEMS_SUCCESSFUL) + +#define PRIORITY_HIGH 1 + +#define PRIORITY_INIT 2 + +#define PRIORITY_MID 3 + +#define PRIORITY_SWAPOUT 4 + +#define PRIORITY_LOW 5 + +#define PRIORITY_IDLE 6 + +#define BLOCK_SIZE 1 + +#define BLOCK_COUNT 1 + +typedef rtems_bdbuf_buffer *(*access_func)(char task); + +typedef void (*release_func)(char task, rtems_bdbuf_buffer *bd); + +static dev_t dev; + +static rtems_id task_id_init; + +static rtems_id task_id_purger; + +static rtems_id task_id_waiter; + +static const rtems_driver_address_table disk_ops = { + .initialization_entry = NULL, + RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES +}; + +static void set_task_prio(rtems_id task, rtems_task_priority prio) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_task_priority cur = 0; + + sc = rtems_task_set_priority(task, prio, &cur); + ASSERT_SC(sc); +} + +static void suspend(rtems_id task) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_task_suspend(task); + ASSERT_SC(sc); +} + +static void resume(rtems_id task) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_task_resume(task); + ASSERT_SC(sc); +} + +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; + + if (r->req == RTEMS_BLKDEV_REQ_WRITE) { + set_task_prio(RTEMS_SELF, PRIORITY_IDLE); + set_task_prio(RTEMS_SELF, PRIORITY_SWAPOUT); + } + + 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 rtems_bdbuf_buffer *do_get(char task) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_bdbuf_buffer *bd = NULL; + + printk("%c: try get\n", task); + + sc = rtems_bdbuf_get(dev, 0, &bd); + ASSERT_SC(sc); + + printk("%c: get\n", task); + + return bd; +} + +static rtems_bdbuf_buffer *do_get_mod(char task) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_bdbuf_buffer *bd = NULL; + + printk("%c: try get modified\n", task); + + sc = rtems_bdbuf_get(dev, 0, &bd); + ASSERT_SC(sc); + + sc = rtems_bdbuf_release_modified(bd); + ASSERT_SC(sc); + + sc = rtems_bdbuf_get(dev, 0, &bd); + ASSERT_SC(sc); + + printk("%c: get modified\n", task); + + return bd; +} + +static rtems_bdbuf_buffer *do_read(char task) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_bdbuf_buffer *bd = NULL; + + printk("%c: try read\n", task); + + sc = rtems_bdbuf_read(dev, 0, &bd); + ASSERT_SC(sc); + + printk("%c: read\n", task); + + return bd; +} + +static void do_rel(char task, rtems_bdbuf_buffer *bd) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + printk("%c: release\n", task); + + sc = rtems_bdbuf_release(bd); + ASSERT_SC(sc); + + printk("%c: release done\n", task); +} + +void do_rel_mod(char task, rtems_bdbuf_buffer *bd) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + printk("%c: release modified\n", task); + + sc = rtems_bdbuf_release_modified(bd); + ASSERT_SC(sc); + + printk("%c: release modified done\n", task); +} + +static void do_sync(char task, rtems_bdbuf_buffer *bd) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + printk("%c: sync\n", task); + + sc = rtems_bdbuf_sync(bd); + ASSERT_SC(sc); + + printk("%c: sync done\n", task); +} + +static void purge(char task) +{ + printk("%c: purge\n", task); + + rtems_bdbuf_purge_dev(dev); +} + +static void task_purger(rtems_task_argument arg) +{ + while (true) { + suspend(RTEMS_SELF); + + set_task_prio(RTEMS_SELF, PRIORITY_HIGH); + + purge('P'); + } + + rtems_task_delete(RTEMS_SELF); +} + +static void activate_purger(rtems_task_priority prio) +{ + set_task_prio(task_id_purger, prio); + resume(task_id_purger); +} + +static void task_waiter(rtems_task_argument arg) +{ + while (true) { + rtems_bdbuf_buffer *bd = NULL; + + suspend(RTEMS_SELF); + + bd = do_get('W'); + + do_rel('W', bd); + } + + rtems_task_delete(RTEMS_SELF); +} + +static void create_waiter(void) +{ + resume(task_id_waiter); + set_task_prio(task_id_waiter, PRIORITY_IDLE); +} + +static void restore_waiter(void) +{ + set_task_prio(task_id_waiter, PRIORITY_HIGH); +} + +static void check_access(access_func ac, release_func rel, bool waiter) +{ + rtems_bdbuf_buffer *bd = (*ac)('I'); + + if (waiter) { + create_waiter(); + } + + purge('I'); + + (*rel)('I', bd); + + if (waiter) { + restore_waiter(); + } +} + +static void check_intermediate(release_func rel, bool waiter) +{ + rtems_bdbuf_buffer *bd = do_read('I'); + + if (waiter) { + create_waiter(); + } + + (*rel)('I', bd); + + purge('I'); + + if (waiter) { + restore_waiter(); + } +} + +static void check_transfer(rtems_task_priority prio, bool waiter) +{ + rtems_bdbuf_buffer *bd = do_read('I'); + + if (waiter) { + create_waiter(); + } + + activate_purger(prio); + + do_sync('I', bd); + + if (waiter) { + restore_waiter(); + } +} + +static const bool waiter_table [] = { + true, + false +}; + +static const access_func access_table [] = { + do_get, + do_get_mod, + do_read +}; + +static const release_func release_table [] = { + do_rel, + do_rel_mod, + do_sync +}; + +static const rtems_task_priority purger_table [] = { + PRIORITY_MID, + PRIORITY_LOW +}; + +#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array [0])) + +#define WAITER_COUNT ARRAY_COUNT(waiter_table) + +#define ACCESS_COUNT ARRAY_COUNT(access_table) + +#define RELEASE_COUNT ARRAY_COUNT(release_table) + +#define PURGER_COUNT ARRAY_COUNT(purger_table) + +static const char *waiter_assoc_table [WAITER_COUNT] = { + "with waiter", + "without waiter" +}; + +static const char *access_assoc_table [ACCESS_COUNT] = { + "get", + "access modified", + "read" +}; + +static const char *release_assoc_table [RELEASE_COUNT] = { + "release", + "release modified", + "sync" +}; + +static const char *purger_assoc_table [PURGER_COUNT] = { + "sync", + "transfer" +}; + +static rtems_task Init(rtems_task_argument argument) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + size_t i_w = 0; + size_t i_ac = 0; + size_t i_rel = 0; + size_t i_p = 0; + + printk("\n\n*** TEST BLOCK 10 ***\n"); + + task_id_init = rtems_task_self(); + + sc = rtems_disk_io_initialize(); + ASSERT_SC(sc); + + sc = disk_register(BLOCK_SIZE, BLOCK_COUNT, &dev); + ASSERT_SC(sc); + + sc = rtems_task_create( + rtems_build_name('P', 'U', 'R', 'G'), + PRIORITY_HIGH, + 0, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &task_id_purger + ); + ASSERT_SC(sc); + + sc = rtems_task_start(task_id_purger, task_purger, 0); + ASSERT_SC(sc); + + set_task_prio(task_id_purger, PRIORITY_LOW); + + sc = rtems_task_create( + rtems_build_name('W', 'A', 'I', 'T'), + PRIORITY_HIGH, + 0, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &task_id_waiter + ); + ASSERT_SC(sc); + + sc = rtems_task_start(task_id_waiter, task_waiter, 0); + ASSERT_SC(sc); + + for (i_ac = 0; i_ac < ACCESS_COUNT; ++i_ac) { + for (i_rel = 0; i_rel < RELEASE_COUNT; ++i_rel) { + for (i_w = 0; i_w < WAITER_COUNT; ++i_w) { + printk("test case [access]: %s and %s %s\n", access_assoc_table [i_ac], release_assoc_table [i_rel], waiter_assoc_table [i_w]); + check_access(access_table [i_ac], release_table [i_rel], waiter_table [i_w]); + } + } + } + + for (i_rel = 0; i_rel < RELEASE_COUNT; ++i_rel) { + for (i_w = 0; i_w < WAITER_COUNT; ++i_w) { + printk("test case [intermediate]: %s %s\n", release_assoc_table [i_rel], waiter_assoc_table [i_w]); + check_intermediate(release_table [i_rel], waiter_table [i_w]); + } + } + + for (i_p = 0; i_p < PURGER_COUNT; ++i_p) { + for (i_w = 0; i_w < WAITER_COUNT; ++i_w) { + printk("test case [transfer]: %s %s\n", purger_assoc_table [i_p], waiter_assoc_table [i_w]); + check_transfer(purger_table [i_p], waiter_table [i_w]); + } + } + + printk("*** END OF TEST BLOCK 10 ***\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 5 +#define CONFIGURE_MAXIMUM_DRIVERS 4 +#define CONFIGURE_MAXIMUM_SEMAPHORES 5 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT_TASK_PRIORITY PRIORITY_INIT +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES + +#define CONFIGURE_SWAPOUT_TASK_PRIORITY PRIORITY_SWAPOUT + +#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 -- cgit v1.2.3