Coverage Report

Created: 2026-06-14 06:25

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