[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