* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define _GNU_SOURCE
+#include <sched.h>
+
#include <signal.h>
#include <math.h>
#include <vppinfra/format.h>
#include <vlib/vlib.h>
#include <vlib/threads.h>
-#include <vlib/unix/physmem.h>
-
#include <vlib/unix/cj.h>
+
#if DPDK==1
#include <rte_config.h>
#include <rte_common.h>
if (!tm->cpu_socket_bitmap)
tm->cpu_socket_bitmap = clib_bitmap_set(0, 0, 1);
+ /* pin main thread to main_lcore */
+#if DPDK==0
+ {
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(tm->main_lcore, &cpuset);
+ pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+ }
+#endif
+
/* as many threads as stacks... */
vec_validate_aligned (vlib_worker_threads, vec_len(vlib_thread_stacks)-1,
CLIB_CACHE_LINE_BYTES);
static int
vlib_launch_thread (void *fp, vlib_worker_thread_t *w, unsigned lcore_id)
{
- pthread_t dummy;
void *(*fp_arg)(void *) = fp;
#if DPDK==1
return -1;
else
#endif
- return pthread_create (&dummy, NULL /* attr */, fp_arg, (void *)w);
+ {
+ int ret;
+ pthread_t worker;
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(lcore_id, &cpuset);
+
+ ret = pthread_create (&worker, NULL /* attr */, fp_arg, (void *)w);
+ if(ret == 0)
+ return pthread_setaffinity_np(worker, sizeof(cpu_set_t), &cpuset);
+ else
+ return ret;
+ }
}
static clib_error_t * start_workers (vlib_main_t * vm)
vlib_node_runtime_t * rt;
u32 n_vlib_mains = tm->n_vlib_mains;
u32 worker_thread_index;
-
+ u8 * main_heap = clib_mem_get_per_cpu_heap();
+ mheap_t * main_heap_header = mheap_header (main_heap);
+
vec_reset_length (vlib_worker_threads);
/* Set up the main thread */
vec_add2_aligned (vlib_worker_threads, w, 1, CLIB_CACHE_LINE_BYTES);
- w->elog_track.name = "thread 0";
+ w->elog_track.name = "main thread";
elog_track_register (&vm->elog_main, &w->elog_track);
if (vec_len(tm->thread_prefix))
}
#endif
+ /*
+ * Truth of the matter: we always use at least two
+ * threads. So, make the main heap thread-safe
+ * and make the event log thread-safe.
+ */
+ main_heap_header->flags |= MHEAP_FLAG_THREAD_SAFE;
+ vm->elog_main.lock =
+ clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
+ CLIB_CACHE_LINE_BYTES);
+ vm->elog_main.lock[0] = 0;
+
if (n_vlib_mains > 1)
{
- u8 * heap = clib_mem_get_per_cpu_heap();
- mheap_t * h = mheap_header (heap);
-
- /* make the main heap thread-safe */
- h->flags |= MHEAP_FLAG_THREAD_SAFE;
-
- /* Make the event-log MP-safe */
- vm->elog_main.lock =
- clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES,
- CLIB_CACHE_LINE_BYTES);
-
- vm->elog_main.lock[0] = 0;
-
vec_validate (vlib_mains, tm->n_vlib_mains - 1);
_vec_len (vlib_mains) = 0;
vec_add1 (vlib_mains, vm);
for (k = 0; k < tr->count; k++)
{
vec_add2 (vlib_worker_threads, w, 1);
- /*
- * Share the main heap which is now thread-safe.
- *
- * To allocate separate heaps, code:
- * mheap_alloc (0 / * use VM * /, tr->mheap_size);
- */
- w->thread_mheap = heap;
+ if (tr->mheap_size)
+ w->thread_mheap = mheap_alloc (0 /* use VM */, tr->mheap_size);
+ else
+ w->thread_mheap = main_heap;
w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads];
w->thread_function = tr->function;
w->thread_function_arg = w;
w->instance_id = k;
w->registration = tr;
- w->elog_track.name = (char *) format (0, "thread %d", i+1);
+ w->elog_track.name =
+ (char *) format (0, "%s %d", tr->name, k+1);
vec_add1 (w->elog_track.name, 0);
elog_track_register (&vm->elog_main, &w->elog_track);
continue;
/* Allocate "to-worker-N" frame queue */
- fq = vlib_frame_queue_alloc (FRAME_QUEUE_NELTS);
+ if (tr->frame_queue_nelts) {
+ fq = vlib_frame_queue_alloc (tr->frame_queue_nelts);
+ } else {
+ fq = vlib_frame_queue_alloc (FRAME_QUEUE_NELTS);
+ }
+
vec_validate (vlib_frame_queues, worker_thread_index);
vlib_frame_queues[worker_thread_index] = fq;
oldheap = clib_mem_set_heap (w->thread_mheap);
vm_clone = clib_mem_alloc (sizeof (*vm_clone));
- memcpy (vm_clone, vlib_mains[0], sizeof (*vm_clone));
+ clib_memcpy (vm_clone, vlib_mains[0], sizeof (*vm_clone));
vm_clone->cpu_index = worker_thread_index;
vm_clone->heap_base = w->thread_mheap;
{
vlib_next_frame_t *nf = &nm_clone->next_frames[j];
u32 save_node_runtime_index;
+ u32 save_flags;
save_node_runtime_index = nf->node_runtime_index;
+ save_flags = nf->flags & VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
vlib_next_frame_init (nf);
nf->node_runtime_index = save_node_runtime_index;
+ nf->flags = save_flags;
}
/* fork the frame dispatch queue */
{
vlib_node_t *n;
n = clib_mem_alloc_no_fail (sizeof(*n));
- memcpy (n, nm->nodes[j], sizeof (*n));
+ clib_memcpy (n, nm->nodes[j], sizeof (*n));
/* none of the copied nodes have enqueue rights given out */
n->owner_node_index = VLIB_INVALID_NODE_INDEX;
memset (&n->stats_total, 0, sizeof (n->stats_total));
clib_mem_set_heap (oldheap);
vec_add1 (vlib_mains, vm_clone);
- unix_physmem_init (vm_clone, 0 /* physmem not required */);
-
vm_clone->error_main.counters =
vec_dup(vlib_mains[0]->error_main.counters);
vm_clone->error_main.counters_last_clear =
for (j = 0; j < tr->count; j++)
{
vec_add2 (vlib_worker_threads, w, 1);
- w->thread_mheap = mheap_alloc (0 /* use VM */, tr->mheap_size);
+ if (tr->mheap_size)
+ w->thread_mheap = mheap_alloc (0 /* use VM */, tr->mheap_size);
+ else
+ w->thread_mheap = main_heap;
w->thread_stack = vlib_thread_stacks[w - vlib_worker_threads];
w->thread_function = tr->function;
w->thread_function_arg = w;
w->instance_id = j;
- w->elog_track.name = (char *) format (0, "thread %d", i+1);
+ w->elog_track.name =
+ (char *) format (0, "%s %d", tr->name, j+1);
w->registration = tr;
vec_add1 (w->elog_track.name, 0);
elog_track_register (&vm->elog_main, &w->elog_track);
/* Re-clone error heap */
u64 * old_counters = vm_clone->error_main.counters;
u64 * old_counters_all_clear = vm_clone->error_main.counters_last_clear;
- memcpy (&vm_clone->error_main, &vm->error_main, sizeof (vm->error_main));
+ clib_memcpy (&vm_clone->error_main, &vm->error_main, sizeof (vm->error_main));
j = vec_len(vm->error_main.counters) - 1;
vec_validate_aligned(old_counters, j, CLIB_CACHE_LINE_BYTES);
vec_validate_aligned(old_counters_all_clear, j, CLIB_CACHE_LINE_BYTES);
{
vlib_next_frame_t *nf = &nm_clone->next_frames[j];
u32 save_node_runtime_index;
+ u32 save_flags;
save_node_runtime_index = nf->node_runtime_index;
+ save_flags = nf->flags & VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
vlib_next_frame_init (nf);
nf->node_runtime_index = save_node_runtime_index;
+ nf->flags = save_flags;
}
old_nodes_clone = nm_clone->nodes;
old_n_clone = old_nodes_clone[j];
new_n_clone = clib_mem_alloc_no_fail (sizeof(*new_n_clone));
- memcpy (new_n_clone, new_n, sizeof (*new_n));
+ clib_memcpy (new_n_clone, new_n, sizeof (*new_n));
/* none of the copied nodes have enqueue rights given out */
new_n_clone->owner_node_index = VLIB_INVALID_NODE_INDEX;
else
{
/* Copy stats if the old data is valid */
- memcpy (&new_n_clone->stats_total,
+ clib_memcpy (&new_n_clone->stats_total,
&old_n_clone->stats_total,
sizeof (new_n_clone->stats_total));
- memcpy (&new_n_clone->stats_last_clear,
+ clib_memcpy (&new_n_clone->stats_last_clear,
&old_n_clone->stats_last_clear,
sizeof (new_n_clone->stats_last_clear));
while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
{
- if (unformat (input, "main-thread-io"))
- tm->main_thread_is_io_node = 1;
- else if (unformat (input, "use-pthreads"))
+ if (unformat (input, "use-pthreads"))
tm->use_pthreads = 1;
else if (unformat (input, "thread-prefix %v", &tm->thread_prefix))
;
VLIB_EARLY_CONFIG_FUNCTION (cpu_config, "cpu");
-#if !defined (__x86_64__)
+#if !defined (__x86_64__) && !defined (__aarch64__) && !defined (__powerpc64__) && !defined(__arm__)
void __sync_fetch_and_add_8 (void)
{
fformat(stderr, "%s called\n", __FUNCTION__);
if (++vlib_worker_threads[0].recursion_level > 1)
return;
+ vlib_worker_threads[0].barrier_sync_count++;
+
ASSERT (os_get_cpu_number() == 0);
deadline = vlib_time_now (vm) + BARRIER_SYNC_TIMEOUT;
"ID", "Name", "Type", "LWP",
"lcore", "Core", "Socket", "State");
+#if !defined(__powerpc64__)
for (i = 0; i < vec_len(vlib_worker_threads); i++)
{
w = vlib_worker_threads + i;
w->registration ? w->registration->name : "",
w->lwp);
+#if DPDK==1
int lcore = w->dpdk_lcore_id;
if (lcore > -1)
{
line = format(line, "unknown");
}
}
-
+#endif
vlib_cli_output(vm, "%v", line);
vec_free(line);
}
+#endif
return 0;
}