source: rtems-libbsd/freebsd/lib/libc/resolv/mtctxres.c @ f41a394

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f41a394 was d48955b, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 6, 2013 at 8:02:16 AM

Add and use <machine/rtems-bsd-user-space.h>

  • Property mode set to 100644
File size: 2.8 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3#include <sys/cdefs.h>
4__FBSDID("$FreeBSD$");
5
6#include <port_before.h>
7#ifdef DO_PTHREADS
8#include <pthread.h>
9#ifdef _LIBC
10#include <pthread_np.h>
11#endif
12#endif
13#include <errno.h>
14#include <netdb.h>
15#include <stdlib.h>
16#include <string.h>
17#include <resolv_mt.h>
18#include <port_after.h>
19
20#ifdef DO_PTHREADS
21static pthread_key_t    key;
22static int              mt_key_initialized = 0;
23
24static int              __res_init_ctx(void);
25static void             __res_destroy_ctx(void *);
26
27#if defined(sun) && !defined(__GNUC__)
28#pragma init    (_mtctxres_init)
29#endif
30#endif
31
32static mtctxres_t       sharedctx;
33
34#ifdef DO_PTHREADS
35/*
36 * Initialize the TSD key. By doing this at library load time, we're
37 * implicitly running without interference from other threads, so there's
38 * no need for locking.
39 */
40static void
41_mtctxres_init(void) {
42        int pthread_keycreate_ret;
43
44        pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
45        if (pthread_keycreate_ret == 0)
46                mt_key_initialized = 1;
47}
48#endif
49
50#ifndef _LIBC
51/*
52 * To support binaries that used the private MT-safe interface in
53 * Solaris 8, we still need to provide the __res_enable_mt()
54 * and __res_disable_mt() entry points. They're do-nothing routines.
55 */
56int
57__res_enable_mt(void) {
58        return (-1);
59}
60
61int
62__res_disable_mt(void) {
63        return (0);
64}
65#endif
66
67#ifdef DO_PTHREADS
68static int
69__res_init_ctx(void) {
70
71        mtctxres_t      *mt;
72        int             ret;
73
74
75        if (pthread_getspecific(key) != 0) {
76                /* Already exists */
77                return (0);
78        }
79
80        if ((mt = malloc(sizeof (mtctxres_t))) == 0) {
81                errno = ENOMEM;
82                return (-1);
83        }
84
85        memset(mt, 0, sizeof (mtctxres_t));
86
87        if ((ret = pthread_setspecific(key, mt)) != 0) {
88                free(mt);
89                errno = ret;
90                return (-1);
91        }
92
93        return (0);
94}
95
96static void
97__res_destroy_ctx(void *value) {
98
99        mtctxres_t      *mt = (mtctxres_t *)value;
100
101        if (mt != 0)
102                free(mt);
103}
104#endif
105
106mtctxres_t *
107___mtctxres(void) {
108#ifdef DO_PTHREADS
109        mtctxres_t      *mt;
110
111#ifdef _LIBC
112#ifndef __rtems__
113        if (pthread_main_np() != 0)
114                return (&sharedctx);
115#endif /* __rtems__ */
116#endif
117
118        /*
119         * This if clause should only be executed if we are linking
120         * statically.  When linked dynamically _mtctxres_init() should
121         * be called at binding time due the #pragma above.
122         */
123        if (!mt_key_initialized) {
124                static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
125                if (pthread_mutex_lock(&keylock) == 0) {
126                        _mtctxres_init();
127                        (void) pthread_mutex_unlock(&keylock);
128                }
129        }
130
131        /*
132         * If we have already been called in this thread return the existing
133         * context.  Otherwise recreat a new context and return it.  If
134         * that fails return a global context.
135         */
136        if (mt_key_initialized) {
137                if (((mt = pthread_getspecific(key)) != 0) ||
138                    (__res_init_ctx() == 0 &&
139                     (mt = pthread_getspecific(key)) != 0)) {
140                        return (mt);
141                }
142        }
143#endif
144        return (&sharedctx);
145}
Note: See TracBrowser for help on using the repository browser.