mirror of https://github.com/BOINC/boinc.git
client/hostinfo_unix: addapt for Apple Silicon M1 / arm64 CPU #2
- The native arm64 client tries to launch a separate helper program that is compiled only for the x86_64 architecture. If successful, this means that Rosetta2 is installed and the host can run x86_64 applications, so x86_64-apple-darwin is added as an alternative platform. The helper program 'detect_rosetta_cpu' gets the feature string for the emulated x86_64 CPU (e.g. SSE), and writes it to a file in the BOINC data directory. If this file exists, this file is read in hostinfo_unix_mac() and the features of the meulated CPU are added to that of the native CPU.
This commit is contained in:
parent
de4e0f9823
commit
365a1bbc29
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2020 University of California
|
||||
// Copyright (C) 2021 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -53,6 +53,7 @@ extern int compareOSVersionTo(int toMajor, int toMinor);
|
|||
|
||||
#include "client_types.h"
|
||||
#include "client_state.h"
|
||||
#include "client_msgs.h"
|
||||
#include "log_flags.h"
|
||||
#include "project.h"
|
||||
|
||||
|
@ -72,6 +73,90 @@ void CLIENT_STATE::add_platform(const char* platform) {
|
|||
}
|
||||
|
||||
|
||||
#if defined (__APPLE__) && defined (__arm64__)
|
||||
// detect a possibly emulated x86_64 CPU and its features on a Apple Silicon M1 Mac
|
||||
//
|
||||
int launch_child_process_to_detect_emulated_cpu() {
|
||||
int prog;
|
||||
char data_dir[MAXPATHLEN];
|
||||
char execpath[MAXPATHLEN];
|
||||
int retval = 0;
|
||||
|
||||
retval = boinc_delete_file(EMULATED_CPU_INFO_FILENAME);
|
||||
if (retval) {
|
||||
msg_printf(0, MSG_INFO,
|
||||
"Failed to delete old %s. error code %d",
|
||||
EMULATED_CPU_INFO_FILENAME, retval
|
||||
);
|
||||
} else {
|
||||
for (;;) {
|
||||
if (!boinc_file_exists(EMULATED_CPU_INFO_FILENAME)) break;
|
||||
boinc_sleep(0.01);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// write the EMULATED_CPU_INFO into the BOINC data dir
|
||||
boinc_getcwd(data_dir);
|
||||
|
||||
// the execuable should be in BOINC data dir
|
||||
strncpy(execpath, data_dir, sizeof(execpath));
|
||||
strncat(execpath, "/" EMULATED_CPU_INFO_EXECUTABLE, sizeof(execpath) - strlen(execpath) - 1);
|
||||
|
||||
if (log_flags.coproc_debug) {
|
||||
msg_printf(0, MSG_INFO,
|
||||
"[x86_64-M1] launching child process at %s",
|
||||
execpath
|
||||
);
|
||||
}
|
||||
|
||||
int argc = 1;
|
||||
char* const argv[2] = {
|
||||
const_cast<char *>(execpath),
|
||||
NULL
|
||||
};
|
||||
|
||||
retval = run_program(
|
||||
data_dir,
|
||||
execpath,
|
||||
argc,
|
||||
argv,
|
||||
0,
|
||||
prog
|
||||
);
|
||||
|
||||
if (retval) {
|
||||
if (log_flags.coproc_debug) {
|
||||
msg_printf(0, MSG_INFO,
|
||||
"[x86_64-M1] run_program of child process returned error %d",
|
||||
retval
|
||||
);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = get_exit_status(prog);
|
||||
if (retval) {
|
||||
char buf[200];
|
||||
if (WIFEXITED(retval)) {
|
||||
int code = WEXITSTATUS(retval);
|
||||
snprintf(buf, sizeof(buf), "process exited with status %d: %s", code, strerror(code));
|
||||
} else if (WIFSIGNALED(retval)) {
|
||||
int sig = WTERMSIG(retval);
|
||||
snprintf(buf, sizeof(buf), "process was terminated by signal %d", sig);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "unknown status %d", retval);
|
||||
}
|
||||
msg_printf(0, MSG_INFO,
|
||||
"Emulated CPU detection failed: %s",
|
||||
buf
|
||||
);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
// determine the list of supported platforms.
|
||||
//
|
||||
void CLIENT_STATE::detect_platforms() {
|
||||
|
@ -106,8 +191,9 @@ void CLIENT_STATE::detect_platforms() {
|
|||
}
|
||||
#elif defined(__arm64__)
|
||||
add_platform("arm64-apple-darwin");
|
||||
//TODO: Add test for Mac OS Version when Apple Rosetta emulator is removed
|
||||
add_platform("x86_64-apple-darwin");
|
||||
if (!launch_child_process_to_detect_emulated_cpu()) {
|
||||
add_platform("x86_64-apple-darwin");
|
||||
}
|
||||
#else
|
||||
#error Mac client now requires a 64-bit system
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2021 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
// as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
//
|
||||
// BOINC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// This helper program is used to detect an emulated x86_64 CPU on Apples
|
||||
// ARM64 CPUs (M1). It should be compiiled _only_ for x86_64 architecture.
|
||||
// It writes the feature string of the meulated CPU to a file
|
||||
// EMULATED_CPU_INFO_FILENAME in the current working directory.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "hostinfo.h" // for P_FEATURES_SIZE
|
||||
#include "filesys.h" // for boinc_fopen()
|
||||
#include "file_names.h" // for EMULATED_CPU_INFO_FILENAME
|
||||
|
||||
int main () {
|
||||
size_t len;
|
||||
char features[P_FEATURES_SIZE];
|
||||
FILE*fp;
|
||||
|
||||
len = sizeof(features);
|
||||
sysctlbyname("machdep.cpu.features", features, &len, NULL, 0);
|
||||
if ((fp = boinc_fopen(EMULATED_CPU_INFO_FILENAME, "w"))) {
|
||||
fprintf(fp," %s\n", features);
|
||||
fclose(fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2018 University of California
|
||||
// Copyright (C) 2021 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -71,7 +71,9 @@ extern void send_log_after(const char* filename, double t, MIOFILE& mf);
|
|||
#define CLIENT_OPAQUE_FILENAME "client_opaque.txt"
|
||||
#define CONFIG_FILE "cc_config.xml"
|
||||
#define NVC_CONFIG_FILE "nvc_config.xml"
|
||||
#define COPROC_INFO_FILENAME "coproc_info.xml"
|
||||
#define COPROC_INFO_FILENAME "coproc_info.txt"
|
||||
#define EMULATED_CPU_INFO_EXECUTABLE "detect_rosetta_cpu"
|
||||
#define EMULATED_CPU_INFO_FILENAME "emulated_cpu_info.txt"
|
||||
#define CPU_BENCHMARKS_FILE_NAME "cpu_benchmarks"
|
||||
#define CREATE_ACCOUNT_FILENAME "create_account.xml"
|
||||
#define DAILY_XFER_HISTORY_FILENAME "daily_xfer_history.xml"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// This file is part of BOINC.
|
||||
// http://boinc.berkeley.edu
|
||||
// Copyright (C) 2020 University of California
|
||||
// Copyright (C) 2021 University of California
|
||||
//
|
||||
// BOINC is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License
|
||||
|
@ -892,6 +892,24 @@ static void get_cpu_info_mac(HOST_INFO& host) {
|
|||
|
||||
sysctlbyname("hw.optional.ucnormal_mem", &feature, &len, NULL, 0);
|
||||
if (feature) feature_string += " ucnormal_mem";
|
||||
|
||||
// read features of the emulated CPU if there is a file containing these
|
||||
char fpath[MAXPATHLEN];
|
||||
boinc_getcwd(fpath);
|
||||
strcat(fpath,"/");
|
||||
strcat(fpath,EMULATED_CPU_INFO_FILENAME);
|
||||
if (boinc_file_exists(fpath)) {
|
||||
FILE* fp = boinc_fopen(fpath, "r");
|
||||
if (fp) {
|
||||
fgets(features, sizeof(features), fp);
|
||||
feature_string += features;
|
||||
fclose(fp);
|
||||
} else if (log_flags.coproc_debug) {
|
||||
msg_printf(0, MSG_INFO, "[x86_64-M1] couldn't open file %s", fpath);
|
||||
}
|
||||
} else if (log_flags.coproc_debug) {
|
||||
msg_printf(0, MSG_INFO, "[x86_64-M1] didn't find file %s", fpath);
|
||||
}
|
||||
#endif // defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
strncpy(features,feature_string.c_str(),sizeof(features));
|
||||
|
|
Loading…
Reference in New Issue