Skip to content

Commit 1b07a10

Browse files
committed
Refactored a bit protection traking to avoid re-entrance
1 parent d743c82 commit 1b07a10

File tree

1 file changed

+76
-58
lines changed

1 file changed

+76
-58
lines changed

src/custommem.c

+76-58
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,44 @@ static size_t roundSize(size_t size)
342342
return size;
343343
}
344344

345+
#ifdef DYNAREC
346+
#define GET_PROT_WAIT(A, B) \
347+
uint32_t A; \
348+
do { \
349+
A = native_lock_xchg_b(&block[B], PROT_WAIT); \
350+
} while(A==PROT_WAIT)
351+
#define GET_PROT(A, B) \
352+
uint32_t A; \
353+
do { \
354+
A = native_lock_get_b(&block[B]); \
355+
} while(A==PROT_WAIT)
356+
357+
#define SET_PROT(A, B) native_lock_storeb(&block[A], B)
358+
#define LOCK_NODYNAREC()
359+
#define UNLOCK_DYNAREC() UNLOCK_PROT()
360+
#define UNLOCK_NODYNAREC()
361+
#else
362+
#define GET_PROT_WAIT(A, B) uint32_t A = block[B]
363+
#define GET_PROT(A, B) uint32_t A = block[B]
364+
#define SET_PROT(A, B) block[A] = B
365+
#define LOCK_NODYNAREC() LOCK_PROT()
366+
#define UNLOCK_DYNAREC()
367+
#define UNLOCK_NODYNAREC() UNLOCK_PROT()
368+
#endif
369+
static uintptr_t defered_prot_p = 0;
370+
static size_t defered_prot_sz = 0;
371+
static uint32_t defered_prot_prot = 0;
372+
#define LOCK_PROT() mutex_lock(&mutex_prot)
373+
#define LOCK_PROT_READ() mutex_lock(&mutex_prot)
374+
#define UNLOCK_PROT() if(defered_prot_p) { \
375+
uintptr_t p = defered_prot_p; size_t sz = defered_prot_sz; uint32_t prot = defered_prot_prot; \
376+
defered_prot_p = 0; \
377+
mutex_unlock(&mutex_prot); \
378+
setProtection(p, sz, prot); \
379+
} else mutex_unlock(&mutex_prot)
380+
#define UNLOCK_PROT_READ() mutex_unlock(&mutex_prot)
381+
382+
345383
#ifdef TRACE_MEMSTAT
346384
static uint64_t customMalloc_allocated = 0;
347385
#endif
@@ -399,8 +437,13 @@ void* customMalloc(size_t size)
399437
void* ret = allocBlock(p_blocks[i].block, p, size, &p_blocks[i].first);
400438
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
401439
mutex_unlock(&mutex_blocks);
402-
if(mapallmem)
403-
setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE);
440+
if(mapallmem) {
441+
// defer the setProtection...
442+
//setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE);
443+
defered_prot_p = (uintptr_t)p;
444+
defered_prot_sz = allocsize;
445+
defered_prot_prot = PROT_READ|PROT_WRITE;
446+
}
404447
return ret;
405448
}
406449
void* customCalloc(size_t n, size_t size)
@@ -461,31 +504,6 @@ void customFree(void* p)
461504
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Free\n", (void*)addr);
462505
}
463506

464-
#ifdef DYNAREC
465-
#define GET_PROT_WAIT(A, B) \
466-
uint32_t A; \
467-
do { \
468-
A = native_lock_xchg_b(&block[B], PROT_WAIT); \
469-
} while(A==PROT_WAIT)
470-
#define GET_PROT(A, B) \
471-
uint32_t A; \
472-
do { \
473-
A = native_lock_get_b(&block[B]); \
474-
} while(A==PROT_WAIT)
475-
476-
#define SET_PROT(A, B) native_lock_storeb(&block[A], B)
477-
#define LOCK_NODYNAREC()
478-
#define UNLOCK_DYNAREC() mutex_unlock(&mutex_prot)
479-
#define UNLOCK_NODYNAREC()
480-
#else
481-
#define GET_PROT_WAIT(A, B) uint32_t A = block[B]
482-
#define GET_PROT(A, B) uint32_t A = block[B]
483-
#define SET_PROT(A, B) block[A] = B
484-
#define LOCK_NODYNAREC() mutex_lock(&mutex_prot)
485-
#define UNLOCK_DYNAREC()
486-
#define UNLOCK_NODYNAREC() mutex_unlock(&mutex_prot)
487-
#endif
488-
489507
#ifdef DYNAREC
490508
#define NCHUNK 64
491509
typedef struct mmaplist_s {
@@ -999,7 +1017,7 @@ void protectDBJumpTable(uintptr_t addr, size_t size, void* jump, void* ref)
9991017
uintptr_t cur = addr&~(box64_pagesize-1);
10001018
uintptr_t end = ALIGN(addr+size);
10011019

1002-
mutex_lock(&mutex_prot);
1020+
LOCK_PROT();
10031021
while(cur!=end) {
10041022
uint32_t prot = 0, oprot;
10051023
uintptr_t bend = 0;
@@ -1025,7 +1043,7 @@ void protectDBJumpTable(uintptr_t addr, size_t size, void* jump, void* ref)
10251043
}
10261044
if(jump)
10271045
setJumpTableIfRef64((void*)addr, jump, ref);
1028-
mutex_unlock(&mutex_prot);
1046+
UNLOCK_PROT();
10291047
}
10301048

10311049
// Remove the Write flag from an adress range, so DB can be executed safely
@@ -1036,7 +1054,7 @@ void protectDB(uintptr_t addr, uintptr_t size)
10361054
uintptr_t cur = addr&~(box64_pagesize-1);
10371055
uintptr_t end = ALIGN(addr+size);
10381056

1039-
mutex_lock(&mutex_prot);
1057+
LOCK_PROT();
10401058
while(cur!=end) {
10411059
uint32_t prot = 0, oprot;
10421060
uintptr_t bend = 0;
@@ -1060,7 +1078,7 @@ void protectDB(uintptr_t addr, uintptr_t size)
10601078
rb_set(memprot, cur, bend, prot);
10611079
cur = bend;
10621080
}
1063-
mutex_unlock(&mutex_prot);
1081+
UNLOCK_PROT();
10641082
}
10651083

10661084
// Add the Write flag from an adress range, and mark all block as dirty
@@ -1071,7 +1089,7 @@ void unprotectDB(uintptr_t addr, size_t size, int mark)
10711089
uintptr_t cur = addr&~(box64_pagesize-1);
10721090
uintptr_t end = ALIGN(addr+size);
10731091

1074-
mutex_lock(&mutex_prot);
1092+
LOCK_PROT();
10751093
while(cur!=end) {
10761094
uint32_t prot = 0, oprot;
10771095
uintptr_t bend = 0;
@@ -1098,27 +1116,27 @@ void unprotectDB(uintptr_t addr, size_t size, int mark)
10981116
rb_set(memprot, cur, bend, prot);
10991117
cur = bend;
11001118
}
1101-
mutex_unlock(&mutex_prot);
1119+
UNLOCK_PROT();
11021120
}
11031121

11041122
int isprotectedDB(uintptr_t addr, size_t size)
11051123
{
11061124
dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
11071125
addr &=~(box64_pagesize-1);
11081126
uintptr_t end = ALIGN(addr+size);
1109-
mutex_lock(&mutex_prot);
1127+
LOCK_PROT_READ();
11101128
while (addr < end) {
11111129
uint32_t prot;
11121130
uintptr_t bend;
11131131
if (!rb_get_end(memprot, addr, &prot, &bend) || !(prot&PROT_DYN)) {
11141132
dynarec_log(LOG_DEBUG, "0\n");
1115-
mutex_unlock(&mutex_prot);
1133+
UNLOCK_PROT_READ();
11161134
return 0;
11171135
} else {
11181136
addr = bend;
11191137
}
11201138
}
1121-
mutex_unlock(&mutex_prot);
1139+
UNLOCK_PROT_READ();
11221140
dynarec_log(LOG_DEBUG, "1\n");
11231141
return 1;
11241142
}
@@ -1128,7 +1146,7 @@ int isprotectedDB(uintptr_t addr, size_t size)
11281146
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
11291147
{
11301148
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%hhx\n", (void*)addr, (void*)(addr+size-1), prot);
1131-
mutex_lock(&mutex_prot);
1149+
LOCK_PROT();
11321150
uintptr_t cur = addr & ~(box64_pagesize-1);
11331151
uintptr_t end = ALIGN(cur+size);
11341152
rb_set(mapallmem, cur, cur+size, 1);
@@ -1149,18 +1167,18 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
11491167
rb_set(memprot, cur, bend, prot|dyn);
11501168
cur = bend;
11511169
}
1152-
mutex_unlock(&mutex_prot);
1170+
UNLOCK_PROT();
11531171
}
11541172

11551173
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
11561174
{
11571175
size = ALIGN(size);
1158-
mutex_lock(&mutex_prot);
1176+
LOCK_PROT();
11591177
uintptr_t cur = addr & ~(box64_pagesize-1);
11601178
uintptr_t end = ALIGN(cur+size);
11611179
rb_set(mapallmem, cur, end, 1);
11621180
rb_set(memprot, cur, end, prot);
1163-
mutex_unlock(&mutex_prot);
1181+
UNLOCK_PROT();
11641182
}
11651183

11661184
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
@@ -1169,15 +1187,15 @@ void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
11691187
return;
11701188
addr &= ~(box64_pagesize-1);
11711189
size = ALIGN(size);
1172-
mutex_lock(&mutex_prot);
1190+
LOCK_PROT();
11731191
rb_set(mmapmem, addr, addr+size, 1);
1174-
mutex_unlock(&mutex_prot);
1192+
UNLOCK_PROT();
11751193
if(prot)
11761194
setProtection(addr, size, prot);
11771195
else {
1178-
mutex_lock(&mutex_prot);
1196+
LOCK_PROT();
11791197
rb_set(mapallmem, addr, addr+size, 1);
1180-
mutex_unlock(&mutex_prot);
1198+
UNLOCK_PROT();
11811199
}
11821200
}
11831201

@@ -1188,32 +1206,32 @@ void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot)
11881206
if(prot)
11891207
setProtection(addr, size, prot);
11901208
else {
1191-
mutex_lock(&mutex_prot);
1209+
LOCK_PROT();
11921210
rb_set(mapallmem, addr, addr+size, 1);
1193-
mutex_unlock(&mutex_prot);
1211+
UNLOCK_PROT();
11941212
}
11951213
}
11961214

11971215
void refreshProtection(uintptr_t addr)
11981216
{
1199-
mutex_lock(&mutex_prot);
1217+
LOCK_PROT();
12001218
uint32_t prot;
12011219
uintptr_t bend;
12021220
if (rb_get_end(memprot, addr, &prot, &bend)) {
12031221
int ret = mprotect((void*)(addr&~(box64_pagesize-1)), box64_pagesize, prot&~PROT_CUSTOM);
12041222
dynarec_log(LOG_DEBUG, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr, (void*)(addr&~(box64_pagesize-1)), prot, ret, ret?strerror(errno):"ok");
12051223
}
1206-
mutex_unlock(&mutex_prot);
1224+
UNLOCK_PROT();
12071225
}
12081226

12091227
void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
12101228
{
12111229
dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
12121230
size = ALIGN(size);
12131231
addr &= ~(box64_pagesize-1);
1214-
mutex_lock(&mutex_prot);
1232+
LOCK_PROT();
12151233
rb_set(mapallmem, addr, addr+size, 1);
1216-
mutex_unlock(&mutex_prot);
1234+
UNLOCK_PROT();
12171235
// don't need to add precise tracking probably
12181236
}
12191237

@@ -1254,18 +1272,18 @@ void freeProtection(uintptr_t addr, size_t size)
12541272
size = ALIGN(size);
12551273
addr &= ~(box64_pagesize-1);
12561274
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
1257-
mutex_lock(&mutex_prot);
1275+
LOCK_PROT();
12581276
rb_unset(mapallmem, addr, addr+size);
12591277
rb_unset(mmapmem, addr, addr+size);
12601278
rb_unset(memprot, addr, addr+size);
1261-
mutex_unlock(&mutex_prot);
1279+
UNLOCK_PROT();
12621280
}
12631281

12641282
uint32_t getProtection(uintptr_t addr)
12651283
{
1266-
mutex_lock(&mutex_prot);
1284+
LOCK_PROT_READ();
12671285
uint32_t ret = rb_get(memprot, addr);
1268-
mutex_unlock(&mutex_prot);
1286+
UNLOCK_PROT_READ();
12691287
return ret;
12701288
}
12711289

@@ -1280,7 +1298,7 @@ int getMmapped(uintptr_t addr)
12801298

12811299
void* find31bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
12821300
{
1283-
int prot;
1301+
uint32_t prot;
12841302
if(hint<LOWEST) hint = LOWEST;
12851303
uintptr_t bend = 0;
12861304
uintptr_t cur = (uintptr_t)hint;
@@ -1313,7 +1331,7 @@ void* find47bitBlock(size_t size)
13131331
}
13141332
void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
13151333
{
1316-
int prot;
1334+
uint32_t prot;
13171335
if(hint<LOWEST) hint = LOWEST;
13181336
uintptr_t bend = 0;
13191337
uintptr_t cur = (uintptr_t)hint;
@@ -1347,7 +1365,7 @@ void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask)
13471365

13481366
int isBlockFree(void* hint, size_t size)
13491367
{
1350-
int prot;
1368+
uint32_t prot;
13511369
uintptr_t bend = 0;
13521370
uintptr_t cur = (uintptr_t)hint;
13531371
if(!rb_get_end(mapallmem, cur, &prot, &bend)) {
@@ -1425,7 +1443,7 @@ void reserveHighMem()
14251443
return; // don't reserve by default
14261444
uintptr_t cur = 1ULL<<47;
14271445
uintptr_t bend = 0;
1428-
int prot;
1446+
uint32_t prot;
14291447
while (bend!=0xffffffffffffffffLL) {
14301448
if(!rb_get_end(mapallmem, cur, &prot, &bend)) {
14311449
void* ret = internal_mmap((void*)cur, bend-cur, 0, MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE|MAP_NORESERVE, -1, 0);

0 commit comments

Comments
 (0)