• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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