sleep.c revision 28172
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
4626338Speter#ifndef _THREAD_SAFE
4725862Speterstatic void
4825862Spetersleephandler()
4925862Speter{
5026385Speter	return;
5125862Speter}
5226338Speter#endif	/* _THREAD_SAFE */
5325861Sache
541573Srgrimesunsigned int
551573Srgrimessleep(seconds)
561573Srgrimes	unsigned int seconds;
571573Srgrimes{
5826338Speter#ifdef _THREAD_SAFE
5925862Speter	struct timespec time_to_sleep;
6025862Speter	struct timespec time_remaining;
6113545Sjulian
6225862Speter	if (seconds != 0) {
6325862Speter		time_to_sleep.tv_sec = seconds;
6425862Speter		time_to_sleep.tv_nsec = 0;
6528172Sache		(void)nanosleep(&time_to_sleep, &time_remaining);
6628172Sache		seconds = time_remaining.tv_sec;
6725870Speter		if (time_remaining.tv_nsec > 0)
6828172Sache			seconds++;      /* round up */
6925862Speter	}
7028172Sache	return (seconds);
7125861Sache#else
7226338Speter	struct timespec time_to_sleep;
7326338Speter	struct timespec time_remaining;
7426338Speter	struct sigaction act, oact;
7526338Speter	sigset_t mask, omask;
7628125Sache	int alarm_blocked;
7726338Speter
7826338Speter	if (seconds != 0) {
7928172Sache		time_to_sleep.tv_sec = seconds;
8028172Sache		time_to_sleep.tv_nsec = 0;
8126338Speter
8228125Sache		/* Block SIGALRM while fiddling with it */
8326338Speter		sigemptyset(&mask);
8426338Speter		sigaddset(&mask, SIGALRM);
8528172Sache		if (sigprocmask(SIG_BLOCK, &mask, &omask))
8628172Sache			return (seconds);
8726338Speter
8828125Sache		/* Was SIGALRM blocked already? */
8928125Sache		alarm_blocked = sigismember(&omask, SIGALRM);
9026338Speter
9128125Sache		if (!alarm_blocked) {
9228125Sache			/*
9328125Sache			 * Set up handler to interrupt signanosleep only if
9428125Sache			 * SIGALRM was unblocked. (Save some syscalls)
9528125Sache			 */
9628125Sache			memset(&act, 0, sizeof(act));
9728125Sache			act.sa_handler = sleephandler;
9828172Sache			if (sigaction(SIGALRM, &act, &oact)) {
9928172Sache				(void)sigprocmask(SIG_SETMASK, &omask,
10028172Sache						  (sigset_t *)0);
10128172Sache				return (seconds);
10228172Sache			}
10328125Sache		}
10426338Speter
10528125Sache  		/*
10628125Sache  		 * signanosleep() uses the given mask for the lifetime of
10728125Sache  		 * the syscall only - it resets on return.  Note that the
10828125Sache		 * old sleep() explicitly unblocks SIGALRM during the sleep,
10928125Sache		 * we don't do that now since we don't depend on SIGALRM
11028125Sache		 * to end the timeout.  If the process blocks SIGALRM, it
11128125Sache		 * gets what it asks for.
11228125Sache  		 */
11328172Sache		(void)signanosleep(&time_to_sleep, &time_remaining, &omask);
11428125Sache
11528128Sache		if (!alarm_blocked) {
11628128Sache			/* Unwind */
11728172Sache			(void)sigaction(SIGALRM, &oact, (struct sigaction *)0);
11828172Sache			(void)sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
11928128Sache		}
12028128Sache
12126338Speter		/* return how long is left */
12228172Sache		seconds = time_remaining.tv_sec;
12326338Speter		if (time_remaining.tv_nsec > 0)
12428172Sache			seconds++;      /* round up */
12526338Speter	}
12628172Sache	return (seconds);
12726338Speter#endif	/* _THREAD_SAFE */
1281573Srgrimes}
129