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 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 } 204