From 0d15414ed6c144f7f7e4ce63476b3eb9b94acceb Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Wed, 5 Aug 2009 00:00:54 +0000 Subject: 009-08-05 Chris Johns * libmisc/dummy/dummy-networking.c: New. * libmisc/dummy/dummy.c, libmisc/Makefile.am: Move trhe networking configuration into a separate file so configuration varations do not cause conflicts. * score/inline/rtems/score/object.inl, score/include/rtems/score/object.h: Remove warnings. * score/inline/rtems/score/object.inl: Add _Chain_First, _Chain_Last, _Chain_Mext, and _Chain_Previous. * sapi/inline/rtems/chain.inl: Add rtems_chain_first, rtems_chain_last, rtems_chain_mext, and rtems_chain_previous. * libblock/include/rtems/diskdevs.h: Remove the bdbuf pool id and block_size_log2. Add media_block_size. * libblock/src/diskdevs.c: Remove size restrictions on block size. Add media block size initialisation. Remove comment to clean up the bdbuf cache. * libblock/src/blkdev.c: Remove references to block_size_log2. Allow any block size. * libblock/include/rtems/bdbuf.h, libblock/src/bdbuf.c: Remove all references to pools and make the cache handle demand driver variable buffer size allocation. Added worker threads support the swapout task. * sapi/include/confdefs.h: Updated the bdbuf configutation. --- cpukit/libblock/include/rtems/bdbuf.h | 261 ++++++++++++++++------------------ 1 file changed, 125 insertions(+), 136 deletions(-) (limited to 'cpukit/libblock/include/rtems/bdbuf.h') diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h index 1f79f89d0d..16f86fcdd3 100644 --- a/cpukit/libblock/include/rtems/bdbuf.h +++ b/cpukit/libblock/include/rtems/bdbuf.h @@ -10,9 +10,10 @@ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia * Author: Victor V. Vengerov * - * Copyright (C) 2008 Chris Johns + * Copyright (C) 2008,2009 Chris Johns * Rewritten to remove score mutex access. Fixes many performance * issues. + Change to support demand driven variable buffer sizes. * * @(#) bdbuf.h,v 1.9 2005/02/02 00:06:18 joel Exp */ @@ -44,8 +45,33 @@ extern "C" { * devices and file systems. The code provides read ahead and write queuing to * the drivers and fast cache look up using an AVL tree. * - * The buffers are held in pools based on size. Each pool has buffers and the - * buffers follow this state machine: + * The block size used by a file system can be set at runtime and must be a + * multiple of the disk device block size. The disk device's physical block + * size is called the media block size. The file system can set the block size + * it uses to a larger multiple of the media block size. The driver must be + * able to handle buffers sizes larger than one media block. + * + * The user configures the amount of memory to be used as buffers in the cache, + * and the minimum and maximum buffer size. The cache will allocate additional + * memory for the buffer descriptors and groups. There are enough buffer + * descriptors allocated so all the buffer memory can be used as minimum sized + * buffers. + * + * The cache is a single pool of buffers. The buffer memory is divided into + * groups where the size of buffer memory allocated to a group is the maximum + * buffer size. A group's memory can be divided down into small buffer sizes + * that are a multiple of 2 of the minimum buffer size. A group is the minumum + * allocation unit for buffers of a specific size. If a buffer of maximum size + * is request the group will have a single buffer. If a buffer of minium size + * is requested the group is divided into minimum sized buffers and the + * remaining buffers are held ready for use. A group keeps track of which + * buffers are with a file system or driver and groups who have buffer in use + * cannot be realloced. Groups with no buffers in use can be taken and + * realloced to a new size. This is how buffers of different sizes move around + * the cache. + + * The buffers are held in various lists in the cache. All buffers follow this + * state machine: * * @dot * digraph g { @@ -82,14 +108,14 @@ extern "C" { * to another requester until released back to the cache. The same goes to a * buffer in the transfer state. The transfer state means being read or * written. If the file system has modifed the block and releases it as - * modified it placed on the pool's modified list and a hold timer + * modified it placed on the cache's modified list and a hold timer * initialised. The buffer is held for the hold time before being written to * disk. Buffers are held for a configurable period of time on the modified * list as a write sets the state to transfer and this locks the buffer out - * from the file system until the write complete. Buffers are often repeatable - * accessed and modified in a series of small updates so if sent to the disk - * when released as modified the user would have to block waiting until it had - * been written. This would be a performance problem. + * from the file system until the write completes. Buffers are often accessed + * and modified in a series of small updates so if sent to the disk when + * released as modified the user would have to block waiting until it had been + * written. This would be a performance problem. * * The code performs mulitple block reads and writes. Multiple block reads or * read ahead increases performance with hardware that supports it. It also @@ -103,12 +129,22 @@ extern "C" { * than the LRU list. This means these buffers are used before buffers used by * the file system. * - * The pool has the following lists of buffers: + * The cache has the following lists of buffers: * - @c ready: Empty buffers created when the pool is initialised. * - @c modified: Buffers waiting to be written to disk. * - @c sync: Buffers to be synced to disk. * - @c lru: Accessed buffers released in least recently used order. * + * The cache scans the ready list then the LRU list for a suitable buffer in + * this order. A suitable buffer is one that matches the same allocation size + * as the device the buffer is for. The a buffer's group has no buffers in use + * with the file system or driver the group is reallocated. This means the + * buffers in the group are invalidated, resized and placed on the ready queue. + * There is a performance issue with this design. The reallocation of a group + * may forced recently accessed buffers out of the cache when they should + * not. The design should be change to have groups on a LRU list if they have + * no buffers in use. + * * @{ */ @@ -127,15 +163,21 @@ typedef enum RTEMS_BDBUF_STATE_TRANSFER = 7 /**< Being transferred to or from disk */ } rtems_bdbuf_buf_state; +/** + * Forward reference to the block. + */ +struct rtems_bdbuf_group; +typedef struct rtems_bdbuf_group rtems_bdbuf_group; + /** * To manage buffers we using buffer descriptors (BD). A BD holds a buffer plus * a range of other information related to managing the buffer in the cache. To - * speed-up buffer lookup descriptors are organized in AVL-Tree. The fields + * speed-up buffer lookup descriptors are organized in AVL-Tree. The fields * 'dev' and 'block' are search keys. */ typedef struct rtems_bdbuf_buffer { - rtems_chain_node link; /* Link in the BD onto a number of lists. */ + rtems_chain_node link; /**< Link the BD onto a number of lists. */ struct rtems_bdbuf_avl_node { @@ -154,94 +196,57 @@ typedef struct rtems_bdbuf_buffer volatile rtems_bdbuf_buf_state state; /**< State of the buffer. */ - volatile uint32_t waiters; /**< The number of threads waiting on this - * buffer. */ - rtems_bdpool_id pool; /**< Identifier of buffer pool to which this buffer - belongs */ - - volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer - * has been held in the cache modified. */ + volatile uint32_t waiters; /**< The number of threads waiting on this + * buffer. */ + rtems_bdbuf_group* group; /**< Pointer to the group of BDs this BD is + * part of. */ + volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer + * has been held in the cache modified. */ } rtems_bdbuf_buffer; /** - * The groups of the blocks with the same size are collected in a pool. Note - * that a several of the buffer's groups with the same size can exists. + * A group is a continuous block of buffer descriptors. A group covers the + * maximum configured buffer size and is the allocation size for the buffers to + * a specific buffer size. If you allocate a buffer to be a specific size, all + * buffers in the group, if there are more than 1 will also be that size. The + * number of buffers in a group is a multiple of 2, ie 1, 2, 4, 8, etc. */ -typedef struct rtems_bdbuf_pool +struct rtems_bdbuf_group { - uint32_t blksize; /**< The size of the blocks (in bytes) */ - uint32_t nblks; /**< Number of blocks in this pool */ - - uint32_t flags; /**< Configuration flags */ - - rtems_id lock; /**< The pool lock. Lock this data and - * all BDs. */ - rtems_id sync_lock; /**< Sync calls lock writes. */ - bool sync_active; /**< True if a sync is active. */ - rtems_id sync_requester; /**< The sync requester. */ - dev_t sync_device; /**< The device to sync */ - - rtems_bdbuf_buffer* tree; /**< Buffer descriptor lookup AVL tree - * root */ - rtems_chain_control ready; /**< Free buffers list (or read-ahead) */ - rtems_chain_control lru; /**< Last recently used list */ - rtems_chain_control modified; /**< Modified buffers list */ - rtems_chain_control sync; /**< Buffers to sync list */ - - rtems_id access; /**< Obtain if waiting for a buffer in the - * ACCESS state. */ - volatile uint32_t access_waiters; /**< Count of access blockers. */ - rtems_id transfer; /**< Obtain if waiting for a buffer in the - * TRANSFER state. */ - volatile uint32_t transfer_waiters; /**< Count of transfer blockers. */ - rtems_id waiting; /**< Obtain if waiting for a buffer and the - * none are available. */ - volatile uint32_t wait_waiters; /**< Count of waiting blockers. */ - - rtems_bdbuf_buffer* bds; /**< Pointer to table of buffer descriptors - * allocated for this buffer pool. */ - void* buffers; /**< The buffer's memory. */ -} rtems_bdbuf_pool; - -/** - * Configuration structure describes block configuration (size, amount, memory - * location) for buffering layer pool. - */ -typedef struct rtems_bdbuf_pool_config { - int size; /**< Size of block */ - int num; /**< Number of blocks of appropriate size */ - unsigned char* mem_area; /**< Pointer to the blocks location or NULL, in this - * case memory for blocks will be allocated by - * Buffering Layer with the help of RTEMS partition - * manager */ -} rtems_bdbuf_pool_config; - -/** - * External reference to the pool configuration table describing each pool in - * the system. - * - * The configuration table is provided by the application. - */ -extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[]; - -/** - * External reference the size of the pool configuration table - * @ref rtems_bdbuf_pool_configuration. - * - * The configuration table size is provided by the application. - */ -extern size_t rtems_bdbuf_pool_configuration_size; + rtems_chain_node link; /**< Link the groups on a LRU list if they + * have no buffers in use. */ + size_t bds_per_group; /**< The number of BD allocated to this + * group. This value must be a multiple of + * 2. */ + uint32_t users; /**< How many users the block has. */ + rtems_bdbuf_buffer* bdbuf; /**< First BD this block covers. */ +}; /** * Buffering configuration definition. See confdefs.h for support on using this * structure. */ typedef struct rtems_bdbuf_config { - uint32_t max_read_ahead_blocks; /**< Number of blocks to read ahead. */ - uint32_t max_write_blocks; /**< Number of blocks to write at once. */ - rtems_task_priority swapout_priority; /**< Priority of the swap out task. */ - uint32_t swapout_period; /**< Period swapout checks buf timers. */ - uint32_t swap_block_hold; /**< Period a buffer is held. */ + uint32_t max_read_ahead_blocks; /**< Number of blocks to read + * ahead. */ + uint32_t max_write_blocks; /**< Number of blocks to write + * at once. */ + rtems_task_priority swapout_priority; /**< Priority of the swap out + * task. */ + uint32_t swapout_period; /**< Period swapout checks buf + * timers. */ + uint32_t swap_block_hold; /**< Period a buffer is held. */ + uint32_t swapout_workers; /**< The number of worker + * threads for the swapout + * task. */ + rtems_task_priority swapout_worker_priority; /**< Priority of the swap out + * task. */ + size_t size; /**< Size of memory in the + * cache */ + uint32_t buffer_min; /**< Minimum buffer size. */ + uint32_t buffer_max; /**< Maximum buffer size + * supported. It is also the + * allocation size. */ } rtems_bdbuf_config; /** @@ -249,7 +254,7 @@ typedef struct rtems_bdbuf_config { * * The configuration is provided by the application. */ -extern rtems_bdbuf_config rtems_bdbuf_configuration; +extern const rtems_bdbuf_config rtems_bdbuf_configuration; /** * The max_read_ahead_blocks value is altered if there are fewer buffers @@ -277,12 +282,36 @@ extern rtems_bdbuf_config rtems_bdbuf_configuration; */ #define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000 +/** + * Default swap-out worker tasks. Currently disabled. + */ +#define RTEMS_BDBUF_SWAPOUT_WORKER_TASKS_DEFAULT 0 + +/** + * Default swap-out worker task priority. The same as the swapout task. + */ +#define RTEMS_BDBUF_SWAPOUT_WORKER_TASK_PRIORITY_DEFAULT \ + RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT + +/** + * Default size of memory allocated to the cache. + */ +#define RTEMS_BDBUF_CACHE_MEMORY_SIZE_DEFAULT (64 * 512) + +/** + * Default minimum size of buffers. + */ +#define RTEMS_BDBUF_BUFFER_MIN_SIZE_DEFAULT (512) + +/** + * Default maximum size of buffers. + */ +#define RTEMS_BDBUF_BUFFER_MAX_SIZE_DEFAULT (4096) + /** * Prepare buffering layer to work - initialize buffer descritors and (if it is - * neccessary) buffers. Buffers will be allocated accoriding to the - * configuration table, each entry describes the size of block and the size of - * the pool. After initialization all blocks is placed into the ready state. - * lists. + * neccessary) buffers. After initialization all blocks is placed into the + * ready state. * * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed * successfully or error code if error is occured) @@ -395,13 +424,12 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd); /** * Synchronize all modified buffers for this device with the disk and wait - * until the transfers have completed. The sync mutex for the pool is locked + * until the transfers have completed. The sync mutex for the cache is locked * stopping the addition of any further modifed buffers. It is only the * currently modified buffers that are written. * - * @note Nesting calls to sync multiple devices attached to a single pool will - * be handled sequentially. A nested call will be blocked until the first sync - * request has complete. This is only true for device using the same pool. + * @note Nesting calls to sync multiple devices will be handled sequentially. A + * nested call will be blocked until the first sync request has complete. * * @param dev Block device number * @@ -411,45 +439,6 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd); rtems_status_code rtems_bdbuf_syncdev (dev_t dev); -/** - * Find first appropriate buffer pool. This primitive returns the index of - * first buffer pool which block size is greater than or equal to specified - * size. - * - * @param block_size Requested block size - * @param pool The pool to use for the requested pool size. - * - * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed - * successfully or error code if error is occured) - * @retval RTEMS_INVALID_SIZE The specified block size is invalid (not a power - * of 2) - * @retval RTEMS_NOT_DEFINED The buffer pool for this or greater block size - * is not configured. - */ -rtems_status_code -rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool); - -/** - * Obtain characteristics of buffer pool with specified number. - * - * @param pool Buffer pool number - * @param block_size Block size for which buffer pool is configured returned - * there - * @param blocks Number of buffers in buffer pool. - * - * RETURNS: - * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed - * successfully or error code if error is occured) - * @retval RTEMS_INVALID_SIZE The appropriate buffer pool is not configured. - * - * @note Buffer pools enumerated continuously starting from 0. - */ -rtems_status_code rtems_bdbuf_get_pool_info( - rtems_bdpool_id pool, - uint32_t *block_size, - uint32_t *blocks -); - /** @} */ #ifdef __cplusplus -- cgit v1.2.3