Changeset fc027be in rtems


Ignore:
Timestamp:
Jul 26, 2016, 8:34:21 AM (3 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.10
Children:
f9126f6
Parents:
a5c1b2b
git-author:
Sebastian Huber <sebastian.huber@…> (07/26/16 08:34:21)
git-committer:
Gedare Bloom <gedare@…> (03/23/18 15:33:59)
Message:

sptests/spmutex01: refactor and add deadlock test

Location:
testsuites/sptests/spmutex01
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • testsuites/sptests/spmutex01/init.c

    ra5c1b2b rfc027be  
    1717#endif
    1818
     19#include <threads.h>
     20#include <setjmp.h>
     21
     22#include <rtems.h>
     23#include <rtems/libcsupport.h>
     24
     25#ifdef RTEMS_POSIX_API
     26#include <errno.h>
     27#include <pthread.h>
     28#endif
     29
    1930#include "tmacros.h"
    2031
     
    2233
    2334#define TASK_COUNT 5
     35
     36#define MTX_COUNT 3
    2437
    2538typedef enum {
    2639  REQ_WAKE_UP_MASTER = RTEMS_EVENT_0,
    2740  REQ_WAKE_UP_HELPER = RTEMS_EVENT_1,
    28   REQ_MTX_OBTAIN = RTEMS_EVENT_2,
    29   REQ_MTX_RELEASE = RTEMS_EVENT_3
     41  REQ_MTX_0_OBTAIN = RTEMS_EVENT_2,
     42  REQ_MTX_0_RELEASE = RTEMS_EVENT_3,
     43  REQ_MTX_1_OBTAIN = RTEMS_EVENT_4,
     44  REQ_MTX_1_RELEASE = RTEMS_EVENT_5,
     45  REQ_MTX_2_OBTAIN = RTEMS_EVENT_6,
     46  REQ_MTX_2_RELEASE = RTEMS_EVENT_7,
     47  REQ_MTX_C11_OBTAIN = RTEMS_EVENT_8,
     48  REQ_MTX_C11_RELEASE = RTEMS_EVENT_9,
     49  REQ_MTX_POSIX_OBTAIN = RTEMS_EVENT_10,
     50  REQ_MTX_POSIX_RELEASE = RTEMS_EVENT_11
    3051} request_id;
    3152
    3253typedef enum {
     54  M,
    3355  A_1,
    3456  A_2_0,
    3557  A_2_1,
    36   M,
    3758  H,
    3859  NONE
    3960} task_id;
    4061
     62typedef enum {
     63  MTX_0,
     64  MTX_1,
     65  MTX_2
     66} mutex_id;
     67
    4168typedef struct {
    42   rtems_id mtx;
     69  rtems_id mtx[MTX_COUNT];
     70  mtx_t mtx_c11;
     71#ifdef RTEMS_POSIX_API
     72  pthread_mutex_t mtx_posix;
     73#endif
    4374  rtems_id tasks[TASK_COUNT];
    4475  int generation[TASK_COUNT];
    4576  int expected_generation[TASK_COUNT];
     77  jmp_buf deadlock_return_context;
    4678} test_context;
    4779
     
    110142}
    111143
    112 static void obtain(test_context *ctx)
    113 {
    114   rtems_status_code sc;
    115 
    116   sc = rtems_semaphore_obtain(ctx->mtx, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     144static void obtain(test_context *ctx, mutex_id id)
     145{
     146  rtems_status_code sc;
     147
     148  sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    117149  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
    118150}
    119151
    120 static void release(test_context *ctx)
    121 {
    122   rtems_status_code sc;
    123 
    124   sc = rtems_semaphore_release(ctx->mtx);
     152static void deadlock_obtain(test_context *ctx, mutex_id id)
     153{
     154  rtems_status_code sc;
     155
     156  sc = rtems_semaphore_obtain(ctx->mtx[id], RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     157  rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
     158}
     159
     160static void release(test_context *ctx, mutex_id id)
     161{
     162  rtems_status_code sc;
     163
     164  sc = rtems_semaphore_release(ctx->mtx[id]);
    125165  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
    126166}
     167
     168static void obtain_c11(test_context *ctx)
     169{
     170  int status;
     171
     172  status = mtx_lock(&ctx->mtx_c11);
     173  rtems_test_assert(status == thrd_success);
     174}
     175
     176static void deadlock_obtain_c11(test_context *ctx)
     177{
     178  if (setjmp(ctx->deadlock_return_context) == 0) {
     179    (void) mtx_lock(&ctx->mtx_c11);
     180  }
     181}
     182
     183static void release_c11(test_context *ctx)
     184{
     185  int status;
     186
     187  status = mtx_unlock(&ctx->mtx_c11);
     188  rtems_test_assert(status == thrd_success);
     189}
     190
     191#ifdef RTEMS_POSIX_API
     192static void obtain_posix(test_context *ctx)
     193{
     194  int error;
     195
     196  error = pthread_mutex_lock(&ctx->mtx_posix);
     197  rtems_test_assert(error == 0);
     198}
     199
     200static void deadlock_obtain_posix(test_context *ctx)
     201{
     202  int error;
     203
     204  error = pthread_mutex_lock(&ctx->mtx_posix);
     205  rtems_test_assert(error == EDEADLK);
     206}
     207
     208static void release_posix(test_context *ctx)
     209{
     210  int error;
     211
     212  error = pthread_mutex_unlock(&ctx->mtx_posix);
     213  rtems_test_assert(error == 0);
     214}
     215#endif
    127216
    128217static void check_generations(test_context *ctx, task_id a, task_id b)
     
    180269    rtems_event_set events = wait_for_events();
    181270
    182     if ((events & REQ_MTX_OBTAIN) != 0) {
    183       obtain(ctx);
    184       ++ctx->generation[id];
    185     }
    186 
    187     if ((events & REQ_MTX_RELEASE) != 0) {
    188       release(ctx);
    189       ++ctx->generation[id];
    190     }
    191   }
    192 }
    193 
    194 static void test(void)
    195 {
    196   test_context *ctx = &test_instance;
    197   rtems_status_code sc;
     271    if ((events & REQ_MTX_0_OBTAIN) != 0) {
     272      obtain(ctx, MTX_0);
     273      ++ctx->generation[id];
     274    }
     275
     276    if ((events & REQ_MTX_0_RELEASE) != 0) {
     277      release(ctx, MTX_0);
     278      ++ctx->generation[id];
     279    }
     280
     281    if ((events & REQ_MTX_1_OBTAIN) != 0) {
     282      obtain(ctx, MTX_1);
     283      ++ctx->generation[id];
     284    }
     285
     286    if ((events & REQ_MTX_1_RELEASE) != 0) {
     287      release(ctx, MTX_1);
     288      ++ctx->generation[id];
     289    }
     290
     291    if ((events & REQ_MTX_2_OBTAIN) != 0) {
     292      obtain(ctx, MTX_2);
     293      ++ctx->generation[id];
     294    }
     295
     296    if ((events & REQ_MTX_2_RELEASE) != 0) {
     297      release(ctx, MTX_2);
     298      ++ctx->generation[id];
     299    }
     300
     301    if ((events & REQ_MTX_C11_OBTAIN) != 0) {
     302      obtain_c11(ctx);
     303      ++ctx->generation[id];
     304    }
     305
     306    if ((events & REQ_MTX_C11_RELEASE) != 0) {
     307      release_c11(ctx);
     308      ++ctx->generation[id];
     309    }
     310
     311#ifdef RTEMS_POSIX_API
     312    if ((events & REQ_MTX_POSIX_OBTAIN) != 0) {
     313      obtain_posix(ctx);
     314      ++ctx->generation[id];
     315    }
     316
     317    if ((events & REQ_MTX_POSIX_RELEASE) != 0) {
     318      release_posix(ctx);
     319      ++ctx->generation[id];
     320    }
     321#endif
     322  }
     323}
     324
     325static void set_up(test_context *ctx)
     326{
     327  rtems_status_code sc;
     328  int status;
     329  size_t i;
    198330
    199331  ctx->tasks[M] = rtems_task_self();
     
    203335  start_task(ctx, H, helper, 3);
    204336
    205   sc = rtems_semaphore_create(
    206     rtems_build_name(' ', 'M', 'T', 'X'),
    207     1,
    208     RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
    209     0,
    210     &ctx->mtx
    211   );
    212   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
    213 
    214   obtain(ctx);
    215   request(ctx, A_1, REQ_MTX_OBTAIN);
     337  for (i = 0; i < MTX_COUNT; ++i) {
     338    sc = rtems_semaphore_create(
     339      rtems_build_name(' ', 'M', 'T', 'X'),
     340      1,
     341      RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
     342      0,
     343      &ctx->mtx[i]
     344    );
     345    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     346  }
     347
     348  status = mtx_init(&ctx->mtx_c11, mtx_plain);
     349  rtems_test_assert(status == thrd_success);
     350
     351#ifdef RTEMS_POSIX_API
     352  {
     353    int error;
     354    pthread_mutexattr_t attr;
     355
     356    error = pthread_mutexattr_init(&attr);
     357    rtems_test_assert(error == 0);
     358
     359    error = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
     360    rtems_test_assert(error == 0);
     361
     362    error = pthread_mutex_init(&ctx->mtx_posix, &attr);
     363    rtems_test_assert(error == 0);
     364
     365    error = pthread_mutexattr_destroy(&attr);
     366    rtems_test_assert(error == 0);
     367  }
     368#endif
     369}
     370
     371static void test_inherit(test_context *ctx)
     372{
     373  obtain(ctx, MTX_0);
     374  request(ctx, A_1, REQ_MTX_0_OBTAIN);
    216375  check_generations(ctx, NONE, NONE);
    217376  assert_prio(ctx, M, 1);
    218   release(ctx);
     377  release(ctx, MTX_0);
    219378  check_generations(ctx, A_1, NONE);
    220379  assert_prio(ctx, M, 3);
    221   request(ctx, A_1, REQ_MTX_RELEASE);
    222   check_generations(ctx, A_1, NONE);
    223 
    224   obtain(ctx);
    225   request(ctx, A_2_0, REQ_MTX_OBTAIN);
    226   request(ctx, A_1, REQ_MTX_OBTAIN);
    227   request(ctx, A_2_1, REQ_MTX_OBTAIN);
     380  request(ctx, A_1, REQ_MTX_0_RELEASE);
     381  check_generations(ctx, A_1, NONE);
     382}
     383
     384static void test_inherit_fifo_for_equal_priority(test_context *ctx)
     385{
     386  obtain(ctx, MTX_0);
     387  request(ctx, A_2_0, REQ_MTX_0_OBTAIN);
     388  request(ctx, A_1, REQ_MTX_0_OBTAIN);
     389  request(ctx, A_2_1, REQ_MTX_0_OBTAIN);
    228390  check_generations(ctx, NONE, NONE);
    229391  assert_prio(ctx, M, 1);
    230   release(ctx);
     392  release(ctx, MTX_0);
    231393  check_generations(ctx, A_1, NONE);
    232394  assert_prio(ctx, M, 3);
    233395  assert_prio(ctx, A_1, 1);
    234   request(ctx, A_1, REQ_MTX_RELEASE);
     396  request(ctx, A_1, REQ_MTX_0_RELEASE);
    235397  check_generations(ctx, A_1, A_2_0);
    236   request(ctx, A_2_0, REQ_MTX_RELEASE);
     398  request(ctx, A_2_0, REQ_MTX_0_RELEASE);
    237399  check_generations(ctx, A_2_0, A_2_1);
    238   request(ctx, A_2_1, REQ_MTX_RELEASE);
     400  request(ctx, A_2_1, REQ_MTX_0_RELEASE);
    239401  check_generations(ctx, A_2_1, NONE);
    240402}
    241403
     404static void test_deadlock_two_classic(test_context *ctx)
     405{
     406  obtain(ctx, MTX_0);
     407  request(ctx, A_1, REQ_MTX_1_OBTAIN);
     408  check_generations(ctx, A_1, NONE);
     409  request(ctx, A_1, REQ_MTX_0_OBTAIN);
     410  check_generations(ctx, NONE, NONE);
     411  deadlock_obtain(ctx, MTX_1);
     412  release(ctx, MTX_0);
     413  check_generations(ctx, A_1, NONE);
     414  request(ctx, A_1, REQ_MTX_0_RELEASE);
     415  check_generations(ctx, A_1, NONE);
     416  request(ctx, A_1, REQ_MTX_1_RELEASE);
     417  check_generations(ctx, A_1, NONE);
     418}
     419
     420static void test_deadlock_three_classic(test_context *ctx)
     421{
     422  obtain(ctx, MTX_0);
     423  request(ctx, A_1, REQ_MTX_1_OBTAIN);
     424  check_generations(ctx, A_1, NONE);
     425  request(ctx, A_2_0, REQ_MTX_2_OBTAIN);
     426  check_generations(ctx, A_2_0, NONE);
     427  request(ctx, A_2_0, REQ_MTX_1_OBTAIN);
     428  check_generations(ctx, NONE, NONE);
     429  request(ctx, A_1, REQ_MTX_0_OBTAIN);
     430  check_generations(ctx, NONE, NONE);
     431  deadlock_obtain(ctx, MTX_2);
     432  release(ctx, MTX_0);
     433  check_generations(ctx, A_1, NONE);
     434  request(ctx, A_1, REQ_MTX_0_RELEASE);
     435  check_generations(ctx, A_1, NONE);
     436  request(ctx, A_1, REQ_MTX_1_RELEASE);
     437  check_generations(ctx, A_1, A_2_0);
     438  request(ctx, A_2_0, REQ_MTX_2_RELEASE);
     439  check_generations(ctx, A_2_0, NONE);
     440  request(ctx, A_2_0, REQ_MTX_1_RELEASE);
     441  check_generations(ctx, A_2_0, NONE);
     442}
     443
     444static void test_deadlock_c11_and_classic(test_context *ctx)
     445{
     446  obtain_c11(ctx);
     447  request(ctx, A_1, REQ_MTX_0_OBTAIN);
     448  check_generations(ctx, A_1, NONE);
     449  request(ctx, A_1, REQ_MTX_C11_OBTAIN);
     450  check_generations(ctx, NONE, NONE);
     451  deadlock_obtain(ctx, MTX_0);
     452  release_c11(ctx);
     453  check_generations(ctx, A_1, NONE);
     454  request(ctx, A_1, REQ_MTX_C11_RELEASE);
     455  check_generations(ctx, A_1, NONE);
     456  request(ctx, A_1, REQ_MTX_0_RELEASE);
     457  check_generations(ctx, A_1, NONE);
     458}
     459
     460static void test_deadlock_classic_and_c11(test_context *ctx)
     461{
     462  obtain(ctx, MTX_0);
     463  request(ctx, A_1, REQ_MTX_C11_OBTAIN);
     464  check_generations(ctx, A_1, NONE);
     465  request(ctx, A_1, REQ_MTX_0_OBTAIN);
     466  check_generations(ctx, NONE, NONE);
     467  deadlock_obtain_c11(ctx);
     468  release(ctx, MTX_0);
     469  check_generations(ctx, A_1, NONE);
     470  request(ctx, A_1, REQ_MTX_0_RELEASE);
     471  check_generations(ctx, A_1, NONE);
     472  request(ctx, A_1, REQ_MTX_C11_RELEASE);
     473  check_generations(ctx, A_1, NONE);
     474}
     475
     476static void test_deadlock_posix_and_classic(test_context *ctx)
     477{
     478#ifdef RTEMS_POSIX_API
     479  obtain_posix(ctx);
     480  request(ctx, A_1, REQ_MTX_0_OBTAIN);
     481  check_generations(ctx, A_1, NONE);
     482  request(ctx, A_1, REQ_MTX_POSIX_OBTAIN);
     483  check_generations(ctx, NONE, NONE);
     484  deadlock_obtain(ctx, MTX_0);
     485  release_posix(ctx);
     486  check_generations(ctx, A_1, NONE);
     487  request(ctx, A_1, REQ_MTX_POSIX_RELEASE);
     488  check_generations(ctx, A_1, NONE);
     489  request(ctx, A_1, REQ_MTX_0_RELEASE);
     490  check_generations(ctx, A_1, NONE);
     491#endif
     492}
     493
     494static void test_deadlock_classic_and_posix(test_context *ctx)
     495{
     496#ifdef RTEMS_POSIX_API
     497  obtain(ctx, MTX_0);
     498  request(ctx, A_1, REQ_MTX_POSIX_OBTAIN);
     499  check_generations(ctx, A_1, NONE);
     500  request(ctx, A_1, REQ_MTX_0_OBTAIN);
     501  check_generations(ctx, NONE, NONE);
     502  deadlock_obtain_posix(ctx);
     503  release(ctx, MTX_0);
     504  check_generations(ctx, A_1, NONE);
     505  request(ctx, A_1, REQ_MTX_0_RELEASE);
     506  check_generations(ctx, A_1, NONE);
     507  request(ctx, A_1, REQ_MTX_POSIX_RELEASE);
     508  check_generations(ctx, A_1, NONE);
     509#endif
     510}
     511
     512static void tear_down(test_context *ctx)
     513{
     514  rtems_status_code sc;
     515  size_t i;
     516
     517  for (i = 1; i < TASK_COUNT; ++i) {
     518    sc = rtems_task_delete(ctx->tasks[i]);
     519    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     520  }
     521
     522  for (i = 0; i < MTX_COUNT; ++i) {
     523    sc = rtems_semaphore_delete(ctx->mtx[i]);
     524    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     525  }
     526
     527  mtx_destroy(&ctx->mtx_c11);
     528
     529#ifdef RTEMS_POSIX_API
     530  {
     531    int error;
     532
     533    error = pthread_mutex_destroy(&ctx->mtx_posix);
     534    rtems_test_assert(error == 0);
     535  }
     536#endif
     537}
     538
    242539static void Init(rtems_task_argument arg)
    243540{
     541  test_context *ctx = &test_instance;
     542  rtems_resource_snapshot snapshot;
     543
    244544  TEST_BEGIN();
    245 
    246   test();
    247 
     545  rtems_resource_snapshot_take(&snapshot);
     546
     547  set_up(ctx);
     548  test_inherit(ctx);
     549  test_inherit_fifo_for_equal_priority(ctx);
     550  test_deadlock_two_classic(ctx);
     551  test_deadlock_three_classic(ctx);
     552  test_deadlock_c11_and_classic(ctx);
     553  test_deadlock_classic_and_c11(ctx);
     554  test_deadlock_posix_and_classic(ctx);
     555  test_deadlock_classic_and_posix(ctx);
     556  tear_down(ctx);
     557
     558  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
    248559  TEST_END();
    249560  rtems_test_exit(0);
    250561}
    251562
     563static void fatal_extension(
     564  rtems_fatal_source source,
     565  bool is_internal,
     566  rtems_fatal_code error
     567)
     568{
     569
     570  if (
     571    source == INTERNAL_ERROR_CORE
     572      && !is_internal
     573      && error == INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK
     574  ) {
     575    test_context *ctx = &test_instance;
     576
     577    longjmp(ctx->deadlock_return_context, 1);
     578  }
     579}
     580
    252581#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
    253582#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
     
    255584#define CONFIGURE_MAXIMUM_TASKS TASK_COUNT
    256585
    257 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
    258 
    259 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
     586#define CONFIGURE_MAXIMUM_SEMAPHORES 3
     587
     588#ifdef RTEMS_POSIX_API
     589#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 1
     590#endif
     591
     592#define CONFIGURE_INITIAL_EXTENSIONS \
     593  { .fatal = fatal_extension }, \
     594  RTEMS_TEST_INITIAL_EXTENSION
    260595
    261596#define CONFIGURE_INIT_TASK_PRIORITY 3
Note: See TracChangeset for help on using the changeset viewer.