Coverage Report

Created: 2022-07-08 09:39

/home/mdboom/Work/builds/cpython/Python/thread.c
Line
Count
Source (jump to first uncovered line)
1
2
/* Thread package.
3
   This is intended to be usable independently from Python.
4
   The implementation for system foobar is in a file thread_foobar.h
5
   which is included by this file dependent on config settings.
6
   Stuff shared by all thread_*.h files is collected here. */
7
8
#include "Python.h"
9
#include "pycore_pystate.h"       // _PyInterpreterState_GET()
10
#include "pycore_structseq.h"     // _PyStructSequence_FiniType()
11
12
#ifndef _POSIX_THREADS
13
/* This means pthreads are not implemented in libc headers, hence the macro
14
   not present in unistd.h. But they still can be implemented as an external
15
   library (e.g. gnu pth in pthread emulation) */
16
# ifdef HAVE_PTHREAD_H
17
#  include <pthread.h> /* _POSIX_THREADS */
18
# endif
19
#endif
20
21
#ifndef DONT_HAVE_STDIO_H
22
#include <stdio.h>
23
#endif
24
25
#include <stdlib.h>
26
27
#ifndef _POSIX_THREADS
28
29
/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
30
   enough of the Posix threads package is implemented to support python
31
   threads.
32
33
   This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
34
   a check of __ia64 to verify that we're running on an ia64 system instead
35
   of a pa-risc system.
36
*/
37
#ifdef __hpux
38
#ifdef _SC_THREADS
39
#define _POSIX_THREADS
40
#endif
41
#endif
42
43
#endif /* _POSIX_THREADS */
44
45
static int initialized;
46
47
static void PyThread__init_thread(void); /* Forward */
48
49
void
50
PyThread_init_thread(void)
51
{
52
    if (initialized)
  Branch (52:9): [True: 385, False: 73]
53
        return;
54
    initialized = 1;
55
    PyThread__init_thread();
56
}
57
58
#if defined(_POSIX_THREADS)
59
#   define PYTHREAD_NAME "pthread"
60
#   include "thread_pthread.h"
61
#elif defined(NT_THREADS)
62
#   define PYTHREAD_NAME "nt"
63
#   include "thread_nt.h"
64
#else
65
#   error "Require native threads. See https://bugs.python.org/issue31370"
66
#endif
67
68
69
/* return the current thread stack size */
70
size_t
71
PyThread_get_stacksize(void)
72
{
73
    return _PyInterpreterState_GET()->threads.stacksize;
74
}
75
76
/* Only platforms defining a THREAD_SET_STACKSIZE() macro
77
   in thread_<platform>.h support changing the stack size.
78
   Return 0 if stack size is valid,
79
      -1 if stack size value is invalid,
80
      -2 if setting stack size is not supported. */
81
int
82
PyThread_set_stacksize(size_t size)
83
{
84
#if defined(THREAD_SET_STACKSIZE)
85
    return THREAD_SET_STACKSIZE(size);
86
#else
87
    return -2;
88
#endif
89
}
90
91
92
/* Thread Specific Storage (TSS) API
93
94
   Cross-platform components of TSS API implementation.
95
*/
96
97
Py_tss_t *
98
PyThread_tss_alloc(void)
99
{
100
    Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t));
101
    if (new_key == NULL) {
  Branch (101:9): [True: 0, False: 1]
102
        return NULL;
103
    }
104
    new_key->_is_initialized = 0;
105
    return new_key;
106
}
107
108
void
109
PyThread_tss_free(Py_tss_t *key)
110
{
111
    if (key != NULL) {
  Branch (111:9): [True: 1, False: 0]
112
        PyThread_tss_delete(key);
113
        PyMem_RawFree((void *)key);
114
    }
115
}
116
117
int
118
PyThread_tss_is_created(Py_tss_t *key)
119
{
120
    assert(key != NULL);
121
    return key->_is_initialized;
122
}
123
124
125
PyDoc_STRVAR(threadinfo__doc__,
126
"sys.thread_info\n\
127
\n\
128
A named tuple holding information about the thread implementation.");
129
130
static PyStructSequence_Field threadinfo_fields[] = {
131
    {"name",    "name of the thread implementation"},
132
    {"lock",    "name of the lock implementation"},
133
    {"version", "name and version of the thread library"},
134
    {0}
135
};
136
137
static PyStructSequence_Desc threadinfo_desc = {
138
    "sys.thread_info",           /* name */
139
    threadinfo__doc__,           /* doc */
140
    threadinfo_fields,           /* fields */
141
    3
142
};
143
144
static PyTypeObject ThreadInfoType;
145
146
PyObject*
147
PyThread_GetInfo(void)
148
{
149
    PyObject *threadinfo, *value;
150
    int pos = 0;
151
#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
152
     && defined(_CS_GNU_LIBPTHREAD_VERSION))
153
    char buffer[255];
154
    int len;
155
#endif
156
157
    if (ThreadInfoType.tp_name == 0) {
  Branch (157:9): [True: 107, False: 171]
158
        if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0)
  Branch (158:13): [True: 0, False: 107]
159
            return NULL;
160
    }
161
162
    threadinfo = PyStructSequence_New(&ThreadInfoType);
163
    if (threadinfo == NULL)
  Branch (163:9): [True: 0, False: 278]
164
        return NULL;
165
166
    value = PyUnicode_FromString(PYTHREAD_NAME);
167
    if (value == NULL) {
  Branch (167:9): [True: 0, False: 278]
168
        Py_DECREF(threadinfo);
169
        return NULL;
170
    }
171
    PyStructSequence_SET_ITEM(threadinfo, pos++, value);
172
173
#ifdef _POSIX_THREADS
174
#ifdef USE_SEMAPHORES
175
    value = PyUnicode_FromString("semaphore");
176
#else
177
    value = PyUnicode_FromString("mutex+cond");
178
#endif
179
    if (value == NULL) {
  Branch (179:9): [True: 0, False: 278]
180
        Py_DECREF(threadinfo);
181
        return NULL;
182
    }
183
#else
184
    Py_INCREF(Py_None);
185
    value = Py_None;
186
#endif
187
    PyStructSequence_SET_ITEM(threadinfo, pos++, value);
188
189
#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
190
     && defined(_CS_GNU_LIBPTHREAD_VERSION))
191
    value = NULL;
192
    len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
193
    if (1 < len && (size_t)len < sizeof(buffer)) {
  Branch (193:9): [True: 278, False: 0]
  Branch (193:20): [True: 278, False: 0]
194
        value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
195
        if (value == NULL)
  Branch (195:13): [True: 0, False: 278]
196
            PyErr_Clear();
197
    }
198
    if (value == NULL)
  Branch (198:9): [True: 0, False: 278]
199
#endif
200
    {
201
        Py_INCREF(Py_None);
202
        value = Py_None;
203
    }
204
    PyStructSequence_SET_ITEM(threadinfo, pos++, value);
205
    return threadinfo;
206
}
207
208
209
void
210
_PyThread_FiniType(PyInterpreterState *interp)
211
{
212
    if (!_Py_IsMainInterpreter(interp)) {
  Branch (212:9): [True: 169, False: 103]
213
        return;
214
    }
215
216
    _PyStructSequence_FiniType(&ThreadInfoType);
217
}