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 #include "pt_event_queue.h"
30
31 #include <string.h>
32
33
pt_evq_inc(uint8_t idx)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
pt_event_init(struct pt_event * event)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
pt_evq_init(struct pt_event_queue * evq)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
pt_evq_standalone(struct pt_event_queue * evq)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
pt_evq_enqueue(struct pt_event_queue * evq,enum pt_event_binding evb)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
pt_evq_dequeue(struct pt_event_queue * evq,enum pt_event_binding evb)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
pt_evq_clear(struct pt_event_queue * evq,enum pt_event_binding evb)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
pt_evq_empty(const struct pt_event_queue * evq,enum pt_event_binding evb)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
pt_evq_pending(const struct pt_event_queue * evq,enum pt_event_binding evb)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
pt_evq_find(struct pt_event_queue * evq,enum pt_event_binding evb,enum pt_event_type evt)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 }
204