Changeset 8b655705 in mainline for uspace/lib/c/generic/time.c


Ignore:
Timestamp:
2011-04-15T19:38:07Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9dd730d1
Parents:
6b9e85b (diff), b2fb47f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/time.c

    r6b9e85b r8b655705  
    3434
    3535#include <sys/time.h>
    36 #include <unistd.h>
    37 #include <ipc/ipc.h>
    38 #include <stdio.h>
     36#include <time.h>
     37#include <bool.h>
    3938#include <arch/barrier.h>
    40 #include <unistd.h>
    41 #include <atomic.h>
    42 #include <sysinfo.h>
    43 #include <ipc/services.h>
    44 #include <libc.h>
    45 
     39#include <macros.h>
     40#include <errno.h>
    4641#include <sysinfo.h>
    4742#include <as.h>
    4843#include <ddi.h>
    49 
    50 #include <time.h>
    51 
    52 /* Pointers to public variables with time */
     44#include <libc.h>
     45
     46/** Pointer to kernel shared variables with time */
    5347struct {
    5448        volatile sysarg_t seconds1;
     
    5953/** Add microseconds to given timeval.
    6054 *
    61  * @param tv            Destination timeval.
    62  * @param usecs         Number of microseconds to add.
     55 * @param tv    Destination timeval.
     56 * @param usecs Number of microseconds to add.
     57 *
    6358 */
    6459void tv_add(struct timeval *tv, suseconds_t usecs)
     
    6661        tv->tv_sec += usecs / 1000000;
    6762        tv->tv_usec += usecs % 1000000;
     63       
    6864        if (tv->tv_usec > 1000000) {
    6965                tv->tv_sec++;
     
    7470/** Subtract two timevals.
    7571 *
    76  * @param tv1           First timeval.
    77  * @param tv2           Second timeval.
    78  *
    79  * @return              Return difference between tv1 and tv2 (tv1 - tv2) in
    80  *                      microseconds.
     72 * @param tv1 First timeval.
     73 * @param tv2 Second timeval.
     74 *
     75 * @return Difference between tv1 and tv2 (tv1 - tv2) in
     76 *         microseconds.
     77 *
    8178 */
    8279suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
    8380{
    84         suseconds_t result;
    85 
    86         result = tv1->tv_usec - tv2->tv_usec;
    87         result += (tv1->tv_sec - tv2->tv_sec) * 1000000;
    88 
    89         return result;
     81        return (tv1->tv_usec - tv2->tv_usec) +
     82            ((tv1->tv_sec - tv2->tv_sec) * 1000000);
    9083}
    9184
    9285/** Decide if one timeval is greater than the other.
    9386 *
    94  * @param t1            First timeval.
    95  * @param t2            Second timeval.
    96  *
    97  * @return              Return true tv1 is greater than tv2. Otherwise return
    98  *                      false.
     87 * @param t1 First timeval.
     88 * @param t2 Second timeval.
     89 *
     90 * @return True if tv1 is greater than tv2.
     91 * @return False otherwise.
     92 *
    9993 */
    10094int tv_gt(struct timeval *tv1, struct timeval *tv2)
    10195{
    10296        if (tv1->tv_sec > tv2->tv_sec)
    103                 return 1;
    104         if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec > tv2->tv_usec)
    105                 return 1;
    106         return 0;
     97                return true;
     98       
     99        if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec))
     100                return true;
     101       
     102        return false;
    107103}
    108104
    109105/** Decide if one timeval is greater than or equal to the other.
    110106 *
    111  * @param tv1           First timeval.
    112  * @param tv2           Second timeval.
    113  *
    114  * @return              Return true if tv1 is greater than or equal to tv2.
    115  *                      Otherwise return false.
     107 * @param tv1 First timeval.
     108 * @param tv2 Second timeval.
     109 *
     110 * @return True if tv1 is greater than or equal to tv2.
     111 * @return False otherwise.
     112 *
    116113 */
    117114int tv_gteq(struct timeval *tv1, struct timeval *tv2)
    118115{
    119116        if (tv1->tv_sec > tv2->tv_sec)
    120                 return 1;
    121         if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec >= tv2->tv_usec)
    122                 return 1;
    123         return 0;
    124 }
    125 
    126 
    127 /** POSIX gettimeofday
    128  *
    129  * The time variables are memory mapped(RO) from kernel, which updates
    130  * them periodically. As it is impossible to read 2 values atomically, we
    131  * use a trick: First read a seconds, then read microseconds, then
    132  * read seconds again. If a second elapsed in the meantime, set it to zero.
    133  * This provides assurance, that at least the
    134  * sequence of subsequent gettimeofday calls is ordered.
     117                return true;
     118       
     119        if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec))
     120                return true;
     121       
     122        return false;
     123}
     124
     125/** Get time of day
     126 *
     127 * The time variables are memory mapped (read-only) from kernel which
     128 * updates them periodically.
     129 *
     130 * As it is impossible to read 2 values atomically, we use a trick:
     131 * First we read the seconds, then we read the microseconds, then we
     132 * read the seconds again. If a second elapsed in the meantime, set
     133 * the microseconds to zero.
     134 *
     135 * This assures that the values returned by two subsequent calls
     136 * to gettimeofday() are monotonous.
     137 *
    135138 */
    136139int gettimeofday(struct timeval *tv, struct timezone *tz)
    137140{
    138         void *mapping;
    139         sysarg_t s1, s2;
    140         int rights;
    141         int res;
    142 
    143         if (!ktime) {
    144                 mapping = as_get_mappable_page(PAGE_SIZE);
    145                 /* Get the mapping of kernel clock */
    146                 res = ipc_share_in_start_1_1(PHONE_NS, mapping, PAGE_SIZE,
    147                     SERVICE_MEM_REALTIME, &rights);
    148                 if (res) {
    149                         printf("Failed to initialize timeofday memarea\n");
    150                         _exit(1);
     141        if (ktime == NULL) {
     142                uintptr_t faddr;
     143                int rc = sysinfo_get_value("clock.faddr", &faddr);
     144                if (rc != EOK) {
     145                        errno = rc;
     146                        return -1;
    151147                }
    152                 if (!(rights & AS_AREA_READ)) {
    153                         printf("Received bad rights on time area: %X\n",
    154                             rights);
    155                         as_area_destroy(mapping);
    156                         _exit(1);
     148               
     149                void *addr = as_get_mappable_page(PAGE_SIZE);
     150                if (addr == NULL) {
     151                        errno = ENOMEM;
     152                        return -1;
    157153                }
    158                 ktime = mapping;
    159         }
     154               
     155                rc = physmem_map((void *) faddr, addr, 1,
     156                    AS_AREA_READ | AS_AREA_CACHEABLE);
     157                if (rc != EOK) {
     158                        as_area_destroy(addr);
     159                        errno = rc;
     160                        return -1;
     161                }
     162               
     163                ktime = addr;
     164        }
     165       
    160166        if (tz) {
    161167                tz->tz_minuteswest = 0;
    162168                tz->tz_dsttime = DST_NONE;
    163169        }
    164 
    165         s2 = ktime->seconds2;
     170       
     171        sysarg_t s2 = ktime->seconds2;
     172       
    166173        read_barrier();
    167174        tv->tv_usec = ktime->useconds;
     175       
    168176        read_barrier();
    169         s1 = ktime->seconds1;
     177        sysarg_t s1 = ktime->seconds1;
     178       
    170179        if (s1 != s2) {
     180                tv->tv_sec = max(s1, s2);
    171181                tv->tv_usec = 0;
    172                 tv->tv_sec = s1 > s2 ? s1 : s2;
    173182        } else
    174183                tv->tv_sec = s1;
    175 
     184       
    176185        return 0;
    177186}
     
    180189{
    181190        struct timeval tv;
    182 
    183191        if (gettimeofday(&tv, NULL))
    184192                return (time_t) -1;
     193       
    185194        if (tloc)
    186195                *tloc = tv.tv_sec;
     196       
    187197        return tv.tv_sec;
    188198}
    189199
    190 /** Wait unconditionally for specified number of microseconds */
     200/** Wait unconditionally for specified number of microseconds
     201 *
     202 */
    191203int usleep(useconds_t usec)
    192204{
     
    195207}
    196208
    197 /** Wait unconditionally for specified number of seconds */
     209/** Wait unconditionally for specified number of seconds
     210 *
     211 */
    198212unsigned int sleep(unsigned int sec)
    199213{
    200         /* Sleep in 1000 second steps to support
    201            full argument range */
     214        /*
     215         * Sleep in 1000 second steps to support
     216         * full argument range
     217         */
     218       
    202219        while (sec > 0) {
    203220                unsigned int period = (sec > 1000) ? 1000 : sec;
    204        
     221               
    205222                usleep(period * 1000000);
    206223                sec -= period;
    207224        }
     225       
    208226        return 0;
    209227}
Note: See TracChangeset for help on using the changeset viewer.