Comment by jart
5 years ago
We're pretty much on the same page. I'm not sure if I share your enthusiasm for clone(), but I think the canonical Linux interface is what's going to save us from the dark patterns we see in userspace. I think everyone should learn how to use raw system calls. Because the first thought that's going to cross their mind is "wow I thought my C library was doing all these things" and then they're going to want a C library that offers more value than putting a number in the eax register.
For example if you want to call fork() using asm() then on Linux it's simple:
int fork(void) {
int ax;
asm volatile("syscall" : "=a"(ax) : "0"(57) : "rcx", "r11", "memory", "cc");
if (ax > -4096) errno = -ax, ax = -1;
return ax;
}
But if you want to support XNU, FreeBSD, OpenBSD, FreeBSD, and NetBSD too, it gets a little trickier:
int fork(void) {
char cf;
int ax, dx;
ax = IsLinux() ? 57 : 2;
if (IsXnu()) ax |= 0x2000000;
asm volatile("clc\n\t"
"syscall"
: "+a"(ax), "=d"(dx), "=@ccc"(cf)
: "1"(0)
: "rcx", "r11", "memory", "cc");
if (cf) ax = -ax;
if (ax > -4096) errno = -ax, ax = -1;
if (ax != -1) ax &= dx - 1;
return ax;
}
Cosmopolitan abstracts stuff like that for you, but right now that's only if you're the kind of person who doesn't need threads. I imagine you are, since folks who do smart things with multiprocessing models like Go and Chromium usually don't want C libraries potentially stepping on their toes. Oh gosh threads. The day I figure out how to do those, will be day the whole world will want to use this thing. But I want people who use Cosmopolitan Libc to know what value it's providing them. I think the best way to do that is by raising awareness of the systems engineering fundamentals like this. Because that's something you're right to point out that the Linux community leadership has room for improvement on.
I remember simple use cases for clone() such as spawning child processes with just enough shared resources to execve(). I remember reading a lot of old emails from Torvalds about it, can't find them anymore.
I used to value portability but now I believe in using Linux everywhere and for everything. I like OpenBSD too but Linux is the stable one you can build anything on. What I wanted to eventually accomplish is a 100% freestanding Linux user space with no libraries at all. Maybe boot straight into the program I want to use, just like we can pass init=/usr/bin/bash in the kernel command line. How far could this go? Using nothing but system calls it's actually possible to get a framebuffer and use software renderering to draw some graphics. I'm guessing pretty far.
By starting from scratch like this it's possible to fix all the historical problems with our systems. For example, I think it's unacceptable when libraries keep global state. This can't be fixed without getting rid of libc and its buffers and caches and errno. Removing this cruft would actually simplify a threads implementation. And then there's completely insane stuff like .init and .fini sections:
https://blogs.oracle.com/solaris/init-and-fini-processing-wh...
A similar statically-linked user space project I found years ago:
https://github.com/arsv/minibase
That seems kind of contradictory. Your biases are tuned towards what works for big codebases but you're taking a first principles approach. A simplified threads implementation is called Java. Plus it gives you cool classes like Phaser. Threads will always be a horror show with C/C++. There's a reason why Linux is the only kernel that implements clone(). It's controversial.