Recent submissions

Comment · 1 year ago
Fun stuff. A long time ago, I did something similar by reverse-engineering the Adobe Illustrator format (technically a PostScript macro dialect.) We generated files that could then get touched up by artists.

Everything but PostScript itself was closed-source. We could have definitely used 5086 pages of documentation. Even 2 would have been nice. Young whippersnappers don't know how good they have it...

Comment · 1 year ago
> How do I allocate memory for addressing it with FS/GS?

Allocate the variable normally, then compute the offset in one thread (e.g. offset = uintptr_t(&variable) - get_fs()), then access it by adding the offset to FS in any thread (e.g. (vartype *) (offset + get_fs())). The only difference from how it normally works is that you can manually force it to be inlined, sidestepping the codegen problems you described in your post. But if you can avoid those problems by not using constructors instead, that's definitely better.

I used "FS/GS" because GS is used instead of FS on some systems for the same purpose.

The shared library-specific issues are one of the reasons I was suggesting maybe looking into hashing, e.g. perhaps as a fallback solution when the TLS approach fails.

Comment · 1 year ago
To the author: If you have a specific situation that the codegen is failing to optimize well (e.g. the ctor cases that you ran into) you can store the offset to your variable in a non-TLS global, then manually add the FS/GS to it. Use inline asm if you need to bypass any init checks.

An alternative that might be worth looking into is just hashing the FS/GS into a table index. It will be slower than the well-optimized case, but it will let you opt out of the TLS allocation process altogether. This might be a good thing in some cases for a low-level facility like a function tracer.

Comment · 1 year ago
I've switched the default to DDG when they started requiring JS. I run with JS enabled, but the fact that it's now required screams fingerprinting and other shenanigans. 90% of my searches are trivial, so DDG is now a better default fit.

Hey Google, here's a modest proposal: nerdsearch.google.com. Return the same results, but in a spartan HN-like format, with no JS or fingerprinting or other "did be evil" things. Non-techies will never find out about it if you don't advertise it. You can still fingerprint people who don't know or care about it.

> Gmail? YouTube? Gemini? Chrome? Android

Most of these are best-in-class, so I think I detect some bias in the question.

Comment · 1 year ago
I don't really disagree with what you wrote. To expand upon my argument, the issues you mention can also be self-policed, or maybe enforced with higher safety levels of the presumptive -W20 switch:

- No reference variables in user code (reference parameters are OK.)

- Any classes that hold reference member variables can only be instantiated on the stack. The objects the references refer to must either be stack objects or reference parameters to the instantiating function.

- For durable links to sub-objects, use handles (tuples of std::shared_ptr to the main object plus a sub-object link or identifier.)

- Alternatively, require externally-accessible sub-objects to be held in shared_ptr's by the main object. They can then have superset lifetimes when needed.

I'll stick to the memory safety topic, but similar solutions exist for some of the other topics you mention, e.g. by avoiding std::optional.

Comment · 1 year ago
Comment · 1 year ago
Halloween came early this year. Pretty ghoulish too.
Comment · 1 year ago
> Who says you can’t make a library that does both?

Of course you can. I just meant that the linked article didn't.

> On LR/SC: to any atomics experts listening, isn’t it technically “obstruction-free” (as per the Wikipedia definitions at least) rather than lock-free?

The better criterion IMO is loop-free, which makes it a little easier to understand. Consider the following spin-locking code (with overabundant memory barriers):

   do { p = *a; } while (p == 0x1 || !atomic_compare_and_swap(p, 0x1, a));
   memory_barrier();
   // do stuff that looks at *p
   q->next = p;
   memory_barrier();
   atomic_store(q, a);
Here's the equivalent LL/SC version:

   do {
     p = ll(a);
     memory_barrier();
     // do stuff that looks at *p
     q->next = p;
     memory_barrier();
   } while (!sc(q, a));
The pointer-tagging version is also obviously not loop-free. Which is faster, in which cases, and by how much?

The oversimplified answer is that LL/SC is probably slightly faster than spin-locking on most platforms and cases, but pointer-tagging might not be.

Comment · 1 year ago
> How are you counting "advantages", and how did you come up with the requisite number being 4 or 5?

The vagueness was intentional. There is of course no homogeneous way of combining advantages into a cardinal measure. It's just a rhetorical device.

The point is that it falls short of the amount needed. Another, more subtle point is that I didn't count disadvantages. The argument applies even if you think Rust doesn't have any.

Comment · 1 year ago
Comment · 1 year ago
"Safety" is just an attack vector. AI has a few very motivated enemies with a lot to lose.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton