const char *rt_print_buffer_name(void) { struct print_buffer *buffer = pthread_getspecific(buffer_key); if (!buffer) { int res = -1; if (auto_init) res = rt_print_init(0, NULL); if (res) return NULL; buffer = pthread_getspecific(buffer_key); } return buffer->name; }
static int vprint_to_buffer(FILE *stream, int fortify_level, int priority, unsigned int mode, size_t sz, 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, str_len; int res = 0; 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; smp_mb(); /* Is our write limit the end of the ring buffer? */ if (write_pos >= read_pos) { /* Keep a safety 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->len = 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; if (mode == RT_PRINT_MODE_FORMAT) { if (stream != RT_PRINT_SYSLOG_STREAM) { /* We do not need the terminating \0 */ #ifdef CONFIG_XENO_FORTIFY if (fortify_level > 0) res = __vsnprintf_chk(head->data, len, fortify_level - 1, len > 0 ? len : 0, format, args); else #else (void)fortify_level; #endif res = vsnprintf(head->data, len, format, args); if (res < len) { /* Text was written completely, res contains its length */ len = res; } else { /* Text was truncated */ res = len; } } else { /* We DO need the terminating \0 */ #ifdef CONFIG_XENO_FORTIFY if (fortify_level > 0) res = __vsnprintf_chk(head->data, len, fortify_level - 1, len > 0 ? len : 0, format, args); else #endif 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 >= 1) { str_len = sz; len = (str_len < len) ? str_len : len; memcpy(head->data, format, len); } else len = 0; /* 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; head->len = len; /* 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->len = 0; write_pos = 0; } /* All entry data must be written before we can update write_pos */ smp_wmb(); buffer->write_pos = write_pos; return res; }
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; }