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