-------- Original Message --------
Subject: Re: :: rt_printf with daemonized task (09-Okt-2009 16:59)
From: Jan Kiszka <[email protected]>
To: [email protected]
>
> Yes (to the former), avoiding code duplication was the motivation for
> this functions.
>
> Another wish: Please split up your changes into two patches: first the
> atfork fix, on top of it the syslog extension. That allows us, e.g., to
> apply the fix also to 2.4.
... and the next patch for a syslog enabled rt_print.
>
> Jan
>
> --
> Siemens AG, Corporate Technology, CT SE 2
> Corporate Competence Center Embedded Linux
Oliver
--- rtdk.h.original 2007-12-09 11:46:36.000000000 +0100
+++ rtdk.h 2009-10-09 11:46:52.767271100 +0200
int rt_vprintf(const char *format, va_list args);
int rt_fprintf(FILE *stream, const char *format, ...);
int rt_printf(const char *format, ...);
+void rt_syslog( int priority, char *format, ...);
+void rt_vsyslog(int priority, char *format, va_list args);
+
int rt_print_init(size_t buffer_size, const char *name);
void rt_print_cleanup(void);
--- rt_print.c.forkonly 2009-10-16 16:19:25.949289800 +0200
+++ rt_print.c.wsyslog 2009-10-16 16:31:01.952464300 +0200
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <syslog.h>
#include <rtdk.h>
#include <asm/xenomai/system.h>
#define RT_PRINT_LINE_BREAK 256
+#define RT_PRINT_SYSLOG_STREAM NULL
+
struct entry_head {
FILE *dest;
uint32_t seq_no;
+ int priority;
char text[1];
} __attribute__((packed));
static pthread_key_t __buffer_key;
static pthread_t __printer_thread;
+static int print_to_buffer(FILE *stream, int priority,
+ const char *format,va_list args);
static void cleanup_buffer(struct print_buffer *buffer);
static void print_buffers(void);
+static void forked_child_init(void);
/* *** rt_print API *** */
int rt_vfprintf(FILE *stream, const char *format, va_list args)
{
- struct print_buffer *buffer = pthread_getspecific(__buffer_key);
- off_t write_pos, read_pos;
- struct entry_head *head;
- int len;
- int res;
-
- if (!buffer) {
- res = 0;
- if (__auto_init)
- res = rt_print_init(0, NULL);
- else
- res = EIO;
-
- if (res) {
- errno = res;
- return -1;
- }
- buffer = pthread_getspecific(__buffer_key);
- }
-
- /* Take a snapshot of the ring buffer state */
- write_pos = buffer->write_pos;
- read_pos = buffer->read_pos;
- xnarch_read_memory_barrier();
-
- /* Is our write limit the end of the ring buffer? */
- if (write_pos >= read_pos) {
- /* Keep a savety margin to the end for at least an empty entry
*/
- len = buffer->size - write_pos - sizeof(struct entry_head);
-
- /* Special case: We were stuck at the end of the ring buffer
- with space left there only for one empty entry. Now
- read_pos was moved forward and we can wrap around. */
- if (len == 0 && read_pos > sizeof(struct entry_head)) {
- /* Write out empty entry */
- head = buffer->ring + write_pos;
- head->seq_no = __seq_no;
- head->text[0] = 0;
-
- /* Forward to the ring buffer start */
- write_pos = 0;
- len = read_pos - 1;
- }
- } else {
- /* Our limit is the read_pos ahead of our write_pos. One byte
- margin is required to detect a full ring. */
- len = read_pos - write_pos - 1;
- }
-
- /* Account for head length */
- len -= sizeof(struct entry_head);
- if (len < 0)
- len = 0;
-
- head = buffer->ring + write_pos;
-
- res = vsnprintf(head->text, len, format, args);
-
- if (res < len) {
- /* Text was written completely, res contains its length */
- len = res;
- } else {
- /* Text was truncated, remove closing \0 that entry_head
- already includes */
- len--;
- }
-
- /* If we were able to write some text, finalise the entry */
- if (len > 0) {
- head->seq_no = ++__seq_no;
- head->dest = stream;
-
- /* Move forward by text and head length */
- write_pos += len + sizeof(struct entry_head);
- }
-
- /* Wrap around early if there is more space on the other side */
- if (write_pos >= buffer->size - RT_PRINT_LINE_BREAK &&
- read_pos <= write_pos && read_pos > buffer->size - write_pos) {
- /* An empty entry marks the wrap-around */
- head = buffer->ring + write_pos;
- head->seq_no = __seq_no;
- head->text[0] = 0;
-
- write_pos = 0;
- }
-
- /* All entry data must be written before we can update write_pos */
- xnarch_write_memory_barrier();
-
- buffer->write_pos = write_pos;
-
- return res;
+ return print_to_buffer(stream, 0, format, args);
}
int rt_vprintf(const char *format, va_list args)
return n;
}
+void rt_syslog(int priority, char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ print_to_buffer(RT_PRINT_SYSLOG_STREAM, priority, format, args);
+ va_end(args);
+
+ return;
+}
+
+void rt_vsyslog(int priority, char *format, va_list args )
+{
+ print_to_buffer(RT_PRINT_SYSLOG_STREAM, priority, format, args);
+
+ return;
+}
+
static void set_buffer_name(struct print_buffer *buffer, const char *name)
{
int n;
/* *** Deferred Output Management *** */
+static int print_to_buffer(FILE *stream, int priority,
+ const char
*format,va_list args)
+{
+ struct print_buffer *buffer = pthread_getspecific(__buffer_key);
+ off_t write_pos, read_pos;
+ struct entry_head *head;
+ int len;
+ int res;
+
+ if (!buffer) {
+ res = 0;
+ if (__auto_init)
+ res = rt_print_init(0, NULL);
+ else
+ res = EIO;
+
+ if (res) {
+ errno = res;
+ return -1;
+ }
+ buffer = pthread_getspecific(__buffer_key);
+ }
+
+ /* Take a snapshot of the ring buffer state */
+ write_pos = buffer->write_pos;
+ read_pos = buffer->read_pos;
+ xnarch_read_memory_barrier();
+
+ /* Is our write limit the end of the ring buffer? */
+ if (write_pos >= read_pos) {
+ /* Keep a savety margin to the end for at least an empty entry
*/
+ len = buffer->size - write_pos - sizeof(struct entry_head);
+
+ /* Special case: We were stuck at the end of the ring buffer
+ with space left there only for one empty entry. Now
+ read_pos was moved forward and we can wrap around. */
+ if (len == 0 && read_pos > sizeof(struct entry_head)) {
+ /* Write out empty entry */
+ head = buffer->ring + write_pos;
+ head->seq_no = __seq_no;
+ head->priority = 0;
+ head->text[0] = 0;
+
+ /* Forward to the ring buffer start */
+ write_pos = 0;
+ len = read_pos - 1;
+ }
+ } else {
+ /* Our limit is the read_pos ahead of our write_pos. One byte
+ margin is required to detect a full ring. */
+ len = read_pos - write_pos - 1;
+ }
+
+ /* Account for head length */
+ len -= sizeof(struct entry_head);
+ if (len < 0)
+ len = 0;
+
+ head = buffer->ring + write_pos;
+
+ res = vsnprintf(head->text, len, format, args);
+
+ if (res < len) {
+ /* Text was written completely, res contains its length */
+ len = res;
+ } else {
+ /* Text was truncated, remove closing \0 that entry_head
+ already includes */
+ len--;
+ }
+
+ /* If we were able to write some text, finalise the entry */
+ if (len > 0) {
+ head->seq_no = ++__seq_no;
+ head->priority = priority;
+ head->dest = stream;
+
+ /* Move forward by text and head length */
+ write_pos += len + sizeof(struct entry_head);
+ }
+
+ /* Wrap around early if there is more space on the other side */
+ if (write_pos >= buffer->size - RT_PRINT_LINE_BREAK &&
+ read_pos <= write_pos && read_pos > buffer->size - write_pos) {
+ /* An empty entry marks the wrap-around */
+ head = buffer->ring + write_pos;
+ head->seq_no = __seq_no;
+ head->priority = priority;
+ head->text[0] = 0;
+
+ write_pos = 0;
+ }
+
+ /* All entry data must be written before we can update write_pos */
+ xnarch_write_memory_barrier();
+
+ buffer->write_pos = write_pos;
+
+ return res;
+}
+
static void cleanup_buffer(struct print_buffer *buffer)
{
struct print_buffer *prev, *next;
if (len) {
/* Print out non-empty entry and proceed */
- fprintf(head->dest, "%s", head->text);
+ /* Check if output goes to syslog */
+ if (head->dest == RT_PRINT_SYSLOG_STREAM) {
+ syslog( head->priority, "%s", head->text );
+ } else {
+ /* Output goes to specified stream */
+ fprintf(head->dest, "%s", head->text);
+ }
+
read_pos += sizeof(*head) + len;
} else {
/* Emptry entries mark the wrap-around */
To: [email protected]
Cc: [email protected]
[email protected]
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help