1 /* 2 * Copyright (c) 2000-2001, 2005-2007 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 */ 9 10 #pragma ident "%Z%%M% %I% %E% SMI" 11 12 #include <sm/gen.h> 13 SM_RCSID("@(#)$Id: t-sem.c,v 1.16 2007/03/21 23:22:10 ca Exp $") 14 15 #include <stdio.h> 16 17 #if SM_CONF_SEM 18 # include <stdlib.h> 19 # include <unistd.h> 20 # include <sysexits.h> 21 # include <sm/heap.h> 22 # include <sm/string.h> 23 # include <sm/signal.h> 24 # include <sm/test.h> 25 # include <sm/sem.h> 26 27 # define T_SM_SEM_KEY (4321L) 28 29 static void 30 delay(t, s) 31 int t; 32 char *s; 33 { 34 if (t > 0) 35 { 36 #if DEBUG 37 fprintf(stderr, "sleep(%d) before %s\n", t, s); 38 #endif /* DEBUG */ 39 sleep(t); 40 } 41 #if DEBUG 42 fprintf(stderr, "%s\n", s); 43 #endif /* DEBUG */ 44 } 45 46 47 /* 48 ** SEMINTER -- interactive testing of semaphores. 49 ** 50 ** Parameters: 51 ** owner -- create semaphores. 52 ** 53 ** Returns: 54 ** 0 on success 55 ** < 0 on failure. 56 */ 57 58 static int 59 seminter(owner) 60 bool owner; 61 { 62 int semid; 63 int t; 64 65 semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner); 66 if (semid < 0) 67 { 68 perror("sm_sem_start failed"); 69 return 1; 70 } 71 72 while ((t = getchar()) != EOF) 73 { 74 switch (t) 75 { 76 case 'a': 77 delay(0, "try to acq"); 78 if (sm_sem_acq(semid, 0, 2) < 0) 79 { 80 perror("sm_sem_acq failed"); 81 return 1; 82 } 83 delay(0, "acquired"); 84 break; 85 86 case 'r': 87 delay(0, "try to rel"); 88 if (sm_sem_rel(semid, 0, 2) < 0) 89 { 90 perror("sm_sem_rel failed"); 91 return 1; 92 } 93 delay(0, "released"); 94 break; 95 96 case 'v': 97 if ((t = sm_sem_get(semid, 0)) < 0) 98 { 99 perror("get_sem failed"); 100 return 1; 101 } 102 printf("semval: %d\n", t); 103 break; 104 105 } 106 } 107 if (owner) 108 return sm_sem_stop(semid); 109 return 0; 110 } 111 112 /* 113 ** SEM_CLEANUP -- cleanup if something breaks 114 ** 115 ** Parameters: 116 ** sig -- signal. 117 ** 118 ** Returns: 119 ** none. 120 */ 121 122 static int semid_c = -1; 123 void 124 sem_cleanup(sig) 125 int sig; 126 { 127 if (semid_c >= 0) 128 (void) sm_sem_stop(semid_c); 129 exit(EX_UNAVAILABLE); 130 } 131 132 /* 133 ** SEMTEST -- test of semaphores 134 ** 135 ** Parameters: 136 ** owner -- create semaphores. 137 ** 138 ** Returns: 139 ** 0 on success 140 ** < 0 on failure. 141 */ 142 143 # define MAX_CNT 10 144 145 static int 146 semtest(owner) 147 int owner; 148 { 149 int semid, r; 150 int cnt = 0; 151 152 semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner); 153 if (semid < 0) 154 { 155 perror("sm_sem_start failed"); 156 return -1; 157 } 158 159 if (owner) 160 { 161 /* just in case someone kills the program... */ 162 semid_c = semid; 163 (void) sm_signal(SIGHUP, sem_cleanup); 164 (void) sm_signal(SIGINT, sem_cleanup); 165 (void) sm_signal(SIGTERM, sem_cleanup); 166 167 delay(1, "parent: acquire 1"); 168 cnt = 0; 169 do 170 { 171 r = sm_sem_acq(semid, 0, 0); 172 if (r < 0) 173 { 174 sleep(1); 175 ++cnt; 176 } 177 } while (r < 0 && cnt <= MAX_CNT); 178 SM_TEST(r >= 0); 179 if (r < 0) 180 return r; 181 182 delay(3, "parent: release 1"); 183 cnt = 0; 184 do 185 { 186 r = sm_sem_rel(semid, 0, 0); 187 if (r < 0) 188 { 189 sleep(1); 190 ++cnt; 191 } 192 } while (r < 0 && cnt <= MAX_CNT); 193 SM_TEST(r >= 0); 194 if (r < 0) 195 return r; 196 197 delay(1, "parent: getval"); 198 cnt = 0; 199 do 200 { 201 r = sm_sem_get(semid, 0); 202 if (r <= 0) 203 { 204 sleep(1); 205 ++cnt; 206 } 207 } while (r <= 0 && cnt <= MAX_CNT); 208 SM_TEST(r > 0); 209 if (r <= 0) 210 return r; 211 212 delay(1, "parent: acquire 2"); 213 cnt = 0; 214 do 215 { 216 r = sm_sem_acq(semid, 0, 0); 217 if (r < 0) 218 { 219 sleep(1); 220 ++cnt; 221 } 222 } while (r < 0 && cnt <= MAX_CNT); 223 SM_TEST(r >= 0); 224 if (r < 0) 225 return r; 226 227 cnt = 0; 228 do 229 { 230 r = sm_sem_rel(semid, 0, 0); 231 if (r < 0) 232 { 233 sleep(1); 234 ++cnt; 235 } 236 } while (r < 0 && cnt <= MAX_CNT); 237 SM_TEST(r >= 0); 238 if (r < 0) 239 return r; 240 } 241 else 242 { 243 delay(1, "child: acquire 1"); 244 cnt = 0; 245 do 246 { 247 r = sm_sem_acq(semid, 0, 0); 248 if (r < 0) 249 { 250 sleep(1); 251 ++cnt; 252 } 253 } while (r < 0 && cnt <= MAX_CNT); 254 SM_TEST(r >= 0); 255 if (r < 0) 256 return r; 257 258 delay(1, "child: release 1"); 259 cnt = 0; 260 do 261 { 262 r = sm_sem_rel(semid, 0, 0); 263 if (r < 0) 264 { 265 sleep(1); 266 ++cnt; 267 } 268 } while (r < 0 && cnt <= MAX_CNT); 269 SM_TEST(r >= 0); 270 if (r < 0) 271 return r; 272 273 } 274 if (owner) 275 return sm_sem_stop(semid); 276 return 0; 277 } 278 279 int 280 main(argc, argv) 281 int argc; 282 char *argv[]; 283 { 284 bool interactive = false; 285 bool owner = false; 286 int ch; 287 int r = 0; 288 289 # define OPTIONS "io" 290 while ((ch = getopt(argc, argv, OPTIONS)) != -1) 291 { 292 switch ((char) ch) 293 { 294 case 'i': 295 interactive = true; 296 break; 297 298 case 'o': 299 owner = true; 300 break; 301 302 default: 303 break; 304 } 305 } 306 307 if (interactive) 308 r = seminter(owner); 309 else 310 { 311 pid_t pid; 312 313 printf("This test takes about 8 seconds.\n"); 314 printf("If it takes longer than 30 seconds, please interrupt it\n"); 315 printf("and compile again without semaphore support, i.e.,"); 316 printf("-DSM_CONF_SEM=0\n"); 317 if ((pid = fork()) < 0) 318 { 319 perror("fork failed\n"); 320 return -1; 321 } 322 323 sm_test_begin(argc, argv, "test semaphores"); 324 if (pid == 0) 325 { 326 /* give the parent the chance to setup data */ 327 sleep(1); 328 r = semtest(false); 329 } 330 else 331 { 332 r = semtest(true); 333 } 334 SM_TEST(r == 0); 335 return sm_test_end(); 336 } 337 return r; 338 } 339 #else /* SM_CONF_SEM */ 340 int 341 main(argc, argv) 342 int argc; 343 char *argv[]; 344 { 345 printf("No support for semaphores configured on this machine\n"); 346 return 0; 347 } 348 #endif /* SM_CONF_SEM */ 349