You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by so...@apache.org on 2017/05/01 23:25:19 UTC

[trafficserver] 04/05: TS-4872: Hoist lock-free log buffer manipulation.

This is an automated email from the ASF dual-hosted git repository.

sorber pushed a commit to branch 6.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 549826fb54399181065e0ad95e28e597fdcd62cf
Author: James Peach <jp...@apache.org>
AuthorDate: Thu Sep 15 11:58:02 2016 -0700

    TS-4872: Hoist lock-free log buffer manipulation.
    
    Hoist the lock-free log buffer manipulations into helper functions.
    This make is a bit clearer what they are trying to do, and clarifies
    things so that the clang static analyzer doesn't think there is a
    memory leak here.
    
    (cherry picked from commit cb566cc3cf19892a07d7d274af2b045e957d6ce1)
    
     Conflicts:
    	proxy/logging/LogObject.cc
---
 proxy/logging/LogObject.cc | 53 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 37 insertions(+), 16 deletions(-)

diff --git a/proxy/logging/LogObject.cc b/proxy/logging/LogObject.cc
index c6c94c4..d272b18 100644
--- a/proxy/logging/LogObject.cc
+++ b/proxy/logging/LogObject.cc
@@ -380,6 +380,29 @@ LogObject::displayAsXML(FILE *fd, bool extended)
   fprintf(fd, "</LogObject>\n");
 }
 
+static head_p
+increment_pointer_version(volatile head_p *dst)
+{
+  head_p h;
+  head_p new_h;
+
+  do {
+    INK_QUEUE_LD(h, *dst);
+    SET_FREELIST_POINTER_VERSION(new_h, FREELIST_POINTER(h), FREELIST_VERSION(h) + 1);
+  } while (ink_atomic_cas(&dst->data, h.data, new_h.data) == false);
+
+  return h;
+}
+
+static bool
+write_pointer_version(volatile head_p *dst, head_p old_h, void *ptr, head_p::version_type vers)
+{
+  head_p tmp_h;
+
+  SET_FREELIST_POINTER_VERSION(tmp_h, ptr, vers);
+  return ink_atomic_cas(&dst->data, old_h.data, tmp_h.data);
+}
+
 LogBuffer *
 LogObject::_checkout_write(size_t *write_offset, size_t bytes_needed)
 {
@@ -391,14 +414,10 @@ LogObject::_checkout_write(size_t *write_offset, size_t bytes_needed)
   do {
     // To avoid a race condition, we keep a count of held references in
     // the pointer itself and add this to m_outstanding_references.
-    head_p h;
-    int result = 0;
-    do {
-      INK_QUEUE_LD(h, m_log_buffer);
-      head_p new_h;
-      SET_FREELIST_POINTER_VERSION(new_h, FREELIST_POINTER(h), FREELIST_VERSION(h) + 1);
-      result = ink_atomic_cas(&m_log_buffer.data, h.data, new_h.data);
-    } while (!result);
+
+    // Increment the version of m_log_buffer, returning the previous version.
+    head_p h = increment_pointer_version(&m_log_buffer);
+
     buffer           = (LogBuffer *)FREELIST_POINTER(h);
     result_code      = buffer->checkout_write(write_offset, bytes_needed);
     bool decremented = false;
@@ -418,6 +437,7 @@ LogObject::_checkout_write(size_t *write_offset, size_t bytes_needed)
       // swap the new buffer for the old one
       INK_WRITE_MEMORY_BARRIER;
       head_p old_h;
+
       do {
         INK_QUEUE_LD(old_h, m_log_buffer);
         if (FREELIST_POINTER(old_h) != FREELIST_POINTER(h)) {
@@ -428,10 +448,8 @@ LogObject::_checkout_write(size_t *write_offset, size_t bytes_needed)
           delete new_buffer;
           break;
         }
-        head_p tmp_h;
-        SET_FREELIST_POINTER_VERSION(tmp_h, new_buffer, 0);
-        result = ink_atomic_cas(&m_log_buffer.data, old_h.data, tmp_h.data);
-      } while (!result);
+      } while (!write_pointer_version(&m_log_buffer, old_h, new_buffer, 0));
+
       if (FREELIST_POINTER(old_h) == FREELIST_POINTER(h)) {
         ink_atomic_increment(&buffer->m_references, FREELIST_VERSION(old_h) - 1);
 
@@ -439,7 +457,9 @@ LogObject::_checkout_write(size_t *write_offset, size_t bytes_needed)
         Debug("log-logbuffer", "adding buffer %d to flush list after checkout", buffer->get_id());
         m_buffer_manager[idx].add_to_flush_queue(buffer);
         Log::preproc_notify[idx].signal();
+        buffer = NULL;
       }
+
       decremented = true;
       break;
 
@@ -460,19 +480,20 @@ LogObject::_checkout_write(size_t *write_offset, size_t bytes_needed)
     default:
       ink_assert(false);
     }
+
     if (!decremented) {
       head_p old_h;
+
       do {
         INK_QUEUE_LD(old_h, m_log_buffer);
         if (FREELIST_POINTER(old_h) != FREELIST_POINTER(h))
           break;
-        head_p tmp_h;
-        SET_FREELIST_POINTER_VERSION(tmp_h, FREELIST_POINTER(h), FREELIST_VERSION(old_h) - 1);
-        result = ink_atomic_cas(&m_log_buffer.data, old_h.data, tmp_h.data);
-      } while (!result);
+      } while (!write_pointer_version(&m_log_buffer, old_h, FREELIST_POINTER(h), FREELIST_VERSION(old_h) - 1));
+
       if (FREELIST_POINTER(old_h) != FREELIST_POINTER(h))
         ink_atomic_increment(&buffer->m_references, -1);
     }
+
   } while (retry && write_offset); // if write_offset is null, we do
   // not retry because we really do
   // not want to write to the buffer

-- 
To stop receiving notification emails like this one, please contact
"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>.