Changeset 1fc2e960 in rtems


Ignore:
Timestamp:
Jun 2, 2014, 12:46:18 PM (5 years ago)
Author:
Ralf Kirchner <ralf.kirchner@…>
Branches:
4.11, master
Children:
3e201139
Parents:
d8ac087
git-author:
Ralf Kirchner <ralf.kirchner@…> (06/02/14 12:46:18)
git-committer:
Sebastian Huber <sebastian.huber@…> (06/02/14 14:26:25)
Message:

libblock: Add RTEMS_BDBUF_USE_PTHREAD

Use the PTHREAD mutexes and condition variables if available. This
helps on SMP configurations to avoid the home grown condition variables
via disabled preemption.

Location:
cpukit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libblock/include/rtems/bdbuf.h

    rd8ac087 r1fc2e960  
    175175/**@{**/
    176176
     177#if defined(RTEMS_POSIX_API)
     178  /*
     179   * Use the PTHREAD mutexes and condition variables if available.  This helps
     180   * on SMP configurations to avoid the home grown condition variables via
     181   * disabled preemption.
     182   */
     183  #define RTEMS_BDBUF_USE_PTHREAD
     184#endif
     185
    177186/**
    178187 * @brief State of a buffer of the cache.
  • cpukit/libblock/src/bdbuf.c

    rd8ac087 r1fc2e960  
    7878} rtems_bdbuf_swapout_worker;
    7979
     80#if defined(RTEMS_BDBUF_USE_PTHREAD)
     81typedef pthread_mutex_t rtems_bdbuf_lock_type;
     82#else
     83typedef rtems_id rtems_bdbuf_lock_type;
     84#endif
     85
    8086/**
    8187 * Buffer waiters synchronization.
    8288 */
    8389typedef struct rtems_bdbuf_waiters {
    84   unsigned count;
    85   rtems_id sema;
     90  unsigned       count;
     91#if defined(RTEMS_BDBUF_USE_PTHREAD)
     92  pthread_cond_t cond_var;
     93#else
     94  rtems_id       sema;
     95#endif
    8696} rtems_bdbuf_waiters;
    8797
     
    107117  uint32_t            flags;             /**< Configuration flags. */
    108118
    109   rtems_id            lock;              /**< The cache lock. It locks all
     119  rtems_bdbuf_lock_type lock;            /**< The cache lock. It locks all
    110120                                          * cache data, BD and lists. */
    111   rtems_id            sync_lock;         /**< Sync calls block writes. */
     121  rtems_bdbuf_lock_type sync_lock;       /**< Sync calls block writes. */
    112122  bool                sync_active;       /**< True if a sync is active. */
    113123  rtems_id            sync_requester;    /**< The sync requester. */
     
    170180  RTEMS_BDBUF_FATAL_WAIT_EVNT,
    171181  RTEMS_BDBUF_FATAL_WAIT_TRANS_EVNT,
    172   RTEMS_BDBUF_FATAL_ONCE
     182  RTEMS_BDBUF_FATAL_ONCE,
     183  RTEMS_BDBUF_FATAL_MTX_ATTR_INIT,
     184  RTEMS_BDBUF_FATAL_MTX_ATTR_SETPROTO,
     185  RTEMS_BDBUF_FATAL_MTX_ATTR_SETTYPE,
     186  RTEMS_BDBUF_FATAL_CV_WAIT,
     187  RTEMS_BDBUF_FATAL_CV_BROADCAST
    173188} rtems_bdbuf_fatal_code;
    174189
     
    318333{
    319334  rtems_bdbuf_fatal ((((uint32_t) state) << 16) | error);
     335}
     336
     337static rtems_status_code
     338rtems_bdbuf_lock_create (rtems_name name, rtems_bdbuf_lock_type *lock)
     339{
     340#if defined(RTEMS_BDBUF_USE_PTHREAD)
     341  int                 eno;
     342  pthread_mutexattr_t attr;
     343
     344  (void) name;
     345
     346  eno = pthread_mutexattr_init (&attr);
     347  if (eno != 0)
     348    rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_MTX_ATTR_INIT);
     349
     350  eno = pthread_mutexattr_setprotocol (&attr, PTHREAD_PRIO_INHERIT);
     351  if (eno != 0)
     352    rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_MTX_ATTR_SETPROTO);
     353
     354  eno = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
     355  if (eno != 0)
     356    rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_MTX_ATTR_SETTYPE);
     357
     358  eno = pthread_mutex_init (lock, &attr);
     359
     360  pthread_mutexattr_destroy (&attr);
     361
     362  if (eno != 0)
     363    return RTEMS_UNSATISFIED;
     364
     365  return RTEMS_SUCCESSFUL;
     366#else
     367  return rtems_semaphore_create(
     368    name,
     369    1,
     370    RTEMS_BDBUF_CACHE_LOCK_ATTRIBS,
     371    0,
     372    lock
     373  );
     374#endif
     375}
     376
     377static void
     378rtems_bdbuf_lock_delete (rtems_bdbuf_lock_type *lock)
     379{
     380#if defined(RTEMS_BDBUF_USE_PTHREAD)
     381  pthread_mutex_destroy (lock);
     382#else
     383  rtems_semaphore_delete (*lock);
     384#endif
     385}
     386
     387static rtems_status_code
     388rtems_bdbuf_waiter_create (rtems_name name, rtems_bdbuf_waiters *waiter)
     389{
     390#if defined(RTEMS_BDBUF_USE_PTHREAD)
     391  int eno = pthread_cond_init (&waiter->cond_var, NULL);
     392  if (eno != 0)
     393    return RTEMS_UNSATISFIED;
     394
     395  return RTEMS_SUCCESSFUL;
     396#else
     397  return rtems_semaphore_create(
     398    name,
     399    0,
     400    RTEMS_BDBUF_CACHE_WAITER_ATTRIBS,
     401    0,
     402    &waiter->sema
     403  );
     404#endif
     405}
     406
     407static void
     408rtems_bdbuf_waiter_delete (rtems_bdbuf_waiters *waiter)
     409{
     410#if defined(RTEMS_BDBUF_USE_PTHREAD)
     411  pthread_cond_destroy (&waiter->cond_var);
     412#else
     413  rtems_semaphore_delete (waiter->sema);
     414#endif
    320415}
    321416
     
    836931 */
    837932static void
    838 rtems_bdbuf_lock (rtems_id lock, uint32_t fatal_error_code)
    839 {
    840   rtems_status_code sc = rtems_semaphore_obtain (lock,
     933rtems_bdbuf_lock (rtems_bdbuf_lock_type *lock, uint32_t fatal_error_code)
     934{
     935#if defined(RTEMS_BDBUF_USE_PTHREAD)
     936  int eno = pthread_mutex_lock (lock);
     937  if (eno != 0)
     938    rtems_bdbuf_fatal (fatal_error_code);
     939#else
     940  rtems_status_code sc = rtems_semaphore_obtain (*lock,
    841941                                                 RTEMS_WAIT,
    842942                                                 RTEMS_NO_TIMEOUT);
    843943  if (sc != RTEMS_SUCCESSFUL)
    844944    rtems_bdbuf_fatal (fatal_error_code);
     945#endif
    845946}
    846947
     
    852953 */
    853954static void
    854 rtems_bdbuf_unlock (rtems_id lock, uint32_t fatal_error_code)
    855 {
    856   rtems_status_code sc = rtems_semaphore_release (lock);
     955rtems_bdbuf_unlock (rtems_bdbuf_lock_type *lock, uint32_t fatal_error_code)
     956{
     957#if defined(RTEMS_BDBUF_USE_PTHREAD)
     958  int eno = pthread_mutex_unlock (lock);
     959  if (eno != 0)
     960    rtems_bdbuf_fatal (fatal_error_code);
     961#else
     962  rtems_status_code sc = rtems_semaphore_release (*lock);
    857963  if (sc != RTEMS_SUCCESSFUL)
    858964    rtems_bdbuf_fatal (fatal_error_code);
     965#endif
    859966}
    860967
     
    865972rtems_bdbuf_lock_cache (void)
    866973{
    867   rtems_bdbuf_lock (bdbuf_cache.lock, RTEMS_BDBUF_FATAL_CACHE_LOCK);
     974  rtems_bdbuf_lock (&bdbuf_cache.lock, RTEMS_BDBUF_FATAL_CACHE_LOCK);
    868975}
    869976
     
    874981rtems_bdbuf_unlock_cache (void)
    875982{
    876   rtems_bdbuf_unlock (bdbuf_cache.lock, RTEMS_BDBUF_FATAL_CACHE_UNLOCK);
     983  rtems_bdbuf_unlock (&bdbuf_cache.lock, RTEMS_BDBUF_FATAL_CACHE_UNLOCK);
    877984}
    878985
     
    883990rtems_bdbuf_lock_sync (void)
    884991{
    885   rtems_bdbuf_lock (bdbuf_cache.sync_lock, RTEMS_BDBUF_FATAL_SYNC_LOCK);
     992  rtems_bdbuf_lock (&bdbuf_cache.sync_lock, RTEMS_BDBUF_FATAL_SYNC_LOCK);
    886993}
    887994
     
    892999rtems_bdbuf_unlock_sync (void)
    8931000{
    894   rtems_bdbuf_unlock (bdbuf_cache.sync_lock,
     1001  rtems_bdbuf_unlock (&bdbuf_cache.sync_lock,
    8951002                      RTEMS_BDBUF_FATAL_SYNC_UNLOCK);
    8961003}
     
    9081015}
    9091016
     1017#if !defined(RTEMS_BDBUF_USE_PTHREAD)
    9101018static rtems_mode
    9111019rtems_bdbuf_disable_preemption (void)
     
    9301038    rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_PREEMPT_RST);
    9311039}
     1040#endif
    9321041
    9331042/**
     
    9491058rtems_bdbuf_anonymous_wait (rtems_bdbuf_waiters *waiters)
    9501059{
    951   rtems_status_code sc;
    952   rtems_mode        prev_mode;
    953 
    9541060  /*
    9551061   * Indicate we are waiting.
     
    9571063  ++waiters->count;
    9581064
    959   /*
    960    * Disable preemption then unlock the cache and block.  There is no POSIX
    961    * condition variable in the core API so this is a work around.
    962    *
    963    * The issue is a task could preempt after the cache is unlocked because it is
    964    * blocking or just hits that window, and before this task has blocked on the
    965    * semaphore. If the preempting task flushes the queue this task will not see
    966    * the flush and may block for ever or until another transaction flushes this
    967    * semaphore.
    968    */
    969   prev_mode = rtems_bdbuf_disable_preemption ();
    970 
    971   /*
    972    * Unlock the cache, wait, and lock the cache when we return.
    973    */
    974   rtems_bdbuf_unlock_cache ();
    975 
    976   sc = rtems_semaphore_obtain (waiters->sema, RTEMS_WAIT, RTEMS_BDBUF_WAIT_TIMEOUT);
    977 
    978   if (sc == RTEMS_TIMEOUT)
    979     rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAIT_TO);
    980 
    981   if (sc != RTEMS_UNSATISFIED)
    982     rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAIT_2);
    983 
    984   rtems_bdbuf_lock_cache ();
    985 
    986   rtems_bdbuf_restore_preemption (prev_mode);
     1065#if defined(RTEMS_BDBUF_USE_PTHREAD)
     1066  {
     1067    int eno = pthread_cond_wait (&waiters->cond_var, &bdbuf_cache.lock);
     1068    if (eno != 0)
     1069      rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CV_WAIT);
     1070  }
     1071#else
     1072  {
     1073    rtems_status_code sc;
     1074    rtems_mode        prev_mode;
     1075
     1076    /*
     1077     * Disable preemption then unlock the cache and block.  There is no POSIX
     1078     * condition variable in the core API so this is a work around.
     1079     *
     1080     * The issue is a task could preempt after the cache is unlocked because it is
     1081     * blocking or just hits that window, and before this task has blocked on the
     1082     * semaphore. If the preempting task flushes the queue this task will not see
     1083     * the flush and may block for ever or until another transaction flushes this
     1084     * semaphore.
     1085     */
     1086    prev_mode = rtems_bdbuf_disable_preemption();
     1087
     1088    /*
     1089     * Unlock the cache, wait, and lock the cache when we return.
     1090     */
     1091    rtems_bdbuf_unlock_cache ();
     1092
     1093    sc = rtems_semaphore_obtain (waiters->sema, RTEMS_WAIT, RTEMS_BDBUF_WAIT_TIMEOUT);
     1094
     1095    if (sc == RTEMS_TIMEOUT)
     1096      rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAIT_TO);
     1097
     1098    if (sc != RTEMS_UNSATISFIED)
     1099      rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAIT_2);
     1100
     1101    rtems_bdbuf_lock_cache ();
     1102
     1103    rtems_bdbuf_restore_preemption (prev_mode);
     1104  }
     1105#endif
    9871106
    9881107  --waiters->count;
     
    10041123 */
    10051124static void
    1006 rtems_bdbuf_wake (const rtems_bdbuf_waiters *waiters)
    1007 {
    1008   rtems_status_code sc = RTEMS_SUCCESSFUL;
    1009 
     1125rtems_bdbuf_wake (rtems_bdbuf_waiters *waiters)
     1126{
    10101127  if (waiters->count > 0)
    10111128  {
    1012     sc = rtems_semaphore_flush (waiters->sema);
     1129#if defined(RTEMS_BDBUF_USE_PTHREAD)
     1130    int eno = pthread_cond_broadcast (&waiters->cond_var);
     1131    if (eno != 0)
     1132      rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CV_BROADCAST);
     1133#else
     1134    rtems_status_code sc = rtems_semaphore_flush (waiters->sema);
    10131135    if (sc != RTEMS_SUCCESSFUL)
    10141136      rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_CACHE_WAKE);
     1137#endif
    10151138  }
    10161139}
     
    14341557   * Create the locks for the cache.
    14351558   */
    1436   sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 'l'),
    1437                                1, RTEMS_BDBUF_CACHE_LOCK_ATTRIBS, 0,
    1438                                &bdbuf_cache.lock);
     1559
     1560  sc = rtems_bdbuf_lock_create (rtems_build_name ('B', 'D', 'C', 'l'),
     1561                                &bdbuf_cache.lock);
    14391562  if (sc != RTEMS_SUCCESSFUL)
    14401563    goto error;
     
    14421565  rtems_bdbuf_lock_cache ();
    14431566
    1444   sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 's'),
    1445                                1, RTEMS_BDBUF_CACHE_LOCK_ATTRIBS, 0,
    1446                                &bdbuf_cache.sync_lock);
     1567  sc = rtems_bdbuf_lock_create (rtems_build_name ('B', 'D', 'C', 's'),
     1568                                &bdbuf_cache.sync_lock);
    14471569  if (sc != RTEMS_SUCCESSFUL)
    14481570    goto error;
    14491571
    1450   sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 'a'),
    1451                                0, RTEMS_BDBUF_CACHE_WAITER_ATTRIBS, 0,
    1452                                &bdbuf_cache.access_waiters.sema);
     1572  sc = rtems_bdbuf_waiter_create (rtems_build_name ('B', 'D', 'C', 'a'),
     1573                                  &bdbuf_cache.access_waiters);
    14531574  if (sc != RTEMS_SUCCESSFUL)
    14541575    goto error;
    14551576
    1456   sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 't'),
    1457                                0, RTEMS_BDBUF_CACHE_WAITER_ATTRIBS, 0,
    1458                                &bdbuf_cache.transfer_waiters.sema);
     1577  sc = rtems_bdbuf_waiter_create (rtems_build_name ('B', 'D', 'C', 't'),
     1578                                  &bdbuf_cache.transfer_waiters);
    14591579  if (sc != RTEMS_SUCCESSFUL)
    14601580    goto error;
    14611581
    1462   sc = rtems_semaphore_create (rtems_build_name ('B', 'D', 'C', 'b'),
    1463                                0, RTEMS_BDBUF_CACHE_WAITER_ATTRIBS, 0,
    1464                                &bdbuf_cache.buffer_waiters.sema);
     1582  sc = rtems_bdbuf_waiter_create (rtems_build_name ('B', 'D', 'C', 'b'),
     1583                                  &bdbuf_cache.buffer_waiters);
    14651584  if (sc != RTEMS_SUCCESSFUL)
    14661585    goto error;
     
    16211740  free (bdbuf_cache.swapout_workers);
    16221741
    1623   rtems_semaphore_delete (bdbuf_cache.buffer_waiters.sema);
    1624   rtems_semaphore_delete (bdbuf_cache.access_waiters.sema);
    1625   rtems_semaphore_delete (bdbuf_cache.transfer_waiters.sema);
    1626   rtems_semaphore_delete (bdbuf_cache.sync_lock);
     1742  rtems_bdbuf_waiter_delete (&bdbuf_cache.buffer_waiters);
     1743  rtems_bdbuf_waiter_delete (&bdbuf_cache.access_waiters);
     1744  rtems_bdbuf_waiter_delete (&bdbuf_cache.transfer_waiters);
     1745  rtems_bdbuf_lock_delete (&bdbuf_cache.sync_lock);
    16271746
    16281747  if (bdbuf_cache.lock != 0)
    16291748  {
    16301749    rtems_bdbuf_unlock_cache ();
    1631     rtems_semaphore_delete (bdbuf_cache.lock);
     1750    rtems_bdbuf_lock_delete (&bdbuf_cache.lock);
    16321751  }
    16331752
  • cpukit/sapi/include/confdefs.h

    rd8ac087 r1fc2e960  
    15211521    0 : CONFIGURE_BDBUF_TASK_STACK_SIZE - CONFIGURE_MINIMUM_TASK_STACK_SIZE))
    15221522
    1523   /*
    1524    *  Semaphores:
    1525    *    o disk lock
    1526    *    o bdbuf lock
    1527    *    o bdbuf sync lock
    1528    *    o bdbuf access condition
    1529    *    o bdbuf transfer condition
    1530    *    o bdbuf buffer condition
    1531    */
    1532   #define CONFIGURE_LIBBLOCK_SEMAPHORES 6
     1523  #ifdef RTEMS_BDBUF_USE_PTHREAD
     1524    /*
     1525     * Semaphores:
     1526     *   o disk lock
     1527     */
     1528    #define CONFIGURE_LIBBLOCK_SEMAPHORES 1
     1529
     1530    /*
     1531     * POSIX Mutexes:
     1532     *  o bdbuf lock
     1533     *  o bdbuf sync lock
     1534     */
     1535    #define CONFIGURE_LIBBLOCK_POSIX_MUTEXES 2
     1536
     1537    /*
     1538     * POSIX Condition Variables:
     1539     *  o bdbuf access condition
     1540     *  o bdbuf transfer condition
     1541     *  o bdbuf buffer condition
     1542     */
     1543    #define CONFIGURE_LIBBLOCK_POSIX_CONDITION_VARIABLES 3
     1544  #else
     1545    /*
     1546     * Semaphores:
     1547     *   o disk lock
     1548     *   o bdbuf lock
     1549     *   o bdbuf sync lock
     1550     *   o bdbuf access condition
     1551     *   o bdbuf transfer condition
     1552     *   o bdbuf buffer condition
     1553     */
     1554    #define CONFIGURE_LIBBLOCK_SEMAPHORES 6
     1555
     1556    #define CONFIGURE_LIBBLOCK_POSIX_MUTEXES 0
     1557    #define CONFIGURE_LIBBLOCK_POSIX_CONDITION_VARIABLES 0
     1558  #endif
    15331559
    15341560  #if defined(CONFIGURE_HAS_OWN_BDBUF_TABLE) || \
     
    15411567  #define CONFIGURE_LIBBLOCK_TASK_EXTRA_STACKS 0
    15421568  #define CONFIGURE_LIBBLOCK_SEMAPHORES 0
     1569  #define CONFIGURE_LIBBLOCK_POSIX_MUTEXES 0
     1570  #define CONFIGURE_LIBBLOCK_POSIX_CONDITION_VARIABLES 0
    15431571#endif /* CONFIGURE_APPLICATION_NEEDS_LIBBLOCK */
    15441572
     
    22102238  #define CONFIGURE_POSIX_MUTEXES \
    22112239    (CONFIGURE_MAXIMUM_POSIX_MUTEXES + \
     2240      CONFIGURE_LIBBLOCK_POSIX_MUTEXES + \
    22122241      CONFIGURE_GNAT_MUTEXES + \
    22132242      CONFIGURE_MAXIMUM_ADA_TASKS + \
     
    22212250  #define CONFIGURE_POSIX_CONDITION_VARIABLES \
    22222251    (CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES + \
     2252      CONFIGURE_LIBBLOCK_POSIX_CONDITION_VARIABLES + \
    22232253      CONFIGURE_MAXIMUM_ADA_TASKS + \
    22242254      CONFIGURE_MAXIMUM_FAKE_ADA_TASKS + \
Note: See TracChangeset for help on using the changeset viewer.