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
26struct 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
34isc_astack_t *
35isc_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
48bool
49isc_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
63void *
64isc_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
76void
77isc_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