Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for MSVC 2019 without c11 atomics #612

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,31 @@ jobs:
build\${{matrix.buildType}}\run-test262.exe -c tests.conf
build\${{matrix.buildType}}\function_source.exe

windows-msvc-2019:
runs-on: windows-2019
strategy:
fail-fast: false
matrix:
arch: [x64, Win32]
buildType: [Debug, Release]
steps:
- uses: actions/checkout@v4
- name: build
run: |
cmake -B build -DBUILD_EXAMPLES=ON -G "Visual Studio 16 2019" -A ${{matrix.arch}}
cmake --build build --config ${{matrix.buildType}}
- name: stats
run: |
build\${{matrix.buildType}}\qjs.exe -qd
- name: test
run: |
cp build\${{matrix.buildType}}\fib.dll examples\
cp build\${{matrix.buildType}}\point.dll examples\
build\${{matrix.buildType}}\qjs.exe examples\test_fib.js
build\${{matrix.buildType}}\qjs.exe examples\test_point.js
build\${{matrix.buildType}}\run-test262.exe -c tests.conf
build\${{matrix.buildType}}\function_source.exe

windows-clang:
runs-on: windows-latest
strategy:
Expand Down
71 changes: 63 additions & 8 deletions quickjs-libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,15 @@ extern char **environ;

#include "cutils.h"
#include "list.h"

#if !defined(EMSCRIPTEN) && !defined(__wasi__) && !defined(__STDC_NO_ATOMICS__)
#if defined(_MSC_VER) && _MSC_VER < 1941
#pragma message("This msvc is too old to support c11atomics, so atomics are disabled.")
#else
#include "quickjs-c-atomics.h"
#define CONFIG_ATOMICS
#endif
#endif
#include "quickjs-libc.h"

#define MAX_SAFE_INTEGER (((int64_t) 1 << 53) - 1)
Expand Down Expand Up @@ -141,6 +149,9 @@ typedef struct {
typedef struct {
int ref_count;
#ifdef USE_WORKER
#ifndef CONFIG_ATOMICS
pthread_mutex_t ref_count_mutex;
#endif
pthread_mutex_t mutex;
#endif
struct list_head msg_queue; /* list of JSWorkerMessage.link */
Expand Down Expand Up @@ -169,7 +180,33 @@ typedef struct JSThreadState {
} JSThreadState;

static uint64_t os_pending_signals;
static _Atomic int can_js_os_poll;
#ifdef CONFIG_ATOMICS
#define ATOMIC_OS_POLL_SET(x) atomic_store(&_can_js_os_poll, x)
#define ATOMIC_OS_POLL_GET() atomic_load(&_can_js_os_poll)
static _Atomic int _can_js_os_poll;
#else
#ifdef USE_WORKER
#define ATOMIC_OS_POLL_SET(x) js_os_poll_set(x)
#define ATOMIC_OS_POLL_GET() js_os_poll_get()
static int _can_js_os_poll;
static pthread_mutex_t _poll_mutex;
static void js_os_poll_set(int value) {
pthread_mutex_lock(&_poll_mutex);
_can_js_os_poll = value;
pthread_mutex_unlock(&_poll_mutex);
}
static int js_os_poll_get(void) {
pthread_mutex_lock(&_poll_mutex);
int value = _can_js_os_poll;
pthread_mutex_unlock(&_poll_mutex);
return value;
}
#else
// the os cannot poll safely, we always return false.
#define ATOMIC_OS_POLL_SET(x)
#define ATOMIC_OS_POLL_GET() 0
#endif
#endif

static void js_std_dbuf_init(JSContext *ctx, DynBuf *s)
{
Expand Down Expand Up @@ -3282,16 +3319,34 @@ typedef struct {
} WorkerFuncArgs;

typedef struct {
#ifndef CONFIG_ATOMICS
pthread_mutex_t ref_count_mutex;
#endif
int ref_count;
uint64_t buf[];
} JSSABHeader;

static JSContext *(*js_worker_new_context_func)(JSRuntime *rt);

#ifdef CONFIG_ATOMICS
// we do not use mutex when atomics are available
#define ATOMIC_REF_COUNT_ADD(x, v) atomic_add_int(&x->ref_count, v)
static int atomic_add_int(int *ptr, int v)
{
return atomic_fetch_add((_Atomic uint32_t*)ptr, v) + v;
}
#else
// we need mutex when atomics are NOT available
#define ATOMIC_REF_COUNT_ADD(x, v) mutex_add_int(&x->ref_count, v, &x->ref_count_mutex)
static int mutex_add_int(int *ptr, int v, pthread_mutex_t* mutex)
{
pthread_mutex_lock(mutex);
int updated = (*ptr) + v;
*ptr = updated;
pthread_mutex_unlock(mutex);
return updated;
}
#endif

/* shared array buffer allocator */
static void *js_sab_alloc(void *opaque, size_t size)
Expand All @@ -3309,7 +3364,7 @@ static void js_sab_free(void *opaque, void *ptr)
JSSABHeader *sab;
int ref_count;
sab = (JSSABHeader *)((uint8_t *)ptr - sizeof(JSSABHeader));
ref_count = atomic_add_int(&sab->ref_count, -1);
ref_count = ATOMIC_REF_COUNT_ADD(sab, -1);
assert(ref_count >= 0);
if (ref_count == 0) {
free(sab);
Expand All @@ -3320,7 +3375,7 @@ static void js_sab_dup(void *opaque, void *ptr)
{
JSSABHeader *sab;
sab = (JSSABHeader *)((uint8_t *)ptr - sizeof(JSSABHeader));
atomic_add_int(&sab->ref_count, 1);
ATOMIC_REF_COUNT_ADD(sab, 1);
}

static JSWorkerMessagePipe *js_new_message_pipe(void)
Expand All @@ -3347,7 +3402,7 @@ static JSWorkerMessagePipe *js_new_message_pipe(void)

static JSWorkerMessagePipe *js_dup_message_pipe(JSWorkerMessagePipe *ps)
{
atomic_add_int(&ps->ref_count, 1);
ATOMIC_REF_COUNT_ADD(ps, 1);
return ps;
}

Expand All @@ -3372,7 +3427,7 @@ static void js_free_message_pipe(JSWorkerMessagePipe *ps)
if (!ps)
return;

ref_count = atomic_add_int(&ps->ref_count, -1);
ref_count = ATOMIC_REF_COUNT_ADD(ps, -1);
assert(ref_count >= 0);
if (ref_count == 0) {
list_for_each_safe(el, el1, &ps->msg_queue) {
Expand Down Expand Up @@ -3844,7 +3899,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {

static int js_os_init(JSContext *ctx, JSModuleDef *m)
{
atomic_store(&can_js_os_poll, TRUE);
ATOMIC_OS_POLL_SET(TRUE);

#ifdef USE_WORKER
{
Expand Down Expand Up @@ -4099,7 +4154,7 @@ JSValue js_std_loop(JSContext *ctx)
}
}

if (!atomic_load(&can_js_os_poll) || js_os_poll(ctx))
if (!ATOMIC_OS_POLL_GET() || js_os_poll(ctx))
break;
}
done:
Expand Down Expand Up @@ -4131,7 +4186,7 @@ JSValue js_std_await(JSContext *ctx, JSValue obj)
if (err < 0) {
js_std_dump_error(ctx1);
}
if (atomic_load(&can_js_os_poll))
if (ATOMIC_OS_POLL_GET())
js_os_poll(ctx);
} else {
/* not a promise */
Expand Down
4 changes: 4 additions & 0 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@
#endif

#if !defined(EMSCRIPTEN) && !defined(__wasi__) && !defined(__STDC_NO_ATOMICS__)
#if defined(_MSC_VER) && _MSC_VER < 1941
#pragma message("This msvc is too old to support c11atomics, so atomics are disabled.")
#else
#include "quickjs-c-atomics.h"
#define CONFIG_ATOMICS
#endif
#endif

#ifndef __GNUC__
#define __extension__
Expand Down
Loading