/src/libusb/libusb/os/threads_posix.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * libusb synchronization using POSIX Threads |
3 | | * |
4 | | * Copyright © 2011 Vitali Lovich <vlovich@aliph.com> |
5 | | * Copyright © 2011 Peter Stuge <peter@stuge.se> |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this library; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #include "libusbi.h" |
23 | | |
24 | | #include <errno.h> |
25 | | #include <limits.h> |
26 | | #if defined(__ANDROID__) |
27 | | # include <unistd.h> |
28 | | #elif defined(__HAIKU__) |
29 | | # include <os/kernel/OS.h> |
30 | | #elif defined(__linux__) |
31 | | # include <sys/syscall.h> |
32 | | # include <unistd.h> |
33 | | #elif defined(__NetBSD__) |
34 | | # include <lwp.h> |
35 | | #elif defined(__OpenBSD__) |
36 | | # include <unistd.h> |
37 | | #elif defined(__sun__) |
38 | | # include <sys/lwp.h> |
39 | | #endif |
40 | | |
41 | | void usbi_cond_init(pthread_cond_t *cond) |
42 | 0 | { |
43 | 0 | #ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK |
44 | 0 | pthread_condattr_t condattr; |
45 | |
|
46 | 0 | PTHREAD_CHECK(pthread_condattr_init(&condattr)); |
47 | 0 | PTHREAD_CHECK(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)); |
48 | 0 | PTHREAD_CHECK(pthread_cond_init(cond, &condattr)); |
49 | 0 | PTHREAD_CHECK(pthread_condattr_destroy(&condattr)); |
50 | | #else |
51 | | PTHREAD_CHECK(pthread_cond_init(cond, NULL)); |
52 | | #endif |
53 | 0 | } |
54 | | |
55 | | int usbi_cond_timedwait(pthread_cond_t *cond, |
56 | | pthread_mutex_t *mutex, const struct timeval *tv) |
57 | 0 | { |
58 | 0 | struct timespec timeout; |
59 | 0 | int r; |
60 | |
|
61 | 0 | #ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK |
62 | 0 | usbi_get_monotonic_time(&timeout); |
63 | | #else |
64 | | usbi_get_real_time(&timeout); |
65 | | #endif |
66 | |
|
67 | 0 | timeout.tv_sec += tv->tv_sec; |
68 | 0 | timeout.tv_nsec += tv->tv_usec * 1000L; |
69 | 0 | if (timeout.tv_nsec >= NSEC_PER_SEC) { |
70 | 0 | timeout.tv_nsec -= NSEC_PER_SEC; |
71 | 0 | timeout.tv_sec++; |
72 | 0 | } |
73 | |
|
74 | 0 | r = pthread_cond_timedwait(cond, mutex, &timeout); |
75 | 0 | if (r == 0) |
76 | 0 | return 0; |
77 | 0 | else if (r == ETIMEDOUT) |
78 | 0 | return LIBUSB_ERROR_TIMEOUT; |
79 | 0 | else |
80 | 0 | return LIBUSB_ERROR_OTHER; |
81 | 0 | } |
82 | | |
83 | | unsigned long usbi_get_tid(void) |
84 | 0 | { |
85 | 0 | static _Thread_local unsigned long tl_tid; |
86 | 0 | unsigned long tid; |
87 | |
|
88 | 0 | if (tl_tid) |
89 | 0 | return tl_tid; |
90 | | |
91 | | #if defined(__ANDROID__) |
92 | | tid = (unsigned long)gettid(); |
93 | | #elif defined(__APPLE__) |
94 | | #ifdef HAVE_PTHREAD_THREADID_NP |
95 | | uint64_t thread_id; |
96 | | |
97 | | if (pthread_threadid_np(NULL, &thread_id) == 0) |
98 | | tid = (unsigned long)thread_id; |
99 | | else |
100 | | tid = ULONG_MAX; |
101 | | #else |
102 | | tid = (unsigned long)pthread_mach_thread_np(pthread_self()); |
103 | | #endif |
104 | | #elif defined(__HAIKU__) |
105 | | tid = (unsigned long)get_pthread_thread_id(pthread_self()); |
106 | | #elif defined(__linux__) |
107 | 0 | tid = (unsigned long)syscall(SYS_gettid); |
108 | | #elif defined(__NetBSD__) |
109 | | tid = (unsigned long)_lwp_self(); |
110 | | #elif defined(__OpenBSD__) |
111 | | tid = (unsigned long)getthrid(); |
112 | | #elif defined(__sun__) |
113 | | tid = (unsigned long)_lwp_self(); |
114 | | #else |
115 | | tid = ULONG_MAX; |
116 | | #endif |
117 | |
|
118 | 0 | if (tid == ULONG_MAX) { |
119 | | /* If we don't have a thread ID, at least return a unique |
120 | | * value that can be used to distinguish individual |
121 | | * threads. */ |
122 | 0 | tid = (unsigned long)(uintptr_t)pthread_self(); |
123 | 0 | } |
124 | |
|
125 | 0 | return tl_tid = tid; |
126 | 0 | } |