Changeset af67ee1


Ignore:
Timestamp:
Aug 27, 2021, 12:51:55 PM (10 months ago)
Author:
caparsons <caparson@…>
Branches:
enum, forall-pointer-decay, jacob/cs343-translation, master
Children:
1b97976
Parents:
9f5a19fa
Message:

Added support for locks as parameters to mutex stmt

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    r9f5a19fa raf67ee1  
    116116        concurrency/monitor.hfa \
    117117        concurrency/mutex.hfa \
    118         concurrency/thread.hfa
     118        concurrency/thread.hfa \
     119        concurrency/mutex_stmt.hfa
    119120
    120121thread_libsrc = ${inst_thread_headers_src} ${inst_thread_headers_src:.hfa=.cfa} \
  • libcfa/src/concurrency/monitor.cfa

    r9f5a19fa raf67ee1  
    990990}
    991991
     992//-----------------------------------------------------------------------------
     993// Enter routine for mutex stmt
     994// Can't be accepted since a mutex stmt is effectively an anonymous routine
     995// Thus we do not need a monitor group
     996void lock( monitor$ * this ) {
     997        thread$ * thrd = active_thread();
     998
     999        // Lock the monitor spinlock
     1000        lock( this->lock __cfaabi_dbg_ctx2 );
     1001
     1002        __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
     1003
     1004        if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) {
     1005                abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this );
     1006        }
     1007        else if( !this->owner ) {
     1008                // No one has the monitor, just take it
     1009                __set_owner( this, thrd );
     1010
     1011                __cfaabi_dbg_print_safe( "Kernel :  mon is free \n" );
     1012        }
     1013        else if( this->owner == thrd) {
     1014                // We already have the monitor, just note how many times we took it
     1015                this->recursion += 1;
     1016
     1017                __cfaabi_dbg_print_safe( "Kernel :  mon already owned \n" );
     1018        }
     1019        else {
     1020                __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
     1021
     1022                // Some one else has the monitor, wait in line for it
     1023                /* paranoid */ verify( thrd->link.next == 0p );
     1024                append( this->entry_queue, thrd );
     1025                /* paranoid */ verify( thrd->link.next == 1p );
     1026
     1027                unlock( this->lock );
     1028                park();
     1029
     1030                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     1031
     1032                /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     1033                return;
     1034        }
     1035
     1036        __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     1037
     1038        /* paranoid */ verifyf( active_thread() == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", active_thread(), this->owner, this->recursion, this );
     1039        /* paranoid */ verify( this->lock.lock );
     1040
     1041        // Release the lock and leave
     1042        unlock( this->lock );
     1043        return;
     1044}
     1045
     1046// Leave routine for mutex stmt
     1047// Is just a wrapper around __leave for the is_lock trait to see
     1048void unlock( monitor$ * this ) { __leave( this ); }
     1049
    9921050// Local Variables: //
    9931051// mode: c //
  • libcfa/src/concurrency/monitor.hfa

    r9f5a19fa raf67ee1  
    149149void __waitfor_internal( const __waitfor_mask_t & mask, int duration );
    150150
     151// lock and unlock routines for mutex statements to use
     152void lock( monitor$ * this );
     153void unlock( monitor$ * this );
     154
    151155// Local Variables: //
    152156// mode: c //
  • src/Concurrency/Keywords.cc

    r9f5a19fa raf67ee1  
    9393                ObjectDecl * addField( StructDecl * );
    9494                void addRoutines( ObjectDecl *, FunctionDecl * );
     95                void addLockUnlockRoutines( StructDecl * );
    9596
    9697                virtual bool is_target( StructDecl * decl ) = 0;
     
    322323                StructDecl* dtor_guard_decl = nullptr;
    323324                StructDecl* thread_guard_decl = nullptr;
     325                StructDecl* lock_guard_decl = nullptr;
    324326
    325327                static std::unique_ptr< Type > generic_func;
     
    463465        }
    464466
    465 
    466467        void ConcurrentSueKeyword::handle( StructDecl * decl ) {
    467468                if( ! decl->body ) return;
     
    479480                FunctionDecl * func = forwardDeclare( decl );
    480481                ObjectDecl * field = addField( decl );
     482
     483                // add get_.* routine
    481484                addRoutines( field, func );
     485                // add lock/unlock routines to monitors for use by mutex stmt
     486                addLockUnlockRoutines( decl );
    482487        }
    483488
     
    612617        }
    613618
     619        // This function adds the get_.* routine body for coroutines, monitors etc
     620        //              after their corresponding struct has been made
    614621        void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
    615622                CompoundStmt * statement = new CompoundStmt();
     
    634641
    635642                declsToAddAfter.push_back( get_decl );
     643        }
     644
     645        // Generates lock/unlock routines for monitors to be used by mutex stmts
     646        void ConcurrentSueKeyword::addLockUnlockRoutines( StructDecl * decl ) {
     647                // this routine will be called for all ConcurrentSueKeyword children so only continue if we are a monitor
     648                if ( !decl->is_monitor() ) return;
     649
     650                FunctionType * lock_fn_type = new FunctionType( noQualifiers, false );
     651                FunctionType * unlock_fn_type = new FunctionType( noQualifiers, false );
     652
     653                // create this ptr parameter for both routines
     654                ObjectDecl * this_decl = new ObjectDecl(
     655                        "this",
     656                        noStorageClasses,
     657                        LinkageSpec::Cforall,
     658                        nullptr,
     659                        new ReferenceType(
     660                                noQualifiers,
     661                                new StructInstType(
     662                                        noQualifiers,
     663                                        decl
     664                                )
     665                        ),
     666                        nullptr
     667                );
     668
     669                lock_fn_type->get_parameters().push_back( this_decl->clone() );
     670                unlock_fn_type->get_parameters().push_back( this_decl->clone() );
     671
     672                delete this_decl;
     673
     674
     675                //////////////////////////////////////////////////////////////////////
     676                // The following generates this lock routine for all monitors
     677                /*
     678                        void lock (monitor_t & this) {
     679                                lock(get_monitor(this));
     680                        }       
     681                */
     682                FunctionDecl * lock_decl = new FunctionDecl(
     683                        "lock",
     684                        Type::Static,
     685                        LinkageSpec::Cforall,
     686                        lock_fn_type,
     687                        nullptr,
     688                        { },
     689                        Type::Inline
     690                );
     691                fixupGenerics(lock_fn_type, decl);
     692
     693                UntypedExpr * get_monitor_lock =  new UntypedExpr (
     694                        new NameExpr( "get_monitor" ),
     695                        { new VariableExpr( lock_fn_type->get_parameters().front() ) }
     696                );
     697
     698                CompoundStmt * lock_statement = new CompoundStmt();
     699                lock_statement->push_back(
     700                        new ExprStmt(
     701                                new UntypedExpr (
     702                                        new NameExpr( "lock" ),
     703                                        {
     704                                                get_monitor_lock
     705                                        }
     706                                )
     707                        )
     708                );
     709                lock_decl->set_statements( lock_statement );
     710
     711                //////////////////////////////////////////////////////////////////
     712                // The following generates this routine for all monitors
     713                /*
     714                        void unlock (monitor_t & this) {
     715                                unlock(get_monitor(this));
     716                        }       
     717                */
     718                FunctionDecl * unlock_decl = new FunctionDecl(
     719                        "unlock",
     720                        Type::Static,
     721                        LinkageSpec::Cforall,
     722                        unlock_fn_type,
     723                        nullptr,
     724                        { },
     725                        Type::Inline
     726                );
     727                fixupGenerics(unlock_fn_type, decl);
     728
     729                CompoundStmt * unlock_statement = new CompoundStmt();
     730
     731                UntypedExpr * get_monitor_unlock =  new UntypedExpr (
     732                        new NameExpr( "get_monitor" ),
     733                        { new VariableExpr( unlock_fn_type->get_parameters().front() ) }
     734                );
     735
     736                unlock_statement->push_back(
     737                        new ExprStmt(
     738                                new UntypedExpr(
     739                                        new NameExpr( "unlock" ),
     740                                        {
     741                                                get_monitor_unlock
     742                                        }
     743                                )
     744                        )
     745                );
     746                unlock_decl->set_statements( unlock_statement );
     747               
     748                // pushes routines to declsToAddAfter to add at a later time
     749                declsToAddAfter.push_back( lock_decl );
     750                declsToAddAfter.push_back( unlock_decl );
    636751        }
    637752
     
    9371052                        assert( !thread_guard_decl );
    9381053                        thread_guard_decl = decl;
     1054                }
     1055                else if ( decl->name == "__mutex_stmt_lock_guard" && decl->body ) {
     1056                        assert( !lock_guard_decl );
     1057                        lock_guard_decl = decl;
    9391058                }
    9401059        }
     
    10811200                                new PointerType(
    10821201                                        noQualifiers,
    1083                                         new StructInstType(
    1084                                                 noQualifiers,
    1085                                                 monitor_decl
    1086                                         )
     1202                                        new TypeofType( noQualifiers, args.front()->clone() )
    10871203                                ),
    10881204                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
     
    10931209                                map_range < std::list<Initializer*> > ( args, [](Expression * var ){
    10941210                                        return new SingleInit( new UntypedExpr(
    1095                                                 new NameExpr( "get_monitor" ),
     1211                                                new NameExpr( "__get_pointer" ),
    10961212                                                { var }
    10971213                                        ) );
     
    10991215                        )
    11001216                );
     1217
     1218                StructInstType * lock_guard_struct = new StructInstType( noQualifiers, lock_guard_decl );
     1219                TypeExpr * lock_type_expr = new TypeExpr( new TypeofType( noQualifiers, args.front()->clone() ) );
     1220
     1221                lock_guard_struct->parameters.push_back( lock_type_expr ) ;
    11011222
    11021223                // in reverse order :
     
    11081229                                LinkageSpec::Cforall,
    11091230                                nullptr,
    1110                                 new StructInstType(
    1111                                         noQualifiers,
    1112                                         guard_decl
    1113                                 ),
     1231                                lock_guard_struct,
    11141232                                new ListInit(
    11151233                                        {
  • tests/concurrent/mutexstmt/locks.cfa

    r9f5a19fa raf67ee1  
    1 #include <mutex_stmt_locks.hfa>
     1#include <mutex_stmt.hfa>
    22#include <locks.hfa>
    33
     
    1313        for (unsigned int i = 0; i < num_times; i++) {
    1414                mutex ( m1 ) count++;
    15                 mutex ( m1 ) {
     15                mutex ( m1 ) { 
    1616                        assert(!insideFlag);
    1717                        insideFlag = true;
     
    6565        printf("Start Test: single lock mutual exclusion\n");
    6666        {
    67                 T_Mutex t[10];
     67                T_Mutex t[1];
    6868        }
    6969        printf("End Test: single lock mutual exclusion\n");
  • tests/concurrent/mutexstmt/monitors.cfa

    r9f5a19fa raf67ee1  
    11#include <monitor.hfa>
     2#include <mutex_stmt.hfa>
    23#include <stdio.h>
    34#include <stdlib.hfa>
     
    1314bool insideFlag = false;
    1415int count = 0;
     16bool startFlag = false;
    1517
    1618void main( T_Mutex & this ) {
Note: See TracChangeset for help on using the changeset viewer.