Changeset 04803bf in mainline for uspace/lib/c/generic/time.c


Ignore:
Timestamp:
2011-03-21T22:00:17Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
143932e3
Parents:
b50b5af2 (diff), 7308e84 (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 (needs fixes).

File:
1 moved

Legend:

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

    rb50b5af2 r04803bf  
    3131 */
    3232/** @file
    33  */ 
     33 */
    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 <futex.h>
    43 #include <sysinfo.h>
    44 #include <ipc/services.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                         printf("Address was 0x%x\n", (unsigned)mapping);
    151                         _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;
    152147                }
    153                 if (!(rights & AS_AREA_READ)) {
    154                         printf("Received bad rights on time area: %X\n",
    155                             rights);
    156                         as_area_destroy(mapping);
    157                         _exit(1);
     148               
     149                void *addr = as_get_mappable_page(PAGE_SIZE);
     150                if (addr == NULL) {
     151                        errno = ENOMEM;
     152                        return -1;
    158153                }
    159                 ktime = mapping;
    160         }
     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       
    161166        if (tz) {
    162167                tz->tz_minuteswest = 0;
    163168                tz->tz_dsttime = DST_NONE;
    164169        }
    165 
    166         s2 = ktime->seconds2;
     170       
     171        sysarg_t s2 = ktime->seconds2;
     172       
    167173        read_barrier();
    168174        tv->tv_usec = ktime->useconds;
     175       
    169176        read_barrier();
    170         s1 = ktime->seconds1;
     177        sysarg_t s1 = ktime->seconds1;
     178       
    171179        if (s1 != s2) {
     180                tv->tv_sec = max(s1, s2);
    172181                tv->tv_usec = 0;
    173                 tv->tv_sec = s1 > s2 ? s1 : s2;
    174182        } else
    175183                tv->tv_sec = s1;
    176 
     184       
    177185        return 0;
    178186}
     
    181189{
    182190        struct timeval tv;
    183 
    184191        if (gettimeofday(&tv, NULL))
    185192                return (time_t) -1;
     193       
    186194        if (tloc)
    187195                *tloc = tv.tv_sec;
     196       
    188197        return tv.tv_sec;
    189198}
    190199
    191 /** Wait unconditionally for specified number of microseconds */
    192 int usleep(unsigned long usec)
    193 {
    194         atomic_t futex = FUTEX_INITIALIZER;
    195 
    196         futex_initialize(&futex, 0);
    197         futex_down_timeout(&futex, usec, 0);
     200/** Wait unconditionally for specified number of microseconds
     201 *
     202 */
     203int usleep(useconds_t usec)
     204{
     205        (void) __SYSCALL1(SYS_THREAD_USLEEP, usec);
    198206        return 0;
    199207}
    200208
    201 /** Wait unconditionally for specified number of seconds */
    202 unsigned int sleep(unsigned int seconds)
    203 {
    204         atomic_t futex = FUTEX_INITIALIZER;
    205 
    206         futex_initialize(&futex, 0);
    207        
    208         /* Sleep in 1000 second steps to support
    209            full argument range */
    210         while (seconds > 0) {
    211                 unsigned int period = (seconds > 1000) ? 1000 : seconds;
    212        
    213                 futex_down_timeout(&futex, period * 1000000, 0);
    214                 seconds -= period;
    215         }
     209/** Wait unconditionally for specified number of seconds
     210 *
     211 */
     212unsigned int sleep(unsigned int sec)
     213{
     214        /*
     215         * Sleep in 1000 second steps to support
     216         * full argument range
     217         */
     218       
     219        while (sec > 0) {
     220                unsigned int period = (sec > 1000) ? 1000 : sec;
     221               
     222                usleep(period * 1000000);
     223                sec -= period;
     224        }
     225       
    216226        return 0;
    217227}
Note: See TracChangeset for help on using the changeset viewer.