Changeset ad7a6c9 in mainline for uspace/lib/c/generic/time.c
- Timestamp:
- 2011-03-30T13:10:24Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4ae90f9
- Parents:
- 6e50466 (diff), d6b81941 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/time.c
r6e50466 rad7a6c9 34 34 35 35 #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> 39 38 #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> 46 41 #include <sysinfo.h> 47 42 #include <as.h> 48 43 #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 */ 53 47 struct { 54 48 volatile sysarg_t seconds1; … … 59 53 /** Add microseconds to given timeval. 60 54 * 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 * 63 58 */ 64 59 void tv_add(struct timeval *tv, suseconds_t usecs) … … 66 61 tv->tv_sec += usecs / 1000000; 67 62 tv->tv_usec += usecs % 1000000; 63 68 64 if (tv->tv_usec > 1000000) { 69 65 tv->tv_sec++; … … 74 70 /** Subtract two timevals. 75 71 * 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 * 81 78 */ 82 79 suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2) 83 80 { 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); 90 83 } 91 84 92 85 /** Decide if one timeval is greater than the other. 93 86 * 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 * 99 93 */ 100 94 int tv_gt(struct timeval *tv1, struct timeval *tv2) 101 95 { 102 96 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; 107 103 } 108 104 109 105 /** Decide if one timeval is greater than or equal to the other. 110 106 * 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 * 116 113 */ 117 114 int tv_gteq(struct timeval *tv1, struct timeval *tv2) 118 115 { 119 116 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 * 135 138 */ 136 139 int gettimeofday(struct timeval *tv, struct timezone *tz) 137 140 { 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; 151 147 } 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; 157 153 } 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 160 166 if (tz) { 161 167 tz->tz_minuteswest = 0; 162 168 tz->tz_dsttime = DST_NONE; 163 169 } 164 165 s2 = ktime->seconds2; 170 171 sysarg_t s2 = ktime->seconds2; 172 166 173 read_barrier(); 167 174 tv->tv_usec = ktime->useconds; 175 168 176 read_barrier(); 169 s1 = ktime->seconds1; 177 sysarg_t s1 = ktime->seconds1; 178 170 179 if (s1 != s2) { 180 tv->tv_sec = max(s1, s2); 171 181 tv->tv_usec = 0; 172 tv->tv_sec = s1 > s2 ? s1 : s2;173 182 } else 174 183 tv->tv_sec = s1; 175 184 176 185 return 0; 177 186 } … … 180 189 { 181 190 struct timeval tv; 182 183 191 if (gettimeofday(&tv, NULL)) 184 192 return (time_t) -1; 193 185 194 if (tloc) 186 195 *tloc = tv.tv_sec; 196 187 197 return tv.tv_sec; 188 198 } 189 199 190 /** Wait unconditionally for specified number of microseconds */ 200 /** Wait unconditionally for specified number of microseconds 201 * 202 */ 191 203 int usleep(useconds_t usec) 192 204 { … … 195 207 } 196 208 197 /** Wait unconditionally for specified number of seconds */ 209 /** Wait unconditionally for specified number of seconds 210 * 211 */ 198 212 unsigned int sleep(unsigned int sec) 199 213 { 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 202 219 while (sec > 0) { 203 220 unsigned int period = (sec > 1000) ? 1000 : sec; 204 221 205 222 usleep(period * 1000000); 206 223 sec -= period; 207 224 } 225 208 226 return 0; 209 227 }
Note:
See TracChangeset
for help on using the changeset viewer.