File: native_ext.c

package info (click to toggle)
python-memray 1.17.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 24,396 kB
  • sloc: python: 28,451; ansic: 16,507; sh: 10,586; cpp: 8,494; javascript: 1,474; makefile: 822; awk: 12
file content (131 lines) | stat: -rw-r--r-- 2,649 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include <assert.h>
#include <pthread.h>
#ifdef __linux__
#include <malloc.h>
#endif

#pragma GCC push_options
#pragma GCC optimize ("O0")

// Regular call chain
//
__attribute__((noinline)) static void baz() {
    void* p = valloc(1234);
    free(p);
}

__attribute__((noinline)) static void bar() {
    baz();
}

__attribute__((noinline)) static void foo() {
    bar();
}

PyObject*
run_simple(PyObject* mod , PyObject* arg)
{
    foo();
    Py_RETURN_NONE;
}

// Inlined call chain

__attribute__((always_inline)) static inline void baz_inline() {
    void *p = valloc(1234);
    free(p);
}

__attribute__((always_inline)) static inline void bar_inline() {
    baz_inline();
}

__attribute__((always_inline)) static inline void foo_inline() {
    bar_inline();
}

PyObject*
run_inline(PyObject* mod, PyObject* arg)
{
    foo_inline();
    Py_RETURN_NONE;
}

void* thread_worker(void* arg)
{
    foo();
    return NULL;
}

PyObject*
run_in_thread(PyObject* mod, PyObject* arg)
{
    pthread_t thread;
    pthread_create(&thread, NULL, &thread_worker, NULL);
    pthread_join(thread, NULL);
    Py_RETURN_NONE;
}

void deep_call(long n) {
    if (n == 0) {
        return foo();
    }
    return deep_call(n-1);
}

PyObject*
run_deep(PyObject* mod, PyObject* n_stack)
{
    long n = PyLong_AsLong(n_stack);
    if (n == -1 && PyErr_Occurred()) {
        return NULL;
    }
    deep_call(n);
    Py_RETURN_NONE;
}


PyObject*
run_recursive(PyObject* mod, PyObject* args)
{
    long n;
    PyObject* callback;
    if (!PyArg_ParseTuple(args, "lO", &n, &callback)) {
        return NULL;
    }
    if (n <= 0) {
        foo();
        Py_RETURN_NONE;
    }
    return PyObject_CallFunction(callback, "i", n-1);
}

#pragma GCC pop_options

static PyMethodDef methods[] = {
        {"run_simple", run_simple, METH_NOARGS, "Execute a chain of native functions"},
        {"run_inline", run_inline, METH_NOARGS, "Execute a chain of native inlined_functions"},
        {"run_in_thread", run_in_thread, METH_NOARGS, "Like run_simple, but in a bg thread"},
        {"run_deep", run_deep, METH_O, "Execute a chain of native inlined functions in a deep stack"},
        {"run_recursive", run_recursive, METH_VARARGS, "Execute a callback if the second argument is bigger than 0"},
        {NULL, NULL, 0, NULL},
};

#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "native_ext", "", -1, methods};

PyMODINIT_FUNC
PyInit_native_ext(void)
{
    return PyModule_Create(&moduledef);
}
#else
PyMODINIT_FUNC
initnative_ext(void)
{
    Py_InitModule("native_ext", methods);
}
#endif