Changeset a9ce782


Ignore:
Timestamp:
Feb 7, 2026, 1:40:26 PM (15 hours ago)
Author:
Matthew Au-Yeung <mw2auyeu@…>
Branches:
stuck-waitfor-destruct
Parents:
c7d106a
git-author:
Matthew Au-Yeung <mw2auyeu@…> (02/07/26 13:40:05)
git-committer:
Matthew Au-Yeung <mw2auyeu@…> (02/07/26 13:40:26)
Message:

Add a generated hash to fix stuck waitfor comparing static inline mutex destructors

Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/bits/defs.hfa

    rc7d106a ra9ce782  
    2626
    2727typedef void (* fptr_t)();
     28typedef uint64_t func_id_t;
    2829typedef int_fast16_t __lock_size_t;
    2930
  • libcfa/src/concurrency/invoke.h

    rc7d106a ra9ce782  
    159159                // last function that acquired monitors
    160160                fptr_t func;
     161
     162                // hash-based function identity for cross-TU matching
     163                func_id_t func_id;
    161164        };
    162165
     
    288291                        (this.size){0};
    289292                        (this.func){NULL};
    290                 }
    291 
    292                 static inline void ?{}(__monitor_group_t & this, struct monitor$ ** data, __lock_size_t size, fptr_t func) {
     293                        (this.func_id){0};
     294                }
     295
     296                static inline void ?{}(__monitor_group_t & this, struct monitor$ ** data, __lock_size_t size, fptr_t func, func_id_t func_id) {
    293297                        (this.data){data};
    294298                        (this.size){size};
    295299                        (this.func){func};
     300                        (this.func_id){func_id};
    296301                }
    297302
     
    299304                        if( (lhs.data != 0) != (rhs.data != 0) ) return false;
    300305                        if( lhs.size != rhs.size ) return false;
    301                         if( lhs.func != rhs.func ) return false;
     306                        // Use hash-based comparison when both sides have a valid func_id,
     307                        // otherwise fall back to function pointer comparison (for library code
     308                        // like join() that cannot compute the hash at compile time).
     309                        if( lhs.func_id != 0 && rhs.func_id != 0 ) {
     310                                if( lhs.func_id != rhs.func_id ) return false;
     311                        } else {
     312                                if( lhs.func != rhs.func ) return false;
     313                        }
    302314
    303315                        // Check that all the monitors match
     
    314326                        lhs.size = rhs.size;
    315327                        lhs.func = rhs.func;
     328                        lhs.func_id = rhs.func_id;
    316329                }
    317330        }
  • libcfa/src/concurrency/kernel/startup.cfa

    rc7d106a ra9ce782  
    517517        doregister(curr_cluster, this);
    518518
    519         monitors{ &self_mon_p, 1, (fptr_t)0 };
     519        monitors{ &self_mon_p, 1, (fptr_t)0, (func_id_t)0 };
    520520}
    521521
  • libcfa/src/concurrency/monitor.cfa

    rc7d106a ra9ce782  
    140140}
    141141
    142 static void __dtor_enter( monitor$ * this, fptr_t func, bool join ) {
     142static void __dtor_enter( monitor$ * this, fptr_t func, func_id_t func_id, bool join ) {
    143143        thread$ * thrd = active_thread();
    144144        #if defined( __CFA_WITH_VERIFY__ )
     
    190190        __lock_size_t count = 1;
    191191        monitor$ ** monitors = &this;
    192         __monitor_group_t group = { &this, 1, func };
     192        __monitor_group_t group = { &this, 1, func, func_id };
    193193        if ( is_accepted( this, group) ) {
    194194                __cfaabi_dbg_print_safe( "Kernel : mon accepts dtor, block and signal it \n" );
     
    341341// Ctor for monitor guard
    342342// Sorts monitors before entering
    343 void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count, fptr_t func ) libcfa_public {
     343void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count, fptr_t func, func_id_t func_id ) libcfa_public {
    344344        thread$ * thrd = active_thread();
    345345
     
    355355
    356356        // Update thread context (needed for conditions)
    357         (thrd->monitors){m, count, func};
     357        (thrd->monitors){m, count, func, func_id};
    358358
    359359        // __cfaabi_dbg_print_safe( "MGUARD : enter %d\n", count);
    360360
    361361        // Enter the monitors in order
    362         __monitor_group_t group = {this.m, this.count, func};
     362        __monitor_group_t group = {this.m, this.count, func, func_id};
    363363        enter( group );
    364364
     
    367367
    368368void ?{}( monitor_guard_t & this, monitor$ * m [], __lock_size_t count ) libcfa_public {
    369         this{ m, count, 0p };
     369        this{ m, count, 0p, 0 };
    370370}
    371371
     
    386386// Ctor for monitor guard
    387387// Sorts monitors before entering
    388 void ?{}( monitor_dtor_guard_t & this, monitor$ * m [], fptr_t func, bool join ) libcfa_public {
     388void ?{}( monitor_dtor_guard_t & this, monitor$ * m [], fptr_t func, func_id_t func_id, bool join ) libcfa_public {
    389389        // optimization
    390390        thread$ * thrd = active_thread();
     
    400400
    401401        // Update thread context (needed for conditions)
    402         (thrd->monitors){m, 1, func};
    403 
    404         __dtor_enter( this.m, func, join );
     402        (thrd->monitors){m, 1, func, func_id};
     403
     404        __dtor_enter( this.m, func, func_id, join );
    405405}
    406406
  • libcfa/src/concurrency/monitor.hfa

    rc7d106a ra9ce782  
    4848};
    4949
    50 void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count, void (*func)() );
     50void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count, void (*func)(), func_id_t func_id );
    5151void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count );
    5252void ^?{}( monitor_guard_t & this );
     
    5858};
    5959
    60 void ?{}( monitor_dtor_guard_t & this, monitor$ ** m, void (*func)(), bool join );
     60void ?{}( monitor_dtor_guard_t & this, monitor$ ** m, void (*func)(), func_id_t func_id, bool join );
    6161void ^?{}( monitor_dtor_guard_t & this );
    6262
  • libcfa/src/concurrency/thread.cfa

    rc7d106a ra9ce782  
    6161
    6262        doregister(curr_cluster, this);
    63         monitors{ &self_mon_p, 1, (fptr_t)0 };
     63        monitors{ &self_mon_p, 1, (fptr_t)0, (func_id_t)0 };
    6464}
    6565
     
    9393    | { EHM_DEFAULT_VTABLE(ThreadCancelled(T)); })
    9494void ?{}( thread_dtor_guard_t & this,
    95                 T & thrd, void(*cancelHandler)(ThreadCancelled(T) &)) {
     95                T & thrd, func_id_t func_id, void(*cancelHandler)(ThreadCancelled(T) &)) {
    9696        monitor$ * m = get_monitor(thrd);
    9797        thread$ * desc = get_thread(thrd);
     
    100100        void (*dtor)(T& mutex this) = ^?{};
    101101        bool join = cancelHandler != (void(*)(ThreadCancelled(T)&))0;
    102         (this.mg){&m, (void(*)())dtor, join};
     102        this.func_id = func_id;
     103        (this.mg){&m, (void(*)())dtor, func_id, join};
    103104
    104105
     
    172173        | { EHM_DEFAULT_VTABLE(ThreadCancelled(T)); })
    173174T & join( T & this ) {
    174         thread_dtor_guard_t guard = { this, defaultResumptionHandler };
     175        thread_dtor_guard_t guard = { this, (func_id_t)0, defaultResumptionHandler };
    175176        return this;
    176177}
  • libcfa/src/concurrency/thread.hfa

    rc7d106a ra9ce782  
    8383struct thread_dtor_guard_t {
    8484        monitor_dtor_guard_t mg;
     85        func_id_t func_id;
    8586};
    8687
    8788forall( T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled(T))
    8889        | { EHM_DEFAULT_VTABLE(ThreadCancelled(T)); })
    89 void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(ThreadCancelled(T) &) );
     90void ?{}( thread_dtor_guard_t & this, T & thrd, func_id_t func_id, void(*)(ThreadCancelled(T) &) );
    9091void ^?{}( thread_dtor_guard_t & this );
    9192
  • src/Concurrency/Keywords.cpp

    rc7d106a ra9ce782  
    2929#include "Common/Examine.hpp"
    3030#include "Common/Utility.hpp"
     31#include "Concurrency/MutexFuncHash.hpp"
    3132#include "Common/UniqueName.hpp"
    3233#include "ControlStruct/LabelGenerator.hpp"
     
    10771078
    10781079        // In reverse order:
    1079         // monitor_dtor_guard_t __guard = { __monitor, func, false };
     1080        // monitor_dtor_guard_t __guard = { __monitor, func, func_id, false };
    10801081        mutBody->push_front(
    10811082                new ast::DeclStmt( location, new ast::ObjectDecl(
     
    10941095                                                        generic_func,
    10951096                                                        ast::ExplicitCast ) ),
     1097                                        new ast::SingleInit( location,
     1098                                                Concurrency::hashMangleExpr( location, func ) ),
    10961099                                        new ast::SingleInit( location,
    10971100                                                ast::ConstantExpr::from_bool( location, false ) ),
     
    11751178                                                ast::ExplicitCast
    11761179                                        ) ),
     1180                                        new ast::SingleInit( location,
     1181                                                Concurrency::hashMangleExpr( location, func ) ),
    11771182                                },
    11781183                                {},
     
    14751480
    14761481ast::CompoundStmt * MutexKeyword::addThreadDtorStatements(
    1477                 const ast::FunctionDecl*, const ast::CompoundStmt * body,
     1482                const ast::FunctionDecl* func, const ast::CompoundStmt * body,
    14781483                const std::vector<const ast::DeclWithType * > & args ) {
    14791484        assert( args.size() == 1 );
     
    14871492        const CodeLocation & location = mutBody->location;
    14881493
    1489         // thread_dtor_guard_t __guard = { this, intptr( 0 ) };
     1494        // thread_dtor_guard_t __guard = { this, func_id, intptr( 0 ) };
    14901495        mutBody->push_front( new ast::DeclStmt(
    14911496                location,
     
    15001505                                                new ast::CastExpr( location,
    15011506                                                        new ast::VariableExpr( location, arg ), argType ) ),
     1507                                        new ast::SingleInit( location,
     1508                                                Concurrency::hashMangleExpr( location, func ) ),
    15021509                                        new ast::SingleInit(
    15031510                                                location,
  • src/Concurrency/Waitfor.cpp

    rc7d106a ra9ce782  
    2222#include "InitTweak/InitTweak.hpp"
    2323#include "ResolvExpr/Resolver.hpp"
     24#include "Concurrency/MutexFuncHash.hpp"
    2425
    2526#include "AST/Print.hpp"
     
    331332                makeAccStmt( location, acceptables, index, "func",
    332333                        funcExpr, context ),
     334                makeAccStmt( location, acceptables, index, "func_id",
     335                        Concurrency::hashMangleExpr( location,
     336                                variableExpr->var.strict_as<ast::DeclWithType>() ),
     337                        context ),
    333338                makeAccStmt( location, acceptables, index, "data",
    334339                        new ast::VariableExpr( location, monitors ), context ),
  • src/Validate/Autogen.cpp

    rc7d106a ra9ce782  
    402402        }
    403403
    404         ast::FunctionDecl * decl = genProto( "^?{}", { dst }, {} );
    405         // For concurrent types, remove static storage and inline specifier, and add
    406         // cfa_linkonce attribute so the destructor has external linkage with linkonce
    407         // semantics. This is required for waitfor to work correctly across translation
    408         // units - the function pointer must be the same everywhere, and cfa_linkonce
    409         // ensures only one definition survives linking.
    410         if ( isConcurrentType() ) {
    411                 auto mut = ast::mutate( decl );
    412                 mut->storage = ast::Storage::Classes();
    413                 mut->funcSpec = ast::Function::Specs();
    414                 mut->attributes.push_back( new ast::Attribute( "cfa_linkonce" ) );
    415         }
    416         return decl;
     404        return genProto( "^?{}", { dst }, {} );
    417405}
    418406
Note: See TracChangeset for help on using the changeset viewer.