[llvm-commits] [compiler-rt] r159812 - in /compiler-rt/trunk/lib/sanitizer_common: sanitizer_list.h tests/sanitizer_list_test.cc

Kostya Serebryany kcc at google.com
Fri Jul 6 02:03:46 PDT 2012


Author: kcc
Date: Fri Jul  6 04:03:45 2012
New Revision: 159812

URL: http://llvm.org/viewvc/llvm-project?rev=159812&view=rev
Log:
[tsan] add intrusive list to be used in tsan allocator, etc

Added:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_list.h
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_list_test.cc

Added: compiler-rt/trunk/lib/sanitizer_common/sanitizer_list.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_list.h?rev=159812&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_list.h (added)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_list.h Fri Jul  6 04:03:45 2012
@@ -0,0 +1,120 @@
+//===-- sanitizer_list.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains implementation of a list class to be used by
+// ThreadSanitizer, etc run-times.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_LIST_H
+#define SANITIZER_LIST_H
+
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+// Intrusive singly-linked list with size(), push_back(), push_front()
+// pop_front(), append_front() and append_back().
+// This class should be a POD (so that it can be put into TLS)
+// and an object with all zero fields should represent a valid empty list.
+// This class does not have a CTOR, so clear() should be called on all
+// non-zero-initialized objects before using.
+template<class Item>
+struct IntrusiveList {
+  void clear() {
+    first_ = last_ = 0;
+    size_ = 0;
+  }
+
+  bool empty() const { return size_ == 0; }
+  uptr size() const { return size_; }
+
+  void push_back(Item *x) {
+    if (empty()) {
+      x->next = 0;
+      first_ = last_ = x;
+      size_ = 1;
+    } else {
+      x->next = 0;
+      last_->next = x;
+      last_ = x;
+      size_++;
+    }
+  }
+
+  void push_front(Item *x) {
+    if (empty()) {
+      x->next = 0;
+      first_ = last_ = x;
+      size_ = 1;
+    } else {
+      x->next = first_;
+      first_ = x;
+      size_++;
+    }
+  }
+
+  void pop_front() {
+    CHECK(!empty());
+    first_ = first_->next;
+    if (first_ == 0)
+      last_ = 0;
+    size_--;
+  }
+
+  Item *front() { return first_; }
+  Item *back() { return last_; }
+
+  void append_front(IntrusiveList<Item> *l) {
+    CHECK_NE(this, l);
+    if (empty()) {
+      *this = *l;
+    } else {
+      l->last_ = first_;
+      first_ = l->first_;
+      size_ += l->size();
+    }
+    l->clear();
+  }
+
+  void append_back(IntrusiveList<Item> *l) {
+    CHECK_NE(this, l);
+    if (empty()) {
+      *this = *l;
+    } else {
+      last_->next = l->first_;
+      last_ = l->last_;
+      size_ += l->size();
+    }
+    l->clear();
+  }
+
+  void CheckConsistency() {
+    if (size_ == 0) {
+      CHECK_EQ(first_, 0);
+      CHECK_EQ(last_, 0);
+    } else {
+      uptr count = 0;
+      for (Item *i = first_; ; i = i->next) {
+        count++;
+        if (i == last_) break;
+      }
+      CHECK_EQ(size(), count);
+      CHECK_EQ(last_->next, 0);
+    }
+  }
+
+// private, don't use directly.
+  uptr size_;
+  Item *first_;
+  Item *last_;
+};
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_LIST_H

Added: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_list_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_list_test.cc?rev=159812&view=auto
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_list_test.cc (added)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_list_test.cc Fri Jul  6 04:03:45 2012
@@ -0,0 +1,150 @@
+//===-- sanitizer_list_test.cc --------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_list.h"
+#include "gtest/gtest.h"
+
+namespace __sanitizer {
+
+struct ListItem {
+  ListItem *next;
+};
+
+typedef IntrusiveList<ListItem> List;
+
+// Check that IntrusiveList can be made thread-local.
+static THREADLOCAL List static_list;
+
+static void SetList(List *l, ListItem *x, ListItem *y = 0, ListItem *z = 0) {
+  l->clear();
+  l->push_back(x);
+  if (y) l->push_back(y);
+  if (z) l->push_back(z);
+}
+
+static void CheckList(List *l, ListItem *i1, ListItem *i2 = 0, ListItem *i3 = 0,
+                      ListItem *i4 = 0, ListItem *i5 = 0, ListItem *i6 = 0) {
+  if (i1) {
+    CHECK_EQ(l->front(), i1);
+    l->pop_front();
+  }
+  if (i2) {
+    CHECK_EQ(l->front(), i2);
+    l->pop_front();
+  }
+  if (i3) {
+    CHECK_EQ(l->front(), i3);
+    l->pop_front();
+  }
+  if (i4) {
+    CHECK_EQ(l->front(), i4);
+    l->pop_front();
+  }
+  if (i5) {
+    CHECK_EQ(l->front(), i5);
+    l->pop_front();
+  }
+  if (i6) {
+    CHECK_EQ(l->front(), i6);
+    l->pop_front();
+  }
+  CHECK(l->empty());
+}
+
+TEST(SanitizerCommon, IntrusiveList) {
+  ListItem items[6];
+  CHECK_EQ(static_list.size(), 0);
+
+  List l;
+  l.clear();
+  
+  ListItem *x = &items[0];
+  ListItem *y = &items[1];
+  ListItem *z = &items[2];
+  ListItem *a = &items[3];
+  ListItem *b = &items[4];
+  ListItem *c = &items[5];
+
+  CHECK_EQ(l.size(), 0);
+  l.push_back(x);
+  CHECK_EQ(l.size(), 1);
+  CHECK_EQ(l.back(), x);
+  CHECK_EQ(l.front(), x);
+  l.pop_front();
+  CHECK(l.empty());
+  l.CheckConsistency();
+
+  l.push_front(x);
+  CHECK_EQ(l.size(), 1);
+  CHECK_EQ(l.back(), x);
+  CHECK_EQ(l.front(), x);
+  l.pop_front();
+  CHECK(l.empty());
+  l.CheckConsistency();
+
+  l.push_front(x);
+  l.push_front(y);
+  l.push_front(z);
+  CHECK_EQ(l.size(), 3);
+  CHECK_EQ(l.front(), z);
+  CHECK_EQ(l.back(), x);
+  l.CheckConsistency();
+  
+  l.pop_front();
+  CHECK_EQ(l.size(), 2);
+  CHECK_EQ(l.front(), y);
+  CHECK_EQ(l.back(), x);
+  l.pop_front();
+  l.pop_front();
+  CHECK(l.empty());
+  l.CheckConsistency();
+
+  l.push_back(x);
+  l.push_back(y);
+  l.push_back(z);
+  CHECK_EQ(l.size(), 3);
+  CHECK_EQ(l.front(), x);
+  CHECK_EQ(l.back(), z);
+  l.CheckConsistency();
+
+  l.pop_front();
+  CHECK_EQ(l.size(), 2);
+  CHECK_EQ(l.front(), y);
+  CHECK_EQ(l.back(), z);
+  l.pop_front();
+  l.pop_front();
+  CHECK(l.empty());
+  l.CheckConsistency();
+
+  List l1, l2;
+  l1.clear();
+  l2.clear();
+
+  l1.append_front(&l2);
+  CHECK(l1.empty());
+  CHECK(l2.empty());
+
+  l1.append_back(&l2);
+  CHECK(l1.empty());
+  CHECK(l2.empty());
+
+  SetList(&l1, x);
+  CheckList(&l1, x);
+
+  SetList(&l1, x, y, z);
+  SetList(&l2, a, b, c);
+  l1.append_back(&l2);
+  CheckList(&l1, x, y, z, a, b, c);
+  CHECK(l2.empty());
+}
+
+}  // namespace __sanitizer





More information about the llvm-commits mailing list