[email protected] wrote:
>
>
>
>
> -------- 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, ...);
Stray space.
> +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);
If you move the definition of print_to_buffer right below this prototype
block, you would avoid having to add this prototype and you would have
likely generated a more reviewable patch. The large code movement below
is very hard to check regarding correctness as I do not see the actually
modified lines.
> static void cleanup_buffer(struct print_buffer *buffer);
> static void print_buffers(void);
> +static void forked_child_init(void);
Stray prototype.
>
> /* *** 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;
Unneeded return.
> +}
> +
> +void rt_vsyslog(int priority, char *format, va_list args )
> +{
> + print_to_buffer(RT_PRINT_SYSLOG_STREAM, priority, format, args);
> +
> + return;
Here too.
> +}
> +
> 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)
When moving this function, please also indent this properly and take
care for a space after the ','.
> +{
> + 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 */
>
>
>
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help