LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/thread/thread.c - thread_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 1154 1158 99.7 %
Date: 2024-07-12 23:21:00 Functions: 59 59 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 125 234 53.4 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2016 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  *   Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "spdk/stdinc.h"
       8                 :            : 
       9                 :            : #include "spdk_internal/cunit.h"
      10                 :            : 
      11                 :            : #include "thread/thread_internal.h"
      12                 :            : 
      13                 :            : #include "thread/thread.c"
      14                 :            : #include "common/lib/ut_multithread.c"
      15                 :            : 
      16                 :            : static int g_sched_rc = 0;
      17                 :            : 
      18                 :            : static int
      19                 :         24 : _thread_schedule(struct spdk_thread *thread)
      20                 :            : {
      21                 :         24 :         return g_sched_rc;
      22                 :            : }
      23                 :            : 
      24                 :            : static bool
      25                 :         12 : _thread_op_supported(enum spdk_thread_op op)
      26                 :            : {
      27         [ +  - ]:         12 :         switch (op) {
      28                 :         12 :         case SPDK_THREAD_OP_NEW:
      29                 :         12 :                 return true;
      30                 :          0 :         default:
      31                 :          0 :                 return false;
      32                 :            :         }
      33                 :            : }
      34                 :            : 
      35                 :            : static int
      36                 :         12 : _thread_op(struct spdk_thread *thread, enum spdk_thread_op op)
      37                 :            : {
      38         [ +  - ]:         12 :         switch (op) {
      39                 :         12 :         case SPDK_THREAD_OP_NEW:
      40                 :         12 :                 return _thread_schedule(thread);
      41                 :          0 :         default:
      42                 :          0 :                 return -ENOTSUP;
      43                 :            :         }
      44                 :            : }
      45                 :            : 
      46                 :            : static void
      47                 :          6 : thread_alloc(void)
      48                 :            : {
      49                 :            :         struct spdk_thread *thread;
      50                 :            : 
      51                 :            :         /* No schedule callback */
      52                 :          6 :         spdk_thread_lib_init(NULL, 0);
      53                 :          6 :         thread = spdk_thread_create(NULL, NULL);
      54         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
      55                 :          6 :         spdk_set_thread(thread);
      56                 :          6 :         spdk_thread_exit(thread);
      57         [ +  + ]:         12 :         while (!spdk_thread_is_exited(thread)) {
      58                 :          6 :                 spdk_thread_poll(thread, 0, 0);
      59                 :            :         }
      60                 :          6 :         spdk_thread_destroy(thread);
      61                 :          6 :         spdk_thread_lib_fini();
      62                 :            : 
      63                 :            :         /* Schedule callback exists */
      64                 :          6 :         spdk_thread_lib_init(_thread_schedule, 0);
      65                 :            : 
      66                 :            :         /* Scheduling succeeds */
      67                 :          6 :         g_sched_rc = 0;
      68                 :          6 :         thread = spdk_thread_create(NULL, NULL);
      69         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
      70                 :          6 :         spdk_set_thread(thread);
      71                 :          6 :         spdk_thread_exit(thread);
      72         [ +  + ]:         12 :         while (!spdk_thread_is_exited(thread)) {
      73                 :          6 :                 spdk_thread_poll(thread, 0, 0);
      74                 :            :         }
      75                 :          6 :         spdk_thread_destroy(thread);
      76                 :            : 
      77                 :            :         /* Scheduling fails */
      78                 :          6 :         g_sched_rc = -1;
      79                 :          6 :         thread = spdk_thread_create(NULL, NULL);
      80         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread == NULL);
      81                 :            : 
      82                 :          6 :         spdk_thread_lib_fini();
      83                 :            : 
      84                 :            :         /* Scheduling callback exists with extended thread library initialization. */
      85                 :          6 :         spdk_thread_lib_init_ext(_thread_op, _thread_op_supported, 0,
      86                 :            :                                  SPDK_DEFAULT_MSG_MEMPOOL_SIZE);
      87                 :            : 
      88                 :            :         /* Scheduling succeeds */
      89                 :          6 :         g_sched_rc = 0;
      90                 :          6 :         thread = spdk_thread_create(NULL, NULL);
      91         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
      92                 :          6 :         spdk_set_thread(thread);
      93                 :          6 :         spdk_thread_exit(thread);
      94         [ +  + ]:         12 :         while (!spdk_thread_is_exited(thread)) {
      95                 :          6 :                 spdk_thread_poll(thread, 0, 0);
      96                 :            :         }
      97                 :          6 :         spdk_thread_destroy(thread);
      98                 :            : 
      99                 :            :         /* Scheduling fails */
     100                 :          6 :         g_sched_rc = -1;
     101                 :          6 :         thread = spdk_thread_create(NULL, NULL);
     102         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread == NULL);
     103                 :            : 
     104                 :          6 :         spdk_thread_lib_fini();
     105                 :          6 : }
     106                 :            : 
     107                 :            : static void
     108                 :         18 : send_msg_cb(void *ctx)
     109                 :            : {
     110                 :         18 :         bool *done = ctx;
     111                 :            : 
     112                 :         18 :         *done = true;
     113                 :         18 : }
     114                 :            : 
     115                 :            : static void
     116                 :          6 : thread_send_msg(void)
     117                 :            : {
     118                 :            :         struct spdk_thread *thread0;
     119                 :          6 :         bool done = false;
     120                 :            : 
     121                 :          6 :         allocate_threads(2);
     122                 :          6 :         set_thread(0);
     123                 :          6 :         thread0 = spdk_get_thread();
     124                 :            : 
     125                 :          6 :         set_thread(1);
     126                 :            :         /* Simulate thread 1 sending a message to thread 0. */
     127                 :          6 :         spdk_thread_send_msg(thread0, send_msg_cb, &done);
     128                 :            : 
     129                 :            :         /* We have not polled thread 0 yet, so done should be false. */
     130         [ -  + ]:          6 :         CU_ASSERT(!done);
     131                 :            : 
     132                 :            :         /*
     133                 :            :          * Poll thread 1.  The message was sent to thread 0, so this should be
     134                 :            :          *  a nop and done should still be false.
     135                 :            :          */
     136                 :          6 :         poll_thread(1);
     137         [ -  + ]:          6 :         CU_ASSERT(!done);
     138                 :            : 
     139                 :            :         /*
     140                 :            :          * Poll thread 0.  This should execute the message and done should then
     141                 :            :          *  be true.
     142                 :            :          */
     143                 :          6 :         poll_thread(0);
     144         [ -  + ]:          6 :         CU_ASSERT(done);
     145                 :            : 
     146                 :          6 :         free_threads();
     147                 :          6 : }
     148                 :            : 
     149                 :            : static int
     150                 :        108 : poller_run_done(void *ctx)
     151                 :            : {
     152                 :        108 :         bool    *poller_run = ctx;
     153                 :            : 
     154                 :        108 :         *poller_run = true;
     155                 :            : 
     156                 :        108 :         return -1;
     157                 :            : }
     158                 :            : 
     159                 :            : static void
     160                 :          6 : thread_poller(void)
     161                 :            : {
     162                 :          6 :         struct spdk_poller      *poller = NULL;
     163                 :          6 :         bool                    poller_run = false;
     164                 :            : 
     165                 :          6 :         allocate_threads(1);
     166                 :            : 
     167                 :          6 :         set_thread(0);
     168                 :          6 :         MOCK_SET(spdk_get_ticks, 0);
     169                 :            :         /* Register a poller with no-wait time and test execution */
     170                 :          6 :         poller = spdk_poller_register(poller_run_done, &poller_run, 0);
     171                 :          6 :         CU_ASSERT(poller != NULL);
     172                 :            : 
     173                 :          6 :         poll_threads();
     174         [ -  + ]:          6 :         CU_ASSERT(poller_run == true);
     175                 :            : 
     176                 :          6 :         spdk_poller_unregister(&poller);
     177                 :          6 :         CU_ASSERT(poller == NULL);
     178                 :            : 
     179                 :            :         /* Register a poller with 1000us wait time and test single execution */
     180                 :          6 :         poller_run = false;
     181                 :          6 :         poller = spdk_poller_register(poller_run_done, &poller_run, 1000);
     182                 :          6 :         CU_ASSERT(poller != NULL);
     183                 :            : 
     184                 :          6 :         poll_threads();
     185         [ -  + ]:          6 :         CU_ASSERT(poller_run == false);
     186                 :            : 
     187                 :          6 :         spdk_delay_us(1000);
     188                 :          6 :         poll_threads();
     189         [ -  + ]:          6 :         CU_ASSERT(poller_run == true);
     190                 :            : 
     191                 :          6 :         poller_run = false;
     192                 :          6 :         poll_threads();
     193         [ -  + ]:          6 :         CU_ASSERT(poller_run == false);
     194                 :            : 
     195                 :          6 :         spdk_delay_us(1000);
     196                 :          6 :         poll_threads();
     197         [ -  + ]:          6 :         CU_ASSERT(poller_run == true);
     198                 :            : 
     199                 :          6 :         spdk_poller_unregister(&poller);
     200                 :          6 :         CU_ASSERT(poller == NULL);
     201                 :            : 
     202                 :          6 :         free_threads();
     203                 :          6 : }
     204                 :            : 
     205                 :            : struct poller_ctx {
     206                 :            :         struct spdk_poller      *poller;
     207                 :            :         bool                    run;
     208                 :            : };
     209                 :            : 
     210                 :            : static int
     211                 :         30 : poller_run_pause(void *ctx)
     212                 :            : {
     213                 :         30 :         struct poller_ctx *poller_ctx = ctx;
     214                 :            : 
     215                 :         30 :         poller_ctx->run = true;
     216                 :         30 :         spdk_poller_pause(poller_ctx->poller);
     217                 :            : 
     218                 :         30 :         return 0;
     219                 :            : }
     220                 :            : 
     221                 :            : /* Verify the same poller can be switched multiple times between
     222                 :            :  * pause and resume while it runs.
     223                 :            :  */
     224                 :            : static int
     225                 :         30 : poller_run_pause_resume_pause(void *ctx)
     226                 :            : {
     227                 :         30 :         struct poller_ctx *poller_ctx = ctx;
     228                 :            : 
     229                 :         30 :         poller_ctx->run = true;
     230                 :            : 
     231                 :         30 :         spdk_poller_pause(poller_ctx->poller);
     232                 :         30 :         spdk_poller_resume(poller_ctx->poller);
     233                 :         30 :         spdk_poller_pause(poller_ctx->poller);
     234                 :            : 
     235                 :         30 :         return 0;
     236                 :            : }
     237                 :            : 
     238                 :            : static void
     239                 :         12 : poller_msg_pause_cb(void *ctx)
     240                 :            : {
     241                 :         12 :         struct spdk_poller *poller = ctx;
     242                 :            : 
     243                 :         12 :         spdk_poller_pause(poller);
     244                 :         12 : }
     245                 :            : 
     246                 :            : static void
     247                 :         12 : poller_msg_resume_cb(void *ctx)
     248                 :            : {
     249                 :         12 :         struct spdk_poller *poller = ctx;
     250                 :            : 
     251                 :         12 :         spdk_poller_resume(poller);
     252                 :         12 : }
     253                 :            : 
     254                 :            : static void
     255                 :          6 : poller_pause(void)
     256                 :            : {
     257                 :          6 :         struct poller_ctx poller_ctx = {};
     258                 :          6 :         unsigned int delay[] = { 0, 1000 };
     259                 :            :         unsigned int i;
     260                 :            : 
     261                 :          6 :         allocate_threads(1);
     262                 :          6 :         set_thread(0);
     263                 :            : 
     264                 :            :         /* Register a poller that pauses itself */
     265                 :          6 :         poller_ctx.poller = spdk_poller_register(poller_run_pause, &poller_ctx, 0);
     266                 :          6 :         CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
     267                 :            : 
     268                 :          6 :         poller_ctx.run = false;
     269                 :          6 :         poll_threads();
     270         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, true);
     271                 :            : 
     272                 :          6 :         poller_ctx.run = false;
     273                 :          6 :         poll_threads();
     274         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, false);
     275                 :            : 
     276                 :          6 :         spdk_poller_unregister(&poller_ctx.poller);
     277                 :          6 :         CU_ASSERT_PTR_NULL(poller_ctx.poller);
     278                 :            : 
     279                 :            :         /* Register a poller that switches between pause and resume itself */
     280                 :          6 :         poller_ctx.poller = spdk_poller_register(poller_run_pause_resume_pause, &poller_ctx, 0);
     281                 :          6 :         CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
     282                 :            : 
     283                 :          6 :         poller_ctx.run = false;
     284                 :          6 :         poll_threads();
     285         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, true);
     286                 :            : 
     287                 :          6 :         poller_ctx.run = false;
     288                 :          6 :         poll_threads();
     289         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, false);
     290                 :            : 
     291                 :          6 :         spdk_poller_unregister(&poller_ctx.poller);
     292                 :          6 :         CU_ASSERT_PTR_NULL(poller_ctx.poller);
     293                 :            : 
     294                 :            :         /* Verify that resuming an unpaused poller doesn't do anything */
     295                 :          6 :         poller_ctx.poller = spdk_poller_register(poller_run_done, &poller_ctx.run, 0);
     296                 :          6 :         CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
     297                 :            : 
     298                 :          6 :         spdk_poller_resume(poller_ctx.poller);
     299                 :            : 
     300                 :          6 :         poller_ctx.run = false;
     301                 :          6 :         poll_threads();
     302         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, true);
     303                 :            : 
     304                 :            :         /* Verify that pausing the same poller twice works too */
     305                 :          6 :         spdk_poller_pause(poller_ctx.poller);
     306                 :            : 
     307                 :          6 :         poller_ctx.run = false;
     308                 :          6 :         poll_threads();
     309         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, false);
     310                 :            : 
     311                 :          6 :         spdk_poller_pause(poller_ctx.poller);
     312                 :          6 :         poll_threads();
     313         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, false);
     314                 :            : 
     315                 :          6 :         spdk_poller_resume(poller_ctx.poller);
     316                 :          6 :         poll_threads();
     317         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, true);
     318                 :            : 
     319                 :            :         /* Verify that a poller is run when it's resumed immediately after pausing */
     320                 :          6 :         poller_ctx.run = false;
     321                 :          6 :         spdk_poller_pause(poller_ctx.poller);
     322                 :          6 :         spdk_poller_resume(poller_ctx.poller);
     323                 :          6 :         poll_threads();
     324         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, true);
     325                 :            : 
     326                 :          6 :         spdk_poller_unregister(&poller_ctx.poller);
     327                 :          6 :         CU_ASSERT_PTR_NULL(poller_ctx.poller);
     328                 :            : 
     329                 :            :         /* Poll the thread to make sure the previous poller gets unregistered */
     330                 :          6 :         poll_threads();
     331                 :          6 :         CU_ASSERT_EQUAL(spdk_thread_has_pollers(spdk_get_thread()), false);
     332                 :            : 
     333                 :            :         /* Verify that it's possible to unregister a paused poller */
     334                 :          6 :         poller_ctx.poller = spdk_poller_register(poller_run_done, &poller_ctx.run, 0);
     335                 :          6 :         CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
     336                 :            : 
     337                 :          6 :         poller_ctx.run = false;
     338                 :          6 :         poll_threads();
     339         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, true);
     340                 :            : 
     341                 :          6 :         spdk_poller_pause(poller_ctx.poller);
     342                 :            : 
     343                 :          6 :         poller_ctx.run = false;
     344                 :          6 :         poll_threads();
     345         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, false);
     346                 :            : 
     347                 :          6 :         spdk_poller_unregister(&poller_ctx.poller);
     348                 :            : 
     349                 :          6 :         poll_threads();
     350         [ -  + ]:          6 :         CU_ASSERT_EQUAL(poller_ctx.run, false);
     351                 :          6 :         CU_ASSERT_EQUAL(spdk_thread_has_pollers(spdk_get_thread()), false);
     352                 :            : 
     353                 :            :         /* Register pollers with 0 and 1000us wait time and pause/resume them */
     354         [ +  + ]:         18 :         for (i = 0; i < SPDK_COUNTOF(delay); ++i) {
     355                 :         12 :                 poller_ctx.poller = spdk_poller_register(poller_run_done, &poller_ctx.run, delay[i]);
     356                 :         12 :                 CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
     357                 :            : 
     358                 :         12 :                 spdk_delay_us(delay[i]);
     359                 :         12 :                 poller_ctx.run = false;
     360                 :         12 :                 poll_threads();
     361         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, true);
     362                 :            : 
     363                 :         12 :                 spdk_poller_pause(poller_ctx.poller);
     364                 :            : 
     365                 :         12 :                 spdk_delay_us(delay[i]);
     366                 :         12 :                 poller_ctx.run = false;
     367                 :         12 :                 poll_threads();
     368         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, false);
     369                 :            : 
     370                 :         12 :                 spdk_poller_resume(poller_ctx.poller);
     371                 :            : 
     372                 :         12 :                 spdk_delay_us(delay[i]);
     373                 :         12 :                 poll_threads();
     374         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, true);
     375                 :            : 
     376                 :            :                 /* Verify that the poller can be paused/resumed from spdk_thread_send_msg */
     377                 :         12 :                 spdk_thread_send_msg(spdk_get_thread(), poller_msg_pause_cb, poller_ctx.poller);
     378                 :            : 
     379                 :         12 :                 spdk_delay_us(delay[i]);
     380                 :         12 :                 poller_ctx.run = false;
     381                 :         12 :                 poll_threads();
     382         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, false);
     383                 :            : 
     384                 :         12 :                 spdk_thread_send_msg(spdk_get_thread(), poller_msg_resume_cb, poller_ctx.poller);
     385                 :            : 
     386                 :         12 :                 poll_threads();
     387         [ +  + ]:         12 :                 if (delay[i] > 0) {
     388                 :          6 :                         spdk_delay_us(delay[i]);
     389                 :          6 :                         poll_threads();
     390                 :            :                 }
     391         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, true);
     392                 :            : 
     393                 :         12 :                 spdk_poller_unregister(&poller_ctx.poller);
     394                 :         12 :                 CU_ASSERT_PTR_NULL(poller_ctx.poller);
     395                 :            : 
     396                 :            :                 /* Register a timed poller that pauses itself */
     397                 :         12 :                 poller_ctx.poller = spdk_poller_register(poller_run_pause, &poller_ctx, delay[i]);
     398                 :         12 :                 CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
     399                 :            : 
     400                 :         12 :                 spdk_delay_us(delay[i]);
     401                 :         12 :                 poller_ctx.run = false;
     402                 :         12 :                 poll_threads();
     403         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, true);
     404                 :            : 
     405                 :         12 :                 poller_ctx.run = false;
     406                 :         12 :                 spdk_delay_us(delay[i]);
     407                 :         12 :                 poll_threads();
     408         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, false);
     409                 :            : 
     410                 :         12 :                 spdk_poller_resume(poller_ctx.poller);
     411                 :            : 
     412         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, false);
     413                 :         12 :                 spdk_delay_us(delay[i]);
     414                 :         12 :                 poll_threads();
     415         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, true);
     416                 :            : 
     417                 :         12 :                 spdk_poller_unregister(&poller_ctx.poller);
     418                 :         12 :                 CU_ASSERT_PTR_NULL(poller_ctx.poller);
     419                 :            : 
     420                 :            :                 /* Register a timed poller that switches between pause and resume itself */
     421                 :         24 :                 poller_ctx.poller = spdk_poller_register(poller_run_pause_resume_pause,
     422                 :         12 :                                     &poller_ctx, delay[i]);
     423                 :         12 :                 CU_ASSERT_PTR_NOT_NULL(poller_ctx.poller);
     424                 :            : 
     425                 :         12 :                 spdk_delay_us(delay[i]);
     426                 :         12 :                 poller_ctx.run = false;
     427                 :         12 :                 poll_threads();
     428         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, true);
     429                 :            : 
     430                 :         12 :                 poller_ctx.run = false;
     431                 :         12 :                 spdk_delay_us(delay[i]);
     432                 :         12 :                 poll_threads();
     433         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, false);
     434                 :            : 
     435                 :         12 :                 spdk_poller_resume(poller_ctx.poller);
     436                 :            : 
     437         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, false);
     438                 :         12 :                 spdk_delay_us(delay[i]);
     439                 :         12 :                 poll_threads();
     440         [ -  + ]:         12 :                 CU_ASSERT_EQUAL(poller_ctx.run, true);
     441                 :            : 
     442                 :         12 :                 spdk_poller_unregister(&poller_ctx.poller);
     443                 :         12 :                 CU_ASSERT_PTR_NULL(poller_ctx.poller);
     444                 :            :         }
     445                 :            : 
     446                 :          6 :         free_threads();
     447                 :          6 : }
     448                 :            : 
     449                 :            : static void
     450                 :         48 : for_each_cb(void *ctx)
     451                 :            : {
     452                 :         48 :         int *count = ctx;
     453                 :            : 
     454                 :         48 :         (*count)++;
     455                 :         48 : }
     456                 :            : 
     457                 :            : static void
     458                 :          6 : thread_for_each(void)
     459                 :            : {
     460                 :          6 :         int count = 0;
     461                 :            :         int i;
     462                 :            : 
     463                 :          6 :         allocate_threads(3);
     464                 :          6 :         set_thread(0);
     465                 :            : 
     466                 :          6 :         spdk_for_each_thread(for_each_cb, &count, for_each_cb);
     467                 :            : 
     468                 :            :         /* We have not polled thread 0 yet, so count should be 0 */
     469                 :          6 :         CU_ASSERT(count == 0);
     470                 :            : 
     471                 :            :         /* Poll each thread to verify the message is passed to each */
     472         [ +  + ]:         24 :         for (i = 0; i < 3; i++) {
     473                 :         18 :                 poll_thread(i);
     474                 :         18 :                 CU_ASSERT(count == (i + 1));
     475                 :            :         }
     476                 :            : 
     477                 :            :         /*
     478                 :            :          * After each thread is called, the completion calls it
     479                 :            :          * one more time.
     480                 :            :          */
     481                 :          6 :         poll_thread(0);
     482                 :          6 :         CU_ASSERT(count == 4);
     483                 :            : 
     484                 :          6 :         free_threads();
     485                 :          6 : }
     486                 :            : 
     487                 :            : static int
     488                 :         42 : channel_create(void *io_device, void *ctx_buf)
     489                 :            : {
     490                 :         42 :         int *ch_count = io_device;
     491                 :            : 
     492                 :         42 :         (*ch_count)++;
     493                 :         42 :         return 0;
     494                 :            : }
     495                 :            : 
     496                 :            : static void
     497                 :         42 : channel_destroy(void *io_device, void *ctx_buf)
     498                 :            : {
     499                 :         42 :         int *ch_count = io_device;
     500                 :            : 
     501                 :         42 :         (*ch_count)--;
     502                 :         42 : }
     503                 :            : 
     504                 :            : static void
     505                 :         42 : channel_msg(struct spdk_io_channel_iter *i)
     506                 :            : {
     507                 :         42 :         int *msg_count = spdk_io_channel_iter_get_ctx(i);
     508                 :            : 
     509                 :         42 :         (*msg_count)++;
     510                 :         42 :         spdk_for_each_channel_continue(i, 0);
     511                 :         42 : }
     512                 :            : 
     513                 :            : static void
     514                 :         18 : channel_cpl(struct spdk_io_channel_iter *i, int status)
     515                 :            : {
     516                 :         18 :         int *msg_count = spdk_io_channel_iter_get_ctx(i);
     517                 :            : 
     518                 :         18 :         (*msg_count)++;
     519                 :         18 : }
     520                 :            : 
     521                 :            : static void
     522                 :          6 : for_each_channel_remove(void)
     523                 :            : {
     524                 :            :         struct spdk_io_channel *ch0, *ch1, *ch2;
     525                 :          6 :         int ch_count = 0;
     526                 :          6 :         int msg_count = 0;
     527                 :            : 
     528                 :          6 :         allocate_threads(3);
     529                 :          6 :         set_thread(0);
     530                 :          6 :         spdk_io_device_register(&ch_count, channel_create, channel_destroy, sizeof(int), NULL);
     531                 :          6 :         ch0 = spdk_get_io_channel(&ch_count);
     532                 :          6 :         set_thread(1);
     533                 :          6 :         ch1 = spdk_get_io_channel(&ch_count);
     534                 :          6 :         set_thread(2);
     535                 :          6 :         ch2 = spdk_get_io_channel(&ch_count);
     536                 :          6 :         CU_ASSERT(ch_count == 3);
     537                 :            : 
     538                 :            :         /*
     539                 :            :          * Test that io_channel handles the case where we start to iterate through
     540                 :            :          *  the channels, and during the iteration, one of the channels is deleted.
     541                 :            :          * This is done in some different and sometimes non-intuitive orders, because
     542                 :            :          *  some operations are deferred and won't execute until their threads are
     543                 :            :          *  polled.
     544                 :            :          *
     545                 :            :          * Case #1: Put the I/O channel before spdk_for_each_channel.
     546                 :            :          */
     547                 :          6 :         set_thread(0);
     548                 :          6 :         spdk_put_io_channel(ch0);
     549                 :          6 :         CU_ASSERT(ch_count == 3);
     550                 :          6 :         poll_threads();
     551                 :          6 :         CU_ASSERT(ch_count == 2);
     552                 :          6 :         spdk_for_each_channel(&ch_count, channel_msg, &msg_count, channel_cpl);
     553                 :          6 :         CU_ASSERT(msg_count == 0);
     554                 :          6 :         poll_threads();
     555                 :          6 :         CU_ASSERT(msg_count == 3);
     556                 :            : 
     557                 :          6 :         msg_count = 0;
     558                 :            : 
     559                 :            :         /*
     560                 :            :          * Case #2: Put the I/O channel after spdk_for_each_channel, but before
     561                 :            :          *  thread 0 is polled.
     562                 :            :          */
     563                 :          6 :         ch0 = spdk_get_io_channel(&ch_count);
     564                 :          6 :         CU_ASSERT(ch_count == 3);
     565                 :          6 :         spdk_for_each_channel(&ch_count, channel_msg, &msg_count, channel_cpl);
     566                 :          6 :         spdk_put_io_channel(ch0);
     567                 :          6 :         CU_ASSERT(ch_count == 3);
     568                 :            : 
     569                 :          6 :         poll_threads();
     570                 :          6 :         CU_ASSERT(ch_count == 2);
     571                 :          6 :         CU_ASSERT(msg_count == 4);
     572                 :          6 :         set_thread(1);
     573                 :          6 :         spdk_put_io_channel(ch1);
     574                 :          6 :         CU_ASSERT(ch_count == 2);
     575                 :          6 :         set_thread(2);
     576                 :          6 :         spdk_put_io_channel(ch2);
     577                 :          6 :         CU_ASSERT(ch_count == 2);
     578                 :          6 :         poll_threads();
     579                 :          6 :         CU_ASSERT(ch_count == 0);
     580                 :            : 
     581                 :          6 :         spdk_io_device_unregister(&ch_count, NULL);
     582                 :          6 :         poll_threads();
     583                 :            : 
     584                 :          6 :         free_threads();
     585                 :          6 : }
     586                 :            : 
     587                 :            : struct unreg_ctx {
     588                 :            :         bool    ch_done;
     589                 :            :         bool    foreach_done;
     590                 :            : };
     591                 :            : 
     592                 :            : static void
     593                 :          6 : unreg_ch_done(struct spdk_io_channel_iter *i)
     594                 :            : {
     595                 :          6 :         struct unreg_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
     596                 :            : 
     597                 :          6 :         ctx->ch_done = true;
     598                 :            : 
     599         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(i->cur_thread != NULL);
     600                 :          6 :         spdk_for_each_channel_continue(i, 0);
     601                 :          6 : }
     602                 :            : 
     603                 :            : static void
     604                 :          6 : unreg_foreach_done(struct spdk_io_channel_iter *i, int status)
     605                 :            : {
     606                 :          6 :         struct unreg_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
     607                 :            : 
     608                 :          6 :         ctx->foreach_done = true;
     609                 :          6 : }
     610                 :            : 
     611                 :            : static void
     612                 :          6 : for_each_channel_unreg(void)
     613                 :            : {
     614                 :            :         struct spdk_io_channel *ch0;
     615                 :            :         struct io_device *dev;
     616                 :          6 :         struct unreg_ctx ctx = {};
     617                 :          6 :         int io_target = 0;
     618                 :            : 
     619                 :          6 :         allocate_threads(1);
     620                 :          6 :         set_thread(0);
     621                 :          6 :         CU_ASSERT(RB_EMPTY(&g_io_devices));
     622                 :          6 :         spdk_io_device_register(&io_target, channel_create, channel_destroy, sizeof(int), NULL);
     623                 :          6 :         CU_ASSERT(!RB_EMPTY(&g_io_devices));
     624                 :          6 :         dev = RB_MIN(io_device_tree, &g_io_devices);
     625         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
     626                 :          6 :         CU_ASSERT(RB_NEXT(io_device_tree, &g_io_devices, dev) == NULL);
     627                 :          6 :         ch0 = spdk_get_io_channel(&io_target);
     628                 :            : 
     629                 :          6 :         spdk_io_device_register(&io_target, channel_create, channel_destroy, sizeof(int), NULL);
     630                 :            : 
     631                 :            :         /*
     632                 :            :          * There is already a device registered at &io_target, so a new io_device should not
     633                 :            :          *  have been added to g_io_devices.
     634                 :            :          */
     635                 :          6 :         CU_ASSERT(dev == RB_MIN(io_device_tree, &g_io_devices));
     636                 :          6 :         CU_ASSERT(RB_NEXT(io_device_tree, &g_io_devices, dev) == NULL);
     637                 :            : 
     638                 :          6 :         spdk_for_each_channel(&io_target, unreg_ch_done, &ctx, unreg_foreach_done);
     639                 :          6 :         spdk_io_device_unregister(&io_target, NULL);
     640                 :            :         /*
     641                 :            :          * There is an outstanding foreach call on the io_device, so the unregister should not
     642                 :            :          *  have immediately removed the device.
     643                 :            :          */
     644                 :          6 :         CU_ASSERT(dev == RB_MIN(io_device_tree, &g_io_devices));
     645                 :            : 
     646                 :          6 :         poll_thread(0);
     647         [ -  + ]:          6 :         CU_ASSERT(ctx.ch_done == true);
     648         [ -  + ]:          6 :         CU_ASSERT(ctx.foreach_done == true);
     649                 :            : 
     650                 :            :         /*
     651                 :            :          * There are no more foreach operations outstanding, so the device should be
     652                 :            :          * unregistered.
     653                 :            :          */
     654                 :          6 :         CU_ASSERT(RB_EMPTY(&g_io_devices));
     655                 :            : 
     656                 :          6 :         set_thread(0);
     657                 :          6 :         spdk_put_io_channel(ch0);
     658                 :            : 
     659                 :          6 :         poll_threads();
     660                 :            : 
     661                 :          6 :         free_threads();
     662                 :          6 : }
     663                 :            : 
     664                 :            : static void
     665                 :          6 : thread_name(void)
     666                 :            : {
     667                 :            :         struct spdk_thread *thread;
     668                 :            :         const char *name;
     669                 :            : 
     670                 :          6 :         spdk_thread_lib_init(NULL, 0);
     671                 :            : 
     672                 :            :         /* Create thread with no name, which automatically generates one */
     673                 :          6 :         thread = spdk_thread_create(NULL, NULL);
     674                 :          6 :         spdk_set_thread(thread);
     675                 :          6 :         thread = spdk_get_thread();
     676         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
     677                 :          6 :         name = spdk_thread_get_name(thread);
     678                 :          6 :         CU_ASSERT(name != NULL);
     679                 :          6 :         spdk_thread_exit(thread);
     680         [ +  + ]:         12 :         while (!spdk_thread_is_exited(thread)) {
     681                 :          6 :                 spdk_thread_poll(thread, 0, 0);
     682                 :            :         }
     683                 :          6 :         spdk_thread_destroy(thread);
     684                 :            : 
     685                 :            :         /* Create thread named "test_thread" */
     686                 :          6 :         thread = spdk_thread_create("test_thread", NULL);
     687                 :          6 :         spdk_set_thread(thread);
     688                 :          6 :         thread = spdk_get_thread();
     689         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
     690                 :          6 :         name = spdk_thread_get_name(thread);
     691         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(name != NULL);
     692         [ -  + ]:          6 :         CU_ASSERT(strcmp(name, "test_thread") == 0);
     693                 :          6 :         spdk_thread_exit(thread);
     694         [ +  + ]:         12 :         while (!spdk_thread_is_exited(thread)) {
     695                 :          6 :                 spdk_thread_poll(thread, 0, 0);
     696                 :            :         }
     697                 :          6 :         spdk_thread_destroy(thread);
     698                 :            : 
     699                 :          6 :         spdk_thread_lib_fini();
     700                 :          6 : }
     701                 :            : 
     702                 :            : static uint64_t g_device1;
     703                 :            : static uint64_t g_device2;
     704                 :            : static uint64_t g_device3;
     705                 :            : 
     706                 :            : static uint64_t g_ctx1 = 0x1111;
     707                 :            : static uint64_t g_ctx2 = 0x2222;
     708                 :            : 
     709                 :            : static int g_create_cb_calls = 0;
     710                 :            : static int g_destroy_cb_calls = 0;
     711                 :            : 
     712                 :            : static int
     713                 :         12 : create_cb_1(void *io_device, void *ctx_buf)
     714                 :            : {
     715                 :         12 :         CU_ASSERT(io_device == &g_device1);
     716                 :         12 :         *(uint64_t *)ctx_buf = g_ctx1;
     717                 :         12 :         g_create_cb_calls++;
     718                 :         12 :         return 0;
     719                 :            : }
     720                 :            : 
     721                 :            : static void
     722                 :         12 : destroy_cb_1(void *io_device, void *ctx_buf)
     723                 :            : {
     724                 :         12 :         CU_ASSERT(io_device == &g_device1);
     725                 :         12 :         CU_ASSERT(*(uint64_t *)ctx_buf == g_ctx1);
     726                 :         12 :         g_destroy_cb_calls++;
     727                 :         12 : }
     728                 :            : 
     729                 :            : static int
     730                 :          6 : create_cb_2(void *io_device, void *ctx_buf)
     731                 :            : {
     732                 :          6 :         CU_ASSERT(io_device == &g_device2);
     733                 :          6 :         *(uint64_t *)ctx_buf = g_ctx2;
     734                 :          6 :         g_create_cb_calls++;
     735                 :          6 :         return 0;
     736                 :            : }
     737                 :            : 
     738                 :            : static void
     739                 :          6 : destroy_cb_2(void *io_device, void *ctx_buf)
     740                 :            : {
     741                 :          6 :         CU_ASSERT(io_device == &g_device2);
     742                 :          6 :         CU_ASSERT(*(uint64_t *)ctx_buf == g_ctx2);
     743                 :          6 :         g_destroy_cb_calls++;
     744                 :          6 : }
     745                 :            : 
     746                 :            : static void
     747                 :          6 : channel(void)
     748                 :            : {
     749                 :            :         struct spdk_io_channel *ch1, *ch2;
     750                 :            :         void *ctx;
     751                 :            : 
     752                 :          6 :         allocate_threads(1);
     753                 :          6 :         set_thread(0);
     754                 :            : 
     755                 :          6 :         spdk_io_device_register(&g_device1, create_cb_1, destroy_cb_1, sizeof(g_ctx1), NULL);
     756                 :          6 :         spdk_io_device_register(&g_device2, create_cb_2, destroy_cb_2, sizeof(g_ctx2), NULL);
     757                 :            : 
     758                 :          6 :         g_create_cb_calls = 0;
     759                 :          6 :         ch1 = spdk_get_io_channel(&g_device1);
     760                 :          6 :         CU_ASSERT(g_create_cb_calls == 1);
     761         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch1 != NULL);
     762                 :          6 :         CU_ASSERT(spdk_io_channel_get_io_device(ch1) == &g_device1);
     763                 :            : 
     764                 :          6 :         g_create_cb_calls = 0;
     765                 :          6 :         ch2 = spdk_get_io_channel(&g_device1);
     766                 :          6 :         CU_ASSERT(g_create_cb_calls == 0);
     767                 :          6 :         CU_ASSERT(ch1 == ch2);
     768         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch2 != NULL);
     769                 :          6 :         CU_ASSERT(spdk_io_channel_get_io_device(ch2) == &g_device1);
     770                 :            : 
     771                 :          6 :         g_destroy_cb_calls = 0;
     772                 :          6 :         spdk_put_io_channel(ch2);
     773                 :          6 :         poll_threads();
     774                 :          6 :         CU_ASSERT(g_destroy_cb_calls == 0);
     775                 :            : 
     776                 :          6 :         g_create_cb_calls = 0;
     777                 :          6 :         ch2 = spdk_get_io_channel(&g_device2);
     778                 :          6 :         CU_ASSERT(g_create_cb_calls == 1);
     779                 :          6 :         CU_ASSERT(ch1 != ch2);
     780         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch2 != NULL);
     781                 :          6 :         CU_ASSERT(spdk_io_channel_get_io_device(ch2) == &g_device2);
     782                 :            : 
     783                 :          6 :         ctx = spdk_io_channel_get_ctx(ch2);
     784                 :          6 :         CU_ASSERT(*(uint64_t *)ctx == g_ctx2);
     785                 :            : 
     786                 :          6 :         g_destroy_cb_calls = 0;
     787                 :          6 :         spdk_put_io_channel(ch1);
     788                 :          6 :         poll_threads();
     789                 :          6 :         CU_ASSERT(g_destroy_cb_calls == 1);
     790                 :            : 
     791                 :          6 :         g_destroy_cb_calls = 0;
     792                 :          6 :         spdk_put_io_channel(ch2);
     793                 :          6 :         poll_threads();
     794                 :          6 :         CU_ASSERT(g_destroy_cb_calls == 1);
     795                 :            : 
     796                 :          6 :         ch1 = spdk_get_io_channel(&g_device3);
     797                 :          6 :         CU_ASSERT(ch1 == NULL);
     798                 :            : 
     799                 :          6 :         spdk_io_device_unregister(&g_device1, NULL);
     800                 :          6 :         poll_threads();
     801                 :          6 :         spdk_io_device_unregister(&g_device2, NULL);
     802                 :          6 :         poll_threads();
     803                 :          6 :         CU_ASSERT(RB_EMPTY(&g_io_devices));
     804                 :          6 :         free_threads();
     805                 :          6 :         CU_ASSERT(TAILQ_EMPTY(&g_threads));
     806                 :          6 : }
     807                 :            : 
     808                 :            : static int
     809                 :          6 : create_cb(void *io_device, void *ctx_buf)
     810                 :            : {
     811                 :          6 :         uint64_t *refcnt = (uint64_t *)ctx_buf;
     812                 :            : 
     813                 :          6 :         CU_ASSERT(*refcnt == 0);
     814                 :          6 :         *refcnt = 1;
     815                 :            : 
     816                 :          6 :         return 0;
     817                 :            : }
     818                 :            : 
     819                 :            : static void
     820                 :          6 : destroy_cb(void *io_device, void *ctx_buf)
     821                 :            : {
     822                 :          6 :         uint64_t *refcnt = (uint64_t *)ctx_buf;
     823                 :            : 
     824                 :          6 :         CU_ASSERT(*refcnt == 1);
     825                 :          6 :         *refcnt = 0;
     826                 :          6 : }
     827                 :            : 
     828                 :            : /**
     829                 :            :  * This test is checking that a sequence of get, put, get, put without allowing
     830                 :            :  * the deferred put operation to complete doesn't result in releasing the memory
     831                 :            :  * for the channel twice.
     832                 :            :  */
     833                 :            : static void
     834                 :          6 : channel_destroy_races(void)
     835                 :            : {
     836                 :          5 :         uint64_t device;
     837                 :            :         struct spdk_io_channel *ch;
     838                 :            : 
     839                 :          6 :         allocate_threads(1);
     840                 :          6 :         set_thread(0);
     841                 :            : 
     842                 :          6 :         spdk_io_device_register(&device, create_cb, destroy_cb, sizeof(uint64_t), NULL);
     843                 :            : 
     844                 :          6 :         ch = spdk_get_io_channel(&device);
     845         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
     846                 :            : 
     847                 :          6 :         spdk_put_io_channel(ch);
     848                 :            : 
     849                 :          6 :         ch = spdk_get_io_channel(&device);
     850         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
     851                 :            : 
     852                 :          6 :         spdk_put_io_channel(ch);
     853                 :          6 :         poll_threads();
     854                 :            : 
     855                 :          6 :         spdk_io_device_unregister(&device, NULL);
     856                 :          6 :         poll_threads();
     857                 :            : 
     858                 :          6 :         CU_ASSERT(RB_EMPTY(&g_io_devices));
     859                 :          6 :         free_threads();
     860                 :          6 :         CU_ASSERT(TAILQ_EMPTY(&g_threads));
     861                 :          6 : }
     862                 :            : 
     863                 :            : static void
     864                 :          6 : thread_exit_test(void)
     865                 :            : {
     866                 :            :         struct spdk_thread *thread;
     867                 :            :         struct spdk_io_channel *ch;
     868                 :          5 :         struct spdk_poller *poller1, *poller2;
     869                 :            :         void *ctx;
     870                 :          6 :         bool done1 = false, done2 = false, poller1_run = false, poller2_run = false;
     871                 :            :         int rc __attribute__((unused));
     872                 :            : 
     873                 :          6 :         MOCK_SET(spdk_get_ticks, 10);
     874                 :          6 :         MOCK_SET(spdk_get_ticks_hz, 1);
     875                 :            : 
     876                 :          6 :         allocate_threads(4);
     877                 :            : 
     878                 :            :         /* Test if all pending messages are reaped for the exiting thread, and the
     879                 :            :          * thread moves to the exited state.
     880                 :            :          */
     881                 :          6 :         set_thread(0);
     882                 :          6 :         thread = spdk_get_thread();
     883                 :            : 
     884                 :            :         /* Sending message to thread 0 will be accepted. */
     885                 :          6 :         rc = spdk_thread_send_msg(thread, send_msg_cb, &done1);
     886                 :          6 :         CU_ASSERT(rc == 0);
     887         [ -  + ]:          6 :         CU_ASSERT(!done1);
     888                 :            : 
     889                 :            :         /* Move thread 0 to the exiting state. */
     890                 :          6 :         spdk_thread_exit(thread);
     891                 :            : 
     892                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == false);
     893                 :            : 
     894                 :            :         /* Sending message to thread 0 will be still accepted. */
     895                 :          6 :         rc = spdk_thread_send_msg(thread, send_msg_cb, &done2);
     896                 :          6 :         CU_ASSERT(rc == 0);
     897                 :            : 
     898                 :            :         /* Thread 0 will reap pending messages. */
     899                 :          6 :         poll_thread(0);
     900         [ -  + ]:          6 :         CU_ASSERT(done1 == true);
     901         [ -  + ]:          6 :         CU_ASSERT(done2 == true);
     902                 :            : 
     903                 :            :         /* Thread 0 will move to the exited state. */
     904                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == true);
     905                 :            : 
     906                 :            :         /* Test releasing I/O channel is reaped even after the thread moves to
     907                 :            :          * the exiting state
     908                 :            :          */
     909                 :          6 :         set_thread(1);
     910                 :            : 
     911                 :          6 :         spdk_io_device_register(&g_device1, create_cb_1, destroy_cb_1, sizeof(g_ctx1), NULL);
     912                 :            : 
     913                 :          6 :         g_create_cb_calls = 0;
     914                 :          6 :         ch = spdk_get_io_channel(&g_device1);
     915                 :          6 :         CU_ASSERT(g_create_cb_calls == 1);
     916         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
     917                 :            : 
     918                 :          6 :         ctx = spdk_io_channel_get_ctx(ch);
     919                 :          6 :         CU_ASSERT(*(uint64_t *)ctx == g_ctx1);
     920                 :            : 
     921                 :          6 :         g_destroy_cb_calls = 0;
     922                 :          6 :         spdk_put_io_channel(ch);
     923                 :            : 
     924                 :          6 :         thread = spdk_get_thread();
     925                 :          6 :         spdk_thread_exit(thread);
     926                 :            : 
     927                 :            :         /* Thread 1 will not move to the exited state yet because I/O channel release
     928                 :            :          * does not complete yet.
     929                 :            :          */
     930                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == false);
     931                 :            : 
     932                 :            :         /* Thread 1 will be able to get the another reference of I/O channel
     933                 :            :          * even after the thread moves to the exiting state.
     934                 :            :          */
     935                 :          6 :         g_create_cb_calls = 0;
     936                 :          6 :         ch = spdk_get_io_channel(&g_device1);
     937                 :            : 
     938                 :          6 :         CU_ASSERT(g_create_cb_calls == 0);
     939         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
     940                 :            : 
     941                 :          6 :         ctx = spdk_io_channel_get_ctx(ch);
     942                 :          6 :         CU_ASSERT(*(uint64_t *)ctx == g_ctx1);
     943                 :            : 
     944                 :          6 :         spdk_put_io_channel(ch);
     945                 :            : 
     946                 :          6 :         poll_threads();
     947                 :          6 :         CU_ASSERT(g_destroy_cb_calls == 1);
     948                 :            : 
     949                 :            :         /* Thread 1 will move to the exited state after I/O channel is released.
     950                 :            :          * are released.
     951                 :            :          */
     952                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == true);
     953                 :            : 
     954                 :          6 :         spdk_io_device_unregister(&g_device1, NULL);
     955                 :          6 :         poll_threads();
     956                 :            : 
     957                 :            :         /* Test if unregistering poller is reaped for the exiting thread, and the
     958                 :            :          * thread moves to the exited thread.
     959                 :            :          */
     960                 :          6 :         set_thread(2);
     961                 :          6 :         thread = spdk_get_thread();
     962                 :            : 
     963                 :          6 :         poller1 = spdk_poller_register(poller_run_done, &poller1_run, 0);
     964                 :          6 :         CU_ASSERT(poller1 != NULL);
     965                 :            : 
     966                 :          6 :         spdk_poller_unregister(&poller1);
     967                 :            : 
     968                 :          6 :         spdk_thread_exit(thread);
     969                 :            : 
     970                 :          6 :         poller2 = spdk_poller_register(poller_run_done, &poller2_run, 0);
     971                 :            : 
     972                 :          6 :         poll_threads();
     973                 :            : 
     974         [ -  + ]:          6 :         CU_ASSERT(poller1_run == false);
     975         [ -  + ]:          6 :         CU_ASSERT(poller2_run == true);
     976                 :            : 
     977                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == false);
     978                 :            : 
     979                 :          6 :         spdk_poller_unregister(&poller2);
     980                 :            : 
     981                 :          6 :         poll_threads();
     982                 :            : 
     983                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == true);
     984                 :            : 
     985                 :            :         /* Test if the exiting thread is exited forcefully after timeout. */
     986                 :          6 :         set_thread(3);
     987                 :          6 :         thread = spdk_get_thread();
     988                 :            : 
     989                 :          6 :         poller1 = spdk_poller_register(poller_run_done, &poller1_run, 0);
     990                 :          6 :         CU_ASSERT(poller1 != NULL);
     991                 :            : 
     992                 :          6 :         spdk_thread_exit(thread);
     993                 :            : 
     994                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == false);
     995                 :            : 
     996                 :          6 :         MOCK_SET(spdk_get_ticks, 11);
     997                 :            : 
     998                 :          6 :         poll_threads();
     999                 :            : 
    1000                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == false);
    1001                 :            : 
    1002                 :            :         /* Cause timeout forcefully. */
    1003                 :          6 :         MOCK_SET(spdk_get_ticks, 15);
    1004                 :            : 
    1005                 :          6 :         poll_threads();
    1006                 :            : 
    1007                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == true);
    1008                 :            : 
    1009                 :          6 :         spdk_poller_unregister(&poller1);
    1010                 :            : 
    1011                 :          6 :         poll_threads();
    1012                 :            : 
    1013   [ -  -  -  + ]:          6 :         MOCK_CLEAR(spdk_get_ticks);
    1014   [ -  -  -  + ]:          6 :         MOCK_CLEAR(spdk_get_ticks_hz);
    1015                 :            : 
    1016                 :          6 :         free_threads();
    1017                 :          6 : }
    1018                 :            : 
    1019                 :            : static int
    1020                 :         12 : poller_run_idle(void *ctx)
    1021                 :            : {
    1022                 :         12 :         uint64_t delay_us = (uint64_t)ctx;
    1023                 :            : 
    1024                 :         12 :         spdk_delay_us(delay_us);
    1025                 :            : 
    1026                 :         12 :         return 0;
    1027                 :            : }
    1028                 :            : 
    1029                 :            : static int
    1030                 :         12 : poller_run_busy(void *ctx)
    1031                 :            : {
    1032                 :         12 :         uint64_t delay_us = (uint64_t)ctx;
    1033                 :            : 
    1034                 :         12 :         spdk_delay_us(delay_us);
    1035                 :            : 
    1036                 :         12 :         return 1;
    1037                 :            : }
    1038                 :            : 
    1039                 :            : static void
    1040                 :          6 : thread_update_stats_test(void)
    1041                 :            : {
    1042                 :          5 :         struct spdk_poller      *poller;
    1043                 :            :         struct spdk_thread      *thread;
    1044                 :            : 
    1045                 :          6 :         MOCK_SET(spdk_get_ticks, 10);
    1046                 :            : 
    1047                 :          6 :         allocate_threads(1);
    1048                 :            : 
    1049                 :          6 :         set_thread(0);
    1050                 :          6 :         thread = spdk_get_thread();
    1051                 :            : 
    1052                 :          6 :         CU_ASSERT(thread->tsc_last == 10);
    1053                 :          6 :         CU_ASSERT(thread->stats.idle_tsc == 0);
    1054                 :          6 :         CU_ASSERT(thread->stats.busy_tsc == 0);
    1055                 :            : 
    1056                 :            :         /* Test if idle_tsc is updated expectedly. */
    1057                 :          6 :         poller = spdk_poller_register(poller_run_idle, (void *)1000, 0);
    1058                 :          6 :         CU_ASSERT(poller != NULL);
    1059                 :            : 
    1060                 :          6 :         spdk_delay_us(100);
    1061                 :            : 
    1062                 :          6 :         poll_thread_times(0, 1);
    1063                 :            : 
    1064                 :          6 :         CU_ASSERT(thread->tsc_last == 1110);
    1065                 :          6 :         CU_ASSERT(thread->stats.idle_tsc == 1000);
    1066                 :          6 :         CU_ASSERT(thread->stats.busy_tsc == 0);
    1067                 :            : 
    1068                 :          6 :         spdk_delay_us(100);
    1069                 :            : 
    1070                 :          6 :         poll_thread_times(0, 1);
    1071                 :            : 
    1072                 :          6 :         CU_ASSERT(thread->tsc_last == 2210);
    1073                 :          6 :         CU_ASSERT(thread->stats.idle_tsc == 2000);
    1074                 :          6 :         CU_ASSERT(thread->stats.busy_tsc == 0);
    1075                 :            : 
    1076                 :          6 :         spdk_poller_unregister(&poller);
    1077                 :            : 
    1078                 :            :         /* Test if busy_tsc is updated expectedly. */
    1079                 :          6 :         poller = spdk_poller_register(poller_run_busy, (void *)100000, 0);
    1080                 :          6 :         CU_ASSERT(poller != NULL);
    1081                 :            : 
    1082                 :          6 :         spdk_delay_us(10000);
    1083                 :            : 
    1084                 :          6 :         poll_thread_times(0, 1);
    1085                 :            : 
    1086                 :          6 :         CU_ASSERT(thread->tsc_last == 112210);
    1087                 :          6 :         CU_ASSERT(thread->stats.idle_tsc == 2000);
    1088                 :          6 :         CU_ASSERT(thread->stats.busy_tsc == 100000);
    1089                 :            : 
    1090                 :          6 :         spdk_delay_us(10000);
    1091                 :            : 
    1092                 :          6 :         poll_thread_times(0, 1);
    1093                 :            : 
    1094                 :          6 :         CU_ASSERT(thread->tsc_last == 222210);
    1095                 :          6 :         CU_ASSERT(thread->stats.idle_tsc == 2000);
    1096                 :          6 :         CU_ASSERT(thread->stats.busy_tsc == 200000);
    1097                 :            : 
    1098                 :          6 :         spdk_poller_unregister(&poller);
    1099                 :            : 
    1100   [ -  -  -  + ]:          6 :         MOCK_CLEAR(spdk_get_ticks);
    1101                 :            : 
    1102                 :          6 :         free_threads();
    1103                 :          6 : }
    1104                 :            : 
    1105                 :            : struct ut_nested_ch {
    1106                 :            :         struct spdk_io_channel *child;
    1107                 :            :         struct spdk_poller *poller;
    1108                 :            : };
    1109                 :            : 
    1110                 :            : struct ut_nested_dev {
    1111                 :            :         struct ut_nested_dev *child;
    1112                 :            : };
    1113                 :            : 
    1114                 :            : static int
    1115                 :         36 : ut_null_poll(void *ctx)
    1116                 :            : {
    1117                 :         36 :         return -1;
    1118                 :            : }
    1119                 :            : 
    1120                 :            : static int
    1121                 :         18 : ut_nested_ch_create_cb(void *io_device, void *ctx_buf)
    1122                 :            : {
    1123                 :         18 :         struct ut_nested_ch *_ch = ctx_buf;
    1124                 :         18 :         struct ut_nested_dev *_dev = io_device;
    1125                 :            :         struct ut_nested_dev *_child;
    1126                 :            : 
    1127                 :         18 :         _child = _dev->child;
    1128                 :            : 
    1129         [ +  + ]:         18 :         if (_child != NULL) {
    1130                 :         12 :                 _ch->child = spdk_get_io_channel(_child);
    1131         [ -  + ]:         12 :                 SPDK_CU_ASSERT_FATAL(_ch->child != NULL);
    1132                 :            :         } else {
    1133                 :          6 :                 _ch->child = NULL;
    1134                 :            :         }
    1135                 :            : 
    1136                 :         18 :         _ch->poller = spdk_poller_register(ut_null_poll, NULL, 0);
    1137         [ -  + ]:         18 :         SPDK_CU_ASSERT_FATAL(_ch->poller != NULL);
    1138                 :            : 
    1139                 :         18 :         return 0;
    1140                 :            : }
    1141                 :            : 
    1142                 :            : static void
    1143                 :         18 : ut_nested_ch_destroy_cb(void *io_device, void *ctx_buf)
    1144                 :            : {
    1145                 :         18 :         struct ut_nested_ch *_ch = ctx_buf;
    1146                 :            :         struct spdk_io_channel *child;
    1147                 :            : 
    1148                 :         18 :         child = _ch->child;
    1149         [ +  + ]:         18 :         if (child != NULL) {
    1150                 :         12 :                 spdk_put_io_channel(child);
    1151                 :            :         }
    1152                 :            : 
    1153                 :         18 :         spdk_poller_unregister(&_ch->poller);
    1154                 :         18 : }
    1155                 :            : 
    1156                 :            : static void
    1157                 :         18 : ut_check_nested_ch_create(struct spdk_io_channel *ch, struct io_device *dev)
    1158                 :            : {
    1159                 :         18 :         CU_ASSERT(ch->ref == 1);
    1160                 :         18 :         CU_ASSERT(ch->dev == dev);
    1161                 :         18 :         CU_ASSERT(dev->refcnt == 1);
    1162                 :         18 : }
    1163                 :            : 
    1164                 :            : static void
    1165                 :         18 : ut_check_nested_ch_destroy_pre(struct spdk_io_channel *ch, struct io_device *dev)
    1166                 :            : {
    1167                 :         18 :         CU_ASSERT(ch->ref == 0);
    1168                 :         18 :         CU_ASSERT(ch->destroy_ref == 1);
    1169                 :         18 :         CU_ASSERT(dev->refcnt == 1);
    1170                 :         18 : }
    1171                 :            : 
    1172                 :            : static void
    1173                 :         18 : ut_check_nested_ch_destroy_post(struct io_device *dev)
    1174                 :            : {
    1175                 :         18 :         CU_ASSERT(dev->refcnt == 0);
    1176                 :         18 : }
    1177                 :            : 
    1178                 :            : static void
    1179                 :         24 : ut_check_nested_poller_register(struct spdk_poller *poller)
    1180                 :            : {
    1181         [ -  + ]:         24 :         SPDK_CU_ASSERT_FATAL(poller != NULL);
    1182                 :         24 : }
    1183                 :            : 
    1184                 :            : static void
    1185                 :          6 : nested_channel(void)
    1186                 :            : {
    1187                 :          5 :         struct ut_nested_dev _dev1, _dev2, _dev3;
    1188                 :            :         struct ut_nested_ch *_ch1, *_ch2, *_ch3;
    1189                 :            :         struct io_device *dev1, *dev2, *dev3;
    1190                 :            :         struct spdk_io_channel *ch1, *ch2, *ch3;
    1191                 :          5 :         struct spdk_poller *poller;
    1192                 :            :         struct spdk_thread *thread;
    1193                 :            : 
    1194                 :          6 :         allocate_threads(1);
    1195                 :          6 :         set_thread(0);
    1196                 :            : 
    1197                 :          6 :         thread = spdk_get_thread();
    1198         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
    1199                 :            : 
    1200                 :          6 :         _dev1.child = &_dev2;
    1201                 :          6 :         _dev2.child = &_dev3;
    1202                 :          6 :         _dev3.child = NULL;
    1203                 :            : 
    1204                 :          6 :         spdk_io_device_register(&_dev1, ut_nested_ch_create_cb, ut_nested_ch_destroy_cb,
    1205                 :            :                                 sizeof(struct ut_nested_ch), "dev1");
    1206                 :          6 :         spdk_io_device_register(&_dev2, ut_nested_ch_create_cb, ut_nested_ch_destroy_cb,
    1207                 :            :                                 sizeof(struct ut_nested_ch), "dev2");
    1208                 :          6 :         spdk_io_device_register(&_dev3, ut_nested_ch_create_cb, ut_nested_ch_destroy_cb,
    1209                 :            :                                 sizeof(struct ut_nested_ch), "dev3");
    1210                 :            : 
    1211                 :          6 :         dev1 = io_device_get(&_dev1);
    1212         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev1 != NULL);
    1213                 :          6 :         dev2 = io_device_get(&_dev2);
    1214         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev2 != NULL);
    1215                 :          6 :         dev3 = io_device_get(&_dev3);
    1216         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev3 != NULL);
    1217                 :            : 
    1218                 :            :         /* A single call spdk_get_io_channel() to dev1 will also create channels
    1219                 :            :          * to dev2 and dev3 continuously. Pollers will be registered together.
    1220                 :            :          */
    1221                 :          6 :         ch1 = spdk_get_io_channel(&_dev1);
    1222         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch1 != NULL);
    1223                 :            : 
    1224                 :          6 :         _ch1 = spdk_io_channel_get_ctx(ch1);
    1225                 :          6 :         ch2 = _ch1->child;
    1226         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch2 != NULL);
    1227                 :            : 
    1228                 :          6 :         _ch2 = spdk_io_channel_get_ctx(ch2);
    1229                 :          6 :         ch3 = _ch2->child;
    1230         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch3 != NULL);
    1231                 :            : 
    1232                 :          6 :         _ch3 = spdk_io_channel_get_ctx(ch3);
    1233                 :          6 :         CU_ASSERT(_ch3->child == NULL);
    1234                 :            : 
    1235                 :          6 :         ut_check_nested_ch_create(ch1, dev1);
    1236                 :          6 :         ut_check_nested_ch_create(ch2, dev2);
    1237                 :          6 :         ut_check_nested_ch_create(ch3, dev3);
    1238                 :            : 
    1239                 :          6 :         poller = spdk_poller_register(ut_null_poll, NULL, 0);
    1240                 :            : 
    1241                 :          6 :         ut_check_nested_poller_register(poller);
    1242                 :          6 :         ut_check_nested_poller_register(_ch1->poller);
    1243                 :          6 :         ut_check_nested_poller_register(_ch2->poller);
    1244                 :          6 :         ut_check_nested_poller_register(_ch3->poller);
    1245                 :            : 
    1246                 :          6 :         spdk_poller_unregister(&poller);
    1247                 :          6 :         poll_thread_times(0, 1);
    1248                 :            : 
    1249                 :            :         /* A single call spdk_put_io_channel() to dev1 will also destroy channels
    1250                 :            :          * to dev2 and dev3 continuously. Pollers will be unregistered together.
    1251                 :            :          */
    1252                 :          6 :         spdk_put_io_channel(ch1);
    1253                 :            : 
    1254                 :            :         /* Start exiting the current thread after unregistering the non-nested
    1255                 :            :          * I/O channel.
    1256                 :            :          */
    1257                 :          6 :         spdk_thread_exit(thread);
    1258                 :            : 
    1259                 :          6 :         ut_check_nested_ch_destroy_pre(ch1, dev1);
    1260                 :          6 :         poll_thread_times(0, 1);
    1261                 :          6 :         ut_check_nested_ch_destroy_post(dev1);
    1262                 :            : 
    1263                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == false);
    1264                 :            : 
    1265                 :          6 :         ut_check_nested_ch_destroy_pre(ch2, dev2);
    1266                 :          6 :         poll_thread_times(0, 1);
    1267                 :          6 :         ut_check_nested_ch_destroy_post(dev2);
    1268                 :            : 
    1269                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == false);
    1270                 :            : 
    1271                 :          6 :         ut_check_nested_ch_destroy_pre(ch3, dev3);
    1272                 :          6 :         poll_thread_times(0, 1);
    1273                 :          6 :         ut_check_nested_ch_destroy_post(dev3);
    1274                 :            : 
    1275                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread) == true);
    1276                 :            : 
    1277                 :          6 :         spdk_io_device_unregister(&_dev1, NULL);
    1278                 :          6 :         spdk_io_device_unregister(&_dev2, NULL);
    1279                 :          6 :         spdk_io_device_unregister(&_dev3, NULL);
    1280                 :          6 :         CU_ASSERT(RB_EMPTY(&g_io_devices));
    1281                 :            : 
    1282                 :          6 :         free_threads();
    1283                 :          6 :         CU_ASSERT(TAILQ_EMPTY(&g_threads));
    1284                 :          6 : }
    1285                 :            : 
    1286                 :            : static int
    1287                 :         12 : create_cb2(void *io_device, void *ctx_buf)
    1288                 :            : {
    1289                 :         12 :         uint64_t *devcnt = (uint64_t *)io_device;
    1290                 :            : 
    1291                 :         12 :         *devcnt += 1;
    1292                 :            : 
    1293                 :         12 :         return 0;
    1294                 :            : }
    1295                 :            : 
    1296                 :            : static void
    1297                 :         12 : destroy_cb2(void *io_device, void *ctx_buf)
    1298                 :            : {
    1299                 :         12 :         uint64_t *devcnt = (uint64_t *)io_device;
    1300                 :            : 
    1301                 :         12 :         CU_ASSERT(*devcnt > 0);
    1302                 :         12 :         *devcnt -= 1;
    1303                 :         12 : }
    1304                 :            : 
    1305                 :            : static void
    1306                 :          6 : unregister_cb2(void *io_device)
    1307                 :            : {
    1308                 :          6 :         uint64_t *devcnt = (uint64_t *)io_device;
    1309                 :            : 
    1310                 :          6 :         CU_ASSERT(*devcnt == 0);
    1311                 :          6 : }
    1312                 :            : 
    1313                 :            : static void
    1314                 :          6 : device_unregister_and_thread_exit_race(void)
    1315                 :            : {
    1316                 :          6 :         uint64_t device = 0;
    1317                 :            :         struct spdk_io_channel *ch1, *ch2;
    1318                 :            :         struct spdk_thread *thread1, *thread2;
    1319                 :            : 
    1320                 :            :         /* Create two threads and each thread gets a channel from the same device. */
    1321                 :          6 :         allocate_threads(2);
    1322                 :          6 :         set_thread(0);
    1323                 :            : 
    1324                 :          6 :         thread1 = spdk_get_thread();
    1325         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread1 != NULL);
    1326                 :            : 
    1327                 :          6 :         spdk_io_device_register(&device, create_cb2, destroy_cb2, sizeof(uint64_t), NULL);
    1328                 :            : 
    1329                 :          6 :         ch1 = spdk_get_io_channel(&device);
    1330         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch1 != NULL);
    1331                 :            : 
    1332                 :          6 :         set_thread(1);
    1333                 :            : 
    1334                 :          6 :         thread2 = spdk_get_thread();
    1335         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread2 != NULL);
    1336                 :            : 
    1337                 :          6 :         ch2 = spdk_get_io_channel(&device);
    1338         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch2 != NULL);
    1339                 :            : 
    1340                 :          6 :         set_thread(0);
    1341                 :            : 
    1342                 :            :         /* Move thread 0 to the exiting state, but it should keep exiting until two channels
    1343                 :            :          * and a device are released.
    1344                 :            :          */
    1345                 :          6 :         spdk_thread_exit(thread1);
    1346                 :          6 :         poll_thread(0);
    1347                 :            : 
    1348                 :          6 :         spdk_put_io_channel(ch1);
    1349                 :            : 
    1350                 :          6 :         spdk_io_device_unregister(&device, unregister_cb2);
    1351                 :          6 :         poll_thread(0);
    1352                 :            : 
    1353                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread1) == false);
    1354                 :            : 
    1355                 :          6 :         set_thread(1);
    1356                 :            : 
    1357                 :            :         /* Move thread 1 to the exiting state, but it should keep exiting until its channel
    1358                 :            :          * is released.
    1359                 :            :          */
    1360                 :          6 :         spdk_thread_exit(thread2);
    1361                 :          6 :         poll_thread(1);
    1362                 :            : 
    1363                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread2) == false);
    1364                 :            : 
    1365                 :          6 :         spdk_put_io_channel(ch2);
    1366                 :          6 :         poll_thread(1);
    1367                 :            : 
    1368                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread1) == false);
    1369                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread2) == true);
    1370                 :            : 
    1371                 :          6 :         poll_thread(0);
    1372                 :            : 
    1373                 :          6 :         CU_ASSERT(spdk_thread_is_exited(thread1) == true);
    1374                 :            : 
    1375                 :          6 :         free_threads();
    1376                 :          6 : }
    1377                 :            : 
    1378                 :            : static int
    1379                 :         66 : dummy_poller(void *arg)
    1380                 :            : {
    1381                 :         66 :         return SPDK_POLLER_IDLE;
    1382                 :            : }
    1383                 :            : 
    1384                 :            : static void
    1385                 :          6 : cache_closest_timed_poller(void)
    1386                 :            : {
    1387                 :            :         struct spdk_thread *thread;
    1388                 :          5 :         struct spdk_poller *poller1, *poller2, *poller3, *tmp;
    1389                 :            : 
    1390                 :          6 :         allocate_threads(1);
    1391                 :          6 :         set_thread(0);
    1392                 :            : 
    1393                 :          6 :         thread = spdk_get_thread();
    1394         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
    1395                 :            : 
    1396                 :          6 :         poller1 = spdk_poller_register(dummy_poller, NULL, 1000);
    1397         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller1 != NULL);
    1398                 :            : 
    1399                 :          6 :         poller2 = spdk_poller_register(dummy_poller, NULL, 1500);
    1400         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller2 != NULL);
    1401                 :            : 
    1402                 :          6 :         poller3 = spdk_poller_register(dummy_poller, NULL, 1800);
    1403         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller3 != NULL);
    1404                 :            : 
    1405                 :          6 :         poll_threads();
    1406                 :            : 
    1407                 :            :         /* When multiple timed pollers are inserted, the cache should
    1408                 :            :          * have the closest timed poller.
    1409                 :            :          */
    1410                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller1);
    1411                 :          6 :         CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller1);
    1412                 :            : 
    1413                 :          6 :         spdk_delay_us(1000);
    1414                 :          6 :         poll_threads();
    1415                 :            : 
    1416                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller2);
    1417                 :          6 :         CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller2);
    1418                 :            : 
    1419                 :            :         /* If we unregister a timed poller by spdk_poller_unregister()
    1420                 :            :          * when it is waiting, it is marked as being unregistered and
    1421                 :            :          * is actually unregistered when it is expired.
    1422                 :            :          *
    1423                 :            :          * Hence if we unregister the closest timed poller when it is waiting,
    1424                 :            :          * the cache is not updated to the next timed poller until it is expired.
    1425                 :            :          */
    1426                 :          6 :         tmp = poller2;
    1427                 :            : 
    1428                 :          6 :         spdk_poller_unregister(&poller2);
    1429                 :          6 :         CU_ASSERT(poller2 == NULL);
    1430                 :            : 
    1431                 :          6 :         spdk_delay_us(499);
    1432                 :          6 :         poll_threads();
    1433                 :            : 
    1434                 :          6 :         CU_ASSERT(thread->first_timed_poller == tmp);
    1435                 :          6 :         CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == tmp);
    1436                 :            : 
    1437                 :          6 :         spdk_delay_us(1);
    1438                 :          6 :         poll_threads();
    1439                 :            : 
    1440                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller3);
    1441                 :          6 :         CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller3);
    1442                 :            : 
    1443                 :            :         /* If we pause a timed poller by spdk_poller_pause() when it is waiting,
    1444                 :            :          * it is marked as being paused and is actually paused when it is expired.
    1445                 :            :          *
    1446                 :            :          * Hence if we pause the closest timed poller when it is waiting, the cache
    1447                 :            :          * is not updated to the next timed poller until it is expired.
    1448                 :            :          */
    1449                 :          6 :         spdk_poller_pause(poller3);
    1450                 :            : 
    1451                 :          6 :         spdk_delay_us(299);
    1452                 :          6 :         poll_threads();
    1453                 :            : 
    1454                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller3);
    1455                 :          6 :         CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller3);
    1456                 :            : 
    1457                 :          6 :         spdk_delay_us(1);
    1458                 :          6 :         poll_threads();
    1459                 :            : 
    1460                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller1);
    1461                 :          6 :         CU_ASSERT(RB_MIN(timed_pollers_tree, &thread->timed_pollers) == poller1);
    1462                 :            : 
    1463                 :            :         /* After unregistering all timed pollers, the cache should
    1464                 :            :          * be NULL.
    1465                 :            :          */
    1466                 :          6 :         spdk_poller_unregister(&poller1);
    1467                 :          6 :         spdk_poller_unregister(&poller3);
    1468                 :            : 
    1469                 :          6 :         spdk_delay_us(200);
    1470                 :          6 :         poll_threads();
    1471                 :            : 
    1472                 :          6 :         CU_ASSERT(thread->first_timed_poller == NULL);
    1473                 :          6 :         CU_ASSERT(RB_EMPTY(&thread->timed_pollers));
    1474                 :            : 
    1475                 :          6 :         free_threads();
    1476                 :          6 : }
    1477                 :            : 
    1478                 :            : static void
    1479                 :          6 : multi_timed_pollers_have_same_expiration(void)
    1480                 :            : {
    1481                 :            :         struct spdk_thread *thread;
    1482                 :          5 :         struct spdk_poller *poller1, *poller2, *poller3, *poller4, *tmp;
    1483                 :            :         uint64_t start_ticks;
    1484                 :            : 
    1485                 :          6 :         allocate_threads(1);
    1486                 :          6 :         set_thread(0);
    1487                 :            : 
    1488                 :          6 :         thread = spdk_get_thread();
    1489         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(thread != NULL);
    1490                 :            : 
    1491                 :            :         /*
    1492                 :            :          * case 1: multiple timed pollers have the same next_run_tick.
    1493                 :            :          */
    1494                 :          6 :         start_ticks = spdk_get_ticks();
    1495                 :            : 
    1496                 :          6 :         poller1 = spdk_poller_register(dummy_poller, NULL, 500);
    1497         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller1 != NULL);
    1498                 :            : 
    1499                 :          6 :         poller2 = spdk_poller_register(dummy_poller, NULL, 500);
    1500         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller2 != NULL);
    1501                 :            : 
    1502                 :          6 :         poller3 = spdk_poller_register(dummy_poller, NULL, 1000);
    1503         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller3 != NULL);
    1504                 :            : 
    1505                 :          6 :         poller4 = spdk_poller_register(dummy_poller, NULL, 1500);
    1506         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller4 != NULL);
    1507                 :            : 
    1508                 :            :         /* poller1 and poller2 have the same next_run_tick but cache has poller1
    1509                 :            :          * because poller1 is registered earlier than poller2.
    1510                 :            :          */
    1511                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller1);
    1512                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 500);
    1513                 :          6 :         CU_ASSERT(poller2->next_run_tick == start_ticks + 500);
    1514                 :          6 :         CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
    1515                 :          6 :         CU_ASSERT(poller4->next_run_tick == start_ticks + 1500);
    1516                 :            : 
    1517                 :            :         /* after 500 usec, poller1 and poller2 are expired. */
    1518                 :          6 :         spdk_delay_us(500);
    1519                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 500);
    1520                 :          6 :         poll_threads();
    1521                 :            : 
    1522                 :            :         /* poller1, poller2, and poller3 have the same next_run_tick but cache
    1523                 :            :          * has poller3 because poller3 is not expired yet.
    1524                 :            :          */
    1525                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller3);
    1526                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 1000);
    1527                 :          6 :         CU_ASSERT(poller2->next_run_tick == start_ticks + 1000);
    1528                 :          6 :         CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
    1529                 :          6 :         CU_ASSERT(poller4->next_run_tick == start_ticks + 1500);
    1530                 :            : 
    1531                 :            :         /* after 500 usec, poller1, poller2, and poller3 are expired. */
    1532                 :          6 :         spdk_delay_us(500);
    1533                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 1000);
    1534                 :          6 :         poll_threads();
    1535                 :            : 
    1536                 :            :         /* poller1, poller2, and poller4 have the same next_run_tick but cache
    1537                 :            :          * has poller4 because poller4 is not expired yet.
    1538                 :            :          */
    1539                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller4);
    1540                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 1500);
    1541                 :          6 :         CU_ASSERT(poller2->next_run_tick == start_ticks + 1500);
    1542                 :          6 :         CU_ASSERT(poller3->next_run_tick == start_ticks + 2000);
    1543                 :          6 :         CU_ASSERT(poller4->next_run_tick == start_ticks + 1500);
    1544                 :            : 
    1545                 :            :         /* after 500 usec, poller1, poller2, and poller4 are expired. */
    1546                 :          6 :         spdk_delay_us(500);
    1547                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 1500);
    1548                 :          6 :         poll_threads();
    1549                 :            : 
    1550                 :            :         /* poller1, poller2, and poller3 have the same next_run_tick but cache
    1551                 :            :          * has poller3 because poller3 is updated earlier than poller1 and poller2.
    1552                 :            :          */
    1553                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller3);
    1554                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 2000);
    1555                 :          6 :         CU_ASSERT(poller2->next_run_tick == start_ticks + 2000);
    1556                 :          6 :         CU_ASSERT(poller3->next_run_tick == start_ticks + 2000);
    1557                 :          6 :         CU_ASSERT(poller4->next_run_tick == start_ticks + 3000);
    1558                 :            : 
    1559                 :          6 :         spdk_poller_unregister(&poller1);
    1560                 :          6 :         spdk_poller_unregister(&poller2);
    1561                 :          6 :         spdk_poller_unregister(&poller3);
    1562                 :          6 :         spdk_poller_unregister(&poller4);
    1563                 :            : 
    1564                 :          6 :         spdk_delay_us(1500);
    1565                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 3000);
    1566                 :          6 :         poll_threads();
    1567                 :            : 
    1568                 :          6 :         CU_ASSERT(thread->first_timed_poller == NULL);
    1569                 :          6 :         CU_ASSERT(RB_EMPTY(&thread->timed_pollers));
    1570                 :            : 
    1571                 :            :         /*
    1572                 :            :          * case 2: unregister timed pollers while multiple timed pollers are registered.
    1573                 :            :          */
    1574                 :          6 :         start_ticks = spdk_get_ticks();
    1575                 :            : 
    1576                 :          6 :         poller1 = spdk_poller_register(dummy_poller, NULL, 500);
    1577         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller1 != NULL);
    1578                 :            : 
    1579                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller1);
    1580                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 500);
    1581                 :            : 
    1582                 :            :         /* after 250 usec, register poller2 and poller3. */
    1583                 :          6 :         spdk_delay_us(250);
    1584                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 250);
    1585                 :            : 
    1586                 :          6 :         poller2 = spdk_poller_register(dummy_poller, NULL, 500);
    1587         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller2 != NULL);
    1588                 :            : 
    1589                 :          6 :         poller3 = spdk_poller_register(dummy_poller, NULL, 750);
    1590         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(poller3 != NULL);
    1591                 :            : 
    1592                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller1);
    1593                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 500);
    1594                 :          6 :         CU_ASSERT(poller2->next_run_tick == start_ticks + 750);
    1595                 :          6 :         CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
    1596                 :            : 
    1597                 :            :         /* unregister poller2 which is not the closest. */
    1598                 :          6 :         tmp = poller2;
    1599                 :          6 :         spdk_poller_unregister(&poller2);
    1600                 :            : 
    1601                 :            :         /* after 250 usec, poller1 is expired. */
    1602                 :          6 :         spdk_delay_us(250);
    1603                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 500);
    1604                 :          6 :         poll_threads();
    1605                 :            : 
    1606                 :            :         /* poller2 is not unregistered yet because it is not expired. */
    1607                 :          6 :         CU_ASSERT(thread->first_timed_poller == tmp);
    1608                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 1000);
    1609                 :          6 :         CU_ASSERT(tmp->next_run_tick == start_ticks + 750);
    1610                 :          6 :         CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
    1611                 :            : 
    1612                 :          6 :         spdk_delay_us(250);
    1613                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 750);
    1614                 :          6 :         poll_threads();
    1615                 :            : 
    1616                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller3);
    1617                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 1000);
    1618                 :          6 :         CU_ASSERT(poller3->next_run_tick == start_ticks + 1000);
    1619                 :            : 
    1620                 :          6 :         spdk_poller_unregister(&poller3);
    1621                 :            : 
    1622                 :          6 :         spdk_delay_us(250);
    1623                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 1000);
    1624                 :          6 :         poll_threads();
    1625                 :            : 
    1626                 :          6 :         CU_ASSERT(thread->first_timed_poller == poller1);
    1627                 :          6 :         CU_ASSERT(poller1->next_run_tick == start_ticks + 1500);
    1628                 :            : 
    1629                 :          6 :         spdk_poller_unregister(&poller1);
    1630                 :            : 
    1631                 :          6 :         spdk_delay_us(500);
    1632                 :          6 :         CU_ASSERT(spdk_get_ticks() == start_ticks + 1500);
    1633                 :          6 :         poll_threads();
    1634                 :            : 
    1635                 :          6 :         CU_ASSERT(thread->first_timed_poller == NULL);
    1636                 :          6 :         CU_ASSERT(RB_EMPTY(&thread->timed_pollers));
    1637                 :            : 
    1638                 :          6 :         free_threads();
    1639                 :          6 : }
    1640                 :            : 
    1641                 :            : static int
    1642                 :         42 : dummy_create_cb(void *io_device, void *ctx_buf)
    1643                 :            : {
    1644                 :         42 :         return 0;
    1645                 :            : }
    1646                 :            : 
    1647                 :            : static void
    1648                 :         42 : dummy_destroy_cb(void *io_device, void *ctx_buf)
    1649                 :            : {
    1650                 :         42 : }
    1651                 :            : 
    1652                 :            : /* We had a bug that the compare function for the io_device tree
    1653                 :            :  * did not work as expected because subtraction caused overflow
    1654                 :            :  * when the difference between two keys was more than 32 bits.
    1655                 :            :  * This test case verifies the fix for the bug.
    1656                 :            :  */
    1657                 :            : static void
    1658                 :          6 : io_device_lookup(void)
    1659                 :            : {
    1660                 :          5 :         struct io_device dev1, dev2, *dev;
    1661                 :            :         struct spdk_io_channel *ch;
    1662                 :            : 
    1663                 :            :         /* The compare function io_device_cmp() had a overflow bug.
    1664                 :            :          * Verify the fix first.
    1665                 :            :          */
    1666                 :          6 :         dev1.io_device = (void *)0x7FFFFFFF;
    1667                 :          6 :         dev2.io_device = NULL;
    1668                 :          6 :         CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
    1669                 :          6 :         CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
    1670                 :            : 
    1671                 :            :         /* Check if overflow due to 32 bits does not occur. */
    1672                 :          6 :         dev1.io_device = (void *)0x80000000;
    1673                 :          6 :         CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
    1674                 :          6 :         CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
    1675                 :            : 
    1676                 :          6 :         dev1.io_device = (void *)0x100000000;
    1677                 :          6 :         CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
    1678                 :          6 :         CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
    1679                 :            : 
    1680                 :          6 :         dev1.io_device = (void *)0x8000000000000000;
    1681                 :          6 :         CU_ASSERT(io_device_cmp(&dev1, &dev2) > 0);
    1682                 :          6 :         CU_ASSERT(io_device_cmp(&dev2, &dev1) < 0);
    1683                 :            : 
    1684                 :          6 :         allocate_threads(1);
    1685                 :          6 :         set_thread(0);
    1686                 :            : 
    1687                 :          6 :         spdk_io_device_register((void *)0x1, dummy_create_cb, dummy_destroy_cb, 0, NULL);
    1688                 :          6 :         spdk_io_device_register((void *)0x7FFFFFFF, dummy_create_cb, dummy_destroy_cb, 0, NULL);
    1689                 :          6 :         spdk_io_device_register((void *)0x80000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
    1690                 :          6 :         spdk_io_device_register((void *)0x100000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
    1691                 :          6 :         spdk_io_device_register((void *)0x8000000000000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
    1692                 :          6 :         spdk_io_device_register((void *)0x8000000100000000, dummy_create_cb, dummy_destroy_cb, 0, NULL);
    1693                 :          6 :         spdk_io_device_register((void *)UINT64_MAX, dummy_create_cb, dummy_destroy_cb, 0, NULL);
    1694                 :            : 
    1695                 :            :         /* RB_MIN and RB_NEXT should return devs in ascending order by addresses.
    1696                 :            :          * RB_FOREACH uses RB_MIN and RB_NEXT internally.
    1697                 :            :          */
    1698                 :          6 :         dev = RB_MIN(io_device_tree, &g_io_devices);
    1699         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
    1700                 :          6 :         CU_ASSERT(dev->io_device == (void *)0x1);
    1701                 :            : 
    1702                 :          6 :         dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
    1703         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
    1704                 :          6 :         CU_ASSERT(dev->io_device == (void *)0x7FFFFFFF);
    1705                 :            : 
    1706                 :          6 :         dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
    1707         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
    1708                 :          6 :         CU_ASSERT(dev->io_device == (void *)0x80000000);
    1709                 :            : 
    1710                 :          6 :         dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
    1711         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
    1712                 :          6 :         CU_ASSERT(dev->io_device == (void *)0x100000000);
    1713                 :            : 
    1714                 :          6 :         dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
    1715         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
    1716                 :          6 :         CU_ASSERT(dev->io_device == (void *)0x8000000000000000);
    1717                 :            : 
    1718                 :          6 :         dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
    1719         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
    1720                 :          6 :         CU_ASSERT(dev->io_device == (void *)0x8000000100000000);
    1721                 :            : 
    1722                 :          6 :         dev = RB_NEXT(io_device_tree, &g_io_devices, dev);
    1723         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(dev != NULL);
    1724                 :          6 :         CU_ASSERT(dev->io_device == (void *)UINT64_MAX);
    1725                 :            : 
    1726                 :            :         /* Verify spdk_get_io_channel() creates io_channels associated with the
    1727                 :            :          * correct io_devices.
    1728                 :            :          */
    1729                 :          6 :         ch = spdk_get_io_channel((void *)0x1);
    1730         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
    1731                 :          6 :         CU_ASSERT(ch->dev->io_device == (void *)0x1);
    1732                 :          6 :         spdk_put_io_channel(ch);
    1733                 :            : 
    1734                 :          6 :         ch = spdk_get_io_channel((void *)0x7FFFFFFF);
    1735         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
    1736                 :          6 :         CU_ASSERT(ch->dev->io_device == (void *)0x7FFFFFFF);
    1737                 :          6 :         spdk_put_io_channel(ch);
    1738                 :            : 
    1739                 :          6 :         ch = spdk_get_io_channel((void *)0x80000000);
    1740         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
    1741                 :          6 :         CU_ASSERT(ch->dev->io_device == (void *)0x80000000);
    1742                 :          6 :         spdk_put_io_channel(ch);
    1743                 :            : 
    1744                 :          6 :         ch = spdk_get_io_channel((void *)0x100000000);
    1745         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
    1746                 :          6 :         CU_ASSERT(ch->dev->io_device == (void *)0x100000000);
    1747                 :          6 :         spdk_put_io_channel(ch);
    1748                 :            : 
    1749                 :          6 :         ch = spdk_get_io_channel((void *)0x8000000000000000);
    1750         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
    1751                 :          6 :         CU_ASSERT(ch->dev->io_device == (void *)0x8000000000000000);
    1752                 :          6 :         spdk_put_io_channel(ch);
    1753                 :            : 
    1754                 :          6 :         ch = spdk_get_io_channel((void *)0x8000000100000000);
    1755         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
    1756                 :          6 :         CU_ASSERT(ch->dev->io_device == (void *)0x8000000100000000);
    1757                 :          6 :         spdk_put_io_channel(ch);
    1758                 :            : 
    1759                 :          6 :         ch = spdk_get_io_channel((void *)UINT64_MAX);
    1760         [ -  + ]:          6 :         SPDK_CU_ASSERT_FATAL(ch != NULL);
    1761                 :          6 :         CU_ASSERT(ch->dev->io_device == (void *)UINT64_MAX);
    1762                 :          6 :         spdk_put_io_channel(ch);
    1763                 :            : 
    1764                 :          6 :         poll_threads();
    1765                 :            : 
    1766                 :          6 :         spdk_io_device_unregister((void *)0x1, NULL);
    1767                 :          6 :         spdk_io_device_unregister((void *)0x7FFFFFFF, NULL);
    1768                 :          6 :         spdk_io_device_unregister((void *)0x80000000, NULL);
    1769                 :          6 :         spdk_io_device_unregister((void *)0x100000000, NULL);
    1770                 :          6 :         spdk_io_device_unregister((void *)0x8000000000000000, NULL);
    1771                 :          6 :         spdk_io_device_unregister((void *)0x8000000100000000, NULL);
    1772                 :          6 :         spdk_io_device_unregister((void *)UINT64_MAX, NULL);
    1773                 :            : 
    1774                 :          6 :         poll_threads();
    1775                 :            : 
    1776                 :          6 :         CU_ASSERT(RB_EMPTY(&g_io_devices));
    1777                 :            : 
    1778                 :          6 :         free_threads();
    1779                 :          6 : }
    1780                 :            : 
    1781                 :            : static enum spin_error g_spin_err;
    1782                 :            : static uint32_t g_spin_err_count = 0;
    1783                 :            : 
    1784                 :            : static void
    1785                 :         36 : ut_track_abort(enum spin_error err)
    1786                 :            : {
    1787                 :         36 :         g_spin_err = err;
    1788                 :         36 :         g_spin_err_count++;
    1789                 :         36 : }
    1790                 :            : 
    1791                 :            : static void
    1792                 :          6 : spdk_spin(void)
    1793                 :            : {
    1794                 :          5 :         struct spdk_spinlock lock;
    1795                 :            : 
    1796                 :          6 :         g_spin_abort_fn = ut_track_abort;
    1797                 :            : 
    1798                 :            :         /* Do not need to be on an SPDK thread to initialize an spdk_spinlock */
    1799                 :          6 :         g_spin_err_count = 0;
    1800                 :          6 :         spdk_spin_init(&lock);
    1801                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1802                 :            : 
    1803                 :            :         /* Trying to take a lock while not on an SPDK thread is an error */
    1804                 :          6 :         g_spin_err_count = 0;
    1805                 :          6 :         spdk_spin_lock(&lock);
    1806                 :          6 :         CU_ASSERT(g_spin_err_count == 1);
    1807                 :          6 :         CU_ASSERT(g_spin_err == SPIN_ERR_NOT_SPDK_THREAD);
    1808                 :            : 
    1809                 :            :         /* Trying to check if a lock is held while not on an SPDK thread is an error */
    1810                 :          6 :         g_spin_err_count = 0;
    1811                 :          6 :         spdk_spin_held(&lock);
    1812                 :          6 :         CU_ASSERT(g_spin_err_count == 1);
    1813                 :          6 :         CU_ASSERT(g_spin_err == SPIN_ERR_NOT_SPDK_THREAD);
    1814                 :            : 
    1815                 :            :         /* Do not need to be on an SPDK thread to destroy an spdk_spinlock */
    1816                 :          6 :         g_spin_err_count = 0;
    1817                 :          6 :         spdk_spin_destroy(&lock);
    1818                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1819                 :            : 
    1820                 :          6 :         allocate_threads(2);
    1821                 :          6 :         set_thread(0);
    1822                 :            : 
    1823                 :            :         /* Can initialize an spdk_spinlock on an SPDK thread */
    1824                 :          6 :         g_spin_err_count = 0;
    1825                 :          6 :         spdk_spin_init(&lock);
    1826                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1827                 :            : 
    1828                 :            :         /* Can take spinlock */
    1829                 :          6 :         g_spin_err_count = 0;
    1830                 :          6 :         spdk_spin_lock(&lock);
    1831                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1832                 :            : 
    1833                 :            :         /* Can release spinlock */
    1834                 :          6 :         g_spin_err_count = 0;
    1835                 :          6 :         spdk_spin_unlock(&lock);
    1836                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1837                 :            : 
    1838                 :            :         /* Deadlock detected */
    1839                 :          6 :         g_spin_err_count = 0;
    1840                 :          6 :         g_spin_err = SPIN_ERR_NONE;
    1841                 :          6 :         spdk_spin_lock(&lock);
    1842                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1843                 :          6 :         spdk_spin_lock(&lock);
    1844                 :          6 :         CU_ASSERT(g_spin_err_count == 1);
    1845                 :          6 :         CU_ASSERT(g_spin_err == SPIN_ERR_DEADLOCK);
    1846                 :            : 
    1847                 :            :         /* Cannot unlock from wrong thread */
    1848                 :          6 :         set_thread(1);
    1849                 :          6 :         g_spin_err_count = 0;
    1850                 :          6 :         spdk_spin_unlock(&lock);
    1851                 :          6 :         CU_ASSERT(g_spin_err_count == 1);
    1852                 :          6 :         CU_ASSERT(g_spin_err == SPIN_ERR_WRONG_THREAD);
    1853                 :            : 
    1854                 :            :         /* Get back to a known good state */
    1855                 :          6 :         set_thread(0);
    1856                 :          6 :         g_spin_err_count = 0;
    1857                 :          6 :         spdk_spin_unlock(&lock);
    1858                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1859                 :            : 
    1860                 :            :         /* Cannot release the same lock twice */
    1861                 :          6 :         g_spin_err_count = 0;
    1862                 :          6 :         spdk_spin_lock(&lock);
    1863                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1864                 :          6 :         spdk_spin_unlock(&lock);
    1865                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1866                 :          6 :         spdk_spin_unlock(&lock);
    1867                 :          6 :         CU_ASSERT(g_spin_err_count == 1);
    1868                 :          6 :         CU_ASSERT(g_spin_err == SPIN_ERR_WRONG_THREAD);
    1869                 :            : 
    1870                 :            :         /* A lock that is not held is properly recognized */
    1871                 :          6 :         g_spin_err_count = 0;
    1872                 :          6 :         CU_ASSERT(!spdk_spin_held(&lock));
    1873                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1874                 :            : 
    1875                 :            :         /* A lock that is held is recognized as held by only the thread that holds it. */
    1876                 :          6 :         set_thread(1);
    1877                 :          6 :         g_spin_err_count = 0;
    1878                 :          6 :         spdk_spin_lock(&lock);
    1879                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1880                 :          6 :         CU_ASSERT(spdk_spin_held(&lock));
    1881                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1882                 :          6 :         set_thread(0);
    1883                 :          6 :         CU_ASSERT(!spdk_spin_held(&lock));
    1884                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1885                 :            : 
    1886                 :            :         /* After releasing, no one thinks it is held */
    1887                 :          6 :         set_thread(1);
    1888                 :          6 :         spdk_spin_unlock(&lock);
    1889                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1890                 :          6 :         CU_ASSERT(!spdk_spin_held(&lock));
    1891                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1892                 :          6 :         set_thread(0);
    1893                 :          6 :         CU_ASSERT(!spdk_spin_held(&lock));
    1894                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1895                 :            : 
    1896                 :            :         /* Destroying a lock that is held is an error. */
    1897                 :          6 :         set_thread(0);
    1898                 :          6 :         g_spin_err_count = 0;
    1899                 :          6 :         spdk_spin_lock(&lock);
    1900                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1901                 :          6 :         spdk_spin_destroy(&lock);
    1902                 :          6 :         CU_ASSERT(g_spin_err_count == 1);
    1903                 :          6 :         CU_ASSERT(g_spin_err == SPIN_ERR_LOCK_HELD);
    1904                 :          6 :         g_spin_err_count = 0;
    1905                 :          6 :         spdk_spin_unlock(&lock);
    1906                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1907                 :            : 
    1908                 :            :         /* Clean up */
    1909                 :          6 :         g_spin_err_count = 0;
    1910                 :          6 :         spdk_spin_destroy(&lock);
    1911                 :          6 :         CU_ASSERT(g_spin_err_count == 0);
    1912                 :          6 :         free_threads();
    1913                 :          6 :         g_spin_abort_fn = __posix_abort;
    1914                 :          6 : }
    1915                 :            : 
    1916                 :            : static void
    1917                 :          6 : for_each_channel_and_thread_exit_race(void)
    1918                 :            : {
    1919                 :            :         struct spdk_io_channel *ch1, *ch2;
    1920                 :            :         struct spdk_thread *thread0;
    1921                 :          6 :         int ch_count = 0;
    1922                 :          6 :         int msg_count = 0;
    1923                 :            : 
    1924                 :          6 :         allocate_threads(3);
    1925                 :          6 :         set_thread(0);
    1926                 :          6 :         spdk_io_device_register(&ch_count, channel_create, channel_destroy, sizeof(int), NULL);
    1927                 :          6 :         set_thread(1);
    1928                 :          6 :         ch1 = spdk_get_io_channel(&ch_count);
    1929                 :          6 :         set_thread(2);
    1930                 :          6 :         ch2 = spdk_get_io_channel(&ch_count);
    1931                 :          6 :         CU_ASSERT(ch_count == 2);
    1932                 :            : 
    1933                 :            :         /*
    1934                 :            :          * Test one race condition between spdk_thread_exit() and spdk_for_each_channel().
    1935                 :            :          *
    1936                 :            :          * thread 0 does not have io_channel and calls spdk_thread_exit() immediately
    1937                 :            :          * after spdk_for_each_channel(). In this case, thread 0 should exit after
    1938                 :            :          * spdk_for_each_channel() completes.
    1939                 :            :          */
    1940                 :            : 
    1941                 :          6 :         set_thread(0);
    1942                 :          6 :         thread0 = spdk_get_thread();
    1943                 :            : 
    1944                 :          6 :         CU_ASSERT(thread0->for_each_count == 0);
    1945                 :            : 
    1946                 :          6 :         spdk_for_each_channel(&ch_count, channel_msg, &msg_count, channel_cpl);
    1947                 :          6 :         CU_ASSERT(msg_count == 0);
    1948                 :          6 :         CU_ASSERT(thread0->for_each_count == 1);
    1949                 :          6 :         CU_ASSERT(thread0->state == SPDK_THREAD_STATE_RUNNING);
    1950                 :            : 
    1951                 :          6 :         spdk_thread_exit(thread0);
    1952                 :          6 :         CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITING);
    1953                 :            : 
    1954                 :          6 :         poll_threads();
    1955                 :          6 :         CU_ASSERT(msg_count == 3);
    1956                 :          6 :         CU_ASSERT(thread0->for_each_count == 0);
    1957                 :          6 :         CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITED);
    1958                 :            : 
    1959                 :          6 :         set_thread(1);
    1960                 :          6 :         spdk_put_io_channel(ch1);
    1961                 :          6 :         CU_ASSERT(ch_count == 2);
    1962                 :          6 :         set_thread(2);
    1963                 :          6 :         spdk_put_io_channel(ch2);
    1964                 :          6 :         CU_ASSERT(ch_count == 2);
    1965                 :          6 :         poll_threads();
    1966                 :          6 :         CU_ASSERT(ch_count == 0);
    1967                 :            : 
    1968                 :          6 :         spdk_io_device_unregister(&ch_count, NULL);
    1969                 :          6 :         poll_threads();
    1970                 :            : 
    1971                 :          6 :         free_threads();
    1972                 :          6 : }
    1973                 :            : 
    1974                 :            : static void
    1975                 :          6 : for_each_thread_and_thread_exit_race(void)
    1976                 :            : {
    1977                 :            :         struct spdk_thread *thread0;
    1978                 :          6 :         int count = 0;
    1979                 :            :         int i;
    1980                 :            : 
    1981                 :          6 :         allocate_threads(3);
    1982                 :          6 :         set_thread(0);
    1983                 :          6 :         thread0 = spdk_get_thread();
    1984                 :            : 
    1985                 :            :         /* Even if thread 0 starts exiting, spdk_for_each_thread() should complete normally
    1986                 :            :          * and then thread 0 should be moved to EXITED.
    1987                 :            :          */
    1988                 :            : 
    1989                 :          6 :         spdk_for_each_thread(for_each_cb, &count, for_each_cb);
    1990                 :          6 :         CU_ASSERT(thread0->for_each_count == 1);
    1991                 :          6 :         CU_ASSERT(thread0->state == SPDK_THREAD_STATE_RUNNING);
    1992                 :            : 
    1993                 :          6 :         spdk_thread_exit(thread0);
    1994                 :          6 :         CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITING);
    1995                 :            : 
    1996                 :            :         /* We have not polled thread 0 yet, so count should be 0 */
    1997                 :          6 :         CU_ASSERT(count == 0);
    1998                 :            : 
    1999                 :            :         /* Poll each thread to verify the message is passed to each */
    2000         [ +  + ]:         24 :         for (i = 0; i < 3; i++) {
    2001                 :         18 :                 poll_thread(i);
    2002                 :         18 :                 CU_ASSERT(count == (i + 1));
    2003                 :            :         }
    2004                 :            : 
    2005                 :            :         /*
    2006                 :            :          * After each thread is called, the completion calls it
    2007                 :            :          * one more time.
    2008                 :            :          */
    2009                 :          6 :         poll_thread(0);
    2010                 :          6 :         CU_ASSERT(count == 4);
    2011                 :            : 
    2012                 :          6 :         CU_ASSERT(thread0->for_each_count == 0);
    2013                 :          6 :         CU_ASSERT(thread0->state == SPDK_THREAD_STATE_EXITED);
    2014                 :            : 
    2015                 :          6 :         free_threads();
    2016                 :          6 : }
    2017                 :            : 
    2018                 :            : int
    2019                 :          6 : main(int argc, char **argv)
    2020                 :            : {
    2021                 :          6 :         CU_pSuite       suite = NULL;
    2022                 :            :         unsigned int    num_failures;
    2023                 :            : 
    2024                 :          6 :         CU_initialize_registry();
    2025                 :            : 
    2026                 :          6 :         suite = CU_add_suite("io_channel", NULL, NULL);
    2027                 :            : 
    2028                 :          6 :         CU_ADD_TEST(suite, thread_alloc);
    2029                 :          6 :         CU_ADD_TEST(suite, thread_send_msg);
    2030                 :          6 :         CU_ADD_TEST(suite, thread_poller);
    2031                 :          6 :         CU_ADD_TEST(suite, poller_pause);
    2032                 :          6 :         CU_ADD_TEST(suite, thread_for_each);
    2033                 :          6 :         CU_ADD_TEST(suite, for_each_channel_remove);
    2034                 :          6 :         CU_ADD_TEST(suite, for_each_channel_unreg);
    2035                 :          6 :         CU_ADD_TEST(suite, thread_name);
    2036                 :          6 :         CU_ADD_TEST(suite, channel);
    2037                 :          6 :         CU_ADD_TEST(suite, channel_destroy_races);
    2038                 :          6 :         CU_ADD_TEST(suite, thread_exit_test);
    2039                 :          6 :         CU_ADD_TEST(suite, thread_update_stats_test);
    2040                 :          6 :         CU_ADD_TEST(suite, nested_channel);
    2041                 :          6 :         CU_ADD_TEST(suite, device_unregister_and_thread_exit_race);
    2042                 :          6 :         CU_ADD_TEST(suite, cache_closest_timed_poller);
    2043                 :          6 :         CU_ADD_TEST(suite, multi_timed_pollers_have_same_expiration);
    2044                 :          6 :         CU_ADD_TEST(suite, io_device_lookup);
    2045                 :          6 :         CU_ADD_TEST(suite, spdk_spin);
    2046                 :          6 :         CU_ADD_TEST(suite, for_each_channel_and_thread_exit_race);
    2047                 :          6 :         CU_ADD_TEST(suite, for_each_thread_and_thread_exit_race);
    2048                 :            : 
    2049                 :          6 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
    2050                 :          6 :         CU_cleanup_registry();
    2051                 :          6 :         return num_failures;
    2052                 :            : }

Generated by: LCOV version 1.14