diff options
Diffstat (limited to 'kernel/include/util')
-rw-r--r-- | kernel/include/util/atomic.h | 31 | ||||
-rw-r--r-- | kernel/include/util/bits.h | 27 | ||||
-rw-r--r-- | kernel/include/util/debug.h | 305 | ||||
-rw-r--r-- | kernel/include/util/delay.h | 73 | ||||
-rw-r--r-- | kernel/include/util/gdb.h | 5 | ||||
-rw-r--r-- | kernel/include/util/init.h | 21 | ||||
-rw-r--r-- | kernel/include/util/list.h | 224 | ||||
-rw-r--r-- | kernel/include/util/printf.h | 87 | ||||
-rw-r--r-- | kernel/include/util/string.h | 93 | ||||
-rw-r--r-- | kernel/include/util/time.h | 25 | ||||
-rw-r--r-- | kernel/include/util/timer.h | 28 |
11 files changed, 919 insertions, 0 deletions
diff --git a/kernel/include/util/atomic.h b/kernel/include/util/atomic.h new file mode 100644 index 0000000..2c67e38 --- /dev/null +++ b/kernel/include/util/atomic.h @@ -0,0 +1,31 @@ +#ifndef ATOMIC_H +#define ATOMIC_H + +typedef int atomic_t; + +#define ATOMIC_INIT(i) (i) + +static inline int __atomic_add_unless(atomic_t *a, int v, int u) +{ + int c, old; + c = __sync_fetch_and_add(a, 0); + while (c != u && (old = __sync_val_compare_and_swap(a, c, c + v)) != c) + c = old; + return c; +} + +static inline void atomic_set(atomic_t *a, int i) { *a = i; } + +static inline void atomic_inc(atomic_t *a) { __sync_add_and_fetch(a, 1); } + +static inline int atomic_dec_and_test(atomic_t *a) +{ + return __sync_sub_and_fetch(a, 1) == 0; +} + +static inline int atomic_inc_not_zero(atomic_t *a) +{ + return __atomic_add_unless(a, 1, 0); +} + +#endif
\ No newline at end of file diff --git a/kernel/include/util/bits.h b/kernel/include/util/bits.h new file mode 100644 index 0000000..d328574 --- /dev/null +++ b/kernel/include/util/bits.h @@ -0,0 +1,27 @@ +#pragma once + +#include "kernel.h" +#include "types.h" + +#define BIT(n) (1 << (n)) + +static inline void bit_flip(void *addr, uintptr_t bit) +{ + uint32_t *map = (uint32_t *)addr; + map += (bit >> 5); + *map ^= (uint32_t)(1 << (bit & 0x1f)); +} + +static inline int bit_check(const void *addr, uintptr_t bit) +{ + const uint32_t *map = (const uint32_t *)addr; + map += (bit >> 5); + return (*map & (1 << (bit & 0x1f))); +} + +#define MOD_POW_2(x, y) ((x) & ((y)-1)) + +#define IS_POW_2(x) (!MOD_POW_2(x, x)) + +#define SELECT(condition, trueval, falseval) \ + (!!(condition) * (trueval) + !condition * (falseval)) diff --git a/kernel/include/util/debug.h b/kernel/include/util/debug.h new file mode 100644 index 0000000..7e6eb91 --- /dev/null +++ b/kernel/include/util/debug.h @@ -0,0 +1,305 @@ +#pragma once + +#include "globals.h" +#include "main/interrupt.h" +#include "mm/page.h" +#include "proc/spinlock.h" +#include "types.h" +#include <main/apic.h> + +/* How to create new dbg modes: + * + * 1) Add a new '#define DBG_NAME DBG_MODE(number)' down below. Make sure the + * number you choose is not already being used and is less than 64. + * 2) Add a new entry into the DBG_TAB below. Make sure it is above the entry + * for "all". The first entry should be the name you want to use to + * disable/enable it in the makefile, the second should be the #define'd + * name you gave it in step 1 and the third should be a color from the list + * directly below this comment. Make sure you include the '\' at the end of + * the line with the new entry. + * + */ + +/* + * These color definitions are from the ANSI specs. + * Do a web search for ANSI color codes to find out + * more funky shit like this + */ + +#define _NORMAL_ "\x1b[0m" +#define _BLACK_ "\x1b[30;47m" +#define _RED_ "\x1b[31;40m" +#define _GREEN_ "\x1b[32;40m" +#define _YELLOW_ "\x1b[33;40m" +#define _BLUE_ "\x1b[34;40m" +#define _MAGENTA_ "\x1b[35;40m" +#define _CYAN_ "\x1b[36;40m" +#define _WHITE_ "\x1b[37;40m" + +#define _BRED_ "\x1b[1;31;40m" +#define _BGREEN_ "\x1b[1;32;40m" +#define _BYELLOW_ "\x1b[1;33;40m" +#define _BBLUE_ "\x1b[1;34;40m" +#define _BMAGENTA_ "\x1b[1;35;40m" +#define _BCYAN_ "\x1b[1;36;40m" +#define _BWHITE_ "\x1b[1;37;40m" + +#define DBG_MODE(x) (1ULL << (x)) + +/* These defines list all of the possible debugging + * types. They are flags, so make sure to use the + * DBG_MODE macro to declare new values. */ +#define DBG_ALL (~0ULL) /* umm, "verbose" */ +#define DBG_CORE DBG_MODE(0) /* core boot code */ +#define DBG_MM DBG_MODE(1) /* memory management */ +#define DBG_INIT DBG_MODE(2) /* boot/init code */ +#define DBG_SCHED DBG_MODE(3) /* swtch, scheduling */ +#define DBG_DISK DBG_MODE(4) /* disk driver */ +#define DBG_TEMP DBG_MODE(5) /* for resolving temporary problems */ +#define DBG_KMALLOC DBG_MODE(6) /* kmalloc, kmem_cache_alloc */ +#define DBG_PAGEALLOC DBG_MODE(7) /* page_alloc, etc. */ +#define DBG_INTR DBG_MODE(8) /* misc. trap/interrupt */ +#define DBG_TERM DBG_MODE(9) /* the terminal device */ +#define DBG_FORK DBG_MODE(10) /* fork(2) */ +#define DBG_PROC DBG_MODE(11) /* process stuff */ +#define DBG_VNREF DBG_MODE(12) /* vnode reference counts */ +#define DBG_PFRAME DBG_MODE(13) /* pframe subsys */ +#define DBG_ERROR DBG_MODE(14) /* error conditions */ +#define DBG_SYSCALL DBG_MODE(15) /* system calls */ +#define DBG_FREF DBG_MODE(16) /* file reference counts */ +#define DBG_PGTBL DBG_MODE(17) /* page table manipulation */ +#define DBG_BRK DBG_MODE(18) /* process break; user memory alloc */ +#define DBG_EXEC DBG_MODE(19) /* new process exec */ +#define DBG_VFS DBG_MODE(20) /* vfs */ +#define DBG_S5FS DBG_MODE(21) /* system V file system */ +#define DBG_KB DBG_MODE(22) /* keyboard */ +#define DBG_THR DBG_MODE(23) /* thread stuff */ +#define DBG_PRINT DBG_MODE(24) /* printdbg.c */ +#define DBG_OSYSCALL DBG_MODE(25) /* other system calls */ +#define DBG_VM DBG_MODE(28) /* VM */ +#define DBG_TEST DBG_MODE(30) /* for testing code */ +#define DBG_TESTPASS DBG_MODE(31) /* for testing code */ +#define DBG_TESTFAIL DBG_MODE(32) /* for testing code */ + +#define DBG_MEMDEV DBG_MODE(33) /* For memory devices ("null" and "zero") */ +#define DBG_ANON DBG_MODE(34) /* anonymous vm objects */ +#define DBG_VMMAP DBG_MODE(35) /* vm area mappings */ +#define DBG_ELF DBG_MODE(37) /* elf loader */ +#define DBG_USER DBG_MODE(38) /* user land */ +#define DBG_DEFAULT DBG_ERROR /* default modes, 0 for none */ + +/* This defines the name that is used in the + * environment variable to turn on the given + * debugging type, along with the color of the debug type */ +/* NOTE that there is an order to these objects - the color chosen for a + * debug statement with multiple DBG specifiers will be the first matching + * result in the table */ +/* Note that rearranging the table will affect results, and may be beneficial + * later */ +#define DBG_TAB \ + /* General */ \ + {"error", DBG_ERROR, _BWHITE_}, {"temp", DBG_TEMP, _NORMAL_}, \ + {"print", DBG_PRINT, _NORMAL_}, {"test", DBG_TEST, _RED_}, \ + {"testpass", DBG_TESTPASS, _GREEN_}, \ + {"testfail", DBG_TESTFAIL, _RED_}, /* Kern 1 */ \ + {"proc", DBG_PROC, _BLUE_}, {"thr", DBG_THR, _CYAN_}, \ + {"sched", DBG_SCHED, _GREEN_}, \ + {"init", DBG_INIT, _NORMAL_}, /* Kern 2 */ \ + {"term", DBG_TERM, _BMAGENTA_}, {"disk", DBG_DISK, _YELLOW_}, \ + {"memdev", DBG_MEMDEV, _BBLUE_}, /* VFS */ \ + {"vfs", DBG_VFS, _WHITE_}, {"fref", DBG_FREF, _MAGENTA_}, \ + {"vnref", DBG_VNREF, _CYAN_}, /* S5FS */ \ + {"s5fs", DBG_S5FS, _BRED_}, \ + {"pframe", DBG_PFRAME, _BMAGENTA_}, /* VM */ \ + {"anon", DBG_ANON, _WHITE_}, {"vmmap", DBG_VMMAP, _BGREEN_}, \ + {"fork", DBG_FORK, _BYELLOW_}, {"brk", DBG_BRK, _YELLOW_}, \ + {"exec", DBG_EXEC, _BRED_}, {"elf", DBG_ELF, _BGREEN_}, \ + {"pgtbl", DBG_PGTBL, _BBLUE_}, {"osyscall", DBG_OSYSCALL, _BMAGENTA_}, \ + {"vm", DBG_VM, _RED_}, /* Syscalls (VFS - VM) */ \ + {"syscall", DBG_SYSCALL, _RED_}, /* support code */ \ + {"intr", DBG_INTR, _BRED_}, {"kmalloc", DBG_KMALLOC, _MAGENTA_}, \ + {"pagealloc", DBG_PAGEALLOC, _WHITE_}, {"kb", DBG_KB, _BLUE_}, \ + {"core", DBG_CORE, _GREEN_}, {"mm", DBG_MM, _RED_}, \ + {"user", DBG_USER, _BYELLOW_}, \ + /* Note this MUST be last or the color code will break */ /* Also note \ + that the \ + color \ + specified \ + here is \ + effectively \ + the \ + "default" \ + */ \ + {"all", DBG_ALL, _NORMAL_}, \ + { \ + NULL, 0, NULL \ + } + +extern uint64_t dbg_modes; + +/* A common interface for functions which provide human-readable information + * about some data structure. Functions implementing this interface should fill + * buf with up to size characters to describe the data passed in as data, then + * return the number of characters writen. If there is not enough space in buf + * to write all information then only size characters will be writen and size + * will be returned. The returned string will be null terminated regardless of + * its length. */ +typedef size_t (*dbg_infofunc_t)(const void *data, char *buf, size_t size); + +#define DBG_BUFFER_SIZE (PAGE_SIZE) + +void dbg_init(void); + +void dbg_print(char *fmt, ...) __attribute__((format(printf, 1, 2))); + +void dbg_printinfo(dbg_infofunc_t func, const void *data); + +const char *dbg_color(uint64_t d_mode); + +#if defined(__SMP__) || defined(__KPREEMPT__) +#define DEBUG_ENTER \ + uint8_t __ipl = apic_initialized() ? intr_setipl(IPL_HIGH) : IPL_LOW; \ +#define DEBUG_EXIT \ + if (apic_initialized()) \ + intr_setipl(__ipl); +#else +#define DEBUG_ENTER \ + do \ + { \ + } while (0); +#define DEBUG_EXIT \ + do \ + { \ + } while (0); +#endif + +#ifndef NDEBUG +#define dbg(mode, ...) \ + do \ + { \ + if (dbg_active(mode)) \ + { \ + DEBUG_ENTER \ + dbg_print("%s", dbg_color(mode)); \ + dbg_print("C%ld P%ld ", curcore.kc_id, \ + curproc ? curproc->p_pid : -1L); \ + dbg_print("%s:%d %s(): ", __FILE__, __LINE__, __func__); \ + dbg_print(__VA_ARGS__); \ + dbg_print("%s", _NORMAL_); \ + DEBUG_EXIT \ + } \ + } while (0) + +#define dbg_force(mode, ...) \ + do \ + { \ + DEBUG_ENTER \ + dbg_print("%s", dbg_color(mode)); \ + dbg_print("C%ld P%ld ", curcore.kc_id, \ + curproc ? curproc->p_pid : -1L); \ + dbg_print("%s:%d %s(): ", __FILE__, __LINE__, __func__); \ + dbg_print(__VA_ARGS__); \ + dbg_print("%s", _NORMAL_); \ + DEBUG_EXIT \ + } while (0) + +#define dbgq(mode, ...) \ + do \ + { \ + if (dbg_active(mode)) \ + { \ + DEBUG_ENTER \ + dbg_print("%s", dbg_color(mode)); \ + dbg_print("C%ld P%ld ", curcore.kc_id, \ + curproc ? curproc->p_pid : -1L); \ + dbg_print(__VA_ARGS__); \ + dbg_print("%s", _NORMAL_); \ + DEBUG_EXIT \ + } \ + } while (0) + +#define dbginfo(mode, func, data) \ + do \ + { \ + if (dbg_active(mode)) \ + { \ + DEBUG_ENTER \ + dbg_print("%s", dbg_color(mode)); \ + dbg_print("C%ld P%ld ", curcore.kc_id, \ + curproc ? curproc->p_pid : -1L); \ + dbg_printinfo(func, data); \ + dbg_print("%s", _NORMAL_); \ + DEBUG_EXIT \ + } \ + } while (0) + +#define dbg_active(mode) (dbg_modes & (mode)) + +void dbg_add_mode(const char *mode); + +void dbg_add_modes(const char *modes); + +#else +#define dbg(mode, ...) +#define dbgq(mode, ...) +#define dbginfo(mode, func, data) +#define dbg_active(mode) 0 +#define dbg_add_mode(mode) +#define dbg_add_modes(modes) +#endif + +noreturn void dbg_panic(const char *file, int line, const char *func, + const char *fmt, ...) + __attribute__((format(printf, 4, 5))); + +#define panic(...) dbg_panic(__FILE__, __LINE__, __func__, __VA_ARGS__) + +#ifndef NDEBUG +#define KASSERT(x) \ + do \ + { \ + if (!(x)) \ + panic("assertion failed: %s", #x); \ + } while (0) + +#define KASSERT_GENERIC(left, right, comparator, comp_str) \ + do \ + { \ + int __left = (int)(left); \ + int __right = (int)(right); \ + if (!comparator(__left, __right)) \ + { \ + panic("assertion failed: %s %s %s. Left: %d, Right: %d\n", #left, \ + comp_str, #right, __left, __right); \ + } \ + } while (0) + +static long equals(long l, long r) +{ + return l == r; +} + +static long notequals(long l, long r) { return l != r; } + +static long lessthan(long l, long r) { return l < r; } + +static long greaterthan(long l, long r) { return l > r; } + +static long lessthaneq(long l, long r) { return l <= r; } + +static long greaterthaneq(long l, long r) { return l >= r; } + +#define KASSERTEQ(l, r) KASSERT_GENERIC(l, r, equals, "==") +#define KASSERTNEQ(l, r) KASSERT_GENERIC(l, r, notequals, "!=") +#define KASSERT_GREATER(l, r) KASSERT_GENERIC(l, r, greaterthan, ">") +#define KASSERT_LESS(l, r) KASSERT_GENERIC(l, r, lessthan, "<") +#define KASSERT_GREQ(l, r) KASSERT_GENERIC(l, r, greaterthaneq, ">=") +#define KASSERT_LESSEQ(l, r) KASSERT_GENERIC(l, r, lessthaneq, "<=") +#else +#define KASSERT(x) +#define KASSERTEQ(l, r) +#define KASSERT_GREATER(l, r) +#define KASSERT_LESS(l, r) +#define KASSERT_GREQ(l, r) +#define KASSERT_LESSEQ(l, r) +#endif diff --git a/kernel/include/util/delay.h b/kernel/include/util/delay.h new file mode 100644 index 0000000..29cf3b2 --- /dev/null +++ b/kernel/include/util/delay.h @@ -0,0 +1,73 @@ +#pragma once + +#include "types.h" +#include "util/debug.h" + +/* Approximate numbers taken from various points in Linux kernel */ +#define LOOPS_PER_JIFFY (1 << 12) +#define HZ 100 /* Found this in a random place in the kernel */ + +/* From arch/x86/lib/delay.c in Linux kernel */ +/* + * Precise Delay Loops for i386 + * + * Copyright (C) 1993 Linus Torvalds + * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz> + * Copyright (C) 2008 Jiri Hladky <hladky _dot_ jiri _at_ gmail _dot_ com> + * + * The __delay function must _NOT_ be inlined as its execution time + * depends wildly on alignment on many x86 processors. The additional + * jump magic is needed to get the timing stable on all the CPU's + * we have to worry about. + */ + +static void __delay(unsigned long loops) +{ + __asm__ volatile( + " test %0,%0 \n" + " jz 3f \n" + " jmp 1f \n" + + ".align 16 \n" + "1: jmp 2f \n" + + ".align 16 \n" + "2: dec %0 \n" + " jnz 2b \n" + "3: dec %0 \n" + + : /* we don't need output */ + : "a"(loops)); +} + +static inline void __const_udelay(unsigned long xloops) +{ + int d0; + + xloops *= 4; + __asm__ volatile("mull %%edx" + : "=d"(xloops), "=&a"(d0) + : "1"(xloops), "0"(LOOPS_PER_JIFFY * (HZ / 4))); + + __delay(++xloops); +} + +static inline void __udelay(unsigned long usecs) +{ + __const_udelay(usecs * 4295); /* 2**32 / 1000000 */ +} + +static inline void __ndelay(unsigned long nsecs) +{ + __const_udelay(nsecs * 5); /* 2**32 / 1000000000 */ +} + +#define udelay(n) \ + (__builtin_constant_p(n) ? ((n) > 20000 ? panic("Delay too large!") \ + : __const_udelay((n)*4295)) \ + : __udelay(n)) + +#define ndelay(n) \ + (__builtin_constant_p(n) \ + ? ((n) > 20000 ? panic("Delay too large!") : __const_udelay((n)*5)) \ + : __ndelay(n)) diff --git a/kernel/include/util/gdb.h b/kernel/include/util/gdb.h new file mode 100644 index 0000000..cc28dbc --- /dev/null +++ b/kernel/include/util/gdb.h @@ -0,0 +1,5 @@ +#pragma once + +#define GDB_DEFINE_HOOK(name, ...) \ + void __py_hook_##name(__VA_ARGS__) {} +#define GDB_CALL_HOOK(name, ...) __py_hook_##name(__VA_ARGS__) diff --git a/kernel/include/util/init.h b/kernel/include/util/init.h new file mode 100644 index 0000000..9be7e3c --- /dev/null +++ b/kernel/include/util/init.h @@ -0,0 +1,21 @@ +#pragma once + +#define init_func(func) \ + __asm__( \ + ".pushsection .init\n\t" \ + ".long " #func \ + "\n\t" \ + ".string \"" #func \ + "\"\n\t" \ + ".popsection\n\t"); +#define init_depends(name) \ + __asm__( \ + ".pushsection .init\n\t" \ + ".long 0\n\t" \ + ".string \"" #name \ + "\"\n\t" \ + ".popsection\n\t"); + +typedef void (*init_func_t)(); + +void init_call_all(void); diff --git a/kernel/include/util/list.h b/kernel/include/util/list.h new file mode 100644 index 0000000..5fd44c1 --- /dev/null +++ b/kernel/include/util/list.h @@ -0,0 +1,224 @@ +#pragma once + +#include "kernel.h" + +/* + * Generic circular doubly linked list implementation. + * + * list_t is the head of the list. + * list_link_t should be included in structures which want to be + * linked on a list_t. + * + * All of the list functions take pointers to list_t and list_link_t + * types, unless otherwise specified. + * + * list_init(list) initializes a list_t to an empty list. + * + * list_empty(list) returns 1 iff the list is empty. + * + * Insertion functions. + * list_insert_head(list, link) inserts link at the front of the list. + * list_insert_tail(list, link) inserts link at the end of the list. + * list_insert_before(olink, nlink) inserts nlink before olink in list. + * + * Removal functions. + * Head is list->l_next. Tail is list->l_prev. + * The following functions should only be called on non-empty lists. + * list_remove(link) removes a specific element from the list. + * list_remove_head(list) removes the first element of list. + * list_remove_tail(list) removes the last element of list. + * + * Item accessors. + * list_item(link, type, member) + * + * Given a list_link_t* and the name of the type of structure which contains + * the list_link_t and the name of the member corresponding to the list_link_t, + * returns a pointer (of type "type*") to the item. + * + * Example: + * struct my_struct { list_link_t my_link }; + * struct my_struct a; + * list_link_init(&a.my_link); + * + * struct my_struct *b = list_item(&a.my_link, struct my_struct, my_link); + * // b should equal &a here + * + * To iterate over a list, + * list_link_t *link; + * for (link = list->l_next; + * link != list; link = link->l_next) + * ... + * + * Or, use the macros, which will work even if you list_remove() the + * current link: + * list_iterate(list, iterator, type, member) { + * ... use iterator ... + * } + * (see also list_iterate_reverse for iterating in reverse) + * + * Where: + * - list is a pointer to the list_t to iterate over, + * - iterator is a name for the loop variable which will take on the value + * of each item in the list, + * - type is the type of items in the list, + * - member is the name of the field in the item type that is the list_link_t + * + * Example (from kernel/drivers/chardev.c) + * // chardevs is a list_t + * // chardev_t has a cd_link member which is a list_link_t + * list_iterate(&chardevs, cd, chardev_t, cd_link) + * { + * if (dev->cd_id == cd->cd_id) + * { + * return -1; + * } + * } + */ + +/** + * Initialize a list_t. + */ +#define LIST_INITIALIZER(list) \ + { \ + .l_next = &(list), .l_prev = &(list) \ + } + +/** + * Initialize a list link. + */ +#define LIST_LINK_INITIALIZER(list_link) \ + { \ + .l_next = NULL, .l_prev = NULL \ + } + +typedef struct list +{ + struct list *l_next; + struct list *l_prev; +} list_t, list_link_t; + +/** + * Initialize a list link. + */ +void list_link_init(list_link_t *link); + +/** + * Initialize a list_t. + */ +void list_init(list_t *list); + +/** + * Check if a link is linked to some list. + * + * @param link The link to check. + * @return long 1 if linked, 0 otherwise. + */ +long list_link_is_linked(const list_link_t *link); + +/** + * Check if a list is empty. + * + * @param list The list to check. + * @return long 1 if empty, 0 otherwise. + */ +long list_empty(const list_t *list); + +/** + * Assert that the internal state of a list is sane, and + * panic if it is not. + * + * @param list The list to check for sanity. + */ +void list_assert_sanity(const list_t *list); + +/** + * Insert a new link onto a list before another link. + * + * @param link The link before which the new link should be inserted. + * @param to_insert The new link to be inserted. + */ +void list_insert_before(list_link_t *link, list_link_t *to_insert); + +/** + * Insert a new link at the head (beginning) of a given list. + * + * @param list The list to insert on. + * @param link The new link to insert. + */ +void list_insert_head(list_t *list, list_link_t *link); + +/** + * Insert a new link at the tail (end) of a given list. + * + * @param list The list to insert on. + * @param link The new link to insert. + */ +void list_insert_tail(list_t *list, list_link_t *link); + +/** + * Remove a particular link from the list it's on. + * + * @param link The link to be removed from its list. + */ +void list_remove(list_link_t *link); + +/** + * Get a pointer to the item that contains the given link. + * + * For instance, given a list_link_t contained within a proc_t, get a reference + * to the proc_t itself. + * + * @param link The link contained within the item to access. + * @param type The type of the outer item struct (e.g., proc_t) + * @param member The name of the struct member which is the list_link_t (e.g. p_list_link) + * + */ +#define list_item(link, type, member) \ + (type *)((char *)(link)-offsetof(type, member)) + +/** + * Get the item at the head of the list. See list_item for explanation + * of type and member. + */ +#define list_head(list, type, member) list_item((list)->l_next, type, member) + +/** + * Get the item at the tail of the list. See list_item for explanation + * of type and member. + */ +#define list_tail(list, type, member) list_item((list)->l_prev, type, member) + +/** + * Get the next item in a list that occurs after the given item. + * + * @param current An item from the list (e.g. a proc_t) + * See list_item for explanation of type and member. + */ +#define list_next(current, type, member) \ + list_head(&(current)->member, type, member) + +/** + * Get the previous item in a list given an item. See list_next for explanation. + */ +#define list_prev(current, type, member) \ + list_tail(&(current)->member, type, member) + +/** + * Iterate over elements in in a list. See comment at top of list.h for + * detailed description. + */ +#define list_iterate(list, var, type, member) \ + for (type *var = list_head(list, type, member), \ + *__next_##var = list_next(var, type, member); \ + &var->member != (list); \ + var = __next_##var, __next_##var = list_next(var, type, member)) + +/** + * Iterate over the elements of a list in reverse. See comment at top of list.h for + * detailed description. + */ +#define list_iterate_reverse(list, var, type, member) \ + for (type *var = list_tail(list, type, member), \ + *__next_##var = list_prev(var, type, member); \ + &var->member != (list); \ + var = __next_##var, __next_##var = list_prev(var, type, member)) diff --git a/kernel/include/util/printf.h b/kernel/include/util/printf.h new file mode 100644 index 0000000..430b156 --- /dev/null +++ b/kernel/include/util/printf.h @@ -0,0 +1,87 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: lib.h + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Changes: + * + * Date: Aug 2003 + * + * Environment: Xen Minimal OS + * Description: Random useful library functions, contains some freebsd stuff + * + **************************************************************************** + * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $ + **************************************************************************** + * + *- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/i386/include/stdarg.h,v 1.10 1999/08/28 00:44:26 peter Exp + *$ + */ + +#pragma once + +#include "stdarg.h" +#include <types.h> + +/* printing */ +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); + +int vscnprintf(char *buf, size_t size, const char *fmt, va_list args); + +int snprintf(char *buf, size_t size, const char *fmt, ...); + +int scnprintf(char *buf, size_t size, const char *fmt, ...); + +// a pretty simple way to avoid kernel buffer overflow attacks, no? +// int vsprintf(char *buf, const char *fmt, va_list args); +// int sprintf(char *buf, const char *fmt, ...); + +/* A variation on printf designed to be used in debug info functions. + * The function takes in a pointer to the address of a string buffer + * and a pointer to the size of the buffer. The buffer address pointed + * by str is incremented to point to the null character writen at the + * end of the new string. The size is decremented by the number of + * characters writen, not including the null character. The function + * returns the number of characters left in the buffer (after taking + * in to account the null character). */ +int iprintf(char **str, size_t *size, char *fmt, ...) + __attribute__((format(printf, 3, 4))); + +int vsscanf(const char *buf, const char *fmt, va_list args); + +int sscanf(const char *buf, const char *fmt, ...); diff --git a/kernel/include/util/string.h b/kernel/include/util/string.h new file mode 100644 index 0000000..04dc0f7 --- /dev/null +++ b/kernel/include/util/string.h @@ -0,0 +1,93 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: lib.h + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * Changes: + * + * Date: Aug 2003 + * + * Environment: Xen Minimal OS + * Description: Random useful library functions, contains some freebsd stuff + * + **************************************************************************** + * $Id: h-insert.h,v 1.4 2002/11/08 16:03:55 rn Exp $ + **************************************************************************** + * + *- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/i386/include/stdarg.h,v 1.10 1999/08/28 00:44:26 peter Exp + *$ + */ + +#pragma once + +#include "stdarg.h" +#include "types.h" + +/* string and memory manipulation */ +int memcmp(const void *cs, const void *ct, size_t count); + +void *memcpy(void *dest, const void *src, size_t count); + +int strncmp(const char *cs, const char *ct, size_t count); + +int strcmp(const char *cs, const char *ct); + +char *strcpy(char *dest, const char *src); + +char *strncpy(char *dest, const char *src, size_t count); + +void *memset(void *s, int c, size_t count); + +size_t strnlen(const char *s, size_t count); + +size_t strlen(const char *s); + +char *strchr(const char *s, int c); + +char *strrchr(const char *s, int c); + +char *strstr(const char *s1, const char *s2); + +char *strcat(char *dest, const char *src); + +char *strdup(const char *s); + +char *strtok(char *s, const char *d); + +/* return string-representation of an errno */ +char *strerror(int errnum); diff --git a/kernel/include/util/time.h b/kernel/include/util/time.h new file mode 100644 index 0000000..fe3df18 --- /dev/null +++ b/kernel/include/util/time.h @@ -0,0 +1,25 @@ +#pragma once + +#include "types.h" +#include "util/debug.h" + +extern uint64_t timer_tickcount; +extern uint64_t kernel_preempted_count; +extern uint64_t user_preempted_count; +extern uint64_t not_preempted_count; +extern uint64_t idle_count; +extern volatile uint64_t jiffies; + +void time_init(); + +void time_spin(time_t ms); + +void time_sleep(time_t ms); + +long do_usleep(useconds_t usec); + +time_t core_uptime(); + +time_t do_time(); + +size_t time_stats(char *buf, size_t len); diff --git a/kernel/include/util/timer.h b/kernel/include/util/timer.h new file mode 100644 index 0000000..57889f9 --- /dev/null +++ b/kernel/include/util/timer.h @@ -0,0 +1,28 @@ +#ifndef TIMER_H +#define TIMER_H + +#include "util/list.h" + +typedef struct timer +{ + void (*function)(uint64_t data); + uint64_t data; + uint64_t expires; + list_link_t link; +} timer_t; + +void timer_init(timer_t *timer); + +void timer_add(timer_t *timer); + +int timer_del(timer_t *timer); + +int timer_mod(timer_t *timer, int expires); + +int timer_pending(timer_t *timer); + +int timer_del_sync(timer_t *timer); + +void __timers_fire(); + +#endif
\ No newline at end of file |