]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/processor-trace/libipt/src/pt_event_queue.c
Import Intel Processor Trace decoder library from
[FreeBSD/FreeBSD.git] / contrib / processor-trace / libipt / src / pt_event_queue.c
1 /*
2  * Copyright (c) 2013-2018, 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 #include "pt_event_queue.h"
30
31 #include <string.h>
32
33
34 static inline uint8_t pt_evq_inc(uint8_t idx)
35 {
36         idx += 1;
37         idx %= evq_max;
38
39         return idx;
40 }
41
42 static struct pt_event *pt_event_init(struct pt_event *event)
43 {
44         if (event)
45                 memset(event, 0, sizeof(*event));
46
47         return event;
48 }
49
50 void pt_evq_init(struct pt_event_queue *evq)
51 {
52         if (!evq)
53                 return;
54
55         memset(evq, 0, sizeof(*evq));
56 }
57
58 struct pt_event *pt_evq_standalone(struct pt_event_queue *evq)
59 {
60         if (!evq)
61                 return NULL;
62
63         return pt_event_init(&evq->standalone);
64 }
65
66 struct pt_event *pt_evq_enqueue(struct pt_event_queue *evq,
67                                 enum pt_event_binding evb)
68 {
69         uint8_t begin, end, gap, idx;
70
71         if (!evq)
72                 return NULL;
73
74         if (evb_max <= evb)
75                 return NULL;
76
77         begin = evq->begin[evb];
78         idx = evq->end[evb];
79
80         if (evq_max <= begin)
81                 return NULL;
82
83         if (evq_max <= idx)
84                 return NULL;
85
86         end = pt_evq_inc(idx);
87         gap = pt_evq_inc(end);
88
89         /* Leave a gap so we don't overwrite the last dequeued event. */
90         if (begin == gap)
91                 return NULL;
92
93         evq->end[evb] = end;
94
95         return pt_event_init(&evq->queue[evb][idx]);
96 }
97
98 struct pt_event *pt_evq_dequeue(struct pt_event_queue *evq,
99                                 enum pt_event_binding evb)
100 {
101         uint8_t begin, end;
102
103         if (!evq)
104                 return NULL;
105
106         if (evb_max <= evb)
107                 return NULL;
108
109         begin = evq->begin[evb];
110         end = evq->end[evb];
111
112         if (evq_max <= begin)
113                 return NULL;
114
115         if (evq_max <= end)
116                 return NULL;
117
118         if (begin == end)
119                 return NULL;
120
121         evq->begin[evb] = pt_evq_inc(begin);
122
123         return &evq->queue[evb][begin];
124 }
125
126 int pt_evq_clear(struct pt_event_queue *evq, enum pt_event_binding evb)
127 {
128         if (!evq)
129                 return -pte_internal;
130
131         if (evb_max <= evb)
132                 return -pte_internal;
133
134         evq->begin[evb] = 0;
135         evq->end[evb] = 0;
136
137         return 0;
138 }
139
140 int pt_evq_empty(const struct pt_event_queue *evq, enum pt_event_binding evb)
141 {
142         uint8_t begin, end;
143
144         if (!evq)
145                 return -pte_internal;
146
147         if (evb_max <= evb)
148                 return -pte_internal;
149
150         begin = evq->begin[evb];
151         end = evq->end[evb];
152
153         if (evq_max <= begin)
154                 return -pte_internal;
155
156         if (evq_max <= end)
157                 return -pte_internal;
158
159         return begin == end;
160 }
161
162 int pt_evq_pending(const struct pt_event_queue *evq, enum pt_event_binding evb)
163 {
164         int errcode;
165
166         errcode = pt_evq_empty(evq, evb);
167         if (errcode < 0)
168                 return errcode;
169
170         return !errcode;
171 }
172
173 struct pt_event *pt_evq_find(struct pt_event_queue *evq,
174                              enum pt_event_binding evb,
175                              enum pt_event_type evt)
176 {
177         uint8_t begin, end;
178
179         if (!evq)
180                 return NULL;
181
182         if (evb_max <= evb)
183                 return NULL;
184
185         begin = evq->begin[evb];
186         end = evq->end[evb];
187
188         if (evq_max <= begin)
189                 return NULL;
190
191         if (evq_max <= end)
192                 return NULL;
193
194         for (; begin != end; begin = pt_evq_inc(begin)) {
195                 struct pt_event *ev;
196
197                 ev = &evq->queue[evb][begin];
198                 if (ev->type == evt)
199                         return ev;
200         }
201
202         return NULL;
203 }