Ignore:
Timestamp:
Jul 4, 2017, 9:40:16 AM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, 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:
208e5be
Parents:
9c951e3 (diff), f7cb0bc (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' into references

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/libcfa/concurrency/monitor.c

    r9c951e3 rb1e63ac5  
    5656                else if( this->owner == thrd) {
    5757                        //We already have the monitor, just not how many times we took it
    58                         assert( this->recursion > 0 );
     58                        verify( this->recursion > 0 );
    5959                        this->recursion += 1;
    6060                }
     
    6262                        //Some one else has the monitor, wait in line for it
    6363                        append( &this->entry_queue, thrd );
     64                        LIB_DEBUG_PRINT_SAFE("%p Blocking on entry\n", thrd);
    6465                        ScheduleInternal( &this->lock );
    6566
     
    7778                lock( &this->lock );
    7879
    79                 thread_desc * thrd = this_thread();
    80 
    8180                LIB_DEBUG_PRINT_SAFE("%p Leaving %p (o: %p, r: %i)\n", thrd, this, this->owner, this->recursion);
    82                 assertf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i)", thrd, this->owner, this->recursion );
     81                verifyf( this_thread() == this->owner, "Expected owner to be %p, got %p (r: %i)", this_thread(), this->owner, this->recursion );
    8382
    8483                //Leaving a recursion level, decrement the counter
     
    9796                unlock( &this->lock );
    9897
     98                LIB_DEBUG_PRINT_SAFE("Next owner is %p\n", new_owner);
     99
    99100                //We need to wake-up the thread
    100101                ScheduleThread( new_owner );
     
    134135}
    135136
    136 void debug_break() __attribute__(( noinline ))
    137 {
    138        
     137void ?{}(__condition_node_t * this, thread_desc * waiting_thread, unsigned short count, uintptr_t user_info ) {
     138        this->waiting_thread = waiting_thread;
     139        this->count = count;
     140        this->next = NULL;
     141        this->user_info = user_info;
     142}
     143
     144void ?{}(__condition_criterion_t * this ) {
     145        this->ready  = false;
     146        this->target = NULL;
     147        this->owner  = NULL;
     148        this->next   = NULL;
     149}
     150
     151void ?{}(__condition_criterion_t * this, monitor_desc * target, __condition_node_t * owner ) {
     152        this->ready  = false;
     153        this->target = target;
     154        this->owner  = owner;
     155        this->next   = NULL;
    139156}
    140157
    141158//-----------------------------------------------------------------------------
    142159// Internal scheduling
    143 void wait( condition * this ) {
     160void wait( condition * this, uintptr_t user_info = 0 ) {
    144161        LIB_DEBUG_PRINT_SAFE("Waiting\n");
    145162
     
    148165        //Check that everything is as expected
    149166        assertf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors );
    150         assertf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count );
     167        verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count );
     168        verifyf( this->monitor_count < 32u, "Excessive monitor count (%i)", this->monitor_count );
    151169
    152170        unsigned short count = this->monitor_count;
     
    156174        LIB_DEBUG_PRINT_SAFE("count %i\n", count);
    157175
    158         __condition_node_t waiter;
    159         waiter.waiting_thread = this_thread();
    160         waiter.count = count;
    161         waiter.next = NULL;
     176        __condition_node_t waiter = { this_thread(), count, user_info };
    162177
    163178        __condition_criterion_t criteria[count];
    164179        for(int i = 0; i < count; i++) {
    165                 criteria[i].ready  = false;
    166                 criteria[i].target = this->monitors[i];
    167                 criteria[i].owner  = &waiter;
    168                 criteria[i].next   = NULL;
     180                (&criteria[i]){ this->monitors[i], &waiter };
    169181                LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] );
    170182        }
     
    184196        }
    185197
    186         debug_break();
    187 
    188198        for( int i = 0; i < count; i++) {
    189199                thread_desc * new_owner = next_thread( this->monitors[i] );
    190200                thread_count = insert_unique( threads, thread_count, new_owner );
    191201        }
    192 
    193         debug_break();
    194202
    195203        LIB_DEBUG_PRINT_SAFE("Will unblock: ");
     
    212220}
    213221
    214 void signal( condition * this ) {
    215         if( !this->blocked.head ) {
     222bool signal( condition * this ) {
     223        if( is_empty( this ) ) {
    216224                LIB_DEBUG_PRINT_SAFE("Nothing to signal\n");
    217                 return;
     225                return false;
    218226        }
    219227
    220228        //Check that everything is as expected
    221         assert( this->monitors );
    222         assert( this->monitor_count != 0 );
     229        verify( this->monitors );
     230        verify( this->monitor_count != 0 );
    223231
    224232        unsigned short count = this->monitor_count;
    225233       
     234        //Some more checking in debug
    226235        LIB_DEBUG_DO(
    227236                thread_desc * this_thrd = this_thread();
     
    237246        );
    238247
     248        //Lock all the monitors
    239249        lock_all( this->monitors, NULL, count );
    240250        LIB_DEBUG_PRINT_SAFE("Signalling");
    241251
     252        //Pop the head of the waiting queue
    242253        __condition_node_t * node = pop_head( &this->blocked );
     254
     255        //Add the thread to the proper AS stack
    243256        for(int i = 0; i < count; i++) {
    244257                __condition_criterion_t * crit = &node->criteria[i];
     
    250263        LIB_DEBUG_PRINT_SAFE("\n");
    251264
     265        //Release
    252266        unlock_all( this->monitors, count );
     267
     268        return true;
     269}
     270
     271bool signal_block( condition * this ) {
     272        if( !this->blocked.head ) {
     273                LIB_DEBUG_PRINT_SAFE("Nothing to signal\n");
     274                return false;
     275        }
     276
     277        //Check that everything is as expected
     278        verifyf( this->monitors != NULL, "Waiting with no monitors (%p)", this->monitors );
     279        verifyf( this->monitor_count != 0, "Waiting with 0 monitors (%i)", this->monitor_count );
     280
     281        unsigned short count = this->monitor_count;
     282        unsigned int recursions[ count ];               //Save the current recursion levels to restore them later
     283        spinlock *   locks     [ count ];               //We need to pass-in an array of locks to ScheduleInternal
     284
     285        lock_all( this->monitors, locks, count );
     286
     287        //create creteria
     288        __condition_node_t waiter = { this_thread(), count, 0 };
     289
     290        __condition_criterion_t criteria[count];
     291        for(int i = 0; i < count; i++) {
     292                (&criteria[i]){ this->monitors[i], &waiter };
     293                LIB_DEBUG_PRINT_SAFE( "Criterion %p\n", &criteria[i] );
     294                push( &criteria[i].target->signal_stack, &criteria[i] );
     295        }
     296
     297        waiter.criteria = criteria;
     298
     299        //save contexts
     300        save_recursion( this->monitors, recursions, count );
     301
     302        //Find the thread to run
     303        thread_desc * signallee = pop_head( &this->blocked )->waiting_thread;
     304        for(int i = 0; i < count; i++) {
     305                set_owner( this->monitors[i], signallee );
     306        }
     307
     308        LIB_DEBUG_PRINT_SAFE( "Waiting on signal block\n" );
     309
     310        //Everything is ready to go to sleep
     311        ScheduleInternal( locks, count, &signallee, 1 );
     312
     313
     314
     315
     316        LIB_DEBUG_PRINT_SAFE( "Back from signal block\n" );
     317
     318        //We are back, restore the owners and recursions
     319        lock_all( locks, count );
     320        restore_recursion( this->monitors, recursions, count );
     321        unlock_all( locks, count );
     322
     323        return true;
     324}
     325
     326uintptr_t front( condition * this ) {
     327        verifyf( !is_empty(this),
     328                "Attempt to access user data on an empty condition.\n"
     329                "Possible cause is not checking if the condition is empty before reading stored data."
     330        );
     331        return this->blocked.head->user_info;
     332}
     333
     334//-----------------------------------------------------------------------------
     335// Internal scheduling
     336void __accept_internal( unsigned short count, __acceptable_t * acceptables, void (*func)(void) ) {
     337        // thread_desc * this = this_thread();
     338
     339        // unsigned short count = this->current_monitor_count;
     340        // unsigned int recursions[ count ];            //Save the current recursion levels to restore them later
     341        // spinlock *   locks     [ count ];            //We need to pass-in an array of locks to ScheduleInternal
     342
     343        // lock_all( this->current_monitors, locks, count );
     344
     345
     346
     347
     348
     349        // // // Everything is ready to go to sleep
     350        // // ScheduleInternal( locks, count, threads, thread_count );
     351
     352
     353        // //WE WOKE UP
     354
     355
     356        // //We are back, restore the owners and recursions
     357        // lock_all( locks, count );
     358        // restore_recursion( this->monitors, recursions, count );
     359        // unlock_all( locks, count );
    253360}
    254361
     
    335442
    336443        for(    int i = 0; i < count; i++ ) {
     444
    337445                LIB_DEBUG_PRINT_SAFE( "Checking %p for %p\n", &criteria[i], target );
    338446                if( &criteria[i] == target ) {
     
    379487
    380488void append( __condition_blocked_queue_t * this, __condition_node_t * c ) {
    381         assert(this->tail != NULL);
     489        verify(this->tail != NULL);
    382490        *this->tail = c;
    383491        this->tail = &c->next;
Note: See TracChangeset for help on using the changeset viewer.