X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fovs-thread.c;h=b0e10ee898789d64ed1c92c4e5fb9c03483e0bd0;hb=4be4d22c33f67c2154d4252746970ef1032c58a6;hp=1f346b93044a3ae55d9cd06cb94554e145e0c493;hpb=ca6ba70092b1528e12d3140d70232175a13c335d;p=cascardo%2Fovs.git diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index 1f346b930..b0e10ee89 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014 Nicira, Inc. + * Copyright (c) 2013, 2014, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,9 @@ #include #include #include "compiler.h" +#include "fatal-signal.h" #include "hash.h" +#include "list.h" #include "netdev-dpdk.h" #include "ovs-rcu.h" #include "poll-loop.h" @@ -38,7 +40,7 @@ * cut-and-paste. Since "sparse" is just a checker, not a compiler, it * doesn't matter that we don't define them. */ #else -#include "vlog.h" +#include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovs_thread); @@ -117,7 +119,7 @@ TRY_LOCK_FUNCTION(rwlock, trywrlock); l->where = WHERE; \ error = pthread_##TYPE##_##FUN(&l->lock); \ if (OVS_UNLIKELY(error)) { \ - ovs_abort(error, "pthread_%s_%sfailed", #TYPE, #FUN); \ + ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \ } \ } UNLOCK_FUNCTION(mutex, unlock, ""); @@ -330,14 +332,33 @@ ovsthread_wrapper(void *aux_) /* The order of the following calls is important, because * ovsrcu_quiesce_end() saves a copy of the thread name. */ - set_subprogram_name("%s%u", aux.name, id); + char *subprogram_name = xasprintf("%s%u", aux.name, id); + set_subprogram_name(subprogram_name); + free(subprogram_name); ovsrcu_quiesce_end(); - thread_set_nonpmd(); - return aux.start(aux.arg); } +static void +set_min_stack_size(pthread_attr_t *attr, size_t min_stacksize) +{ + size_t stacksize; + int error; + + error = pthread_attr_getstacksize(attr, &stacksize); + if (error) { + ovs_abort(error, "pthread_attr_getstacksize failed"); + } + + if (stacksize < min_stacksize) { + error = pthread_attr_setstacksize(attr, min_stacksize); + if (error) { + ovs_abort(error, "pthread_attr_setstacksize failed"); + } + } +} + /* Starts a thread that calls 'start(arg)'. Sets the thread's name to 'name' * (suffixed by its ovsthread_id()). Returns the new thread's pthread_t. */ pthread_t @@ -356,10 +377,20 @@ ovs_thread_create(const char *name, void *(*start)(void *), void *arg) aux->arg = arg; ovs_strlcpy(aux->name, name, sizeof aux->name); + /* Some small systems use a default stack size as small as 80 kB, but OVS + * requires approximately 384 kB according to the following analysis: + * http://openvswitch.org/pipermail/dev/2016-January/065049.html + * + * We use 512 kB to give us some margin of error. */ + pthread_attr_t attr; + pthread_attr_init(&attr); + set_min_stack_size(&attr, 512 * 1024); + error = pthread_create(&thread, NULL, ovsthread_wrapper, aux); if (error) { ovs_abort(error, "pthread_create failed"); } + pthread_attr_destroy(&attr); return thread; } @@ -582,6 +613,15 @@ count_cpu_cores(void) return n_cores > 0 ? n_cores : 0; } + +/* Returns 'true' if current thread is PMD thread. */ +bool +thread_is_pmd(void) +{ + const char *name = get_subprogram_name(); + return !strncmp(name, "pmd", 3); +} + /* ovsthread_key. */ @@ -621,14 +661,14 @@ static struct ovs_mutex key_mutex = OVS_MUTEX_INITIALIZER; * Together, 'inuse_keys' and 'free_keys' hold an ovsthread_key for every index * from 0 to n_keys - 1, inclusive. */ static struct ovs_list inuse_keys OVS_GUARDED_BY(key_mutex) - = LIST_INITIALIZER(&inuse_keys); + = OVS_LIST_INITIALIZER(&inuse_keys); static struct ovs_list free_keys OVS_GUARDED_BY(key_mutex) - = LIST_INITIALIZER(&free_keys); + = OVS_LIST_INITIALIZER(&free_keys); static unsigned int n_keys OVS_GUARDED_BY(key_mutex); /* All existing struct ovsthread_key_slots. */ static struct ovs_list slots_list OVS_GUARDED_BY(key_mutex) - = LIST_INITIALIZER(&slots_list); + = OVS_LIST_INITIALIZER(&slots_list); static void * clear_slot(struct ovsthread_key_slots *slots, unsigned int index) @@ -663,12 +703,24 @@ ovsthread_key_destruct__(void *slots_) n = n_keys; ovs_mutex_unlock(&key_mutex); - for (i = 0; i < n / L2_SIZE; i++) { + for (i = 0; i < DIV_ROUND_UP(n, L2_SIZE); i++) { free(slots->p1[i]); } free(slots); } +/* Cancels the callback to ovsthread_key_destruct__(). + * + * Cancelling the call to the destructor during the main thread exit + * is needed while using pthreads-win32 library in Windows. It has been + * observed that in pthreads-win32, a call to the destructor during + * main thread exit causes undefined behavior. */ +static void +ovsthread_cancel_ovsthread_key_destruct__(void *aux OVS_UNUSED) +{ + pthread_setspecific(tsd_key, NULL); +} + /* Initializes '*keyp' as a thread-specific data key. The data items are * initially null in all threads. * @@ -685,6 +737,8 @@ ovsthread_key_create(ovsthread_key_t *keyp, void (*destructor)(void *)) if (ovsthread_once_start(&once)) { xpthread_key_create(&tsd_key, ovsthread_key_destruct__); + fatal_signal_add_hook(ovsthread_cancel_ovsthread_key_destruct__, + NULL, NULL, true); ovsthread_once_done(&once); }