Imported Upstream version 17.05
[deb_dpdk.git] / app / test / test_spinlock.c
diff --git a/app/test/test_spinlock.c b/app/test/test_spinlock.c
deleted file mode 100644 (file)
index 2d94eec..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/queue.h>
-
-#include <rte_common.h>
-#include <rte_memory.h>
-#include <rte_memzone.h>
-#include <rte_per_lcore.h>
-#include <rte_launch.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_lcore.h>
-#include <rte_cycles.h>
-#include <rte_spinlock.h>
-#include <rte_atomic.h>
-
-#include "test.h"
-
-/*
- * Spinlock test
- * =============
- *
- * - There is a global spinlock and a table of spinlocks (one per lcore).
- *
- * - The test function takes all of these locks and launches the
- *   ``test_spinlock_per_core()`` function on each core (except the master).
- *
- *   - The function takes the global lock, display something, then releases
- *     the global lock.
- *   - The function takes the per-lcore lock, display something, then releases
- *     the per-core lock.
- *
- * - The main function unlocks the per-lcore locks sequentially and
- *   waits between each lock. This triggers the display of a message
- *   for each core, in the correct order. The autotest script checks that
- *   this order is correct.
- *
- * - A load test is carried out, with all cores attempting to lock a single lock
- *   multiple times
- */
-
-static rte_spinlock_t sl, sl_try;
-static rte_spinlock_t sl_tab[RTE_MAX_LCORE];
-static rte_spinlock_recursive_t slr;
-static unsigned count = 0;
-
-static rte_atomic32_t synchro;
-
-static int
-test_spinlock_per_core(__attribute__((unused)) void *arg)
-{
-       rte_spinlock_lock(&sl);
-       printf("Global lock taken on core %u\n", rte_lcore_id());
-       rte_spinlock_unlock(&sl);
-
-       rte_spinlock_lock(&sl_tab[rte_lcore_id()]);
-       printf("Hello from core %u !\n", rte_lcore_id());
-       rte_spinlock_unlock(&sl_tab[rte_lcore_id()]);
-
-       return 0;
-}
-
-static int
-test_spinlock_recursive_per_core(__attribute__((unused)) void *arg)
-{
-       unsigned id = rte_lcore_id();
-
-       rte_spinlock_recursive_lock(&slr);
-       printf("Global recursive lock taken on core %u - count = %d\n",
-              id, slr.count);
-       rte_spinlock_recursive_lock(&slr);
-       printf("Global recursive lock taken on core %u - count = %d\n",
-              id, slr.count);
-       rte_spinlock_recursive_lock(&slr);
-       printf("Global recursive lock taken on core %u - count = %d\n",
-              id, slr.count);
-
-       printf("Hello from within recursive locks from core %u !\n", id);
-
-       rte_spinlock_recursive_unlock(&slr);
-       printf("Global recursive lock released on core %u - count = %d\n",
-              id, slr.count);
-       rte_spinlock_recursive_unlock(&slr);
-       printf("Global recursive lock released on core %u - count = %d\n",
-              id, slr.count);
-       rte_spinlock_recursive_unlock(&slr);
-       printf("Global recursive lock released on core %u - count = %d\n",
-              id, slr.count);
-
-       return 0;
-}
-
-static rte_spinlock_t lk = RTE_SPINLOCK_INITIALIZER;
-static uint64_t lock_count[RTE_MAX_LCORE] = {0};
-
-#define TIME_MS 100
-
-static int
-load_loop_fn(void *func_param)
-{
-       uint64_t time_diff = 0, begin;
-       uint64_t hz = rte_get_timer_hz();
-       uint64_t lcount = 0;
-       const int use_lock = *(int*)func_param;
-       const unsigned lcore = rte_lcore_id();
-
-       /* wait synchro for slaves */
-       if (lcore != rte_get_master_lcore())
-               while (rte_atomic32_read(&synchro) == 0);
-
-       begin = rte_get_timer_cycles();
-       while (time_diff < hz * TIME_MS / 1000) {
-               if (use_lock)
-                       rte_spinlock_lock(&lk);
-               lcount++;
-               if (use_lock)
-                       rte_spinlock_unlock(&lk);
-               /* delay to make lock duty cycle slighlty realistic */
-               rte_delay_us(1);
-               time_diff = rte_get_timer_cycles() - begin;
-       }
-       lock_count[lcore] = lcount;
-       return 0;
-}
-
-static int
-test_spinlock_perf(void)
-{
-       unsigned int i;
-       uint64_t total = 0;
-       int lock = 0;
-       const unsigned lcore = rte_lcore_id();
-
-       printf("\nTest with no lock on single core...\n");
-       load_loop_fn(&lock);
-       printf("Core [%u] count = %"PRIu64"\n", lcore, lock_count[lcore]);
-       memset(lock_count, 0, sizeof(lock_count));
-
-       printf("\nTest with lock on single core...\n");
-       lock = 1;
-       load_loop_fn(&lock);
-       printf("Core [%u] count = %"PRIu64"\n", lcore, lock_count[lcore]);
-       memset(lock_count, 0, sizeof(lock_count));
-
-       printf("\nTest with lock on %u cores...\n", rte_lcore_count());
-
-       /* Clear synchro and start slaves */
-       rte_atomic32_set(&synchro, 0);
-       rte_eal_mp_remote_launch(load_loop_fn, &lock, SKIP_MASTER);
-
-       /* start synchro and launch test on master */
-       rte_atomic32_set(&synchro, 1);
-       load_loop_fn(&lock);
-
-       rte_eal_mp_wait_lcore();
-
-       RTE_LCORE_FOREACH(i) {
-               printf("Core [%u] count = %"PRIu64"\n", i, lock_count[i]);
-               total += lock_count[i];
-       }
-
-       printf("Total count = %"PRIu64"\n", total);
-
-       return 0;
-}
-
-/*
- * Use rte_spinlock_trylock() to trylock a spinlock object,
- * If it could not lock the object sucessfully, it would
- * return immediately and the variable of "count" would be
- * increased by one per times. the value of "count" could be
- * checked as the result later.
- */
-static int
-test_spinlock_try(__attribute__((unused)) void *arg)
-{
-       if (rte_spinlock_trylock(&sl_try) == 0) {
-               rte_spinlock_lock(&sl);
-               count ++;
-               rte_spinlock_unlock(&sl);
-       }
-
-       return 0;
-}
-
-
-/*
- * Test rte_eal_get_lcore_state() in addition to spinlocks
- * as we have "waiting" then "running" lcores.
- */
-static int
-test_spinlock(void)
-{
-       int ret = 0;
-       int i;
-
-       /* slave cores should be waiting: print it */
-       RTE_LCORE_FOREACH_SLAVE(i) {
-               printf("lcore %d state: %d\n", i,
-                      (int) rte_eal_get_lcore_state(i));
-       }
-
-       rte_spinlock_init(&sl);
-       rte_spinlock_init(&sl_try);
-       rte_spinlock_recursive_init(&slr);
-       for (i=0; i<RTE_MAX_LCORE; i++)
-               rte_spinlock_init(&sl_tab[i]);
-
-       rte_spinlock_lock(&sl);
-
-       RTE_LCORE_FOREACH_SLAVE(i) {
-               rte_spinlock_lock(&sl_tab[i]);
-               rte_eal_remote_launch(test_spinlock_per_core, NULL, i);
-       }
-
-       /* slave cores should be busy: print it */
-       RTE_LCORE_FOREACH_SLAVE(i) {
-               printf("lcore %d state: %d\n", i,
-                      (int) rte_eal_get_lcore_state(i));
-       }
-       rte_spinlock_unlock(&sl);
-
-       RTE_LCORE_FOREACH_SLAVE(i) {
-               rte_spinlock_unlock(&sl_tab[i]);
-               rte_delay_ms(10);
-       }
-
-       rte_eal_mp_wait_lcore();
-
-       rte_spinlock_recursive_lock(&slr);
-
-       /*
-        * Try to acquire a lock that we already own
-        */
-       if(!rte_spinlock_recursive_trylock(&slr)) {
-               printf("rte_spinlock_recursive_trylock failed on a lock that "
-                      "we already own\n");
-               ret = -1;
-       } else
-               rte_spinlock_recursive_unlock(&slr);
-
-       RTE_LCORE_FOREACH_SLAVE(i) {
-               rte_eal_remote_launch(test_spinlock_recursive_per_core, NULL, i);
-       }
-       rte_spinlock_recursive_unlock(&slr);
-       rte_eal_mp_wait_lcore();
-
-       /*
-        * Test if it could return immediately from try-locking a locked object.
-        * Here it will lock the spinlock object first, then launch all the slave
-        * lcores to trylock the same spinlock object.
-        * All the slave lcores should give up try-locking a locked object and
-        * return immediately, and then increase the "count" initialized with zero
-        * by one per times.
-        * We can check if the "count" is finally equal to the number of all slave
-        * lcores to see if the behavior of try-locking a locked spinlock object
-        * is correct.
-        */
-       if (rte_spinlock_trylock(&sl_try) == 0) {
-               return -1;
-       }
-       count = 0;
-       RTE_LCORE_FOREACH_SLAVE(i) {
-               rte_eal_remote_launch(test_spinlock_try, NULL, i);
-       }
-       rte_eal_mp_wait_lcore();
-       rte_spinlock_unlock(&sl_try);
-       if (rte_spinlock_is_locked(&sl)) {
-               printf("spinlock is locked but it should not be\n");
-               return -1;
-       }
-       rte_spinlock_lock(&sl);
-       if (count != ( rte_lcore_count() - 1)) {
-               ret = -1;
-       }
-       rte_spinlock_unlock(&sl);
-
-       /*
-        * Test if it can trylock recursively.
-        * Use rte_spinlock_recursive_trylock() to check if it can lock a spinlock
-        * object recursively. Here it will try to lock a spinlock object twice.
-        */
-       if (rte_spinlock_recursive_trylock(&slr) == 0) {
-               printf("It failed to do the first spinlock_recursive_trylock but it should able to do\n");
-               return -1;
-       }
-       if (rte_spinlock_recursive_trylock(&slr) == 0) {
-               printf("It failed to do the second spinlock_recursive_trylock but it should able to do\n");
-               return -1;
-       }
-       rte_spinlock_recursive_unlock(&slr);
-       rte_spinlock_recursive_unlock(&slr);
-
-       if (test_spinlock_perf() < 0)
-               return -1;
-
-       return ret;
-}
-
-REGISTER_TEST_COMMAND(spinlock_autotest, test_spinlock);