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
evtQueueAlloc(uint32_t size,EvtQueueForciblyDiscardEvtCbkF forceDiscardCbk)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
evtQueueFree(struct EvtQueue * q)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
evtQueueEnqueue(struct EvtQueue * q,uint32_t evtType,void * evtData,TaggedPtr evtFreeData,bool atFront)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
evtQueueDequeue(struct EvtQueue * q,uint32_t * evtTypeP,void ** evtDataP,TaggedPtr * evtFreeDataP,bool sleepIfNone)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