/* * Copyright (c) 2005 Christophe Varoqui */ #include #include #include #include #include #include #include "memory.h" #include "log_pthread.h" #include "log.h" #include "lock.h" static pthread_t log_thr; static pthread_mutex_t logq_lock; static pthread_mutex_t logev_lock; static pthread_cond_t logev_cond; static int logq_running; static int log_messages_pending; void log_safe (int prio, const char * fmt, va_list ap) { if (prio > LOG_DEBUG) prio = LOG_DEBUG; if (log_thr == (pthread_t)0) { vsyslog(prio, fmt, ap); return; } pthread_mutex_lock(&logq_lock); log_enqueue(prio, fmt, ap); pthread_mutex_unlock(&logq_lock); pthread_mutex_lock(&logev_lock); log_messages_pending = 1; pthread_cond_signal(&logev_cond); pthread_mutex_unlock(&logev_lock); } static void flush_logqueue (void) { int empty; do { pthread_mutex_lock(&logq_lock); empty = log_dequeue(la->buff); pthread_mutex_unlock(&logq_lock); if (!empty) log_syslog(la->buff); } while (empty == 0); } static void * log_thread (__attribute__((unused)) void * et) { int running; pthread_mutex_lock(&logev_lock); logq_running = 1; pthread_mutex_unlock(&logev_lock); mlockall(MCL_CURRENT | MCL_FUTURE); logdbg(stderr,"enter log_thread\n"); while (1) { pthread_mutex_lock(&logev_lock); if (logq_running && !log_messages_pending) pthread_cond_wait(&logev_cond, &logev_lock); log_messages_pending = 0; running = logq_running; pthread_mutex_unlock(&logev_lock); if (!running) break; flush_logqueue(); } return NULL; } void log_thread_start (pthread_attr_t *attr) { logdbg(stderr,"enter log_thread_start\n"); pthread_mutex_init(&logq_lock, NULL); pthread_mutex_init(&logev_lock, NULL); pthread_cond_init(&logev_cond, NULL); if (log_init("multipathd", 0)) { fprintf(stderr,"can't initialize log buffer\n"); exit(1); } if (pthread_create(&log_thr, attr, log_thread, NULL)) { fprintf(stderr,"can't start log thread\n"); exit(1); } return; } void log_thread_reset (void) { logdbg(stderr,"resetting log\n"); pthread_mutex_lock(&logq_lock); log_reset("multipathd"); pthread_mutex_unlock(&logq_lock); } void log_thread_stop (void) { logdbg(stderr,"enter log_thread_stop\n"); pthread_mutex_lock(&logev_lock); logq_running = 0; pthread_cond_signal(&logev_cond); pthread_mutex_unlock(&logev_lock); pthread_mutex_lock(&logq_lock); pthread_cancel(log_thr); pthread_mutex_unlock(&logq_lock); pthread_join(log_thr, NULL); log_thr = (pthread_t)0; flush_logqueue(); pthread_mutex_destroy(&logq_lock); pthread_mutex_destroy(&logev_lock); pthread_cond_destroy(&logev_cond); log_close(); }