Changes in / [b3d70eba:5c3632f]
- Files:
-
- 1 deleted
- 16 edited
-
doc/proposals/concurrency/thePlan.md (modified) (1 diff)
-
src/CodeGen/CodeGenerator.cc (modified) (17 diffs)
-
src/CodeGen/CodeGenerator.h (modified) (2 diffs)
-
src/CodeGen/GenType.cc (modified) (8 diffs)
-
src/CodeGen/GenType.h (modified) (1 diff)
-
src/CodeGen/Generate.cc (modified) (1 diff)
-
src/CodeGen/Generate.h (modified) (1 diff)
-
src/SynTree/Declaration.h (modified) (3 diffs)
-
src/libcfa/concurrency/invoke.h (modified) (3 diffs)
-
src/libcfa/concurrency/kernel (modified) (2 diffs)
-
src/libcfa/concurrency/kernel.c (modified) (7 diffs)
-
src/libcfa/concurrency/monitor (modified) (3 diffs)
-
src/libcfa/concurrency/monitor.c (modified) (2 diffs)
-
src/libcfa/concurrency/thread.c (modified) (1 diff)
-
src/main.cc (modified) (4 diffs)
-
src/tests/.expect/memberCtors-ERR1.txt (modified) (1 diff)
-
src/tests/sched_internal.c (deleted)
Legend:
- Unmodified
- Added
- Removed
-
doc/proposals/concurrency/thePlan.md
rb3d70eba r5c3632f 10 10 done - Multi monitors calls, 11 11 done - Monitors as a language feature (not calling enter/leave by hand) 12 Internal scheduling 12 13 13 _Phase 3_ : Monitor features 14 Internal scheduling 15 External scheduling 16 17 _Phase 4_ : Kernel features 14 _Phase 3_ : Kernel features 18 15 Preemption 19 16 Detach thread 20 17 Cluster migration 18 19 _Phase 4_ : Monitor features 20 External scheduling 21 21 22 22 _Phase 5_ : Performance -
src/CodeGen/CodeGenerator.cc
rb3d70eba r5c3632f 89 89 } 90 90 91 CodeGenerator::CodeGenerator( std::ostream & os, bool pretty , bool genC ) : indent( *this), cur_indent( 0 ), insideFunction( false ), output( os ), printLabels( *this ), pretty( pretty ), genC( genC) {}91 CodeGenerator::CodeGenerator( std::ostream & os, bool pretty ) : indent( *this), cur_indent( 0 ), insideFunction( false ), output( os ), printLabels( *this ), pretty( pretty ) {} 92 92 93 93 CodeGenerator::CodeGenerator( std::ostream & os, std::string init, int indentation, bool infunp ) … … 136 136 functionDecl->get_funcSpec().print( output ); 137 137 138 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), pretty , genC);138 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), pretty ); 139 139 140 140 asmName( functionDecl ); … … 147 147 148 148 void CodeGenerator::visit( ObjectDecl * objectDecl ) { 149 if (objectDecl->get_name().empty() && genC ) { 150 // only generate an anonymous name when generating C code, otherwise it clutters the output too much 149 if (objectDecl->get_name().empty()) { 151 150 static UniqueName name = { "__anonymous_object" }; 152 151 objectDecl->set_name( name.newName() ); … … 157 156 158 157 handleStorageClass( objectDecl ); 159 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty , genC);158 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty ); 160 159 161 160 asmName( objectDecl ); … … 172 171 } 173 172 174 void CodeGenerator::handleAggregate( AggregateDecl * aggDecl , const std::string & kind) {173 void CodeGenerator::handleAggregate( AggregateDecl * aggDecl ) { 175 174 genAttributes( aggDecl->get_attributes() ); 176 175 177 if( ! aggDecl->get_parameters().empty() && ! genC ) {178 // assertf( ! genC, "Aggregate type parameters should not reach code generation." );179 output << "forall(";180 genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() );181 output << ")" << endl;182 }183 184 output << kind;185 176 if ( aggDecl->get_name() != "" ) 186 177 output << aggDecl->get_name(); 187 178 179 // std::list< Declaration * > & memb = aggDecl->get_members(); 180 // if ( ! memb.empty() ) { 188 181 if ( aggDecl->has_body() ) { 189 182 std::list< Declaration * > & memb = aggDecl->get_members(); … … 205 198 void CodeGenerator::visit( StructDecl * structDecl ) { 206 199 extension( structDecl ); 207 handleAggregate( structDecl, "struct " ); 200 output << "struct "; 201 handleAggregate( structDecl ); 208 202 } 209 203 210 204 void CodeGenerator::visit( UnionDecl * unionDecl ) { 211 205 extension( unionDecl ); 212 handleAggregate( unionDecl, "union " ); 206 output << "union "; 207 handleAggregate( unionDecl ); 213 208 } 214 209 … … 247 242 248 243 void CodeGenerator::visit( TypedefDecl * typeDecl ) { 249 assert f( ! genC,"Typedefs are removed and substituted in earlier passes." );250 output << "typedef ";251 output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl;244 assert( false && "Typedefs are removed and substituted in earlier passes." ); 245 //output << "typedef "; 246 //output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty ); 252 247 } 253 248 254 249 void CodeGenerator::visit( TypeDecl * typeDecl ) { 255 if ( genC ) { 256 // really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes, 257 // still to be done 258 extension( typeDecl ); 259 output << "extern unsigned long " << typeDecl->get_name(); 260 if ( typeDecl->get_base() ) { 261 output << " = sizeof( " << genType( typeDecl->get_base(), "", pretty, genC ) << " )"; 262 } // if 263 } else { 264 output << typeDecl->typeString() << " " << typeDecl->get_name(); 265 if ( ! typeDecl->get_assertions().empty() ) { 266 output << " | { "; 267 genCommaList( typeDecl->get_assertions().begin(), typeDecl->get_assertions().end() ); 268 output << " }"; 269 } 270 } 250 // really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes, 251 // still to be done 252 extension( typeDecl ); 253 output << "extern unsigned long " << typeDecl->get_name(); 254 if ( typeDecl->get_base() ) { 255 output << " = sizeof( " << genType( typeDecl->get_base(), "", pretty ) << " )"; 256 } // if 271 257 } 272 258 … … 307 293 308 294 void CodeGenerator::visit( ConstructorInit * init ){ 309 assertf( ! genC, "ConstructorInit nodes should not reach code generation." ); 310 // xxx - generate something reasonable for constructor/destructor pairs 311 output << "<ctorinit>"; 295 assertf( false, "ConstructorInit nodes should not make it to CodeGen." ); 312 296 } 313 297 … … 563 547 // at least one result type of cast, but not an lvalue 564 548 output << "("; 565 output << genType( castExpr->get_result(), "", pretty , genC);549 output << genType( castExpr->get_result(), "", pretty ); 566 550 output << ")"; 567 551 } else { … … 574 558 575 559 void CodeGenerator::visit( UntypedMemberExpr * memberExpr ) { 576 assertf( ! genC, "UntypedMemberExpr should not reach code generation." ); 577 extension( memberExpr ); 578 memberExpr->get_aggregate()->accept( *this ); 579 output << "."; 580 memberExpr->get_member()->accept( *this ); 560 assert( false ); 581 561 } 582 562 … … 607 587 output << "sizeof("; 608 588 if ( sizeofExpr->get_isType() ) { 609 output << genType( sizeofExpr->get_type(), "", pretty , genC);589 output << genType( sizeofExpr->get_type(), "", pretty ); 610 590 } else { 611 591 sizeofExpr->get_expr()->accept( *this ); … … 619 599 output << "__alignof__("; 620 600 if ( alignofExpr->get_isType() ) { 621 output << genType( alignofExpr->get_type(), "", pretty , genC);601 output << genType( alignofExpr->get_type(), "", pretty ); 622 602 } else { 623 603 alignofExpr->get_expr()->accept( *this ); … … 627 607 628 608 void CodeGenerator::visit( UntypedOffsetofExpr * offsetofExpr ) { 629 assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." ); 630 output << "offsetof("; 631 output << genType( offsetofExpr->get_type(), "", pretty, genC ); 632 output << ", " << offsetofExpr->get_member(); 633 output << ")"; 609 assert( false && "UntypedOffsetofExpr should not reach code generation." ); 634 610 } 635 611 … … 637 613 // use GCC builtin 638 614 output << "__builtin_offsetof("; 639 output << genType( offsetofExpr->get_type(), "", pretty , genC);615 output << genType( offsetofExpr->get_type(), "", pretty ); 640 616 output << ", " << mangleName( offsetofExpr->get_member() ); 641 617 output << ")"; … … 643 619 644 620 void CodeGenerator::visit( OffsetPackExpr * offsetPackExpr ) { 645 assertf( ! genC, "OffsetPackExpr should not reach code generation." ); 646 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")"; 621 assert( false && "OffsetPackExpr should not reach code generation." ); 647 622 } 648 623 … … 680 655 } 681 656 682 void CodeGenerator::visit( UntypedTupleExpr * tupleExpr ) { 683 assertf( ! genC, "UntypedTupleExpr should not reach code generation." ); 684 output << "["; 685 genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() ); 686 output << "]"; 687 } 688 689 void CodeGenerator::visit( TupleExpr * tupleExpr ) { 690 assertf( ! genC, "TupleExpr should not reach code generation." ); 691 output << "["; 692 genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() ); 693 output << "]"; 694 } 695 696 void CodeGenerator::visit( TypeExpr * typeExpr ) { 697 assertf( ! genC, "TypeExpr should not reach code generation." ); 698 output<< genType( typeExpr->get_type(), "", pretty, genC ); 699 } 657 void CodeGenerator::visit( UntypedTupleExpr * tupleExpr ) { assertf( false, "UntypedTupleExpr should not make it to Code Gen" ); } 658 659 void CodeGenerator::visit( TupleExpr * tupleExpr ) { assertf( false, "TupleExpr should not make it to Code Gen" ); } 660 661 void CodeGenerator::visit( TypeExpr * typeExpr ) {} 700 662 701 663 void CodeGenerator::visit( AsmExpr * asmExpr ) { … … 713 675 void CodeGenerator::visit( CompoundLiteralExpr *compLitExpr ) { 714 676 assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) ); 715 output << "(" << genType( compLitExpr->get_result(), "", pretty , genC) << ")";677 output << "(" << genType( compLitExpr->get_result(), "", pretty ) << ")"; 716 678 compLitExpr->get_initializer()->accept( *this ); 717 679 } -
src/CodeGen/CodeGenerator.h
rb3d70eba r5c3632f 30 30 static int tabsize; 31 31 32 CodeGenerator( std::ostream &os, bool pretty = false , bool genC = false);32 CodeGenerator( std::ostream &os, bool pretty = false ); 33 33 CodeGenerator( std::ostream &os, std::string, int indent = 0, bool infun = false ); 34 34 CodeGenerator( std::ostream &os, char *, int indent = 0, bool infun = false ); … … 121 121 LabelPrinter printLabels; 122 122 bool pretty = false; // pretty print 123 bool genC = false; // true if output has to be C code124 123 125 124 void printDesignators( std::list< Expression * > & ); 126 125 void handleStorageClass( DeclarationWithType *decl ); 127 void handleAggregate( AggregateDecl *aggDecl , const std::string & kind);126 void handleAggregate( AggregateDecl *aggDecl ); 128 127 void handleTypedef( NamedTypeDecl *namedType ); 129 128 std::string mangleName( DeclarationWithType * decl ); -
src/CodeGen/GenType.cc
rb3d70eba r5c3632f 28 28 class GenType : public Visitor { 29 29 public: 30 GenType( const std::string &typeString, bool pretty = false , bool genC = false);30 GenType( const std::string &typeString, bool pretty = false ); 31 31 std::string get_typeString() const { return typeString; } 32 32 void set_typeString( const std::string &newValue ) { typeString = newValue; } … … 48 48 private: 49 49 void handleQualifiers( Type *type ); 50 std::string handleGeneric( ReferenceToType * refType );51 50 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic ); 52 51 53 52 std::string typeString; 54 53 bool pretty = false; // pretty print 55 bool genC = false; // generating C code?56 54 }; 57 55 58 std::string genType( Type *type, const std::string &baseString, bool pretty , bool genC) {59 GenType gt( baseString, pretty , genC);56 std::string genType( Type *type, const std::string &baseString, bool pretty ) { 57 GenType gt( baseString, pretty ); 60 58 std::ostringstream os; 61 59 62 60 if ( ! type->get_attributes().empty() ) { 63 CodeGenerator cg( os, pretty , genC);61 CodeGenerator cg( os, pretty ); 64 62 cg.genAttributes( type->get_attributes() ); 65 63 } // if … … 70 68 71 69 std::string genPrettyType( Type * type, const std::string & baseString ) { 72 return genType( type, baseString, true , false);70 return genType( type, baseString, true ); 73 71 } 74 72 75 GenType::GenType( const std::string &typeString, bool pretty , bool genC ) : typeString( typeString ), pretty( pretty ), genC( genC) {}73 GenType::GenType( const std::string &typeString, bool pretty ) : typeString( typeString ), pretty( pretty ) {} 76 74 77 75 void GenType::visit( VoidType *voidType ) { … … 114 112 } // if 115 113 if ( dimension != 0 ) { 116 CodeGenerator cg( os, pretty , genC);114 CodeGenerator cg( os, pretty ); 117 115 dimension->accept( cg ); 118 116 } else if ( isVarLen ) { … … 168 166 } // if 169 167 } else { 170 CodeGenerator cg( os, pretty , genC);168 CodeGenerator cg( os, pretty ); 171 169 os << "(" ; 172 170 … … 186 184 funcType->get_returnVals().front()->get_type()->accept( *this ); 187 185 } // if 188 189 // add forall190 if( ! funcType->get_forall().empty() && ! genC ) {191 // assertf( ! genC, "Aggregate type parameters should not reach code generation." );192 std::ostringstream os;193 CodeGenerator cg( os, pretty, genC );194 os << "forall(";195 cg.genCommaList( funcType->get_forall().begin(), funcType->get_forall().end() );196 os << ")" << std::endl;197 typeString = os.str() + typeString;198 }199 }200 201 std::string GenType::handleGeneric( ReferenceToType * refType ) {202 if ( ! refType->get_parameters().empty() ) {203 std::ostringstream os;204 CodeGenerator cg( os, pretty, genC );205 os << "(";206 cg.genCommaList( refType->get_parameters().begin(), refType->get_parameters().end() );207 os << ") ";208 return os.str();209 }210 return "";211 186 } 212 187 213 188 void GenType::visit( StructInstType *structInst ) { 214 typeString = structInst->get_name() + handleGeneric( structInst ) + " " + typeString; 215 if ( genC ) typeString = "struct " + typeString; 189 typeString = "struct " + structInst->get_name() + " " + typeString; 216 190 handleQualifiers( structInst ); 217 191 } 218 192 219 193 void GenType::visit( UnionInstType *unionInst ) { 220 typeString = unionInst->get_name() + handleGeneric( unionInst ) + " " + typeString; 221 if ( genC ) typeString = "union " + typeString; 194 typeString = "union " + unionInst->get_name() + " " + typeString; 222 195 handleQualifiers( unionInst ); 223 196 } 224 197 225 198 void GenType::visit( EnumInstType *enumInst ) { 226 typeString = enumInst->get_name() + " " + typeString; 227 if ( genC ) typeString = "enum " + typeString; 199 typeString = "enum " + enumInst->get_name() + " " + typeString; 228 200 handleQualifiers( enumInst ); 229 201 } … … 235 207 236 208 void GenType::visit( TupleType * tupleType ) { 237 assertf( ! genC, "Tuple types should not reach code generation." );209 assertf( pretty, "Tuple types should not make it to Code Gen." ); 238 210 Visitor::visit( tupleType ); 239 211 unsigned int i = 0; … … 242 214 for ( Type * t : *tupleType ) { 243 215 i++; 244 os << genType( t, "", pretty , genC) << (i == tupleType->size() ? "" : ", ");216 os << genType( t, "", pretty ) << (i == tupleType->size() ? "" : ", "); 245 217 } 246 218 os << "]"; -
src/CodeGen/GenType.h
rb3d70eba r5c3632f 21 21 22 22 namespace CodeGen { 23 std::string genType( Type *type, const std::string &baseString, bool pretty = false , bool genC = false);23 std::string genType( Type *type, const std::string &baseString, bool pretty = false ); 24 24 std::string genPrettyType( Type * type, const std::string & baseString ); 25 25 } // namespace CodeGen -
src/CodeGen/Generate.cc
rb3d70eba r5c3632f 27 27 28 28 namespace CodeGen { 29 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty , bool generateC) {30 CodeGen::CodeGenerator cgv( os, pretty , generateC);29 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty ) { 30 CodeGen::CodeGenerator cgv( os, pretty ); 31 31 for ( auto & dcl : translationUnit ) { 32 32 if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) { -
src/CodeGen/Generate.h
rb3d70eba r5c3632f 23 23 24 24 namespace CodeGen { 25 /// Generates code . doIntrinsics determines if intrinsic functions are printed, pretty formats output nicely (e.g., uses unmangled names, etc.), generateC is true when the output must consist only of C code (allows some assertions, etc.)26 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty , bool generateC = false);25 /// Generates code 26 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty ); 27 27 } // namespace CodeGen 28 28 -
src/SynTree/Declaration.h
rb3d70eba r5c3632f 167 167 std::list< DeclarationWithType* >& get_assertions() { return assertions; } 168 168 169 virtual NamedTypeDecl *clone() const = 0; 170 virtual void print( std::ostream &os, int indent = 0 ) const; 171 virtual void printShort( std::ostream &os, int indent = 0 ) const; 172 protected: 169 173 virtual std::string typeString() const = 0; 170 171 virtual NamedTypeDecl *clone() const = 0;172 virtual void print( std::ostream &os, int indent = 0 ) const;173 virtual void printShort( std::ostream &os, int indent = 0 ) const;174 protected:175 174 private: 176 175 Type *base; … … 203 202 TypeDecl * set_sized( bool newValue ) { sized = newValue; return this; } 204 203 205 virtual std::string typeString() const;206 207 204 virtual TypeDecl *clone() const { return new TypeDecl( *this ); } 208 205 virtual void accept( Visitor &v ) { v.visit( this ); } 209 206 virtual TypeDecl *acceptMutator( Mutator &m ) { return m.mutate( this ); } 210 207 private: 208 virtual std::string typeString() const; 211 209 Kind kind; 212 210 bool sized; … … 219 217 TypedefDecl( const TypedefDecl &other ) : Parent( other ) {} 220 218 221 virtual std::string typeString() const;222 223 219 virtual TypedefDecl *clone() const { return new TypedefDecl( *this ); } 224 220 virtual void accept( Visitor &v ) { v.visit( this ); } 225 221 virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); } 226 222 private: 223 virtual std::string typeString() const; 227 224 }; 228 225 -
src/libcfa/concurrency/invoke.h
rb3d70eba r5c3632f 33 33 }; 34 34 35 struct __thread_queue_t {35 struct simple_thread_list { 36 36 struct thread_desc * head; 37 37 struct thread_desc ** tail; 38 38 }; 39 39 40 struct __thread_stack_t {41 struct thread_desc * top;42 };43 44 40 #ifdef __CFORALL__ 45 41 extern "Cforall" { 46 void ?{}( struct __thread_queue_t * ); 47 void append( struct __thread_queue_t *, struct thread_desc * ); 48 struct thread_desc * pop_head( struct __thread_queue_t * ); 49 50 void ?{}( struct __thread_stack_t * ); 51 void push( struct __thread_stack_t *, struct thread_desc * ); 52 struct thread_desc * pop( struct __thread_stack_t * ); 42 void ?{}( struct simple_thread_list * ); 43 void append( struct simple_thread_list *, struct thread_desc * ); 44 struct thread_desc * pop_head( struct simple_thread_list * ); 53 45 54 46 void ?{}(spinlock * this); … … 58 50 59 51 struct coStack_t { 60 unsigned int size; // size of stack61 void *storage; // pointer to stack62 void *limit; // stack grows towards stack limit63 void *base; // base of stack64 void *context; // address of cfa_context_t65 void *top; // address of top of storage66 bool userStack; // whether or not the user allocated the stack52 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 67 59 }; 68 60 … … 70 62 71 63 struct coroutine_desc { 72 struct coStack_t stack; // stack information of the coroutine73 const char *name; // textual name for coroutine/task, initialized by uC++ generated code74 int errno_; // copy of global UNIX variable errno75 enum coroutine_state state; // current execution status for coroutine76 struct coroutine_desc *starter; // first coroutine to resume this one77 struct coroutine_desc *last; // last coroutine to resume this one64 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 78 70 }; 79 71 80 72 struct monitor_desc { 81 struct spinlock lock; // spinlock to protect internal data 82 struct thread_desc * owner; // current owner of the monitor 83 struct __thread_queue_t entry_queue; // queue of threads that are blocked waiting for the monitor 84 struct __thread_stack_t signal_stack; // stack of threads to run next once we exit the monitor 85 struct monitor_desc * stack_owner; // if bulk acquiring was used we need to synchronize signals with an other monitor 86 unsigned int recursion; // monitor routines can be called recursively, we need to keep track of that 73 struct spinlock lock; 74 struct thread_desc * owner; 75 struct simple_thread_list entry_queue; 76 unsigned int recursion; 87 77 }; 88 78 89 79 struct thread_desc { 90 struct coroutine_desc cor; // coroutine body used to store context 91 struct monitor_desc mon; // monitor body used for mutual exclusion 92 struct thread_desc * next; // instrusive link field for threads 93 struct monitor_desc ** current_monitors; // currently held monitors 94 unsigned short current_monitor_count; // number of currently held monitors 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 95 83 }; 96 84 -
src/libcfa/concurrency/kernel
rb3d70eba r5c3632f 32 32 33 33 struct signal_once { 34 volatile bool cond ;34 volatile bool condition; 35 35 struct spinlock lock; 36 struct __thread_queue_t blocked;36 struct simple_thread_list blocked; 37 37 }; 38 38 … … 46 46 // Cluster 47 47 struct cluster { 48 __thread_queue_t ready_queue;48 simple_thread_list ready_queue; 49 49 spinlock lock; 50 50 }; -
src/libcfa/concurrency/kernel.c
rb3d70eba r5c3632f 299 299 // Scheduler routines 300 300 void ScheduleThread( thread_desc * thrd ) { 301 if( !thrd ) return;302 303 301 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 304 302 … … 475 473 476 474 void ?{}( signal_once * this ) { 477 this->cond = false;475 this->condition = false; 478 476 } 479 477 void ^?{}( signal_once * this ) { … … 483 481 void wait( signal_once * this ) { 484 482 lock( &this->lock ); 485 if( !this->cond ) {483 if( !this->condition ) { 486 484 append( &this->blocked, this_thread() ); 487 485 ScheduleInternal( &this->lock ); … … 494 492 lock( &this->lock ); 495 493 { 496 this->cond = true;494 this->condition = true; 497 495 498 496 thread_desc * it; … … 506 504 //----------------------------------------------------------------------------- 507 505 // Queues 508 void ?{}( __thread_queue_t * this ) {506 void ?{}( simple_thread_list * this ) { 509 507 this->head = NULL; 510 508 this->tail = &this->head; 511 509 } 512 510 513 void append( __thread_queue_t * this, thread_desc * t ) {511 void append( simple_thread_list * this, thread_desc * t ) { 514 512 assert(this->tail != NULL); 515 513 *this->tail = t; … … 517 515 } 518 516 519 thread_desc * pop_head( __thread_queue_t * this ) {517 thread_desc * pop_head( simple_thread_list * this ) { 520 518 thread_desc * head = this->head; 521 519 if( head ) { … … 528 526 return head; 529 527 } 530 531 void ?{}( __thread_stack_t * this ) {532 this->top = NULL;533 }534 535 void push( __thread_stack_t * this, thread_desc * t ) {536 assert(t->next != NULL);537 t->next = this->top;538 this->top = t;539 }540 541 thread_desc * pop( __thread_stack_t * this ) {542 thread_desc * top = this->top;543 if( top ) {544 this->top = top->next;545 top->next = NULL;546 }547 return top;548 }549 528 // Local Variables: // 550 529 // mode: c // -
src/libcfa/concurrency/monitor
rb3d70eba r5c3632f 18 18 #define MONITOR_H 19 19 20 #include <stddef.h>21 22 20 #include "assert" 23 21 #include "invoke.h" … … 25 23 26 24 static inline void ?{}(monitor_desc * this) { 27 this->owner = NULL; 28 this->stack_owner = NULL; 25 this->owner = 0; 29 26 this->recursion = 0; 30 27 } 28 29 //Array entering routine 30 void enter(monitor_desc **, int count); 31 void leave(monitor_desc **, int count); 31 32 32 33 struct monitor_guard_t { 33 34 monitor_desc ** m; 34 35 int count; 35 monitor_desc ** prev_mntrs;36 unsigned short prev_count;37 36 }; 38 37 … … 41 40 } 42 41 43 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ); 44 void ^?{}( monitor_guard_t * this ); 45 46 //----------------------------------------------------------------------------- 47 // Internal scheduling 48 struct condition { 49 __thread_queue_t blocked; 50 monitor_desc ** monitors; 51 unsigned short monitor_count; 52 }; 53 54 static inline void ?{}( condition * this ) { 55 this->monitors = NULL; 56 this->monitor_count = 0; 42 static inline void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) { 43 this->m = m; 44 this->count = count; 45 qsort(this->m, count); 46 enter( this->m, this->count ); 57 47 } 58 48 59 void wait( condition * this ); 60 void signal( condition * this ); 49 static inline void ^?{}( monitor_guard_t * this ) { 50 leave( this->m, this->count ); 51 } 52 53 61 54 #endif //MONITOR_H -
src/libcfa/concurrency/monitor.c
rb3d70eba r5c3632f 18 18 19 19 #include "kernel_private.h" 20 #include "libhdr.h"21 22 void set_owner( monitor_desc * this, thread_desc * owner ) {23 //Pass the monitor appropriately24 this->owner = owner;25 26 //We are passing the monitor to someone else, which means recursion level is not 027 this->recursion = owner ? 1 : 0;28 }29 20 30 21 extern "C" { 31 void __enter_monitor_desc(monitor_desc * this , monitor_desc * leader) {22 void __enter_monitor_desc(monitor_desc * this) { 32 23 lock( &this->lock ); 33 24 thread_desc * thrd = this_thread(); 34 25 35 // //Update the stack owner36 // this->stack_owner = leader;37 38 LIB_DEBUG_PRINT_SAFE("Entering %p (o: %p, r: %i)\n", this, this->owner, this->recursion);39 40 26 if( !this->owner ) { 41 27 //No one has the monitor, just take it 42 set_owner( this, thrd ); 28 this->owner = thrd; 29 this->recursion = 1; 43 30 } 44 31 else if( this->owner == thrd) { … … 57 44 58 45 unlock( &this->lock ); 59 return;60 46 } 61 47 62 // leave pseudo code : 63 // decrement level 64 // leve == 0 ? 65 // no : done 66 // yes : 67 // signal stack empty ? 68 // has leader : 69 // bulk acquiring means we don't own the signal stack 70 // ignore it but don't release the monitor 71 // yes : 72 // next in entry queue is new owner 73 // no : 74 // top of the signal stack is the owner 75 // context switch to him right away 76 // 77 void __leave_monitor_desc(monitor_desc * this, monitor_desc * leader) { 48 void __leave_monitor_desc(monitor_desc * this) { 78 49 lock( &this->lock ); 79 50 80 LIB_DEBUG_PRINT_SAFE("Leaving %p (o: %p, r: %i)\n", this, this->owner, this->recursion);81 82 51 thread_desc * thrd = this_thread(); 83 assert f( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", this->owner, thrd, this->recursion);52 assert( thrd == this->owner ); 84 53 85 54 //Leaving a recursion level, decrement the counter 86 55 this->recursion -= 1; 87 56 88 //If we haven't left the last level of recursion 89 //it means we don't need to do anything 90 if( this->recursion != 0) { 91 // this->stack_owner = leader; 92 unlock( &this->lock ); 93 return; 94 } 95 96 // //If we don't own the signal stack then just leave it to the owner 97 // if( this->stack_owner ) { 98 // this->stack_owner = leader; 99 // unlock( &this->lock ); 100 // return; 101 // } 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 ); 102 62 103 //We are the stack owner and have left the last recursion level.104 //We are in charge of passing the monitor105 thread_desc * new_owner = 0;63 //We are passing the monitor to someone else, which means recursion level is not 0 64 this->recursion = new_owner ? 1 : 0; 65 } 106 66 107 //Check the signaller stack108 new_owner = pop( &this->signal_stack );109 if( new_owner ) {110 //The signaller stack is not empty,111 //transfer control immediately112 set_owner( this, new_owner );113 // this->stack_owner = leader;114 ScheduleInternal( &this->lock, new_owner );115 return;116 }117 118 // No signaller thread119 // Get the next thread in the entry_queue120 new_owner = pop_head( &this->entry_queue );121 set_owner( this, new_owner );122 123 // //Update the stack owner124 // this->stack_owner = leader;125 126 //We can now let other threads in safely127 67 unlock( &this->lock ); 128 68 129 //We need to wake-up the thread 130 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 } 131 73 } 132 74 } 133 75 134 static inline void enter(monitor_desc ** monitors, int count) { 135 __enter_monitor_desc( monitors[0], NULL ); 136 for(int i = 1; i < count; i++) { 137 __enter_monitor_desc( monitors[i], monitors[0] ); 76 void enter(monitor_desc ** monitors, int count) { 77 for(int i = 0; i < count; i++) { 78 __enter_monitor_desc( monitors[i] ); 138 79 } 139 80 } 140 81 141 static inline void leave(monitor_desc ** monitors, int count) { 142 __leave_monitor_desc( monitors[0], NULL ); 143 for(int i = count - 1; i >= 1; i--) { 144 __leave_monitor_desc( monitors[i], monitors[0] ); 82 void leave(monitor_desc ** monitors, int count) { 83 for(int i = count - 1; i >= 0; i--) { 84 __leave_monitor_desc( monitors[i] ); 145 85 } 146 86 } 147 148 void ?{}( monitor_guard_t * this, monitor_desc ** m, int count ) {149 this->m = m;150 this->count = count;151 qsort(this->m, count);152 enter( this->m, this->count );153 154 this->prev_mntrs = this_thread()->current_monitors;155 this->prev_count = this_thread()->current_monitor_count;156 157 this_thread()->current_monitors = m;158 this_thread()->current_monitor_count = count;159 }160 161 void ^?{}( monitor_guard_t * this ) {162 leave( this->m, this->count );163 164 this_thread()->current_monitors = this->prev_mntrs;165 this_thread()->current_monitor_count = this->prev_count;166 }167 168 //-----------------------------------------------------------------------------169 // Internal scheduling170 void wait( condition * this ) {171 assertf(false, "NO SUPPORTED");172 // LIB_DEBUG_FPRINTF("Waiting\n");173 thread_desc * this_thrd = this_thread();174 175 if( !this->monitors ) {176 this->monitors = this_thrd->current_monitors;177 this->monitor_count = this_thrd->current_monitor_count;178 }179 180 unsigned short count = this->monitor_count;181 182 //Check that everything is as expected183 assert( this->monitors != NULL );184 assert( this->monitor_count != 0 );185 186 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later187 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal188 189 // LIB_DEBUG_FPRINTF("Getting ready to wait\n");190 191 //Loop on all the monitors and release the owner192 for( unsigned int i = 0; i < count; i++ ) {193 monitor_desc * cur = this->monitors[i];194 195 assert( cur );196 197 // LIB_DEBUG_FPRINTF("cur %p lock %p\n", cur, &cur->lock);198 199 //Store the locks for later200 locks[i] = &cur->lock;201 202 //Protect the monitors203 lock( locks[i] );204 {205 //Save the recursion levels206 recursions[i] = cur->recursion;207 208 //Release the owner209 cur->recursion = 0;210 cur->owner = NULL;211 }212 //Release the monitor213 unlock( locks[i] );214 }215 216 // LIB_DEBUG_FPRINTF("Waiting now\n");217 218 //Everything is ready to go to sleep219 ScheduleInternal( locks, count );220 221 222 //WE WOKE UP223 224 225 //We are back, restore the owners and recursions226 for( unsigned int i = 0; i < count; i++ ) {227 monitor_desc * cur = this->monitors[i];228 229 //Protect the monitors230 lock( locks[i] );231 {232 //Release the owner233 cur->owner = this_thrd;234 cur->recursion = recursions[i];235 }236 //Release the monitor237 unlock( locks[i] );238 }239 }240 241 static void __signal_internal( condition * this ) {242 assertf(false, "NO SUPPORTED");243 if( !this->blocked.head ) return;244 245 //Check that everything is as expected246 assert( this->monitors );247 assert( this->monitor_count != 0 );248 249 LIB_DEBUG_DO(250 if ( this->monitors != this_thread()->current_monitors ) {251 abortf( "Signal on condition %p made outside of the correct monitor(s)", this );252 } // if253 );254 255 monitor_desc * owner = this->monitors[0];256 lock( &owner->lock );257 {258 thread_desc * unblock = pop_head( &this->blocked );259 push( &owner->signal_stack, unblock );260 }261 unlock( &owner->lock );262 }263 264 void signal( condition * this ) {265 __signal_internal( this );266 } -
src/libcfa/concurrency/thread.c
rb3d70eba r5c3632f 39 39 this->mon.recursion = 1; 40 40 this->next = NULL; 41 42 this->current_monitors = NULL;43 this->current_monitor_count = 0;44 41 } 45 42 -
src/main.cc
rb3d70eba r5c3632f 304 304 GenPoly::box( translationUnit ); 305 305 306 // print tree right before code generation 307 if ( codegenp ) { 308 dump( translationUnit ); 309 return 0; 310 } // if 311 306 312 if ( optind < argc ) { // any commands after the flags and input file ? => output file name 307 313 output = new ofstream( argv[ optind ] ); 308 314 } // if 309 315 310 CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp , true);316 CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp ); 311 317 312 318 CodeGen::FixMain::fix( *output, treep ? "../prelude/bootloader.c" : CFA_LIBDIR "/bootloader.c" ); … … 387 393 break; 388 394 case CtorInitFix: 389 case 'c': // print after constructors and destructors are replaced395 case 'c': 390 396 ctorinitp = true; 391 397 break; … … 444 450 validp = true; 445 451 break; 446 case 'y': // dump AST on error452 case 'y': 447 453 errorp = true; 448 454 break; 449 case 'z': // dump as codegen rather than AST455 case 'z': 450 456 codegenp = true; 451 break; 452 case 'Z': // prettyprint during codegen (i.e. print unmangled names, etc.) 457 case 'Z': 453 458 prettycodegenp = true; 454 459 break; … … 496 501 } // if 497 502 498 // depending on commandline options, either generate code or dump the AST 499 if ( codegenp ) { 500 CodeGen::generate( decls, out, ! noprotop, prettycodegenp ); 501 } else { 502 printAll( decls, out ); 503 } 503 printAll( decls, out ); 504 504 deleteAll( translationUnit ); 505 505 } // dump -
src/tests/.expect/memberCtors-ERR1.txt
rb3d70eba r5c3632f 1 memberCtors.c:62 error: in void ?{}( B *b), field a2 used before being constructed1 memberCtors.c:62 error: in void ?{}(struct B *b), field a2 used before being constructed 2 2 make: *** [memberCtors-ERR1] Error 1
Note:
See TracChangeset
for help on using the changeset viewer.