timemodule.c revision c410e929741252d3cfca848fcc0df616c0f225ef
1/*********************************************************** 2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, 3The Netherlands. 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 or Corporation for National Research Initiatives or 13CNRI not be used in advertising or publicity pertaining to 14distribution of the software without specific, written prior 15permission. 16 17While CWI is the initial source for this software, a modified version 18is made available by the Corporation for National Research Initiatives 19(CNRI) at the Internet address ftp://ftp.python.org. 20 21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH 22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH 24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28PERFORMANCE OF THIS SOFTWARE. 29 30******************************************************************/ 31 32/* Time module */ 33 34#include "Python.h" 35 36#include <ctype.h> 37 38#ifdef HAVE_SELECT 39#include "mymath.h" 40#endif 41 42#ifdef macintosh 43#include <time.h> 44#include <OSUtils.h> 45#ifdef USE_GUSI2 46/* GUSI, the I/O library which has the time() function and such uses the 47** Mac epoch of 1904. MSL, the C library which has localtime() and so uses 48** the ANSI epoch of 1900. 49*/ 50#define GUSI_TO_MSL_EPOCH (4*365*24*60*60) 51#endif /* USE_GUSI2 */ 52#else 53#include <sys/types.h> 54#endif 55 56#ifdef QUICKWIN 57#include <io.h> 58#endif 59 60#ifdef HAVE_UNISTD_H 61#include <unistd.h> 62#endif 63 64#if defined(HAVE_SELECT) && !defined(__BEOS__) 65#include "myselect.h" 66#else 67#include "mytime.h" 68#endif 69 70#ifdef HAVE_FTIME 71#include <sys/timeb.h> 72#if !defined(MS_WINDOWS) && !defined(PYOS_OS2) 73extern int ftime(); 74#endif /* MS_WINDOWS */ 75#endif /* HAVE_FTIME */ 76 77#if defined(__WATCOMC__) && !defined(__QNX__) 78#include <i86.h> 79#else 80#ifdef MS_WINDOWS 81#include <windows.h> 82#ifdef MS_WIN16 83/* These overrides not needed for Win32 */ 84#define timezone _timezone 85#define tzname _tzname 86#define daylight _daylight 87#define altzone _altzone 88#endif /* MS_WIN16 */ 89#endif /* MS_WINDOWS */ 90#endif /* !__WATCOMC__ || __QNX__ */ 91 92#ifdef MS_WIN32 93/* Win32 has better clock replacement */ 94#include <largeint.h> 95#undef HAVE_CLOCK /* We have our own version down below */ 96#endif /* MS_WIN32 */ 97 98#if defined(PYCC_VACPP) 99#include <sys/time.h> 100#endif 101 102#ifdef __BEOS__ 103/* For bigtime_t, snooze(). - [cjh] */ 104#include <support/SupportDefs.h> 105#include <kernel/OS.h> 106#ifndef CLOCKS_PER_SEC 107/* C'mon, fix the bloody headers... - [cjh] */ 108#define CLOCKS_PER_SEC 1000 109#endif 110#endif 111 112/* Forward declarations */ 113static int floatsleep Py_PROTO((double)); 114static double floattime Py_PROTO(()); 115 116/* For Y2K check */ 117static PyObject *moddict; 118 119#ifdef macintosh 120/* Our own timezone. We have enough information to deduce whether 121** DST is on currently, but unfortunately we cannot put it to good 122** use because we don't know the rules (and that is needed to have 123** localtime() return correct tm_isdst values for times other than 124** the current time. So, we cop out and only tell the user the current 125** timezone. 126*/ 127static long timezone; 128 129static void 130initmactimezone() 131{ 132 MachineLocation loc; 133 long delta; 134 135 ReadLocation(&loc); 136 137 if (loc.latitude == 0 && loc.longitude == 0 && loc.u.gmtDelta == 0) 138 return; 139 140 delta = loc.u.gmtDelta & 0x00FFFFFF; 141 142 if (delta & 0x00800000) 143 delta |= 0xFF000000; 144 145 timezone = -delta; 146} 147#endif /* macintosh */ 148 149 150static PyObject * 151time_time(self, args) 152 PyObject *self; 153 PyObject *args; 154{ 155 double secs; 156 if (!PyArg_NoArgs(args)) 157 return NULL; 158 secs = floattime(); 159 if (secs == 0.0) { 160 PyErr_SetFromErrno(PyExc_IOError); 161 return NULL; 162 } 163 return PyFloat_FromDouble(secs); 164} 165 166static char time_doc[] = 167"time() -> floating point number\n\ 168\n\ 169Return the current time in seconds since the Epoch.\n\ 170Fractions of a second may be present if the system clock provides them."; 171 172#ifdef HAVE_CLOCK 173 174#ifndef CLOCKS_PER_SEC 175#ifdef CLK_TCK 176#define CLOCKS_PER_SEC CLK_TCK 177#else 178#define CLOCKS_PER_SEC 1000000 179#endif 180#endif 181 182static PyObject * 183time_clock(self, args) 184 PyObject *self; 185 PyObject *args; 186{ 187 if (!PyArg_NoArgs(args)) 188 return NULL; 189 return PyFloat_FromDouble(((double)clock()) / CLOCKS_PER_SEC); 190} 191#endif /* HAVE_CLOCK */ 192 193#ifdef MS_WIN32 194/* Due to Mark Hammond */ 195static PyObject * 196time_clock(self, args) 197 PyObject *self; 198 PyObject *args; 199{ 200 static LARGE_INTEGER ctrStart; 201 static LARGE_INTEGER divisor = {0,0}; 202 LARGE_INTEGER now, diff, rem; 203 204 if (!PyArg_NoArgs(args)) 205 return NULL; 206 207 if (LargeIntegerEqualToZero(divisor)) { 208 QueryPerformanceCounter(&ctrStart); 209 if (!QueryPerformanceFrequency(&divisor) || 210 LargeIntegerEqualToZero(divisor)) { 211 /* Unlikely to happen - 212 this works on all intel machines at least! 213 Revert to clock() */ 214 return PyFloat_FromDouble(clock()); 215 } 216 } 217 QueryPerformanceCounter(&now); 218 diff = LargeIntegerSubtract(now, ctrStart); 219 diff = LargeIntegerDivide(diff, divisor, &rem); 220 /* XXX - we assume both divide results fit in 32 bits. This is 221 true on Intels. First person who can afford a machine that 222 doesnt deserves to fix it :-) 223 */ 224 return PyFloat_FromDouble((double)diff.LowPart + 225 ((double)rem.LowPart / (double)divisor.LowPart)); 226} 227 228#define HAVE_CLOCK /* So it gets included in the methods */ 229#endif /* MS_WIN32 */ 230 231#ifdef HAVE_CLOCK 232static char clock_doc[] = 233"clock() -> floating point number\n\ 234\n\ 235Return the CPU time or real time since the start of the process or since\n\ 236the first call to clock(). This has as much precision as the system records."; 237#endif 238 239static PyObject * 240time_sleep(self, args) 241 PyObject *self; 242 PyObject *args; 243{ 244 double secs; 245 if (!PyArg_Parse(args, "d", &secs)) 246 return NULL; 247 if (floatsleep(secs) != 0) 248 return NULL; 249 Py_INCREF(Py_None); 250 return Py_None; 251} 252 253static char sleep_doc[] = 254"sleep(seconds)\n\ 255\n\ 256Delay execution for a given number of seconds. The argument may be\n\ 257a floating point number for subsecond precision."; 258 259static PyObject * 260tmtotuple(p) 261 struct tm *p; 262{ 263 return Py_BuildValue("(iiiiiiiii)", 264 p->tm_year + 1900, 265 p->tm_mon + 1, /* Want January == 1 */ 266 p->tm_mday, 267 p->tm_hour, 268 p->tm_min, 269 p->tm_sec, 270 (p->tm_wday + 6) % 7, /* Want Monday == 0 */ 271 p->tm_yday + 1, /* Want January, 1 == 1 */ 272 p->tm_isdst); 273} 274 275static PyObject * 276time_convert(when, function) 277 time_t when; 278 struct tm * (*function) Py_PROTO((const time_t *)); 279{ 280 struct tm *p; 281 errno = 0; 282#if defined(macintosh) && defined(USE_GUSI2) 283 when = when + GUSI_TO_MSL_EPOCH; 284#endif 285 p = function(&when); 286 if (p == NULL) { 287#ifdef EINVAL 288 if (errno == 0) 289 errno = EINVAL; 290#endif 291 return PyErr_SetFromErrno(PyExc_IOError); 292 } 293 return tmtotuple(p); 294} 295 296static PyObject * 297time_gmtime(self, args) 298 PyObject *self; 299 PyObject *args; 300{ 301 double when; 302 if (!PyArg_Parse(args, "d", &when)) 303 return NULL; 304 return time_convert((time_t)when, gmtime); 305} 306 307static char gmtime_doc[] = 308"gmtime(seconds) -> tuple\n\ 309\n\ 310Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a. GMT)."; 311 312static PyObject * 313time_localtime(self, args) 314 PyObject *self; 315 PyObject *args; 316{ 317 double when; 318 if (!PyArg_Parse(args, "d", &when)) 319 return NULL; 320 return time_convert((time_t)when, localtime); 321} 322 323static char localtime_doc[] = 324"localtime(seconds) -> tuple\n\ 325Convert seconds since the Epoch to a time tuple expressing local time."; 326 327static int 328gettmarg(args, p) 329 PyObject *args; 330 struct tm *p; 331{ 332 int y; 333 memset((ANY *) p, '\0', sizeof(struct tm)); 334 335 if (!PyArg_Parse(args, "(iiiiiiiii)", 336 &y, 337 &p->tm_mon, 338 &p->tm_mday, 339 &p->tm_hour, 340 &p->tm_min, 341 &p->tm_sec, 342 &p->tm_wday, 343 &p->tm_yday, 344 &p->tm_isdst)) 345 return 0; 346 if (y < 1900) { 347 PyObject *accept = PyDict_GetItemString(moddict, 348 "accept2dyear"); 349 if (accept == NULL || !PyInt_Check(accept) || 350 PyInt_AsLong(accept) == 0) { 351 PyErr_SetString(PyExc_ValueError, 352 "year >= 1900 required"); 353 return 0; 354 } 355 if (69 <= y && y <= 99) 356 y += 1900; 357 else if (0 <= y && y <= 68) 358 y += 2000; 359 else { 360 PyErr_SetString(PyExc_ValueError, 361 "year out of range (00-99, 1900-*)"); 362 return 0; 363 } 364 } 365 p->tm_year = y - 1900; 366 p->tm_mon--; 367 p->tm_wday = (p->tm_wday + 1) % 7; 368 p->tm_yday--; 369 return 1; 370} 371 372#ifdef HAVE_STRFTIME 373static PyObject * 374time_strftime(self, args) 375 PyObject *self; 376 PyObject *args; 377{ 378 PyObject *tup; 379 struct tm buf; 380 const char *fmt; 381 int fmtlen, buflen; 382 char *outbuf = 0; 383 int i; 384 385 memset((ANY *) &buf, '\0', sizeof(buf)); 386 387 if (!PyArg_ParseTuple(args, "sO:strftime", &fmt, &tup) 388 || !gettmarg(tup, &buf)) 389 return NULL; 390 fmtlen = strlen(fmt); 391 392 /* I hate these functions that presume you know how big the output 393 * will be ahead of time... 394 */ 395 for (i = 1024; ; i += i) { 396 outbuf = malloc(i); 397 if (outbuf == NULL) { 398 return PyErr_NoMemory(); 399 } 400 buflen = strftime(outbuf, i, fmt, &buf); 401 if (buflen > 0 || i >= 256 * fmtlen) { 402 /* If the buffer is 256 times as long as the format, 403 it's probably not failing for lack of room! 404 More likely, the format yields an empty result, 405 e.g. an empty format, or %Z when the timezone 406 is unknown. */ 407 PyObject *ret; 408 ret = PyString_FromStringAndSize(outbuf, buflen); 409 free(outbuf); 410 return ret; 411 } 412 free(outbuf); 413 } 414} 415 416static char strftime_doc[] = 417"strftime(format, tuple) -> string\n\ 418\n\ 419Convert a time tuple to a string according to a format specification.\n\ 420See the library reference manual for formatting codes."; 421#endif /* HAVE_STRFTIME */ 422 423#ifdef HAVE_STRPTIME 424/* extern char *strptime(); /* Enable this if it's not declared in <time.h> */ 425 426static PyObject * 427time_strptime(self, args) 428 PyObject *self; 429 PyObject *args; 430{ 431 struct tm tm; 432 char *fmt = "%a %b %d %H:%M:%S %Y"; 433 char *buf; 434 char *s; 435 436 if (!PyArg_ParseTuple(args, "s|s:strptime", &buf, &fmt)) 437 return NULL; 438 memset((ANY *) &tm, '\0', sizeof(tm)); 439 s = strptime(buf, fmt, &tm); 440 if (s == NULL) { 441 PyErr_SetString(PyExc_ValueError, "format mismatch"); 442 return NULL; 443 } 444 while (*s && isspace(*s)) 445 s++; 446 if (*s) { 447 PyErr_Format(PyExc_ValueError, 448 "unconverted data remains: '%.400s'", s); 449 return NULL; 450 } 451 return tmtotuple(&tm); 452} 453 454static char strptime_doc[] = 455"strptime(string, format) -> tuple\n\ 456Parse a string to a time tuple according to a format specification.\n\ 457See the library reference manual for formatting codes (same as strftime())."; 458#endif /* HAVE_STRPTIME */ 459 460static PyObject * 461time_asctime(self, args) 462 PyObject *self; 463 PyObject *args; 464{ 465 PyObject *tup; 466 struct tm buf; 467 char *p; 468 if (!PyArg_ParseTuple(args, "O:asctime", &tup)) 469 return NULL; 470 if (!gettmarg(tup, &buf)) 471 return NULL; 472 p = asctime(&buf); 473 if (p[24] == '\n') 474 p[24] = '\0'; 475 return PyString_FromString(p); 476} 477 478static char asctime_doc[] = 479"asctime(tuple) -> string\n\ 480\n\ 481Convert a time tuple to a string, e.g. 'Sat Jun 06 16:26:11 1998'."; 482 483static PyObject * 484time_ctime(self, args) 485 PyObject *self; 486 PyObject *args; 487{ 488 double dt; 489 time_t tt; 490 char *p; 491 if (!PyArg_Parse(args, "d", &dt)) 492 return NULL; 493 tt = (time_t)dt; 494#if defined(macintosh) && defined(USE_GUSI2) 495 tt = tt + GUSI_TO_MSL_EPOCH; 496#endif 497 p = ctime(&tt); 498 if (p == NULL) { 499 PyErr_SetString(PyExc_ValueError, "unconvertible time"); 500 return NULL; 501 } 502 if (p[24] == '\n') 503 p[24] = '\0'; 504 return PyString_FromString(p); 505} 506 507static char ctime_doc[] = 508"ctime(seconds) -> string\n\ 509\n\ 510Convert a time in seconds since the Epoch to a string in local time.\n\ 511This is equivalent to asctime(localtime(seconds))."; 512 513#ifdef HAVE_MKTIME 514static PyObject * 515time_mktime(self, args) 516 PyObject *self; 517 PyObject *args; 518{ 519 PyObject *tup; 520 struct tm buf; 521 time_t tt; 522 if (!PyArg_ParseTuple(args, "O:mktime", &tup)) 523 return NULL; 524 tt = time(&tt); 525 buf = *localtime(&tt); 526 if (!gettmarg(tup, &buf)) 527 return NULL; 528 tt = mktime(&buf); 529 if (tt == (time_t)(-1)) { 530 PyErr_SetString(PyExc_OverflowError, 531 "mktime argument out of range"); 532 return NULL; 533 } 534#if defined(macintosh) && defined(USE_GUSI2) 535 tt = tt - GUSI_TO_MSL_EPOCH; 536#endif 537 return PyFloat_FromDouble((double)tt); 538} 539 540static char mktime_doc[] = 541"mktime(tuple) -> floating point number\n\ 542\n\ 543Convert a time tuple in local time to seconds since the Epoch."; 544#endif /* HAVE_MKTIME */ 545 546static PyMethodDef time_methods[] = { 547 {"time", time_time, 0, time_doc}, 548#ifdef HAVE_CLOCK 549 {"clock", time_clock, 0, clock_doc}, 550#endif 551 {"sleep", time_sleep, 0, sleep_doc}, 552 {"gmtime", time_gmtime, 0, gmtime_doc}, 553 {"localtime", time_localtime, 0, localtime_doc}, 554 {"asctime", time_asctime, 1, asctime_doc}, 555 {"ctime", time_ctime, 0, ctime_doc}, 556#ifdef HAVE_MKTIME 557 {"mktime", time_mktime, 1, mktime_doc}, 558#endif 559#ifdef HAVE_STRFTIME 560 {"strftime", time_strftime, 1, strftime_doc}, 561#endif 562#ifdef HAVE_STRPTIME 563 {"strptime", time_strptime, 1, strptime_doc}, 564#endif 565 {NULL, NULL} /* sentinel */ 566}; 567 568static void 569ins(d, name, v) 570 PyObject *d; 571 char *name; 572 PyObject *v; 573{ 574 if (v == NULL) 575 Py_FatalError("Can't initialize time module -- NULL value"); 576 if (PyDict_SetItemString(d, name, v) != 0) 577 Py_FatalError( 578 "Can't initialize time module -- PyDict_SetItemString failed"); 579 Py_DECREF(v); 580} 581 582static char module_doc[] = 583"This module provides various functions to manipulate time values.\n\ 584\n\ 585There are two standard representations of time. One is the number\n\ 586of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\ 587or a floating point number (to represent fractions of seconds).\n\ 588The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\ 589The actual value can be retrieved by calling gmtime(0).\n\ 590\n\ 591The other representation is a tuple of 9 integers giving local time.\n\ 592The tuple items are:\n\ 593 year (four digits, e.g. 1998)\n\ 594 month (1-12)\n\ 595 day (1-31)\n\ 596 hours (0-23)\n\ 597 minutes (0-59)\n\ 598 seconds (0-59)\n\ 599 weekday (0-6, Monday is 0)\n\ 600 Julian day (day in the year, 1-366)\n\ 601 DST (Daylight Savings Time) flag (-1, 0 or 1)\n\ 602If the DST flag is 0, the time is given in the regular time zone;\n\ 603if it is 1, the time is given in the DST time zone;\n\ 604if it is -1, mktime() should guess based on the date and time.\n\ 605\n\ 606Variables:\n\ 607\n\ 608timezone -- difference in seconds between UTC and local standard time\n\ 609altzone -- difference in seconds between UTC and local DST time\n\ 610daylight -- whether local time should reflect DST\n\ 611tzname -- tuple of (standard time zone name, DST time zone name)\n\ 612\n\ 613Functions:\n\ 614\n\ 615time() -- return current time in seconds since the Epoch as a float\n\ 616clock() -- return CPU time since process start as a float\n\ 617sleep() -- delay for a number of seconds given as a float\n\ 618gmtime() -- convert seconds since Epoch to UTC tuple\n\ 619localtime() -- convert seconds since Epoch to local time tuple\n\ 620asctime() -- convert time tuple to string\n\ 621ctime() -- convert time in seconds to string\n\ 622mktime() -- convert local time tuple to seconds since Epoch\n\ 623strftime() -- convert time tuple to string according to format specification\n\ 624strptime() -- parse string to time tuple according to format specification\n\ 625"; 626 627 628DL_EXPORT(void) 629inittime() 630{ 631 PyObject *m, *d; 632 char *p; 633 m = Py_InitModule3("time", time_methods, module_doc); 634 d = PyModule_GetDict(m); 635 /* Accept 2-digit dates unless PYTHONY2K is set and non-empty */ 636 p = getenv("PYTHONY2K"); 637 ins(d, "accept2dyear", PyInt_FromLong((long) (!p || !*p))); 638 /* Squirrel away the module's dictionary for the y2k check */ 639 Py_INCREF(d); 640 moddict = d; 641#if defined(HAVE_TZNAME) && !defined(__GLIBC__) 642 tzset(); 643#ifdef PYOS_OS2 644 ins(d, "timezone", PyInt_FromLong((long)_timezone)); 645#else /* !PYOS_OS2 */ 646 ins(d, "timezone", PyInt_FromLong((long)timezone)); 647#endif /* PYOS_OS2 */ 648#ifdef HAVE_ALTZONE 649 ins(d, "altzone", PyInt_FromLong((long)altzone)); 650#else 651#ifdef PYOS_OS2 652 ins(d, "altzone", PyInt_FromLong((long)_timezone-3600)); 653#else /* !PYOS_OS2 */ 654 ins(d, "altzone", PyInt_FromLong((long)timezone-3600)); 655#endif /* PYOS_OS2 */ 656#endif 657 ins(d, "daylight", PyInt_FromLong((long)daylight)); 658 ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1])); 659#else /* !HAVE_TZNAME || __GLIBC__ */ 660#ifdef HAVE_TM_ZONE 661 { 662#define YEAR ((time_t)((365 * 24 + 6) * 3600)) 663 time_t t; 664 struct tm *p; 665 long janzone, julyzone; 666 char janname[10], julyname[10]; 667 t = (time((time_t *)0) / YEAR) * YEAR; 668 p = localtime(&t); 669 janzone = -p->tm_gmtoff; 670 strncpy(janname, p->tm_zone ? p->tm_zone : " ", 9); 671 janname[9] = '\0'; 672 t += YEAR/2; 673 p = localtime(&t); 674 julyzone = -p->tm_gmtoff; 675 strncpy(julyname, p->tm_zone ? p->tm_zone : " ", 9); 676 julyname[9] = '\0'; 677 678 if( janzone < julyzone ) { 679 /* DST is reversed in the southern hemisphere */ 680 ins(d, "timezone", PyInt_FromLong(julyzone)); 681 ins(d, "altzone", PyInt_FromLong(janzone)); 682 ins(d, "daylight", 683 PyInt_FromLong((long)(janzone != julyzone))); 684 ins(d, "tzname", 685 Py_BuildValue("(zz)", julyname, janname)); 686 } else { 687 ins(d, "timezone", PyInt_FromLong(janzone)); 688 ins(d, "altzone", PyInt_FromLong(julyzone)); 689 ins(d, "daylight", 690 PyInt_FromLong((long)(janzone != julyzone))); 691 ins(d, "tzname", 692 Py_BuildValue("(zz)", janname, julyname)); 693 } 694 } 695#else 696#ifdef macintosh 697 /* The only thing we can obtain is the current timezone 698 ** (and whether dst is currently _active_, but that is not what 699 ** we're looking for:-( ) 700 */ 701 initmactimezone(); 702 ins(d, "timezone", PyInt_FromLong(timezone)); 703 ins(d, "altzone", PyInt_FromLong(timezone)); 704 ins(d, "daylight", PyInt_FromLong((long)0)); 705 ins(d, "tzname", Py_BuildValue("(zz)", "", "")); 706#endif /* macintosh */ 707#endif /* HAVE_TM_ZONE */ 708#endif /* !HAVE_TZNAME || __GLIBC__ */ 709 if (PyErr_Occurred()) 710 Py_FatalError("Can't initialize time module"); 711} 712 713 714/* Implement floattime() for various platforms */ 715 716static double 717floattime() 718{ 719 /* There are three ways to get the time: 720 (1) gettimeofday() -- resolution in microseconds 721 (2) ftime() -- resolution in milliseconds 722 (3) time() -- resolution in seconds 723 In all cases the return value is a float in seconds. 724 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may 725 fail, so we fall back on ftime() or time(). 726 Note: clock resolution does not imply clock accuracy! */ 727#ifdef HAVE_GETTIMEOFDAY 728 { 729 struct timeval t; 730#ifdef GETTIMEOFDAY_NO_TZ 731 if (gettimeofday(&t) == 0) 732 return (double)t.tv_sec + t.tv_usec*0.000001; 733#else /* !GETTIMEOFDAY_NO_TZ */ 734 if (gettimeofday(&t, (struct timezone *)NULL) == 0) 735 return (double)t.tv_sec + t.tv_usec*0.000001; 736#endif /* !GETTIMEOFDAY_NO_TZ */ 737 } 738#endif /* !HAVE_GETTIMEOFDAY */ 739 { 740#if defined(HAVE_FTIME) 741 struct timeb t; 742 ftime(&t); 743 return (double)t.time + (double)t.millitm * (double)0.001; 744#else /* !HAVE_FTIME */ 745 time_t secs; 746 time(&secs); 747 return (double)secs; 748#endif /* !HAVE_FTIME */ 749 } 750} 751 752 753/* Implement floatsleep() for various platforms. 754 When interrupted (or when another error occurs), return -1 and 755 set an exception; else return 0. */ 756 757static int 758#ifdef MPW 759floatsleep(double secs) 760#else 761 floatsleep(secs) 762 double secs; 763#endif /* MPW */ 764{ 765/* XXX Should test for MS_WIN32 first! */ 766#if defined(HAVE_SELECT) && !defined(__BEOS__) 767 struct timeval t; 768 double frac; 769 frac = fmod(secs, 1.0); 770 secs = floor(secs); 771 t.tv_sec = (long)secs; 772 t.tv_usec = (long)(frac*1000000.0); 773 Py_BEGIN_ALLOW_THREADS 774 if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) { 775#ifdef EINTR 776 if (errno != EINTR) { 777#else 778 if (1) { 779#endif 780 Py_BLOCK_THREADS 781 PyErr_SetFromErrno(PyExc_IOError); 782 return -1; 783 } 784 } 785 Py_END_ALLOW_THREADS 786#else /* !HAVE_SELECT || __BEOS__ */ 787#ifdef macintosh 788#define MacTicks (* (long *)0x16A) 789 long deadline; 790 deadline = MacTicks + (long)(secs * 60.0); 791 while (MacTicks < deadline) { 792 /* XXX Should call some yielding function here */ 793 if (PyErr_CheckSignals()) 794 return -1; 795 } 796#else /* !macintosh */ 797#if defined(__WATCOMC__) && !defined(__QNX__) 798 /* XXX Can't interrupt this sleep */ 799 Py_BEGIN_ALLOW_THREADS 800 delay((int)(secs * 1000 + 0.5)); /* delay() uses milliseconds */ 801 Py_END_ALLOW_THREADS 802#else /* !__WATCOMC__ || __QNX__ */ 803#ifdef MSDOS 804 struct timeb t1, t2; 805 double frac; 806 extern double fmod Py_PROTO((double, double)); 807 extern double floor Py_PROTO((double)); 808 if (secs <= 0.0) 809 return; 810 frac = fmod(secs, 1.0); 811 secs = floor(secs); 812 ftime(&t1); 813 t2.time = t1.time + (int)secs; 814 t2.millitm = t1.millitm + (int)(frac*1000.0); 815 while (t2.millitm >= 1000) { 816 t2.time++; 817 t2.millitm -= 1000; 818 } 819 for (;;) { 820#ifdef QUICKWIN 821 Py_BEGIN_ALLOW_THREADS 822 _wyield(); 823 Py_END_ALLOW_THREADS 824#endif 825 if (PyErr_CheckSignals()) 826 return -1; 827 ftime(&t1); 828 if (t1.time > t2.time || 829 t1.time == t2.time && t1.millitm >= t2.millitm) 830 break; 831 } 832#else /* !MSDOS */ 833#ifdef MS_WIN32 834 /* XXX Can't interrupt this sleep */ 835 Py_BEGIN_ALLOW_THREADS 836 Sleep((int)(secs*1000)); 837 Py_END_ALLOW_THREADS 838#else /* !MS_WIN32 */ 839#ifdef PYOS_OS2 840 /* This Sleep *IS* Interruptable by Exceptions */ 841 Py_BEGIN_ALLOW_THREADS 842 if (DosSleep(secs * 1000) != NO_ERROR) { 843 Py_BLOCK_THREADS 844 PyErr_SetFromErrno(PyExc_IOError); 845 return -1; 846 } 847 Py_END_ALLOW_THREADS 848#else /* !PYOS_OS2 */ 849#ifdef __BEOS__ 850 /* This sleep *CAN BE* interrupted. */ 851 { 852 if( secs <= 0.0 ) { 853 return; 854 } 855 856 Py_BEGIN_ALLOW_THREADS 857 /* BeOS snooze() is in microseconds... */ 858 if( snooze( (bigtime_t)( secs * 1000.0 * 1000.0 ) ) == B_INTERRUPTED ) { 859 Py_BLOCK_THREADS 860 PyErr_SetFromErrno( PyExc_IOError ); 861 return -1; 862 } 863 Py_END_ALLOW_THREADS 864 } 865#else /* !__BEOS__ */ 866 /* XXX Can't interrupt this sleep */ 867 Py_BEGIN_ALLOW_THREADS 868 sleep((int)secs); 869 Py_END_ALLOW_THREADS 870#endif /* !__BEOS__ */ 871#endif /* !PYOS_OS2 */ 872#endif /* !MS_WIN32 */ 873#endif /* !MSDOS */ 874#endif /* !__WATCOMC__ || __QNX__ */ 875#endif /* !macintosh */ 876#endif /* !HAVE_SELECT */ 877 return 0; 878} 879