Skip to content

Commit

Permalink
Use atomics when available
Browse files Browse the repository at this point in the history
  • Loading branch information
josephcsible committed May 20, 2020
1 parent 0d83524 commit 488fd22
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 14 deletions.
6 changes: 3 additions & 3 deletions ldebug.c
Expand Up @@ -169,12 +169,12 @@ LUA_API int lua_gethookcount (lua_State *L) {
** gcc ensures that for all platforms where it runs).
*/
LUA_API void lua_setglobalhook (lua_State *L, lua_Hook func) {
G(L)->globalhook = func;
LUA_ATOMIC_STORE_RELEASE(G(L)->globalhook, func);
}


LUA_API lua_Hook lua_getglobalhook (lua_State *L) {
return G(L)->globalhook;
return LUA_ATOMIC_LOAD_ACQUIRE(G(L)->globalhook);
}


Expand Down Expand Up @@ -810,7 +810,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) {

int luaG_traceexec (lua_State *L, const Instruction *pc) {
CallInfo *ci = L->ci;
lua_Hook globalhook = G(L)->globalhook;
lua_Hook globalhook = LUA_ATOMIC_LOAD_ACQUIRE(G(L)->globalhook);
lu_byte mask = L->hookmask;
int counthook;
if (!globalhook && !(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
Expand Down
6 changes: 3 additions & 3 deletions ldo.c
Expand Up @@ -311,7 +311,7 @@ void luaD_hook (lua_State *L, lua_Hook hook, int event, int line,
** active.
*/
void luaD_hookcall (lua_State *L, CallInfo *ci) {
lua_Hook globalhook = G(L)->globalhook;
lua_Hook globalhook = LUA_ATOMIC_LOAD_ACQUIRE(G(L)->globalhook);
int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL;
Proto *p;
if (!globalhook && !(L->hookmask & LUA_MASKCALL)) /* some other hook? */
Expand All @@ -329,7 +329,7 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) {
static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
ptrdiff_t oldtop = savestack(L, L->top); /* hook may change top */
int delta = 0;
lua_Hook globalhook = G(L)->globalhook;
lua_Hook globalhook = LUA_ATOMIC_LOAD_ACQUIRE(G(L)->globalhook);
if (isLuacode(ci)) {
Proto *p = clLvalue(s2v(ci->func))->p;
if (p->is_vararg)
Expand Down Expand Up @@ -472,7 +472,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
Cfunc: {
int n; /* number of returns */
CallInfo *ci;
lua_Hook globalhook = G(L)->globalhook;
lua_Hook globalhook = LUA_ATOMIC_LOAD_ACQUIRE(G(L)->globalhook);
checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
ci = next_ci(L);
ci->nresults = nresults;
Expand Down
2 changes: 1 addition & 1 deletion lstate.c
Expand Up @@ -419,7 +419,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->gcstepsize = LUAI_GCSTEPSIZE;
setgcparam(g->genmajormul, LUAI_GENMAJORMUL);
g->genminormul = LUAI_GENMINORMUL;
g->globalhook = NULL;
LUA_ATOMIC_STORE_RELEASE(g->globalhook, NULL);
for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
/* memory allocation error: free partial state */
Expand Down
2 changes: 1 addition & 1 deletion lstate.h
Expand Up @@ -272,7 +272,7 @@ typedef struct global_State {
lua_WarnFunction warnf; /* warning function */
void *ud_warn; /* auxiliary data to 'warnf' */
unsigned int Cstacklimit; /* current limit for the C stack */
volatile lua_Hook globalhook;
LUA_ATOMIC(lua_Hook) globalhook;
} global_State;


Expand Down
16 changes: 13 additions & 3 deletions lua.c
Expand Up @@ -32,7 +32,7 @@
#define LUA_INITVARVERSION LUA_INIT_VAR LUA_VERSUFFIX


static lua_State *globalL = NULL;
static LUA_ATOMIC(lua_State *) globalL;

static const char *progname = LUA_PROGNAME;

Expand All @@ -47,6 +47,16 @@ static void lstop (lua_State *L, lua_Debug *ar) {
}


/*
** If pointers aren't lock-free, then signal handlers can't safely set them,
** since what they interrupted might be holding the lock they need to take,
** resulting in a deadlock. Fail at compile time if we detect that.
*/
#if defined(ATOMIC_POINTER_LOCK_FREE) && ATOMIC_POINTER_LOCK_FREE != 2
#error "Hooks can't be safely set from signal handlers!"
#endif


/*
** Function to be called at a C signal. Because a C signal cannot
** just change a Lua state (as there is no proper synchronization),
Expand All @@ -55,7 +65,7 @@ static void lstop (lua_State *L, lua_Debug *ar) {
*/
static void laction (int i) {
signal(i, SIG_DFL); /* if another SIGINT happens, terminate process */
lua_setglobalhook(globalL, lstop);
lua_setglobalhook(LUA_ATOMIC_LOAD_ACQUIRE(globalL), lstop);
}


Expand Down Expand Up @@ -133,7 +143,7 @@ static int docall (lua_State *L, int narg, int nres) {
int base = lua_gettop(L) - narg; /* function index */
lua_pushcfunction(L, msghandler); /* push message handler */
lua_insert(L, base); /* put it under function and args */
globalL = L; /* to be available to 'laction' */
LUA_ATOMIC_STORE_RELEASE(globalL, L); /* to be available to 'laction' */
signal(SIGINT, laction); /* set C-signal handler */
status = lua_pcall(L, narg, nres, base);
signal(SIGINT, SIG_DFL); /* reset C-signal handler */
Expand Down
32 changes: 32 additions & 0 deletions lua.h
Expand Up @@ -29,6 +29,38 @@
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"


/*
** Stuff to use atomics if able, or falling back to the technically-incorrect
** but probably good enough "volatile" if not
*/
#if defined(__cplusplus) && __cplusplus >= 201103L

/* C++11 atomics */
#include <atomic>

#define LUA_ATOMIC(t) std::atomic<t>
#define LUA_ATOMIC_LOAD_ACQUIRE(obj) obj.load(std::memory_order_acquire)
#define LUA_ATOMIC_STORE_RELEASE(obj, desired) obj.store(desired, std::memory_order_release)

#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)

/* C11 atomics */
#include <stdatomic.h>

#define LUA_ATOMIC(t) _Atomic(t)
#define LUA_ATOMIC_LOAD_ACQUIRE(obj) atomic_load_explicit(&obj, memory_order_acquire)
#define LUA_ATOMIC_STORE_RELEASE(obj, desired) atomic_store_explicit(&obj, desired, memory_order_release)

#else

/* no atomics */
#define LUA_ATOMIC(t) t volatile
#define LUA_ATOMIC_LOAD_ACQUIRE(obj) (obj)
#define LUA_ATOMIC_STORE_RELEASE(obj, desired) (obj = desired)

#endif


/* mark for precompiled code ('<esc>Lua') */
#define LUA_SIGNATURE "\x1bLua"

Expand Down
4 changes: 2 additions & 2 deletions lvm.c
Expand Up @@ -1044,7 +1044,7 @@ void luaV_finishOp (lua_State *L) {



#define updatetrap(ci) (trap = ci->u.l.trap || G(L)->globalhook)
#define updatetrap(ci) (trap = ci->u.l.trap || LUA_ATOMIC_LOAD_ACQUIRE(G(L)->globalhook))

#define updatebase(ci) (base = ci->func + 1)

Expand Down Expand Up @@ -1134,7 +1134,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
#include "ljumptab.h"
#endif
tailcall:
trap = L->hookmask || G(L)->globalhook;
trap = L->hookmask || LUA_ATOMIC_LOAD_ACQUIRE(G(L)->globalhook);
cl = clLvalue(s2v(ci->func));
k = cl->p->k;
pc = ci->u.l.savedpc;
Expand Down
2 changes: 1 addition & 1 deletion makefile
Expand Up @@ -53,7 +53,7 @@ LOCAL = $(TESTS) $(CWARNS)


# enable Linux goodies
MYCFLAGS= $(LOCAL) -std=c99 -DLUA_USE_LINUX -DLUA_USE_READLINE
MYCFLAGS= $(LOCAL) -std=c11 -DLUA_USE_LINUX -DLUA_USE_READLINE
MYLDFLAGS= $(LOCAL) -Wl,-E
MYLIBS= -ldl -lreadline

Expand Down

0 comments on commit 488fd22

Please sign in to comment.