source: src/libcfa/concurrency/monitor.c @ 78d3dd5

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 78d3dd5 was 690f13c, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

First step in implementing internal scheduling

  • Property mode set to 100644
File size: 3.3 KB
Line 
1//                              -*- Mode: CFA -*-
2//
3// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
4//
5// The contents of this file are covered under the licence agreement in the
6// file "LICENCE" distributed with Cforall.
7//
8// monitor_desc.c --
9//
10// Author           : Thierry Delisle
11// Created On       : Thd Feb 23 12:27:26 2017
12// Last Modified By : Thierry Delisle
13// Last Modified On : --
14// Update Count     : 0
15//
16
17#include "monitor"
18
19#include "kernel_private.h"
20
21void set_owner( monitor_desc * this, thread_desc * owner ) {
22        //Pass the monitor appropriately
23        this->owner = owner;
24
25        //We are passing the monitor to someone else, which means recursion level is not 0
26        this->recursion = owner ? 1 : 0;
27}
28
29extern "C" {
30        void __enter_monitor_desc(monitor_desc * this) {
31                lock( &this->lock );
32                thread_desc * thrd = this_thread();
33
34                if( !this->owner ) {
35                        //No one has the monitor, just take it
36                        this->owner = thrd;
37                        this->recursion = 1;
38                }
39                else if( this->owner == thrd) {
40                        //We already have the monitor, just not how many times we took it
41                        assert( this->recursion > 0 );
42                        this->recursion += 1;
43                }
44                else {
45                        //Some one else has the monitor, wait in line for it
46                        append( &this->entry_queue, thrd );
47                        ScheduleInternal( &this->lock );
48
49                        //ScheduleInternal will unlock spinlock, no need to unlock ourselves
50                        return; 
51                }
52
53                unlock( &this->lock );
54        }
55
56        // leave pseudo code :
57        //      decrement level
58        //      leve == 0 ?
59        //              no : done
60        //              yes :
61        //                      signal stack empty ?
62        //                              has leader :
63        //                                      bulk acquiring means we don't own the signal stack
64        //                                      ignore it but don't release the monitor
65        //                              yes :
66        //                                      next in entry queue is new owner
67        //                              no :
68        //                                      top of the signal stack is the owner
69        //                                      context switch to him right away
70        //
71        void __leave_monitor_desc(monitor_desc * this) {
72                lock( &this->lock );
73
74                thread_desc * thrd = this_thread();
75                assert( thrd == this->owner );
76
77                //Leaving a recursion level, decrement the counter
78                this->recursion -= 1;
79
80                //If we haven't left the last level of recursion
81                //it means we don't need to do anything
82                if( this->recursion != 0) {
83                        unlock( &this->lock );
84                        return;
85                }
86                       
87                //If we don't own the signal stack then just leave it to the owner
88                if( this->stack_owner ) {
89                        assert( this->owner == this->stack_owner );
90                        unlock( &this->lock );
91                        return;
92                }
93
94                //We are the stack owner and have left the last recursion level.
95                //We are in charge of passing the monitor
96                thread_desc * new_owner = 0;
97
98                //Check the signaller stack
99                new_owner = pop( &this->signal_stack );
100                if( new_owner ) {
101                        //The signaller stack is not empty,
102                        //transfer control immediately
103                        set_owner( this, new_owner );
104                        ScheduleInternal( &this->lock, new_owner );
105                        return;
106                }
107               
108                // No signaller thread
109                // Get the next thread in the entry_queue
110                new_owner = pop_head( &this->entry_queue );
111                set_owner( this, new_owner );
112
113                //We can now let other threads in safely
114                unlock( &this->lock );
115
116                //We need to wake-up the thread
117                ScheduleThread( new_owner );
118        }
119}
120
121void enter(monitor_desc ** monitors, int count) {
122        for(int i = 0; i < count; i++) {
123                __enter_monitor_desc( monitors[i] );
124        }
125}
126
127void leave(monitor_desc ** monitors, int count) {
128        for(int i = count - 1; i >= 0; i--) {
129                __leave_monitor_desc( monitors[i] );
130        }
131}
Note: See TracBrowser for help on using the repository browser.