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}