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
This commit is contained in:
Tomasz Sowa 2012-04-28 20:57:57 +00:00
parent 1da1eef768
commit fc33b4f882
5 changed files with 74 additions and 16 deletions

View File

@ -139,8 +139,6 @@ void Job::DoJob(PT::Space & job)
{ {
try try
{ {
// !! FIXME plugin.Call() can log messages
// we need Lock/Unlock mechanism there
PluginRes res = plugin.Call((Session*)0, WINIX_JOB, &job); PluginRes res = plugin.Call((Session*)0, WINIX_JOB, &job);
if( res.res_true == 0 ) if( res.res_true == 0 )

View File

@ -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) 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); bool res = (db && config && cur && system && functions && templates && synchro && session_manager);
if( !res ) if( !res )
{
Lock();
log << log1 << "Plugin: cannot call a function - some of the winix pointers are null" << logend; log << log1 << "Plugin: cannot call a function - some of the winix pointers are null" << logend;
Unlock();
}
info.db = db; info.db = db;
info.config = config; 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 * Plugin::LoadInitFun(const char * filename, Fun1 & fun_init)
{ {
void * p = dlopen(filename, RTLD_NOW | RTLD_LOCAL); 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( !slot->second.is_running )
{ {
if( config->log_plugin_call ) if( config->log_plugin_call )
{
Lock();
log << log1 << "Plugin: calling plugin id: " << slot->second.index << ", message: " << message << logend; log << log1 << "Plugin: calling plugin id: " << slot->second.index << ", message: " << message << logend;
Unlock();
}
slot->second.is_running = true; 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; slot->second.is_running = false;
if( config->log_plugin_call ) if( config->log_plugin_call )
{
Lock();
log << log1 << "Plugin: returning from plugin id: " << slot->second.index << ", message: " << message log << log1 << "Plugin: returning from plugin id: " << slot->second.index << ", message: " << message
<< ", result: " << (info.res? "true" : "false") << logend; << ", result: " << (info.res? "true" : "false") << logend;
Unlock();
}
} }
else else
{ {
Lock();
log << log1 << "Plugin: id: " << slot->second.index log << log1 << "Plugin: id: " << slot->second.index
<< ", message: " << message << ", message: " << message
<< ", recurrences are not allowed" << logend; << ", recurrences are not allowed" << logend;
Unlock();
} }
} }
@ -430,10 +460,10 @@ size_t Plugin::Size()
/* /*
!! IMPROVE ME !! IMPROVE ME
Assign() can work only if other threads are not started Assign() can work only if other threads are not started
we can add some barrier/flag so when other threads starts we can add some barrier/flag so when other threads starts
then we cannot use Assign() method then we cannot use Assign() method
*/ */
void Plugin::Assign(int message, Fun1 fun1) void Plugin::Assign(int message, Fun1 fun1)
{ {

View File

@ -225,19 +225,20 @@ private:
Synchro * synchro; Synchro * synchro;
SessionManager * session_manager; SessionManager * session_manager;
std::wstring temp_path; std::wstring temp_path; // used when loading plugins
std::string afilename;
Plugins plugins; Plugins plugins;
typedef std::multimap<int, Slot> Slots; typedef std::multimap<int, Slot> Slots;
Slots slots; Slots slots;
std::string afilename;
void * LoadInitFun(const char * filename, Fun1 & fun_init); void * LoadInitFun(const char * filename, Fun1 & fun_init);
void Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info); void Call(Session * ses, int message, Slots::iterator & slot, PluginInfo & info);
bool SetPointers(PluginInfo & info); bool SetPointers(PluginInfo & info);
void Lock();
void Unlock();
}; };

View File

@ -2,31 +2,53 @@
* This file is a part of Winix * This file is a part of Winix
* and is not publicly distributed * and is not publicly distributed
* *
* Copyright (c) 2010, Tomasz Sowa * Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
*/ */
#include "synchro.h"
#include <errno.h>
#include "synchro.h"
Synchro::Synchro() : mutex(PTHREAD_MUTEX_INITIALIZER) Synchro::Synchro() : mutex(PTHREAD_MUTEX_INITIALIZER)
{ {
was_stop_signal = false; was_stop_signal = false;
ref = 0;
} }
bool Synchro::Lock() 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() void Synchro::Unlock()
{ {
pthread_mutex_unlock(&mutex); if( ref > 0 )
{
ref -= 1;
}
else
{
pthread_mutex_unlock(&mutex);
}
} }

View File

@ -2,7 +2,7 @@
* This file is a part of Winix * This file is a part of Winix
* and is not publicly distributed * and is not publicly distributed
* *
* Copyright (c) 2010, Tomasz Sowa * Copyright (c) 2010-2012, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
*/ */
@ -28,6 +28,13 @@ struct Synchro
bool Lock(); bool Lock();
void Unlock(); void Unlock();
private:
// deadlock counter
// we can call Lock() more than one in the same thread
int ref;
}; };