1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include "aircrack-ng/defs.h"
#include "aircrack-ng/adt/circular_buffer.h"
#include "aircrack-ng/adt/circular_queue.h"
// The definition of our circular queue is hidden from the API user.
struct circular_queue_t
{
cbuf_handle_t cbuf; /// Circular buffer.
pthread_mutex_t lock; /// Lock protecting whole structure.
char padding1[CACHELINE_SIZE - sizeof(pthread_mutex_t)];
pthread_cond_t full_cv; /// Signals upon no longer full.
char padding2[CACHELINE_SIZE - sizeof(pthread_cond_t)];
pthread_cond_t empty_cv; /// Signals upon no longer empty.
};
API_EXPORT cqueue_handle_t circular_queue_init(uint8_t * buffer,
size_t bufferSize,
size_t elementSize)
{
REQUIRE(buffer && bufferSize && elementSize);
REQUIRE(bufferSize % elementSize == 0);
cqueue_handle_t cq = calloc(1, sizeof(circular_queue_t));
ALLEGE(cq);
cq->cbuf = circular_buffer_init(buffer, bufferSize, elementSize);
ALLEGE(cq->cbuf);
ALLEGE(pthread_mutex_init(&(cq->lock), NULL) == 0);
ALLEGE(pthread_cond_init(&(cq->empty_cv), NULL) == 0);
ALLEGE(pthread_cond_init(&(cq->full_cv), NULL) == 0);
return cq;
}
API_EXPORT void circular_queue_free(cqueue_handle_t cq)
{
REQUIRE(cq);
circular_buffer_free(cq->cbuf);
cq->cbuf = NULL;
ALLEGE(pthread_cond_destroy(&(cq->empty_cv)) == 0);
ALLEGE(pthread_cond_destroy(&(cq->full_cv)) == 0);
ALLEGE(pthread_mutex_destroy(&(cq->lock)) == 0);
free(cq);
}
API_EXPORT void circular_queue_reset(cqueue_handle_t cq)
{
REQUIRE(cq);
ALLEGE(pthread_mutex_lock(&(cq->lock)) == 0);
circular_buffer_reset(cq->cbuf);
ALLEGE(pthread_mutex_unlock(&(cq->lock)) == 0);
}
static inline void
do_push(cqueue_handle_t cq, void const * const data, size_t size)
{
REQUIRE(cq && data && size > 0);
REQUIRE(!circular_buffer_is_full(cq->cbuf));
circular_buffer_put(cq->cbuf, data, size);
ALLEGE(pthread_cond_signal(&(cq->empty_cv)) == 0);
ALLEGE(pthread_mutex_unlock(&(cq->lock)) == 0);
}
API_EXPORT void
circular_queue_push(cqueue_handle_t cq, void const * const data, size_t size)
{
REQUIRE(cq && data && size > 0);
ALLEGE(pthread_mutex_lock(&(cq->lock)) == 0);
while (circular_buffer_is_full(cq->cbuf))
{
ALLEGE(pthread_cond_wait(&(cq->full_cv), &(cq->lock)) == 0);
}
do_push(cq, data, size);
}
API_EXPORT int circular_queue_try_push(cqueue_handle_t cq,
void const * const data,
size_t size)
{
REQUIRE(cq && data && size > 0);
ALLEGE(pthread_mutex_lock(&(cq->lock)) == 0);
if (circular_buffer_is_full(cq->cbuf))
{
ALLEGE(pthread_mutex_unlock(&(cq->lock)) == 0);
return -1;
}
do_push(cq, data, size);
return 0;
}
API_EXPORT void
circular_queue_pop(cqueue_handle_t cq, void * const * data, size_t size)
{
REQUIRE(cq && data && size > 0);
ALLEGE(pthread_mutex_lock(&(cq->lock)) == 0);
while (circular_buffer_is_empty(cq->cbuf))
{
ALLEGE(pthread_cond_wait(&(cq->empty_cv), &(cq->lock)) == 0);
}
ALLEGE(!circular_buffer_is_empty(cq->cbuf));
circular_buffer_get(cq->cbuf, data, size);
ALLEGE(pthread_cond_signal(&(cq->full_cv)) == 0);
ALLEGE(pthread_mutex_unlock(&(cq->lock)) == 0);
}
API_EXPORT bool circular_queue_is_empty(cqueue_handle_t cq)
{
REQUIRE(cq);
bool rc;
ALLEGE(pthread_mutex_lock(&(cq->lock)) == 0);
rc = circular_buffer_is_empty(cq->cbuf);
ALLEGE(pthread_mutex_unlock(&(cq->lock)) == 0);
return rc;
}
API_EXPORT bool circular_queue_is_full(cqueue_handle_t cq)
{
REQUIRE(cq);
bool rc;
ALLEGE(pthread_mutex_lock(&(cq->lock)) == 0);
rc = circular_buffer_is_full(cq->cbuf);
ALLEGE(pthread_mutex_unlock(&(cq->lock)) == 0);
return rc;
}
|