Changeset 58775d30 in mainline for uspace/lib/c
- Timestamp:
- 2015-03-16T16:07:21Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2003739
- Parents:
- 6069061 (diff), 795e2bf (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. - Location:
- uspace/lib/c
- Files:
-
- 3 added
- 22 edited
-
Makefile (modified) (2 diffs)
-
arch/ia32/Makefile.common (modified) (1 diff)
-
arch/ia64/include/libarch/types.h (modified) (1 diff)
-
generic/adt/hash_table.c (modified) (1 diff)
-
generic/async.c (modified) (5 diffs)
-
generic/fibril.c (modified) (11 diffs)
-
generic/fibril_synch.c (modified) (1 diff)
-
generic/futex.c (modified) (2 diffs)
-
generic/io/console.c (modified) (1 diff)
-
generic/io/window.c (modified) (1 diff)
-
generic/ipc.c (modified) (11 diffs)
-
generic/libc.c (modified) (3 diffs)
-
generic/malloc.c (modified) (13 diffs)
-
generic/smp_memory_barrier.c (added)
-
generic/thread.c (modified) (4 diffs)
-
generic/time.c (modified) (16 diffs)
-
include/adt/list.h (modified) (1 diff)
-
include/compiler/barrier.h (added)
-
include/futex.h (modified) (1 diff)
-
include/io/window.h (modified) (2 diffs)
-
include/ipc/common.h (modified) (2 diffs)
-
include/malloc.h (modified) (1 diff)
-
include/rwlock.h (modified) (1 diff)
-
include/smp_memory_barrier.h (added)
-
include/sys/time.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/Makefile
r6069061 r58775d30 47 47 LSONAME = libc.so0 48 48 49 LIBS = $(LIBURCU_PREFIX)/liburcu.a 50 EXTRA_CFLAGS += -I$(LIBURCU_PREFIX) 51 49 52 -include $(CONFIG_MAKEFILE) 50 53 -include arch/$(UARCH)/Makefile.inc … … 88 91 generic/pcb.c \ 89 92 generic/smc.c \ 93 generic/smp_memory_barrier.c \ 90 94 generic/thread.c \ 91 95 generic/tls.c \ -
uspace/lib/c/arch/ia32/Makefile.common
r6069061 r58775d30 32 32 GCC_CFLAGS += -march=pentium -fno-omit-frame-pointer 33 33 endif 34 34 35 CLANG_CFLAGS += -fno-omit-frame-pointer 35 36 -
uspace/lib/c/arch/ia64/include/libarch/types.h
r6069061 r58775d30 46 46 #define SSIZE_MAX INT64_MAX 47 47 48 typedef struct {49 uint64_t lo;50 int64_t hi;51 } __attribute__((aligned(16))) int128_t;52 53 typedef struct {54 uint64_t lo;55 uint64_t hi;56 } __attribute__((aligned(16))) uint128_t;57 58 48 typedef uint64_t sysarg_t; 59 49 typedef int64_t native_t; -
uspace/lib/c/generic/adt/hash_table.c
r6069061 r58775d30 134 134 free(h->bucket); 135 135 136 h->bucket = 0;136 h->bucket = NULL; 137 137 h->bucket_cnt = 0; 138 138 } -
uspace/lib/c/generic/async.c
r6069061 r58775d30 167 167 168 168 /** Async framework global futex */ 169 atomic_t async_futex = FUTEX_INITIALIZER;169 futex_t async_futex = FUTEX_INITIALIZER; 170 170 171 171 /** Number of threads waiting for IPC in the kernel. */ … … 820 820 if (usecs) { 821 821 getuptime(&conn->wdata.to_event.expires); 822 tv_add (&conn->wdata.to_event.expires, usecs);822 tv_add_diff(&conn->wdata.to_event.expires, usecs); 823 823 } else 824 824 conn->wdata.to_event.inlist = false; … … 1214 1214 1215 1215 } else { 1216 timeout = tv_sub(&waiter->to_event.expires, &tv); 1216 timeout = tv_sub_diff(&waiter->to_event.expires, 1217 &tv); 1217 1218 futex_up(&async_futex); 1218 1219 } … … 1505 1506 1506 1507 getuptime(&msg->wdata.to_event.expires); 1507 tv_add (&msg->wdata.to_event.expires, timeout);1508 tv_add_diff(&msg->wdata.to_event.expires, timeout); 1508 1509 1509 1510 /* … … 1587 1588 1588 1589 getuptime(&msg->wdata.to_event.expires); 1589 tv_add (&msg->wdata.to_event.expires, timeout);1590 tv_add_diff(&msg->wdata.to_event.expires, timeout); 1590 1591 1591 1592 futex_down(&async_futex); -
uspace/lib/c/generic/fibril.c
r6069061 r58775d30 49 49 #include <assert.h> 50 50 #include <async.h> 51 #include <futex.h> 52 53 #ifdef FUTEX_UPGRADABLE 54 #include <rcu.h> 55 #endif 51 56 52 57 /** … … 54 59 * serialized_list and manager_list. 55 60 */ 56 static atomic_t fibril_futex = FUTEX_INITIALIZER;61 static futex_t fibril_futex = FUTEX_INITIALIZER; 57 62 58 63 static LIST_INITIALIZE(ready_list); … … 83 88 { 84 89 fibril_t *fibril = __tcb_get()->fibril_data; 90 91 #ifdef FUTEX_UPGRADABLE 92 rcu_register_fibril(); 93 #endif 85 94 86 95 /* Call the implementing function. */ … … 146 155 int retval = 0; 147 156 148 futex_ down(&fibril_futex);157 futex_lock(&fibril_futex); 149 158 150 159 if (stype == FIBRIL_PREEMPT && list_empty(&ready_list)) … … 168 177 if ((stype == FIBRIL_TO_MANAGER) || (stype == FIBRIL_FROM_DEAD)) { 169 178 while (list_empty(&manager_list)) { 170 futex_u p(&fibril_futex);179 futex_unlock(&fibril_futex); 171 180 async_create_manager(); 172 futex_ down(&fibril_futex);181 futex_lock(&fibril_futex); 173 182 } 174 183 } … … 203 212 } 204 213 205 return 1; /* futex_u palready done here */214 return 1; /* futex_unlock already done here */ 206 215 } 207 216 … … 246 255 list_remove(&dstf->link); 247 256 248 futex_up(&fibril_futex); 257 futex_unlock(&fibril_futex); 258 259 #ifdef FUTEX_UPGRADABLE 260 if (stype == FIBRIL_FROM_DEAD) { 261 rcu_deregister_fibril(); 262 } 263 #endif 264 249 265 context_restore(&dstf->ctx); 250 266 /* not reached */ 251 267 252 268 ret_0: 253 futex_u p(&fibril_futex);269 futex_unlock(&fibril_futex); 254 270 return retval; 255 271 } … … 318 334 fibril_t *fibril = (fibril_t *) fid; 319 335 320 futex_ down(&fibril_futex);336 futex_lock(&fibril_futex); 321 337 322 338 if ((fibril->flags & FIBRIL_SERIALIZED)) … … 325 341 list_append(&fibril->link, &ready_list); 326 342 327 futex_u p(&fibril_futex);343 futex_unlock(&fibril_futex); 328 344 } 329 345 … … 338 354 fibril_t *fibril = (fibril_t *) fid; 339 355 340 futex_ down(&fibril_futex);356 futex_lock(&fibril_futex); 341 357 list_append(&fibril->link, &manager_list); 342 futex_u p(&fibril_futex);358 futex_unlock(&fibril_futex); 343 359 } 344 360 … … 346 362 void fibril_remove_manager(void) 347 363 { 348 futex_ down(&fibril_futex);364 futex_lock(&fibril_futex); 349 365 350 366 if (!list_empty(&manager_list)) 351 367 list_remove(list_first(&manager_list)); 352 368 353 futex_u p(&fibril_futex);369 futex_unlock(&fibril_futex); 354 370 } 355 371 -
uspace/lib/c/generic/fibril_synch.c
r6069061 r58775d30 380 380 if (timeout) { 381 381 getuptime(&wdata.to_event.expires); 382 tv_add (&wdata.to_event.expires, timeout);382 tv_add_diff(&wdata.to_event.expires, timeout); 383 383 async_insert_timeout(&wdata); 384 384 } -
uspace/lib/c/generic/futex.c
r6069061 r58775d30 35 35 #include <futex.h> 36 36 #include <atomic.h> 37 #include <libarch/barrier.h>38 #include <libc.h>39 #include <sys/types.h>40 37 41 38 /** Initialize futex counter. … … 47 44 void futex_initialize(futex_t *futex, int val) 48 45 { 49 atomic_set( futex, val);46 atomic_set(&futex->val, val); 50 47 } 51 48 52 /** Try to down the futex. 53 * 54 * @param futex Futex. 55 * 56 * @return Non-zero if the futex was acquired. 57 * @return Zero if the futex was not acquired. 58 * 59 */ 60 int futex_trydown(futex_t *futex) 49 50 #ifdef FUTEX_UPGRADABLE 51 52 int _upgrade_futexes = 0; 53 static futex_t upg_and_wait_futex = FUTEX_INITIALIZER; 54 55 void futex_upgrade_all_and_wait(void) 61 56 { 62 int rc; 63 64 rc = cas(futex, 1, 0); 65 CS_ENTER_BARRIER(); 66 67 return rc; 57 futex_down(&upg_and_wait_futex); 58 59 if (!_upgrade_futexes) { 60 rcu_assign(_upgrade_futexes, 1); 61 _rcu_synchronize(BM_BLOCK_THREAD); 62 } 63 64 futex_up(&upg_and_wait_futex); 68 65 } 69 66 70 /** Down the futex. 71 * 72 * @param futex Futex. 73 * 74 * @return ENOENT if there is no such virtual address. 75 * @return Zero in the uncontended case. 76 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED. 77 * 78 */ 79 int futex_down(futex_t *futex) 80 { 81 atomic_signed_t nv; 82 83 nv = (atomic_signed_t) atomic_predec(futex); 84 CS_ENTER_BARRIER(); 85 if (nv < 0) 86 return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->count); 87 88 return 0; 89 } 90 91 /** Up the futex. 92 * 93 * @param futex Futex. 94 * 95 * @return ENOENT if there is no such virtual address. 96 * @return Zero in the uncontended case. 97 * 98 */ 99 int futex_up(futex_t *futex) 100 { 101 CS_LEAVE_BARRIER(); 102 103 if ((atomic_signed_t) atomic_postinc(futex) < 0) 104 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->count); 105 106 return 0; 107 } 67 #endif 108 68 109 69 /** @} -
uspace/lib/c/generic/io/console.c
r6069061 r58775d30 259 259 struct timeval t1; 260 260 gettimeofday(&t1, NULL); 261 *timeout -= tv_sub (&t1, &t0);261 *timeout -= tv_sub_diff(&t1, &t0); 262 262 263 263 return true; -
uspace/lib/c/generic/io/window.c
r6069061 r58775d30 40 40 #include <stdio.h> 41 41 42 int win_register(async_sess_t *sess, service_id_t *in, service_id_t *out) 42 int win_register(async_sess_t *sess, window_flags_t flags, service_id_t *in, 43 service_id_t *out) 43 44 { 44 45 async_exch_t *exch = async_exchange_begin(sess); 45 int ret = async_req_ 0_2(exch, WINDOW_REGISTER, in, out);46 int ret = async_req_1_2(exch, WINDOW_REGISTER, flags, in, out); 46 47 async_exchange_end(exch); 47 48 -
uspace/lib/c/generic/ipc.c
r6069061 r58775d30 81 81 LIST_INITIALIZE(queued_calls); 82 82 83 static atomic_t ipc_futex = FUTEX_INITIALIZER;83 static futex_t ipc_futex = FUTEX_INITIALIZER; 84 84 85 85 /** Send asynchronous message via syscall. … … 136 136 if (!call) { 137 137 /* Nothing to do regardless if failed or not */ 138 futex_u p(&ipc_futex);138 futex_unlock(&ipc_futex); 139 139 return; 140 140 } 141 141 142 142 if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { 143 futex_u p(&ipc_futex);143 futex_unlock(&ipc_futex); 144 144 145 145 /* Call asynchronous handler with error code */ … … 152 152 153 153 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 154 futex_u p(&ipc_futex);154 futex_unlock(&ipc_futex); 155 155 156 156 call->u.msg.phoneid = phoneid; … … 175 175 /* Add call to the list of dispatched calls */ 176 176 list_append(&call->list, &dispatched_calls); 177 futex_u p(&ipc_futex);177 futex_unlock(&ipc_futex); 178 178 } 179 179 … … 219 219 */ 220 220 221 futex_ down(&ipc_futex);221 futex_lock(&ipc_futex); 222 222 ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, 223 223 imethod, arg1, arg2, arg3, arg4); … … 226 226 if (!call) { 227 227 call = ipc_prepare_async(private, callback); 228 if (!call) 228 if (!call) { 229 futex_unlock(&ipc_futex); 229 230 return; 231 } 230 232 } 231 233 … … 289 291 */ 290 292 291 futex_ down(&ipc_futex);293 futex_lock(&ipc_futex); 292 294 ipc_callid_t callid = 293 295 ipc_call_async_internal(phoneid, &call->u.msg.data); … … 384 386 call->u.callid = callid; 385 387 386 futex_ down(&ipc_futex);388 futex_lock(&ipc_futex); 387 389 list_append(&call->list, &dispatched_calls); 388 futex_u p(&ipc_futex);390 futex_unlock(&ipc_futex); 389 391 } 390 392 … … 412 414 callid &= ~IPC_CALLID_ANSWERED; 413 415 414 futex_ down(&ipc_futex);416 futex_lock(&ipc_futex); 415 417 416 418 link_t *item; … … 423 425 list_remove(&call->list); 424 426 425 futex_u p(&ipc_futex);427 futex_unlock(&ipc_futex); 426 428 427 429 if (call->callback) … … 434 436 } 435 437 436 futex_u p(&ipc_futex);438 futex_unlock(&ipc_futex); 437 439 } 438 440 -
uspace/lib/c/generic/libc.c
r6069061 r58775d30 52 52 #include "private/io.h" 53 53 54 #ifdef FUTEX_UPGRADABLE 55 #include <rcu.h> 56 #endif 57 54 58 #ifdef CONFIG_RTLD 55 59 #include <rtld/rtld.h> 56 60 #endif 61 57 62 58 63 static bool env_setup = false; … … 62 67 /* Initialize user task run-time environment */ 63 68 __malloc_init(); 64 __async_init();65 69 66 70 fibril_t *fibril = fibril_setup(); … … 72 76 /* Save the PCB pointer */ 73 77 __pcb = (pcb_t *) pcb_ptr; 78 79 #ifdef FUTEX_UPGRADABLE 80 rcu_register_fibril(); 81 #endif 82 83 __async_init(); 74 84 75 85 /* The basic run-time environment is setup */ -
uspace/lib/c/generic/malloc.c
r6069061 r58775d30 67 67 /** Heap shrink granularity 68 68 * 69 * Try not to pump and stress the heap to much69 * Try not to pump and stress the heap too much 70 70 * by shrinking and enlarging it too often. 71 * A heap area won't shr unk if itthe released71 * A heap area won't shrink if the released 72 72 * free block is smaller than this constant. 73 73 * … … 200 200 do { \ 201 201 if (!(expr)) {\ 202 futex_up(&malloc_futex); \202 heap_unlock(); \ 203 203 assert_abort(#expr, __FILE__, __LINE__); \ 204 204 } \ … … 210 210 211 211 #endif /* NDEBUG */ 212 213 214 #ifdef FUTEX_UPGRADABLE 215 /** True if the heap may be accessed from multiple threads. */ 216 static bool multithreaded = false; 217 218 /** Makes accesses to the heap thread safe. */ 219 void malloc_enable_multithreaded(void) 220 { 221 multithreaded = true; 222 } 223 224 /** Serializes access to the heap from multiple threads. */ 225 static inline void heap_lock(void) 226 { 227 if (multithreaded) { 228 futex_down(&malloc_futex); 229 } else { 230 /* 231 * Malloc never switches fibrils while the heap is locked. 232 * Similarly, it never creates new threads from within the 233 * locked region. Therefore, if there are no other threads 234 * except this one, the whole operation will complete without 235 * any interruptions. 236 */ 237 } 238 } 239 240 /** Serializes access to the heap from multiple threads. */ 241 static inline void heap_unlock(void) 242 { 243 if (multithreaded) { 244 futex_up(&malloc_futex); 245 } else { 246 /* 247 * Malloc never switches fibrils while the heap is locked. 248 * Similarly, it never creates new threads from within the 249 * locked region. Therefore, if there are no other threads 250 * except this one, the whole operation will complete without 251 * any interruptions. 252 */ 253 } 254 } 255 256 #else 257 258 /** Makes accesses to the heap thread safe. */ 259 void malloc_enable_multithreaded(void) 260 { 261 /* No-op. Already using thread-safe heap locking operations. */ 262 } 263 264 /** Serializes access to the heap from multiple threads. */ 265 static inline void heap_lock(void) 266 { 267 futex_down(&malloc_futex); 268 } 269 270 /** Serializes access to the heap from multiple threads. */ 271 static inline void heap_unlock(void) 272 { 273 futex_up(&malloc_futex); 274 } 275 #endif 276 212 277 213 278 /** Initialize a heap block … … 785 850 void *malloc(const size_t size) 786 851 { 787 futex_down(&malloc_futex);852 heap_lock(); 788 853 void *block = malloc_internal(size, BASE_ALIGN); 789 futex_up(&malloc_futex);790 854 heap_unlock(); 855 791 856 return block; 792 857 } … … 807 872 size_t palign = 808 873 1 << (fnzb(max(sizeof(void *), align) - 1) + 1); 809 810 futex_down(&malloc_futex);874 875 heap_lock(); 811 876 void *block = malloc_internal(size, palign); 812 futex_up(&malloc_futex);813 877 heap_unlock(); 878 814 879 return block; 815 880 } … … 828 893 return malloc(size); 829 894 830 futex_down(&malloc_futex);895 heap_lock(); 831 896 832 897 /* Calculate the position of the header. */ … … 885 950 } 886 951 887 futex_up(&malloc_futex);952 heap_unlock(); 888 953 889 954 if (reloc) { … … 908 973 return; 909 974 910 futex_down(&malloc_futex);975 heap_lock(); 911 976 912 977 /* Calculate the position of the header. */ … … 953 1018 heap_shrink(area); 954 1019 955 futex_up(&malloc_futex);1020 heap_unlock(); 956 1021 } 957 1022 958 1023 void *heap_check(void) 959 1024 { 960 futex_down(&malloc_futex);1025 heap_lock(); 961 1026 962 1027 if (first_heap_area == NULL) { 963 futex_up(&malloc_futex);1028 heap_unlock(); 964 1029 return (void *) -1; 965 1030 } … … 975 1040 (((uintptr_t) area->start % PAGE_SIZE) != 0) || 976 1041 (((uintptr_t) area->end % PAGE_SIZE) != 0)) { 977 futex_up(&malloc_futex);1042 heap_unlock(); 978 1043 return (void *) area; 979 1044 } … … 986 1051 /* Check heap block consistency */ 987 1052 if (head->magic != HEAP_BLOCK_HEAD_MAGIC) { 988 futex_up(&malloc_futex);1053 heap_unlock(); 989 1054 return (void *) head; 990 1055 } … … 994 1059 if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) || 995 1060 (head->size != foot->size)) { 996 futex_up(&malloc_futex);1061 heap_unlock(); 997 1062 return (void *) foot; 998 1063 } … … 1000 1065 } 1001 1066 1002 futex_up(&malloc_futex);1067 heap_unlock(); 1003 1068 1004 1069 return NULL; -
uspace/lib/c/generic/thread.c
r6069061 r58775d30 46 46 #include "private/thread.h" 47 47 48 #ifdef FUTEX_UPGRADABLE 49 #include <rcu.h> 50 #endif 51 52 48 53 /** Main thread function. 49 54 * … … 63 68 __tcb_set(fibril->tcb); 64 69 70 #ifdef FUTEX_UPGRADABLE 71 rcu_register_fibril(); 72 futex_upgrade_all_and_wait(); 73 #endif 74 65 75 uarg->uspace_thread_function(uarg->uspace_thread_arg); 66 76 /* … … 73 83 /* If there is a manager, destroy it */ 74 84 async_destroy_manager(); 85 86 #ifdef FUTEX_UPGRADABLE 87 rcu_deregister_fibril(); 88 #endif 89 75 90 fibril_teardown(fibril); 76 91 … … 106 121 return ENOMEM; 107 122 } 123 124 /* Make heap thread safe. */ 125 malloc_enable_multithreaded(); 108 126 109 127 uarg->uspace_entry = (void *) FADDR(__thread_entry); -
uspace/lib/c/generic/time.c
r6069061 r58775d30 59 59 #define MINS_PER_HOUR 60 60 60 #define SECS_PER_MIN 60 61 #define USECS_PER_SEC 1000000 61 62 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 62 63 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) … … 252 253 * Optionally add specified amount of seconds. 253 254 * 254 * @param tm Broken-down time to normalize.255 * @param sec_add Secondsto add.255 * @param tm Broken-down time to normalize. 256 * @param tv Timeval to add. 256 257 * 257 258 * @return 0 on success, -1 on overflow 258 259 * 259 260 */ 260 static int normalize_t ime(struct tm *tm, time_t sec_add)261 static int normalize_tm_tv(struct tm *tm, const struct timeval *tv) 261 262 { 262 263 // TODO: DST correction 263 264 264 265 /* Set initial values. */ 265 time_t sec = tm->tm_sec + sec_add; 266 time_t usec = tm->tm_usec + tv->tv_usec; 267 time_t sec = tm->tm_sec + tv->tv_sec; 266 268 time_t min = tm->tm_min; 267 269 time_t hour = tm->tm_hour; … … 271 273 272 274 /* Adjust time. */ 275 sec += floor_div(usec, USECS_PER_SEC); 276 usec = floor_mod(usec, USECS_PER_SEC); 273 277 min += floor_div(sec, SECS_PER_MIN); 274 278 sec = floor_mod(sec, SECS_PER_MIN); … … 319 323 320 324 /* And put the values back to the struct. */ 325 tm->tm_usec = (int) usec; 321 326 tm->tm_sec = (int) sec; 322 327 tm->tm_min = (int) min; … … 335 340 } 336 341 342 static int normalize_tm_time(struct tm *tm, time_t time) 343 { 344 struct timeval tv = { 345 .tv_sec = time, 346 .tv_usec = 0 347 }; 348 349 return normalize_tm_tv(tm, &tv); 350 } 351 352 337 353 /** Which day the week-based year starts on. 338 354 * … … 442 458 } 443 459 460 static void tv_normalize(struct timeval *tv) 461 { 462 while (tv->tv_usec > USECS_PER_SEC) { 463 tv->tv_sec++; 464 tv->tv_usec -= USECS_PER_SEC; 465 } 466 while (tv->tv_usec < 0) { 467 tv->tv_sec--; 468 tv->tv_usec += USECS_PER_SEC; 469 } 470 } 471 444 472 /** Add microseconds to given timeval. 445 473 * … … 448 476 * 449 477 */ 450 void tv_add(struct timeval *tv, suseconds_t usecs) 451 { 452 tv->tv_sec += usecs / 1000000; 453 tv->tv_usec += usecs % 1000000; 454 455 if (tv->tv_usec > 1000000) { 456 tv->tv_sec++; 457 tv->tv_usec -= 1000000; 458 } 459 } 460 461 /** Subtract two timevals. 478 void tv_add_diff(struct timeval *tv, suseconds_t usecs) 479 { 480 tv->tv_sec += usecs / USECS_PER_SEC; 481 tv->tv_usec += usecs % USECS_PER_SEC; 482 tv_normalize(tv); 483 } 484 485 /** Add two timevals. 462 486 * 463 487 * @param tv1 First timeval. 464 488 * @param tv2 Second timeval. 489 */ 490 void tv_add(struct timeval *tv1, struct timeval *tv2) 491 { 492 tv1->tv_sec += tv2->tv_sec; 493 tv1->tv_usec += tv2->tv_usec; 494 tv_normalize(tv1); 495 } 496 497 /** Subtract two timevals. 498 * 499 * @param tv1 First timeval. 500 * @param tv2 Second timeval. 465 501 * 466 502 * @return Difference between tv1 and tv2 (tv1 - tv2) in … … 468 504 * 469 505 */ 470 suseconds_t tv_sub (struct timeval *tv1, struct timeval *tv2)506 suseconds_t tv_sub_diff(struct timeval *tv1, struct timeval *tv2) 471 507 { 472 508 return (tv1->tv_usec - tv2->tv_usec) + 473 ((tv1->tv_sec - tv2->tv_sec) * 1000000); 509 ((tv1->tv_sec - tv2->tv_sec) * USECS_PER_SEC); 510 } 511 512 /** Subtract two timevals. 513 * 514 * @param tv1 First timeval. 515 * @param tv2 Second timeval. 516 * 517 */ 518 void tv_sub(struct timeval *tv1, struct timeval *tv2) 519 { 520 tv1->tv_sec -= tv2->tv_sec; 521 tv1->tv_usec -= tv2->tv_usec; 522 tv_normalize(tv1); 474 523 } 475 524 … … 573 622 goto fallback; 574 623 575 tv->tv_usec = 0;624 tv->tv_usec = time.tm_usec; 576 625 tv->tv_sec = mktime(&time); 577 626 … … 689 738 // TODO: detect overflow 690 739 691 normalize_t ime(tm, 0);740 normalize_tm_time(tm, 0); 692 741 return secs_since_epoch(tm); 693 742 } … … 944 993 945 994 /* Set result to epoch. */ 995 result->tm_usec = 0; 946 996 result->tm_sec = 0; 947 997 result->tm_min = 0; … … 951 1001 result->tm_year = 70; /* 1970 */ 952 1002 953 if (normalize_t ime(result, time) == -1)1003 if (normalize_tm_time(result, time) == -1) 954 1004 return EOVERFLOW; 955 1005 … … 1014 1064 * Time is expressed relative to the user's specified timezone. 1015 1065 * 1016 * @param t imer Timeto convert.1066 * @param tv Timeval to convert. 1017 1067 * @param result Structure to store the result to. 1018 1068 * … … 1020 1070 * 1021 1071 */ 1022 int time_ local2tm(const time_t time, struct tm *restrict result)1072 int time_tv2tm(const struct timeval *tv, struct tm *restrict result) 1023 1073 { 1024 1074 // TODO: Deal with timezones. … … 1026 1076 1027 1077 /* Set result to epoch. */ 1078 result->tm_usec = 0; 1028 1079 result->tm_sec = 0; 1029 1080 result->tm_min = 0; … … 1033 1084 result->tm_year = 70; /* 1970 */ 1034 1085 1035 if (normalize_t ime(result, time) == -1)1086 if (normalize_tm_tv(result, tv) == -1) 1036 1087 return EOVERFLOW; 1037 1088 1038 1089 return EOK; 1090 } 1091 1092 /** Converts a time value to a broken-down local time. 1093 * 1094 * Time is expressed relative to the user's specified timezone. 1095 * 1096 * @param timer Time to convert. 1097 * @param result Structure to store the result to. 1098 * 1099 * @return EOK on success or a negative error code. 1100 * 1101 */ 1102 int time_local2tm(const time_t time, struct tm *restrict result) 1103 { 1104 struct timeval tv = { 1105 .tv_sec = time, 1106 .tv_usec = 0 1107 }; 1108 1109 return time_tv2tm(&tv, result); 1039 1110 } 1040 1111 -
uspace/lib/c/include/adt/list.h
r6069061 r58775d30 58 58 */ 59 59 #define LIST_INITIALIZE(name) \ 60 list_t name = { \ 60 list_t name = LIST_INITIALIZER(name) 61 62 /** Initializer for statically allocated list. 63 * 64 * @code 65 * struct named_list { 66 * const char *name; 67 * list_t list; 68 * } var = { 69 * .name = "default name", 70 * .list = LIST_INITIALIZER(name_list.list) 71 * }; 72 * @endcode 73 * 74 * @param name Name of the new statically allocated list. 75 * 76 */ 77 #define LIST_INITIALIZER(name) \ 78 { \ 61 79 .head = { \ 62 80 .prev = &(name).head, \ -
uspace/lib/c/include/futex.h
r6069061 r58775d30 38 38 #include <atomic.h> 39 39 #include <sys/types.h> 40 #include <libc.h> 40 41 41 #define FUTEX_INITIALIZER {1} 42 typedef struct futex { 43 atomic_t val; 44 #ifdef FUTEX_UPGRADABLE 45 int upgraded; 46 #endif 47 } futex_t; 42 48 43 typedef atomic_t futex_t;44 49 45 50 extern void futex_initialize(futex_t *futex, int value); 46 extern int futex_down(futex_t *futex); 47 extern int futex_trydown(futex_t *futex); 48 extern int futex_up(futex_t *futex); 51 52 #ifdef FUTEX_UPGRADABLE 53 #include <rcu.h> 54 55 #define FUTEX_INITIALIZE(val) {{ (val) }, 0} 56 57 #define futex_lock(fut) \ 58 ({ \ 59 rcu_read_lock(); \ 60 (fut)->upgraded = rcu_access(_upgrade_futexes); \ 61 if ((fut)->upgraded) \ 62 (void) futex_down((fut)); \ 63 }) 64 65 #define futex_trylock(fut) \ 66 ({ \ 67 rcu_read_lock(); \ 68 int _upgraded = rcu_access(_upgrade_futexes); \ 69 if (_upgraded) { \ 70 int _acquired = futex_trydown((fut)); \ 71 if (!_acquired) { \ 72 rcu_read_unlock(); \ 73 } else { \ 74 (fut)->upgraded = true; \ 75 } \ 76 _acquired; \ 77 } else { \ 78 (fut)->upgraded = false; \ 79 1; \ 80 } \ 81 }) 82 83 #define futex_unlock(fut) \ 84 ({ \ 85 if ((fut)->upgraded) \ 86 (void) futex_up((fut)); \ 87 rcu_read_unlock(); \ 88 }) 89 90 extern int _upgrade_futexes; 91 92 extern void futex_upgrade_all_and_wait(void); 93 94 #else 95 96 #define FUTEX_INITIALIZE(val) {{ (val) }} 97 98 #define futex_lock(fut) (void) futex_down((fut)) 99 #define futex_trylock(fut) futex_trydown((fut)) 100 #define futex_unlock(fut) (void) futex_up((fut)) 101 102 #endif 103 104 #define FUTEX_INITIALIZER FUTEX_INITIALIZE(1) 105 106 /** Try to down the futex. 107 * 108 * @param futex Futex. 109 * 110 * @return Non-zero if the futex was acquired. 111 * @return Zero if the futex was not acquired. 112 * 113 */ 114 static inline int futex_trydown(futex_t *futex) 115 { 116 return cas(&futex->val, 1, 0); 117 } 118 119 /** Down the futex. 120 * 121 * @param futex Futex. 122 * 123 * @return ENOENT if there is no such virtual address. 124 * @return Zero in the uncontended case. 125 * @return Otherwise one of ESYNCH_OK_ATOMIC or ESYNCH_OK_BLOCKED. 126 * 127 */ 128 static inline int futex_down(futex_t *futex) 129 { 130 if ((atomic_signed_t) atomic_predec(&futex->val) < 0) 131 return __SYSCALL1(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count); 132 133 return 0; 134 } 135 136 /** Up the futex. 137 * 138 * @param futex Futex. 139 * 140 * @return ENOENT if there is no such virtual address. 141 * @return Zero in the uncontended case. 142 * 143 */ 144 static inline int futex_up(futex_t *futex) 145 { 146 if ((atomic_signed_t) atomic_postinc(&futex->val) < 0) 147 return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->val.count); 148 149 return 0; 150 } 49 151 50 152 #endif -
uspace/lib/c/include/io/window.h
r6069061 r58775d30 42 42 #include <io/kbd_event.h> 43 43 #include <io/pos_event.h> 44 45 typedef enum { 46 WINDOW_MAIN = 1, 47 WINDOW_DECORATED = 2, 48 WINDOW_RESIZEABLE = 4 49 } window_flags_t; 44 50 45 51 typedef enum { … … 108 114 } window_event_t; 109 115 110 extern int win_register(async_sess_t *, service_id_t *, service_id_t *); 116 extern int win_register(async_sess_t *, window_flags_t, service_id_t *, 117 service_id_t *); 111 118 112 119 extern int win_get_event(async_sess_t *, window_event_t *); -
uspace/lib/c/include/ipc/common.h
r6069061 r58775d30 40 40 #include <atomic.h> 41 41 #include <abi/proc/task.h> 42 #include <futex.h> 42 43 43 44 #define IPC_FLAG_BLOCKING 0x01 … … 51 52 typedef sysarg_t ipc_callid_t; 52 53 53 extern atomic_t async_futex;54 extern futex_t async_futex; 54 55 55 56 #endif -
uspace/lib/c/include/malloc.h
r6069061 r58775d30 48 48 extern void *heap_check(void); 49 49 50 extern void malloc_enable_multithreaded(void); 50 51 #endif 51 52 -
uspace/lib/c/include/rwlock.h
r6069061 r58775d30 49 49 50 50 #define rwlock_initialize(rwlock) futex_initialize((rwlock), 1) 51 #define rwlock_read_lock(rwlock) futex_ down((rwlock))52 #define rwlock_write_lock(rwlock) futex_ down((rwlock))53 #define rwlock_read_unlock(rwlock) futex_u p((rwlock))54 #define rwlock_write_unlock(rwlock) futex_u p((rwlock))51 #define rwlock_read_lock(rwlock) futex_lock((rwlock)) 52 #define rwlock_write_lock(rwlock) futex_lock((rwlock)) 53 #define rwlock_read_unlock(rwlock) futex_unlock((rwlock)) 54 #define rwlock_write_unlock(rwlock) futex_unlock((rwlock)) 55 55 56 56 #endif -
uspace/lib/c/include/sys/time.h
r6069061 r58775d30 50 50 51 51 struct tm { 52 int tm_usec; /* Microseconds [0,999999]. */ 52 53 int tm_sec; /* Seconds [0,60]. */ 53 54 int tm_min; /* Minutes [0,59]. */ … … 71 72 }; 72 73 73 extern void tv_add(struct timeval *, suseconds_t); 74 extern suseconds_t tv_sub(struct timeval *, struct timeval *); 74 extern void tv_add_diff(struct timeval *, suseconds_t); 75 extern void tv_add(struct timeval *, struct timeval *); 76 extern suseconds_t tv_sub_diff(struct timeval *, struct timeval *); 77 extern void tv_sub(struct timeval *, struct timeval *); 75 78 extern int tv_gt(struct timeval *, struct timeval *); 76 79 extern int tv_gteq(struct timeval *, struct timeval *); … … 79 82 80 83 extern void udelay(useconds_t); 84 extern int usleep(useconds_t); 81 85 82 86 extern time_t mktime(struct tm *); … … 84 88 extern int time_utc2str(const time_t, char *); 85 89 extern void time_tm2str(const struct tm *, char *); 90 extern int time_tv2tm(const struct timeval *, struct tm *); 86 91 extern int time_local2tm(const time_t, struct tm *); 87 92 extern int time_local2str(const time_t, char *);
Note:
See TracChangeset
for help on using the changeset viewer.
