2 * Copyright (c) 2005 Christophe Varoqui
3 * Copyright (c) 2005 Benjamin Marzinski, Redhat
4 * Copyright (c) 2005 Jun'ichi Nomura, NEC
18 #define ALIGN(len, s) (((len)+(s)-1)/(s)*(s))
21 static pthread_mutex_t logq_lock = PTHREAD_MUTEX_INITIALIZER;
24 static void dump_logarea (void)
28 logdbg(stderr, "\n==== area: start addr = %p, end addr = %p ====\n",
30 logdbg(stderr, "|addr |next |prio|msg\n");
32 for (msg = (struct logmsg *)la->head; (void *)msg != la->tail;
34 logdbg(stderr, "|%p |%p |%i |%s\n", (void *)msg, msg->next,
35 msg->prio, (char *)&msg->str);
37 logdbg(stderr, "|%p |%p |%i |%s\n", (void *)msg, msg->next,
38 msg->prio, (char *)&msg->str);
40 logdbg(stderr, "\n\n");
44 static int logarea_init (int size)
46 logdbg(stderr,"enter logarea_init\n");
47 la = (struct logarea *)MALLOC(sizeof(struct logarea));
52 if (size < MAX_MSG_SIZE)
53 size = DEFAULT_AREA_SIZE;
55 la->start = MALLOC(size);
60 memset(la->start, 0, size);
63 la->end = la->start + size;
67 la->buff = MALLOC(MAX_MSG_SIZE + sizeof(struct logmsg));
78 int log_init(char *program_name, int size)
82 logdbg(stderr,"enter log_init\n");
84 pthread_mutex_lock(&logq_lock);
85 pthread_cleanup_push(cleanup_mutex, &logq_lock);
87 openlog(program_name, 0, LOG_DAEMON);
89 ret = logarea_init(size);
91 pthread_cleanup_pop(1);
96 static void free_logarea (void)
104 void log_close (void)
106 pthread_mutex_lock(&logq_lock);
107 pthread_cleanup_push(cleanup_mutex, &logq_lock);
113 pthread_cleanup_pop(1);
117 void log_reset (char *program_name)
119 pthread_mutex_lock(&logq_lock);
120 pthread_cleanup_push(cleanup_mutex, &logq_lock);
123 openlog(program_name, 0, LOG_DAEMON);
125 pthread_cleanup_pop(1);
128 __attribute__((format(printf, 2, 0)))
129 static int _log_enqueue(int prio, const char * fmt, va_list ap)
132 char buff[MAX_MSG_SIZE];
134 struct logmsg * lastmsg;
136 lastmsg = (struct logmsg *)la->tail;
139 fwd = sizeof(struct logmsg) +
140 strlen((char *)&lastmsg->str) * sizeof(char) + 1;
141 la->tail += ALIGN(fwd, sizeof(void *));
143 vsnprintf(buff, MAX_MSG_SIZE, fmt, ap);
144 len = ALIGN(sizeof(struct logmsg) + strlen(buff) * sizeof(char) + 1,
147 /* not enough space on tail : rewind */
148 if (la->head <= la->tail && len > (la->end - la->tail)) {
149 logdbg(stderr, "enqueue: rewind tail to %p\n", la->tail);
150 if (la->head == la->start ) {
151 logdbg(stderr, "enqueue: can not rewind tail, drop msg\n");
153 return 1; /* can't reuse */
155 la->tail = la->start;
158 la->head = la->start;
161 /* not enough space on head : drop msg */
162 if (la->head > la->tail && len >= (la->head - la->tail)) {
163 logdbg(stderr, "enqueue: log area overrun, drop msg\n");
171 /* ok, we can stage the msg in the area */
173 msg = (struct logmsg *)la->tail;
175 memcpy((void *)&msg->str, buff, strlen(buff) + 1);
176 lastmsg->next = la->tail;
177 msg->next = la->head;
179 logdbg(stderr, "enqueue: %p, %p, %i, %s\n", (void *)msg, msg->next,
180 msg->prio, (char *)&msg->str);
188 int log_enqueue(int prio, const char *fmt, va_list ap)
192 pthread_mutex_lock(&logq_lock);
193 pthread_cleanup_push(cleanup_mutex, &logq_lock);
195 ret = _log_enqueue(prio, fmt, ap);
196 pthread_cleanup_pop(1);
200 static int _log_dequeue(void *buff)
202 struct logmsg * src = (struct logmsg *)la->head;
203 struct logmsg * dst = (struct logmsg *)buff;
204 struct logmsg * lst = (struct logmsg *)la->tail;
209 int len = strlen((char *)&src->str) * sizeof(char) +
210 sizeof(struct logmsg) + 1;
212 dst->prio = src->prio;
213 memcpy(dst, src, len);
215 if (la->tail == la->head)
216 la->empty = 1; /* we purge the last logmsg */
218 la->head = src->next;
219 lst->next = la->head;
221 logdbg(stderr, "dequeue: %p, %p, %i, %s\n",
222 (void *)src, src->next, src->prio, (char *)&src->str);
224 memset((void *)src, 0, len);
229 int log_dequeue(void *buff)
233 pthread_mutex_lock(&logq_lock);
234 pthread_cleanup_push(cleanup_mutex, &logq_lock);
236 ret = _log_dequeue(buff);
237 pthread_cleanup_pop(1);
242 * this one can block under memory pressure
244 void log_syslog (void * buff)
246 struct logmsg * msg = (struct logmsg *)buff;
248 syslog(msg->prio, "%s", (char *)&msg->str);