1 /*
2  * Copyright (c) 2013-2019, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef PT_EVENT_QUEUE_H
30 #define PT_EVENT_QUEUE_H
31 
32 #include "intel-pt.h"
33 
34 #include <stdint.h>
35 
36 
37 /* Events are grouped by the packet the event binds to. */
38 enum pt_event_binding {
39 	evb_psbend,
40 	evb_tip,
41 	evb_fup,
42 
43 	evb_max
44 };
45 
46 enum {
47 	/* The maximal number of pending events - should be a power of two. */
48 	evq_max = 8
49 };
50 
51 /* A queue of events. */
52 struct pt_event_queue {
53 	/* A collection of event queues, one per binding. */
54 	struct pt_event queue[evb_max][evq_max];
55 
56 	/* The begin and end indices for the above event queues. */
57 	uint8_t begin[evb_max];
58 	uint8_t end[evb_max];
59 
60 	/* A standalone event to be published immediately. */
61 	struct pt_event standalone;
62 };
63 
64 
65 /* Initialize (or reset) an event queue. */
66 extern void pt_evq_init(struct pt_event_queue *);
67 
68 /* Get a standalone event.
69  *
70  * Returns a pointer to the standalone event on success.
71  * Returns NULL if @evq is NULL.
72  */
73 extern struct pt_event *pt_evq_standalone(struct pt_event_queue *evq);
74 
75 /* Enqueue an event.
76  *
77  * Adds a new event to @evq for binding @evb.
78  *
79  * Returns a pointer to the new event on success.
80  * Returns NULL if @evq is NULL or @evb is invalid.
81  * Returns NULL if @evq is full.
82  */
83 extern struct pt_event *pt_evq_enqueue(struct pt_event_queue *evq,
84 				       enum pt_event_binding evb);
85 
86 
87 /* Dequeue an event.
88  *
89  * Removes the first event for binding @evb from @evq.
90  *
91  * Returns a pointer to the dequeued event on success.
92  * Returns NULL if @evq is NULL or @evb is invalid.
93  * Returns NULL if @evq is empty.
94  */
95 extern struct pt_event *pt_evq_dequeue(struct pt_event_queue *evq,
96 				       enum pt_event_binding evb);
97 
98 /* Clear a queue and discard events.
99  *
100  * Removes all events for binding @evb from @evq.
101  *
102  * Returns zero on success, a negative error code otherwise.
103  * Returns -pte_internal if @evq is NULL or @evb is invalid.
104  */
105 extern int pt_evq_clear(struct pt_event_queue *evq,
106 			enum pt_event_binding evb);
107 
108 /* Check for emptiness.
109  *
110  * Check if @evq for binding @evb is empty.
111  *
112  * Returns a positive number if @evq is empty.
113  * Returns zero if @evq is not empty.
114  * Returns -pte_internal if @evq is NULL or @evb is invalid.
115  */
116 extern int pt_evq_empty(const struct pt_event_queue *evq,
117 			enum pt_event_binding evb);
118 
119 /* Check for non-emptiness.
120  *
121  * Check if @evq for binding @evb contains pending events.
122  *
123  * Returns a positive number if @evq is not empty.
124  * Returns zero if @evq is empty.
125  * Returns -pte_internal if @evq is NULL or @evb is invalid.
126  */
127 extern int pt_evq_pending(const struct pt_event_queue *evq,
128 			  enum pt_event_binding evb);
129 
130 /* Find an event by type.
131  *
132  * Searches @evq for binding @evb for an event of type @evt.
133  *
134  * Returns a pointer to the first matching event on success.
135  * Returns NULL if there is no such event.
136  * Returns NULL if @evq is NULL.
137  * Returns NULL if @evb or @evt is invalid.
138  */
139 extern struct pt_event *pt_evq_find(struct pt_event_queue *evq,
140 				    enum pt_event_binding evb,
141 				    enum pt_event_type evt);
142 
143 #endif /* PT_EVENT_QUEUE_H */
144