LCOV - code coverage report
Current view: top level - spdk/test/thread/lock - spdk_lock.c (source / functions) Hit Total Coverage
Test: Combined Lines: 203 221 91.9 %
Date: 2024-08-11 15:22:23 Functions: 21 21 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 79 167 47.3 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "spdk/stdinc.h"
       6                 :            : 
       7                 :            : #include "spdk/env.h"
       8                 :            : #include "spdk/event.h"
       9                 :            : #include "spdk/string.h"
      10                 :            : #include "spdk/thread.h"
      11                 :            : #include "spdk/util.h"
      12                 :            : #include "spdk_internal/thread.h"
      13                 :            : #include "spdk/barrier.h"
      14                 :            : 
      15                 :            : #include "thread/thread.c"
      16                 :            : 
      17                 :            : /*
      18                 :            :  * Used by multiple tests
      19                 :            :  */
      20                 :            : 
      21                 :            : typedef void (*test_setup_fn)(void);
      22                 :            : 
      23                 :            : struct test {
      24                 :            :         /* Initialized in g_tests array */
      25                 :            :         const char              *name;
      26                 :            :         uint32_t                thread_count;
      27                 :            :         test_setup_fn           setup_fn;
      28                 :            :         spdk_poller_fn          end_fn;
      29                 :            :         uint32_t                poller_thread_number;
      30                 :            :         /* State set while a test is running */
      31                 :            :         struct spdk_poller      *poller;
      32                 :            : };
      33                 :            : 
      34                 :            : #define ASSERT(cond) do { \
      35                 :            :         if (cond) { \
      36                 :            :                 g_pass++; \
      37                 :            :         } else { \
      38                 :            :                 g_fail++; \
      39                 :            :                 printf("FAIL: %s:%d %s %s\n", __FILE__, __LINE__, __func__, #cond); \
      40                 :            :         } \
      41                 :            : } while (0);
      42                 :            : 
      43                 :            : #define WORKER_COUNT 2
      44                 :            : 
      45                 :            : static uint32_t g_pass;
      46                 :            : static uint32_t g_fail;
      47                 :            : static struct spdk_thread *g_thread[WORKER_COUNT];
      48                 :            : /* Protects g_lock_error_count during updates by spin_abort_fn(). */
      49                 :            : pthread_mutex_t g_lock_lock = PTHREAD_MUTEX_INITIALIZER;
      50                 :            : uint32_t g_lock_error_count[SPIN_ERR_LAST];
      51                 :            : 
      52                 :            : static void launch_next_test(void *arg);
      53                 :            : 
      54                 :            : static bool
      55                 :         24 : check_spin_err_count(enum spin_error *expect)
      56                 :            : {
      57                 :            :         enum spin_error i;
      58                 :         24 :         bool ret = true;
      59                 :            : 
      60         [ +  + ]:        264 :         for (i = SPIN_ERR_NONE; i < SPIN_ERR_LAST; i++) {
      61         [ -  + ]:        240 :                 if (g_lock_error_count[i] != expect[i]) {
      62         [ #  # ]:          0 :                         printf("FAIL: %s: Error %d expected %u, got %u\n", __func__, i,
      63                 :          0 :                                expect[i], g_lock_error_count[i]);
      64                 :          0 :                         ret = false;
      65                 :            :                 }
      66                 :            :         }
      67                 :            : 
      68                 :         24 :         return ret;
      69                 :            : }
      70                 :            : 
      71                 :            : /* A spin_abort_fn() implementation */
      72                 :            : static void
      73                 :         15 : do_not_abort(enum spin_error error)
      74                 :            : {
      75                 :         15 :         struct spdk_thread *thread = spdk_get_thread();
      76                 :            :         uint32_t i;
      77                 :            : 
      78                 :            :         /*
      79                 :            :          * Only count on threads for the current test. Those from a previous test may continue to
      80                 :            :          * rack up errors in their death throes. A real application will abort() or exit() on the
      81                 :            :          * first error.
      82                 :            :          */
      83         [ +  + ]:         45 :         for (i = 0; i < SPDK_COUNTOF(g_thread); i++) {
      84         [ +  + ]:         30 :                 if (g_thread[i] != thread) {
      85                 :         18 :                         continue;
      86                 :            :                 }
      87   [ +  -  -  - ]:         12 :                 ASSERT(error >= SPIN_ERR_NONE && error < SPIN_ERR_LAST);
      88         [ +  - ]:         12 :                 if (error >= SPIN_ERR_NONE && error < SPIN_ERR_LAST) {
      89         [ -  + ]:         12 :                         pthread_mutex_lock(&g_lock_lock);
      90                 :         12 :                         g_lock_error_count[error]++;
      91         [ -  + ]:         12 :                         pthread_mutex_unlock(&g_lock_lock);
      92                 :            :                 }
      93                 :            :         }
      94                 :         15 : }
      95                 :            : 
      96                 :            : /*
      97                 :            :  * contend - make sure that two concurrent threads can take turns at getting the lock
      98                 :            :  */
      99                 :            : 
     100                 :            : struct contend_worker_data {
     101                 :            :         struct spdk_poller *poller;
     102                 :            :         uint64_t wait_time;
     103                 :            :         uint64_t hold_time;
     104                 :            :         uint32_t increments;
     105                 :            :         uint32_t delay_us;
     106                 :            :         uint32_t bit;
     107                 :            : };
     108                 :            : 
     109                 :            : static struct spdk_spinlock g_contend_spinlock;
     110                 :            : static uint32_t g_contend_remaining;
     111                 :            : static uint32_t g_get_lock_times = 50000;
     112                 :            : static struct contend_worker_data g_contend_data[WORKER_COUNT] = {
     113                 :            :         { .bit = 0, .delay_us = 3 },
     114                 :            :         { .bit = 1, .delay_us = 5 },
     115                 :            : };
     116                 :            : 
     117                 :            : static inline uint64_t
     118                 :     600000 : timediff(struct timespec *ts0, struct timespec *ts1)
     119                 :            : {
     120                 :     600000 :         return (ts1->tv_sec - ts0->tv_sec) * SPDK_SEC_TO_NSEC + ts1->tv_nsec - ts0->tv_nsec;
     121                 :            : }
     122                 :            : 
     123                 :            : static uint32_t g_contend_word;
     124                 :            : 
     125                 :            : static int
     126                 :     300000 : contend_worker_fn(void *arg)
     127                 :            : {
     128                 :     300000 :         struct contend_worker_data *data = arg;
     129                 :     300000 :         struct timespec ts0, ts1, ts2;
     130         [ -  + ]:     300000 :         const uint32_t mask = 1 << data->bit;
     131                 :            : 
     132         [ -  + ]:     300000 :         clock_gettime(CLOCK_MONOTONIC, &ts0);
     133                 :     300000 :         spdk_spin_lock(&g_contend_spinlock);
     134         [ -  + ]:     300000 :         clock_gettime(CLOCK_MONOTONIC, &ts1);
     135                 :     300000 :         data->wait_time += timediff(&ts0, &ts1);
     136                 :            : 
     137      [ +  +  - ]:     300000 :         switch (data->increments & 0x1) {
     138                 :     150000 :         case 0:
     139   [ +  -  -  - ]:     150000 :                 ASSERT((g_contend_word & mask) == 0);
     140                 :     150000 :                 g_contend_word |= mask;
     141                 :     150000 :                 break;
     142                 :     150000 :         case 1:
     143   [ +  -  -  - ]:     150000 :                 ASSERT((g_contend_word & mask) == mask);
     144                 :     150000 :                 g_contend_word ^= mask;
     145                 :     150000 :                 break;
     146                 :          0 :         default:
     147                 :          0 :                 abort();
     148                 :            :         }
     149                 :     300000 :         data->increments++;
     150                 :     300000 :         spdk_delay_us(data->delay_us);
     151                 :            : 
     152         [ +  + ]:     300000 :         if (data->increments == g_get_lock_times) {
     153                 :          6 :                 g_contend_remaining--;
     154                 :          6 :                 spdk_poller_unregister(&data->poller);
     155         [ -  + ]:          6 :                 assert(data->poller == NULL);
     156                 :            :         }
     157                 :            : 
     158                 :     300000 :         spdk_spin_unlock(&g_contend_spinlock);
     159         [ -  + ]:     300000 :         clock_gettime(CLOCK_MONOTONIC, &ts2);
     160                 :     300000 :         data->hold_time += timediff(&ts1, &ts2);
     161                 :            : 
     162                 :     300000 :         return SPDK_POLLER_BUSY;
     163                 :            : }
     164                 :            : 
     165                 :            : static void
     166                 :          6 : contend_start_worker_poller(void *ctx)
     167                 :            : {
     168                 :          6 :         struct contend_worker_data *data = ctx;
     169                 :            : 
     170                 :          6 :         data->poller = SPDK_POLLER_REGISTER(contend_worker_fn, data, 0);
     171         [ -  + ]:          6 :         if (data->poller == NULL) {
     172   [ #  #  #  # ]:          0 :                 fprintf(stderr, "Failed to start poller\n");
     173                 :          0 :                 abort();
     174                 :            :         }
     175                 :          6 : }
     176                 :            : 
     177                 :            : static void
     178                 :          3 : contend_setup(void)
     179                 :            : {
     180                 :            :         uint32_t i;
     181                 :            : 
     182         [ -  + ]:          3 :         memset(&g_contend_spinlock, 0, sizeof(g_contend_spinlock));
     183                 :          3 :         spdk_spin_init(&g_contend_spinlock);
     184                 :          3 :         g_contend_remaining = SPDK_COUNTOF(g_contend_data);
     185                 :            : 
     186                 :            :         /* Add a poller to each thread */
     187         [ +  + ]:          9 :         for (i = 0; i < SPDK_COUNTOF(g_contend_data); i++) {
     188                 :          6 :                 spdk_thread_send_msg(g_thread[i], contend_start_worker_poller, &g_contend_data[i]);
     189                 :            :         }
     190                 :          3 : }
     191                 :            : 
     192                 :            : static int
     193                 :      14716 : contend_end(void *arg)
     194                 :            : {
     195                 :      14716 :         struct test *test = arg;
     196                 :      14716 :         enum spin_error expect[SPIN_ERR_LAST] = { 0 };
     197                 :            :         uint32_t i;
     198                 :            : 
     199         [ +  + ]:      14716 :         if (g_contend_remaining != 0) {
     200                 :      14713 :                 return SPDK_POLLER_IDLE;
     201                 :            :         }
     202                 :            : 
     203   [ +  -  -  - ]:          3 :         ASSERT(check_spin_err_count(expect));
     204   [ +  -  -  - ]:          3 :         ASSERT(g_get_lock_times == g_contend_data[0].increments);
     205   [ +  -  -  - ]:          3 :         ASSERT(g_get_lock_times == g_contend_data[1].increments);
     206                 :            : 
     207         [ -  + ]:          3 :         printf("%8s %8s %8s %8s %8s\n", "Worker", "Delay", "Wait us", "Hold us", "Total us");
     208         [ +  + ]:          9 :         for (i = 0; i < SPDK_COUNTOF(g_contend_data); i++) {
     209         [ -  + ]:          6 :                 printf("%8" PRIu32 " %8" PRIu32 " %8" PRIu64 " %8" PRIu64 " %8" PRIu64 "\n",
     210                 :          4 :                        i, g_contend_data[i].delay_us,
     211                 :          6 :                        g_contend_data[i].wait_time / 1000, g_contend_data[i].hold_time / 1000,
     212                 :          6 :                        (g_contend_data[i].wait_time + g_contend_data[i].hold_time) / 1000);
     213                 :            :         }
     214                 :            : 
     215                 :          3 :         spdk_poller_unregister(&test->poller);
     216                 :          3 :         spdk_thread_send_msg(spdk_thread_get_app_thread(), launch_next_test, NULL);
     217                 :          3 :         return SPDK_POLLER_BUSY;
     218                 :            : }
     219                 :            : 
     220                 :            : /*
     221                 :            :  * hold_by_poller - a lock held by a poller when it returns trips an assert
     222                 :            :  */
     223                 :            : 
     224                 :            : static struct spdk_spinlock g_hold_by_poller_spinlock;
     225                 :            : struct spdk_poller *g_hold_by_poller_poller;
     226                 :            : static bool g_hold_by_poller_done;
     227                 :            : 
     228                 :            : static int
     229                 :          6 : hold_by_poller(void *arg)
     230                 :            : {
     231                 :            :         static int times_called = 0;
     232                 :          6 :         enum spin_error expect[SPIN_ERR_LAST] = { 0 };
     233                 :            : 
     234                 :            :         /* This polller will be called three times, trying to take the lock the first two times. */
     235      [ +  +  - ]:          6 :         switch (times_called) {
     236                 :          3 :         case 0:
     237   [ +  -  -  - ]:          3 :                 ASSERT(check_spin_err_count(expect));
     238                 :          3 :                 break;
     239                 :          3 :         case 1:
     240                 :          3 :                 expect[SPIN_ERR_HOLD_DURING_SWITCH] = 1;
     241   [ +  -  -  - ]:          3 :                 ASSERT(check_spin_err_count(expect));
     242                 :          3 :                 break;
     243                 :          0 :         default:
     244                 :          0 :                 abort();
     245                 :            :         }
     246                 :            : 
     247                 :          6 :         spdk_spin_lock(&g_hold_by_poller_spinlock);
     248                 :            : 
     249         [ -  + ]:          6 :         memset(expect, 0, sizeof(expect));
     250      [ +  +  - ]:          6 :         switch (times_called) {
     251                 :          3 :         case 0:
     252   [ +  -  -  - ]:          3 :                 ASSERT(check_spin_err_count(expect));
     253                 :          3 :                 break;
     254                 :          3 :         case 1:
     255                 :          3 :                 expect[SPIN_ERR_DEADLOCK] = 1;
     256                 :          3 :                 expect[SPIN_ERR_HOLD_DURING_SWITCH] = 1;
     257   [ +  -  -  - ]:          3 :                 ASSERT(check_spin_err_count(expect));
     258                 :            :                 /*
     259                 :            :                  * Unlock so that future polls don't continue to increase the "hold during switch"
     260                 :            :                  * count. Without this, the SPIN_ERR_HOLD_DURING_SWITCH is indeterminant.
     261                 :            :                  */
     262                 :          3 :                 spdk_spin_unlock(&g_hold_by_poller_spinlock);
     263   [ +  -  -  - ]:          3 :                 ASSERT(check_spin_err_count(expect));
     264                 :          3 :                 spdk_poller_unregister(&g_hold_by_poller_poller);
     265                 :          3 :                 g_hold_by_poller_done = true;
     266                 :          3 :                 break;
     267                 :          0 :         default:
     268                 :          0 :                 abort();
     269                 :            :         }
     270                 :            : 
     271                 :          6 :         times_called++;
     272                 :            : 
     273                 :          6 :         return SPDK_POLLER_BUSY;
     274                 :            : }
     275                 :            : 
     276                 :            : static void
     277                 :          3 : hold_by_poller_start(void *arg)
     278                 :            : {
     279         [ -  + ]:          3 :         memset(g_lock_error_count, 0, sizeof(g_lock_error_count));
     280                 :          3 :         spdk_spin_init(&g_hold_by_poller_spinlock);
     281                 :            : 
     282                 :          3 :         g_hold_by_poller_poller = spdk_poller_register(hold_by_poller, NULL, 0);
     283                 :          3 : }
     284                 :            : 
     285                 :            : static void
     286                 :          3 : hold_by_poller_setup(void)
     287                 :            : {
     288                 :          3 :         spdk_thread_send_msg(g_thread[0], hold_by_poller_start, NULL);
     289                 :          3 : }
     290                 :            : 
     291                 :            : static int
     292                 :          6 : hold_by_poller_end(void *arg)
     293                 :            : {
     294                 :          6 :         struct test *test = arg;
     295                 :          6 :         enum spin_error expect[SPIN_ERR_LAST] = { 0 };
     296                 :            : 
     297                 :            :         /* Wait for hold_by_poller() to complete its work. */
     298   [ +  +  +  + ]:          6 :         if (!g_hold_by_poller_done) {
     299                 :          3 :                 return SPDK_POLLER_IDLE;
     300                 :            :         }
     301                 :            : 
     302                 :            :         /* Some final checks to be sure all the expected errors were seen */
     303                 :          3 :         expect[SPIN_ERR_DEADLOCK] = 1;
     304                 :          3 :         expect[SPIN_ERR_HOLD_DURING_SWITCH] = 1;
     305   [ +  -  -  - ]:          3 :         ASSERT(check_spin_err_count(expect));
     306                 :            : 
     307                 :            :         /* All done, move on to next test */
     308                 :          3 :         spdk_poller_unregister(&test->poller);
     309                 :          3 :         spdk_thread_send_msg(spdk_thread_get_app_thread(), launch_next_test, NULL);
     310                 :            : 
     311                 :          3 :         return SPDK_POLLER_BUSY;
     312                 :            : }
     313                 :            : 
     314                 :            : /*
     315                 :            :  * hold_by_message - A message sent to a thread retains the lock when it returns.
     316                 :            :  */
     317                 :            : 
     318                 :            : static struct spdk_spinlock g_hold_by_message_spinlock;
     319                 :            : static bool g_hold_by_message_done;
     320                 :            : 
     321                 :            : static void
     322                 :          3 : hold_by_message(void *ctx)
     323                 :            : {
     324                 :          3 :         spdk_spin_lock(&g_hold_by_message_spinlock);
     325                 :            : 
     326                 :          3 :         g_hold_by_message_done = true;
     327                 :          3 : }
     328                 :            : 
     329                 :            : static void
     330                 :          3 : hold_by_message_setup(void)
     331                 :            : {
     332         [ -  + ]:          3 :         memset(g_lock_error_count, 0, sizeof(g_lock_error_count));
     333                 :          3 :         spdk_spin_init(&g_hold_by_message_spinlock);
     334                 :            : 
     335                 :          3 :         spdk_thread_send_msg(g_thread[0], hold_by_message, NULL);
     336                 :          3 : }
     337                 :            : 
     338                 :            : static int
     339                 :          3 : hold_by_message_end(void *arg)
     340                 :            : {
     341                 :          3 :         struct test *test = arg;
     342                 :          3 :         enum spin_error expect[SPIN_ERR_LAST] = { 0 };
     343                 :            : 
     344                 :            :         /* Wait for the message to be processed */
     345   [ -  +  -  + ]:          3 :         if (!g_hold_by_message_done) {
     346                 :          0 :                 return SPDK_POLLER_IDLE;
     347                 :            :         }
     348                 :            : 
     349                 :            :         /* Verify an error was seen */
     350                 :          3 :         expect[SPIN_ERR_HOLD_DURING_SWITCH] = 1;
     351   [ +  -  -  - ]:          3 :         ASSERT(check_spin_err_count(expect));
     352                 :            : 
     353                 :            :         /* All done, move on to next test */
     354                 :          3 :         spdk_poller_unregister(&test->poller);
     355                 :          3 :         spdk_thread_send_msg(spdk_thread_get_app_thread(), launch_next_test, NULL);
     356                 :            : 
     357                 :          3 :         return SPDK_POLLER_BUSY;
     358                 :            : }
     359                 :            : 
     360                 :            : /*
     361                 :            :  * Test definitions
     362                 :            :  */
     363                 :            : 
     364                 :            : static void
     365                 :          9 : start_threads(uint32_t count)
     366                 :            : {
     367                 :            :         struct spdk_cpuset *cpuset;
     368                 :            :         uint32_t i;
     369                 :            : 
     370                 :          9 :         cpuset = spdk_cpuset_alloc();
     371         [ -  + ]:          9 :         if (cpuset == NULL) {
     372   [ #  #  #  # ]:          0 :                 fprintf(stderr, "failed to allocate cpuset\n");
     373                 :          0 :                 abort();
     374                 :            :         }
     375                 :            : 
     376         [ -  + ]:          9 :         assert(count <= SPDK_COUNTOF(g_thread));
     377                 :            : 
     378         [ +  + ]:         21 :         for (i = 0; i < count; i++) {
     379                 :         12 :                 spdk_cpuset_zero(cpuset);
     380                 :         12 :                 spdk_cpuset_set_cpu(cpuset, i, true);
     381                 :         12 :                 g_thread[i] = spdk_thread_create("worker", cpuset);
     382         [ -  + ]:         12 :                 if (g_thread[i] == NULL) {
     383   [ #  #  #  # ]:          0 :                         fprintf(stderr, "failed to create thread\n");
     384                 :          0 :                         abort();
     385                 :            :                 }
     386                 :            :         }
     387                 :          9 :         spdk_cpuset_free(cpuset);
     388                 :          9 : }
     389                 :            : 
     390                 :            : static void
     391                 :         12 : stop_thread(void *arg)
     392                 :            : {
     393                 :         12 :         struct spdk_thread *thread = arg;
     394                 :            : 
     395                 :         12 :         spdk_thread_exit(thread);
     396                 :         12 : }
     397                 :            : 
     398                 :            : static void
     399                 :          9 : stop_threads(void)
     400                 :            : {
     401                 :            :         uint32_t i;
     402                 :            : 
     403         [ +  + ]:         21 :         for (i = 0; i < SPDK_COUNTOF(g_thread); i++) {
     404         [ +  + ]:         18 :                 if (g_thread[i] == NULL) {
     405                 :          6 :                         break;
     406                 :            :                 }
     407                 :         12 :                 spdk_thread_send_msg(g_thread[i], stop_thread, g_thread[i]);
     408                 :         12 :                 g_thread[i] = NULL;
     409                 :            :         }
     410                 :          9 : }
     411                 :            : 
     412                 :            : static struct test g_tests[] = {
     413                 :            :         {"contend", 2, contend_setup, contend_end, 0},
     414                 :            :         {"hold_by_poller", 1, hold_by_poller_setup, hold_by_poller_end, 0},
     415                 :            :         {"hold_by_message", 1, hold_by_message_setup, hold_by_message_end, 1},
     416                 :            : };
     417                 :            : 
     418                 :            : static void
     419                 :          9 : launch_end_poller(void *arg)
     420                 :            : {
     421                 :          9 :         struct test *test = arg;
     422                 :            : 
     423                 :          9 :         test->poller = SPDK_POLLER_REGISTER(test->end_fn, test, 100);
     424                 :          9 : }
     425                 :            : 
     426                 :            : static void
     427                 :         12 : launch_next_test(void *arg)
     428                 :            : {
     429                 :            :         struct test *test;
     430                 :            :         static uint32_t last_fail_count = 0;
     431                 :            :         static uint32_t current_test = 0;
     432                 :            : 
     433         [ -  + ]:         12 :         assert(spdk_thread_is_app_thread(NULL));
     434                 :            : 
     435         [ +  + ]:         12 :         if (current_test != 0) {
     436                 :          9 :                 const char *name = g_tests[current_test - 1].name;
     437         [ +  - ]:          9 :                 if (g_fail == last_fail_count) {
     438         [ -  + ]:          9 :                         printf("PASS test %s\n", name);
     439                 :            :                 } else {
     440         [ #  # ]:          0 :                         printf("FAIL test %s (%u failed assertions)\n", name,
     441                 :            :                                g_fail - last_fail_count);
     442                 :            :                 }
     443                 :          9 :                 stop_threads();
     444                 :            :         }
     445                 :            : 
     446         [ +  + ]:         12 :         if (current_test == SPDK_COUNTOF(g_tests)) {
     447                 :          3 :                 spdk_app_stop(g_fail);
     448                 :            : 
     449                 :          3 :                 return;
     450                 :            :         }
     451                 :            : 
     452                 :          9 :         test = &g_tests[current_test];
     453                 :            : 
     454         [ -  + ]:          9 :         printf("Starting test %s\n", test->name);
     455                 :          9 :         start_threads(test->thread_count);
     456                 :            : 
     457         [ +  + ]:          9 :         if (test->poller_thread_number == 0) {
     458                 :          6 :                 launch_end_poller(test);
     459                 :            :         } else {
     460                 :            :                 /*
     461                 :            :                  * A test may set a done flag then return, expecting the error to be generated
     462                 :            :                  * when the poller or message goes off CPU. To ensure that we don't check for the
     463                 :            :                  * error between the time that "done" is set and the time the error is registered,
     464                 :            :                  * check for the error on the thread that runs the poller or handles the message.
     465                 :            :                  */
     466                 :          3 :                 spdk_thread_send_msg(g_thread[test->poller_thread_number - 1],
     467                 :            :                                      launch_end_poller, test);
     468                 :            :         }
     469                 :            : 
     470                 :            :         /*
     471                 :            :          * The setup function starts after the end poller. If it's not done this way, the start
     472                 :            :          * function may trigger an error condition (thread->lock_count != 0) that would cause
     473                 :            :          * extraneous calls to spin_abort_fn() as the end poller is registered.
     474                 :            :          */
     475                 :          9 :         test->setup_fn();
     476                 :            : 
     477                 :          9 :         current_test++;
     478                 :            : }
     479                 :            : 
     480                 :            : static void
     481                 :          3 : start_tests(void *arg)
     482                 :            : {
     483                 :          3 :         g_spin_abort_fn = do_not_abort;
     484                 :          3 :         spdk_thread_send_msg(spdk_thread_get_app_thread(), launch_next_test, NULL);
     485                 :          3 : }
     486                 :            : 
     487                 :            : int
     488                 :          3 : main(int argc, char **argv)
     489                 :            : {
     490                 :          3 :         struct spdk_app_opts opts;
     491                 :          3 :         char *me = argv[0];
     492                 :            :         int ret;
     493                 :          3 :         char mask[8];
     494                 :            : 
     495                 :          3 :         spdk_app_opts_init(&opts, sizeof(opts));
     496                 :          3 :         opts.name = "spdk_lock_test";
     497         [ -  + ]:          3 :         snprintf(mask, sizeof(mask), "0x%x", (1 << SPDK_COUNTOF(g_thread)) - 1);
     498                 :          3 :         opts.reactor_mask = mask;
     499                 :          3 :         opts.rpc_addr = NULL;
     500                 :            : 
     501                 :          3 :         spdk_app_start(&opts, start_tests, NULL);
     502                 :            : 
     503                 :          3 :         spdk_app_fini();
     504                 :            : 
     505         [ -  + ]:          3 :         printf("%s summary:\n", me);
     506         [ -  + ]:          3 :         printf(" %8u assertions passed\n", g_pass);
     507         [ -  + ]:          3 :         printf(" %8u assertions failed\n", g_fail);
     508                 :            : 
     509         [ -  + ]:          3 :         if (g_pass + g_fail == 0) {
     510                 :          0 :                 ret = 1;
     511                 :            :         } else {
     512                 :          3 :                 ret = spdk_min(g_fail, 127);
     513                 :            :         }
     514                 :          3 :         return ret;
     515                 :            : }

Generated by: LCOV version 1.14