diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2010-01-26 15:09:03 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2010-01-26 15:09:03 +0000 |
commit | e7fb54eb0593f80966502ca9b3cc2159e5e4a863 (patch) | |
tree | af42febc3419f1f4cc7ab383825b9db24b6a499f | |
parent | User extension API: add const to some params, inline _User_extensions_Add_API... (diff) | |
download | rtems-e7fb54eb0593f80966502ca9b3cc2159e5e4a863.tar.bz2 |
add purge capability to libblock, add proper test case
-rw-r--r-- | cpukit/ChangeLog | 9 | ||||
-rw-r--r-- | cpukit/libblock/include/rtems/bdbuf.h | 67 | ||||
-rw-r--r-- | cpukit/libblock/src/bdbuf.c | 376 | ||||
-rw-r--r-- | testsuites/libtests/ChangeLog | 8 | ||||
-rw-r--r-- | testsuites/libtests/Makefile.am | 2 | ||||
-rw-r--r-- | testsuites/libtests/block05/Makefile.am | 2 | ||||
-rw-r--r-- | testsuites/libtests/block05/block05.doc | 28 | ||||
-rw-r--r-- | testsuites/libtests/block05/block05.png | bin | 0 -> 54778 bytes | |||
-rw-r--r-- | testsuites/libtests/block10/Makefile.am | 27 | ||||
-rw-r--r-- | testsuites/libtests/block10/block10.doc | 47 | ||||
-rw-r--r-- | testsuites/libtests/block10/block10.png | bin | 0 -> 70224 bytes | |||
-rw-r--r-- | testsuites/libtests/block10/block10.scn | 226 | ||||
-rw-r--r-- | testsuites/libtests/block10/init.c | 481 | ||||
-rw-r--r-- | testsuites/libtests/configure.ac | 1 |
14 files changed, 1134 insertions, 140 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index a6673f0a1d..722c8f3fae 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,5 +1,14 @@ 2010-01-26 Sebastian Huber <sebastian.huber@embedded-brains.de> + * libblock/include/rtems/bdbuf.h: Documentation. New states + RTEMS_BDBUF_STATE_ACCESS_PURGED and RTEMS_BDBUF_STATE_TRANSFER_PURGED. + Declare rtems_bdbuf_purge_dev() and rtems_bdbuf_purge_major(). + * libblock/src/bdbuf.c: Implemented ability to purge buffers from the + cache depending on the device identifier or major number. See test + "libtests/block10". + +2010-01-26 Sebastian Huber <sebastian.huber@embedded-brains.de> + * score/src/userextaddapiset.c: Removed file. * score/Makefile.am: Update for removed file. * sapi/include/rtems/extension.h, sapi/src/extensioncreate.c, diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h index f4e87568da..66a9bbf59b 100644 --- a/cpukit/libblock/include/rtems/bdbuf.h +++ b/cpukit/libblock/include/rtems/bdbuf.h @@ -86,7 +86,9 @@ extern "C" { * ac [label="ACCESS CACHED",style="filled",fillcolor="royalblue"]; * am [label="ACCESS MODIFIED",style="filled",fillcolor="royalblue"]; * ae [label="ACCESS EMPTY",style="filled",fillcolor="royalblue"]; + * ap [label="ACCESS PURGED",style="filled",fillcolor="royalblue"]; * t [label="TRANSFER",style="filled",fillcolor="red"]; + * tp [label="TRANSFER PURGED",style="filled",fillcolor="red"]; * s [label="SYNC",style="filled",fillcolor="red"]; * m [label="MODIFIED",style="filled",fillcolor="gold"]; * i [label="INITIAL"]; @@ -97,26 +99,33 @@ extern "C" { * i -> f [label="Init"]; * f -> e [label="Buffer Recycle"]; * e -> ae [label="Get"]; - * e -> t [label="Read\nRead Ahead"]; - * c -> f [label="Reallocate\nBlock Size Changed"]; + * e -> t [label="Read"]; + * e -> f [label="Nobody Waits"]; * c -> ac [label="Get\nRead"]; - * c -> e [label="Buffer Recycle"]; + * c -> e [label="Buffer Recycle\nPurge"]; + * c -> f [label="Reallocate\nBlock Size Changed"]; * t -> c [label="Transfer Done",color="red",fontcolor="red"]; - * t -> e [label="Transfer Error With Waiter",color="red",fontcolor="red"]; - * t -> f [label="Transfer Error Without Waiter",color="red",fontcolor="red"]; + * t -> e [label="Transfer Error",color="red",fontcolor="red"]; + * t -> tp [label="Purge"]; + * tp -> e [label="Transfer Done\nTransfer Error",color="red",fontcolor="red"]; * m -> t [label="Swapout"]; * m -> s [label="Block Size Changed"]; * m -> am [label="Get\nRead"]; + * m -> e [label="Purge"]; * ac -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"]; * ac -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; * ac -> c [label="Release",color="royalblue",fontcolor="royalblue"]; + * ac -> ap [label="Purge"]; * am -> m [label="Release\nRelease Modified",color="royalblue",fontcolor="royalblue"]; * am -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; + * am -> ap [label="Purge"]; * ae -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"]; * ae -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; - * ae -> e [label="Release With Waiter",color="royalblue",fontcolor="royalblue"]; - * ae -> f [label="Release Without Waiter",color="royalblue",fontcolor="royalblue"]; + * ae -> e [label="Release",color="royalblue",fontcolor="royalblue"]; + * ae -> ap [label="Purge"]; + * ap -> e [label="Release\nRelease Modified\nSync",color="royalblue",fontcolor="royalblue"]; * s -> t [label="Swapout"]; + * s -> e [label="Purge",color="red",fontcolor="red"]; * } * @enddot * @@ -184,22 +193,26 @@ extern "C" { * </tr> * <tr> * <td>EMPTY</td><td></td><td>X</td> - * <td>X</td><td></td><td></td><td></td><td></td> + * <td></td><td></td><td></td><td></td><td></td> * </tr> * <tr> * <td>CACHED</td><td>X</td><td>X</td> * <td>X</td><td></td><td></td><td></td><td></td> * </tr> * <tr> - * <td>ACCESS_CACHED</td><td>X</td><td>X</td> + * <td>ACCESS CACHED</td><td>X</td><td>X</td> + * <td></td><td></td><td></td><td>X</td><td>X</td> + * </tr> + * <tr> + * <td>ACCESS MODIFIED</td><td>X</td><td>X</td> * <td></td><td></td><td></td><td>X</td><td>X</td> * </tr> * <tr> - * <td>ACCESS_MODIFIED</td><td>X</td><td>X</td> + * <td>ACCESS EMPTY</td><td></td><td>X</td> * <td></td><td></td><td></td><td>X</td><td>X</td> * </tr> * <tr> - * <td>ACCESS_EMPTY</td><td></td><td>X</td> + * <td>ACCESS PURGED</td><td></td><td>X</td> * <td></td><td></td><td></td><td>X</td><td>X</td> * </tr> * <tr> @@ -214,6 +227,10 @@ extern "C" { * <td>TRANSFER</td><td>X</td><td>X</td> * <td></td><td></td><td></td><td>X</td><td>X</td> * </tr> + * <tr> + * <td>TRANSFER PURGED</td><td></td><td>X</td> + * <td></td><td></td><td></td><td>X</td><td>X</td> + * </tr> * </table> */ typedef enum @@ -249,6 +266,11 @@ typedef enum RTEMS_BDBUF_STATE_ACCESS_EMPTY, /** + * @brief Accessed by upper layer with purged data. + */ + RTEMS_BDBUF_STATE_ACCESS_PURGED, + + /** * @brief Modified by upper layer. */ RTEMS_BDBUF_STATE_MODIFIED, @@ -261,7 +283,12 @@ typedef enum /** * @brief In transfer by block device driver. */ - RTEMS_BDBUF_STATE_TRANSFER + RTEMS_BDBUF_STATE_TRANSFER, + + /** + * @brief In transfer by block device driver and purged. + */ + RTEMS_BDBUF_STATE_TRANSFER_PURGED } rtems_bdbuf_buf_state; /** @@ -542,6 +569,22 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd); rtems_status_code rtems_bdbuf_syncdev (dev_t dev); +/** + * @brief Purges all buffers that matches the device identifier @a dev. + * + * This may result in loss of data. + */ +void +rtems_bdbuf_purge_dev (dev_t dev); + +/** + * @brief Purges all buffers that matches the device major number @a major. + * + * This may result in loss of data. + */ +void +rtems_bdbuf_purge_major (rtems_device_major_number major); + /** @} */ #ifdef __cplusplus diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 056a7c8ec2..862591503f 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -144,6 +144,7 @@ typedef struct rtems_bdbuf_cache #define RTEMS_BLKDEV_FATAL_ERROR(n) \ (((uint32_t)'B' << 24) | ((uint32_t)(n) & (uint32_t)0x00FFFFFF)) +#define RTEMS_BLKDEV_FATAL_BDBUF_STATE_11 RTEMS_BLKDEV_FATAL_ERROR(1) #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_4 RTEMS_BLKDEV_FATAL_ERROR(2) #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_5 RTEMS_BLKDEV_FATAL_ERROR(3) #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_6 RTEMS_BLKDEV_FATAL_ERROR(4) @@ -1033,6 +1034,62 @@ rtems_bdbuf_has_buffer_waiters (void) } static void +rtems_bdbuf_remove_from_tree (rtems_bdbuf_buffer *bd) +{ + if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) + rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_TREE_RM); +} + +static void +rtems_bdbuf_remove_from_tree_and_lru_list (rtems_bdbuf_buffer *bd) +{ + switch (bd->state) + { + case RTEMS_BDBUF_STATE_FREE: + break; + case RTEMS_BDBUF_STATE_CACHED: + rtems_bdbuf_remove_from_tree (bd); + break; + default: + rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_STATE_10); + } + + rtems_chain_extract (&bd->link); +} + +static void +rtems_bdbuf_make_free_and_add_to_lru_list (rtems_bdbuf_buffer *bd) +{ + rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_FREE); + rtems_chain_prepend (&bdbuf_cache.lru, &bd->link); +} + +static void +rtems_bdbuf_make_empty (rtems_bdbuf_buffer *bd) +{ + rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_EMPTY); +} + +static void +rtems_bdbuf_make_cached_and_add_to_lru_list (rtems_bdbuf_buffer *bd) +{ + rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_CACHED); + rtems_chain_append (&bdbuf_cache.lru, &bd->link); +} + +static void +rtems_bdbuf_discard_buffer (rtems_bdbuf_buffer *bd) +{ + rtems_bdbuf_make_empty (bd); + + if (bd->waiters == 0) + { + rtems_bdbuf_remove_from_tree (bd); + rtems_bdbuf_make_free_and_add_to_lru_list (bd); + } +} + +static void rtems_bdbuf_add_to_modified_list_after_access (rtems_bdbuf_buffer *bd) { if (bdbuf_cache.sync_active && bdbuf_cache.sync_device == bd->dev) @@ -1075,9 +1132,8 @@ rtems_bdbuf_add_to_modified_list_after_access (rtems_bdbuf_buffer *bd) static void rtems_bdbuf_add_to_lru_list_after_access (rtems_bdbuf_buffer *bd) { - rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_CACHED); - rtems_chain_append (&bdbuf_cache.lru, &bd->link); rtems_bdbuf_group_release (bd); + rtems_bdbuf_make_cached_and_add_to_lru_list (bd); if (bd->waiters) rtems_bdbuf_wake (&bdbuf_cache.access_waiters); @@ -1085,17 +1141,6 @@ rtems_bdbuf_add_to_lru_list_after_access (rtems_bdbuf_buffer *bd) rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); } -static void -rtems_bdbuf_add_to_sync_list_after_access (rtems_bdbuf_buffer *bd) -{ - rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_SYNC); - - rtems_chain_append (&bdbuf_cache.sync, &bd->link); - - if (bd->waiters) - rtems_bdbuf_wake (&bdbuf_cache.access_waiters); -} - /** * Compute the number of BDs per group for a given buffer size. * @@ -1121,60 +1166,15 @@ rtems_bdbuf_bds_per_group (size_t size) } static void -rtems_bdbuf_remove_from_tree (rtems_bdbuf_buffer *bd) -{ - if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) - rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_TREE_RM); -} - -static void -rtems_bdbuf_remove_from_tree_and_lru_list (rtems_bdbuf_buffer *bd) -{ - switch (bd->state) - { - case RTEMS_BDBUF_STATE_FREE: - break; - case RTEMS_BDBUF_STATE_CACHED: - rtems_bdbuf_remove_from_tree (bd); - break; - default: - rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_STATE_10); - } - - rtems_chain_extract (&bd->link); -} - -static void -rtems_bdbuf_make_free_and_add_to_lru_list (rtems_bdbuf_buffer *bd) -{ - rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_FREE); - rtems_chain_prepend (&bdbuf_cache.lru, &bd->link); -} - -static void -rtems_bdbuf_make_empty_and_add_to_lru_list (rtems_bdbuf_buffer *bd) -{ - rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_EMPTY); - rtems_chain_append (&bdbuf_cache.lru, &bd->link); -} - -static void -rtems_bdbuf_release_empty_buffer (rtems_bdbuf_buffer *bd) +rtems_bdbuf_discard_buffer_after_access (rtems_bdbuf_buffer *bd) { rtems_bdbuf_group_release (bd); + rtems_bdbuf_discard_buffer (bd); if (bd->waiters) - { - rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_EMPTY); - rtems_chain_append (&bdbuf_cache.lru, &bd->link); rtems_bdbuf_wake (&bdbuf_cache.access_waiters); - } else - { - rtems_bdbuf_remove_from_tree (bd); - rtems_bdbuf_make_free_and_add_to_lru_list (bd); rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); - } } /** @@ -1220,9 +1220,9 @@ rtems_bdbuf_group_realloc (rtems_bdbuf_group* group, size_t new_bds_per_group) } static void -rtems_bdbuf_recycle_buffer (rtems_bdbuf_buffer *bd, - dev_t dev, - rtems_blkdev_bnum block) +rtems_bdbuf_setup_empty_buffer (rtems_bdbuf_buffer *bd, + dev_t dev, + rtems_blkdev_bnum block) { bd->dev = dev; bd->block = block; @@ -1233,7 +1233,7 @@ rtems_bdbuf_recycle_buffer (rtems_bdbuf_buffer *bd, if (rtems_bdbuf_avl_insert (&bdbuf_cache.tree, bd) != 0) rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_RECYCLE); - rtems_bdbuf_make_empty_and_add_to_lru_list (bd); + rtems_bdbuf_make_empty (bd); } static rtems_bdbuf_buffer * @@ -1246,7 +1246,7 @@ rtems_bdbuf_get_buffer_from_lru_list (dev_t dev, while (!rtems_chain_is_tail (&bdbuf_cache.lru, node)) { rtems_bdbuf_buffer *bd = (rtems_bdbuf_buffer *) node; - rtems_bdbuf_buffer *recycle_bd = NULL; + rtems_bdbuf_buffer *empty_bd = NULL; if (rtems_bdbuf_tracer) printf ("bdbuf:next-bd: %tu (%td:%" PRId32 ") %zd -> %zd\n", @@ -1263,17 +1263,17 @@ rtems_bdbuf_get_buffer_from_lru_list (dev_t dev, { rtems_bdbuf_remove_from_tree_and_lru_list (bd); - recycle_bd = bd; + empty_bd = bd; } else if (bd->group->users == 0) - recycle_bd = rtems_bdbuf_group_realloc (bd->group, bds_per_group); + empty_bd = rtems_bdbuf_group_realloc (bd->group, bds_per_group); } - if (recycle_bd != NULL) + if (empty_bd != NULL) { - rtems_bdbuf_recycle_buffer (recycle_bd, dev, block); + rtems_bdbuf_setup_empty_buffer (empty_bd, dev, block); - return recycle_bd; + return empty_bd; } node = rtems_chain_next (node); @@ -1529,10 +1529,12 @@ rtems_bdbuf_wait_for_access (rtems_bdbuf_buffer *bd) case RTEMS_BDBUF_STATE_ACCESS_CACHED: case RTEMS_BDBUF_STATE_ACCESS_EMPTY: case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: + case RTEMS_BDBUF_STATE_ACCESS_PURGED: rtems_bdbuf_wait (bd, &bdbuf_cache.access_waiters); break; - case RTEMS_BDBUF_STATE_TRANSFER: case RTEMS_BDBUF_STATE_SYNC: + case RTEMS_BDBUF_STATE_TRANSFER: + case RTEMS_BDBUF_STATE_TRANSFER_PURGED: rtems_bdbuf_wait (bd, &bdbuf_cache.transfer_waiters); break; default: @@ -1586,10 +1588,12 @@ rtems_bdbuf_wait_for_recycle (rtems_bdbuf_buffer *bd) case RTEMS_BDBUF_STATE_ACCESS_CACHED: case RTEMS_BDBUF_STATE_ACCESS_EMPTY: case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: + case RTEMS_BDBUF_STATE_ACCESS_PURGED: rtems_bdbuf_wait (bd, &bdbuf_cache.access_waiters); break; - case RTEMS_BDBUF_STATE_TRANSFER: case RTEMS_BDBUF_STATE_SYNC: + case RTEMS_BDBUF_STATE_TRANSFER: + case RTEMS_BDBUF_STATE_TRANSFER_PURGED: rtems_bdbuf_wait (bd, &bdbuf_cache.transfer_waiters); break; default: @@ -1611,9 +1615,11 @@ rtems_bdbuf_wait_for_sync_done (rtems_bdbuf_buffer *bd) case RTEMS_BDBUF_STATE_ACCESS_CACHED: case RTEMS_BDBUF_STATE_ACCESS_EMPTY: case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: + case RTEMS_BDBUF_STATE_ACCESS_PURGED: return; case RTEMS_BDBUF_STATE_SYNC: case RTEMS_BDBUF_STATE_TRANSFER: + case RTEMS_BDBUF_STATE_TRANSFER_PURGED: rtems_bdbuf_wait (bd, &bdbuf_cache.transfer_waiters); break; default: @@ -1631,6 +1637,35 @@ rtems_bdbuf_wait_for_buffer (void) rtems_bdbuf_anonymous_wait (&bdbuf_cache.buffer_waiters); } +static void +rtems_bdbuf_sync_after_access (rtems_bdbuf_buffer *bd) +{ + rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_SYNC); + + rtems_chain_append (&bdbuf_cache.sync, &bd->link); + + if (bd->waiters) + rtems_bdbuf_wake (&bdbuf_cache.access_waiters); + + rtems_bdbuf_wake_swapper (); + rtems_bdbuf_wait_for_sync_done (bd); + + /* + * We may have created a cached or empty buffer which may be recycled. + */ + if (bd->waiters == 0 + && (bd->state == RTEMS_BDBUF_STATE_CACHED + || bd->state == RTEMS_BDBUF_STATE_EMPTY)) + { + if (bd->state == RTEMS_BDBUF_STATE_EMPTY) + { + rtems_bdbuf_remove_from_tree (bd); + rtems_bdbuf_make_free_and_add_to_lru_list (bd); + } + rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); + } +} + static rtems_bdbuf_buffer * rtems_bdbuf_get_buffer_for_read_ahead (dev_t dev, rtems_blkdev_bnum block, @@ -1930,8 +1965,8 @@ rtems_bdbuf_execute_transfer_request (const rtems_disk_device *dd, rtems_status_code sc = RTEMS_SUCCESSFUL; int result = 0; uint32_t transfer_index = 0; - bool wake_transfer = false; - bool wake_buffer = false; + bool wake_transfer_waiters = false; + bool wake_buffer_waiters = false; if (cache_locked) rtems_bdbuf_unlock_cache (); @@ -1951,38 +1986,28 @@ rtems_bdbuf_execute_transfer_request (const rtems_disk_device *dd, for (transfer_index = 0; transfer_index < req->bufnum; ++transfer_index) { rtems_bdbuf_buffer *bd = req->bufs [transfer_index].user; - bool waiters = bd->waiters > 0; + bool waiters = bd->waiters; if (waiters) - wake_transfer = true; + wake_transfer_waiters = true; else - wake_buffer = true; + wake_buffer_waiters = true; rtems_bdbuf_group_release (bd); - if (sc == RTEMS_SUCCESSFUL) - { - rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_CACHED); - rtems_chain_append (&bdbuf_cache.lru, &bd->link); - } - else if (waiters) - { - rtems_bdbuf_make_empty_and_add_to_lru_list (bd); - } + if (sc == RTEMS_SUCCESSFUL && bd->state == RTEMS_BDBUF_STATE_TRANSFER) + rtems_bdbuf_make_cached_and_add_to_lru_list (bd); else - { - rtems_bdbuf_remove_from_tree (bd); - rtems_bdbuf_make_free_and_add_to_lru_list (bd); - } + rtems_bdbuf_discard_buffer (bd); if (rtems_bdbuf_tracer) rtems_bdbuf_show_users ("transfer", bd); } - if (wake_transfer) + if (wake_transfer_waiters) rtems_bdbuf_wake (&bdbuf_cache.transfer_waiters); - if (wake_buffer) + if (wake_buffer_waiters) rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); if (!cache_locked) @@ -2100,7 +2125,8 @@ rtems_bdbuf_release (rtems_bdbuf_buffer *bd) rtems_bdbuf_add_to_lru_list_after_access (bd); break; case RTEMS_BDBUF_STATE_ACCESS_EMPTY: - rtems_bdbuf_release_empty_buffer (bd); + case RTEMS_BDBUF_STATE_ACCESS_PURGED: + rtems_bdbuf_discard_buffer_after_access (bd); break; case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: rtems_bdbuf_add_to_modified_list_after_access (bd); @@ -2134,6 +2160,9 @@ rtems_bdbuf_release_modified (rtems_bdbuf_buffer *bd) case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: rtems_bdbuf_add_to_modified_list_after_access (bd); break; + case RTEMS_BDBUF_STATE_ACCESS_PURGED: + rtems_bdbuf_discard_buffer_after_access (bd); + break; default: rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_STATE_6); break; @@ -2161,7 +2190,10 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer *bd) case RTEMS_BDBUF_STATE_ACCESS_CACHED: case RTEMS_BDBUF_STATE_ACCESS_EMPTY: case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: - rtems_bdbuf_add_to_sync_list_after_access (bd); + rtems_bdbuf_sync_after_access (bd); + break; + case RTEMS_BDBUF_STATE_ACCESS_PURGED: + rtems_bdbuf_discard_buffer_after_access (bd); break; default: rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_STATE_5); @@ -2171,25 +2203,6 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer *bd) if (rtems_bdbuf_tracer) rtems_bdbuf_show_usage (); - rtems_bdbuf_wake_swapper (); - rtems_bdbuf_wait_for_sync_done (bd); - - /* - * If no one intercepts the sync, we created a cached buffer which may be - * recycled. - */ - if (bd->waiters == 0 - && (bd->state == RTEMS_BDBUF_STATE_CACHED - || bd->state == RTEMS_BDBUF_STATE_EMPTY)) - { - if (bd->state == RTEMS_BDBUF_STATE_EMPTY) - { - rtems_bdbuf_remove_from_tree (bd); - rtems_bdbuf_make_free_and_add_to_lru_list (bd); - } - rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); - } - rtems_bdbuf_unlock_cache (); return RTEMS_SUCCESSFUL; @@ -2809,3 +2822,140 @@ rtems_bdbuf_swapout_task (rtems_task_argument arg) rtems_task_delete (RTEMS_SELF); } + +static void +rtems_bdbuf_purge_list (rtems_chain_control *purge_list) +{ + bool wake_buffer_waiters = false; + rtems_chain_node *node = NULL; + + while ((node = rtems_chain_get (purge_list)) != NULL) + { + rtems_bdbuf_buffer *bd = (rtems_bdbuf_buffer *) node; + + if (bd->waiters == 0) + wake_buffer_waiters = true; + + rtems_bdbuf_discard_buffer (bd); + } + + if (wake_buffer_waiters) + rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); +} + +typedef bool (*rtems_bdbuf_purge_compare)(dev_t a, dev_t b); + +static void +rtems_bdbuf_gather_for_purge (rtems_chain_control *purge_list, + rtems_bdbuf_purge_compare compare, + dev_t dev) +{ + rtems_bdbuf_buffer *stack [RTEMS_BDBUF_AVL_MAX_HEIGHT]; + rtems_bdbuf_buffer **prev = stack; + rtems_bdbuf_buffer *cur = bdbuf_cache.tree; + + *prev = NULL; + + while (cur != NULL) + { + if ((*compare) (cur->dev, dev)) + { + switch (cur->state) + { + case RTEMS_BDBUF_STATE_FREE: + case RTEMS_BDBUF_STATE_EMPTY: + case RTEMS_BDBUF_STATE_ACCESS_PURGED: + case RTEMS_BDBUF_STATE_TRANSFER_PURGED: + break; + case RTEMS_BDBUF_STATE_SYNC: + rtems_bdbuf_wake (&bdbuf_cache.transfer_waiters); + /* Fall through */ + case RTEMS_BDBUF_STATE_MODIFIED: + rtems_bdbuf_group_release (cur); + /* Fall through */ + case RTEMS_BDBUF_STATE_CACHED: + rtems_chain_extract (&cur->link); + rtems_chain_append (purge_list, &cur->link); + break; + case RTEMS_BDBUF_STATE_TRANSFER: + rtems_bdbuf_set_state (cur, RTEMS_BDBUF_STATE_TRANSFER_PURGED); + break; + case RTEMS_BDBUF_STATE_ACCESS_CACHED: + case RTEMS_BDBUF_STATE_ACCESS_EMPTY: + case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: + rtems_bdbuf_set_state (cur, RTEMS_BDBUF_STATE_ACCESS_PURGED); + break; + default: + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_STATE_11); + } + } + + if (cur->avl.left != NULL) + { + /* Left */ + ++prev; + *prev = cur; + cur = cur->avl.left; + } + else if (cur->avl.right != NULL) + { + /* Right */ + ++prev; + *prev = cur; + cur = cur->avl.right; + } + else + { + while (*prev != NULL && cur == (*prev)->avl.right) + { + /* Up */ + cur = *prev; + --prev; + } + if (*prev != NULL) + /* Right */ + cur = (*prev)->avl.right; + else + /* Finished */ + cur = NULL; + } + } +} + +static void +rtems_bdbuf_purge (rtems_bdbuf_purge_compare compare, dev_t dev) +{ + rtems_chain_control purge_list; + + rtems_chain_initialize_empty (&purge_list); + rtems_bdbuf_lock_cache (); + rtems_bdbuf_gather_for_purge (&purge_list, compare, dev); + rtems_bdbuf_purge_list (&purge_list); + rtems_bdbuf_unlock_cache (); +} + +static bool +rtems_bdbuf_purge_compare_dev (dev_t a, dev_t b) +{ + return a == b; +} + +void +rtems_bdbuf_purge_dev (dev_t dev) +{ + rtems_bdbuf_purge (rtems_bdbuf_purge_compare_dev, dev); +} + +static bool +rtems_bdbuf_purge_compare_major (dev_t a, dev_t b) +{ + return rtems_filesystem_dev_major_t (a) == rtems_filesystem_dev_major_t (b); +} + +void +rtems_bdbuf_purge_major (rtems_device_major_number major) +{ + dev_t dev = rtems_filesystem_make_dev_t (major, 0); + + rtems_bdbuf_purge (rtems_bdbuf_purge_compare_major, dev); +} diff --git a/testsuites/libtests/ChangeLog b/testsuites/libtests/ChangeLog index 5062f44164..23530b02c7 100644 --- a/testsuites/libtests/ChangeLog +++ b/testsuites/libtests/ChangeLog @@ -1,3 +1,11 @@ +2010-01-21 Sebastian Huber <Sebastian.Huber@embedded-brains.de> + + * block05/block05.png, block10/block10.doc, block10/init.c, + block10/.cvsignore, block10/block10.scn, block10/block10.png, + block10/Makefile.am: New files. + * configure.ac, Makefile.am: Update for new files. + * block05/block05.doc: Update for new state transitions. + 2010-01-20 Joel Sherrill <joel.sherrill@oarcorp.com> * block08/.cvsignore, block09/.cvsignore: New files. diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am index cc51b4970b..c3974f7c35 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 \ - block08 block09 stringto01 + block08 block09 block10 stringto01 SUBDIRS += POSIX include $(top_srcdir)/../automake/subdirs.am diff --git a/testsuites/libtests/block05/Makefile.am b/testsuites/libtests/block05/Makefile.am index f8429cc116..01c6247142 100644 --- a/testsuites/libtests/block05/Makefile.am +++ b/testsuites/libtests/block05/Makefile.am @@ -7,7 +7,7 @@ MANAGERS = io semaphore event rtems_tests_PROGRAMS = block05 block05_SOURCES = init.c -dist_rtems_tests_DATA = block05.scn block05.doc +dist_rtems_tests_DATA = block05.scn block05.doc block05.png include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg include $(top_srcdir)/../automake/compile.am diff --git a/testsuites/libtests/block05/block05.doc b/testsuites/libtests/block05/block05.doc index 819701f250..a1042f6c93 100644 --- a/testsuites/libtests/block05/block05.doc +++ b/testsuites/libtests/block05/block05.doc @@ -1,7 +1,7 @@ # # $Id$ # -# Copyright (c) 2009 +# Copyright (c) 2009, 2010 # embedded brains GmbH # Obere Lagerstr. 30 # D-82178 Puchheim @@ -31,15 +31,17 @@ concepts: State changes count during this test: - | PREVIOUS STATE - | 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 + | PREVIOUS STATE + | FR EM CA AC AM AE AP MO SY TF TP +---------+------------------------------------------------------------------ + FR | 12240 11980 0 0 0 0 0 0 0 0 0 + EM | 11981 0 21499 0 0 12503 0 0 0 0 0 + CA | 0 0 0 9717 0 0 0 0 0 33978 0 + AC | 0 0 22195 0 0 0 0 0 0 0 0 +NEW AM | 0 0 0 0 0 0 0 3340 0 0 0 +STATE AE | 0 21121 0 0 0 0 0 0 0 0 0 + AP | 0 0 0 0 0 0 0 0 0 0 0 + MO | 0 0 0 6242 2224 4306 0 0 0 0 0 + SY | 0 0 0 6236 1116 4312 0 0 0 0 0 + TF | 0 12882 0 0 0 0 0 9432 11664 0 0 + TP | 0 0 0 0 0 0 0 0 0 0 0 diff --git a/testsuites/libtests/block05/block05.png b/testsuites/libtests/block05/block05.png Binary files differnew file mode 100644 index 0000000000..f48098c6d0 --- /dev/null +++ b/testsuites/libtests/block05/block05.png 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 +# <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: 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 Binary files differnew file mode 100644 index 0000000000..6ff93dadc1 --- /dev/null +++ b/testsuites/libtests/block10/block10.png 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 + * <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 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 <rtems/confdefs.h> diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac index a93ba4ccda..d1d472c598 100644 --- a/testsuites/libtests/configure.ac +++ b/testsuites/libtests/configure.ac @@ -42,6 +42,7 @@ block06/Makefile block07/Makefile block08/Makefile block09/Makefile +block10/Makefile bspcmdline01/Makefile cpuuse/Makefile heapwalk/Makefile |