diff options
| author | Steve French <sfrench@us.ibm.com> | 2006-01-12 17:47:08 -0500 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2006-01-12 17:47:08 -0500 |
| commit | 94bc2be31a01a3055ec94176e595dfe208e92d3b (patch) | |
| tree | ebfbe81c6718a6390bfa1b99c6d228237d818576 /kernel/time.c | |
| parent | c32a0b689cb9cc160cfcd19735bbf50bb70c6ef4 (diff) | |
| parent | 58cba4650a7a414eabd2b40cc9d8e45fcdf192d9 (diff) | |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'kernel/time.c')
| -rw-r--r-- | kernel/time.c | 118 |
1 files changed, 101 insertions, 17 deletions
diff --git a/kernel/time.c b/kernel/time.c index b94bfa8c03e0..7477b1d2079e 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 31 | #include <linux/timex.h> | 31 | #include <linux/timex.h> |
| 32 | #include <linux/capability.h> | ||
| 32 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
| 33 | #include <linux/smp_lock.h> | 34 | #include <linux/smp_lock.h> |
| 34 | #include <linux/syscalls.h> | 35 | #include <linux/syscalls.h> |
| @@ -154,6 +155,9 @@ int do_sys_settimeofday(struct timespec *tv, struct timezone *tz) | |||
| 154 | static int firsttime = 1; | 155 | static int firsttime = 1; |
| 155 | int error = 0; | 156 | int error = 0; |
| 156 | 157 | ||
| 158 | if (!timespec_valid(tv)) | ||
| 159 | return -EINVAL; | ||
| 160 | |||
| 157 | error = security_settime(tv, tz); | 161 | error = security_settime(tv, tz); |
| 158 | if (error) | 162 | if (error) |
| 159 | return error; | 163 | return error; |
| @@ -561,27 +565,107 @@ void getnstimeofday(struct timespec *tv) | |||
| 561 | EXPORT_SYMBOL_GPL(getnstimeofday); | 565 | EXPORT_SYMBOL_GPL(getnstimeofday); |
| 562 | #endif | 566 | #endif |
| 563 | 567 | ||
| 564 | void getnstimestamp(struct timespec *ts) | 568 | /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. |
| 569 | * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 | ||
| 570 | * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. | ||
| 571 | * | ||
| 572 | * [For the Julian calendar (which was used in Russia before 1917, | ||
| 573 | * Britain & colonies before 1752, anywhere else before 1582, | ||
| 574 | * and is still in use by some communities) leave out the | ||
| 575 | * -year/100+year/400 terms, and add 10.] | ||
| 576 | * | ||
| 577 | * This algorithm was first published by Gauss (I think). | ||
| 578 | * | ||
| 579 | * WARNING: this function will overflow on 2106-02-07 06:28:16 on | ||
| 580 | * machines were long is 32-bit! (However, as time_t is signed, we | ||
| 581 | * will already get problems at other places on 2038-01-19 03:14:08) | ||
| 582 | */ | ||
| 583 | unsigned long | ||
| 584 | mktime(const unsigned int year0, const unsigned int mon0, | ||
| 585 | const unsigned int day, const unsigned int hour, | ||
| 586 | const unsigned int min, const unsigned int sec) | ||
| 565 | { | 587 | { |
| 566 | unsigned int seq; | 588 | unsigned int mon = mon0, year = year0; |
| 567 | struct timespec wall2mono; | ||
| 568 | 589 | ||
| 569 | /* synchronize with settimeofday() changes */ | 590 | /* 1..12 -> 11,12,1..10 */ |
| 570 | do { | 591 | if (0 >= (int) (mon -= 2)) { |
| 571 | seq = read_seqbegin(&xtime_lock); | 592 | mon += 12; /* Puts Feb last since it has leap day */ |
| 572 | getnstimeofday(ts); | 593 | year -= 1; |
| 573 | wall2mono = wall_to_monotonic; | ||
| 574 | } while(unlikely(read_seqretry(&xtime_lock, seq))); | ||
| 575 | |||
| 576 | /* adjust to monotonicaly-increasing values */ | ||
| 577 | ts->tv_sec += wall2mono.tv_sec; | ||
| 578 | ts->tv_nsec += wall2mono.tv_nsec; | ||
| 579 | while (unlikely(ts->tv_nsec >= NSEC_PER_SEC)) { | ||
| 580 | ts->tv_nsec -= NSEC_PER_SEC; | ||
| 581 | ts->tv_sec++; | ||
| 582 | } | 594 | } |
| 595 | |||
| 596 | return ((((unsigned long) | ||
| 597 | (year/4 - year/100 + year/400 + 367*mon/12 + day) + | ||
| 598 | year*365 - 719499 | ||
| 599 | )*24 + hour /* now have hours */ | ||
| 600 | )*60 + min /* now have minutes */ | ||
| 601 | )*60 + sec; /* finally seconds */ | ||
| 602 | } | ||
| 603 | |||
| 604 | EXPORT_SYMBOL(mktime); | ||
| 605 | |||
| 606 | /** | ||
| 607 | * set_normalized_timespec - set timespec sec and nsec parts and normalize | ||
| 608 | * | ||
| 609 | * @ts: pointer to timespec variable to be set | ||
| 610 | * @sec: seconds to set | ||
| 611 | * @nsec: nanoseconds to set | ||
| 612 | * | ||
| 613 | * Set seconds and nanoseconds field of a timespec variable and | ||
| 614 | * normalize to the timespec storage format | ||
| 615 | * | ||
| 616 | * Note: The tv_nsec part is always in the range of | ||
| 617 | * 0 <= tv_nsec < NSEC_PER_SEC | ||
| 618 | * For negative values only the tv_sec field is negative ! | ||
| 619 | */ | ||
| 620 | void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec) | ||
| 621 | { | ||
| 622 | while (nsec >= NSEC_PER_SEC) { | ||
| 623 | nsec -= NSEC_PER_SEC; | ||
| 624 | ++sec; | ||
| 625 | } | ||
| 626 | while (nsec < 0) { | ||
| 627 | nsec += NSEC_PER_SEC; | ||
| 628 | --sec; | ||
| 629 | } | ||
| 630 | ts->tv_sec = sec; | ||
| 631 | ts->tv_nsec = nsec; | ||
| 632 | } | ||
| 633 | |||
| 634 | /** | ||
| 635 | * ns_to_timespec - Convert nanoseconds to timespec | ||
| 636 | * @nsec: the nanoseconds value to be converted | ||
| 637 | * | ||
| 638 | * Returns the timespec representation of the nsec parameter. | ||
| 639 | */ | ||
| 640 | inline struct timespec ns_to_timespec(const nsec_t nsec) | ||
| 641 | { | ||
| 642 | struct timespec ts; | ||
| 643 | |||
| 644 | if (nsec) | ||
| 645 | ts.tv_sec = div_long_long_rem_signed(nsec, NSEC_PER_SEC, | ||
| 646 | &ts.tv_nsec); | ||
| 647 | else | ||
| 648 | ts.tv_sec = ts.tv_nsec = 0; | ||
| 649 | |||
| 650 | return ts; | ||
| 651 | } | ||
| 652 | |||
| 653 | /** | ||
| 654 | * ns_to_timeval - Convert nanoseconds to timeval | ||
| 655 | * @nsec: the nanoseconds value to be converted | ||
| 656 | * | ||
| 657 | * Returns the timeval representation of the nsec parameter. | ||
| 658 | */ | ||
| 659 | struct timeval ns_to_timeval(const nsec_t nsec) | ||
| 660 | { | ||
| 661 | struct timespec ts = ns_to_timespec(nsec); | ||
| 662 | struct timeval tv; | ||
| 663 | |||
| 664 | tv.tv_sec = ts.tv_sec; | ||
| 665 | tv.tv_usec = (suseconds_t) ts.tv_nsec / 1000; | ||
| 666 | |||
| 667 | return tv; | ||
| 583 | } | 668 | } |
| 584 | EXPORT_SYMBOL_GPL(getnstimestamp); | ||
| 585 | 669 | ||
| 586 | #if (BITS_PER_LONG < 64) | 670 | #if (BITS_PER_LONG < 64) |
| 587 | u64 get_jiffies_64(void) | 671 | u64 get_jiffies_64(void) |
