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