timemodule.c revision 80c9d88cbfb50dcf65e57da7283ee2d73b8d3698
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 THINK_C
73#ifndef THINK_C_3_0
74/* Difference in origin between Mac and Unix clocks: */
75#define TIMEDIFF ((time_t) \
76	(((1970-1904)*365L + (1970-1904)/4) * 24 * 3600))
77	secs -= TIMEDIFF;
78#endif
79#endif
80	return newintobject((long)secs);
81}
82
83static jmp_buf sleep_intr;
84
85static void
86sleep_catcher(sig)
87	int sig;
88{
89	longjmp(sleep_intr, 1);
90}
91
92static object *
93time_sleep(self, args)
94	object *self;
95	object *args;
96{
97	int secs;
98	SIGTYPE (*sigsave)();
99	if (!getintarg(args, &secs))
100		return NULL;
101	if (setjmp(sleep_intr)) {
102		signal(SIGINT, sigsave);
103		err_set(KeyboardInterrupt);
104		return NULL;
105	}
106	sigsave = signal(SIGINT, SIG_IGN);
107	if (sigsave != (SIGTYPE (*)()) SIG_IGN)
108		signal(SIGINT, sleep_catcher);
109	sleep(secs);
110	signal(SIGINT, sigsave);
111	INCREF(None);
112	return None;
113}
114
115#ifdef THINK_C
116#define DO_MILLI
117#endif /* THINK_C */
118
119#ifdef AMOEBA
120#define DO_MILLI
121extern long sys_milli();
122#define millitimer sys_milli
123#endif /* AMOEBA */
124
125#ifdef BSD_TIME
126#define DO_MILLI
127#endif /* BSD_TIME */
128
129#ifdef TURBO_C
130#define DO_MILLI
131#endif
132
133#ifdef DO_MILLI
134
135static object *
136time_millisleep(self, args)
137	object *self;
138	object *args;
139{
140	long msecs;
141	SIGTYPE (*sigsave)();
142	if (!getlongarg(args, &msecs))
143		return NULL;
144	if (setjmp(sleep_intr)) {
145		signal(SIGINT, sigsave);
146		err_set(KeyboardInterrupt);
147		return NULL;
148	}
149	sigsave = signal(SIGINT, SIG_IGN);
150	if (sigsave != (SIGTYPE (*)()) SIG_IGN)
151		signal(SIGINT, sleep_catcher);
152	millisleep(msecs);
153	signal(SIGINT, sigsave);
154	INCREF(None);
155	return None;
156}
157
158static object *
159time_millitimer(self, args)
160	object *self;
161	object *args;
162{
163	long msecs;
164	extern long millitimer();
165	if (!getnoarg(args))
166		return NULL;
167	msecs = millitimer();
168	return newintobject(msecs);
169}
170
171#endif /* DO_MILLI */
172
173
174static struct methodlist time_methods[] = {
175#ifdef DO_MILLI
176	{"millisleep",	time_millisleep},
177	{"millitimer",	time_millitimer},
178#endif /* DO_MILLI */
179	{"sleep",	time_sleep},
180	{"time",	time_time},
181	{NULL,		NULL}		/* sentinel */
182};
183
184
185void
186inittime()
187{
188	initmodule("time", time_methods);
189}
190
191
192#ifdef THINK_C
193
194#define MacTicks	(* (long *)0x16A)
195
196#ifdef THINK_C_3_0
197sleep(msecs)
198	int msecs;
199{
200	register long deadline;
201
202	deadline = MacTicks + msecs * 60;
203	while (MacTicks < deadline) {
204		if (intrcheck())
205			sleep_catcher(SIGINT);
206	}
207}
208#endif
209
210millisleep(msecs)
211	long msecs;
212{
213	register long deadline;
214
215	deadline = MacTicks + msecs * 3 / 50; /* msecs * 60 / 1000 */
216	while (MacTicks < deadline) {
217		if (intrcheck())
218			sleep_catcher(SIGINT);
219	}
220}
221
222long
223millitimer()
224{
225	return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
226}
227
228#endif /* THINK_C */
229
230
231#ifdef BSD_TIME
232
233long
234millitimer()
235{
236	struct timeval t;
237	struct timezone tz;
238	if (gettimeofday(&t, &tz) != 0)
239		return -1;
240	return t.tv_sec*1000 + t.tv_usec/1000;
241
242}
243
244millisleep(msecs)
245	long msecs;
246{
247	struct timeval t;
248	t.tv_sec = msecs/1000;
249	t.tv_usec = (msecs%1000)*1000;
250	(void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
251}
252
253#endif /* BSD_TIME */
254
255
256#ifdef TURBO_C /* Maybe also for MS-DOS? */
257
258#ifndef CLOCKS_PER_SEC
259#define CLOCKS_PER_SEC 55	/* 54.945 msec per tick (18.2 HZ clock) */
260#endif
261
262static
263millisleep(msecs)
264	long msecs;
265{
266	delay(msecs);
267}
268
269static long
270millitimer()
271{
272	clock_t ticks;
273
274	ticks = clock();	/* ticks since program start */
275	return ticks * CLOCKS_PER_SEC;
276}
277
278#endif /* TURBO_C */
279