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