authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-29 11:05:43-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-29 11:05:43-07:00
logc37fe4b6784cef125ed7b4e043ee3122dd09f491
tree6849e3e3ad809c9bceb03d7391f9e20528a29ef5
parent390c7d84b24355ba3346ec1214a0a8de8a7c5df3
parent9d23e711ef98a4c941165457c1fdcdc736b264dc
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20841 from alexrp/atomic-stuff

`std.atomic`: `cache_line` and `spinLoopHint()` specialization for more architectures

1 files changed, 73 insertions(+), 10 deletions(-)

lib/std/atomic.zig+73-10
......@@ -378,21 +378,33 @@ pub inline fn spinLoopHint() void {
378378 // No-op instruction that can hint to save (or share with a hardware-thread)
379379 // pipelining/power resources
380380 // https://software.intel.com/content/www/us/en/develop/articles/benefitting-power-and-performance-sleep-loops.html
381 .x86, .x86_64 => asm volatile ("pause" ::: "memory"),
381 .x86,
382 .x86_64,
383 => asm volatile ("pause" ::: "memory"),
382384
383385 // No-op instruction that serves as a hardware-thread resource yield hint.
384386 // https://stackoverflow.com/a/7588941
385 .powerpc64, .powerpc64le => asm volatile ("or 27, 27, 27" ::: "memory"),
387 .powerpc,
388 .powerpcle,
389 .powerpc64,
390 .powerpc64le,
391 => asm volatile ("or 27, 27, 27" ::: "memory"),
386392
387393 // `isb` appears more reliable for releasing execution resources than `yield`
388394 // on common aarch64 CPUs.
389395 // https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8258604
390396 // https://bugs.mysql.com/bug.php?id=100664
391 .aarch64, .aarch64_be => asm volatile ("isb" ::: "memory"),
397 .aarch64,
398 .aarch64_be,
399 => asm volatile ("isb" ::: "memory"),
392400
393401 // `yield` was introduced in v6k but is also available on v6m.
394402 // https://www.keil.com/support/man/docs/armasm/armasm_dom1361289926796.htm
395 .arm, .armeb, .thumb, .thumbeb => {
403 .arm,
404 .armeb,
405 .thumb,
406 .thumbeb,
407 => {
396408 const can_yield = comptime std.Target.arm.featureSetHasAny(builtin.target.cpu.features, .{
397409 .has_v6k, .has_v6m,
398410 });
......@@ -402,6 +414,22 @@ pub inline fn spinLoopHint() void {
402414 asm volatile ("" ::: "memory");
403415 }
404416 },
417
418 // The 8-bit immediate specifies the amount of cycles to pause for. We can't really be too
419 // opinionated here.
420 .hexagon,
421 => asm volatile ("pause(#1)" ::: "memory"),
422
423 .riscv32,
424 .riscv64,
425 => {
426 if (comptime std.Target.riscv.featureSetHas(builtin.target.cpu.features, .zihintpause)) {
427 asm volatile ("pause" ::: "memory");
428 } else {
429 asm volatile ("" ::: "memory");
430 }
431 },
432
405433 // Memory barrier to prevent the compiler from optimizing away the spin-loop
406434 // even if no hint_instruction was provided.
407435 else => asm volatile ("" ::: "memory"),
......@@ -429,26 +457,61 @@ pub const cache_line = switch (builtin.cpu.arch) {
429457 // - https://www.mono-project.com/news/2016/09/12/arm64-icache/
430458 // - https://cpufun.substack.com/p/more-m1-fun-hardware-information
431459 //
432 // powerpc64: PPC has 128-byte cache lines
460 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/arc/Kconfig#L212
433461 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9
434 .x86_64, .aarch64, .powerpc64 => 128,
462 .x86_64,
463 .aarch64,
464 .aarch64_be,
465 .arc,
466 .powerpc64,
467 .powerpc64le,
468 => 128,
435469
436 // These platforms reportedly have 32-byte cache lines
437470 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7
438471 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7
439472 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7
440473 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9
441474 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7
442 .arm, .mips, .mips64, .riscv64 => 32,
475 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/hexagon/include/asm/cache.h#L13
476 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sparc/include/asm/cache.h#L14
477 .arm,
478 .armeb,
479 .thumb,
480 .thumbeb,
481 .hexagon,
482 .mips,
483 .mipsel,
484 .mips64,
485 .mips64el,
486 .riscv32,
487 .riscv64,
488 .sparc,
489 .sparcel,
490 .sparc64,
491 => 32,
492
493 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/m68k/include/asm/cache.h#L10
494 .m68k,
495 => 16,
496
497 // - https://www.ti.com/lit/pdf/slaa498
498 .msp430,
499 => 8,
443500
444 // This platform reportedly has 256-byte cache lines
445501 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7
446 .s390x => 256,
502 // - https://sxauroratsubasa.sakura.ne.jp/documents/guide/pdfs/Aurora_ISA_guide.pdf
503 .s390x,
504 .ve,
505 => 256,
447506
448507 // Other x86 and WASM platforms have 64-byte cache lines.
449508 // The rest of the architectures are assumed to be similar.
450509 // - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9
510 // - https://github.com/golang/go/blob/0a9321ad7f8c91e1b0c7184731257df923977eb9/src/internal/cpu/cpu_loong64.go#L11
451511 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7
512 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/xtensa/variants/csp/include/variant/core.h#L209
513 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/csky/Kconfig#L183
514 // - https://www.xmos.com/download/The-XMOS-XS3-Architecture.pdf
452515 else => 64,
453516};
454517