From 4847abc8ebf6a48318142ddd7e5700981a0c8732 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 16:44:55 +0300 Subject: [PATCH 01/10] blog: why-cores --- site/blog/why-cores.md | 258 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 site/blog/why-cores.md diff --git a/site/blog/why-cores.md b/site/blog/why-cores.md new file mode 100644 index 0000000..71fe12d --- /dev/null +++ b/site/blog/why-cores.md @@ -0,0 +1,258 @@ +--- +title: "Why more `/sys/class/hwmon/*/temp*_label` than CPU cores?" + +date: 2025-06-05 + +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? +- Other 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. + +Most likely the 32 core CPU I was testing this on was actually just the 64 core +version with a bunch of the cores disabled. From 32e0386270639c7107e4aab8c2b9809fbb6e90e3 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 16:46:55 +0300 Subject: [PATCH 02/10] blog: disable descriptions when unset --- site/blog/_data.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/site/blog/_data.ts b/site/blog/_data.ts index d50cb78..bd76e4f 100644 --- a/site/blog/_data.ts +++ b/site/blog/_data.ts @@ -1,4 +1,6 @@ export default { layout: "text.vto", type: "article", + + description: null, }; From 9be051d775717f3d54fc427eeb2aa4fc1630b9e7 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 16:52:29 +0300 Subject: [PATCH 03/10] blog(why-cores): more explanaiton about cpu binning --- site/blog/why-cores.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/site/blog/why-cores.md b/site/blog/why-cores.md index 71fe12d..80b1f59 100644 --- a/site/blog/why-cores.md +++ b/site/blog/why-cores.md @@ -254,5 +254,15 @@ 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. -Most likely the 32 core CPU I was testing this on was actually just the 64 core -version with a bunch of the cores disabled. +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. From 0b001d957e5158ea804590a938de525f877cf558 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 17:09:06 +0300 Subject: [PATCH 04/10] dumb inside:tm: --- site/assets/images/cpu-dumb-maybe.webp | Bin 0 -> 13794 bytes site/blog/why-cores.md | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 site/assets/images/cpu-dumb-maybe.webp diff --git a/site/assets/images/cpu-dumb-maybe.webp b/site/assets/images/cpu-dumb-maybe.webp new file mode 100644 index 0000000000000000000000000000000000000000..44e37f18265b166dd93c428901d5d90502a86e69 GIT binary patch literal 13794 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 V@$O5;uj*LGTX2ua)Y~#K001EmK`sCQ literal 0 HcmV?d00001 diff --git a/site/blog/why-cores.md b/site/blog/why-cores.md index 80b1f59..82894b9 100644 --- a/site/blog/why-cores.md +++ b/site/blog/why-cores.md @@ -3,6 +3,9 @@ title: "Why more `/sys/class/hwmon/*/temp*_label` than CPU cores?" date: 2025-06-05 +color: "#99CF9F" +thumbnail: /assets/images/cpu-dumb-maybe.webp + keywords: - hardware --- From 9c78876e9b69ff92d7cc099a0e93d2baf2cfb17a Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 17:20:17 +0300 Subject: [PATCH 05/10] blog(why-cores): fix --- site/blog/why-cores.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/blog/why-cores.md b/site/blog/why-cores.md index 82894b9..52c2b17 100644 --- a/site/blog/why-cores.md +++ b/site/blog/why-cores.md @@ -227,8 +227,8 @@ Core 47 Notice something? I do: - `temp1_label` is `Package id 0` - what is that? -- Other 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 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) From 3abff9ebd1f83b34ecdc06e4ff90dedf4c1fe62c Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 17:33:22 +0300 Subject: [PATCH 06/10] blog: move dates to filenames --- site/blog/{test.md => 2024-01-01-test.md} | 2 +- site/blog/{htmnix.md => 2024-03-04-htmnix.md} | 2 -- site/blog/{cosmic-drift.md => 2024-04-02-cosmic-drift.md} | 2 -- site/blog/{nix-iceberg.md => 2024-04-15-nix-iceberg.md} | 1 - site/blog/{swap-i.md => 2024-05-20-swap-i.md} | 2 -- site/blog/{gitignore.md => 2024-09-30-gitignore.md} | 2 -- site/blog/{why-cores.md => 2025-06-05-why-cores.md} | 2 -- 7 files changed, 1 insertion(+), 12 deletions(-) rename site/blog/{test.md => 2024-01-01-test.md} (99%) rename site/blog/{htmnix.md => 2024-03-04-htmnix.md} (99%) rename site/blog/{cosmic-drift.md => 2024-04-02-cosmic-drift.md} (99%) rename site/blog/{nix-iceberg.md => 2024-04-15-nix-iceberg.md} (99%) rename site/blog/{swap-i.md => 2024-05-20-swap-i.md} (99%) rename site/blog/{gitignore.md => 2024-09-30-gitignore.md} (99%) rename site/blog/{why-cores.md => 2025-06-05-why-cores.md} (99%) diff --git a/site/blog/test.md b/site/blog/2024-01-01-test.md similarity index 99% rename from site/blog/test.md rename to site/blog/2024-01-01-test.md index 2b9257e..abb6da3 100644 --- a/site/blog/test.md +++ b/site/blog/2024-01-01-test.md @@ -1,7 +1,7 @@ --- -date: 2024-01-01 title: Test description: "Testing" + draft: true --- diff --git a/site/blog/htmnix.md b/site/blog/2024-03-04-htmnix.md similarity index 99% rename from site/blog/htmnix.md rename to site/blog/2024-03-04-htmnix.md index eb6d0ff..847b0ec 100644 --- a/site/blog/htmnix.md +++ b/site/blog/2024-03-04-htmnix.md @@ -2,8 +2,6 @@ title: HTMNIX description: How the absolutely cursed HTMNIX project works. -date: 2024-03-04 - keywords: - html - nix diff --git a/site/blog/cosmic-drift.md b/site/blog/2024-04-02-cosmic-drift.md similarity index 99% rename from site/blog/cosmic-drift.md rename to site/blog/2024-04-02-cosmic-drift.md index 9f6dab4..862d7cb 100644 --- a/site/blog/cosmic-drift.md +++ b/site/blog/2024-04-02-cosmic-drift.md @@ -2,8 +2,6 @@ title: Cosmic Drift description: Or how I missed the school bus because of a cosmic ray. -date: 2024-04-02 - keywords: - time - unix-timestamps diff --git a/site/blog/nix-iceberg.md b/site/blog/2024-04-15-nix-iceberg.md similarity index 99% rename from site/blog/nix-iceberg.md rename to site/blog/2024-04-15-nix-iceberg.md index 847b205..5e7e727 100644 --- a/site/blog/nix-iceberg.md +++ b/site/blog/2024-04-15-nix-iceberg.md @@ -2,7 +2,6 @@ title: Explaining the Nix iceberg description: And revealing how cursed Nix is. -date: 2024-04-15 draft: true keywords: diff --git a/site/blog/swap-i.md b/site/blog/2024-05-20-swap-i.md similarity index 99% rename from site/blog/swap-i.md rename to site/blog/2024-05-20-swap-i.md index 4f27fa3..7d3522b 100644 --- a/site/blog/swap-i.md +++ b/site/blog/2024-05-20-swap-i.md @@ -2,8 +2,6 @@ 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. -date: 2024-05-20 - keywords: - localisation - modal-editors diff --git a/site/blog/gitignore.md b/site/blog/2024-09-30-gitignore.md similarity index 99% rename from site/blog/gitignore.md rename to site/blog/2024-09-30-gitignore.md index 27a507d..65ea639 100644 --- a/site/blog/gitignore.md +++ b/site/blog/2024-09-30-gitignore.md @@ -5,8 +5,6 @@ description: And how to roll the rock over the edge. color: "#A5804C" thumbnail: /assets/images/sisyphus-ds-store.webp -date: 2024-09-30 - keywords: - vcs --- diff --git a/site/blog/why-cores.md b/site/blog/2025-06-05-why-cores.md similarity index 99% rename from site/blog/why-cores.md rename to site/blog/2025-06-05-why-cores.md index 52c2b17..1e4acd4 100644 --- a/site/blog/why-cores.md +++ b/site/blog/2025-06-05-why-cores.md @@ -1,8 +1,6 @@ --- title: "Why more `/sys/class/hwmon/*/temp*_label` than CPU cores?" -date: 2025-06-05 - color: "#99CF9F" thumbnail: /assets/images/cpu-dumb-maybe.webp From 104140528a5715fd3f9a827405f4fe50f4625637 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 18:42:50 +0300 Subject: [PATCH 07/10] blog(nix-iceberg): even more text --- site/assets/css/default.css | 10 +- site/blog/2024-04-15-nix-iceberg.md | 212 +++++++++++++++++++++++++--- 2 files changed, 198 insertions(+), 24 deletions(-) diff --git a/site/assets/css/default.css b/site/assets/css/default.css index b95be3b..4f6b6f8 100644 --- a/site/assets/css/default.css +++ b/site/assets/css/default.css @@ -171,7 +171,7 @@ html, body { @apply wrap-anywhere; } - &:not(:has(> code:only-child)) { + &:not(:has(> code:only-child)):not(:has(> img)) { @apply px-1; &:not(.font-mono) { @@ -230,8 +230,8 @@ html, body { code:not(pre > code) { @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:active &:not(:is(h1, h2, h3, h4, h5, h6) *) { + a:hover &:not(:only-child, :is(h1, h2, h3, h4, h5, h6) *), + a:active &:not(:only-child, :is(h1, h2, h3, h4, h5, h6) *) { @apply border-transparent; } } @@ -252,9 +252,7 @@ html, body { } & li::before { - @apply pr-1; - - content: "[" counter(item) "]"; + content: counter(item) ". "; } } diff --git a/site/blog/2024-04-15-nix-iceberg.md b/site/blog/2024-04-15-nix-iceberg.md index 5e7e727..c693b2f 100644 --- a/site/blog/2024-04-15-nix-iceberg.md +++ b/site/blog/2024-04-15-nix-iceberg.md @@ -15,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 some truly arcane examples of Nix code. -Some knowledge of Nix is required, you may get confused in the terminology if -you've never used it. +Some knowledge of Nix is required, you may get confused with the terminology if +you've never used Nix. -![The Nix Iceberg](/assets/images/nix-iceberg.webp) - -[Here's the original source for this image, on cohost.](https://cohost.org/leftpaddotpy/post/3885451-the-nix-iceberg) +[![The Nix Iceberg](/assets/images/nix-iceberg.webp)](https://cohost.org/leftpaddotpy/post/3885451-the-nix-iceberg) Let's start: @@ -53,7 +51,7 @@ So, what are we doing in this snippet? 2. Creating a derivation that runs an echo command, which writes a Nix expression to the output file. 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? @@ -518,14 +516,14 @@ known. # Tier 3: `assigned nix hacker at employment` -

+

```sh #!/usr/bin/env nix-shell #!nix-shell -i python3 -p python3 ``` -

+ _(taken verbatim from `man nix-shell`)_ @@ -564,7 +562,16 @@ print t ## `--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 @@ -716,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 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: +[Here's the snippet:](https://github.com/NixOS/nix/blob/aa165301d1ae3b306319a6a834dc1d4e340a7112/src/libexpr/eval.cc#L2525-L2528) ```cpp bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx) @@ -778,10 +784,11 @@ impure binaries to the Nix store. ## `rec { a = 5; b = a + 1; __overrides.a = 6; }` -There is a special field named `__overrides` in recursive attrset expressions, -which simply overrides the parent attribute set with the keys inside it. This is -different from the update operator (`//`) because that will not override the -self-references in the recursive attribute set. +There is a special field named `__overrides` in keyed expressions (attribute +sets, `let-in`'s and as secret third thing), which simply overrides the parent +attribute set with the keys inside it. This is different from the update +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; } // { a = 6; }).b` will evaluate to 6. @@ -813,7 +820,58 @@ TODO ## `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 `[ 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 @@ -821,16 +879,25 @@ TODO ## `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 ## `__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 +TODO + ## `(_:_) != (_:_)` but `(a:a) == (a:a)` Evaluating `(_:_) == (_:_)`, we see that it is `false`, which means the two @@ -854,3 +921,112 @@ TODO This is the legacy `let` syntax. Equivalent to `let huh = "?"; in huh`. ## 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 ` + +This looks like we are importing , and getting the `fetchurl.nix` file in +it. + +Let's see if that is true: + +```nix +nix-repl> builtins.readDir +``` + + + +This is because `` is actually `corepkgs`, 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) + +### test suite of nix wasn't run + +TODO + +### fixed-output derivation sandboxing + +TODO + +### `importNative` + +[`builtins.importNative`](https://nix.dev/manual/nix/2.24/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` + +

+ +```nix +nix-repl> builtins.fromJSON ''{"uwu\u0000": 1, "uwu": 2}'' +{ uwu = 2; "uwu" = 1; } +``` + +

+ +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` From 10093e1e650eb07e871c3edfd8ec8d0e3c55283a Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 18:59:11 +0300 Subject: [PATCH 08/10] blog(nix-iceberg): update manual links --- site/blog/2024-04-15-nix-iceberg.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/blog/2024-04-15-nix-iceberg.md b/site/blog/2024-04-15-nix-iceberg.md index c693b2f..e1b109c 100644 --- a/site/blog/2024-04-15-nix-iceberg.md +++ b/site/blog/2024-04-15-nix-iceberg.md @@ -744,7 +744,7 @@ want with this information. As surprising as it sounds, Nix does indeed supports plugins. You can load 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. From the configuration reference: @@ -776,7 +776,7 @@ Some example plugins are [`nix-doc`](https://github.com/lf-/nix-doc) and ## `/bin/sh` and sandbox impurity 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 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 @@ -971,7 +971,7 @@ TODO ### `importNative` -[`builtins.importNative`](https://nix.dev/manual/nix/2.24/command-ref/conf-file.html#conf-allow-unsafe-native-code-during-evaluation) +[`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. From 011b7c7680f2b13a4c024787ffe2e5a86e6f36ed Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 19:03:30 +0300 Subject: [PATCH 09/10] blog(nix-iceberg): explain --- site/blog/2024-04-15-nix-iceberg.md | 41 +++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/site/blog/2024-04-15-nix-iceberg.md b/site/blog/2024-04-15-nix-iceberg.md index e1b109c..59218c4 100644 --- a/site/blog/2024-04-15-nix-iceberg.md +++ b/site/blog/2024-04-15-nix-iceberg.md @@ -950,17 +950,54 @@ Let's see if that is true: ```nix nix-repl> builtins.readDir +{ + ".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 `` is actually `corepkgs`, which is a Nix path +This is because +[`` 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 +``. + ### test suite of nix wasn't run TODO From f5cf07e8b73c799bb7fa04ebcb6b671c62967f39 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Thu, 5 Jun 2025 20:15:43 +0300 Subject: [PATCH 10/10] blog(why-cores): rename thumbnail --- .../images/{cpu-dumb-maybe.webp => cpu-dumb.webp} | Bin site/blog/2025-06-05-why-cores.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename site/assets/images/{cpu-dumb-maybe.webp => cpu-dumb.webp} (100%) diff --git a/site/assets/images/cpu-dumb-maybe.webp b/site/assets/images/cpu-dumb.webp similarity index 100% rename from site/assets/images/cpu-dumb-maybe.webp rename to site/assets/images/cpu-dumb.webp diff --git a/site/blog/2025-06-05-why-cores.md b/site/blog/2025-06-05-why-cores.md index 1e4acd4..8ca2bdb 100644 --- a/site/blog/2025-06-05-why-cores.md +++ b/site/blog/2025-06-05-why-cores.md @@ -2,7 +2,7 @@ title: "Why more `/sys/class/hwmon/*/temp*_label` than CPU cores?" color: "#99CF9F" -thumbnail: /assets/images/cpu-dumb-maybe.webp +thumbnail: /assets/images/cpu-dumb.webp keywords: - hardware