xref: /aosp_15_r20/external/fastrpc/inc/pls.h (revision 418b791d679beb2078b579a3b6936cf330c41799)
1*418b791dSBob Badour #ifndef PLS_H
2*418b791dSBob Badour #define PLS_H
3*418b791dSBob Badour 
4*418b791dSBob Badour /**
5*418b791dSBob Badour  * Copyright (c) 2019, The Linux Foundation. All rights reserved.
6*418b791dSBob Badour  *
7*418b791dSBob Badour  * Redistribution and use in source and binary forms, with or without
8*418b791dSBob Badour  * modification, are permitted provided that the following conditions are
9*418b791dSBob Badour  * met:
10*418b791dSBob Badour  *    * Redistributions of source code must retain the above copyright
11*418b791dSBob Badour  *      notice, this list of conditions and the following disclaimer.
12*418b791dSBob Badour  *    * Redistributions in binary form must reproduce the above
13*418b791dSBob Badour  *      copyright notice, this list of conditions and the following
14*418b791dSBob Badour  *      disclaimer in the documentation and/or other materials provided
15*418b791dSBob Badour  *      with the distribution.
16*418b791dSBob Badour  *    * Neither the name of The Linux Foundation nor the names of its
17*418b791dSBob Badour  *      contributors may be used to endorse or promote products derived
18*418b791dSBob Badour  *      from this software without specific prior written permission.
19*418b791dSBob Badour  *
20*418b791dSBob Badour  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21*418b791dSBob Badour  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22*418b791dSBob Badour  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23*418b791dSBob Badour  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24*418b791dSBob Badour  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25*418b791dSBob Badour  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26*418b791dSBob Badour  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27*418b791dSBob Badour  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28*418b791dSBob Badour  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29*418b791dSBob Badour  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30*418b791dSBob Badour  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*418b791dSBob Badour  */
32*418b791dSBob Badour 
33*418b791dSBob Badour #include <stdlib.h>
34*418b791dSBob Badour #include "AEEStdDef.h"
35*418b791dSBob Badour #include "AEEatomic.h"
36*418b791dSBob Badour #include "verify.h"
37*418b791dSBob Badour #include "HAP_farf.h"
38*418b791dSBob Badour 
39*418b791dSBob Badour struct PLS;
40*418b791dSBob Badour 
41*418b791dSBob Badour struct plskey {
42*418b791dSBob Badour    uintptr_t type;
43*418b791dSBob Badour    uintptr_t key;
44*418b791dSBob Badour };
45*418b791dSBob Badour 
46*418b791dSBob Badour struct PLS {
47*418b791dSBob Badour    struct PLS* next;
48*418b791dSBob Badour    struct plskey key;
49*418b791dSBob Badour    void (*dtor)(void* data);
50*418b791dSBob Badour    uint64_t data[1];
51*418b791dSBob Badour };
52*418b791dSBob Badour 
53*418b791dSBob Badour 
54*418b791dSBob Badour struct pls_table {
55*418b791dSBob Badour    struct PLS* lst;
56*418b791dSBob Badour    uint32_t uRefs;
57*418b791dSBob Badour    uint32_t primThread;
58*418b791dSBob Badour };
59*418b791dSBob Badour 
60*418b791dSBob Badour /**
61*418b791dSBob Badour  * initialize on every thread and stick the pls_thread_deinit
62*418b791dSBob Badour  * function into the threads tls
63*418b791dSBob Badour  */
pls_thread_init(struct pls_table * me,uintptr_t tid)64*418b791dSBob Badour static __inline int pls_thread_init(struct pls_table* me, uintptr_t tid) {
65*418b791dSBob Badour    if(tid == me->primThread) {
66*418b791dSBob Badour       return 0;
67*418b791dSBob Badour    }
68*418b791dSBob Badour    if(0 == atomic_CompareOrAdd(&me->uRefs, 0, 1)) {
69*418b791dSBob Badour       return -1;
70*418b791dSBob Badour    }
71*418b791dSBob Badour    return 0;
72*418b791dSBob Badour }
73*418b791dSBob Badour 
74*418b791dSBob Badour /* call this constructor before the first thread creation with the
75*418b791dSBob Badour  * first threads id
76*418b791dSBob Badour  */
pls_ctor(struct pls_table * me,uintptr_t primThread)77*418b791dSBob Badour static __inline void pls_ctor(struct pls_table* me, uintptr_t primThread) {
78*418b791dSBob Badour    me->uRefs = 1;
79*418b791dSBob Badour    me->primThread = primThread;
80*418b791dSBob Badour }
81*418b791dSBob Badour 
pls_thread_deinit(struct pls_table * me)82*418b791dSBob Badour static __inline struct pls_table* pls_thread_deinit(struct pls_table* me) {
83*418b791dSBob Badour    if(me && 0 != me->uRefs && 0 == atomic_Add(&me->uRefs, -1)) {
84*418b791dSBob Badour       struct PLS* lst, *next;
85*418b791dSBob Badour       lst = me->lst;
86*418b791dSBob Badour       me->lst = 0;
87*418b791dSBob Badour       while(lst) {
88*418b791dSBob Badour          next = lst->next;
89*418b791dSBob Badour          if(lst->dtor) {
90*418b791dSBob Badour             FARF(HIGH, "pls dtor %p", lst->dtor);
91*418b791dSBob Badour             lst->dtor((void*)lst->data);
92*418b791dSBob Badour          }
93*418b791dSBob Badour          free(lst);
94*418b791dSBob Badour          lst = next;
95*418b791dSBob Badour       }
96*418b791dSBob Badour       return me;
97*418b791dSBob Badour    }
98*418b791dSBob Badour    return 0;
99*418b791dSBob Badour }
100*418b791dSBob Badour 
101*418b791dSBob Badour /**
102*418b791dSBob Badour  * adds a new key to the local storage, overriding
103*418b791dSBob Badour  * any previous value at the key.  Overriding the key
104*418b791dSBob Badour  * does not cause the destructor to run.
105*418b791dSBob Badour  *
106*418b791dSBob Badour  * @param type, type part of the key to be used for lookup,
107*418b791dSBob Badour           these should be static addresses.
108*418b791dSBob Badour  * @param key, the key to be used for lookup
109*418b791dSBob Badour  * @param size, the size of the data
110*418b791dSBob Badour  * @param ctor, constructor that takes a context and memory of size
111*418b791dSBob Badour  * @param ctx, constructor context passed as the first argument to ctor
112*418b791dSBob Badour  * @param dtor, destructor to run at pls shutdown
113*418b791dSBob Badour  * @param ppo, output data
114*418b791dSBob Badour  * @retval, 0 for success
115*418b791dSBob Badour  */
116*418b791dSBob Badour 
pls_add(struct pls_table * me,uintptr_t type,uintptr_t key,int size,int (* ctor)(void * ctx,void * data),void * ctx,void (* dtor)(void * data),void ** ppo)117*418b791dSBob Badour static __inline int pls_add(struct pls_table* me, uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* data), void** ppo) {
118*418b791dSBob Badour    int nErr = 0;
119*418b791dSBob Badour    struct PLS* pls = 0;
120*418b791dSBob Badour    struct PLS* prev;
121*418b791dSBob Badour    VERIFY(me->uRefs != 0);
122*418b791dSBob Badour    VERIFY(0 != (pls = (struct PLS*)calloc(1, size + sizeof(*pls) - sizeof(pls->data))));
123*418b791dSBob Badour    if(ctor) {
124*418b791dSBob Badour       VERIFY(0 == ctor(ctx, (void*)pls->data));
125*418b791dSBob Badour    }
126*418b791dSBob Badour    pls->dtor = dtor;
127*418b791dSBob Badour    pls->key.type = type;
128*418b791dSBob Badour    pls->key.key = key;
129*418b791dSBob Badour    do {
130*418b791dSBob Badour       pls->next = me->lst;
131*418b791dSBob Badour       prev = (struct PLS*)atomic_CompareAndExchangeUP((uintptr_t*)&me->lst, (uintptr_t)pls, (uintptr_t)pls->next);
132*418b791dSBob Badour    } while(prev != pls->next);
133*418b791dSBob Badour    if(ppo) {
134*418b791dSBob Badour       *ppo = (void*)pls->data;
135*418b791dSBob Badour    }
136*418b791dSBob Badour    FARF(HIGH, "pls added %p", dtor);
137*418b791dSBob Badour bail:
138*418b791dSBob Badour    if(nErr && pls) {
139*418b791dSBob Badour       free(pls);
140*418b791dSBob Badour    }
141*418b791dSBob Badour    return nErr;
142*418b791dSBob Badour }
143*418b791dSBob Badour 
144*418b791dSBob Badour static __inline int pls_lookup(struct pls_table* me, uintptr_t type, uintptr_t key, void** ppo);
145*418b791dSBob Badour 
146*418b791dSBob Badour /**
147*418b791dSBob Badour  * like add, but will only add 1 item if two threads try to add at the same time.  returns
148*418b791dSBob Badour  * item if its already there, otherwise tries to add.
149*418b791dSBob Badour  * ctor may be called twice
150*418b791dSBob Badour  * callers should avoid calling pls_add which will override the singleton
151*418b791dSBob Badour  */
pls_add_lookup_singleton(struct pls_table * me,uintptr_t type,uintptr_t key,int size,int (* ctor)(void * ctx,void * data),void * ctx,void (* dtor)(void * data),void ** ppo)152*418b791dSBob Badour static __inline int pls_add_lookup_singleton(struct pls_table* me, uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* data), void** ppo) {
153*418b791dSBob Badour    int nErr = 0;
154*418b791dSBob Badour    struct PLS* pls = 0;
155*418b791dSBob Badour    struct PLS* prev;
156*418b791dSBob Badour    if(0 == pls_lookup(me, type, key, ppo)) {
157*418b791dSBob Badour       return 0;
158*418b791dSBob Badour    }
159*418b791dSBob Badour    VERIFY(me->uRefs != 0);
160*418b791dSBob Badour    VERIFY(0 != (pls = (struct PLS*)calloc(1, size + sizeof(*pls) - sizeof(pls->data))));
161*418b791dSBob Badour    if(ctor) {
162*418b791dSBob Badour       VERIFY(0 == ctor(ctx, (void*)pls->data));
163*418b791dSBob Badour    }
164*418b791dSBob Badour    pls->dtor = dtor;
165*418b791dSBob Badour    pls->key.type = type;
166*418b791dSBob Badour    pls->key.key = key;
167*418b791dSBob Badour    do {
168*418b791dSBob Badour       pls->next = me->lst;
169*418b791dSBob Badour       if(0 == pls_lookup(me, type, key, ppo)) {
170*418b791dSBob Badour          if(pls->dtor) {
171*418b791dSBob Badour             pls->dtor((void*)pls->data);
172*418b791dSBob Badour          }
173*418b791dSBob Badour          free(pls);
174*418b791dSBob Badour          return 0;
175*418b791dSBob Badour       }
176*418b791dSBob Badour       prev = (struct PLS*)atomic_CompareAndExchangeUP((uintptr_t*)&me->lst, (uintptr_t)pls, (uintptr_t)pls->next);
177*418b791dSBob Badour    } while(prev != pls->next);
178*418b791dSBob Badour    if(ppo) {
179*418b791dSBob Badour       *ppo = (void*)pls->data;
180*418b791dSBob Badour    }
181*418b791dSBob Badour    FARF(HIGH, "pls added %p", dtor);
182*418b791dSBob Badour bail:
183*418b791dSBob Badour    if(nErr && pls) {
184*418b791dSBob Badour       free(pls);
185*418b791dSBob Badour    }
186*418b791dSBob Badour    return nErr;
187*418b791dSBob Badour }
188*418b791dSBob Badour 
189*418b791dSBob Badour 
190*418b791dSBob Badour /**
191*418b791dSBob Badour  * finds the last data pointer added for key to the local storage
192*418b791dSBob Badour  *
193*418b791dSBob Badour  * @param key, the key to be used for lookup
194*418b791dSBob Badour  * @param ppo, output data
195*418b791dSBob Badour  * @retval, 0 for success
196*418b791dSBob Badour  */
197*418b791dSBob Badour 
pls_lookup(struct pls_table * me,uintptr_t type,uintptr_t key,void ** ppo)198*418b791dSBob Badour static __inline int pls_lookup(struct pls_table* me, uintptr_t type, uintptr_t key, void** ppo) {
199*418b791dSBob Badour    struct PLS* lst;
200*418b791dSBob Badour    for(lst = me->lst; me->uRefs != 0 && lst != 0; lst = lst->next) {
201*418b791dSBob Badour       if(lst->key.type == type && lst->key.key == key) {
202*418b791dSBob Badour          if(ppo) {
203*418b791dSBob Badour             *ppo = lst->data;
204*418b791dSBob Badour          }
205*418b791dSBob Badour          return 0;
206*418b791dSBob Badour       }
207*418b791dSBob Badour    }
208*418b791dSBob Badour    return -1;
209*418b791dSBob Badour }
210*418b791dSBob Badour 
211*418b791dSBob Badour #endif //PLS_H
212*418b791dSBob Badour 
213*418b791dSBob Badour 
214