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