{{htmlmetatags>metatag-robots=() metatag-title=(Define a protothread | Multithreading on retrocomputers) metatag-keywords=(Multithreading,Commodore 64,Commodore VIC20,Atari,Commodore128,MIDRES Library,6502,6510) metatag-description=(How to implement fast and efficient multithreading on computers with limited resources.) metatag-media-og:image=(:mt6502.png) metatag-og:title=(Define a protothread | Multithreading on retrocomputers) metatag-og:description=(How to implement fast and efficient multithreading on computers with limited resources.) }} ====== Multithreading on retrocomputers ====== ===== HOW TO DEFINE A PROTOTHREAD ===== The main advantage of protothreads over ordinary threads is that **they are really lightweight**: all protothreads run on the same stack, and the context switch coincides with the "rewind" of the stack. It follows that defining a protothread has the same complexity as defining a function C, to which a "prologue" and an "epilogue" must be added. This is done with the ''MR_PT_THREAD'' annotation, followed by the ''MR_PTI_BEGIN'' and finalized by ''MR_PTI_END'' annotation. MR_PT_THREAD(function) { MR_PTI_BEGIN(); // ... logic ... MR_PTI_YIELD(); // ... logic ... MR_PTI_END(); } The absence of the stack is an advantage in systems with strict memory constraints, that is, those in which a stack for a thread could use a large part of the available memory. However, with protothreads, this does not happen. A protothread requires only two bytes of memory to function and this space is reserved by allocating at least one variable of the type ''mr_protothread'': mr_protothread functionThread; As you can see, the ''MR_PTI_YIELD'' function is called at least once in the function. This call is necessary because, as we have anticipated, **they are cooperative and not preventive threads**: that is, there is the need for the programmer to indicate the best point where the execution can be blocked, and from which to resume. To start the threads it is sufficient to call (continuously) the function with the following syntax: while(1) { function(&functionThread); } Note how it is possible to execute ''N'' protothreads with the same code, allocating ''N'' variables of type ''mr_protothread'' and recalling, in sequence, each of them: mr_protothread functionThread1; mr_protothread functionThread2; ... mr_protothread functionThreadN; ... while(1) { function(&functionThread1); function(&functionThread2); ... function(&functionThreadN); } Move to [[:mt6502:coordinate|COORDINATE THE PROTOTHREADS]].