Protothreads is basically a "automatically generated" state-machine under the hood. Don't make them too large.. jumping back into context gets slower and slower as the states count grow. In PT that are all statements that can yield; because a yield also needs the ability to re-start from there.
You're also limited to PT statements only in 1 function. Because it's a switch-case underneath, it cannot span multiple functions or files. That makes writing true multi-tasking code impossible.
But it's probably the most functional option out there.
A true preemptive scheduler on 8-bit PICs is not practical. As mentoined in the MicroChip post.. the compiler will re-use the same memory locations depending on the call tree. This makes functions non-reentrant and thus not thread-safe.
The FN-options is unsustainable:
XC8 v1.35 changelog
FN-type directives All FN-type directives are no longer supported and should not be used. Such directive include: FNBREAK, FNSIZE, FNROOT etc. The FNCALL and FNROOT directives are still issued by the compiler, but it is recommended that these not be used in handwritten assembly code.