t-sem.c revision 147078
115103Sphk/* 215103Sphk * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. 315103Sphk * All rights reserved. 415103Sphk * 515103Sphk * By using this file, you agree to the terms and conditions set 615103Sphk * forth in the LICENSE file which can be found at the top level of 715103Sphk * the sendmail distribution. 815103Sphk */ 915103Sphk 1015103Sphk#include <sm/gen.h> 1115103SphkSM_RCSID("@(#)$Id: t-sem.c,v 1.14 2005/03/25 21:27:41 ca Exp $") 1215103Sphk 1315103Sphk#include <stdio.h> 1415103Sphk 1515103Sphk#if SM_CONF_SEM 1615103Sphk# include <stdlib.h> 1715103Sphk# include <unistd.h> 1815103Sphk# include <sysexits.h> 1915103Sphk# include <sm/heap.h> 2015103Sphk# include <sm/string.h> 2115103Sphk# include <sm/signal.h> 2215103Sphk# include <sm/test.h> 2315103Sphk# include <sm/sem.h> 2415103Sphk 2515103Sphkstatic void 2615103Sphkdelay(t, s) 2715103Sphk int t; 2815103Sphk char *s; 2915103Sphk{ 3015103Sphk if (t > 0) 3115103Sphk { 3215103Sphk#if DEBUG 3315103Sphk fprintf(stderr, "sleep(%d) before %s\n", t, s); 3415103Sphk#endif /* DEBUG */ 3515103Sphk sleep(t); 3615103Sphk } 3715103Sphk#if DEBUG 3815103Sphk fprintf(stderr, "%s\n", s); 3915103Sphk#endif /* DEBUG */ 4050477Speter} 4115103Sphk 4215103Sphk 4315103Sphk/* 4415103Sphk** SEMINTER -- interactive testing of semaphores. 4515103Sphk** 4615103Sphk** Parameters: 4715103Sphk** owner -- create semaphores. 4846155Sphk** 4931990Sgpalmer** Returns: 5028918Skato** 0 on success 5115103Sphk** < 0 on failure. 5215103Sphk*/ 5315103Sphk 5415103Sphkstatic int 5515103Sphkseminter(owner) 5615103Sphk bool owner; 5723382Sbde{ 5815103Sphk int semid; 5915103Sphk int t; 6015103Sphk 6115103Sphk semid = sm_sem_start(SM_SEM_KEY, SM_NSEM, 0, owner); 6215103Sphk if (semid < 0) 6348891Sphk { 6448891Sphk perror("sm_sem_start failed"); 6515103Sphk return 1; 6615103Sphk } 6715103Sphk 6815103Sphk while ((t = getchar()) != EOF) 6915103Sphk { 7015103Sphk switch (t) 7134925Sdufault { 7234925Sdufault case 'a': 7334029Sdufault delay(0, "try to acq"); 7450465Smarcel if (sm_sem_acq(semid, 0, 2) < 0) 7550465Smarcel { 7650465Smarcel perror("sm_sem_acq failed"); 7746381Sbillf return 1; 7846381Sbillf } 7915103Sphk delay(0, "acquired"); 8046381Sbillf break; 8146381Sbillf 8215103Sphk case 'r': 8346381Sbillf delay(0, "try to rel"); 8446381Sbillf if (sm_sem_rel(semid, 0, 2) < 0) 8515103Sphk { 8646381Sbillf perror("sm_sem_rel failed"); 8746381Sbillf return 1; 8815103Sphk } 8915103Sphk delay(0, "released"); 9046381Sbillf break; 9146381Sbillf 9215103Sphk case 'v': 9346381Sbillf if ((t = sm_sem_get(semid, 0)) < 0) 9446381Sbillf { 9515103Sphk perror("get_sem failed"); 9646381Sbillf return 1; 9746381Sbillf } 9815103Sphk printf("semval: %d\n", t); 9946381Sbillf break; 10046381Sbillf 10115103Sphk } 10246381Sbillf } 10346381Sbillf if (owner) 10415103Sphk return sm_sem_stop(semid); 10546381Sbillf return 0; 10646381Sbillf} 10715103Sphk 10846381Sbillf/* 10946381Sbillf** SEM_CLEANUP -- cleanup if something breaks 11015103Sphk** 11115103Sphk** Parameters: 11246381Sbillf** sig -- signal. 11346381Sbillf** 11415103Sphk** Returns: 11546381Sbillf** none. 11646381Sbillf*/ 11715103Sphk 11815103Sphkstatic int semid_c = -1; 11915103Sphkvoid 12015103Sphksem_cleanup(sig) 12146381Sbillf int sig; 12246381Sbillf{ 12315103Sphk if (semid_c >= 0) 12431990Sgpalmer (void) sm_sem_stop(semid_c); 12546381Sbillf exit(EX_UNAVAILABLE); 12646381Sbillf} 12731990Sgpalmer 12846381Sbillf/* 12946381Sbillf** SEMTEST -- test of semaphores 13031990Sgpalmer** 13115103Sphk** Parameters: 13246381Sbillf** owner -- create semaphores. 13346381Sbillf** 13415103Sphk** Returns: 13546381Sbillf** 0 on success 13646381Sbillf** < 0 on failure. 13715103Sphk*/ 13828885Skato 13928885Skato# define MAX_CNT 10 14046381Sbillf 14128885Skatostatic int 14215103Sphksemtest(owner) 14315103Sphk int owner; 14446155Sphk{ 14562573Sphk int semid, r; 14646155Sphk int cnt = 0; 14746155Sphk 14815103Sphk semid = sm_sem_start(SM_SEM_KEY, 1, 0, owner); 14957111Srwatson if (semid < 0) 15057163Srwatson { 15157111Srwatson perror("sm_sem_start failed"); 15246155Sphk return -1; 15346155Sphk } 15446155Sphk 15557111Srwatson if (owner) 15646155Sphk { 15746155Sphk /* just in case someone kills the program... */ 15846155Sphk semid_c = semid; 15946155Sphk (void) sm_signal(SIGHUP, sem_cleanup); 16046155Sphk (void) sm_signal(SIGINT, sem_cleanup); 16146155Sphk (void) sm_signal(SIGTERM, sem_cleanup); 16246155Sphk 16346381Sbillf delay(1, "parent: acquire 1"); 16446155Sphk cnt = 0; 16515103Sphk do 16615103Sphk { 16715103Sphk r = sm_sem_acq(semid, 0, 0); 16862573Sphk if (r < 0) 16915103Sphk { 17015103Sphk sleep(1); 17115103Sphk ++cnt; 17215103Sphk } 17315103Sphk } while (r < 0 && cnt <= MAX_CNT); 17415103Sphk SM_TEST(r >= 0); 17515103Sphk if (r < 0) 17626923Sjoerg return r; 17715103Sphk 17815103Sphk delay(3, "parent: release 1"); 17915103Sphk cnt = 0; 18015103Sphk do 18115103Sphk { 18261370Srwatson r = sm_sem_rel(semid, 0, 0); 18361370Srwatson if (r < 0) 18461370Srwatson { 18515103Sphk sleep(1); 18617281Swollman ++cnt; 18746381Sbillf } 18815103Sphk } while (r < 0 && cnt <= MAX_CNT); 18915103Sphk SM_TEST(r >= 0); 19015103Sphk if (r < 0) 19146381Sbillf return r; 19215103Sphk 19315103Sphk delay(1, "parent: getval"); 19415103Sphk cnt = 0; 19515103Sphk do 19615103Sphk { 19715103Sphk r = sm_sem_get(semid, 0); 19846381Sbillf if (r <= 0) 19946381Sbillf { 20046381Sbillf sleep(1); 20146381Sbillf ++cnt; 20246381Sbillf } 20346381Sbillf } while (r <= 0 && cnt <= MAX_CNT); 20446381Sbillf SM_TEST(r > 0); 20546381Sbillf if (r <= 0) 20646381Sbillf return r; 20746381Sbillf 20846381Sbillf delay(1, "parent: acquire 2"); 20946381Sbillf cnt = 0; 21018540Sbde do 21146381Sbillf { 21246381Sbillf r = sm_sem_acq(semid, 0, 0); 21346381Sbillf if (r < 0) 21446381Sbillf { 21546381Sbillf sleep(1); 21646381Sbillf ++cnt; 21746381Sbillf } 21846381Sbillf } while (r < 0 && cnt <= MAX_CNT); 21946381Sbillf SM_TEST(r >= 0); 22046381Sbillf if (r < 0) 22146381Sbillf return r; 22246381Sbillf 22346381Sbillf cnt = 0; 22446381Sbillf do 22546381Sbillf { 22646381Sbillf r = sm_sem_rel(semid, 0, 0); 22746381Sbillf if (r < 0) 22846381Sbillf { 22946381Sbillf sleep(1); 23046381Sbillf ++cnt; 23146381Sbillf } 23246381Sbillf } while (r < 0 && cnt <= MAX_CNT); 23346381Sbillf SM_TEST(r >= 0); 23446381Sbillf if (r < 0) 23546381Sbillf return r; 23646381Sbillf } 23746381Sbillf else 23848891Sphk { 23948891Sphk delay(1, "child: acquire 1"); 24048891Sphk cnt = 0; 24148891Sphk do 24248891Sphk { 24348891Sphk r = sm_sem_acq(semid, 0, 0); 24448891Sphk if (r < 0) 24548927Sphk { 24649535Sphk sleep(1); 24748927Sphk ++cnt; 24848927Sphk } 24958926Sphk } while (r < 0 && cnt <= MAX_CNT); 25060041Sphk SM_TEST(r >= 0); 25158926Sphk if (r < 0) 25258926Sphk return r; 25358926Sphk 25458926Sphk delay(1, "child: release 1"); 25558926Sphk 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 second, 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