source: src/Concurrency/Keywords.cc @ 0583064b

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 0583064b was cb0e6de, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Threads now use monitor semantics to wait until completion

  • Property mode set to 100644
File size: 11.3 KB
Line 
1//                              -*- Mode: CPP -*-
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// Keywords.cc --
9//
10// Author           : Thierry Delisle
11// Created On       : Mon Mar 13 12:41:22 2017
12// Last Modified By :
13// Last Modified On :
14// Update Count     : 3
15//
16
17#include "Concurrency/Keywords.h"
18
19#include "SymTab/AddVisit.h"
20#include "SynTree/Declaration.h"
21#include "SynTree/Expression.h"
22#include "SynTree/Initializer.h"
23#include "SynTree/Mutator.h"
24#include "SynTree/Statement.h"
25#include "SynTree/Type.h"
26#include "SynTree/Visitor.h"
27
28namespace Concurrency {
29
30        namespace {
31                const std::list<Label> noLabels;
32                const std::list< Attribute * > noAttributes;
33                Type::StorageClasses noStorage;
34                Type::Qualifiers noQualifiers;
35        }
36
37        //=============================================================================================
38        // Visitors declaration
39        //=============================================================================================
40
41        //-----------------------------------------------------------------------------
42        //Handles thread type declarations :
43        // thread Mythread {                         struct MyThread {
44        //      int data;                                  int data;
45        //      a_struct_t more_data;                      a_struct_t more_data;
46        //                                =>             thread_desc __thrd_d;
47        // };                                        };
48        //                                           static inline thread_desc * get_thread( MyThread * this ) { return &this->__thrd_d; }
49        //                                           void main( MyThread * this );
50        //
51        class ThreadKeyword final : public Mutator {
52          public:
53
54                static void implement( std::list< Declaration * > & translationUnit ) {}
55        };
56
57        //-----------------------------------------------------------------------------
58        //Handles coroutine type declarations :
59        // coroutine MyCoroutine {                   struct MyCoroutine {
60        //      int data;                                  int data;
61        //      a_struct_t more_data;                      a_struct_t more_data;
62        //                                =>             coroutine_desc __cor_d;
63        // };                                        };
64        //                                           static inline coroutine_desc * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
65        //                                           void main( MyCoroutine * this );
66        //
67        class CoroutineKeyword final : public Visitor {
68            template< typename Visitor >
69            friend void SymTab::acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
70          public:
71
72                using Visitor::visit;
73                virtual void visit( StructDecl * decl ) override final;
74
75                void handle( StructDecl * );
76                Declaration * addField( StructDecl * );
77                void addRoutines( StructDecl *, Declaration * );
78
79                static void implement( std::list< Declaration * > & translationUnit ) {
80                        CoroutineKeyword impl;
81                        SymTab::acceptAndAdd( translationUnit, impl );
82                }
83
84          private:
85                std::list< Declaration * > declsToAdd, declsToAddAfter;
86                StructDecl* coroutine_decl = nullptr;
87        };
88
89        //-----------------------------------------------------------------------------
90        //Handles monitor type declarations :
91        // monitor MyMonitor {                       struct MyMonitor {
92        //      int data;                                  int data;
93        //      a_struct_t more_data;                      a_struct_t more_data;
94        //                                =>             monitor_desc __mon_d;
95        // };                                        };
96        //                                           static inline monitor_desc * get_coroutine( MyMonitor * this ) { return &this->__cor_d; }
97        //                                           void main( MyMonitor * this );
98        //
99        class MonitorKeyword final : public Mutator {
100          public:
101
102                static void implement( std::list< Declaration * > & translationUnit ) {}
103        };
104
105        //-----------------------------------------------------------------------------
106        //Handles mutex routines definitions :
107        // void foo( A * mutex a, B * mutex b,  int i ) {                  void foo( A * a, B * b,  int i ) {
108        //                                                                       monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
109        //                                                                       monitor_guard_t __guard = { __monitors, 2 };
110        //    /*Some code*/                                       =>           /*Some code*/
111        // }                                                               }
112        //
113        class MutexKeyword final : public Visitor {
114          public:
115
116                using Visitor::visit;
117                virtual void visit( FunctionDecl * decl ) override final;
118                virtual void visit(   StructDecl * decl ) override final;
119
120                std::list<DeclarationWithType*> findMutexArgs( FunctionDecl* );
121                void validate( DeclarationWithType * );
122                void addStatments( CompoundStmt *, const std::list<DeclarationWithType * > &);
123
124                static void implement( std::list< Declaration * > & translationUnit ) {
125                        MutexKeyword impl;
126                        acceptAll( translationUnit, impl );
127                }
128
129          private:
130                StructDecl* monitor_decl = nullptr;
131                StructDecl* guard_decl = nullptr;
132        };
133
134        //=============================================================================================
135        // General entry routine
136        //=============================================================================================
137        void applyKeywords( std::list< Declaration * > & translationUnit ) {
138                ThreadKeyword   ::implement( translationUnit );
139                CoroutineKeyword        ::implement( translationUnit );
140                MonitorKeyword  ::implement( translationUnit );
141                MutexKeyword    ::implement( translationUnit );
142        }
143
144        //=============================================================================================
145        // Coroutine keyword implementation
146        //=============================================================================================
147        void CoroutineKeyword::visit(StructDecl * decl) {
148                if( decl->get_name() == "coroutine_desc" ) {
149                        assert( !coroutine_decl );
150                        coroutine_decl = decl;
151                }
152                else if ( decl->is_coroutine() ) {
153                        handle( decl );
154                }
155
156        }
157
158        void CoroutineKeyword::handle( StructDecl * decl ) {
159                if( ! decl->has_body() ) return;
160
161                if( !coroutine_decl ) throw SemanticError( "coroutine keyword requires coroutines to be in scope, add #include <coroutine>", decl );
162
163                Declaration * field = addField( decl );
164                addRoutines( decl, field );
165        }
166
167        Declaration * CoroutineKeyword::addField( StructDecl * decl ) {
168                Declaration * cor = new ObjectDecl(
169                        "__cor",
170                        noStorage,
171                        LinkageSpec::Cforall,
172                        nullptr,
173                        new StructInstType(
174                                noQualifiers,
175                                coroutine_decl
176                        ),
177                        nullptr
178                );
179
180                decl->get_members().push_back( cor );
181
182                return cor;
183        }
184
185        void CoroutineKeyword::addRoutines( StructDecl * decl, Declaration * field ) {
186                FunctionType * type = new FunctionType( noQualifiers, false );
187                type->get_parameters().push_back(
188                        new ObjectDecl(
189                                "this",
190                                noStorage,
191                                LinkageSpec::Cforall,
192                                nullptr,
193                                new PointerType(
194                                        noQualifiers,
195                                        new StructInstType(
196                                                noQualifiers,
197                                                decl
198                                        )
199                                ),
200                                nullptr
201                        )
202                );
203                type->get_returnVals().push_back(
204                        new ObjectDecl(
205                                "ret",
206                                noStorage,
207                                LinkageSpec::Cforall,
208                                nullptr,
209                                new PointerType(
210                                        noQualifiers,
211                                        new StructInstType(
212                                                noQualifiers,
213                                                coroutine_decl
214                                        )
215                                ),
216                                nullptr
217                        )
218                );
219
220                CompoundStmt * statement = new CompoundStmt( noLabels );
221                statement->push_back( 
222                        new ReturnStmt(
223                                noLabels,
224                                new AddressExpr(
225                                        new UntypedMemberExpr(
226                                                new NameExpr( "__cor" ),
227                                                new UntypedExpr(
228                                                        new NameExpr( "*?" ),
229                                                        { new NameExpr( "this" ) }
230                                                )
231                                        )
232                                )
233                        )
234                );
235
236                FunctionDecl * get_decl = new FunctionDecl(
237                        "get_coroutine",
238                        Type::Static,
239                        LinkageSpec::Cforall,
240                        type,
241                        statement,
242                        noAttributes,
243                        Type::Inline
244                );
245
246                declsToAddAfter.push_back( get_decl );
247
248                get_decl->fixUniqueId();
249        }
250       
251
252        //=============================================================================================
253        // Mutex keyword implementation
254        //=============================================================================================
255        void MutexKeyword::visit(FunctionDecl* decl) {
256                std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl );
257                if( mutexArgs.empty() ) return;
258
259                for(auto arg : mutexArgs) {
260                        validate( arg );
261                }
262
263                CompoundStmt* body = decl->get_statements();
264                if( ! body ) return;
265
266                if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
267                if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
268
269                addStatments( body, mutexArgs );
270        }
271
272        void MutexKeyword::visit(StructDecl* decl) {
273                if( decl->get_name() == "monitor_desc" ) {
274                        assert( !monitor_decl );
275                        monitor_decl = decl;
276                }
277                else if( decl->get_name() == "monitor_guard_t" ) {
278                        assert( !guard_decl );
279                        guard_decl = decl;
280                }
281        }
282
283        std::list<DeclarationWithType*> MutexKeyword::findMutexArgs( FunctionDecl* decl ) {
284                std::list<DeclarationWithType*> mutexArgs;
285
286                for( auto arg : decl->get_functionType()->get_parameters()) {
287                        //Find mutex arguments
288                        Type* ty = arg->get_type();
289                        if( ! ty->get_mutex() ) continue;
290
291                        //Append it to the list
292                        mutexArgs.push_back( arg );
293                }
294
295                return mutexArgs;
296        }
297
298        void MutexKeyword::validate( DeclarationWithType * arg ) {
299                Type* ty = arg->get_type();
300
301                //Makes sure it's not a copy
302                PointerType* pty = dynamic_cast< PointerType * >( ty );
303                if( ! pty ) throw SemanticError( "Mutex argument must be of pointer/reference type ", arg );
304
305                //Make sure the we are pointing directly to a type
306                Type* base = pty->get_base();
307                if(  dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
308
309                //Make sure that typed isn't mutex
310                if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
311        }
312
313        void MutexKeyword::addStatments( CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {
314                ObjectDecl * monitors = new ObjectDecl(
315                        "__monitors",
316                        noStorage,
317                        LinkageSpec::Cforall,
318                        nullptr,
319                        new ArrayType(
320                                noQualifiers,
321                                new PointerType(
322                                        noQualifiers,
323                                        new StructInstType(
324                                                noQualifiers,
325                                                monitor_decl
326                                        )
327                                ),
328                                new ConstantExpr( Constant::from_ulong( args.size() ) ),
329                                false,
330                                false
331                        ),
332                        new ListInit(
333                                map_range < std::list<Initializer*> > ( args, [this](DeclarationWithType * var ){
334                                        Type * type = var->get_type()->clone();
335                                        type->set_mutex( false );
336                                        return new SingleInit( new UntypedExpr(
337                                                new NameExpr( "get_monitor" ),
338                                                {  new CastExpr( new VariableExpr( var ), type ) }
339                                        ) );
340                                })
341                        )
342                );
343
344                //in reverse order :
345                // monitor_guard_t __guard = { __monitors, # };
346                body->push_front(
347                        new DeclStmt( noLabels, new ObjectDecl(
348                                "__guard",
349                                noStorage,
350                                LinkageSpec::Cforall,
351                                nullptr,
352                                new StructInstType(
353                                        noQualifiers,
354                                        guard_decl
355                                ),
356                                new ListInit(
357                                        {
358                                                new SingleInit( new VariableExpr( monitors ) ),
359                                                new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) )
360                                        },
361                                        noDesignators,
362                                        true
363                                )
364                        ))
365                );
366
367                //monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
368                body->push_front( new DeclStmt( noLabels, monitors) );
369        }
370};
Note: See TracBrowser for help on using the repository browser.