summaryrefslogtreecommitdiff
path: root/libmultipath/log_pthread.c
blob: 035ae5d01febcd90ce3ac550fa15d5de5fe1135e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * Copyright (c) 2005 Christophe Varoqui
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <syslog.h>
#include <pthread.h>
#include <sys/mman.h>

#include "memory.h"

#include "log_pthread.h"
#include "log.h"
#include "lock.h"

pthread_t log_thr;

pthread_mutex_t logq_lock;
pthread_mutex_t logev_lock;
pthread_cond_t logev_cond;

int logq_running;

void log_safe (int prio, const char * fmt, va_list ap)
{
	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);
	pthread_cond_signal(&logev_cond);
	pthread_mutex_unlock(&logev_lock);
}

void log_thread_flush (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 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 (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);
		pthread_cond_wait(&logev_cond, &logev_lock);
		running = logq_running;
		pthread_mutex_unlock(&logev_lock);
		if (!running)
			break;
		log_thread_flush();
	}
	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_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();
}