1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <platform.h> 18 #include <eventQ.h> 19 #include <stddef.h> 20 #include <timer.h> 21 #include <stdio.h> 22 #include <heap.h> 23 #include <slab.h> 24 #include <cpu.h> 25 #include <util.h> 26 #include <plat/inc/plat.h> 27 #include <plat/inc/taggedPtr.h> 28 29 30 struct EvtRecord { 31 struct EvtRecord *next; 32 struct EvtRecord *prev; 33 uint32_t evtType; 34 void* evtData; 35 TaggedPtr evtFreeData; 36 }; 37 38 struct EvtQueue { 39 struct EvtRecord *head; 40 struct EvtRecord *tail; 41 struct SlabAllocator *evtsSlab; 42 EvtQueueForciblyDiscardEvtCbkF forceDiscardCbk; 43 }; 44 45 46 47 struct EvtQueue* evtQueueAlloc(uint32_t size, EvtQueueForciblyDiscardEvtCbkF forceDiscardCbk) 48 { 49 struct EvtQueue *q = heapAlloc(sizeof(struct EvtQueue)); 50 struct SlabAllocator *slab = slabAllocatorNew(sizeof(struct EvtRecord), alignof(struct EvtRecord), size); 51 52 if (q && slab) { 53 q->forceDiscardCbk = forceDiscardCbk; 54 q->evtsSlab = slab; 55 q->head = NULL; 56 q->tail = NULL; 57 return q; 58 } 59 60 if (q) 61 heapFree(q); 62 if (slab) 63 slabAllocatorDestroy(slab); 64 65 return NULL; 66 } 67 68 void evtQueueFree(struct EvtQueue* q) 69 { 70 struct EvtRecord *t; 71 72 while (q->head) { 73 t = q->head; 74 q->head = q->head->next; 75 q->forceDiscardCbk(t->evtType, t->evtData, t->evtFreeData); 76 slabAllocatorFree(q->evtsSlab, t); 77 } 78 79 slabAllocatorDestroy(q->evtsSlab); 80 heapFree(q); 81 } 82 83 bool evtQueueEnqueue(struct EvtQueue* q, uint32_t evtType, void *evtData, TaggedPtr evtFreeData, bool atFront) 84 { 85 struct EvtRecord *rec; 86 uint64_t intSta; 87 88 if (!q) 89 return false; 90 91 rec = slabAllocatorAlloc(q->evtsSlab); 92 if (!rec) { 93 intSta = cpuIntsOff(); 94 95 //find a victim for discarding 96 rec = q->head; 97 while (rec && !(rec->evtType & EVENT_TYPE_BIT_DISCARDABLE)) 98 rec = rec->next; 99 100 if (rec) { 101 q->forceDiscardCbk(rec->evtType, rec->evtData, rec->evtFreeData); 102 if (rec->prev) 103 rec->prev->next = rec->next; 104 else 105 q->head = rec->next; 106 if (rec->next) 107 rec->next->prev = rec->prev; 108 else 109 q->tail = rec->prev; 110 } 111 112 cpuIntsRestore (intSta); 113 if (!rec) 114 return false; 115 } 116 117 rec->next = NULL; 118 rec->evtType = evtType; 119 rec->evtData = evtData; 120 rec->evtFreeData = evtFreeData; 121 122 intSta = cpuIntsOff(); 123 124 if (atFront) { /* this is almost always not the case */ 125 rec->prev = NULL; 126 rec->next = q->head; 127 q->head = rec; 128 if (q->tail) 129 rec->next->prev = rec; 130 else 131 q->tail = rec; 132 } 133 else { /* the common case */ 134 rec->prev = q->tail; 135 q->tail = rec; 136 if (q->head) 137 rec->prev->next = rec; 138 else 139 q->head = rec; 140 } 141 142 cpuIntsRestore(intSta); 143 platWake(); 144 return true; 145 } 146 147 bool evtQueueDequeue(struct EvtQueue* q, uint32_t *evtTypeP, void **evtDataP, TaggedPtr *evtFreeDataP, bool sleepIfNone) 148 { 149 struct EvtRecord *rec = NULL; 150 uint64_t intSta; 151 152 while(1) { 153 intSta = cpuIntsOff(); 154 155 rec = q->head; 156 if (rec) { 157 q->head = rec->next; 158 if (q->head) 159 q->head->prev = NULL; 160 else 161 q->tail = NULL; 162 break; 163 } 164 else if (!sleepIfNone) 165 break; 166 else if (!timIntHandler()) { // check for timers. if any fire, do not sleep (since by the time callbacks run, moremight be due) 167 platSleep(); //sleep 168 timIntHandler(); //first thing when awake: check timers 169 } 170 cpuIntsRestore(intSta); 171 } 172 173 cpuIntsRestore(intSta); 174 175 if (!rec) 176 return false; 177 178 *evtTypeP = rec->evtType; 179 *evtDataP = rec->evtData; 180 *evtFreeDataP = rec->evtFreeData; 181 slabAllocatorFree(q->evtsSlab, rec); 182 183 return true; 184 } 185 186