Changeset 46b881c in mainline for uspace/lib/c/generic/time.c


Ignore:
Timestamp:
2011-01-29T11:36:41Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0b6931a, 8add9ca5
Parents:
e26a4633 (diff), ffa2c8ef (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:

IPC/async: strictly isolate the use of low-level IPC methods (ipc_*) and async framework methods (async_*) in user code, do not allow a mixture of both in a single source file

Benefits for future plans

  • The async framework could use different communication style under the hood, but keeping the same high-level API
  • The async framework can be integrated more tightly with sessions without potential problems of intermixing session-aware async methods with session-unaware low-level methods in user code
  • The async_serialize_start()/_end() can be deprecated more easily
File:
1 edited

Legend:

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

    re26a4633 r46b881c  
    3535#include <sys/time.h>
    3636#include <unistd.h>
    37 #include <ipc/ipc.h>
    38 #include <stdio.h>
     37#include <bool.h>
     38#include <ipc/ns.h>
    3939#include <arch/barrier.h>
    40 #include <unistd.h>
    41 #include <atomic.h>
    42 #include <sysinfo.h>
    43 #include <ipc/services.h>
     40#include <macros.h>
    4441#include <libc.h>
    45 
    46 #include <sysinfo.h>
    47 #include <as.h>
    48 #include <ddi.h>
    49 
    5042#include <time.h>
    5143
    52 /* Pointers to public variables with time */
     44/** Pointer to kernel shared variables with time */
    5345struct {
    5446        volatile sysarg_t seconds1;
     
    5951/** Add microseconds to given timeval.
    6052 *
    61  * @param tv            Destination timeval.
    62  * @param usecs         Number of microseconds to add.
     53 * @param tv    Destination timeval.
     54 * @param usecs Number of microseconds to add.
     55 *
    6356 */
    6457void tv_add(struct timeval *tv, suseconds_t usecs)
     
    6659        tv->tv_sec += usecs / 1000000;
    6760        tv->tv_usec += usecs % 1000000;
     61       
    6862        if (tv->tv_usec > 1000000) {
    6963                tv->tv_sec++;
     
    7468/** Subtract two timevals.
    7569 *
    76  * @param tv1           First timeval.
    77  * @param tv2           Second timeval.
    78  *
    79  * @return              Return difference between tv1 and tv2 (tv1 - tv2) in
    80  *                      microseconds.
     70 * @param tv1 First timeval.
     71 * @param tv2 Second timeval.
     72 *
     73 * @return Difference between tv1 and tv2 (tv1 - tv2) in
     74 *         microseconds.
     75 *
    8176 */
    8277suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
    8378{
    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;
     79        return (tv1->tv_usec - tv2->tv_usec) +
     80            ((tv1->tv_sec - tv2->tv_sec) * 1000000);
    9081}
    9182
    9283/** Decide if one timeval is greater than the other.
    9384 *
    94  * @param t1            First timeval.
    95  * @param t2            Second timeval.
    96  *
    97  * @return              Return true tv1 is greater than tv2. Otherwise return
    98  *                      false.
     85 * @param t1 First timeval.
     86 * @param t2 Second timeval.
     87 *
     88 * @return True if tv1 is greater than tv2.
     89 * @return False otherwise.
     90 *
    9991 */
    10092int tv_gt(struct timeval *tv1, struct timeval *tv2)
    10193{
    10294        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;
     95                return true;
     96       
     97        if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec))
     98                return true;
     99       
     100        return false;
    107101}
    108102
    109103/** Decide if one timeval is greater than or equal to the other.
    110104 *
    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.
     105 * @param tv1 First timeval.
     106 * @param tv2 Second timeval.
     107 *
     108 * @return True if tv1 is greater than or equal to tv2.
     109 * @return False otherwise.
     110 *
    116111 */
    117112int tv_gteq(struct timeval *tv1, struct timeval *tv2)
    118113{
    119114        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.
     115                return true;
     116       
     117        if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec))
     118                return true;
     119       
     120        return false;
     121}
     122
     123/** Get time of day
     124 *
     125 * The time variables are memory mapped (read-only) from kernel which
     126 * updates them periodically.
     127 *
     128 * As it is impossible to read 2 values atomically, we use a trick:
     129 * First we read the seconds, then we read the microseconds, then we
     130 * read the seconds again. If a second elapsed in the meantime, set
     131 * the microseconds to zero.
     132 *
     133 * This assures that the values returned by two subsequent calls
     134 * to gettimeofday() are monotonous.
     135 *
    135136 */
    136137int gettimeofday(struct timeval *tv, struct timezone *tz)
    137138{
    138         void *mapping;
    139         sysarg_t s1, s2;
    140         int rights;
    141         int res;
    142 
    143139        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);
    151                 }
    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);
    157                 }
    158                 ktime = mapping;
    159         }
     140                ktime = service_realtime_share_in();
     141                if (!ktime)
     142                        return -1;
     143        }
     144       
    160145        if (tz) {
    161146                tz->tz_minuteswest = 0;
    162147                tz->tz_dsttime = DST_NONE;
    163148        }
    164 
    165         s2 = ktime->seconds2;
     149       
     150        sysarg_t s2 = ktime->seconds2;
     151       
    166152        read_barrier();
    167153        tv->tv_usec = ktime->useconds;
     154       
    168155        read_barrier();
    169         s1 = ktime->seconds1;
     156        sysarg_t s1 = ktime->seconds1;
     157       
    170158        if (s1 != s2) {
     159                tv->tv_sec = max(s1, s2);
    171160                tv->tv_usec = 0;
    172                 tv->tv_sec = s1 > s2 ? s1 : s2;
    173161        } else
    174162                tv->tv_sec = s1;
    175 
     163       
    176164        return 0;
    177165}
     
    180168{
    181169        struct timeval tv;
    182 
    183170        if (gettimeofday(&tv, NULL))
    184171                return (time_t) -1;
     172       
    185173        if (tloc)
    186174                *tloc = tv.tv_sec;
     175       
    187176        return tv.tv_sec;
    188177}
    189178
    190 /** Wait unconditionally for specified number of microseconds */
     179/** Wait unconditionally for specified number of microseconds
     180 *
     181 */
    191182int usleep(useconds_t usec)
    192183{
     
    195186}
    196187
    197 /** Wait unconditionally for specified number of seconds */
     188/** Wait unconditionally for specified number of seconds
     189 *
     190 */
    198191unsigned int sleep(unsigned int sec)
    199192{
    200         /* Sleep in 1000 second steps to support
    201            full argument range */
     193        /*
     194         * Sleep in 1000 second steps to support
     195         * full argument range
     196         */
     197       
    202198        while (sec > 0) {
    203199                unsigned int period = (sec > 1000) ? 1000 : sec;
    204        
     200               
    205201                usleep(period * 1000000);
    206202                sec -= period;
    207203        }
     204       
    208205        return 0;
    209206}
Note: See TracChangeset for help on using the changeset viewer.