Changeset 3b4ca3a in rtems


Ignore:
Timestamp:
11/27/14 13:41:17 (9 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, 5, master
Children:
01557b0
Parents:
e22af78
git-author:
Sebastian Huber <sebastian.huber@…> (11/27/14 13:41:17)
git-committer:
Sebastian Huber <sebastian.huber@…> (11/28/14 09:56:46)
Message:

bdbuf: Fix race condition with sync active flag

Bug report by Oleg Kravtsov:

In rtems_bdbuf_swapout_processing() function there is the following
lines:

if (bdbuf_cache.sync_active && !transfered_buffers)
{

rtems_id sync_requester;
rtems_bdbuf_lock_cache ();
...

}

Here access to bdbuf_cache.sync_active is not protected with anything.
Imagine the following test case:

  1. Task1 releases buffer(s) with bdbuf_release_modified() calls;
  1. After a while swapout task starts and flushes all buffers;
  1. In the end of that swapout flush we are before that part of code, and

assume there is task switching (just before "if (bdbuf_cache.sync_active
&& !transfered_buffers)");

  1. Some other task (with higher priority) does bdbuf_release_modified

and rtems_bdbuf_syncdev().

This task successfully gets both locks sync and pool (in
rtems_bdbuf_syncdev() function), sets sync_active to true and starts
waiting for RTEMS_BDBUF_TRANSFER_SYNC event with only sync lock got.

  1. Task switching happens again and we are again before "if

(bdbuf_cache.sync_active && !transfered_buffers)".

As the result we check sync_active and we come inside that "if"
statement.

  1. The result is that we send RTEMS_BDBUF_TRANSFER_SYNC event! Though

ALL modified messages of that task are not flushed yet!

close #1485

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libblock/src/bdbuf.c

    re22af78 r3b4ca3a  
    27502750  rtems_bdbuf_swapout_worker* worker;
    27512751  bool                        transfered_buffers = false;
     2752  bool                        sync_active;
    27522753
    27532754  rtems_bdbuf_lock_cache ();
     2755
     2756  /*
     2757   * To set this to true you need the cache and the sync lock.
     2758   */
     2759  sync_active = bdbuf_cache.sync_active;
    27542760
    27552761  /*
     
    27622768   * sync operations.
    27632769   */
    2764   if (bdbuf_cache.sync_active)
     2770  if (sync_active)
    27652771    worker = NULL;
    27662772  else
     
    27742780  rtems_chain_initialize_empty (&transfer->bds);
    27752781  transfer->dd = BDBUF_INVALID_DEV;
    2776   transfer->syncing = bdbuf_cache.sync_active;
     2782  transfer->syncing = sync_active;
    27772783
    27782784  /*
     
    27812787   * list. This means the dev is BDBUF_INVALID_DEV.
    27822788   */
    2783   if (bdbuf_cache.sync_active)
     2789  if (sync_active)
    27842790    transfer->dd = bdbuf_cache.sync_device;
    27852791
     
    28002806                                           &bdbuf_cache.modified,
    28012807                                           &transfer->bds,
    2802                                            bdbuf_cache.sync_active,
     2808                                           sync_active,
    28032809                                           update_timers,
    28042810                                           timer_delta);
     
    28312837  }
    28322838
    2833   if (bdbuf_cache.sync_active && !transfered_buffers)
     2839  if (sync_active && !transfered_buffers)
    28342840  {
    28352841    rtems_id sync_requester;
Note: See TracChangeset for help on using the changeset viewer.