Initial commit of vpp code.
[vpp.git] / vlib / vlib / threads.h
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef included_vlib_threads_h
16 #define included_vlib_threads_h
17
18 #include <vlib/main.h>
19
20 vlib_main_t **vlib_mains;
21
22 static inline uword
23 vlib_get_cpu_number_inline (void)
24 {
25   void * sp;
26   uword n;
27   u32 len;
28
29   /* Get any old stack address. */
30   sp = &sp;
31
32   n = ((uword)sp - (uword)vlib_thread_stacks[0]) >> 20;
33
34   /* "processes" have their own stacks, and they always run in thread 0 */
35   n = n >= len ? 0 : n;
36
37   return n;
38 }
39
40 void
41 vlib_set_thread_name (char *name);
42
43 /* arg is actually a vlib__thread_t * */
44 typedef void (vlib_thread_function_t) (void * arg);
45
46 typedef struct vlib_thread_registration_ {
47   /* constructor generated list of thread registrations */
48   struct vlib_thread_registration_ * next;
49
50   /* config parameters */
51   char * name;
52   char * short_name;
53   vlib_thread_function_t * function;
54   uword mheap_size;
55   int fixed_count;
56   u32 count;
57   int no_data_structure_clone;
58   /* All threads of this type run on pthreads */
59   int use_pthreads;
60   u32 first_index;
61   uword * coremask;
62 } vlib_thread_registration_t;
63
64 #define VLIB_MAX_CPUS 32
65
66 /* 
67  * Objects passed around by "index" are cache-line aligned.
68  * We can stick the owner CPU into the low 6 bits.
69  */
70 #if VLIB_MAX_CPUS > 64
71 #error VLIB_MAX_CPUS must be <= 64
72 #endif
73
74 #define VLIB_CPU_MASK (VLIB_MAX_CPUS - 1) /* 0x3f, max */
75 #define VLIB_OFFSET_MASK (~VLIB_CPU_MASK)
76
77 #define VLIB_LOG2_THREAD_STACK_SIZE (20)
78 #define VLIB_THREAD_STACK_SIZE (1<<VLIB_LOG2_THREAD_STACK_SIZE)
79
80 typedef enum {
81     VLIB_FRAME_QUEUE_ELT_DISPATCH_FRAME,
82 } vlib_frame_queue_msg_type_t;
83
84 typedef struct {
85   volatile u32 valid;
86   u32 msg_type;         
87   u32 n_vectors;
88   u32 last_n_vectors;
89
90   /* 256 * 4 = 1024 bytes, even mult of cache line size */
91   u32 buffer_index[VLIB_FRAME_SIZE];
92
93   /* Pad to a cache line boundary */
94   u8 pad[CLIB_CACHE_LINE_BYTES - 4 * sizeof(u32)];
95 } vlib_frame_queue_elt_t;
96
97 typedef struct {
98   /* First cache line */
99   volatile u32 *wait_at_barrier;
100   volatile u32 *workers_at_barrier;
101   u8 pad0[CLIB_CACHE_LINE_BYTES - (2 * sizeof (u32 *))];
102
103   /* Second Cache Line */
104   void *thread_mheap;
105   u8 * thread_stack;
106   void (*thread_function)(void *);
107   void * thread_function_arg;
108   i64 recursion_level; 
109   elog_track_t elog_track; 
110   u32 instance_id;
111   vlib_thread_registration_t *registration;
112   u8 *name;
113
114   long lwp;
115   int dpdk_lcore_id;
116 } vlib_worker_thread_t;
117
118 vlib_worker_thread_t *vlib_worker_threads;
119
120 typedef struct {
121   /* enqueue side */
122   volatile u64 tail;
123   u64 enqueues;
124   u64 enqueue_ticks;
125   u64 enqueue_vectors;
126   u32 enqueue_full_events;
127   u32 enqueue_efd_discards;
128   u8 pad2[CLIB_CACHE_LINE_BYTES 
129           - (2 * sizeof(u32))
130           - (4 * sizeof(u64))];
131
132   /* dequeue side */
133   volatile u64 head;
134   u64 dequeues;
135   u64 dequeue_ticks;
136   u64 dequeue_vectors;
137   u64 trace;
138   u64 vector_threshold;
139   u8 pad4[CLIB_CACHE_LINE_BYTES 
140           - (6 * sizeof(u64))];
141
142   /* dequeue hint to enqueue side */
143   volatile u64 head_hint;
144   u8 pad5 [CLIB_CACHE_LINE_BYTES - sizeof(u64)];
145
146   /* read-only, constant, shared */
147   vlib_frame_queue_elt_t *elts;
148   u32 nelts;
149 } vlib_frame_queue_t;
150
151 vlib_frame_queue_t **vlib_frame_queues;
152
153 /* Called early, in thread 0's context */
154 clib_error_t * vlib_thread_init (vlib_main_t * vm);
155
156 vlib_worker_thread_t * vlib_alloc_thread (vlib_main_t * vm);
157
158 int vlib_frame_queue_enqueue (vlib_main_t *vm, u32 node_runtime_index,
159                               u32 frame_queue_index, vlib_frame_t *frame,
160                               vlib_frame_queue_msg_type_t type);
161
162 int vlib_frame_queue_dequeue (int thread_id, 
163                               vlib_main_t *vm, 
164                               vlib_node_main_t *nm);
165
166 u64 dispatch_node (vlib_main_t * vm,
167                    vlib_node_runtime_t * node,
168                    vlib_node_type_t type,
169                    vlib_node_state_t dispatch_state,
170                    vlib_frame_t * frame,
171                    u64 last_time_stamp);
172
173 u64 dispatch_pending_node (vlib_main_t * vm,
174                            vlib_pending_frame_t * p,
175                            u64 last_time_stamp);
176
177 void vlib_worker_thread_node_runtime_update(void);
178
179 void vlib_create_worker_threads (vlib_main_t *vm, int n, 
180                                  void (*thread_function)(void *));
181
182 void vlib_worker_thread_init (vlib_worker_thread_t * w);
183
184 /* Check for a barrier sync request every 30ms */
185 #define BARRIER_SYNC_DELAY (0.030000)
186
187 #if CLIB_DEBUG > 0
188 /* long barrier timeout, for gdb... */
189 #define BARRIER_SYNC_TIMEOUT (600.1)
190 #else
191 #define BARRIER_SYNC_TIMEOUT (1.0)
192 #endif
193
194 void vlib_worker_thread_barrier_sync(vlib_main_t *vm);
195 void vlib_worker_thread_barrier_release(vlib_main_t *vm);
196
197 always_inline void vlib_smp_unsafe_warning (void)
198 {
199   if (CLIB_DEBUG > 0)
200     {
201       if (os_get_cpu_number())
202         fformat(stderr, "%s: SMP unsafe warning...\n", __FUNCTION__);
203     }
204 }
205
206 typedef enum {
207     VLIB_WORKER_THREAD_FORK_FIXUP_ILLEGAL = 0,
208     VLIB_WORKER_THREAD_FORK_FIXUP_NEW_SW_IF_INDEX,
209 } vlib_fork_fixup_t;
210
211 void vlib_worker_thread_fork_fixup (vlib_fork_fixup_t which);
212
213 static inline void vlib_worker_thread_barrier_check (void)
214 {
215     if (PREDICT_FALSE(*vlib_worker_threads->wait_at_barrier))
216     {
217         clib_smp_atomic_add (vlib_worker_threads->workers_at_barrier, 1);
218         while (*vlib_worker_threads->wait_at_barrier)
219             ;
220         clib_smp_atomic_add (vlib_worker_threads->workers_at_barrier, -1);
221     }
222 }
223
224 #define foreach_vlib_main(body)                                         \
225 do {                                                                    \
226     vlib_main_t ** __vlib_mains = 0, *this_vlib_main;                   \
227     int ii;                                                             \
228                                                                         \
229     if (vec_len (vlib_mains) == 0)                                      \
230         vec_add1 (__vlib_mains, &vlib_global_main);                     \
231     else                                                                \
232     {                                                                   \
233         for (ii = 0; ii < vec_len (vlib_mains); ii++)                   \
234         {                                                               \
235             this_vlib_main = vlib_mains[ii];                            \
236             if (this_vlib_main)                                         \
237                 vec_add1 (__vlib_mains, this_vlib_main);                \
238         }                                                               \
239     }                                                                   \
240                                                                         \
241     for (ii = 0; ii < vec_len (__vlib_mains); ii++)                     \
242     {                                                                   \
243         this_vlib_main = __vlib_mains[ii];                              \
244         /* body uses this_vlib_main... */                               \
245         (body);                                                         \
246     }                                                                   \
247     vec_free (__vlib_mains);                                            \
248 } while (0);
249
250
251 /* Early-Fast-Discard (EFD) */
252 #define VLIB_EFD_DISABLED                   0
253 #define VLIB_EFD_DISCARD_ENABLED            (1 << 0)
254 #define VLIB_EFD_MONITOR_ENABLED            (1 << 1)
255
256 #define VLIB_EFD_DEF_WORKER_HI_THRESH_PCT   90
257
258 /* EFD worker thread settings */
259 typedef struct vlib_efd_t {
260   u16 enabled;
261   u16 queue_hi_thresh;
262   u8  ip_prec_bitmap;
263   u8  mpls_exp_bitmap;
264   u8  vlan_cos_bitmap;
265   u8  pad;
266 } vlib_efd_t;
267
268 typedef struct {
269   /* Link list of registrations, built by constructors */
270   vlib_thread_registration_t * next;
271   
272   /* Vector of registrations, w/ non-data-structure clones at the top */
273   vlib_thread_registration_t ** registrations;
274
275   uword * thread_registrations_by_name;
276
277   vlib_worker_thread_t * worker_threads;
278
279   /* thread / cpu / io thread parameters */
280   u32 main_thread_is_io_node;
281
282   /* 
283    * Launch all threads as pthreads, 
284    * not eal_rte_launch (strict affinity) threads 
285    */
286   int use_pthreads;
287
288   /* Number of vlib_main / vnet_main clones */
289   u32 n_vlib_mains;
290
291   /* Number of thread stacks to create */
292   u32 n_thread_stacks;
293
294   /* Number of pthreads */
295   u32 n_pthreads;
296
297   /* Number of DPDK eal threads */
298   u32 n_eal_threads;
299
300   /* Number of cores to skip, must match the core mask */
301   u32 skip_cores;
302
303   /* Thread prefix name */
304   u8 *thread_prefix;
305
306   /* main thread lcore */
307   u8 main_lcore;
308
309   /* Bitmap of available CPU cores */
310   uword * cpu_core_bitmap;
311
312   /* Bitmap of available CPU sockets (NUMA nodes) */
313   uword * cpu_socket_bitmap;
314
315   vlib_efd_t efd;
316   
317 } vlib_thread_main_t;
318
319 vlib_thread_main_t vlib_thread_main;
320
321 #define VLIB_REGISTER_THREAD(x,...)                     \
322   __VA_ARGS__ vlib_thread_registration_t x;             \
323 static void __vlib_add_thread_registration_##x (void)   \
324   __attribute__((__constructor__)) ;                    \
325 static void __vlib_add_thread_registration_##x (void)   \
326 {                                                       \
327   vlib_thread_main_t * tm = &vlib_thread_main;          \
328   x.next = tm->next;                                    \
329   tm->next = &x;                                        \
330 }                                                       \
331 __VA_ARGS__ vlib_thread_registration_t x 
332
333 #endif /* included_vlib_threads_h */