/src/openvswitch/lib/ovs-thread.h
Line | Count | Source |
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(struct ovs_rwlock *); |
73 | | void ovs_rwlock_destroy(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 | | 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 | | void xpthread_sigmask(int, const sigset_t *, sigset_t *); |
121 | | |
122 | | pthread_t ovs_thread_create(const char *name, void *(*)(void *), void *); |
123 | | void xpthread_join(pthread_t, void **); |
124 | | |
125 | | /* Per-thread data. |
126 | | * |
127 | | * |
128 | | * Standard Forms |
129 | | * ============== |
130 | | * |
131 | | * Multiple forms of standard per-thread data exist, each with its own pluses |
132 | | * and minuses. In general, if one of these forms is appropriate, then it's a |
133 | | * good idea to use it: |
134 | | * |
135 | | * - POSIX per-thread data via pthread_key_t is portable to any pthreads |
136 | | * implementation, and allows a destructor function to be defined. It |
137 | | * only (directly) supports per-thread pointers, which are always |
138 | | * initialized to NULL. It requires once-only allocation of a |
139 | | * pthread_key_t value. It is relatively slow. Typically few |
140 | | * "pthread_key_t"s are available (POSIX requires only at least 128, |
141 | | * glibc supplies only 1024). |
142 | | * |
143 | | * - The thread_local feature newly defined in C11 <threads.h> works with |
144 | | * any data type and initializer, and it is fast. thread_local does not |
145 | | * require once-only initialization like pthread_key_t. C11 does not |
146 | | * define what happens if one attempts to access a thread_local object |
147 | | * from a thread other than the one to which that object belongs. There |
148 | | * is no provision to call a user-specified destructor when a thread |
149 | | * ends. Typical implementations allow for an arbitrary amount of |
150 | | * thread_local storage, but statically allocated only. |
151 | | * |
152 | | * - The __thread keyword is a GCC extension similar to thread_local but |
153 | | * with a longer history. __thread is not portable to every GCC version |
154 | | * or environment. __thread does not restrict the use of a thread-local |
155 | | * object outside its own thread. |
156 | | * |
157 | | * Here's a handy summary: |
158 | | * |
159 | | * pthread_key_t thread_local __thread |
160 | | * ------------- ------------ ------------- |
161 | | * portability high low medium |
162 | | * speed low high high |
163 | | * supports destructors? yes no no |
164 | | * needs key allocation? yes no no |
165 | | * arbitrary initializer? no yes yes |
166 | | * cross-thread access? yes no yes |
167 | | * amount available? few arbitrary arbitrary |
168 | | * dynamically allocated? yes no no |
169 | | * |
170 | | * |
171 | | * Extensions |
172 | | * ========== |
173 | | * |
174 | | * OVS provides some extensions and wrappers: |
175 | | * |
176 | | * - In a situation where the performance of thread_local or __thread is |
177 | | * desirable, but portability is required, DEFINE_STATIC_PER_THREAD_DATA |
178 | | * and DECLARE_EXTERN_PER_THREAD_DATA/DEFINE_EXTERN_PER_THREAD_DATA may |
179 | | * be appropriate (see below). |
180 | | * |
181 | | * - DEFINE_PER_THREAD_MALLOCED_DATA can be convenient for simple |
182 | | * per-thread malloc()'d buffers. |
183 | | * |
184 | | * - struct ovs_tsd provides an alternative to pthread_key_t that isn't |
185 | | * limited to a small number of keys. |
186 | | */ |
187 | | |
188 | | /* For static data, use this macro in a source file: |
189 | | * |
190 | | * DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, INITIALIZER). |
191 | | * |
192 | | * For global data, "declare" the data in the header and "define" it in |
193 | | * the source file, with: |
194 | | * |
195 | | * DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME). |
196 | | * DEFINE_EXTERN_PER_THREAD_DATA(NAME, INITIALIZER). |
197 | | * |
198 | | * One should prefer to use POSIX per-thread data, via pthread_key_t, when its |
199 | | * performance is acceptable, because of its portability (see the table above). |
200 | | * This macro is an alternatives that takes advantage of thread_local (and |
201 | | * __thread), for its performance, when it is available, and falls back to |
202 | | * POSIX per-thread data otherwise. |
203 | | * |
204 | | * Defines per-thread variable NAME with the given TYPE, initialized to |
205 | | * INITIALIZER (which must be valid as an initializer for a variable with |
206 | | * static lifetime). |
207 | | * |
208 | | * The public interface to the variable is: |
209 | | * |
210 | | * TYPE *NAME_get(void) |
211 | | * TYPE *NAME_get_unsafe(void) |
212 | | * |
213 | | * Returns the address of this thread's instance of NAME. |
214 | | * |
215 | | * Use NAME_get() in a context where this might be the first use of the |
216 | | * per-thread variable in the program. Use NAME_get_unsafe(), which |
217 | | * avoids a conditional test and is thus slightly faster, in a context |
218 | | * where one knows that NAME_get() has already been called previously. |
219 | | * |
220 | | * There is no "NAME_set()" (or "NAME_set_unsafe()") function. To set the |
221 | | * value of the per-thread variable, dereference the pointer returned by |
222 | | * TYPE_get() or TYPE_get_unsafe(), e.g. *TYPE_get() = 0. |
223 | | */ |
224 | | #if HAVE_THREAD_LOCAL || HAVE___THREAD |
225 | | |
226 | | #if HAVE_THREAD_LOCAL |
227 | | #include <threads.h> |
228 | | #elif HAVE___THREAD |
229 | | #define thread_local __thread |
230 | | #else |
231 | | #error |
232 | | #endif |
233 | | |
234 | | #define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ |
235 | | typedef TYPE NAME##_type; \ |
236 | | \ |
237 | | static NAME##_type * \ |
238 | | NAME##_get_unsafe(void) \ |
239 | 30.5k | { \ |
240 | 30.5k | static thread_local NAME##_type var = __VA_ARGS__; \ |
241 | 30.5k | return &var; \ |
242 | 30.5k | } \ Unexecuted instantiation: dp-packet.c:counter_dp_packet_batch_grow_get_unsafe flow.c:counter_flow_extract_get_unsafe Line | Count | Source | 239 | 4.35k | { \ | 240 | 4.35k | static thread_local NAME##_type var = __VA_ARGS__; \ | 241 | 4.35k | return &var; \ | 242 | 4.35k | } \ |
flow.c:counter_miniflow_extract_ipv4_pkt_len_error_get_unsafe Line | Count | Source | 239 | 192 | { \ | 240 | 192 | static thread_local NAME##_type var = __VA_ARGS__; \ | 241 | 192 | return &var; \ | 242 | 192 | } \ |
flow.c:counter_miniflow_extract_ipv4_pkt_too_short_get_unsafe Line | Count | Source | 239 | 42 | { \ | 240 | 42 | static thread_local NAME##_type var = __VA_ARGS__; \ | 241 | 42 | return &var; \ | 242 | 42 | } \ |
flow.c:counter_miniflow_extract_ipv6_pkt_len_error_get_unsafe Line | Count | Source | 239 | 117 | { \ | 240 | 117 | static thread_local NAME##_type var = __VA_ARGS__; \ | 241 | 117 | return &var; \ | 242 | 117 | } \ |
flow.c:counter_miniflow_extract_ipv6_pkt_too_short_get_unsafe Line | Count | Source | 239 | 42 | { \ | 240 | 42 | static thread_local NAME##_type var = __VA_ARGS__; \ | 241 | 42 | return &var; \ | 242 | 42 | } \ |
Unexecuted instantiation: flow.c:counter_miniflow_malloc_get_unsafe 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: 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 util.c:counter_util_xalloc_get_unsafe Line | Count | Source | 239 | 25.7k | { \ | 240 | 25.7k | static thread_local NAME##_type var = __VA_ARGS__; \ | 241 | 25.7k | return &var; \ | 242 | 25.7k | } \ |
Unexecuted instantiation: util.c:strerror_buffer_get_unsafe Unexecuted instantiation: vlog.c:msg_num_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: coverage.c:coverage_clear_time_get_unsafe Unexecuted instantiation: dp-packet-gso.c:counter_dp_packet_gso_get_unsafe Unexecuted instantiation: dp-packet-gso.c:counter_dp_packet_partial_gso_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 Unexecuted instantiation: hmap.c:counter_hmap_pathological_get_unsafe Unexecuted instantiation: hmap.c:counter_hmap_expand_get_unsafe 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:counter_datapath_drop_hw_post_process_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_hw_post_process_consumed_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_dpif_netdev_output_grow_queues_get_unsafe Unexecuted instantiation: dpif-netdev.c:counter_dpif_netdev_recirc_big_batch_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 |
243 | | \ |
244 | | static NAME##_type * \ |
245 | | NAME##_get(void) \ |
246 | 30.5k | { \ |
247 | 30.5k | return NAME##_get_unsafe(); \ |
248 | 30.5k | } Unexecuted instantiation: dp-packet.c:counter_dp_packet_batch_grow_get flow.c:counter_flow_extract_get Line | Count | Source | 246 | 4.35k | { \ | 247 | 4.35k | return NAME##_get_unsafe(); \ | 248 | 4.35k | } |
flow.c:counter_miniflow_extract_ipv4_pkt_len_error_get Line | Count | Source | 246 | 192 | { \ | 247 | 192 | return NAME##_get_unsafe(); \ | 248 | 192 | } |
flow.c:counter_miniflow_extract_ipv4_pkt_too_short_get Line | Count | Source | 246 | 42 | { \ | 247 | 42 | return NAME##_get_unsafe(); \ | 248 | 42 | } |
flow.c:counter_miniflow_extract_ipv6_pkt_len_error_get Line | Count | Source | 246 | 117 | { \ | 247 | 117 | return NAME##_get_unsafe(); \ | 248 | 117 | } |
flow.c:counter_miniflow_extract_ipv6_pkt_too_short_get Line | Count | Source | 246 | 42 | { \ | 247 | 42 | return NAME##_get_unsafe(); \ | 248 | 42 | } |
Unexecuted instantiation: flow.c:counter_miniflow_malloc_get 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: 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 util.c:counter_util_xalloc_get Line | Count | Source | 246 | 25.7k | { \ | 247 | 25.7k | return NAME##_get_unsafe(); \ | 248 | 25.7k | } |
Unexecuted instantiation: util.c:strerror_buffer_get Unexecuted instantiation: vlog.c:msg_num_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: coverage.c:coverage_clear_time_get Unexecuted instantiation: dp-packet-gso.c:counter_dp_packet_gso_get Unexecuted instantiation: dp-packet-gso.c:counter_dp_packet_partial_gso_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 Unexecuted instantiation: hmap.c:counter_hmap_pathological_get Unexecuted instantiation: hmap.c:counter_hmap_expand_get 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:counter_datapath_drop_hw_post_process_get Unexecuted instantiation: dpif-netdev.c:counter_datapath_drop_hw_post_process_consumed_get Unexecuted instantiation: dpif-netdev.c:counter_dpif_netdev_output_grow_queues_get Unexecuted instantiation: dpif-netdev.c:counter_dpif_netdev_recirc_big_batch_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 |
249 | | #define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ |
250 | | typedef TYPE NAME##_type; \ |
251 | | extern thread_local NAME##_type NAME##_var; \ |
252 | | \ |
253 | | static inline NAME##_type * \ |
254 | | NAME##_get_unsafe(void) \ |
255 | 0 | { \ |
256 | 0 | return (NAME##_type *)&NAME##_var; \ |
257 | 0 | } \ Unexecuted instantiation: dp-packet.c:ovsthread_id_get_unsafe Unexecuted instantiation: flow.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev.c:ovsthread_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: util.c:ovsthread_id_get_unsafe Unexecuted instantiation: uuid.c:ovsthread_id_get_unsafe Unexecuted instantiation: vlog.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-linux.c:ovsthread_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: async-append-aio.c:ovsthread_id_get_unsafe Unexecuted instantiation: dirs.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: coverage.c:ovsthread_id_get_unsafe Unexecuted instantiation: dp-packet-gso.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-offload.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-offload-dummy.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif.c:ovsthread_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: meta-flow.c:ovsthread_id_get_unsafe Unexecuted instantiation: netdev-vport.c:ovsthread_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: daemon-unix.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netlink.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netlink-rtnl.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-offload-tc.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-offload-tc-netdev.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: ct-dpif.c:ovsthread_id_get_unsafe Unexecuted instantiation: daemon.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpctl.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netdev.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-dpcls.c:ovsthread_id_get_unsafe Unexecuted instantiation: dpif-netdev-perf.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 |
258 | | \ |
259 | | static inline NAME##_type * \ |
260 | | NAME##_get(void) \ |
261 | 0 | { \ |
262 | 0 | return NAME##_get_unsafe(); \ |
263 | 0 | } Unexecuted instantiation: dp-packet.c:ovsthread_id_get Unexecuted instantiation: flow.c:ovsthread_id_get Unexecuted instantiation: netdev.c:ovsthread_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: util.c:ovsthread_id_get Unexecuted instantiation: uuid.c:ovsthread_id_get Unexecuted instantiation: vlog.c:ovsthread_id_get Unexecuted instantiation: netdev-linux.c:ovsthread_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: async-append-aio.c:ovsthread_id_get Unexecuted instantiation: dirs.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: coverage.c:ovsthread_id_get Unexecuted instantiation: dp-packet-gso.c:ovsthread_id_get Unexecuted instantiation: dpif-offload.c:ovsthread_id_get Unexecuted instantiation: dpif-offload-dummy.c:ovsthread_id_get Unexecuted instantiation: dpif.c:ovsthread_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: meta-flow.c:ovsthread_id_get Unexecuted instantiation: netdev-vport.c:ovsthread_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: daemon-unix.c:ovsthread_id_get Unexecuted instantiation: dpif-netlink.c:ovsthread_id_get Unexecuted instantiation: dpif-netlink-rtnl.c:ovsthread_id_get Unexecuted instantiation: dpif-offload-tc.c:ovsthread_id_get Unexecuted instantiation: dpif-offload-tc-netdev.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: ct-dpif.c:ovsthread_id_get Unexecuted instantiation: daemon.c:ovsthread_id_get Unexecuted instantiation: dpctl.c:ovsthread_id_get Unexecuted instantiation: dpif-netdev.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-dpcls.c:ovsthread_id_get Unexecuted instantiation: dpif-netdev-perf.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 |
264 | | #define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ |
265 | | thread_local NAME##_type NAME##_var = __VA_ARGS__; |
266 | | #else /* no C implementation support for thread-local storage */ |
267 | | #define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ |
268 | | typedef TYPE NAME##_type; \ |
269 | | static pthread_key_t NAME##_key; \ |
270 | | \ |
271 | | static NAME##_type * \ |
272 | | NAME##_get_unsafe(void) \ |
273 | | { \ |
274 | | return pthread_getspecific(NAME##_key); \ |
275 | | } \ |
276 | | \ |
277 | | static void \ |
278 | | NAME##_once_init(void) \ |
279 | | { \ |
280 | | if (pthread_key_create(&NAME##_key, free)) { \ |
281 | | abort(); \ |
282 | | } \ |
283 | | } \ |
284 | | \ |
285 | | static NAME##_type * \ |
286 | | NAME##_get(void) \ |
287 | | { \ |
288 | | static pthread_once_t once = PTHREAD_ONCE_INIT; \ |
289 | | NAME##_type *value; \ |
290 | | \ |
291 | | pthread_once(&once, NAME##_once_init); \ |
292 | | value = NAME##_get_unsafe(); \ |
293 | | if (!value) { \ |
294 | | static const NAME##_type initial_value = __VA_ARGS__; \ |
295 | | \ |
296 | | value = xmalloc__(sizeof *value); \ |
297 | | *value = initial_value; \ |
298 | | xpthread_setspecific(NAME##_key, value); \ |
299 | | } \ |
300 | | return value; \ |
301 | | } |
302 | | #define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ |
303 | | typedef TYPE NAME##_type; \ |
304 | | static pthread_key_t NAME##_key; \ |
305 | | \ |
306 | | static inline NAME##_type * \ |
307 | | NAME##_get_unsafe(void) \ |
308 | | { \ |
309 | | return (NAME##_type *)pthread_getspecific(NAME##_key); \ |
310 | | } \ |
311 | | \ |
312 | | NAME##_type *NAME##_get(void); |
313 | | #define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ |
314 | | static void \ |
315 | | NAME##_once_init(void) \ |
316 | | { \ |
317 | | if (pthread_key_create(&NAME##_key, free)) { \ |
318 | | abort(); \ |
319 | | } \ |
320 | | } \ |
321 | | \ |
322 | | NAME##_type * \ |
323 | | NAME##_get(void) \ |
324 | | { \ |
325 | | static pthread_once_t once = PTHREAD_ONCE_INIT; \ |
326 | | NAME##_type *value; \ |
327 | | \ |
328 | | pthread_once(&once, NAME##_once_init); \ |
329 | | value = NAME##_get_unsafe(); \ |
330 | | if (!value) { \ |
331 | | static const NAME##_type initial_value = __VA_ARGS__; \ |
332 | | \ |
333 | | value = xmalloc__(sizeof *value); \ |
334 | | *value = initial_value; \ |
335 | | xpthread_setspecific(NAME##_key, value); \ |
336 | | } \ |
337 | | return value; \ |
338 | | } |
339 | | #endif |
340 | | |
341 | | /* DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME). |
342 | | * |
343 | | * This is a simple wrapper around POSIX per-thread data primitives. It |
344 | | * defines per-thread variable NAME with the given TYPE, which must be a |
345 | | * pointer type. In each thread, the per-thread variable is initialized to |
346 | | * NULL. When a thread terminates, the variable is freed with free(). |
347 | | * |
348 | | * The public interface to the variable is: |
349 | | * |
350 | | * TYPE NAME_get(void) |
351 | | * TYPE NAME_get_unsafe(void) |
352 | | * |
353 | | * Returns the value of per-thread variable NAME in this thread. |
354 | | * |
355 | | * Use NAME_get() in a context where this might be the first use of the |
356 | | * per-thread variable in the program. Use NAME_get_unsafe(), which |
357 | | * avoids a conditional test and is thus slightly faster, in a context |
358 | | * where one knows that NAME_get() has already been called previously. |
359 | | * |
360 | | * TYPE NAME_set(TYPE new_value) |
361 | | * TYPE NAME_set_unsafe(TYPE new_value) |
362 | | * |
363 | | * Sets the value of per-thread variable NAME to 'new_value' in this |
364 | | * thread, and returns its previous value. |
365 | | * |
366 | | * Use NAME_set() in a context where this might be the first use of the |
367 | | * per-thread variable in the program. Use NAME_set_unsafe(), which |
368 | | * avoids a conditional test and is thus slightly faster, in a context |
369 | | * where one knows that NAME_set() has already been called previously. |
370 | | */ |
371 | | #define DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME) \ |
372 | | static pthread_key_t NAME##_key; \ |
373 | | \ |
374 | | static void \ |
375 | | NAME##_once_init(void) \ |
376 | 0 | { \ |
377 | 0 | if (pthread_key_create(&NAME##_key, free)) { \ |
378 | 0 | abort(); \ |
379 | 0 | } \ |
380 | 0 | } \ Unexecuted instantiation: timeval.c:cpu_tracker_var_once_init Unexecuted instantiation: util.c:subprogram_name_once_init Unexecuted instantiation: dpif-netdev-dpcls.c:block_array_once_init |
381 | | \ |
382 | | static void \ |
383 | | NAME##_init(void) \ |
384 | 0 | { \ |
385 | 0 | static pthread_once_t once = PTHREAD_ONCE_INIT; \ |
386 | 0 | pthread_once(&once, NAME##_once_init); \ |
387 | 0 | } \ |
388 | | \ |
389 | | static TYPE \ |
390 | | NAME##_get_unsafe(void) \ |
391 | 0 | { \ |
392 | 0 | return pthread_getspecific(NAME##_key); \ |
393 | 0 | } \ Unexecuted instantiation: timeval.c:cpu_tracker_var_get_unsafe Unexecuted instantiation: util.c:subprogram_name_get_unsafe Unexecuted instantiation: dpif-netdev-dpcls.c:block_array_get_unsafe |
394 | | \ |
395 | | static OVS_UNUSED TYPE \ |
396 | | NAME##_get(void) \ |
397 | 0 | { \ |
398 | 0 | NAME##_init(); \ |
399 | 0 | return NAME##_get_unsafe(); \ |
400 | 0 | } \ Unexecuted instantiation: timeval.c:cpu_tracker_var_get Unexecuted instantiation: util.c:subprogram_name_get Unexecuted instantiation: dpif-netdev-dpcls.c:block_array_get |
401 | | \ |
402 | | static TYPE \ |
403 | | NAME##_set_unsafe(TYPE value) \ |
404 | 0 | { \ |
405 | 0 | TYPE old_value = NAME##_get_unsafe(); \ |
406 | 0 | xpthread_setspecific(NAME##_key, value); \ |
407 | 0 | return old_value; \ |
408 | 0 | } \ Unexecuted instantiation: timeval.c:cpu_tracker_var_set_unsafe Unexecuted instantiation: util.c:subprogram_name_set_unsafe Unexecuted instantiation: dpif-netdev-dpcls.c:block_array_set_unsafe |
409 | | \ |
410 | | static OVS_UNUSED TYPE \ |
411 | | NAME##_set(TYPE value) \ |
412 | 0 | { \ |
413 | 0 | NAME##_init(); \ |
414 | 0 | return NAME##_set_unsafe(value); \ |
415 | 0 | } Unexecuted instantiation: timeval.c:cpu_tracker_var_set Unexecuted instantiation: util.c:subprogram_name_set Unexecuted instantiation: dpif-netdev-dpcls.c:block_array_set |
416 | | |
417 | | /* Dynamically allocated thread-specific data with lots of slots. |
418 | | * |
419 | | * pthread_key_t can provide as few as 128 pieces of thread-specific data (even |
420 | | * glibc is limited to 1,024). Thus, one must be careful to allocate only a |
421 | | * few keys globally. One cannot, for example, allocate a key for every |
422 | | * instance of a data structure if there might be an arbitrary number of those |
423 | | * data structures. |
424 | | * |
425 | | * This API is similar to the pthread one (simply search and replace pthread_ |
426 | | * by ovsthread_) but it a much larger limit that can be raised if necessary |
427 | | * (by recompiling). Thus, one may more freely use this form of |
428 | | * thread-specific data. |
429 | | * |
430 | | * ovsthread_key_t also differs from pthread_key_t in the following ways: |
431 | | * |
432 | | * - Destructors must not access thread-specific data (via ovsthread_key). |
433 | | * |
434 | | * - The pthread_key_t API allows concurrently exiting threads to start |
435 | | * executing the destructor after pthread_key_delete() returns. The |
436 | | * ovsthread_key_t API guarantees that, when ovsthread_key_delete() |
437 | | * returns, all destructors have returned and no new ones will start |
438 | | * execution. |
439 | | */ |
440 | | typedef struct ovsthread_key *ovsthread_key_t; |
441 | | |
442 | | void ovsthread_key_create(ovsthread_key_t *, void (*destructor)(void *)); |
443 | | void ovsthread_key_delete(ovsthread_key_t); |
444 | | |
445 | | void ovsthread_setspecific(ovsthread_key_t, const void *); |
446 | | void *ovsthread_getspecific(ovsthread_key_t); |
447 | | |
448 | | /* Thread ID. |
449 | | * |
450 | | * pthread_t isn't so nice for some purposes. Its size and representation are |
451 | | * implementation dependent, which means that there is no way to hash it. |
452 | | * This thread ID avoids the problem. |
453 | | */ |
454 | | |
455 | 0 | #define OVSTHREAD_ID_UNSET UINT_MAX |
456 | | DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, ovsthread_id); |
457 | | |
458 | | /* Initializes the unique per thread identifier */ |
459 | | unsigned int ovsthread_id_init(void); |
460 | | |
461 | | /* Returns a per-thread identifier unique within the lifetime of the |
462 | | * process. */ |
463 | | static inline unsigned int |
464 | | ovsthread_id_self(void) |
465 | 0 | { |
466 | 0 | unsigned int id = *ovsthread_id_get(); |
467 | |
|
468 | 0 | if (OVS_UNLIKELY(id == OVSTHREAD_ID_UNSET)) { |
469 | 0 | id = ovsthread_id_init(); |
470 | 0 | } |
471 | |
|
472 | 0 | return id; |
473 | 0 | } Unexecuted instantiation: dp-packet.c:ovsthread_id_self Unexecuted instantiation: 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: util.c:ovsthread_id_self Unexecuted instantiation: uuid.c:ovsthread_id_self Unexecuted instantiation: vlog.c:ovsthread_id_self Unexecuted instantiation: netdev-linux.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: async-append-aio.c:ovsthread_id_self Unexecuted instantiation: dirs.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: coverage.c:ovsthread_id_self Unexecuted instantiation: dp-packet-gso.c:ovsthread_id_self Unexecuted instantiation: dpif-offload.c:ovsthread_id_self Unexecuted instantiation: dpif-offload-dummy.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: meta-flow.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: dpif-offload-tc.c:ovsthread_id_self Unexecuted instantiation: dpif-offload-tc-netdev.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: ct-dpif.c:ovsthread_id_self Unexecuted instantiation: daemon.c:ovsthread_id_self Unexecuted instantiation: dpctl.c:ovsthread_id_self Unexecuted instantiation: dpif-netdev.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-dpcls.c:ovsthread_id_self Unexecuted instantiation: dpif-netdev-perf.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 |
474 | | |
475 | | /* Simulated global counter. |
476 | | * |
477 | | * Incrementing such a counter is meant to be cheaper than incrementing a |
478 | | * global counter protected by a lock. It is probably more expensive than |
479 | | * incrementing a truly thread-local variable, but such a variable has no |
480 | | * straightforward way to get the sum. |
481 | | * |
482 | | * |
483 | | * Thread-safety |
484 | | * ============= |
485 | | * |
486 | | * Fully thread-safe. */ |
487 | | |
488 | | struct ovsthread_stats { |
489 | | struct ovs_mutex mutex; |
490 | | void *volatile buckets[16]; |
491 | | }; |
492 | | |
493 | | void ovsthread_stats_init(struct ovsthread_stats *); |
494 | | void ovsthread_stats_destroy(struct ovsthread_stats *); |
495 | | |
496 | | void *ovsthread_stats_bucket_get(struct ovsthread_stats *, |
497 | | void *(*new_bucket)(void)); |
498 | | |
499 | | #define OVSTHREAD_STATS_FOR_EACH_BUCKET(BUCKET, IDX, STATS) \ |
500 | | for ((IDX) = ovs_thread_stats_next_bucket(STATS, 0); \ |
501 | | ((IDX) < ARRAY_SIZE((STATS)->buckets) \ |
502 | | ? ((BUCKET) = (STATS)->buckets[IDX], true) \ |
503 | | : false); \ |
504 | | (IDX) = ovs_thread_stats_next_bucket(STATS, (IDX) + 1)) |
505 | | size_t ovs_thread_stats_next_bucket(const struct ovsthread_stats *, size_t); |
506 | | |
507 | | bool single_threaded(void); |
508 | | |
509 | | void assert_single_threaded_at(const char *where); |
510 | 0 | #define assert_single_threaded() assert_single_threaded_at(OVS_SOURCE_LOCATOR) |
511 | | |
512 | | pid_t xfork_at(const char *where); |
513 | 0 | #define xfork() xfork_at(OVS_SOURCE_LOCATOR) |
514 | | |
515 | | void forbid_forking(const char *reason); |
516 | | bool may_fork(void); |
517 | | |
518 | | /* Useful functions related to threading. */ |
519 | | |
520 | | int count_cpu_cores(void); |
521 | | int count_total_cores(void); |
522 | | bool thread_is_pmd(void); |
523 | | |
524 | | #endif /* ovs-thread.h */ |