runtime/cgo: use CreateThread instead of _beginthread

_beginthread is intended to be used together with the C runtime.
The cgo runtime doesn't use it, so better use CreateThread directly,
which is the Windows API for creating threads.

Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-longtest,gotip-windows-arm64
Change-Id: Ic6cf75f69f62a3babf5e74155da1aac70961886c
Reviewed-on: https://go-review.googlesource.com/c/go/+/651995
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
qmuntal 2025-02-24 15:37:41 +01:00 committed by Quim Muntal
parent c5ff26a7a0
commit 00e793cfe3
5 changed files with 23 additions and 22 deletions

View File

@ -2,19 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
# ifdef __CYGWIN__
#ifdef __CYGWIN__
#error "don't use the cygwin compiler to build native Windows programs; use MinGW instead"
#else
// Exclude the following code from Cygwin builds.
// Cygwin doesn't implement process.h nor does it support _beginthread.
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "libcgo.h"
#include "libcgo_windows.h"
@ -69,7 +65,7 @@ _cgo_maybe_run_preinit() {
}
void
x_cgo_sys_thread_create(void (*func)(void*), void* arg) {
x_cgo_sys_thread_create(unsigned long (__stdcall *func)(void*), void* arg) {
_cgo_beginthread(func, arg);
}
@ -141,26 +137,25 @@ void (*(_cgo_get_context_function(void)))(struct context_arg*) {
return ret;
}
void _cgo_beginthread(void (*func)(void*), void* arg) {
void _cgo_beginthread(unsigned long (__stdcall *func)(void*), void* arg) {
int tries;
uintptr_t thandle;
HANDLE thandle;
for (tries = 0; tries < 20; tries++) {
thandle = _beginthread(func, 0, arg);
if (thandle == -1 && errno == EACCES) {
thandle = CreateThread(NULL, 0, func, arg, 0, NULL);
if (thandle == 0 && GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {
// "Insufficient resources", try again in a bit.
//
// Note that the first Sleep(0) is a yield.
Sleep(tries); // milliseconds
continue;
} else if (thandle == -1) {
} else if (thandle == 0) {
break;
}
CloseHandle(thandle);
return; // Success!
}
fprintf(stderr, "runtime: failed to create new OS thread (%d)\n", errno);
fprintf(stderr, "runtime: failed to create new OS thread (%lu)\n", GetLastError());
abort();
}
#endif // __CYGWIN__

View File

@ -11,7 +11,7 @@
#include "libcgo.h"
#include "libcgo_windows.h"
static void threadentry(void*);
static unsigned long __stdcall threadentry(void*);
static void (*setg_gcc)(void*);
static DWORD *tls_g;
@ -29,7 +29,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
}
extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
static void
static unsigned long
__stdcall
threadentry(void *v)
{
ThreadStart ts;
@ -50,4 +51,5 @@ threadentry(void *v)
);
crosscall1(ts.fn, setg_gcc, ts.g);
return 0;
}

View File

@ -11,7 +11,7 @@
#include "libcgo.h"
#include "libcgo_windows.h"
static void threadentry(void*);
static unsigned long __stdcall threadentry(void*);
static void (*setg_gcc)(void*);
static DWORD *tls_g;
@ -30,7 +30,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
}
extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
static void
static unsigned long
__stdcall
threadentry(void *v)
{
ThreadStart ts;
@ -49,4 +50,5 @@ threadentry(void *v)
);
crosscall1(ts.fn, setg_gcc, (void*)ts.g);
return 0;
}

View File

@ -11,7 +11,7 @@
#include "libcgo.h"
#include "libcgo_windows.h"
static void threadentry(void*);
static unsigned long __stdcall threadentry(void*);
static void (*setg_gcc)(void*);
void
@ -28,7 +28,8 @@ _cgo_sys_thread_start(ThreadStart *ts)
extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
static void
static unsigned long
__stdcall
threadentry(void *v)
{
ThreadStart ts;
@ -37,4 +38,5 @@ threadentry(void *v)
free(v);
crosscall1(ts.fn, setg_gcc, (void *)ts.g);
return 0;
}

View File

@ -3,4 +3,4 @@
// license that can be found in the LICENSE file.
// Call _beginthread, aborting on failure.
void _cgo_beginthread(void (*func)(void*), void* arg);
void _cgo_beginthread(unsigned long (__stdcall *func)(void*), void* arg);