1f57949ebSmckusick /*
2*bac379f5Sbostic * Copyright (c) 1989, 1993
3*bac379f5Sbostic * The Regents of the University of California. All rights reserved.
4f9c00025Sbostic *
524ce2517Sbostic * %sccs.include.redist.c%
6f57949ebSmckusick */
7f57949ebSmckusick
8c34e25a4Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*bac379f5Sbostic static char sccsid[] = "@(#)usleep.c 8.1 (Berkeley) 06/04/93";
10f9c00025Sbostic #endif /* LIBC_SCCS and not lint */
1112e61e86Sserge
1212e61e86Sserge #include <sys/time.h>
13f9c00025Sbostic #include <sys/signal.h>
14ae227ee3Sdonn #include <unistd.h>
1512e61e86Sserge
1612e61e86Sserge #define TICK 10000 /* system clock resolution in microseconds */
17f9c00025Sbostic #define USPS 1000000 /* number of microseconds in a second */
1812e61e86Sserge
1912e61e86Sserge #define setvec(vec, a) \
2012e61e86Sserge vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
2112e61e86Sserge
2212e61e86Sserge static int ringring;
2312e61e86Sserge
24ae227ee3Sdonn void
usleep(useconds)25f9c00025Sbostic usleep(useconds)
26f9c00025Sbostic unsigned int useconds;
2712e61e86Sserge {
28f9c00025Sbostic register struct itimerval *itp;
2912e61e86Sserge struct itimerval itv, oitv;
3012e61e86Sserge struct sigvec vec, ovec;
31f9c00025Sbostic long omask;
32ae227ee3Sdonn static void sleephandler();
3312e61e86Sserge
34f9c00025Sbostic itp = &itv;
35f9c00025Sbostic if (!useconds)
3612e61e86Sserge return;
3712e61e86Sserge timerclear(&itp->it_interval);
3812e61e86Sserge timerclear(&itp->it_value);
3912e61e86Sserge if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
4012e61e86Sserge return;
41f9c00025Sbostic itp->it_value.tv_sec = useconds / USPS;
42f9c00025Sbostic itp->it_value.tv_usec = useconds % USPS;
4312e61e86Sserge if (timerisset(&oitv.it_value)) {
4412e61e86Sserge if (timercmp(&oitv.it_value, &itp->it_value, >)) {
4512e61e86Sserge oitv.it_value.tv_sec -= itp->it_value.tv_sec;
4612e61e86Sserge oitv.it_value.tv_usec -= itp->it_value.tv_usec;
4712e61e86Sserge if (oitv.it_value.tv_usec < 0) {
4812e61e86Sserge oitv.it_value.tv_usec += USPS;
4912e61e86Sserge oitv.it_value.tv_sec--;
5012e61e86Sserge }
5112e61e86Sserge } else {
5212e61e86Sserge itp->it_value = oitv.it_value;
5312e61e86Sserge oitv.it_value.tv_sec = 0;
5412e61e86Sserge oitv.it_value.tv_usec = 2 * TICK;
5512e61e86Sserge }
5612e61e86Sserge }
57f9c00025Sbostic setvec(vec, sleephandler);
5812e61e86Sserge (void) sigvec(SIGALRM, &vec, &ovec);
5912e61e86Sserge omask = sigblock(sigmask(SIGALRM));
6012e61e86Sserge ringring = 0;
6112e61e86Sserge (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
6212e61e86Sserge while (!ringring)
6312e61e86Sserge sigpause(omask &~ sigmask(SIGALRM));
6412e61e86Sserge (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
6512e61e86Sserge (void) sigsetmask(omask);
6612e61e86Sserge (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
6712e61e86Sserge }
6812e61e86Sserge
69f9c00025Sbostic static void
sleephandler()70f9c00025Sbostic sleephandler()
7112e61e86Sserge {
7212e61e86Sserge ringring = 1;
7312e61e86Sserge }
74