/* * Copyright (C) Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * See the COPYRIGHT file distributed with this work for additional * information regarding copyright ownership. */ /* * This is a generic implementation of a two-lock concurrent queue. * There are built-in mutex locks for the head and tail of the queue, * allowing elements to be safely added and removed at the same time. * * NULL is "end of list" * -1 is "not linked" */ #ifndef ISC_QUEUE_H #define ISC_QUEUE_H 1 #include <isc/assertions.h> #include <isc/boolean.h> #include <isc/mutex.h> #ifdef ISC_QUEUE_CHECKINIT #define ISC_QLINK_INSIST(x) ISC_INSIST(x) #else #define ISC_QLINK_INSIST(x) (void)0 #endif #define ISC_QLINK(type) struct { type *prev, *next; } #define ISC_QLINK_INIT(elt, link) \ do { \ (elt)->link.next = (elt)->link.prev = (void *)(-1); \ } while(0) #define ISC_QLINK_LINKED(elt, link) ((void*)(elt)->link.next != (void*)(-1)) #define ISC_QUEUE(type) struct { \ type *head, *tail; \ isc_mutex_t headlock, taillock; \ } #define ISC_QUEUE_INIT(queue, link) \ do { \ (void) isc_mutex_init(&(queue).taillock); \ (void) isc_mutex_init(&(queue).headlock); \ (queue).tail = (queue).head = NULL; \ } while (0) #define ISC_QUEUE_EMPTY(queue) ISC_TF((queue).head == NULL) #define ISC_QUEUE_DESTROY(queue) \ do { \ ISC_QLINK_INSIST(ISC_QUEUE_EMPTY(queue)); \ (void) isc_mutex_destroy(&(queue).taillock); \ (void) isc_mutex_destroy(&(queue).headlock); \ } while (0) /* * queues are meant to separate the locks at either end. For best effect, that * means keeping the ends separate - i.e. non-empty queues work best. * * a push to an empty queue has to take the pop lock to update * the pop side of the queue. * Popping the last entry has to take the push lock to update * the push side of the queue. * * The order is (pop, push), because a pop is presumably in the * latency path and a push is when we're done. * * We do an MT hot test in push to see if we need both locks, so we can * acquire them in order. Hopefully that makes the case where we get * the push lock and find we need the pop lock (and have to release it) rare. * * > 1 entry - no collision, push works on one end, pop on the other * 0 entry - headlock race * pop wins - return(NULL), push adds new as both head/tail * push wins - updates head/tail, becomes 1 entry case. * 1 entry - taillock race * pop wins - return(pop) sets head/tail NULL, becomes 0 entry case * push wins - updates {head,tail}->link.next, pop updates head * with new ->link.next and doesn't update tail * */ #define ISC_QUEUE_PUSH(queue, elt, link) \ do { \ isc_boolean_t headlocked = ISC_FALSE; \ ISC_QLINK_INSIST(!ISC_QLINK_LINKED(elt, link)); \ if ((queue).head == NULL) { \ LOCK(&(queue).headlock); \ headlocked = ISC_TRUE; \ } \ LOCK(&(queue).taillock); \ if ((queue).tail == NULL && !headlocked) { \ UNLOCK(&(queue).taillock); \ LOCK(&(queue).headlock); \ LOCK(&(queue).taillock); \ headlocked = ISC_TRUE; \ } \ (elt)->link.prev = (queue).tail; \ (elt)->link.next = NULL; \ if ((queue).tail != NULL) \ (queue).tail->link.next = (elt); \ (queue).tail = (elt); \ UNLOCK(&(queue).taillock); \ if (headlocked) { \ if ((queue).head == NULL) \ (queue).head = (elt); \ UNLOCK(&(queue).headlock); \ } \ } while (0) #define ISC_QUEUE_POP(queue, link, ret) \ do { \ LOCK(&(queue).headlock); \ ret = (queue).head; \ while (ret != NULL) { \ if (ret->link.next == NULL) { \ LOCK(&(queue).taillock); \ if (ret->link.next == NULL) { \ (queue).head = (queue).tail = NULL; \ UNLOCK(&(queue).taillock); \ break; \ }\ UNLOCK(&(queue).taillock); \ } \ (queue).head = ret->link.next; \ (queue).head->link.prev = NULL; \ break; \ } \ UNLOCK(&(queue).headlock); \ if (ret != NULL) \ (ret)->link.next = (ret)->link.prev = (void *)(-1); \ } while(0) #define ISC_QUEUE_UNLINK(queue, elt, link) \ do { \ ISC_QLINK_INSIST(ISC_QLINK_LINKED(elt, link)); \ LOCK(&(queue).headlock); \ LOCK(&(queue).taillock); \ if ((elt)->link.prev == NULL) \ (queue).head = (elt)->link.next; \ else \ (elt)->link.prev->link.next = (elt)->link.next; \ if ((elt)->link.next == NULL) \ (queue).tail = (elt)->link.prev; \ else \ (elt)->link.next->link.prev = (elt)->link.prev; \ UNLOCK(&(queue).taillock); \ UNLOCK(&(queue).headlock); \ (elt)->link.next = (elt)->link.prev = (void *)(-1); \ } while(0) #endif /* ISC_QUEUE_H */
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
aes.h | File | 1.05 KB | 0644 |
|
app.h | File | 10.23 KB | 0644 |
|
assertions.h | File | 2.78 KB | 0644 |
|
atomic.h | File | 4.15 KB | 0644 |
|
backtrace.h | File | 3.8 KB | 0644 |
|
base32.h | File | 3.94 KB | 0644 |
|
base64.h | File | 2.39 KB | 0644 |
|
bind9.h | File | 849 B | 0644 |
|
boolean.h | File | 746 B | 0644 |
|
buffer.h | File | 25.69 KB | 0644 |
|
bufferlist.h | File | 1.42 KB | 0644 |
|
commandline.h | File | 1.69 KB | 0644 |
|
condition.h | File | 1.44 KB | 0644 |
|
counter.h | File | 1.88 KB | 0644 |
|
crc64.h | File | 986 B | 0644 |
|
deprecated.h | File | 622 B | 0644 |
|
dir.h | File | 1.96 KB | 0644 |
|
entropy.h | File | 8.76 KB | 0644 |
|
errno.h | File | 658 B | 0644 |
|
errno2result.h | File | 893 B | 0644 |
|
error.h | File | 1.4 KB | 0644 |
|
event.h | File | 2.98 KB | 0644 |
|
eventclass.h | File | 1.35 KB | 0644 |
|
file.h | File | 11.43 KB | 0644 |
|
formatcheck.h | File | 892 B | 0644 |
|
fsaccess.h | File | 7.25 KB | 0644 |
|
hash.h | File | 7.52 KB | 0644 |
|
heap.h | File | 5.14 KB | 0644 |
|
hex.h | File | 2.33 KB | 0644 |
|
hmacmd5.h | File | 1.75 KB | 0644 |
|
hmacsha.h | File | 4.44 KB | 0644 |
|
ht.h | File | 4.29 KB | 0644 |
|
httpd.h | File | 2.26 KB | 0644 |
|
int.h | File | 1.37 KB | 0644 |
|
interfaceiter.h | File | 3.03 KB | 0644 |
|
iterated_hash.h | File | 1.02 KB | 0644 |
|
json.h | File | 1.42 KB | 0644 |
|
keyboard.h | File | 976 B | 0644 |
|
lang.h | File | 636 B | 0644 |
|
lex.h | File | 9.42 KB | 0644 |
|
lfsr.h | File | 2.88 KB | 0644 |
|
lib.h | File | 1.04 KB | 0644 |
|
likely.h | File | 718 B | 0644 |
|
list.h | File | 5.65 KB | 0644 |
|
log.h | File | 28.06 KB | 0644 |
|
magic.h | File | 993 B | 0644 |
|
md5.h | File | 2.34 KB | 0644 |
|
mem.h | File | 20.63 KB | 0644 |
|
meminfo.h | File | 690 B | 0644 |
|
msgcat.h | File | 2.66 KB | 0644 |
|
msgs.h | File | 8.22 KB | 0644 |
|
mutex.h | File | 3.44 KB | 0644 |
|
mutexblock.h | File | 1.34 KB | 0644 |
|
net.h | File | 10.32 KB | 0644 |
|
netaddr.h | File | 4.56 KB | 0644 |
|
netdb.h | File | 862 B | 0644 |
|
netscope.h | File | 947 B | 0644 |
|
offset.h | File | 699 B | 0644 |
|
once.h | File | 981 B | 0644 |
|
ondestroy.h | File | 2.79 KB | 0644 |
|
os.h | File | 670 B | 0644 |
|
parseint.h | File | 1.49 KB | 0644 |
|
platform.h | File | 9.31 KB | 0644 |
|
pool.h | File | 3.42 KB | 0644 |
|
portset.h | File | 3.21 KB | 0644 |
|
print.h | File | 2.49 KB | 0644 |
|
queue.h | File | 4.66 KB | 0644 |
|
quota.h | File | 2.29 KB | 0644 |
|
radix.h | File | 6.37 KB | 0644 |
|
random.h | File | 2.99 KB | 0644 |
|
ratelimiter.h | File | 3.38 KB | 0644 |
|
refcount.h | File | 7.89 KB | 0644 |
|
regex.h | File | 766 B | 0644 |
|
region.h | File | 1.99 KB | 0644 |
|
resource.h | File | 2.8 KB | 0644 |
|
result.h | File | 4.62 KB | 0644 |
|
resultclass.h | File | 1.56 KB | 0644 |
|
rwlock.h | File | 3.6 KB | 0644 |
|
safe.h | File | 1.21 KB | 0644 |
|
serial.h | File | 1.4 KB | 0644 |
|
sha1.h | File | 1.52 KB | 0644 |
|
sha2.h | File | 5.65 KB | 0644 |
|
sockaddr.h | File | 6 KB | 0644 |
|
socket.h | File | 35.81 KB | 0644 |
|
stat.h | File | 805 B | 0644 |
|
stats.h | File | 3.02 KB | 0644 |
|
stdio.h | File | 1.74 KB | 0644 |
|
stdlib.h | File | 703 B | 0644 |
|
stdtime.h | File | 1.3 KB | 0644 |
|
strerror.h | File | 776 B | 0644 |
|
string.h | File | 5.94 KB | 0644 |
|
symtab.h | File | 4.21 KB | 0644 |
|
syslog.h | File | 843 B | 0644 |
|
task.h | File | 21.08 KB | 0644 |
|
taskpool.h | File | 3.61 KB | 0644 |
|
thread.h | File | 1.47 KB | 0644 |
|
time.h | File | 8.66 KB | 0644 |
|
timer.h | File | 10.54 KB | 0644 |
|
tm.h | File | 894 B | 0644 |
|
types.h | File | 5.54 KB | 0644 |
|
util.h | File | 7.49 KB | 0644 |
|
version.h | File | 688 B | 0644 |
|
xml.h | File | 1.07 KB | 0644 |
|