blob: 317a60b92b6b60605119c069172d7e169a092a4f (
plain)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
|
/*
* Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @file sah_queue.c
*
* @brief This file provides a FIFO Queue implementation.
*
*/
/******************************************************************************
*
* CAUTION:
*******************************************************************
*/
/* SAHARA Includes */
#include <sah_queue_manager.h>
#ifdef DIAG_DRV_QUEUE
#include <diagnostic.h>
#endif
/******************************************************************************
* Queue Functions
******************************************************************************/
/*!
*******************************************************************************
* This function constructs a new sah_Queue.
*
* @brief sah_Queue Constructor
*
* @return A pointer to a newly allocated sah_Queue.
* @return NULL if allocation of memory failed.
*/
/******************************************************************************
*
* CAUTION: This function may sleep in low-memory situations, as it uses
* kmalloc ( ..., GFP_KERNEL).
******************************************************************************/
sah_Queue *sah_Queue_Construct(void)
{
sah_Queue *q = (sah_Queue *) os_alloc_memory(sizeof(sah_Queue),
GFP_KERNEL);
if (q != NULL) {
/* Initialise the queue to an empty state. */
q->head = NULL;
q->tail = NULL;
q->count = 0;
}
#ifdef DIAG_DRV_QUEUE
else {
LOG_KDIAG("kmalloc() failed.");
}
#endif
return q;
}
/*!
*******************************************************************************
* This function destroys a sah_Queue.
*
* @brief sah_Queue Destructor
*
* @param q A pointer to a sah_Queue.
*
* @return void
*/
/******************************************************************************
*
* CAUTION: This function does not free any queue entries.
*
******************************************************************************/
void sah_Queue_Destroy(sah_Queue * q)
{
#ifdef DIAG_DRV_QUEUE
if (q == NULL) {
LOG_KDIAG("Trying to kfree() a NULL pointer.");
} else {
if (q->count != 0) {
LOG_KDIAG
("Trying to destroy a queue that is not empty.");
}
}
#endif
if (q != NULL) {
os_free_memory(q);
q = NULL;
}
}
/*!
*******************************************************************************
* This function appends a sah_Head_Desc to the tail of a sah_Queue.
*
* @brief Appends a sah_Head_Desc to a sah_Queue.
*
* @param q A pointer to a sah_Queue to append to.
* @param entry A pointer to a sah_Head_Desc to append.
*
* @pre The #desc_queue_lock must be held before calling this function.
*
* @return void
*/
/******************************************************************************
*
* CAUTION: NONE
******************************************************************************/
void sah_Queue_Append_Entry(sah_Queue * q, sah_Head_Desc * entry)
{
sah_Head_Desc *tail_entry = NULL;
if ((q == NULL) || (entry == NULL)) {
#ifdef DIAG_DRV_QUEUE
LOG_KDIAG("Null pointer input.");
#endif
return;
}
if (q->count == 0) {
/* The queue is empty */
q->head = entry;
q->tail = entry;
entry->next = NULL;
entry->prev = NULL;
} else {
/* The queue is not empty */
tail_entry = q->tail;
tail_entry->next = entry;
entry->next = NULL;
entry->prev = tail_entry;
q->tail = entry;
}
q->count++;
}
/*!
*******************************************************************************
* This function a removes a sah_Head_Desc from the head of a sah_Queue.
*
* @brief Removes a sah_Head_Desc from a the head of a sah_Queue.
*
* @param q A pointer to a sah_Queue to remove from.
*
* @pre The #desc_queue_lock must be held before calling this function.
*
* @return void
*/
/******************************************************************************
*
* CAUTION: This does not kfree() the entry.
******************************************************************************/
void sah_Queue_Remove_Entry(sah_Queue * q)
{
sah_Queue_Remove_Any_Entry(q, q->head);
}
/*!
*******************************************************************************
* This function a removes a sah_Head_Desc from anywhere in a sah_Queue.
*
* @brief Removes a sah_Head_Desc from anywhere in a sah_Queue.
*
* @param qq A pointer to a sah_Queue to remove from.
* @param entry A pointer to a sah_Head_Desc to remove.
*
* @pre The #desc_queue_lock must be held before calling this function.
*
* @return void
*/
/******************************************************************************
*
* CAUTION: This does not kfree() the entry. Does not check to see if the entry
* actually belongs to the queue.
******************************************************************************/
void sah_Queue_Remove_Any_Entry(sah_Queue * q, sah_Head_Desc * entry)
{
sah_Head_Desc *prev_entry = NULL;
sah_Head_Desc *next_entry = NULL;
if ((q == NULL) || (entry == NULL)) {
#if defined DIAG_DRV_QUEUE && defined DIAG_DURING_INTERRUPT
LOG_KDIAG("Null pointer input.");
#endif
return;
}
if (q->count == 1) {
/* If q is the only entry in the queue. */
q->tail = NULL;
q->head = NULL;
q->count = 0;
} else if (q->count > 1) {
/* There are 2 or more entries in the queue. */
#if defined DIAG_DRV_QUEUE && defined DIAG_DURING_INTERRUPT
if ((entry->next == NULL) && (entry->prev == NULL)) {
LOG_KDIAG
("Queue is not empty yet both next and prev pointers"
" are NULL");
}
#endif
if (entry->next == NULL) {
/* If this is the end of the queue */
prev_entry = entry->prev;
prev_entry->next = NULL;
q->tail = prev_entry;
} else if (entry->prev == NULL) {
/* If this is the head of the queue */
next_entry = entry->next;
next_entry->prev = NULL;
q->head = next_entry;
} else {
/* If this is somewhere in the middle of the queue */
prev_entry = entry->prev;
next_entry = entry->next;
prev_entry->next = next_entry;
next_entry->prev = prev_entry;
}
q->count--;
}
/*
* Otherwise we are removing an entry from an empty queue.
* Don't do anything in the product code
*/
#if defined DIAG_DRV_QUEUE && defined DIAG_DURING_INTERRUPT
else {
LOG_KDIAG("Trying to remove an entry from an empty queue.");
}
#endif
entry->next = NULL;
entry->prev = NULL;
}
/* End of sah_queue.c */
|