Ignore:
Timestamp:
Jun 1, 2016, 7:50:44 AM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
5, master
Children:
f807b84
Parents:
6b5df95
git-author:
Sebastian Huber <sebastian.huber@…> (06/01/16 07:50:44)
git-committer:
Sebastian Huber <sebastian.huber@…> (06/01/16 07:53:43)
Message:

smptests/smpatomic01: New test cases

Demonstrate that a read-modify-write atomic operation may be necessary
on some archtitectures to observe the latest value written.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • testsuites/smptests/smpatomic01/init.c

    r6b5df95 ra9cc6a84  
    11/*
    2  * Copyright (c) 2013-2015 embedded brains GmbH.  All rights reserved.
     2 * Copyright (c) 2013, 2016 embedded brains GmbH.  All rights reserved.
    33 *
    44 *  embedded brains GmbH
     
    2020
    2121#include <rtems/score/atomic.h>
     22#include <rtems/score/smpbarrier.h>
    2223#include <rtems.h>
     24#include <rtems/bsd.h>
    2325#include <rtems/test.h>
    2426#include <limits.h>
     
    2830
    2931const char rtems_test_name[] = "SMPATOMIC 1";
     32
     33#define MS_PER_TICK 10
    3034
    3135#define MASTER_PRIORITY 1
     
    4347  unsigned long second_value;
    4448  Atomic_Flag global_flag;
     49  SMP_barrier_Control barrier;
     50  SMP_barrier_State barrier_state[CPU_COUNT];
     51  sbintime_t load_trigger_time;
     52  sbintime_t load_change_time[CPU_COUNT];
     53  int load_count[CPU_COUNT];
     54  sbintime_t rmw_trigger_time;
     55  sbintime_t rmw_change_time[CPU_COUNT];
     56  int rmw_count[CPU_COUNT];
    4557} smpatomic01_context;
    4658
     
    409421    ctx->second_value
    410422  );
     423}
     424
     425static rtems_interval test_atomic_store_load_rmw_init(
     426  rtems_test_parallel_context *base,
     427  void *arg,
     428  size_t active_workers
     429)
     430{
     431  smpatomic01_context *ctx = (smpatomic01_context *) base;
     432  size_t i;
     433
     434  _Atomic_Init_ulong(&ctx->atomic_value, 0);
     435
     436  _SMP_barrier_Control_initialize(&ctx->barrier);
     437
     438  for (i = 0; i < active_workers; ++i) {
     439    _SMP_barrier_State_initialize(&ctx->barrier_state[i]);
     440  }
     441
     442  return 0;
     443}
     444
     445static sbintime_t now(void)
     446{
     447  struct bintime bt;
     448
     449  rtems_bsd_binuptime(&bt);
     450  return bttosbt(bt);
     451}
     452
     453static void test_atomic_store_load_rmw_body(
     454  rtems_test_parallel_context *base,
     455  void *arg,
     456  size_t active_workers,
     457  size_t worker_index
     458)
     459{
     460  smpatomic01_context *ctx = (smpatomic01_context *) base;
     461  uint32_t cpu_self_index;
     462  sbintime_t t;
     463  int counter;
     464
     465  if (rtems_test_parallel_is_master_worker(worker_index)) {
     466    rtems_status_code sc;
     467
     468    sc = rtems_task_wake_after(1);
     469    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
     470
     471    t = now();
     472    t += (MS_PER_TICK / 2) * SBT_1MS;
     473    ctx->load_trigger_time = t;
     474    t += MS_PER_TICK * SBT_1MS;
     475    ctx->rmw_trigger_time = t;
     476  }
     477
     478  _Atomic_Fence(ATOMIC_ORDER_SEQ_CST);
     479
     480  _SMP_barrier_Wait(
     481    &ctx->barrier,
     482    &ctx->barrier_state[worker_index],
     483    active_workers
     484  );
     485
     486  /*
     487   * Use the physical processor index, to observe timing differences introduced
     488   * by the system topology.
     489   */
     490  cpu_self_index = rtems_get_current_processor();
     491
     492  /* Store release and load acquire test case */
     493
     494  counter = 0;
     495  t = ctx->load_trigger_time;
     496
     497  while (now() < t) {
     498    /* Wait */
     499  }
     500
     501  if (cpu_self_index == 0) {
     502    _Atomic_Store_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELEASE);
     503  } else {
     504    while (_Atomic_Load_ulong(&ctx->atomic_value, ATOMIC_ORDER_ACQUIRE) == 0) {
     505      ++counter;
     506    }
     507  }
     508
     509  ctx->load_change_time[cpu_self_index] = now();
     510  ctx->load_count[cpu_self_index] = counter;
     511
     512  /* Read-modify-write test case */
     513
     514  if (cpu_self_index == 0) {
     515    _Atomic_Store_ulong(&ctx->atomic_value, 0, ATOMIC_ORDER_RELAXED);
     516  }
     517
     518  counter = 0;
     519  t = ctx->rmw_trigger_time;
     520
     521  while (now() < t) {
     522    /* Wait */
     523  }
     524
     525  if (cpu_self_index == 0) {
     526    _Atomic_Store_ulong(&ctx->atomic_value, 1, ATOMIC_ORDER_RELAXED);
     527  } else {
     528    while (
     529      (_Atomic_Fetch_or_ulong(&ctx->atomic_value, 2, ATOMIC_ORDER_RELAXED) & 1)
     530        == 0
     531    ) {
     532      ++counter;
     533    }
     534  }
     535
     536  ctx->rmw_change_time[cpu_self_index] = now();
     537  ctx->rmw_count[cpu_self_index] = counter;
     538}
     539
     540static void test_atomic_store_load_rmw_fini(
     541  rtems_test_parallel_context *base,
     542  void *arg,
     543  size_t active_workers
     544)
     545{
     546  smpatomic01_context *ctx = (smpatomic01_context *) base;
     547  size_t i;
     548  struct bintime bt;
     549  struct timespec ts;
     550
     551  printf("=== atomic store release and load acquire test case ===\n");
     552
     553  for (i = 0; i < active_workers; ++i) {
     554    bt = sbttobt(ctx->load_change_time[i] - ctx->load_trigger_time);
     555    bintime2timespec(&bt, &ts);
     556    printf(
     557      "processor %zu delta %lins, load count %i\n",
     558      i,
     559      ts.tv_nsec,
     560      ctx->load_count[i]
     561    );
     562  }
     563
     564  printf("=== atomic read-modify-write test case ===\n");
     565
     566  for (i = 0; i < active_workers; ++i) {
     567    bt = sbttobt(ctx->rmw_change_time[i] - ctx->rmw_trigger_time);
     568    bintime2timespec(&bt, &ts);
     569    printf(
     570      "processor %zu delta %lins, read-modify-write count %i\n",
     571      i,
     572      ts.tv_nsec,
     573      ctx->rmw_count[i]
     574    );
     575  }
    411576}
    412577
     
    436601    .body = test_atomic_fence_body,
    437602    .fini = test_atomic_fence_fini
    438   },
     603  }, {
     604    .init = test_atomic_store_load_rmw_init,
     605    .body = test_atomic_store_load_rmw_body,
     606    .fini = test_atomic_store_load_rmw_fini
     607  }
    439608};
    440609
     
    472641#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
    473642
     643#define CONFIGURE_MICROSECONDS_PER_TICK (MS_PER_TICK * 1000)
     644
    474645#define CONFIGURE_SMP_APPLICATION
    475646
Note: See TracChangeset for help on using the changeset viewer.