// -*- Mode: CFA -*- // // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // threads -- // // Author : Thierry Delisle // Created On : Mon Nov 28 12:27:26 2016 // Last Modified By : Thierry Delisle // Last Modified On : Mon Nov 28 12:27:26 2016 // Update Count : 0 // #ifndef __THREADS_H__ #define __THREADS_H__ #include "assert" // #include "invoke.h" //----------------------------------------------------------------------------- // Coroutine trait // Anything that implements this trait can be resumed. // Anything that is resumed is a coroutine. trait is_coroutine(dtype T) { void co_main(T* this); coroutine* get_coroutine(T* this); }; //----------------------------------------------------------------------------- // Ctors and dtors void ?{}(coStack_t* this); void ?{}(coroutine* this); void ^?{}(coStack_t* this); void ^?{}(coroutine* this); //----------------------------------------------------------------------------- // Public coroutine API static inline void suspend(); forall(dtype T | is_coroutine(T)) static inline void resume(T* cor); forall(dtype T | is_coroutine(T)) void prime(T* cor); //----------------------------------------------------------------------------- // PRIVATE exposed because of inline // Start coroutine routines extern "C" { forall(dtype T | is_coroutine(T)) void CtxInvokeCoroutine(T* this); forall(dtype T | is_coroutine(T)) void CtxStart(T* this, void (*invoke)(T*)); } // Get current coroutine extern coroutine* current_coroutine; //PRIVATE, never use directly static inline coroutine* this_coroutine(void) { return current_coroutine; } // Private wrappers for context switch and stack creation extern void corCxtSw(coroutine* src, coroutine* dst); extern void create_stack( coStack_t* this, unsigned int storageSize ); // Suspend implementation inlined for performance static inline void suspend() { coroutine* src = this_coroutine(); // optimization assertf( src->last != 0, "Attempt to suspend coroutine %.256s (%p) that has never been resumed.\n" "Possible cause is a suspend executed in a member called by a coroutine user rather than by the coroutine main.", src->name, src ); assertf( src->last->notHalted, "Attempt by coroutine %.256s (%p) to suspend back to terminated coroutine %.256s (%p).\n" "Possible cause is terminated coroutine's main routine has already returned.", src->name, src, src->last->name, src->last ); corCxtSw( src, src->last ); } // Resume implementation inlined for performance forall(dtype T | is_coroutine(T)) static inline void resume(T* cor) { coroutine* src = this_coroutine(); // optimization coroutine* dst = get_coroutine(cor); if( unlikely(!dst->stack.base) ) { create_stack(&dst->stack, dst->stack.size); CtxStart(cor, CtxInvokeCoroutine); } // not resuming self ? if ( src != dst ) { assertf( dst->notHalted , "Attempt by coroutine %.256s (%p) to resume terminated coroutine %.256s (%p).\n" "Possible cause is terminated coroutine's main routine has already returned.", src->name, src, dst->name, dst ); // set last resumer dst->last = src; } // if // always done for performance testing corCxtSw( src, dst ); } #endif //__THREADS_H__ // Local Variables: // // mode: c // // tab-width: 4 // // End: //