Skip to content

Commit 985b47a

Browse files
Initial version
1 parent dea4083 commit 985b47a

13 files changed

+432
-3
lines changed

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ struct _Py_global_strings {
305305
STRUCT_FOR_ID(alias)
306306
STRUCT_FOR_ID(align)
307307
STRUCT_FOR_ID(all)
308+
STRUCT_FOR_ID(all_interpreters)
308309
STRUCT_FOR_ID(all_threads)
309310
STRUCT_FOR_ID(allow_code)
310311
STRUCT_FOR_ID(alphabet)

Include/internal/pycore_runtime_init_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/Setup

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ PYTHONPATH=$(COREPYTHONPATH)
285285

286286
#*shared*
287287
#_ctypes_test _ctypes/_ctypes_test.c
288-
#_remote_debugging _remote_debugging/module.c _remote_debugging/object_reading.c _remote_debugging/code_objects.c _remote_debugging/frames.c _remote_debugging/threads.c _remote_debugging/asyncio.c
288+
#_remote_debugging _remote_debugging/module.c _remote_debugging/object_reading.c _remote_debugging/code_objects.c _remote_debugging/frames.c _remote_debugging/threads.c _remote_debugging/asyncio.c _remote_debugging/interpreters.c
289289
#_testcapi _testcapimodule.c
290290
#_testimportmultiple _testimportmultiple.c
291291
#_testmultiphase _testmultiphase.c

Modules/Setup.stdlib.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
@MODULE__PICKLE_TRUE@_pickle _pickle.c
4242
@MODULE__QUEUE_TRUE@_queue _queuemodule.c
4343
@MODULE__RANDOM_TRUE@_random _randommodule.c
44-
@MODULE__REMOTE_DEBUGGING_TRUE@_remote_debugging _remote_debugging/module.c _remote_debugging/object_reading.c _remote_debugging/code_objects.c _remote_debugging/frames.c _remote_debugging/frame_cache.c _remote_debugging/threads.c _remote_debugging/asyncio.c _remote_debugging/binary_io_writer.c _remote_debugging/binary_io_reader.c _remote_debugging/subprocess.c
44+
@MODULE__REMOTE_DEBUGGING_TRUE@_remote_debugging _remote_debugging/module.c _remote_debugging/object_reading.c _remote_debugging/code_objects.c _remote_debugging/frames.c _remote_debugging/frame_cache.c _remote_debugging/threads.c _remote_debugging/asyncio.c _remote_debugging/binary_io_writer.c _remote_debugging/binary_io_reader.c _remote_debugging/subprocess.c _remote_debugging/interpreters.c
4545
@MODULE__STRUCT_TRUE@_struct _struct.c
4646

4747
# build supports subinterpreters

Modules/_remote_debugging/_remote_debugging.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,12 @@ typedef struct {
345345
size_t count;
346346
} StackChunkList;
347347

348+
typedef struct {
349+
proc_handle_t handle;
350+
uintptr_t runtime_start_address;
351+
struct _Py_DebugOffsets debug_offsets;
352+
} RuntimeOffsets;
353+
348354
/*
349355
* Context for frame chain traversal operations.
350356
*/
@@ -389,6 +395,14 @@ typedef int (*set_entry_processor_func)(
389395
void *context
390396
);
391397

398+
typedef int (*interpreter_processor_func)(
399+
RuntimeOffsets *offsets,
400+
uintptr_t interpreter_state_addr,
401+
unsigned long iid,
402+
void *context
403+
);
404+
405+
392406
/* ============================================================================
393407
* STRUCTSEQ DESCRIPTORS (extern declarations)
394408
* ============================================================================ */
@@ -586,6 +600,17 @@ extern void _Py_RemoteDebug_InitThreadsState(RemoteUnwinderObject *unwinder, _Py
586600
extern int _Py_RemoteDebug_StopAllThreads(RemoteUnwinderObject *unwinder, _Py_RemoteDebug_ThreadsState *st);
587601
extern void _Py_RemoteDebug_ResumeAllThreads(RemoteUnwinderObject *unwinder, _Py_RemoteDebug_ThreadsState *st);
588602

603+
/* ============================================================================
604+
* INTERPRETER FUNCTION DECLARATIONS
605+
* ============================================================================ */
606+
607+
extern int
608+
iterate_interpreters(
609+
RuntimeOffsets *offsets,
610+
interpreter_processor_func processor,
611+
void *context
612+
);
613+
589614
/* ============================================================================
590615
* ASYNCIO FUNCTION DECLARATIONS
591616
* ============================================================================ */

Modules/_remote_debugging/clinic/module.c.h

Lines changed: 77 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/******************************************************************************
2+
* Remote Debugging Module - GC Stats Functions
3+
*
4+
* This file contains function for read GC stats from interpreter state.
5+
******************************************************************************/
6+
7+
#ifndef Py_REMOTE_DEBUGGING_GC_STATS_H
8+
#define Py_REMOTE_DEBUGGING_GC_STATS_H
9+
10+
#ifdef __cplusplus
11+
extern "C" {
12+
#endif
13+
14+
#include "_remote_debugging.h"
15+
16+
static int
17+
read_gc_stats(struct gc_stats *stats, unsigned long iid, PyObject *result)
18+
{
19+
#define ADD_LOCAL_ULONG(name) do { \
20+
val = PyLong_FromUnsignedLong(name); \
21+
if (!val || PyDict_SetItemString(item, #name, val) < 0) { \
22+
goto error; \
23+
} \
24+
Py_DECREF(val); \
25+
} while(0)
26+
27+
#define ADD_STATS_SSIZE(name) do { \
28+
val = PyLong_FromSsize_t(stats_item->name); \
29+
if (!val || PyDict_SetItemString(item, #name, val) < 0) { \
30+
goto error; \
31+
} \
32+
Py_DECREF(val); \
33+
} while(0)
34+
35+
#define ADD_STATS_INT64(name) do { \
36+
val = PyLong_FromInt64(stats_item->name); \
37+
if (!val || PyDict_SetItemString(item, #name, val) < 0) { \
38+
goto error; \
39+
} \
40+
Py_DECREF(val); \
41+
} while(0)
42+
43+
#define ADD_STATS_DOUBLE(name) do { \
44+
val = PyFloat_FromDouble(stats_item->name); \
45+
if (!val || PyDict_SetItemString(item, #name, val) < 0) { \
46+
goto error; \
47+
} \
48+
Py_DECREF(val); \
49+
} while(0)
50+
51+
PyObject *item = NULL;
52+
PyObject *val = NULL;
53+
54+
for(unsigned long gen = 0; gen < NUM_GENERATIONS; gen++) {
55+
struct gc_generation_stats *items;
56+
int size;
57+
if (gen == 0) {
58+
items = (struct gc_generation_stats *)stats->young.items;
59+
size = GC_YOUNG_STATS_SIZE;
60+
}
61+
else {
62+
items = (struct gc_generation_stats *)stats->old[gen-1].items;
63+
size = GC_OLD_STATS_SIZE;
64+
}
65+
for(int i = 0; i < size; i++, items++) {
66+
struct gc_generation_stats *stats_item = items;
67+
item = PyDict_New();
68+
if (item == NULL) {
69+
goto error;
70+
}
71+
72+
ADD_LOCAL_ULONG(gen);
73+
ADD_LOCAL_ULONG(iid);
74+
75+
ADD_STATS_INT64(ts_start);
76+
ADD_STATS_INT64(ts_stop);
77+
ADD_STATS_SSIZE(heap_size);
78+
ADD_STATS_SSIZE(work_to_do);
79+
ADD_STATS_SSIZE(collections);
80+
ADD_STATS_SSIZE(object_visits);
81+
ADD_STATS_SSIZE(collected);
82+
ADD_STATS_SSIZE(uncollectable);
83+
ADD_STATS_SSIZE(candidates);
84+
ADD_STATS_SSIZE(objects_transitively_reachable);
85+
ADD_STATS_SSIZE(objects_not_transitively_reachable);
86+
87+
ADD_STATS_DOUBLE(duration);
88+
val = NULL;
89+
90+
int rc = PyList_Append(result, item);
91+
Py_CLEAR(item);
92+
if (rc < 0) {
93+
goto error;
94+
}
95+
}
96+
}
97+
98+
#undef ADD_LOCAL_ULONG
99+
#undef ADD_STATS_SSIZE
100+
#undef ADD_STATS_INT64
101+
#undef ADD_STATS_DOUBLE
102+
103+
return 0;
104+
105+
error:
106+
Py_XDECREF(val);
107+
Py_XDECREF(item);
108+
109+
return -1;
110+
}
111+
112+
static int
113+
get_gc_stats_from_interpreter_state(RuntimeOffsets *offsets,
114+
uintptr_t interpreter_state_addr,
115+
unsigned long iid,
116+
void *context)
117+
{
118+
struct gc_stats stats;
119+
uintptr_t gc_stats_address = interpreter_state_addr
120+
+ offsets->debug_offsets.interpreter_state.gc
121+
+ offsets->debug_offsets.gc.generation_stats;
122+
uint64_t gc_stats_size = offsets->debug_offsets.gc.generation_stats_size;
123+
if (_Py_RemoteDebug_ReadRemoteMemory(&offsets->handle,
124+
gc_stats_address,
125+
gc_stats_size,
126+
&stats) < 0) {
127+
PyErr_SetString(PyExc_RuntimeError, "Failed to read GC state");
128+
return -1;
129+
}
130+
131+
PyObject *result = context;
132+
if (read_gc_stats(&stats, iid, result) < 0) {
133+
return -1;
134+
}
135+
136+
return 0;
137+
}
138+
139+
#ifdef __cplusplus
140+
}
141+
#endif
142+
143+
#endif /* Py_REMOTE_DEBUGGING_GC_STATS_H */

0 commit comments

Comments
 (0)