- Timestamp:
- Mar 21, 2017, 10:07:52 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- cb91437
- Parents:
- 829c907 (diff), a53e10a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Concurrency/Keywords.cc
r829c907 r87d13cd 17 17 #include "Concurrency/Keywords.h" 18 18 19 #include "SymTab/AddVisit.h" 19 20 #include "SynTree/Declaration.h" 20 21 #include "SynTree/Expression.h" … … 29 30 namespace { 30 31 const std::list<Label> noLabels; 32 const std::list< Attribute * > noAttributes; 31 33 Type::StorageClasses noStorage; 32 34 Type::Qualifiers noQualifiers; … … 63 65 // void main( MyCoroutine * this ); 64 66 // 65 class CoroutineKeyword final : public Mutator { 67 class CoroutineKeyword final : public Visitor { 68 template< typename Visitor > 69 friend void SymTab::acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor ); 66 70 public: 67 71 68 static void implement( std::list< Declaration * > & translationUnit ) {} 72 using Visitor::visit; 73 virtual void visit( StructDecl * decl ) override final; 74 75 void handle( StructDecl * ); 76 Declaration * addField( StructDecl * ); 77 void addRoutines( StructDecl *, Declaration * ); 78 79 static void implement( std::list< Declaration * > & translationUnit ) { 80 CoroutineKeyword impl; 81 SymTab::acceptAndAdd( translationUnit, impl ); 82 } 83 84 private: 85 std::list< Declaration * > declsToAdd, declsToAddAfter; 86 StructDecl* coroutine_decl = nullptr; 69 87 }; 70 88 … … 97 115 98 116 using Visitor::visit; 99 virtual void visit( FunctionDecl * functionDecl ) override final;100 virtual void visit( StructDecl * functionDecl ) override final;117 virtual void visit( FunctionDecl * decl ) override final; 118 virtual void visit( StructDecl * decl ) override final; 101 119 102 120 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* ); … … 111 129 private: 112 130 StructDecl* monitor_decl = nullptr; 131 StructDecl* guard_decl = nullptr; 113 132 }; 114 133 … … 124 143 125 144 //============================================================================================= 145 // Coroutine keyword implementation 146 //============================================================================================= 147 void CoroutineKeyword::visit(StructDecl * decl) { 148 if( decl->get_name() == "coroutine_desc" ) { 149 assert( !coroutine_decl ); 150 coroutine_decl = decl; 151 } 152 else if ( decl->is_coroutine() ) { 153 handle( decl ); 154 } 155 156 } 157 158 void CoroutineKeyword::handle( StructDecl * decl ) { 159 if( ! decl->has_body() ) return; 160 161 if( !coroutine_decl ) throw SemanticError( "coroutine keyword requires coroutines to be in scope, add #include <coroutine>", decl ); 162 163 Declaration * field = addField( decl ); 164 addRoutines( decl, field ); 165 } 166 167 Declaration * CoroutineKeyword::addField( StructDecl * decl ) { 168 Declaration * cor = new ObjectDecl( 169 "__cor", 170 noStorage, 171 LinkageSpec::Cforall, 172 nullptr, 173 new StructInstType( 174 noQualifiers, 175 coroutine_decl 176 ), 177 nullptr 178 ); 179 180 decl->get_members().push_back( cor ); 181 182 return cor; 183 } 184 185 void CoroutineKeyword::addRoutines( StructDecl * decl, Declaration * field ) { 186 FunctionType * type = new FunctionType( noQualifiers, false ); 187 type->get_parameters().push_back( 188 new ObjectDecl( 189 "this", 190 noStorage, 191 LinkageSpec::Cforall, 192 nullptr, 193 new PointerType( 194 noQualifiers, 195 new StructInstType( 196 noQualifiers, 197 decl 198 ) 199 ), 200 nullptr 201 ) 202 ); 203 type->get_returnVals().push_back( 204 new ObjectDecl( 205 "ret", 206 noStorage, 207 LinkageSpec::Cforall, 208 nullptr, 209 new PointerType( 210 noQualifiers, 211 new StructInstType( 212 noQualifiers, 213 coroutine_decl 214 ) 215 ), 216 nullptr 217 ) 218 ); 219 220 CompoundStmt * statement = new CompoundStmt( noLabels ); 221 statement->push_back( 222 new ReturnStmt( 223 noLabels, 224 new AddressExpr( 225 new UntypedMemberExpr( 226 new NameExpr( "__cor" ), 227 new UntypedExpr( 228 new NameExpr( "*?" ), 229 { new NameExpr( "this" ) } 230 ) 231 ) 232 ) 233 ) 234 ); 235 236 FunctionDecl * get_decl = new FunctionDecl( 237 "get_coroutine", 238 Type::Static, 239 LinkageSpec::Cforall, 240 type, 241 statement, 242 noAttributes, 243 Type::Inline 244 ); 245 246 declsToAddAfter.push_back( get_decl ); 247 248 get_decl->fixUniqueId(); 249 } 250 251 252 //============================================================================================= 126 253 // Mutex keyword implementation 127 254 //============================================================================================= … … 137 264 if( ! body ) return; 138 265 139 assert(monitor_decl); 266 if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl ); 267 if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl ); 268 140 269 addStatments( body, mutexArgs ); 141 270 } … … 146 275 monitor_decl = decl; 147 276 } 277 else if( decl->get_name() == "monitor_guard_t" ) { 278 assert( !guard_decl ); 279 guard_decl = decl; 280 } 148 281 } 149 282 … … 175 308 176 309 //Make sure that typed isn't mutex 177 if( !base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );310 if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg ); 178 311 } 179 312 180 313 void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) { 181 182 314 ObjectDecl * monitors = new ObjectDecl( 183 315 "__monitors", … … 199 331 ), 200 332 new ListInit( 201 map_range < std::list<Initializer*> > ( args, [](DeclarationWithType * var ){ 333 map_range < std::list<Initializer*> > ( args, [this](DeclarationWithType * var ){ 334 Type * type = var->get_type()->clone(); 335 type->set_mutex( false ); 202 336 return new SingleInit( new UntypedExpr( 203 337 new NameExpr( "get_monitor" ), 204 { new VariableExpr( var) }338 { new CastExpr( new VariableExpr( var ), type ) } 205 339 ) ); 206 340 }) … … 218 352 new StructInstType( 219 353 noQualifiers, 220 "monitor_guard_t"354 guard_decl 221 355 ), 222 356 new ListInit( … … 224 358 new SingleInit( new VariableExpr( monitors ) ), 225 359 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ) 226 } 360 }, 361 noDesignators, 362 true 227 363 ) 228 364 )) 229 365 ); 230 366 231 //monitor_desc * __monitors[] = { a, b};367 //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) }; 232 368 body->push_front( new DeclStmt( noLabels, monitors) ); 233 369 } -
src/InitTweak/FixInit.cc
r829c907 r87d13cd 534 534 } else { 535 535 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 536 unqExpr->set_object( new ObjectDecl( toString("_unq _expr_", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );536 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) ); 537 537 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 538 538 } … … 764 764 } 765 765 } else { 766 stmtsToAddAfter.push_back( ctor ); 766 ImplicitCtorDtorStmt * implicit = safe_dynamic_cast< ImplicitCtorDtorStmt * > ( ctor ); 767 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->get_callStmt() ); 768 ApplicationExpr * ctorCall = nullptr; 769 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->get_expr() )) && ctorCall->get_args().size() == 2 ) { 770 // clean up intrinsic copy constructor calls by making them into SingleInits 771 objDecl->set_init( new SingleInit( ctorCall->get_args().back() ) ); 772 ctorCall->get_args().pop_back(); 773 } else { 774 stmtsToAddAfter.push_back( ctor ); 775 objDecl->set_init( NULL ); 776 ctorInit->set_ctor( NULL ); 777 } 767 778 } // if 768 objDecl->set_init( NULL );769 ctorInit->set_ctor( NULL );770 779 } else if ( Initializer * init = ctorInit->get_init() ) { 771 780 objDecl->set_init( init ); -
src/Parser/ExpressionNode.cc
r829c907 r87d13cd 163 163 ConstantExpr *build_constantStr( const std::string & str ) { 164 164 // string should probably be a primitive type 165 ArrayType *at = new ArrayType( emptyQualifiers, new BasicType( emptyQualifiers, BasicType::Char ),165 ArrayType *at = new ArrayType( emptyQualifiers, new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), 166 166 new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::UnsignedInt ), 167 167 toString( str.size()+1-2 ) ) ), // +1 for '\0' and -2 for '"' -
src/Parser/lex.ll
r829c907 r87d13cd 202 202 __const__ { KEYWORD_RETURN(CONST); } // GCC 203 203 continue { KEYWORD_RETURN(CONTINUE); } 204 _Coroutine { KEYWORD_RETURN(COROUTINE); } // CFA204 coroutine { KEYWORD_RETURN(COROUTINE); } // CFA 205 205 default { KEYWORD_RETURN(DEFAULT); } 206 206 disable { KEYWORD_RETURN(DISABLE); } // CFA -
src/SynTree/Type.h
r829c907 r87d13cd 117 117 bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); } 118 118 bool operator<=( Qualifiers other ) const { 119 return is_const <= other.is_const && is_volatile <= other.is_volatile && 120 is_mutex >= other.is_mutex && is_atomic == other.is_atomic; 119 return is_const <= other.is_const //Any non-const converts to const without cost 120 && is_volatile <= other.is_volatile //Any non-volatile converts to volatile without cost 121 && is_mutex >= other.is_mutex //Any mutex converts to non-mutex without cost 122 && is_atomic == other.is_atomic; //No conversion from atomic to non atomic is free 121 123 } 122 124 bool operator<( Qualifiers other ) const { return *this != other && *this <= other; } … … 155 157 virtual Type * getComponent( unsigned i ) { assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i ); return this; } 156 158 159 /// return type without outer pointers and arrays 157 160 Type *stripDeclarator(); 158 161 -
src/Tuples/TupleExpansion.cc
r829c907 r87d13cd 194 194 } 195 195 BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool ); 196 ObjectDecl * finished = new ObjectDecl( toString( "_unq _expr_finished_", id), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ), new SingleInit( new ConstantExpr( Constant( boolType->clone(), "0" ) ), noDesignators ) );196 ObjectDecl * finished = new ObjectDecl( toString( "_unq", id, "_finished_" ), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ), new SingleInit( new ConstantExpr( Constant( boolType->clone(), "0" ) ), noDesignators ) ); 197 197 addDeclaration( finished ); 198 198 // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N)) … … 225 225 if ( ! typeMap.count( tupleSize ) ) { 226 226 // generate struct type to replace tuple type based on the number of components in the tuple 227 StructDecl * decl = new StructDecl( toString( "_tuple _type_", tupleSize) );227 StructDecl * decl = new StructDecl( toString( "_tuple", tupleSize, "_" ) ); 228 228 decl->set_body( true ); 229 229 for ( size_t i = 0; i < tupleSize; ++i ) { -
src/benchmark/CorCtxSwitch.c
r829c907 r87d13cd 24 24 25 25 struct GreatSuspender { 26 coroutine_desc c;26 coroutine_desc __cor; 27 27 }; 28 28 -
src/benchmark/bench.c
r829c907 r87d13cd 86 86 //======================================= 87 87 88 struct CoroutineDummy { coroutine_desc c; };88 struct CoroutineDummy { coroutine_desc __cor; }; 89 89 DECL_COROUTINE(CoroutineDummy); 90 90 void main(CoroutineDummy * this) {} … … 119 119 struct CoroutineResume { 120 120 int N; 121 coroutine_desc c;121 coroutine_desc __cor; 122 122 }; 123 123 … … 150 150 //======================================= 151 151 152 struct ThreadDummy { thread_desc t; };152 struct ThreadDummy { thread_desc __thrd; }; 153 153 DECL_THREAD(ThreadDummy); 154 154 void main(ThreadDummy * this) {} … … 180 180 int N; 181 181 long long result; 182 thread_desc t;182 thread_desc __thrd; 183 183 }; 184 184 -
src/benchmark/csv-data.c
r829c907 r87d13cd 26 26 27 27 struct GreatSuspender { 28 coroutine_desc c;28 coroutine_desc __cor; 29 29 }; 30 30 -
src/driver/Makefile.am
r829c907 r87d13cd 32 32 33 33 install-exec-hook: 34 @test -z "$(CFA_BINDIR)" || $(MKDIR_P) "$(CFA_BINDIR)" 34 35 @echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa '$(CFA_BINDIR)/$(CFA_NAME)'"; \ 35 36 $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa $(CFA_BINDIR)/$(CFA_NAME) || exit $$? -
src/driver/Makefile.in
r829c907 r87d13cd 530 530 531 531 install-exec-hook: 532 @test -z "$(CFA_BINDIR)" || $(MKDIR_P) "$(CFA_BINDIR)" 532 533 @echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa '$(CFA_BINDIR)/$(CFA_NAME)'"; \ 533 534 $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) cfa $(CFA_BINDIR)/$(CFA_NAME) || exit $$? -
src/examples/multicore.c
r829c907 r87d13cd 2 2 #include <thread> 3 3 4 struct MyThread { thread_desc t; };4 struct MyThread { thread_desc __thrd; }; 5 5 6 6 DECL_THREAD(MyThread); -
src/libcfa/concurrency/coroutine
r829c907 r87d13cd 30 30 }; 31 31 32 #define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X* this) { return &this-> c; } void main(X* this)32 #define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X* this) { return &this->__cor; } void main(X* this) 33 33 34 34 //----------------------------------------------------------------------------- -
src/libcfa/concurrency/invoke.c
r829c907 r87d13cd 29 29 30 30 extern void __suspend_internal(void); 31 extern void __ thread_signal_termination(struct thread_desc*);31 extern void __leave_monitor_desc( struct monitor_desc * this ); 32 32 33 33 void CtxInvokeCoroutine( … … 56 56 57 57 void CtxInvokeThread( 58 void (*dtor)(void *), 58 59 void (*main)(void *), 59 60 struct thread_desc *(*get_thread)(void *), … … 63 64 64 65 struct thread_desc* thrd = get_thread( this ); 65 struct coroutine_desc* cor = &thrd->c; 66 struct coroutine_desc* cor = &thrd->cor; 67 struct monitor_desc* mon = &thrd->mon; 66 68 cor->state = Active; 67 69 … … 69 71 main( this ); 70 72 71 __ thread_signal_termination(thrd);73 __leave_monitor_desc( mon ); 72 74 73 75 //Final suspend, should never return … … 91 93 struct FakeStack { 92 94 void *fixedRegisters[3]; // fixed registers ebx, edi, esi (popped on 1st uSwitch, values unimportant) 93 uint32_t mxcr; 94 uint16_t fcw;// X97 FPU control word (preserved across function calls)95 void *rturn; 95 uint32_t mxcr; // SSE Status and Control bits (control bits are preserved across function calls) 96 uint16_t fcw; // X97 FPU control word (preserved across function calls) 97 void *rturn; // where to go on return from uSwitch 96 98 void *dummyReturn; // fake return compiler would have pushed on call to uInvoke 97 99 void *argument[3]; // for 16-byte ABI, 16-byte alignment starts here … … 105 107 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->argument[0] = this; // argument to invoke 106 108 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->rturn = invoke; 109 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->mxcr = 0x1F80; //Vol. 2A 3-520 110 ((struct FakeStack *)(((struct machine_context_t *)stack->context)->SP))->fcw = 0x037F; //Vol. 1 8-7 107 111 108 112 #elif defined( __x86_64__ ) 109 113 110 114 struct FakeStack { 111 void *fixedRegisters[5]; 112 uint32_t mxcr; 113 uint16_t fcw; 114 void *rturn; 115 void *dummyReturn; 115 void *fixedRegisters[5]; // fixed registers rbx, r12, r13, r14, r15 116 uint32_t mxcr; // SSE Status and Control bits (control bits are preserved across function calls) 117 uint16_t fcw; // X97 FPU control word (preserved across function calls) 118 void *rturn; // where to go on return from uSwitch 119 void *dummyReturn; // NULL return address to provide proper alignment 116 120 }; 117 121 -
src/libcfa/concurrency/invoke.h
r829c907 r87d13cd 28 28 #define unlikely(x) __builtin_expect(!!(x), 0) 29 29 #define thread_local _Thread_local 30 #define SCHEDULER_CAPACITY 1031 30 32 31 struct spinlock { … … 39 38 }; 40 39 41 struct signal_once {42 volatile bool condition;43 struct spinlock lock;44 struct simple_thread_list blocked;45 };46 47 40 #ifdef __CFORALL__ 48 41 extern "Cforall" { … … 53 46 void ?{}(spinlock * this); 54 47 void ^?{}(spinlock * this); 55 56 void ?{}(signal_once * this);57 void ^?{}(signal_once * this);58 48 } 59 49 #endif 60 50 61 51 struct coStack_t { 62 unsigned int size; 63 void *storage; 64 void *limit; 65 void *base; 66 void *context; 67 void *top; 68 bool userStack; 52 unsigned int size; // size of stack 53 void *storage; // pointer to stack 54 void *limit; // stack grows towards stack limit 55 void *base; // base of stack 56 void *context; // address of cfa_context_t 57 void *top; // address of top of storage 58 bool userStack; // whether or not the user allocated the stack 69 59 }; 70 60 … … 72 62 73 63 struct coroutine_desc { 74 struct coStack_t stack; 75 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 76 int errno_; // copy of global UNIX variable errno 77 enum coroutine_state state; // current execution status for coroutine 78 struct coroutine_desc *starter; // first coroutine to resume this one 79 struct coroutine_desc *last; // last coroutine to resume this one 64 struct coStack_t stack; // stack information of the coroutine 65 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 66 int errno_; // copy of global UNIX variable errno 67 enum coroutine_state state; // current execution status for coroutine 68 struct coroutine_desc *starter; // first coroutine to resume this one 69 struct coroutine_desc *last; // last coroutine to resume this one 70 }; 71 72 struct monitor_desc { 73 struct spinlock lock; 74 struct thread_desc * owner; 75 struct simple_thread_list entry_queue; 76 unsigned int recursion; 80 77 }; 81 78 82 79 struct thread_desc { 83 struct coroutine_desc c ;// coroutine body used to store context84 struct signal_once terminated; // indicate if execuation state is not halted85 struct thread_desc * next; 80 struct coroutine_desc cor; // coroutine body used to store context 81 struct monitor_desc mon; // monitor body used for mutual exclusion 82 struct thread_desc * next; // instrusive link field for threads 86 83 }; 87 84 -
src/libcfa/concurrency/kernel
r829c907 r87d13cd 30 30 void lock( spinlock * ); 31 31 void unlock( spinlock * ); 32 33 struct signal_once { 34 volatile bool condition; 35 struct spinlock lock; 36 struct simple_thread_list blocked; 37 }; 38 39 void ?{}(signal_once * this); 40 void ^?{}(signal_once * this); 32 41 33 42 void wait( signal_once * ); -
src/libcfa/concurrency/kernel.c
r829c907 r87d13cd 107 107 108 108 void ?{}( thread_desc * this, current_stack_info_t * info) { 109 (&this->c ){ info };109 (&this->cor){ info }; 110 110 } 111 111 … … 113 113 // Processor coroutine 114 114 void ?{}(processorCtx_t * this, processor * proc) { 115 (&this-> c){};115 (&this->__cor){}; 116 116 this->proc = proc; 117 117 proc->runner = this; … … 119 119 120 120 void ?{}(processorCtx_t * this, processor * proc, current_stack_info_t * info) { 121 (&this-> c){ info };121 (&this->__cor){ info }; 122 122 this->proc = proc; 123 123 proc->runner = this; … … 255 255 processorCtx_t proc_cor_storage = { proc, &info }; 256 256 257 LIB_DEBUG_PRINTF("Coroutine : created stack %p\n", proc_cor_storage. c.stack.base);257 LIB_DEBUG_PRINTF("Coroutine : created stack %p\n", proc_cor_storage.__cor.stack.base); 258 258 259 259 //Set global state 260 proc->current_coroutine = &proc->runner-> c;260 proc->current_coroutine = &proc->runner->__cor; 261 261 proc->current_thread = NULL; 262 262 … … 268 268 // back to here. Instead directly call the main since we already are on the 269 269 // appropriate stack. 270 proc_cor_storage. c.state = Active;270 proc_cor_storage.__cor.state = Active; 271 271 main( &proc_cor_storage ); 272 proc_cor_storage. c.state = Halted;272 proc_cor_storage.__cor.state = Halted; 273 273 274 274 // Main routine of the core returned, the core is now fully terminated … … 359 359 this_processor = systemProcessor; 360 360 this_processor->current_thread = mainThread; 361 this_processor->current_coroutine = &mainThread->c ;361 this_processor->current_coroutine = &mainThread->cor; 362 362 363 363 // SKULLDUGGERY: Force a context switch to the system processor to set the main thread's context to the current UNIX -
src/libcfa/concurrency/kernel_private.h
r829c907 r87d13cd 35 35 struct processorCtx_t { 36 36 processor * proc; 37 coroutine_desc c;37 coroutine_desc __cor; 38 38 }; 39 39 -
src/libcfa/concurrency/monitor
r829c907 r87d13cd 22 22 #include "stdlib" 23 23 24 struct monitor_desc {25 spinlock lock;26 thread_desc * owner;27 simple_thread_list entry_queue;28 unsigned int recursion;29 };30 31 24 static inline void ?{}(monitor_desc * this) { 32 25 this->owner = 0; 33 26 this->recursion = 0; 34 27 } 35 36 //Basic entering routine37 void enter(monitor_desc *);38 void leave(monitor_desc *);39 28 40 29 //Array entering routine … … 49 38 static inline int ?<?(monitor_desc* lhs, monitor_desc* rhs) { 50 39 return ((intptr_t)lhs) < ((intptr_t)rhs); 51 }52 53 static inline void ?{}( monitor_guard_t * this, monitor_desc ** m ) {54 this->m = m;55 this->count = 1;56 enter( *this->m );57 40 } 58 41 -
src/libcfa/concurrency/monitor.c
r829c907 r87d13cd 19 19 #include "kernel_private.h" 20 20 21 void enter(monitor_desc * this) { 22 lock( &this->lock ); 23 thread_desc * thrd = this_thread(); 21 extern "C" { 22 void __enter_monitor_desc(monitor_desc * this) { 23 lock( &this->lock ); 24 thread_desc * thrd = this_thread(); 24 25 25 if( !this->owner ) {26 //No one has the monitor, just take it27 this->owner = thrd;28 this->recursion = 1;29 }30 else if( this->owner == thrd) {31 //We already have the monitor, just not how many times we took it32 assert( this->recursion > 0 );33 this->recursion += 1;34 }35 else {36 //Some one else has the monitor, wait in line for it37 append( &this->entry_queue, thrd );38 ScheduleInternal( &this->lock );26 if( !this->owner ) { 27 //No one has the monitor, just take it 28 this->owner = thrd; 29 this->recursion = 1; 30 } 31 else if( this->owner == thrd) { 32 //We already have the monitor, just not how many times we took it 33 assert( this->recursion > 0 ); 34 this->recursion += 1; 35 } 36 else { 37 //Some one else has the monitor, wait in line for it 38 append( &this->entry_queue, thrd ); 39 ScheduleInternal( &this->lock ); 39 40 40 //ScheduleInternal will unlock spinlock, no need to unlock ourselves 41 return; 41 //ScheduleInternal will unlock spinlock, no need to unlock ourselves 42 return; 43 } 44 45 unlock( &this->lock ); 42 46 } 43 47 44 unlock( &this->lock );45 } 48 void __leave_monitor_desc(monitor_desc * this) { 49 lock( &this->lock ); 46 50 47 void leave(monitor_desc * this) { 48 lock( &this->lock);51 thread_desc * thrd = this_thread(); 52 assert( thrd == this->owner ); 49 53 50 thread_desc * thrd = this_thread();51 assert( thrd == this->owner );54 //Leaving a recursion level, decrement the counter 55 this->recursion -= 1; 52 56 53 //Leaving a recursion level, decrement the counter 54 this->recursion -= 1; 57 //If we left the last level of recursion it means we are changing who owns the monitor 58 thread_desc * new_owner = 0; 59 if( this->recursion == 0) { 60 //Get the next thread in the list 61 new_owner = this->owner = pop_head( &this->entry_queue ); 55 62 56 //If we left the last level of recursion it means we are changing who owns the monitor 57 thread_desc * new_owner = 0; 58 if( this->recursion == 0) { 59 //Get the next thread in the list 60 new_owner = this->owner = pop_head( &this->entry_queue ); 63 //We are passing the monitor to someone else, which means recursion level is not 0 64 this->recursion = new_owner ? 1 : 0; 65 } 61 66 62 //We are passing the monitor to someone else, which means recursion level is not 0 63 this->recursion = new_owner ? 1 : 0; 64 } 67 unlock( &this->lock ); 65 68 66 unlock( &this->lock ); 67 68 //If we have a new owner, we need to wake-up the thread 69 if( new_owner ) { 70 ScheduleThread( new_owner ); 69 //If we have a new owner, we need to wake-up the thread 70 if( new_owner ) { 71 ScheduleThread( new_owner ); 72 } 71 73 } 72 74 } … … 74 76 void enter(monitor_desc ** monitors, int count) { 75 77 for(int i = 0; i < count; i++) { 76 // printf("%d\n", i); 77 enter( monitors[i] ); 78 __enter_monitor_desc( monitors[i] ); 78 79 } 79 80 } … … 81 82 void leave(monitor_desc ** monitors, int count) { 82 83 for(int i = count - 1; i >= 0; i--) { 83 // printf("%d\n", i); 84 leave( monitors[i] ); 84 __leave_monitor_desc( monitors[i] ); 85 85 } 86 86 } -
src/libcfa/concurrency/thread
r829c907 r87d13cd 22 22 23 23 #include "coroutine" 24 #include "monitor" 24 25 25 26 //----------------------------------------------------------------------------- … … 28 29 // Anything that is resumed is a coroutine. 29 30 trait is_thread(dtype T) { 31 void ^?{}(T* mutex this); 30 32 void main(T* this); 31 33 thread_desc* get_thread(T* this); 32 34 }; 33 35 34 #define DECL_THREAD(X) thread_desc* get_thread(X* this) { return &this-> t; } void main(X* this)36 #define DECL_THREAD(X) thread_desc* get_thread(X* this) { return &this->__thrd; } void main(X* this) 35 37 36 38 forall( dtype T | is_thread(T) ) 37 39 static inline coroutine_desc* get_coroutine(T* this) { 38 return &get_thread(this)->c ;40 return &get_thread(this)->cor; 39 41 } 40 42 41 static inline coroutine_desc* get_coroutine(thread_desc* this) { 42 return &this->c; 43 forall( dtype T | is_thread(T) ) 44 static inline monitor_desc* get_monitor(T * this) { 45 return &get_thread(this)->mon; 46 } 47 48 static inline coroutine_desc* get_coroutine(thread_desc * this) { 49 return &this->cor; 50 } 51 52 static inline monitor_desc* get_monitor(thread_desc * this) { 53 return &this->mon; 43 54 } 44 55 … … 64 75 void ?{}( scoped(T)* this, P params ); 65 76 66 forall( dtype T | sized(T) | is_thread(T) | { void ^?{}(T*); })77 forall( dtype T | sized(T) | is_thread(T) ) 67 78 void ^?{}( scoped(T)* this ); 68 79 -
src/libcfa/concurrency/thread.c
r829c907 r87d13cd 35 35 void start( T* this ); 36 36 37 forall( dtype T | is_thread(T) )38 void stop( T* this );39 40 37 //----------------------------------------------------------------------------- 41 38 // Thread ctors and dtors 42 39 43 40 void ?{}(thread_desc* this) { 44 (&this->c){}; 45 this->c.name = "Anonymous Coroutine"; 46 (&this->terminated){}; 41 (&this->cor){}; 42 this->cor.name = "Anonymous Coroutine"; 43 this->mon.owner = this; 44 this->mon.recursion = 1; 47 45 this->next = NULL; 48 46 } 49 47 50 48 void ^?{}(thread_desc* this) { 51 ^(&this->c ){};49 ^(&this->cor){}; 52 50 } 53 51 … … 64 62 } 65 63 66 forall( dtype T | sized(T) | is_thread(T) | { void ^?{}(T*); })64 forall( dtype T | sized(T) | is_thread(T) ) 67 65 void ^?{}( scoped(T)* this ) { 68 stop(&this->handle);69 66 ^(&this->handle){}; 70 67 } … … 86 83 87 84 ScheduleThread(thrd_h); 88 }89 90 forall( dtype T | is_thread(T) )91 void stop( T* this ) {92 wait( & get_thread(this)->terminated );93 85 } 94 86 … … 116 108 } 117 109 118 // C Helper to signal the termination of a thread_desc119 // Used in invoke.c120 extern "C" {121 void __thread_signal_termination( thread_desc * this ) {122 this->c.state = Halted;123 LIB_DEBUG_PRINTF("Thread end : %p\n", this);124 signal( &this->terminated );125 }126 }127 128 110 // Local Variables: // 129 111 // mode: c // -
src/libcfa/iostream.c
r829c907 r87d13cd 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Mar 21 2 0:58:48201713 // Update Count : 34 712 // Last Modified On : Tue Mar 21 22:05:57 2017 13 // Update Count : 348 14 14 // 15 15 -
src/main.cc
r829c907 r87d13cd 241 241 OPTPRINT( "fixNames" ) 242 242 CodeGen::fixNames( translationUnit ); 243 OPTPRINT( " tweakInit" )243 OPTPRINT( "genInit" ) 244 244 InitTweak::genInit( translationUnit ); 245 245 OPTPRINT( "expandMemberTuples" ); -
src/tests/avltree/avl.h
r829c907 r87d13cd 61 61 void ?{}(tree(K, V) *t, K key, V value); 62 62 63 forall(otype K | Comparable(K), otype V)63 forall(otype K, otype V) 64 64 void ^?{}(tree(K, V) * t); 65 65 -
src/tests/avltree/avl1.c
r829c907 r87d13cd 12 12 } 13 13 14 forall(otype K | Comparable(K), otype V)14 forall(otype K, otype V) 15 15 void ^?{}(tree(K, V) * t){ 16 16 delete(t->left); -
src/tests/avltree/avl_test.c
r829c907 r87d13cd 25 25 26 26 // int -> char * 27 tree(int, c har *) * smap = create(-1, "baz");27 tree(int, const char *) * smap = create(-1, "baz"); 28 28 insert(&smap, 12, "bar"); 29 29 insert(&smap, 2, "foo"); … … 35 35 delete(smap); 36 36 37 // char* -> char* 38 struct c_str { char *str; }; // wraps a C string 39 int ?<?(c_str a, c_str b) { 40 return strcmp(a.str,b.str) < 0; 37 // const char* -> const char* 38 int ?<?(const char * a, const char * b) { 39 return strcmp(a, b) < 0; 41 40 } 42 tree(c_str, char *) * ssmap = create((c_str){"queso"}, "cheese"); 43 insert(&ssmap, (c_str){"foo"}, "bar"); 44 insert(&ssmap, (c_str){"hello"}, "world"); 41 42 tree(const char *, const char *) * ssmap = create("queso", "cheese"); 43 insert(&ssmap, "foo", "bar"); 44 insert(&ssmap, "hello", "world"); 45 45 assert( height(ssmap) == 2 ); 46 46 47 printf("%s %s %s\n", *find(ssmap, (c_str){"hello"}), *find(ssmap, (c_str){"foo"}), *find(ssmap, (c_str){"queso"}));47 printf("%s %s %s\n", *find(ssmap, "hello"), *find(ssmap, "foo"), *find(ssmap, "queso")); 48 48 49 remove(&ssmap, (c_str){"foo"});49 remove(&ssmap, "foo"); 50 50 delete(ssmap); 51 51 } -
src/tests/completeTypeError.c
r829c907 r87d13cd 62 62 63 63 forall(dtype T | sized(T)) 64 void qu x(T * z) {64 void quux(T * z) { 65 65 // okay 66 66 bar(z); -
src/tests/coroutine.c
r829c907 r87d13cd 2 2 #include <coroutine> 3 3 4 structFibonacci {4 coroutine Fibonacci { 5 5 int fn; // used for communication 6 coroutine_desc c;7 6 }; 8 7 … … 11 10 } 12 11 13 coroutine_desc* get_coroutine(Fibonacci* this) {14 return &this->c;15 }16 17 12 void main(Fibonacci* this) { 18 #ifdef MORE_DEBUG19 sout | "Starting main of coroutine " | this | endl;20 sout | "Started from " | this->c.last | endl;21 #endif22 13 int fn1, fn2; // retained between resumes 23 14 this->fn = 0; … … 45 36 int main() { 46 37 Fibonacci f1, f2; 47 #ifdef MORE_DEBUG48 Fibonacci *pf1 = &f1, *pf2 = &f2;49 coroutine_desc *cf1 = &f1.c, *cf2 = &f2.c;50 covptr_t *vf1 = vtable(pf1), *vf2 = vtable(pf2);51 coroutine_desc *cv1 = get_coroutine(vf1), *cv2 = get_coroutine(vf2);52 Fibonacci *ov1 = (Fibonacci *)get_object(vf1), *ov2 = (Fibonacci *)get_object(vf2);53 54 sout | "User coroutines : " | pf1 | ' ' | pf2 | endl;55 sout | "Coroutine data : " | cf1 | ' ' | cf2 | endl;56 sout | "Vptr address : " | vf1 | ' ' | vf2 | endl;57 sout | "Vptr obj data : " | ov1 | ' ' | ov2 | endl;58 sout | "Vptr cor data : " | cv1 | ' ' | cv2 | endl;59 #endif60 38 for ( int i = 1; i <= 10; i += 1 ) { 61 39 sout | next(&f1) | ' ' | next(&f2) | endl; -
src/tests/dtor-early-exit.c
r829c907 r87d13cd 28 28 // don't want these called 29 29 void ?{}(A * a) { assert( false ); } 30 void ?{}(A * a, c har * name) { a->name = name; sout | "construct " | name | endl; a->x = (int*)malloc(); }31 void ?{}(A * a, c har * name, int * ptr) { assert( false ); }30 void ?{}(A * a, const char * name) { a->name = name; sout | "construct " | name | endl; a->x = (int*)malloc(); } 31 void ?{}(A * a, const char * name, int * ptr) { assert( false ); } 32 32 33 33 A ?=?(A * a, A a) { sout | "assign " | a->name | " " | a.name; return a; } -
src/tests/monitor.c
r829c907 r87d13cd 13 13 } 14 14 15 monitor_desc * get_monitor( global_t * this ) { 16 return &this->m; 17 } 18 15 19 static global_t global; 16 20 17 void increment( /*mutex*/ global_t * this ) { 18 monitor_desc * mon = &this->m; 19 monitor_guard_t g1 = { &mon }; 20 { 21 monitor_guard_t g2 = { &mon }; 22 { 23 monitor_guard_t g3 = { &mon }; 24 this->value += 1; 25 } 26 } 21 void increment3( global_t * mutex this ) { 22 this->value += 1; 27 23 } 28 24 29 struct MyThread { thread_desc t; }; 25 void increment2( global_t * mutex this ) { 26 increment3( this ); 27 } 28 29 void increment( global_t * mutex this ) { 30 increment2( this ); 31 } 32 33 struct MyThread { thread_desc __thrd; }; 30 34 31 35 DECL_THREAD(MyThread); 32 36 33 37 void ?{}( MyThread * this ) {} 38 void ^?{}( MyThread * mutex this ) {} 34 39 35 40 void main( MyThread* this ) { 36 for(int i = 0; i < 1 000000; i++) {41 for(int i = 0; i < 1_000_000; i++) { 37 42 increment( &global ); 38 43 } -
src/tests/multi-monitor.c
r829c907 r87d13cd 6 6 static int global12, global23, global13; 7 7 8 static monitor_desc m1, m2, m3; 8 struct monitor_t { 9 monitor_desc m; 10 }; 9 11 10 void increment( /*mutex*/ monitor_desc * p1, /*mutex*/ monitor_desc * p2, int * value ) { 11 monitor_desc * mons[] = { p1, p2 }; 12 monitor_guard_t g = { mons, 2 }; 12 monitor_desc * get_monitor( monitor_t * this ) { 13 return &this->m; 14 } 15 16 static monitor_t m1, m2, m3; 17 18 void increment( monitor_t * mutex p1, monitor_t * mutex p2, int * value ) { 13 19 *value += 1; 14 20 } 15 21 16 22 struct MyThread { 17 thread_desc t;23 thread_desc __thrd; 18 24 int target; 19 25 }; … … 24 30 this->target = target; 25 31 } 32 33 void ^?{}( MyThread * mutex this ) {} 26 34 27 35 void main( MyThread* this ) { -
src/tests/thread.c
r829c907 r87d13cd 4 4 #include <thread> 5 5 6 struct First { thread_desc t; signal_once* lock; };7 struct Second { thread_desc t; signal_once* lock; };6 struct First { thread_desc __thrd; signal_once* lock; }; 7 struct Second { thread_desc __thrd; signal_once* lock; }; 8 8 9 9 DECL_THREAD(First); … … 12 12 void ?{}( First * this, signal_once* lock ) { this->lock = lock; } 13 13 void ?{}( Second * this, signal_once* lock ) { this->lock = lock; } 14 15 void ^?{}( First * mutex this ) {} 16 void ^?{}( Second * mutex this ) {} 14 17 15 18 void main(First* this) {
Note: See TracChangeset
for help on using the changeset viewer.