The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/clock_subr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: clock_subr.c,v 1.27 2016/08/15 15:51:39 jakllsch Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1988 University of Utah.
    5  * Copyright (c) 1982, 1990, 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * the Systems Programming Group of the University of Utah Computer
   10  * Science Department.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  * from: Utah $Hdr: clock.c 1.18 91/01/21$
   37  *
   38  *      @(#)clock.c     8.2 (Berkeley) 1/12/94
   39  */
   40 
   41 /*
   42  * Generic routines to convert between a POSIX date
   43  * (seconds since 1/1/1970) and yr/mo/day/hr/min/sec
   44  * Derived from arch/hp300/hp300/clock.c
   45  */
   46 
   47 #if HAVE_NBTOOL_CONFIG_H
   48 #include "nbtool_config.h"
   49 #endif /* HAVE_NBTOOL_CONFIG_H */
   50 
   51 #ifdef _KERNEL
   52 #include <sys/cdefs.h>
   53 __KERNEL_RCSID(0, "$NetBSD: clock_subr.c,v 1.27 2016/08/15 15:51:39 jakllsch Exp $");
   54 
   55 #include <sys/param.h>
   56 #include <sys/systm.h>
   57 #include <sys/errno.h>
   58 #else /* ! _KERNEL */
   59 #include <string.h>
   60 #include <time.h>
   61 #include <errno.h>
   62 #endif /* ! _KERNEL */
   63 
   64 #include "../sys/clock.h"
   65 #include <dev/clock_subr.h>
   66 
   67 #define FEBRUARY        2
   68 
   69 /* for easier alignment:
   70  * time from the epoch to 2001 (there were 8 leap years): */
   71 #define DAYSTO2001      (365*31+8)
   72 
   73 /* 4 year intervals include 1 leap year */
   74 #define DAYS4YEARS      (365*4+1)
   75 
   76 /* 100 year intervals include 24 leap years */
   77 #define DAYS100YEARS    (365*100+24)
   78 
   79 /* 400 year intervals include 97 leap years */
   80 #define DAYS400YEARS    (365*400+97)
   81 
   82 time_t
   83 clock_ymdhms_to_secs(struct clock_ymdhms *dt)
   84 {
   85         uint64_t secs, i, year, days;
   86 
   87         year = dt->dt_year;
   88 
   89         /*
   90          * Compute days since start of time
   91          * First from years, then from months.
   92          */
   93         if (year < POSIX_BASE_YEAR)
   94                 return -1;
   95         days = 0;
   96         if (is_leap_year(year) && dt->dt_mon > FEBRUARY)
   97                 days++;
   98 
   99         if (year < 2001) {
  100                 /* simple way for early years */
  101                 for (i = POSIX_BASE_YEAR; i < year; i++)
  102                         days += days_per_year(i);
  103         } else {
  104                 /* years are properly aligned */
  105                 days += DAYSTO2001;
  106                 year -= 2001;
  107 
  108                 i = year / 400;
  109                 days += i * DAYS400YEARS;
  110                 year -= i * 400;
  111 
  112                 i = year / 100;
  113                 days += i * DAYS100YEARS;
  114                 year -= i * 100;
  115 
  116                 i = year / 4;
  117                 days += i * DAYS4YEARS;
  118                 year -= i * 4;
  119 
  120                 for (i = dt->dt_year-year; i < dt->dt_year; i++)
  121                         days += days_per_year(i);
  122         }
  123 
  124 
  125         /* Months */
  126         for (i = 1; i < dt->dt_mon; i++)
  127                 days += days_in_month(i);
  128         days += (dt->dt_day - 1);
  129 
  130         /* Add hours, minutes, seconds. */
  131         secs = (((uint64_t)days
  132             * 24 + dt->dt_hour)
  133             * 60 + dt->dt_min)
  134             * 60 + dt->dt_sec;
  135 
  136         if ((time_t)secs < 0 || secs > __type_max(time_t))
  137                 return -1;
  138         return secs;
  139 }
  140 
  141 int
  142 clock_secs_to_ymdhms(time_t secs, struct clock_ymdhms *dt)
  143 {
  144         int leap;
  145         uint64_t i;
  146         time_t days;
  147         time_t rsec;    /* remainder seconds */
  148 
  149         if (secs < 0)
  150                 return EINVAL;
  151 
  152         days = secs / SECS_PER_DAY;
  153         rsec = secs % SECS_PER_DAY;
  154 
  155         /* Day of week (Note: 1/1/1970 was a Thursday) */
  156         dt->dt_wday = (days + 4) % 7;
  157 
  158         if (days >= DAYSTO2001) {
  159                 days -= DAYSTO2001;
  160                 dt->dt_year = 2001;
  161 
  162                 i = days / DAYS400YEARS;
  163                 days -= i*DAYS400YEARS;
  164                 dt->dt_year += i*400;
  165 
  166                 i = days / DAYS100YEARS;
  167                 days -= i*DAYS100YEARS;
  168                 dt->dt_year += i*100;
  169 
  170                 i = days / DAYS4YEARS;
  171                 days -= i*DAYS4YEARS;
  172                 dt->dt_year += i*4;
  173 
  174                 for (i = dt->dt_year; days >= days_per_year(i); i++)
  175                         days -= days_per_year(i);
  176                 dt->dt_year = i;
  177         } else {
  178                 /* Subtract out whole years, counting them in i. */
  179                 for (i = POSIX_BASE_YEAR; days >= days_per_year(i); i++)
  180                         days -= days_per_year(i);
  181                 dt->dt_year = i;
  182         }
  183 
  184         /* Subtract out whole months, counting them in i. */
  185         for (leap = 0, i = 1; days >= days_in_month(i)+leap; i++) {
  186                 days -= days_in_month(i)+leap;
  187                 if (i == 1 && is_leap_year(dt->dt_year))
  188                         leap = 1;
  189                 else
  190                         leap = 0;
  191         }
  192         dt->dt_mon = i;
  193 
  194         /* Days are what is left over (+1) from all that. */
  195         dt->dt_day = days + 1;
  196 
  197         /* Hours, minutes, seconds are easy */
  198         dt->dt_hour = rsec / SECS_PER_HOUR;
  199         rsec = rsec % SECS_PER_HOUR;
  200         dt->dt_min  = rsec / SECS_PER_MINUTE;
  201         rsec = rsec % SECS_PER_MINUTE;
  202         dt->dt_sec  = rsec;
  203 
  204         return 0;
  205 }

Cache object: a5ce5d97b39cbe1c01acd7798a92342a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.