1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 #include <inttypes.h>
13 #include <string.h>
14
15 #include <isc/astack.h>
16 #include <isc/atomic.h>
17 #include <isc/mem.h>
18 #include <isc/mutex.h>
19 #include <isc/types.h>
20 #include <isc/util.h>
21
22 struct isc_astack {
23 isc_mem_t *mctx;
24 size_t size;
25 size_t pos;
26 isc_mutex_t lock;
27 uintptr_t nodes[];
28 };
29
30 isc_astack_t *
isc_astack_new(isc_mem_t * mctx,size_t size)31 isc_astack_new(isc_mem_t *mctx, size_t size) {
32 isc_astack_t *stack = isc_mem_get(
33 mctx, sizeof(isc_astack_t) + size * sizeof(uintptr_t));
34
35 *stack = (isc_astack_t){
36 .size = size,
37 };
38 isc_mem_attach(mctx, &stack->mctx);
39 memset(stack->nodes, 0, size * sizeof(uintptr_t));
40 isc_mutex_init(&stack->lock);
41 return (stack);
42 }
43
44 bool
isc_astack_trypush(isc_astack_t * stack,void * obj)45 isc_astack_trypush(isc_astack_t *stack, void *obj) {
46 if (!isc_mutex_trylock(&stack->lock)) {
47 if (stack->pos >= stack->size) {
48 UNLOCK(&stack->lock);
49 return (false);
50 }
51 stack->nodes[stack->pos++] = (uintptr_t)obj;
52 UNLOCK(&stack->lock);
53 return (true);
54 } else {
55 return (false);
56 }
57 }
58
59 void *
isc_astack_pop(isc_astack_t * stack)60 isc_astack_pop(isc_astack_t *stack) {
61 LOCK(&stack->lock);
62 uintptr_t rv;
63 if (stack->pos == 0) {
64 rv = 0;
65 } else {
66 rv = stack->nodes[--stack->pos];
67 }
68 UNLOCK(&stack->lock);
69 return ((void *)rv);
70 }
71
72 void
isc_astack_destroy(isc_astack_t * stack)73 isc_astack_destroy(isc_astack_t *stack) {
74 LOCK(&stack->lock);
75 REQUIRE(stack->pos == 0);
76 UNLOCK(&stack->lock);
77
78 isc_mutex_destroy(&stack->lock);
79
80 isc_mem_putanddetach(&stack->mctx, stack,
81 sizeof(struct isc_astack) +
82 stack->size * sizeof(uintptr_t));
83 }
84