* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: vtracer_async_queue.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
////////////////////////////////////////////////////////////
// File: vtracer_async_queue.h
// Copyright (C) 2001-2006 Sun Microsystems, Inc.
// re-entrant queue structure for devices to send dma's, strings etc to the tracer
// this is the interface between blaze, the vcpu and devices (not relevant to tracer)
// use dd if=/dev/random | od -XN 8 to get the random suffix
#ifndef _vtracer_async_queue_h_8b214547ac275755_
#define _vtracer_async_queue_h_8b214547ac275755_
class vtracer_async_queue_el
{
vtracer_async_queue_el(const union vtracer_async_data_u
* arg_data
) {
memcpy(&data
, arg_data
, sizeof(union vtracer_async_data_u
));
union vtracer_async_data_u data
;
vtracer_async_queue_el
* next
;
}; // struct vtracer_async_queue_el
class vtracer_async_queue
{
mutex_init(&mu
, NULL
, NULL
);
// for fast, non-locking "single reader" use
// example: if (trace_async_queue->getsize()) { dequeue(...); if (rtype_DMA) vtracer->dma(...); }
// this avoids the lock/unlock operations when the queue is empty, which is the common case
// use dequeue() in conjunction with getsize() for fast single-reader use
// if multiple threads wish to dequeue, they must call mt_dequeue() instead of getsize() and dequeue()
// WARNING: precondition: head != NULL. must enforce by calling is_empty before calling dequeue
// WARNING: only one thread can "own" the queue - ie call is_empty() and dequeue().
void dequeue(vtracer_async_data_u
* data
) {
volatile vtracer_async_queue_el
* el
= head
;
if (head
== NULL
) tail
= NULL
;
memcpy((void *) data
, (void *) &el
->data
, sizeof(vtracer_async_data_u
));
} // void dequeue(int &iswrite, uint64_t &paddr, int64_t &nbytes)
// enqueue is called by (multiple) writer threads to add async records
void enqueue(vtracer_async_data_u
* data
) {
vtracer_async_queue_el
* el
= new vtracer_async_queue_el(data
);
} // void enqueue(int iswrite, uint64_t paddr, int64_t nbytes)
// mt_dequeue atomically checks if the async queue is empty and dequeues the head if non-empty.
// Use it if multiple threads want to read out of the queue.
// Returns zero if queue was empty, positive otherwise. The number of records remaining is (return_value-1) or 0 if empty
// example: if (mt_dequeue(...)) if (dma) vtracer->dma(...); etc
int mt_dequeue(vtracer_async_data_u
* data
) {
volatile vtracer_async_queue_el
* el
= head
;
if (head
== NULL
) tail
= NULL
;
memcpy((void *) data
, (void *) &el
->data
, sizeof(vtracer_async_data_u
));
} // int mt_dequeue(vtracer_async_data_u * data)
volatile vtracer_async_queue_el
* head
;
volatile vtracer_async_queue_el
* tail
;
}; // class vtracer_async_queue
// this is instantiated elsewhere in blaze initialization code
extern vtracer_async_queue
* trace_async_queue
;
#define TRACE_DMA(TD_iswrite, TD_nbytes, TD_pa, TD_devid) \
if (g_vcpu[g_vcpu_id_max]->config.trace_on) { \
vtracer_async_data_u ad = {0}; \
ad.dma.rtype = vtracer_async_data_u::rtype_DMA; \
ad.dma.iswrite = TD_iswrite; \
ad.dma.nbytes = TD_nbytes; \
ad.dma.devid = TD_devid; \
trace_async_queue->enqueue(&ad); \
#endif // _vtracer_async_queue_h_8b214547ac275755_