49b3474180dafe29941232061082fc5c0b3b7c53
[cascardo/ovs.git] / lib / ovs-thread.c
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 #include <config.h>
18 #include "ovs-thread.h"
19 #include <errno.h>
20 #include <poll.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include "compiler.h"
24 #include "hash.h"
25 #include "ovs-rcu.h"
26 #include "poll-loop.h"
27 #include "socket-util.h"
28 #include "util.h"
29
30 #ifdef __CHECKER__
31 /* Omit the definitions in this file because they are somewhat difficult to
32  * write without prompting "sparse" complaints, without ugliness or
33  * cut-and-paste.  Since "sparse" is just a checker, not a compiler, it
34  * doesn't matter that we don't define them. */
35 #else
36 #include "vlog.h"
37
38 VLOG_DEFINE_THIS_MODULE(ovs_thread);
39
40 /* If there is a reason that we cannot fork anymore (unless the fork will be
41  * immediately followed by an exec), then this points to a string that
42  * explains why. */
43 static const char *must_not_fork;
44
45 /* True if we created any threads beyond the main initial thread. */
46 static bool multithreaded;
47
48 #define LOCK_FUNCTION(TYPE, FUN) \
49     void \
50     ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \
51                             const char *where) \
52         OVS_NO_THREAD_SAFETY_ANALYSIS \
53     { \
54         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
55         int error; \
56  \
57         /* Verify that 'l' was initialized. */ \
58         if (OVS_UNLIKELY(!l->where)) { \
59             ovs_abort(0, "%s: %s() passed uninitialized ovs_"#TYPE, \
60                       where, __func__); \
61         } \
62  \
63         error = pthread_##TYPE##_##FUN(&l->lock); \
64         if (OVS_UNLIKELY(error)) { \
65             ovs_abort(error, "%s: pthread_%s_%s failed", where, #TYPE, #FUN); \
66         } \
67         l->where = where; \
68  }
69 LOCK_FUNCTION(mutex, lock);
70 LOCK_FUNCTION(rwlock, rdlock);
71 LOCK_FUNCTION(rwlock, wrlock);
72
73 #define TRY_LOCK_FUNCTION(TYPE, FUN) \
74     int \
75     ovs_##TYPE##_##FUN##_at(const struct ovs_##TYPE *l_, \
76                             const char *where) \
77         OVS_NO_THREAD_SAFETY_ANALYSIS \
78     { \
79         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
80         int error; \
81  \
82         /* Verify that 'l' was initialized. */ \
83         if (OVS_UNLIKELY(!l->where)) { \
84             ovs_abort(0, "%s: %s() passed uninitialized ovs_"#TYPE, \
85                       where, __func__); \
86         } \
87  \
88         error = pthread_##TYPE##_##FUN(&l->lock); \
89         if (OVS_UNLIKELY(error) && error != EBUSY) { \
90             ovs_abort(error, "%s: pthread_%s_%s failed", where, #TYPE, #FUN); \
91         } \
92         if (!error) { \
93             l->where = where; \
94         } \
95         return error; \
96     }
97 TRY_LOCK_FUNCTION(mutex, trylock);
98 TRY_LOCK_FUNCTION(rwlock, tryrdlock);
99 TRY_LOCK_FUNCTION(rwlock, trywrlock);
100
101 #define UNLOCK_FUNCTION(TYPE, FUN, WHERE) \
102     void \
103     ovs_##TYPE##_##FUN(const struct ovs_##TYPE *l_) \
104         OVS_NO_THREAD_SAFETY_ANALYSIS \
105     { \
106         struct ovs_##TYPE *l = CONST_CAST(struct ovs_##TYPE *, l_); \
107         int error; \
108  \
109         /* Verify that 'l' was initialized. */ \
110         ovs_assert(l->where); \
111  \
112         l->where = WHERE; \
113         error = pthread_##TYPE##_##FUN(&l->lock); \
114         if (OVS_UNLIKELY(error)) { \
115             ovs_abort(error, "pthread_%s_%sfailed", #TYPE, #FUN); \
116         } \
117     }
118 UNLOCK_FUNCTION(mutex, unlock, "<unlocked>");
119 UNLOCK_FUNCTION(mutex, destroy, NULL);
120 UNLOCK_FUNCTION(rwlock, unlock, "<unlocked>");
121 UNLOCK_FUNCTION(rwlock, destroy, NULL);
122
123 #define XPTHREAD_FUNC1(FUNCTION, PARAM1)                \
124     void                                                \
125     x##FUNCTION(PARAM1 arg1)                            \
126     {                                                   \
127         int error = FUNCTION(arg1);                     \
128         if (OVS_UNLIKELY(error)) {                      \
129             ovs_abort(error, "%s failed", #FUNCTION);   \
130         }                                               \
131     }
132 #define XPTHREAD_FUNC2(FUNCTION, PARAM1, PARAM2)        \
133     void                                                \
134     x##FUNCTION(PARAM1 arg1, PARAM2 arg2)               \
135     {                                                   \
136         int error = FUNCTION(arg1, arg2);               \
137         if (OVS_UNLIKELY(error)) {                      \
138             ovs_abort(error, "%s failed", #FUNCTION);   \
139         }                                               \
140     }
141 #define XPTHREAD_FUNC3(FUNCTION, PARAM1, PARAM2, PARAM3)\
142     void                                                \
143     x##FUNCTION(PARAM1 arg1, PARAM2 arg2, PARAM3 arg3)  \
144     {                                                   \
145         int error = FUNCTION(arg1, arg2, arg3);         \
146         if (OVS_UNLIKELY(error)) {                      \
147             ovs_abort(error, "%s failed", #FUNCTION);   \
148         }                                               \
149     }
150
151 XPTHREAD_FUNC1(pthread_mutex_lock, pthread_mutex_t *);
152 XPTHREAD_FUNC1(pthread_mutex_unlock, pthread_mutex_t *);
153 XPTHREAD_FUNC1(pthread_mutexattr_init, pthread_mutexattr_t *);
154 XPTHREAD_FUNC1(pthread_mutexattr_destroy, pthread_mutexattr_t *);
155 XPTHREAD_FUNC2(pthread_mutexattr_settype, pthread_mutexattr_t *, int);
156 XPTHREAD_FUNC2(pthread_mutexattr_gettype, pthread_mutexattr_t *, int *);
157
158 XPTHREAD_FUNC1(pthread_rwlockattr_init, pthread_rwlockattr_t *);
159 XPTHREAD_FUNC1(pthread_rwlockattr_destroy, pthread_rwlockattr_t *);
160 #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
161 XPTHREAD_FUNC2(pthread_rwlockattr_setkind_np, pthread_rwlockattr_t *, int);
162 #endif
163
164 XPTHREAD_FUNC2(pthread_cond_init, pthread_cond_t *, pthread_condattr_t *);
165 XPTHREAD_FUNC1(pthread_cond_destroy, pthread_cond_t *);
166 XPTHREAD_FUNC1(pthread_cond_signal, pthread_cond_t *);
167 XPTHREAD_FUNC1(pthread_cond_broadcast, pthread_cond_t *);
168
169 XPTHREAD_FUNC3(pthread_barrier_init, pthread_barrier_t *,
170                pthread_barrierattr_t *, unsigned int);
171 XPTHREAD_FUNC1(pthread_barrier_destroy, pthread_barrier_t *);
172
173 XPTHREAD_FUNC2(pthread_join, pthread_t, void **);
174
175 typedef void destructor_func(void *);
176 XPTHREAD_FUNC2(pthread_key_create, pthread_key_t *, destructor_func *);
177 XPTHREAD_FUNC1(pthread_key_delete, pthread_key_t);
178 XPTHREAD_FUNC2(pthread_setspecific, pthread_key_t, const void *);
179
180 static void
181 ovs_mutex_init__(const struct ovs_mutex *l_, int type)
182 {
183     struct ovs_mutex *l = CONST_CAST(struct ovs_mutex *, l_);
184     pthread_mutexattr_t attr;
185     int error;
186
187     l->where = "<unlocked>";
188     xpthread_mutexattr_init(&attr);
189     xpthread_mutexattr_settype(&attr, type);
190     error = pthread_mutex_init(&l->lock, &attr);
191     if (OVS_UNLIKELY(error)) {
192         ovs_abort(error, "pthread_mutex_init failed");
193     }
194     xpthread_mutexattr_destroy(&attr);
195 }
196
197 /* Initializes 'mutex' as a normal (non-recursive) mutex. */
198 void
199 ovs_mutex_init(const struct ovs_mutex *mutex)
200 {
201     ovs_mutex_init__(mutex, PTHREAD_MUTEX_ERRORCHECK);
202 }
203
204 /* Initializes 'mutex' as a recursive mutex. */
205 void
206 ovs_mutex_init_recursive(const struct ovs_mutex *mutex)
207 {
208     ovs_mutex_init__(mutex, PTHREAD_MUTEX_RECURSIVE);
209 }
210
211 /* Initializes 'mutex' as a recursive mutex. */
212 void
213 ovs_mutex_init_adaptive(const struct ovs_mutex *mutex)
214 {
215 #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
216     ovs_mutex_init__(mutex, PTHREAD_MUTEX_ADAPTIVE_NP);
217 #else
218     ovs_mutex_init(mutex);
219 #endif
220 }
221
222 void
223 ovs_rwlock_init(const struct ovs_rwlock *l_)
224 {
225     struct ovs_rwlock *l = CONST_CAST(struct ovs_rwlock *, l_);
226     pthread_rwlockattr_t attr;
227     int error;
228
229     l->where = "<unlocked>";
230
231     xpthread_rwlockattr_init(&attr);
232 #ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
233     xpthread_rwlockattr_setkind_np(
234         &attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
235 #endif
236     error = pthread_rwlock_init(&l->lock, NULL);
237     if (OVS_UNLIKELY(error)) {
238         ovs_abort(error, "pthread_rwlock_init failed");
239     }
240     xpthread_rwlockattr_destroy(&attr);
241 }
242
243 void
244 ovs_mutex_cond_wait(pthread_cond_t *cond, const struct ovs_mutex *mutex_)
245 {
246     struct ovs_mutex *mutex = CONST_CAST(struct ovs_mutex *, mutex_);
247     int error;
248
249     ovsrcu_quiesce_start();
250     error = pthread_cond_wait(cond, &mutex->lock);
251     ovsrcu_quiesce_end();
252
253     if (OVS_UNLIKELY(error)) {
254         ovs_abort(error, "pthread_cond_wait failed");
255     }
256 }
257
258 int
259 xpthread_barrier_wait(pthread_barrier_t *barrier)
260 {
261     int error;
262
263     ovsrcu_quiesce_start();
264     error = pthread_barrier_wait(barrier);
265     ovsrcu_quiesce_end();
266
267     if (error && OVS_UNLIKELY(error != PTHREAD_BARRIER_SERIAL_THREAD)) {
268         ovs_abort(error, "pthread_barrier_wait failed");
269     }
270
271     return error;
272 }
273 \f
274 DEFINE_EXTERN_PER_THREAD_DATA(ovsthread_id, 0);
275
276 struct ovsthread_aux {
277     void *(*start)(void *);
278     void *arg;
279     char name[16];
280 };
281
282 static void *
283 ovsthread_wrapper(void *aux_)
284 {
285     static atomic_uint next_id = ATOMIC_VAR_INIT(1);
286
287     struct ovsthread_aux *auxp = aux_;
288     struct ovsthread_aux aux;
289     unsigned int id;
290
291     atomic_add(&next_id, 1, &id);
292     *ovsthread_id_get() = id;
293
294     aux = *auxp;
295     free(auxp);
296
297     /* The order of the following calls is important, because
298      * ovsrcu_quiesce_end() saves a copy of the thread name. */
299     set_subprogram_name("%s%u", aux.name, id);
300     ovsrcu_quiesce_end();
301
302     return aux.start(aux.arg);
303 }
304
305 /* Starts a thread that calls 'start(arg)'.  Sets the thread's name to 'name'
306  * (suffixed by its ovsthread_id()).  Returns the new thread's pthread_t. */
307 pthread_t
308 ovs_thread_create(const char *name, void *(*start)(void *), void *arg)
309 {
310     struct ovsthread_aux *aux;
311     pthread_t thread;
312     int error;
313
314     forbid_forking("multiple threads exist");
315     multithreaded = true;
316     ovsrcu_quiesce_end();
317
318     aux = xmalloc(sizeof *aux);
319     aux->start = start;
320     aux->arg = arg;
321     ovs_strlcpy(aux->name, name, sizeof aux->name);
322
323     error = pthread_create(&thread, NULL, ovsthread_wrapper, aux);
324     if (error) {
325         ovs_abort(error, "pthread_create failed");
326     }
327     return thread;
328 }
329 \f
330 bool
331 ovsthread_once_start__(struct ovsthread_once *once)
332 {
333     ovs_mutex_lock(&once->mutex);
334     if (!ovsthread_once_is_done__(once)) {
335         return false;
336     }
337     ovs_mutex_unlock(&once->mutex);
338     return true;
339 }
340
341 void
342 ovsthread_once_done(struct ovsthread_once *once)
343 {
344     atomic_store(&once->done, true);
345     ovs_mutex_unlock(&once->mutex);
346 }
347 \f
348 bool
349 single_threaded(void)
350 {
351     return !multithreaded;
352 }
353
354 /* Asserts that the process has not yet created any threads (beyond the initial
355  * thread).
356  *
357  * ('where' is used in logging.  Commonly one would use
358  * assert_single_threaded() to automatically provide the caller's source file
359  * and line number for 'where'.) */
360 void
361 assert_single_threaded_at(const char *where)
362 {
363     if (multithreaded) {
364         VLOG_FATAL("%s: attempted operation not allowed when multithreaded",
365                    where);
366     }
367 }
368
369 #ifndef _WIN32
370 /* Forks the current process (checking that this is allowed).  Aborts with
371  * VLOG_FATAL if fork() returns an error, and otherwise returns the value
372  * returned by fork().
373  *
374  * ('where' is used in logging.  Commonly one would use xfork() to
375  * automatically provide the caller's source file and line number for
376  * 'where'.) */
377 pid_t
378 xfork_at(const char *where)
379 {
380     pid_t pid;
381
382     if (must_not_fork) {
383         VLOG_FATAL("%s: attempted to fork but forking not allowed (%s)",
384                    where, must_not_fork);
385     }
386
387     pid = fork();
388     if (pid < 0) {
389         VLOG_FATAL("%s: fork failed (%s)", where, ovs_strerror(errno));
390     }
391     return pid;
392 }
393 #endif
394
395 /* Notes that the process must not call fork() from now on, for the specified
396  * 'reason'.  (The process may still fork() if it execs itself immediately
397  * afterward.) */
398 void
399 forbid_forking(const char *reason)
400 {
401     ovs_assert(reason != NULL);
402     must_not_fork = reason;
403 }
404
405 /* Returns true if the process is allowed to fork, false otherwise. */
406 bool
407 may_fork(void)
408 {
409     return !must_not_fork;
410 }
411 \f
412 /* ovsthread_stats. */
413
414 void
415 ovsthread_stats_init(struct ovsthread_stats *stats)
416 {
417     int i;
418
419     ovs_mutex_init(&stats->mutex);
420     for (i = 0; i < ARRAY_SIZE(stats->buckets); i++) {
421         stats->buckets[i] = NULL;
422     }
423 }
424
425 void
426 ovsthread_stats_destroy(struct ovsthread_stats *stats)
427 {
428     ovs_mutex_destroy(&stats->mutex);
429 }
430
431 void *
432 ovsthread_stats_bucket_get(struct ovsthread_stats *stats,
433                            void *(*new_bucket)(void))
434 {
435     unsigned int idx = ovsthread_id_self() & (ARRAY_SIZE(stats->buckets) - 1);
436     void *bucket = stats->buckets[idx];
437     if (!bucket) {
438         ovs_mutex_lock(&stats->mutex);
439         bucket = stats->buckets[idx];
440         if (!bucket) {
441             bucket = stats->buckets[idx] = new_bucket();
442         }
443         ovs_mutex_unlock(&stats->mutex);
444     }
445     return bucket;
446 }
447
448 size_t
449 ovs_thread_stats_next_bucket(const struct ovsthread_stats *stats, size_t i)
450 {
451     for (; i < ARRAY_SIZE(stats->buckets); i++) {
452         if (stats->buckets[i]) {
453             break;
454         }
455     }
456     return i;
457 }
458
459 \f
460 /* Parses /proc/cpuinfo for the total number of physical cores on this system
461  * across all CPU packages, not counting hyper-threads.
462  *
463  * Sets *n_cores to the total number of cores on this system, or 0 if the
464  * number cannot be determined. */
465 static void
466 parse_cpuinfo(long int *n_cores)
467 {
468     static const char file_name[] = "/proc/cpuinfo";
469     char line[128];
470     uint64_t cpu = 0; /* Support up to 64 CPU packages on a single system. */
471     long int cores = 0;
472     FILE *stream;
473
474     stream = fopen(file_name, "r");
475     if (!stream) {
476         VLOG_DBG("%s: open failed (%s)", file_name, ovs_strerror(errno));
477         return;
478     }
479
480     while (fgets(line, sizeof line, stream)) {
481         unsigned int id;
482
483         /* Find the next CPU package. */
484         if (ovs_scan(line, "physical id%*[^:]: %u", &id)) {
485             if (id > 63) {
486                 VLOG_WARN("Counted over 64 CPU packages on this system. "
487                           "Parsing %s for core count may be inaccurate.",
488                           file_name);
489                 cores = 0;
490                 break;
491             }
492
493             if (cpu & (1 << id)) {
494                 /* We've already counted this package's cores. */
495                 continue;
496             }
497             cpu |= 1 << id;
498
499             /* Find the number of cores for this package. */
500             while (fgets(line, sizeof line, stream)) {
501                 int count;
502
503                 if (ovs_scan(line, "cpu cores%*[^:]: %u", &count)) {
504                     cores += count;
505                     break;
506                 }
507             }
508         }
509     }
510     fclose(stream);
511
512     *n_cores = cores;
513 }
514
515 /* Returns the total number of cores on this system, or 0 if the number cannot
516  * be determined.
517  *
518  * Tries not to count hyper-threads, but may be inaccurate - particularly on
519  * platforms that do not provide /proc/cpuinfo, but also if /proc/cpuinfo is
520  * formatted different to the layout that parse_cpuinfo() expects. */
521 int
522 count_cpu_cores(void)
523 {
524     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
525     static long int n_cores;
526
527     if (ovsthread_once_start(&once)) {
528 #ifndef _WIN32
529         parse_cpuinfo(&n_cores);
530         if (!n_cores) {
531             n_cores = sysconf(_SC_NPROCESSORS_ONLN);
532         }
533 #else
534         SYSTEM_INFO sysinfo;
535         GetSystemInfo(&sysinfo);
536         n_cores = sysinfo.dwNumberOfProcessors;
537 #endif
538         ovsthread_once_done(&once);
539     }
540
541     return n_cores > 0 ? n_cores : 0;
542 }
543 \f
544 /* ovsthread_key. */
545
546 #define L1_SIZE 1024
547 #define L2_SIZE 1024
548 #define MAX_KEYS (L1_SIZE * L2_SIZE)
549
550 /* A piece of thread-specific data. */
551 struct ovsthread_key {
552     struct list list_node;      /* In 'inuse_keys' or 'free_keys'. */
553     void (*destructor)(void *); /* Called at thread exit. */
554
555     /* Indexes into the per-thread array in struct ovsthread_key_slots.
556      * This key's data is stored in p1[index / L2_SIZE][index % L2_SIZE]. */
557     unsigned int index;
558 };
559
560 /* Per-thread data structure. */
561 struct ovsthread_key_slots {
562     struct list list_node;      /* In 'slots_list'. */
563     void **p1[L1_SIZE];
564 };
565
566 /* Contains "struct ovsthread_key_slots *". */
567 static pthread_key_t tsd_key;
568
569 /* Guards data structures below. */
570 static struct ovs_mutex key_mutex = OVS_MUTEX_INITIALIZER;
571
572 /* 'inuse_keys' holds "struct ovsthread_key"s that have been created and not
573  * yet destroyed.
574  *
575  * 'free_keys' holds "struct ovsthread_key"s that have been deleted and are
576  * ready for reuse.  (We keep them around only to be able to easily locate
577  * free indexes.)
578  *
579  * Together, 'inuse_keys' and 'free_keys' hold an ovsthread_key for every index
580  * from 0 to n_keys - 1, inclusive. */
581 static struct list inuse_keys OVS_GUARDED_BY(key_mutex)
582     = LIST_INITIALIZER(&inuse_keys);
583 static struct list free_keys OVS_GUARDED_BY(key_mutex)
584     = LIST_INITIALIZER(&free_keys);
585 static unsigned int n_keys OVS_GUARDED_BY(key_mutex);
586
587 /* All existing struct ovsthread_key_slots. */
588 static struct list slots_list OVS_GUARDED_BY(key_mutex)
589     = LIST_INITIALIZER(&slots_list);
590
591 static void *
592 clear_slot(struct ovsthread_key_slots *slots, unsigned int index)
593 {
594     void **p2 = slots->p1[index / L2_SIZE];
595     if (p2) {
596         void **valuep = &p2[index % L2_SIZE];
597         void *value = *valuep;
598         *valuep = NULL;
599         return value;
600     } else {
601         return NULL;
602     }
603 }
604
605 static void
606 ovsthread_key_destruct__(void *slots_)
607 {
608     struct ovsthread_key_slots *slots = slots_;
609     struct ovsthread_key *key;
610     unsigned int n;
611     int i;
612
613     ovs_mutex_lock(&key_mutex);
614     list_remove(&slots->list_node);
615     LIST_FOR_EACH (key, list_node, &inuse_keys) {
616         void *value = clear_slot(slots, key->index);
617         if (value && key->destructor) {
618             key->destructor(value);
619         }
620     }
621     n = n_keys;
622     ovs_mutex_unlock(&key_mutex);
623
624     for (i = 0; i < n / L2_SIZE; i++) {
625         free(slots->p1[i]);
626     }
627     free(slots);
628 }
629
630 /* Initializes '*keyp' as a thread-specific data key.  The data items are
631  * initially null in all threads.
632  *
633  * If a thread exits with non-null data, then 'destructor', if nonnull, will be
634  * called passing the final data value as its argument.  'destructor' must not
635  * call any thread-specific data functions in this API.
636  *
637  * This function is similar to xpthread_key_create(). */
638 void
639 ovsthread_key_create(ovsthread_key_t *keyp, void (*destructor)(void *))
640 {
641     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
642     struct ovsthread_key *key;
643
644     if (ovsthread_once_start(&once)) {
645         xpthread_key_create(&tsd_key, ovsthread_key_destruct__);
646         ovsthread_once_done(&once);
647     }
648
649     ovs_mutex_lock(&key_mutex);
650     if (list_is_empty(&free_keys)) {
651         key = xmalloc(sizeof *key);
652         key->index = n_keys++;
653         if (key->index >= MAX_KEYS) {
654             abort();
655         }
656     } else {
657         key = CONTAINER_OF(list_pop_back(&free_keys),
658                             struct ovsthread_key, list_node);
659     }
660     list_push_back(&inuse_keys, &key->list_node);
661     key->destructor = destructor;
662     ovs_mutex_unlock(&key_mutex);
663
664     *keyp = key;
665 }
666
667 /* Frees 'key'.  The destructor supplied to ovsthread_key_create(), if any, is
668  * not called.
669  *
670  * This function is similar to xpthread_key_delete(). */
671 void
672 ovsthread_key_delete(ovsthread_key_t key)
673 {
674     struct ovsthread_key_slots *slots;
675
676     ovs_mutex_lock(&key_mutex);
677
678     /* Move 'key' from 'inuse_keys' to 'free_keys'. */
679     list_remove(&key->list_node);
680     list_push_back(&free_keys, &key->list_node);
681
682     /* Clear this slot in all threads. */
683     LIST_FOR_EACH (slots, list_node, &slots_list) {
684         clear_slot(slots, key->index);
685     }
686
687     ovs_mutex_unlock(&key_mutex);
688 }
689
690 static void **
691 ovsthread_key_lookup__(const struct ovsthread_key *key)
692 {
693     struct ovsthread_key_slots *slots;
694     void **p2;
695
696     slots = pthread_getspecific(tsd_key);
697     if (!slots) {
698         slots = xzalloc(sizeof *slots);
699
700         ovs_mutex_lock(&key_mutex);
701         pthread_setspecific(tsd_key, slots);
702         list_push_back(&slots_list, &slots->list_node);
703         ovs_mutex_unlock(&key_mutex);
704     }
705
706     p2 = slots->p1[key->index / L2_SIZE];
707     if (!p2) {
708         p2 = xzalloc(L2_SIZE * sizeof *p2);
709         slots->p1[key->index / L2_SIZE] = p2;
710     }
711
712     return &p2[key->index % L2_SIZE];
713 }
714
715 /* Sets the value of thread-specific data item 'key', in the current thread, to
716  * 'value'.
717  *
718  * This function is similar to pthread_setspecific(). */
719 void
720 ovsthread_setspecific(ovsthread_key_t key, const void *value)
721 {
722     *ovsthread_key_lookup__(key) = CONST_CAST(void *, value);
723 }
724
725 /* Returns the value of thread-specific data item 'key' in the current thread.
726  *
727  * This function is similar to pthread_getspecific(). */
728 void *
729 ovsthread_getspecific(ovsthread_key_t key)
730 {
731     return *ovsthread_key_lookup__(key);
732 }
733 #endif