Changeset b3d70eba
- Timestamp:
- Apr 19, 2017, 10:31:57 PM (6 years ago)
- Branches:
- aaron-thesis, arm-eh, 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:
- 12d3187, 4e9151f, 6a8ac0b
- Parents:
- 5c3632f (diff), e3987770 (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. - Files:
-
- 1 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/proposals/concurrency/thePlan.md
r5c3632f rb3d70eba 10 10 done - Multi monitors calls, 11 11 done - Monitors as a language feature (not calling enter/leave by hand) 12 13 _Phase 3_ : Monitor features 12 14 Internal scheduling 15 External scheduling 13 16 14 _Phase 3_ : Kernel features17 _Phase 4_ : Kernel features 15 18 Preemption 16 19 Detach thread 17 20 Cluster migration 18 19 _Phase 4_ : Monitor features20 External scheduling21 21 22 22 _Phase 5_ : Performance -
src/CodeGen/CodeGenerator.cc
r5c3632f rb3d70eba 89 89 } 90 90 91 CodeGenerator::CodeGenerator( std::ostream & os, bool pretty ) : indent( *this), cur_indent( 0 ), insideFunction( false ), output( os ), printLabels( *this ), pretty( pretty) {}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 ) {} 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 );138 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), pretty, genC ); 139 139 140 140 asmName( functionDecl ); … … 147 147 148 148 void CodeGenerator::visit( ObjectDecl * objectDecl ) { 149 if (objectDecl->get_name().empty()) { 149 if (objectDecl->get_name().empty() && genC ) { 150 // only generate an anonymous name when generating C code, otherwise it clutters the output too much 150 151 static UniqueName name = { "__anonymous_object" }; 151 152 objectDecl->set_name( name.newName() ); … … 156 157 157 158 handleStorageClass( objectDecl ); 158 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty );159 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty, genC ); 159 160 160 161 asmName( objectDecl ); … … 171 172 } 172 173 173 void CodeGenerator::handleAggregate( AggregateDecl * aggDecl ) {174 void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) { 174 175 genAttributes( aggDecl->get_attributes() ); 175 176 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; 176 185 if ( aggDecl->get_name() != "" ) 177 186 output << aggDecl->get_name(); 178 187 179 // std::list< Declaration * > & memb = aggDecl->get_members();180 // if ( ! memb.empty() ) {181 188 if ( aggDecl->has_body() ) { 182 189 std::list< Declaration * > & memb = aggDecl->get_members(); … … 198 205 void CodeGenerator::visit( StructDecl * structDecl ) { 199 206 extension( structDecl ); 200 output << "struct "; 201 handleAggregate( structDecl ); 207 handleAggregate( structDecl, "struct " ); 202 208 } 203 209 204 210 void CodeGenerator::visit( UnionDecl * unionDecl ) { 205 211 extension( unionDecl ); 206 output << "union "; 207 handleAggregate( unionDecl ); 212 handleAggregate( unionDecl, "union " ); 208 213 } 209 214 … … 242 247 243 248 void CodeGenerator::visit( TypedefDecl * typeDecl ) { 244 assert ( false &&"Typedefs are removed and substituted in earlier passes." );245 //output << "typedef ";246 //output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty );249 assertf( ! genC, "Typedefs are removed and substituted in earlier passes." ); 250 output << "typedef "; 251 output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl; 247 252 } 248 253 249 254 void CodeGenerator::visit( TypeDecl * typeDecl ) { 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 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 } 257 271 } 258 272 … … 293 307 294 308 void CodeGenerator::visit( ConstructorInit * init ){ 295 assertf( false, "ConstructorInit nodes should not make it to CodeGen." ); 309 assertf( ! genC, "ConstructorInit nodes should not reach code generation." ); 310 // xxx - generate something reasonable for constructor/destructor pairs 311 output << "<ctorinit>"; 296 312 } 297 313 … … 547 563 // at least one result type of cast, but not an lvalue 548 564 output << "("; 549 output << genType( castExpr->get_result(), "", pretty );565 output << genType( castExpr->get_result(), "", pretty, genC ); 550 566 output << ")"; 551 567 } else { … … 558 574 559 575 void CodeGenerator::visit( UntypedMemberExpr * memberExpr ) { 560 assert( false ); 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 ); 561 581 } 562 582 … … 587 607 output << "sizeof("; 588 608 if ( sizeofExpr->get_isType() ) { 589 output << genType( sizeofExpr->get_type(), "", pretty );609 output << genType( sizeofExpr->get_type(), "", pretty, genC ); 590 610 } else { 591 611 sizeofExpr->get_expr()->accept( *this ); … … 599 619 output << "__alignof__("; 600 620 if ( alignofExpr->get_isType() ) { 601 output << genType( alignofExpr->get_type(), "", pretty );621 output << genType( alignofExpr->get_type(), "", pretty, genC ); 602 622 } else { 603 623 alignofExpr->get_expr()->accept( *this ); … … 607 627 608 628 void CodeGenerator::visit( UntypedOffsetofExpr * offsetofExpr ) { 609 assert( false && "UntypedOffsetofExpr should not reach code generation." ); 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 << ")"; 610 634 } 611 635 … … 613 637 // use GCC builtin 614 638 output << "__builtin_offsetof("; 615 output << genType( offsetofExpr->get_type(), "", pretty );639 output << genType( offsetofExpr->get_type(), "", pretty, genC ); 616 640 output << ", " << mangleName( offsetofExpr->get_member() ); 617 641 output << ")"; … … 619 643 620 644 void CodeGenerator::visit( OffsetPackExpr * offsetPackExpr ) { 621 assert( false && "OffsetPackExpr should not reach code generation." ); 645 assertf( ! genC, "OffsetPackExpr should not reach code generation." ); 646 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")"; 622 647 } 623 648 … … 655 680 } 656 681 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 ) {} 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 } 662 700 663 701 void CodeGenerator::visit( AsmExpr * asmExpr ) { … … 675 713 void CodeGenerator::visit( CompoundLiteralExpr *compLitExpr ) { 676 714 assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) ); 677 output << "(" << genType( compLitExpr->get_result(), "", pretty ) << ")";715 output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")"; 678 716 compLitExpr->get_initializer()->accept( *this ); 679 717 } -
src/CodeGen/CodeGenerator.h
r5c3632f rb3d70eba 30 30 static int tabsize; 31 31 32 CodeGenerator( std::ostream &os, bool pretty = false );32 CodeGenerator( std::ostream &os, bool pretty = false, bool genC = 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 code 123 124 124 125 void printDesignators( std::list< Expression * > & ); 125 126 void handleStorageClass( DeclarationWithType *decl ); 126 void handleAggregate( AggregateDecl *aggDecl );127 void handleAggregate( AggregateDecl *aggDecl, const std::string & kind ); 127 128 void handleTypedef( NamedTypeDecl *namedType ); 128 129 std::string mangleName( DeclarationWithType * decl ); -
src/CodeGen/GenType.cc
r5c3632f rb3d70eba 28 28 class GenType : public Visitor { 29 29 public: 30 GenType( const std::string &typeString, bool pretty = false );30 GenType( const std::string &typeString, bool pretty = false, bool genC = 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 ); 50 51 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic ); 51 52 52 53 std::string typeString; 53 54 bool pretty = false; // pretty print 55 bool genC = false; // generating C code? 54 56 }; 55 57 56 std::string genType( Type *type, const std::string &baseString, bool pretty ) {57 GenType gt( baseString, pretty );58 std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC ) { 59 GenType gt( baseString, pretty, genC ); 58 60 std::ostringstream os; 59 61 60 62 if ( ! type->get_attributes().empty() ) { 61 CodeGenerator cg( os, pretty );63 CodeGenerator cg( os, pretty, genC ); 62 64 cg.genAttributes( type->get_attributes() ); 63 65 } // if … … 68 70 69 71 std::string genPrettyType( Type * type, const std::string & baseString ) { 70 return genType( type, baseString, true );72 return genType( type, baseString, true, false ); 71 73 } 72 74 73 GenType::GenType( const std::string &typeString, bool pretty ) : typeString( typeString ), pretty( pretty) {}75 GenType::GenType( const std::string &typeString, bool pretty, bool genC ) : typeString( typeString ), pretty( pretty ), genC( genC ) {} 74 76 75 77 void GenType::visit( VoidType *voidType ) { … … 112 114 } // if 113 115 if ( dimension != 0 ) { 114 CodeGenerator cg( os, pretty );116 CodeGenerator cg( os, pretty, genC ); 115 117 dimension->accept( cg ); 116 118 } else if ( isVarLen ) { … … 166 168 } // if 167 169 } else { 168 CodeGenerator cg( os, pretty );170 CodeGenerator cg( os, pretty, genC ); 169 171 os << "(" ; 170 172 … … 184 186 funcType->get_returnVals().front()->get_type()->accept( *this ); 185 187 } // if 188 189 // add forall 190 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 ""; 186 211 } 187 212 188 213 void GenType::visit( StructInstType *structInst ) { 189 typeString = "struct " + structInst->get_name() + " " + typeString; 214 typeString = structInst->get_name() + handleGeneric( structInst ) + " " + typeString; 215 if ( genC ) typeString = "struct " + typeString; 190 216 handleQualifiers( structInst ); 191 217 } 192 218 193 219 void GenType::visit( UnionInstType *unionInst ) { 194 typeString = "union " + unionInst->get_name() + " " + typeString; 220 typeString = unionInst->get_name() + handleGeneric( unionInst ) + " " + typeString; 221 if ( genC ) typeString = "union " + typeString; 195 222 handleQualifiers( unionInst ); 196 223 } 197 224 198 225 void GenType::visit( EnumInstType *enumInst ) { 199 typeString = "enum " + enumInst->get_name() + " " + typeString; 226 typeString = enumInst->get_name() + " " + typeString; 227 if ( genC ) typeString = "enum " + typeString; 200 228 handleQualifiers( enumInst ); 201 229 } … … 207 235 208 236 void GenType::visit( TupleType * tupleType ) { 209 assertf( pretty, "Tuple types should not make it to Code Gen." );237 assertf( ! genC, "Tuple types should not reach code generation." ); 210 238 Visitor::visit( tupleType ); 211 239 unsigned int i = 0; … … 214 242 for ( Type * t : *tupleType ) { 215 243 i++; 216 os << genType( t, "", pretty ) << (i == tupleType->size() ? "" : ", ");244 os << genType( t, "", pretty, genC ) << (i == tupleType->size() ? "" : ", "); 217 245 } 218 246 os << "]"; -
src/CodeGen/GenType.h
r5c3632f rb3d70eba 21 21 22 22 namespace CodeGen { 23 std::string genType( Type *type, const std::string &baseString, bool pretty = false );23 std::string genType( Type *type, const std::string &baseString, bool pretty = false, bool genC = false ); 24 24 std::string genPrettyType( Type * type, const std::string & baseString ); 25 25 } // namespace CodeGen -
src/CodeGen/Generate.cc
r5c3632f rb3d70eba 27 27 28 28 namespace CodeGen { 29 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty ) {30 CodeGen::CodeGenerator cgv( os, pretty );29 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC ) { 30 CodeGen::CodeGenerator cgv( os, pretty, generateC ); 31 31 for ( auto & dcl : translationUnit ) { 32 32 if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) { -
src/CodeGen/Generate.h
r5c3632f rb3d70eba 23 23 24 24 namespace CodeGen { 25 /// Generates code 26 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty );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 ); 27 27 } // namespace CodeGen 28 28 -
src/SynTree/Declaration.h
r5c3632f rb3d70eba 167 167 std::list< DeclarationWithType* >& get_assertions() { return assertions; } 168 168 169 virtual std::string typeString() const = 0; 170 169 171 virtual NamedTypeDecl *clone() const = 0; 170 172 virtual void print( std::ostream &os, int indent = 0 ) const; 171 173 virtual void printShort( std::ostream &os, int indent = 0 ) const; 172 174 protected: 173 virtual std::string typeString() const = 0;174 175 private: 175 176 Type *base; … … 202 203 TypeDecl * set_sized( bool newValue ) { sized = newValue; return this; } 203 204 205 virtual std::string typeString() const; 206 204 207 virtual TypeDecl *clone() const { return new TypeDecl( *this ); } 205 208 virtual void accept( Visitor &v ) { v.visit( this ); } 206 209 virtual TypeDecl *acceptMutator( Mutator &m ) { return m.mutate( this ); } 207 210 private: 208 virtual std::string typeString() const;209 211 Kind kind; 210 212 bool sized; … … 217 219 TypedefDecl( const TypedefDecl &other ) : Parent( other ) {} 218 220 221 virtual std::string typeString() const; 222 219 223 virtual TypedefDecl *clone() const { return new TypedefDecl( *this ); } 220 224 virtual void accept( Visitor &v ) { v.visit( this ); } 221 225 virtual Declaration *acceptMutator( Mutator &m ) { return m.mutate( this ); } 222 226 private: 223 virtual std::string typeString() const;224 227 }; 225 228 -
src/libcfa/concurrency/invoke.h
r5c3632f rb3d70eba 33 33 }; 34 34 35 struct simple_thread_list {35 struct __thread_queue_t { 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 40 44 #ifdef __CFORALL__ 41 45 extern "Cforall" { 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 * ); 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 * ); 45 53 46 54 void ?{}(spinlock * this); … … 50 58 51 59 struct coStack_t { 52 unsigned int size; // size of stack53 void *storage; // pointer to stack54 void *limit; // stack grows towards stack limit55 void *base; // base of stack56 void *context; // address of cfa_context_t57 void *top; // address of top of storage58 bool userStack; // whether or not the user allocated the stack60 unsigned int size; // size of stack 61 void *storage; // pointer to stack 62 void *limit; // stack grows towards stack limit 63 void *base; // base of stack 64 void *context; // address of cfa_context_t 65 void *top; // address of top of storage 66 bool userStack; // whether or not the user allocated the stack 59 67 }; 60 68 … … 62 70 63 71 struct coroutine_desc { 64 struct coStack_t stack; // stack information of the coroutine65 const char *name; // textual name for coroutine/task, initialized by uC++ generated code66 int errno_; // copy of global UNIX variable errno67 enum coroutine_state state; // current execution status for coroutine68 struct coroutine_desc *starter; // first coroutine to resume this one69 struct coroutine_desc *last; // last coroutine to resume this one72 struct coStack_t stack; // stack information of the coroutine 73 const char *name; // textual name for coroutine/task, initialized by uC++ generated code 74 int errno_; // copy of global UNIX variable errno 75 enum coroutine_state state; // current execution status for coroutine 76 struct coroutine_desc *starter; // first coroutine to resume this one 77 struct coroutine_desc *last; // last coroutine to resume this one 70 78 }; 71 79 72 80 struct monitor_desc { 73 struct spinlock lock; 74 struct thread_desc * owner; 75 struct simple_thread_list entry_queue; 76 unsigned int recursion; 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 77 87 }; 78 88 79 89 struct thread_desc { 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 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 83 95 }; 84 96 -
src/libcfa/concurrency/kernel
r5c3632f rb3d70eba 32 32 33 33 struct signal_once { 34 volatile bool cond ition;34 volatile bool cond; 35 35 struct spinlock lock; 36 struct simple_thread_list blocked;36 struct __thread_queue_t blocked; 37 37 }; 38 38 … … 46 46 // Cluster 47 47 struct cluster { 48 simple_thread_list ready_queue;48 __thread_queue_t ready_queue; 49 49 spinlock lock; 50 50 }; -
src/libcfa/concurrency/kernel.c
r5c3632f rb3d70eba 299 299 // Scheduler routines 300 300 void ScheduleThread( thread_desc * thrd ) { 301 if( !thrd ) return; 302 301 303 assertf( thrd->next == NULL, "Expected null got %p", thrd->next ); 302 304 … … 473 475 474 476 void ?{}( signal_once * this ) { 475 this->cond ition= false;477 this->cond = false; 476 478 } 477 479 void ^?{}( signal_once * this ) { … … 481 483 void wait( signal_once * this ) { 482 484 lock( &this->lock ); 483 if( !this->cond ition) {485 if( !this->cond ) { 484 486 append( &this->blocked, this_thread() ); 485 487 ScheduleInternal( &this->lock ); … … 492 494 lock( &this->lock ); 493 495 { 494 this->cond ition= true;496 this->cond = true; 495 497 496 498 thread_desc * it; … … 504 506 //----------------------------------------------------------------------------- 505 507 // Queues 506 void ?{}( simple_thread_list * this ) {508 void ?{}( __thread_queue_t * this ) { 507 509 this->head = NULL; 508 510 this->tail = &this->head; 509 511 } 510 512 511 void append( simple_thread_list * this, thread_desc * t ) {513 void append( __thread_queue_t * this, thread_desc * t ) { 512 514 assert(this->tail != NULL); 513 515 *this->tail = t; … … 515 517 } 516 518 517 thread_desc * pop_head( simple_thread_list * this ) {519 thread_desc * pop_head( __thread_queue_t * this ) { 518 520 thread_desc * head = this->head; 519 521 if( head ) { … … 526 528 return head; 527 529 } 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 } 528 549 // Local Variables: // 529 550 // mode: c // -
src/libcfa/concurrency/monitor
r5c3632f rb3d70eba 18 18 #define MONITOR_H 19 19 20 #include <stddef.h> 21 20 22 #include "assert" 21 23 #include "invoke.h" … … 23 25 24 26 static inline void ?{}(monitor_desc * this) { 25 this->owner = 0; 27 this->owner = NULL; 28 this->stack_owner = NULL; 26 29 this->recursion = 0; 27 30 } 28 29 //Array entering routine30 void enter(monitor_desc **, int count);31 void leave(monitor_desc **, int count);32 31 33 32 struct monitor_guard_t { 34 33 monitor_desc ** m; 35 34 int count; 35 monitor_desc ** prev_mntrs; 36 unsigned short prev_count; 36 37 }; 37 38 … … 40 41 } 41 42 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 ); 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; 47 57 } 48 58 49 static inline void ^?{}( monitor_guard_t * this ) { 50 leave( this->m, this->count ); 51 } 52 53 59 void wait( condition * this ); 60 void signal( condition * this ); 54 61 #endif //MONITOR_H -
src/libcfa/concurrency/monitor.c
r5c3632f rb3d70eba 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 appropriately 24 this->owner = owner; 25 26 //We are passing the monitor to someone else, which means recursion level is not 0 27 this->recursion = owner ? 1 : 0; 28 } 20 29 21 30 extern "C" { 22 void __enter_monitor_desc(monitor_desc * this ) {31 void __enter_monitor_desc(monitor_desc * this, monitor_desc * leader) { 23 32 lock( &this->lock ); 24 33 thread_desc * thrd = this_thread(); 25 34 35 // //Update the stack owner 36 // this->stack_owner = leader; 37 38 LIB_DEBUG_PRINT_SAFE("Entering %p (o: %p, r: %i)\n", this, this->owner, this->recursion); 39 26 40 if( !this->owner ) { 27 41 //No one has the monitor, just take it 28 this->owner = thrd; 29 this->recursion = 1; 42 set_owner( this, thrd ); 30 43 } 31 44 else if( this->owner == thrd) { … … 44 57 45 58 unlock( &this->lock ); 46 } 47 48 void __leave_monitor_desc(monitor_desc * this) { 59 return; 60 } 61 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) { 49 78 lock( &this->lock ); 50 79 80 LIB_DEBUG_PRINT_SAFE("Leaving %p (o: %p, r: %i)\n", this, this->owner, this->recursion); 81 51 82 thread_desc * thrd = this_thread(); 52 assert ( thrd == this->owner);83 assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", this->owner, thrd, this->recursion ); 53 84 54 85 //Leaving a recursion level, decrement the counter 55 86 this->recursion -= 1; 56 87 57 //If we left the last level of recursion it means we are changing who owns the monitor 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 // } 102 103 //We are the stack owner and have left the last recursion level. 104 //We are in charge of passing the monitor 58 105 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 ); 62 63 //We are passing the monitor to someone else, which means recursion level is not 0 64 this->recursion = new_owner ? 1 : 0; 65 } 66 106 107 //Check the signaller stack 108 new_owner = pop( &this->signal_stack ); 109 if( new_owner ) { 110 //The signaller stack is not empty, 111 //transfer control immediately 112 set_owner( this, new_owner ); 113 // this->stack_owner = leader; 114 ScheduleInternal( &this->lock, new_owner ); 115 return; 116 } 117 118 // No signaller thread 119 // Get the next thread in the entry_queue 120 new_owner = pop_head( &this->entry_queue ); 121 set_owner( this, new_owner ); 122 123 // //Update the stack owner 124 // this->stack_owner = leader; 125 126 //We can now let other threads in safely 67 127 unlock( &this->lock ); 68 128 69 //If we have a new owner, we need to wake-up the thread 70 if( new_owner ) { 71 ScheduleThread( new_owner ); 72 } 73 } 74 } 75 76 void enter(monitor_desc ** monitors, int count) { 77 for(int i = 0; i < count; i++) { 78 __enter_monitor_desc( monitors[i] ); 79 } 80 } 81 82 void leave(monitor_desc ** monitors, int count) { 83 for(int i = count - 1; i >= 0; i--) { 84 __leave_monitor_desc( monitors[i] ); 85 } 86 } 129 //We need to wake-up the thread 130 ScheduleThread( new_owner ); 131 } 132 } 133 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] ); 138 } 139 } 140 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] ); 145 } 146 } 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 scheduling 170 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 expected 183 assert( this->monitors != NULL ); 184 assert( this->monitor_count != 0 ); 185 186 unsigned int recursions[ count ]; //Save the current recursion levels to restore them later 187 spinlock * locks [ count ]; //We need to pass-in an array of locks to ScheduleInternal 188 189 // LIB_DEBUG_FPRINTF("Getting ready to wait\n"); 190 191 //Loop on all the monitors and release the owner 192 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 later 200 locks[i] = &cur->lock; 201 202 //Protect the monitors 203 lock( locks[i] ); 204 { 205 //Save the recursion levels 206 recursions[i] = cur->recursion; 207 208 //Release the owner 209 cur->recursion = 0; 210 cur->owner = NULL; 211 } 212 //Release the monitor 213 unlock( locks[i] ); 214 } 215 216 // LIB_DEBUG_FPRINTF("Waiting now\n"); 217 218 //Everything is ready to go to sleep 219 ScheduleInternal( locks, count ); 220 221 222 //WE WOKE UP 223 224 225 //We are back, restore the owners and recursions 226 for( unsigned int i = 0; i < count; i++ ) { 227 monitor_desc * cur = this->monitors[i]; 228 229 //Protect the monitors 230 lock( locks[i] ); 231 { 232 //Release the owner 233 cur->owner = this_thrd; 234 cur->recursion = recursions[i]; 235 } 236 //Release the monitor 237 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 expected 246 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 } // if 253 ); 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
r5c3632f rb3d70eba 39 39 this->mon.recursion = 1; 40 40 this->next = NULL; 41 42 this->current_monitors = NULL; 43 this->current_monitor_count = 0; 41 44 } 42 45 -
src/main.cc
r5c3632f rb3d70eba 304 304 GenPoly::box( translationUnit ); 305 305 306 // print tree right before code generation307 if ( codegenp ) {308 dump( translationUnit );309 return 0;310 } // if311 312 306 if ( optind < argc ) { // any commands after the flags and input file ? => output file name 313 307 output = new ofstream( argv[ optind ] ); 314 308 } // if 315 309 316 CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp );310 CodeGen::generate( translationUnit, *output, ! noprotop, prettycodegenp, true ); 317 311 318 312 CodeGen::FixMain::fix( *output, treep ? "../prelude/bootloader.c" : CFA_LIBDIR "/bootloader.c" ); … … 393 387 break; 394 388 case CtorInitFix: 395 case 'c': 389 case 'c': // print after constructors and destructors are replaced 396 390 ctorinitp = true; 397 391 break; … … 450 444 validp = true; 451 445 break; 452 case 'y': 446 case 'y': // dump AST on error 453 447 errorp = true; 454 448 break; 455 case 'z': 449 case 'z': // dump as codegen rather than AST 456 450 codegenp = true; 457 case 'Z': 451 break; 452 case 'Z': // prettyprint during codegen (i.e. print unmangled names, etc.) 458 453 prettycodegenp = true; 459 454 break; … … 501 496 } // if 502 497 503 printAll( decls, out ); 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 } 504 504 deleteAll( translationUnit ); 505 505 } // dump -
src/tests/.expect/memberCtors-ERR1.txt
r5c3632f rb3d70eba 1 memberCtors.c:62 error: in void ?{}( structB *b), field a2 used before being constructed1 memberCtors.c:62 error: in void ?{}(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.