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 |