From fc33b4f88200464286a90176792a3c879d300601 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sat, 28 Apr 2012 20:57:57 +0000 Subject: [PATCH] added: a deadlock counter to Synchro class now we can use Lock() more than one in the same thread and next Unlock() will recognize it sample: Lock(); // first lock -- resources locked Lock(); // second lock -- skipped (counter incremented) ... Unlock(); // first unlock -- skipped (because counter greater than zero) Unlock(); // second unlock -- actually unlocking git-svn-id: svn://ttmath.org/publicrep/winix/trunk@830 e52654a7-88a9-db11-a3e9-0013d4bc506e --- core/job.cpp | 2 -- core/plugin.cpp | 40 +++++++++++++++++++++++++++++++++++----- core/plugin.h | 7 ++++--- core/synchro.cpp | 32 +++++++++++++++++++++++++++----- core/synchro.h | 9 ++++++++- 5 files changed, 74 insertions(+), 16 deletions(-) diff --git a/core/job.cpp b/core/job.cpp index cd78a37..4c53ae9 100755 --- a/core/job.cpp +++ b/core/job.cpp @@ -139,8 +139,6 @@ void Job::DoJob(PT::Space & job) { try { - // !! FIXME plugin.Call() can log messages - // we need Lock/Unlock mechanism there PluginRes res = plugin.Call((Session*)0, WINIX_JOB, &job); if( res.res_true == 0 ) diff --git a/core/plugin.cpp b/core/plugin.cpp index 834277e..83a28c9 100755 --- a/core/plugin.cpp +++ b/core/plugin.cpp @@ -98,6 +98,21 @@ void Plugin::SetSessionManager(SessionManager * psession_manager) +void Plugin::Lock() +{ + if( synchro ) + synchro->Lock(); +} + + +void Plugin::Unlock() +{ + if( synchro ) + synchro->Unlock(); +} + + + bool Plugin::SetPointers(PluginInfo & info) { @@ -105,7 +120,11 @@ bool Plugin::SetPointers(PluginInfo & info) bool res = (db && config && cur && system && functions && templates && synchro && session_manager); if( !res ) + { + Lock(); log << log1 << "Plugin: cannot call a function - some of the winix pointers are null" << logend; + Unlock(); + } info.db = db; info.config = config; @@ -145,7 +164,8 @@ void Plugin::LoadPlugin(const std::string & filename) } - +// we don't have to use Lock() here because plusings are read +// before threads are started void * Plugin::LoadInitFun(const char * filename, Fun1 & fun_init) { void * p = dlopen(filename, RTLD_NOW | RTLD_LOCAL); @@ -265,7 +285,11 @@ void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo if( !slot->second.is_running ) { if( config->log_plugin_call ) + { + Lock(); log << log1 << "Plugin: calling plugin id: " << slot->second.index << ", message: " << message << logend; + Unlock(); + } slot->second.is_running = true; @@ -278,15 +302,21 @@ void Plugin::Call(Session * ses, int message, Slots::iterator & slot, PluginInfo slot->second.is_running = false; if( config->log_plugin_call ) + { + Lock(); log << log1 << "Plugin: returning from plugin id: " << slot->second.index << ", message: " << message << ", result: " << (info.res? "true" : "false") << logend; + Unlock(); + } } else { + Lock(); log << log1 << "Plugin: id: " << slot->second.index << ", message: " << message << ", recurrences are not allowed" << logend; + Unlock(); } } @@ -430,10 +460,10 @@ size_t Plugin::Size() /* - !! IMPROVE ME - Assign() can work only if other threads are not started - we can add some barrier/flag so when other threads starts - then we cannot use Assign() method + !! IMPROVE ME + Assign() can work only if other threads are not started + we can add some barrier/flag so when other threads starts + then we cannot use Assign() method */ void Plugin::Assign(int message, Fun1 fun1) { diff --git a/core/plugin.h b/core/plugin.h index 11360f2..de772d0 100755 --- a/core/plugin.h +++ b/core/plugin.h @@ -225,19 +225,20 @@ private: Synchro * synchro; SessionManager * session_manager; - std::wstring temp_path; + std::wstring temp_path; // used when loading plugins + std::string afilename; Plugins plugins; typedef std::multimap Slots; Slots slots; - - std::string afilename; void * LoadInitFun(const char * filename, Fun1 & fun_init); void Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info); bool SetPointers(PluginInfo & info); + void Lock(); + void Unlock(); }; diff --git a/core/synchro.cpp b/core/synchro.cpp index 47f8227..81bd3d7 100755 --- a/core/synchro.cpp +++ b/core/synchro.cpp @@ -2,31 +2,53 @@ * This file is a part of Winix * and is not publicly distributed * - * Copyright (c) 2010, Tomasz Sowa + * Copyright (c) 2010-2012, Tomasz Sowa * All rights reserved. * */ - -#include "synchro.h" +#include +#include "synchro.h" Synchro::Synchro() : mutex(PTHREAD_MUTEX_INITIALIZER) { was_stop_signal = false; + ref = 0; } bool Synchro::Lock() { - return pthread_mutex_lock(&mutex) == 0; + int res = pthread_mutex_lock(&mutex); + + if( res == EDEADLK ) + { + // Lock() method in this thread was called before + ref += 1; + return true; + } + else + { + ref = 0; + } + +return res == 0; } + void Synchro::Unlock() { - pthread_mutex_unlock(&mutex); + if( ref > 0 ) + { + ref -= 1; + } + else + { + pthread_mutex_unlock(&mutex); + } } diff --git a/core/synchro.h b/core/synchro.h index 0756f7c..65056c1 100755 --- a/core/synchro.h +++ b/core/synchro.h @@ -2,7 +2,7 @@ * This file is a part of Winix * and is not publicly distributed * - * Copyright (c) 2010, Tomasz Sowa + * Copyright (c) 2010-2012, Tomasz Sowa * All rights reserved. * */ @@ -28,6 +28,13 @@ struct Synchro bool Lock(); void Unlock(); + +private: + + // deadlock counter + // we can call Lock() more than one in the same thread + int ref; + };