Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/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"
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
42
{
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
42
    if (initialized)
74
28
        return;
75
14
    initialized = 1;
76
14
    dprintf(("PyThread_init_thread called\n"));
77
14
    PyThread__init_thread();
78
14
}
79
80
#if defined(_POSIX_THREADS)
81
14
#   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
14
{
171
14
    PyObject *threadinfo, *value;
172
14
    int pos = 0;
173
14
#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
174
14
     && defined(_CS_GNU_LIBPTHREAD_VERSION))
175
14
    char buffer[255];
176
14
    int len;
177
14
#endif
178
179
14
    if (ThreadInfoType.tp_name == 0) {
180
14
        if (PyStructSequence_InitType2(&ThreadInfoType, &threadinfo_desc) < 0)
181
0
            return NULL;
182
14
    }
183
184
14
    threadinfo = PyStructSequence_New(&ThreadInfoType);
185
14
    if (threadinfo == NULL)
186
0
        return NULL;
187
188
14
    value = PyUnicode_FromString(PYTHREAD_NAME);
189
14
    if (value == NULL) {
190
0
        Py_DECREF(threadinfo);
191
0
        return NULL;
192
0
    }
193
14
    PyStructSequence_SET_ITEM(threadinfo, pos++, value);
194
195
14
#ifdef _POSIX_THREADS
196
14
#ifdef USE_SEMAPHORES
197
14
    value = PyUnicode_FromString("semaphore");
198
#else
199
    value = PyUnicode_FromString("mutex+cond");
200
#endif
201
14
    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
14
    PyStructSequence_SET_ITEM(threadinfo, pos++, value);
210
211
14
#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \
212
14
     && defined(_CS_GNU_LIBPTHREAD_VERSION))
213
14
    value = NULL;
214
14
    len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
215
14
    if (1 < len && (size_t)len < sizeof(buffer)) {
216
14
        value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
217
14
        if (value == NULL)
218
0
            PyErr_Clear();
219
14
    }
220
14
    if (value == NULL)
221
0
#endif
222
0
    {
223
0
        Py_INCREF(Py_None);
224
0
        value = Py_None;
225
0
    }
226
14
    PyStructSequence_SET_ITEM(threadinfo, pos++, value);
227
14
    return threadinfo;
228
14
}