time.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2006 Ondrej Palkovsky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <sys/time.h>
00036 #include <time.h>
00037 #include <bool.h>
00038 #include <arch/barrier.h>
00039 #include <macros.h>
00040 #include <errno.h>
00041 #include <sysinfo.h>
00042 #include <as.h>
00043 #include <ddi.h>
00044 #include <libc.h>
00045 
00047 struct {
00048         volatile sysarg_t seconds1;
00049         volatile sysarg_t useconds;
00050         volatile sysarg_t seconds2;
00051 } *ktime = NULL;
00052 
00059 void tv_add(struct timeval *tv, suseconds_t usecs)
00060 {
00061         tv->tv_sec += usecs / 1000000;
00062         tv->tv_usec += usecs % 1000000;
00063         
00064         if (tv->tv_usec > 1000000) {
00065                 tv->tv_sec++;
00066                 tv->tv_usec -= 1000000;
00067         }
00068 }
00069 
00079 suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
00080 {
00081         return (tv1->tv_usec - tv2->tv_usec) +
00082             ((tv1->tv_sec - tv2->tv_sec) * 1000000);
00083 }
00084 
00094 int tv_gt(struct timeval *tv1, struct timeval *tv2)
00095 {
00096         if (tv1->tv_sec > tv2->tv_sec)
00097                 return true;
00098         
00099         if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec))
00100                 return true;
00101         
00102         return false;
00103 }
00104 
00114 int tv_gteq(struct timeval *tv1, struct timeval *tv2)
00115 {
00116         if (tv1->tv_sec > tv2->tv_sec)
00117                 return true;
00118         
00119         if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec))
00120                 return true;
00121         
00122         return false;
00123 }
00124 
00139 int gettimeofday(struct timeval *tv, struct timezone *tz)
00140 {
00141         if (ktime == NULL) {
00142                 uintptr_t faddr;
00143                 int rc = sysinfo_get_value("clock.faddr", &faddr);
00144                 if (rc != EOK) {
00145                         errno = rc;
00146                         return -1;
00147                 }
00148                 
00149                 void *addr = as_get_mappable_page(PAGE_SIZE);
00150                 if (addr == NULL) {
00151                         errno = ENOMEM;
00152                         return -1;
00153                 }
00154                 
00155                 rc = physmem_map((void *) faddr, addr, 1,
00156                     AS_AREA_READ | AS_AREA_CACHEABLE);
00157                 if (rc != EOK) {
00158                         as_area_destroy(addr);
00159                         errno = rc;
00160                         return -1;
00161                 }
00162                 
00163                 ktime = addr;
00164         }
00165         
00166         if (tz) {
00167                 tz->tz_minuteswest = 0;
00168                 tz->tz_dsttime = DST_NONE;
00169         }
00170         
00171         sysarg_t s2 = ktime->seconds2;
00172         
00173         read_barrier();
00174         tv->tv_usec = ktime->useconds;
00175         
00176         read_barrier();
00177         sysarg_t s1 = ktime->seconds1;
00178         
00179         if (s1 != s2) {
00180                 tv->tv_sec = max(s1, s2);
00181                 tv->tv_usec = 0;
00182         } else
00183                 tv->tv_sec = s1;
00184         
00185         return 0;
00186 }
00187 
00188 time_t time(time_t *tloc)
00189 {
00190         struct timeval tv;
00191         if (gettimeofday(&tv, NULL))
00192                 return (time_t) -1;
00193         
00194         if (tloc)
00195                 *tloc = tv.tv_sec;
00196         
00197         return tv.tv_sec;
00198 }
00199 
00203 int usleep(useconds_t usec)
00204 {
00205         (void) __SYSCALL1(SYS_THREAD_USLEEP, usec);
00206         return 0;
00207 }
00208 
00209 void udelay(useconds_t time)
00210 {
00211         (void) __SYSCALL1(SYS_THREAD_UDELAY, (sysarg_t) time);
00212 }
00213 
00214 
00218 unsigned int sleep(unsigned int sec)
00219 {
00220         /*
00221          * Sleep in 1000 second steps to support
00222          * full argument range
00223          */
00224         
00225         while (sec > 0) {
00226                 unsigned int period = (sec > 1000) ? 1000 : sec;
00227                 
00228                 usleep(period * 1000000);
00229                 sec -= period;
00230         }
00231         
00232         return 0;
00233 }
00234 

Generated on Thu Jun 2 07:45:46 2011 for HelenOS/USB by  doxygen 1.4.7