diff --git a/2021/Makefile b/2021/Makefile new file mode 100644 index 0000000..8211a5f --- /dev/null +++ b/2021/Makefile @@ -0,0 +1,25 @@ +SUBDIRS := $(shell echo day??) + +EXCLUDE := --exclude 'cob-01/' + +.PHONY: clean $(SUBDIRS) + +clean: + for dir in $(SUBDIRS) ; do \ + make -C $$dir clean ; \ + done + +all: $(SUBDIRS) + +$(SUBDIRS): + @echo "=========================================" + @echo "================= $@ =================" + @echo "=========================================" + @echo + @echo "+++++++++++++++++ ex1" + @$(MAKE) --no-print-directory -C $@ ex1 2>&1 + @echo "+++++++++++++++++ ex2" + @$(MAKE) --no-print-directory -C $@ ex2 2>&1 + +output: + @$(MAKE) --no-print-directory all >OUTPUT 2>&1 diff --git a/2021/templates/Makefile b/2021/templates/Makefile new file mode 100644 index 0000000..855b615 --- /dev/null +++ b/2021/templates/Makefile @@ -0,0 +1,26 @@ +INPUT := INPUT.txt +SHELL := /bin/bash +CFLAGS := -w +TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n" +export PATH := .:$(PATH) + +.PHONY: clean all compile deploy ex1 ex2 + +all: ex1 ex2 + +compile: ex1-c ex2-c + +ex1: ex1-c + @$(TIME) ex1.bash < $(INPUT) + @$(TIME) ex1-c < $(INPUT) + +ex2: ex2-c + @$(TIME) ex2.bash < $(INPUT) + @#$(TIME) ex2-sort.bash < $(INPUT) + @$(TIME) ex2-c < $(INPUT) + +clean: + @rm -f ex1-c ex2-c core + +deploy: + @$(MAKE) -C .. deploy diff --git a/2021/templates/bits.c b/2021/templates/bits.c new file mode 100644 index 0000000..47e567e --- /dev/null +++ b/2021/templates/bits.c @@ -0,0 +1,85 @@ +/* bits.c - bits.h tests + * + * Copyright (C) 2021 Bruno Raoult ("br") + * Licensed under the GNU General Public License v3.0 or later. + * Some rights reserved. See COPYING. + * + * You should have received a copy of the GNU General Public License along with this + * program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "bits.h" + +#ifdef BIN_bits +#include +#include + +static inline int _popcount64(u64 n) +{ + int count = 0; + while (n) { + count++; + n &= (n - 1); + } + return count; +} + +static inline int _ctz64(u64 n) +{ + return _popcount64((n & -n) - 1); +} + +static inline int _clz64(u64 n) +{ + u64 r, q; + + r = (n > 0xFFFFFFFF) << 5; n >>= r; + q = (n > 0xFFFF) << 4; n >>= q; r |= q; + q = (n > 0xFF ) << 3; n >>= q; r |= q; + q = (n > 0xF ) << 2; n >>= q; r |= q; + q = (n > 0x3 ) << 1; n >>= q; r |= q; + r |= (n >> 1); + return __WORDSIZE - r - 1; +} + +static inline int _ffs64(u64 n) +{ + if (n == 0) + return (0); + + return _popcount64(n ^ ~-n); +} + + +int main(int ac, char **av) +{ + u64 u = 123, _tmp; + int curbit; + int base = 10; + debug_init(0); + if (ac > 2) + base = atoi(*(av+2)); + if (ac > 1) { + u = strtoul(*(av+1), NULL, base); + printf("base=%d input=%#lx\n", base, u); + printf("popcount64(%lu) = %d/%d\n", u, popcount64(u), _popcount64(u)); + printf("ctz64(%lu) = %d/%d\n", u, ctz64(u), _ctz64(u)); + printf("clz64(%lu) = %d/%d\n", u, clz64(u), _clz64(u)); + printf("ffs64(%lu) = %d/%d\n", u, ffs64(u), _ffs64(u)); + printf("\n"); + + bit_for_each64(curbit, _tmp, u) { + printf("loop: curbit=%d tmp=%ld\n", curbit, _tmp); + } + printf("\n"); + bit_for_each64_2(curbit, _tmp, u) { + printf("loop2: curbit=%d tmp=%ld\n", curbit, _tmp); + } + + } + return 0; +} +#endif /* BIN_bits */ diff --git a/2021/templates/bits.h b/2021/templates/bits.h new file mode 100644 index 0000000..6205c52 --- /dev/null +++ b/2021/templates/bits.h @@ -0,0 +1,167 @@ +/* bits.h - bits functions. + * + * Copyright (C) 2021 Bruno Raoult ("br") + * Licensed under the GNU General Public License v3.0 or later. + * Some rights reserved. See COPYING. + * + * You should have received a copy of the GNU General Public License along with this + * program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ +#ifndef BITS_H +#define BITS_H + +#include + +/* next include will define __WORDSIZE: 32 or 64 + */ +#include + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +/* no plan to support 32bits for now... + */ +#if __WORDSIZE != 64 +ERROR_64_BYTES_WORDSIZE_ONLY +#endif + +typedef int64_t s64; +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; +typedef unsigned int uint; +typedef unsigned char uchar; + +/* count trailing zeroes : 00101000 -> 3 + * ^^^ + */ +static inline int ctz64(u64 n) +{ +# if __has_builtin(__builtin_ctzl) +# ifdef DEBUG_BITS + log_f(1, "builtin ctzl.\n"); +# endif + return __builtin_ctzl(n); + +# elif __has_builtin(__builtin_clzl) +# ifdef DEBUG_BITS + log_f(1, "builtin clzl.\n"); +# endif + return __WORDSIZE - (__builtin_clzl(n & -n) + 1); + +# else +# ifdef DEBUG_BITS + log_f(1, "emulated.\n"); +# endif + return popcount64((n & −n) − 1); +# endif +} + +/* count leading zeroes : 00101000 -> 2 + * ^^ + */ +static inline int clz64(u64 n) +{ +# if __has_builtin(__builtin_clzl) +# ifdef DEBUG_BITS + log_f(1, "builtin.\n"); +# endif + return __builtin_clzl(n); + +# else +# ifdef DEBUG_BITS + log_f(1, "emulated.\n"); +# endif + u64 r, q; + + r = (n > 0xFFFFFFFF) << 5; n >>= r; + q = (n > 0xFFFF) << 4; n >>= q; r |= q; + q = (n > 0xFF ) << 3; n >>= q; r |= q; + q = (n > 0xF ) << 2; n >>= q; r |= q; + q = (n > 0x3 ) << 1; n >>= q; r |= q; + r |= (n >> 1); + return __WORDSIZE - r - 1; +# endif +} + +/* find first set : 00101000 -> 4 + * ^ + */ +static inline uint ffs64(u64 n) +{ +# if __has_builtin(__builtin_ffsl) +# ifdef DEBUG_BITS + log_f(1, "builtin ffsl.\n"); +# endif + return __builtin_ffsll(n); + +# elif __has_builtin(__builtin_ctzl) +# ifdef DEBUG_BITS + log_f(1, "builtin ctzl.\n"); +# endif + if (n == 0) + return (0); + return __builtin_ctzl(n) + 1; + +# else +# ifdef DEBUG_BITS + log_f(1, "emulated.\n"); +# endif + return popcount64(n ^ ~-n); +# endif +} + +static inline int popcount64(u64 n) +{ +# if __has_builtin(__builtin_popcountl) +# ifdef DEBUG_BITS + log_f(1, "builtin.\n"); +# endif + return __builtin_popcountl(n); + +# else +# ifdef DEBUG_BITS + log_f(1, "emulated.\n"); +# endif + int count = 0; + while (n) { + count++; + n &= (n - 1); + } + return count; +# endif +} + +/** bit_for_each64 - iterate over an u64 bits + * @pos: an int used as current bit + * @tmp: a temp u64 used as temporary storage + * @ul: the u64 to loop over + * + * Usage: + * u64 u=139, _t; // u=b10001011 + * int cur; + * bit_for_each64(cur, _t, u) { + * printf("%d\n", cur); + * } + * This will display the position of each bit set in ul: 1, 2, 4, 8 + * + * I should probably re-think the implementation... + */ +#define bit_for_each64(pos, tmp, ul) \ + for (tmp = ul, pos = ffs64(tmp); tmp; tmp &= (tmp - 1), pos = ffs64(tmp)) + +/** or would it be more useful (counting bits from zero instead of 1) ? + */ +#define bit_for_each64_2(pos, tmp, ul) \ + for (tmp = ul, pos = ctz64(tmp); tmp; tmp ^= 1<. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include +#include +#include +#include "debug.h" + +#define NANOSEC 1000000000 /* nano sec in sec */ +#define MILLISEC 1000000 /* milli sec in sec */ + +static s64 timer_start; /* in nanosecond */ +static u32 debug_level=0; + +void debug_level_set(u32 level) +{ + debug_level = level;; + + log(0, "debug level set to %u\n", level); +} + +void debug_init(u32 level) +{ + struct timespec timer; + + debug_level_set(level); + if (!clock_gettime(CLOCK_MONOTONIC, &timer)) { + timer_start = timer.tv_sec * NANOSEC + timer.tv_nsec; + } + else { + timer_start = 0; + } + log(0, "timer started.\n"); +} + +inline static s64 timer_elapsed() +{ + struct timespec timer; + + clock_gettime(CLOCK_MONOTONIC, &timer); + return (timer.tv_sec * NANOSEC + timer.tv_nsec) - timer_start; +} + + +/* void debug - log function + * @timestamp : boolean + * @indent : indent level (2 spaces each) + * @src : source file/func name (or NULL) + * @line : line number + */ +void debug(u32 level, bool timestamp, u32 indent, const char *src, + u32 line, const char *fmt, ...) +{ + if (level > debug_level) + return; + + va_list ap; + + if (indent) + printf("%*s", 2*(indent-1), ""); + + if (timestamp) { + s64 diff = timer_elapsed(); + printf("%ld.%03ld ", diff/NANOSEC, (diff/1000000)%1000); + printf("%010ld ", diff); + } + + if (src) { + if (line) + printf("[%s:%u] ", src, line); + else + printf("[%s] ", src); + } + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} + +#ifdef BIN_debug +#include + +int main() +{ + int foo=1; + debug_init(5); + + log(0, "log0=%d\n", foo++); + log(1, "log1=%d\n", foo++); + log(2, "log2=%d\n", foo++); + log_i(2, "log_i 2=%d\n", foo++); + log_i(5, "log_i 5=%d\n", foo++); + log_i(6, "log_i 6=%d\n", foo++); + log_it(4, "log_it 4=%d\n", foo++); + log_f(1, "log_f 5=%d\n", foo++); +} +#endif diff --git a/2021/templates/debug.h b/2021/templates/debug.h new file mode 100644 index 0000000..06514fe --- /dev/null +++ b/2021/templates/debug.h @@ -0,0 +1,68 @@ +/* move.h - debug/log management. + * + * Copyright (C) 2021 Bruno Raoult ("br") + * Licensed under the GNU General Public License v3.0 or later. + * Some rights reserved. See COPYING. + * + * You should have received a copy of the GNU General Public License along with this + * program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include +#include + +#include "bits.h" + +void debug_init(u32 level); +void debug_level_set(u32 level); +void debug_devel_set(u32 level); +void debug(u32 level, bool timestamp, u32 indent, + const char *src, u32 line, const char *, ...); + +#ifdef DEBUG + +/* format: only printf + */ +#define log(level, fmt, args...) \ + debug((level), false, 0, NULL, 0, fmt, ##args) + +/* format: func name, no line number, no indent, no timestamp + * foo:15 val=2 + */ +#define log_f(level, fmt, args...) \ + debug((level), false, 0, __func__, 0, fmt, ##args) + +/* format : func name, indent, no timestamp + * foo:15 val=2 + */ +#define log_i(level, fmt, args...) \ + debug((level), false, (level), __func__, __LINE__, fmt, ##args) + +/* format : func name, indent, timestamp + * []foo:15 val=2 + */ +#define log_it(level, fmt, args...) \ + debug((level), true, (level), __func__, __LINE__, fmt, ##args) + +/* format: file name, no indent, no timestamp + * foo:15 val=2 + * + * #define log_f(level, fmt, args...) \ + * debug((level), false, 0, __FILE__, __LINE__, fmt, args) + */ + +#else +#define log(level, fmt, args...) +#define log_i(...) +#define log_it(...) +#define log_f(...) + +#endif /* DEBUG */ + +#endif /* DEBUG_H */ diff --git a/2021/templates/ex1-c.c b/2021/templates/ex1-c.c new file mode 100644 index 0000000..7012fef --- /dev/null +++ b/2021/templates/ex1-c.c @@ -0,0 +1,58 @@ +/* ex1-c: Advent2021 game, day 1/game 1 + */ + +#include +#include +#include + +#include "debug.h" + +#define XMOVE 3 + +int my_strlen(str) + char *str; +{ + int i; + for (i=0; *str; ++i, ++str) + ; + return i; +} + +static int usage(char *prg) +{ + fprintf(stderr, "Usage: %s [-ilw] [file...]\n", prg); + return 1; +} + +int main(int ac, char **av) +{ + int opt; + char str[80]; + + while ((opt = getopt(ac, av, "d:f:")) != -1) { + switch (opt) { + case 'd': + debug_level_set(atoi(optarg)); + break; + default: + return usage(*av); + } + } + printf("optind = %d ac = %d\n", optind, ac); + + if (optind < ac) + return usage(*av); + + scanf("%s", str); /* ignore 1st line */ + + while (scanf("%s", str) != EOF) { + line++; + col+=XMOVE; + linelen=my_strlen(str); + mod=col%linelen; + if (*(str+mod) == '#') + count++; + } + printf ("%s : lines:%d pos:%d found:%d\n", *av, line, col, count); + exit (0); +} diff --git a/2021/templates/ex1.bash b/2021/templates/ex1.bash new file mode 100755 index 0000000..afa4f5a --- /dev/null +++ b/2021/templates/ex1.bash @@ -0,0 +1,21 @@ +#!/bin/bash +# +# ex1.bash: Advent2020 game, day 3/game 1. + +CMD=${0##*/} + +XMOVE=3 # 3 right + +declare -i xpos=0 ypos=0 count=0 linelen=0 modpos=0 + +read -r line # ignore 1st line + +while read -r line; do + (( ypos++ )) + (( xpos += XMOVE )) # move right + (( linelen = ${#line} )) + (( modpos = (xpos % linelen) )) + [[ ${line:modpos:1} = \# ]] && ((count++)) +done +printf "%s : lines:%d pos=%d found:%d\n" "$CMD" $ypos $xpos $count +exit 0 diff --git a/2021/templates/ex2-c.c b/2021/templates/ex2-c.c new file mode 100644 index 0000000..590c40c --- /dev/null +++ b/2021/templates/ex2-c.c @@ -0,0 +1,60 @@ +/* ex1-c: Advent2020 game, day 3/game 2 + */ + +#include +#include + +struct { + int dx; + int dy; + int pos; + int count; +} set[] = { + { 1, 1, 0, 0}, + { 3, 1, 0, 0}, + { 5, 1, 0, 0}, + { 7, 1, 0, 0}, + { 1, 2, 0, 0}, + {-1, -1, 0, 0} /* end marker - not necessary */ +}; + +int my_strlen(str) + char *str; +{ + int i; + for (i=0; *str; ++i, ++str) + ; + return i; +} + +int main(ac, av) + int ac; + char **av; +{ + int line=0, linelen=0, mod=0, i; + unsigned long res=1; + char str[80]; + + scanf("%s", str); /* ignore 1st line */ + + while (scanf("%s", str) != EOF) { + line++; + linelen=my_strlen(str); + for (i=0; set[i].dx >= 0; ++i) { + if (! (line % set[i].dy )) { /* line ok for this set */ + set[i].pos += set[i].dx; /* increment set column */ + mod = set[i].pos % linelen; + if ( str[mod] == '#') + set[i].count++; + } + } + } + printf("%s : ", *av); + for (i=0; set[i].dx != -1; ++i) { + printf("[%d]=[%d, %d, %d, %d] ", i, + set[i].dx, set[i].dy, set[i].pos, set[i].count); + res*=set[i].count; + } + printf ("res:%lu\n", res); + exit (0); +} diff --git a/2021/templates/ex2.bash b/2021/templates/ex2.bash new file mode 100755 index 0000000..51fc9cb --- /dev/null +++ b/2021/templates/ex2.bash @@ -0,0 +1,34 @@ +#!/bin/bash +# +# ex1.bash: Advent2020 game, day 3/game 2. + +CMD=${0##*/} + +XMOVES=(1 3 5 7 1) # moves right +YMOVES=(1 1 1 1 2) # moves down +declare -i linelen=0 modpos=0 res=1 +declare -a xpos xcount + +read -r line # ignore 1st line + +while read -r line; do + (( ypos++ )) + (( linelen = ${#line} )) + + for ((i=0; i<${#XMOVES[@]}; ++i)); do + if ((ypos % YMOVES[i] == 0)); then + (( xpos[i] += XMOVES[i] )) # move right + (( modpos = (xpos[i] % linelen) )) + [[ ${line:modpos:1} = \# ]] && ((xcount[i]++)) + fi + done +done +echo "xpos=${xpos[*]} xcount=${xcount[*]}" +printf "%s : " "$CMD" +for ((i=0; i<${#XMOVES[@]}; ++i)); do + printf "[%d]=[%d, %d, %d, %d] " $i "${XMOVES[$i]}" "${YMOVES[$i]}" \ + "${xpos[$i]}" "${xcount[$i]}" + (( res *= xcount[i] )) +done +printf "res:%d\n " $res +exit 0 diff --git a/2021/templates/list.h b/2021/templates/list.h new file mode 100644 index 0000000..d005caf --- /dev/null +++ b/2021/templates/list.h @@ -0,0 +1,995 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* adaptation of kernel's + * Main change is that I don't use READ_ONCE and WRITE_ONCE + * See https://www.kernel.org/doc/Documentation/memory-barriers.txt + */ +#ifndef __BR_LIST_H +#define __BR_LIST_H + +#include +#include + +/************ originally in */ +struct list_head { + struct list_head *next, *prev; +}; +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +/************ originally in */ +# define POISON_POINTER_DELTA 0 +/* These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) +#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) + +/************ originally in */ +#define container_of(ptr, type, member) ({ \ + void *__mptr = (void *)(ptr); \ + ((type *)(__mptr - offsetof(type, member))); }) + +/* + * Circular doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * INIT_LIST_HEAD - Initialize a list_head structure + * @list: list_head structure to be initialized. + * + * Initializes the list_head to point to itself. If it is a list header, + * the result is an empty list. + */ +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/* + * Delete a list entry and clear the 'prev' pointer. + * + * This is a special-purpose list clearing method used in the networking code + * for lists allocated as per-cpu, where we don't want to incur the extra + * WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this + * needs to check the node 'prev' pointer instead of calling list_empty(). + */ +static inline void __list_del_clearprev(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = NULL; +} + +static inline void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del_entry(entry); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +/** + * list_replace_init - replace old entry by new one and initialize the old one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position + * @entry1: the location to place entry2 + * @entry2: the location to place entry1 + */ +static inline void list_swap(struct list_head *entry1, + struct list_head *entry2) +{ + struct list_head *pos = entry2->prev; + + list_del(entry2); + list_replace(entry1, entry2); + if (pos == entry1) + pos = entry2; + list_add(entry1, pos); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del_entry(entry); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del_entry(list); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del_entry(list); + list_add_tail(list, head); +} + +/** + * list_bulk_move_tail - move a subsection of a list to its tail + * @head: the head that will follow our entry + * @first: first entry to move + * @last: last entry to move, can be the same as first + * + * Move all entries between @first and including @last before @head. + * All three entries must belong to the same linked list. + */ +static inline void list_bulk_move_tail(struct list_head *head, + struct list_head *first, + struct list_head *last) +{ + first->prev->next = last->next; + last->next->prev = first->prev; + + head->prev->next = first; + first->prev = head->prev; + + last->next = head; + head->prev = last; +} + +/** + * list_is_first -- tests whether @list is the first entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_first(const struct list_head *list, + const struct list_head *head) +{ + return list->prev == head; +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_rotate_left - rotate the list to the left + * @head: the head of the list + */ +static inline void list_rotate_left(struct list_head *head) +{ + struct list_head *first; + + if (!list_empty(head)) { + first = head->next; + list_move_tail(first, head); + } +} + +/** + * list_rotate_to_front() - Rotate list to specific item. + * @list: The desired new front of the list. + * @head: The head of the list. + * + * Rotates list so that @list becomes the new front of the list. + */ +static inline void list_rotate_to_front(struct list_head *list, + struct list_head *head) +{ + /* + * Deletes the list head from the list denoted by @head and + * places it as the tail of @list, this effectively rotates the + * list so that @list is at the front. + */ + list_move_tail(head, list); +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static inline void __list_cut_position(struct list_head *list, + struct list_head *head, struct list_head *entry) +{ + struct list_head *new_first = entry->next; + list->next = head->next; + list->next->prev = list; + list->prev = entry; + entry->next = list; + head->next = new_first; + new_first->prev = head; +} + +/** + * list_cut_position - cut a list into two + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * and if so we won't cut the list + * + * This helper moves the initial part of @head, up to and + * including @entry, from @head to @list. You should + * pass on @entry an element you know is on @head. @list + * should be an empty list or a list you do not care about + * losing its data. + * + */ +static inline void list_cut_position(struct list_head *list, + struct list_head *head, struct list_head *entry) +{ + if (list_empty(head)) + return; + if (list_is_singular(head) && + (head->next != entry && head != entry)) + return; + if (entry == head) + INIT_LIST_HEAD(list); + else + __list_cut_position(list, head, entry); +} + +/** + * list_cut_before - cut a list into two, before given entry + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * + * This helper moves the initial part of @head, up to but + * excluding @entry, from @head to @list. You should pass + * in @entry an element you know is on @head. @list should + * be an empty list or a list you do not care about losing + * its data. + * If @entry == @head, all entries on @head are moved to + * @list. + */ +static inline void list_cut_before(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + if (head->next == entry) { + INIT_LIST_HEAD(list); + return; + } + list->next = head->next; + list->next->prev = list; + list->prev = entry->prev; + list->prev->next = list; + head->next = entry; + entry->prev = head; +} + +static inline void __list_splice(const struct list_head *list, + struct list_head *prev, + struct list_head *next) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * list_splice - join two lists, this is designed for stacks + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head, head->next); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head->prev, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head, head->next); + INIT_LIST_HEAD(list); + } +} + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_last_entry - get the last element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +/** + * list_first_entry_or_null - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note that if the list is empty, it returns NULL. + */ +#define list_first_entry_or_null(ptr, type, member) ({ \ + struct list_head *head__ = (ptr); \ + struct list_head *pos__ = head__->next; \ + pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ + }) + +/** + * list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_next_entry(pos, member) \ + list_entry((pos)->member.next, __typeof__(*(pos)), member) + +/** + * list_prev_entry - get the prev element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_prev_entry(pos, member) \ + list_entry((pos)->member.prev, __typeof__(*(pos)), member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_continue - continue iteration over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * Continue to iterate over a list, continuing after the current position. + */ +#define list_for_each_continue(pos, head) \ + for (pos = pos->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_entry_is_head - test if the entry points to the head of the list + * @pos: the type * to cursor + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_entry_is_head(pos, head, member) \ + (&pos->member == (head)) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_first_entry(head, __typeof__(*pos), member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_last_entry(head, __typeof__(*pos), member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_prev_entry(pos, member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_head within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, __typeof__(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_prev_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_prev_entry(pos, member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_from_reverse - iterate backwards over list of given type + * from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate backwards over list of given type, continuing from current position. + */ +#define list_for_each_entry_from_reverse(pos, head, member) \ + for (; !list_entry_is_head(pos, head, member); \ + pos = list_prev_entry(pos, member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_first_entry(head, __typeof__(*pos), member), \ + n = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_continue - continue list iteration safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_next_entry(pos, member), \ + n = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_from - iterate over list from current point safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_last_entry(head, __typeof__(*pos), member), \ + n = list_prev_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_prev_entry(n, member)) + +/** + * list_safe_reset_next - reset a stale list_for_each_entry_safe loop + * @pos: the loop cursor used in the list_for_each_entry_safe loop + * @n: temporary storage used in list_for_each_entry_safe + * @member: the name of the list_head within the struct. + * + * list_safe_reset_next is not safe to use in general if the list may be + * modified concurrently (eg. the lock is dropped in the loop body). An + * exception to this is if the cursor element (pos) is pinned in the list, + * and list_safe_reset_next is called after re-taking the lock and before + * completing the current iteration of the loop body. + */ +#define list_safe_reset_next(pos, n, member) \ + n = list_next_entry(pos, member) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +/** + * hlist_unhashed - Has node been removed from list and reinitialized? + * @h: Node to be checked + * + * Not that not all removal functions will leave a node in unhashed + * state. For example, hlist_nulls_del_init_rcu() does leave the + * node in unhashed state, but hlist_nulls_del() does not. + */ +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +/** + * hlist_unhashed_lockless - Version of hlist_unhashed for lockless use + * @h: Node to be checked + * + * This variant of hlist_unhashed() must be used in lockless contexts + * to avoid potential load-tearing. The READ_ONCE() is paired with the + * various WRITE_ONCE() in hlist helpers that are defined below. + */ +static inline int hlist_unhashed_lockless(const struct hlist_node *h) +{ + return !h->pprev; +} + +/** + * hlist_empty - Is the specified hlist_head structure an empty hlist? + * @h: Structure to check. + */ +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + + *pprev = next; + if (next) + next->pprev = pprev; +} + +/** + * hlist_del - Delete the specified hlist_node from its list + * @n: Node to delete. + * + * Note that this function leaves the node in hashed state. Use + * hlist_del_init() or similar instead to unhash @n. + */ +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_init - Delete the specified hlist_node from its list and initialize + * @n: Node to delete. + * + * Note that this function leaves the node in unhashed state. + */ +static inline void hlist_del_init(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +/** + * hlist_add_head - add a new entry at the beginning of the hlist + * @n: new entry to be added + * @h: hlist head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + +/** + * hlist_add_before - add a new entry before the one specified + * @n: new entry to be added + * @next: hlist node to add it before, which must be non-NULL + */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +/** + * hlist_add_behind - add a new entry after the one specified + * @n: new entry to be added + * @prev: hlist node to add it after, which must be non-NULL + */ +static inline void hlist_add_behind(struct hlist_node *n, + struct hlist_node *prev) +{ + n->next = prev->next; + prev->next = n; + n->pprev = &prev->next; + + if (n->next) + n->next->pprev = &n->next; +} + +/** + * hlist_add_fake - create a fake hlist consisting of a single headless node + * @n: Node to make a fake list out of + * + * This makes @n appear to be its own predecessor on a headless hlist. + * The point of this is to allow things like hlist_del() to work correctly + * in cases where there is no list. + */ +static inline void hlist_add_fake(struct hlist_node *n) +{ + n->pprev = &n->next; +} + +/** + * hlist_fake: Is this node a fake hlist? + * @h: Node to check for being a self-referential fake hlist. + */ +static inline bool hlist_fake(struct hlist_node *h) +{ + return h->pprev == &h->next; +} + +/** + * hlist_is_singular_node - is node the only element of the specified hlist? + * @n: Node to check for singularity. + * @h: Header for potentially singular list. + * + * Check whether the node is the only node of the head without + * accessing head, thus avoiding unnecessary cache misses. + */ +static inline bool +hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h) +{ + return !n->next && n->pprev == &h->first; +} + +/** + * hlist_move_list - Move an hlist + * @old: hlist_head for old list. + * @new: hlist_head for new list. + * + * Move a list from one list head to another. Fixup the pprev + * reference of the first entry if it exists. + */ +static inline void hlist_move_list(struct hlist_head *old, + struct hlist_head *new) +{ + new->first = old->first; + if (new->first) + new->first->pprev = &new->first; + old->first = NULL; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos ; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +#define hlist_entry_safe(ptr, type, member) \ + ({ __typeof__(ptr) ____ptr = (ptr); \ + ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + }) + +/** + * hlist_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(pos, head, member) \ + for (pos = hlist_entry_safe((head)->first, __typeof__(*(pos)), member); \ + pos; \ + pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member)) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after current point + * @pos: the type * to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(pos, member) \ + for (pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member); \ + pos; \ + pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member)) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from current point + * @pos: the type * to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(pos, member) \ + for (; pos; \ + pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member)) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: a &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = hlist_entry_safe((head)->first, __typeof__(*pos), member); \ + pos && ({ n = pos->member.next; 1; }); \ + pos = hlist_entry_safe(n, __typeof__(*pos), member)) + +#endif