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

📄 bdbuf.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 4 页
字号:
    *bd = bd_buf;               return RTEMS_SUCCESSFUL;}/* bdbuf_release -- *     Release buffer. Decrease buffer usage counter. If it is zero, further *     processing depends on modified attribute. If buffer was modified, it *     is inserted into mod chain and swapout task waken up. If buffer was *     not modified, it is returned to the end of lru chain making it available *     for further use. * * PARAMETERS: *     bd_buf - pointer to the released buffer descriptor. * * RETURNS: *     RTEMS_SUCCESSFUL if buffer released successfully, or error code if *     error occured. * * NOTE: *     This is internal function. It is assumed that task made non-preemptive *     before its invocation. */static rtems_status_codebdbuf_release(bdbuf_buffer *bd_buf){    bdbuf_pool *bd_pool;    rtems_status_code rc = RTEMS_SUCCESSFUL;    if (bd_buf->use_count <= 0)        return RTEMS_INTERNAL_ERROR;        bd_pool = bd_ctx.pool + bd_buf->pool;    bd_buf->use_count--;    if (bd_buf->use_count == 0)    {        if (bd_buf->modified)        {                        /* Buffer was modified. Insert buffer to the modified buffers             * list and initiate flushing. */            Chain_Append(&bd_ctx.mod, &bd_buf->link);            /* Release the flush_sema */            rc = rtems_semaphore_release(bd_ctx.flush_sema);        }        else        {            /* Buffer was not modified. Add this descriptor to the              * end of lru chain and make it available for reuse. */            Chain_Append(&bd_pool->lru, &bd_buf->link);            rc = rtems_semaphore_release(bd_pool->bufget_sema);        }    }    return rc;}/* rtems_bdbuf_release -- *     Release buffer allocated before. This primitive decrease the *     usage counter. If it is zero, further destiny of buffer depends on *     'modified' status. If buffer was modified, it is placed to the end of *     mod list and flush task waken up. If buffer was not modified, *     it is placed to the end of lru list, and bufget_sema released, allowing *     to reuse this buffer. * * PARAMETERS: *     bd_buf - pointer to the bdbuf_buffer structure previously obtained using *              get/read primitive.  * * RETURNS: *     RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully *     or error code if error is occured) * * SIDE EFFECTS: *     flush_sema and bufget_sema semaphores may be released by this primitive. */rtems_status_codertems_bdbuf_release(bdbuf_buffer *bd_buf){    preemption_key key;    rtems_status_code rc = RTEMS_SUCCESSFUL;    if (bd_buf == NULL)        return RTEMS_INVALID_ADDRESS;        DISABLE_PREEMPTION(key);        rc = bdbuf_release(bd_buf);        ENABLE_PREEMPTION(key);        return rc;}/* rtems_bdbuf_release_modified -- *     Release buffer allocated before, assuming that it is _modified_ by *     it's owner. This primitive decrease usage counter for buffer, mark  *     buffer descriptor as modified. If usage counter is 0, insert it at *     end of mod chain and release flush_sema semaphore to activate the *     flush task. * * PARAMETERS: *     bd_buf - pointer to the bdbuf_buffer structure previously obtained using *              get/read primitive. * * RETURNS: *     RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully *     or error code if error is occured) * * SIDE EFFECTS: *     flush_sema semaphore may be released by this primitive. */rtems_status_codertems_bdbuf_release_modified(bdbuf_buffer *bd_buf){    preemption_key key;    rtems_status_code rc = RTEMS_SUCCESSFUL;    if (bd_buf == NULL)        return RTEMS_INVALID_ADDRESS;        DISABLE_PREEMPTION(key);    if (!bd_buf->modified)    {        bdbuf_initialize_transfer_sema(bd_buf);    }    bd_buf->modified = TRUE;    bd_buf->actual = TRUE;    rc = bdbuf_release(bd_buf);            ENABLE_PREEMPTION(key);        return rc;}/* rtems_bdbuf_sync -- *     Wait until specified buffer synchronized with disk. Invoked on exchanges *     critical for data consistency on the media. This primitive mark owned *     block as modified, decrease usage counter. If usage counter is 0, *     block inserted to the mod chain and flush_sema semaphore released. *     Finally, primitives blocked on transfer_sema semaphore. * * PARAMETERS: *     bd_buf - pointer to the bdbuf_buffer structure previously obtained using *              get/read primitive. * * RETURNS: *     RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully *     or error code if error is occured) * * SIDE EFFECTS: *     Primitive may be blocked on transfer_sema semaphore. */rtems_status_codertems_bdbuf_sync(bdbuf_buffer *bd_buf){    preemption_key key;    ISR_Level level;    rtems_status_code rc = RTEMS_SUCCESSFUL;    if (bd_buf == NULL)        return RTEMS_INVALID_ADDRESS;        DISABLE_PREEMPTION(key);    if (!bd_buf->modified)    {        bdbuf_initialize_transfer_sema(bd_buf);    }    bd_buf->modified = TRUE;    bd_buf->actual = TRUE;    rc = bdbuf_release(bd_buf);    if (rc == RTEMS_SUCCESSFUL)    {        rtems_interrupt_disable(level);        _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,                          WATCHDOG_NO_TIMEOUT, level);    }        ENABLE_PREEMPTION(key);        return rc;}/* rtems_bdbuf_syncdev -- *     Synchronize with disk all buffers containing the blocks belonging to *     specified device. * * PARAMETERS: *     dev - block device number * * RETURNS: *     RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully *     or error code if error is occured) */rtems_status_codertems_bdbuf_syncdev(dev_t dev){    preemption_key key;    ISR_Level level;                bdbuf_buffer *bd_buf;    disk_device *dd;    bdbuf_pool  *pool;        dd = rtems_disk_lookup(dev);    if (dd == NULL)        return RTEMS_INVALID_ID;        pool = bd_ctx.pool + dd->pool;            DISABLE_PREEMPTION(key);    do {        bd_buf = avl_search_for_sync(&pool->tree, dd);        if (bd_buf != NULL /* && bd_buf->modified */)        {            rtems_interrupt_disable(level);            _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,                              WATCHDOG_NO_TIMEOUT, level);        }    } while (bd_buf != NULL);    ENABLE_PREEMPTION(key);    return rtems_disk_release(dd);}/* bdbuf_swapout_task -- *     Body of task which take care on flushing modified buffers to the *     disk. */static rtems_task bdbuf_swapout_task(rtems_task_argument unused){    rtems_status_code rc;    int result;    ISR_Level level;    bdbuf_buffer *bd_buf;    bdbuf_pool *bd_pool;    disk_device *dd;    blkdev_request1 req;    while (1)    {        rc = rtems_semaphore_obtain(bd_ctx.flush_sema, RTEMS_WAIT, 0);        if (rc != RTEMS_SUCCESSFUL)        {            rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_SWAPOUT);        }                    bd_buf = (bdbuf_buffer *)Chain_Get(&bd_ctx.mod);        if (bd_buf == NULL)        {            /* It is possible that flush_sema semaphore will be released, but             * buffer to be removed from mod chain before swapout task start             * its processing. */            continue;        }        bd_buf->in_progress = TRUE;        bd_buf->use_count++;        bd_pool = bd_ctx.pool + bd_buf->pool;        dd = rtems_disk_lookup(bd_buf->dev);        req.req.req = BLKDEV_REQ_WRITE;        req.req.req_done = bdbuf_write_transfer_done;        req.req.done_arg = bd_buf;        req.req.start = bd_buf->block + dd->start;        req.req.count = 1;        req.req.bufnum = 1;        req.req.bufs[0].length = dd->block_size;        req.req.bufs[0].buffer = bd_buf->buffer;        /* transfer_sema initialized when bd_buf inserted in the mod chain            first time */        result = dd->ioctl(dd->phys_dev->dev, BLKIO_REQUEST, &req);                rtems_disk_release(dd);                if (result == -1)        {            bd_buf->status = RTEMS_IO_ERROR;            bd_buf->error = errno;            /* Release tasks waiting on syncing this buffer */            _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,                              CORE_MUTEX_STATUS_SUCCESSFUL);        }        else        {            if (bd_buf->in_progress)            {                rtems_interrupt_disable(level);                _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE, 0, level);            }        }        bd_buf->use_count--;        /* Another task have chance to use this buffer, or even         * modify it. If buffer is not in use, insert it in appropriate chain         * and release semaphore */        if (bd_buf->use_count == 0)        {            if (bd_buf->modified)            {                Chain_Append(&bd_ctx.mod, &bd_buf->link);                rc = rtems_semaphore_release(bd_ctx.flush_sema);            }            else            {                Chain_Append(&bd_pool->lru, &bd_buf->link);                rc = rtems_semaphore_release(bd_pool->bufget_sema);            }        }    }}/* rtems_bdbuf_find_pool -- *     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. * * PARAMETERS: *     block_size - requested block size *     pool       - placeholder for result * * RETURNS: *     RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully, *     RTEMS_INVALID_SIZE if specified block size is invalid (not a power  *     of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size *     is not configured. */rtems_status_codertems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool){    rtems_bdpool_id i;    bdbuf_pool *p;    int cursize = INT_MAX;    rtems_bdpool_id curid = -1;    rtems_boolean found = FALSE;    int j;        for (j = block_size; (j != 0) && ((j & 1) == 0); j >>= 1);    if (j != 1)        return RTEMS_INVALID_SIZE;        for (i = 0, p = bd_ctx.pool; i < bd_ctx.npools; i++, p++)    {        if ((p->blksize >= block_size) &&            (p->blksize < cursize))        {            curid = i;            cursize = p->blksize;            found = TRUE;        }    }        if (found)    {        if (pool != NULL)            *pool = curid;        return RTEMS_SUCCESSFUL;    }    else    {        return RTEMS_NOT_DEFINED;    }}/* rtems_bdbuf_get_pool_info -- *     Obtain characteristics of buffer pool with specified number. * * PARAMETERS: *     pool       - buffer pool number *     block_size - block size for which buffer pool is configured returned *                  there *     blocks     - number of buffers in buffer pool returned there  * * RETURNS: *     RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully, *     RTEMS_INVALID_NUMBER if appropriate buffer pool is not configured. * * NOTE: *     Buffer pools enumerated contiguously starting from 0. */rtems_status_codertems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size,                          int *blocks){    if (pool >= bd_ctx.npools)        return RTEMS_INVALID_NUMBER;        if (block_size != NULL)    {        *block_size = bd_ctx.pool[pool].blksize;    }        if (blocks != NULL)    {        *blocks = bd_ctx.pool[pool].nblks;    }        return RTEMS_SUCCESSFUL;}

⌨️ 快捷键说明

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