18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Simple pointer stack
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * (c) 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "pstack.h"
98c2ecf20Sopenharmony_ci#include "debug.h"
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
128c2ecf20Sopenharmony_ci#include <stdlib.h>
138c2ecf20Sopenharmony_ci#include <string.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistruct pstack {
168c2ecf20Sopenharmony_ci	unsigned short	top;
178c2ecf20Sopenharmony_ci	unsigned short	max_nr_entries;
188c2ecf20Sopenharmony_ci	void		*entries[];
198c2ecf20Sopenharmony_ci};
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct pstack *pstack__new(unsigned short max_nr_entries)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	struct pstack *pstack = zalloc((sizeof(*pstack) +
248c2ecf20Sopenharmony_ci				       max_nr_entries * sizeof(void *)));
258c2ecf20Sopenharmony_ci	if (pstack != NULL)
268c2ecf20Sopenharmony_ci		pstack->max_nr_entries = max_nr_entries;
278c2ecf20Sopenharmony_ci	return pstack;
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_civoid pstack__delete(struct pstack *pstack)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	free(pstack);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cibool pstack__empty(const struct pstack *pstack)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	return pstack->top == 0;
388c2ecf20Sopenharmony_ci}
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_civoid pstack__remove(struct pstack *pstack, void *key)
418c2ecf20Sopenharmony_ci{
428c2ecf20Sopenharmony_ci	unsigned short i = pstack->top, last_index = pstack->top - 1;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	while (i-- != 0) {
458c2ecf20Sopenharmony_ci		if (pstack->entries[i] == key) {
468c2ecf20Sopenharmony_ci			if (i < last_index)
478c2ecf20Sopenharmony_ci				memmove(pstack->entries + i,
488c2ecf20Sopenharmony_ci					pstack->entries + i + 1,
498c2ecf20Sopenharmony_ci					(last_index - i) * sizeof(void *));
508c2ecf20Sopenharmony_ci			--pstack->top;
518c2ecf20Sopenharmony_ci			return;
528c2ecf20Sopenharmony_ci		}
538c2ecf20Sopenharmony_ci	}
548c2ecf20Sopenharmony_ci	pr_err("%s: %p not on the pstack!\n", __func__, key);
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_civoid pstack__push(struct pstack *pstack, void *key)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	if (pstack->top == pstack->max_nr_entries) {
608c2ecf20Sopenharmony_ci		pr_err("%s: top=%d, overflow!\n", __func__, pstack->top);
618c2ecf20Sopenharmony_ci		return;
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci	pstack->entries[pstack->top++] = key;
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_civoid *pstack__pop(struct pstack *pstack)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	void *ret;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	if (pstack->top == 0) {
718c2ecf20Sopenharmony_ci		pr_err("%s: underflow!\n", __func__);
728c2ecf20Sopenharmony_ci		return NULL;
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	ret = pstack->entries[--pstack->top];
768c2ecf20Sopenharmony_ci	pstack->entries[pstack->top] = NULL;
778c2ecf20Sopenharmony_ci	return ret;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_civoid *pstack__peek(struct pstack *pstack)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	if (pstack->top == 0)
838c2ecf20Sopenharmony_ci		return NULL;
848c2ecf20Sopenharmony_ci	return pstack->entries[pstack->top - 1];
858c2ecf20Sopenharmony_ci}
86