Live data from Hacker News

Implementing simple cooperative threads in C

brennan.io

61–70 of 88 posts

Re: Implementing simple cooperative threads in C

#61
post #26

Earlier quoted context omitted.

Are there exceptions in C? If I’m interviewing someone for a programming job and I see goto in there C code... they better have an amazing reason or they won’t be getting the job. Harsh, but it’s reality of how few people are suited for embedded programming.

I spend a lot of time dicking with embedded C code. I think using goto is reasonable some cases. The classic case is to short circuit a block of code when there is an error of some sort. function(){ // early returns here. // stuff // more stuff if(oops_err){ goto some_error; } // yet more stuff // normal exit return 0; // bad exit some_error: // clean up return oops_err; } The above is fine, you avoid a convoluted ex…

Not only is it fine, I think it's easier to reason about the control flow with this code than with languages that support exceptions like C++.

Re: Implementing simple cooperative threads in C

#62

I find the contrast between the text color and background color to be too low for comfortable reading.

Hey, I hear you and I don't want reading my site to be uncomfortable! My site uses the solarized light colorscheme [1], which I chose because I use the solarized schemes for my text editors. I think they are lower contrast to lend themselves to long editing sessions without being jarring on the eyes, but maybe that's not ideal for webpages? In any case, if I added a small JS powered button to switch into a higher con…

Hi Stephen, I appreciate your willingness to accept feedback. I'm flattered that you would add a button to make my reading experience better, but I think a website should be readable by default, so the button would just be a workaround from my point of view.

I would also like to respectfully challenge your assumption that lower contrast text is less jarring for the eyes for long reading sessions. If it were so, they'd be printing books in light gray color, wouldn't they?

Looking at the Solarized theme, my guess is it's the yellow-ish background that removes the strain on the eyes, as #fff is typically very bright. Since most people aren't focusing on the background when reading, it doesn't cause the eyes to focus more than usual. However, changing the color of the text is a different matter because that's what the eyes are focusing on, and making the text lighter causes it to be harder to read.

That's easy to verify: on the opacity scale of 0.0 to 1.0, where 1.0 is fully opaque, #000 (full black) at 0.1 opacity (almost transparent) is harder to focus on than 0.9 opacity (almost fully opaque). The only reason why some (most?) designers wouldn't be caught dead using #000 at 1.0 opacity for text, despite it being the most readable text color, is because very few things in the real world are at #000 or #fff, so the general advice is to use some shade that's close to it to make the webpage look more natural.

They're essentially trading off readability for aesthetics, and my original comment was that you traded off too much readability for aesthetics, in my opinion.

That said, if I were you, I wouldn't trust my opinion or anyone else's really. Seeing as you made it to HN, you could run an A/B test to see if serving a higher contrast page causes people to spend more time on that page on average, presumably because they're spending more time reading the content, instead of just skimming it like me. That way you'd be making informed changes based on data, not people's subjective experiences (including mine and yours).

Just for fun, I fiddled with the text color on your webpage and I'd say anything lighter than #555 for the body and #666 for the h2 seems too washed out (with the same background color).

Finally, I do want to note that the content is excellent. Happy Memorial Day!

Re: Implementing simple cooperative threads in C

#64
post #59

Earlier quoted context omitted.

> FWIW, the original implementation of Java (when it was known as Oak) used this trick to manage user level threading. There was also a some code to do the stack swap since you were in a virtual machine anyway, that stuff was all there to be adjusted. I never knew Java did this. I figured most "interpreted" languages (via direct interpreters or bytecode) would be trivial to implement any kind of threads (even pre-emp…

> I figured most "interpreted" languages would be trivial to implement any kind of threads, because at any point the interpreter could decide to save the state of one language thread and switch to another, without bothering the interpreter's own stack. Some language interpreters keep the "virtual" stack and the C stack separate like this, including current versions of Lua. As you suggest, this allows Lua to support c…

I was curious about these changes to Lua 5.4, so I had a look. When you create a Lua coroutine that allocates 200 Lua stack frames and then yields across them, the first longjmp crosses 200ish C stack frames. When you later resume, all those C stack frames are gone, but there wasn't any important state in them! Lua just calls luaV_execute in a loop[0]. (Trampolining?) So at that point, for that coroutine, the lower 200ish Lua stack frames do not have corresponding C stack frames, but any Lua subroutines you then call will have corresponding C stack frames.

[0] https://github.com/lua/lua/blob/9b7987a9d1471ba94764286b28e0...

Re: Implementing simple cooperative threads in C

#65
post #9

FWIW, the original implementation of Java (when it was known as Oak) used this trick to manage user level threading. There was also a some code to do the stack swap since you were in a virtual machine anyway, that stuff was all there to be adjusted. Random meta note brenns10, the idiom for giving up the processor is 'yield' (rather than 'relinquish') it is common in cooperative systems. That said, the code in Java th…

> FWIW, the original implementation of Java (when it was known as Oak) used this trick to manage user level threading. There was also a some code to do the stack swap since you were in a virtual machine anyway, that stuff was all there to be adjusted. I never knew Java did this. I figured most "interpreted" languages (via direct interpreters or bytecode) would be trivial to implement any kind of threads (even pre-emp…

Two observations about "unsafeness" of your threading system:

1. As a matter of paranoia I would likely write schedule() entirely in assembly -- it's a simple function and if you write it by hand you can be certain the compiler doesn't "cleverly" optimize something that will cause pain across the context switch.

2. Your 16K stacks are allocated straight out of the heap, which means stack under or overflows are going to stomp all over adjacent allocations (possibly other stacks), and be a pain to debug. You'll likely want to look at using mmap() and friends to allocate stacks with guard pages to catch this. You can also just range-check the SP when context switching (maybe as an optional debug build thing) which may catch things before a lot of damage is done.

Re: Implementing simple cooperative threads in C

#66

This style of coop multi-tasking was in Crash Team Racing on PS1 for a while. Unfortunately on a machine with only 2meg of ram it turned out to take too much memory and be too fragile. The stacks had to be small, add one printf for debugging and you'd overflow the stack. Eventually it was torn out.

I'm surprised you didn't pile on by making a printf which switches to the main stack, does the actual printf, and switches back.

Re: Implementing simple cooperative threads in C

#67

The main problems I've seen with cooperative threading (aka fibers) are threefold: 1. You need to decide how much stack space to allocate to a fiber beforehand. If you go over this limit, you will segfault. 2. Thread local storage doesnt exist anymore since you're potentially swapping between different kernel threads (and different fibers are using the same thread and will share storage). 3. Certain types of locks ca…

I think there's a fourth problem that's even more dire: what do you do about blocking?

A blocking call stalls the whole system. It doesn't in a non-cooperative threading environment. Various languages have "solved" this by not allowing you to use blocking calls and sometimes add syntactic sugar like async/await, but this sucks. The point of having threads is to use them like threads. At least Go gets this right.

Re: Implementing simple cooperative threads in C

#68

Earlier quoted context omitted.

> FWIW, the original implementation of Java (when it was known as Oak) used this trick to manage user level threading. There was also a some code to do the stack swap since you were in a virtual machine anyway, that stuff was all there to be adjusted. I never knew Java did this. I figured most "interpreted" languages (via direct interpreters or bytecode) would be trivial to implement any kind of threads (even pre-emp…

Two observations about "unsafeness" of your threading system: 1. As a matter of paranoia I would likely write schedule() entirely in assembly -- it's a simple function and if you write it by hand you can be certain the compiler doesn't "cleverly" optimize something that will cause pain across the context switch. 2. Your 16K stacks are allocated straight out of the heap, which means stack under or overflows are going…

It's a bit difficult to get guard pages working together with 2MB pages, though.

And in todays age of swap-less systems, you typically don't want to pollute the TLB with loads of 4k pages.

Re: Implementing simple cooperative threads in C

#69
Before diving into something complex as e.g. FreeRTOS, can anyone recommend production ready code preferably in C that shows off preemptive task scheduling using an external timer including features like priorities and task delays?

The post is a good explanation regarding stack handling.

Post reply on HN