sleep.c revision 25870
11573Srgrimes/*
21573Srgrimes * Copyright (c) 1989, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 3. All advertising materials mentioning features or use of this software
141573Srgrimes *    must display the following acknowledgement:
151573Srgrimes *	This product includes software developed by the University of
161573Srgrimes *	California, Berkeley and its contributors.
171573Srgrimes * 4. Neither the name of the University nor the names of its contributors
181573Srgrimes *    may be used to endorse or promote products derived from this software
191573Srgrimes *    without specific prior written permission.
201573Srgrimes *
211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311573Srgrimes * SUCH DAMAGE.
321573Srgrimes */
331573Srgrimes
341573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
351573Srgrimesstatic char sccsid[] = "@(#)sleep.c	8.1 (Berkeley) 6/4/93";
361573Srgrimes#endif /* LIBC_SCCS and not lint */
371573Srgrimes
381573Srgrimes#include <sys/time.h>
3911659Sphk#include <signal.h>
401573Srgrimes#include <unistd.h>
4125861Sache#ifdef  _THREAD_SAFE
4225861Sache#include <pthread.h>
4325861Sache#include "pthread_private.h"
4425862Speter#endif
451573Srgrimes
4625862Speter#if !defined(_THREAD_SAFE) && !defined(USE_NANOSLEEP)
4725861Sache#define	setvec(vec, a) \
4825861Sache	vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
4925861Sache
5025861Sachestatic int ringring;
5125862Speter
5225862Speterstatic void
5325862Spetersleephandler()
5425862Speter{
5525862Speter	ringring = 1;
5625862Speter}
5725861Sache#endif
5825861Sache
591573Srgrimesunsigned int
601573Srgrimessleep(seconds)
611573Srgrimes	unsigned int seconds;
621573Srgrimes{
6325862Speter#if defined(_THREAD_SAFE) || defined(USE_NANOSLEEP)
6425862Speter	struct timespec time_to_sleep;
6525862Speter	struct timespec time_remaining;
6613545Sjulian
6725862Speter	if (seconds != 0) {
6825862Speter		time_to_sleep.tv_sec = seconds;
6925862Speter		time_to_sleep.tv_nsec = 0;
7025862Speter		nanosleep(&time_to_sleep, &time_remaining);
7125862Speter		seconds = time_remaining.tv_sec;
7225870Speter		if (time_remaining.tv_nsec > 0)
7325870Speter			seconds++;	/* round up */
7425862Speter	}
7525862Speter	return (seconds);
7625861Sache#else
7725861Sache	register struct itimerval *itp;
7825861Sache	struct itimerval itv, oitv;
7925861Sache	struct sigvec vec, ovec;
8025861Sache	long omask;
8125861Sache	static void sleephandler();
8225861Sache
8325861Sache	itp = &itv;
8425861Sache	if (!seconds)
8525861Sache		return 0;
8625861Sache	timerclear(&itp->it_interval);
8725861Sache	timerclear(&itp->it_value);
8825861Sache	if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
8925861Sache		return seconds;
9025861Sache	itp->it_value.tv_sec = seconds;
9125861Sache	if (timerisset(&oitv.it_value)) {
9225861Sache		if (timercmp(&oitv.it_value, &itp->it_value, >))
9325861Sache			oitv.it_value.tv_sec -= itp->it_value.tv_sec;
9425861Sache		else {
9525861Sache			itp->it_value = oitv.it_value;
9625861Sache			/*
9725861Sache			 * This is a hack, but we must have time to return
9825861Sache			 * from the setitimer after the alarm or else it'll
9925861Sache			 * be restarted.  And, anyway, sleep never did
10025861Sache			 * anything more than this before.
10125861Sache			 */
10225861Sache			oitv.it_value.tv_sec = 1;
10325861Sache			oitv.it_value.tv_usec = 0;
10425861Sache		}
1051573Srgrimes	}
10625861Sache	setvec(vec, sleephandler);
10725861Sache	(void) sigvec(SIGALRM, &vec, &ovec);
10825861Sache	omask = sigblock(sigmask(SIGALRM));
10925861Sache	ringring = 0;
11025861Sache	(void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
11125861Sache	while (!ringring)
11225861Sache		sigpause(omask &~ sigmask(SIGALRM));
11325861Sache	(void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
11425861Sache	(void) sigsetmask(omask);
11525861Sache	(void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
11625861Sache	return 0;
11725861Sache#endif
1181573Srgrimes}
119