From 3899a5379f4bfa067e73b4612a547a308a6634ec Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 29 Jul 2008 02:21:15 +0000 Subject: 2008-07-29 Chris Johns * libblock/Makefile.am: Removed src/show_bdbuf.c. * libblock/src/show_bdbuf.c: Removed. * libblock/include/rtems/bdbuf.h, cpukit/libblock/src/bdbuf.c: Rewritten the bdbuf code. Remove pre-emption disable, score access, fixed many bugs and increased performance. * libblock/include/rtems/blkdev.h: Added RTEMS_BLKDEV_CAPABILITIES block device request. Cleaned up comments. Added block and user fields to the sg buffer request. Move to rtems_* namespace. * libblock/include/rtems/diskdevs.h, cpukit/libblock/src/diskdevs.c: Move to rtems_* namespace. Add a capabilities field for drivers. Change rtems_disk_lookup to rtems_disk_obtain to match the release call. You do not lookup and release a disk, you obtain and release a disk. * libblock/include/rtems/ide_part_table.h, libblock/include/rtems/ramdisk.h, libblock/src/ide_part_table.c: Move to rtems_* namespace. * libblock/include/rtems/nvdisk.h: Formatting change. * libblock/src/blkdev.c: Move to rtems_* namespace. Change rtems_disk_lookup to rtems_disk_obtain * libblock/src/flashdisk.c: Move to rtems_* namespace. Use the new support for the block number in the scatter/grather request struct. This allows non-continuous buffer requests for those drivers that can support increasing performance. * libblock/src/nvdisk.c: Move to rtems_* namespace. Removed warnings. Added better error checking. Fixed some comments. * libblock/src/ramdisk.c: Move to rtems_* namespace. Added some trace functions to help debugging upper layers. Use the new support for the block number in the scatter/grather request struct. This allows non-continuous buffer requests for those drivers that can support increasing performance. * libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h: Use new chains API. Removed temporary hack and changed set_errno_and_return_minus_one to rtems_set_errno_and_return_minus_one. Move fat_buf_access from header and stopped it being inlined. Updated to libblock changes. * libfs/src/dosfs/fat_fat_operations.c, libfs/src/dosfs/fat_file.c, libfs/src/dosfs/msdos_create.c, libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_eval.c, libfs/src/dosfs/msdos_file.c, libfs/src/dosfs/msdos_format.c, libfs/src/dosfs/msdos_free.c, libfs/src/dosfs/msdos_initsupp.c, libfs/src/dosfs/msdos_misc.c, libfs/src/dosfs/msdos_mknod.c: Use new chains API. Removed temporary hack and changed set_errno_and_return_minus_one to rtems_set_errno_and_return_minus_one. Updated to libblock changes. * libmisc/Makefile.am: Add new ls and rm command files. * libmisc/shell/cmp-ls.c, libmisc/shell/extern-ls.h, libmisc/shell/filemode.c, libmisc/shell/print-ls.c, libmisc/shell/pwcache.c, libmisc/shell/utils-ls.c, libmisc/shell/vis.c, shell/vis.h: New. * libmisc/shell/extern-cp.h, libmisc/shell/main_cp.c, libmisc/shell/utils-cp.c: Fixed the usage call bug. * libmisc/shell/main_blksync.c: Updated to the new block IO ioctl command. * libmisc/shell/main_ls.c, libmisc/shell/main_rm.c: Updated to BSD commands with more features. * score/src/coremutex.c: Fix the strick order mutex code. * libmisc/shell/shell.c: Change shell tasks mode to be timeslice and no ASR. * sapi/include/confdefs.h: Change ata_driver_task_priority to rtems_ata_driver_task_priority. Add the new BD buf cache parameters with defaults. * score/src/interr.c: Do not return if the CPU halt call returns. --- cpukit/libblock/include/rtems/bdbuf.h | 250 ++++++++++++++++++---------------- 1 file changed, 136 insertions(+), 114 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 f4308963dd..991da1fdaa 100644 --- a/cpukit/libblock/include/rtems/bdbuf.h +++ b/cpukit/libblock/include/rtems/bdbuf.h @@ -25,116 +25,143 @@ extern "C" { #include "rtems/blkdev.h" #include "rtems/diskdevs.h" - -/* - * To manage buffers we using Buffer Descriptors. - * To speed-up buffer lookup descriptors are organized in AVL-Tree. - * The fields 'dev' and 'block' are search key. +/** + * State of a buffer in the cache. */ +typedef enum +{ + RTEMS_BDBUF_STATE_EMPTY = 0, /* Not in use. */ + RTEMS_BDBUF_STATE_READ_AHEAD = 1, /* Holds read ahead data only */ + RTEMS_BDBUF_STATE_CACHED = 2, /* In the cache and available */ + RTEMS_BDBUF_STATE_ACCESS = 3, /* The user has the buffer */ + RTEMS_BDBUF_STATE_MODIFIED = 4, /* In the cache but modified */ + RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5, /* With the user but modified */ + RTEMS_BDBUF_STATE_SYNC = 6, /* Requested to be sync'ed */ + RTEMS_BDBUF_STATE_TRANSFER = 7 /* Being transferred to or from disk */ +} rtems_bdbuf_buf_state; -/* Buffer descriptors - * Descriptors organized in AVL-tree to speedup buffer lookup. - * dev and block fields are search key in AVL-tree. - * Modified buffers, free buffers and used buffers linked in 'mod', 'free' and - * 'lru' chains appropriately. +/** + * 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 + * 'dev' and 'block' are search keys. */ +typedef struct rtems_bdbuf_buffer +{ + rtems_chain_node link; /* Link in the BD onto a number of lists. */ -typedef struct bdbuf_buffer { - Chain_Node link; /* Link in the lru, mod or free chains */ - - struct bdbuf_avl_node { - signed char cache; /* Cache */ + struct rtems_bdbuf_avl_node + { + signed char cache; /* Cache */ + struct rtems_bdbuf_buffer* left; /* Left Child */ + struct rtems_bdbuf_buffer* right; /* Right Child */ + signed char bal; /* The balance of the sub-tree */ + } avl; - struct bdbuf_buffer* left; /* Left Child */ - struct bdbuf_buffer* right; /* Right Child */ + dev_t dev; /* device number */ + rtems_blkdev_bnum block; /* block number on the device */ - signed char bal; /* The balance of the sub-tree */ - } avl; + unsigned char* buffer; /* Pointer to the buffer memory area */ + int error; /* If not 0 indicate an error value (errno) + * which can be used by user later */ - dev_t dev; /* device number */ - blkdev_bnum block; /* block number on the device */ + volatile rtems_bdbuf_buf_state state; /* State of the buffer. */ - unsigned char *buffer; /* Pointer to the buffer memory area */ - rtems_status_code status; /* Last I/O operation completion status */ - int error; /* If status != RTEMS_SUCCESSFUL, this field contains - errno value which can be used by user later */ - boolean modified:1; /* =1 if buffer was modified */ - boolean in_progress:1; /* =1 if exchange with disk is in progress; - need to wait on semaphore */ - boolean actual:1; /* Buffer contains actual data */ - int use_count; /* Usage counter; incremented when somebody use - this buffer; decremented when buffer released - without modification or when buffer is flushed - by swapout task */ + 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 */ - rtems_bdpool_id pool; /* Identifier of buffer pool to which this buffer - belongs */ - CORE_mutex_Control transfer_sema; - /* Transfer operation semaphore */ -} bdbuf_buffer; + 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. + */ +typedef struct rtems_bdbuf_pool +{ + int blksize; /* The size of the blocks (in bytes) */ + int 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. */ + boolean 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; -/* - * the following data structures are internal to the bdbuf layer, - * but it is convenient to have them visible from the outside for inspection +/** + * Configuration structure describes block configuration (size, amount, memory + * location) for buffering layer pool. */ -/* - * The groups of the blocks with the same size are collected in the - * bd_pool. Note that a several of the buffer's groups with the - * same size can exists. +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 references provided by the user for each pool in the system. */ -typedef struct bdbuf_pool -{ - bdbuf_buffer *tree; /* Buffer descriptor lookup AVL tree root */ - - Chain_Control free; /* Free buffers list */ - Chain_Control lru; /* Last recently used list */ - - int blksize; /* The size of the blocks (in bytes) */ - int nblks; /* Number of blocks in this pool */ - rtems_id bufget_sema; /* Buffer obtain counting semaphore */ - void *mallocd_bufs; /* Pointer to the malloc'd buffer memory, - or NULL, if buffer memory provided in - buffer configuration */ - bdbuf_buffer *bdbufs; /* Pointer to table of buffer descriptors - allocated for this buffer pool. */ -} bdbuf_pool; - -/* Buffering layer context definition */ -struct bdbuf_context { - bdbuf_pool *pool; /* Table of buffer pools */ - int npools; /* Number of entries in pool table */ - - Chain_Control mod; /* Modified buffers list */ - rtems_id flush_sema; /* Buffer flush semaphore; counting - semaphore; incremented when buffer - flushed to the disk; decremented when - buffer modified */ - rtems_id swapout_task; /* Swapout task ID */ -}; - /* - * the context of the buffering layer, visible for inspection - */ -extern struct bdbuf_context rtems_bdbuf_ctx; - -/* bdbuf_config structure describes block configuration (size, - * amount, memory location) for buffering layer +extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[]; +extern int rtems_bdbuf_pool_configuration_size; + +/** + * Buffering configuration definition. See confdefs.h for support on using this + * structure. */ typedef struct rtems_bdbuf_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 */ + int max_read_ahead_blocks; /*<< Number of blocks to read ahead. */ + int 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. */ } rtems_bdbuf_config; -extern rtems_bdbuf_config rtems_bdbuf_configuration[]; -extern int rtems_bdbuf_configuration_size; +/** + * External referernce to the configuration. The configuration is provided by + * the user. + */ +extern rtems_bdbuf_config rtems_bdbuf_configuration; -#define SWAPOUT_TASK_DEFAULT_PRIORITY 15 -extern rtems_task_priority swapout_task_priority; +/** + * The max_read_ahead_blocks value is altered if there are fewer buffers + * than this defined max. This stops thrashing in the cache. + */ +#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 32 +#define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT 16 +#define RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT 15 +#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250 /* milli-seconds */ +#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000 /* milli-seconds */ /* rtems_bdbuf_init -- * Prepare buffering layer to work - initialize buffer descritors @@ -143,17 +170,12 @@ extern rtems_task_priority swapout_task_priority; * amount requested. After initialization all blocks is placed into * free elements lists. * - * PARAMETERS: - * conf_table - pointer to the buffers configuration table - * size - number of entries in configuration table - * * RETURNS: * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully * or error code if error is occured) */ rtems_status_code -rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size); - +rtems_bdbuf_init (); /* rtems_bdbuf_get -- * Obtain block buffer. If specified block already cached (i.e. there's @@ -177,8 +199,8 @@ rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size); * SIDE EFFECTS: * bufget_sema semaphore obtained by this primitive. */ -rtems_status_code -rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr); + rtems_status_code + rtems_bdbuf_get(dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd); /* rtems_bdbuf_read -- * (Similar to the rtems_bdbuf_get, except reading data from media) @@ -201,8 +223,8 @@ rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr); * SIDE EFFECTS: * bufget_sema and transfer_sema semaphores obtained by this primitive. */ -rtems_status_code -rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr); + rtems_status_code + rtems_bdbuf_read(dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd); /* rtems_bdbuf_release -- * Release buffer allocated before. This primitive decrease the @@ -223,8 +245,8 @@ rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr); * SIDE EFFECTS: * flush_sema and bufget_sema semaphores may be released by this primitive. */ -rtems_status_code -rtems_bdbuf_release(bdbuf_buffer *bd_buf); + rtems_status_code + rtems_bdbuf_release(rtems_bdbuf_buffer* bd); /* rtems_bdbuf_release_modified -- * Release buffer allocated before, assuming that it is _modified_ by @@ -244,8 +266,8 @@ rtems_bdbuf_release(bdbuf_buffer *bd_buf); * SIDE EFFECTS: * flush_sema semaphore may be released by this primitive. */ -rtems_status_code -rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf); + rtems_status_code + rtems_bdbuf_release_modified(rtems_bdbuf_buffer* bd); /* rtems_bdbuf_sync -- * Wait until specified buffer synchronized with disk. Invoked on exchanges @@ -265,8 +287,8 @@ rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf); * SIDE EFFECTS: * Primitive may be blocked on transfer_sema semaphore. */ -rtems_status_code -rtems_bdbuf_sync(bdbuf_buffer *bd_buf); + rtems_status_code + rtems_bdbuf_sync(rtems_bdbuf_buffer* bd); /* rtems_bdbuf_syncdev -- * Synchronize with disk all buffers containing the blocks belonging to @@ -279,8 +301,8 @@ rtems_bdbuf_sync(bdbuf_buffer *bd_buf); * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully * or error code if error is occured) */ -rtems_status_code -rtems_bdbuf_syncdev(dev_t dev); + rtems_status_code + rtems_bdbuf_syncdev(dev_t dev); /* rtems_bdbuf_find_pool -- * Find first appropriate buffer pool. This primitive returns the index @@ -297,8 +319,8 @@ rtems_bdbuf_syncdev(dev_t dev); * of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size * is not configured. */ -rtems_status_code -rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool); + rtems_status_code + rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool); /* rtems_bdbuf_get_pool_info -- * Obtain characteristics of buffer pool with specified number. @@ -316,8 +338,8 @@ rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool); * NOTE: * Buffer pools enumerated contiguously starting from 0. */ -rtems_status_code -rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size, int *blocks); + rtems_status_code + rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size, int *blocks); #ifdef __cplusplus } -- cgit v1.2.3