Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ExeBy/smexe_ro.../usr/include/bind9/isc
File: queue.h
/*
[0] Fix | Delete
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
[1] Fix | Delete
*
[2] Fix | Delete
* This Source Code Form is subject to the terms of the Mozilla Public
[3] Fix | Delete
* License, v. 2.0. If a copy of the MPL was not distributed with this
[4] Fix | Delete
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
[5] Fix | Delete
*
[6] Fix | Delete
* See the COPYRIGHT file distributed with this work for additional
[7] Fix | Delete
* information regarding copyright ownership.
[8] Fix | Delete
*/
[9] Fix | Delete
[10] Fix | Delete
[11] Fix | Delete
/*
[12] Fix | Delete
* This is a generic implementation of a two-lock concurrent queue.
[13] Fix | Delete
* There are built-in mutex locks for the head and tail of the queue,
[14] Fix | Delete
* allowing elements to be safely added and removed at the same time.
[15] Fix | Delete
*
[16] Fix | Delete
* NULL is "end of list"
[17] Fix | Delete
* -1 is "not linked"
[18] Fix | Delete
*/
[19] Fix | Delete
[20] Fix | Delete
#ifndef ISC_QUEUE_H
[21] Fix | Delete
#define ISC_QUEUE_H 1
[22] Fix | Delete
[23] Fix | Delete
#include <stdbool.h>
[24] Fix | Delete
[25] Fix | Delete
#include <isc/assertions.h>
[26] Fix | Delete
#include <isc/mutex.h>
[27] Fix | Delete
[28] Fix | Delete
#ifdef ISC_QUEUE_CHECKINIT
[29] Fix | Delete
#define ISC_QLINK_INSIST(x) ISC_INSIST(x)
[30] Fix | Delete
#else
[31] Fix | Delete
#define ISC_QLINK_INSIST(x) (void)0
[32] Fix | Delete
#endif
[33] Fix | Delete
[34] Fix | Delete
#define ISC_QLINK(type) struct { type *prev, *next; }
[35] Fix | Delete
[36] Fix | Delete
#define ISC_QLINK_INIT(elt, link) \
[37] Fix | Delete
do { \
[38] Fix | Delete
(elt)->link.next = (elt)->link.prev = (void *)(-1); \
[39] Fix | Delete
} while(0)
[40] Fix | Delete
[41] Fix | Delete
#define ISC_QLINK_LINKED(elt, link) ((void*)(elt)->link.next != (void*)(-1))
[42] Fix | Delete
[43] Fix | Delete
#define ISC_QUEUE(type) struct { \
[44] Fix | Delete
type *head, *tail; \
[45] Fix | Delete
isc_mutex_t headlock, taillock; \
[46] Fix | Delete
}
[47] Fix | Delete
[48] Fix | Delete
#define ISC_QUEUE_INIT(queue, link) \
[49] Fix | Delete
do { \
[50] Fix | Delete
(void) isc_mutex_init(&(queue).taillock); \
[51] Fix | Delete
(void) isc_mutex_init(&(queue).headlock); \
[52] Fix | Delete
(queue).tail = (queue).head = NULL; \
[53] Fix | Delete
} while (0)
[54] Fix | Delete
[55] Fix | Delete
#define ISC_QUEUE_EMPTY(queue) ((queue).head == NULL)
[56] Fix | Delete
[57] Fix | Delete
#define ISC_QUEUE_DESTROY(queue) \
[58] Fix | Delete
do { \
[59] Fix | Delete
ISC_QLINK_INSIST(ISC_QUEUE_EMPTY(queue)); \
[60] Fix | Delete
(void) isc_mutex_destroy(&(queue).taillock); \
[61] Fix | Delete
(void) isc_mutex_destroy(&(queue).headlock); \
[62] Fix | Delete
} while (0)
[63] Fix | Delete
[64] Fix | Delete
/*
[65] Fix | Delete
* queues are meant to separate the locks at either end. For best effect, that
[66] Fix | Delete
* means keeping the ends separate - i.e. non-empty queues work best.
[67] Fix | Delete
*
[68] Fix | Delete
* a push to an empty queue has to take the pop lock to update
[69] Fix | Delete
* the pop side of the queue.
[70] Fix | Delete
* Popping the last entry has to take the push lock to update
[71] Fix | Delete
* the push side of the queue.
[72] Fix | Delete
*
[73] Fix | Delete
* The order is (pop, push), because a pop is presumably in the
[74] Fix | Delete
* latency path and a push is when we're done.
[75] Fix | Delete
*
[76] Fix | Delete
* We do an MT hot test in push to see if we need both locks, so we can
[77] Fix | Delete
* acquire them in order. Hopefully that makes the case where we get
[78] Fix | Delete
* the push lock and find we need the pop lock (and have to release it) rare.
[79] Fix | Delete
*
[80] Fix | Delete
* > 1 entry - no collision, push works on one end, pop on the other
[81] Fix | Delete
* 0 entry - headlock race
[82] Fix | Delete
* pop wins - return(NULL), push adds new as both head/tail
[83] Fix | Delete
* push wins - updates head/tail, becomes 1 entry case.
[84] Fix | Delete
* 1 entry - taillock race
[85] Fix | Delete
* pop wins - return(pop) sets head/tail NULL, becomes 0 entry case
[86] Fix | Delete
* push wins - updates {head,tail}->link.next, pop updates head
[87] Fix | Delete
* with new ->link.next and doesn't update tail
[88] Fix | Delete
*
[89] Fix | Delete
*/
[90] Fix | Delete
#define ISC_QUEUE_PUSH(queue, elt, link) \
[91] Fix | Delete
do { \
[92] Fix | Delete
bool headlocked = false; \
[93] Fix | Delete
ISC_QLINK_INSIST(!ISC_QLINK_LINKED(elt, link)); \
[94] Fix | Delete
LOCK(&(queue).taillock); \
[95] Fix | Delete
if ((queue).tail == NULL) { \
[96] Fix | Delete
UNLOCK(&(queue).taillock); \
[97] Fix | Delete
LOCK(&(queue).headlock); \
[98] Fix | Delete
LOCK(&(queue).taillock); \
[99] Fix | Delete
headlocked = true; \
[100] Fix | Delete
} \
[101] Fix | Delete
(elt)->link.prev = (queue).tail; \
[102] Fix | Delete
(elt)->link.next = NULL; \
[103] Fix | Delete
if ((queue).tail != NULL) \
[104] Fix | Delete
(queue).tail->link.next = (elt); \
[105] Fix | Delete
(queue).tail = (elt); \
[106] Fix | Delete
UNLOCK(&(queue).taillock); \
[107] Fix | Delete
if (headlocked) { \
[108] Fix | Delete
if ((queue).head == NULL) \
[109] Fix | Delete
(queue).head = (elt); \
[110] Fix | Delete
UNLOCK(&(queue).headlock); \
[111] Fix | Delete
} \
[112] Fix | Delete
} while (0)
[113] Fix | Delete
[114] Fix | Delete
#define ISC_QUEUE_POP(queue, link, ret) \
[115] Fix | Delete
do { \
[116] Fix | Delete
LOCK(&(queue).headlock); \
[117] Fix | Delete
ret = (queue).head; \
[118] Fix | Delete
while (ret != NULL) { \
[119] Fix | Delete
if (ret->link.next == NULL) { \
[120] Fix | Delete
LOCK(&(queue).taillock); \
[121] Fix | Delete
if (ret->link.next == NULL) { \
[122] Fix | Delete
(queue).head = (queue).tail = NULL; \
[123] Fix | Delete
UNLOCK(&(queue).taillock); \
[124] Fix | Delete
break; \
[125] Fix | Delete
}\
[126] Fix | Delete
UNLOCK(&(queue).taillock); \
[127] Fix | Delete
} \
[128] Fix | Delete
(queue).head = ret->link.next; \
[129] Fix | Delete
(queue).head->link.prev = NULL; \
[130] Fix | Delete
break; \
[131] Fix | Delete
} \
[132] Fix | Delete
UNLOCK(&(queue).headlock); \
[133] Fix | Delete
if (ret != NULL) \
[134] Fix | Delete
(ret)->link.next = (ret)->link.prev = (void *)(-1); \
[135] Fix | Delete
} while(0)
[136] Fix | Delete
[137] Fix | Delete
#define ISC_QUEUE_UNLINK(queue, elt, link) \
[138] Fix | Delete
do { \
[139] Fix | Delete
ISC_QLINK_INSIST(ISC_QLINK_LINKED(elt, link)); \
[140] Fix | Delete
LOCK(&(queue).headlock); \
[141] Fix | Delete
LOCK(&(queue).taillock); \
[142] Fix | Delete
if ((elt)->link.prev == NULL) \
[143] Fix | Delete
(queue).head = (elt)->link.next; \
[144] Fix | Delete
else \
[145] Fix | Delete
(elt)->link.prev->link.next = (elt)->link.next; \
[146] Fix | Delete
if ((elt)->link.next == NULL) \
[147] Fix | Delete
(queue).tail = (elt)->link.prev; \
[148] Fix | Delete
else \
[149] Fix | Delete
(elt)->link.next->link.prev = (elt)->link.prev; \
[150] Fix | Delete
UNLOCK(&(queue).taillock); \
[151] Fix | Delete
UNLOCK(&(queue).headlock); \
[152] Fix | Delete
(elt)->link.next = (elt)->link.prev = (void *)(-1); \
[153] Fix | Delete
} while(0)
[154] Fix | Delete
[155] Fix | Delete
#define ISC_QUEUE_UNLINKIFLINKED(queue, elt, link) \
[156] Fix | Delete
do { \
[157] Fix | Delete
LOCK(&(queue).headlock); \
[158] Fix | Delete
LOCK(&(queue).taillock); \
[159] Fix | Delete
if (ISC_QLINK_LINKED(elt, link)) { \
[160] Fix | Delete
if ((elt)->link.prev == NULL) \
[161] Fix | Delete
(queue).head = (elt)->link.next; \
[162] Fix | Delete
else \
[163] Fix | Delete
(elt)->link.prev->link.next = (elt)->link.next; \
[164] Fix | Delete
if ((elt)->link.next == NULL) \
[165] Fix | Delete
(queue).tail = (elt)->link.prev; \
[166] Fix | Delete
else \
[167] Fix | Delete
(elt)->link.next->link.prev = (elt)->link.prev; \
[168] Fix | Delete
} \
[169] Fix | Delete
UNLOCK(&(queue).taillock); \
[170] Fix | Delete
UNLOCK(&(queue).headlock); \
[171] Fix | Delete
(elt)->link.next = (elt)->link.prev = (void *)(-1); \
[172] Fix | Delete
} while(0)
[173] Fix | Delete
[174] Fix | Delete
#endif /* ISC_QUEUE_H */
[175] Fix | Delete
[176] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function