blob: 17dff19626d177e38482c72193f44cb5911927b7 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumf1644a51992-04-05 14:25:41 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumf70e43a1991-02-19 12:39:46 +00003Netherlands.
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
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Time module */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027#include "allobjects.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000028#include "modsupport.h"
Guido van Rossumff4949e1992-08-05 19:58:53 +000029#include "ceval.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000030
31#include "sigtype.h"
32
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000033#include <signal.h>
34#include <setjmp.h>
35
Guido van Rossuma2b7f401993-01-04 09:09:59 +000036#ifdef BSD_TIME
37#define HAVE_GETTIMEOFDAY
38#endif
39
Guido van Rossum6d946f91992-08-14 13:49:30 +000040#ifdef macintosh
41#define NO_UNISTD
42#endif
43
Guido van Rossum2762f251992-03-27 17:22:13 +000044#ifndef NO_UNISTD
45#include <unistd.h>
46#endif
47
Guido van Rossum80c9d881991-04-16 08:47:51 +000048/* What happens here is not trivial.
49 The BSD_TIME code needs <sys/time.h> (for struct timeval).
50 The rest of the code needs only time_t, except some MS-DOS
51 code which needs clock_t as well.
52 Standard C says that time_t is defined in <time.h>, and
53 does not have <sys/types.h>; THINK C agrees (MS-DOS too?).
54 What's worse, in pure 4.3 BSD, older SunOS versions, and
55 probably everything derived from BSD, you can't #include
56 both <time.h> and <sys/time.h> in the same file, since
57 <sys/time.h> includes <time.h> without any protection,
58 and <time.h> contains a typedef, which can't be parsed twice!
59 So on traditional UNIX systems we include <sys/types.h>
60 and <sys/time.h> and hope this implies <time.h> and time_t,
61 while on other systems, including conforming Standard C
62 systems (where 'unix' can't be defined), we rely on <time.h>.
63 Still one problem: BSD_TIME won't work with strict Standard C...
64*/
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000065
Guido van Rossum80c9d881991-04-16 08:47:51 +000066#ifdef unix
67#include <sys/types.h>
68#include <sys/time.h> /* Implies <time.h> everywhere, as far as I know */
69#else /* !unix */
70#include <time.h>
71#endif /* !unix */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000072
Guido van Rossum27aaa6d1992-03-12 17:33:14 +000073#ifdef DO_TIMES
74#include <sys/times.h>
75#include <sys/param.h>
76#include <errno.h>
77#endif
78
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000079/* Time methods */
80
81static object *
82time_time(self, args)
83 object *self;
84 object *args;
85{
Guido van Rossuma2b7f401993-01-04 09:09:59 +000086#ifdef HAVE_GETTIMEOFDAY
87 struct timeval t;
88 struct timezone tz;
89 if (!getnoarg(args))
90 return NULL;
91 if (gettimeofday(&t, &tz) != 0) {
92 err_errno(IOError);
93 return NULL;
94 }
95 return newfloatobject(t.tv_sec*1.0 + t.tv_usec*0.000001);
96#else /* !HAVE_GETTIMEOFDAY */
Guido van Rossum6590d4a1991-04-04 10:49:03 +000097 time_t secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000098 if (!getnoarg(args))
99 return NULL;
Guido van Rossum80c9d881991-04-16 08:47:51 +0000100 time(&secs);
Guido van Rossum00c567c1991-07-27 23:09:30 +0000101#ifdef macintosh
102/* The Mac epoch is 1904, while UNIX uses 1970; Python prefers 1970 */
103/* Moreover, the Mac returns local time. This we cannot fix... */
Guido van Rossum6590d4a1991-04-04 10:49:03 +0000104#define TIMEDIFF ((time_t) \
105 (((1970-1904)*365L + (1970-1904)/4) * 24 * 3600))
106 secs -= TIMEDIFF;
Guido van Rossum00c567c1991-07-27 23:09:30 +0000107#endif
Guido van Rossuma2b7f401993-01-04 09:09:59 +0000108 return newfloatobject((double)secs);
109#endif /* !HAVE_GETTIMEOFDAY */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000110}
111
112static jmp_buf sleep_intr;
113
Guido van Rossum2762f251992-03-27 17:22:13 +0000114/* ARGSUSED */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000115static void
116sleep_catcher(sig)
Guido van Rossum2762f251992-03-27 17:22:13 +0000117 int sig; /* Not used but required by interface */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000118{
119 longjmp(sleep_intr, 1);
120}
121
122static object *
123time_sleep(self, args)
124 object *self;
125 object *args;
126{
Guido van Rossumff4949e1992-08-05 19:58:53 +0000127 long secs;
Guido van Rossum2762f251992-03-27 17:22:13 +0000128 SIGTYPE (*sigsave)() = 0; /* Initialized to shut lint up */
Guido van Rossumff4949e1992-08-05 19:58:53 +0000129 if (!getargs(args, "l", &secs))
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000131 BGN_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132 if (setjmp(sleep_intr)) {
Guido van Rossumff4949e1992-08-05 19:58:53 +0000133 RET_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000134 signal(SIGINT, sigsave);
135 err_set(KeyboardInterrupt);
136 return NULL;
137 }
138 sigsave = signal(SIGINT, SIG_IGN);
139 if (sigsave != (SIGTYPE (*)()) SIG_IGN)
140 signal(SIGINT, sleep_catcher);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000141#ifdef BSD_TIME
142 longsleep(secs);
143#else
144 sleep((int)secs);
145#endif
146 END_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000147 signal(SIGINT, sigsave);
148 INCREF(None);
149 return None;
150}
151
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000152#ifdef macintosh
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000153#define DO_MILLI
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000154#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000155
156#ifdef AMOEBA
157#define DO_MILLI
158extern long sys_milli();
159#define millitimer sys_milli
160#endif /* AMOEBA */
161
Guido van Rossum426035c1991-02-19 12:27:35 +0000162#ifdef BSD_TIME
163#define DO_MILLI
164#endif /* BSD_TIME */
165
Guido van Rossum80c9d881991-04-16 08:47:51 +0000166#ifdef TURBO_C
167#define DO_MILLI
168#endif
169
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000170#ifdef DO_MILLI
171
172static object *
173time_millisleep(self, args)
174 object *self;
175 object *args;
176{
177 long msecs;
178 SIGTYPE (*sigsave)();
179 if (!getlongarg(args, &msecs))
180 return NULL;
Guido van Rossumff4949e1992-08-05 19:58:53 +0000181 BGN_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000182 if (setjmp(sleep_intr)) {
Guido van Rossumff4949e1992-08-05 19:58:53 +0000183 RET_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000184 signal(SIGINT, sigsave);
185 err_set(KeyboardInterrupt);
186 return NULL;
187 }
188 sigsave = signal(SIGINT, SIG_IGN);
189 if (sigsave != (SIGTYPE (*)()) SIG_IGN)
190 signal(SIGINT, sleep_catcher);
191 millisleep(msecs);
Guido van Rossumff4949e1992-08-05 19:58:53 +0000192 END_SAVE
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000193 signal(SIGINT, sigsave);
194 INCREF(None);
195 return None;
196}
197
198static object *
199time_millitimer(self, args)
200 object *self;
201 object *args;
202{
203 long msecs;
204 extern long millitimer();
205 if (!getnoarg(args))
206 return NULL;
207 msecs = millitimer();
208 return newintobject(msecs);
209}
210
211#endif /* DO_MILLI */
212
Guido van Rossum27aaa6d1992-03-12 17:33:14 +0000213#ifdef DO_TIMES
214
215static object *
216time_times(self, args)
217 object *self;
218 object *args;
219{
220 struct tms t;
221 clock_t c;
222 object *tuple;
Guido van Rossum2762f251992-03-27 17:22:13 +0000223 if (!getnoarg(args))
224 return NULL;
Guido van Rossum27aaa6d1992-03-12 17:33:14 +0000225 errno = 0;
226 c = times(&t);
227 if (c == (clock_t) -1) {
228 err_errno(IOError);
229 return NULL;
230 }
231 tuple = newtupleobject(4);
232 if (tuple == NULL)
233 return NULL;
234 settupleitem(tuple, 0, newfloatobject((double)t.tms_utime / HZ));
235 settupleitem(tuple, 1, newfloatobject((double)t.tms_stime / HZ));
236 settupleitem(tuple, 2, newfloatobject((double)t.tms_cutime / HZ));
237 settupleitem(tuple, 3, newfloatobject((double)t.tms_cstime / HZ));
238 if (err_occurred()) {
239 DECREF(tuple);
240 return NULL;
241 }
242 return tuple;
243}
244
245#endif
246
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000247
248static struct methodlist time_methods[] = {
249#ifdef DO_MILLI
250 {"millisleep", time_millisleep},
251 {"millitimer", time_millitimer},
252#endif /* DO_MILLI */
Guido van Rossum27aaa6d1992-03-12 17:33:14 +0000253#ifdef DO_TIMES
254 {"times", time_times},
255#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000256 {"sleep", time_sleep},
257 {"time", time_time},
258 {NULL, NULL} /* sentinel */
259};
260
261
262void
263inittime()
264{
265 initmodule("time", time_methods);
266}
267
268
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000269#ifdef macintosh
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000270
271#define MacTicks (* (long *)0x16A)
272
Guido van Rossum80c9d881991-04-16 08:47:51 +0000273#ifdef THINK_C_3_0
Guido van Rossumff4949e1992-08-05 19:58:53 +0000274sleep(secs)
275 int secs;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000276{
277 register long deadline;
278
Guido van Rossumff4949e1992-08-05 19:58:53 +0000279 deadline = MacTicks + mecs * 60;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000280 while (MacTicks < deadline) {
281 if (intrcheck())
282 sleep_catcher(SIGINT);
283 }
284}
Guido van Rossum80c9d881991-04-16 08:47:51 +0000285#endif
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000286
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000287millisleep(msecs)
288 long msecs;
289{
290 register long deadline;
291
292 deadline = MacTicks + msecs * 3 / 50; /* msecs * 60 / 1000 */
293 while (MacTicks < deadline) {
294 if (intrcheck())
295 sleep_catcher(SIGINT);
296 }
297}
298
Guido van Rossum6590d4a1991-04-04 10:49:03 +0000299long
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000300millitimer()
301{
302 return MacTicks * 50 / 3; /* MacTicks * 1000 / 60 */
303}
304
Guido van Rossum1d2a9ad1991-06-24 22:23:45 +0000305#endif /* macintosh */
Guido van Rossum426035c1991-02-19 12:27:35 +0000306
307
308#ifdef BSD_TIME
309
Guido van Rossumed233a51992-06-23 09:07:03 +0000310#include "myselect.h" /* Implies <sys/types.h>, <sys/time.h>, <sys/param.h> */
Guido van Rossum6a1f54c1991-05-05 20:15:54 +0000311
Guido van Rossum56627461991-04-03 19:15:32 +0000312long
Guido van Rossum426035c1991-02-19 12:27:35 +0000313millitimer()
314{
315 struct timeval t;
316 struct timezone tz;
317 if (gettimeofday(&t, &tz) != 0)
318 return -1;
319 return t.tv_sec*1000 + t.tv_usec/1000;
Guido van Rossum426035c1991-02-19 12:27:35 +0000320}
321
Guido van Rossum426035c1991-02-19 12:27:35 +0000322millisleep(msecs)
323 long msecs;
324{
325 struct timeval t;
326 t.tv_sec = msecs/1000;
327 t.tv_usec = (msecs%1000)*1000;
328 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
329}
330
Guido van Rossumff4949e1992-08-05 19:58:53 +0000331longsleep(secs)
332 long secs;
333{
334 struct timeval t;
335 t.tv_sec = secs;
336 t.tv_usec = 0;
337 (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
338}
339
Guido van Rossum426035c1991-02-19 12:27:35 +0000340#endif /* BSD_TIME */
341
Guido van Rossum80c9d881991-04-16 08:47:51 +0000342
343#ifdef TURBO_C /* Maybe also for MS-DOS? */
344
345#ifndef CLOCKS_PER_SEC
346#define CLOCKS_PER_SEC 55 /* 54.945 msec per tick (18.2 HZ clock) */
347#endif
348
349static
350millisleep(msecs)
351 long msecs;
352{
353 delay(msecs);
354}
355
356static long
357millitimer()
358{
359 clock_t ticks;
360
361 ticks = clock(); /* ticks since program start */
362 return ticks * CLOCKS_PER_SEC;
363}
364
365#endif /* TURBO_C */