1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: 3 #ident "$Id$" 4 /*====== 5 This file is part of PerconaFT. 6 7 8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. 9 10 PerconaFT is free software: you can redistribute it and/or modify 11 it under the terms of the GNU General Public License, version 2, 12 as published by the Free Software Foundation. 13 14 PerconaFT is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 21 22 ---------------------------------------- 23 24 PerconaFT is free software: you can redistribute it and/or modify 25 it under the terms of the GNU Affero General Public License, version 3, 26 as published by the Free Software Foundation. 27 28 PerconaFT is distributed in the hope that it will be useful, 29 but WITHOUT ANY WARRANTY; without even the implied warranty of 30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 31 GNU Affero General Public License for more details. 32 33 You should have received a copy of the GNU Affero General Public License 34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 35 ======= */ 36 37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." 38 39 #include "test.h" 40 41 // test create and destroy 42 43 static void test_create_destroy(void) { 44 struct st_rwlock the_rwlock, *rwlock = &the_rwlock; 45 46 rwlock_init(toku_uninstrumented, rwlock); 47 rwlock_destroy(rwlock); 48 } 49 50 // test read lock and unlock with no writers 51 52 static void test_simple_read_lock(int n) { 53 struct st_rwlock the_rwlock, *rwlock = &the_rwlock; 54 55 rwlock_init(toku_uninstrumented, rwlock); 56 assert(rwlock_readers(rwlock) == 0); 57 int i; 58 for (i = 1; i <= n; i++) { 59 rwlock_read_lock(rwlock, 0); 60 assert(rwlock_readers(rwlock) == i); 61 assert(rwlock_users(rwlock) == i); 62 } 63 for (i=n-1; i>=0; i--) { 64 rwlock_read_unlock(rwlock); 65 assert(rwlock_readers(rwlock) == i); 66 assert(rwlock_users(rwlock) == i); 67 } 68 rwlock_destroy(rwlock); 69 } 70 71 // test write lock and unlock with no readers 72 73 static void test_simple_write_lock(void) { 74 struct st_rwlock the_rwlock, *rwlock = &the_rwlock; 75 76 rwlock_init(toku_uninstrumented, rwlock); 77 assert(rwlock_users(rwlock) == 0); 78 rwlock_write_lock(rwlock, 0); 79 assert(rwlock_writers(rwlock) == 1); 80 assert(rwlock_users(rwlock) == 1); 81 rwlock_write_unlock(rwlock); 82 assert(rwlock_users(rwlock) == 0); 83 rwlock_destroy(rwlock); 84 } 85 86 struct rw_event { 87 int e; 88 struct st_rwlock the_rwlock; 89 toku_mutex_t mutex; 90 }; 91 92 static void rw_event_init(struct rw_event *rwe) { 93 rwe->e = 0; 94 rwlock_init(toku_uninstrumented, &rwe->the_rwlock); 95 toku_mutex_init(toku_uninstrumented, &rwe->mutex, nullptr); 96 } 97 98 static void rw_event_destroy(struct rw_event *rwe) { 99 rwlock_destroy(&rwe->the_rwlock); 100 toku_mutex_destroy(&rwe->mutex); 101 } 102 103 static void * 104 test_writer_priority_thread (void *arg) { 105 struct rw_event *CAST_FROM_VOIDP(rwe, arg); 106 107 toku_mutex_lock(&rwe->mutex); 108 rwlock_write_lock(&rwe->the_rwlock, &rwe->mutex); 109 rwe->e++; assert(rwe->e == 3); 110 toku_mutex_unlock(&rwe->mutex); 111 sleep(1); 112 toku_mutex_lock(&rwe->mutex); 113 rwe->e++; assert(rwe->e == 4); 114 rwlock_write_unlock(&rwe->the_rwlock); 115 toku_mutex_unlock(&rwe->mutex); 116 117 return arg; 118 } 119 120 // test writer priority over new readers 121 122 static void 123 test_writer_priority (void) { 124 struct rw_event rw_event, *rwe = &rw_event; 125 ZERO_STRUCT(rw_event); 126 int r; 127 128 rw_event_init(rwe); 129 toku_mutex_lock(&rwe->mutex); 130 rwlock_read_lock(&rwe->the_rwlock, &rwe->mutex); 131 sleep(1); 132 rwe->e++; assert(rwe->e == 1); 133 toku_mutex_unlock(&rwe->mutex); 134 135 toku_pthread_t tid; 136 r = toku_pthread_create( 137 toku_uninstrumented, &tid, 0, test_writer_priority_thread, rwe); 138 sleep(1); 139 toku_mutex_lock(&rwe->mutex); 140 rwe->e++; 141 assert(rwe->e == 2); 142 toku_mutex_unlock(&rwe->mutex); 143 144 sleep(1); 145 toku_mutex_lock(&rwe->mutex); 146 rwlock_read_unlock(&rwe->the_rwlock); 147 toku_mutex_unlock(&rwe->mutex); 148 sleep(1); 149 toku_mutex_lock(&rwe->mutex); 150 rwlock_read_lock(&rwe->the_rwlock, &rwe->mutex); 151 rwe->e++; assert(rwe->e == 5); 152 toku_mutex_unlock(&rwe->mutex); 153 sleep(1); 154 toku_mutex_lock(&rwe->mutex); 155 rwlock_read_unlock(&rwe->the_rwlock); 156 toku_mutex_unlock(&rwe->mutex); 157 158 void *ret; 159 r = toku_pthread_join(tid, &ret); assert(r == 0); 160 161 rw_event_destroy(rwe); 162 } 163 164 // test single writer 165 166 static void * 167 test_single_writer_thread (void *arg) { 168 struct rw_event *CAST_FROM_VOIDP(rwe, arg); 169 170 toku_mutex_lock(&rwe->mutex); 171 rwlock_write_lock(&rwe->the_rwlock, &rwe->mutex); 172 rwe->e++; assert(rwe->e == 3); 173 assert(rwlock_writers(&rwe->the_rwlock) == 1); 174 rwlock_write_unlock(&rwe->the_rwlock); 175 toku_mutex_unlock(&rwe->mutex); 176 177 return arg; 178 } 179 180 static void 181 test_single_writer (void) { 182 struct rw_event rw_event, *rwe = &rw_event; 183 ZERO_STRUCT(rw_event); 184 int r; 185 186 rw_event_init(rwe); 187 assert(rwlock_writers(&rwe->the_rwlock) == 0); 188 toku_mutex_lock(&rwe->mutex); 189 rwlock_write_lock(&rwe->the_rwlock, &rwe->mutex); 190 assert(rwlock_writers(&rwe->the_rwlock) == 1); 191 sleep(1); 192 rwe->e++; assert(rwe->e == 1); 193 toku_mutex_unlock(&rwe->mutex); 194 195 toku_pthread_t tid; 196 r = toku_pthread_create( 197 toku_uninstrumented, &tid, 0, test_single_writer_thread, rwe); 198 sleep(1); 199 toku_mutex_lock(&rwe->mutex); 200 rwe->e++; 201 assert(rwe->e == 2); 202 assert(rwlock_writers(&rwe->the_rwlock) == 1); 203 assert(rwlock_users(&rwe->the_rwlock) == 2); 204 rwlock_write_unlock(&rwe->the_rwlock); 205 toku_mutex_unlock(&rwe->mutex); 206 207 void *ret; 208 r = toku_pthread_join(tid, &ret); assert(r == 0); 209 210 assert(rwlock_writers(&rwe->the_rwlock) == 0); 211 rw_event_destroy(rwe); 212 } 213 214 int 215 test_main(int argc, const char *argv[]) { 216 default_parse_args(argc, argv); 217 test_create_destroy(); 218 test_simple_read_lock(0); 219 test_simple_read_lock(42); 220 test_simple_write_lock(); 221 test_writer_priority(); 222 test_single_writer(); 223 224 return 0; 225 } 226