summaryrefslogtreecommitdiff
path: root/src/lj_profile.c
diff options
context:
space:
mode:
authorMike Pall <mike>2013-09-16 11:23:10 +0200
committerMike Pall <mike>2013-09-16 11:23:10 +0200
commitb30a789ab8513f58c9696ed1e20042065e0fcef0 (patch)
treebb6d502900e13b1ef262bef8f2ab3d5b74458517 /src/lj_profile.c
parent8201fda2fc4f43856a27607b4784e9b09fd3ccb4 (diff)
downloadluajit-b30a789ab8513f58c9696ed1e20042065e0fcef0.tar.gz
luajit-b30a789ab8513f58c9696ed1e20042065e0fcef0.tar.bz2
luajit-b30a789ab8513f58c9696ed1e20042065e0fcef0.zip
Protect g->hookmask with lock when using profiler thread.
Diffstat (limited to 'src/lj_profile.c')
-rw-r--r--src/lj_profile.c36
1 files changed, 32 insertions, 4 deletions
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>
42typedef unsigned int (WINAPI *WMM_TPFUNC)(unsigned int); 46typedef 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;
85void LJ_FASTCALL lj_profile_interpreter(lua_State *L) 93void 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. */
171static void profile_timer_start(ProfileState *ps) 195static 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