static void *logwriter_thread(void *arg) { /* set name */ prctl(PR_SET_NAME, "sdlog2_writer", 0); int log_fd = open_log_file(); if (log_fd < 0) { return NULL; } struct logbuffer_s *logbuf = (struct logbuffer_s *)arg; /* write log messages formats, version and parameters */ log_bytes_written += write_formats(log_fd); log_bytes_written += write_version(log_fd); log_bytes_written += write_parameters(log_fd); fsync(log_fd); int poll_count = 0; void *read_ptr; int n = 0; bool should_wait = false; bool is_part = false; while (true) { /* make sure threads are synchronized */ pthread_mutex_lock(&logbuffer_mutex); /* update read pointer if needed */ if (n > 0) { logbuffer_mark_read(&lb, n); } /* only wait if no data is available to process */ if (should_wait && !logwriter_should_exit) { /* blocking wait for new data at this line */ pthread_cond_wait(&logbuffer_cond, &logbuffer_mutex); } /* only get pointer to thread-safe data, do heavy I/O a few lines down */ int available = logbuffer_get_ptr(logbuf, &read_ptr, &is_part); /* continue */ pthread_mutex_unlock(&logbuffer_mutex); if (available > 0) { /* do heavy IO here */ if (available > MAX_WRITE_CHUNK) { n = MAX_WRITE_CHUNK; } else { n = available; } n = write(log_fd, read_ptr, n); should_wait = (n == available) && !is_part; if (n < 0) { main_thread_should_exit = true; err(1, "error writing log file"); } if (n > 0) { log_bytes_written += n; } } else { n = 0; /* exit only with empty buffer */ if (main_thread_should_exit || logwriter_should_exit) { break; } should_wait = true; } if (++poll_count == 10) { fsync(log_fd); poll_count = 0; } } fsync(log_fd); close(log_fd); return NULL; }
static void *logwriter_thread(void *arg) { /* set name */ prctl(PR_SET_NAME, "sdlog2_writer", 0); struct logbuffer_s *logbuf = (struct logbuffer_s *)arg; int log_file = open_logfile(); /* write log messages formats */ write_formats(log_file); int poll_count = 0; void *read_ptr; int n = 0; bool should_wait = false; bool is_part = false; while (true) { /* make sure threads are synchronized */ pthread_mutex_lock(&logbuffer_mutex); /* update read pointer if needed */ if (n > 0) { logbuffer_mark_read(&lb, n); } /* only wait if no data is available to process */ if (should_wait && !logwriter_should_exit) { /* blocking wait for new data at this line */ pthread_cond_wait(&logbuffer_cond, &logbuffer_mutex); } /* only get pointer to thread-safe data, do heavy I/O a few lines down */ int available = logbuffer_get_ptr(logbuf, &read_ptr, &is_part); #ifdef SDLOG2_DEBUG int rp = logbuf->read_ptr; int wp = logbuf->write_ptr; #endif /* continue */ pthread_mutex_unlock(&logbuffer_mutex); if (available > 0) { /* do heavy IO here */ if (available > MAX_WRITE_CHUNK) { n = MAX_WRITE_CHUNK; } else { n = available; } n = write(log_file, read_ptr, n); should_wait = (n == available) && !is_part; #ifdef SDLOG2_DEBUG printf("write %i %i of %i rp=%i wp=%i, is_part=%i, should_wait=%i\n", log_bytes_written, n, available, rp, wp, (int)is_part, (int)should_wait); #endif if (n < 0) { main_thread_should_exit = true; err(1, "error writing log file"); } if (n > 0) { log_bytes_written += n; } } else { n = 0; #ifdef SDLOG2_DEBUG printf("no data available, main_thread_should_exit=%i, logwriter_should_exit=%i\n", (int)main_thread_should_exit, (int)logwriter_should_exit); #endif /* exit only with empty buffer */ if (main_thread_should_exit || logwriter_should_exit) { #ifdef SDLOG2_DEBUG printf("break logwriter thread\n"); #endif break; } should_wait = true; } if (++poll_count == 10) { fsync(log_file); poll_count = 0; } } fsync(log_file); close(log_file); #ifdef SDLOG2_DEBUG printf("logwriter thread exit\n"); #endif return OK; }