I’ve wondered for years why SCHED_IDLE tasks are allowed to preempt other
tasks. Nobody seems to know, and I’ve not had the time to dig in and understand
the Linux kernel scheduler better. But now I finally have my answer.
I want to be able to run a CPU-heavy task in the background, without it stealing any CPU, any at all, from other processes.
If you read various documentation, you’d be forgiven if this is as simple as
schedtool -D -e ./my-background-thing.
SCHED_FIFO can be used only with static priorities higher than 0,
which means that when a SCHED_FIFO thread becomes runnable, it
will always immediately preempt any currently running SCHED_OTHER,
SCHED_BATCH, or SCHED_IDLE thread.
(and similar statements, e.g. from sched.7)
But if you try that, you’ll find that it’ll actually preempt other processes, taking little but nonzero CPU. There’s a test program, if you want to try it out.
I literally want it to take zero CPU. And not just against SCHED_FIFO/RR, but
everything.
There appear to be two places that minmax guarantees can show up.
Settings with default values:
$ sudo sysctl -a | grep sched_rt_
kernel. Continue readingIn a previous post I described load balancing for TCP-based HTTP with connection offloading, and mentioned that HTTP/3 can do even more. By the power of AI writing a HTTP/3 version of both the load balancer (sni-router-h3) and the webserver (tarweb-h3), I have experimented enough to have more to say about how that works.
To be clear: this post is 100% human-written.
In this post I will use this terminology:
While it is possible to use TCP_REPAIR to transfer an established connection
between machines (from router to backend), it requires some more
infrastructure. The kernel on the chosen backend must be synced up on the
connection state (sequence numbers, etc) that TCP_REPAIR provides, but that’s
actually just the easy part. It must also be able to send packets to the client
with the original server’s IP address as source, and packets going from the
client to the backend must somehow find their way to the same backend, in a
network-efficient way.
There are other problems Continue reading
After my post on undefined behavior in C some people insisted that it’s demonstrably fine, we know what the code will do, and at worst we’ll get a segfault.
This is false.
Here’s an example.
#include<utility>
// Let's pretend this is a memory mapped device controlling
// motors and gears and stuff.
volatile int device_command = 0;
void serve_hot_chocolate() {
device_command = 42;
// Oh no, we spilled some hot chocolate, invoking UB.
//
// The definition of `std::unreachable()` is:
// Invokes undefined behavior at a given point.
std::unreachable();
}
void explode() {
device_command = 3;
}
int main() {
serve_hot_chocolate();
}
With GCC 16.2 with -O1.
"serve_hot_chocolate()":
mov DWORD PTR "device_command"[rip], 42
"explode()":
mov DWORD PTR "device_command"[rip], 3
ret
"main":
mov DWORD PTR "device_command"[rip], 42
"device_command":
.zero 4
Ruh roh. Exploding chocolate! The function explode() will be executed, even
though it was never called!
Some people insisted that dereferencing a null pointer is fine. It’ll just try to access address zero! And these people supposedly know what happens when you try: if nothing is mapped there, you’ll get a segfault.
Again, not true.
Let’s say we change Continue reading
When building software defined radio flowgraphs it’s common to want to inspect the live data as it flows through various stages. In GNU Radio, and RustRadio, the handoff points are very clear. They are the streams between the blocks.
In GNU Radio you can stop the graph, click a bit in gnuradio-companion, and have a new time sink (or whatever you need) added, and then start the graph up again. But it makes for a lot of stopping and starting. There’s also the drawback that it assumes that the GNU Radio flowgraph is graphical in the first place, and not running headless on a raspberry pi somewhere.
And for large graphs, preemptively adding GUI elements for everything you may possibly want to read at runtime can clutter things up, and waste CPU processing and rendering data you’re not interested in.
Another use case is if you have a constantly running RF sniff process using an SDR, to get a second reader of the same data, to help develop the next version without shutting down the one already running.
So clearly, what you want is to be able to connect to the flowgraph over the network, and start streaming any and Continue reading
While writing some software defined radio applications, I have found myself wanting to run them headless on some raspberry pi or similar, but then occasionally connect to it and inspect it live.
I want to stream sample data, and tags data, and drop data on overflow. The main use case is for a UI, so it should not block the rest of the processing if the network or UI is slow, or disconnected.
I also want the protocol to support lossless sources, for example a stream coming from a SigMF file.
I’ve been dragging my heels on this, because surely this protocol already exists. And if I make a new one then nobody else is compatible with it.
GNU Radio has ZeroMQ sink and source blocks, but a UI running Continue reading
Until now, my HF antennas have mostly been off the shelf. I’ve gone out with an AlexLoop (hmm, alexloop.com seems to be down. I don’t know if that’s permanent), and the Elecraft AX1. They’ve both been fine, but have some drawbacks. The AX1 is a bit finicky about getting its radial(s) good enough, and the AlexLoop is a bit tricky to set up in a temporary but stable way.
I have not have good experience with the half wave G5RV, yet, for some reason.
So since all HF antennas are compromises, why not try an inverted V dipole? I had the UniBalun recommended to me, so I went with that. There are some minor things to think about, which is what this blog post is about.
To become an antenna, I also needed antenna wire, and a way to put the middle of the dipole high up, with the antenna wire extending straight diagonally down. For a 20m (14MHz) antenna, I cut two 5.2m pieces, expecting to need to either cut or fold them back a bit, for the right resonance.
On the UniBalun side I could just crimp an M4 ring to attach the antenna wire, Continue reading
Previously I successfully did some receiving and some transmitting over the amateur radio transponder on the satellite QO-100. That is to say, my FT8 was heard by others (but not me, due to my small dish), and I successfully decoded FT8 from some others.
There are three problems with my QO-100 ground station:
I really appreciate the constant FT8 activity when tuning my station. Sure, I could look at the band edge beacons, but I like this too. And strangely, I can not actually find the edge beacons.
Today is about the third issue: Frequency stability. Because the B200 was GPS locked last time, the main suspect was the LNB. The Othernet Bullseye LNB TCXO from Passion-Radio.com is a fine LNB, but it’s Continue reading
I’ve been playing a bit with OFDM in software defined radio lately. And after watching a video that wasn’t even close to correct, I thought I’d write down my understanding in a blog post. I wouldn’t call myself an expert, so worst case someone will correct me, and I’m happy to be corrected.
In my experiments with OFDM my initial goal is understanding, so e.g. I won’t blindly use some hierarchical GNU Radio block.
I think that in order to internalize OFDM, we first need to remind ourselves how a purely “real” wave becomes a complex number, at a high level.
The real signal is a value that’s a function of time. Glossing over details, this is not feasible for most of our signals, as we would need to provide a new value to the transmitter at a rate twice as high as the highest frequency we care about. For 2.4GHz experiments, we’d need 4.8 billion samples per second.
Quadrature sampling allows us to represent a slice of bandwidth at a manageable rate. We can then provide the I/Q data to hardware, instructing it to hold that “until further notice”. Continue reading
As I mentioned in a previous post I wanted to make a WASM version of the RF scanner / RF survey tool, so that it can be run without any drivers or tools installed on the local machine.
Well, now I have. It’s available at https://rf-survey.habets.se/ as a GitHub page, automatically deploying from the github repo.
If you don’t have a compatible SDR, then you can at least enjoy the video here.
Step by step for doing a screen recording on Sway.
I want to capture exact 16x9 dimensions, and exactly the the right content. I do it pretty rarely, but yeah this should be automated.
Run this command, and move the pointer to the window you want to record.
$ sleep 2;swaymsg -t get_tree | jq '.. | objects | select(.focused? == true) | {app_id, id, name, window_properties}'
{
"app_id": "brave-browser",
"id": 802,
"name": "WebUSB RF Survey - Brave",
"window_properties": null
}
swaymsg '[con_id=802] floating enable,move position 200 px 256 px, resize set width 1600 px height 901 px'
(yes, 901. This may be because of my 1.3 scaling on that monitor, giving an off by one pixel due to rounding)
sleep 2;swaymsg -t get_tree | jq '.. | objects | select(.focused? == true) | .rect'
{
"x": 2120,
"y": 256,
"width": 1600,
"height": 900
}
wf-recorder -g '2120,257 1600x900' -f output.mp4
(yes, 257. Add one. Probably same reason)
$ slurp
2163,333 1514x37
Continue readingI have previously blogged about doing RF surveys using software defined radio. The most interesting aspect to me has been to inventory the business of the different WiFi channels, in order to not clash with neighbouring access points.
I’ve now written better software for doing these surveys.
2.4GHz is a mess (overlapping channels), has much less spectrum, and goes through walls more than 5GHz worth. There’s also a bunch of other crap on 2.4GHz polluting the airwaves, including microwave ovens. So if you’ve thought about this at all, you know to stay off of 2.4GHz.
It’s tempting to get a QuadRF in order to add more dimensions to the 5GHz RF survey, but so far I’ve resisted buying this particular toy.
I’m plotting the spectrum power in both dB and linear. With linear scale the busyness really pops.
There’s even a bunch of noise between the channels. Is it microwaves? Or someone running the 1/5/9/13 channel split? No, if anything it looks like channel 14, which is not legal here.
As a power WiFi user I started using U-NII-3 channels (149-165) as soon as they Continue reading
In a previous post I made pipes in unix shells more reliable. Well, it had some drawbacks. I’ll summarize the problem, the failed previous version, and then show the new and improved one.
Downstream processes in a unix shell pipe cannot know if the upstream finished successfully, or exited with an error. This means that it can’t know if it should “commit” the data it received.
Example uses:
$ pg_dumpall | xz -9 | google_cloud_storage_upload gs://bucket/path/postgres.dump
$ generate_data | psql --single-transaction
In both of these cases you want the right hand side to STOP, and not finalize the upload or commit the transaction.
$ goodpipe <<EOF
[
["gsutil", "cat", "gs://example/input-unsorted.txt"],
["sort", "-S300M", "-n"],
["gzip", "-9"],
["gsutil", "cp", "-", "gs://example/input-sorted-numerically.txt.gz"]
]
EOF
This works fine for simple cases, but doesn’t support tee or per-command
environment variables very well.
And I don’t want to invent a complex language, so my replacement took a different path.
wp instead wraps the input and/or output with a very minimal encapsulating
protocol. This allows normal data to pass through, but still allows the
downstream to get EOF as metadata.
This is a follow-up to a previous post about raytracing Quake demos.
But first, the money shot:
And flat shaded and textured videos. Youtube is Very Aggressive™ with its compression, so the quality there is not good. For pixel quality the above images showcase it better.
One of my original reasons for creating the quake demo povray files is that it was a good source of data for 3D experiments. POV-Ray is a great raytracer, though entirely CPU (no GPU) and no longer state of the art.
POV-Ray has plenty of built in options, but takes forever to render the 30-60fps demos I want to play with.
Also POV-Ray is AGPL now, so nope nope nope nope nope. That’s a dead end.
We live in interesting times. We could be living in a time when no two people are running the same email client, or music player, or shell. There used to be a barrier to writing these things custom. I know people who wrote their own shell and use it as a daily driver. I wrote my own email client, and use that.
There are many people out there, me included, who Continue reading
I’ve been able to find some time, lately, to work on my project backlog. And because it’s 2026, I’ve been using AI as a diligent intern.
I’ve ranted before about
seccomp, but
still used it for a project or two. But then, rarely, it triggered an
unexpected openat. That’s exactly the kind of I do want to detect and kill
the binary for, so I don’t just want to allow it. I want to know where it’s
coming from.
strace showed it’s trying to read /proc/sys/vm/overcommit_memory.
It’s certainly not my code. But just the Rust transitive dependency tree is quite a few crates:
$ cargo tree | sed -r 's/^[^a-z]+//;s/ .*//' | sort -u | wc -l
236
Step 1 was to run it in gdb, and reproduce the problem. But it’s a bit
trickier than that, because seccomp fully kills the process, so no backtrace.
And setting breakpoints requires a few more syscalls to work, just for the
process to work under gdb (e.g. sigaltstack).
And turns out some calls fail with EINTR if running under a debugger.
Yes, I can fix all these things. But why not put the AI intern on it?
This is just a short followup to the last RustRadio post. If you came for more rants about C, you’ll be disappointed.
I’ve never been that interested in writing UI code, including HTML. You can see the “programmer art” in the screenshots linked from www.habets.pp.se.
And then the slightly different tech section, that doesn’t serve much of a purpose now that we have github.
I’ve not been happier with GTK, QT, and the others either.
But [RustRadio][rustradio] needs a UI.
I feel like the browser is the most stable and portable UI. So I’d already decided on that. So now I have to manually do a bunch of DOM manipulation, to create an interactive UI? Or worse, learn the React/Angular/Whatever flavor of the day, that will be obsolete by next afternoon? Gag me with a spoon.
For now I’m just continuing to focus on the SDR and architectural parts of RustRadio, and I’m letting the LLM-written code do the HTML manipulation.
Yeah, it’s kinda vibe coding. But doesn’t use unsafe, and it demonstrably
outputs what I want. (I mean, sure it may require some follow-up prompts), so
who cares?
The Continue reading
If he had been a programmer, Cardinal Richelieu would have said “Give me six lines written by the hand of the most expert C programmer in the world, and I will find enough in them to trigger undefined behavior”.
Nobody can write correct C, or C++. And I say that as someone who’s written C and C++ on an almost daily basis for about 30 years. I listen to C++ podcasts. I watch C++ conference talks. I enjoy reading and writing C++.
C++ has served us well, but it’s 2026, and the environment of 1985 (C++) or 1972 (C) is not the environment of today.
I’m definitely not the first to say this. I remember reading a post by someone prominent about a decade ago saying that a good case can be made that use of C++ is a SOX violation. And while I was not onboard with the rest of their rant (nor their confusion about “its” vs “it’s”), I never disagreed about that point.
With time I found it to be more and more true. WAY more things are undefined behavior (UB) than you’d expect.
Everyone knows that double-free, use after free, accessing outside the bounds of an Continue reading
I’ve previously pointed out that the AX.25 implementation in the kernel is pretty poor. It’s not really being maintained, and even when it gets fixes after I reported it, with people running LTS OSs it can take like 5 years before before the fix actually reaches users, if ever. So when writing applications, you still have to work around kernel bugs from a decade ago. This makes it kind of pointless to upstream patches.
The exception is security patches, and reading between the lines of why the AX.25 code is now being removed from the kernel, it sounds like maybe some LLM (like the looming “Mythos” and the related Glasswing) may have found some severe problems. But even if there aren’t any known security problems yet, having code is now more of a liability than ever. Code needs to be removed, or taken responsibility of. (tangent about ffmpeg at the bottom of this post)
With the kernel code removed, say goodbye to the old walkthrough.
Well, not “new”, per se, but “replacement”.
With the socket based API about to be gone, we need some other way for applications to send packets and Continue reading
You may have seen it too. This trend of “I wrote some software to solve a problem. I think it’s pretty great. Does anyone have any feedback?”. Maybe it’s a budget app. Or some company management thingy, tracking sales. Or invoicing.
Maybe you take a look. It looks pretty slick. But then you get a feeling of uncanny valley. It’s just not right. Maybe you can’t even put your finger on it.
I’m not an accountant, so when I see some accounting software do something in a different way, it’s interesting. Why is it that way? What can I learn from the fact that a professional thinks it should be this way?
You already know what’s weird about it, if nothing else because of the title of this post. The software works this way because the LLM wrote it that way. There’s no reason. It’s not even wrong.
How do you give “feedback” on that? My feedback would be that you don’t understand the problem you’re trying to solve, and have shown no sign you intend to understand it, so how could you possibly think you can solve it?
You’re not asking for feedback. You’re asking for someone Continue reading
I’ve previously blogged about RustRadio, my GNU Radio like framework for writing software defined radio applications in Rust. And now there’s more progress of an interesting kind.
Anything that tries to do something similar to GNU Radio needs a few things:
In addition to these, GNU Radio also has the excellent GNU Radio Companion for interactive creation of flowgraphs, but I’m not tackling that yet.
I have a core framework, and some components (blocks). But the UI has been a bit lacking.
I’ve played around with TUI applications, but I always knew I also wanted to support having a UI in the browser. I’m not as interested in adding support for QT or Windows native UI. The browser will do fine.
There are two ways to get the UI in the browser:
While I’ll want (1) eventually, and have some ideas about that, this post is about running everything in the browser, using Wasm.
I know that this is just scratching the surface Continue reading
If you start two threads, bound to run on exactly the same core, and one is SCHED_IDLE, why does it