1 /*
   2  * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
   3  *
   4  * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
   5  * Virtual Machine, which is developed at Christian Doppler Laboratory on
   6  * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
   7  * contact us at <http://mevss.jku.at/> if you need additional information
   8  * or have any questions.
   9  *
  10  * This code is free software; you can redistribute it and/or modify it
  11  * under the terms of the GNU General Public License version 2 only, as
  12  * published by the Free Software Foundation.
  13  *
  14  * This code is distributed in the hope that it will be useful, but WITHOUT
  15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17  * version 2 for more details (a copy is included in the LICENSE file that
  18  * accompanied this code).
  19  *
  20  * You should have received a copy of the GNU General Public License version
  21  * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
  22  *
  23  */
  24 
  25 #include "evtrace/traceBufferQueue.hpp"
  26 
  27 #include "evtrace/traceBuffer.hpp"
  28 
  29 class TraceBufferQueue::SpinLocker: public StackObj {
  30 private:
  31   TraceBufferQueue * const _queue;
  32 
  33 public:
  34   SpinLocker(TraceBufferQueue *q, const char *s) : _queue(q) {
  35     Thread::SpinAcquire(&_queue->_mtx, s);
  36   }
  37 
  38   ~SpinLocker() {
  39     Thread::SpinRelease(&_queue->_mtx);
  40   }
  41 };
  42 
  43 TraceBufferQueue::TraceBufferQueue()
  44 : _head(NULL),
  45   _tail(NULL),
  46   _mtx(0),
  47   _enqueue_ops(0),
  48   _dequeue_ops(0)
  49 {
  50 }
  51 
  52 TraceBufferQueue::~TraceBufferQueue() {
  53 }
  54 
  55 size_t TraceBufferQueue::count() {
  56   SpinLocker sl(this, "TraceBufferQueue - count");
  57   return (_enqueue_ops - _dequeue_ops);
  58 }
  59 
  60 TraceBuffer * TraceBufferQueue::try_dequeue() {
  61   TraceBuffer *buffer = NULL;
  62 
  63   {
  64     SpinLocker sl(this, "TraceBufferQueue - try_dequeue");
  65     if (_head != NULL) {
  66       buffer = _head;
  67       _head = _head->queue_next;
  68       if (_head == NULL) {
  69         _tail = NULL;
  70       }
  71       _dequeue_ops++;
  72     }
  73   }
  74 
  75   if (buffer != NULL) {
  76     buffer->queue_next = NULL;
  77   }
  78   return buffer;
  79 }
  80 
  81 void TraceBufferQueue::enqueue(TraceBuffer * const buffer) {
  82   assert(buffer != NULL, "sanity");
  83   assert(buffer->queue_next == NULL, "queue linkage");
  84 
  85   SpinLocker sl(this, "TraceBufferQueue - enqueue");
  86   if (_tail != NULL) {
  87     _tail->queue_next = buffer;
  88   } else {
  89     _head = buffer;
  90   }
  91   _tail = buffer;
  92   _enqueue_ops++;
  93 }