• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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         return;
56     }
57     OsalAtomicInc(&holder->available);
58 }
59 
CanMsgGet(const struct CanMsg * msg)60 void CanMsgGet(const struct CanMsg *msg)
61 {
62     struct CanMsgHolder *holder = NULL;
63 
64     if (msg == NULL) {
65         return;
66     }
67     holder = CONTAINER_OF(msg, struct CanMsgHolder, cmsg);
68     HdfSRefAcquire(&holder->ref);
69 }
70 
CanMsgPut(const struct CanMsg * msg)71 void CanMsgPut(const struct CanMsg *msg)
72 {
73     struct CanMsgHolder *holder = NULL;
74 
75     if (msg == NULL) {
76         return;
77     }
78     holder = CONTAINER_OF(msg, struct CanMsgHolder, cmsg);
79     HdfSRefRelease(&holder->ref);
80 }
81 
CanMsgHolderOnFirstGet(struct HdfSRef * sref)82 static void CanMsgHolderOnFirstGet(struct HdfSRef *sref)
83 {
84     (void)sref;
85 }
86 
CanMsgHolderOnLastPut(struct HdfSRef * sref)87 static void CanMsgHolderOnLastPut(struct HdfSRef *sref)
88 {
89     struct CanMsgHolder *holder = NULL;
90 
91     if (sref == NULL) {
92         return;
93     }
94     holder = CONTAINER_OF(sref, struct CanMsgHolder, ref);
95     CanMsgPoolRecycleHolder(holder);
96 }
97 
98 struct IHdfSRefListener g_canMsgExtListener = {
99     .OnFirstAcquire = CanMsgHolderOnFirstGet,
100     .OnLastRelease = CanMsgHolderOnLastPut,
101 };
102 
CanMsgPoolObtainMsg(struct CanMsgPool * pool)103 struct CanMsg *CanMsgPoolObtainMsg(struct CanMsgPool *pool)
104 {
105     struct CanMsgHolder *holder = NULL;
106 
107     if (pool == NULL) {
108         return NULL;
109     }
110 
111     holder = CanMsgPoolAcquireHolder(pool);
112     if (holder == NULL) {
113         return NULL;
114     }
115 
116     HdfSRefConstruct(&holder->ref, &g_canMsgExtListener);
117     CanMsgGet(&holder->cmsg);
118     return &holder->cmsg;
119 }
120 
CanMsgPoolCreate(size_t size)121 struct CanMsgPool *CanMsgPoolCreate(size_t size)
122 {
123     size_t i;
124     struct CanMsgPool *pool = NULL;
125 
126     if (size > CAN_MSG_POOL_SIZE_MAX) {
127         HDF_LOGE("CanMsgPoolCreate: invalid pool size %zu", size);
128         return NULL;
129     }
130     pool = OsalMemCalloc(sizeof(*pool) + sizeof(struct CanMsgHolder) * size);
131     if (pool == NULL) {
132         HDF_LOGE("CanMsgPoolCreate: alloc pool mem failed");
133         return NULL;
134     }
135 
136     pool->size = size;
137     pool->holders = (struct CanMsgHolder *)((uint8_t *)pool + sizeof(*pool));
138     for (i = 0; i < size; i++) {
139         OsalAtomicSet(&pool->holders[i].available, 1);
140     }
141 
142     HDF_LOGI("CanMsgPoolCreate: pool = %p", pool);
143     return pool;
144 }
145 
CanMsgPoolDestroy(struct CanMsgPool * pool)146 void CanMsgPoolDestroy(struct CanMsgPool *pool)
147 {
148     size_t drain;
149     struct CanMsgHolder *holder = NULL;
150 
151     if (pool == NULL) {
152         return;
153     }
154     drain = pool->size;
155     while (drain > 0) {
156         holder = CanMsgPoolAcquireHolder(pool);
157         if (holder == NULL) {
158             HDF_LOGI("CanMsgPoolDestroy: wait pool, drain = %zu", drain);
159             OsalMSleep(200); //wait for 200 ms
160             continue;
161         }
162         drain--;
163     };
164     HDF_LOGI("CanMsgPoolDestroy: pool = %p", pool);
165     OsalMemFree(pool);
166 }
167