diff options
| author | Mike Pall <mike> | 2011-05-08 22:33:04 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2011-05-08 22:33:04 +0200 |
| commit | 77ba7726e2f8b6ffe86be6c89b5beda5cab86d2d (patch) | |
| tree | 476f063d2f19470222e61aa26865ce4d68200a7d /src | |
| parent | 87553d9e77f440da012ed79eb373feaea8b03315 (diff) | |
| download | luajit-77ba7726e2f8b6ffe86be6c89b5beda5cab86d2d.tar.gz luajit-77ba7726e2f8b6ffe86be6c89b5beda5cab86d2d.tar.bz2 luajit-77ba7726e2f8b6ffe86be6c89b5beda5cab86d2d.zip | |
FFI: Save errno/GetLastError() around allocations, hooks etc.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_alloc.c | 52 | ||||
| -rw-r--r-- | src/lj_dispatch.c | 4 | ||||
| -rw-r--r-- | src/lj_dispatch.h | 17 | ||||
| -rw-r--r-- | src/lj_trace.c | 4 |
4 files changed, 72 insertions, 5 deletions
diff --git a/src/lj_alloc.c b/src/lj_alloc.c index 2f3fb473..8d4edb5e 100644 --- a/src/lj_alloc.c +++ b/src/lj_alloc.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #define lj_alloc_c | 23 | #define lj_alloc_c |
| 24 | #define LUA_CORE | 24 | #define LUA_CORE |
| 25 | 25 | ||
| 26 | /* To get the mremap prototype. Must be defind before any system includes. */ | 26 | /* To get the mremap prototype. Must be defined before any system includes. */ |
| 27 | #if defined(__linux__) && !defined(_GNU_SOURCE) | 27 | #if defined(__linux__) && !defined(_GNU_SOURCE) |
| 28 | #define _GNU_SOURCE | 28 | #define _GNU_SOURCE |
| 29 | #endif | 29 | #endif |
| @@ -98,18 +98,22 @@ static void INIT_MMAP(void) | |||
| 98 | /* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ | 98 | /* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ |
| 99 | static LJ_AINLINE void *CALL_MMAP(size_t size) | 99 | static LJ_AINLINE void *CALL_MMAP(size_t size) |
| 100 | { | 100 | { |
| 101 | DWORD olderr = GetLastError(); | ||
| 101 | void *ptr = NULL; | 102 | void *ptr = NULL; |
| 102 | long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, | 103 | long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, |
| 103 | MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); | 104 | MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); |
| 105 | SetLastError(olderr); | ||
| 104 | return st == 0 ? ptr : MFAIL; | 106 | return st == 0 ? ptr : MFAIL; |
| 105 | } | 107 | } |
| 106 | 108 | ||
| 107 | /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ | 109 | /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ |
| 108 | static LJ_AINLINE void *DIRECT_MMAP(size_t size) | 110 | static LJ_AINLINE void *DIRECT_MMAP(size_t size) |
| 109 | { | 111 | { |
| 112 | DWORD olderr = GetLastError(); | ||
| 110 | void *ptr = NULL; | 113 | void *ptr = NULL; |
| 111 | long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, | 114 | long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size, |
| 112 | MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE); | 115 | MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE); |
| 116 | SetLastError(olderr); | ||
| 113 | return st == 0 ? ptr : MFAIL; | 117 | return st == 0 ? ptr : MFAIL; |
| 114 | } | 118 | } |
| 115 | 119 | ||
| @@ -120,15 +124,19 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size) | |||
| 120 | /* Win32 MMAP via VirtualAlloc */ | 124 | /* Win32 MMAP via VirtualAlloc */ |
| 121 | static LJ_AINLINE void *CALL_MMAP(size_t size) | 125 | static LJ_AINLINE void *CALL_MMAP(size_t size) |
| 122 | { | 126 | { |
| 127 | DWORD olderr = GetLastError(); | ||
| 123 | void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); | 128 | void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); |
| 129 | SetLastError(olderr); | ||
| 124 | return ptr ? ptr : MFAIL; | 130 | return ptr ? ptr : MFAIL; |
| 125 | } | 131 | } |
| 126 | 132 | ||
| 127 | /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ | 133 | /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ |
| 128 | static LJ_AINLINE void *DIRECT_MMAP(size_t size) | 134 | static LJ_AINLINE void *DIRECT_MMAP(size_t size) |
| 129 | { | 135 | { |
| 136 | DWORD olderr = GetLastError(); | ||
| 130 | void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, | 137 | void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, |
| 131 | PAGE_READWRITE); | 138 | PAGE_READWRITE); |
| 139 | SetLastError(olderr); | ||
| 132 | return ptr ? ptr : MFAIL; | 140 | return ptr ? ptr : MFAIL; |
| 133 | } | 141 | } |
| 134 | 142 | ||
| @@ -137,6 +145,7 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size) | |||
| 137 | /* This function supports releasing coalesed segments */ | 145 | /* This function supports releasing coalesed segments */ |
| 138 | static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) | 146 | static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) |
| 139 | { | 147 | { |
| 148 | DWORD olderr = GetLastError(); | ||
| 140 | MEMORY_BASIC_INFORMATION minfo; | 149 | MEMORY_BASIC_INFORMATION minfo; |
| 141 | char *cptr = (char *)ptr; | 150 | char *cptr = (char *)ptr; |
| 142 | while (size) { | 151 | while (size) { |
| @@ -150,11 +159,13 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) | |||
| 150 | cptr += minfo.RegionSize; | 159 | cptr += minfo.RegionSize; |
| 151 | size -= minfo.RegionSize; | 160 | size -= minfo.RegionSize; |
| 152 | } | 161 | } |
| 162 | SetLastError(olderr); | ||
| 153 | return 0; | 163 | return 0; |
| 154 | } | 164 | } |
| 155 | 165 | ||
| 156 | #else | 166 | #else |
| 157 | 167 | ||
| 168 | #include <errno.h> | ||
| 158 | #include <sys/mman.h> | 169 | #include <sys/mman.h> |
| 159 | 170 | ||
| 160 | #define MMAP_PROT (PROT_READ|PROT_WRITE) | 171 | #define MMAP_PROT (PROT_READ|PROT_WRITE) |
| @@ -169,7 +180,13 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) | |||
| 169 | #if LJ_TARGET_LINUX | 180 | #if LJ_TARGET_LINUX |
| 170 | 181 | ||
| 171 | /* Actually this only gives us max. 1GB in current Linux kernels. */ | 182 | /* Actually this only gives us max. 1GB in current Linux kernels. */ |
| 172 | #define CALL_MMAP(s) mmap(NULL, (s), MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0) | 183 | static LJ_AINLINE void *CALL_MMAP(size_t size) |
| 184 | { | ||
| 185 | int olderr = errno; | ||
| 186 | void *ptr = mmap(NULL, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0); | ||
| 187 | errno = olderr; | ||
| 188 | return ptr; | ||
| 189 | } | ||
| 173 | 190 | ||
| 174 | #elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) | 191 | #elif LJ_TARGET_OSX || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) |
| 175 | 192 | ||
| @@ -188,6 +205,7 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) | |||
| 188 | 205 | ||
| 189 | static LJ_AINLINE void *CALL_MMAP(size_t size) | 206 | static LJ_AINLINE void *CALL_MMAP(size_t size) |
| 190 | { | 207 | { |
| 208 | int olderr = errno; | ||
| 191 | /* Hint for next allocation. Doesn't need to be thread-safe. */ | 209 | /* Hint for next allocation. Doesn't need to be thread-safe. */ |
| 192 | static uintptr_t alloc_hint = MMAP_REGION_START; | 210 | static uintptr_t alloc_hint = MMAP_REGION_START; |
| 193 | int retry = 0; | 211 | int retry = 0; |
| @@ -205,6 +223,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size) | |||
| 205 | if ((uintptr_t)p >= MMAP_REGION_START && | 223 | if ((uintptr_t)p >= MMAP_REGION_START && |
| 206 | (uintptr_t)p + size < MMAP_REGION_END) { | 224 | (uintptr_t)p + size < MMAP_REGION_END) { |
| 207 | alloc_hint = (uintptr_t)p + size; | 225 | alloc_hint = (uintptr_t)p + size; |
| 226 | errno = olderr; | ||
| 208 | return p; | 227 | return p; |
| 209 | } | 228 | } |
| 210 | if (p != CMFAIL) munmap(p, size); | 229 | if (p != CMFAIL) munmap(p, size); |
| @@ -212,6 +231,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size) | |||
| 212 | retry = 1; | 231 | retry = 1; |
| 213 | alloc_hint = MMAP_REGION_START; | 232 | alloc_hint = MMAP_REGION_START; |
| 214 | } | 233 | } |
| 234 | errno = olderr; | ||
| 215 | return CMFAIL; | 235 | return CMFAIL; |
| 216 | } | 236 | } |
| 217 | 237 | ||
| @@ -224,17 +244,39 @@ static LJ_AINLINE void *CALL_MMAP(size_t size) | |||
| 224 | #else | 244 | #else |
| 225 | 245 | ||
| 226 | /* 32 bit mode is easy. */ | 246 | /* 32 bit mode is easy. */ |
| 227 | #define CALL_MMAP(s) mmap(NULL, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) | 247 | static LJ_AINLINE void *CALL_MMAP(size_t size) |
| 248 | { | ||
| 249 | int olderr = errno; | ||
| 250 | void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0); | ||
| 251 | errno = olderr; | ||
| 252 | return ptr; | ||
| 253 | } | ||
| 228 | 254 | ||
| 229 | #endif | 255 | #endif |
| 230 | 256 | ||
| 231 | #define INIT_MMAP() ((void)0) | 257 | #define INIT_MMAP() ((void)0) |
| 232 | #define DIRECT_MMAP(s) CALL_MMAP(s) | 258 | #define DIRECT_MMAP(s) CALL_MMAP(s) |
| 233 | #define CALL_MUNMAP(a, s) munmap((a), (s)) | 259 | |
| 260 | static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) | ||
| 261 | { | ||
| 262 | int olderr = errno; | ||
| 263 | int ret = munmap(ptr, size); | ||
| 264 | errno = olderr; | ||
| 265 | return ret; | ||
| 266 | } | ||
| 234 | 267 | ||
| 235 | #if LJ_TARGET_LINUX | 268 | #if LJ_TARGET_LINUX |
| 236 | /* Need to define _GNU_SOURCE to get the mremap prototype. */ | 269 | /* Need to define _GNU_SOURCE to get the mremap prototype. */ |
| 237 | #define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) | 270 | static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, |
| 271 | int flags) | ||
| 272 | { | ||
| 273 | int olderr = errno; | ||
| 274 | ptr = mremap(ptr, osz, nsz, flags); | ||
| 275 | errno = olderr; | ||
| 276 | return ptr; | ||
| 277 | } | ||
| 278 | |||
| 279 | #define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv)) | ||
| 238 | #define CALL_MREMAP_NOMOVE 0 | 280 | #define CALL_MREMAP_NOMOVE 0 |
| 239 | #define CALL_MREMAP_MAYMOVE 1 | 281 | #define CALL_MREMAP_MAYMOVE 1 |
| 240 | #if LJ_64 | 282 | #if LJ_64 |
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index 0b14e21c..42027e7d 100644 --- a/src/lj_dispatch.c +++ b/src/lj_dispatch.c | |||
| @@ -348,6 +348,7 @@ static BCReg cur_topslot(GCproto *pt, const BCIns *pc, uint32_t nres) | |||
| 348 | /* Instruction dispatch. Used by instr/line/return hooks or when recording. */ | 348 | /* Instruction dispatch. Used by instr/line/return hooks or when recording. */ |
| 349 | void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) | 349 | void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) |
| 350 | { | 350 | { |
| 351 | ERRNO_SAVE | ||
| 351 | GCfunc *fn = curr_func(L); | 352 | GCfunc *fn = curr_func(L); |
| 352 | GCproto *pt = funcproto(fn); | 353 | GCproto *pt = funcproto(fn); |
| 353 | void *cf = cframe_raw(L->cframe); | 354 | void *cf = cframe_raw(L->cframe); |
| @@ -382,6 +383,7 @@ void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc) | |||
| 382 | } | 383 | } |
| 383 | if ((g->hookmask & LUA_MASKRET) && bc_isret(bc_op(pc[-1]))) | 384 | if ((g->hookmask & LUA_MASKRET) && bc_isret(bc_op(pc[-1]))) |
| 384 | callhook(L, LUA_HOOKRET, -1); | 385 | callhook(L, LUA_HOOKRET, -1); |
| 386 | ERRNO_RESTORE | ||
| 385 | } | 387 | } |
| 386 | 388 | ||
| 387 | /* Initialize call. Ensure stack space and return # of missing parameters. */ | 389 | /* Initialize call. Ensure stack space and return # of missing parameters. */ |
| @@ -405,6 +407,7 @@ static int call_init(lua_State *L, GCfunc *fn) | |||
| 405 | /* Call dispatch. Used by call hooks, hot calls or when recording. */ | 407 | /* Call dispatch. Used by call hooks, hot calls or when recording. */ |
| 406 | ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc) | 408 | ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns *pc) |
| 407 | { | 409 | { |
| 410 | ERRNO_SAVE | ||
| 408 | GCfunc *fn = curr_func(L); | 411 | GCfunc *fn = curr_func(L); |
| 409 | BCOp op; | 412 | BCOp op; |
| 410 | global_State *g = G(L); | 413 | global_State *g = G(L); |
| @@ -443,6 +446,7 @@ out: | |||
| 443 | (op == BC_FUNCF || op == BC_FUNCV)) | 446 | (op == BC_FUNCF || op == BC_FUNCV)) |
| 444 | op = (BCOp)((int)op+(int)BC_IFUNCF-(int)BC_FUNCF); | 447 | op = (BCOp)((int)op+(int)BC_IFUNCF-(int)BC_FUNCF); |
| 445 | #endif | 448 | #endif |
| 449 | ERRNO_RESTORE | ||
| 446 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ | 450 | return makeasmfunc(lj_bc_ofs[op]); /* Return static dispatch target. */ |
| 447 | } | 451 | } |
| 448 | 452 | ||
diff --git a/src/lj_dispatch.h b/src/lj_dispatch.h index 3ba983a8..dd4f68fe 100644 --- a/src/lj_dispatch.h +++ b/src/lj_dispatch.h | |||
| @@ -69,4 +69,21 @@ LJ_FUNCA void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc); | |||
| 69 | LJ_FUNCA ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns*pc); | 69 | LJ_FUNCA ASMFunction LJ_FASTCALL lj_dispatch_call(lua_State *L, const BCIns*pc); |
| 70 | LJ_FUNCA void LJ_FASTCALL lj_dispatch_return(lua_State *L, const BCIns *pc); | 70 | LJ_FUNCA void LJ_FASTCALL lj_dispatch_return(lua_State *L, const BCIns *pc); |
| 71 | 71 | ||
| 72 | #if LJ_HASFFI && !defined(_BUILDVM_H) | ||
| 73 | /* Save/restore errno and GetLastError() around hooks, exits and recording. */ | ||
| 74 | #include <errno.h> | ||
| 75 | #if LJ_TARGET_WINDOWS | ||
| 76 | #define WIN32_LEAN_AND_MEAN | ||
| 77 | #include <windows.h> | ||
| 78 | #define ERRNO_SAVE int olderr = errno; DWORD oldwerr = GetLastError(); | ||
| 79 | #define ERRNO_RESTORE errno = olderr; SetLastError(oldwerr); | ||
| 80 | #else | ||
| 81 | #define ERRNO_SAVE int olderr = errno; | ||
| 82 | #define ERRNO_RESTORE errno = olderr; | ||
| 83 | #endif | ||
| 84 | #else | ||
| 85 | #define ERRNO_SAVE | ||
| 86 | #define ERRNO_RESTORE | ||
| 87 | #endif | ||
| 88 | |||
| 72 | #endif | 89 | #endif |
diff --git a/src/lj_trace.c b/src/lj_trace.c index 69124542..ab75c9d2 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
| @@ -638,6 +638,7 @@ void lj_trace_ins(jit_State *J, const BCIns *pc) | |||
| 638 | /* A hotcount triggered. Start recording a root trace. */ | 638 | /* A hotcount triggered. Start recording a root trace. */ |
| 639 | void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc) | 639 | void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc) |
| 640 | { | 640 | { |
| 641 | ERRNO_SAVE | ||
| 641 | /* Note: pc is the interpreter bytecode PC here. It's offset by 1. */ | 642 | /* Note: pc is the interpreter bytecode PC here. It's offset by 1. */ |
| 642 | hotcount_set(J2GG(J), pc, J->param[JIT_P_hotloop]+1); /* Reset hotcount. */ | 643 | hotcount_set(J2GG(J), pc, J->param[JIT_P_hotloop]+1); /* Reset hotcount. */ |
| 643 | /* Only start a new trace if not recording or inside __gc call or vmevent. */ | 644 | /* Only start a new trace if not recording or inside __gc call or vmevent. */ |
| @@ -648,6 +649,7 @@ void LJ_FASTCALL lj_trace_hot(jit_State *J, const BCIns *pc) | |||
| 648 | J->state = LJ_TRACE_START; | 649 | J->state = LJ_TRACE_START; |
| 649 | lj_trace_ins(J, pc-1); | 650 | lj_trace_ins(J, pc-1); |
| 650 | } | 651 | } |
| 652 | ERRNO_RESTORE | ||
| 651 | } | 653 | } |
| 652 | 654 | ||
| 653 | /* Check for a hot side exit. If yes, start recording a side trace. */ | 655 | /* Check for a hot side exit. If yes, start recording a side trace. */ |
| @@ -684,6 +686,7 @@ static TValue *trace_exit_cp(lua_State *L, lua_CFunction dummy, void *ud) | |||
| 684 | /* A trace exited. Restore interpreter state. */ | 686 | /* A trace exited. Restore interpreter state. */ |
| 685 | int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | 687 | int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) |
| 686 | { | 688 | { |
| 689 | ERRNO_SAVE | ||
| 687 | lua_State *L = J->L; | 690 | lua_State *L = J->L; |
| 688 | ExitDataCP exd; | 691 | ExitDataCP exd; |
| 689 | int errcode; | 692 | int errcode; |
| @@ -738,6 +741,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) | |||
| 738 | } | 741 | } |
| 739 | } | 742 | } |
| 740 | /* Return MULTRES or 0. */ | 743 | /* Return MULTRES or 0. */ |
| 744 | ERRNO_RESTORE | ||
| 741 | switch (bc_op(*pc)) { | 745 | switch (bc_op(*pc)) { |
| 742 | case BC_CALLM: case BC_CALLMT: | 746 | case BC_CALLM: case BC_CALLMT: |
| 743 | return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc)); | 747 | return (int)((BCReg)(L->top - L->base) - bc_a(*pc) - bc_c(*pc)); |
