Coverage Report

Created: 2020-09-15 12:33

/Users/buildslave/jenkins/workspace/coverage/llvm-project/libcxx/src/thread.cpp
Line
Count
Source (jump to first uncovered line)
1
//===------------------------- thread.cpp----------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "__config"
10
#ifndef _LIBCPP_HAS_NO_THREADS
11
12
#include "thread"
13
#include "exception"
14
#include "vector"
15
#include "future"
16
#include "limits"
17
#include <sys/types.h>
18
19
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
20
# include <sys/param.h>
21
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
22
#   include <sys/sysctl.h>
23
# endif
24
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
25
26
#if __has_include(<unistd.h>)
27
#include <unistd.h>
28
#endif
29
30
#if defined(__NetBSD__)
31
#pragma weak pthread_create // Do not create libpthread dependency
32
#endif
33
34
#if defined(_LIBCPP_WIN32API)
35
#include <windows.h>
36
#endif
37
38
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
39
#pragma comment(lib, "pthread")
40
#endif
41
42
_LIBCPP_BEGIN_NAMESPACE_STD
43
44
thread::~thread()
45
59
{
46
59
    if (!__libcpp_thread_isnull(&__t_))
47
0
        terminate();
48
59
}
49
50
void
51
thread::join()
52
38
{
53
38
    int ec = EINVAL;
54
38
    if (!__libcpp_thread_isnull(&__t_))
55
38
    {
56
38
        ec = __libcpp_thread_join(&__t_);
57
38
        if (ec == 0)
58
38
            __t_ = _LIBCPP_NULL_THREAD;
59
38
    }
60
38
61
38
    if (ec)
62
0
        __throw_system_error(ec, "thread::join failed");
63
38
}
64
65
void
66
thread::detach()
67
8
{
68
8
    int ec = EINVAL;
69
8
    if (!__libcpp_thread_isnull(&__t_))
70
8
    {
71
8
        ec = __libcpp_thread_detach(&__t_);
72
8
        if (ec == 0)
73
8
            __t_ = _LIBCPP_NULL_THREAD;
74
8
    }
75
8
76
8
    if (ec)
77
0
        __throw_system_error(ec, "thread::detach failed");
78
8
}
79
80
unsigned
81
thread::hardware_concurrency() _NOEXCEPT
82
2
{
83
2
#if defined(CTL_HW) && defined(HW_NCPU)
84
2
    unsigned n;
85
2
    int mib[2] = {CTL_HW, HW_NCPU};
86
2
    std::size_t s = sizeof(n);
87
2
    sysctl(mib, 2, &n, &s, 0, 0);
88
2
    return n;
89
#elif defined(_SC_NPROCESSORS_ONLN)
90
    long result = sysconf(_SC_NPROCESSORS_ONLN);
91
    // sysconf returns -1 if the name is invalid, the option does not exist or
92
    // does not have a definite limit.
93
    // if sysconf returns some other negative number, we have no idea
94
    // what is going on. Default to something safe.
95
    if (result < 0)
96
        return 0;
97
    return static_cast<unsigned>(result);
98
#elif defined(_LIBCPP_WIN32API)
99
    SYSTEM_INFO info;
100
    GetSystemInfo(&info);
101
    return info.dwNumberOfProcessors;
102
#else  // defined(CTL_HW) && defined(HW_NCPU)
103
    // TODO: grovel through /proc or check cpuid on x86 and similar
104
    // instructions on other architectures.
105
#   if defined(_LIBCPP_WARNING)
106
        _LIBCPP_WARNING("hardware_concurrency not yet implemented")
107
#   else
108
#       warning hardware_concurrency not yet implemented
109
#   endif
110
    return 0;  // Means not computable [thread.thread.static]
111
#endif  // defined(CTL_HW) && defined(HW_NCPU)
112
2
}
113
114
namespace this_thread
115
{
116
117
void
118
sleep_for(const chrono::nanoseconds& ns)
119
5
{
120
5
    if (ns > chrono::nanoseconds::zero())
121
5
    {
122
5
        __libcpp_thread_sleep_for(ns);
123
5
    }
124
5
}
125
126
}  // this_thread
127
128
__thread_specific_ptr<__thread_struct>&
129
__thread_local_data()
130
56
{
131
56
    static __thread_specific_ptr<__thread_struct> __p;
132
56
    return __p;
133
56
}
134
135
// __thread_struct_imp
136
137
template <class T>
138
class _LIBCPP_HIDDEN __hidden_allocator
139
{
140
public:
141
    typedef T  value_type;
142
143
    T* allocate(size_t __n)
144
0
        {return static_cast<T*>(::operator new(__n * sizeof(T)));}
Unexecuted instantiation: std::__1::__hidden_allocator<std::__1::pair<std::__1::condition_variable*, std::__1::mutex*> >::allocate(unsigned long)
Unexecuted instantiation: std::__1::__hidden_allocator<std::__1::__assoc_sub_state*>::allocate(unsigned long)
145
0
    void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));}
Unexecuted instantiation: std::__1::__hidden_allocator<std::__1::__assoc_sub_state*>::deallocate(std::__1::__assoc_sub_state**, unsigned long)
Unexecuted instantiation: std::__1::__hidden_allocator<std::__1::pair<std::__1::condition_variable*, std::__1::mutex*> >::deallocate(std::__1::pair<std::__1::condition_variable*, std::__1::mutex*>*, unsigned long)
146
147
0
    size_t max_size() const {return size_t(~0) / sizeof(T);}
Unexecuted instantiation: std::__1::__hidden_allocator<std::__1::pair<std::__1::condition_variable*, std::__1::mutex*> >::max_size() const
Unexecuted instantiation: std::__1::__hidden_allocator<std::__1::__assoc_sub_state*>::max_size() const
148
};
149
150
class _LIBCPP_HIDDEN __thread_struct_imp
151
{
152
    typedef vector<__assoc_sub_state*,
153
                          __hidden_allocator<__assoc_sub_state*> > _AsyncStates;
154
    typedef vector<pair<condition_variable*, mutex*>,
155
               __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
156
157
    _AsyncStates async_states_;
158
    _Notify notify_;
159
160
    __thread_struct_imp(const __thread_struct_imp&);
161
    __thread_struct_imp& operator=(const __thread_struct_imp&);
162
public:
163
56
    __thread_struct_imp() {}
164
    ~__thread_struct_imp();
165
166
    void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
167
    void __make_ready_at_thread_exit(__assoc_sub_state* __s);
168
};
169
170
__thread_struct_imp::~__thread_struct_imp()
171
56
{
172
56
    for (_Notify::iterator i = notify_.begin(), e = notify_.end();
173
56
            i != e; 
++i0
)
174
0
    {
175
0
        i->second->unlock();
176
0
        i->first->notify_all();
177
0
    }
178
56
    for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
179
56
            i != e; 
++i0
)
180
0
    {
181
0
        (*i)->__make_ready();
182
0
        (*i)->__release_shared();
183
0
    }
184
56
}
185
186
void
187
__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
188
0
{
189
0
    notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
190
0
}
191
192
void
193
__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
194
0
{
195
0
    async_states_.push_back(__s);
196
0
    __s->__add_shared();
197
0
}
198
199
// __thread_struct
200
201
__thread_struct::__thread_struct()
202
    : __p_(new __thread_struct_imp)
203
56
{
204
56
}
205
206
__thread_struct::~__thread_struct()
207
56
{
208
56
    delete __p_;
209
56
}
210
211
void
212
__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
213
0
{
214
0
    __p_->notify_all_at_thread_exit(cv, m);
215
0
}
216
217
void
218
__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
219
0
{
220
0
    __p_->__make_ready_at_thread_exit(__s);
221
0
}
222
223
_LIBCPP_END_NAMESPACE_STD
224
225
#endif // !_LIBCPP_HAS_NO_THREADS