| 110 | } |
| 111 | |
| 112 | static int |
| 113 | check_callers(int * cannot) |
| 114 | { |
| 115 | /* |
| 116 | * get base addresses of multiarray and python, check if |
| 117 | * backtrace is in these libraries only calling dladdr if a new max address |
| 118 | * is found. |
| 119 | * When after the initial multiarray stack everything is inside python we |
| 120 | * can elide as no C-API user could have messed up the reference counts. |
| 121 | * Only check until the python frame evaluation function is found |
| 122 | * approx 10us overhead for stack size of 10 |
| 123 | * |
| 124 | * TODO some calls go over scalarmath in umath but we cannot get the base |
| 125 | * address of it from multiarraymodule as it is not linked against it |
| 126 | */ |
| 127 | static int init = 0; |
| 128 | /* |
| 129 | * measured DSO object memory start and end, if an address is located |
| 130 | * inside these bounds it is part of that library so we don't need to call |
| 131 | * dladdr on it (assuming linear memory) |
| 132 | */ |
| 133 | static void * pos_python_start; |
| 134 | static void * pos_python_end; |
| 135 | static void * pos_ma_start; |
| 136 | static void * pos_ma_end; |
| 137 | |
| 138 | /* known address storage to save dladdr calls */ |
| 139 | static void * py_addr[64]; |
| 140 | static void * pyeval_addr[64]; |
| 141 | static npy_intp n_py_addr = 0; |
| 142 | static npy_intp n_pyeval = 0; |
| 143 | |
| 144 | void *buffer[NPY_MAX_STACKSIZE]; |
| 145 | int i, nptrs; |
| 146 | int ok = 0; |
| 147 | /* cannot determine callers */ |
| 148 | if (init == -1) { |
| 149 | *cannot = 1; |
| 150 | return 0; |
| 151 | } |
| 152 | |
| 153 | nptrs = backtrace(buffer, NPY_MAX_STACKSIZE); |
| 154 | if (nptrs == 0) { |
| 155 | /* complete failure, disable elision */ |
| 156 | init = -1; |
| 157 | *cannot = 1; |
| 158 | return 0; |
| 159 | } |
| 160 | |
| 161 | /* setup DSO base addresses, ends updated later */ |
| 162 | if (NPY_UNLIKELY(init == 0)) { |
| 163 | Dl_info info; |
| 164 | /* get python base address */ |
| 165 | if (dladdr(&PyNumber_Or, &info)) { |
| 166 | pos_python_start = info.dli_fbase; |
| 167 | pos_python_end = info.dli_fbase; |
| 168 | } |
| 169 | else { |
no test coverage detected