Changeset 11a2d9b


Ignore:
Timestamp:
Oct 2, 2017, 6:02:32 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
21b7161
Parents:
3096ec1 (diff), 617b4b2 (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:/u/cforall/software/cfa/cfa-cc

Location:
src
Files:
2 added
12 edited

Legend:

Unmodified
Added
Removed
  • src/Concurrency/Keywords.cc

    r3096ec1 r11a2d9b  
    196196                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
    197197                void validate( DeclarationWithType * );
     198                void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    198199                void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &);
    199200
     
    206207                StructDecl* monitor_decl = nullptr;
    207208                StructDecl* guard_decl = nullptr;
     209                StructDecl* dtor_guard_decl = nullptr;
    208210
    209211                static std::unique_ptr< Type > generic_func;
     
    229231
    230232                void postvisit( FunctionDecl * decl );
     233                void previsit ( StructDecl   * decl );
    231234
    232235                void addStartStatement( FunctionDecl * decl, DeclarationWithType * param );
     
    236239                        acceptAll( translationUnit, impl );
    237240                }
     241
     242          private :
     243                bool thread_ctor_seen = false;
     244                StructDecl * thread_decl = nullptr;
    238245        };
    239246
     
    403410                if( mutexArgs.empty() ) return;
    404411
     412                if( CodeGen::isConstructor(decl->name) ) throw SemanticError( "constructors cannot have mutex parameters", decl );
     413
     414                bool isDtor = CodeGen::isDestructor( decl->name );
     415
     416                if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( "destructors can only have 1 mutex argument", decl );
     417
    405418                for(auto arg : mutexArgs) {
    406419                        validate( arg );
     
    412425                if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
    413426                if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
    414 
    415                 addStatments( decl, body, mutexArgs );
     427                if( !dtor_guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
     428
     429                if( isDtor ) {
     430                        addDtorStatments( decl, body, mutexArgs );
     431                }
     432                else {
     433                        addStatments( decl, body, mutexArgs );
     434                }
    416435        }
    417436
     
    425444                        assert( !guard_decl );
    426445                        guard_decl = decl;
     446                }
     447                else if( decl->name == "monitor_dtor_guard_t" ) {
     448                        assert( !dtor_guard_decl );
     449                        dtor_guard_decl = decl;
    427450                }
    428451        }
     
    457480                //Make sure that typed isn't mutex
    458481                if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
     482        }
     483
     484        void MutexKeyword::addDtorStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
     485                Type * arg_type = args.front()->get_type()->clone();
     486                arg_type->set_mutex( false );
     487
     488                ObjectDecl * monitors = new ObjectDecl(
     489                        "__monitor",
     490                        noStorage,
     491                        LinkageSpec::Cforall,
     492                        nullptr,
     493                        new PointerType(
     494                                noQualifiers,
     495                                new StructInstType(
     496                                        noQualifiers,
     497                                        monitor_decl
     498                                )
     499                        ),
     500                        new SingleInit( new UntypedExpr(
     501                                new NameExpr( "get_monitor" ),
     502                                {  new CastExpr( new VariableExpr( args.front() ), arg_type ) }
     503                        ))
     504                );
     505
     506                assert(generic_func);
     507
     508                //in reverse order :
     509                // monitor_guard_t __guard = { __monitors, #, func };
     510                body->push_front(
     511                        new DeclStmt( noLabels, new ObjectDecl(
     512                                "__guard",
     513                                noStorage,
     514                                LinkageSpec::Cforall,
     515                                nullptr,
     516                                new StructInstType(
     517                                        noQualifiers,
     518                                        dtor_guard_decl
     519                                ),
     520                                new ListInit(
     521                                        {
     522                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
     523                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )
     524                                        },
     525                                        noDesignators,
     526                                        true
     527                                )
     528                        ))
     529                );
     530
     531                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
     532                body->push_front( new DeclStmt( noLabels, monitors) );
    459533        }
    460534
     
    523597        // General entry routine
    524598        //=============================================================================================
     599        void ThreadStarter::previsit( StructDecl * decl ) {
     600                if( decl->name == "thread_desc" && decl->body ) {
     601                        assert( !thread_decl );
     602                        thread_decl = decl;
     603                }
     604        }
     605
    525606        void ThreadStarter::postvisit(FunctionDecl * decl) {
    526607                if( ! CodeGen::isConstructor(decl->name) ) return;
     608
     609                Type * typeof_this = InitTweak::getTypeofThis(decl->type);
     610                StructInstType * ctored_type = dynamic_cast< StructInstType * >( typeof_this );
     611                if( ctored_type && ctored_type->baseStruct == thread_decl ) {
     612                        thread_ctor_seen = true;
     613                }
    527614
    528615                DeclarationWithType * param = decl->get_functionType()->get_parameters().front();
    529616                auto type  = dynamic_cast< StructInstType * >( InitTweak::getPointerBase( param->get_type() ) );
    530617                if( type && type->get_baseStruct()->is_thread() ) {
     618                        if( !thread_decl || !thread_ctor_seen ) {
     619                                throw SemanticError("thread keyword requires threads to be in scope, add #include <thread>");
     620                        }
     621
    531622                        addStartStatement( decl, param );
    532623                }
  • src/InitTweak/InitTweak.cc

    r3096ec1 r11a2d9b  
    270270        }
    271271
    272         Type * getThisType( FunctionType * ftype ) {
    273                 assertf( ftype, "getThisType: nullptr ftype" );
    274                 ObjectDecl * thisParam = getThisParam( ftype );
     272        Type * getTypeofThis( FunctionType * ftype ) {
     273                assertf( ftype, "getTypeofThis: nullptr ftype" );
     274                ObjectDecl * thisParam = getParamThis( ftype );
    275275                ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( thisParam->type );
    276276                return refType->base;
    277277        }
    278278
    279         ObjectDecl * getThisParam( FunctionType * ftype ) {
    280                 assertf( ftype, "getThisParam: nullptr ftype" );
     279        ObjectDecl * getParamThis( FunctionType * ftype ) {
     280                assertf( ftype, "getParamThis: nullptr ftype" );
    281281                auto & params = ftype->parameters;
    282                 assertf( ! params.empty(), "getThisParam: ftype with 0 parameters: %s", toString( ftype ).c_str() );
     282                assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( ftype ).c_str() );
    283283                return strict_dynamic_cast< ObjectDecl * >( params.front() );
    284284        }
  • src/InitTweak/InitTweak.h

    r3096ec1 r11a2d9b  
    3131
    3232        /// returns the base type of the first parameter to a constructor/destructor/assignment function
    33         Type * getThisType( FunctionType * ftype );
     33        Type * getTypeofThis( FunctionType * ftype );
    3434
    3535        /// returns the first parameter of a constructor/destructor/assignment function
    36         ObjectDecl * getThisParam( FunctionType * ftype );
     36        ObjectDecl * getParamThis( FunctionType * ftype );
    3737
    3838        /// transform Initializer into an argument list that can be passed to a call expression
  • src/Parser/ExpressionNode.cc

    r3096ec1 r11a2d9b  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Sep 26 11:23:36 2017
    13 // Update Count     : 780
     12// Last Modified On : Wed Sep 27 22:51:55 2017
     13// Update Count     : 781
    1414//
    1515
     
    207207
    208208        assert( 0 <= size && size < 6 );
     209        // Constant type is correct for overload resolving.
    209210        ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][size] ), str, v ) );
    210         if ( size < 2 ) {                                                                       // hh or h, less than int ?
     211        if ( Unsigned && size < 2 ) {                                           // hh or h, less than int ?
    211212                // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
    212213                ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][size] ) );
  • src/libcfa/concurrency/invoke.h

    r3096ec1 r11a2d9b  
    9696            struct __condition_stack_t signal_stack;  // stack of conditions to run next once we exit the monitor
    9797            unsigned int recursion;                   // monitor routines can be called recursively, we need to keep track of that
    98             struct __waitfor_mask_t mask;               // mask used to know if some thread is waiting for something while holding the monitor
     98            struct __waitfor_mask_t mask;             // mask used to know if some thread is waiting for something while holding the monitor
     99            struct __condition_node_t * dtor_node;    // node used to signal the dtor in a waitfor dtor
    99100      };
    100101
  • src/libcfa/concurrency/monitor

    r3096ec1 r11a2d9b  
    2929static inline void ?{}(monitor_desc & this) {
    3030        (this.lock){};
    31         this.owner = NULL;
    3231        (this.entry_queue){};
    3332        (this.signal_stack){};
    34         this.recursion = 0;
     33        this.owner         = NULL;
     34        this.recursion     = 0;
    3535        this.mask.accepted = NULL;
    3636        this.mask.clauses  = NULL;
    3737        this.mask.size     = 0;
     38        this.dtor_node     = NULL;
    3839}
     40
     41// static inline int ?<?(monitor_desc* lhs, monitor_desc* rhs) {
     42//      return ((intptr_t)lhs) < ((intptr_t)rhs);
     43// }
    3944
    4045struct monitor_guard_t {
     
    4651};
    4752
    48 static inline int ?<?(monitor_desc* lhs, monitor_desc* rhs) {
    49         return ((intptr_t)lhs) < ((intptr_t)rhs);
    50 }
    51 
    5253void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, void (*func)() );
    5354void ^?{}( monitor_guard_t & this );
     55
     56
     57struct monitor_dtor_guard_t {
     58        monitor_desc * m;
     59        monitor_desc ** prev_mntrs;
     60        unsigned short  prev_count;
     61        fptr_t          prev_func;
     62};
     63
     64void ?{}( monitor_dtor_guard_t & this, monitor_desc ** m, void (*func)() );
     65void ^?{}( monitor_dtor_guard_t & this );
    5466
    5567//-----------------------------------------------------------------------------
  • src/libcfa/concurrency/monitor.c

    r3096ec1 r11a2d9b  
    9494                }
    9595                else if( this->owner == thrd) {
    96                         // We already have the monitor, just not how many times we took it
     96                        // We already have the monitor, just note how many times we took it
    9797                        verify( this->recursion > 0 );
    9898                        this->recursion += 1;
     
    127127                unlock( &this->lock );
    128128                return;
     129        }
     130
     131        static void __enter_monitor_dtor( monitor_desc * this, fptr_t func ) {
     132                // Lock the monitor spinlock, lock_yield to reduce contention
     133                lock_yield( &this->lock DEBUG_CTX2 );
     134                thread_desc * thrd = this_thread;
     135
     136                LIB_DEBUG_PRINT_SAFE("Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     137
     138
     139                if( !this->owner ) {
     140                        LIB_DEBUG_PRINT_SAFE("Kernel : Destroying free mon %p\n", this);
     141
     142                        // No one has the monitor, just take it
     143                        set_owner( this, thrd );
     144
     145                        unlock( &this->lock );
     146                        return;
     147                }
     148                else if( this->owner == thrd) {
     149                        // We already have the monitor... but where about to destroy it so the nesting will fail
     150                        // Abort!
     151                        abortf("Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.");
     152                }
     153
     154                int count = 1;
     155                monitor_desc ** monitors = &this;
     156                __monitor_group_t group = { &this, 1, func };
     157                if( is_accepted( this, group) ) {
     158                        LIB_DEBUG_PRINT_SAFE("Kernel :  mon accepts dtor, block and signal it \n");
     159
     160                        // Wake the thread that is waiting for this
     161                        __condition_criterion_t * urgent = pop( &this->signal_stack );
     162                        verify( urgent );
     163
     164                        // Reset mask
     165                        reset_mask( this );
     166
     167                        // Create the node specific to this wait operation
     168                        wait_ctx_primed( this_thread, 0 )
     169
     170                        // Some one else has the monitor, wait for him to finish and then run
     171                        BlockInternal( &this->lock, urgent->owner->waiting_thread );
     172
     173                        // Some one was waiting for us, enter
     174                        set_owner( this, thrd );
     175                }
     176                else {
     177                        LIB_DEBUG_PRINT_SAFE("Kernel :  blocking \n");
     178
     179                        wait_ctx( this_thread, 0 )
     180                        this->dtor_node = &waiter;
     181
     182                        // Some one else has the monitor, wait in line for it
     183                        append( &this->entry_queue, thrd );
     184                        BlockInternal( &this->lock );
     185
     186                        // BlockInternal will unlock spinlock, no need to unlock ourselves
     187                        return;
     188                }
     189
     190                LIB_DEBUG_PRINT_SAFE("Kernel : Destroying %p\n", this);
     191
    129192        }
    130193
     
    158221        }
    159222
     223        // Leave single monitor for the last time
     224        void __leave_dtor_monitor_desc( monitor_desc * this ) {
     225                LIB_DEBUG_DO(
     226                        if( this_thread != this->owner ) {
     227                                abortf("Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, this_thread, this->owner);
     228                        }
     229                        if( this->recursion != 1 ) {
     230                                abortf("Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
     231                        }
     232                )
     233        }
     234
    160235        // Leave the thread monitor
    161236        // last routine called by a thread.
     
    210285// Ctor for monitor guard
    211286// Sorts monitors before entering
    212 void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, void (*func)() ) {
     287void ?{}( monitor_guard_t & this, monitor_desc ** m, int count, fptr_t func ) {
    213288        // Store current array
    214289        this.m = m;
     
    246321
    247322        // LIB_DEBUG_PRINT_SAFE("MGUARD : left\n");
     323
     324        // Restore thread context
     325        this_thread->monitors.list = this.prev_mntrs;
     326        this_thread->monitors.size = this.prev_count;
     327        this_thread->monitors.func = this.prev_func;
     328}
     329
     330
     331// Ctor for monitor guard
     332// Sorts monitors before entering
     333void ?{}( monitor_dtor_guard_t & this, monitor_desc ** m, fptr_t func ) {
     334        // Store current array
     335        this.m = *m;
     336
     337        // Save previous thread context
     338        this.prev_mntrs = this_thread->monitors.list;
     339        this.prev_count = this_thread->monitors.size;
     340        this.prev_func  = this_thread->monitors.func;
     341
     342        // Update thread context (needed for conditions)
     343        this_thread->monitors.list = m;
     344        this_thread->monitors.size = 1;
     345        this_thread->monitors.func = func;
     346
     347        __enter_monitor_dtor( this.m, func );
     348}
     349
     350
     351// Dtor for monitor guard
     352void ^?{}( monitor_dtor_guard_t & this ) {
     353        // Leave the monitors in order
     354        __leave_dtor_monitor_desc( this.m );
    248355
    249356        // Restore thread context
     
    448555                        *mask.accepted = index;
    449556                        if( mask.clauses[index].is_dtor ) {
    450                                 #warning case not implemented
     557                                LIB_DEBUG_PRINT_SAFE("Kernel : dtor already there\n");
     558                                verifyf( mask.clauses[index].size == 1        , "ERROR: Accepted dtor has more than 1 mutex parameter." );
     559
     560                                monitor_desc * mon2dtor = mask.clauses[index].list[0];
     561                                verifyf( mon2dtor->dtor_node, "ERROR: Accepted monitor has no dtor_node." );
     562
     563                                __condition_criterion_t * dtor_crit = mon2dtor->dtor_node->criteria;
     564                                push( &mon2dtor->signal_stack, dtor_crit );
     565
     566                                unlock_all( locks, count );
    451567                        }
    452568                        else {
  • src/tests/.expect/64/literals.txt

    r3096ec1 r11a2d9b  
    12521252    ((void)(-((long double )0x.0123456789p09)));
    12531253    ((void)__f__F_c__1('a'));
    1254     ((void)__f__F_Sc__1(((signed char )20)));
     1254    ((void)__f__F_Sc__1(20));
    12551255    ((void)__f__F_Uc__1(((unsigned char )21u)));
    1256     ((void)__f__F_s__1(((signed short int )22)));
     1256    ((void)__f__F_s__1(22));
    12571257    ((void)__f__F_Us__1(((unsigned short int )23u)));
    12581258    ((void)__f__F_Ul__1(((unsigned long int )24)));
  • src/tests/Makefile.am

    r3096ec1 r11a2d9b  
    2222concurrent = yes
    2323quick_test += coroutine thread monitor
    24 concurrent_test = coroutine thread monitor multi-monitor sched-int-block sched-int-disjoint sched-int-wait sched-ext-barge sched-ext-else sched-ext-parse sched-ext-statment preempt
     24concurrent_test =        \
     25        coroutine          \
     26        thread             \
     27        monitor            \
     28        multi-monitor      \
     29        preempt            \
     30        sched-int-block    \
     31        sched-int-disjoint \
     32        sched-int-wait     \
     33        sched-ext-barge    \
     34        sched-ext-dtor     \
     35        sched-ext-else     \
     36        sched-ext-parse    \
     37        sched-ext-recurse  \
     38        sched-ext-statment \
     39        sched-ext-when
     40
    2541else
    2642concurrent=no
  • src/tests/Makefile.in

    r3096ec1 r11a2d9b  
    320320@BUILD_CONCURRENCY_TRUE@concurrent = yes
    321321@BUILD_CONCURRENCY_FALSE@concurrent_test =
    322 @BUILD_CONCURRENCY_TRUE@concurrent_test = coroutine thread monitor multi-monitor sched-int-block sched-int-disjoint sched-int-wait sched-ext-barge sched-ext-else sched-ext-parse sched-ext-statment preempt
     322@BUILD_CONCURRENCY_TRUE@concurrent_test = \
     323@BUILD_CONCURRENCY_TRUE@        coroutine          \
     324@BUILD_CONCURRENCY_TRUE@        thread             \
     325@BUILD_CONCURRENCY_TRUE@        monitor            \
     326@BUILD_CONCURRENCY_TRUE@        multi-monitor      \
     327@BUILD_CONCURRENCY_TRUE@        preempt            \
     328@BUILD_CONCURRENCY_TRUE@        sched-int-block    \
     329@BUILD_CONCURRENCY_TRUE@        sched-int-disjoint \
     330@BUILD_CONCURRENCY_TRUE@        sched-int-wait     \
     331@BUILD_CONCURRENCY_TRUE@        sched-ext-barge    \
     332@BUILD_CONCURRENCY_TRUE@        sched-ext-dtor     \
     333@BUILD_CONCURRENCY_TRUE@        sched-ext-else     \
     334@BUILD_CONCURRENCY_TRUE@        sched-ext-parse    \
     335@BUILD_CONCURRENCY_TRUE@        sched-ext-recurse  \
     336@BUILD_CONCURRENCY_TRUE@        sched-ext-statment \
     337@BUILD_CONCURRENCY_TRUE@        sched-ext-when
     338
    323339
    324340# applies to both programs
  • src/tests/coroutine.c

    r3096ec1 r11a2d9b  
    1010// Created On       : Thu Jun  8 07:29:37 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun  8 07:37:12 2017
    13 // Update Count     : 5
     12// Last Modified On : Sun Sep 17 21:38:15 2017
     13// Update Count     : 7
    1414//
    1515
     
    1818
    1919coroutine Fibonacci {
    20         int fn;                                         // used for communication
     20        int fn;                                                                                         // used for communication
    2121};
    2222
     
    2626
    2727void main( Fibonacci & this ) {
    28         int fn1, fn2;                                   // retained between resumes
    29         this.fn = 0;                                    // case 0
     28        int fn1, fn2;                                                                           // retained between resumes
     29        this.fn = 0;                                                                            // case 0
    3030        fn1 = this.fn;
    31         suspend();                                              // return to last resume
     31        suspend();                                                                                      // restart last resume
    3232
    33         this.fn = 1;                                    // case 1
    34         fn2 = fn1;
    35         fn1 = this.fn;
    36         suspend();                                              // return to last resume
     33        this.fn = 1;                                                                            // case 1
     34        fn2 = fn1;  fn1 = this.fn;
     35        suspend();                                                                                      // restart last resume
    3736
    38         for ( ;; ) {                                    // general case
     37        for ( ;; ) {                                                                            // general case
    3938                this.fn = fn1 + fn2;
    40                 fn2 = fn1;
    41                 fn1 = this.fn;
    42                 suspend();                                      // return to last resume
     39                fn2 = fn1;  fn1 = this.fn;
     40                suspend();                                                                              // restart last resume
    4341        } // for
    4442}
    4543
    4644int next( Fibonacci & this ) {
    47         resume( this );                                 // transfer to last suspend
     45        resume( this );                                                                         // restart last suspend
    4846        return this.fn;
    4947}
     
    5250        Fibonacci f1, f2;
    5351        for ( int i = 1; i <= 10; i += 1 ) {
    54                 sout | next( f1 ) | ' ' | next( f2 ) | endl;
     52                sout | next( f1 ) | next( f2 ) | endl;
    5553        } // for
    5654}
  • src/tests/gmp.c

    r3096ec1 r11a2d9b  
    1010// Created On       : Tue Apr 19 08:55:51 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep  4 09:51:18 2017
    13 // Update Count     : 550
     12// Last Modified On : Thu Sep 28 18:33:51 2017
     13// Update Count     : 555
    1414//
    1515
     
    9797
    9898        sout | "Factorial Numbers" | endl;
    99         Int fact;
    100         fact = 1;                                                                                       // 1st case
     99        Int fact = 1;                                                                           // 1st case
    101100        sout | (int)0 | fact | endl;
    102101        for ( unsigned int i = 1; i <= 40; i += 1 ) {
Note: See TracChangeset for help on using the changeset viewer.