aboutsummaryrefslogtreecommitdiff
path: root/unix/os/zwmsec.c
blob: 617478b8082cd33afc2a62490110b49c793818a8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
 */

#include <stdio.h>
#define	import_kernel
#define	import_knames
#define import_spp
#include <iraf.h>

/* Comment out or ifdef the following if usleep is not available. */
#define USE_USLEEP

#ifdef USE_USLEEP
#define ONEHOUR (60 * 60 * 1000)


/* ZWMSEC -- Suspend task execution (sleep) for the specified number
 * of milliseconds.
 */
int
ZWMSEC (XINT *msec)
{
	/* Usleep doesn't really appear to be a standard, but it is
	 * available on most platforms.
	 */
	if (*msec > ONEHOUR)
	    sleep (*msec / 1000);
	else
	    (void) usleep ((unsigned int)(*msec) * 1000);

	return (XOK);
}


#else
#include <sys/time.h>
#include <signal.h>

#define	mask(s)	(1<<((s)-1))

static int ringring;
static void napmsx();


/* ZWMSEC -- Suspend task execution (sleep) for the specified number
 * of milliseconds.
 */
int
ZWMSEC (XINT *msec)
{
	struct itimerval itv, oitv;
	register struct itimerval *itp = &itv;
	SIGFUNC	sv_handler;
	int omask;

	if (*msec == 0)
	    return (XOK);

	timerclear (&itp->it_interval);
	timerclear (&itp->it_value);
	if (setitimer (ITIMER_REAL, itp, &oitv) < 0)
	    return (XERR);

#ifndef SOLARIS
	omask = sigblock(0);
#endif

	itp->it_value.tv_usec = (*msec % 1000) * 1000;
	itp->it_value.tv_sec  = (*msec / 1000);

	if (timerisset (&oitv.it_value)) {
	    if (timercmp(&oitv.it_value, &itp->it_value, >))
		oitv.it_value.tv_sec -= itp->it_value.tv_sec;
	    else {
		itp->it_value = oitv.it_value;
		/* This is a hack, but we must have time to
		 * return from the setitimer after the alarm
		 * or else it'll be restarted.  And, anyway,
		 * sleep never did anything more than this before.
		 */
		oitv.it_value.tv_sec  = 1;
		oitv.it_value.tv_usec = 0;
	    }
	}

	ringring = 0;
	sv_handler = signal (SIGALRM, (SIGFUNC)napmsx);
	(void) setitimer (ITIMER_REAL, itp, (struct itimerval *)0);

	while (!ringring)
#ifdef SOLARIS
	    sigpause (SIGALRM);
#else
	    sigpause (omask &~ mask(SIGALRM));
#endif

	signal (SIGALRM, sv_handler);
	(void) setitimer (ITIMER_REAL, &oitv, (struct itimerval *)0);

	return (XOK);
}


static void
napmsx()
{
	ringring = 1;
}
#endif