1 /*
2  * Copyright (c) 2020 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "lock_free_queue.h"
16 #include <ohos_errno.h>
17 #include <securec.h>
18 #include <memory_adapter.h>
19 
LFQUE_Create(int size,int count)20 LockFreeQueue *LFQUE_Create(int size, int count)
21 {
22     if (size <= 0 || count <= 0) {
23         return NULL;
24     }
25 
26     int total = size * count + 1;
27     if (total <= 0) {
28         return NULL;
29     }
30 
31     register LockFreeQueue *queue = (LockFreeQueue *)SAMGR_Malloc(sizeof(LockFreeQueue) + total);
32     if (queue == NULL) {
33         return NULL;
34     }
35     queue->write = 0;
36     queue->read = 0;
37     queue->itemSize = size;
38     queue->totalSize = total;
39     return queue;
40 }
41 
LFQUE_IsFull(LockFreeQueue * queue)42 BOOL LFQUE_IsFull(LockFreeQueue *queue)
43 {
44     uint32 nextWrite = queue->write + 1;
45     if (nextWrite >= queue->totalSize) {
46         nextWrite = 0;
47     }
48     return (nextWrite == queue->read);
49 }
50 
LFQUE_IsEmpty(LockFreeQueue * queue)51 BOOL LFQUE_IsEmpty(LockFreeQueue *queue)
52 {
53     return (queue->write == queue->read);
54 }
55 
LFQUE_Push(LockFreeQueue * queue,const void * element,uint8 pri)56 int LFQUE_Push(LockFreeQueue *queue, const void *element, uint8 pri)
57 {
58     (void)pri;
59     if (queue == NULL || element == NULL) {
60         return EC_INVALID;
61     }
62 
63     if (LFQUE_IsFull(queue)) {
64         return EC_BUSBUSY;
65     }
66     uint32 copyLen = (queue->totalSize - queue->write < queue->itemSize) ?
67                   (queue->totalSize - queue->write) : queue->itemSize;
68     if (memcpy_s(&queue->buffer[queue->write], copyLen, element, copyLen) != EOK) {
69         return EC_INVALID;
70     }
71 
72     element += copyLen;
73     copyLen = queue->itemSize - copyLen;
74     if (copyLen > 0) {
75         if (memcpy_s(queue->buffer, copyLen, element, copyLen) != EOK) {
76             return EC_INVALID;
77         }
78     }
79 
80     uint32 write = queue->write + queue->itemSize;
81     if (write >= queue->totalSize) {
82         write = write - queue->totalSize;
83     }
84     queue->write = write;
85     return EC_SUCCESS;
86 }
87 
LFQUE_Pop(LockFreeQueue * queue,void * element,uint8 * pri)88 int LFQUE_Pop(LockFreeQueue *queue, void *element, uint8 *pri)
89 {
90     (void)pri;
91     if (queue == NULL || element == NULL) {
92         return EC_INVALID;
93     }
94     if (LFQUE_IsEmpty(queue)) {
95         return EC_FAILURE;
96     }
97 
98     uint32 copyLen = (queue->totalSize - queue->read < queue->itemSize) ?
99                   (queue->totalSize - queue->read) : queue->itemSize;
100     if (memcpy_s(element, copyLen, &queue->buffer[queue->read], copyLen) != EOK) {
101         return EC_FAILURE;
102     }
103 
104     element += copyLen;
105     copyLen = queue->itemSize - copyLen;
106     if (copyLen > 0) {
107         if (memcpy_s(element, copyLen, queue->buffer, copyLen) != EOK) {
108             return EC_FAILURE;
109         }
110     }
111 
112     uint32 read = queue->read + queue->itemSize;
113     if (read >= queue->totalSize) {
114         read = read - queue->totalSize;
115     }
116     queue->read = read;
117     return EC_SUCCESS;
118 }