// -*- Mode: CFA -*- // // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // monitor_desc.c -- // // Author : Thierry Delisle // Created On : Thd Feb 23 12:27:26 2017 // Last Modified By : Thierry Delisle // Last Modified On : -- // Update Count : 0 // #include "monitor" #include "kernel_private.h" void enter(monitor_desc * this) { lock( &this->lock ); thread_desc * thrd = this_thread(); if( !this->owner ) { //No one has the monitor, just take it this->owner = thrd; this->recursion = 1; } else if( this->owner == thrd) { //We already have the monitor, just not how many times we took it assert( this->recursion > 0 ); this->recursion += 1; } else { //Some one else has the monitor, wait in line for it append( &this->entry_queue, thrd ); ScheduleInternal( &this->lock ); //ScheduleInternal will unlock spinlock, no need to unlock ourselves return; } unlock( &this->lock ); } void leave(monitor_desc * this) { lock( &this->lock ); thread_desc * thrd = this_thread(); assert( thrd == this->owner ); //Leaving a recursion level, decrement the counter this->recursion -= 1; //If we left the last level of recursion it means we are changing who owns the monitor thread_desc * new_owner = 0; if( this->recursion == 0) { //Get the next thread in the list new_owner = this->owner = pop_head( &this->entry_queue ); //We are passing the monitor to someone else, which means recursion level is not 0 this->recursion = new_owner ? 1 : 0; } unlock( &this->lock ); //If we have a new owner, we need to wake-up the thread if( new_owner ) { ScheduleThread( new_owner ); } } void enter(monitor_desc ** monitors, int count) { for(int i = 0; i < count; i++) { // printf("%d\n", i); enter( monitors[i] ); } } void leave(monitor_desc ** monitors, int count) { for(int i = count - 1; i >= 0; i--) { // printf("%d\n", i); leave( monitors[i] ); } }