diff options
author | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
commit | 292dd876ee765c478b27c93cc51e93a558ed58bf (patch) | |
tree | 5b740e93253295baee2a9c414a6c66d03d44a9ef /kernel/time.c | |
parent | d4ec6c7cc9a15a7a529719bc3b84f46812f9842e (diff) | |
parent | 9fdb62af92c741addbea15545f214a6e89460865 (diff) |
Pull release into acpica branch
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) |