1
Fork 0
mirror of https://github.com/RGBCube/Site synced 2025-08-01 05:27:46 +00:00

Compare commits

...

10 commits

10 changed files with 509 additions and 36 deletions

View file

@ -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) ". ";
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,7 +1,7 @@
---
date: 2024-01-01
title: Test
description: "Testing"
draft: true
---

View file

@ -2,8 +2,6 @@
title: HTMNIX
description: How the absolutely cursed HTMNIX project works.
date: 2024-03-04
keywords:
- html
- nix

View file

@ -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

View file

@ -2,7 +2,6 @@
title: Explaining the Nix iceberg
description: And revealing how cursed Nix is.
date: 2024-04-15
draft: true
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
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:
@ -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
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?
@ -519,14 +516,14 @@ known.
# Tier 3: `assigned nix hacker at employment`
<h2>
<h2><small>
```sh
#!/usr/bin/env nix-shell
#!nix-shell -i python3 -p python3
```
</h2>
</small></h2>
_(taken verbatim from `man nix-shell`)_
@ -565,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
@ -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
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)
@ -739,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:
@ -771,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
@ -779,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.
@ -814,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 `[ <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
@ -822,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
@ -855,3 +921,149 @@ 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 <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`

View file

@ -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

View file

@ -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
---

View 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.

View file

@ -1,4 +1,6 @@
export default {
layout: "text.vto",
type: "article",
description: null,
};