1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdio.h> 35 #include <stdint.h> 36 #include <unistd.h> 37 #include <sys/queue.h> 38 39 #include <rte_common.h> 40 #include <rte_memory.h> 41 #include <rte_memzone.h> 42 #include <rte_per_lcore.h> 43 #include <rte_launch.h> 44 #include <rte_atomic.h> 45 #include <rte_rwlock.h> 46 #include <rte_eal.h> 47 #include <rte_per_lcore.h> 48 #include <rte_lcore.h> 49 #include <rte_cycles.h> 50 51 #include "test.h" 52 53 /* 54 * rwlock test 55 * =========== 56 * 57 * - There is a global rwlock and a table of rwlocks (one per lcore). 58 * 59 * - The test function takes all of these locks and launches the 60 * ``test_rwlock_per_core()`` function on each core (except the master). 61 * 62 * - The function takes the global write lock, display something, 63 * then releases the global lock. 64 * - Then, it takes the per-lcore write lock, display something, and 65 * releases the per-core lock. 66 * - Finally, a read lock is taken during 100 ms, then released. 67 * 68 * - The main function unlocks the per-lcore locks sequentially and 69 * waits between each lock. This triggers the display of a message 70 * for each core, in the correct order. 71 * 72 * Then, it tries to take the global write lock and display the last 73 * message. The autotest script checks that the message order is correct. 74 */ 75 76 static rte_rwlock_t sl; 77 static rte_rwlock_t sl_tab[RTE_MAX_LCORE]; 78 79 static int 80 test_rwlock_per_core(__attribute__((unused)) void *arg) 81 { 82 rte_rwlock_write_lock(&sl); 83 printf("Global write lock taken on core %u\n", rte_lcore_id()); 84 rte_rwlock_write_unlock(&sl); 85 86 rte_rwlock_write_lock(&sl_tab[rte_lcore_id()]); 87 printf("Hello from core %u !\n", rte_lcore_id()); 88 rte_rwlock_write_unlock(&sl_tab[rte_lcore_id()]); 89 90 rte_rwlock_read_lock(&sl); 91 printf("Global read lock taken on core %u\n", rte_lcore_id()); 92 rte_delay_ms(100); 93 printf("Release global read lock on core %u\n", rte_lcore_id()); 94 rte_rwlock_read_unlock(&sl); 95 96 return 0; 97 } 98 99 static int 100 test_rwlock(void) 101 { 102 int i; 103 104 rte_rwlock_init(&sl); 105 for (i=0; i<RTE_MAX_LCORE; i++) 106 rte_rwlock_init(&sl_tab[i]); 107 108 rte_rwlock_write_lock(&sl); 109 110 RTE_LCORE_FOREACH_SLAVE(i) { 111 rte_rwlock_write_lock(&sl_tab[i]); 112 rte_eal_remote_launch(test_rwlock_per_core, NULL, i); 113 } 114 115 rte_rwlock_write_unlock(&sl); 116 117 RTE_LCORE_FOREACH_SLAVE(i) { 118 rte_rwlock_write_unlock(&sl_tab[i]); 119 rte_delay_ms(100); 120 } 121 122 rte_rwlock_write_lock(&sl); 123 /* this message should be the last message of test */ 124 printf("Global write lock taken on master core %u\n", rte_lcore_id()); 125 rte_rwlock_write_unlock(&sl); 126 127 rte_eal_mp_wait_lcore(); 128 129 return 0; 130 } 131 132 REGISTER_TEST_COMMAND(rwlock_autotest, test_rwlock); 133