LCOV - code coverage report
Current view: top level - lib - ovs-thread.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 210 255 82.4 %
Date: 2016-09-14 01:02:56 Functions: 50 62 80.6 %
Branches: 76 158 48.1 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2013, 2014, 2015, 2016 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                 :            : #include <config.h>
      18                 :            : #include "ovs-thread.h"
      19                 :            : #include <errno.h>
      20                 :            : #include <poll.h>
      21                 :            : #ifndef _WIN32
      22                 :            : #include <signal.h>
      23                 :            : #endif
      24                 :            : #include <stdlib.h>
      25                 :            : #include <unistd.h>
      26                 :            : #include "compiler.h"
      27                 :            : #include "fatal-signal.h"
      28                 :            : #include "hash.h"
      29                 :            : #include "openvswitch/list.h"
      30                 :            : #include "netdev-dpdk.h"
      31                 :            : #include "ovs-rcu.h"
      32                 :            : #include "poll-loop.h"
      33                 :            : #include "seq.h"
      34                 :            : #include "socket-util.h"
      35                 :            : #include "util.h"
      36                 :            : 
      37                 :            : #ifdef __CHECKER__
      38                 :            : /* Omit the definitions in this file because they are somewhat difficult to
      39                 :            :  * write without prompting "sparse" complaints, without ugliness or
      40                 :            :  * cut-and-paste.  Since "sparse" is just a checker, not a compiler, it
      41                 :            :  * doesn't matter that we don't define them. */
      42                 :            : #else
      43                 :            : #include "openvswitch/vlog.h"
      44                 :            : 
      45                 :      53956 : VLOG_DEFINE_THIS_MODULE(ovs_thread);
      46                 :            : 
      47                 :            : /* If there is a reason that we cannot fork anymore (unless the fork will be
      48                 :            :  * immediately followed by an exec), then this points to a string that
      49                 :            :  * explains why. */
      50                 :            : static const char *must_not_fork;
      51                 :            : 
      52                 :            : /* True if we created any threads beyond the main initial thread. */
      53                 :            : static bool multithreaded;
      54                 :            : 
      55                 :            : #define LOCK_FUNCTION(TYPE, FUN) \
      56                 :            :     void \
      57                 :            :     ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \
      58                 :            :                             const char *where) \
      59                 :            :         OVS_NO_THREAD_SAFETY_ANALYSIS \
      60                 :            :     { \
      61                 :            :         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
      62                 :            :         int error; \
      63                 :            :  \
      64                 :            :         /* Verify that 'l' was initialized. */ \
      65                 :            :         if (OVS_UNLIKELY(!l->where)) { \
      66                 :            :             ovs_abort(0, "%s: %s() passed uninitialized ovs_"#TYPE, \
      67                 :            :                       where, __func__); \
      68                 :            :         } \
      69                 :            :  \
      70                 :            :         error = pthread_##TYPE##_##FUN(&l->lock); \
      71                 :            :         if (OVS_UNLIKELY(error)) { \
      72                 :            :             ovs_abort(error, "%s: pthread_%s_%s failed", where, #TYPE, #FUN); \
      73                 :            :         } \
      74                 :            :         l->where = where; \
      75                 :            :  }
      76 [ -  + ][ -  + ]:  164248450 : LOCK_FUNCTION(mutex, lock);
      77 [ -  + ][ -  + ]:     808356 : LOCK_FUNCTION(rwlock, rdlock);
      78 [ -  + ][ -  + ]:     409126 : LOCK_FUNCTION(rwlock, wrlock);
      79                 :            : 
      80                 :            : #define TRY_LOCK_FUNCTION(TYPE, FUN) \
      81                 :            :     int \
      82                 :            :     ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \
      83                 :            :                             const char *where) \
      84                 :            :         OVS_NO_THREAD_SAFETY_ANALYSIS \
      85                 :            :     { \
      86                 :            :         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
      87                 :            :         int error; \
      88                 :            :  \
      89                 :            :         /* Verify that 'l' was initialized. */ \
      90                 :            :         if (OVS_UNLIKELY(!l->where)) { \
      91                 :            :             ovs_abort(0, "%s: %s() passed uninitialized ovs_"#TYPE, \
      92                 :            :                       where, __func__); \
      93                 :            :         } \
      94                 :            :  \
      95                 :            :         error = pthread_##TYPE##_##FUN(&l->lock); \
      96                 :            :         if (OVS_UNLIKELY(error) && error != EBUSY) { \
      97                 :            :             ovs_abort(error, "%s: pthread_%s_%s failed", where, #TYPE, #FUN); \
      98                 :            :         } \
      99                 :            :         if (!error) { \
     100                 :            :             l->where = where; \
     101                 :            :         } \
     102                 :            :         return error; \
     103                 :            :     }
     104 [ -  + ][ +  + ]:    1257631 : TRY_LOCK_FUNCTION(mutex, trylock);
         [ -  + ][ +  + ]
     105 [ #  # ][ #  # ]:          0 : TRY_LOCK_FUNCTION(rwlock, tryrdlock);
         [ #  # ][ #  # ]
     106 [ #  # ][ #  # ]:          0 : TRY_LOCK_FUNCTION(rwlock, trywrlock);
         [ #  # ][ #  # ]
     107                 :            : 
     108                 :            : #define UNLOCK_FUNCTION(TYPE, FUN, WHERE) \
     109                 :            :     void \
     110                 :            :     ovs_##TYPE##_##FUN(const struct ovs_##TYPE *l_) \
     111                 :            :         OVS_NO_THREAD_SAFETY_ANALYSIS \
     112                 :            :     { \
     113                 :            :         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
     114                 :            :         int error; \
     115                 :            :  \
     116                 :            :         /* Verify that 'l' was initialized. */ \
     117                 :            :         ovs_assert(l->where); \
     118                 :            :  \
     119                 :            :         l->where = WHERE; \
     120                 :            :         error = pthread_##TYPE##_##FUN(&l->lock); \
     121                 :            :         if (OVS_UNLIKELY(error)) { \
     122                 :            :             ovs_abort(error, "pthread_%s_%s failed", #TYPE, #FUN); \
     123                 :            :         } \
     124                 :            :     }
     125 [ -  + ][ -  + ]:  165428091 : UNLOCK_FUNCTION(mutex, unlock, "<unlocked>");
     126 [ -  + ][ -  + ]:    1552203 : UNLOCK_FUNCTION(mutex, destroy, NULL);
     127 [ -  + ][ -  + ]:    1217481 : UNLOCK_FUNCTION(rwlock, unlock, "<unlocked>");
     128 [ -  + ][ -  + ]:       2726 : UNLOCK_FUNCTION(rwlock, destroy, NULL);
     129                 :            : 
     130                 :            : #define XPTHREAD_FUNC1(FUNCTION, PARAM1)                \
     131                 :            :     void                                                \
     132                 :            :     x##FUNCTION(PARAM1 arg1)                            \
     133                 :            :     {                                                   \
     134                 :            :         int error = FUNCTION(arg1);                     \
     135                 :            :         if (OVS_UNLIKELY(error)) {                      \
     136                 :            :             ovs_abort(error, "%s failed", #FUNCTION);   \
     137                 :            :         }                                               \
     138                 :            :     }
     139                 :            : #define XPTHREAD_FUNC2(FUNCTION, PARAM1, PARAM2)        \
     140                 :            :     void                                                \
     141                 :            :     x##FUNCTION(PARAM1 arg1, PARAM2 arg2)               \
     142                 :            :     {                                                   \
     143                 :            :         int error = FUNCTION(arg1, arg2);               \
     144                 :            :         if (OVS_UNLIKELY(error)) {                      \
     145                 :            :             ovs_abort(error, "%s failed", #FUNCTION);   \
     146                 :            :         }                                               \
     147                 :            :     }
     148                 :            : #define XPTHREAD_FUNC3(FUNCTION, PARAM1, PARAM2, PARAM3)\
     149                 :            :     void                                                \
     150                 :            :     x##FUNCTION(PARAM1 arg1, PARAM2 arg2, PARAM3 arg3)  \
     151                 :            :     {                                                   \
     152                 :            :         int error = FUNCTION(arg1, arg2, arg3);         \
     153                 :            :         if (OVS_UNLIKELY(error)) {                      \
     154                 :            :             ovs_abort(error, "%s failed", #FUNCTION);   \
     155                 :            :         }                                               \
     156                 :            :     }
     157                 :            : 
     158         [ #  # ]:          0 : XPTHREAD_FUNC1(pthread_mutex_lock, pthread_mutex_t *);
     159         [ #  # ]:          0 : XPTHREAD_FUNC1(pthread_mutex_unlock, pthread_mutex_t *);
     160         [ -  + ]:    2329858 : XPTHREAD_FUNC1(pthread_mutexattr_init, pthread_mutexattr_t *);
     161         [ -  + ]:    2329845 : XPTHREAD_FUNC1(pthread_mutexattr_destroy, pthread_mutexattr_t *);
     162         [ -  + ]:    2329854 : XPTHREAD_FUNC2(pthread_mutexattr_settype, pthread_mutexattr_t *, int);
     163         [ #  # ]:          0 : XPTHREAD_FUNC2(pthread_mutexattr_gettype, pthread_mutexattr_t *, int *);
     164                 :            : 
     165         [ -  + ]:       2726 : XPTHREAD_FUNC1(pthread_rwlockattr_init, pthread_rwlockattr_t *);
     166         [ -  + ]:       2726 : XPTHREAD_FUNC1(pthread_rwlockattr_destroy, pthread_rwlockattr_t *);
     167                 :            : #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
     168         [ -  + ]:       2726 : XPTHREAD_FUNC2(pthread_rwlockattr_setkind_np, pthread_rwlockattr_t *, int);
     169                 :            : #endif
     170                 :            : 
     171         [ -  + ]:       1240 : XPTHREAD_FUNC2(pthread_cond_init, pthread_cond_t *, pthread_condattr_t *);
     172         [ -  + ]:         94 : XPTHREAD_FUNC1(pthread_cond_destroy, pthread_cond_t *);
     173         [ -  + ]:        202 : XPTHREAD_FUNC1(pthread_cond_signal, pthread_cond_t *);
     174         [ #  # ]:          0 : XPTHREAD_FUNC1(pthread_cond_broadcast, pthread_cond_t *);
     175                 :            : 
     176         [ -  + ]:       9186 : XPTHREAD_FUNC2(pthread_join, pthread_t, void **);
     177                 :            : 
     178                 :            : typedef void destructor_func(void *);
     179         [ -  + ]:      96954 : XPTHREAD_FUNC2(pthread_key_create, pthread_key_t *, destructor_func *);
     180         [ #  # ]:          0 : XPTHREAD_FUNC1(pthread_key_delete, pthread_key_t);
     181         [ -  + ]:      93850 : XPTHREAD_FUNC2(pthread_setspecific, pthread_key_t, const void *);
     182                 :            : 
     183                 :            : #ifndef _WIN32
     184         [ -  + ]:        648 : XPTHREAD_FUNC3(pthread_sigmask, int, const sigset_t *, sigset_t *);
     185                 :            : #endif
     186                 :            : 
     187                 :            : static void
     188                 :    1164928 : ovs_mutex_init__(const struct ovs_mutex *l_, int type)
     189                 :            : {
     190                 :    1164928 :     struct ovs_mutex *l = CONST_CAST(struct ovs_mutex *, l_);
     191                 :            :     pthread_mutexattr_t attr;
     192                 :            :     int error;
     193                 :            : 
     194                 :    1164928 :     l->where = "<unlocked>";
     195                 :    1164928 :     xpthread_mutexattr_init(&attr);
     196                 :    1164928 :     xpthread_mutexattr_settype(&attr, type);
     197                 :    1164927 :     error = pthread_mutex_init(&l->lock, &attr);
     198         [ -  + ]:    1164924 :     if (OVS_UNLIKELY(error)) {
     199                 :          0 :         ovs_abort(error, "pthread_mutex_init failed");
     200                 :            :     }
     201                 :    1164924 :     xpthread_mutexattr_destroy(&attr);
     202                 :    1164918 : }
     203                 :            : 
     204                 :            : /* Initializes 'mutex' as a normal (non-recursive) mutex. */
     205                 :            : void
     206                 :     966222 : ovs_mutex_init(const struct ovs_mutex *mutex)
     207                 :            : {
     208                 :     966222 :     ovs_mutex_init__(mutex, PTHREAD_MUTEX_ERRORCHECK);
     209                 :     966213 : }
     210                 :            : 
     211                 :            : /* Initializes 'mutex' as a recursive mutex. */
     212                 :            : void
     213                 :      24824 : ovs_mutex_init_recursive(const struct ovs_mutex *mutex)
     214                 :            : {
     215                 :      24824 :     ovs_mutex_init__(mutex, PTHREAD_MUTEX_RECURSIVE);
     216                 :      24824 : }
     217                 :            : 
     218                 :            : /* Initializes 'mutex' as a recursive mutex. */
     219                 :            : void
     220                 :     173882 : ovs_mutex_init_adaptive(const struct ovs_mutex *mutex)
     221                 :            : {
     222                 :            : #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
     223                 :     173882 :     ovs_mutex_init__(mutex, PTHREAD_MUTEX_ADAPTIVE_NP);
     224                 :            : #else
     225                 :            :     ovs_mutex_init(mutex);
     226                 :            : #endif
     227                 :     173882 : }
     228                 :            : 
     229                 :            : void
     230                 :       1363 : ovs_rwlock_init(const struct ovs_rwlock *l_)
     231                 :            : {
     232                 :       1363 :     struct ovs_rwlock *l = CONST_CAST(struct ovs_rwlock *, l_);
     233                 :            :     pthread_rwlockattr_t attr;
     234                 :            :     int error;
     235                 :            : 
     236                 :       1363 :     l->where = "<unlocked>";
     237                 :            : 
     238                 :       1363 :     xpthread_rwlockattr_init(&attr);
     239                 :            : #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
     240                 :       1363 :     xpthread_rwlockattr_setkind_np(
     241                 :            :         &attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
     242                 :            : #endif
     243                 :       1363 :     error = pthread_rwlock_init(&l->lock, NULL);
     244         [ -  + ]:       1363 :     if (OVS_UNLIKELY(error)) {
     245                 :          0 :         ovs_abort(error, "pthread_rwlock_init failed");
     246                 :            :     }
     247                 :       1363 :     xpthread_rwlockattr_destroy(&attr);
     248                 :       1363 : }
     249                 :            : 
     250                 :            : /* Provides an error-checking wrapper around pthread_cond_wait().
     251                 :            :  *
     252                 :            :  * If the wait can take a significant amount of time, consider bracketing this
     253                 :            :  * call with calls to ovsrcu_quiesce_start() and ovsrcu_quiesce_end().  */
     254                 :            : void
     255                 :        101 : ovs_mutex_cond_wait(pthread_cond_t *cond, const struct ovs_mutex *mutex_)
     256                 :            : {
     257                 :        101 :     struct ovs_mutex *mutex = CONST_CAST(struct ovs_mutex *, mutex_);
     258                 :            :     int error;
     259                 :            : 
     260                 :        101 :     error = pthread_cond_wait(cond, &mutex->lock);
     261                 :            : 
     262         [ -  + ]:        101 :     if (OVS_UNLIKELY(error)) {
     263                 :          0 :         ovs_abort(error, "pthread_cond_wait failed");
     264                 :            :     }
     265                 :        101 : }
     266                 :            : 
     267                 :            : /* Initializes the 'barrier'.  'size' is the number of threads
     268                 :            :  * expected to hit the barrier. */
     269                 :            : void
     270                 :       4532 : ovs_barrier_init(struct ovs_barrier *barrier, uint32_t size)
     271                 :            : {
     272                 :       4532 :     barrier->size = size;
     273                 :       4532 :     atomic_count_init(&barrier->count, 0);
     274                 :       4532 :     barrier->seq = seq_create();
     275                 :       4532 : }
     276                 :            : 
     277                 :            : /* Destroys the 'barrier'. */
     278                 :            : void
     279                 :       4532 : ovs_barrier_destroy(struct ovs_barrier *barrier)
     280                 :            : {
     281                 :       4532 :     seq_destroy(barrier->seq);
     282                 :       4532 : }
     283                 :            : 
     284                 :            : /* Makes the calling thread block on the 'barrier' until all
     285                 :            :  * 'barrier->size' threads hit the barrier.
     286                 :            :  * ovs_barrier provides the necessary acquire-release semantics to make
     287                 :            :  * the effects of prior memory accesses of all the participating threads
     288                 :            :  * visible on return and to prevent the following memory accesses to be
     289                 :            :  * reordered before the ovs_barrier_block(). */
     290                 :            : void
     291                 :      86950 : ovs_barrier_block(struct ovs_barrier *barrier)
     292                 :            : {
     293                 :      86950 :     uint64_t seq = seq_read(barrier->seq);
     294                 :            :     uint32_t orig;
     295                 :            : 
     296                 :      86950 :     orig = atomic_count_inc(&barrier->count);
     297         [ +  + ]:      86950 :     if (orig + 1 == barrier->size) {
     298                 :      86848 :         atomic_count_set(&barrier->count, 0);
     299                 :            :         /* seq_change() serves as a release barrier against the other threads,
     300                 :            :          * so the zeroed count is visible to them as they continue. */
     301                 :      86848 :         seq_change(barrier->seq);
     302                 :            :     } else {
     303                 :            :         /* To prevent thread from waking up by other event,
     304                 :            :          * keeps waiting for the change of 'barrier->seq'. */
     305         [ +  + ]:        209 :         while (seq == seq_read(barrier->seq)) {
     306                 :        107 :             seq_wait(barrier->seq, seq);
     307                 :        107 :             poll_block();
     308                 :            :         }
     309                 :            :     }
     310                 :      86950 : }
     311                 :            : 
     312                 :            : DEFINE_EXTERN_PER_THREAD_DATA(ovsthread_id, 0);
     313                 :            : 
     314                 :            : struct ovsthread_aux {
     315                 :            :     void *(*start)(void *);
     316                 :            :     void *arg;
     317                 :            :     char name[16];
     318                 :            : };
     319                 :            : 
     320                 :            : static void *
     321                 :       5783 : ovsthread_wrapper(void *aux_)
     322                 :            : {
     323                 :            :     static atomic_count next_id = ATOMIC_COUNT_INIT(1);
     324                 :            : 
     325                 :       5783 :     struct ovsthread_aux *auxp = aux_;
     326                 :            :     struct ovsthread_aux aux;
     327                 :            :     unsigned int id;
     328                 :            : 
     329                 :       5783 :     id = atomic_count_inc(&next_id);
     330                 :       5783 :     *ovsthread_id_get() = id;
     331                 :            : 
     332                 :       5783 :     aux = *auxp;
     333                 :       5783 :     free(auxp);
     334                 :            : 
     335                 :            :     /* The order of the following calls is important, because
     336                 :            :      * ovsrcu_quiesce_end() saves a copy of the thread name. */
     337                 :       5783 :     char *subprogram_name = xasprintf("%s%u", aux.name, id);
     338                 :       5783 :     set_subprogram_name(subprogram_name);
     339                 :       5781 :     free(subprogram_name);
     340                 :       5781 :     ovsrcu_quiesce_end();
     341                 :            : 
     342                 :       5783 :     return aux.start(aux.arg);
     343                 :            : }
     344                 :            : 
     345                 :            : static void
     346                 :       5783 : set_min_stack_size(pthread_attr_t *attr, size_t min_stacksize)
     347                 :            : {
     348                 :            :     size_t stacksize;
     349                 :            :     int error;
     350                 :            : 
     351                 :       5783 :     error = pthread_attr_getstacksize(attr, &stacksize);
     352         [ -  + ]:       5783 :     if (error) {
     353                 :          0 :         ovs_abort(error, "pthread_attr_getstacksize failed");
     354                 :            :     }
     355                 :            : 
     356         [ -  + ]:       5783 :     if (stacksize < min_stacksize) {
     357                 :          0 :         error = pthread_attr_setstacksize(attr, min_stacksize);
     358         [ #  # ]:          0 :         if (error) {
     359                 :          0 :             ovs_abort(error, "pthread_attr_setstacksize failed");
     360                 :            :         }
     361                 :            :     }
     362                 :       5783 : }
     363                 :            : 
     364                 :            : /* Starts a thread that calls 'start(arg)'.  Sets the thread's name to 'name'
     365                 :            :  * (suffixed by its ovsthread_id()).  Returns the new thread's pthread_t. */
     366                 :            : pthread_t
     367                 :       5783 : ovs_thread_create(const char *name, void *(*start)(void *), void *arg)
     368                 :            : {
     369                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     370                 :            :     struct ovsthread_aux *aux;
     371                 :            :     pthread_t thread;
     372                 :            :     int error;
     373                 :            : 
     374                 :       5783 :     forbid_forking("multiple threads exist");
     375                 :            : 
     376         [ +  + ]:       5783 :     if (ovsthread_once_start(&once)) {
     377                 :            :         /* The first call to this function has to happen in the main thread.
     378                 :            :          * Before the process becomes multithreaded we make sure that the
     379                 :            :          * main thread is considered non quiescent.
     380                 :            :          *
     381                 :            :          * For other threads this is done in ovs_thread_wrapper(), but the
     382                 :            :          * main thread has no such wrapper.
     383                 :            :          *
     384                 :            :          * There's no reason to call ovsrcu_quiesce_end() in subsequent
     385                 :            :          * invocations of this function and it might introduce problems
     386                 :            :          * for other threads. */
     387                 :        616 :         ovsrcu_quiesce_end();
     388                 :        616 :         ovsthread_once_done(&once);
     389                 :            :     }
     390                 :            : 
     391                 :       5783 :     multithreaded = true;
     392                 :       5783 :     aux = xmalloc(sizeof *aux);
     393                 :       5783 :     aux->start = start;
     394                 :       5783 :     aux->arg = arg;
     395                 :       5783 :     ovs_strlcpy(aux->name, name, sizeof aux->name);
     396                 :            : 
     397                 :            :     /* Some small systems use a default stack size as small as 80 kB, but OVS
     398                 :            :      * requires approximately 384 kB according to the following analysis:
     399                 :            :      * http://openvswitch.org/pipermail/dev/2016-January/065049.html
     400                 :            :      *
     401                 :            :      * We use 512 kB to give us some margin of error. */
     402                 :            :     pthread_attr_t attr;
     403                 :       5783 :     pthread_attr_init(&attr);
     404                 :       5783 :     set_min_stack_size(&attr, 512 * 1024);
     405                 :            : 
     406                 :       5783 :     error = pthread_create(&thread, &attr, ovsthread_wrapper, aux);
     407         [ -  + ]:       5783 :     if (error) {
     408                 :          0 :         ovs_abort(error, "pthread_create failed");
     409                 :            :     }
     410                 :       5783 :     pthread_attr_destroy(&attr);
     411                 :       5783 :     return thread;
     412                 :            : }
     413                 :            : 
     414                 :            : bool
     415                 :     103082 : ovsthread_once_start__(struct ovsthread_once *once)
     416                 :            : {
     417                 :     103082 :     ovs_mutex_lock(&once->mutex);
     418                 :            :     /* Mutex synchronizes memory, so we get the current value of 'done'. */
     419         [ +  + ]:     103082 :     if (!once->done) {
     420                 :     103072 :         return true;
     421                 :            :     }
     422                 :         10 :     ovs_mutex_unlock(&once->mutex);
     423                 :         10 :     return false;
     424                 :            : }
     425                 :            : 
     426                 :            : void
     427                 :     103072 : ovsthread_once_done(struct ovsthread_once *once)
     428                 :            : {
     429                 :            :     /* We need release semantics here, so that the following store may not
     430                 :            :      * be moved ahead of any of the preceding initialization operations.
     431                 :            :      * A release atomic_thread_fence provides that prior memory accesses
     432                 :            :      * will not be reordered to take place after the following store. */
     433                 :     103072 :     atomic_thread_fence(memory_order_release);
     434                 :     103072 :     once->done = true;
     435                 :     103072 :     ovs_mutex_unlock(&once->mutex);
     436                 :     103072 : }
     437                 :            : 
     438                 :            : bool
     439                 :   16967397 : single_threaded(void)
     440                 :            : {
     441                 :   16967397 :     return !multithreaded;
     442                 :            : }
     443                 :            : 
     444                 :            : /* Asserts that the process has not yet created any threads (beyond the initial
     445                 :            :  * thread).
     446                 :            :  *
     447                 :            :  * ('where' is used in logging.  Commonly one would use
     448                 :            :  * assert_single_threaded() to automatically provide the caller's source file
     449                 :            :  * and line number for 'where'.) */
     450                 :            : void
     451                 :      85273 : assert_single_threaded_at(const char *where)
     452                 :            : {
     453         [ -  + ]:      85273 :     if (multithreaded) {
     454                 :          0 :         VLOG_FATAL("%s: attempted operation not allowed when multithreaded",
     455                 :            :                    where);
     456                 :            :     }
     457                 :      85273 : }
     458                 :            : 
     459                 :            : #ifndef _WIN32
     460                 :            : /* Forks the current process (checking that this is allowed).  Aborts with
     461                 :            :  * VLOG_FATAL if fork() returns an error, and otherwise returns the value
     462                 :            :  * returned by fork().
     463                 :            :  *
     464                 :            :  * ('where' is used in logging.  Commonly one would use xfork() to
     465                 :            :  * automatically provide the caller's source file and line number for
     466                 :            :  * 'where'.) */
     467                 :            : pid_t
     468                 :       2149 : xfork_at(const char *where)
     469                 :            : {
     470                 :            :     pid_t pid;
     471                 :            : 
     472         [ -  + ]:       2149 :     if (must_not_fork) {
     473                 :          0 :         VLOG_FATAL("%s: attempted to fork but forking not allowed (%s)",
     474                 :            :                    where, must_not_fork);
     475                 :            :     }
     476                 :            : 
     477                 :       2149 :     pid = fork();
     478         [ -  + ]:       4223 :     if (pid < 0) {
     479                 :          0 :         VLOG_FATAL("%s: fork failed (%s)", where, ovs_strerror(errno));
     480                 :            :     }
     481                 :       4223 :     return pid;
     482                 :            : }
     483                 :            : #endif
     484                 :            : 
     485                 :            : /* Notes that the process must not call fork() from now on, for the specified
     486                 :            :  * 'reason'.  (The process may still fork() if it execs itself immediately
     487                 :            :  * afterward.) */
     488                 :            : void
     489                 :       7962 : forbid_forking(const char *reason)
     490                 :            : {
     491         [ -  + ]:       7962 :     ovs_assert(reason != NULL);
     492                 :       7962 :     must_not_fork = reason;
     493                 :       7962 : }
     494                 :            : 
     495                 :            : /* Returns true if the process is allowed to fork, false otherwise. */
     496                 :            : bool
     497                 :          0 : may_fork(void)
     498                 :            : {
     499                 :          0 :     return !must_not_fork;
     500                 :            : }
     501                 :            : 
     502                 :            : /* ovsthread_stats. */
     503                 :            : 
     504                 :            : void
     505                 :          0 : ovsthread_stats_init(struct ovsthread_stats *stats)
     506                 :            : {
     507                 :            :     int i;
     508                 :            : 
     509                 :          0 :     ovs_mutex_init(&stats->mutex);
     510         [ #  # ]:          0 :     for (i = 0; i < ARRAY_SIZE(stats->buckets); i++) {
     511                 :          0 :         stats->buckets[i] = NULL;
     512                 :            :     }
     513                 :          0 : }
     514                 :            : 
     515                 :            : void
     516                 :          0 : ovsthread_stats_destroy(struct ovsthread_stats *stats)
     517                 :            : {
     518                 :          0 :     ovs_mutex_destroy(&stats->mutex);
     519                 :          0 : }
     520                 :            : 
     521                 :            : void *
     522                 :          0 : ovsthread_stats_bucket_get(struct ovsthread_stats *stats,
     523                 :            :                            void *(*new_bucket)(void))
     524                 :            : {
     525                 :          0 :     unsigned int idx = ovsthread_id_self() & (ARRAY_SIZE(stats->buckets) - 1);
     526                 :          0 :     void *bucket = stats->buckets[idx];
     527         [ #  # ]:          0 :     if (!bucket) {
     528                 :          0 :         ovs_mutex_lock(&stats->mutex);
     529                 :          0 :         bucket = stats->buckets[idx];
     530         [ #  # ]:          0 :         if (!bucket) {
     531                 :          0 :             bucket = stats->buckets[idx] = new_bucket();
     532                 :            :         }
     533                 :          0 :         ovs_mutex_unlock(&stats->mutex);
     534                 :            :     }
     535                 :          0 :     return bucket;
     536                 :            : }
     537                 :            : 
     538                 :            : size_t
     539                 :          0 : ovs_thread_stats_next_bucket(const struct ovsthread_stats *stats, size_t i)
     540                 :            : {
     541         [ #  # ]:          0 :     for (; i < ARRAY_SIZE(stats->buckets); i++) {
     542         [ #  # ]:          0 :         if (stats->buckets[i]) {
     543                 :          0 :             break;
     544                 :            :         }
     545                 :            :     }
     546                 :          0 :     return i;
     547                 :            : }
     548                 :            : 
     549                 :            : 
     550                 :            : /* Returns the total number of cores available to this process, or 0 if the
     551                 :            :  * number cannot be determined. */
     552                 :            : int
     553                 :       4238 : count_cpu_cores(void)
     554                 :            : {
     555                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     556                 :            :     static long int n_cores;
     557                 :            : 
     558         [ +  + ]:       4238 :     if (ovsthread_once_start(&once)) {
     559                 :            : #ifndef _WIN32
     560                 :        615 :         n_cores = sysconf(_SC_NPROCESSORS_ONLN);
     561                 :            : #ifdef __linux__
     562         [ +  - ]:        615 :         if (n_cores > 0) {
     563                 :        615 :             cpu_set_t *set = CPU_ALLOC(n_cores);
     564                 :            : 
     565         [ +  - ]:        615 :             if (set) {
     566                 :        615 :                 size_t size = CPU_ALLOC_SIZE(n_cores);
     567                 :            : 
     568         [ +  - ]:        615 :                 if (!sched_getaffinity(0, size, set)) {
     569                 :        615 :                     n_cores = CPU_COUNT_S(size, set);
     570                 :            :                 }
     571                 :        615 :                 CPU_FREE(set);
     572                 :            :             }
     573                 :            :         }
     574                 :            : #endif
     575                 :            : #else
     576                 :            :         SYSTEM_INFO sysinfo;
     577                 :            :         GetSystemInfo(&sysinfo);
     578                 :            :         n_cores = sysinfo.dwNumberOfProcessors;
     579                 :            : #endif
     580                 :        615 :         ovsthread_once_done(&once);
     581                 :            :     }
     582                 :            : 
     583                 :       4238 :     return n_cores > 0 ? n_cores : 0;
     584                 :            : }
     585                 :            : 
     586                 :            : /* Returns 'true' if current thread is PMD thread. */
     587                 :            : bool
     588                 :     327401 : thread_is_pmd(void)
     589                 :            : {
     590                 :     327401 :     const char *name = get_subprogram_name();
     591                 :     327401 :     return !strncmp(name, "pmd", 3);
     592                 :            : }
     593                 :            : 
     594                 :            : 
     595                 :            : /* ovsthread_key. */
     596                 :            : 
     597                 :            : #define L1_SIZE 1024
     598                 :            : #define L2_SIZE 1024
     599                 :            : #define MAX_KEYS (L1_SIZE * L2_SIZE)
     600                 :            : 
     601                 :            : /* A piece of thread-specific data. */
     602                 :            : struct ovsthread_key {
     603                 :            :     struct ovs_list list_node;  /* In 'inuse_keys' or 'free_keys'. */
     604                 :            :     void (*destructor)(void *); /* Called at thread exit. */
     605                 :            : 
     606                 :            :     /* Indexes into the per-thread array in struct ovsthread_key_slots.
     607                 :            :      * This key's data is stored in p1[index / L2_SIZE][index % L2_SIZE]. */
     608                 :            :     unsigned int index;
     609                 :            : };
     610                 :            : 
     611                 :            : /* Per-thread data structure. */
     612                 :            : struct ovsthread_key_slots {
     613                 :            :     struct ovs_list list_node;  /* In 'slots_list'. */
     614                 :            :     void **p1[L1_SIZE];
     615                 :            : };
     616                 :            : 
     617                 :            : /* Contains "struct ovsthread_key_slots *". */
     618                 :            : static pthread_key_t tsd_key;
     619                 :            : 
     620                 :            : /* Guards data structures below. */
     621                 :            : static struct ovs_mutex key_mutex = OVS_MUTEX_INITIALIZER;
     622                 :            : 
     623                 :            : /* 'inuse_keys' holds "struct ovsthread_key"s that have been created and not
     624                 :            :  * yet destroyed.
     625                 :            :  *
     626                 :            :  * 'free_keys' holds "struct ovsthread_key"s that have been deleted and are
     627                 :            :  * ready for reuse.  (We keep them around only to be able to easily locate
     628                 :            :  * free indexes.)
     629                 :            :  *
     630                 :            :  * Together, 'inuse_keys' and 'free_keys' hold an ovsthread_key for every index
     631                 :            :  * from 0 to n_keys - 1, inclusive. */
     632                 :            : static struct ovs_list inuse_keys OVS_GUARDED_BY(key_mutex)
     633                 :            :     = OVS_LIST_INITIALIZER(&inuse_keys);
     634                 :            : static struct ovs_list free_keys OVS_GUARDED_BY(key_mutex)
     635                 :            :     = OVS_LIST_INITIALIZER(&free_keys);
     636                 :            : static unsigned int n_keys OVS_GUARDED_BY(key_mutex);
     637                 :            : 
     638                 :            : /* All existing struct ovsthread_key_slots. */
     639                 :            : static struct ovs_list slots_list OVS_GUARDED_BY(key_mutex)
     640                 :            :     = OVS_LIST_INITIALIZER(&slots_list);
     641                 :            : 
     642                 :            : static void *
     643                 :        694 : clear_slot(struct ovsthread_key_slots *slots, unsigned int index)
     644                 :            : {
     645                 :        694 :     void **p2 = slots->p1[index / L2_SIZE];
     646         [ +  - ]:        694 :     if (p2) {
     647                 :        694 :         void **valuep = &p2[index % L2_SIZE];
     648                 :        694 :         void *value = *valuep;
     649                 :        694 :         *valuep = NULL;
     650                 :        694 :         return value;
     651                 :            :     } else {
     652                 :          0 :         return NULL;
     653                 :            :     }
     654                 :            : }
     655                 :            : 
     656                 :            : static void
     657                 :        174 : ovsthread_key_destruct__(void *slots_)
     658                 :            : {
     659                 :        174 :     struct ovsthread_key_slots *slots = slots_;
     660                 :            :     struct ovsthread_key *key;
     661                 :            :     unsigned int n;
     662                 :            :     int i;
     663                 :            : 
     664                 :        174 :     ovs_mutex_lock(&key_mutex);
     665                 :        174 :     ovs_list_remove(&slots->list_node);
     666         [ +  + ]:        598 :     LIST_FOR_EACH (key, list_node, &inuse_keys) {
     667                 :        424 :         void *value = clear_slot(slots, key->index);
     668 [ +  + ][ +  + ]:        424 :         if (value && key->destructor) {
     669                 :        141 :             key->destructor(value);
     670                 :            :         }
     671                 :            :     }
     672                 :        174 :     n = n_keys;
     673                 :        174 :     ovs_mutex_unlock(&key_mutex);
     674                 :            : 
     675         [ +  + ]:        348 :     for (i = 0; i < DIV_ROUND_UP(n, L2_SIZE); i++) {
     676                 :        174 :         free(slots->p1[i]);
     677                 :            :     }
     678                 :        174 :     free(slots);
     679                 :        174 : }
     680                 :            : 
     681                 :            : /* Cancels the callback to ovsthread_key_destruct__().
     682                 :            :  *
     683                 :            :  * Cancelling the call to the destructor during the main thread exit
     684                 :            :  * is needed while using pthreads-win32 library in Windows. It has been
     685                 :            :  * observed that in pthreads-win32, a call to the destructor during
     686                 :            :  * main thread exit causes undefined behavior. */
     687                 :            : static void
     688                 :        678 : ovsthread_cancel_ovsthread_key_destruct__(void *aux OVS_UNUSED)
     689                 :            : {
     690                 :        678 :     pthread_setspecific(tsd_key, NULL);
     691                 :        678 : }
     692                 :            : 
     693                 :            : /* Initializes '*keyp' as a thread-specific data key.  The data items are
     694                 :            :  * initially null in all threads.
     695                 :            :  *
     696                 :            :  * If a thread exits with non-null data, then 'destructor', if nonnull, will be
     697                 :            :  * called passing the final data value as its argument.  'destructor' must not
     698                 :            :  * call any thread-specific data functions in this API.
     699                 :            :  *
     700                 :            :  * This function is similar to xpthread_key_create(). */
     701                 :            : void
     702                 :       1906 : ovsthread_key_create(ovsthread_key_t *keyp, void (*destructor)(void *))
     703                 :            : {
     704                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     705                 :            :     struct ovsthread_key *key;
     706                 :            : 
     707         [ +  + ]:       1906 :     if (ovsthread_once_start(&once)) {
     708                 :        678 :         xpthread_key_create(&tsd_key, ovsthread_key_destruct__);
     709                 :        678 :         fatal_signal_add_hook(ovsthread_cancel_ovsthread_key_destruct__,
     710                 :            :                               NULL, NULL, true);
     711                 :        678 :         ovsthread_once_done(&once);
     712                 :            :     }
     713                 :            : 
     714                 :       1906 :     ovs_mutex_lock(&key_mutex);
     715         [ +  + ]:       1906 :     if (ovs_list_is_empty(&free_keys)) {
     716                 :       1881 :         key = xmalloc(sizeof *key);
     717                 :       1881 :         key->index = n_keys++;
     718         [ -  + ]:       1881 :         if (key->index >= MAX_KEYS) {
     719                 :          0 :             abort();
     720                 :            :         }
     721                 :            :     } else {
     722                 :         25 :         key = CONTAINER_OF(ovs_list_pop_back(&free_keys),
     723                 :            :                             struct ovsthread_key, list_node);
     724                 :            :     }
     725                 :       1906 :     ovs_list_push_back(&inuse_keys, &key->list_node);
     726                 :       1906 :     key->destructor = destructor;
     727                 :       1906 :     ovs_mutex_unlock(&key_mutex);
     728                 :            : 
     729                 :       1906 :     *keyp = key;
     730                 :       1906 : }
     731                 :            : 
     732                 :            : /* Frees 'key'.  The destructor supplied to ovsthread_key_create(), if any, is
     733                 :            :  * not called.
     734                 :            :  *
     735                 :            :  * This function is similar to xpthread_key_delete(). */
     736                 :            : void
     737                 :        190 : ovsthread_key_delete(ovsthread_key_t key)
     738                 :            : {
     739                 :            :     struct ovsthread_key_slots *slots;
     740                 :            : 
     741                 :        190 :     ovs_mutex_lock(&key_mutex);
     742                 :            : 
     743                 :            :     /* Move 'key' from 'inuse_keys' to 'free_keys'. */
     744                 :        190 :     ovs_list_remove(&key->list_node);
     745                 :        190 :     ovs_list_push_back(&free_keys, &key->list_node);
     746                 :            : 
     747                 :            :     /* Clear this slot in all threads. */
     748         [ +  + ]:        460 :     LIST_FOR_EACH (slots, list_node, &slots_list) {
     749                 :        270 :         clear_slot(slots, key->index);
     750                 :            :     }
     751                 :            : 
     752                 :        190 :     ovs_mutex_unlock(&key_mutex);
     753                 :        190 : }
     754                 :            : 
     755                 :            : static void **
     756                 :     122655 : ovsthread_key_lookup__(const struct ovsthread_key *key)
     757                 :            : {
     758                 :            :     struct ovsthread_key_slots *slots;
     759                 :            :     void **p2;
     760                 :            : 
     761                 :     122655 :     slots = pthread_getspecific(tsd_key);
     762         [ +  + ]:     122655 :     if (!slots) {
     763                 :        874 :         slots = xzalloc(sizeof *slots);
     764                 :            : 
     765                 :        874 :         ovs_mutex_lock(&key_mutex);
     766                 :        874 :         pthread_setspecific(tsd_key, slots);
     767                 :        874 :         ovs_list_push_back(&slots_list, &slots->list_node);
     768                 :        874 :         ovs_mutex_unlock(&key_mutex);
     769                 :            :     }
     770                 :            : 
     771                 :     122655 :     p2 = slots->p1[key->index / L2_SIZE];
     772         [ +  + ]:     122655 :     if (!p2) {
     773                 :        874 :         p2 = xzalloc(L2_SIZE * sizeof *p2);
     774                 :        874 :         slots->p1[key->index / L2_SIZE] = p2;
     775                 :            :     }
     776                 :            : 
     777                 :     122655 :     return &p2[key->index % L2_SIZE];
     778                 :            : }
     779                 :            : 
     780                 :            : /* Sets the value of thread-specific data item 'key', in the current thread, to
     781                 :            :  * 'value'.
     782                 :            :  *
     783                 :            :  * This function is similar to pthread_setspecific(). */
     784                 :            : void
     785                 :       1563 : ovsthread_setspecific(ovsthread_key_t key, const void *value)
     786                 :            : {
     787                 :       1563 :     *ovsthread_key_lookup__(key) = CONST_CAST(void *, value);
     788                 :       1563 : }
     789                 :            : 
     790                 :            : /* Returns the value of thread-specific data item 'key' in the current thread.
     791                 :            :  *
     792                 :            :  * This function is similar to pthread_getspecific(). */
     793                 :            : void *
     794                 :     121092 : ovsthread_getspecific(ovsthread_key_t key)
     795                 :            : {
     796                 :     121092 :     return *ovsthread_key_lookup__(key);
     797                 :            : }
     798                 :            : #endif

Generated by: LCOV version 1.12