Skip to content

Commit 62fb636

Browse files
authored
Implement os.Worker on Windows (#1003)
1 parent fc31927 commit 62fb636

File tree

8 files changed

+305
-214
lines changed

8 files changed

+305
-214
lines changed

.github/workflows/ci.yml

-25
Original file line numberDiff line numberDiff line change
@@ -209,31 +209,6 @@ jobs:
209209
cl.exe /DJS_NAN_BOXING=0 /Zs cxxtest.cc
210210
cl.exe /DJS_NAN_BOXING=1 /Zs cxxtest.cc
211211
212-
windows-msvc-vs2019:
213-
runs-on: windows-2019
214-
strategy:
215-
fail-fast: false
216-
matrix:
217-
arch: [x64, Win32]
218-
buildType: [Debug, Release]
219-
steps:
220-
- uses: actions/checkout@v4
221-
- name: build
222-
run: |
223-
cmake -B build -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio 16 2019" -A ${{matrix.arch}}
224-
cmake --build build --config ${{matrix.buildType}} --target qjs_exe
225-
- name: stats
226-
run: |
227-
build\${{matrix.buildType}}\qjs.exe -qd
228-
- name: Set up Visual Studio shell
229-
uses: egor-tensin/vs-shell@v2
230-
with:
231-
arch: ${{ matrix.arch == 'x64' && 'x64' || 'x86' }}
232-
- name: cxxtest
233-
run: |
234-
cl.exe /DJS_NAN_BOXING=0 /Zs cxxtest.cc
235-
cl.exe /DJS_NAN_BOXING=1 /Zs cxxtest.cc
236-
237212
windows-clang:
238213
runs-on: windows-latest
239214
strategy:

CMakeLists.txt

+11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
1010
set(CMAKE_C_EXTENSIONS ON)
1111
set(CMAKE_C_STANDARD 11)
1212

13+
# MINGW doesn't exist in older cmake versions, newer versions don't know
14+
# about CMAKE_COMPILER_IS_MINGW, and there is no unique CMAKE_C_COMPILER_ID
15+
# for mingw-based compilers...
16+
if(MINGW)
17+
# do nothing
18+
elseif(CMAKE_C_COMPILER MATCHES "mingw")
19+
set(MINGW TRUE)
20+
else()
21+
set(MINGW FALSE)
22+
endif()
23+
1324
if(NOT CMAKE_BUILD_TYPE)
1425
message(STATUS "No build type selected, default to Release")
1526
set(CMAKE_BUILD_TYPE "Release")

cutils.c

+72-4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
#if !defined(_MSC_VER)
3232
#include <sys/time.h>
3333
#endif
34+
#if defined(_WIN32)
35+
#include <windows.h>
36+
#include <process.h> // _beginthread
37+
#endif
3438

3539
#include "cutils.h"
3640

@@ -1199,8 +1203,7 @@ int64_t js__gettimeofday_us(void) {
11991203

12001204
/*--- Cross-platform threading APIs. ----*/
12011205

1202-
#if !defined(EMSCRIPTEN) && !defined(__wasi__)
1203-
1206+
#if JS_HAVE_THREADS
12041207
#if defined(_WIN32)
12051208
typedef void (*js__once_cb)(void);
12061209

@@ -1267,6 +1270,37 @@ int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
12671270
return -1;
12681271
}
12691272

1273+
int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg,
1274+
int flags)
1275+
{
1276+
HANDLE h, cp;
1277+
1278+
*thrd = INVALID_HANDLE_VALUE;
1279+
if (flags & ~JS_THREAD_CREATE_DETACHED)
1280+
return -1;
1281+
h = (HANDLE)_beginthread(start, /*stacksize*/2<<20, arg);
1282+
if (!h)
1283+
return -1;
1284+
if (flags & JS_THREAD_CREATE_DETACHED)
1285+
return 0;
1286+
// _endthread() automatically closes the handle but we want to wait on
1287+
// it so make a copy. Race-y for very short-lived threads. Can be solved
1288+
// by switching to _beginthreadex(CREATE_SUSPENDED) but means changing
1289+
// |start| from __cdecl to __stdcall.
1290+
cp = GetCurrentProcess();
1291+
if (DuplicateHandle(cp, h, cp, thrd, 0, FALSE, DUPLICATE_SAME_ACCESS))
1292+
return 0;
1293+
return -1;
1294+
}
1295+
1296+
int js_thread_join(js_thread_t thrd)
1297+
{
1298+
if (WaitForSingleObject(thrd, INFINITE))
1299+
return -1;
1300+
CloseHandle(thrd);
1301+
return 0;
1302+
}
1303+
12701304
#else /* !defined(_WIN32) */
12711305

12721306
void js_once(js_once_t *guard, void (*callback)(void)) {
@@ -1407,9 +1441,43 @@ int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout) {
14071441
return -1;
14081442
}
14091443

1410-
#endif
1444+
int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg,
1445+
int flags)
1446+
{
1447+
union {
1448+
void (*x)(void *);
1449+
void *(*f)(void *);
1450+
} u = {start};
1451+
pthread_attr_t attr;
1452+
int ret;
1453+
1454+
if (flags & ~JS_THREAD_CREATE_DETACHED)
1455+
return -1;
1456+
if (pthread_attr_init(&attr))
1457+
return -1;
1458+
ret = -1;
1459+
if (pthread_attr_setstacksize(&attr, 2<<20))
1460+
goto fail;
1461+
if (flags & JS_THREAD_CREATE_DETACHED)
1462+
if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
1463+
goto fail;
1464+
if (pthread_create(thrd, &attr, u.f, arg))
1465+
goto fail;
1466+
ret = 0;
1467+
fail:
1468+
pthread_attr_destroy(&attr);
1469+
return ret;
1470+
}
1471+
1472+
int js_thread_join(js_thread_t thrd)
1473+
{
1474+
if (pthread_join(thrd, NULL))
1475+
return -1;
1476+
return 0;
1477+
}
14111478

1412-
#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
1479+
#endif /* !defined(_WIN32) */
1480+
#endif /* JS_HAVE_THREADS */
14131481

14141482
#ifdef __GNUC__
14151483
#pragma GCC visibility pop

cutils.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -563,18 +563,26 @@ static inline size_t js__malloc_usable_size(const void *ptr)
563563

564564
/* Cross-platform threading APIs. */
565565

566-
#if !defined(EMSCRIPTEN) && !defined(__wasi__)
566+
#if defined(EMSCRIPTEN) || defined(__wasi__)
567+
568+
#define JS_HAVE_THREADS 0
569+
570+
#else
571+
572+
#define JS_HAVE_THREADS 1
567573

568574
#if defined(_WIN32)
569575
#define JS_ONCE_INIT INIT_ONCE_STATIC_INIT
570576
typedef INIT_ONCE js_once_t;
571577
typedef CRITICAL_SECTION js_mutex_t;
572578
typedef CONDITION_VARIABLE js_cond_t;
579+
typedef HANDLE js_thread_t;
573580
#else
574581
#define JS_ONCE_INIT PTHREAD_ONCE_INIT
575582
typedef pthread_once_t js_once_t;
576583
typedef pthread_mutex_t js_mutex_t;
577584
typedef pthread_cond_t js_cond_t;
585+
typedef pthread_t js_thread_t;
578586
#endif
579587

580588
void js_once(js_once_t *guard, void (*callback)(void));
@@ -591,6 +599,15 @@ void js_cond_broadcast(js_cond_t *cond);
591599
void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex);
592600
int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout);
593601

602+
enum {
603+
JS_THREAD_CREATE_DETACHED = 1,
604+
};
605+
606+
// creates threads with 2 MB stacks (glibc default)
607+
int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg,
608+
int flags);
609+
int js_thread_join(js_thread_t thrd);
610+
594611
#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
595612

596613
#ifdef __cplusplus

docs/docs/supported_platforms.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ sidebar_position: 8
88
|---|---|---|
99
| GNU/Linux | * | glibc and musl are supported |
1010
| macOS | macOS >= 11 | Currently supported macOS releases |
11-
| Windows | >= Windows 7* | VS >= 2022 and Clang are supported |
11+
| Windows | >= Windows 7* | VS >= 2022 and Clang are supported; requires `<stdatomic.h>` |
1212
| FreeBSD | * | Limited testing |
1313
| OpenBSD | * | Limited testing |
1414
| NetBSD | * | Limited testing |

0 commit comments

Comments
 (0)