Skip to content

Commit da5d73c

Browse files
authored
Add lock around coverage operations (#59517)
Fixes #59355
1 parent b9e4274 commit da5d73c

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

src/codegen.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2827,10 +2827,9 @@ static void visitLine(jl_codectx_t &ctx, uint64_t *ptr, Value *addend, const cha
28272827
Value *pv = ConstantExpr::getIntToPtr(
28282828
ConstantInt::get(ctx.types().T_size, (uintptr_t)ptr),
28292829
getPointerTy(ctx.builder.getContext()));
2830-
Value *v = ctx.builder.CreateLoad(getInt64Ty(ctx.builder.getContext()), pv, true, name);
2831-
v = ctx.builder.CreateAdd(v, addend);
2832-
ctx.builder.CreateStore(v, pv, true); // volatile, not atomic, so this might be an underestimate,
2833-
// but it's faster this way
2830+
ctx.builder.CreateAtomicRMW(AtomicRMWInst::Add, pv,
2831+
addend, MaybeAlign(),
2832+
AtomicOrdering::Monotonic);
28342833
}
28352834

28362835
// Code coverage

src/coverage.cpp

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// This file is a part of Julia. License is MIT: https://julialang.org/license
22

3+
#include <cstdint>
4+
#include <pthread.h>
35
#include <string>
46
#include <fstream>
57
#include <map>
@@ -15,7 +17,7 @@
1517

1618
using namespace llvm;
1719

18-
static int codegen_imaging_mode(void)
20+
static int codegen_imaging_mode(void) JL_NOTSAFEPOINT
1921
{
2022
return jl_options.image_codegen || (jl_generating_output() && jl_options.use_pkgimages);
2123
}
@@ -26,7 +28,9 @@ const int logdata_blocksize = 32; // target getting nearby lines in the same gen
2628
typedef uint64_t logdata_block[logdata_blocksize];
2729
typedef StringMap< SmallVector<logdata_block*, 0> > logdata_t;
2830

29-
static uint64_t *allocLine(SmallVector<logdata_block*, 0> &vec, int line)
31+
pthread_mutex_t coverage_lock = PTHREAD_MUTEX_INITIALIZER;
32+
33+
static uint64_t *allocLine(SmallVector<logdata_block*, 0> &vec, int line) JL_NOTSAFEPOINT
3034
{
3135
unsigned block = line / logdata_blocksize;
3236
line = line % logdata_blocksize;
@@ -45,39 +49,49 @@ static uint64_t *allocLine(SmallVector<logdata_block*, 0> &vec, int line)
4549

4650
static logdata_t coverageData;
4751

48-
JL_DLLEXPORT void jl_coverage_alloc_line(StringRef filename, int line)
52+
JL_DLLEXPORT void jl_coverage_alloc_line(StringRef filename, int line) JL_NOTSAFEPOINT
4953
{
5054
assert(!codegen_imaging_mode());
5155
if (filename == "" || filename == "none" || filename == "no file" || filename == "<missing>" || line < 0)
5256
return;
57+
pthread_mutex_lock(&coverage_lock);
5358
allocLine(coverageData[filename], line);
59+
pthread_mutex_unlock(&coverage_lock);
5460
}
5561

56-
JL_DLLEXPORT uint64_t *jl_coverage_data_pointer(StringRef filename, int line)
62+
JL_DLLEXPORT uint64_t *jl_coverage_data_pointer(StringRef filename, int line) JL_NOTSAFEPOINT
5763
{
58-
return allocLine(coverageData[filename], line);
64+
pthread_mutex_lock(&coverage_lock);
65+
uint64_t* ret = allocLine(coverageData[filename], line);
66+
pthread_mutex_unlock(&coverage_lock);
67+
return ret;
5968
}
6069

61-
extern "C" JL_DLLEXPORT void jl_coverage_visit_line(const char *filename_, size_t len_filename, int line)
70+
extern "C" JL_DLLEXPORT void jl_coverage_visit_line(const char *filename_, size_t len_filename, int line) JL_NOTSAFEPOINT
6271
{
6372
StringRef filename = StringRef(filename_, len_filename);
6473
if (codegen_imaging_mode() || filename == "" || filename == "none" || filename == "no file" || filename == "<missing>" || line < 0)
6574
return;
75+
pthread_mutex_lock(&coverage_lock);
6676
SmallVector<logdata_block*, 0> &vec = coverageData[filename];
6777
uint64_t *ptr = allocLine(vec, line);
6878
(*ptr)++;
79+
pthread_mutex_unlock(&coverage_lock);
6980
}
7081

7182
// Memory allocation log (malloc_log)
7283

7384
static logdata_t mallocData;
7485

75-
JL_DLLEXPORT uint64_t *jl_malloc_data_pointer(StringRef filename, int line)
86+
JL_DLLEXPORT uint64_t *jl_malloc_data_pointer(StringRef filename, int line) JL_NOTSAFEPOINT
7687
{
77-
return allocLine(mallocData[filename], line);
88+
pthread_mutex_lock(&coverage_lock);
89+
uint64_t* ret = allocLine(mallocData[filename], line);
90+
pthread_mutex_unlock(&coverage_lock);
91+
return ret;
7892
}
7993

80-
static void clear_log_data(logdata_t &logData, int resetValue)
94+
static void clear_log_data(logdata_t &logData, int resetValue) JL_NOTSAFEPOINT
8195
{
8296
logdata_t::iterator it = logData.begin();
8397
for (; it != logData.end(); it++) {
@@ -97,18 +111,22 @@ static void clear_log_data(logdata_t &logData, int resetValue)
97111
}
98112

99113
// Resets the malloc counts.
100-
extern "C" JL_DLLEXPORT void jl_clear_malloc_data(void)
114+
extern "C" JL_DLLEXPORT void jl_clear_malloc_data(void) JL_NOTSAFEPOINT
101115
{
116+
pthread_mutex_lock(&coverage_lock);
102117
clear_log_data(mallocData, 1);
118+
pthread_mutex_unlock(&coverage_lock);
103119
}
104120

105121
// Resets the code coverage
106-
extern "C" JL_DLLEXPORT void jl_clear_coverage_data(void)
122+
extern "C" JL_DLLEXPORT void jl_clear_coverage_data(void) JL_NOTSAFEPOINT
107123
{
124+
pthread_mutex_lock(&coverage_lock);
108125
clear_log_data(coverageData, 0);
126+
pthread_mutex_unlock(&coverage_lock);
109127
}
110128

111-
static void write_log_data(logdata_t &logData, const char *extension)
129+
static void write_log_data(logdata_t &logData, const char *extension) JL_NOTSAFEPOINT
112130
{
113131
std::string base = std::string(jl_options.julia_bindir);
114132
base = base + "/../share/julia/base/";
@@ -163,7 +181,7 @@ static void write_log_data(logdata_t &logData, const char *extension)
163181
}
164182
}
165183

166-
static void write_lcov_data(logdata_t &logData, const std::string &outfile)
184+
static void write_lcov_data(logdata_t &logData, const std::string &outfile) JL_NOTSAFEPOINT
167185
{
168186
std::ofstream outf(outfile.c_str(), std::ofstream::ate | std::ofstream::out | std::ofstream::binary);
169187
//std::string base = std::string(jl_options.julia_bindir);
@@ -203,8 +221,9 @@ static void write_lcov_data(logdata_t &logData, const std::string &outfile)
203221
outf.close();
204222
}
205223

206-
extern "C" JL_DLLEXPORT void jl_write_coverage_data(const char *output)
224+
extern "C" JL_DLLEXPORT void jl_write_coverage_data(const char *output) JL_NOTSAFEPOINT
207225
{
226+
pthread_mutex_lock(&coverage_lock);
208227
if (output) {
209228
StringRef output_pattern(output);
210229
if (output_pattern.ends_with(".info"))
@@ -215,11 +234,14 @@ extern "C" JL_DLLEXPORT void jl_write_coverage_data(const char *output)
215234
raw_string_ostream(stm) << "." << uv_os_getpid() << ".cov";
216235
write_log_data(coverageData, stm.c_str());
217236
}
237+
pthread_mutex_unlock(&coverage_lock);
218238
}
219239

220-
extern "C" void jl_write_malloc_log(void)
240+
extern "C" void jl_write_malloc_log(void) JL_NOTSAFEPOINT
221241
{
242+
pthread_mutex_lock(&coverage_lock);
222243
std::string stm;
223244
raw_string_ostream(stm) << "." << uv_os_getpid() << ".mem";
224245
write_log_data(mallocData, stm.c_str());
246+
pthread_mutex_unlock(&coverage_lock);
225247
}

src/julia.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2619,7 +2619,7 @@ JL_DLLEXPORT ssize_t jl_sizeof_jl_options(void);
26192619
// Parse an argc/argv pair to extract general julia options, passing back out
26202620
// any arguments that should be passed on to the script.
26212621
JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp);
2622-
JL_DLLEXPORT char *jl_format_filename(const char *output_pattern);
2622+
JL_DLLEXPORT char *jl_format_filename(const char *output_pattern) JL_NOTSAFEPOINT;
26232623

26242624
uint64_t parse_heap_size_option(const char *optarg, const char *option_name, int allow_pct);
26252625

src/runtime_ccall.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ jl_value_t *jl_get_JIT(void)
106106
// %L The local hostname.
107107
// %l The local hostname, including the domain name.
108108
// %u The local username.
109-
std::string jl_format_filename(StringRef output_pattern)
109+
std::string jl_format_filename(StringRef output_pattern) JL_NOTSAFEPOINT
110110
{
111111
std::string buf;
112112
raw_string_ostream outfile(buf);
@@ -168,7 +168,7 @@ std::string jl_format_filename(StringRef output_pattern)
168168
return outfile.str();
169169
}
170170

171-
extern "C" JL_DLLEXPORT char *jl_format_filename(const char *output_pattern)
171+
extern "C" JL_DLLEXPORT char *jl_format_filename(const char *output_pattern) JL_NOTSAFEPOINT
172172
{
173173
return strdup(jl_format_filename(StringRef(output_pattern)).c_str());
174174
}

0 commit comments

Comments
 (0)