diff options
| author | Mike Pall <mike> | 2013-09-16 11:23:10 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-09-16 11:23:10 +0200 |
| commit | b30a789ab8513f58c9696ed1e20042065e0fcef0 (patch) | |
| tree | bb6d502900e13b1ef262bef8f2ab3d5b74458517 /src | |
| parent | 8201fda2fc4f43856a27607b4784e9b09fd3ccb4 (diff) | |
| download | luajit-b30a789ab8513f58c9696ed1e20042065e0fcef0.tar.gz luajit-b30a789ab8513f58c9696ed1e20042065e0fcef0.tar.bz2 luajit-b30a789ab8513f58c9696ed1e20042065e0fcef0.zip | |
Protect g->hookmask with lock when using profiler thread.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.dep | 6 | ||||
| -rw-r--r-- | src/lib_jit.c | 2 | ||||
| -rw-r--r-- | src/lj_dispatch.c | 34 | ||||
| -rw-r--r-- | src/lj_profile.c | 36 |
4 files changed, 49 insertions, 29 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep index 9ae6043a..6348d483 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -24,9 +24,9 @@ lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | |||
| 24 | lj_strfmt.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | 24 | lj_strfmt.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h |
| 25 | lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 25 | lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
| 26 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ | 26 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ |
| 27 | lj_state.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ | 27 | lj_state.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h lj_trace.h lj_dispatch.h \ |
| 28 | lj_target.h lj_target_*.h lj_dispatch.h lj_vm.h lj_vmevent.h lj_lib.h \ | 28 | lj_traceerr.h lj_ircall.h lj_iropt.h lj_target.h lj_target_*.h lj_vm.h \ |
| 29 | luajit.h lj_libdef.h | 29 | lj_vmevent.h lj_lib.h luajit.h lj_libdef.h |
| 30 | lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 30 | lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
| 31 | lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h | 31 | lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h |
| 32 | lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 32 | lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
diff --git a/src/lib_jit.c b/src/lib_jit.c index be075ce4..7bb642cb 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #if LJ_HASJIT | 24 | #if LJ_HASJIT |
| 25 | #include "lj_ir.h" | 25 | #include "lj_ir.h" |
| 26 | #include "lj_jit.h" | 26 | #include "lj_jit.h" |
| 27 | #include "lj_trace.h" | ||
| 27 | #include "lj_ircall.h" | 28 | #include "lj_ircall.h" |
| 28 | #include "lj_iropt.h" | 29 | #include "lj_iropt.h" |
| 29 | #include "lj_target.h" | 30 | #include "lj_target.h" |
| @@ -560,6 +561,7 @@ static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, | |||
| 560 | if (G(L2)->panic) G(L2)->panic(L2); | 561 | if (G(L2)->panic) G(L2)->panic(L2); |
| 561 | exit(EXIT_FAILURE); | 562 | exit(EXIT_FAILURE); |
| 562 | } | 563 | } |
| 564 | lj_trace_abort(G(L2)); | ||
| 563 | } | 565 | } |
| 564 | } | 566 | } |
| 565 | 567 | ||
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index 01bc4239..af269c44 100644 --- a/src/lj_dispatch.c +++ b/src/lj_dispatch.c | |||
| @@ -508,28 +508,18 @@ out: | |||
| 508 | void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc) | 508 | void LJ_FASTCALL lj_dispatch_profile(lua_State *L, const BCIns *pc) |
| 509 | { | 509 | { |
| 510 | ERRNO_SAVE | 510 | ERRNO_SAVE |
| 511 | global_State *g = G(L); | 511 | GCfunc *fn = curr_func(L); |
| 512 | uint8_t mask = g->hookmask; | 512 | GCproto *pt = funcproto(fn); |
| 513 | g->hookmask = (mask & ~HOOK_PROFILE); | 513 | void *cf = cframe_raw(L->cframe); |
| 514 | lj_dispatch_update(g); | 514 | const BCIns *oldpc = cframe_pc(cf); |
| 515 | if (!(mask & HOOK_VMEVENT)) { | 515 | global_State *g; |
| 516 | GCfunc *fn = curr_func(L); | 516 | setcframe_pc(cf, pc); |
| 517 | GCproto *pt = funcproto(fn); | 517 | L->top = L->base + cur_topslot(pt, pc, cframe_multres_n(cf)); |
| 518 | void *cf = cframe_raw(L->cframe); | 518 | lj_profile_interpreter(L); |
| 519 | const BCIns *oldpc = cframe_pc(cf); | 519 | setcframe_pc(cf, oldpc); |
| 520 | uint8_t oldh = hook_save(g); | 520 | g = G(L); |
| 521 | BCReg slots; | 521 | setgcref(g->cur_L, obj2gco(L)); |
| 522 | hook_vmevent(g); | 522 | setvmstate(g, INTERP); |
| 523 | setcframe_pc(cf, pc); | ||
| 524 | slots = cur_topslot(pt, pc, cframe_multres_n(cf)); | ||
| 525 | L->top = L->base + slots; /* Fix top. */ | ||
| 526 | lj_profile_interpreter(L); | ||
| 527 | setgcref(g->cur_L, obj2gco(L)); | ||
| 528 | setcframe_pc(cf, oldpc); | ||
| 529 | hook_restore(g, oldh); | ||
| 530 | lj_trace_abort(g); | ||
| 531 | setvmstate(g, INTERP); | ||
| 532 | } | ||
| 533 | ERRNO_RESTORE | 523 | ERRNO_RESTORE |
| 534 | } | 524 | } |
| 535 | #endif | 525 | #endif |
diff --git a/src/lj_profile.c b/src/lj_profile.c index c7bc6168..1984a676 100644 --- a/src/lj_profile.c +++ b/src/lj_profile.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | 26 | ||
| 27 | #include <sys/time.h> | 27 | #include <sys/time.h> |
| 28 | #include <signal.h> | 28 | #include <signal.h> |
| 29 | #define profile_lock(ps) UNUSED(ps) | ||
| 30 | #define profile_unlock(ps) UNUSED(ps) | ||
| 29 | 31 | ||
| 30 | #elif LJ_PROFILE_PTHREAD | 32 | #elif LJ_PROFILE_PTHREAD |
| 31 | 33 | ||
| @@ -34,12 +36,16 @@ | |||
| 34 | #if LJ_TARGET_PS3 | 36 | #if LJ_TARGET_PS3 |
| 35 | #include <sys/timer.h> | 37 | #include <sys/timer.h> |
| 36 | #endif | 38 | #endif |
| 39 | #define profile_lock(ps) pthread_mutex_lock(&ps->lock) | ||
| 40 | #define profile_unlock(ps) pthread_mutex_unlock(&ps->lock) | ||
| 37 | 41 | ||
| 38 | #elif LJ_PROFILE_WTHREAD | 42 | #elif LJ_PROFILE_WTHREAD |
| 39 | 43 | ||
| 40 | #define WIN32_LEAN_AND_MEAN | 44 | #define WIN32_LEAN_AND_MEAN |
| 41 | #include <windows.h> | 45 | #include <windows.h> |
| 42 | typedef unsigned int (WINAPI *WMM_TPFUNC)(unsigned int); | 46 | typedef unsigned int (WINAPI *WMM_TPFUNC)(unsigned int); |
| 47 | #define profile_lock(ps) EnterCriticalSection(&ps->lock) | ||
| 48 | #define profile_unlock(ps) LeaveCriticalSection(&ps->lock) | ||
| 43 | 49 | ||
| 44 | #endif | 50 | #endif |
| 45 | 51 | ||
| @@ -55,6 +61,7 @@ typedef struct ProfileState { | |||
| 55 | #if LJ_PROFILE_SIGPROF | 61 | #if LJ_PROFILE_SIGPROF |
| 56 | struct sigaction oldsa; /* Previous SIGPROF state. */ | 62 | struct sigaction oldsa; /* Previous SIGPROF state. */ |
| 57 | #elif LJ_PROFILE_PTHREAD | 63 | #elif LJ_PROFILE_PTHREAD |
| 64 | pthread_mutex_t lock; /* g->hookmask update lock. */ | ||
| 58 | pthread_t thread; /* Timer thread. */ | 65 | pthread_t thread; /* Timer thread. */ |
| 59 | int abort; /* Abort timer thread. */ | 66 | int abort; /* Abort timer thread. */ |
| 60 | #elif LJ_PROFILE_WTHREAD | 67 | #elif LJ_PROFILE_WTHREAD |
| @@ -63,6 +70,7 @@ typedef struct ProfileState { | |||
| 63 | WMM_TPFUNC wmm_tbp; /* WinMM timeBeginPeriod function. */ | 70 | WMM_TPFUNC wmm_tbp; /* WinMM timeBeginPeriod function. */ |
| 64 | WMM_TPFUNC wmm_tep; /* WinMM timeEndPeriod function. */ | 71 | WMM_TPFUNC wmm_tep; /* WinMM timeEndPeriod function. */ |
| 65 | #endif | 72 | #endif |
| 73 | CRITICAL_SECTION lock; /* g->hookmask update lock. */ | ||
| 66 | HANDLE thread; /* Timer thread. */ | 74 | HANDLE thread; /* Timer thread. */ |
| 67 | int abort; /* Abort timer thread. */ | 75 | int abort; /* Abort timer thread. */ |
| 68 | #endif | 76 | #endif |
| @@ -85,9 +93,23 @@ static ProfileState profile_state; | |||
| 85 | void LJ_FASTCALL lj_profile_interpreter(lua_State *L) | 93 | void LJ_FASTCALL lj_profile_interpreter(lua_State *L) |
| 86 | { | 94 | { |
| 87 | ProfileState *ps = &profile_state; | 95 | ProfileState *ps = &profile_state; |
| 88 | int samples = ps->samples; | 96 | global_State *g = G(L); |
| 89 | ps->samples = 0; | 97 | uint8_t mask; |
| 90 | ps->cb(ps->data, L, samples, ps->vmstate); /* Invoke user callback. */ | 98 | profile_lock(ps); |
| 99 | mask = (g->hookmask & ~HOOK_PROFILE); | ||
| 100 | if (!(mask & HOOK_VMEVENT)) { | ||
| 101 | int samples = ps->samples; | ||
| 102 | ps->samples = 0; | ||
| 103 | g->hookmask = HOOK_VMEVENT; | ||
| 104 | lj_dispatch_update(g); | ||
| 105 | profile_unlock(ps); | ||
| 106 | ps->cb(ps->data, L, samples, ps->vmstate); /* Invoke user callback. */ | ||
| 107 | profile_lock(ps); | ||
| 108 | mask |= (g->hookmask & HOOK_PROFILE); | ||
| 109 | } | ||
| 110 | g->hookmask = mask; | ||
| 111 | lj_dispatch_update(g); | ||
| 112 | profile_unlock(ps); | ||
| 91 | } | 113 | } |
| 92 | 114 | ||
| 93 | /* Trigger profile hook. Asynchronous call from OS-specific profile timer. */ | 115 | /* Trigger profile hook. Asynchronous call from OS-specific profile timer. */ |
| @@ -95,9 +117,10 @@ static void profile_trigger(ProfileState *ps) | |||
| 95 | { | 117 | { |
| 96 | global_State *g = ps->g; | 118 | global_State *g = ps->g; |
| 97 | uint8_t mask; | 119 | uint8_t mask; |
| 120 | profile_lock(ps); | ||
| 98 | ps->samples++; /* Always increment number of samples. */ | 121 | ps->samples++; /* Always increment number of samples. */ |
| 99 | mask = g->hookmask; | 122 | mask = g->hookmask; |
| 100 | if (!(mask & HOOK_PROFILE)) { /* Set profile hook, unless already set. */ | 123 | if (!(mask & (HOOK_PROFILE|HOOK_VMEVENT))) { /* Set profile hook. */ |
| 101 | int st = g->vmstate; | 124 | int st = g->vmstate; |
| 102 | ps->vmstate = st >= 0 ? 'N' : | 125 | ps->vmstate = st >= 0 ? 'N' : |
| 103 | st == ~LJ_VMST_INTERP ? 'I' : | 126 | st == ~LJ_VMST_INTERP ? 'I' : |
| @@ -106,6 +129,7 @@ static void profile_trigger(ProfileState *ps) | |||
| 106 | g->hookmask = (mask | HOOK_PROFILE); | 129 | g->hookmask = (mask | HOOK_PROFILE); |
| 107 | lj_dispatch_update(g); | 130 | lj_dispatch_update(g); |
| 108 | } | 131 | } |
| 132 | profile_unlock(ps); | ||
| 109 | } | 133 | } |
| 110 | 134 | ||
| 111 | /* -- OS-specific profile timer handling ---------------------------------- */ | 135 | /* -- OS-specific profile timer handling ---------------------------------- */ |
| @@ -170,6 +194,7 @@ static void *profile_thread(ProfileState *ps) | |||
| 170 | /* Start profiling timer thread. */ | 194 | /* Start profiling timer thread. */ |
| 171 | static void profile_timer_start(ProfileState *ps) | 195 | static void profile_timer_start(ProfileState *ps) |
| 172 | { | 196 | { |
| 197 | pthread_mutex_init(&ps->lock, 0); | ||
| 173 | ps->abort = 0; | 198 | ps->abort = 0; |
| 174 | pthread_create(&ps->thread, NULL, (void *(*)(void *))profile_thread, ps); | 199 | pthread_create(&ps->thread, NULL, (void *(*)(void *))profile_thread, ps); |
| 175 | } | 200 | } |
| @@ -179,6 +204,7 @@ static void profile_timer_stop(ProfileState *ps) | |||
| 179 | { | 204 | { |
| 180 | ps->abort = 1; | 205 | ps->abort = 1; |
| 181 | pthread_join(ps->thread, NULL); | 206 | pthread_join(ps->thread, NULL); |
| 207 | pthread_mutex_destroy(&ps->lock); | ||
| 182 | } | 208 | } |
| 183 | 209 | ||
| 184 | #elif LJ_PROFILE_WTHREAD | 210 | #elif LJ_PROFILE_WTHREAD |
| @@ -218,6 +244,7 @@ static void profile_timer_start(ProfileState *ps) | |||
| 218 | } | 244 | } |
| 219 | } | 245 | } |
| 220 | #endif | 246 | #endif |
| 247 | InitializeCriticalSection(&ps->lock); | ||
| 221 | ps->abort = 0; | 248 | ps->abort = 0; |
| 222 | ps->thread = CreateThread(NULL, 0, profile_thread, ps, 0, NULL); | 249 | ps->thread = CreateThread(NULL, 0, profile_thread, ps, 0, NULL); |
| 223 | } | 250 | } |
| @@ -227,6 +254,7 @@ static void profile_timer_stop(ProfileState *ps) | |||
| 227 | { | 254 | { |
| 228 | ps->abort = 1; | 255 | ps->abort = 1; |
| 229 | WaitForSingleObject(ps->thread, INFINITE); | 256 | WaitForSingleObject(ps->thread, INFINITE); |
| 257 | DeleteCriticalSection(&ps->lock); | ||
| 230 | } | 258 | } |
| 231 | 259 | ||
| 232 | #endif | 260 | #endif |
