Changeset 98d1b90


Ignore:
Timestamp:
Mar 21, 2022, 12:17:27 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
Children:
4ecc35a
Parents:
adb3ea1 (diff), 41d3c8d (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:software/cfa/cfa-cc

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/locks.hfa

    radb3ea1 r98d1b90  
    164164}
    165165
    166 static inline bool lock(linear_backoff_then_block_lock & this) with(this) {
     166static inline void lock(linear_backoff_then_block_lock & this) with(this) {
    167167        // if owner just return
    168         if (active_thread() == owner) return true;
     168        if (active_thread() == owner) return;
    169169        size_t compare_val = 0;
    170170        int spin = spin_start;
     
    172172        for( ;; ) {
    173173                compare_val = 0;
    174                 if (internal_try_lock(this, compare_val)) return true;
     174                if (internal_try_lock(this, compare_val)) return;
    175175                if (2 == compare_val) break;
    176176                for (int i = 0; i < spin; i++) Pause();
     
    179179        }
    180180
    181         if(2 != compare_val && try_lock_contention(this)) return true;
     181        if(2 != compare_val && try_lock_contention(this)) return;
    182182        // block until signalled
    183         while (block(this)) if(try_lock_contention(this)) return true;
    184 
    185         // this should never be reached as block(this) always returns true
    186         return false;
     183        while (block(this)) if(try_lock_contention(this)) return;
    187184}
    188185
  • libcfa/src/concurrency/mutex_stmt.hfa

    radb3ea1 r98d1b90  
    1212};
    1313
     14
     15struct __mutex_stmt_lock_guard {
     16    void ** lockarr;
     17    __lock_size_t count;
     18};
     19
     20static inline void ?{}( __mutex_stmt_lock_guard & this, void * lockarr [], __lock_size_t count  ) {
     21    this.lockarr = lockarr;
     22    this.count = count;
     23
     24    // Sort locks based on address
     25    __libcfa_small_sort(this.lockarr, count);
     26
     27    // acquire locks in order
     28    // for ( size_t i = 0; i < count; i++ ) {
     29    //     lock(*this.lockarr[i]);
     30    // }
     31}
     32
     33static inline void ^?{}( __mutex_stmt_lock_guard & this ) with(this) {
     34    // for ( size_t i = count; i > 0; i-- ) {
     35    //     unlock(*lockarr[i - 1]);
     36    // }
     37}
     38
    1439forall(L & | is_lock(L)) {
    15 
    16     struct __mutex_stmt_lock_guard {
    17         L ** lockarr;
    18         __lock_size_t count;
    19     };
    20    
    21     static inline void ?{}( __mutex_stmt_lock_guard(L) & this, L * lockarr [], __lock_size_t count  ) {
    22         this.lockarr = lockarr;
    23         this.count = count;
    24 
    25         // Sort locks based on address
    26         __libcfa_small_sort(this.lockarr, count);
    27 
    28         // acquire locks in order
    29         for ( size_t i = 0; i < count; i++ ) {
    30             lock(*this.lockarr[i]);
    31         }
    32     }
    33    
    34     static inline void ^?{}( __mutex_stmt_lock_guard(L) & this ) with(this) {
    35         for ( size_t i = count; i > 0; i-- ) {
    36             unlock(*lockarr[i - 1]);
    37         }
    38     }
    3940
    4041    struct scoped_lock {
     
    5152    }
    5253
    53     static inline L * __get_ptr( L & this ) {
     54    static inline void * __get_mutexstmt_lock_ptr( L & this ) {
    5455        return &this;
    5556    }
    5657
    57     static inline L __get_type( L & this );
     58    static inline L __get_mutexstmt_lock_type( L & this );
    5859
    59     static inline L __get_type( L * this );
     60    static inline L __get_mutexstmt_lock_type( L * this );
    6061}
  • src/Concurrency/Keywords.cc

    radb3ea1 r98d1b90  
    12041204                                        //new TypeofType( noQualifiers, args.front()->clone() )
    12051205                                        new TypeofType( noQualifiers, new UntypedExpr(
    1206                                                         new NameExpr( "__get_type" ),
     1206                                                        new NameExpr( "__get_mutexstmt_lock_type" ),
    12071207                                                        { args.front()->clone() }
    12081208                                                )
     
    12161216                                map_range < std::list<Initializer*> > ( args, [](Expression * var ){
    12171217                                        return new SingleInit( new UntypedExpr(
    1218                                                         new NameExpr( "__get_ptr" ),
     1218                                                        new NameExpr( "__get_mutexstmt_lock_ptr" ),
    12191219                                                        { var }
    12201220                                        ) );
     
    12271227                TypeExpr * lock_type_expr = new TypeExpr(
    12281228                        new TypeofType( noQualifiers, new UntypedExpr(
    1229                                 new NameExpr( "__get_type" ),
     1229                                new NameExpr( "__get_mutexstmt_lock_type" ),
    12301230                                { args.front()->clone() }
    12311231                                )
  • src/Concurrency/KeywordsNew.cpp

    radb3ea1 r98d1b90  
    1414//
    1515
     16#include <iostream>
     17
    1618#include "Concurrency/Keywords.h"
    1719
     
    2628#include "Common/Examine.h"
    2729#include "Common/utility.h"
     30#include "Common/UniqueName.h"
    2831#include "ControlStruct/LabelGeneratorNew.hpp"
    2932#include "InitTweak/InitTweak.h"
     
    167170        const ast::StructDecl * typeid_decl = nullptr;
    168171        const ast::StructDecl * vtable_decl = nullptr;
     172
    169173};
    170174
     
    874878
    875879// --------------------------------------------------------------------------
    876 struct MutexKeyword final {
     880struct MutexKeyword final : public ast::WithDeclsToAdd<> {
    877881        const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl );
    878882        void postvisit( const ast::StructDecl * decl );
     
    887891        ast::CompoundStmt * addStatements( const ast::CompoundStmt * body, const std::vector<ast::ptr<ast::Expr>> & args );
    888892        ast::CompoundStmt * addThreadDtorStatements( const ast::FunctionDecl* func, const ast::CompoundStmt * body, const std::vector<const ast::DeclWithType *> & args );
    889 
     893        ast::ExprStmt * genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param);
     894        ast::IfStmt * genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam );
    890895private:
    891896        const ast::StructDecl * monitor_decl = nullptr;
     
    896901
    897902        static ast::ptr<ast::Type> generic_func;
     903
     904        UniqueName mutex_func_namer = UniqueName("__lock_unlock_curr");
    898905};
    899906
     
    9971004
    9981005const ast::Stmt * MutexKeyword::postvisit( const ast::MutexStmt * stmt ) {
     1006        if ( !lock_guard_decl ) {
     1007                SemanticError( stmt->location, "mutex stmt requires a header, add #include <mutex_stmt.hfa>\n" );
     1008        }
    9991009        ast::CompoundStmt * body =
    10001010                        new ast::CompoundStmt( stmt->location, { stmt->stmt } );
    1001         addStatements( body, stmt->mutexObjs );
    1002         return body;
     1011       
     1012        return addStatements( body, stmt->mutexObjs );;
    10031013}
    10041014
     
    11951205}
    11961206
     1207// generates a cast to the void ptr to the appropriate lock type and dereferences it before calling lock or unlock on it
     1208// used to undo the type erasure done by storing all the lock pointers as void
     1209ast::ExprStmt * MutexKeyword::genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param ) {
     1210        return new ast::ExprStmt( location,
     1211                new ast::UntypedExpr( location,
     1212                        new ast::NameExpr( location, fnName ), {
     1213                                ast::UntypedExpr::createDeref(
     1214                                        location,
     1215                                        new ast::CastExpr( location,
     1216                                                param,
     1217                                                new ast::PointerType( new ast::TypeofType( new ast::UntypedExpr(
     1218                                                        expr->location,
     1219                                                        new ast::NameExpr( expr->location, "__get_mutexstmt_lock_type" ),
     1220                                                        { expr }
     1221                                                ) ) ),
     1222                                                ast::GeneratedFlag::ExplicitCast
     1223                                        )
     1224                                )
     1225                        }
     1226                )
     1227        );
     1228}
     1229
     1230ast::IfStmt * MutexKeyword::genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ) {
     1231        ast::IfStmt * outerLockIf = nullptr;
     1232        ast::IfStmt * lastLockIf = nullptr;
     1233
     1234        //adds an if/elif clause for each lock to assign type from void ptr based on ptr address
     1235        for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1236               
     1237                ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
     1238                        new ast::NameExpr( location, "?==?" ), {
     1239                                ast::deepCopy( thisParam ),
     1240                                new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
     1241                        }
     1242                );
     1243
     1244                ast::IfStmt * currLockIf = new ast::IfStmt(
     1245                        location,
     1246                        ifCond,
     1247                        genVirtLockUnlockExpr( fnName, args.at(i), location, ast::deepCopy( thisParam ) )
     1248                );
     1249               
     1250                if ( i == 0 ) {
     1251                        outerLockIf = currLockIf;
     1252                } else {
     1253                        // add ifstmt to else of previous stmt
     1254                        lastLockIf->else_ = currLockIf;
     1255                }
     1256
     1257                lastLockIf = currLockIf;
     1258        }
     1259        return outerLockIf;
     1260}
     1261
    11971262ast::CompoundStmt * MutexKeyword::addStatements(
    11981263                const ast::CompoundStmt * body,
    11991264                const std::vector<ast::ptr<ast::Expr>> & args ) {
    1200         ast::CompoundStmt * mutBody = ast::mutate( body );
    12011265
    12021266        // Code is generated near the beginning of the compound statement.
    1203         const CodeLocation & location = mutBody->location;
     1267        const CodeLocation & location = body->location;
     1268
     1269                // final body to return
     1270        ast::CompoundStmt * newBody = new ast::CompoundStmt( location );
     1271
     1272        // std::string lockFnName = mutex_func_namer.newName();
     1273        // std::string unlockFnName = mutex_func_namer.newName();
    12041274
    12051275        // Make pointer to the monitors.
     
    12091279                new ast::ArrayType(
    12101280                        new ast::PointerType(
    1211                                 new ast::TypeofType(
    1212                                         new ast::UntypedExpr(
    1213                                                 location,
    1214                                                 new ast::NameExpr( location, "__get_type" ),
    1215                                                 { args.front() }
    1216                                         )
    1217                                 )
     1281                                new ast::VoidType()
    12181282                        ),
    12191283                        ast::ConstantExpr::from_ulong( location, args.size() ),
     
    12291293                                                new ast::UntypedExpr(
    12301294                                                        expr->location,
    1231                                                         new ast::NameExpr( expr->location, "__get_ptr" ),
     1295                                                        new ast::NameExpr( expr->location, "__get_mutexstmt_lock_ptr" ),
    12321296                                                        { expr }
    12331297                                                )
     
    12421306        ast::StructInstType * lock_guard_struct =
    12431307                        new ast::StructInstType( lock_guard_decl );
    1244         ast::TypeExpr * lock_type_expr = new ast::TypeExpr(
    1245                 location,
    1246                 new ast::TypeofType(
    1247                         new ast::UntypedExpr(
    1248                                 location,
    1249                                 new ast::NameExpr( location, "__get_type" ),
    1250                                 { args.front() }
    1251                         )
    1252                 )
    1253         );
    1254 
    1255         lock_guard_struct->params.push_back( lock_type_expr );
    1256 
    1257         // In reverse order:
     1308
     1309        // use try stmts to lock and finally to unlock
     1310        ast::TryStmt * outerTry = nullptr;
     1311        ast::TryStmt * currentTry;
     1312        ast::CompoundStmt * lastBody = nullptr;
     1313
     1314        // adds a nested try stmt for each lock we are locking
     1315        for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1316                ast::UntypedExpr * innerAccess = new ast::UntypedExpr(
     1317                        location,
     1318                        new ast::NameExpr( location,"?[?]" ), {
     1319                                new ast::NameExpr( location, "__monitors" ),
     1320                                ast::ConstantExpr::from_int( location, i )
     1321                        }
     1322                );
     1323
     1324                // make the try body
     1325                ast::CompoundStmt * currTryBody = new ast::CompoundStmt( location );
     1326                ast::IfStmt * lockCall = genTypeDiscrimLockUnlock( "lock", args, location, innerAccess );
     1327                currTryBody->push_back( lockCall );
     1328
     1329                // make the finally stmt
     1330                ast::CompoundStmt * currFinallyBody = new ast::CompoundStmt( location );
     1331                ast::IfStmt * unlockCall = genTypeDiscrimLockUnlock( "unlock", args, location, innerAccess );
     1332                currFinallyBody->push_back( unlockCall );
     1333
     1334                // construct the current try
     1335                currentTry = new ast::TryStmt(
     1336                        location,
     1337                        currTryBody,
     1338                        {},
     1339                        new ast::FinallyStmt( location, currFinallyBody )
     1340                );
     1341                if ( i == 0 ) outerTry = currentTry;
     1342                else {
     1343                        // pushback try into the body of the outer try
     1344                        lastBody->push_back( currentTry );
     1345                }
     1346                lastBody = currTryBody;
     1347        }
     1348
     1349        // push body into innermost try body
     1350        if ( lastBody != nullptr ) {
     1351                lastBody->push_back( body );
     1352                newBody->push_front( outerTry );
     1353        }       
     1354
    12581355        // monitor_guard_t __guard = { __monitors, # };
    1259         mutBody->push_front(
     1356        newBody->push_front(
    12601357                new ast::DeclStmt(
    12611358                        location,
     
    12841381
    12851382        // monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
    1286         mutBody->push_front( new ast::DeclStmt( location, monitors ) );
    1287 
    1288         return mutBody;
     1383        newBody->push_front( new ast::DeclStmt( location, monitors ) );
     1384
     1385        // // The parameter for both __lock_curr/__unlock_curr routines.
     1386        // ast::ObjectDecl * this_decl = new ast::ObjectDecl(
     1387        //      location,
     1388        //      "this",
     1389        //      new ast::PointerType( new ast::VoidType() ),
     1390        //      nullptr,
     1391        //      {},
     1392        //      ast::Linkage::Cforall
     1393        // );
     1394
     1395        // ast::FunctionDecl * lock_decl = new ast::FunctionDecl(
     1396        //      location,
     1397        //      lockFnName,
     1398        //      { /* forall */ },
     1399        //      {
     1400        //              // Copy the declaration of this.
     1401        //              this_decl,
     1402        //      },
     1403        //      { /* returns */ },
     1404        //      nullptr,
     1405        //      0,
     1406        //      ast::Linkage::Cforall,
     1407        //      { /* attributes */ },
     1408        //      ast::Function::Inline
     1409        // );
     1410
     1411        // ast::FunctionDecl * unlock_decl = new ast::FunctionDecl(
     1412        //      location,
     1413        //      unlockFnName,
     1414        //      { /* forall */ },
     1415        //      {
     1416        //              // Copy the declaration of this.
     1417        //              ast::deepCopy( this_decl ),
     1418        //      },
     1419        //      { /* returns */ },
     1420        //      nullptr,
     1421        //      0,
     1422        //      ast::Linkage::Cforall,
     1423        //      { /* attributes */ },
     1424        //      ast::Function::Inline
     1425        // );
     1426
     1427        // ast::IfStmt * outerLockIf = nullptr;
     1428        // ast::IfStmt * outerUnlockIf = nullptr;
     1429        // ast::IfStmt * lastLockIf = nullptr;
     1430        // ast::IfStmt * lastUnlockIf = nullptr;
     1431
     1432        // //adds an if/elif clause for each lock to assign type from void ptr based on ptr address
     1433        // for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1434        //      ast::VariableExpr * thisParam = new ast::VariableExpr( location, InitTweak::getParamThis( lock_decl ) );
     1435        //      ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
     1436        //              new ast::NameExpr( location, "?==?" ), {
     1437        //                      thisParam,
     1438        //                      new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
     1439        //              }
     1440        //      );
     1441
     1442        //      ast::IfStmt * currLockIf = new ast::IfStmt(
     1443        //              location,
     1444        //              ast::deepCopy( ifCond ),
     1445        //              genVirtLockUnlockExpr( "lock", args.at(i), location, ast::deepCopy( thisParam ) )
     1446        //      );
     1447
     1448        //      ast::IfStmt * currUnlockIf = new ast::IfStmt(
     1449        //              location,
     1450        //              ifCond,
     1451        //              genVirtLockUnlockExpr( "unlock", args.at(i), location, ast::deepCopy( thisParam ) )
     1452        //      );
     1453               
     1454        //      if ( i == 0 ) {
     1455        //              outerLockIf = currLockIf;
     1456        //              outerUnlockIf = currUnlockIf;
     1457        //      } else {
     1458        //              // add ifstmt to else of previous stmt
     1459        //              lastLockIf->else_ = currLockIf;
     1460        //              lastUnlockIf->else_ = currUnlockIf;
     1461        //      }
     1462
     1463        //      lastLockIf = currLockIf;
     1464        //      lastUnlockIf = currUnlockIf;
     1465        // }
     1466       
     1467        // // add pointer typing if/elifs to body of routines
     1468        // lock_decl->stmts = new ast::CompoundStmt( location, { outerLockIf } );
     1469        // unlock_decl->stmts = new ast::CompoundStmt( location, { outerUnlockIf } );
     1470
     1471        // // add routines to scope
     1472        // declsToAddBefore.push_back( lock_decl );
     1473        // declsToAddBefore.push_back( unlock_decl );
     1474
     1475        // newBody->push_front(new ast::DeclStmt( location, lock_decl ));
     1476        // newBody->push_front(new ast::DeclStmt( location, unlock_decl ));
     1477
     1478        return newBody;
    12891479}
    12901480
  • tests/concurrent/mutexstmt/.expect/locks.txt

    radb3ea1 r98d1b90  
    33Start Test: multi lock deadlock/mutual exclusion
    44End Test: multi lock deadlock/mutual exclusion
     5Start Test: multi polymorphic lock deadlock/mutual exclusion
     6End Test: multi polymorphic lock deadlock/mutual exclusion
  • tests/concurrent/mutexstmt/locks.cfa

    radb3ea1 r98d1b90  
    44
    55const unsigned int num_times = 10000;
     6
     7Duration default_preemption() { return 0; }
    68
    79single_acquisition_lock m1, m2, m3, m4, m5;
     
    2325}
    2426
     27void refTest( single_acquisition_lock & m ) {
     28        mutex ( m ) {
     29                assert(!insideFlag);
     30                insideFlag = true;
     31                assert(insideFlag);
     32                insideFlag = false;
     33        }
     34}
     35
    2536thread T_Multi {};
    2637
    2738void main( T_Multi & this ) {
    2839        for (unsigned int i = 0; i < num_times; i++) {
     40                refTest( m1 );
    2941                mutex ( m1 ) {
    3042                        assert(!insideFlag);
     
    6072}
    6173
     74single_acquisition_lock l1;
     75linear_backoff_then_block_lock l2;
     76owner_lock l3;
     77
     78thread T_Multi_Poly {};
     79
     80void main( T_Multi_Poly & this ) {
     81        for (unsigned int i = 0; i < num_times; i++) {
     82                refTest( l1 );
     83                mutex ( l1 ) {
     84                        assert(!insideFlag);
     85                        insideFlag = true;
     86                        assert(insideFlag);
     87                        insideFlag = false;
     88                }
     89                mutex ( l1, l2, l3 ) {
     90                        assert(!insideFlag);
     91                        insideFlag = true;
     92                        assert(insideFlag);
     93                        insideFlag = false;
     94                }
     95                mutex ( l3, l1 ) {
     96                        assert(!insideFlag);
     97                        insideFlag = true;
     98                        assert(insideFlag);
     99                        insideFlag = false;
     100                }
     101                mutex ( l1, l2 ) {
     102                        assert(!insideFlag);
     103                        insideFlag = true;
     104                        assert(insideFlag);
     105                        insideFlag = false;
     106                }
     107        }
     108}
     109
    62110int num_tasks = 10;
    63111int main() {
    64         processor p[10];
     112        processor p[num_tasks - 1];
    65113
    66114        printf("Start Test: single lock mutual exclusion\n");
    67115        {
    68                 T_Mutex t[10];
     116                T_Mutex t[num_tasks];
    69117        }
    70118        assert(count == num_tasks * num_times);
     
    72120        printf("Start Test: multi lock deadlock/mutual exclusion\n");
    73121        {
    74                 T_Multi t[10];
     122                T_Multi t[num_tasks];
    75123        }
    76124        printf("End Test: multi lock deadlock/mutual exclusion\n");
     125        printf("Start Test: multi polymorphic lock deadlock/mutual exclusion\n");
     126        {
     127                T_Multi_Poly t[num_tasks];
     128        }
     129        printf("End Test: multi polymorphic lock deadlock/mutual exclusion\n");
    77130}
Note: See TracChangeset for help on using the changeset viewer.