timemodule.c revision 00c567ce6f7c796a11ca3db36b22b6dbd24797cc
1/***********************************************************
2Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The
3Netherlands.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Time module */
26
27#include "allobjects.h"
28
29#include "modsupport.h"
30
31#include "sigtype.h"
32
33#include <signal.h>
34#include <setjmp.h>
35
36/* What happens here is not trivial.
37   The BSD_TIME code needs <sys/time.h> (for struct timeval).
38   The rest of the code needs only time_t, except some MS-DOS
39   code which needs clock_t as well.
40   Standard C says that time_t is defined in <time.h>, and
41   does not have <sys/types.h>; THINK C agrees (MS-DOS too?).
42   What's worse, in pure 4.3 BSD, older SunOS versions, and
43   probably everything derived from BSD, you can't #include
44   both <time.h> and <sys/time.h> in the same file, since
45   <sys/time.h> includes <time.h> without any protection,
46   and <time.h> contains a typedef, which can't be parsed twice!
47   So on traditional UNIX systems we include <sys/types.h>
48   and <sys/time.h> and hope this implies <time.h> and time_t,
49   while on other systems, including conforming Standard C
50   systems (where 'unix' can't be defined), we rely on <time.h>.
51   Still one problem: BSD_TIME won't work with strict Standard C...
52*/
53
54#ifdef unix
55#include <sys/types.h>
56#include <sys/time.h> /* Implies <time.h> everywhere, as far as I know */
57#else /* !unix */
58#include <time.h>
59#endif /* !unix */
60
61/* Time methods */
62
63static object *
64time_time(self, args)
65	object *self;
66	object *args;
67{
68	time_t secs;
69	if (!getnoarg(args))
70		return NULL;
71	time(&secs);
72#ifdef macintosh
73/* The Mac epoch is 1904, while UNIX uses 1970; Python prefers 1970 */
74/* Moreover, the Mac returns local time.  This we cannot fix... */
75#define TIMEDIFF ((time_t) \
76	(((1970-1904)*365L + (1970-1904)/4) * 24 * 3600))
77	secs -= TIMEDIFF;
78#endif
79	return newintobject((long)secs);
80}
81
82static jmp_buf sleep_intr;
83
84static void
85sleep_catcher(sig)
86	int sig;
87{
88	longjmp(sleep_intr, 1);
89}
90
91static object *
92time_sleep(self, args)
93	object *self;
94	object *args;
95{
96	int secs;
97	SIGTYPE (*sigsave)();
98	if (!getintarg(args, &secs))
99		return NULL;
100	if (setjmp(sleep_intr)) {
101		signal(SIGINT, sigsave);
102		err_set(KeyboardInterrupt);
103		return NULL;
104	}
105	sigsave = signal(SIGINT, SIG_IGN);
106	if (sigsave != (SIGTYPE (*)()) SIG_IGN)
107		signal(SIGINT, sleep_catcher);
108	sleep(secs);
109	signal(SIGINT, sigsave);
110	INCREF(None);
111	return None;
112}
113
114#ifdef macintosh
115#define DO_MILLI
116#endif
117
118#ifdef AMOEBA
119#define DO_MILLI
120extern long sys_milli();
121#define millitimer sys_milli
122#endif /* AMOEBA */
123
124#ifdef BSD_TIME
125#define DO_MILLI
126#endif /* BSD_TIME */
127
128#ifdef TURBO_C
129#define DO_MILLI
130#endif
131
132#ifdef DO_MILLI
133
134static object *
135time_millisleep(self, args)
136	object *self;
137	object *args;
138{
139	long msecs;
140	SIGTYPE (*sigsave)();
141	if (!getlongarg(args, &msecs))
142		return NULL;
143	if (setjmp(sleep_intr)) {
144		signal(SIGINT, sigsave);
145		err_set(KeyboardInterrupt);
146		return NULL;
147	}
148	sigsave = signal(SIGINT, SIG_IGN);
149	if (sigsave != (SIGTYPE (*)()) SIG_IGN)
150		signal(SIGINT, sleep_catcher);
151	millisleep(msecs);
152	signal(SIGINT, sigsave);
153	INCREF(None);
154	return None;
155}
156
157static object *
158time_millitimer(self, args)
159	object *self;
160	object *args;
161{
162	long msecs;
163	extern long millitimer();
164	if (!getnoarg(args))
165		return NULL;
166	msecs = millitimer();
167	return newintobject(msecs);
168}
169
170#endif /* DO_MILLI */
171
172
173static struct methodlist time_methods[] = {
174#ifdef DO_MILLI
175	{"millisleep",	time_millisleep},
176	{"millitimer",	time_millitimer},
177#endif /* DO_MILLI */
178	{"sleep",	time_sleep},
179	{"time",	time_time},
180	{NULL,		NULL}		/* sentinel */
181};
182
183
184void
185inittime()
186{
187	initmodule("time", time_methods);
188}
189
190
191#ifdef macintosh
192
193#define MacTicks	(* (long *)0x16A)
194
195#ifdef THINK_C_3_0
196sleep(msecs)
197	int msecs;
198{
199	register long deadline;
200
201	deadline = MacTicks + msecs * 60;
202	while (MacTicks < deadline) {
203		if (intrcheck())
204			sleep_catcher(SIGINT);
205	}
206}
207#endif
208
209millisleep(msecs)
210	long msecs;
211{
212	register long deadline;
213
214	deadline = MacTicks + msecs * 3 / 50; /* msecs * 60 / 1000 */
215	while (MacTicks < deadline) {
216		if (intrcheck())
217			sleep_catcher(SIGINT);
218	}
219}
220
221long
222millitimer()
223{
224	return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
225}
226
227#endif /* macintosh */
228
229
230#ifdef BSD_TIME
231
232#ifdef _IBMR2
233/* AIX defines fd_set in a separate file.  Sigh... */
234#include <sys/select.h>
235#endif
236
237long
238millitimer()
239{
240	struct timeval t;
241	struct timezone tz;
242	if (gettimeofday(&t, &tz) != 0)
243		return -1;
244	return t.tv_sec*1000 + t.tv_usec/1000;
245
246}
247
248millisleep(msecs)
249	long msecs;
250{
251	struct timeval t;
252	t.tv_sec = msecs/1000;
253	t.tv_usec = (msecs%1000)*1000;
254	(void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
255}
256
257#endif /* BSD_TIME */
258
259
260#ifdef TURBO_C /* Maybe also for MS-DOS? */
261
262#ifndef CLOCKS_PER_SEC
263#define CLOCKS_PER_SEC 55	/* 54.945 msec per tick (18.2 HZ clock) */
264#endif
265
266static
267millisleep(msecs)
268	long msecs;
269{
270	delay(msecs);
271}
272
273static long
274millitimer()
275{
276	clock_t ticks;
277
278	ticks = clock();	/* ticks since program start */
279	return ticks * CLOCKS_PER_SEC;
280}
281
282#endif /* TURBO_C */
283