/src/openvswitch/lib/ovs-thread.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2013, 2014 Nicira, Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at: |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #ifndef OVS_THREAD_H |
18 | | #define OVS_THREAD_H 1 |
19 | | |
20 | | #include <pthread.h> |
21 | | #include <stddef.h> |
22 | | #include <sys/types.h> |
23 | | #include "ovs-atomic.h" |
24 | | #include "ovs-rcu.h" |
25 | | #include "openvswitch/thread.h" |
26 | | #include "util.h" |
27 | | |
28 | | struct seq; |
29 | | |
30 | | /* Poll-block()-able barrier similar to pthread_barrier_t. */ |
31 | | struct ovs_barrier_impl; |
32 | | struct ovs_barrier { |
33 | | OVSRCU_TYPE(struct ovs_barrier_impl *) impl; |
34 | | }; |
35 | | |
36 | | /* Wrappers for pthread_mutexattr_*() that abort the process on any error. */ |
37 | | void xpthread_mutexattr_init(pthread_mutexattr_t *); |
38 | | void xpthread_mutexattr_destroy(pthread_mutexattr_t *); |
39 | | void xpthread_mutexattr_settype(pthread_mutexattr_t *, int type); |
40 | | void xpthread_mutexattr_gettype(pthread_mutexattr_t *, int *typep); |
41 | | |
42 | | /* Read-write lock. |
43 | | * |
44 | | * An ovs_rwlock does not support recursive readers, because POSIX allows |
45 | | * taking the reader lock recursively to deadlock when a thread is waiting on |
46 | | * the write-lock. (NetBSD does deadlock.) glibc rwlocks in their default |
47 | | * configuration do not deadlock, but ovs_rwlock_init() initializes rwlocks as |
48 | | * non-recursive (which will deadlock) for two reasons: |
49 | | * |
50 | | * - glibc only provides fairness to writers in this mode. |
51 | | * |
52 | | * - It's better to find bugs in the primary Open vSwitch target rather |
53 | | * than exposing them only to porters. */ |
54 | | struct OVS_LOCKABLE ovs_rwlock { |
55 | | pthread_rwlock_t lock; |
56 | | const char *where; /* NULL if and only if uninitialized. */ |
57 | | }; |
58 | | |
59 | | /* Initializer. */ |
60 | | #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP |
61 | | #define OVS_RWLOCK_INITIALIZER \ |
62 | | { PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, "<unlocked>" } |
63 | | #else |
64 | | #define OVS_RWLOCK_INITIALIZER { PTHREAD_RWLOCK_INITIALIZER, "<unlocked>" } |
65 | | #endif |
66 | | |
67 | | /* ovs_rwlock functions analogous to pthread_rwlock_*() functions. |
68 | | * |
69 | | * Most of these functions abort the process with an error message on any |
70 | | * error. The "trylock" functions are exception: they pass through a 0 or |
71 | | * EBUSY return value to the caller and abort on any other error. */ |
72 | | void ovs_rwlock_init(const struct ovs_rwlock *); |
73 | | void ovs_rwlock_destroy(const struct ovs_rwlock *); |
74 | | void ovs_rwlock_unlock(const struct ovs_rwlock *rwlock) OVS_RELEASES(rwlock); |
75 | | |
76 | | /* Wrappers for pthread_rwlockattr_*() that abort the process on any error. */ |
77 | | void xpthread_rwlockattr_init(pthread_rwlockattr_t *); |
78 | | void xpthread_rwlockattr_destroy(pthread_rwlockattr_t *); |
79 | | #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP |
80 | | void xpthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int kind); |
81 | | #endif |
82 | | |
83 | | void ovs_rwlock_wrlock_at(const struct ovs_rwlock *rwlock, const char *where) |
84 | | OVS_ACQ_WRLOCK(rwlock); |
85 | | #define ovs_rwlock_wrlock(rwlock) \ |
86 | 0 | ovs_rwlock_wrlock_at(rwlock, OVS_SOURCE_LOCATOR) |
87 | | |
88 | | int ovs_rwlock_trywrlock_at(const struct ovs_rwlock *rwlock, const char *where) |
89 | | OVS_TRY_WRLOCK(0, rwlock); |
90 | | #define ovs_rwlock_trywrlock(rwlock) \ |
91 | | ovs_rwlock_trywrlock_at(rwlock, OVS_SOURCE_LOCATOR) |
92 | | |
93 | | void ovs_rwlock_rdlock_at(const struct ovs_rwlock *rwlock, const char *where) |
94 | | OVS_ACQ_RDLOCK(rwlock); |
95 | | #define ovs_rwlock_rdlock(rwlock) \ |
96 | 0 | ovs_rwlock_rdlock_at(rwlock, OVS_SOURCE_LOCATOR) |
97 | | |
98 | | int ovs_rwlock_tryrdlock_at(const struct ovs_rwlock *rwlock, const char *where) |
99 | | OVS_TRY_RDLOCK(0, rwlock); |
100 | | #define ovs_rwlock_tryrdlock(rwlock) \ |
101 | 0 | ovs_rwlock_tryrdlock_at(rwlock, OVS_SOURCE_LOCATOR) |
102 | | |
103 | | /* ovs_barrier functions analogous to pthread_barrier_*() functions. */ |
104 | | void ovs_barrier_init(struct ovs_barrier *, uint32_t count); |
105 | | void ovs_barrier_destroy(struct ovs_barrier *); |
106 | | void ovs_barrier_block(struct ovs_barrier *); |
107 | | |
108 | | /* Wrappers for xpthread_cond_*() that abort the process on any error. |
109 | | * |
110 | | * Use ovs_mutex_cond_wait() to wait for a condition. */ |
111 | | void xpthread_cond_init(pthread_cond_t *, pthread_condattr_t *); |
112 | | void xpthread_cond_destroy(pthread_cond_t *); |
113 | | void xpthread_cond_signal(pthread_cond_t *); |
114 | | void xpthread_cond_broadcast(pthread_cond_t *); |
115 | | |
116 | | void xpthread_key_create(pthread_key_t *, void (*destructor)(void *)); |
117 | | void xpthread_key_delete(pthread_key_t); |
118 | | void xpthread_setspecific(pthread_key_t, const void *); |
119 | | |
120 | | #ifndef _WIN32 |
121 | | void xpthread_sigmask(int, const sigset_t *, sigset_t *); |
122 | | #endif |
123 | | |
124 | | pthread_t ovs_thread_create(const char *name, void *(*)(void *), void *); |
125 | | void xpthread_join(pthread_t, void **); |
126 | | |
127 | | /* Per-thread data. |
128 | | * |
129 | | * |
130 | | * Standard Forms |
131 | | * ============== |
132 | | * |
133 | | * Multiple forms of standard per-thread data exist, each with its own pluses |
134 | | * and minuses. In general, if one of these forms is appropriate, then it's a |
135 | | * good idea to use it: |
136 | | * |
137 | | * - POSIX per-thread data via pthread_key_t is portable to any pthreads |
138 | | * implementation, and allows a destructor function to be defined. It |
139 | | * only (directly) supports per-thread pointers, which are always |
140 | | * initialized to NULL. It requires once-only allocation of a |
141 | | * pthread_key_t value. It is relatively slow. Typically few |
142 | | * "pthread_key_t"s are available (POSIX requires only at least 128, |
143 | | * glibc supplies only 1024). |
144 | | * |
145 | | * - The thread_local feature newly defined in C11 <threads.h> works with |
146 | | * any data type and initializer, and it is fast. thread_local does not |
147 | | * require once-only initialization like pthread_key_t. C11 does not |
148 | | * define what happens if one attempts to access a thread_local object |
149 | | * from a thread other than the one to which that object belongs. There |
150 | | * is no provision to call a user-specified destructor when a thread |
151 | | * ends. Typical implementations allow for an arbitrary amount of |
152 | | * thread_local storage, but statically allocated only. |
153 | | * |
154 | | * - The __thread keyword is a GCC extension similar to thread_local but |
155 | | * with a longer history. __thread is not portable to every GCC version |
156 | | * or environment. __thread does not restrict the use of a thread-local |
157 | | * object outside its own thread. |
158 | | * |
159 | | * Here's a handy summary: |
160 | | * |
161 | | * pthread_key_t thread_local __thread |
162 | | * ------------- ------------ ------------- |
163 | | * portability high low medium |
164 | | * speed low high high |
165 | | * supports destructors? yes no no |
166 | | * needs key allocation? yes no no |
167 | | * arbitrary initializer? no yes yes |
168 | | * cross-thread access? yes no yes |
169 | | * amount available? few arbitrary arbitrary |
170 | | * dynamically allocated? yes no no |
171 | | * |
172 | | * |
173 | | * Extensions |
174 | | * ========== |
175 | | * |
176 | | * OVS provides some extensions and wrappers: |
177 | | * |
178 | | * - In a situation where the performance of thread_local or __thread is |
179 | | * desirable, but portability is required, DEFINE_STATIC_PER_THREAD_DATA |
180 | | * and DECLARE_EXTERN_PER_THREAD_DATA/DEFINE_EXTERN_PER_THREAD_DATA may |
181 | | * be appropriate (see below). |
182 | | * |
183 | | * - DEFINE_PER_THREAD_MALLOCED_DATA can be convenient for simple |
184 | | * per-thread malloc()'d buffers. |
185 | | * |
186 | | * - struct ovs_tsd provides an alternative to pthread_key_t that isn't |
187 | | * limited to a small number of keys. |
188 | | */ |
189 | | |
190 | | /* For static data, use this macro in a source file: |
191 | | * |
192 | | * DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, INITIALIZER). |
193 | | * |
194 | | * For global data, "declare" the data in the header and "define" it in |
195 | | * the source file, with: |
196 | | * |
197 | | * DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME). |
198 | | * DEFINE_EXTERN_PER_THREAD_DATA(NAME, INITIALIZER). |
199 | | * |
200 | | * One should prefer to use POSIX per-thread data, via pthread_key_t, when its |
201 | | * performance is acceptable, because of its portability (see the table above). |
202 | | * This macro is an alternatives that takes advantage of thread_local (and |
203 | | * __thread), for its performance, when it is available, and falls back to |
204 | | * POSIX per-thread data otherwise. |
205 | | * |
206 | | * Defines per-thread variable NAME with the given TYPE, initialized to |
207 | | * INITIALIZER (which must be valid as an initializer for a variable with |
208 | | * static lifetime). |
209 | | * |
210 | | * The public interface to the variable is: |
211 | | * |
212 | | * TYPE *NAME_get(void) |
213 | | * TYPE *NAME_get_unsafe(void) |
214 | | * |
215 | | * Returns the address of this thread's instance of NAME. |
216 | | * |
217 | | * Use NAME_get() in a context where this might be the first use of the |
218 | | * per-thread variable in the program. Use NAME_get_unsafe(), which |
219 | | * avoids a conditional test and is thus slightly faster, in a context |
220 | | * where one knows that NAME_get() has already been called previously. |
221 | | * |
222 | | * There is no "NAME_set()" (or "NAME_set_unsafe()") function. To set the |
223 | | * value of the per-thread variable, dereference the pointer returned by |
224 | | * TYPE_get() or TYPE_get_unsafe(), e.g. *TYPE_get() = 0. |
225 | | */ |
226 | | #if HAVE_THREAD_LOCAL || HAVE___THREAD |
227 | | |
228 | | #if HAVE_THREAD_LOCAL |
229 | | #include <threads.h> |
230 | | #elif HAVE___THREAD |
231 | | #define thread_local __thread |
232 | | #else |
233 | | #error |
234 | | #endif |
235 | | |
236 | | #define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ |
237 | | typedef TYPE NAME##_type; \ |
238 | | \ |
239 | | static NAME##_type * \ |
240 | | NAME##_get_unsafe(void) \ |
241 | 11.8M | { \ |
242 | 11.8M | static thread_local NAME##_type var = __VA_ARGS__; \ |
243 | 11.8M | return &var; \ |
244 | 11.8M | } \ util.c:counter_util_xalloc_get_unsafe Line | Count | Source | 241 | 11.7M | { \ | 242 | 11.7M | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 11.7M | return &var; \ | 244 | 11.7M | } \ |
Unexecuted instantiation: util.c:strerror_buffer_get_unsafe Unexecuted instantiation: vlog.c:msg_num_get_unsafe Unexecuted instantiation: coverage.c:coverage_clear_time_get_unsafe flow.c:counter_flow_extract_get_unsafe Line | Count | Source | 241 | 66.1k | { \ | 242 | 66.1k | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 66.1k | return &var; \ | 244 | 66.1k | } \ |
flow.c:counter_miniflow_extract_ipv4_pkt_len_error_get_unsafe Line | Count | Source | 241 | 256 | { \ | 242 | 256 | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 256 | return &var; \ | 244 | 256 | } \ |
flow.c:counter_miniflow_extract_ipv4_pkt_too_short_get_unsafe Line | Count | Source | 241 | 73 | { \ | 242 | 73 | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 73 | return &var; \ | 244 | 73 | } \ |
flow.c:counter_miniflow_extract_ipv6_pkt_len_error_get_unsafe Line | Count | Source | 241 | 352 | { \ | 242 | 352 | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 352 | return &var; \ | 244 | 352 | } \ |
flow.c:counter_miniflow_extract_ipv6_pkt_too_short_get_unsafe Line | Count | Source | 241 | 381 | { \ | 242 | 381 | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 381 | return &var; \ | 244 | 381 | } \ |
flow.c:counter_miniflow_malloc_get_unsafe Line | Count | Source | 241 | 46.4k | { \ | 242 | 46.4k | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 46.4k | return &var; \ | 244 | 46.4k | } \ |
Unexecuted instantiation: netdev.c:counter_netdev_received_get_unsafe Unexecuted instantiation: netdev.c:counter_netdev_sent_get_unsafe Unexecuted instantiation: netdev.c:counter_netdev_add_router_get_unsafe Unexecuted instantiation: netdev.c:counter_netdev_get_stats_get_unsafe Unexecuted instantiation: netdev.c:counter_netdev_push_header_drops_get_unsafe Unexecuted instantiation: netdev.c:counter_netdev_soft_seg_good_get_unsafe Unexecuted instantiation: netdev.c:counter_netdev_soft_seg_drops_get_unsafe Unexecuted instantiation: poll-loop.c:counter_poll_create_node_get_unsafe Unexecuted instantiation: poll-loop.c:counter_poll_zero_timeout_get_unsafe Unexecuted instantiation: random.c:seed_get_unsafe Unexecuted instantiation: seq.c:counter_seq_change_get_unsafe Unexecuted instantiation: timeval.c:counter_long_poll_interval_get_unsafe Unexecuted instantiation: timeval.c:last_wakeup_get_unsafe Unexecuted instantiation: timeval.c:last_seq_get_unsafe Unexecuted instantiation: unixctl.c:counter_unixctl_received_get_unsafe Unexecuted instantiation: unixctl.c:counter_unixctl_replied_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_set_policing_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_arp_lookup_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_get_ifindex_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_get_hwaddr_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_set_hwaddr_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_get_ethtool_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_set_ethtool_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_linux_invalid_l4_csum_get_unsafe Unexecuted instantiation: netdev-linux.c:counter_netdev_linux_unknown_l4_csum_get_unsafe Unexecuted instantiation: netlink-socket.c:counter_netlink_overflow_get_unsafe Unexecuted instantiation: netlink-socket.c:counter_netlink_received_get_unsafe Unexecuted instantiation: netlink-socket.c:counter_netlink_recv_jumbo_get_unsafe Unexecuted instantiation: netlink-socket.c:counter_netlink_sent_get_unsafe Unexecuted instantiation: route-table.c:counter_route_table_dump_get_unsafe Unexecuted instantiation: tc.c:counter_tc_netlink_malformed_reply_get_unsafe Unexecuted instantiation: ccmap.c:counter_ccmap_expand_get_unsafe Unexecuted instantiation: ccmap.c:counter_ccmap_shrink_get_unsafe Unexecuted instantiation: cmap.c:counter_cmap_expand_get_unsafe Unexecuted instantiation: cmap.c:counter_cmap_shrink_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_destroy_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_execute_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_execute_error_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_execute_with_help_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_flow_del_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_flow_del_error_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_flow_flush_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_flow_get_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_flow_get_error_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_flow_put_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_flow_put_error_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_meter_del_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_meter_get_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_meter_set_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_port_add_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_port_del_get_unsafe Unexecuted instantiation: dpif.c:counter_dpif_purge_get_unsafe hmap.c:counter_hmap_pathological_get_unsafe Line | Count | Source | 241 | 6 | { \ | 242 | 6 | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 6 | return &var; \ | 244 | 6 | } \ |
hmap.c:counter_hmap_expand_get_unsafe Line | Count | Source | 241 | 28 | { \ | 242 | 28 | static thread_local NAME##_type var = __VA_ARGS__; \ | 243 | 28 | return &var; \ | 244 | 28 | } \ |
Unexecuted instantiation: hmap.c:counter_hmap_shrink_get_unsafe Unexecuted instantiation: hmap.c:counter_hmap_reserve_get_unsafe Unexecuted instantiation: jsonrpc.c:counter_jsonrpc_recv_incomplete_get_unsafe Unexecuted instantiation: odp-execute.c:counter_datapath_drop_sample_error_get_unsafe Unexecuted instantiation: odp-execute.c:counter_datapath_drop_nsh_decap_error_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_of_pipeline_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_bridge_not_found_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_recursion_too_deep_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_too_many_resubmit_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_stack_too_deep_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_no_recirculation_context_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_recirculation_conflict_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_too_many_mpls_labels_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_invalid_tunnel_metadata_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_unsupported_packet_type_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_congestion_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_forwarding_disabled_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_routing_failed_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_output_no_ethernet_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_neigh_cache_miss_get_unsafe Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_header_build_failed_get_unsafe Unexecuted instantiation: stream.c:counter_pstream_open_get_unsafe Unexecuted instantiation: stream.c:counter_stream_open_get_unsafe Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l3csum_checked_get_unsafe Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l3csum_err_get_unsafe Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l4csum_checked_get_unsafe Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l4csum_err_get_unsafe Unexecuted instantiation: netlink-notifier.c:counter_nln_changed_get_unsafe Unexecuted instantiation: conntrack.c:counter_conntrack_full_get_unsafe Unexecuted instantiation: conntrack.c:counter_conntrack_l3csum_checked_get_unsafe Unexecuted instantiation: conntrack.c:counter_conntrack_l3csum_err_get_unsafe Unexecuted instantiation: conntrack.c:counter_conntrack_l4csum_checked_get_unsafe Unexecuted instantiation: conntrack.c:counter_conntrack_l4csum_err_get_unsafe Unexecuted instantiation: conntrack.c:counter_conntrack_lookup_natted_miss_get_unsafe Unexecuted instantiation: conntrack.c:counter_conntrack_zone_full_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_meter_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_upcall_error_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_lock_error_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_userspace_action_error_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_tunnel_push_error_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_tunnel_pop_error_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_recirc_error_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_invalid_port_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_invalid_bond_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_invalid_tnl_port_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_rx_invalid_packet_get_unsafe Unexecuted instantiation: dpif-netdev.c:recirc_depth_get_unsafe Unexecuted instantiation: hindex.c:counter_hindex_pathological_get_unsafe Unexecuted instantiation: hindex.c:counter_hindex_expand_get_unsafe Unexecuted instantiation: hindex.c:counter_hindex_shrink_get_unsafe Unexecuted instantiation: hindex.c:counter_hindex_reserve_get_unsafe Unexecuted instantiation: ipf.c:counter_ipf_stuck_frag_list_expired_get_unsafe Unexecuted instantiation: ipf.c:counter_ipf_stuck_frag_list_purged_get_unsafe Unexecuted instantiation: ipf.c:counter_ipf_l3csum_checked_get_unsafe Unexecuted instantiation: ipf.c:counter_ipf_l3csum_err_get_unsafe Unexecuted instantiation: lockfile.c:counter_lockfile_lock_get_unsafe Unexecuted instantiation: lockfile.c:counter_lockfile_error_get_unsafe Unexecuted instantiation: lockfile.c:counter_lockfile_unlock_get_unsafe Unexecuted instantiation: process.c:counter_process_start_get_unsafe Unexecuted instantiation: conntrack-tcp.c:counter_conntrack_tcp_seq_chk_bypass_get_unsafe Unexecuted instantiation: conntrack-tcp.c:counter_conntrack_tcp_seq_chk_failed_get_unsafe Unexecuted instantiation: conntrack-tcp.c:counter_conntrack_invalid_tcp_flags_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_uncommitted_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_unchanged_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_incomplete_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_aborted_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_success_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_try_again_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_not_locked_get_unsafe Unexecuted instantiation: ovsdb-idl.c:counter_txn_error_get_unsafe |
245 | | \ |
246 | | static NAME##_type * \ |
247 | | NAME##_get(void) \ |
248 | 11.8M | { \ |
249 | 11.8M | return NAME##_get_unsafe(); \ |
250 | 11.8M | } util.c:counter_util_xalloc_get Line | Count | Source | 248 | 11.7M | { \ | 249 | 11.7M | return NAME##_get_unsafe(); \ | 250 | 11.7M | } |
Unexecuted instantiation: util.c:strerror_buffer_get Unexecuted instantiation: vlog.c:msg_num_get Unexecuted instantiation: coverage.c:coverage_clear_time_get flow.c:counter_flow_extract_get Line | Count | Source | 248 | 66.1k | { \ | 249 | 66.1k | return NAME##_get_unsafe(); \ | 250 | 66.1k | } |
flow.c:counter_miniflow_extract_ipv4_pkt_len_error_get Line | Count | Source | 248 | 256 | { \ | 249 | 256 | return NAME##_get_unsafe(); \ | 250 | 256 | } |
flow.c:counter_miniflow_extract_ipv4_pkt_too_short_get Line | Count | Source | 248 | 73 | { \ | 249 | 73 | return NAME##_get_unsafe(); \ | 250 | 73 | } |
flow.c:counter_miniflow_extract_ipv6_pkt_len_error_get Line | Count | Source | 248 | 352 | { \ | 249 | 352 | return NAME##_get_unsafe(); \ | 250 | 352 | } |
flow.c:counter_miniflow_extract_ipv6_pkt_too_short_get Line | Count | Source | 248 | 381 | { \ | 249 | 381 | return NAME##_get_unsafe(); \ | 250 | 381 | } |
flow.c:counter_miniflow_malloc_get Line | Count | Source | 248 | 46.4k | { \ | 249 | 46.4k | return NAME##_get_unsafe(); \ | 250 | 46.4k | } |
Unexecuted instantiation: netdev.c:counter_netdev_received_get Unexecuted instantiation: netdev.c:counter_netdev_sent_get Unexecuted instantiation: netdev.c:counter_netdev_add_router_get Unexecuted instantiation: netdev.c:counter_netdev_get_stats_get Unexecuted instantiation: netdev.c:counter_netdev_push_header_drops_get Unexecuted instantiation: netdev.c:counter_netdev_soft_seg_good_get Unexecuted instantiation: netdev.c:counter_netdev_soft_seg_drops_get Unexecuted instantiation: poll-loop.c:counter_poll_create_node_get Unexecuted instantiation: poll-loop.c:counter_poll_zero_timeout_get Unexecuted instantiation: random.c:seed_get Unexecuted instantiation: seq.c:counter_seq_change_get Unexecuted instantiation: timeval.c:counter_long_poll_interval_get Unexecuted instantiation: timeval.c:last_wakeup_get Unexecuted instantiation: timeval.c:last_seq_get Unexecuted instantiation: unixctl.c:counter_unixctl_received_get Unexecuted instantiation: unixctl.c:counter_unixctl_replied_get Unexecuted instantiation: netdev-linux.c:counter_netdev_set_policing_get Unexecuted instantiation: netdev-linux.c:counter_netdev_arp_lookup_get Unexecuted instantiation: netdev-linux.c:counter_netdev_get_ifindex_get Unexecuted instantiation: netdev-linux.c:counter_netdev_get_hwaddr_get Unexecuted instantiation: netdev-linux.c:counter_netdev_set_hwaddr_get Unexecuted instantiation: netdev-linux.c:counter_netdev_get_ethtool_get Unexecuted instantiation: netdev-linux.c:counter_netdev_set_ethtool_get Unexecuted instantiation: netdev-linux.c:counter_netdev_linux_invalid_l4_csum_get Unexecuted instantiation: netdev-linux.c:counter_netdev_linux_unknown_l4_csum_get Unexecuted instantiation: netlink-socket.c:counter_netlink_overflow_get Unexecuted instantiation: netlink-socket.c:counter_netlink_received_get Unexecuted instantiation: netlink-socket.c:counter_netlink_recv_jumbo_get Unexecuted instantiation: netlink-socket.c:counter_netlink_sent_get Unexecuted instantiation: route-table.c:counter_route_table_dump_get Unexecuted instantiation: tc.c:counter_tc_netlink_malformed_reply_get Unexecuted instantiation: ccmap.c:counter_ccmap_expand_get Unexecuted instantiation: ccmap.c:counter_ccmap_shrink_get Unexecuted instantiation: cmap.c:counter_cmap_expand_get Unexecuted instantiation: cmap.c:counter_cmap_shrink_get Unexecuted instantiation: dpif.c:counter_dpif_destroy_get Unexecuted instantiation: dpif.c:counter_dpif_execute_get Unexecuted instantiation: dpif.c:counter_dpif_execute_error_get Unexecuted instantiation: dpif.c:counter_dpif_execute_with_help_get Unexecuted instantiation: dpif.c:counter_dpif_flow_del_get Unexecuted instantiation: dpif.c:counter_dpif_flow_del_error_get Unexecuted instantiation: dpif.c:counter_dpif_flow_flush_get Unexecuted instantiation: dpif.c:counter_dpif_flow_get_get Unexecuted instantiation: dpif.c:counter_dpif_flow_get_error_get Unexecuted instantiation: dpif.c:counter_dpif_flow_put_get Unexecuted instantiation: dpif.c:counter_dpif_flow_put_error_get Unexecuted instantiation: dpif.c:counter_dpif_meter_del_get Unexecuted instantiation: dpif.c:counter_dpif_meter_get_get Unexecuted instantiation: dpif.c:counter_dpif_meter_set_get Unexecuted instantiation: dpif.c:counter_dpif_port_add_get Unexecuted instantiation: dpif.c:counter_dpif_port_del_get Unexecuted instantiation: dpif.c:counter_dpif_purge_get hmap.c:counter_hmap_pathological_get Line | Count | Source | 248 | 6 | { \ | 249 | 6 | return NAME##_get_unsafe(); \ | 250 | 6 | } |
hmap.c:counter_hmap_expand_get Line | Count | Source | 248 | 28 | { \ | 249 | 28 | return NAME##_get_unsafe(); \ | 250 | 28 | } |
Unexecuted instantiation: hmap.c:counter_hmap_shrink_get Unexecuted instantiation: hmap.c:counter_hmap_reserve_get Unexecuted instantiation: jsonrpc.c:counter_jsonrpc_recv_incomplete_get Unexecuted instantiation: odp-execute.c:counter_datapath_drop_sample_error_get Unexecuted instantiation: odp-execute.c:counter_datapath_drop_nsh_decap_error_get Unexecuted instantiation: odp-execute.c:counter_drop_action_of_pipeline_get Unexecuted instantiation: odp-execute.c:counter_drop_action_bridge_not_found_get Unexecuted instantiation: odp-execute.c:counter_drop_action_recursion_too_deep_get Unexecuted instantiation: odp-execute.c:counter_drop_action_too_many_resubmit_get Unexecuted instantiation: odp-execute.c:counter_drop_action_stack_too_deep_get Unexecuted instantiation: odp-execute.c:counter_drop_action_no_recirculation_context_get Unexecuted instantiation: odp-execute.c:counter_drop_action_recirculation_conflict_get Unexecuted instantiation: odp-execute.c:counter_drop_action_too_many_mpls_labels_get Unexecuted instantiation: odp-execute.c:counter_drop_action_invalid_tunnel_metadata_get Unexecuted instantiation: odp-execute.c:counter_drop_action_unsupported_packet_type_get Unexecuted instantiation: odp-execute.c:counter_drop_action_congestion_get Unexecuted instantiation: odp-execute.c:counter_drop_action_forwarding_disabled_get Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_routing_failed_get Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_output_no_ethernet_get Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_neigh_cache_miss_get Unexecuted instantiation: odp-execute.c:counter_drop_action_tunnel_header_build_failed_get Unexecuted instantiation: stream.c:counter_pstream_open_get Unexecuted instantiation: stream.c:counter_stream_open_get Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l3csum_checked_get Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l3csum_err_get Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l4csum_checked_get Unexecuted instantiation: netdev-native-tnl.c:counter_native_tnl_l4csum_err_get Unexecuted instantiation: netlink-notifier.c:counter_nln_changed_get Unexecuted instantiation: conntrack.c:counter_conntrack_full_get Unexecuted instantiation: conntrack.c:counter_conntrack_l3csum_checked_get Unexecuted instantiation: conntrack.c:counter_conntrack_l3csum_err_get Unexecuted instantiation: conntrack.c:counter_conntrack_l4csum_checked_get Unexecuted instantiation: conntrack.c:counter_conntrack_l4csum_err_get Unexecuted instantiation: conntrack.c:counter_conntrack_lookup_natted_miss_get Unexecuted instantiation: conntrack.c:counter_conntrack_zone_full_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_meter_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_upcall_error_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_lock_error_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_userspace_action_error_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_tunnel_push_error_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_tunnel_pop_error_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_recirc_error_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_invalid_port_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_invalid_bond_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_invalid_tnl_port_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_rx_invalid_packet_get Unexecuted instantiation: dpif-netdev.c:recirc_depth_get Unexecuted instantiation: hindex.c:counter_hindex_pathological_get Unexecuted instantiation: hindex.c:counter_hindex_expand_get Unexecuted instantiation: hindex.c:counter_hindex_shrink_get Unexecuted instantiation: hindex.c:counter_hindex_reserve_get Unexecuted instantiation: ipf.c:counter_ipf_stuck_frag_list_expired_get Unexecuted instantiation: ipf.c:counter_ipf_stuck_frag_list_purged_get Unexecuted instantiation: ipf.c:counter_ipf_l3csum_checked_get Unexecuted instantiation: ipf.c:counter_ipf_l3csum_err_get Unexecuted instantiation: lockfile.c:counter_lockfile_lock_get Unexecuted instantiation: lockfile.c:counter_lockfile_error_get Unexecuted instantiation: lockfile.c:counter_lockfile_unlock_get Unexecuted instantiation: process.c:counter_process_start_get Unexecuted instantiation: conntrack-tcp.c:counter_conntrack_tcp_seq_chk_bypass_get Unexecuted instantiation: conntrack-tcp.c:counter_conntrack_tcp_seq_chk_failed_get Unexecuted instantiation: conntrack-tcp.c:counter_conntrack_invalid_tcp_flags_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_uncommitted_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_unchanged_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_incomplete_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_aborted_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_success_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_try_again_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_not_locked_get Unexecuted instantiation: ovsdb-idl.c:counter_txn_error_get |
251 | | #define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ |
252 | | typedef TYPE NAME##_type; \ |
253 | | extern thread_local NAME##_type NAME##_var; \ |
254 | | \ |
255 | | static inline NAME##_type * \ |
256 | | NAME##_get_unsafe(void) \ |
257 | 0 | { \ |
258 | 0 | return (NAME##_type *)&NAME##_var; \ |
259 | 0 | } \ Unexecuted instantiation: util.c:ovsthread_id_get_unsafe Unexecuted instantiation: vlog.c:ovsthread_id_get_unsafe Unexecuted instantiation: async-append-aio.c:ovsthread_id_get_unsafe Unexecuted instantiation: dirs.c:ovsthread_id_get_unsafe Unexecuted instantiation: coverage.c:ovsthread_id_get_unsafe Unexecuted instantiation: dp-packet.c:ovsthread_id_get_unsafe Unexecuted instantiation: dp-packet.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: flow.c:ovsthread_id_get_unsafe Unexecuted instantiation: flow.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: meta-flow.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: ofp-msgs.c:ovsthread_id_get_unsafe Unexecuted instantiation: ovs-rcu.c:ovsthread_id_get_unsafe Unexecuted instantiation: ovs-router.c:ovsthread_id_get_unsafe Unexecuted instantiation: ovs-thread.c:ovsthread_id_get_unsafe Unexecuted instantiation: packets.c:ovsthread_id_get_unsafe Unexecuted instantiation: poll-loop.c:ovsthread_id_get_unsafe Unexecuted instantiation: random.c:ovsthread_id_get_unsafe Unexecuted instantiation: seq.c:ovsthread_id_get_unsafe Unexecuted instantiation: socket-util.c:ovsthread_id_get_unsafe Unexecuted instantiation: timeval.c:ovsthread_id_get_unsafe Unexecuted instantiation: tnl-ports.c:ovsthread_id_get_unsafe Unexecuted instantiation: unixctl.c:ovsthread_id_get_unsafe Unexecuted instantiation: userspace-tso.c:ovsthread_id_get_unsafe Unexecuted instantiation: uuid.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-linux.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-linux.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: netdev-offload-tc.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-offload-tc.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: netlink-socket.c:ovsthread_id_get_unsafe Unexecuted instantiation: route-table.c:ovsthread_id_get_unsafe Unexecuted instantiation: tc.c:ovsthread_id_get_unsafe Unexecuted instantiation: ccmap.c:ovsthread_id_get_unsafe Unexecuted instantiation: cmap.c:ovsthread_id_get_unsafe Unexecuted instantiation: command-line.c:ovsthread_id_get_unsafe Unexecuted instantiation: connectivity.c:ovsthread_id_get_unsafe Unexecuted instantiation: dp-packet-gso.c:ovsthread_id_get_unsafe Unexecuted instantiation: dp-packet-gso.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: dpif.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: fatal-signal.c:ovsthread_id_get_unsafe Unexecuted instantiation: guarded-list.c:ovsthread_id_get_unsafe Unexecuted instantiation: hmap.c:ovsthread_id_get_unsafe Unexecuted instantiation: jsonrpc.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-offload.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: netdev-offload.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-vport.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-vport.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: netlink.c:ovsthread_id_get_unsafe Unexecuted instantiation: odp-execute.c:ovsthread_id_get_unsafe Unexecuted instantiation: odp-util.c:ovsthread_id_get_unsafe Unexecuted instantiation: stream.c:ovsthread_id_get_unsafe Unexecuted instantiation: tnl-neigh-cache.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-native-tnl.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-native-tnl.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: daemon-unix.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netlink.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netlink.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: dpif-netlink-rtnl.c:ovsthread_id_get_unsafe Unexecuted instantiation: netlink-conntrack.c:ovsthread_id_get_unsafe Unexecuted instantiation: netlink-notifier.c:ovsthread_id_get_unsafe Unexecuted instantiation: stream-ssl.c:ovsthread_id_get_unsafe Unexecuted instantiation: conntrack.c:ovsthread_id_get_unsafe Unexecuted instantiation: daemon.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netdev.c:netdev_offload_thread_id_get_unsafe Unexecuted instantiation: dpif-netdev.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netdev-private-extract.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netdev-perf.c:ovsthread_id_get_unsafe Unexecuted instantiation: fat-rwlock.c:ovsthread_id_get_unsafe Unexecuted instantiation: hindex.c:ovsthread_id_get_unsafe Unexecuted instantiation: ipf.c:ovsthread_id_get_unsafe Unexecuted instantiation: lockfile.c:ovsthread_id_get_unsafe Unexecuted instantiation: ovs-numa.c:ovsthread_id_get_unsafe Unexecuted instantiation: process.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpdk-stub.c:ovsthread_id_get_unsafe Unexecuted instantiation: vswitch-idl.c:ovsthread_id_get_unsafe Unexecuted instantiation: conntrack-icmp.c:ovsthread_id_get_unsafe Unexecuted instantiation: conntrack-tcp.c:ovsthread_id_get_unsafe Unexecuted instantiation: conntrack-tp.c:ovsthread_id_get_unsafe Unexecuted instantiation: conntrack-other.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netdev-extract-study.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netdev-lookup-generic.c:ovsthread_id_get_unsafe Unexecuted instantiation: ovsdb-data.c:ovsthread_id_get_unsafe Unexecuted instantiation: ovsdb-idl.c:ovsthread_id_get_unsafe Unexecuted instantiation: ovsdb-types.c:ovsthread_id_get_unsafe |
260 | | \ |
261 | | static inline NAME##_type * \ |
262 | | NAME##_get(void) \ |
263 | 0 | { \ |
264 | 0 | return NAME##_get_unsafe(); \ |
265 | 0 | } Unexecuted instantiation: util.c:ovsthread_id_get Unexecuted instantiation: vlog.c:ovsthread_id_get Unexecuted instantiation: async-append-aio.c:ovsthread_id_get Unexecuted instantiation: dirs.c:ovsthread_id_get Unexecuted instantiation: coverage.c:ovsthread_id_get Unexecuted instantiation: dp-packet.c:ovsthread_id_get Unexecuted instantiation: dp-packet.c:netdev_offload_thread_id_get Unexecuted instantiation: flow.c:ovsthread_id_get Unexecuted instantiation: flow.c:netdev_offload_thread_id_get Unexecuted instantiation: meta-flow.c:ovsthread_id_get Unexecuted instantiation: netdev.c:ovsthread_id_get Unexecuted instantiation: netdev.c:netdev_offload_thread_id_get Unexecuted instantiation: ofp-msgs.c:ovsthread_id_get Unexecuted instantiation: ovs-rcu.c:ovsthread_id_get Unexecuted instantiation: ovs-router.c:ovsthread_id_get Unexecuted instantiation: ovs-thread.c:ovsthread_id_get Unexecuted instantiation: packets.c:ovsthread_id_get Unexecuted instantiation: poll-loop.c:ovsthread_id_get Unexecuted instantiation: random.c:ovsthread_id_get Unexecuted instantiation: seq.c:ovsthread_id_get Unexecuted instantiation: socket-util.c:ovsthread_id_get Unexecuted instantiation: timeval.c:ovsthread_id_get Unexecuted instantiation: tnl-ports.c:ovsthread_id_get Unexecuted instantiation: unixctl.c:ovsthread_id_get Unexecuted instantiation: userspace-tso.c:ovsthread_id_get Unexecuted instantiation: uuid.c:ovsthread_id_get Unexecuted instantiation: netdev-linux.c:ovsthread_id_get Unexecuted instantiation: netdev-linux.c:netdev_offload_thread_id_get Unexecuted instantiation: netdev-offload-tc.c:ovsthread_id_get Unexecuted instantiation: netdev-offload-tc.c:netdev_offload_thread_id_get Unexecuted instantiation: netlink-socket.c:ovsthread_id_get Unexecuted instantiation: route-table.c:ovsthread_id_get Unexecuted instantiation: tc.c:ovsthread_id_get Unexecuted instantiation: ccmap.c:ovsthread_id_get Unexecuted instantiation: cmap.c:ovsthread_id_get Unexecuted instantiation: command-line.c:ovsthread_id_get Unexecuted instantiation: connectivity.c:ovsthread_id_get Unexecuted instantiation: dp-packet-gso.c:ovsthread_id_get Unexecuted instantiation: dp-packet-gso.c:netdev_offload_thread_id_get Unexecuted instantiation: dpif.c:ovsthread_id_get Unexecuted instantiation: dpif.c:netdev_offload_thread_id_get Unexecuted instantiation: fatal-signal.c:ovsthread_id_get Unexecuted instantiation: guarded-list.c:ovsthread_id_get Unexecuted instantiation: hmap.c:ovsthread_id_get Unexecuted instantiation: jsonrpc.c:ovsthread_id_get Unexecuted instantiation: netdev-offload.c:netdev_offload_thread_id_get Unexecuted instantiation: netdev-offload.c:ovsthread_id_get Unexecuted instantiation: netdev-vport.c:ovsthread_id_get Unexecuted instantiation: netdev-vport.c:netdev_offload_thread_id_get Unexecuted instantiation: netlink.c:ovsthread_id_get Unexecuted instantiation: odp-execute.c:ovsthread_id_get Unexecuted instantiation: odp-util.c:ovsthread_id_get Unexecuted instantiation: stream.c:ovsthread_id_get Unexecuted instantiation: tnl-neigh-cache.c:ovsthread_id_get Unexecuted instantiation: netdev-native-tnl.c:ovsthread_id_get Unexecuted instantiation: netdev-native-tnl.c:netdev_offload_thread_id_get Unexecuted instantiation: daemon-unix.c:ovsthread_id_get Unexecuted instantiation: dpif-netlink.c:ovsthread_id_get Unexecuted instantiation: dpif-netlink.c:netdev_offload_thread_id_get Unexecuted instantiation: dpif-netlink-rtnl.c:ovsthread_id_get Unexecuted instantiation: netlink-conntrack.c:ovsthread_id_get Unexecuted instantiation: netlink-notifier.c:ovsthread_id_get Unexecuted instantiation: stream-ssl.c:ovsthread_id_get Unexecuted instantiation: conntrack.c:ovsthread_id_get Unexecuted instantiation: daemon.c:ovsthread_id_get Unexecuted instantiation: dpif-netdev.c:netdev_offload_thread_id_get Unexecuted instantiation: dpif-netdev.c:ovsthread_id_get Unexecuted instantiation: dpif-netdev-private-extract.c:ovsthread_id_get Unexecuted instantiation: dpif-netdev-perf.c:ovsthread_id_get Unexecuted instantiation: fat-rwlock.c:ovsthread_id_get Unexecuted instantiation: hindex.c:ovsthread_id_get Unexecuted instantiation: ipf.c:ovsthread_id_get Unexecuted instantiation: lockfile.c:ovsthread_id_get Unexecuted instantiation: ovs-numa.c:ovsthread_id_get Unexecuted instantiation: process.c:ovsthread_id_get Unexecuted instantiation: dpdk-stub.c:ovsthread_id_get Unexecuted instantiation: vswitch-idl.c:ovsthread_id_get Unexecuted instantiation: conntrack-icmp.c:ovsthread_id_get Unexecuted instantiation: conntrack-tcp.c:ovsthread_id_get Unexecuted instantiation: conntrack-tp.c:ovsthread_id_get Unexecuted instantiation: conntrack-other.c:ovsthread_id_get Unexecuted instantiation: dpif-netdev-extract-study.c:ovsthread_id_get Unexecuted instantiation: dpif-netdev-lookup-generic.c:ovsthread_id_get Unexecuted instantiation: ovsdb-data.c:ovsthread_id_get Unexecuted instantiation: ovsdb-idl.c:ovsthread_id_get Unexecuted instantiation: ovsdb-types.c:ovsthread_id_get |
266 | | #define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ |
267 | | thread_local NAME##_type NAME##_var = __VA_ARGS__; |
268 | | #else /* no C implementation support for thread-local storage */ |
269 | | #define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ |
270 | | typedef TYPE NAME##_type; \ |
271 | | static pthread_key_t NAME##_key; \ |
272 | | \ |
273 | | static NAME##_type * \ |
274 | | NAME##_get_unsafe(void) \ |
275 | | { \ |
276 | | return pthread_getspecific(NAME##_key); \ |
277 | | } \ |
278 | | \ |
279 | | static void \ |
280 | | NAME##_once_init(void) \ |
281 | | { \ |
282 | | if (pthread_key_create(&NAME##_key, free)) { \ |
283 | | abort(); \ |
284 | | } \ |
285 | | } \ |
286 | | \ |
287 | | static NAME##_type * \ |
288 | | NAME##_get(void) \ |
289 | | { \ |
290 | | static pthread_once_t once = PTHREAD_ONCE_INIT; \ |
291 | | NAME##_type *value; \ |
292 | | \ |
293 | | pthread_once(&once, NAME##_once_init); \ |
294 | | value = NAME##_get_unsafe(); \ |
295 | | if (!value) { \ |
296 | | static const NAME##_type initial_value = __VA_ARGS__; \ |
297 | | \ |
298 | | value = xmalloc__(sizeof *value); \ |
299 | | *value = initial_value; \ |
300 | | xpthread_setspecific(NAME##_key, value); \ |
301 | | } \ |
302 | | return value; \ |
303 | | } |
304 | | #define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ |
305 | | typedef TYPE NAME##_type; \ |
306 | | static pthread_key_t NAME##_key; \ |
307 | | \ |
308 | | static inline NAME##_type * \ |
309 | | NAME##_get_unsafe(void) \ |
310 | | { \ |
311 | | return (NAME##_type *)pthread_getspecific(NAME##_key); \ |
312 | | } \ |
313 | | \ |
314 | | NAME##_type *NAME##_get(void); |
315 | | #define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ |
316 | | static void \ |
317 | | NAME##_once_init(void) \ |
318 | | { \ |
319 | | if (pthread_key_create(&NAME##_key, free)) { \ |
320 | | abort(); \ |
321 | | } \ |
322 | | } \ |
323 | | \ |
324 | | NAME##_type * \ |
325 | | NAME##_get(void) \ |
326 | | { \ |
327 | | static pthread_once_t once = PTHREAD_ONCE_INIT; \ |
328 | | NAME##_type *value; \ |
329 | | \ |
330 | | pthread_once(&once, NAME##_once_init); \ |
331 | | value = NAME##_get_unsafe(); \ |
332 | | if (!value) { \ |
333 | | static const NAME##_type initial_value = __VA_ARGS__; \ |
334 | | \ |
335 | | value = xmalloc__(sizeof *value); \ |
336 | | *value = initial_value; \ |
337 | | xpthread_setspecific(NAME##_key, value); \ |
338 | | } \ |
339 | | return value; \ |
340 | | } |
341 | | #endif |
342 | | |
343 | | /* DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME). |
344 | | * |
345 | | * This is a simple wrapper around POSIX per-thread data primitives. It |
346 | | * defines per-thread variable NAME with the given TYPE, which must be a |
347 | | * pointer type. In each thread, the per-thread variable is initialized to |
348 | | * NULL. When a thread terminates, the variable is freed with free(). |
349 | | * |
350 | | * The public interface to the variable is: |
351 | | * |
352 | | * TYPE NAME_get(void) |
353 | | * TYPE NAME_get_unsafe(void) |
354 | | * |
355 | | * Returns the value of per-thread variable NAME in this thread. |
356 | | * |
357 | | * Use NAME_get() in a context where this might be the first use of the |
358 | | * per-thread variable in the program. Use NAME_get_unsafe(), which |
359 | | * avoids a conditional test and is thus slightly faster, in a context |
360 | | * where one knows that NAME_get() has already been called previously. |
361 | | * |
362 | | * TYPE NAME_set(TYPE new_value) |
363 | | * TYPE NAME_set_unsafe(TYPE new_value) |
364 | | * |
365 | | * Sets the value of per-thread variable NAME to 'new_value' in this |
366 | | * thread, and returns its previous value. |
367 | | * |
368 | | * Use NAME_set() in a context where this might be the first use of the |
369 | | * per-thread variable in the program. Use NAME_set_unsafe(), which |
370 | | * avoids a conditional test and is thus slightly faster, in a context |
371 | | * where one knows that NAME_set() has already been called previously. |
372 | | */ |
373 | | #define DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME) \ |
374 | | static pthread_key_t NAME##_key; \ |
375 | | \ |
376 | | static void \ |
377 | | NAME##_once_init(void) \ |
378 | 0 | { \ |
379 | 0 | if (pthread_key_create(&NAME##_key, free)) { \ |
380 | 0 | abort(); \ |
381 | 0 | } \ |
382 | 0 | } \ Unexecuted instantiation: util.c:subprogram_name_once_init Unexecuted instantiation: timeval.c:cpu_tracker_var_once_init Unexecuted instantiation: dpif-netdev-extract-study.c:study_stats_once_init Unexecuted instantiation: dpif-netdev-lookup-generic.c:block_array_once_init |
383 | | \ |
384 | | static void \ |
385 | | NAME##_init(void) \ |
386 | 0 | { \ |
387 | 0 | static pthread_once_t once = PTHREAD_ONCE_INIT; \ |
388 | 0 | pthread_once(&once, NAME##_once_init); \ |
389 | 0 | } \ Unexecuted instantiation: util.c:subprogram_name_init Unexecuted instantiation: timeval.c:cpu_tracker_var_init Unexecuted instantiation: dpif-netdev-extract-study.c:study_stats_init Unexecuted instantiation: dpif-netdev-lookup-generic.c:block_array_init |
390 | | \ |
391 | | static TYPE \ |
392 | | NAME##_get_unsafe(void) \ |
393 | 0 | { \ |
394 | 0 | return pthread_getspecific(NAME##_key); \ |
395 | 0 | } \ Unexecuted instantiation: util.c:subprogram_name_get_unsafe Unexecuted instantiation: timeval.c:cpu_tracker_var_get_unsafe Unexecuted instantiation: dpif-netdev-extract-study.c:study_stats_get_unsafe Unexecuted instantiation: dpif-netdev-lookup-generic.c:block_array_get_unsafe |
396 | | \ |
397 | | static OVS_UNUSED TYPE \ |
398 | | NAME##_get(void) \ |
399 | 0 | { \ |
400 | 0 | NAME##_init(); \ |
401 | 0 | return NAME##_get_unsafe(); \ |
402 | 0 | } \ Unexecuted instantiation: util.c:subprogram_name_get Unexecuted instantiation: timeval.c:cpu_tracker_var_get Unexecuted instantiation: dpif-netdev-extract-study.c:study_stats_get Unexecuted instantiation: dpif-netdev-lookup-generic.c:block_array_get |
403 | | \ |
404 | | static TYPE \ |
405 | | NAME##_set_unsafe(TYPE value) \ |
406 | 0 | { \ |
407 | 0 | TYPE old_value = NAME##_get_unsafe(); \ |
408 | 0 | xpthread_setspecific(NAME##_key, value); \ |
409 | 0 | return old_value; \ |
410 | 0 | } \ Unexecuted instantiation: util.c:subprogram_name_set_unsafe Unexecuted instantiation: timeval.c:cpu_tracker_var_set_unsafe Unexecuted instantiation: dpif-netdev-extract-study.c:study_stats_set_unsafe Unexecuted instantiation: dpif-netdev-lookup-generic.c:block_array_set_unsafe |
411 | | \ |
412 | | static OVS_UNUSED TYPE \ |
413 | | NAME##_set(TYPE value) \ |
414 | 0 | { \ |
415 | 0 | NAME##_init(); \ |
416 | 0 | return NAME##_set_unsafe(value); \ |
417 | 0 | } Unexecuted instantiation: util.c:subprogram_name_set Unexecuted instantiation: timeval.c:cpu_tracker_var_set Unexecuted instantiation: dpif-netdev-extract-study.c:study_stats_set Unexecuted instantiation: dpif-netdev-lookup-generic.c:block_array_set |
418 | | |
419 | | /* Dynamically allocated thread-specific data with lots of slots. |
420 | | * |
421 | | * pthread_key_t can provide as few as 128 pieces of thread-specific data (even |
422 | | * glibc is limited to 1,024). Thus, one must be careful to allocate only a |
423 | | * few keys globally. One cannot, for example, allocate a key for every |
424 | | * instance of a data structure if there might be an arbitrary number of those |
425 | | * data structures. |
426 | | * |
427 | | * This API is similar to the pthread one (simply search and replace pthread_ |
428 | | * by ovsthread_) but it a much larger limit that can be raised if necessary |
429 | | * (by recompiling). Thus, one may more freely use this form of |
430 | | * thread-specific data. |
431 | | * |
432 | | * ovsthread_key_t also differs from pthread_key_t in the following ways: |
433 | | * |
434 | | * - Destructors must not access thread-specific data (via ovsthread_key). |
435 | | * |
436 | | * - The pthread_key_t API allows concurrently exiting threads to start |
437 | | * executing the destructor after pthread_key_delete() returns. The |
438 | | * ovsthread_key_t API guarantees that, when ovsthread_key_delete() |
439 | | * returns, all destructors have returned and no new ones will start |
440 | | * execution. |
441 | | */ |
442 | | typedef struct ovsthread_key *ovsthread_key_t; |
443 | | |
444 | | void ovsthread_key_create(ovsthread_key_t *, void (*destructor)(void *)); |
445 | | void ovsthread_key_delete(ovsthread_key_t); |
446 | | |
447 | | void ovsthread_setspecific(ovsthread_key_t, const void *); |
448 | | void *ovsthread_getspecific(ovsthread_key_t); |
449 | | |
450 | | /* Thread ID. |
451 | | * |
452 | | * pthread_t isn't so nice for some purposes. Its size and representation are |
453 | | * implementation dependent, which means that there is no way to hash it. |
454 | | * This thread ID avoids the problem. |
455 | | */ |
456 | | |
457 | 0 | #define OVSTHREAD_ID_UNSET UINT_MAX |
458 | | DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, ovsthread_id); |
459 | | |
460 | | /* Initializes the unique per thread identifier */ |
461 | | unsigned int ovsthread_id_init(void); |
462 | | |
463 | | /* Returns a per-thread identifier unique within the lifetime of the |
464 | | * process. */ |
465 | | static inline unsigned int |
466 | | ovsthread_id_self(void) |
467 | 0 | { |
468 | 0 | unsigned int id = *ovsthread_id_get(); |
469 | |
|
470 | 0 | if (OVS_UNLIKELY(id == OVSTHREAD_ID_UNSET)) { |
471 | 0 | id = ovsthread_id_init(); |
472 | 0 | } |
473 | |
|
474 | 0 | return id; |
475 | 0 | } Unexecuted instantiation: util.c:ovsthread_id_self Unexecuted instantiation: vlog.c:ovsthread_id_self Unexecuted instantiation: async-append-aio.c:ovsthread_id_self Unexecuted instantiation: dirs.c:ovsthread_id_self Unexecuted instantiation: coverage.c:ovsthread_id_self Unexecuted instantiation: dp-packet.c:ovsthread_id_self Unexecuted instantiation: flow.c:ovsthread_id_self Unexecuted instantiation: meta-flow.c:ovsthread_id_self Unexecuted instantiation: netdev.c:ovsthread_id_self Unexecuted instantiation: ofp-msgs.c:ovsthread_id_self Unexecuted instantiation: ovs-rcu.c:ovsthread_id_self Unexecuted instantiation: ovs-router.c:ovsthread_id_self Unexecuted instantiation: ovs-thread.c:ovsthread_id_self Unexecuted instantiation: packets.c:ovsthread_id_self Unexecuted instantiation: poll-loop.c:ovsthread_id_self Unexecuted instantiation: random.c:ovsthread_id_self Unexecuted instantiation: seq.c:ovsthread_id_self Unexecuted instantiation: socket-util.c:ovsthread_id_self Unexecuted instantiation: timeval.c:ovsthread_id_self Unexecuted instantiation: tnl-ports.c:ovsthread_id_self Unexecuted instantiation: unixctl.c:ovsthread_id_self Unexecuted instantiation: userspace-tso.c:ovsthread_id_self Unexecuted instantiation: uuid.c:ovsthread_id_self Unexecuted instantiation: netdev-linux.c:ovsthread_id_self Unexecuted instantiation: netdev-offload-tc.c:ovsthread_id_self Unexecuted instantiation: netlink-socket.c:ovsthread_id_self Unexecuted instantiation: route-table.c:ovsthread_id_self Unexecuted instantiation: tc.c:ovsthread_id_self Unexecuted instantiation: ccmap.c:ovsthread_id_self Unexecuted instantiation: cmap.c:ovsthread_id_self Unexecuted instantiation: command-line.c:ovsthread_id_self Unexecuted instantiation: connectivity.c:ovsthread_id_self Unexecuted instantiation: dp-packet-gso.c:ovsthread_id_self Unexecuted instantiation: dpif.c:ovsthread_id_self Unexecuted instantiation: fatal-signal.c:ovsthread_id_self Unexecuted instantiation: guarded-list.c:ovsthread_id_self Unexecuted instantiation: hmap.c:ovsthread_id_self Unexecuted instantiation: jsonrpc.c:ovsthread_id_self Unexecuted instantiation: netdev-offload.c:ovsthread_id_self Unexecuted instantiation: netdev-vport.c:ovsthread_id_self Unexecuted instantiation: netlink.c:ovsthread_id_self Unexecuted instantiation: odp-execute.c:ovsthread_id_self Unexecuted instantiation: odp-util.c:ovsthread_id_self Unexecuted instantiation: stream.c:ovsthread_id_self Unexecuted instantiation: tnl-neigh-cache.c:ovsthread_id_self Unexecuted instantiation: netdev-native-tnl.c:ovsthread_id_self Unexecuted instantiation: daemon-unix.c:ovsthread_id_self Unexecuted instantiation: dpif-netlink.c:ovsthread_id_self Unexecuted instantiation: dpif-netlink-rtnl.c:ovsthread_id_self Unexecuted instantiation: netlink-conntrack.c:ovsthread_id_self Unexecuted instantiation: netlink-notifier.c:ovsthread_id_self Unexecuted instantiation: stream-ssl.c:ovsthread_id_self Unexecuted instantiation: conntrack.c:ovsthread_id_self Unexecuted instantiation: daemon.c:ovsthread_id_self Unexecuted instantiation: dpif-netdev.c:ovsthread_id_self Unexecuted instantiation: dpif-netdev-private-extract.c:ovsthread_id_self Unexecuted instantiation: dpif-netdev-perf.c:ovsthread_id_self Unexecuted instantiation: fat-rwlock.c:ovsthread_id_self Unexecuted instantiation: hindex.c:ovsthread_id_self Unexecuted instantiation: ipf.c:ovsthread_id_self Unexecuted instantiation: lockfile.c:ovsthread_id_self Unexecuted instantiation: ovs-numa.c:ovsthread_id_self Unexecuted instantiation: process.c:ovsthread_id_self Unexecuted instantiation: dpdk-stub.c:ovsthread_id_self Unexecuted instantiation: vswitch-idl.c:ovsthread_id_self Unexecuted instantiation: conntrack-icmp.c:ovsthread_id_self Unexecuted instantiation: conntrack-tcp.c:ovsthread_id_self Unexecuted instantiation: conntrack-tp.c:ovsthread_id_self Unexecuted instantiation: conntrack-other.c:ovsthread_id_self Unexecuted instantiation: dpif-netdev-extract-study.c:ovsthread_id_self Unexecuted instantiation: dpif-netdev-lookup-generic.c:ovsthread_id_self Unexecuted instantiation: ovsdb-data.c:ovsthread_id_self Unexecuted instantiation: ovsdb-idl.c:ovsthread_id_self Unexecuted instantiation: ovsdb-types.c:ovsthread_id_self |
476 | | |
477 | | /* Simulated global counter. |
478 | | * |
479 | | * Incrementing such a counter is meant to be cheaper than incrementing a |
480 | | * global counter protected by a lock. It is probably more expensive than |
481 | | * incrementing a truly thread-local variable, but such a variable has no |
482 | | * straightforward way to get the sum. |
483 | | * |
484 | | * |
485 | | * Thread-safety |
486 | | * ============= |
487 | | * |
488 | | * Fully thread-safe. */ |
489 | | |
490 | | struct ovsthread_stats { |
491 | | struct ovs_mutex mutex; |
492 | | void *volatile buckets[16]; |
493 | | }; |
494 | | |
495 | | void ovsthread_stats_init(struct ovsthread_stats *); |
496 | | void ovsthread_stats_destroy(struct ovsthread_stats *); |
497 | | |
498 | | void *ovsthread_stats_bucket_get(struct ovsthread_stats *, |
499 | | void *(*new_bucket)(void)); |
500 | | |
501 | | #define OVSTHREAD_STATS_FOR_EACH_BUCKET(BUCKET, IDX, STATS) \ |
502 | | for ((IDX) = ovs_thread_stats_next_bucket(STATS, 0); \ |
503 | | ((IDX) < ARRAY_SIZE((STATS)->buckets) \ |
504 | | ? ((BUCKET) = (STATS)->buckets[IDX], true) \ |
505 | | : false); \ |
506 | | (IDX) = ovs_thread_stats_next_bucket(STATS, (IDX) + 1)) |
507 | | size_t ovs_thread_stats_next_bucket(const struct ovsthread_stats *, size_t); |
508 | | |
509 | | bool single_threaded(void); |
510 | | |
511 | | void assert_single_threaded_at(const char *where); |
512 | 0 | #define assert_single_threaded() assert_single_threaded_at(OVS_SOURCE_LOCATOR) |
513 | | |
514 | | #ifndef _WIN32 |
515 | | pid_t xfork_at(const char *where); |
516 | 0 | #define xfork() xfork_at(OVS_SOURCE_LOCATOR) |
517 | | #endif |
518 | | |
519 | | void forbid_forking(const char *reason); |
520 | | bool may_fork(void); |
521 | | |
522 | | /* Useful functions related to threading. */ |
523 | | |
524 | | int count_cpu_cores(void); |
525 | | int count_total_cores(void); |
526 | | bool thread_is_pmd(void); |
527 | | |
528 | | #endif /* ovs-thread.h */ |