|
|
|
/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
|
|
|
|
|
|
|
|
#include <gay/clist.h>
|
|
|
|
#include <gay/config.h>
|
|
|
|
#include <gay/kprintf.h>
|
|
|
|
#include <gay/poison.h>
|
|
|
|
#include <gay/systm.h>
|
|
|
|
|
|
|
|
#if CFG_DEBUG_CLIST
|
|
|
|
#define CLIST_DEBUG_BLOCK
|
|
|
|
#define CLIST_ASSERT(x) KASSERT(x)
|
|
|
|
#else
|
|
|
|
#define CLIST_DEBUG_BLOCK if (0)
|
|
|
|
#define CLIST_ASSERT(x) ({})
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void clist_init(struct clist *head)
|
|
|
|
{
|
|
|
|
CLIST_DEBUG_BLOCK {
|
|
|
|
if (head->next == head && head->prev == head)
|
|
|
|
kprintf("clist_init(%p) called multiple times\n", head);
|
|
|
|
}
|
|
|
|
|
|
|
|
head->next = head;
|
|
|
|
head->prev = head;
|
|
|
|
}
|
|
|
|
|
|
|
|
void clist_add(struct clist *head, struct clist *new)
|
|
|
|
{
|
|
|
|
CLIST_ASSERT(!sus_nil(head->next));
|
|
|
|
CLIST_ASSERT(!sus_nil(new));
|
|
|
|
|
|
|
|
head->prev->next = new;
|
|
|
|
new->next = head;
|
|
|
|
|
|
|
|
new->prev = head->prev;
|
|
|
|
head->prev = new;
|
|
|
|
}
|
|
|
|
|
|
|
|
void clist_add_first(struct clist *head, struct clist *new)
|
|
|
|
{
|
|
|
|
head->next->prev = new;
|
|
|
|
new->next = head->next;
|
|
|
|
|
|
|
|
new->prev = head;
|
|
|
|
head->next = new;
|
|
|
|
}
|
|
|
|
|
|
|
|
void clist_del(struct clist *node)
|
|
|
|
{
|
|
|
|
node->next->prev = node->prev;
|
|
|
|
node->prev->next = node->next;
|
|
|
|
|
|
|
|
CLIST_DEBUG_BLOCK {
|
|
|
|
node->next = (struct clist *)CLIST_POISON_NEXT;
|
|
|
|
node->prev = (struct clist *)CLIST_POISON_PREV;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct clist *clist_del_first(struct clist *head)
|
|
|
|
{
|
|
|
|
CLIST_ASSERT(!clist_is_empty(head));
|
|
|
|
|
|
|
|
struct clist *first = head->next;
|
|
|
|
clist_del(first);
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct clist *clist_del_last(struct clist *head)
|
|
|
|
{
|
|
|
|
CLIST_ASSERT(!clist_is_empty(head));
|
|
|
|
|
|
|
|
struct clist *last = head->prev;
|
|
|
|
clist_del(last);
|
|
|
|
return last;
|
|
|
|
}
|