File: circular_queue.c

package info (click to toggle)
aircrack-ng 1%3A1.6%2Bgit20210130.91820bc-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 19,056 kB
  • sloc: ansic: 67,045; cs: 5,392; sh: 3,773; python: 2,565; pascal: 1,074; asm: 570; makefile: 253; cpp: 46
file content (158 lines) | stat: -rw-r--r-- 3,786 bytes parent folder | download
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;
}