Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / include / vtracer_async_queue.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: vtracer_async_queue.h
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23////////////////////////////////////////////////////////////
24//
25// File: vtracer_async_queue.h
26//
27// Copyright (C) 2001-2006 Sun Microsystems, Inc.
28// All rights reserved.
29//
30
31
32// re-entrant queue structure for devices to send dma's, strings etc to the tracer
33// this is the interface between blaze, the vcpu and devices (not relevant to tracer)
34
35// use dd if=/dev/random | od -XN 8 to get the random suffix
36#ifndef _vtracer_async_queue_h_8b214547ac275755_
37#define _vtracer_async_queue_h_8b214547ac275755_
38
39class vtracer_async_queue_el {
40 public:
41
42 vtracer_async_queue_el(const union vtracer_async_data_u * arg_data) {
43 memcpy(&data, arg_data, sizeof(union vtracer_async_data_u));
44 next = NULL;
45 }
46
47 union vtracer_async_data_u data;
48 vtracer_async_queue_el * next;
49}; // struct vtracer_async_queue_el
50
51
52class vtracer_async_queue {
53
54 public:
55 vtracer_async_queue() {
56 mutex_init(&mu, NULL, NULL);
57 head = tail = NULL;
58 qsize = 0;
59 }
60
61 // for fast, non-locking "single reader" use
62 // example: if (trace_async_queue->getsize()) { dequeue(...); if (rtype_DMA) vtracer->dma(...); }
63 // this avoids the lock/unlock operations when the queue is empty, which is the common case
64 int getsize() {
65 return qsize;
66 }
67
68 // use dequeue() in conjunction with getsize() for fast single-reader use
69 // if multiple threads wish to dequeue, they must call mt_dequeue() instead of getsize() and dequeue()
70
71 // WARNING: precondition: head != NULL. must enforce by calling is_empty before calling dequeue
72 // WARNING: only one thread can "own" the queue - ie call is_empty() and dequeue().
73 void dequeue(vtracer_async_data_u * data) {
74 volatile vtracer_async_queue_el * el = head;
75
76 mutex_lock(&mu);
77 head = el->next;
78 if (head == NULL) tail = NULL;
79 qsize --;
80 mutex_unlock(&mu);
81
82 memcpy((void *) data, (void *) &el->data, sizeof(vtracer_async_data_u));
83 delete el;
84 } // void dequeue(int &iswrite, uint64_t &paddr, int64_t &nbytes)
85
86
87 // enqueue is called by (multiple) writer threads to add async records
88 void enqueue(vtracer_async_data_u * data) {
89 vtracer_async_queue_el * el = new vtracer_async_queue_el(data);
90
91 mutex_lock(&mu);
92 if (tail != NULL) {
93 tail->next = el;
94 } else {
95 head = el;
96 }
97 tail = el;
98 qsize ++;
99 mutex_unlock(&mu);
100
101 } // void enqueue(int iswrite, uint64_t paddr, int64_t nbytes)
102
103
104 // mt_dequeue atomically checks if the async queue is empty and dequeues the head if non-empty.
105 // Use it if multiple threads want to read out of the queue.
106 // Returns zero if queue was empty, positive otherwise. The number of records remaining is (return_value-1) or 0 if empty
107 //
108 // example: if (mt_dequeue(...)) if (dma) vtracer->dma(...); etc
109 int mt_dequeue(vtracer_async_data_u * data) {
110 mutex_lock(&mu);
111 int rv = qsize;
112 if (qsize) {
113 volatile vtracer_async_queue_el * el = head;
114 head = el->next;
115 if (head == NULL) tail = NULL;
116 qsize--;
117 memcpy((void *) data, (void *) &el->data, sizeof(vtracer_async_data_u));
118 delete el;
119 }
120 mutex_unlock(&mu);
121 return rv;
122 } // int mt_dequeue(vtracer_async_data_u * data)
123
124 private:
125 mutex_t mu;
126
127 volatile int qsize;
128 volatile vtracer_async_queue_el * head;
129 volatile vtracer_async_queue_el * tail;
130}; // class vtracer_async_queue
131
132// this is instantiated elsewhere in blaze initialization code
133extern vtracer_async_queue * trace_async_queue;
134
135#define TRACE_DMA(TD_iswrite, TD_nbytes, TD_pa, TD_devid) \
136 if (g_vcpu[g_vcpu_id_max]->config.trace_on) { \
137 vtracer_async_data_u ad = {0}; \
138 ad.dma.rtype = vtracer_async_data_u::rtype_DMA; \
139 ad.dma.iswrite = TD_iswrite; \
140 ad.dma.nbytes = TD_nbytes; \
141 ad.dma.pa = TD_pa; \
142 ad.dma.devid = TD_devid; \
143 trace_async_queue->enqueue(&ad); \
144 }
145
146
147#endif // _vtracer_async_queue_h_8b214547ac275755_