mirror of
https://github.com/RGBCube/Site
synced 2025-08-02 05:57:46 +00:00
Compare commits
10 commits
031900c8c2
...
f5cf07e8b7
Author | SHA1 | Date | |
---|---|---|---|
f5cf07e8b7 | |||
011b7c7680 | |||
10093e1e65 | |||
104140528a | |||
3abff9ebd1 | |||
9c78876e9b | |||
0b001d957e | |||
9be051d775 | |||
32e0386270 | |||
4847abc8eb |
10 changed files with 509 additions and 36 deletions
|
@ -171,7 +171,7 @@ html, body {
|
||||||
@apply wrap-anywhere;
|
@apply wrap-anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:has(> code:only-child)) {
|
&:not(:has(> code:only-child)):not(:has(> img)) {
|
||||||
@apply px-1;
|
@apply px-1;
|
||||||
|
|
||||||
&:not(.font-mono) {
|
&:not(.font-mono) {
|
||||||
|
@ -230,8 +230,8 @@ html, body {
|
||||||
code:not(pre > code) {
|
code:not(pre > code) {
|
||||||
@apply border-1 border-dotted px-2 py-0.5 border-black dark:border-white;
|
@apply border-1 border-dotted px-2 py-0.5 border-black dark:border-white;
|
||||||
|
|
||||||
a:hover &:not(:is(h1, h2, h3, h4, h5, h6) *),
|
a:hover &:not(:only-child, :is(h1, h2, h3, h4, h5, h6) *),
|
||||||
a:active &:not(:is(h1, h2, h3, h4, h5, h6) *) {
|
a:active &:not(:only-child, :is(h1, h2, h3, h4, h5, h6) *) {
|
||||||
@apply border-transparent;
|
@apply border-transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,9 +252,7 @@ html, body {
|
||||||
}
|
}
|
||||||
|
|
||||||
& li::before {
|
& li::before {
|
||||||
@apply pr-1;
|
content: counter(item) ". ";
|
||||||
|
|
||||||
content: "[" counter(item) "]";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
BIN
site/assets/images/cpu-dumb.webp
Normal file
BIN
site/assets/images/cpu-dumb.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
date: 2024-01-01
|
|
||||||
title: Test
|
title: Test
|
||||||
description: "Testing"
|
description: "Testing"
|
||||||
|
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
title: HTMNIX
|
title: HTMNIX
|
||||||
description: How the absolutely cursed HTMNIX project works.
|
description: How the absolutely cursed HTMNIX project works.
|
||||||
|
|
||||||
date: 2024-03-04
|
|
||||||
|
|
||||||
keywords:
|
keywords:
|
||||||
- html
|
- html
|
||||||
- nix
|
- nix
|
|
@ -2,8 +2,6 @@
|
||||||
title: Cosmic Drift
|
title: Cosmic Drift
|
||||||
description: Or how I missed the school bus because of a cosmic ray.
|
description: Or how I missed the school bus because of a cosmic ray.
|
||||||
|
|
||||||
date: 2024-04-02
|
|
||||||
|
|
||||||
keywords:
|
keywords:
|
||||||
- time
|
- time
|
||||||
- unix-timestamps
|
- unix-timestamps
|
|
@ -2,7 +2,6 @@
|
||||||
title: Explaining the Nix iceberg
|
title: Explaining the Nix iceberg
|
||||||
description: And revealing how cursed Nix is.
|
description: And revealing how cursed Nix is.
|
||||||
|
|
||||||
date: 2024-04-15
|
|
||||||
draft: true
|
draft: true
|
||||||
|
|
||||||
keywords:
|
keywords:
|
||||||
|
@ -16,12 +15,10 @@ it a reputation of being arcane and hard to use.
|
||||||
I'll be explaining the contents of the following iceberg chart, which includes
|
I'll be explaining the contents of the following iceberg chart, which includes
|
||||||
some truly arcane examples of Nix code.
|
some truly arcane examples of Nix code.
|
||||||
|
|
||||||
Some knowledge of Nix is required, you may get confused in the terminology if
|
Some knowledge of Nix is required, you may get confused with the terminology if
|
||||||
you've never used it.
|
you've never used Nix.
|
||||||
|
|
||||||

|
[](https://cohost.org/leftpaddotpy/post/3885451-the-nix-iceberg)
|
||||||
|
|
||||||
[Here's the original source for this image, on cohost.](https://cohost.org/leftpaddotpy/post/3885451-the-nix-iceberg)
|
|
||||||
|
|
||||||
Let's start:
|
Let's start:
|
||||||
|
|
||||||
|
@ -54,7 +51,7 @@ So, what are we doing in this snippet?
|
||||||
2. Creating a derivation that runs an echo command, which writes a Nix
|
2. Creating a derivation that runs an echo command, which writes a Nix
|
||||||
expression to the output file.
|
expression to the output file.
|
||||||
3. Then we import the output file, forcing the derivation to be realized as we
|
3. Then we import the output file, forcing the derivation to be realized as we
|
||||||
accessed the contents of it.
|
just accessed the contents of it.
|
||||||
|
|
||||||
> Wait, what does _realization_ mean?
|
> Wait, what does _realization_ mean?
|
||||||
|
|
||||||
|
@ -519,14 +516,14 @@ known.
|
||||||
|
|
||||||
# Tier 3: `assigned nix hacker at employment`
|
# Tier 3: `assigned nix hacker at employment`
|
||||||
|
|
||||||
<h2>
|
<h2><small>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
#!/usr/bin/env nix-shell
|
#!/usr/bin/env nix-shell
|
||||||
#!nix-shell -i python3 -p python3
|
#!nix-shell -i python3 -p python3
|
||||||
```
|
```
|
||||||
|
|
||||||
</h2>
|
</small></h2>
|
||||||
|
|
||||||
_(taken verbatim from `man nix-shell`)_
|
_(taken verbatim from `man nix-shell`)_
|
||||||
|
|
||||||
|
@ -565,7 +562,16 @@ print t
|
||||||
|
|
||||||
## `--accept-flake-config` more like `--pwn-me-mommy`
|
## `--accept-flake-config` more like `--pwn-me-mommy`
|
||||||
|
|
||||||
TODO
|
The
|
||||||
|
[`accept-flake-config`](https://nix.dev/manual/nix/2.29/command-ref/conf-file#conf-accept-flake-config)
|
||||||
|
Nix configuration variable or `--accept-flake-config` flag in Nix commands
|
||||||
|
allows Nix to unconditionally accept flake `nixConfig`'s.
|
||||||
|
|
||||||
|
This is dangerous, because this can enable `builtins.importNative` by enabling
|
||||||
|
the
|
||||||
|
[`allow-unsafe-native-code-during-evaluation`](https://nix.dev/manual/nix/2.29/command-ref/conf-file#conf-allow-unsafe-native-code-during-evaluation)
|
||||||
|
option, which then allows Nix expresions to load arbitrary dynamic libraries,
|
||||||
|
which can do anything as they are not confined to the Nix evaluation sandbox.
|
||||||
|
|
||||||
## Zilch
|
## Zilch
|
||||||
|
|
||||||
|
@ -717,8 +723,7 @@ But if two attribute sets that are compared have the same memory location, Nix
|
||||||
ignores this and does a pointer comparison, totally ignoring all members. This
|
ignores this and does a pointer comparison, totally ignoring all members. This
|
||||||
is a hack.
|
is a hack.
|
||||||
|
|
||||||
[Link to code that does this.](https://github.com/NixOS/nix/blob/aa165301d1ae3b306319a6a834dc1d4e340a7112/src/libexpr/eval.cc#L2525-L2528)
|
[Here's the snippet:](https://github.com/NixOS/nix/blob/aa165301d1ae3b306319a6a834dc1d4e340a7112/src/libexpr/eval.cc#L2525-L2528)
|
||||||
Here's the snippet:
|
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx)
|
bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx)
|
||||||
|
@ -739,7 +744,7 @@ want with this information.
|
||||||
|
|
||||||
As surprising as it sounds, Nix does indeed supports plugins. You can load
|
As surprising as it sounds, Nix does indeed supports plugins. You can load
|
||||||
plugins using the
|
plugins using the
|
||||||
[`plugin-files`](https://nix.dev/manual/nix/2.22/command-ref/conf-file#conf-plugin-files)
|
[`plugin-files`](https://nix.dev/manual/nix/2.29/command-ref/conf-file.html#conf-plugin-files)
|
||||||
configuration option.
|
configuration option.
|
||||||
|
|
||||||
From the configuration reference:
|
From the configuration reference:
|
||||||
|
@ -771,7 +776,7 @@ Some example plugins are [`nix-doc`](https://github.com/lf-/nix-doc) and
|
||||||
## `/bin/sh` and sandbox impurity
|
## `/bin/sh` and sandbox impurity
|
||||||
|
|
||||||
By setting the
|
By setting the
|
||||||
[`sandbox-paths`](https://nix.dev/manual/nix/2.22/command-ref/conf-file#conf-sandbox-paths)
|
[`sandbox-paths`](https://nix.dev/manual/nix/2.29/command-ref/conf-file#conf-sandbox-paths)
|
||||||
option to `/bin/sh=/bin/sh`, Nix will bind the `/bin/sh` path in the build
|
option to `/bin/sh=/bin/sh`, Nix will bind the `/bin/sh` path in the build
|
||||||
sandbox (left) to the `/bin/sh` path in the host (right). This is of course
|
sandbox (left) to the `/bin/sh` path in the host (right). This is of course
|
||||||
impure, but is useful for bootstrapping from absolute scratch without copying
|
impure, but is useful for bootstrapping from absolute scratch without copying
|
||||||
|
@ -779,10 +784,11 @@ impure binaries to the Nix store.
|
||||||
|
|
||||||
## `rec { a = 5; b = a + 1; __overrides.a = 6; }`
|
## `rec { a = 5; b = a + 1; __overrides.a = 6; }`
|
||||||
|
|
||||||
There is a special field named `__overrides` in recursive attrset expressions,
|
There is a special field named `__overrides` in keyed expressions (attribute
|
||||||
which simply overrides the parent attribute set with the keys inside it. This is
|
sets, `let-in`'s and as secret third thing), which simply overrides the parent
|
||||||
different from the update operator (`//`) because that will not override the
|
attribute set with the keys inside it. This is different from the update
|
||||||
self-references in the recursive attribute set.
|
operator (`//`) because that will not override the self-references in the
|
||||||
|
recursive attribute set.
|
||||||
|
|
||||||
`rec { a = 5; b = a + 1; __overrides.a = 6; }.b` will evaluate to 7, while
|
`rec { a = 5; b = a + 1; __overrides.a = 6; }.b` will evaluate to 7, while
|
||||||
`(rec { a = 5; b = a + 1; } // { a = 6; }).b` will evaluate to 6.
|
`(rec { a = 5; b = a + 1; } // { a = 6; }).b` will evaluate to 6.
|
||||||
|
@ -814,7 +820,58 @@ TODO
|
||||||
|
|
||||||
## `let a = _: -1; or = 6; in [ a or 9 ]`
|
## `let a = _: -1; or = 6; in [ a or 9 ]`
|
||||||
|
|
||||||
TODO
|
The Nix parser is weird.
|
||||||
|
|
||||||
|
Normally, `or` is used for attribute path selection defaults:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ foo = 123; }.not-here.not-here-either or 123
|
||||||
|
```
|
||||||
|
|
||||||
|
That above evaluates to `123`.
|
||||||
|
|
||||||
|
But when parsing an expression that is not an attribute-select, `or` is treated
|
||||||
|
as an identifier. This means that in the following `let-in`, we are passing `or`
|
||||||
|
to `a`.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
a = _: -1;
|
||||||
|
or = 6;
|
||||||
|
in a or
|
||||||
|
```
|
||||||
|
|
||||||
|
But there is another piece of weirdness. Function applications that use the
|
||||||
|
literal `or` have higher precedence than the spaces when parsing lists, so these
|
||||||
|
two codeblocks are not equivalent:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
a = _: -1;
|
||||||
|
or = 6;
|
||||||
|
in [ a or ]
|
||||||
|
```
|
||||||
|
|
||||||
|
> This evaluates to `[ -1 ]`
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
a = _: -1;
|
||||||
|
foo = 6;
|
||||||
|
in [ a foo ]
|
||||||
|
```
|
||||||
|
|
||||||
|
> This evaluates to `[ <LAMBDA> 6 ]`
|
||||||
|
|
||||||
|
However, this behaviour might get removed in the future. But currently, in the
|
||||||
|
Nix version that I am using which is `2.28.3`, it prints this warning instead:
|
||||||
|
|
||||||
|
```text
|
||||||
|
warning: at «string»:4:6: This expression uses `or` as an identifier in a way that will change in a future Nix release.
|
||||||
|
Wrap this entire expression in parentheses to preserve its current meaning:
|
||||||
|
(a or)
|
||||||
|
Give feedback at https://github.com/NixOS/nix/pull/11121
|
||||||
|
```
|
||||||
|
|
||||||
## eelco's home address is in nixpkgs
|
## eelco's home address is in nixpkgs
|
||||||
|
|
||||||
|
@ -822,16 +879,25 @@ TODO
|
||||||
|
|
||||||
## `restrict-eval`
|
## `restrict-eval`
|
||||||
|
|
||||||
TODO
|
[From the Nix manual:](https://nix.dev/manual/nix/2.29/command-ref/conf-file.html?highlight=restrict-eval#conf-restrict-eval)
|
||||||
|
|
||||||
|
> If set to true, the Nix evaluator will not allow access to any files outside
|
||||||
|
> of `builtins.nixPath`, or to URIs outside of `allowed-uris`.
|
||||||
|
|
||||||
## nix2
|
## nix2
|
||||||
|
|
||||||
## `__noChroot`
|
## `__noChroot`
|
||||||
|
|
||||||
TODO
|
When the
|
||||||
|
[`sandbox`](https://nix.dev/manual/nix/2.29/command-ref/conf-file.html?highlight=__nos#conf-sandbox)
|
||||||
|
Nix configuration value is set to `relaxed`, fixed-output derivations (FODs)
|
||||||
|
that have the `__noChroot` attribute set to `true` will not run in the Nix
|
||||||
|
sandbox.
|
||||||
|
|
||||||
## cloud scale hydra
|
## cloud scale hydra
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
## `(_:_) != (_:_)` but `(a:a) == (a:a)`
|
## `(_:_) != (_:_)` but `(a:a) == (a:a)`
|
||||||
|
|
||||||
Evaluating `(_:_) == (_:_)`, we see that it is `false`, which means the two
|
Evaluating `(_:_) == (_:_)`, we see that it is `false`, which means the two
|
||||||
|
@ -855,3 +921,149 @@ TODO
|
||||||
This is the legacy `let` syntax. Equivalent to `let huh = "?"; in huh`.
|
This is the legacy `let` syntax. Equivalent to `let huh = "?"; in huh`.
|
||||||
|
|
||||||
## Tier 6: `has meowed before`
|
## Tier 6: `has meowed before`
|
||||||
|
|
||||||
|
### `let { body = 1; __overrides.body = 2; }`
|
||||||
|
|
||||||
|
This is a combination of [`__override`](#rec-a-5-b-a-1-overridesa-6-) for keyed
|
||||||
|
experessions and the [`legacy let syntax`](#let-huh-body-huh-).
|
||||||
|
|
||||||
|
### function identity is load bearing on importing nixpkgs
|
||||||
|
|
||||||
|
Since
|
||||||
|
[attribute sets with function members compare function identities (memory locations)](#let-f-a-a-s-ff-in-f-f-s-s),
|
||||||
|
comparing any attribute set that contains a function is load-bearing on the
|
||||||
|
function's identity.
|
||||||
|
|
||||||
|
The way this affects importing nixpkgs is that nixpkgs internally compares
|
||||||
|
stdenvs, which contain functions, to determine whether if we are
|
||||||
|
cross-compiling.nixpkgs internally compares stdenvs, which contain functions, to
|
||||||
|
determine whether if we are cross-compiling.
|
||||||
|
|
||||||
|
Therefore, function identity really **is** load bearing on importing nixpkgs.
|
||||||
|
|
||||||
|
### `import <nix/fetchurl.nix>`
|
||||||
|
|
||||||
|
This looks like we are importing <nix>, and getting the `fetchurl.nix` file in
|
||||||
|
it.
|
||||||
|
|
||||||
|
Let's see if that is true:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
nix-repl> builtins.readDir <nix>
|
||||||
|
{
|
||||||
|
".clang-format" = "regular";
|
||||||
|
".clang-tidy" = "regular";
|
||||||
|
".dir-locals.el" = "regular";
|
||||||
|
".editorconfig" = "regular";
|
||||||
|
".github" = "directory";
|
||||||
|
".gitignore" = "regular";
|
||||||
|
".mergify.yml" = "regular";
|
||||||
|
".shellcheckrc" = "regular";
|
||||||
|
".version" = "regular";
|
||||||
|
".version-determinate" = "regular";
|
||||||
|
"CITATION.cff" = "regular";
|
||||||
|
"CONTRIBUTING.md" = "regular";
|
||||||
|
COPYING = "regular";
|
||||||
|
"HACKING.md" = "symlink";
|
||||||
|
"README.md" = "regular";
|
||||||
|
contrib = "directory";
|
||||||
|
doc = "directory";
|
||||||
|
"docker.nix" = "regular";
|
||||||
|
"flake.lock" = "regular";
|
||||||
|
"flake.nix" = "regular";
|
||||||
|
maintainers = "directory";
|
||||||
|
"meson.build" = "regular";
|
||||||
|
"meson.options" = "regular";
|
||||||
|
misc = "directory";
|
||||||
|
nix-meson-build-support = "directory";
|
||||||
|
packaging = "directory";
|
||||||
|
"precompiled-headers.h" = "regular";
|
||||||
|
scripts = "directory";
|
||||||
|
src = "directory";
|
||||||
|
tests = "directory";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
There doesn't seem to be a `fetchurl.nix` file here.
|
||||||
|
|
||||||
|
This is because
|
||||||
|
[`<nix/*>` actually falls back to `corepkgs`](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/eval.cc#L3117-L3118),
|
||||||
|
which is a Nix path
|
||||||
|
[defined inside Nix itself.](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/eval.cc#L321)
|
||||||
|
|
||||||
|
[Later, the `fetchurl.nix` path is defined in `corepkgs`](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/eval.cc#L363)
|
||||||
|
and its contents are set to a
|
||||||
|
[generated C++ header.](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/meson.build#L129-L135)
|
||||||
|
|
||||||
|
You do not need to be in impure evaluation mode to use `corepkgs`, aka
|
||||||
|
`<nix/*>`.
|
||||||
|
|
||||||
|
### test suite of nix wasn't run
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### fixed-output derivation sandboxing
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### `importNative`
|
||||||
|
|
||||||
|
[`builtins.importNative`](https://nix.dev/manual/nix/2.29/command-ref/conf-file.html#conf-allow-unsafe-native-code-during-evaluation)
|
||||||
|
allows Nix expressions to import arbitrary dynamic libraries to produce Nix
|
||||||
|
expressions.
|
||||||
|
|
||||||
|
Of course, this is turned off by default as it is a security risk. You probably
|
||||||
|
shouldn't use this.
|
||||||
|
|
||||||
|
### `chromium recompressTarball`
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### more than 1 million chars of indents breaks things
|
||||||
|
|
||||||
|
The weird Nix parser
|
||||||
|
[hard codes `1000000`](https://github.com/NixOS/nix/blob/2afc84fddf463b22196aeb70587bc0c9259e330f/src/libexpr/include/nix/expr/parser-state.hh#L250)
|
||||||
|
instead of `SIZE_MAX` when determining the minimum indent to strip in strings
|
||||||
|
spanning multiple lines.
|
||||||
|
|
||||||
|
So when you have a line with more than a million spaces for the indent, it is
|
||||||
|
ignored and not included in the minimum indent calculation.
|
||||||
|
|
||||||
|
## Tier 7: `wears animal ears to NixCon`
|
||||||
|
|
||||||
|
<h2><small>
|
||||||
|
|
||||||
|
```nix
|
||||||
|
nix-repl> builtins.fromJSON ''{"uwu\u0000": 1, "uwu": 2}''
|
||||||
|
{ uwu = 2; "uwu" = 1; }
|
||||||
|
```
|
||||||
|
|
||||||
|
</small></h2>
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## `(_: builtins.break _)`
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## multiplayer tic-tac-toe in nix repl
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## `let e="e"; in [001.2e01e.30.4]`
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## `/__corepkgs__/`
|
||||||
|
|
||||||
|
[Already explained previously.](#import-nixfetchurlnix)
|
||||||
|
|
||||||
|
## `some-expr`
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## `__darwinAllowLocalNetworking`
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## `builtins.derivationStrict`
|
|
@ -2,8 +2,6 @@
|
||||||
title: Swap the `ı` and `i` key on your keyboard for faster modal editing
|
title: Swap the `ı` and `i` key on your keyboard for faster modal editing
|
||||||
description: How to swap the ı and i key on your Turkish keyboard on Linux.
|
description: How to swap the ı and i key on your Turkish keyboard on Linux.
|
||||||
|
|
||||||
date: 2024-05-20
|
|
||||||
|
|
||||||
keywords:
|
keywords:
|
||||||
- localisation
|
- localisation
|
||||||
- modal-editors
|
- modal-editors
|
|
@ -5,8 +5,6 @@ description: And how to roll the rock over the edge.
|
||||||
color: "#A5804C"
|
color: "#A5804C"
|
||||||
thumbnail: /assets/images/sisyphus-ds-store.webp
|
thumbnail: /assets/images/sisyphus-ds-store.webp
|
||||||
|
|
||||||
date: 2024-09-30
|
|
||||||
|
|
||||||
keywords:
|
keywords:
|
||||||
- vcs
|
- vcs
|
||||||
---
|
---
|
269
site/blog/2025-06-05-why-cores.md
Normal file
269
site/blog/2025-06-05-why-cores.md
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
---
|
||||||
|
title: "Why more `/sys/class/hwmon/*/temp*_label` than CPU cores?"
|
||||||
|
|
||||||
|
color: "#99CF9F"
|
||||||
|
thumbnail: /assets/images/cpu-dumb.webp
|
||||||
|
|
||||||
|
keywords:
|
||||||
|
- hardware
|
||||||
|
---
|
||||||
|
|
||||||
|
So, I am currently working on a Linux tool+daemon to replace
|
||||||
|
[`auto-cpufreq`](https://github.com/AdnanHodzic/auto-cpufreq) with a more
|
||||||
|
efficient, tunable and observable alternative.
|
||||||
|
|
||||||
|
And obviously, to tune a CPU well, knowing how hot it is is a requirement.
|
||||||
|
|
||||||
|
Then, how do you actually see how hot your CPU is in Linux? Using
|
||||||
|
`/sys/class/hwmon` of course.
|
||||||
|
|
||||||
|
This path contains hardware monitoring devices. In the laptop I'm testing this
|
||||||
|
on, `hwmon4` under this directory corresponds to the CPU.
|
||||||
|
|
||||||
|
Let's run a `tree`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/sys/class/hwmon/hwmon4 -> ../../devices/platform/coretemp.0/hwmon/hwmon4
|
||||||
|
├── device -> ../../../coretemp.0
|
||||||
|
│ ├── driver_override
|
||||||
|
│ ├── hwmon
|
||||||
|
│ ├── modalias
|
||||||
|
│ ├── power
|
||||||
|
│ ├── subsystem -> ../../../bus/platform
|
||||||
|
│ └── uevent
|
||||||
|
├── name
|
||||||
|
├── power
|
||||||
|
│ ├── autosuspend_delay_ms
|
||||||
|
│ ├── control
|
||||||
|
│ ├── runtime_active_time
|
||||||
|
│ ├── runtime_status
|
||||||
|
│ └── runtime_suspended_time
|
||||||
|
├── subsystem -> ../../../../../class/hwmon [recursive, not followed]
|
||||||
|
├── temp10_crit
|
||||||
|
├── temp10_crit_alarm
|
||||||
|
├── temp10_input
|
||||||
|
├── temp10_label
|
||||||
|
├── temp10_max
|
||||||
|
├── temp14_crit
|
||||||
|
├── temp14_crit_alarm
|
||||||
|
├── temp14_input
|
||||||
|
├── temp14_label
|
||||||
|
├── temp14_max
|
||||||
|
├── temp18_crit
|
||||||
|
├── temp18_crit_alarm
|
||||||
|
├── temp18_input
|
||||||
|
├── temp18_label
|
||||||
|
├── temp18_max
|
||||||
|
├── temp1_crit
|
||||||
|
├── temp1_crit_alarm
|
||||||
|
├── temp1_input
|
||||||
|
├── temp1_label
|
||||||
|
├── temp1_max
|
||||||
|
├── temp22_crit
|
||||||
|
├── temp22_crit_alarm
|
||||||
|
├── temp22_input
|
||||||
|
├── temp22_label
|
||||||
|
├── temp22_max
|
||||||
|
├── temp26_crit
|
||||||
|
├── temp26_crit_alarm
|
||||||
|
├── temp26_input
|
||||||
|
├── temp26_label
|
||||||
|
├── temp26_max
|
||||||
|
├── temp2_crit
|
||||||
|
├── temp2_crit_alarm
|
||||||
|
├── temp2_input
|
||||||
|
├── temp2_label
|
||||||
|
├── temp2_max
|
||||||
|
├── temp30_crit
|
||||||
|
├── temp30_crit_alarm
|
||||||
|
├── temp30_input
|
||||||
|
├── temp30_label
|
||||||
|
├── temp30_max
|
||||||
|
├── temp34_crit
|
||||||
|
├── temp34_crit_alarm
|
||||||
|
├── temp34_input
|
||||||
|
├── temp34_label
|
||||||
|
├── temp34_max
|
||||||
|
├── temp35_crit
|
||||||
|
├── temp35_crit_alarm
|
||||||
|
├── temp35_input
|
||||||
|
├── temp35_label
|
||||||
|
├── temp35_max
|
||||||
|
├── temp36_crit
|
||||||
|
├── temp36_crit_alarm
|
||||||
|
├── temp36_input
|
||||||
|
├── temp36_label
|
||||||
|
├── temp36_max
|
||||||
|
├── temp37_crit
|
||||||
|
├── temp37_crit_alarm
|
||||||
|
├── temp37_input
|
||||||
|
├── temp37_label
|
||||||
|
├── temp37_max
|
||||||
|
├── temp38_crit
|
||||||
|
├── temp38_crit_alarm
|
||||||
|
├── temp38_input
|
||||||
|
├── temp38_label
|
||||||
|
├── temp38_max
|
||||||
|
├── temp39_crit
|
||||||
|
├── temp39_crit_alarm
|
||||||
|
├── temp39_input
|
||||||
|
├── temp39_label
|
||||||
|
├── temp39_max
|
||||||
|
├── temp40_crit
|
||||||
|
├── temp40_crit_alarm
|
||||||
|
├── temp40_input
|
||||||
|
├── temp40_label
|
||||||
|
├── temp40_max
|
||||||
|
├── temp41_crit
|
||||||
|
├── temp41_crit_alarm
|
||||||
|
├── temp41_input
|
||||||
|
├── temp41_label
|
||||||
|
├── temp41_max
|
||||||
|
├── temp42_crit
|
||||||
|
├── temp42_crit_alarm
|
||||||
|
├── temp42_input
|
||||||
|
├── temp42_label
|
||||||
|
├── temp42_max
|
||||||
|
├── temp43_crit
|
||||||
|
├── temp43_crit_alarm
|
||||||
|
├── temp43_input
|
||||||
|
├── temp43_label
|
||||||
|
├── temp43_max
|
||||||
|
├── temp44_crit
|
||||||
|
├── temp44_crit_alarm
|
||||||
|
├── temp44_input
|
||||||
|
├── temp44_label
|
||||||
|
├── temp44_max
|
||||||
|
├── temp45_crit
|
||||||
|
├── temp45_crit_alarm
|
||||||
|
├── temp45_input
|
||||||
|
├── temp45_label
|
||||||
|
├── temp45_max
|
||||||
|
├── temp46_crit
|
||||||
|
├── temp46_crit_alarm
|
||||||
|
├── temp46_input
|
||||||
|
├── temp46_label
|
||||||
|
├── temp46_max
|
||||||
|
├── temp47_crit
|
||||||
|
├── temp47_crit_alarm
|
||||||
|
├── temp47_input
|
||||||
|
├── temp47_label
|
||||||
|
├── temp47_max
|
||||||
|
├── temp48_crit
|
||||||
|
├── temp48_crit_alarm
|
||||||
|
├── temp48_input
|
||||||
|
├── temp48_label
|
||||||
|
├── temp48_max
|
||||||
|
├── temp49_crit
|
||||||
|
├── temp49_crit_alarm
|
||||||
|
├── temp49_input
|
||||||
|
├── temp49_label
|
||||||
|
├── temp49_max
|
||||||
|
├── temp6_crit
|
||||||
|
├── temp6_crit_alarm
|
||||||
|
├── temp6_input
|
||||||
|
├── temp6_label
|
||||||
|
├── temp6_max
|
||||||
|
└── uevent
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's `cat` all the `_label` files:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/sys/class/hwmon/hwmon4/temp1_label:
|
||||||
|
Package id 0
|
||||||
|
/sys/class/hwmon/hwmon4/temp2_label:
|
||||||
|
Core 0
|
||||||
|
/sys/class/hwmon/hwmon4/temp6_label:
|
||||||
|
Core 4
|
||||||
|
/sys/class/hwmon/hwmon4/temp10_label:
|
||||||
|
Core 8
|
||||||
|
/sys/class/hwmon/hwmon4/temp14_label:
|
||||||
|
Core 12
|
||||||
|
/sys/class/hwmon/hwmon4/temp18_label:
|
||||||
|
Core 16
|
||||||
|
/sys/class/hwmon/hwmon4/temp22_label:
|
||||||
|
Core 20
|
||||||
|
/sys/class/hwmon/hwmon4/temp26_label:
|
||||||
|
Core 24
|
||||||
|
/sys/class/hwmon/hwmon4/temp30_label:
|
||||||
|
Core 28
|
||||||
|
/sys/class/hwmon/hwmon4/temp34_label:
|
||||||
|
Core 32
|
||||||
|
/sys/class/hwmon/hwmon4/temp35_label:
|
||||||
|
Core 33
|
||||||
|
/sys/class/hwmon/hwmon4/temp36_label:
|
||||||
|
Core 34
|
||||||
|
/sys/class/hwmon/hwmon4/temp37_label:
|
||||||
|
Core 35
|
||||||
|
/sys/class/hwmon/hwmon4/temp38_label:
|
||||||
|
Core 36
|
||||||
|
/sys/class/hwmon/hwmon4/temp39_label:
|
||||||
|
Core 37
|
||||||
|
/sys/class/hwmon/hwmon4/temp40_label:
|
||||||
|
Core 38
|
||||||
|
/sys/class/hwmon/hwmon4/temp41_label:
|
||||||
|
Core 39
|
||||||
|
/sys/class/hwmon/hwmon4/temp42_label:
|
||||||
|
Core 40
|
||||||
|
/sys/class/hwmon/hwmon4/temp43_label:
|
||||||
|
Core 41
|
||||||
|
/sys/class/hwmon/hwmon4/temp44_label:
|
||||||
|
Core 42
|
||||||
|
/sys/class/hwmon/hwmon4/temp45_label:
|
||||||
|
Core 43
|
||||||
|
/sys/class/hwmon/hwmon4/temp46_label:
|
||||||
|
Core 44
|
||||||
|
/sys/class/hwmon/hwmon4/temp47_label:
|
||||||
|
Core 45
|
||||||
|
/sys/class/hwmon/hwmon4/temp48_label:
|
||||||
|
Core 46
|
||||||
|
/sys/class/hwmon/hwmon4/temp49_label:
|
||||||
|
Core 47
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice something? I do:
|
||||||
|
|
||||||
|
- `temp1_label` is `Package id 0` - what is that?
|
||||||
|
- The core numbers make no sense. This device only has 32 cores, there shouldn't
|
||||||
|
be any gaps within numbers and the numbers shouldn't go that high.
|
||||||
|
|
||||||
|
The explanation for the first point is simple, looking at the kernel
|
||||||
|
[`coretemp.c`](https://github.com/torvalds/linux/blob/ec7714e4947909190ffb3041a03311a975350fe0/drivers/hwmon/coretemp.c#L348)
|
||||||
|
implementation, we can see that it is the temperature of the CPU as a whole:
|
||||||
|
|
||||||
|
```c
|
||||||
|
static ssize_t show_label(
|
||||||
|
struct device *dev,
|
||||||
|
struct device_attribute *devattr,
|
||||||
|
char *buf
|
||||||
|
) {
|
||||||
|
struct platform_data *pdata = dev_get_drvdata(dev);
|
||||||
|
struct temp_data *tdata = container_of(devattr, struct temp_data, sd_attrs[ATTR_LABEL]);
|
||||||
|
|
||||||
|
if (is_pkg_temp_data(tdata))
|
||||||
|
return sprintf(buf, "Package id %u\n", pdata->pkg_id);
|
||||||
|
|
||||||
|
return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
That leaves us the second question. Why do we have CPUs 1, 2, 6, 10, 14, 18, 22,
|
||||||
|
26, 30, 34-49, instead of the expected 0-31?
|
||||||
|
|
||||||
|
It turns out that CPU It's common for chip manufacturers to disable faulty or
|
||||||
|
degraded cores before shipping. Or if a lower tier SKU[^Stock Keeping Unit] is
|
||||||
|
selling more, cores of higher tier SKUs are disabled to match expectations.
|
||||||
|
|
||||||
|
This process is called `binning`, and it exists to not waste silicon. Since
|
||||||
|
silicon manufacturing is not perfect, some CPUs are more faulty, thus slower
|
||||||
|
than others. The process determintes how faulty a CPU is and sorts them into
|
||||||
|
"bins". This is also why lower tier CPUs who are almost exactly the same as
|
||||||
|
higher tier CPUs exist.
|
||||||
|
|
||||||
|
The likelyhood of faulty silicon also increases with the smaller the
|
||||||
|
architechture size gets (the Apple M4 is 4m, which is crazy), so this method of
|
||||||
|
recycling worse chips is becoming much more valuable by the day.
|
||||||
|
|
||||||
|
So, in summary the 32 core CPU I was testing this on was most likely just the 64
|
||||||
|
core version with a bunch of the cores disabled.
|
|
@ -1,4 +1,6 @@
|
||||||
export default {
|
export default {
|
||||||
layout: "text.vto",
|
layout: "text.vto",
|
||||||
type: "article",
|
type: "article",
|
||||||
|
|
||||||
|
description: null,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue