redmine

Fixed high load locks for the splitted process

... ... @@ -6,9 +6,9 @@ bin_PROGRAMS = clsync
clsync_SOURCES = calc.c cluster.c error.c fileutils.c glibex.c \
indexes.c main.c malloc.c rules.c stringex.c sync.c privileged.c\
calc.h cluster.h fileutils.h glibex.h main.h port-hacks.h \
stringex.h sync.h common.h control.h privileged.h rules.h \
syscalls.h
pthreadex.c calc.h cluster.h fileutils.h glibex.h main.h \
port-hacks.h pthreadex.h stringex.h sync.h common.h control.h \
privileged.h rules.h syscalls.h
clsync_CFLAGS = $(AM_CFLAGS)
... ...
/*
clsyncmgr - intermediate daemon to aggregate clsync's sockets
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
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/>.
*/
... ... @@ -29,9 +29,10 @@
#include <string.h>
#include <stdarg.h>
#include <syslog.h>
#include <pthread.h> /* pthread_self() */
#include <pthread.h> /* pthread_self() */
#include "error.h"
#include "common.h"
#include "pthreadex.h" /* pthread_*_shared() */
static int zero = 0;
static int three = 3;
... ... @@ -41,7 +42,7 @@ static int *debug = &zero;
static int *quiet = &zero;
static int *verbose = &three;
pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t *error_mutex_p;
static int printf_stderr(const char *fmt, ...) {
va_list args;
... ... @@ -169,7 +170,7 @@ void _critical(const char *const function_name, const char *fmt, ...) {
if (*quiet)
return;
pthread_mutex_lock(&error_mutex);
pthread_mutex_lock(error_mutex_p);
outputmethod_t method = *outputmethod;
... ... @@ -197,7 +198,7 @@ void _critical(const char *const function_name, const char *fmt, ...) {
outfunct[method]("_critical(): Got error, but cannot print the backtrace. Current errno: %u: %s\n",
errno, strerror(errno));
flushfunct[method](LOG_CRIT);
pthread_mutex_unlock(&error_mutex);
pthread_mutex_unlock(error_mutex_p);
exit(EXIT_FAILURE);
}
... ... @@ -208,7 +209,7 @@ void _critical(const char *const function_name, const char *fmt, ...) {
}
#endif
pthread_mutex_unlock(&error_mutex);
pthread_mutex_unlock(error_mutex_p);
exit(errno);
return;
... ... @@ -223,7 +224,7 @@ void _error(const char *const function_name, const char *fmt, ...) {
if (*verbose < 1)
return;
pthread_mutex_lock(&error_mutex);
pthread_mutex_lock(error_mutex_p);
pthread_t thread = pthread_self();
pid_t pid = getpid();
... ... @@ -237,7 +238,7 @@ void _error(const char *const function_name, const char *fmt, ...) {
outfunct[method](" (%i: %s)", errno, strerror(errno));
flushfunct[method](LOG_ERR);
pthread_mutex_unlock(&error_mutex);
pthread_mutex_unlock(error_mutex_p);
return;
}
... ... @@ -250,7 +251,7 @@ void _info(const char *const function_name, const char *fmt, ...) {
if (*verbose < 3)
return;
pthread_mutex_lock(&error_mutex);
pthread_mutex_lock(error_mutex_p);
pthread_t thread = pthread_self();
pid_t pid = getpid();
... ... @@ -262,7 +263,7 @@ void _info(const char *const function_name, const char *fmt, ...) {
va_end(args);
flushfunct[method](LOG_INFO);
pthread_mutex_unlock(&error_mutex);
pthread_mutex_unlock(error_mutex_p);
return;
}
... ... @@ -275,7 +276,7 @@ void _warning(const char *const function_name, const char *fmt, ...) {
if (*verbose < 2)
return;
pthread_mutex_lock(&error_mutex);
pthread_mutex_lock(error_mutex_p);
pthread_t thread = pthread_self();
pid_t pid = getpid();
... ... @@ -287,7 +288,7 @@ void _warning(const char *const function_name, const char *fmt, ...) {
va_end(args);
flushfunct[method](LOG_WARNING);
pthread_mutex_unlock(&error_mutex);
pthread_mutex_unlock(error_mutex_p);
return;
}
... ... @@ -301,7 +302,7 @@ void _debug(int debug_level, const char *const function_name, const char *fmt, .
if (debug_level > *debug)
return;
pthread_mutex_lock(&error_mutex);
pthread_mutex_lock(error_mutex_p);
pthread_t thread = pthread_self();
pid_t pid = getpid();
... ... @@ -313,7 +314,7 @@ void _debug(int debug_level, const char *const function_name, const char *fmt, .
va_end(args);
flushfunct[method](LOG_DEBUG);
pthread_mutex_unlock(&error_mutex);
pthread_mutex_unlock(error_mutex_p);
return;
}
#endif
... ... @@ -324,7 +325,7 @@ void error_init(void *_outputmethod, int *_quiet, int *_verbose, int *_debug) {
verbose = _verbose;
debug = _debug;
pthread_mutex_init(&error_mutex, NULL);
pthread_mutex_init_shared(&error_mutex_p);
openlog(NULL, SYSLOG_FLAGS, SYSLOG_FACILITY);
return;
... ...
/*
clsyncmgr - intermediate daemon to aggregate clsync's sockets
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
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/>.
*/
... ...
... ... @@ -22,6 +22,7 @@
#include "error.h" // debug()
#include "syscalls.h" // read_inf()/write_inf()
#include "main.h" // ncpus
#include "pthreadex.h" // pthread_*_shared()
#ifdef CAPABILITIES_SUPPORT
# include <pthread.h> // pthread_create()
... ... @@ -230,20 +231,21 @@ enum highlock_lock_state {
typedef enum highlock_lock_state hllock_state_t;
struct hl_lock {
int enabled;
int count_wait[HLLOCK_MAX];
int count_signal[HLLOCK_MAX];
hllock_state_t state[HLLOCK_MAX];
volatile int locallock_hl_setstate_ifstate;
volatile int enabled;
volatile int count_wait[HLLOCK_MAX];
volatile int count_signal[HLLOCK_MAX];
volatile hllock_state_t state[HLLOCK_MAX];
# ifdef HL_LOCK_TRIES_AUTO
unsigned long tries[PC_MAX];
unsigned long count[PC_MAX];
unsigned long delay[PC_MAX];
double tries_step[PC_MAX];
volatile unsigned long tries[PC_MAX];
volatile unsigned long count[PC_MAX];
volatile unsigned long delay[PC_MAX];
volatile double tries_step[PC_MAX];
# define tries_cur tries[callid]
# define tries_cur tries[callid]
# else
unsigned long tries;
# define tries_cur tries
volatile unsigned long tries;
# define tries_cur tries
# endif
};
# endif
... ... @@ -266,12 +268,13 @@ struct cmd {
volatile int _errno;
# ifdef HL_LOCKS
volatile struct hl_lock hl_lock;
unsigned long hl_lock_tries;
volatile unsigned long hl_lock_tries;
# endif
};
volatile struct cmd *cmd_p;
static inline void cmd_init(volatile struct cmd *cmd_p) {
debug(10, "");
# ifdef HL_LOCKS
memset((void *)cmd_p, 0, sizeof(*cmd_p));
cmd_p->hl_lock.enabled = 1;
... ... @@ -300,42 +303,6 @@ struct pa_options {
int permitted_hookfiles;
};
int pthread_mutex_init_shared(pthread_mutex_t **mutex_p) {
static pthread_mutex_t mutex_initial = PTHREAD_MUTEX_INITIALIZER;
*mutex_p = shm_malloc(sizeof(**mutex_p));
memcpy(*mutex_p, &mutex_initial, sizeof(mutex_initial));
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
return pthread_mutex_init(*mutex_p, &attr);
}
int pthread_mutex_destroy_shared(pthread_mutex_t *mutex_p) {
int rc;
rc = pthread_mutex_destroy(mutex_p);
shm_free(mutex_p);
return rc;
}
int pthread_cond_init_shared(pthread_cond_t **cond_p) {
static pthread_cond_t cond_initial = PTHREAD_COND_INITIALIZER;
*cond_p = shm_malloc(sizeof(**cond_p));
memcpy(*cond_p, &cond_initial, sizeof(cond_initial));
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
return pthread_cond_init(*cond_p, &attr);
}
int pthread_cond_destroy_shared(pthread_cond_t *cond_p) {
int rc;
rc = pthread_cond_destroy(cond_p);
shm_free(cond_p);
return rc;
}
FTS *(*_privileged_fts_open) (
char * const *path_argv,
int options,
... ... @@ -678,29 +645,33 @@ static inline int hl_isready(int lockid) {
}
static inline void hl_setstate(int lockid, hllock_state_t stateid) {
cmd_p->hl_lock.state[lockid] = stateid;
g_atomic_int_set(&cmd_p->hl_lock.state[lockid], stateid);
}
int hl_setstate_ifstate(int lockid, hllock_state_t stateid_new, hllock_state_t stateid_old_mask) {
static int local_lock = 0;
volatile int *local_lock_p = &cmd_p->hl_lock.locallock_hl_setstate_ifstate;
debug(90, "%i, 0x%o, 0x%o", lockid, stateid_new, stateid_old_mask);
if (local_lock)
if (*local_lock_p)
return 0;
g_atomic_int_inc(&local_lock);
if (local_lock != 1) {
g_atomic_int_dec_and_test(&local_lock);
debug(92, "%i", *local_lock_p);
g_atomic_int_inc(local_lock_p);
debug(92, "%i", *local_lock_p);
if (*local_lock_p != 1) {
g_atomic_int_dec_and_test(local_lock_p);
return 0;
}
if (!(cmd_p->hl_lock.state[lockid]&stateid_old_mask)) {
g_atomic_int_dec_and_test(&local_lock);
g_atomic_int_dec_and_test(local_lock_p);
return 0;
}
cmd_p->hl_lock.state[lockid] = stateid_new;
g_atomic_int_dec_and_test(&local_lock);
debug(50, "success");
g_atomic_int_set(&cmd_p->hl_lock.state[lockid], stateid_new);
g_atomic_int_dec_and_test(local_lock_p);
#undef local_lock
return 1;
}
... ... @@ -736,11 +707,13 @@ static inline int hl_signal(int lockid) {
cmd_p->hl_lock.count_signal[lockid]++;
if (hl_setstate_ifstate(lockid, HLLS_SIGNAL, HLLS_READY)) {
while (cmd_p->hl_lock.state[lockid] != HLLS_GOTSIGNAL)
while (cmd_p->hl_lock.state[lockid] != HLLS_GOTSIGNAL) {
if (cmd_p->hl_lock.state[lockid] == HLLS_FALLBACK) {
debug(15, "fallback");
return 0;
}
debug(95, "state == %i != %i, %i", cmd_p->hl_lock.state[lockid], HLLS_GOTSIGNAL, HLLS_FALLBACK);
}
debug(15, "the signal is sent");
hl_setstate(lockid, HLLS_WORKING);
return 1;
... ... @@ -847,6 +820,7 @@ int privileged_handler(ctx_t *ctx_p)
// Waiting for command
debug(10, "Waiting for command");
# ifdef HL_LOCKS
debug(25, "cmd_p->hl_lock.enabled == %i", cmd_p->hl_lock.enabled);
if (!cmd_p->hl_lock.enabled || !hl_wait(
HLLOCK_HANDLER
# ifdef HL_LOCK_TRIES_AUTO
... ... @@ -1517,6 +1491,7 @@ int privileged_init(ctx_t *ctx_p)
unshare(CLONE_NEWIPC);
cmd_p = shm_malloc(sizeof(*cmd_p));
cmd_init(cmd_p);
// Running the privileged helper
SAFE ( (helper_pid = myfork()) == -1, return errno);
... ...
/*
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
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 <string.h>
#include <pthread.h>
#include "pthreadex.h"
#include "malloc.h"
int pthread_mutex_init_shared(pthread_mutex_t **mutex_p) {
static pthread_mutex_t mutex_initial = PTHREAD_MUTEX_INITIALIZER;
*mutex_p = shm_malloc(sizeof(**mutex_p));
memcpy(*mutex_p, &mutex_initial, sizeof(mutex_initial));
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
return pthread_mutex_init(*mutex_p, &attr);
}
int pthread_mutex_destroy_shared(pthread_mutex_t *mutex_p) {
int rc;
rc = pthread_mutex_destroy(mutex_p);
shm_free(mutex_p);
return rc;
}
int pthread_cond_init_shared(pthread_cond_t **cond_p) {
static pthread_cond_t cond_initial = PTHREAD_COND_INITIALIZER;
*cond_p = shm_malloc(sizeof(**cond_p));
memcpy(*cond_p, &cond_initial, sizeof(cond_initial));
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
return pthread_cond_init(*cond_p, &attr);
}
int pthread_cond_destroy_shared(pthread_cond_t *cond_p) {
int rc;
rc = pthread_cond_destroy(cond_p);
shm_free(cond_p);
return rc;
}
... ...
/*
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
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 <pthread.h>
extern int pthread_mutex_init_shared(pthread_mutex_t **mutex_p);
extern int pthread_mutex_destroy_shared(pthread_mutex_t *mutex_p);
extern int pthread_cond_init_shared(pthread_cond_t **cond_p);
extern int pthread_cond_destroy_shared(pthread_cond_t *cond_p);
... ...