19c6d7c21Sopenharmony_ci/*
29c6d7c21Sopenharmony_ci * Copyright (c) 2020 Huawei Device Co., Ltd.
39c6d7c21Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
49c6d7c21Sopenharmony_ci * you may not use this file except in compliance with the License.
59c6d7c21Sopenharmony_ci * You may obtain a copy of the License at
69c6d7c21Sopenharmony_ci *
79c6d7c21Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
89c6d7c21Sopenharmony_ci *
99c6d7c21Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
109c6d7c21Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
119c6d7c21Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129c6d7c21Sopenharmony_ci * See the License for the specific language governing permissions and
139c6d7c21Sopenharmony_ci * limitations under the License.
149c6d7c21Sopenharmony_ci */
159c6d7c21Sopenharmony_ci#include "lock_free_queue.h"
169c6d7c21Sopenharmony_ci#include <ohos_errno.h>
179c6d7c21Sopenharmony_ci#include <securec.h>
189c6d7c21Sopenharmony_ci#include <memory_adapter.h>
199c6d7c21Sopenharmony_ci
209c6d7c21Sopenharmony_ciLockFreeQueue *LFQUE_Create(int size, int count)
219c6d7c21Sopenharmony_ci{
229c6d7c21Sopenharmony_ci    if (size <= 0 || count <= 0) {
239c6d7c21Sopenharmony_ci        return NULL;
249c6d7c21Sopenharmony_ci    }
259c6d7c21Sopenharmony_ci
269c6d7c21Sopenharmony_ci    int total = size * count + 1;
279c6d7c21Sopenharmony_ci    if (total <= 0) {
289c6d7c21Sopenharmony_ci        return NULL;
299c6d7c21Sopenharmony_ci    }
309c6d7c21Sopenharmony_ci
319c6d7c21Sopenharmony_ci    register LockFreeQueue *queue = (LockFreeQueue *)SAMGR_Malloc(sizeof(LockFreeQueue) + total);
329c6d7c21Sopenharmony_ci    if (queue == NULL) {
339c6d7c21Sopenharmony_ci        return NULL;
349c6d7c21Sopenharmony_ci    }
359c6d7c21Sopenharmony_ci    queue->write = 0;
369c6d7c21Sopenharmony_ci    queue->read = 0;
379c6d7c21Sopenharmony_ci    queue->itemSize = size;
389c6d7c21Sopenharmony_ci    queue->totalSize = total;
399c6d7c21Sopenharmony_ci    return queue;
409c6d7c21Sopenharmony_ci}
419c6d7c21Sopenharmony_ci
429c6d7c21Sopenharmony_ciBOOL LFQUE_IsFull(LockFreeQueue *queue)
439c6d7c21Sopenharmony_ci{
449c6d7c21Sopenharmony_ci    uint32 nextWrite = queue->write + 1;
459c6d7c21Sopenharmony_ci    if (nextWrite >= queue->totalSize) {
469c6d7c21Sopenharmony_ci        nextWrite = 0;
479c6d7c21Sopenharmony_ci    }
489c6d7c21Sopenharmony_ci    return (nextWrite == queue->read);
499c6d7c21Sopenharmony_ci}
509c6d7c21Sopenharmony_ci
519c6d7c21Sopenharmony_ciBOOL LFQUE_IsEmpty(LockFreeQueue *queue)
529c6d7c21Sopenharmony_ci{
539c6d7c21Sopenharmony_ci    return (queue->write == queue->read);
549c6d7c21Sopenharmony_ci}
559c6d7c21Sopenharmony_ci
569c6d7c21Sopenharmony_ciint LFQUE_Push(LockFreeQueue *queue, const void *element, uint8 pri)
579c6d7c21Sopenharmony_ci{
589c6d7c21Sopenharmony_ci    (void)pri;
599c6d7c21Sopenharmony_ci    if (queue == NULL || element == NULL) {
609c6d7c21Sopenharmony_ci        return EC_INVALID;
619c6d7c21Sopenharmony_ci    }
629c6d7c21Sopenharmony_ci
639c6d7c21Sopenharmony_ci    if (LFQUE_IsFull(queue)) {
649c6d7c21Sopenharmony_ci        return EC_BUSBUSY;
659c6d7c21Sopenharmony_ci    }
669c6d7c21Sopenharmony_ci    uint32 copyLen = (queue->totalSize - queue->write < queue->itemSize) ?
679c6d7c21Sopenharmony_ci                  (queue->totalSize - queue->write) : queue->itemSize;
689c6d7c21Sopenharmony_ci    if (memcpy_s(&queue->buffer[queue->write], copyLen, element, copyLen) != EOK) {
699c6d7c21Sopenharmony_ci        return EC_INVALID;
709c6d7c21Sopenharmony_ci    }
719c6d7c21Sopenharmony_ci
729c6d7c21Sopenharmony_ci    element += copyLen;
739c6d7c21Sopenharmony_ci    copyLen = queue->itemSize - copyLen;
749c6d7c21Sopenharmony_ci    if (copyLen > 0) {
759c6d7c21Sopenharmony_ci        if (memcpy_s(queue->buffer, copyLen, element, copyLen) != EOK) {
769c6d7c21Sopenharmony_ci            return EC_INVALID;
779c6d7c21Sopenharmony_ci        }
789c6d7c21Sopenharmony_ci    }
799c6d7c21Sopenharmony_ci
809c6d7c21Sopenharmony_ci    uint32 write = queue->write + queue->itemSize;
819c6d7c21Sopenharmony_ci    if (write >= queue->totalSize) {
829c6d7c21Sopenharmony_ci        write = write - queue->totalSize;
839c6d7c21Sopenharmony_ci    }
849c6d7c21Sopenharmony_ci    queue->write = write;
859c6d7c21Sopenharmony_ci    return EC_SUCCESS;
869c6d7c21Sopenharmony_ci}
879c6d7c21Sopenharmony_ci
889c6d7c21Sopenharmony_ciint LFQUE_Pop(LockFreeQueue *queue, void *element, uint8 *pri)
899c6d7c21Sopenharmony_ci{
909c6d7c21Sopenharmony_ci    (void)pri;
919c6d7c21Sopenharmony_ci    if (queue == NULL || element == NULL) {
929c6d7c21Sopenharmony_ci        return EC_INVALID;
939c6d7c21Sopenharmony_ci    }
949c6d7c21Sopenharmony_ci    if (LFQUE_IsEmpty(queue)) {
959c6d7c21Sopenharmony_ci        return EC_FAILURE;
969c6d7c21Sopenharmony_ci    }
979c6d7c21Sopenharmony_ci
989c6d7c21Sopenharmony_ci    uint32 copyLen = (queue->totalSize - queue->read < queue->itemSize) ?
999c6d7c21Sopenharmony_ci                  (queue->totalSize - queue->read) : queue->itemSize;
1009c6d7c21Sopenharmony_ci    if (memcpy_s(element, copyLen, &queue->buffer[queue->read], copyLen) != EOK) {
1019c6d7c21Sopenharmony_ci        return EC_FAILURE;
1029c6d7c21Sopenharmony_ci    }
1039c6d7c21Sopenharmony_ci
1049c6d7c21Sopenharmony_ci    element += copyLen;
1059c6d7c21Sopenharmony_ci    copyLen = queue->itemSize - copyLen;
1069c6d7c21Sopenharmony_ci    if (copyLen > 0) {
1079c6d7c21Sopenharmony_ci        if (memcpy_s(element, copyLen, queue->buffer, copyLen) != EOK) {
1089c6d7c21Sopenharmony_ci            return EC_FAILURE;
1099c6d7c21Sopenharmony_ci        }
1109c6d7c21Sopenharmony_ci    }
1119c6d7c21Sopenharmony_ci
1129c6d7c21Sopenharmony_ci    uint32 read = queue->read + queue->itemSize;
1139c6d7c21Sopenharmony_ci    if (read >= queue->totalSize) {
1149c6d7c21Sopenharmony_ci        read = read - queue->totalSize;
1159c6d7c21Sopenharmony_ci    }
1169c6d7c21Sopenharmony_ci    queue->read = read;
1179c6d7c21Sopenharmony_ci    return EC_SUCCESS;
1189c6d7c21Sopenharmony_ci}