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