diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cbf7ecbe4c2dff51b7fd521589cd4de86c59af78..2c4427474288d2513d76d55ca80a3d522fdb1ccc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,6 +65,8 @@ add_executable(mc-sog main.cpp ModelCheckerTh.h stacksafe.cpp stacksafe.h + SafeDequeue.cpp + SafeDequeue.h ModelCheckerThV2.cpp ModelCheckerThV2.h MCHybridSOG.cpp diff --git a/src/LDDGraph.cpp b/src/LDDGraph.cpp index eaba61f91f4271dfe4c626036c38da531aac1f10..87d9c6af123025054d66a0988602588d75e10af1 100644 --- a/src/LDDGraph.cpp +++ b/src/LDDGraph.cpp @@ -22,8 +22,8 @@ LDDState* LDDGraph::getInitialState() const { /*----------------------find()----------------*/ LDDState * LDDGraph::find(LDDState* c) { - for(MetaLDDNodes::const_iterator i=m_GONodes.begin();!(i==m_GONodes.end());i++) - //if((c->class_state.id()==(*i)->class_state.id())&&(c->blocage==(*i)->blocage)&&(c->boucle==(*i)->boucle)) + std::scoped_lock lock(m_mutex); + for(MetaLDDNodes::const_iterator i=m_GONodes.begin();!(i==m_GONodes.end());i++) if(c->m_lddstate==(*i)->m_lddstate) return *i; return NULL; @@ -62,7 +62,7 @@ size_t LDDGraph::findSHAPos(unsigned char* c,bool &res) /*----------------------insert() ------------*/ void LDDGraph::insert(LDDState *c) { - + std::scoped_lock lock(m_mutex); this->m_GONodes.push_back(c); m_nbStates++; } diff --git a/src/LDDGraph.h b/src/LDDGraph.h index f2a562e93190ab7f798521888fee6c8fdd2363e3..533e07fdd4f35c384304b191eba730560a70a0cd 100755 --- a/src/LDDGraph.h +++ b/src/LDDGraph.h @@ -2,7 +2,8 @@ #define LDDGRAPH_H #include "LDDState.h" #include "CommonSOG.h" - +#include <mutex> +#include <atomic> //#include "LDDStateExtend.h" using namespace std; #include <iostream> @@ -14,6 +15,7 @@ class CommonSOG; class LDDGraph { private: + mutable std::mutex m_mutex; map<string,uint16_t>* m_transition; map<uint16_t,string>* m_places; void printGraph(LDDState *, size_t &); @@ -31,7 +33,7 @@ class LDDGraph LDDState *m_currentstate; long m_nbStates; long m_nbMarking; - long m_nbArcs; + atomic<uint32_t> m_nbArcs; LDDState* find(LDDState*); LDDState* findSHA(unsigned char*); size_t findSHAPos(unsigned char*,bool &res); diff --git a/src/LDDState.h b/src/LDDState.h index 6734ac949b229d5e6e331fc833dd642059a9bff1..a56dbe4afbbed7069e3cfef96a2160b7c7de848f 100755 --- a/src/LDDState.h +++ b/src/LDDState.h @@ -49,7 +49,7 @@ class LDDState { private: bool m_virtual = false; bool m_visited=false; - bool m_completed=false; + volatile bool m_completed=false; uint16_t m_process=0; }; diff --git a/src/ModelCheckerThV2.cpp b/src/ModelCheckerThV2.cpp index 8a7e0f15c28cde66c4633d5210aac59953c68091..8c900027da85ff70b82fcc7facdb45c0e1235438 100644 --- a/src/ModelCheckerThV2.cpp +++ b/src/ModelCheckerThV2.cpp @@ -104,34 +104,29 @@ LDDState* ModelCheckerThV2::getInitialMetaState() { while ( !m_finish_initial ) ; LDDState *initial_metastate = m_graph->getInitialState(); - if ( !initial_metastate->isVisited() ) { - initial_metastate->setVisited(); - while ( !initial_metastate->isCompletedSucc() ) - ; - } + buildSucc(initial_metastate); return initial_metastate; } void ModelCheckerThV2::buildSucc ( LDDState *agregate ) { if ( !agregate->isVisited() ) { - agregate->setVisited(); - while ( !agregate->isCompletedSucc() ) - ; + agregate->setVisited(); + std::unique_lock<std::mutex> lk ( m_mutexStack ); + m_condBuild.wait(lk,[&agregate]{return agregate->isCompletedSucc();}); + lk.unlock(); } } void ModelCheckerThV2::Compute_successors() { int id_thread; - { - std::scoped_lock guard ( m_mutex ); - id_thread = m_id_thread++; - } + + id_thread = m_id_thread++; + //cout<<" I'm here thread id " <<m_id_thread<<endl; - Set fire; - int min_charge = 0; - m_started=false; + Set fire; + if ( id_thread == 0 ) { LDDState *c = new LDDState; MDD Complete_meta_state=Accessible_epsilon ( m_initialMarking ); @@ -141,8 +136,7 @@ void ModelCheckerThV2::Compute_successors() c->setDeadLock ( Set_Bloc ( Complete_meta_state ) ); c->setDiv ( Set_Div ( Complete_meta_state ) ); m_common_stack.push ( Pair ( couple ( c, Complete_meta_state ), fire ) ); - m_condStack.notify_one(); - m_started=true; + m_condStack.notify_one(); m_graph->setInitialState ( c ); m_graph->insert ( c ); m_finish_initial = true; @@ -151,96 +145,55 @@ void ModelCheckerThV2::Compute_successors() LDDState *reached_class; //pthread_barrier_wait ( &m_barrier_builder ); Pair e; - do { - - + do { std::unique_lock<std::mutex> lk ( m_mutexStack ); m_condStack.wait(lk,std::bind(&ModelCheckerThV2::hasToProcess,this)); lk.unlock(); - - if (!m_finish ) { - m_terminaison++; - bool advance=true; - try { - m_common_stack.pop ( e ); - } catch ( ... ) { - advance=false; - } - - if ( advance ) { + + if ( m_common_stack.try_pop ( e ) && !m_finish ) { while ( !e.second.empty() && !m_finish ) { int t = *e.second.begin(); e.second.erase ( t ); - if ( id_thread ) { - std::scoped_lock supervise ( m_supervise_gc_mutex ); - m_gc++; - if ( m_gc == 1 ) { - m_gc_mutex.lock(); - } - } - - //MDD reduced_meta = Complete_meta_state; //Canonize(Complete_meta_state,0); - /*ldd_refs_push(reduced_meta);*/ - if ( id_thread == 0 ) { - std::scoped_lock guard ( m_gc_mutex ); - // #ifdef DEBUG_GC - //displayMDDTableInfo(); - // #endif // DEBUG_GC - sylvan_gc_seq(); - // #ifdef DEBUG_GC - //displayMDDTableInfo(); - // #endif // DEBUG_GC - } - - //pthread_spin_lock(&m_accessible); - + MDD reduced_meta = Accessible_epsilon ( get_successor ( e.first.second, t ) ); ldd_refs_push ( reduced_meta ); reached_class = new LDDState(); - reached_class->m_lddstate = reduced_meta; - m_graph_mutex.lock(); + reached_class->m_lddstate = reduced_meta; LDDState *pos = m_graph->find ( reached_class ); - if ( !pos ) { - // cout<<"not found"<<endl; + if ( !pos ) { m_graph->addArc(); - m_graph->insert ( reached_class ); - m_graph_mutex.unlock(); - //reached_class->setDiv(Set_Div(reduced_meta)); - //reached_class->setDeadLock(Set_Bloc(reduced_meta)); + m_graph->insert ( reached_class ); + fire = firable_obs ( reduced_meta ); reached_class->setDeadLock ( Set_Bloc ( reduced_meta ) ); reached_class->setDiv ( Set_Div ( reduced_meta ) ); m_common_stack.push ( Pair ( couple ( reached_class, reduced_meta ), fire ) ); m_condStack.notify_one(); - + m_graph_mutex.lock(); e.first.first->Successors.insert ( e.first.first->Successors.begin(), LDDEdge ( reached_class, t ) ); reached_class->Predecessors.insert ( reached_class->Predecessors.begin(), LDDEdge ( e.first.first, t ) ); + m_graph_mutex.unlock(); } else { + delete reached_class; m_graph->addArc(); - m_graph_mutex.unlock(); + m_graph_mutex.lock(); e.first.first->Successors.insert ( e.first.first->Successors.begin(), LDDEdge ( pos, t ) ); pos->Predecessors.insert ( pos->Predecessors.begin(), LDDEdge ( e.first.first, t ) ); - delete reached_class; - } - if ( id_thread ) { - std::scoped_lock guard ( m_supervise_gc_mutex ); - m_gc--; - if ( m_gc == 0 ) { - m_gc_mutex.unlock(); - } - + m_graph_mutex.unlock(); + } + } - e.first.first->setCompletedSucc(); + e.first.first->setCompletedSucc();m_condBuild.notify_one(); } //end advance - m_terminaison--; - } + + } while ( !m_finish ); - pthread_barrier_wait ( &m_barrier_builder ); + //pthread_barrier_wait ( &m_barrier_builder ); } @@ -258,10 +211,7 @@ void ModelCheckerThV2::ComputeTh_Succ() /* pthread_barrier_init(&m_barrier_threads, NULL, m_nb_thread+1);*/ pthread_barrier_init ( &m_barrier_builder, NULL, m_nb_thread + 1 ); - - - m_gc=0; - m_terminaison=0; + m_finish=false; for ( int i = 0; i < m_nb_thread; i++ ) { int rc; @@ -276,7 +226,7 @@ ModelCheckerThV2::~ModelCheckerThV2() { m_finish = true; m_condStack.notify_all(); - pthread_barrier_wait ( &m_barrier_builder ); + //pthread_barrier_wait ( &m_barrier_builder ); for ( int i = 0; i < m_nb_thread; i++ ) { m_list_thread[i]->join(); delete m_list_thread[i]; @@ -287,3 +237,4 @@ bool ModelCheckerThV2::hasToProcess() const { return m_finish || !m_common_stack.empty(); } + diff --git a/src/ModelCheckerThV2.h b/src/ModelCheckerThV2.h index 84ec05c648bc106f8ab160896309b549719edeea..ff0ada167db6927e45e106be601fe39d1c6e72f8 100644 --- a/src/ModelCheckerThV2.h +++ b/src/ModelCheckerThV2.h @@ -2,6 +2,7 @@ #define MODELCHECKERTHV2_H #include "ModelCheckBaseMT.h" #include "stacksafe.h" +#include "SafeDequeue.h" #include <atomic> #include <thread> #include <mutex> @@ -21,18 +22,15 @@ public: void ComputeTh_Succ(); private: void preConfigure(); - bool ModelCheckerThV2::hasToProcess() const; - - StackSafe<Pair> m_common_stack; - bool m_started=false; - - int m_id_thread; + bool hasToProcess() const; + SafeDequeue<Pair> m_common_stack; + + atomic<uint8_t> m_id_thread; std::mutex m_mutex,m_graph_mutex,m_gc_mutex,m_supervise_gc_mutex; - pthread_barrier_t m_barrier_builder; - atomic<uint32_t> m_gc,m_terminaison; // + pthread_barrier_t m_barrier_builder; volatile bool m_finish=false; bool m_finish_initial=false; - std::condition_variable m_condStack; + std::condition_variable m_condStack,m_condBuild; std::mutex m_mutexStack; thread* m_list_thread[128]; }; diff --git a/src/SafeDequeue.cpp b/src/SafeDequeue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd4b282f2c7cc907dda5cb656d283b130c51e844 --- /dev/null +++ b/src/SafeDequeue.cpp @@ -0,0 +1,100 @@ +/* + * <one line to give the library's name and an idea of what it does.> + * Copyright (C) 2020 chiheb <email> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "SafeDequeue.h" + +template<typename T> +SafeDequeue<T>::SafeDequeue() +{ + +} + +template<typename T> +SafeDequeue<T>::SafeDequeue ( const SafeDequeue& other ) +{ + std::scoped_lock lk ( other.mut ); + data_queue=other.data_queue; +} + +template<typename T> +SafeDequeue<T>::~SafeDequeue() +{ + +} + +template<typename T> +void SafeDequeue<T>::push ( T new_value ) +{ + std::scoped_lock lk ( mut ); + data_queue.push ( new_value ); + data_cond.notify_one(); + +} + +/*template<typename T> +void SafeDequeue<T>::wait_and_pop ( T& value ) +{ + +}*/ + +template<typename T> +std::shared_ptr<T> SafeDequeue<T>::wait_and_pop() +{ + std::unique_lock<std::mutex> lk ( mut ); + data_cond.wait ( lk,[this] {return !data_queue.empty();} ); + std::shared_ptr<T> res ( std::make_shared<T> ( data_queue.front() ) ); + data_queue.pop(); + return res; +} + +template<typename T> +bool SafeDequeue<T>::try_pop ( T& value ) +{ + std::scoped_lock lk ( mut ); + if ( data_queue.empty() ) { + return false; + } + value=data_queue.front(); + data_queue.pop(); + return true; +} + + +template<typename T> +std::shared_ptr<T> SafeDequeue<T>::try_pop() +{ + std::scoped_lock lk ( mut ); + if ( data_queue.empty() ) { + return std::shared_ptr<T>(); + } + std::shared_ptr<T> res ( std::make_shared<T> ( data_queue.front() ) ); + data_queue.pop(); + return res; +} + +template<typename T> +bool SafeDequeue<T>::empty() const +{ + std::scoped_lock lk ( mut ); + return data_queue.empty(); +} + + +template class SafeDequeue<Pair>; +typedef pair<string *, unsigned int> MSG; +template class SafeDequeue<MSG>; diff --git a/src/SafeDequeue.h b/src/SafeDequeue.h new file mode 100644 index 0000000000000000000000000000000000000000..22b983b5f1b410ffaa335c90b2a209ab8933f397 --- /dev/null +++ b/src/SafeDequeue.h @@ -0,0 +1,78 @@ +/* + * <one line to give the library's name and an idea of what it does.> + * Copyright (C) 2020 chiheb <email> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SAFEDEQUEUE_H +#define SAFEDEQUEUE_H +#include <memory> +#include "LDDState.h" +#include <queue> +#include <mutex> +#include <functional> +#include <condition_variable> + +typedef pair<LDDState *, MDD> couple; +typedef pair<couple, Set> Pair; +struct empty_queue: std::exception { + ~empty_queue() {}; + const char* what() const noexcept {return "";} + + }; +/** + * @todo write docs + */ +template<typename T> +class SafeDequeue { + private: + std::mutex mut; + std::queue<T> data_queue; + std::condition_variable data_cond; + + public: + /** + * Default constructor + */ + SafeDequeue(); + + /** + * Copy constructor + * + * @param other TODO + */ + SafeDequeue ( const SafeDequeue& other ); + + /** + * Destructor + */ + ~SafeDequeue(); + SafeDequeue& operator= ( const SafeDequeue& ) = delete; + void push ( T new_value ); + bool try_pop ( T& value ); + std::shared_ptr<T> try_pop(); + void wait_and_pop ( T& value ) { + std::unique_lock<std::mutex> lk ( mut ); + data_cond.wait ( lk,[this] {return !data_queue.empty();} ); + value=data_queue.front(); + data_queue.pop(); + }; + + + std::shared_ptr<T> wait_and_pop(); + bool empty() const; + }; + +#endif // SAFEDEQUEUE_H diff --git a/src/stacksafe.cpp b/src/stacksafe.cpp index de7f260f0ef86460ca808ac1f0e59367fd703f3f..6b381d20ab35c959886f279b974c85c50247b55b 100644 --- a/src/stacksafe.cpp +++ b/src/stacksafe.cpp @@ -48,16 +48,22 @@ void StackSafe<T>::pop(T& value) value=m_data.top(); m_data.pop(); } - template<typename T> -bool StackSafe<T>::empty() const +bool StackSafe<T>::try_pop(T& value) { std::scoped_lock lock(m_mutex); - return m_data.empty(); + if(m_data.empty()) return false; + value=m_data.top(); + m_data.pop(); + return true; } - template class StackSafe<Pair>; + +template class StackSafe<Pair>; +typedef pair<string *, unsigned int> MSG; +template class StackSafe<MSG>; + diff --git a/src/stacksafe.h b/src/stacksafe.h index af33910ec32b554ffb4e7b048a53562c5e6e1af8..723cf901259c03bfeebcb79346a8e1d666ead5a8 100644 --- a/src/stacksafe.h +++ b/src/stacksafe.h @@ -44,6 +44,10 @@ template<typename T> class StackSafe { void push ( T new_value ); std::shared_ptr<T> pop(); void pop ( T& value ); - bool empty() const; + bool try_pop ( T& value ); + bool empty() const { + std::scoped_lock lock(m_mutex); + return m_data.empty(); + }; }; #endif // STACKSAFE_H diff --git a/src/sylvan_sog.c b/src/sylvan_sog.c index 1ed1663c17b1e68e816a2ba8d451ef2f9a3d86e8..d1c9d5a874d55846b4a908dc56eec361edb66c4b 100644 --- a/src/sylvan_sog.c +++ b/src/sylvan_sog.c @@ -77,50 +77,3 @@ TASK_IMPL_3(MDD, lddmc_firing_lace, MDD, cmark, MDD, minus, MDD ,plus) { } - - -/*TASK_IMPL_3(MDD, lddmc_firing_lace, MDD, cmark, MDD, minus, MDD ,plus) { - - if (cmark == lddmc_true) return lddmc_true; - if (minus == lddmc_false) return lddmc_false; - if (plus == lddmc_false) return lddmc_false; - - MDD result; - if (cache_get3(CACHE_FIRING_LACE, cmark, minus, plus, &result)) { - printf("cached\n"); - sylvan_stats_count(CACHE_FIRING_LACE); - return result; - } - - mddnode_t n_cmark = GETNODE(cmark); - mddnode_t n_plus = GETNODE(plus); - mddnode_t n_minus = GETNODE(minus); - - result= lddmc_false; - //lddmc_refs_pushptr(&result); - for (;;) - { - uint32_t value; - value = mddnode_getvalue(n_cmark); - uint32_t value_minus = mddnode_getvalue(n_minus); - uint32_t value_plus = mddnode_getvalue(n_plus); - if (value>=value_minus) - { - lddmc_refs_push(result); - MDD left=CALL(lddmc_firing_lace, mddnode_getdown(n_cmark), mddnode_getdown(n_minus), mddnode_getdown(n_plus)); - lddmc_refs_push(left); - MDD result2 = - lddmc_makenode(value-value_minus+value_plus,left, lddmc_false); - lddmc_refs_push(result2); - result = lddmc_union( result, result2); - lddmc_refs_pop(3); - } - cmark = mddnode_getright(n_cmark); - if (cmark == lddmc_false) break; - n_cmark = GETNODE(cmark); - } - //lddmc_refs_popptr(1); - if (cache_put3(CACHE_FIRING_LACE, cmark, minus, plus,result)) sylvan_stats_count(CACHE_FIRING_LACE); - return result; -} -*/ diff --git a/third-party/sylvan b/third-party/sylvan index f7e4ec329a6accebb76647b7a93a738d379d7528..8582330575f48f010f175d9f2da630280f4cdb10 160000 --- a/third-party/sylvan +++ b/third-party/sylvan @@ -1 +1 @@ -Subproject commit f7e4ec329a6accebb76647b7a93a738d379d7528 +Subproject commit 8582330575f48f010f175d9f2da630280f4cdb10