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 28 29 struct EvtRecord { 30 struct EvtRecord *next; 31 struct EvtRecord *prev; 32 uint32_t evtType; 33 void* evtData; 34 uintptr_t evtFreeData; 35 }; 36 37 struct EvtQueue { 38 struct EvtRecord *head; 39 struct EvtRecord *tail; 40 struct SlabAllocator *evtsSlab; 41 EvtQueueForciblyDiscardEvtCbkF forceDiscardCbk; 42 }; 43 44 45 46 struct EvtQueue* evtQueueAlloc(uint32_t size, EvtQueueForciblyDiscardEvtCbkF forceDiscardCbk) 47 { 48 struct EvtQueue *q = heapAlloc(sizeof(struct EvtQueue)); 49 struct SlabAllocator *slab = slabAllocatorNew(sizeof(struct EvtRecord), alignof(struct EvtRecord), size); 50 51 if (q && slab) { 52 q->forceDiscardCbk = forceDiscardCbk; 53 q->evtsSlab = slab; 54 q->head = NULL; 55 q->tail = NULL; 56 return q; 57 } 58 59 if (q) 60 heapFree(q); 61 if (slab) 62 slabAllocatorDestroy(slab); 63 64 return NULL; 65 } 66 67 void evtQueueFree(struct EvtQueue* q) 68 { 69 struct EvtRecord *t; 70 71 while (q->head) { 72 t = q->head; 73 q->head = q->head->next; 74 q->forceDiscardCbk(t->evtType, t->evtData, t->evtFreeData); 75 slabAllocatorFree(q->evtsSlab, t); 76 } 77 78 slabAllocatorDestroy(q->evtsSlab); 79 heapFree(q); 80 } 81 82 bool evtQueueEnqueue(struct EvtQueue* q, uint32_t evtType, void *evtData, uintptr_t evtFreeData, bool atFront) 83 { 84 struct EvtRecord *rec; 85 uint64_t intSta; 86 87 if (!q) 88 return false; 89 90 rec = slabAllocatorAlloc(q->evtsSlab); 91 if (!rec) { 92 intSta = cpuIntsOff(); 93 94 //find a victim for discarding 95 rec = q->head; 96 while (rec && !(rec->evtType & EVENT_TYPE_BIT_DISCARDABLE)) 97 rec = rec->next; 98 99 if (rec) { 100 q->forceDiscardCbk(rec->evtType, rec->evtData, rec->evtFreeData); 101 if (rec->prev) 102 rec->prev->next = rec->next; 103 else 104 q->head = rec->next; 105 if (rec->next) 106 rec->next->prev = rec->prev; 107 else 108 q->tail = rec->prev; 109 } 110 111 cpuIntsRestore (intSta); 112 if (!rec) 113 return false; 114 } 115 116 rec->next = NULL; 117 rec->evtType = evtType; 118 rec->evtData = evtData; 119 rec->evtFreeData = evtFreeData; 120 121 intSta = cpuIntsOff(); 122 123 if (atFront) { /* this is almost always not the case */ 124 rec->prev = NULL; 125 rec->next = q->head; 126 q->head = rec; 127 if (q->tail) 128 rec->next->prev = rec; 129 else 130 q->tail = rec; 131 } 132 else { /* the common case */ 133 rec->prev = q->tail; 134 q->tail = rec; 135 if (q->head) 136 rec->prev->next = rec; 137 else 138 q->head = rec; 139 } 140 141 cpuIntsRestore(intSta); 142 platWake(); 143 return true; 144 } 145 146 bool evtQueueDequeue(struct EvtQueue* q, uint32_t *evtTypeP, void **evtDataP, uintptr_t *evtFreeDataP, bool sleepIfNone) 147 { 148 struct EvtRecord *rec = NULL; 149 uint64_t intSta; 150 151 while(1) { 152 intSta = cpuIntsOff(); 153 154 rec = q->head; 155 if (rec) { 156 q->head = rec->next; 157 if (q->head) 158 q->head->prev = NULL; 159 else 160 q->tail = NULL; 161 break; 162 } 163 else if (!sleepIfNone) 164 break; 165 else if (!timIntHandler()) { // check for timers. if any fire, do not sleep (since by the time callbacks run, moremight be due) 166 platSleep(); //sleep 167 timIntHandler(); //first thing when awake: check timers 168 } 169 cpuIntsRestore(intSta); 170 } 171 172 cpuIntsRestore(intSta); 173 174 if (!rec) 175 return false; 176 177 *evtTypeP = rec->evtType; 178 *evtDataP = rec->evtData; 179 *evtFreeDataP = rec->evtFreeData; 180 slabAllocatorFree(q->evtsSlab, rec); 181 182 return true; 183 } 184 185