Module: xenomai-gch
Branch: for-forge
Commit: 1ebdd474129f25167006c31e53d31bdbf3e75df4
URL:    
http://git.xenomai.org/?p=xenomai-gch.git;a=commit;h=1ebdd474129f25167006c31e53d31bdbf3e75df4

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Fri Nov 11 18:07:56 2011 +0100

rtdk/posix: implement fwrite

gcc substitutes fprintf calls with fwrite calls, so we need fwrite. At this
chance get rt_fwrite working for non null terminated data blocks.

---

 include/cobalt/stdio.h         |    4 +
 include/rtdk.h                 |    2 +
 lib/cobalt/posix.wrappers      |    2 +
 lib/cobalt/printf.c            |  134 ++++++++++++++++++++++++++--------------
 lib/cobalt/wrappers.c          |   12 ++++
 testsuite/unit/mutex-torture.c |    4 +
 6 files changed, 111 insertions(+), 47 deletions(-)

diff --git a/include/cobalt/stdio.h b/include/cobalt/stdio.h
index b97ba03..7d161da 100644
--- a/include/cobalt/stdio.h
+++ b/include/cobalt/stdio.h
@@ -22,6 +22,10 @@ COBALT_DECL(int, printf(const char *fmt, ...));
 
 COBALT_DECL(int, puts(const char *s));
 
+int __real_fputs(const char *s, FILE *stream);
+
+size_t __real_fwrite(const void *ptr, size_t sz, size_t nmemb, FILE *stream);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/include/rtdk.h b/include/rtdk.h
index 2ddfacc..398b1c9 100644
--- a/include/rtdk.h
+++ b/include/rtdk.h
@@ -53,6 +53,8 @@ int rt_vprintf(const char *format, va_list args);
 int rt_fprintf(FILE *stream, const char *format, ...);
 int rt_printf(const char *format, ...);
 int rt_puts(const char *s);
+int rt_fputs(const char *s, FILE *stream);
+size_t rt_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
 void rt_syslog(int priority, const char *format, ...);
 void rt_vsyslog(int priority, const char *format, va_list args);
 
diff --git a/lib/cobalt/posix.wrappers b/lib/cobalt/posix.wrappers
index 2aa3d33..a7a6b50 100644
--- a/lib/cobalt/posix.wrappers
+++ b/lib/cobalt/posix.wrappers
@@ -94,6 +94,8 @@
 --wrap fprintf
 --wrap printf
 --wrap puts
+--wrap fputs
+--wrap fwrite
 --wrap syslog
 --wrap vsyslog
 --wrap malloc
diff --git a/lib/cobalt/printf.c b/lib/cobalt/printf.c
index df527fe..7fc988d 100644
--- a/lib/cobalt/printf.c
+++ b/lib/cobalt/printf.c
@@ -48,13 +48,14 @@
 #define RT_PRINT_SYSLOG_STREAM         NULL
 
 #define RT_PRINT_MODE_FORMAT           0
-#define RT_PRINT_MODE_PUTS             1
+#define RT_PRINT_MODE_FWRITE           1
 
 struct entry_head {
        FILE *dest;
        uint32_t seq_no;
        int priority;
-       char text[1];
+       size_t len;
+       char data[0];
 } __attribute__((packed));
 
 struct print_buffer {
@@ -97,7 +98,7 @@ static void print_buffers(void);
 /* *** rt_print API *** */
 
 static int vprint_to_buffer(FILE *stream, int priority, unsigned int mode,
-                           const char *format, va_list args)
+                           size_t sz, const char *format, va_list args)
 {
        struct print_buffer *buffer = pthread_getspecific(buffer_key);
        off_t write_pos, read_pos;
@@ -137,7 +138,7 @@ static int vprint_to_buffer(FILE *stream, int priority, 
unsigned int mode,
                        head = buffer->ring + write_pos;
                        head->seq_no = seq_no;
                        head->priority = 0;
-                       head->text[0] = 0;
+                       head->len = 0;
 
                        /* Forward to the ring buffer start */
                        write_pos = 0;
@@ -157,24 +158,35 @@ static int vprint_to_buffer(FILE *stream, int priority, 
unsigned int mode,
        head = buffer->ring + write_pos;
 
        if (mode == RT_PRINT_MODE_FORMAT) {
-               res = vsnprintf(head->text, len, format, args);
-
-               if (res < len) {
-                       /* Text was written completely, res contains its
-                          length */
-                       len = res;
+               if (stream != RT_PRINT_SYSLOG_STREAM) {
+                       /* We do not need the terminating \0 */
+                       res = vsnprintf(head->data, len + 1, format, args);
+
+                       if (res < len + 1) {
+                               /* Text was written completely, res contains its
+                                  length */
+                               len = res;
+                       } else {
+                               /* Text was truncated */
+                               res = len;
+                       }
                } else {
-                       /* Text was truncated, remove closing \0 that
-                          entry_head already includes */
-                       len--;
-                       res = len;
+                       /* We DO need the terminating \0 */
+                       res = vsnprintf(head->data, len, format, args);
+
+                       if (res < len) {
+                               /* Text was written completely, res contains its
+                                  length */
+                               len = res + 1;
+                       } else {
+                               /* Text was truncated */
+                               res = len;
+                       }
                }
-       } else if (len >= 2) {
-               str_len = strlen(format);
-               len = (str_len < len - 2) ? str_len : len - 2;
-               strncpy(head->text, format, len);
-               head->text[len++] = '\n';
-               head->text[len] = 0;
+       } else if (len >= 1) {
+               str_len = sz;
+               len = (str_len < len) ? str_len : len;
+               memcpy(head->data, format, len);
        } else
                len = 0;
 
@@ -183,6 +195,7 @@ static int vprint_to_buffer(FILE *stream, int priority, 
unsigned int mode,
                head->seq_no = ++seq_no;
                head->priority = priority;
                head->dest = stream;
+               head->len = len;
 
                /* Move forward by text and head length */
                write_pos += len + sizeof(struct entry_head);
@@ -195,7 +208,7 @@ static int vprint_to_buffer(FILE *stream, int priority, 
unsigned int mode,
                head = buffer->ring + write_pos;
                head->seq_no = seq_no;
                head->priority = priority;
-               head->text[0] = 0;
+               head->len = 0;
 
                write_pos = 0;
        }
@@ -209,13 +222,13 @@ static int vprint_to_buffer(FILE *stream, int priority, 
unsigned int mode,
 }
 
 static int print_to_buffer(FILE *stream, int priority, unsigned int mode,
-                          const char *format, ...)
+                          size_t sz, const char *format, ...)
 {
        va_list args;
        int ret;
 
        va_start(args, format);
-       ret = vprint_to_buffer(stream, priority, mode, format, args);
+       ret = vprint_to_buffer(stream, priority, mode, sz, format, args);
        va_end(args);
 
        return ret;
@@ -223,7 +236,8 @@ static int print_to_buffer(FILE *stream, int priority, 
unsigned int mode,
 
 int rt_vfprintf(FILE *stream, const char *format, va_list args)
 {
-       return vprint_to_buffer(stream, 0, RT_PRINT_MODE_FORMAT, format, args);
+       return vprint_to_buffer(stream, 0,
+                               RT_PRINT_MODE_FORMAT, 0, format, args);
 }
 
 int rt_vprintf(const char *format, va_list args)
@@ -255,25 +269,37 @@ int rt_printf(const char *format, ...)
        return n;
 }
 
+int rt_fputs(const char *s, FILE *stream)
+{
+       return print_to_buffer(stream, 0, RT_PRINT_MODE_FWRITE, strlen(s), s);
+}
+
 int rt_puts(const char *s)
 {
-       return print_to_buffer(stdout, 0, RT_PRINT_MODE_PUTS, s);
+       return rt_fputs(s, stdout);
 }
 
+size_t rt_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+       print_to_buffer(stream, 0, RT_PRINT_MODE_FWRITE, size * nmemb, ptr);
+       return nmemb;
+}
+
+
 void rt_syslog(int priority, const char *format, ...)
 {
        va_list args;
 
        va_start(args, format);
        vprint_to_buffer(RT_PRINT_SYSLOG_STREAM, priority,
-                        RT_PRINT_MODE_FORMAT, format, args);
+                        RT_PRINT_MODE_FORMAT, 0, format, args);
        va_end(args);
 }
 
 void rt_vsyslog(int priority, const char *format, va_list args)
 {
        vprint_to_buffer(RT_PRINT_SYSLOG_STREAM, priority,
-                        RT_PRINT_MODE_FORMAT, format, args);
+                        RT_PRINT_MODE_FORMAT, 0, format, args);
 }
 
 static void set_buffer_name(struct print_buffer *buffer, const char *name)
@@ -372,10 +398,8 @@ int rt_print_init(size_t buffer_size, const char 
*buffer_name)
                        return ENOMEM;
 
                buffer->ring = malloc(size);
-               if (!buffer->ring) {
-                       free(buffer);
+               if (!buffer->ring)
                        return ENOMEM;
-               }
 
                rt_print_init_inner(buffer, size);
        }
@@ -538,16 +562,17 @@ static void print_buffers(void)
 
                read_pos = buffer->read_pos;
                head = buffer->ring + read_pos;
-               len = strlen(head->text);
+               len = head->len;
 
                if (len) {
                        /* Print out non-empty entry and proceed */
                        /* Check if output goes to syslog */
                        if (head->dest == RT_PRINT_SYSLOG_STREAM) {
-                               syslog(head->priority, "%s", head->text);
+                               syslog(head->priority,
+                                      "%s", head->data);
                        } else {
-                               /* Output goes to specified stream */
-                               fprintf(head->dest, "%s", head->text);
+                               fwrite(head->data,
+                                      head->len, 1, head->dest);
                        }
 
                        read_pos += sizeof(*head) + len;
@@ -627,7 +652,6 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
 
        first_buffer = NULL;
        seq_no = 0;
-       auto_init = 0;
 
        default_buffer_size = RT_PRINT_DEFAULT_BUFFER;
        value_str = getenv(RT_PRINT_BUFFER_ENV);
@@ -635,7 +659,7 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
                errno = 0;
                default_buffer_size = strtol(value_str, NULL, 10);
                if (errno || default_buffer_size < RT_PRINT_LINE_BREAK) {
-                       fprintf(stderr, "Invalid %s\n", RT_PRINT_BUFFER_ENV);
+                       __real_fprintf(stderr, "Invalid %s\n", 
RT_PRINT_BUFFER_ENV);
                        exit(1);
                }
        }
@@ -646,7 +670,7 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
                errno = 0;
                period = strtoll(value_str, NULL, 10);
                if (errno) {
-                       fprintf(stderr, "Invalid %s\n", RT_PRINT_PERIOD_ENV);
+                       __real_fprintf(stderr, "Invalid %s\n", 
RT_PRINT_PERIOD_ENV);
                        exit(1);
                }
        }
@@ -665,8 +689,8 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
                        errno = 0;
                        buffers_count = strtoul(value_str, NULL, 0);
                        if (errno) {
-                               fprintf(stderr, "Invalid %s\n",
-                                       RT_PRINT_BUFFERS_COUNT_ENV);
+                               __real_fprintf(stderr, "Invalid %s\n",
+                                              RT_PRINT_BUFFERS_COUNT_ENV);
                                exit(1);
                        }
                }
@@ -678,7 +702,7 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
 
                pool_bitmap = malloc(pool_bitmap_len * sizeof(*pool_bitmap));
                if (!pool_bitmap) {
-                       fprintf(stderr, "Error allocating rt_printf "
+                       __real_fprintf(stderr, "Error allocating rt_printf "
                                "buffers\n");
                        exit(1);
                }
@@ -687,8 +711,8 @@ static __attribute__ ((constructor)) void 
__rt_print_init(void)
                pool_len = buffers_count * pool_buf_size;
                pool_start = (unsigned long)malloc(pool_len);
                if (!pool_start) {
-                       fprintf(stderr, "Error allocating rt_printf "
-                               "buffers\n");
+                       __real_fprintf(stderr, "Error allocating rt_printf "
+                                      "buffers\n");
                        exit(1);
                }
 
@@ -734,11 +758,10 @@ int __wrap_vfprintf(FILE *stream, const char *fmt, 
va_list args)
 {
        if (unlikely(xeno_get_current() != XN_NO_HANDLE &&
                     !(xeno_get_current_mode() & XNRELAX)))
-
                return rt_vfprintf(stream, fmt, args);
        else {
                rt_print_flush_buffers();
-               return vfprintf(stream, fmt, args);
+               return __real_vfprintf(stream, fmt, args);
        }
 }
 
@@ -771,15 +794,32 @@ int __wrap_printf(const char *fmt, ...)
        return rc;
 }
 
+int __wrap_fputs(const char *s, FILE *stream)
+{
+       if (unlikely(xeno_get_current() != XN_NO_HANDLE &&
+                    !(xeno_get_current_mode() & XNRELAX)))
+               return rt_fputs(s, stream);
+       else {
+               rt_print_flush_buffers();
+               return __real_fputs(s, stream);
+       }
+}
+
 int __wrap_puts(const char *s)
 {
+       return __wrap_fputs(s, stdout);
+}
+
+size_t __wrap_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
        if (unlikely(xeno_get_current() != XN_NO_HANDLE &&
                     !(xeno_get_current_mode() & XNRELAX)))
-               return rt_puts(s);
+               return rt_fwrite(ptr, size, nmemb, stream);
        else {
                rt_print_flush_buffers();
-               return puts(s);
+               return __real_fwrite(ptr, size, nmemb, stream);
        }
+
 }
 
 void __wrap_vsyslog(int priority, const char *fmt, va_list ap)
@@ -789,7 +829,7 @@ void __wrap_vsyslog(int priority, const char *fmt, va_list 
ap)
                return rt_vsyslog(priority, fmt, ap);
        else {
                rt_print_flush_buffers();
-               vsyslog(priority, fmt, ap);
+               __real_vsyslog(priority, fmt, ap);
        }
 }
 
diff --git a/lib/cobalt/wrappers.c b/lib/cobalt/wrappers.c
index 37a8ab5..cfd3341 100644
--- a/lib/cobalt/wrappers.c
+++ b/lib/cobalt/wrappers.c
@@ -373,6 +373,18 @@ int __real_puts(const char *s)
 }
 
 __attribute__ ((weak))
+int __real_fputs(const char *s, FILE *stream)
+{
+       return fputs(s, stream);
+}
+
+__attribute__ ((weak))
+size_t __real_fwrite(const void *ptr, size_t sz, size_t nmemb, FILE *stream)
+{
+       return fwrite(ptr, sz, nmemb, stream);
+}
+
+__attribute__ ((weak))
 void __real_syslog(int priority, const char *fmt, ...)
 {
        va_list args;
diff --git a/testsuite/unit/mutex-torture.c b/testsuite/unit/mutex-torture.c
index ff76e16..bc32802 100644
--- a/testsuite/unit/mutex-torture.c
+++ b/testsuite/unit/mutex-torture.c
@@ -377,6 +377,10 @@ void mode_switch(void)
 {
        pthread_mutex_t mutex;
 
+       /* Cause a switch to secondary mode */
+#ifdef XENO_POSIX
+       __real_sched_yield();
+#endif
        fprintf(stderr, "mode_switch\n");
 
        dispatch("switch mutex_init", MUTEX_CREATE, 1, 0, &mutex, 1, 0);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to