Skip to content

Commit

Permalink
Don't use _Thread_local in run-test262.c
Browse files Browse the repository at this point in the history
Allows building with tcc and old gcc versions again.
  • Loading branch information
bnoordhuis committed Nov 9, 2024
1 parent 163b1d4 commit e574e6c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 43 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ jobs:
make cxxtest
- name: test
if: ${{ matrix.config.configType != 'examples' && matrix.config.configType != 'tcc' }}
if: ${{ matrix.config.configType != 'examples' }}
run: |
make test
Expand Down Expand Up @@ -191,6 +191,9 @@ jobs:
- name: stats
run: |
./build/qjs -qd
- name: test
run: |
make test
windows-msvc:
runs-on: windows-latest
Expand Down
9 changes: 1 addition & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,7 @@ endif()
# Test262 runner
#

if(EMSCRIPTEN
OR CMAKE_C_COMPILER_ID STREQUAL "TinyCC"
OR (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 5))
# Empty. run-test262 uses pthreads, sorry Windows users.
# tcc and gcc 4.8 don't understand _Thread_local, whereas I
# don't understand why people still use 4.8 in this day and age
# but hey, here we are.
else()
if(NOT EMSCRIPTEN)
add_executable(run-test262
run-test262.c
)
Expand Down
79 changes: 45 additions & 34 deletions run-test262.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ typedef pthread_t js_thread_t;

#define CMD_NAME "run-test262"

typedef struct {
js_mutex_t agent_mutex;
js_cond_t agent_cond;
/* list of Test262Agent.link */
struct list_head agent_list;
js_mutex_t report_mutex;
/* list of AgentReport.link */
struct list_head report_list;
int async_done;
} ThreadLocalStorage;

typedef struct namelist_t {
char **array;
int count;
Expand Down Expand Up @@ -97,7 +108,6 @@ int start_index, stop_index;
int test_excluded;
_Atomic int test_count, test_failed, test_skipped;
_Atomic int new_errors, changed_errors, fixed_errors;
_Thread_local int async_done;

void warning(const char *, ...) __attribute__((__format__(__printf__, 1, 2)));
void fatal(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3)));
Expand Down Expand Up @@ -443,6 +453,7 @@ static void enumerate_tests(const char *path)
static JSValue js_print_262(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
int i;
const char *str;

Expand All @@ -451,9 +462,9 @@ static JSValue js_print_262(JSContext *ctx, JSValue this_val,
if (!str)
return JS_EXCEPTION;
if (!strcmp(str, "Test262:AsyncTestComplete")) {
async_done++;
tls->async_done++;
} else if (strstart(str, "Test262:AsyncTestFailure", NULL)) {
async_done = 2; /* force an error */
tls->async_done = 2; /* force an error */
}
if (outfile) {
if (i != 0)
Expand Down Expand Up @@ -552,28 +563,16 @@ static long cpu_count(void)
#endif
}

typedef struct {
js_mutex_t agent_mutex;
js_cond_t agent_cond;
/* list of Test262Agent.link */
struct list_head agent_list;
js_mutex_t report_mutex;
/* list of AgentReport.link */
struct list_head report_list;
} ThreadLocalStorage;

static void init_thread_local_storage(ThreadLocalStorage *p)
{
js_mutex_init(&p->agent_mutex);
js_cond_init(&p->agent_cond);
init_list_head(&p->agent_list);
js_mutex_init(&p->report_mutex);
init_list_head(&p->report_list);
p->async_done = 0;
}

// points to parent thread's TLS in agent threads
static _Thread_local ThreadLocalStorage *tls;

typedef struct {
struct list_head link;
js_thread_t tid;
Expand All @@ -597,17 +596,20 @@ static void add_helpers(JSContext *ctx);

static void *agent_start(void *arg)
{
Test262Agent *agent = arg;
ThreadLocalStorage *tls;
Test262Agent *agent;
JSRuntime *rt;
JSContext *ctx;
JSValue ret_val;
int ret;

agent = arg;
tls = agent->tls; // shares thread-local storage with parent thread
rt = JS_NewRuntime();
if (rt == NULL) {
fatal(1, "JS_NewRuntime failure");
}
JS_SetRuntimeOpaque(rt, tls);
ctx = JS_NewContext(rt);
if (ctx == NULL) {
JS_FreeRuntime(rt);
Expand Down Expand Up @@ -674,6 +676,7 @@ static void *agent_start(void *arg)
static JSValue js_agent_start(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
const char *script;
Test262Agent *agent;

Expand All @@ -697,6 +700,7 @@ static JSValue js_agent_start(JSContext *ctx, JSValue this_val,

static void js_agent_free(JSContext *ctx)
{
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
struct list_head *el, *el1;
Test262Agent *agent;

Expand All @@ -719,7 +723,7 @@ static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val,
return JS_UNDEFINED;
}

static BOOL is_broadcast_pending(void)
static BOOL is_broadcast_pending(ThreadLocalStorage *tls)
{
struct list_head *el;
Test262Agent *agent;
Expand All @@ -734,6 +738,7 @@ static BOOL is_broadcast_pending(void)
static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
JSValue sab = argv[0];
struct list_head *el;
Test262Agent *agent;
Expand Down Expand Up @@ -765,7 +770,7 @@ static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val,
}
js_cond_broadcast(&tls->agent_cond);

while (is_broadcast_pending()) {
while (is_broadcast_pending(tls)) {
js_cond_wait(&tls->agent_cond, &tls->agent_mutex);
}
js_mutex_unlock(&tls->agent_mutex);
Expand Down Expand Up @@ -819,6 +824,7 @@ static JSValue js_agent_monotonicNow(JSContext *ctx, JSValue this_val,
static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
AgentReport *rep;
JSValue ret;

Expand All @@ -843,6 +849,7 @@ static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val,
static JSValue js_agent_report(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
const char *str;
AgentReport *rep;

Expand Down Expand Up @@ -1338,6 +1345,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
const char *error_type, int eval_flags, int is_async,
int *msec)
{
ThreadLocalStorage *tls = JS_GetRuntimeOpaque(JS_GetRuntime(ctx));
JSValue res_val, exception_val;
int ret, error_line, pos, pos_line;
BOOL is_error, has_error_line, ret_promise;
Expand All @@ -1352,7 +1360,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,

/* a module evaluation returns a promise */
ret_promise = ((eval_flags & JS_EVAL_TYPE_MODULE) != 0);
async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */
tls->async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */

start = get_clock_ms();
res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
Expand All @@ -1373,7 +1381,7 @@ static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len,
} else if (ret == 0) {
if (is_async) {
/* test if the test called $DONE() once */
if (async_done != 1) {
if (tls->async_done != 1) {
res_val = JS_ThrowTypeError(ctx, "$DONE() not called");
} else {
res_val = JS_UNDEFINED;
Expand Down Expand Up @@ -1721,10 +1729,10 @@ JSContext *JS_NewCustomContext(JSRuntime *rt)
return ctx;
}

int run_test_buf(const char *filename, char *harness, namelist_t *ip,
char *buf, size_t buf_len, const char* error_type,
int eval_flags, BOOL is_negative, BOOL is_async,
BOOL can_block, int *msec)
int run_test_buf(ThreadLocalStorage *tls, const char *filename, char *harness,
namelist_t *ip, char *buf, size_t buf_len,
const char* error_type, int eval_flags, BOOL is_negative,
BOOL is_async, BOOL can_block, int *msec)
{
JSRuntime *rt;
JSContext *ctx;
Expand All @@ -1734,6 +1742,7 @@ int run_test_buf(const char *filename, char *harness, namelist_t *ip,
if (rt == NULL) {
fatal(1, "JS_NewRuntime failure");
}
JS_SetRuntimeOpaque(rt, tls);
js_std_init_handlers(rt);
ctx = JS_NewCustomContext(rt);
if (ctx == NULL) {
Expand Down Expand Up @@ -1782,7 +1791,7 @@ int run_test_buf(const char *filename, char *harness, namelist_t *ip,
return ret;
}

int run_test(const char *filename, int *msec)
int run_test(ThreadLocalStorage *tls, const char *filename, int *msec)
{
char harnessbuf[1024];
char *harness;
Expand Down Expand Up @@ -1943,12 +1952,12 @@ int run_test(const char *filename, int *msec)
}
ret = 0;
if (use_nostrict) {
ret = run_test_buf(filename, harness, ip, buf, buf_len,
ret = run_test_buf(tls, filename, harness, ip, buf, buf_len,
error_type, eval_flags, is_negative, is_async,
can_block, msec);
}
if (use_strict) {
ret |= run_test_buf(filename, harness, ip, buf, buf_len,
ret |= run_test_buf(tls, filename, harness, ip, buf, buf_len,
error_type, eval_flags | JS_EVAL_FLAG_STRICT,
is_negative, is_async, can_block, msec);
}
Expand All @@ -1961,7 +1970,8 @@ int run_test(const char *filename, int *msec)
}

/* run a test when called by test262-harness+eshost */
int run_test262_harness_test(const char *filename, BOOL is_module)
int run_test262_harness_test(ThreadLocalStorage *tls, const char *filename,
BOOL is_module)
{
JSRuntime *rt;
JSContext *ctx;
Expand All @@ -1977,6 +1987,7 @@ int run_test262_harness_test(const char *filename, BOOL is_module)
if (rt == NULL) {
fatal(1, "JS_NewRuntime failure");
}
JS_SetRuntimeOpaque(rt, tls);
ctx = JS_NewContext(rt);
if (ctx == NULL) {
JS_FreeRuntime(rt);
Expand Down Expand Up @@ -2072,18 +2083,18 @@ int include_exclude_or_skip(int i) // naming is hard...

void *run_test_dir_list(void *arg)
{
ThreadLocalStorage tls_s, *tls = &tls_s;
const char *p;
int i, msec;

tls = &(ThreadLocalStorage){};
init_thread_local_storage(tls);

for (i = (uintptr_t)arg; i < test_list.count; i += nthreads) {
if (INCLUDE != include_exclude_or_skip(i))
continue;
p = test_list.array[i];
msec = 0;
run_test(p, &msec);
run_test(tls, p, &msec);
if (verbose > 1 || (slow_test_threshold && msec >= slow_test_threshold))
fprintf(stderr, "%s (%d ms)\n", p, msec);
}
Expand Down Expand Up @@ -2124,6 +2135,7 @@ char *get_opt_arg(const char *option, char *arg)

int main(int argc, char **argv)
{
ThreadLocalStorage tls_s, *tls = &tls_s;
int i, optind;
BOOL is_dir_list;
BOOL only_check_errors = FALSE;
Expand All @@ -2134,7 +2146,6 @@ int main(int argc, char **argv)

js_std_set_worker_new_context_func(JS_NewCustomContext);

tls = &(ThreadLocalStorage){};
init_thread_local_storage(tls);
js_mutex_init(&stats_mutex);

Expand Down Expand Up @@ -2209,7 +2220,7 @@ int main(int argc, char **argv)
help();

if (is_test262_harness) {
return run_test262_harness_test(argv[optind], is_module);
return run_test262_harness_test(tls, argv[optind], is_module);
}

nthreads = max_int(nthreads, 1);
Expand Down Expand Up @@ -2276,7 +2287,7 @@ int main(int argc, char **argv)
} else {
while (optind < argc) {
int msec = 0;
run_test(argv[optind++], &msec);
run_test(tls, argv[optind++], &msec);
}
}

Expand Down

0 comments on commit e574e6c

Please sign in to comment.