leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Committer:
leothedragon
Date:
Tue May 04 08:55:12 2021 +0000
Revision:
0:8f0bb79ddd48
nmn

Who changed what in which revision?

UserRevisionLine numberNew contents of line
leothedragon 0:8f0bb79ddd48 1 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 2 // Copyright 2015-2017 ARM Ltd.
leothedragon 0:8f0bb79ddd48 3 //
leothedragon 0:8f0bb79ddd48 4 // SPDX-License-Identifier: Apache-2.0
leothedragon 0:8f0bb79ddd48 5 //
leothedragon 0:8f0bb79ddd48 6 // Licensed under the Apache License, Version 2.0 (the "License");
leothedragon 0:8f0bb79ddd48 7 // you may not use this file except in compliance with the License.
leothedragon 0:8f0bb79ddd48 8 // You may obtain a copy of the License at
leothedragon 0:8f0bb79ddd48 9 //
leothedragon 0:8f0bb79ddd48 10 // http://www.apache.org/licenses/LICENSE-2.0
leothedragon 0:8f0bb79ddd48 11 //
leothedragon 0:8f0bb79ddd48 12 // Unless required by applicable law or agreed to in writing, software
leothedragon 0:8f0bb79ddd48 13 // distributed under the License is distributed on an "AS IS" BASIS,
leothedragon 0:8f0bb79ddd48 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
leothedragon 0:8f0bb79ddd48 15 // See the License for the specific language governing permissions and
leothedragon 0:8f0bb79ddd48 16 // limitations under the License.
leothedragon 0:8f0bb79ddd48 17 // ----------------------------------------------------------------------------
leothedragon 0:8f0bb79ddd48 18
leothedragon 0:8f0bb79ddd48 19 #include "atomic-queue/atomic-queue.h"
leothedragon 0:8f0bb79ddd48 20 #include "atomic.h"
leothedragon 0:8f0bb79ddd48 21
leothedragon 0:8f0bb79ddd48 22 #include <stddef.h>
leothedragon 0:8f0bb79ddd48 23 #include <stdint.h>
leothedragon 0:8f0bb79ddd48 24 #include <stdio.h>
leothedragon 0:8f0bb79ddd48 25
leothedragon 0:8f0bb79ddd48 26 #define CORE_UTIL_ASSERT_MSG(test, msg)
leothedragon 0:8f0bb79ddd48 27
leothedragon 0:8f0bb79ddd48 28
leothedragon 0:8f0bb79ddd48 29 int aq_element_take(struct atomic_queue_element *e, void *ctx)
leothedragon 0:8f0bb79ddd48 30 {
leothedragon 0:8f0bb79ddd48 31 if (!e) { return ATOMIC_QUEUE_NULL_ELEMENT;}
leothedragon 0:8f0bb79ddd48 32 if (!ctx) { return ATOMIC_QUEUE_INVALID_CONTEXT;}
leothedragon 0:8f0bb79ddd48 33 // Duplicate element check using lock
leothedragon 0:8f0bb79ddd48 34 uintptr_t lock; // This is initialized in the do/while loop.
leothedragon 0:8f0bb79ddd48 35 // Check/obtain a lock on the element.
leothedragon 0:8f0bb79ddd48 36 do {
leothedragon 0:8f0bb79ddd48 37 lock = e->lock;
leothedragon 0:8f0bb79ddd48 38 if (lock) {
leothedragon 0:8f0bb79ddd48 39 return ATOMIC_QUEUE_DUPLICATE_ELEMENT;
leothedragon 0:8f0bb79ddd48 40 }
leothedragon 0:8f0bb79ddd48 41 } while (!aq_atomic_cas_uintptr(&e->lock, lock, (uintptr_t)ctx));
leothedragon 0:8f0bb79ddd48 42 return ATOMIC_QUEUE_SUCCESS;
leothedragon 0:8f0bb79ddd48 43 }
leothedragon 0:8f0bb79ddd48 44
leothedragon 0:8f0bb79ddd48 45 int aq_element_release(struct atomic_queue_element *e, void **ctx)
leothedragon 0:8f0bb79ddd48 46 {
leothedragon 0:8f0bb79ddd48 47 if (!e) { return ATOMIC_QUEUE_NULL_ELEMENT;}
leothedragon 0:8f0bb79ddd48 48 if (!ctx) { return ATOMIC_QUEUE_INVALID_CONTEXT;}
leothedragon 0:8f0bb79ddd48 49 *ctx = (void *) e->lock;
leothedragon 0:8f0bb79ddd48 50 e->lock = 0;
leothedragon 0:8f0bb79ddd48 51 return ATOMIC_QUEUE_SUCCESS;
leothedragon 0:8f0bb79ddd48 52 }
leothedragon 0:8f0bb79ddd48 53
leothedragon 0:8f0bb79ddd48 54 int aq_push_tail(struct atomic_queue *q, struct atomic_queue_element *e)
leothedragon 0:8f0bb79ddd48 55 {
leothedragon 0:8f0bb79ddd48 56 CORE_UTIL_ASSERT_MSG(q != NULL, "null queue used");
leothedragon 0:8f0bb79ddd48 57 if (!e) { return ATOMIC_QUEUE_NULL_ELEMENT;}
leothedragon 0:8f0bb79ddd48 58 if (q == NULL) {
leothedragon 0:8f0bb79ddd48 59 return ATOMIC_QUEUE_NULL_QUEUE;
leothedragon 0:8f0bb79ddd48 60 }
leothedragon 0:8f0bb79ddd48 61
leothedragon 0:8f0bb79ddd48 62 do {
leothedragon 0:8f0bb79ddd48 63 e->next = q->tail;
leothedragon 0:8f0bb79ddd48 64 } while (!aq_atomic_cas_uintptr((uintptr_t *)&q->tail, (uintptr_t)e->next, (uintptr_t)e));
leothedragon 0:8f0bb79ddd48 65
leothedragon 0:8f0bb79ddd48 66 return ATOMIC_QUEUE_SUCCESS;
leothedragon 0:8f0bb79ddd48 67 }
leothedragon 0:8f0bb79ddd48 68
leothedragon 0:8f0bb79ddd48 69 struct atomic_queue_element *aq_pop_head(struct atomic_queue *q)
leothedragon 0:8f0bb79ddd48 70 {
leothedragon 0:8f0bb79ddd48 71 CORE_UTIL_ASSERT_MSG(q != NULL, "null queue used");
leothedragon 0:8f0bb79ddd48 72 if (q == NULL) {
leothedragon 0:8f0bb79ddd48 73 return NULL;
leothedragon 0:8f0bb79ddd48 74 }
leothedragon 0:8f0bb79ddd48 75 struct atomic_queue_element *current;
leothedragon 0:8f0bb79ddd48 76 int fail = AQ_ATOMIC_CAS_DEREF_VALUE;
leothedragon 0:8f0bb79ddd48 77 while (fail != AQ_ATOMIC_CAS_DEREF_SUCCESS) {
leothedragon 0:8f0bb79ddd48 78 // Set the element reference pointer to the tail pointer
leothedragon 0:8f0bb79ddd48 79 struct atomic_queue_element *volatile *px = &q->tail;
leothedragon 0:8f0bb79ddd48 80 if (*px == NULL) {
leothedragon 0:8f0bb79ddd48 81 return NULL;
leothedragon 0:8f0bb79ddd48 82 }
leothedragon 0:8f0bb79ddd48 83 fail = AQ_ATOMIC_CAS_DEREF_VALUE;
leothedragon 0:8f0bb79ddd48 84 while (fail == AQ_ATOMIC_CAS_DEREF_VALUE) {
leothedragon 0:8f0bb79ddd48 85 fail = aq_atomic_cas_deref_uintptr((uintptr_t *volatile *)px,
leothedragon 0:8f0bb79ddd48 86 (uintptr_t **)&current,
leothedragon 0:8f0bb79ddd48 87 (uintptr_t) NULL,
leothedragon 0:8f0bb79ddd48 88 NULL,
leothedragon 0:8f0bb79ddd48 89 offsetof(struct atomic_queue_element, next));
leothedragon 0:8f0bb79ddd48 90 if (fail == AQ_ATOMIC_CAS_DEREF_VALUE) {
leothedragon 0:8f0bb79ddd48 91 // Detect a loop to the tail of the queue
leothedragon 0:8f0bb79ddd48 92 if (current->next == q->tail) {
leothedragon 0:8f0bb79ddd48 93 return NULL;
leothedragon 0:8f0bb79ddd48 94 }
leothedragon 0:8f0bb79ddd48 95 px = &current->next;
leothedragon 0:8f0bb79ddd48 96 }
leothedragon 0:8f0bb79ddd48 97 }
leothedragon 0:8f0bb79ddd48 98 }
leothedragon 0:8f0bb79ddd48 99
leothedragon 0:8f0bb79ddd48 100 return current;
leothedragon 0:8f0bb79ddd48 101 }
leothedragon 0:8f0bb79ddd48 102
leothedragon 0:8f0bb79ddd48 103
leothedragon 0:8f0bb79ddd48 104 int aq_empty(struct atomic_queue *q)
leothedragon 0:8f0bb79ddd48 105 {
leothedragon 0:8f0bb79ddd48 106 return q->tail == NULL;
leothedragon 0:8f0bb79ddd48 107 }
leothedragon 0:8f0bb79ddd48 108
leothedragon 0:8f0bb79ddd48 109 unsigned aq_count(struct atomic_queue *q)
leothedragon 0:8f0bb79ddd48 110 {
leothedragon 0:8f0bb79ddd48 111 unsigned x;
leothedragon 0:8f0bb79ddd48 112 struct atomic_queue_element *volatile e;
leothedragon 0:8f0bb79ddd48 113 if (aq_empty(q)) {
leothedragon 0:8f0bb79ddd48 114 return 0;
leothedragon 0:8f0bb79ddd48 115 }
leothedragon 0:8f0bb79ddd48 116 e = q->tail;
leothedragon 0:8f0bb79ddd48 117 for (x = 1; e->next != NULL; x++, e = e->next) {
leothedragon 0:8f0bb79ddd48 118 if (e->next == q->tail) {
leothedragon 0:8f0bb79ddd48 119 return (unsigned) - 1;
leothedragon 0:8f0bb79ddd48 120 }
leothedragon 0:8f0bb79ddd48 121 }
leothedragon 0:8f0bb79ddd48 122 return x;
leothedragon 0:8f0bb79ddd48 123 }
leothedragon 0:8f0bb79ddd48 124
leothedragon 0:8f0bb79ddd48 125 void aq_initialize_element(struct atomic_queue_element *e)
leothedragon 0:8f0bb79ddd48 126 {
leothedragon 0:8f0bb79ddd48 127 if (!e) { return;}
leothedragon 0:8f0bb79ddd48 128 e->lock = 0;
leothedragon 0:8f0bb79ddd48 129 e->next = NULL;
leothedragon 0:8f0bb79ddd48 130 }