⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bdbuf.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Disk I/O buffering * Buffer managment * * Copyright (C) 2001 OKTET Ltd., St.-Peterburg, Russia * Author: Andrey G. Ivanov <Andrey.Ivanov@oktet.ru> *         Victor V. Vengerov <vvv@oktet.ru> *         Alexander Kukuta <kam@oktet.ru> * * @(#) $Id: bdbuf.c,v 1.7 2003/01/03 16:39:46 joel Exp $ */#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__#include <rtems.h>#include <limits.h>#include <errno.h>#include <assert.h>#include "rtems/bdbuf.h"/* Fatal errors: */#define BLKDEV_FATAL_ERROR(n) (((unsigned32)'B' << 24) | ((unsigned32)(n) & (unsigned32)0x00FFFFFF))#define BLKDEV_FATAL_BDBUF_CONSISTENCY BLKDEV_FATAL_ERROR(1)#define BLKDEV_FATAL_BDBUF_SWAPOUT     BLKDEV_FATAL_ERROR(2)#define SWAPOUT_PRIORITY 15#define SWAPOUT_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2)static rtems_task bdbuf_swapout_task(rtems_task_argument unused);/* * 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 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 */};/* Block device request with a single buffer provided */typedef struct blkdev_request1 {    blkdev_request   req;    blkdev_sg_buffer sg[1];} blkdev_request1;/* The static context of buffering layer */static struct bdbuf_context bd_ctx;#define SAFE#ifdef SAFEtypedef rtems_mode preemption_key;#define DISABLE_PREEMPTION(key) \    do {                                                               \        rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &(key)); \    } while (0)#define ENABLE_PREEMPTION(key) \    do {                                                        \        rtems_mode temp;                                        \        rtems_task_mode((key), RTEMS_PREEMPT_MASK, &temp);      \    } while (0)#else typedef boolean preemption_key;#define DISABLE_PREEMPTION(key) \    do {                                             \        (key) = _Thread_Executing->is_preemptible;   \        _Thread_Executing->is_preemptible = 0;       \    } while (0)    #define ENABLE_PREEMPTION(key) \    do {                                             \        _Thread_Executing->is_preemptible = (key);   \        if (_Thread_Evaluate_mode())                 \            _Thread_Dispatch();                      \    } while (0)#endif/* The default maximum height of 32 allows for AVL trees having   between 5,704,880 and 4,294,967,295 nodes, depending on order of   insertion.  You may change this compile-time constant as you   wish. */#ifndef AVL_MAX_HEIGHT#define AVL_MAX_HEIGHT  32#endif/* * avl_search -- *     Searches for the node with specified dev/block. * * PARAMETERS: *     root - pointer to the root node of the AVL-Tree. *     dev, block - search key * * RETURNS: *     NULL if node with specified dev/block not found *     non-NULL - pointer to the node with specified dev/block */static bdbuf_buffer *avl_search(bdbuf_buffer **root, dev_t dev, blkdev_bnum block){    bdbuf_buffer *p = *root;    while ((p != NULL) && ((p->dev != dev) || (p->block != block)))    {        if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))        {            p = p->avl.right;        }        else        {            p = p->avl.left;        }    }        return p;}/* avl_search_for_sync -- *     Search in AVL tree for first modified buffer belongs to specified *     disk device. * * PARAMETERS: *     root - pointer to tree root *     dd - disk device descriptor * * RETURNS: *     Block buffer, or NULL if no modified blocks on specified device *     exists. */static bdbuf_buffer *avl_search_for_sync(bdbuf_buffer **root, disk_device *dd){    dev_t dev = dd->phys_dev->dev;    blkdev_bnum block_start = dd->start;    blkdev_bnum block_end = dd->start + dd->size - 1;    bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];    bdbuf_buffer **buf_prev = buf_stack;    bdbuf_buffer *p = *root;    while (p != NULL)    {        if ((p->dev < dev) || ((p->dev == dev) && (p->block < block_start)))        {            p = p->avl.right;        }        else if ((p->dev > dev) || ((p->dev == dev) && (p->block > block_end)))        {            p = p->avl.left;        }        else if (p->modified)        {            return p;        }        else        {            if (p->avl.right != NULL)            {                *buf_prev++ = p->avl.right;            }            p = p->avl.left;        }        if ((p == NULL) && (buf_prev > buf_stack))        {            p = *--buf_prev;        }    }    return p;}/* * avl_insert -- *     Inserts the specified node to the AVl-Tree. * * PARAMETERS: *     root - Pointer to pointer to the root node *     node - Pointer to the node to add. * * RETURNS: *     0 - The node added successfully *    -1 - An error occured */static intavl_insert(bdbuf_buffer **root, bdbuf_buffer *node){    dev_t dev = node->dev;    blkdev_bnum block = node->block;    bdbuf_buffer *p = *root;    bdbuf_buffer *q, *p1, *p2;    bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];    bdbuf_buffer **buf_prev = buf_stack;    boolean modified = FALSE;    if (p == NULL)    {        *root = node;        node->avl.left = NULL;        node->avl.right = NULL;        node->avl.bal = 0;        return 0;    }    while (p != NULL)    {        *buf_prev++ = p;        if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))        {            p->avl.cache = 1;            q = p->avl.right;            if (q == NULL)            {                q = node;                p->avl.right = q = node;                break;            }        }        else if ((p->dev != dev) || (p->block != block))        {            p->avl.cache = -1;            q = p->avl.left;            if (q == NULL)            {                q = node;                p->avl.left = q;                break;            }        }        else        {            return -1;        }        p = q;    }    q->avl.left = q->avl.right = NULL;    q->avl.bal = 0;    modified = TRUE;    buf_prev--;    while (modified)    {        if (p->avl.cache == -1)        {            switch (p->avl.bal)            {                case 1:                    p->avl.bal = 0;                    modified = FALSE;                    break;                case 0:                    p->avl.bal = -1;                    break;                case -1:                    p1 = p->avl.left;                    if (p1->avl.bal == -1) /* simple LL-turn */                    {                        p->avl.left = p1->avl.right;                        p1->avl.right = p;                        p->avl.bal = 0;                        p = p1;                    }                    else /* double LR-turn */                    {                        p2 = p1->avl.right;                        p1->avl.right = p2->avl.left;                        p2->avl.left = p1;                        p->avl.left = p2->avl.right;                        p2->avl.right = p;                        if (p2->avl.bal == -1) p->avl.bal = +1; else p->avl.bal = 0;                        if (p2->avl.bal == +1) p1->avl.bal = -1; else p1->avl.bal = 0;                        p = p2;                    }                    p->avl.bal = 0;                    modified = FALSE;                    break;                default:                    break;            }        }        else        {            switch (p->avl.bal)            {                case -1:                    p->avl.bal = 0;                    modified = FALSE;                    break;                case 0:                    p->avl.bal = 1;                    break;                case 1:                    p1 = p->avl.right;                    if (p1->avl.bal == 1) /* simple RR-turn */                    {                        p->avl.right = p1->avl.left;                        p1->avl.left = p;                        p->avl.bal = 0;                        p = p1;                    }                    else /* double RL-turn */                    {                        p2 = p1->avl.left;                        p1->avl.left = p2->avl.right;                        p2->avl.right = p1;                        p->avl.right = p2->avl.left;                        p2->avl.left = p;                        if (p2->avl.bal == +1) p->avl.bal = -1; else p->avl.bal = 0;                        if (p2->avl.bal == -1) p1->avl.bal = +1; else p1->avl.bal = 0;                        p = p2;                    }                    p->avl.bal = 0;                    modified = FALSE;                    break;                default:                    break;            }        }        q = p;        if (buf_prev > buf_stack)        {            p = *--buf_prev;            if (p->avl.cache == -1)            {                p->avl.left = q;            }            else            {                p->avl.right = q;            }        }        else        {            *root = p;            break;        }    };    return 0;}/* avl_remove -- *     removes the node from the tree. * * PARAMETERS: *     root_addr - Pointer to pointer to the root node *     node      - Pointer to the node to remove * * RETURNS: *     0 - Item removed *    -1 - No such item found */static intavl_remove(bdbuf_buffer **root, const bdbuf_buffer *node){    dev_t dev = node->dev;    blkdev_bnum block = node->block;    bdbuf_buffer *p = *root;    bdbuf_buffer *q, *r, *s, *p1, *p2;    bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];    bdbuf_buffer **buf_prev = buf_stack;    boolean modified = FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -