Changeset 8d7f3680 in rtems for cpukit/libblock


Ignore:
Timestamp:
Nov 18, 2017, 4:19:13 PM (2 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
2c12262
Parents:
1b2da177
git-author:
Sebastian Huber <sebastian.huber@…> (11/18/17 16:19:13)
git-committer:
Sebastian Huber <sebastian.huber@…> (02/02/18 14:01:21)
Message:

libblock: Use self-contained mutex and cond var

Update #2843.

File:
1 edited

Legend:

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

    r1b2da177 r8d7f3680  
    2020 *    issues.
    2121 *
    22  * Copyright (c) 2009-2014 embedded brains GmbH.
     22 * Copyright (c) 2009, 2017 embedded brains GmbH.
    2323 */
    2424
     
    4141#include <rtems.h>
    4242#include <rtems/error.h>
     43#include <rtems/thread.h>
     44#include <rtems/score/assert.h>
    4345
    4446#include "rtems/bdbuf.h"
     
    7880} rtems_bdbuf_swapout_worker;
    7981
    80 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    81 typedef pthread_mutex_t rtems_bdbuf_lock_type;
    82 #else
    83 typedef rtems_id rtems_bdbuf_lock_type;
    84 #endif
    85 
    8682/**
    8783 * Buffer waiters synchronization.
    8884 */
    8985typedef struct rtems_bdbuf_waiters {
    90   unsigned       count;
    91 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    92   pthread_cond_t cond_var;
    93 #else
    94   rtems_id       sema;
    95 #endif
     86  unsigned                 count;
     87  rtems_condition_variable cond_var;
    9688} rtems_bdbuf_waiters;
    9789
     
    117109  uint32_t            flags;             /**< Configuration flags. */
    118110
    119   rtems_bdbuf_lock_type lock;            /**< The cache lock. It locks all
     111  rtems_mutex         lock;              /**< The cache lock. It locks all
    120112                                          * cache data, BD and lists. */
    121   rtems_bdbuf_lock_type sync_lock;       /**< Sync calls block writes. */
     113  rtems_mutex         sync_lock;         /**< Sync calls block writes. */
    122114  bool                sync_active;       /**< True if a sync is active. */
    123115  rtems_id            sync_requester;    /**< The sync requester. */
     
    150142  bool                read_ahead_enabled; /**< Read-ahead enabled */
    151143  rtems_status_code   init_status;       /**< The initialization status */
     144  pthread_once_t      once;
    152145} rtems_bdbuf_cache;
    153146
    154147typedef enum {
    155   RTEMS_BDBUF_FATAL_CACHE_LOCK,
    156   RTEMS_BDBUF_FATAL_CACHE_UNLOCK,
    157148  RTEMS_BDBUF_FATAL_CACHE_WAIT_2,
    158149  RTEMS_BDBUF_FATAL_CACHE_WAIT_TO,
     
    175166  RTEMS_BDBUF_FATAL_STATE_11,
    176167  RTEMS_BDBUF_FATAL_SWAPOUT_RE,
    177   RTEMS_BDBUF_FATAL_SYNC_LOCK,
    178   RTEMS_BDBUF_FATAL_SYNC_UNLOCK,
    179168  RTEMS_BDBUF_FATAL_TREE_RM,
    180169  RTEMS_BDBUF_FATAL_WAIT_EVNT,
    181   RTEMS_BDBUF_FATAL_WAIT_TRANS_EVNT,
    182   RTEMS_BDBUF_FATAL_ONCE,
    183   RTEMS_BDBUF_FATAL_MTX_ATTR_INIT,
    184   RTEMS_BDBUF_FATAL_MTX_ATTR_SETPROTO,
    185   RTEMS_BDBUF_FATAL_CV_WAIT,
    186   RTEMS_BDBUF_FATAL_CV_BROADCAST
     170  RTEMS_BDBUF_FATAL_WAIT_TRANS_EVNT
    187171} rtems_bdbuf_fatal_code;
    188172
     
    194178#define RTEMS_BDBUF_READ_AHEAD_WAKE_UP RTEMS_EVENT_1
    195179
    196 /**
    197  * Lock semaphore attributes. This is used for locking type mutexes.
    198  *
    199  * @warning Priority inheritance is on.
    200  */
    201 #define RTEMS_BDBUF_CACHE_LOCK_ATTRIBS \
    202   (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \
    203    RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
    204 
    205 /**
    206  * Waiter semaphore attributes.
    207  *
    208  * @warning Do not configure as inherit priority. If a driver is in the driver
    209  *          initialisation table this locked semaphore will have the IDLE task
    210  *          as the holder and a blocking task will raise the priority of the
    211  *          IDLE task which can cause unsual side effects.
    212  */
    213 #define RTEMS_BDBUF_CACHE_WAITER_ATTRIBS \
    214   (RTEMS_PRIORITY | RTEMS_SIMPLE_BINARY_SEMAPHORE | \
    215    RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL)
    216 
    217 /**
    218  * Waiter timeout. Set to non-zero to find some info on a waiter that is
    219  * waiting too long.
    220  */
    221 #define RTEMS_BDBUF_WAIT_TIMEOUT RTEMS_NO_TIMEOUT
    222 #if !defined (RTEMS_BDBUF_WAIT_TIMEOUT)
    223 #define RTEMS_BDBUF_WAIT_TIMEOUT \
    224   (RTEMS_MICROSECONDS_TO_TICKS (20000000))
    225 #endif
    226 
    227180static rtems_task rtems_bdbuf_swapout_task(rtems_task_argument arg);
    228181
     
    232185 * The Buffer Descriptor cache.
    233186 */
    234 static rtems_bdbuf_cache bdbuf_cache;
    235 
    236 static pthread_once_t rtems_bdbuf_once_state = PTHREAD_ONCE_INIT;
     187static rtems_bdbuf_cache bdbuf_cache = {
     188  .lock = RTEMS_MUTEX_INITIALIZER(NULL),
     189  .sync_lock = RTEMS_MUTEX_INITIALIZER(NULL),
     190  .access_waiters = { .cond_var = RTEMS_CONDITION_VARIABLE_INITIALIZER(NULL) },
     191  .transfer_waiters = {
     192    .cond_var = RTEMS_CONDITION_VARIABLE_INITIALIZER(NULL)
     193  },
     194  .buffer_waiters = { .cond_var = RTEMS_CONDITION_VARIABLE_INITIALIZER(NULL) },
     195  .once = PTHREAD_ONCE_INIT
     196};
    237197
    238198#if RTEMS_BDBUF_TRACE
     
    332292{
    333293  rtems_bdbuf_fatal ((((uint32_t) state) << 16) | error);
    334 }
    335 
    336 static rtems_status_code
    337 rtems_bdbuf_lock_create (rtems_name name, rtems_bdbuf_lock_type *lock)
    338 {
    339 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    340   int                 eno;
    341   pthread_mutexattr_t attr;
    342 
    343   (void) name;
    344 
    345   eno = pthread_mutexattr_init (&attr);
    346   if (eno != 0)
    347     rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_MTX_ATTR_INIT);
    348 
    349   eno = pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_INHERIT);
    350   if (eno != 0)
    351     rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_MTX_ATTR_SETPROTO);
    352 
    353   eno = pthread_mutex_init (lock, &attr);
    354 
    355   pthread_mutexattr_destroy (&attr);
    356 
    357   if (eno != 0)
    358     return RTEMS_UNSATISFIED;
    359 
    360   return RTEMS_SUCCESSFUL;
    361 #else
    362   return rtems_semaphore_create(
    363     name,
    364     1,
    365     RTEMS_BDBUF_CACHE_LOCK_ATTRIBS,
    366     0,
    367     lock
    368   );
    369 #endif
    370 }
    371 
    372 static void
    373 rtems_bdbuf_lock_delete (rtems_bdbuf_lock_type *lock)
    374 {
    375 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    376   pthread_mutex_destroy (lock);
    377 #else
    378   rtems_semaphore_delete (*lock);
    379 #endif
    380 }
    381 
    382 static rtems_status_code
    383 rtems_bdbuf_waiter_create (rtems_name name, rtems_bdbuf_waiters *waiter)
    384 {
    385 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    386   int eno = pthread_cond_init (&waiter->cond_var, NULL);
    387   if (eno != 0)
    388     return RTEMS_UNSATISFIED;
    389 
    390   return RTEMS_SUCCESSFUL;
    391 #else
    392   return rtems_semaphore_create(
    393     name,
    394     0,
    395     RTEMS_BDBUF_CACHE_WAITER_ATTRIBS,
    396     0,
    397     &waiter->sema
    398   );
    399 #endif
    400 }
    401 
    402 static void
    403 rtems_bdbuf_waiter_delete (rtems_bdbuf_waiters *waiter)
    404 {
    405 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    406   pthread_cond_destroy (&waiter->cond_var);
    407 #else
    408   rtems_semaphore_delete (waiter->sema);
    409 #endif
    410294}
    411295
     
    923807 *
    924808 * @param lock The mutex to lock.
    925  * @param fatal_error_code The error code if the call fails.
    926  */
    927 static void
    928 rtems_bdbuf_lock (rtems_bdbuf_lock_type *lock, uint32_t fatal_error_code)
    929 {
    930 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    931   int eno = pthread_mutex_lock (lock);
    932   if (eno != 0)
    933     rtems_bdbuf_fatal (fatal_error_code);
    934 #else
    935   rtems_status_code sc = rtems_semaphore_obtain (*lock,
    936                                                  RTEMS_WAIT,
    937                                                  RTEMS_NO_TIMEOUT);
    938   if (sc != RTEMS_SUCCESSFUL)
    939     rtems_bdbuf_fatal (fatal_error_code);
    940 #endif
     809 */
     810static void
     811rtems_bdbuf_lock (rtems_mutex *lock)
     812{
     813  rtems_mutex_lock (lock);
    941814}
    942815
     
    945818 *
    946819 * @param lock The mutex to unlock.
    947  * @param fatal_error_code The error code if the call fails.
    948  */
    949 static void
    950 rtems_bdbuf_unlock (rtems_bdbuf_lock_type *lock, uint32_t fatal_error_code)
    951 {
    952 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    953   int eno = pthread_mutex_unlock (lock);
    954   if (eno != 0)
    955     rtems_bdbuf_fatal (fatal_error_code);
    956 #else
    957   rtems_status_code sc = rtems_semaphore_release (*lock);
    958   if (sc != RTEMS_SUCCESSFUL)
    959     rtems_bdbuf_fatal (fatal_error_code);
    960 #endif
     820 */
     821static void
     822rtems_bdbuf_unlock (rtems_mutex *lock)
     823{
     824  rtems_mutex_unlock (lock);
    961825}
    962826
     
    967831rtems_bdbuf_lock_cache (void)
    968832{
    969   rtems_bdbuf_lock (&bdbuf_cache.lock, RTEMS_BDBUF_FATAL_CACHE_LOCK);
     833  rtems_bdbuf_lock (&bdbuf_cache.lock);
    970834}
    971835
     
    976840rtems_bdbuf_unlock_cache (void)
    977841{
    978   rtems_bdbuf_unlock (&bdbuf_cache.lock, RTEMS_BDBUF_FATAL_CACHE_UNLOCK);
     842  rtems_bdbuf_unlock (&bdbuf_cache.lock);
    979843}
    980844
     
    985849rtems_bdbuf_lock_sync (void)
    986850{
    987   rtems_bdbuf_lock (&bdbuf_cache.sync_lock, RTEMS_BDBUF_FATAL_SYNC_LOCK);
     851  rtems_bdbuf_lock (&bdbuf_cache.sync_lock);
    988852}
    989853
     
    994858rtems_bdbuf_unlock_sync (void)
    995859{
    996   rtems_bdbuf_unlock (&bdbuf_cache.sync_lock,
    997                       RTEMS_BDBUF_FATAL_SYNC_UNLOCK);
     860  rtems_bdbuf_unlock (&bdbuf_cache.sync_lock);
    998861}
    999862
     
    1009872  --bd->group->users;
    1010873}
    1011 
    1012 #if !defined(RTEMS_BDBUF_USE_PTHREAD)
    1013 static rtems_mode
    1014 rtems_bdbuf_disable_preemption (void)
    1015 {
    1016   rtems_status_code sc = RTEMS_SUCCESSFUL;
    1017   rtems_mode prev_mode = 0;
    1018 
    1019   sc = rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &prev_mode);
    1020   if (sc != RTEMS_SUCCESSFUL)
    1021     rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_PREEMPT_DIS);
    1022 
    1023   return prev_mode;
    1024 }
    1025 
    1026 static void
    1027 rtems_bdbuf_restore_preemption (rtems_mode prev_mode)
    1028 {
    1029   rtems_status_code sc = RTEMS_SUCCESSFUL;
    1030 
    1031   sc = rtems_task_mode (prev_mode, RTEMS_ALL_MODE_MASKS, &prev_mode);
    1032   if (sc != RTEMS_SUCCESSFUL)
    1033     rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_PREEMPT_RST);
    1034 }
    1035 #endif
    1036874
    1037875/**
     
    1058896  ++waiters->count;
    1059897
    1060 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    1061   {
    1062     int eno = pthread_cond_wait (&waiters->cond_var, &bdbuf_cache.lock);
    1063     if (eno != 0)
    1064       rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CV_WAIT);
    1065   }
    1066 #else
    1067   {
    1068     rtems_status_code sc;
    1069     rtems_mode        prev_mode;
    1070 
    1071     /*
    1072      * Disable preemption then unlock the cache and block.  There is no POSIX
    1073      * condition variable in the core API so this is a work around.
    1074      *
    1075      * The issue is a task could preempt after the cache is unlocked because it is
    1076      * blocking or just hits that window, and before this task has blocked on the
    1077      * semaphore. If the preempting task flushes the queue this task will not see
    1078      * the flush and may block for ever or until another transaction flushes this
    1079      * semaphore.
    1080      */
    1081     prev_mode = rtems_bdbuf_disable_preemption();
    1082 
    1083     /*
    1084      * Unlock the cache, wait, and lock the cache when we return.
    1085      */
    1086     rtems_bdbuf_unlock_cache ();
    1087 
    1088     sc = rtems_semaphore_obtain (waiters->sema, RTEMS_WAIT, RTEMS_BDBUF_WAIT_TIMEOUT);
    1089 
    1090     if (sc == RTEMS_TIMEOUT)
    1091       rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAIT_TO);
    1092 
    1093     if (sc != RTEMS_UNSATISFIED)
    1094       rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAIT_2);
    1095 
    1096     rtems_bdbuf_lock_cache ();
    1097 
    1098     rtems_bdbuf_restore_preemption (prev_mode);
    1099   }
    1100 #endif
     898  rtems_condition_variable_wait (&waiters->cond_var, &bdbuf_cache.lock);
    1101899
    1102900  --waiters->count;
     
    1122920  if (waiters->count > 0)
    1123921  {
    1124 #if defined(RTEMS_BDBUF_USE_PTHREAD)
    1125     int eno = pthread_cond_broadcast (&waiters->cond_var);
    1126     if (eno != 0)
    1127       rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CV_BROADCAST);
    1128 #else
    1129     rtems_status_code sc = rtems_semaphore_flush (waiters->sema);
    1130     if (sc != RTEMS_SUCCESSFUL)
    1131       rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAKE);
    1132 #endif
     922    rtems_condition_variable_broadcast (&waiters->cond_var);
    1133923  }
    1134924}
     
    15151305  size_t              b;
    15161306  rtems_status_code   sc;
    1517   bool                locked;
    15181307
    15191308  if (rtems_bdbuf_tracer)
     
    15421331  rtems_chain_initialize_empty (&bdbuf_cache.read_ahead_chain);
    15431332
    1544   /*
    1545    * Create the locks for the cache.
    1546    */
    1547 
    1548   sc = rtems_bdbuf_lock_create (rtems_build_name ('B', 'D', 'C', 'l'),
    1549                                 &bdbuf_cache.lock);
    1550   locked = (sc == RTEMS_SUCCESSFUL);
    1551   if (!locked)
    1552     goto error;
     1333  rtems_mutex_set_name (&bdbuf_cache.lock, "bdbuf lock");
     1334  rtems_mutex_set_name (&bdbuf_cache.sync_lock, "bdbuf sync lock");
     1335  rtems_condition_variable_set_name (&bdbuf_cache.access_waiters.cond_var,
     1336                                     "bdbuf access");
     1337  rtems_condition_variable_set_name (&bdbuf_cache.transfer_waiters.cond_var,
     1338                                     "bdbuf transfer");
     1339  rtems_condition_variable_set_name (&bdbuf_cache.buffer_waiters.cond_var,
     1340                                     "bdbuf buffer");
    15531341
    15541342  rtems_bdbuf_lock_cache ();
    1555 
    1556   sc = rtems_bdbuf_lock_create (rtems_build_name ('B', 'D', 'C', 's'),
    1557                                 &bdbuf_cache.sync_lock);
    1558   if (sc != RTEMS_SUCCESSFUL)
    1559     goto error;
    1560 
    1561   sc = rtems_bdbuf_waiter_create (rtems_build_name ('B', 'D', 'C', 'a'),
    1562                                   &bdbuf_cache.access_waiters);
    1563   if (sc != RTEMS_SUCCESSFUL)
    1564     goto error;
    1565 
    1566   sc = rtems_bdbuf_waiter_create (rtems_build_name ('B', 'D', 'C', 't'),
    1567                                   &bdbuf_cache.transfer_waiters);
    1568   if (sc != RTEMS_SUCCESSFUL)
    1569     goto error;
    1570 
    1571   sc = rtems_bdbuf_waiter_create (rtems_build_name ('B', 'D', 'C', 'b'),
    1572                                   &bdbuf_cache.buffer_waiters);
    1573   if (sc != RTEMS_SUCCESSFUL)
    1574     goto error;
    15751343
    15761344  /*
     
    17271495  free (bdbuf_cache.swapout_workers);
    17281496
    1729   rtems_bdbuf_waiter_delete (&bdbuf_cache.buffer_waiters);
    1730   rtems_bdbuf_waiter_delete (&bdbuf_cache.access_waiters);
    1731   rtems_bdbuf_waiter_delete (&bdbuf_cache.transfer_waiters);
    1732   rtems_bdbuf_lock_delete (&bdbuf_cache.sync_lock);
    1733 
    1734   if (locked)
    1735   {
    1736     rtems_bdbuf_unlock_cache ();
    1737     rtems_bdbuf_lock_delete (&bdbuf_cache.lock);
    1738   }
     1497  rtems_bdbuf_unlock_cache ();
    17391498
    17401499  return RTEMS_UNSATISFIED;
     
    17501509rtems_bdbuf_init (void)
    17511510{
    1752   int eno = pthread_once (&rtems_bdbuf_once_state, rtems_bdbuf_init_once);
    1753 
    1754   if (eno != 0)
    1755     rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_ONCE);
     1511  int eno;
     1512
     1513  eno = pthread_once (&bdbuf_cache.once, rtems_bdbuf_init_once);
     1514  _Assert (eno == 0);
     1515  (void) eno;
    17561516
    17571517  return bdbuf_cache.init_status;
Note: See TracChangeset for help on using the changeset viewer.