From ef1d1986544fd84f11dfd0948f8d035b0ccbd1d5 Mon Sep 17 00:00:00 2001 From: vraatikka Date: Wed, 26 Jun 2013 23:13:40 +0300 Subject: [PATCH] Changed log manager API so that pointer reference to logmanager is not used anymore. Every call initializes logmanager now except skygw_logmanager_done and skygw_log_flush. skygw_logmanager_init is still useful because it allows for providing memory address for log manager where it can store a list of preallocated write buffers. TBD. Logmanager access is now protected with spinlock familiar from epoll/core/spinlock.c . It is modified to avoid trashing; misses are counted and every tenth subsequent lock acquiring attempt triggers short random sleep. --- log_manager/log_manager.cc | 415 +++++++++++++++++++++---------------- log_manager/log_manager.h | 13 +- log_manager/makefile | 5 +- log_manager/test/makefile | 4 +- log_manager/test/testlog.c | 150 ++++++++++++-- utils/skygw_utils.cc | 15 +- utils/skygw_utils.h | 5 + 7 files changed, 397 insertions(+), 210 deletions(-) diff --git a/log_manager/log_manager.cc b/log_manager/log_manager.cc index df5c82edd..1958f81e3 100644 --- a/log_manager/log_manager.cc +++ b/log_manager/log_manager.cc @@ -16,7 +16,6 @@ * Copyright SkySQL Ab 2013 */ - #include #include #include @@ -26,11 +25,15 @@ #include #include #include +#include #define MAX_PREFIXLEN 250 #define MAX_SUFFIXLEN 250 #define MAX_PATHLEN 512 +static int lmlock; +static logmanager_t* lm; + /** Write buffer structure */ typedef struct logfile_writebuf_st { skygw_chk_t wb_chk_top; @@ -133,12 +136,15 @@ static logfile_writebuf_t** get_or_create_writebuffers( size_t bufsize); static int logmanager_write( void* ctx, - logmanager_t* lmgr, logfile_id_t id, char* str, bool flush); -static bool logmanager_register(logmanager_t* lmgr); -static bool logmanager_unregister(logmanager_t* lmgr); +static bool logmanager_register(bool writep); +static void logmanager_unregister(void); +static bool logmanager_init_nomutex(void** p_ctx, int argc, char* argv[]); +static void logmanager_done_nomutex(void** ctx); +static void acquire_lock(int* l); +static void release_lock(int* l); static void logfile_write_buffers( logfile_t* lf, logfile_writebuf_t** p_wb, @@ -190,6 +196,81 @@ const size_t get_bufsize_default(void) return (size_t)256; } +static void acquire_lock( + int* l) +{ + register short int misscount = 0; + + while (atomic_add(l, 1) != 0) { + atomic_add(l, -1); + misscount += 1; + if (misscount > 10) { + usleep(rand()%100); + misscount = 0; + } + } +} + +static void release_lock( + int* l) +{ + atomic_add(l, -1); +} + +static bool logmanager_init_nomutex( + void** p_ctx, + int argc, + char* argv[]) +{ + fnames_conf_t* fn; + filewriter_t* fw; + int err; + bool succp = FALSE; + + lm = (logmanager_t *)calloc(1, sizeof(logmanager_t)); + lm->lm_chk_top = CHK_NUM_LOGMANAGER; + lm->lm_chk_tail = CHK_NUM_LOGMANAGER; + lm->lm_clientmes = skygw_message_init(); + lm->lm_logmes = skygw_message_init(); + fn = &lm->lm_fnames_conf; + fw = &lm->lm_filewriter; + + /** Initialize configuration including log file naming info */ + if (!fnames_conf_init(fn, argc, argv)) { + goto return_succp; + } + + /** Initialize logfiles */ + if(!logfiles_init(lm)) { + goto return_succp; + } + + /** Initialize filewriter data and open the (first) log file(s) + * for each log file type. */ + if (!filewriter_init(lm, fw, lm->lm_clientmes, lm->lm_logmes)) { + goto return_succp; + } + /** Initialize and start filewriter thread */ + fw->fwr_thread = skygw_thread_init(strdup("filewriter thr"), + thr_filewriter_fun, + (void *)fw); + + if ((err = skygw_thread_start(fw->fwr_thread)) != 0) { + goto return_succp; + } + /** Wait message from filewriter_thr */ + skygw_message_wait(fw->fwr_clientmes); + succp = TRUE; + lm->lm_enabled = TRUE; + +return_succp: + if (err != 0) { + /** This releases memory of all created objects */ + logmanager_done_nomutex(NULL); + fprintf(stderr, "Initializing logmanager failed.\n"); + } + return succp; +} /** * @node Initializes log managing routines in SkySQL Gateway. @@ -211,120 +292,43 @@ const size_t get_bufsize_default(void) * @details (write detailed description here) * */ -logmanager_t* skygw_logmanager_init( +bool skygw_logmanager_init( void** p_ctx, int argc, char* argv[]) { - logmanager_t* lmgr = NULL; - fnames_conf_t* fn; - filewriter_t* fw; - int err; + bool succp = FALSE; ss_dfprintf(stderr, ">> skygw_logmanager_init\n"); - - lmgr = (logmanager_t *)calloc(1, sizeof(logmanager_t)); - lmgr->lm_chk_top = CHK_NUM_LOGMANAGER; - lmgr->lm_chk_tail = CHK_NUM_LOGMANAGER; - - if (simple_mutex_init( - &lmgr->lm_mutex, - strdup("Logmanager mutex")) == NULL) - { - goto return_err; - } - lmgr->lm_clientmes = skygw_message_init(); - lmgr->lm_logmes = skygw_message_init(); - fn = &lmgr->lm_fnames_conf; - fw = &lmgr->lm_filewriter; - /** Initialize configuration including log file naming info */ - if (!fnames_conf_init(fn, argc, argv)) { - goto return_err; + acquire_lock(&lmlock); + + if (lm != NULL) { + succp = TRUE; + goto return_succp; } - /** Initialize logfiles */ - if(!logfiles_init(lmgr)) { - goto return_err; - } + succp = logmanager_init_nomutex(p_ctx, argc, argv); - /** Initialize filewriter data and open the (first) log file(s) - * for each log file type. */ - if (!filewriter_init(lmgr, fw, lmgr->lm_clientmes, lmgr->lm_logmes)) { - goto return_err; - } - /** Initialize and start filewriter thread */ - fw->fwr_thread = - skygw_thread_init( - strdup("filewriter thr"), - thr_filewriter_fun, - (void *)fw); - - if ((err = skygw_thread_start(fw->fwr_thread)) != 0) { - goto return_err; - } - /** Wait message from filewriter_thr */ - skygw_message_wait(fw->fwr_clientmes); +return_succp: + release_lock(&lmlock); -return_mgr: - lmgr->lm_enabled = TRUE; ss_dfprintf(stderr, "<< skygw_logmanager_init\n"); - return lmgr; - -return_err: - /** This includes clear-up for all created objects */ - skygw_logmanager_done(NULL, &lmgr); - fprintf(stderr, "Initializing logmanager failed.\n"); - goto return_mgr; + return succp; } -/** - * @node End execution of log manager - * - * Parameters: - * @param p_ctx - in, take - * pointer to memory location including context pointer. Context will - * be freed in this function. - * - * @param logmanager - in, use - * pointer to logmanager. - * - * @return void - * - * - * @details Stops file writing thread, releases filewriter, and logfiles. - * - */ -void skygw_logmanager_done( - void** p_ctx, - logmanager_t** logmanager) +static void logmanager_done_nomutex( + void** ctx) { int i; - filewriter_t* fwr; logfile_t* lf; logmanager_t* lmgr; + filewriter_t* fwr; - ss_dfprintf(stderr, ">> skygw_logmanager_done\n"); - lmgr = *logmanager; - - if (lmgr == NULL) { - fprintf(stderr, "Error. Logmanager is not initialized.\n"); - return; - } - CHK_LOGMANAGER(lmgr); - lmgr->lm_enabled = FALSE; - - while (TRUE) { - simple_mutex_lock(&lmgr->lm_mutex, TRUE); - - if (lmgr->lm_nlinks == 0) { - simple_mutex_unlock(&lmgr->lm_mutex); - break; - } - simple_mutex_unlock(&lmgr->lm_mutex); - usleep(100*MSEC_USEC); - } + /** Set global pointer NULL */ + lmgr = lm; + lm = NULL; fwr = &lmgr->lm_filewriter; CHK_FILEWRITER(fwr); @@ -345,14 +349,63 @@ void skygw_logmanager_done( /** Release logfile memory */ logfile_done(lf); } - + /** Release messages and finally logmanager memory */ fnames_conf_done(&lmgr->lm_fnames_conf); skygw_message_done(lmgr->lm_clientmes); skygw_message_done(lmgr->lm_logmes); - simple_mutex_done(&lmgr->lm_mutex); free(lmgr); - *logmanager = NULL; +} + +/** + * @node End execution of log manager + * + * Parameters: + * @param p_ctx - in, take + * pointer to memory location including context pointer. Context will + * be freed in this function. + * + * @param logmanager - in, use + * pointer to logmanager. + * + * @return void + * + * + * @details Stops file writing thread, releases filewriter, and logfiles. + * + */ +void skygw_logmanager_done( + void** p_ctx) +{ + ss_dfprintf(stderr, ">> skygw_logmanager_done\n"); + + acquire_lock(&lmlock); + + if (lm == NULL) { + release_lock(&lmlock); + return; + } + CHK_LOGMANAGER(lm); + /** Mark logmanager unavailable */ + lm->lm_enabled = FALSE; + /** Wait until all users have left or someone shuts down + * logmanager between lock release and acquire. + */ + while(lm != NULL && lm->lm_nlinks != 0) { + release_lock(&lmlock); + pthread_yield(); + acquire_lock(&lmlock); + } + + /** Logmanager was already shut down. Return successfully. */ + if (lm == NULL) { + goto return_void; + } + ss_dassert(lm->lm_nlinks == 0); + logmanager_done_nomutex(p_ctx); + +return_void: + release_lock(&lmlock); ss_dfprintf(stderr, "<< skygw_logmanager_done\n"); } @@ -369,7 +422,6 @@ static logfile_t* logmanager_get_logfile( static int logmanager_write( void* ctx, - logmanager_t* lmgr, logfile_id_t id, char* str, bool flush) @@ -379,14 +431,12 @@ static int logmanager_write( logfile_writebuf_t** wb_arr; int err = 0; - CHK_LOGMANAGER(lmgr); - ss_dassert(id >= LOGFILE_FIRST && id <= LOGFILE_LAST); + CHK_LOGMANAGER(lm); if (id < LOGFILE_FIRST || id > LOGFILE_LAST) { /** invalid id, since we don't have logfile yet, * recall logmanager_write. */ err = logmanager_write(NULL, - lmgr, LOGFILE_ERROR, strdup("Invalid logfile id argument."), TRUE); @@ -396,10 +446,11 @@ static int logmanager_write( STRLOGID(LOGFILE_ERROR)); } err = -1; + ss_dassert(FALSE); goto return_err; } /** Get logfile and check its correctness. */ - lf = logmanager_get_logfile(lmgr, id); + lf = logmanager_get_logfile(lm, id); CHK_LOGFILE(lf); if (lf == NULL) { @@ -420,9 +471,10 @@ static int logmanager_write( err = -1; goto return_err; } - /** Split loginfo to buffers, if necessary, and add buffers - * to logfile. - * Free write buffer pointer array. */ + /** + * Split log string to buffers, if necessary, and add buffers + * to logfile. Free write buffer pointer array. + */ logfile_write_buffers(lf, wb_arr, str); } else { ss_dassert(flush); @@ -566,29 +618,22 @@ static void logfile_write_buffers( int skygw_log_write_flush( void* ctx, - logmanager_t* lmgr, logfile_id_t id, char* str) { int err = 0; - - if (lmgr == NULL) { - fprintf(stderr, "Error. Logmanager is not initialized.\n"); - err = -1; - goto return_err; - } - CHK_LOGMANAGER(lmgr); - - if (!logmanager_register(lmgr)) { - fprintf(stderr, "Logmanager is not available\n"); + + if (!logmanager_register(TRUE)) { + fprintf(stderr, "ERROR: Can't register to logmanager\n"); err = -1; goto return_err; } + CHK_LOGMANAGER(lm); ss_dfprintf(stderr, "skygw_log_write_flush writes to %s :\n\t%s.\n", STRLOGID(id), str); - err = logmanager_write(ctx, lmgr, id, str, TRUE); + err = logmanager_write(ctx, id, str, TRUE); if (err != 0) { fprintf(stderr, "skygw_log_write_flush failed.\n"); @@ -597,7 +642,7 @@ int skygw_log_write_flush( ss_dfprintf(stderr, "skygw_log_write_flush succeeed.\n"); return_unregister: - logmanager_unregister(lmgr); + logmanager_unregister(); return_err: /** Free log string */ free(str); @@ -606,29 +651,22 @@ return_err: int skygw_log_write( void* ctx, - logmanager_t* lmgr, logfile_id_t id, char* str) { int err = 0; - if (lmgr == NULL) { - fprintf(stderr, "Error. Logmanager is not initialized.\n"); - err = -1; - goto return_err; - } - CHK_LOGMANAGER(lmgr); - - if (!logmanager_register(lmgr)) { - fprintf(stderr, "Logmanager is not available\n"); + if (!logmanager_register(TRUE)) { + fprintf(stderr, "ERROR: Can't register to logmanager\n"); err = -1; goto return_err; } + CHK_LOGMANAGER(lm); ss_dfprintf(stderr, "skygw_log_write writes to %s :\n\t%s.\n", STRLOGID(id), str); - err = logmanager_write(ctx, lmgr, id, str, FALSE); + err = logmanager_write(ctx, id, str, FALSE); if (err != 0) { fprintf(stderr, "skygw_log_write failed.\n"); @@ -638,7 +676,7 @@ int skygw_log_write( ss_dfprintf(stderr, "skygw_log_write succeeed.\n"); return_unregister: - logmanager_unregister(lmgr); + logmanager_unregister(); return_err: /** Free log string */ free(str); @@ -646,18 +684,16 @@ return_err: } int skygw_log_flush( - logmanager_t* lmgr, logfile_id_t id) { int err = 0; - CHK_LOGMANAGER(lmgr); - if (!logmanager_register(lmgr)) { - fprintf(stderr, "Logmanager is not available\n"); - err = -1; + if (!logmanager_register(FALSE)) { + fprintf(stderr, "Can't register to logmanager, nothing to flush\n"); goto return_err; } - err = logmanager_write(NULL, lmgr, id, NULL, TRUE); + CHK_LOGMANAGER(lm); + err = logmanager_write(NULL, id, NULL, TRUE); if (err != 0) { fprintf(stderr, "skygw_log_flush failed.\n"); @@ -667,13 +703,13 @@ int skygw_log_flush( "skygw_log_flush : flushed %s successfully.\n", STRLOGID(id)); return_unregister: - logmanager_unregister(lmgr); + logmanager_unregister(); return_err: return err; } /** - * @node Increase link count of logmanager. + * @node Register as a logging client to logmanager. * * Parameters: * @param lmgr - @@ -686,28 +722,54 @@ return_err: * */ static bool logmanager_register( - logmanager_t* lmgr) + bool writep) { - bool succp = FALSE; - int err; - - err = simple_mutex_lock(&lmgr->lm_mutex, TRUE); + bool succp = TRUE; + + acquire_lock(&lmlock); + + if (lm == NULL || !lm->lm_enabled) { + /** + * Flush succeeds if logmanager is shut or shutting down. + * returning FALSE so that flusher doesn't access logmanager + * and its members which would probabaly lead to NULL pointer + * reference. + */ + if (!writep) { + succp = FALSE; + goto return_succp; + } + + ss_dassert(lm == NULL || (lm != NULL && !lm->lm_enabled)); + + /** + * Wait until logmanager shut down has completed. + * logmanager is enabled if someone already restarted + * it between latest lock release, and acquire. + */ + while (lm != NULL && !lm->lm_enabled) { + release_lock(&lmlock); + pthread_yield(); + acquire_lock(&lmlock); + } + + if (lm == NULL) { + succp = logmanager_init_nomutex(NULL, 0, NULL); + } - if (err != 0) { - goto return_succp; } - succp = lmgr->lm_enabled; - + /** if logmanager existed or was succesfully restarted, increase link */ if (succp) { - lmgr->lm_nlinks += 1; + lm->lm_nlinks += 1; } - simple_mutex_unlock(&lmgr->lm_mutex); -return_succp: + + return_succp: + release_lock(&lmlock); return succp; } /** - * @node Decrease link count of logmanager. + * @node Unregister from logmanager. * * Parameters: * @param lmgr - @@ -719,27 +781,14 @@ return_succp: * @details Link count modify is protected by mutex. * */ -static bool logmanager_unregister( - logmanager_t* lmgr) +static void logmanager_unregister(void) { - bool succp = FALSE; - int err; - - err = simple_mutex_lock(&lmgr->lm_mutex, TRUE); + acquire_lock(&lmlock); - if (err != 0) { - goto return_succp; - } - succp = lmgr->lm_enabled; - ss_dassert(succp); - - if (succp) { - lmgr->lm_nlinks -= 1; - ss_dassert(lmgr->lm_nlinks >= 0); - } - simple_mutex_unlock(&lmgr->lm_mutex); -return_succp: - return succp; + lm->lm_nlinks -= 1; + ss_dassert(lm->lm_nlinks >= 0); + + release_lock(&lmlock); } @@ -827,21 +876,21 @@ static bool fnames_conf_init( } fn->fn_trace_prefix = (fn->fn_trace_prefix == NULL) ? - strdup(get_trace_prefix_default()) : NULL; + strdup(get_trace_prefix_default()) : fn->fn_trace_prefix; fn->fn_trace_suffix = (fn->fn_trace_suffix == NULL) ? - strdup(get_trace_suffix_default()) : NULL; + strdup(get_trace_suffix_default()) : fn->fn_trace_suffix; fn->fn_msg_prefix = (fn->fn_msg_prefix == NULL) ? - strdup(get_msg_prefix_default()) : NULL; + strdup(get_msg_prefix_default()) : fn->fn_msg_prefix; fn->fn_msg_suffix = (fn->fn_msg_suffix == NULL) ? - strdup(get_msg_suffix_default()) : NULL; + strdup(get_msg_suffix_default()) : fn->fn_msg_suffix; fn->fn_err_prefix = (fn->fn_err_prefix == NULL) ? - strdup(get_err_prefix_default()) : NULL; + strdup(get_err_prefix_default()) : fn->fn_err_prefix; fn->fn_err_suffix = (fn->fn_err_suffix == NULL) ? - strdup(get_err_suffix_default()) : NULL; + strdup(get_err_suffix_default()) : fn->fn_err_suffix; fn->fn_logpath = (fn->fn_logpath == NULL) ? - strdup(get_logpath_default()) : NULL; + strdup(get_logpath_default()) : fn->fn_logpath; fn->fn_bufsize = (fn->fn_bufsize == 0) ? - get_bufsize_default() : 0; + get_bufsize_default() : fn->fn_bufsize; ss_dfprintf(stderr, "Command line : "); for (i=0; ifn_logpath); memset(fn, 0, sizeof(fnames_conf_t)); } diff --git a/log_manager/log_manager.h b/log_manager/log_manager.h index 23a06492b..008b385f9 100644 --- a/log_manager/log_manager.h +++ b/log_manager/log_manager.h @@ -36,14 +36,11 @@ typedef enum { LOGFILE_INIT, LOGFILE_OPENED, LOGFILE_DONE } logfile_state_t; EXTERN_C_BLOCK_BEGIN -logmanager_t* skygw_logmanager_init(void** ctx, int argc, char* argv[]); -void skygw_logmanager_done(void** ctx, logmanager_t** lm); -int skygw_log_write(void* ctx, logmanager_t* lmgr, logfile_id_t id, char* str); -int skygw_log_flush(logmanager_t* lmgr, logfile_id_t id); -int skygw_log_write_flush(void* ctx, - logmanager_t* lmgr, - logfile_id_t id, - char* str); +bool skygw_logmanager_init(void** ctx, int argc, char* argv[]); +void skygw_logmanager_done(void** ctx); +int skygw_log_write(void* ctx, logfile_id_t id, char* str); +int skygw_log_flush(logfile_id_t id); +int skygw_log_write_flush(void* ctx, logfile_id_t id, char* str); EXTERN_C_BLOCK_END diff --git a/log_manager/makefile b/log_manager/makefile index 86cd77a80..d94e561c6 100644 --- a/log_manager/makefile +++ b/log_manager/makefile @@ -24,15 +24,16 @@ utils: lib: libcomp liblink libcomp: + $(COPY) ../epoll_v1.0/core/atomic.o ./ $(CPP) -c $(CFLAGS) \ - -I$(MARIADB_SRC_PATH)/include/ \ + -I$(MARIADB_SRC_PATH)/include/ -I$(ROOT_PATH)/epoll_v1.0/include \ -I../utils/ -I./ \ -fPIC ./log_manager.cc -o log_manager.o $(LDLIBS) liblink: $(CPP) -shared \ -Wl,-soname,liblog_manager.so \ - -o liblog_manager.so.1.0.1 log_manager.o \ + -o liblog_manager.so.1.0.1 log_manager.o atomic.o \ $(LDLIBS) $(CPP_LDLIBS) $(DEL) ./liblog_manager.so $(LINK) ./liblog_manager.so.1.0.1 ./liblog_manager.so diff --git a/log_manager/test/makefile b/log_manager/test/makefile index db1bfa306..6a883751d 100644 --- a/log_manager/test/makefile +++ b/log_manager/test/makefile @@ -26,9 +26,11 @@ testcomp: -o testlog -DSS_DEBUG \ -I$(SOLIDDB_SRC_PATH)/include \ -I$(MARIADB_SRC_PATH)/include \ + -I$(ROOT_PATH)/epoll_v1.0/include \ -I$(LOG_MANAGER_PATH) -I$(ROOT_PATH)/utils testlog.c \ -llog_manager $(LDLIBS) \ - $(LOG_MANAGER_PATH)/skygw_utils.o + $(LOG_MANAGER_PATH)/skygw_utils.o \ + $(LOG_MANAGER_PATH)/atomic.o testall: - $(LAUNCH_DEBUGGER) $(TESTAPP) $(BACKGR) diff --git a/log_manager/test/testlog.c b/log_manager/test/testlog.c index ee187a21c..a09f64db9 100644 --- a/log_manager/test/testlog.c +++ b/log_manager/test/testlog.c @@ -22,44 +22,166 @@ */ #include +#include #include #include #include +typedef struct thread_st { + skygw_message_t* mes; + simple_mutex_t* mtx; + size_t* nactive; +} thread_t; + +static void* thr_run(void* data); + +#define NTHR 10 + int main(int argc, char* argv[]) { int err; - logmanager_t* lmgr; char* logstr; - lmgr = skygw_logmanager_init(NULL, argc, argv); + int i; + skygw_message_t* mes; + simple_mutex_t* mtx; + size_t nactive; + thread_t* thr[NTHR]; + + + skygw_logmanager_init(NULL, argc, argv); logstr = strdup("My name is Tracey"); - err = skygw_log_write(NULL, lmgr, LOGFILE_TRACE, logstr); + err = skygw_log_write(NULL, LOGFILE_TRACE, logstr); logstr = strdup("My name is Stacey"); - err = skygw_log_write_flush(NULL, lmgr, LOGFILE_TRACE, logstr); + err = skygw_log_write_flush(NULL, LOGFILE_TRACE, logstr); - skygw_logmanager_done(NULL, &lmgr); + skygw_logmanager_done(NULL); logstr = strdup("My name is Philip"); - err = skygw_log_write(NULL, lmgr, LOGFILE_TRACE, logstr); + err = skygw_log_write(NULL, LOGFILE_TRACE, logstr); - lmgr = skygw_logmanager_init(NULL, argc, argv); + skygw_logmanager_init(NULL, argc, argv); logstr = strdup("A terrible error has occurred!"); - err = skygw_log_write_flush(NULL, lmgr, LOGFILE_ERROR, logstr); + err = skygw_log_write_flush(NULL, LOGFILE_ERROR, logstr); logstr = strdup("Hi, how are you?"); - err = skygw_log_write(NULL, lmgr, LOGFILE_MESSAGE, logstr); + err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr); logstr = strdup("I'm doing fine!"); - err = skygw_log_write(NULL, lmgr, LOGFILE_MESSAGE, logstr); + err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr); - logstr = strdup("I was wondering, you know, it has been such a lovely weather whole morning and I thought that would you like to come to my place and have a little piece of cheese with us. Just me and my mom - and you, of course. Then, if you wish, we could listen to the radio and keep company for our little Steven, my mom's cat, you see."); - err = skygw_log_write(NULL, lmgr, LOGFILE_MESSAGE, logstr); + logstr = strdup("Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a+i). In evaluating a[i], C converts it to *(a+i) immediately; the two forms are equivalent. Applying the operatos & to both parts of this equivalence, it follows that &a[i] and a+i are also identical: a+i is the address of the i-th element beyond a."); + err = skygw_log_write(NULL, LOGFILE_ERROR, logstr); + + logstr = strdup("I was wondering, you know, it has been such a lovely weather whole morning and I thought that would you like to come to my place and have a little piece of cheese with us. Just me and my mom - and you, of course. Then, if you wish, we could listen to the radio and keep company for our little Steven, my mom's cat, you know."); + err = skygw_log_write(NULL, LOGFILE_MESSAGE, logstr); + skygw_logmanager_done(NULL); + + mes = skygw_message_init(); + mtx = simple_mutex_init(NULL, strdup("testmtx")); -return_err: - skygw_logmanager_done(NULL, &lmgr); + for (i=0; imes = mes; + thr[i]->mtx = mtx; + thr[i]->nactive = &nactive; + } + nactive = NTHR; + + for (i=0; i 0) { + simple_mutex_unlock(mtx); + continue; + } + break; + } while(TRUE); + /** This is to release memory */ + skygw_logmanager_done(NULL); + + simple_mutex_unlock(mtx); + + for (i=0; imtx, TRUE); + *td->nactive -= 1; + simple_mutex_unlock(td->mtx); + skygw_message_send(td->mes); + return NULL; +} diff --git a/utils/skygw_utils.cc b/utils/skygw_utils.cc index 2b00ae28e..2e302016c 100644 --- a/utils/skygw_utils.cc +++ b/utils/skygw_utils.cc @@ -134,10 +134,21 @@ static bool file_write_header(skygw_file_t* file); static void simple_mutex_free_memory(simple_mutex_t* sm); static void mlist_free_memory(mlist_t* ml, char* name); static void thread_free_memory(skygw_thread_t* th, char* name); - - /** End of static function declarations */ +int atomic_add( + int *variable, + int value) +{ + asm volatile( + "lock; xaddl %%eax, %2;" + :"=a" (value) + : "a" (value), "m" (*variable) + : "memory" ); + return value; +} + + /** mutexed list, mlist */ #if defined(MLIST) diff --git a/utils/skygw_utils.h b/utils/skygw_utils.h index 757d37873..3764d00f3 100644 --- a/utils/skygw_utils.h +++ b/utils/skygw_utils.h @@ -122,6 +122,7 @@ void skygw_file_done(skygw_file_t* file); bool skygw_file_write(skygw_file_t* file, void* data, size_t nbytes); /** Skygw file routines */ +EXTERN_C_BLOCK_BEGIN simple_mutex_t* simple_mutex_init(simple_mutex_t* mutexptr, char* name); int simple_mutex_done(simple_mutex_t* sm); @@ -147,9 +148,13 @@ void skygw_message_reset( skygw_message_t* mes); /** Skygw message routines */ +EXTERN_C_BLOCK_END + int skygw_rwlock_wrlock(skygw_rwlock_t* rwlock); int skygw_rwlock_rdlock(skygw_rwlock_t* rwlock); int skygw_rwlock_unlock(skygw_rwlock_t* rwlock); int skygw_rwlock_init(skygw_rwlock_t** rwlock); +int atomic_add(int *variable, int value); + #endif /* SKYGW_UTILS_H */