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
|