Home | History | Annotate | Download | only in src
      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