• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "can/can_msg.h"
10 #include "hdf_dlist.h"
11 #include "hdf_log.h"
12 #include "osal_atomic.h"
13 #include "osal_mem.h"
14 #include "osal_time.h"
15 #include "securec.h"
16 
17 #define HDF_LOG_TAG can_msg
18 
19 #define CAN_MSG_POOL_SIZE_MAX 32
20 
21 struct CanMsgHolder {
22     struct CanMsg cmsg;
23     struct HdfSRef ref;
24     OsalAtomic available;
25 };
26 
27 struct CanMsgPool {
28     size_t size;
29     struct CanMsgHolder *holders;
30 };
31 
CanMsgPoolAcquireHolder(struct CanMsgPool * pool)32 static struct CanMsgHolder *CanMsgPoolAcquireHolder(struct CanMsgPool *pool)
33 {
34     size_t i;
35     struct CanMsgHolder *holder = NULL;
36 
37     for (i = 0; i < pool->size; i++) {
38         holder = &pool->holders[i];
39         if (OsalAtomicRead(&holder->available) < 1) {
40             continue;
41         }
42         if (OsalAtomicDecReturn(&holder->available) != 0) {
43             OsalAtomicInc(&holder->available);
44             continue;
45         }
46         (void)memset_s(holder, sizeof(*holder), 0, sizeof(*holder));
47         return holder;
48     }
49     return NULL;
50 }
51 
CanMsgPoolRecycleHolder(struct CanMsgHolder * holder)52 static void CanMsgPoolRecycleHolder(struct CanMsgHolder *holder)
53 {
54     if (holder == NULL) {
55         HDF_LOGE("CanMsgPoolRecycleHolder: holder is null!");
56         return;
57     }
58     OsalAtomicInc(&holder->available);
59 }
60 
CanMsgGet(const struct CanMsg * msg)61 void CanMsgGet(const struct CanMsg *msg)
62 {
63     struct CanMsgHolder *holder = NULL;
64 
65     if (msg == NULL) {
66         HDF_LOGE("CanMsgGet: msg is null!");
67         return;
68     }
69     holder = CONTAINER_OF(msg, struct CanMsgHolder, cmsg);
70     HdfSRefAcquire(&holder->ref);
71 }
72 
CanMsgPut(const struct CanMsg * msg)73 void CanMsgPut(const struct CanMsg *msg)
74 {
75     struct CanMsgHolder *holder = NULL;
76 
77     if (msg == NULL) {
78         HDF_LOGE("CanMsgPut: msg is null!");
79         return;
80     }
81     holder = CONTAINER_OF(msg, struct CanMsgHolder, cmsg);
82     HdfSRefRelease(&holder->ref);
83 }
84 
CanMsgHolderOnFirstGet(struct HdfSRef * sref)85 static void CanMsgHolderOnFirstGet(struct HdfSRef *sref)
86 {
87     (void)sref;
88 }
89 
CanMsgHolderOnLastPut(struct HdfSRef * sref)90 static void CanMsgHolderOnLastPut(struct HdfSRef *sref)
91 {
92     struct CanMsgHolder *holder = NULL;
93 
94     if (sref == NULL) {
95         HDF_LOGE("CanMsgHolderOnLastPut: sref is null!");
96         return;
97     }
98     holder = CONTAINER_OF(sref, struct CanMsgHolder, ref);
99     CanMsgPoolRecycleHolder(holder);
100 }
101 
102 struct IHdfSRefListener g_canMsgExtListener = {
103     .OnFirstAcquire = CanMsgHolderOnFirstGet,
104     .OnLastRelease = CanMsgHolderOnLastPut,
105 };
106 
CanMsgPoolObtainMsg(struct CanMsgPool * pool)107 struct CanMsg *CanMsgPoolObtainMsg(struct CanMsgPool *pool)
108 {
109     struct CanMsgHolder *holder = NULL;
110 
111     if (pool == NULL) {
112         HDF_LOGE("CanMsgPoolObtainMsg: pool is null!");
113         return NULL;
114     }
115 
116     holder = CanMsgPoolAcquireHolder(pool);
117     if (holder == NULL) {
118         HDF_LOGE("CanMsgPoolObtainMsg: holder is null!");
119         return NULL;
120     }
121 
122     HdfSRefConstruct(&holder->ref, &g_canMsgExtListener);
123     CanMsgGet(&holder->cmsg);
124     return &holder->cmsg;
125 }
126 
CanMsgPoolCreate(size_t size)127 struct CanMsgPool *CanMsgPoolCreate(size_t size)
128 {
129     size_t i;
130     struct CanMsgPool *pool = NULL;
131 
132     if (size > CAN_MSG_POOL_SIZE_MAX) {
133         HDF_LOGE("CanMsgPoolCreate: invalid pool size %zu", size);
134         return NULL;
135     }
136     pool = OsalMemCalloc(sizeof(*pool) + sizeof(struct CanMsgHolder) * size);
137     if (pool == NULL) {
138         HDF_LOGE("CanMsgPoolCreate: alloc pool mem fail!");
139         return NULL;
140     }
141 
142     pool->size = size;
143     pool->holders = (struct CanMsgHolder *)((uint8_t *)pool + sizeof(*pool));
144     for (i = 0; i < size; i++) {
145         OsalAtomicSet(&pool->holders[i].available, 1);
146     }
147 
148     HDF_LOGI("CanMsgPoolCreate: end!");
149     return pool;
150 }
151 
CanMsgPoolDestroy(struct CanMsgPool * pool)152 void CanMsgPoolDestroy(struct CanMsgPool *pool)
153 {
154     size_t drain;
155     struct CanMsgHolder *holder = NULL;
156 
157     if (pool == NULL) {
158         HDF_LOGE("CanMsgPoolDestroy: pool is null!");
159         return;
160     }
161     drain = pool->size;
162     while (drain > 0) {
163         holder = CanMsgPoolAcquireHolder(pool);
164         if (holder == NULL) {
165             HDF_LOGI("CanMsgPoolDestroy: wait pool, drain = %zu", drain);
166             OsalMSleep(200); //wait for 200 ms
167             continue;
168         }
169         drain--;
170     };
171     HDF_LOGI("CanMsgPoolDestroy: end!");
172     OsalMemFree(pool);
173 }
174