A
Adam Dunkels
dunkels.com · Personal blog · on HN since 2013
Adam Dunkels, an embedded systems researcher and creator of Contiki OS, writes about protothreads and tiny TCP/IP stacks in C.
What HN saysCommenters treat Protothreads as an embedded classic and call it simple and beautiful, linking its expansion page to explain the switch/case trick.
43HN people shared it
35linked it in comments
23stories submitted
527story points
5 months agolast shared
2013people per year2026
Most-shared posts
- 1ProtoThreads: Lightweight, Stackless Threads in C20 people · 216 points · first shared 2013 · 44 comments on HN
- 2Expansion10 people · first shared 2014
- 3Protothreads: Lightweight Stackless Threads in C3 people · 163 points · first shared 2013 · 42 comments on HN
- 4Miniweb – TCP/IP stack and web server in 30 bytes of RAM3 people · 4 points · first shared 2013 · discussion on HN
- 5Toothpaste Null-Terminator2 people · 96 points · first shared 2022 · 76 comments on HN
- 6Software2 people · first shared 2021
- 7Twip2 people · first shared 2021
- 8Stress-Testing 100 Bluetooth Beacons (So the Team Can Sleep Well at Night)1 people · 28 points · first shared 2025 · 13 comments on HN
- 9A Simple Way to Pitch Ideas1 people · 3 points · first shared 2023 · discussion on HN
- 10How to Use Git diff with an sqlite3 Database1 people · 3 points · first shared 2024 · discussion on HN
- 11How Fast Does Claude, Acting as a User Space IP Stack, Respond to Pings?1 people · 2 points · first shared 2026 · discussion on HN
- 126502 Emulator Runs 1 Instruction/S (Written in Markdown, Running in an LLM)1 people · 2 points · first shared 2026 · 1 comments on HN
- 13Can We Vibe Code a Smart Home Device with Matter?1 people · 2 points · first shared 2026 · discussion on HN
- 14How to run a city-wide wireless network from a drawer (2022)1 people · 2 points · first shared 2023 · discussion on HN
- 15A Basic Interpreter in Markdown, Running "Natively" in Claude Code1 people · 1 points · first shared 2026 · discussion on HN
What HN people wrote when they linked it
azubinski · 2023-07-19
It's different and very old story.
Protothreads are classic now:
https://dunkels.com/adam/pt/index.html
Contiki OS is also a piece of embedded development classic:
https://en.wikipedia.org/wiki/Contiki
In general, it's more about syntax than semantics.
Semantics is generally difficult and rarely changes.
j1elo · 2020-05-25
Don't miss out on the brilliant link at the bottom - Adam Dunkels' Protothreads - Lightweight, Stackless Threads in C also uses nested switch/case statements [1].
I learned about the theory with it, and used his library to implement cooperative multitasking on a bare metal embedded AVR C project. I wrote a task manager and dispatcher based on Protothreads, and that effort was what later made it simple for me to understand the JS async/await paradigm that would appear under my radar a couple years later.
EDIT to add that I think the concepts might still apply, since these days I've seen things like stackless async coroutines discussed for Rust... didn't study those in detail yet, but I wouldn't be surprised if the basic concepts are the same.
[1]: Current website: http://dunkels.com/adam/pt/
snops · 2020-04-07
You can use Protothreads[1] for this which work on anything that runs C, as they are just using setjmp/longjmp.
I would recommend FreeRTOS instead, as it has proper prempetive scheduling, context switching and wide debugger support. It's actually only 4 files[2] so not very heavyweight in either memory or stuff to learn, and has decent abstractions for cross thread communication (queues etc). Then you can write continuous code and use preemption, rather than have to code everything as a state machine and co-operatively schedule, which is painful sometimes.
[1] http://dunkels.com/adam/pt/
[2] https://www.freertos.org/Creating-a-new-FreeRTOS-project.html
jlundberg · 2019-05-16
The following page describes the implementation details: http://dunkels.com/adam/pt/expansion.html
josephg · 2017-02-03
Whoa, PT is fantastic.
A full explanation of how it works is here: http://dunkels.com/adam/pt/expansion.html
Its actually a really simple and beautiful. I worry that we give up a lot of this sort of flow expressiveness in more modern languages like Rust.
rdtsc · 2013-10-16
I got to about 500K processes on Erlang's VM on an i7 with lots of memory.
These people people got up to 2M concurrent TCP connections
http://blog.whatsapp.com/index.php/2012/01/1-million-is-so-2011/
And on top of it, it is using isolated heaps. That is beautiful I think. Completely concurrent GC is beautiful.
I know Erlang syntax is not to for everyone's taste (I do like it though). There is also Elixir (http://elixir-lang.org/). But the underlying BEAM VM is an awesome piece of technology.
> The thought was to have a billion threads on a SPARCStation 10
There are some green-thread C libraries I've been playing with, like Protothreads ( http://dunkels.com/adam/pt/index.html ) and libconcurrency ( https://code.google.com/p/libconcurrency/ ) I think they use setjump/longjump trick. Some use setcontext()/getcontext() POSIX call.
I still like Erlang VM best.
vanderZwan · 2025-07-14
This is Céu[0] erasure! ... I'm joking, I'm joking, although I do think it deserves a mention.
Seriously though, neat library! It took me a moment to realize that everything with a pa_ prefix is a macro, for the dumb reason of being used to only see those in ALL_CAPS. Not saying you can't use lower-case macros but I think a short sentence mentioning it before the demo code, and with a "see the protothread under the hood page[1] for an explanation of how it generally works" would help a lot with demystifying the code for people unfamiliar with the concepts involved.
[0] https://ceu-lang.github.io/
[1] https://dunkels.com/adam/pt/expansion.html
jacobmarble · 2024-12-19
I've been using protothreads on the RP2040 (Pico MCU) for task management.
https://dunkels.com/adam/pt/
The extensions available from Hunter Adams at Cornell are also very useful. In particular, PT_YIELD_INTERVAL() has been very useful for me.
https://people.ece.cornell.edu/land/courses/ece4760/RP2040/C_SDK_proto…
sargstuff · 2024-10-21
?? Duff's Device[0] theme song??
10b integers get pushed into an array. Does one need an unfold operation to C the union of (&*p) bits get "twidded n by n, ..." and 'ants go marching n x n' [1].
Couldn't find an appropriate utf-32 glyph for the base case.
Does the 'BOOM' happen at 0, NULL or NILL?
------
Limited HN ability to Hollerith when there's to much Babbage[2], (aka insufficient HN article space), for Simon/Garfunkel electric glow wall for the perl camel example.
------
[0]: duff's device : https://en.wikipedia.org/wiki/Duff%27s_device proto threads : https://dunkels.com/adam/pt/ coroutines : http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
[1] : file:///home/surf/Downloads/counting-and-math-rhymes-002-the-ants-go-marching.pdf
[2] : https://engines.egr.uh.edu/episode/1145
throwawayabcdef · 2024-09-06
see also uip and contiki as well as the other creations from Mr. Dunkles:
https://dunkels.com/adam/software.html
crabmusket · 2024-02-26
I was so sure this was about protothreads til I remembered its name. https://dunkels.com/adam/pt/
jamesmunns · 2023-09-11
From a net-effect standpoint, Rust's implementation of async/await is fairly similar to protothreads, which were used even on smaller AVR and MSP430 targets where rtos threads weren't practical.
That being said, protothreads were implemented using wildly cursed C macros, and offered none of the safety guardrails that Rust has, nor the ergonomics, and had some insane constraints, like "you can't use local variables at all, only statics" because like rust, they were stackless coroutines that meant you would have no control of the stack across await points.
If you were VERY CAREFUL, you could get the same lightweight concurrency with almost the same fundamental model. Woe be on you if you ever had to debug though.
edit - here's a look at how protothreads were expanded: https://dunkels.com/adam/pt/expansion.html
riedel · 2023-09-02
The IoT OS contiki made heavy use of protothreads, which are also Duff's device style coroutines [0]
[0] https://dunkels.com/adam/pt/examples.html
benhoyt · 2023-07-13
This is a fascinating concept that I've written about before: "C#’s async/await compared to protothreads in C++". [1] Both async/await in C# and protothreads [2] in C unroll control flow to a state machine. In C, this is done using some simple but crazy macros using the fact that you can interleave switch statements with other control flow (ala Duff's Device [3]).
Many years ago I ported Adam Dunkel's protothreads library to C++ [4]. You can use C protothreads in C++ directly, of course, but it's a bit nicer to use classes.
[1] https://blog.brush.co.nz/2012/11/async-await-protothreads-cpp/
[2] http://dunkels.com/adam/pt/
[3] https://en.wikipedia.org/wiki/Duff%27s_device
[4] https://github.com/benhoyt/protothreads-cpp/
samsquire · 2023-03-13
Thanks for this.
There is a really good blog post to understand coroutines from an assembly perspective here:
https://blog.dziban.net/coroutines/
I ported the intel assembly syntax in that blog post to at&t syntax and assembled it with GNU Assembler
https://github.com/samsquire/assembly as coroutines.S
there is also protothreads and Tina
http://dunkels.com/adam/pt/
https://github.com/slembcke/Tina
zserge · 2023-02-01
The wiki page says it all, but I'll highlight - Contiki has been written by Adam Dunkels, the one who invented Protothreads (coroutines using Duff's Device), uIP, lwIP and a TCP stack that fits into a single tweet - http://dunkels.com/adam/twip.html
butterisgood · 2021-11-19
Duff's device has been used for more than loop unrolling though.
https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
which inspired:
http://dunkels.com/adam/pt/
And that stuff is just neat!
rramadass · 2021-06-28
Take a look at Adam Dunkels' lwIP and uIP - http://dunkels.com/adam/software.html.
Also Jeremy Bentham's TCP/IP Lean: Web Servers for Embedded Systems is pretty good.
felixr · 2020-05-24
Another interesting approach to lightweight cooperative threading is Protothreads [1][2]. Those are however stackless and make use of duff's device for the implementation; rather, than setjmp/longjmp.
[1] http://dunkels.com/adam/pt/
[2] https://en.wikipedia.org/wiki/Protothread
kitd · 2019-09-22
As explained here [1], it uses a variation of Duff's device. So the claim that Protothreads were invented by Adam Dunkels with support from Oliver Schmidt is slightly misleading IMHO.
But fair play for turning it into a working library.
[1] http://dunkels.com/adam/pt/expansion.html
saagarjha · 2019-05-16
These seem to work with some clever (ab)use of switch statements: http://dunkels.com/adam/pt/expansion.html
dpwm · 2019-05-11
You may be in for a treat if you haven't already come across protothreads [0].
They provide a form of stack-less, co-operative multi-threading and are aimed at microcontrollers.
I came across them by chance, and have used them on an ESP8266 – it's really made everything feel much more clear and far less confusing.
You do need to wrap your head around the trick, but that really shouldn't take long. You also need to put any state that you expect to be preserved between calls of the function into something more persistent – just like with state machines. The examples all use static variables, but I am happier using a struct pointer to maintain state.
[0] http://dunkels.com/adam/pt/
VygmraMGVl · 2019-02-07
Protothreads is a library implementation of this trick. In fact, the protothreads creator even references the linked site in their explanation of protothreads (very last paragraph) [1].
[1] http://dunkels.com/adam/pt/expansion.html
mcwoods · 2019-02-07
Isn't this just an application of a protothread[1]?
There are implementations that use the GCC goto and label pointer, which then avoid the need for a switch statement.
[1] http://dunkels.com/adam/pt/
dimatura · 2018-10-29
Yes, it's basically the idea in Duff's device. Protothreads (http://dunkels.com/adam/pt/) uses a pretty similar trick.
buserror · 2018-01-08
Personally I no longer use pure state machines, as they can become beasts and end up being a royal pain to maintain.
Instead, I use 'duff devices' variations of it (in C) which breaks down the machine into code that looks 'linear' enough, but is in fact, a state machine without the drawbacks.
I've implemented quite a few protocol stacks using that 'trick' and it's still very nice to read/maintain -- the good thing is that it roughtly looks like a coroutine/thread, without any runtime requirements, so will work just fine on embedded systems as well. Same as coroutine/state machines, don't make your 'states' too 'long' or CPU intensive, you'll have the same consequences.
There's an implementation floating around called 'protothreads' [0], but you can really do pretty much the same with a handful of macros.
[0]: http://dunkels.com/adam/pt/
arianvanp · 2017-02-02
https://github.com/arianvp/MidiProject/blob/master/MidiProject.ino
I use duffs device to concurrently read and debounce multiple inputs in my old dj midi controller
http://dunkels.com/adam/pt/expansion.html
huntergoldstein · 2017-02-02
To add onto this:
- http://dunkels.com/adam/pt/
Even though it is an abuse, these sorts of libraries are fascinating to me: making use of language features in unexpected (most likely unintended) ways.
nkurz · 2014-06-06
Thank you, that additional information is helpful: http://dunkels.com/adam/dunkels06protothreads.pdf
I presume you are the same Muneeb Ali listed as co-author? The website mentioned in your profile seems to be down.
muneeb · 2014-06-06
The SenSys'06 paper has all the details:
http://dunkels.com/adam/pt/publications.html
The context for a lot of "wireless sensor networks" discussion in the paper is that Adam's research group was primarily focusing on sensor networks at the time.