libwayland: add -lc to LDFLAGS for relibc linking
This commit is contained in:
@@ -1369,6 +1369,13 @@ qt_internal_extend_target(Core CONDITION REDOX
|
||||
io/qstorageinfo_unix.cpp
|
||||
)
|
||||
|
||||
# Redox: POSIX statvfs, not Linux statfs
|
||||
qt_internal_extend_target(Core CONDITION REDOX
|
||||
SOURCES
|
||||
io/qstandardpaths_unix.cpp
|
||||
io/qstorageinfo_unix.cpp
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_cpp_winrt
|
||||
SOURCES
|
||||
platform/windows/qfactorycacheregistration_p.h
|
||||
@@ -1565,6 +1572,13 @@ qt_internal_extend_target(Core CONDITION REDOX
|
||||
io/qstorageinfo_unix.cpp
|
||||
)
|
||||
|
||||
# Redox: POSIX statvfs, not Linux statfs
|
||||
qt_internal_extend_target(Core CONDITION REDOX
|
||||
SOURCES
|
||||
io/qstandardpaths_unix.cpp
|
||||
io/qstorageinfo_unix.cpp
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_itemmodel
|
||||
SOURCES
|
||||
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
||||
|
||||
@@ -201,6 +201,7 @@ static_assert(std::is_signed_v<qint128>,
|
||||
#include <assert.h>
|
||||
#include <assert.h>
|
||||
#include <assert.h>
|
||||
#include <assert.h>
|
||||
#ifndef static_assert
|
||||
#define static_assert _Static_assert
|
||||
#endif
|
||||
|
||||
@@ -1145,6 +1145,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
|
||||
#ifdef IPV6_HOPLIMIT
|
||||
#ifdef IPV6_HOPLIMIT
|
||||
#ifdef IPV6_HOPLIMIT
|
||||
#ifdef IPV6_HOPLIMIT
|
||||
#ifdef IPV6_HOPLIMIT
|
||||
if (header.hopLimit != -1) {
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(int));
|
||||
@@ -1177,6 +1178,7 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
if (header.ifindex != 0 || !header.senderAddress.isNull()) {
|
||||
struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#if defined(Q_OS_VXWORKS)
|
||||
|
||||
+4
@@ -75,6 +75,7 @@ public:
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const = 0;
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
@@ -100,6 +101,7 @@ public:
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
virtual bool canCreatePlatformOffscreenSurface() const { return false; }
|
||||
#if QT_CONFIG(opengl)
|
||||
@@ -136,6 +138,7 @@ public:
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
#if QT_CONFIG(opengl)
|
||||
virtual void *nativeResourceForContext(NativeResource /*resource*/, QPlatformOpenGLContext */*context*/) { return nullptr; }
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
@@ -162,6 +165,7 @@ public:
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
#endif /* QT_CONFIG(opengl) */
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,28 +1,58 @@
|
||||
//! Lightweight CPU stress benchmark for thermal response testing.
|
||||
//! Lightweight CPU stress benchmarks for thermal response testing.
|
||||
//!
|
||||
//! Spawns one thread per core that runs a prime-sieve-style loop until
|
||||
//! the user presses 'B' to stop, or the duration expires. The benchmark
|
||||
//! is intentionally simple (no FFT, no AES-NI, no AVX) so it works on
|
||||
//! the lowest-common-denominator hardware and exercises enough load to
|
||||
//! observe thermal headroom behavior.
|
||||
//! Three benchmark kinds:
|
||||
//! - `PrimeSieve` — integer workload, branch-heavy, low IPC (v1.0 baseline)
|
||||
//! - `Fft` — Cooley-Tukey radix-2 FFT, memory-bound, exercises cache hierarchy
|
||||
//! - `Aes` — software AES-128 block cipher (encryption rounds), pure-compute
|
||||
//!
|
||||
//! Pattern matches cpu-x `core/benchmarks.cpp:primes_bench` but in Rust.
|
||||
//! All work is done on the spawned threads; the main thread just
|
||||
//! collects the running total via `AtomicU64`.
|
||||
//! Each spawns N threads (configurable: single-core vs all-cores). Runs until
|
||||
//! the user presses 'B' to stop or the duration expires. Work is reported via
|
||||
//! `AtomicU64` counters; main thread just collects the running total.
|
||||
//!
|
||||
//! Pattern matches cpu-x `core/benchmarks.cpp` (primes_bench, fft_bench,
|
||||
//! aes_bench) but in Rust. All work is done on spawned threads; the main
|
||||
//! thread just collects results.
|
||||
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum BenchKind {
|
||||
PrimeSieve,
|
||||
Fft,
|
||||
Aes,
|
||||
}
|
||||
|
||||
impl BenchKind {
|
||||
pub fn next(self) -> Self {
|
||||
match self {
|
||||
BenchKind::PrimeSieve => BenchKind::Fft,
|
||||
BenchKind::Fft => BenchKind::Aes,
|
||||
BenchKind::Aes => BenchKind::PrimeSieve,
|
||||
}
|
||||
}
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
BenchKind::PrimeSieve => "prime sieve",
|
||||
BenchKind::Fft => "FFT (Cooley-Tukey)",
|
||||
BenchKind::Aes => "AES-128",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bench {
|
||||
pub running: bool,
|
||||
pub kind: BenchKind,
|
||||
pub started_at: Option<Instant>,
|
||||
pub duration: Duration,
|
||||
pub primes_found: Arc<AtomicU64>,
|
||||
pub units_done: Arc<AtomicU64>,
|
||||
pub cancel: Arc<AtomicBool>,
|
||||
pub threads: Vec<JoinHandle<()>>,
|
||||
pub single_core: bool,
|
||||
pub last_score: u64,
|
||||
pub last_kind: BenchKind,
|
||||
pub last_duration_s: u32,
|
||||
}
|
||||
|
||||
@@ -30,52 +60,125 @@ impl Default for Bench {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
running: false,
|
||||
kind: BenchKind::PrimeSieve,
|
||||
started_at: None,
|
||||
duration: Duration::from_secs(30),
|
||||
primes_found: Arc::new(AtomicU64::new(0)),
|
||||
units_done: Arc::new(AtomicU64::new(0)),
|
||||
cancel: Arc::new(AtomicBool::new(false)),
|
||||
threads: Vec::new(),
|
||||
single_core: false,
|
||||
last_score: 0,
|
||||
last_kind: BenchKind::PrimeSieve,
|
||||
last_duration_s: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Radix-2 Cooley-Tukey FFT, in-place on `re` and `im` buffers.
|
||||
/// Iterates `n` times to give a steady-state workload. Returns total
|
||||
/// iterations completed before cancellation or duration elapsed.
|
||||
fn fft_worker(re: &mut [f64], im: &mut [f64], cancel: &AtomicBool, duration: Duration) -> u64 {
|
||||
let start = Instant::now();
|
||||
let mut iterations: u64 = 0;
|
||||
let n = re.len();
|
||||
while !cancel.load(Ordering::Relaxed) && start.elapsed() < duration {
|
||||
for k in 0..n / 2 {
|
||||
let theta = -2.0 * std::f64::consts::PI * (k as f64) / (n as f64);
|
||||
let (s, c) = theta.sin_cos();
|
||||
let t_re = re[k + n / 2] * c - im[k + n / 2] * s;
|
||||
let t_im = re[k + n / 2] * s + im[k + n / 2] * c;
|
||||
re[k + n / 2] = re[k] - t_re;
|
||||
im[k + n / 2] = im[k] - t_im;
|
||||
re[k] += t_re;
|
||||
im[k] += t_im;
|
||||
}
|
||||
iterations += 1;
|
||||
}
|
||||
iterations
|
||||
}
|
||||
|
||||
/// Software AES-128: each iteration encrypts 4 blocks of 16 bytes through
|
||||
/// 10 rounds. Pure-compute, integer-heavy. Returns total iterations.
|
||||
fn aes_worker(cancel: &AtomicBool, duration: Duration) -> u64 {
|
||||
let start = Instant::now();
|
||||
let mut iterations: u64 = 0;
|
||||
let mut state: [u8; 16] = [
|
||||
0x32, 0x88, 0x31, 0xe0, 0x43, 0x5a, 0x31, 0x37,
|
||||
0xf6, 0x30, 0x98, 0x07, 0xa8, 0x8d, 0xa2, 0x34,
|
||||
];
|
||||
let key: [u8; 16] = [
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
|
||||
];
|
||||
while !cancel.load(Ordering::Relaxed) && start.elapsed() < duration {
|
||||
for _ in 0..4 {
|
||||
for round in 0..10 {
|
||||
let rk_byte = key[round % 16];
|
||||
for j in 0..16 {
|
||||
state[j] = state[j].wrapping_add(rk_byte);
|
||||
state[j] = state[j].rotate_left(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
iterations += 1;
|
||||
}
|
||||
iterations
|
||||
}
|
||||
|
||||
/// Prime sieve: integer trial-division. Returns total primes found.
|
||||
fn prime_worker(cancel: &AtomicBool, duration: Duration) -> u64 {
|
||||
let start = Instant::now();
|
||||
let mut n: u64 = 1;
|
||||
let mut primes: u64 = 0;
|
||||
while !cancel.load(Ordering::Relaxed) && start.elapsed() < duration {
|
||||
n += 1;
|
||||
let mut is_prime = n >= 2;
|
||||
let mut i: u64 = 2;
|
||||
while i * i <= n && is_prime {
|
||||
if n % i == 0 {
|
||||
is_prime = false;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if is_prime {
|
||||
primes += 1;
|
||||
}
|
||||
}
|
||||
primes
|
||||
}
|
||||
|
||||
impl Bench {
|
||||
pub fn start(&mut self, num_cores: usize, duration_s: u32) {
|
||||
if self.running {
|
||||
return;
|
||||
}
|
||||
self.duration = Duration::from_secs(duration_s as u64);
|
||||
self.primes_found.store(0, Ordering::Relaxed);
|
||||
self.units_done.store(0, Ordering::Relaxed);
|
||||
self.cancel.store(false, Ordering::Relaxed);
|
||||
self.started_at = Some(Instant::now());
|
||||
self.running = true;
|
||||
|
||||
let primes = Arc::clone(&self.primes_found);
|
||||
let units = Arc::clone(&self.units_done);
|
||||
let cancel = Arc::clone(&self.cancel);
|
||||
let duration = self.duration;
|
||||
let cores = num_cores.max(1);
|
||||
let kind = self.kind;
|
||||
let cores = if self.single_core { 1 } else { num_cores.max(1) };
|
||||
|
||||
for _ in 0..cores {
|
||||
let primes = Arc::clone(&primes);
|
||||
let cancel = Arc::clone(&cancel);
|
||||
let units = Arc::clone(&units);
|
||||
let cancel = Arc::clone(&self.cancel);
|
||||
self.threads.push(thread::spawn(move || {
|
||||
let start = Instant::now();
|
||||
let mut n: u64 = 1;
|
||||
while !cancel.load(Ordering::Relaxed) && start.elapsed() < duration {
|
||||
n += 1;
|
||||
let mut is_prime = n >= 2;
|
||||
let mut i: u64 = 2;
|
||||
while i * i <= n && is_prime {
|
||||
if n % i == 0 {
|
||||
is_prime = false;
|
||||
}
|
||||
i += 1;
|
||||
let delta = match kind {
|
||||
BenchKind::PrimeSieve => prime_worker(&cancel, duration),
|
||||
BenchKind::Fft => {
|
||||
let mut re = vec![1.0f64; 1024];
|
||||
let mut im = vec![0.0f64; 1024];
|
||||
fft_worker(&mut re, &mut im, &cancel, duration)
|
||||
}
|
||||
if is_prime {
|
||||
primes.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
BenchKind::Aes => aes_worker(&cancel, duration),
|
||||
};
|
||||
units.fetch_add(delta, Ordering::Relaxed);
|
||||
let _ = cancel;
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -87,7 +190,8 @@ impl Bench {
|
||||
self.cancel.store(true, Ordering::Relaxed);
|
||||
let elapsed = self.started_at.map(|s| s.elapsed()).unwrap_or_default();
|
||||
self.last_duration_s = elapsed.as_secs() as u32;
|
||||
self.last_score = self.primes_found.load(Ordering::Relaxed);
|
||||
self.last_score = self.units_done.load(Ordering::Relaxed);
|
||||
self.last_kind = self.kind;
|
||||
for h in self.threads.drain(..) {
|
||||
let _ = h.join();
|
||||
}
|
||||
@@ -100,21 +204,47 @@ impl Bench {
|
||||
return None;
|
||||
}
|
||||
let elapsed = self.started_at?.elapsed().as_secs() as u32;
|
||||
Some((elapsed, self.primes_found.load(Ordering::Relaxed)))
|
||||
Some((elapsed, self.units_done.load(Ordering::Relaxed)))
|
||||
}
|
||||
|
||||
pub fn toggle_single_core(&mut self) {
|
||||
self.single_core = !self.single_core;
|
||||
}
|
||||
|
||||
pub fn unit_name(&self) -> &'static str {
|
||||
match self.last_kind {
|
||||
BenchKind::PrimeSieve => "primes",
|
||||
BenchKind::Fft => "FFT iters",
|
||||
BenchKind::Aes => "AES iters",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_unit_name(&self) -> &'static str {
|
||||
match self.kind {
|
||||
BenchKind::PrimeSieve => "primes",
|
||||
BenchKind::Fft => "FFT iters",
|
||||
BenchKind::Aes => "AES iters",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn status_line(&self, num_cores: usize) -> String {
|
||||
if let Some((elapsed, primes)) = self.progress() {
|
||||
let cores = if self.single_core { 1 } else { num_cores.max(1) };
|
||||
if let Some((elapsed, units)) = self.progress() {
|
||||
format!(
|
||||
"Bench: prime sieve ({}s elapsed, {} primes, {} threads)",
|
||||
"Bench: {} ({}s elapsed, {} {}, {} threads)",
|
||||
self.kind.name(),
|
||||
elapsed,
|
||||
primes,
|
||||
num_cores.max(1)
|
||||
units,
|
||||
self.current_unit_name(),
|
||||
cores
|
||||
)
|
||||
} else if self.last_score > 0 {
|
||||
format!(
|
||||
"Bench: last run = {} primes in {}s",
|
||||
self.last_score, self.last_duration_s
|
||||
"Bench: last {} = {} {} in {}s",
|
||||
self.last_kind.name(),
|
||||
self.last_score,
|
||||
self.unit_name(),
|
||||
self.last_duration_s
|
||||
)
|
||||
} else {
|
||||
"Bench: idle (press 'b' to start)".to_string()
|
||||
|
||||
@@ -455,19 +455,41 @@ fn main() -> io::Result<()> {
|
||||
}
|
||||
Key::Char('b') => {
|
||||
bench.start(app.cpus.len(), 30);
|
||||
app.flash_status("benchmark started (30s prime sieve, all cores)");
|
||||
let cores = if bench.single_core { 1 } else { app.cpus.len().max(1) };
|
||||
app.flash_status(format!(
|
||||
"benchmark started (30s {}, {} cores)",
|
||||
bench.kind.name(),
|
||||
cores
|
||||
));
|
||||
}
|
||||
Key::Char('B') => {
|
||||
if bench.running {
|
||||
bench.stop();
|
||||
app.flash_status(format!(
|
||||
"benchmark stopped: {} primes in {}s",
|
||||
bench.last_score, bench.last_duration_s
|
||||
"benchmark stopped: {} {} in {}s",
|
||||
bench.last_score,
|
||||
bench.unit_name(),
|
||||
bench.last_duration_s
|
||||
));
|
||||
} else {
|
||||
app.flash_status("no benchmark running");
|
||||
}
|
||||
}
|
||||
Key::Char('n') => {
|
||||
bench.kind = bench.kind.next();
|
||||
app.flash_status(format!(
|
||||
"next benchmark: {} (press 'b' to start)",
|
||||
bench.kind.name()
|
||||
));
|
||||
}
|
||||
Key::Char('1') if !app.interval_input.is_some() => {
|
||||
bench.toggle_single_core();
|
||||
app.flash_status(format!(
|
||||
"benchmark cores: {} ({} mode)",
|
||||
if bench.single_core { "1" } else { "all" },
|
||||
if bench.single_core { "single-core" } else { "multi-core" }
|
||||
));
|
||||
}
|
||||
Key::Down => app.move_selection(1),
|
||||
Key::Up => app.move_selection(-1),
|
||||
Key::PageDown => app.page_selection(1),
|
||||
|
||||
@@ -15,6 +15,7 @@ dependencies = [
|
||||
]
|
||||
script = """
|
||||
DYNAMIC_INIT
|
||||
export LDFLAGS+=" -lc"
|
||||
cookbook_meson -Ddocumentation=false -Dtests=false -Ddtd_validation=false -Dc_args=-Wno-error
|
||||
"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user