--- /dev/null
+LIB= bmk_core
+LIBISPRIVATE= # defined
+
+SRCS= init.c bmk_string.c memalloc.c sched.c subr_prf.c
+
+CPPFLAGS+= -I${.CURDIR}/../../include
+
+.include "${.CURDIR}/arch/${MACHINE}/Makefile.inc"
+
+.include <bsd.lib.mk>
--- /dev/null
+MYDIR:= ${.PARSEDIR}
+.PATH: ${MYDIR}
+
+SRCS+= cpu_sched_switch.S
+
+.include "${MYDIR}/../x86/Makefile.inc"
--- /dev/null
+/*-
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: sched.c
+ * Author: Grzegorz Milos
+ * Changes: Robert Kaiser
+ *
+ * Date: Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <bmk-core/amd64/asm.h>
+
+ENTRY(bmk_cpu_sched_bouncer)
+ popq %rdi
+ popq %rbx
+ pushq $0 /* correct stack alignment for SSE */
+ pushq $0
+ xorq %rbp,%rbp
+ call *%rbx
+ call bmk_sched_exit
+END(bmk_cpu_sched_bouncer)
+
+ENTRY(bmk__cpu_switch)
+ pushq %rbp
+ pushq %rbx
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movq %rsp, (%rdi) /* save ESP */
+ movq (%rsi), %rsp /* restore ESP */
+ movq $1f, 8(%rdi) /* save EIP */
+ pushq 8(%rsi) /* restore EIP */
+ ret
+1:
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbx
+ popq %rbp
+ ret
+END(bmk__cpu_switch)
--- /dev/null
+MYDIR:= ${.PARSEDIR}
+.PATH: ${MYDIR}
+
+SRCS+= cpu_sched_switch.S
+
+.include "${MYDIR}/../x86/Makefile.inc"
--- /dev/null
+/*-
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: sched.c
+ * Author: Grzegorz Milos
+ * Changes: Robert Kaiser
+ *
+ * Date: Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <bmk-core/i386/asm.h>
+
+ENTRY(bmk_cpu_sched_bouncer)
+ popl %eax
+ popl %ebx
+ pushl $0
+ xorl %ebp,%ebp
+ pushl %eax
+ call *%ebx
+ call bmk_sched_exit
+END(bmk_cpu_sched_bouncer)
+
+ENTRY(bmk__cpu_switch)
+ movl 4(%esp), %ecx /* prev */
+ movl 8(%esp), %edx /* next */
+
+ /* reload tls for new thread */
+ movl $0x18, %eax
+ movl %eax, %gs
+
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl %esp, (%ecx) /* save ESP */
+ movl (%edx), %esp /* restore ESP */
+ movl $1f, 4(%ecx) /* save EIP */
+ pushl 4(%edx) /* restore EIP */
+ ret
+1:
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+END(bmk__cpu_switch)
--- /dev/null
+X86DIR:=${.PARSEDIR}
+.PATH: ${X86DIR}
+
+SRCS+= cpu_sched.c
--- /dev/null
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: sched.c
+ * Author: Grzegorz Milos
+ * Changes: Robert Kaiser
+ *
+ * Date: Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <bmk-core/core.h>
+#include <bmk-core/sched.h>
+
+static void
+stack_push(void **stackp, unsigned long value)
+{
+ unsigned long *stack = *stackp;
+
+ stack--;
+ *stack = value;
+ *stackp = stack;
+}
+
+void
+bmk_cpu_sched_create(struct bmk_thread *thread, struct bmk_tcb *tcb,
+ void (*f)(void *), void *arg,
+ void *stack_base, unsigned long stack_size)
+{
+ void *stack_top = (char *)stack_base + stack_size;
+
+ /* Save pointer to the thread on the stack, used by current macro */
+ *(unsigned long *)stack_base = (unsigned long)thread;
+
+ /* these values are used by bmk_cpu_sched_bouncer() */
+ stack_push(&stack_top, (unsigned long)f);
+ stack_push(&stack_top, (unsigned long)arg);
+
+ tcb->btcb_sp = (unsigned long)stack_top;
+ tcb->btcb_ip = (unsigned long)bmk_cpu_sched_bouncer;
+}
+
+struct bmk_thread *
+bmk_cpu_sched_current(void)
+{
+ struct bmk_thread **current;
+
+ current = (void *)((unsigned long)¤t & ~(bmk_stacksize-1));
+ return *current;
+};
--- /dev/null
+/*-
+ * Copyright (c) 2014 Antti Kantee. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * The assumption is that these won't be used very often,
+ * only for the very low-level routines.
+ *
+ * Some code from public domain implementations.
+ */
+
+#include <bmk-core/null.h>
+#include <bmk-core/string.h>
+
+unsigned long
+bmk_strlen(const char *str)
+{
+ unsigned long rv = 0;
+
+ while (*str++)
+ rv++;
+ return rv;
+}
+
+int
+bmk_strcmp(const char *a, const char *b)
+{
+
+ while (*a && *a++ == *b++) {
+ continue;
+ }
+ if (*a) {
+ a--;
+ b--;
+ }
+ return *a - *b;
+}
+
+int
+bmk_strncmp(const char *a, const char *b, unsigned long n)
+{
+ unsigned char u1, u2;
+
+ while (n-- > 0) {
+ u1 = (unsigned char)*a++;
+ u2 = (unsigned char)*b++;
+ if (u1 != u2)
+ return u1 - u2;
+ if (u1 == '\0')
+ return 0;
+ }
+ return 0;
+}
+
+char *
+bmk_strcpy(char *d, const char *s)
+{
+ char *orig = d;
+
+ while ((*d++ = *s++) != '\0')
+ continue;
+ return orig;
+}
+
+char *
+bmk_strncpy(char *d, const char *s, unsigned long n)
+{
+ char *orig = d;
+
+ while ((*d++ = *s++) && n--)
+ continue;
+ while (n--)
+ *d++ = '\0';
+ return orig;
+}
+
+void *
+bmk_memset(void *b, int c, unsigned long n)
+{
+ unsigned char *v = b;
+
+ while (n--)
+ *v++ = (unsigned char)c;
+
+ return b;
+}
+
+void *
+bmk_memcpy(void *d, const void *src, unsigned long n)
+{
+ unsigned char *dp;
+ const unsigned char *sp;
+
+ dp = d;
+ sp = src;
+
+ while (n--)
+ *dp++ = *sp++;
+
+ return d;
+}
+
+void *
+bmk_memchr(const void *d, int c, unsigned long n)
+{
+ const unsigned char *p = d;
+
+ while (n--) {
+ if (*p == (unsigned char)c)
+ return (void *)(unsigned long)p;
+ p++;
+ }
+ return NULL;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2015 Antti Kantee. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include <bmk-core/core.h>
+
+unsigned long bmk_stackpageorder;
+unsigned long bmk_stacksize;
+unsigned long bmk_pagesize;
+
+int
+bmk_core_init(unsigned long stackpageorder, unsigned long pagesize)
+{
+
+ bmk_stackpageorder = stackpageorder;
+ bmk_stacksize = (1<<stackpageorder) * pagesize;
+ bmk_pagesize = pagesize;
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Antti Kantee. All rights reserved.
+ * Copyright (c) 1983, 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. 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.
+ */
+
+/*
+ * malloc.c (Caltech) 2/21/82
+ * Chris Kingsley, kingsley@cit-20.
+ *
+ * This is a very fast storage allocator. It allocates blocks of a small
+ * number of different sizes, and keeps free lists of each size. Blocks that
+ * don't exactly fit are passed up to the next larger size. In this
+ * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long.
+ * This is designed for use in a virtual memory environment.
+ *
+ * Modified for Xen Mini-OS:
+ * + allocate backing storage with page_alloc() instead of sbrk()
+ * + support alignment
+ * + use ANSI C (hey, there's no rush!)
+ */
+
+#ifdef MEMALLOC_TESTING
+#define PAGE_SIZE getpagesize()
+#define MSTATS
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#if defined(RCHECK)
+#include <sys/uio.h>
+#endif
+#if defined(RCHECK) || defined(MSTATS)
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#else
+
+#include <bmk-core/core.h>
+#include <bmk-core/string.h>
+#include <bmk-core/memalloc.h>
+#include <bmk-core/platform.h>
+
+#define NULL (void *)0
+#define ASSERT(x)
+
+#endif
+
+
+/*
+ * The overhead on a block is at least 4 bytes. When free, this space
+ * contains a pointer to the next free block, and the bottom two bits must
+ * be zero. When in use, the first byte is set to MAGIC, and the second
+ * byte is the size index. The remaining bytes are for alignment.
+ * If range checking is enabled then a second word holds the size of the
+ * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
+ * The order of elements is critical: ov_magic must overlay the low order
+ * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
+ */
+union overhead {
+ union overhead *ov_next; /* when free */
+ struct {
+ unsigned long ovu_alignpad; /* padding for alignment */
+ unsigned char ovu_magic; /* magic number */
+ unsigned char ovu_index; /* bucket # */
+#ifdef RCHECK
+ unsigned short ovu_rmagic; /* range magic number */
+ unsigned long ovu_size; /* actual block size */
+#endif
+ } ovu;
+#define ov_alignpad ovu.ovu_alignpad
+#define ov_magic ovu.ovu_magic
+#define ov_index ovu.ovu_index
+#define ov_rmagic ovu.ovu_rmagic
+#define ov_size ovu.ovu_size
+};
+
+#define MAGIC 0xef /* magic # on accounting info */
+#define UNMAGIC 0x12 /* magic # != MAGIC */
+#define UNMAGIC2 0x24 /* magic # != MAGIC/UNMAGIC */
+#ifdef RCHECK
+#define RMAGIC 0x5555 /* magic # on range info */
+#endif
+
+#ifdef RCHECK
+#define RSLOP sizeof (unsigned short)
+#else
+#define RSLOP 0
+#endif
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+MINSHIFT). The
+ * smallest allocatable block is 1<<MINSHIFT bytes. The overhead information
+ * precedes the data area returned to the user.
+ */
+#define MINSHIFT 5
+#define NBUCKETS 30
+#define MINALIGN 16
+static union overhead *nextf[NBUCKETS];
+
+static long pagesz; /* page size */
+static int pagebucket; /* page size bucket */
+
+#ifdef MSTATS
+/*
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+ */
+static u_int nmalloc[NBUCKETS];
+#endif
+
+#if 0
+#ifdef _REENT
+static mutex_t malloc_mutex = MUTEX_INITIALIZER;
+#endif
+#endif
+
+/* not currently reentrant on mini-os */
+#define malloc_lock()
+#define malloc_unlock()
+
+static void morecore(int);
+#ifdef MSTATS
+void mstats(const char *);
+#endif
+
+#if defined(RCHECK) || defined(MEMALLOC_TESTING)
+#define ASSERT(p) if (!(p)) botch(__STRING(p))
+#include <sys/uio.h>
+
+static void botch(const char *);
+
+/*
+ * NOTE: since this may be called while malloc_mutex is locked, stdio must not
+ * be used in this function.
+ */
+static void
+botch(const char *s)
+{
+ struct iovec iov[3];
+
+ iov[0].iov_base = "\nassertion botched: ";
+ iov[0].iov_len = 20;
+ iov[1].iov_base = (void *)s;
+ iov[1].iov_len = strlen(s);
+ iov[2].iov_base = "\n";
+ iov[2].iov_len = 1;
+
+ /*
+ * This place deserves a word of warning: a cancellation point will
+ * occur when executing writev(), and we might be still owning
+ * malloc_mutex. At this point we need to disable cancellation
+ * until `after' abort() because i) establishing a cancellation handler
+ * might, depending on the implementation, result in another malloc()
+ * to be executed, and ii) it is really not desirable to let execution
+ * continue. `Fix me.'
+ *
+ * Note that holding mutex_lock during abort() is safe.
+ */
+
+ (void)writev(STDERR_FILENO, iov, 3);
+ abort();
+}
+#endif
+
+void *
+bmk_memalloc(unsigned long nbytes, unsigned long align)
+{
+ union overhead *op;
+ void *rv;
+ unsigned long allocbytes;
+ int bucket;
+ unsigned amt;
+ unsigned long alignpad;
+
+ malloc_lock();
+
+ if (pagesz == 0) {
+ pagesz = bmk_pagesize;
+ ASSERT(pagesz > 0);
+
+#if 0
+ op = (union overhead *)(void *)sbrk(0);
+ n = n - sizeof (*op) - ((long)op & (n - 1));
+ if (n < 0)
+ n += pagesz;
+ if (n) {
+ if (sbrk((int)n) == (void *)-1) {
+ malloc_unlock();
+ return (NULL);
+ }
+ }
+#endif
+
+ bucket = 0;
+ amt = 1<<MINSHIFT;
+ while (pagesz > amt) {
+ amt <<= 1;
+ bucket++;
+ }
+ pagebucket = bucket;
+ }
+
+ if (align & (align-1))
+ return NULL;
+ if (align < MINALIGN)
+ align = MINALIGN;
+
+ /* need at least this many bytes plus header to satisfy alignment */
+ allocbytes = nbytes + ((sizeof(*op) + (align-1)) & ~(align-1));
+
+ /*
+ * Convert amount of memory requested into closest block size
+ * stored in hash buckets which satisfies request.
+ * Account for space used per block for accounting.
+ */
+ if (allocbytes <= pagesz - RSLOP) {
+#ifndef RCHECK
+ amt = 1<<MINSHIFT; /* size of first bucket */
+ bucket = 0;
+#else
+ amt = 1<<(MINSHIFT+1); /* size of first bucket */
+ bucket = 1;
+#endif
+ } else {
+ amt = (unsigned)pagesz;
+ bucket = pagebucket;
+ }
+ while (allocbytes > amt) {
+ amt <<= 1;
+ if (amt == 0)
+ return (NULL);
+ bucket++;
+ }
+ /*
+ * If nothing in hash bucket right now,
+ * request more memory from the system.
+ */
+ if ((op = nextf[bucket]) == NULL) {
+ morecore(bucket);
+ if ((op = nextf[bucket]) == NULL) {
+ malloc_unlock();
+ return (NULL);
+ }
+ }
+ /* remove from linked list */
+ nextf[bucket] = op->ov_next;
+
+ /* align op before returned memory */
+ rv = (void *)(((unsigned long)(op+1) + align - 1) & ~(align - 1));
+ alignpad = (unsigned long)rv - (unsigned long)op;
+
+#ifdef MEMALLOC_TESTING
+ memset(op, MAGIC, alignpad);
+#endif
+
+ op = ((union overhead *)rv)-1;
+ op->ov_magic = MAGIC;
+ op->ov_index = bucket;
+ op->ov_alignpad = alignpad;
+#ifdef MSTATS
+ nmalloc[bucket]++;
+#endif
+ malloc_unlock();
+#ifdef RCHECK
+ /*
+ * Record allocated size of block and
+ * bound space with magic numbers.
+ */
+ op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
+ op->ov_rmagic = RMAGIC;
+ *(unsigned short *)((char *)(op + 1) + op->ov_size) = RMAGIC;
+#endif
+
+ return rv;
+}
+
+void *
+bmk_xmalloc(unsigned long howmuch)
+{
+ void *rv;
+
+ rv = bmk_memalloc(howmuch, 0);
+ if (rv == NULL)
+ bmk_platform_halt("xmalloc failed");
+ return rv;
+}
+
+void *
+bmk_memcalloc(unsigned long n, unsigned long size)
+{
+ void *v;
+ unsigned long tot = n * size;
+
+ if (size != 0 && tot / size != n)
+ return NULL;
+
+ if ((v = bmk_memalloc(tot, MINALIGN)) != NULL) {
+ bmk_memset(v, 0, tot);
+ }
+ return v;
+}
+
+static void *
+corealloc(int shift)
+{
+ void *v;
+
+#ifdef MEMALLOC_TESTING
+ v = malloc((1<<shift) * pagesz);
+#else
+ v = bmk_platform_allocpg2(shift);
+#endif
+
+ return v;
+}
+
+/*
+ * Allocate more memory to the indicated bucket.
+ */
+static void
+morecore(int bucket)
+{
+ union overhead *op;
+ long sz; /* size of desired block */
+ long amt; /* amount to allocate */
+ long nblks; /* how many blocks we get */
+
+ if (bucket < pagebucket) {
+ amt = 0;
+ nblks = pagesz / (1<<(bucket + MINSHIFT));
+ sz = pagesz / nblks;
+ } else {
+ amt = bucket - pagebucket;
+ nblks = 1;
+ sz = 0; /* dummy */
+ }
+ op = (void *)corealloc(amt);
+ /* no more room! */
+ if (op == NULL)
+ return;
+ /*
+ * Add new memory allocated to that on
+ * free list for this hash bucket.
+ */
+ nextf[bucket] = op;
+ while (--nblks > 0) {
+ op->ov_next =
+ (union overhead *)(void *)((char *)(void *)op+(unsigned long)sz);
+ op = op->ov_next;
+ }
+ op->ov_next = NULL;
+}
+
+void
+bmk_memfree(void *cp)
+{
+ long size;
+ union overhead *op;
+ unsigned long alignpad;
+ void *origp;
+
+ if (cp == NULL)
+ return;
+ op = ((union overhead *)cp)-1;
+ if (op->ov_magic != MAGIC) {
+#ifdef MEMALLOC_TESTING
+ ASSERT(0);
+#endif
+ return; /* sanity */
+ }
+
+#ifdef RCHECK
+ ASSERT(op->ov_rmagic == RMAGIC);
+ ASSERT(*(unsigned short *)((char *)(op + 1) + op->ov_size) == RMAGIC);
+#endif
+ size = op->ov_index;
+ alignpad = op->ov_alignpad;
+ ASSERT(size < NBUCKETS);
+
+ malloc_lock();
+ origp = (unsigned char *)cp - alignpad;
+
+#ifdef MEMALLOC_TESTING
+ {
+ unsigned long i;
+
+ for (i = 0;
+ (unsigned char *)origp + i < (unsigned char *)op;
+ i++) {
+ ASSERT(*((unsigned char *)origp + i) == MAGIC);
+
+ }
+ }
+#endif
+
+ op = (void *)origp;
+ op->ov_next = nextf[(unsigned int)size];/* also clobbers ov_magic */
+ nextf[(unsigned int)size] = op;
+#ifdef MSTATS
+ nmalloc[(unsigned long)size]--;
+#endif
+
+ malloc_unlock();
+}
+
+/*
+ * don't do any of "storage compaction" nonsense, "just" the three modes:
+ * + cp == NULL ==> malloc
+ * + nbytes == 0 ==> free
+ * + else ==> realloc
+ */
+void *
+bmk_memrealloc(void *cp, unsigned long nbytes)
+{
+ union overhead *op;
+ unsigned long size;
+ unsigned long alignpad;
+ void *np;
+
+ if (cp == NULL)
+ return bmk_memalloc(nbytes, MINALIGN);
+
+ if (nbytes == 0) {
+ bmk_memfree(cp);
+ return NULL;
+ }
+
+ op = ((union overhead *)cp)-1;
+ size = op->ov_index;
+ alignpad = op->ov_alignpad;
+
+ /* don't bother "compacting". don't like it? don't use realloc! */
+ if (((1<<(size+MINSHIFT)) - alignpad) >= nbytes)
+ return cp;
+
+ /* we're gonna need a bigger bucket */
+ np = bmk_memalloc(nbytes, 8);
+ if (np == NULL)
+ return NULL;
+
+ bmk_memcpy(np, cp, (1<<(size+MINSHIFT)) - alignpad);
+ bmk_memfree(cp);
+ return np;
+}
+
+#ifdef MSTATS
+/*
+ * mstats - print out statistics about malloc
+ *
+ * Prints two lines of numbers, one showing the length of the free list
+ * for each size category, the second showing the number of mallocs -
+ * frees for each size category.
+ */
+void
+mstats(const char *s)
+{
+ int i, j;
+ union overhead *p;
+ int totfree = 0,
+ totused = 0;
+
+ fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
+ for (i = 0; i < NBUCKETS; i++) {
+ for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
+ ;
+ fprintf(stderr, " %d", j);
+ totfree += j * (1 << (i + 3));
+ }
+ fprintf(stderr, "\nused:\t");
+ for (i = 0; i < NBUCKETS; i++) {
+ fprintf(stderr, " %d", nmalloc[i]);
+ totused += nmalloc[i] * (1 << (i + 3));
+ }
+ fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
+ totused, totfree);
+}
+#endif
+
+#ifdef MEMALLOC_TESTING
+
+#define TEST_MINALLOC 0
+#define TEST_MAXALLOC 64*1024
+
+#define TEST_MINALIGN 1
+#define TEST_MAXALIGN 16
+
+#define NALLOC 1024
+#define NRING 16
+
+static void *
+testalloc(void)
+{
+ void *v, *nv;
+ size_t size1, size2, align;
+
+ /* doesn't give an even bucket distribution, but ... */
+ size1 = random() % ((TEST_MAXALLOC-TEST_MINALLOC)+1) + TEST_MINALLOC;
+ align = random() % ((TEST_MAXALIGN-TEST_MINALIGN)+1) + TEST_MINALIGN;
+
+ v = bmk_memalloc(size1, 1<<align);
+ if (!v)
+ return NULL;
+ ASSERT(((uintptr_t)v & (align-1)) == 0);
+ memset(v, UNMAGIC, size1);
+
+ size2 = random() % ((TEST_MAXALLOC-TEST_MINALLOC)+1) + TEST_MINALLOC;
+ nv = memrealloc(v, size2);
+ if (nv) {
+ memset(nv, UNMAGIC2, size2);
+ return nv;
+ }
+
+ return size2 ? v : NULL;
+}
+
+int
+main()
+{
+ void **rings; /* yay! */
+ void **ring_alloc, **ring_free; /* yay! */
+ int i, n;
+
+ srandom(time(NULL));
+
+ rings = malloc(NALLOC * NRING * sizeof(void *));
+ /* so we can free() immediately without stress */
+ memset(rings, 0, NALLOC * NRING * sizeof(void *));
+
+ for (n = 0;; n = (n+1) % NRING) {
+ if (n == 0)
+ mstats("");
+
+ ring_alloc = &rings[n * NALLOC];
+ ring_free = &rings[((n + NRING/2) % NRING) * NALLOC];
+ for (i = 0; i < NALLOC; i++) {
+ ring_alloc[i] = testalloc();
+ bmk_memfree(ring_free[i]);
+ }
+ }
+}
+#endif
--- /dev/null
+/*-
+ * Copyright (c) 2007-2015 Antti Kantee. All Rights Reserved.
+ * Copyright (c) 2014 Justin Cormack. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ * File: sched.c
+ * Author: Grzegorz Milos
+ * Changes: Robert Kaiser
+ *
+ * Date: Aug 2005
+ *
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <bmk-core/core.h>
+#include <bmk-core/memalloc.h>
+#include <bmk-core/platform.h>
+#include <bmk-core/printf.h>
+#include <bmk-core/queue.h>
+#include <bmk-core/string.h>
+#include <bmk-core/sched.h>
+
+#define TLS_COUNT 2
+#define NAME_MAXLEN 16
+
+#define THREAD_RUNNABLE 0x01
+#define THREAD_MUSTJOIN 0x02
+#define THREAD_JOINED 0x04
+#define THREAD_EXTSTACK 0x08
+#define THREAD_TIMEDOUT 0x10
+
+struct bmk_thread {
+ char bt_name[NAME_MAXLEN];
+
+ void *bt_tls[TLS_COUNT];
+
+ bmk_time_t bt_wakeup_time;
+
+ int bt_flags;
+ int bt_errno;
+
+ void *bt_stackbase;
+
+ void *bt_cookie;
+
+ /* MD thread control block */
+ struct bmk_tcb bt_tcb;
+
+ TAILQ_ENTRY(bmk_thread) bt_entries;
+};
+
+static TAILQ_HEAD(, bmk_thread) zombies = TAILQ_HEAD_INITIALIZER(zombies);
+static TAILQ_HEAD(, bmk_thread) threads = TAILQ_HEAD_INITIALIZER(threads);
+
+static void (*scheduler_hook)(void *, void *);
+
+static int
+is_runnable(struct bmk_thread *thread)
+{
+
+ return thread->bt_flags & THREAD_RUNNABLE;
+}
+
+static void
+set_runnable(struct bmk_thread *thread)
+{
+
+ thread->bt_flags |= THREAD_RUNNABLE;
+}
+
+static void
+clear_runnable(struct bmk_thread *thread)
+{
+
+ thread->bt_flags &= ~THREAD_RUNNABLE;
+}
+
+static void
+stackalloc(void **stack, unsigned long *ss)
+{
+
+ *stack = bmk_platform_allocpg2(bmk_stackpageorder);
+ *ss = bmk_stacksize;
+}
+
+static void
+stackfree(struct bmk_thread *thread)
+{
+
+ bmk_platform_freepg2(thread->bt_stackbase, bmk_stackpageorder);
+}
+
+static void
+print_threadinfo(struct bmk_thread *thread)
+{
+
+ bmk_printf("thread \"%s\" at %p, flags 0x%x\n",
+ thread->bt_name, thread, thread->bt_flags);
+}
+
+static void
+sched_switch(struct bmk_thread *prev, struct bmk_thread *next)
+{
+
+ if (scheduler_hook)
+ scheduler_hook(prev->bt_cookie, next->bt_cookie);
+ bmk_platform_cpu_sched_switch(&prev->bt_tcb, &next->bt_tcb);
+}
+
+struct bmk_thread *
+bmk_sched_current(void)
+{
+
+ return bmk_cpu_sched_current();
+}
+
+void
+bmk_sched_dumpqueue(void)
+{
+ struct bmk_thread *thr;
+
+ bmk_printf("BEGIN schedqueue dump\n");
+ TAILQ_FOREACH(thr, &threads, bt_entries) {
+ print_threadinfo(thr);
+ }
+ bmk_printf("END schedqueue dump\n");
+}
+
+void
+bmk_sched(void)
+{
+ struct bmk_thread *prev, *next, *thread, *tmp;
+ unsigned long flags;
+
+ prev = bmk_sched_current();
+ flags = bmk_platform_splhigh();
+
+#if 0
+ /* XXX */
+ if (_minios_in_hypervisor_callback) {
+ minios_printk("Must not call schedule() from a callback\n");
+ BUG();
+ }
+#endif
+
+ if (flags) {
+ bmk_platform_halt("Must not call sched() with IRQs disabled\n");
+ }
+
+ /* could do time management a bit better here */
+ do {
+ bmk_time_t tm, wakeup;
+
+ /* block domain for max 1s */
+ tm = bmk_clock_monotonic();
+ wakeup = tm + 1*1000*1000*1000ULL;
+
+ next = NULL;
+ TAILQ_FOREACH_SAFE(thread, &threads, bt_entries, tmp) {
+ if (!is_runnable(thread)
+ && thread->bt_wakeup_time >= 0) {
+ if (thread->bt_wakeup_time <= tm) {
+ thread->bt_flags |= THREAD_TIMEDOUT;
+ bmk_sched_wake(thread);
+ } else if (thread->bt_wakeup_time < wakeup)
+ wakeup = thread->bt_wakeup_time;
+ }
+ if (is_runnable(thread)) {
+ next = thread;
+ /* Put this thread on the end of the list */
+ TAILQ_REMOVE(&threads, thread, bt_entries);
+ TAILQ_INSERT_TAIL(&threads, thread, bt_entries);
+ break;
+ }
+ }
+ if (next)
+ break;
+
+ /* sleep for a while */
+ bmk_platform_block(wakeup);
+ } while (1);
+
+ bmk_platform_splx(flags);
+
+ if (prev != next) {
+ sched_switch(prev, next);
+ }
+
+ /* reaper */
+ TAILQ_FOREACH_SAFE(thread, &zombies, bt_entries, tmp) {
+ if (thread != prev) {
+ TAILQ_REMOVE(&zombies, thread, bt_entries);
+ if ((thread->bt_flags & THREAD_EXTSTACK) == 0)
+ stackfree(thread);
+ bmk_memfree(thread);
+ }
+ }
+}
+
+/*
+ * Allocate tls and initialize it.
+ *
+ * XXX: this needs to change in the future so that
+ * we put the tcb in the same space instead of having multiple
+ * random copies flying around.
+ */
+extern const char _tdata_start[], _tdata_end[];
+extern const char _tbss_start[], _tbss_end[];
+static int
+allocothertls(struct bmk_thread *thread)
+{
+ const unsigned long tdatasize = _tdata_end - _tdata_start;
+ const unsigned long tbsssize = _tbss_end - _tbss_start;
+ struct bmk_tcb *tcb = &thread->bt_tcb;
+ char *tlsmem;
+
+ tlsmem = bmk_memalloc(tdatasize + tbsssize, 0);
+
+ bmk_memcpy(tlsmem, _tdata_start, tdatasize);
+ bmk_memset(tlsmem + tdatasize, 0, tbsssize);
+
+ tcb->btcb_tp = (unsigned long)(tlsmem + tdatasize + tbsssize);
+ tcb->btcb_tpsize = tdatasize + tbsssize;
+
+ return 0;
+}
+
+static void
+freeothertls(struct bmk_thread *thread)
+{
+ void *mem;
+
+ mem = (void *)(thread->bt_tcb.btcb_tp-thread->bt_tcb.btcb_tpsize);
+ bmk_memfree(mem);
+}
+
+struct bmk_thread *
+bmk_sched_create(const char *name, void *cookie, int joinable,
+ void (*f)(void *), void *data,
+ void *stack_base, unsigned long stack_size)
+{
+ struct bmk_thread *thread;
+ unsigned long flags;
+
+ thread = bmk_xmalloc(sizeof(*thread));
+ bmk_memset(thread, 0, sizeof(*thread));
+ bmk_strncpy(thread->bt_name, name, sizeof(thread->bt_name)-1);
+
+ if (!stack_base) {
+ bmk_assert(stack_size == 0);
+ stackalloc(&stack_base, &stack_size);
+ } else {
+ thread->bt_flags = THREAD_EXTSTACK;
+ }
+ thread->bt_stackbase = stack_base;
+ if (joinable)
+ thread->bt_flags |= THREAD_MUSTJOIN;
+
+ bmk_cpu_sched_create(thread, &thread->bt_tcb, f, data,
+ stack_base, stack_size);
+
+ thread->bt_cookie = cookie;
+
+ thread->bt_wakeup_time = -1;
+
+ flags = bmk_platform_splhigh();
+ TAILQ_INSERT_TAIL(&threads, thread, bt_entries);
+ bmk_platform_splx(flags);
+
+ allocothertls(thread);
+ set_runnable(thread);
+
+ return thread;
+}
+
+struct join_waiter {
+ struct bmk_thread *jw_thread;
+ struct bmk_thread *jw_wanted;
+ TAILQ_ENTRY(join_waiter) jw_entries;
+};
+static TAILQ_HEAD(, join_waiter) joinwq = TAILQ_HEAD_INITIALIZER(joinwq);
+
+void
+bmk_sched_exit(void)
+{
+ struct bmk_thread *thread = bmk_sched_current();
+ struct join_waiter *jw_iter;
+ unsigned long flags;
+
+ /* if joinable, gate until we are allowed to exit */
+ flags = bmk_platform_splhigh();
+ while (thread->bt_flags & THREAD_MUSTJOIN) {
+ thread->bt_flags |= THREAD_JOINED;
+ bmk_platform_splx(flags);
+
+ /* see if the joiner is already there */
+ TAILQ_FOREACH(jw_iter, &joinwq, jw_entries) {
+ if (jw_iter->jw_wanted == thread) {
+ bmk_sched_wake(jw_iter->jw_thread);
+ break;
+ }
+ }
+ bmk_sched_block(thread);
+ bmk_sched();
+ flags = bmk_platform_splhigh();
+ }
+ freeothertls(thread);
+
+ /* Remove from the thread list */
+ TAILQ_REMOVE(&threads, thread, bt_entries);
+ clear_runnable(thread);
+ /* Put onto exited list */
+ TAILQ_INSERT_HEAD(&zombies, thread, bt_entries);
+ bmk_platform_splx(flags);
+
+ /* bye */
+ bmk_sched();
+ bmk_platform_halt("schedule() returned for a dead thread!\n");
+}
+
+void
+bmk_sched_join(struct bmk_thread *joinable)
+{
+ struct join_waiter jw;
+ struct bmk_thread *thread = bmk_sched_current();
+ unsigned long flags;
+
+ bmk_assert(joinable->bt_flags & THREAD_MUSTJOIN);
+
+ flags = bmk_platform_splhigh();
+ /* wait for exiting thread to hit thread_exit() */
+ while ((joinable->bt_flags & THREAD_JOINED) == 0) {
+ bmk_platform_splx(flags);
+
+ jw.jw_thread = thread;
+ jw.jw_wanted = joinable;
+ TAILQ_INSERT_TAIL(&joinwq, &jw, jw_entries);
+ bmk_sched_block(thread);
+ bmk_sched();
+ TAILQ_REMOVE(&joinwq, &jw, jw_entries);
+
+ flags = bmk_platform_splhigh();
+ }
+
+ /* signal exiting thread that we have seen it and it may now exit */
+ bmk_assert(joinable->bt_flags & THREAD_JOINED);
+ joinable->bt_flags &= ~THREAD_MUSTJOIN;
+ bmk_platform_splx(flags);
+
+ bmk_sched_wake(joinable);
+}
+
+void
+bmk_sched_block_timeout(struct bmk_thread *thread, bmk_time_t deadline)
+{
+
+ thread->bt_wakeup_time = deadline;
+ clear_runnable(thread);
+}
+
+void
+bmk_sched_block(struct bmk_thread *thread)
+{
+
+ bmk_sched_block_timeout(thread, -1);
+}
+
+int
+bmk_sched_nanosleep_abstime(bmk_time_t nsec)
+{
+ struct bmk_thread *thread = bmk_sched_current();
+ int rv;
+
+ thread->bt_flags &= ~THREAD_TIMEDOUT;
+ thread->bt_wakeup_time = nsec;
+ clear_runnable(thread);
+ bmk_sched();
+
+ rv = !!(thread->bt_flags & THREAD_TIMEDOUT);
+ thread->bt_flags &= ~THREAD_TIMEDOUT;
+ return rv;
+}
+
+int
+bmk_sched_nanosleep(bmk_time_t nsec)
+{
+
+ return bmk_sched_nanosleep_abstime(nsec + bmk_clock_monotonic());
+}
+
+void
+bmk_sched_wake(struct bmk_thread *thread)
+{
+
+ thread->bt_wakeup_time = -1;
+ set_runnable(thread);
+}
+
+void
+bmk_sched_init(void (*mainfun)(void *), void *arg)
+{
+ struct bmk_thread *mainthread;
+ struct bmk_thread initthread;
+
+ mainthread = bmk_sched_create("main", NULL, 0, mainfun, arg, NULL, 0);
+ if (mainthread == NULL)
+ bmk_platform_halt("failed to create main thread");
+
+ bmk_memset(&initthread, 0, sizeof(initthread));
+ bmk_strcpy(initthread.bt_name, "init");
+ sched_switch(&initthread, mainthread);
+
+ bmk_platform_halt("bmk_sched_init unreachable");
+}
+
+void
+bmk_sched_set_hook(void (*f)(void *, void *))
+{
+
+ scheduler_hook = f;
+}
+
+struct bmk_thread *
+bmk_sched_init_mainlwp(void *cookie)
+{
+ struct bmk_thread *current = bmk_sched_current();
+
+ current->bt_cookie = cookie;
+ allocothertls(current);
+ return current;
+}
+
+const char *
+bmk_sched_threadname(struct bmk_thread *thread)
+{
+
+ return thread->bt_name;
+}
+
+int *
+bmk_sched_geterrno(void)
+{
+ struct bmk_thread *thread = bmk_sched_current();
+
+ return &thread->bt_errno;
+}
+
+void
+bmk_sched_settls(struct bmk_thread *thread, unsigned int which, void *value)
+{
+
+ if (which >= TLS_COUNT) {
+ bmk_platform_halt("out of bmk sched tls space");
+ }
+ thread->bt_tls[which] = value;
+}
+
+void *
+bmk_sched_gettls(struct bmk_thread *thread, unsigned int which)
+{
+
+ if (which >= TLS_COUNT) {
+ bmk_platform_halt("out of bmk sched tls space");
+ }
+ return thread->bt_tls[which];
+}
+
+void
+bmk_sched_yield(void)
+{
+ struct bmk_thread *current = bmk_sched_current();
+
+ TAILQ_REMOVE(&threads, current, bt_entries);
+ TAILQ_INSERT_TAIL(&threads, current, bt_entries);
+ bmk_sched();
+}
--- /dev/null
+/* $NetBSD: subr_prf.c,v 1.157 2015/02/04 07:10:47 msaitoh Exp $ */
+
+/*-
+ * Copyright (c) 1986, 1988, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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. 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.
+ *
+ * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95
+ */
+
+/*
+ * This is the NetBSD kernel printf code heavily stripped. Format support
+ * is the same, but the wrappers for calling printf have been reduced
+ * down to:
+ * + printf
+ * + snprintf
+ * + vnsprintf
+ */
+
+#define _BMK_PRINTF_VA
+#include <bmk-core/null.h>
+#include <bmk-core/printf.h>
+#include <bmk-core/string.h>
+
+#define TOBUFONLY 0x01
+#define TOCONS 0x02
+
+#define __UNCONST(x) ((void *)(unsigned long)(x))
+#define KPRINTF_BUFSIZE (sizeof(long long)*8/3 + 2)
+
+/*
+ * local prototypes
+ */
+
+static void cons_putchar(int, int);
+static int kprintf(const char *, int, void *, char *, va_list);
+
+/*
+ * globals
+ */
+
+static void
+nullfun(void)
+{
+
+ return;
+}
+
+static void (*v_flush)(void);
+static void (*v_putc)(int);
+
+void
+bmk_printf_init(void (*putc)(int), void (*flush)(void))
+{
+
+ v_putc = putc;
+ if (flush == NULL)
+ flush = nullfun;
+ v_flush = flush;
+}
+
+static const char hexdigits[] = "0123456789abcdef";
+static const char HEXDIGITS[] = "0123456789ABCDEF";
+
+/*
+ * functions
+ */
+
+/* dmesg ring buffer */
+#ifndef BMK_DMESG_SIZE
+#define BMK_DMESG_SIZE (16*1024)
+#endif
+static char bmk_dmesg[BMK_DMESG_SIZE];
+static int bmk_dmesgoff;
+
+/*
+ * putchar: print a single character on console or user terminal.
+ *
+ * => if console, then the last MSGBUFS chars are saved in msgbuf
+ * for inspection later (e.g. dmesg/syslog)
+ * => we must already be in the mutex!
+ */
+static void
+cons_putchar(int c, int flags)
+{
+
+ bmk_dmesg[bmk_dmesgoff] = c;
+ if (++bmk_dmesgoff == sizeof(bmk_dmesg)-1)
+ bmk_dmesgoff = 0;
+ (*v_putc)(c);
+}
+
+static void
+kprintf_lock(void)
+{
+
+ /* XXX */
+}
+
+static void
+kprintf_unlock(void)
+{
+
+ /* XXX */
+}
+
+/*
+ * bmk_printf: print a message to the console
+ */
+void
+bmk_printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ kprintf_lock();
+
+ va_start(ap, fmt);
+ kprintf(fmt, TOCONS, NULL, NULL, ap);
+ va_end(ap);
+
+ kprintf_unlock();
+}
+
+/*
+ * bmk_vprintf: print a message to the console [already have
+ * va_list]
+ */
+void
+bmk_vprintf(const char *fmt, va_list ap)
+{
+ kprintf_lock();
+
+ kprintf(fmt, TOCONS, NULL, NULL, ap);
+
+ kprintf_unlock();
+}
+
+/*
+ * bmk_snprintf: print a message to a buffer
+ */
+int
+bmk_snprintf(char *bf, unsigned long size, const char *fmt, ...)
+{
+ int retval;
+ va_list ap;
+
+ va_start(ap, fmt);
+ retval = bmk_vsnprintf(bf, size, fmt, ap);
+ va_end(ap);
+
+ return retval;
+}
+
+/*
+ * bmk_vsnprintf: print a message to a buffer [already have va_list]
+ */
+int
+bmk_vsnprintf(char *bf, unsigned long size, const char *fmt, va_list ap)
+{
+ int retval;
+ char *p;
+
+ p = bf + size;
+ retval = kprintf(fmt, TOBUFONLY, &p, bf, ap);
+ if (bf && size > 0) {
+ /* nul terminate */
+ if (size <= (unsigned long)retval)
+ bf[size - 1] = '\0';
+ else
+ bf[retval] = '\0';
+ }
+ return retval;
+}
+
+/*
+ * kprintf: scaled down version of printf(3).
+ *
+ * this version based on vfprintf() from libc which was derived from
+ * software contributed to Berkeley by Chris Torek.
+ *
+ * NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS!
+ */
+
+/*
+ * macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) ((unsigned)to_digit(c) <= 9)
+#define to_char(n) ((n) + '0')
+
+/*
+ * flags used during conversion.
+ */
+#define ALT 0x001 /* alternate form */
+#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
+#define LADJUST 0x004 /* left adjustment */
+#define LONGDBL 0x008 /* long double; unimplemented */
+#define LONGINT 0x010 /* long integer */
+#define QUADINT 0x020 /* quad integer */
+#define SHORTINT 0x040 /* short integer */
+#define MAXINT 0x080 /* intmax_t */
+#define PTRINT 0x100 /* intptr_t */
+#define SIZEINT 0x200 /* size_t */
+#define ZEROPAD 0x400 /* zero (as opposed to blank) pad */
+#define FPT 0x800 /* Floating point number */
+
+ /*
+ * To extend shorts properly, we need both signed and unsigned
+ * argument extraction methods.
+ */
+#define SARG() \
+ (flags&MAXINT ? va_arg(ap, long long) : \
+ flags&PTRINT ? va_arg(ap, long) : \
+ flags&SIZEINT ? va_arg(ap, long) : /* XXX */ \
+ flags&QUADINT ? va_arg(ap, long long) : \
+ flags&LONGINT ? va_arg(ap, long) : \
+ flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
+ (long)va_arg(ap, int))
+#define UARG() \
+ (flags&MAXINT ? va_arg(ap, unsigned long long) : \
+ flags&PTRINT ? va_arg(ap, unsigned long) : \
+ flags&SIZEINT ? va_arg(ap, unsigned long) : \
+ flags&QUADINT ? va_arg(ap, unsigned long long) : \
+ flags&LONGINT ? va_arg(ap, unsigned long) : \
+ flags&SHORTINT ? (unsigned long)(unsigned long)va_arg(ap, int) : \
+ (unsigned long)va_arg(ap, unsigned int))
+
+#define KPRINTF_PUTCHAR(C) { \
+ if (oflags == TOBUFONLY) { \
+ if (sbuf && ((vp == NULL) || (sbuf < tailp))) \
+ *sbuf++ = (C); \
+ } else { \
+ cons_putchar((C), oflags); \
+ } \
+}
+
+/*
+ * Guts of kernel printf. Note, we already expect to be in a mutex!
+ */
+static int
+kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap)
+{
+ int ret = 0; /* return value accumulator */
+ const char *fmt; /* format string */
+ int ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ char *cp; /* handy char pointer (short term usage) */
+ int flags; /* flags as above */
+ int width; /* width from format (%8d), or 0 */
+ int prec; /* precision from format (%.3d), or -1 */
+ char sign; /* sign prefix (' ', '+', '-', or \0) */
+
+ unsigned long long _uquad; /* integer arguments %[diouxX] */
+ enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
+ int dprec; /* a copy of prec if [diouxX], 0 otherwise */
+ int realsz; /* field size expanded by dprec */
+ int size; /* size of converted field or string */
+ const char *xdigs; /* digits for [xX] conversion */
+ char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
+ char *tailp; /* tail pointer for snprintf */
+
+ if (oflags == TOBUFONLY && (vp != NULL))
+ tailp = *(char **)vp;
+ else
+ tailp = NULL;
+
+ cp = NULL; /* XXX: shutup gcc */
+ size = 0; /* XXX: shutup gcc */
+
+ fmt = fmt0;
+ ret = 0;
+
+ xdigs = NULL; /* XXX: shut up gcc warning */
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (; *fmt != '%' && *fmt; fmt++) {
+ ret++;
+ KPRINTF_PUTCHAR(*fmt);
+ }
+ if (*fmt == 0)
+ goto done;
+
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ dprec = 0;
+ width = 0;
+ prec = -1;
+ sign = '\0';
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ /*
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (!sign)
+ sign = ' ';
+ goto rflag;
+ case '#':
+ flags |= ALT;
+ goto rflag;
+ case '*':
+ /*
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ if ((width = va_arg(ap, int)) >= 0)
+ goto rflag;
+ width = -width;
+ /* FALLTHROUGH */
+ case '-':
+ flags |= LADJUST;
+ goto rflag;
+ case '+':
+ sign = '+';
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ n = va_arg(ap, int);
+ prec = n < 0 ? -1 : n;
+ goto rflag;
+ }
+ n = 0;
+ while (is_digit(ch)) {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ }
+ prec = n < 0 ? -1 : n;
+ goto reswitch;
+ case '0':
+ /*
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ flags |= ZEROPAD;
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ width = n;
+ goto reswitch;
+ case 'h':
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= MAXINT;
+ goto rflag;
+ case 'l':
+ if (*fmt == 'l') {
+ fmt++;
+ flags |= QUADINT;
+ } else {
+ flags |= LONGINT;
+ }
+ goto rflag;
+ case 'q':
+ flags |= QUADINT;
+ goto rflag;
+ case 't':
+ flags |= PTRINT;
+ goto rflag;
+ case 'z':
+ flags |= SIZEINT;
+ goto rflag;
+ case 'c':
+ *(cp = bf) = va_arg(ap, int);
+ size = 1;
+ sign = '\0';
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ _uquad = SARG();
+ if ((long long)_uquad < 0) {
+ _uquad = -_uquad;
+ sign = '-';
+ }
+ base = DEC;
+ goto number;
+ case 'n':
+ if (flags & MAXINT)
+ *va_arg(ap, long long *) = ret;
+ else if (flags & PTRINT)
+ *va_arg(ap, long *) = ret;
+ else if (flags & SIZEINT)
+ *va_arg(ap, long *) = ret;
+ else if (flags & QUADINT)
+ *va_arg(ap, long long *) = ret;
+ else if (flags & LONGINT)
+ *va_arg(ap, long *) = ret;
+ else if (flags & SHORTINT)
+ *va_arg(ap, short *) = ret;
+ else
+ *va_arg(ap, int *) = ret;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ _uquad = UARG();
+ base = OCT;
+ goto nosign;
+ case 'p':
+ /*
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ /* NOSTRICT */
+ _uquad = (unsigned long)va_arg(ap, void *);
+ base = HEX;
+ xdigs = hexdigits;
+ flags |= HEXPREFIX;
+ ch = 'x';
+ goto nosign;
+ case 's':
+ if ((cp = va_arg(ap, char *)) == NULL)
+ /*XXXUNCONST*/
+ cp = __UNCONST("(null)");
+ if (prec >= 0) {
+ /*
+ * can't use strlen; can only look for the
+ * NUL in the first `prec' characters, and
+ * strlen() will go further.
+ */
+ char *p = bmk_memchr(cp, 0, prec);
+
+ if (p != NULL) {
+ size = p - cp;
+ if (size > prec)
+ size = prec;
+ } else
+ size = prec;
+ } else
+ size = bmk_strlen(cp);
+ sign = '\0';
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ _uquad = UARG();
+ base = DEC;
+ goto nosign;
+ case 'X':
+ xdigs = HEXDIGITS;
+ goto hex;
+ case 'x':
+ xdigs = hexdigits;
+hex: _uquad = UARG();
+ base = HEX;
+ /* leading 0x/X only if non-zero */
+ if (flags & ALT && _uquad != 0)
+ flags |= HEXPREFIX;
+
+ /* unsigned conversions */
+nosign: sign = '\0';
+ /*
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+
+ /*
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ */
+ cp = bf + KPRINTF_BUFSIZE;
+ if (_uquad != 0 || prec != 0) {
+ /*
+ * Unsigned mod is hard, and unsigned mod
+ * by a constant is easier than that by
+ * a variable; hence this switch.
+ */
+ switch (base) {
+ case OCT:
+ do {
+ *--cp = to_char(_uquad & 7);
+ _uquad >>= 3;
+ } while (_uquad);
+ /* handle octal leading 0 */
+ if (flags & ALT && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case DEC:
+ /* many numbers are 1 digit */
+ while (_uquad >= 10) {
+ *--cp = to_char(_uquad % 10);
+ _uquad /= 10;
+ }
+ *--cp = to_char(_uquad);
+ break;
+
+ case HEX:
+ do {
+ *--cp = xdigs[_uquad & 15];
+ _uquad >>= 4;
+ } while (_uquad);
+ break;
+
+ default:
+ /*XXXUNCONST*/
+ cp = __UNCONST("bug in kprintf: bad base");
+ size = bmk_strlen(cp);
+ goto skipsize;
+ }
+ }
+ size = bf + KPRINTF_BUFSIZE - cp;
+ skipsize:
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ /* pretend it was %c with argument ch */
+ cp = bf;
+ *cp = ch;
+ size = 1;
+ sign = '\0';
+ break;
+ }
+
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal [diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * size excludes decimal prec; realsz includes it.
+ */
+ realsz = dprec > size ? dprec : size;
+ if (sign)
+ realsz++;
+ else if (flags & HEXPREFIX)
+ realsz+= 2;
+
+ /* adjust ret */
+ ret += width > realsz ? width : realsz;
+
+ /* right-adjusting blank padding */
+ if ((flags & (LADJUST|ZEROPAD)) == 0) {
+ n = width - realsz;
+ while (n-- > 0)
+ KPRINTF_PUTCHAR(' ');
+ }
+
+ /* prefix */
+ if (sign) {
+ KPRINTF_PUTCHAR(sign);
+ } else if (flags & HEXPREFIX) {
+ KPRINTF_PUTCHAR('0');
+ KPRINTF_PUTCHAR(ch);
+ }
+
+ /* right-adjusting zero padding */
+ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
+ n = width - realsz;
+ while (n-- > 0)
+ KPRINTF_PUTCHAR('0');
+ }
+
+ /* leading zeroes from decimal precision */
+ n = dprec - size;
+ while (n-- > 0)
+ KPRINTF_PUTCHAR('0');
+
+ /* the string or number proper */
+ for (; size--; cp++)
+ KPRINTF_PUTCHAR(*cp);
+ /* left-adjusting padding (always blank) */
+ if (flags & LADJUST) {
+ n = width - realsz;
+ while (n-- > 0)
+ KPRINTF_PUTCHAR(' ');
+ }
+ }
+
+done:
+ if ((oflags == TOBUFONLY) && (vp != NULL))
+ *(char **)vp = sbuf;
+ (*v_flush)();
+
+ return ret;
+}
+++ /dev/null
-LIB= rumprun_core
-LIBISPRIVATE= # defined
-
-SRCS= init.c bmk_string.c memalloc.c sched.c subr_prf.c
-
-CPPFLAGS+= -I${.CURDIR}/../../include
-
-.include "${.CURDIR}/arch/${MACHINE}/Makefile.inc"
-
-.include <bsd.lib.mk>
+++ /dev/null
-MYDIR:= ${.PARSEDIR}
-.PATH: ${MYDIR}
-
-SRCS+= cpu_sched_switch.S
-
-.include "${MYDIR}/../x86/Makefile.inc"
+++ /dev/null
-/*-
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: sched.c
- * Author: Grzegorz Milos
- * Changes: Robert Kaiser
- *
- * Date: Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: simple scheduler for Mini-Os
- *
- * The scheduler is non-preemptive (cooperative), and schedules according
- * to Round Robin algorithm.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <bmk-core/amd64/asm.h>
-
-ENTRY(bmk_cpu_sched_bouncer)
- popq %rdi
- popq %rbx
- pushq $0 /* correct stack alignment for SSE */
- pushq $0
- xorq %rbp,%rbp
- call *%rbx
- call bmk_sched_exit
-END(bmk_cpu_sched_bouncer)
-
-ENTRY(bmk__cpu_switch)
- pushq %rbp
- pushq %rbx
- pushq %r12
- pushq %r13
- pushq %r14
- pushq %r15
- movq %rsp, (%rdi) /* save ESP */
- movq (%rsi), %rsp /* restore ESP */
- movq $1f, 8(%rdi) /* save EIP */
- pushq 8(%rsi) /* restore EIP */
- ret
-1:
- popq %r15
- popq %r14
- popq %r13
- popq %r12
- popq %rbx
- popq %rbp
- ret
-END(bmk__cpu_switch)
+++ /dev/null
-MYDIR:= ${.PARSEDIR}
-.PATH: ${MYDIR}
-
-SRCS+= cpu_sched_switch.S
-
-.include "${MYDIR}/../x86/Makefile.inc"
+++ /dev/null
-/*-
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: sched.c
- * Author: Grzegorz Milos
- * Changes: Robert Kaiser
- *
- * Date: Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: simple scheduler for Mini-Os
- *
- * The scheduler is non-preemptive (cooperative), and schedules according
- * to Round Robin algorithm.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <bmk-core/i386/asm.h>
-
-ENTRY(bmk_cpu_sched_bouncer)
- popl %eax
- popl %ebx
- pushl $0
- xorl %ebp,%ebp
- pushl %eax
- call *%ebx
- call bmk_sched_exit
-END(bmk_cpu_sched_bouncer)
-
-ENTRY(bmk__cpu_switch)
- movl 4(%esp), %ecx /* prev */
- movl 8(%esp), %edx /* next */
-
- /* reload tls for new thread */
- movl $0x18, %eax
- movl %eax, %gs
-
- pushl %ebp
- pushl %ebx
- pushl %esi
- pushl %edi
- movl %esp, (%ecx) /* save ESP */
- movl (%edx), %esp /* restore ESP */
- movl $1f, 4(%ecx) /* save EIP */
- pushl 4(%edx) /* restore EIP */
- ret
-1:
- popl %edi
- popl %esi
- popl %ebx
- popl %ebp
- ret
-END(bmk__cpu_switch)
+++ /dev/null
-X86DIR:=${.PARSEDIR}
-.PATH: ${X86DIR}
-
-SRCS+= cpu_sched.c
+++ /dev/null
-/*
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: sched.c
- * Author: Grzegorz Milos
- * Changes: Robert Kaiser
- *
- * Date: Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: simple scheduler for Mini-Os
- *
- * The scheduler is non-preemptive (cooperative), and schedules according
- * to Round Robin algorithm.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <bmk-core/core.h>
-#include <bmk-core/sched.h>
-
-static void
-stack_push(void **stackp, unsigned long value)
-{
- unsigned long *stack = *stackp;
-
- stack--;
- *stack = value;
- *stackp = stack;
-}
-
-void
-bmk_cpu_sched_create(struct bmk_thread *thread, struct bmk_tcb *tcb,
- void (*f)(void *), void *arg,
- void *stack_base, unsigned long stack_size)
-{
- void *stack_top = (char *)stack_base + stack_size;
-
- /* Save pointer to the thread on the stack, used by current macro */
- *(unsigned long *)stack_base = (unsigned long)thread;
-
- /* these values are used by bmk_cpu_sched_bouncer() */
- stack_push(&stack_top, (unsigned long)f);
- stack_push(&stack_top, (unsigned long)arg);
-
- tcb->btcb_sp = (unsigned long)stack_top;
- tcb->btcb_ip = (unsigned long)bmk_cpu_sched_bouncer;
-}
-
-struct bmk_thread *
-bmk_cpu_sched_current(void)
-{
- struct bmk_thread **current;
-
- current = (void *)((unsigned long)¤t & ~(bmk_stacksize-1));
- return *current;
-};
+++ /dev/null
-/*-
- * Copyright (c) 2014 Antti Kantee. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- */
-
-/*
- * The assumption is that these won't be used very often,
- * only for the very low-level routines.
- *
- * Some code from public domain implementations.
- */
-
-#include <bmk-core/null.h>
-#include <bmk-core/string.h>
-
-unsigned long
-bmk_strlen(const char *str)
-{
- unsigned long rv = 0;
-
- while (*str++)
- rv++;
- return rv;
-}
-
-int
-bmk_strcmp(const char *a, const char *b)
-{
-
- while (*a && *a++ == *b++) {
- continue;
- }
- if (*a) {
- a--;
- b--;
- }
- return *a - *b;
-}
-
-int
-bmk_strncmp(const char *a, const char *b, unsigned long n)
-{
- unsigned char u1, u2;
-
- while (n-- > 0) {
- u1 = (unsigned char)*a++;
- u2 = (unsigned char)*b++;
- if (u1 != u2)
- return u1 - u2;
- if (u1 == '\0')
- return 0;
- }
- return 0;
-}
-
-char *
-bmk_strcpy(char *d, const char *s)
-{
- char *orig = d;
-
- while ((*d++ = *s++) != '\0')
- continue;
- return orig;
-}
-
-char *
-bmk_strncpy(char *d, const char *s, unsigned long n)
-{
- char *orig = d;
-
- while ((*d++ = *s++) && n--)
- continue;
- while (n--)
- *d++ = '\0';
- return orig;
-}
-
-void *
-bmk_memset(void *b, int c, unsigned long n)
-{
- unsigned char *v = b;
-
- while (n--)
- *v++ = (unsigned char)c;
-
- return b;
-}
-
-void *
-bmk_memcpy(void *d, const void *src, unsigned long n)
-{
- unsigned char *dp;
- const unsigned char *sp;
-
- dp = d;
- sp = src;
-
- while (n--)
- *dp++ = *sp++;
-
- return d;
-}
-
-void *
-bmk_memchr(const void *d, int c, unsigned long n)
-{
- const unsigned char *p = d;
-
- while (n--) {
- if (*p == (unsigned char)c)
- return (void *)(unsigned long)p;
- p++;
- }
- return NULL;
-}
+++ /dev/null
-/*-
- * Copyright (c) 2015 Antti Kantee. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- */
-
-#include <bmk-core/core.h>
-
-unsigned long bmk_stackpageorder;
-unsigned long bmk_stacksize;
-unsigned long bmk_pagesize;
-
-int
-bmk_core_init(unsigned long stackpageorder, unsigned long pagesize)
-{
-
- bmk_stackpageorder = stackpageorder;
- bmk_stacksize = (1<<stackpageorder) * pagesize;
- bmk_pagesize = pagesize;
-
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Antti Kantee. All rights reserved.
- * Copyright (c) 1983, 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. 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.
- */
-
-/*
- * malloc.c (Caltech) 2/21/82
- * Chris Kingsley, kingsley@cit-20.
- *
- * This is a very fast storage allocator. It allocates blocks of a small
- * number of different sizes, and keeps free lists of each size. Blocks that
- * don't exactly fit are passed up to the next larger size. In this
- * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long.
- * This is designed for use in a virtual memory environment.
- *
- * Modified for Xen Mini-OS:
- * + allocate backing storage with page_alloc() instead of sbrk()
- * + support alignment
- * + use ANSI C (hey, there's no rush!)
- */
-
-#ifdef MEMALLOC_TESTING
-#define PAGE_SIZE getpagesize()
-#define MSTATS
-
-#include <sys/cdefs.h>
-
-#include <sys/types.h>
-#if defined(RCHECK)
-#include <sys/uio.h>
-#endif
-#if defined(RCHECK) || defined(MSTATS)
-#include <stdio.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#else
-
-#include <bmk-core/core.h>
-#include <bmk-core/string.h>
-#include <bmk-core/memalloc.h>
-#include <bmk-core/platform.h>
-
-#define NULL (void *)0
-#define ASSERT(x)
-
-#endif
-
-
-/*
- * The overhead on a block is at least 4 bytes. When free, this space
- * contains a pointer to the next free block, and the bottom two bits must
- * be zero. When in use, the first byte is set to MAGIC, and the second
- * byte is the size index. The remaining bytes are for alignment.
- * If range checking is enabled then a second word holds the size of the
- * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
- * The order of elements is critical: ov_magic must overlay the low order
- * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
- */
-union overhead {
- union overhead *ov_next; /* when free */
- struct {
- unsigned long ovu_alignpad; /* padding for alignment */
- unsigned char ovu_magic; /* magic number */
- unsigned char ovu_index; /* bucket # */
-#ifdef RCHECK
- unsigned short ovu_rmagic; /* range magic number */
- unsigned long ovu_size; /* actual block size */
-#endif
- } ovu;
-#define ov_alignpad ovu.ovu_alignpad
-#define ov_magic ovu.ovu_magic
-#define ov_index ovu.ovu_index
-#define ov_rmagic ovu.ovu_rmagic
-#define ov_size ovu.ovu_size
-};
-
-#define MAGIC 0xef /* magic # on accounting info */
-#define UNMAGIC 0x12 /* magic # != MAGIC */
-#define UNMAGIC2 0x24 /* magic # != MAGIC/UNMAGIC */
-#ifdef RCHECK
-#define RMAGIC 0x5555 /* magic # on range info */
-#endif
-
-#ifdef RCHECK
-#define RSLOP sizeof (unsigned short)
-#else
-#define RSLOP 0
-#endif
-
-/*
- * nextf[i] is the pointer to the next free block of size 2^(i+MINSHIFT). The
- * smallest allocatable block is 1<<MINSHIFT bytes. The overhead information
- * precedes the data area returned to the user.
- */
-#define MINSHIFT 5
-#define NBUCKETS 30
-#define MINALIGN 16
-static union overhead *nextf[NBUCKETS];
-
-static long pagesz; /* page size */
-static int pagebucket; /* page size bucket */
-
-#ifdef MSTATS
-/*
- * nmalloc[i] is the difference between the number of mallocs and frees
- * for a given block size.
- */
-static u_int nmalloc[NBUCKETS];
-#endif
-
-#if 0
-#ifdef _REENT
-static mutex_t malloc_mutex = MUTEX_INITIALIZER;
-#endif
-#endif
-
-/* not currently reentrant on mini-os */
-#define malloc_lock()
-#define malloc_unlock()
-
-static void morecore(int);
-#ifdef MSTATS
-void mstats(const char *);
-#endif
-
-#if defined(RCHECK) || defined(MEMALLOC_TESTING)
-#define ASSERT(p) if (!(p)) botch(__STRING(p))
-#include <sys/uio.h>
-
-static void botch(const char *);
-
-/*
- * NOTE: since this may be called while malloc_mutex is locked, stdio must not
- * be used in this function.
- */
-static void
-botch(const char *s)
-{
- struct iovec iov[3];
-
- iov[0].iov_base = "\nassertion botched: ";
- iov[0].iov_len = 20;
- iov[1].iov_base = (void *)s;
- iov[1].iov_len = strlen(s);
- iov[2].iov_base = "\n";
- iov[2].iov_len = 1;
-
- /*
- * This place deserves a word of warning: a cancellation point will
- * occur when executing writev(), and we might be still owning
- * malloc_mutex. At this point we need to disable cancellation
- * until `after' abort() because i) establishing a cancellation handler
- * might, depending on the implementation, result in another malloc()
- * to be executed, and ii) it is really not desirable to let execution
- * continue. `Fix me.'
- *
- * Note that holding mutex_lock during abort() is safe.
- */
-
- (void)writev(STDERR_FILENO, iov, 3);
- abort();
-}
-#endif
-
-void *
-bmk_memalloc(unsigned long nbytes, unsigned long align)
-{
- union overhead *op;
- void *rv;
- unsigned long allocbytes;
- int bucket;
- unsigned amt;
- unsigned long alignpad;
-
- malloc_lock();
-
- if (pagesz == 0) {
- pagesz = bmk_pagesize;
- ASSERT(pagesz > 0);
-
-#if 0
- op = (union overhead *)(void *)sbrk(0);
- n = n - sizeof (*op) - ((long)op & (n - 1));
- if (n < 0)
- n += pagesz;
- if (n) {
- if (sbrk((int)n) == (void *)-1) {
- malloc_unlock();
- return (NULL);
- }
- }
-#endif
-
- bucket = 0;
- amt = 1<<MINSHIFT;
- while (pagesz > amt) {
- amt <<= 1;
- bucket++;
- }
- pagebucket = bucket;
- }
-
- if (align & (align-1))
- return NULL;
- if (align < MINALIGN)
- align = MINALIGN;
-
- /* need at least this many bytes plus header to satisfy alignment */
- allocbytes = nbytes + ((sizeof(*op) + (align-1)) & ~(align-1));
-
- /*
- * Convert amount of memory requested into closest block size
- * stored in hash buckets which satisfies request.
- * Account for space used per block for accounting.
- */
- if (allocbytes <= pagesz - RSLOP) {
-#ifndef RCHECK
- amt = 1<<MINSHIFT; /* size of first bucket */
- bucket = 0;
-#else
- amt = 1<<(MINSHIFT+1); /* size of first bucket */
- bucket = 1;
-#endif
- } else {
- amt = (unsigned)pagesz;
- bucket = pagebucket;
- }
- while (allocbytes > amt) {
- amt <<= 1;
- if (amt == 0)
- return (NULL);
- bucket++;
- }
- /*
- * If nothing in hash bucket right now,
- * request more memory from the system.
- */
- if ((op = nextf[bucket]) == NULL) {
- morecore(bucket);
- if ((op = nextf[bucket]) == NULL) {
- malloc_unlock();
- return (NULL);
- }
- }
- /* remove from linked list */
- nextf[bucket] = op->ov_next;
-
- /* align op before returned memory */
- rv = (void *)(((unsigned long)(op+1) + align - 1) & ~(align - 1));
- alignpad = (unsigned long)rv - (unsigned long)op;
-
-#ifdef MEMALLOC_TESTING
- memset(op, MAGIC, alignpad);
-#endif
-
- op = ((union overhead *)rv)-1;
- op->ov_magic = MAGIC;
- op->ov_index = bucket;
- op->ov_alignpad = alignpad;
-#ifdef MSTATS
- nmalloc[bucket]++;
-#endif
- malloc_unlock();
-#ifdef RCHECK
- /*
- * Record allocated size of block and
- * bound space with magic numbers.
- */
- op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
- op->ov_rmagic = RMAGIC;
- *(unsigned short *)((char *)(op + 1) + op->ov_size) = RMAGIC;
-#endif
-
- return rv;
-}
-
-void *
-bmk_xmalloc(unsigned long howmuch)
-{
- void *rv;
-
- rv = bmk_memalloc(howmuch, 0);
- if (rv == NULL)
- bmk_platform_halt("xmalloc failed");
- return rv;
-}
-
-void *
-bmk_memcalloc(unsigned long n, unsigned long size)
-{
- void *v;
- unsigned long tot = n * size;
-
- if (size != 0 && tot / size != n)
- return NULL;
-
- if ((v = bmk_memalloc(tot, MINALIGN)) != NULL) {
- bmk_memset(v, 0, tot);
- }
- return v;
-}
-
-static void *
-corealloc(int shift)
-{
- void *v;
-
-#ifdef MEMALLOC_TESTING
- v = malloc((1<<shift) * pagesz);
-#else
- v = bmk_platform_allocpg2(shift);
-#endif
-
- return v;
-}
-
-/*
- * Allocate more memory to the indicated bucket.
- */
-static void
-morecore(int bucket)
-{
- union overhead *op;
- long sz; /* size of desired block */
- long amt; /* amount to allocate */
- long nblks; /* how many blocks we get */
-
- if (bucket < pagebucket) {
- amt = 0;
- nblks = pagesz / (1<<(bucket + MINSHIFT));
- sz = pagesz / nblks;
- } else {
- amt = bucket - pagebucket;
- nblks = 1;
- sz = 0; /* dummy */
- }
- op = (void *)corealloc(amt);
- /* no more room! */
- if (op == NULL)
- return;
- /*
- * Add new memory allocated to that on
- * free list for this hash bucket.
- */
- nextf[bucket] = op;
- while (--nblks > 0) {
- op->ov_next =
- (union overhead *)(void *)((char *)(void *)op+(unsigned long)sz);
- op = op->ov_next;
- }
- op->ov_next = NULL;
-}
-
-void
-bmk_memfree(void *cp)
-{
- long size;
- union overhead *op;
- unsigned long alignpad;
- void *origp;
-
- if (cp == NULL)
- return;
- op = ((union overhead *)cp)-1;
- if (op->ov_magic != MAGIC) {
-#ifdef MEMALLOC_TESTING
- ASSERT(0);
-#endif
- return; /* sanity */
- }
-
-#ifdef RCHECK
- ASSERT(op->ov_rmagic == RMAGIC);
- ASSERT(*(unsigned short *)((char *)(op + 1) + op->ov_size) == RMAGIC);
-#endif
- size = op->ov_index;
- alignpad = op->ov_alignpad;
- ASSERT(size < NBUCKETS);
-
- malloc_lock();
- origp = (unsigned char *)cp - alignpad;
-
-#ifdef MEMALLOC_TESTING
- {
- unsigned long i;
-
- for (i = 0;
- (unsigned char *)origp + i < (unsigned char *)op;
- i++) {
- ASSERT(*((unsigned char *)origp + i) == MAGIC);
-
- }
- }
-#endif
-
- op = (void *)origp;
- op->ov_next = nextf[(unsigned int)size];/* also clobbers ov_magic */
- nextf[(unsigned int)size] = op;
-#ifdef MSTATS
- nmalloc[(unsigned long)size]--;
-#endif
-
- malloc_unlock();
-}
-
-/*
- * don't do any of "storage compaction" nonsense, "just" the three modes:
- * + cp == NULL ==> malloc
- * + nbytes == 0 ==> free
- * + else ==> realloc
- */
-void *
-bmk_memrealloc(void *cp, unsigned long nbytes)
-{
- union overhead *op;
- unsigned long size;
- unsigned long alignpad;
- void *np;
-
- if (cp == NULL)
- return bmk_memalloc(nbytes, MINALIGN);
-
- if (nbytes == 0) {
- bmk_memfree(cp);
- return NULL;
- }
-
- op = ((union overhead *)cp)-1;
- size = op->ov_index;
- alignpad = op->ov_alignpad;
-
- /* don't bother "compacting". don't like it? don't use realloc! */
- if (((1<<(size+MINSHIFT)) - alignpad) >= nbytes)
- return cp;
-
- /* we're gonna need a bigger bucket */
- np = bmk_memalloc(nbytes, 8);
- if (np == NULL)
- return NULL;
-
- bmk_memcpy(np, cp, (1<<(size+MINSHIFT)) - alignpad);
- bmk_memfree(cp);
- return np;
-}
-
-#ifdef MSTATS
-/*
- * mstats - print out statistics about malloc
- *
- * Prints two lines of numbers, one showing the length of the free list
- * for each size category, the second showing the number of mallocs -
- * frees for each size category.
- */
-void
-mstats(const char *s)
-{
- int i, j;
- union overhead *p;
- int totfree = 0,
- totused = 0;
-
- fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s);
- for (i = 0; i < NBUCKETS; i++) {
- for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
- ;
- fprintf(stderr, " %d", j);
- totfree += j * (1 << (i + 3));
- }
- fprintf(stderr, "\nused:\t");
- for (i = 0; i < NBUCKETS; i++) {
- fprintf(stderr, " %d", nmalloc[i]);
- totused += nmalloc[i] * (1 << (i + 3));
- }
- fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n",
- totused, totfree);
-}
-#endif
-
-#ifdef MEMALLOC_TESTING
-
-#define TEST_MINALLOC 0
-#define TEST_MAXALLOC 64*1024
-
-#define TEST_MINALIGN 1
-#define TEST_MAXALIGN 16
-
-#define NALLOC 1024
-#define NRING 16
-
-static void *
-testalloc(void)
-{
- void *v, *nv;
- size_t size1, size2, align;
-
- /* doesn't give an even bucket distribution, but ... */
- size1 = random() % ((TEST_MAXALLOC-TEST_MINALLOC)+1) + TEST_MINALLOC;
- align = random() % ((TEST_MAXALIGN-TEST_MINALIGN)+1) + TEST_MINALIGN;
-
- v = bmk_memalloc(size1, 1<<align);
- if (!v)
- return NULL;
- ASSERT(((uintptr_t)v & (align-1)) == 0);
- memset(v, UNMAGIC, size1);
-
- size2 = random() % ((TEST_MAXALLOC-TEST_MINALLOC)+1) + TEST_MINALLOC;
- nv = memrealloc(v, size2);
- if (nv) {
- memset(nv, UNMAGIC2, size2);
- return nv;
- }
-
- return size2 ? v : NULL;
-}
-
-int
-main()
-{
- void **rings; /* yay! */
- void **ring_alloc, **ring_free; /* yay! */
- int i, n;
-
- srandom(time(NULL));
-
- rings = malloc(NALLOC * NRING * sizeof(void *));
- /* so we can free() immediately without stress */
- memset(rings, 0, NALLOC * NRING * sizeof(void *));
-
- for (n = 0;; n = (n+1) % NRING) {
- if (n == 0)
- mstats("");
-
- ring_alloc = &rings[n * NALLOC];
- ring_free = &rings[((n + NRING/2) % NRING) * NALLOC];
- for (i = 0; i < NALLOC; i++) {
- ring_alloc[i] = testalloc();
- bmk_memfree(ring_free[i]);
- }
- }
-}
-#endif
+++ /dev/null
-/*-
- * Copyright (c) 2007-2015 Antti Kantee. All Rights Reserved.
- * Copyright (c) 2014 Justin Cormack. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- */
-
-/*
- ****************************************************************************
- * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
- ****************************************************************************
- *
- * File: sched.c
- * Author: Grzegorz Milos
- * Changes: Robert Kaiser
- *
- * Date: Aug 2005
- *
- * Environment: Xen Minimal OS
- * Description: simple scheduler for Mini-Os
- *
- * The scheduler is non-preemptive (cooperative), and schedules according
- * to Round Robin algorithm.
- *
- ****************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <bmk-core/core.h>
-#include <bmk-core/memalloc.h>
-#include <bmk-core/platform.h>
-#include <bmk-core/printf.h>
-#include <bmk-core/queue.h>
-#include <bmk-core/string.h>
-#include <bmk-core/sched.h>
-
-#define TLS_COUNT 2
-#define NAME_MAXLEN 16
-
-#define THREAD_RUNNABLE 0x01
-#define THREAD_MUSTJOIN 0x02
-#define THREAD_JOINED 0x04
-#define THREAD_EXTSTACK 0x08
-#define THREAD_TIMEDOUT 0x10
-
-struct bmk_thread {
- char bt_name[NAME_MAXLEN];
-
- void *bt_tls[TLS_COUNT];
-
- bmk_time_t bt_wakeup_time;
-
- int bt_flags;
- int bt_errno;
-
- void *bt_stackbase;
-
- void *bt_cookie;
-
- /* MD thread control block */
- struct bmk_tcb bt_tcb;
-
- TAILQ_ENTRY(bmk_thread) bt_entries;
-};
-
-static TAILQ_HEAD(, bmk_thread) zombies = TAILQ_HEAD_INITIALIZER(zombies);
-static TAILQ_HEAD(, bmk_thread) threads = TAILQ_HEAD_INITIALIZER(threads);
-
-static void (*scheduler_hook)(void *, void *);
-
-static int
-is_runnable(struct bmk_thread *thread)
-{
-
- return thread->bt_flags & THREAD_RUNNABLE;
-}
-
-static void
-set_runnable(struct bmk_thread *thread)
-{
-
- thread->bt_flags |= THREAD_RUNNABLE;
-}
-
-static void
-clear_runnable(struct bmk_thread *thread)
-{
-
- thread->bt_flags &= ~THREAD_RUNNABLE;
-}
-
-static void
-stackalloc(void **stack, unsigned long *ss)
-{
-
- *stack = bmk_platform_allocpg2(bmk_stackpageorder);
- *ss = bmk_stacksize;
-}
-
-static void
-stackfree(struct bmk_thread *thread)
-{
-
- bmk_platform_freepg2(thread->bt_stackbase, bmk_stackpageorder);
-}
-
-static void
-print_threadinfo(struct bmk_thread *thread)
-{
-
- bmk_printf("thread \"%s\" at %p, flags 0x%x\n",
- thread->bt_name, thread, thread->bt_flags);
-}
-
-static void
-sched_switch(struct bmk_thread *prev, struct bmk_thread *next)
-{
-
- if (scheduler_hook)
- scheduler_hook(prev->bt_cookie, next->bt_cookie);
- bmk_platform_cpu_sched_switch(&prev->bt_tcb, &next->bt_tcb);
-}
-
-struct bmk_thread *
-bmk_sched_current(void)
-{
-
- return bmk_cpu_sched_current();
-}
-
-void
-bmk_sched_dumpqueue(void)
-{
- struct bmk_thread *thr;
-
- bmk_printf("BEGIN schedqueue dump\n");
- TAILQ_FOREACH(thr, &threads, bt_entries) {
- print_threadinfo(thr);
- }
- bmk_printf("END schedqueue dump\n");
-}
-
-void
-bmk_sched(void)
-{
- struct bmk_thread *prev, *next, *thread, *tmp;
- unsigned long flags;
-
- prev = bmk_sched_current();
- flags = bmk_platform_splhigh();
-
-#if 0
- /* XXX */
- if (_minios_in_hypervisor_callback) {
- minios_printk("Must not call schedule() from a callback\n");
- BUG();
- }
-#endif
-
- if (flags) {
- bmk_platform_halt("Must not call sched() with IRQs disabled\n");
- }
-
- /* could do time management a bit better here */
- do {
- bmk_time_t tm, wakeup;
-
- /* block domain for max 1s */
- tm = bmk_clock_monotonic();
- wakeup = tm + 1*1000*1000*1000ULL;
-
- next = NULL;
- TAILQ_FOREACH_SAFE(thread, &threads, bt_entries, tmp) {
- if (!is_runnable(thread)
- && thread->bt_wakeup_time >= 0) {
- if (thread->bt_wakeup_time <= tm) {
- thread->bt_flags |= THREAD_TIMEDOUT;
- bmk_sched_wake(thread);
- } else if (thread->bt_wakeup_time < wakeup)
- wakeup = thread->bt_wakeup_time;
- }
- if (is_runnable(thread)) {
- next = thread;
- /* Put this thread on the end of the list */
- TAILQ_REMOVE(&threads, thread, bt_entries);
- TAILQ_INSERT_TAIL(&threads, thread, bt_entries);
- break;
- }
- }
- if (next)
- break;
-
- /* sleep for a while */
- bmk_platform_block(wakeup);
- } while (1);
-
- bmk_platform_splx(flags);
-
- if (prev != next) {
- sched_switch(prev, next);
- }
-
- /* reaper */
- TAILQ_FOREACH_SAFE(thread, &zombies, bt_entries, tmp) {
- if (thread != prev) {
- TAILQ_REMOVE(&zombies, thread, bt_entries);
- if ((thread->bt_flags & THREAD_EXTSTACK) == 0)
- stackfree(thread);
- bmk_memfree(thread);
- }
- }
-}
-
-/*
- * Allocate tls and initialize it.
- *
- * XXX: this needs to change in the future so that
- * we put the tcb in the same space instead of having multiple
- * random copies flying around.
- */
-extern const char _tdata_start[], _tdata_end[];
-extern const char _tbss_start[], _tbss_end[];
-static int
-allocothertls(struct bmk_thread *thread)
-{
- const unsigned long tdatasize = _tdata_end - _tdata_start;
- const unsigned long tbsssize = _tbss_end - _tbss_start;
- struct bmk_tcb *tcb = &thread->bt_tcb;
- char *tlsmem;
-
- tlsmem = bmk_memalloc(tdatasize + tbsssize, 0);
-
- bmk_memcpy(tlsmem, _tdata_start, tdatasize);
- bmk_memset(tlsmem + tdatasize, 0, tbsssize);
-
- tcb->btcb_tp = (unsigned long)(tlsmem + tdatasize + tbsssize);
- tcb->btcb_tpsize = tdatasize + tbsssize;
-
- return 0;
-}
-
-static void
-freeothertls(struct bmk_thread *thread)
-{
- void *mem;
-
- mem = (void *)(thread->bt_tcb.btcb_tp-thread->bt_tcb.btcb_tpsize);
- bmk_memfree(mem);
-}
-
-struct bmk_thread *
-bmk_sched_create(const char *name, void *cookie, int joinable,
- void (*f)(void *), void *data,
- void *stack_base, unsigned long stack_size)
-{
- struct bmk_thread *thread;
- unsigned long flags;
-
- thread = bmk_xmalloc(sizeof(*thread));
- bmk_memset(thread, 0, sizeof(*thread));
- bmk_strncpy(thread->bt_name, name, sizeof(thread->bt_name)-1);
-
- if (!stack_base) {
- bmk_assert(stack_size == 0);
- stackalloc(&stack_base, &stack_size);
- } else {
- thread->bt_flags = THREAD_EXTSTACK;
- }
- thread->bt_stackbase = stack_base;
- if (joinable)
- thread->bt_flags |= THREAD_MUSTJOIN;
-
- bmk_cpu_sched_create(thread, &thread->bt_tcb, f, data,
- stack_base, stack_size);
-
- thread->bt_cookie = cookie;
-
- thread->bt_wakeup_time = -1;
-
- flags = bmk_platform_splhigh();
- TAILQ_INSERT_TAIL(&threads, thread, bt_entries);
- bmk_platform_splx(flags);
-
- allocothertls(thread);
- set_runnable(thread);
-
- return thread;
-}
-
-struct join_waiter {
- struct bmk_thread *jw_thread;
- struct bmk_thread *jw_wanted;
- TAILQ_ENTRY(join_waiter) jw_entries;
-};
-static TAILQ_HEAD(, join_waiter) joinwq = TAILQ_HEAD_INITIALIZER(joinwq);
-
-void
-bmk_sched_exit(void)
-{
- struct bmk_thread *thread = bmk_sched_current();
- struct join_waiter *jw_iter;
- unsigned long flags;
-
- /* if joinable, gate until we are allowed to exit */
- flags = bmk_platform_splhigh();
- while (thread->bt_flags & THREAD_MUSTJOIN) {
- thread->bt_flags |= THREAD_JOINED;
- bmk_platform_splx(flags);
-
- /* see if the joiner is already there */
- TAILQ_FOREACH(jw_iter, &joinwq, jw_entries) {
- if (jw_iter->jw_wanted == thread) {
- bmk_sched_wake(jw_iter->jw_thread);
- break;
- }
- }
- bmk_sched_block(thread);
- bmk_sched();
- flags = bmk_platform_splhigh();
- }
- freeothertls(thread);
-
- /* Remove from the thread list */
- TAILQ_REMOVE(&threads, thread, bt_entries);
- clear_runnable(thread);
- /* Put onto exited list */
- TAILQ_INSERT_HEAD(&zombies, thread, bt_entries);
- bmk_platform_splx(flags);
-
- /* bye */
- bmk_sched();
- bmk_platform_halt("schedule() returned for a dead thread!\n");
-}
-
-void
-bmk_sched_join(struct bmk_thread *joinable)
-{
- struct join_waiter jw;
- struct bmk_thread *thread = bmk_sched_current();
- unsigned long flags;
-
- bmk_assert(joinable->bt_flags & THREAD_MUSTJOIN);
-
- flags = bmk_platform_splhigh();
- /* wait for exiting thread to hit thread_exit() */
- while ((joinable->bt_flags & THREAD_JOINED) == 0) {
- bmk_platform_splx(flags);
-
- jw.jw_thread = thread;
- jw.jw_wanted = joinable;
- TAILQ_INSERT_TAIL(&joinwq, &jw, jw_entries);
- bmk_sched_block(thread);
- bmk_sched();
- TAILQ_REMOVE(&joinwq, &jw, jw_entries);
-
- flags = bmk_platform_splhigh();
- }
-
- /* signal exiting thread that we have seen it and it may now exit */
- bmk_assert(joinable->bt_flags & THREAD_JOINED);
- joinable->bt_flags &= ~THREAD_MUSTJOIN;
- bmk_platform_splx(flags);
-
- bmk_sched_wake(joinable);
-}
-
-void
-bmk_sched_block_timeout(struct bmk_thread *thread, bmk_time_t deadline)
-{
-
- thread->bt_wakeup_time = deadline;
- clear_runnable(thread);
-}
-
-void
-bmk_sched_block(struct bmk_thread *thread)
-{
-
- bmk_sched_block_timeout(thread, -1);
-}
-
-int
-bmk_sched_nanosleep_abstime(bmk_time_t nsec)
-{
- struct bmk_thread *thread = bmk_sched_current();
- int rv;
-
- thread->bt_flags &= ~THREAD_TIMEDOUT;
- thread->bt_wakeup_time = nsec;
- clear_runnable(thread);
- bmk_sched();
-
- rv = !!(thread->bt_flags & THREAD_TIMEDOUT);
- thread->bt_flags &= ~THREAD_TIMEDOUT;
- return rv;
-}
-
-int
-bmk_sched_nanosleep(bmk_time_t nsec)
-{
-
- return bmk_sched_nanosleep_abstime(nsec + bmk_clock_monotonic());
-}
-
-void
-bmk_sched_wake(struct bmk_thread *thread)
-{
-
- thread->bt_wakeup_time = -1;
- set_runnable(thread);
-}
-
-void
-bmk_sched_init(void (*mainfun)(void *), void *arg)
-{
- struct bmk_thread *mainthread;
- struct bmk_thread initthread;
-
- mainthread = bmk_sched_create("main", NULL, 0, mainfun, arg, NULL, 0);
- if (mainthread == NULL)
- bmk_platform_halt("failed to create main thread");
-
- bmk_memset(&initthread, 0, sizeof(initthread));
- bmk_strcpy(initthread.bt_name, "init");
- sched_switch(&initthread, mainthread);
-
- bmk_platform_halt("bmk_sched_init unreachable");
-}
-
-void
-bmk_sched_set_hook(void (*f)(void *, void *))
-{
-
- scheduler_hook = f;
-}
-
-struct bmk_thread *
-bmk_sched_init_mainlwp(void *cookie)
-{
- struct bmk_thread *current = bmk_sched_current();
-
- current->bt_cookie = cookie;
- allocothertls(current);
- return current;
-}
-
-const char *
-bmk_sched_threadname(struct bmk_thread *thread)
-{
-
- return thread->bt_name;
-}
-
-int *
-bmk_sched_geterrno(void)
-{
- struct bmk_thread *thread = bmk_sched_current();
-
- return &thread->bt_errno;
-}
-
-void
-bmk_sched_settls(struct bmk_thread *thread, unsigned int which, void *value)
-{
-
- if (which >= TLS_COUNT) {
- bmk_platform_halt("out of bmk sched tls space");
- }
- thread->bt_tls[which] = value;
-}
-
-void *
-bmk_sched_gettls(struct bmk_thread *thread, unsigned int which)
-{
-
- if (which >= TLS_COUNT) {
- bmk_platform_halt("out of bmk sched tls space");
- }
- return thread->bt_tls[which];
-}
-
-void
-bmk_sched_yield(void)
-{
- struct bmk_thread *current = bmk_sched_current();
-
- TAILQ_REMOVE(&threads, current, bt_entries);
- TAILQ_INSERT_TAIL(&threads, current, bt_entries);
- bmk_sched();
-}
+++ /dev/null
-/* $NetBSD: subr_prf.c,v 1.157 2015/02/04 07:10:47 msaitoh Exp $ */
-
-/*-
- * Copyright (c) 1986, 1988, 1991, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * 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. 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.
- *
- * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95
- */
-
-/*
- * This is the NetBSD kernel printf code heavily stripped. Format support
- * is the same, but the wrappers for calling printf have been reduced
- * down to:
- * + printf
- * + snprintf
- * + vnsprintf
- */
-
-#define _BMK_PRINTF_VA
-#include <bmk-core/null.h>
-#include <bmk-core/printf.h>
-#include <bmk-core/string.h>
-
-#define TOBUFONLY 0x01
-#define TOCONS 0x02
-
-#define __UNCONST(x) ((void *)(unsigned long)(x))
-#define KPRINTF_BUFSIZE (sizeof(long long)*8/3 + 2)
-
-/*
- * local prototypes
- */
-
-static void cons_putchar(int, int);
-static int kprintf(const char *, int, void *, char *, va_list);
-
-/*
- * globals
- */
-
-static void
-nullfun(void)
-{
-
- return;
-}
-
-static void (*v_flush)(void);
-static void (*v_putc)(int);
-
-void
-bmk_printf_init(void (*putc)(int), void (*flush)(void))
-{
-
- v_putc = putc;
- if (flush == NULL)
- flush = nullfun;
- v_flush = flush;
-}
-
-static const char hexdigits[] = "0123456789abcdef";
-static const char HEXDIGITS[] = "0123456789ABCDEF";
-
-/*
- * functions
- */
-
-/* dmesg ring buffer */
-#ifndef BMK_DMESG_SIZE
-#define BMK_DMESG_SIZE (16*1024)
-#endif
-static char bmk_dmesg[BMK_DMESG_SIZE];
-static int bmk_dmesgoff;
-
-/*
- * putchar: print a single character on console or user terminal.
- *
- * => if console, then the last MSGBUFS chars are saved in msgbuf
- * for inspection later (e.g. dmesg/syslog)
- * => we must already be in the mutex!
- */
-static void
-cons_putchar(int c, int flags)
-{
-
- bmk_dmesg[bmk_dmesgoff] = c;
- if (++bmk_dmesgoff == sizeof(bmk_dmesg)-1)
- bmk_dmesgoff = 0;
- (*v_putc)(c);
-}
-
-static void
-kprintf_lock(void)
-{
-
- /* XXX */
-}
-
-static void
-kprintf_unlock(void)
-{
-
- /* XXX */
-}
-
-/*
- * bmk_printf: print a message to the console
- */
-void
-bmk_printf(const char *fmt, ...)
-{
- va_list ap;
-
- kprintf_lock();
-
- va_start(ap, fmt);
- kprintf(fmt, TOCONS, NULL, NULL, ap);
- va_end(ap);
-
- kprintf_unlock();
-}
-
-/*
- * bmk_vprintf: print a message to the console [already have
- * va_list]
- */
-void
-bmk_vprintf(const char *fmt, va_list ap)
-{
- kprintf_lock();
-
- kprintf(fmt, TOCONS, NULL, NULL, ap);
-
- kprintf_unlock();
-}
-
-/*
- * bmk_snprintf: print a message to a buffer
- */
-int
-bmk_snprintf(char *bf, unsigned long size, const char *fmt, ...)
-{
- int retval;
- va_list ap;
-
- va_start(ap, fmt);
- retval = bmk_vsnprintf(bf, size, fmt, ap);
- va_end(ap);
-
- return retval;
-}
-
-/*
- * bmk_vsnprintf: print a message to a buffer [already have va_list]
- */
-int
-bmk_vsnprintf(char *bf, unsigned long size, const char *fmt, va_list ap)
-{
- int retval;
- char *p;
-
- p = bf + size;
- retval = kprintf(fmt, TOBUFONLY, &p, bf, ap);
- if (bf && size > 0) {
- /* nul terminate */
- if (size <= (unsigned long)retval)
- bf[size - 1] = '\0';
- else
- bf[retval] = '\0';
- }
- return retval;
-}
-
-/*
- * kprintf: scaled down version of printf(3).
- *
- * this version based on vfprintf() from libc which was derived from
- * software contributed to Berkeley by Chris Torek.
- *
- * NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS!
- */
-
-/*
- * macros for converting digits to letters and vice versa
- */
-#define to_digit(c) ((c) - '0')
-#define is_digit(c) ((unsigned)to_digit(c) <= 9)
-#define to_char(n) ((n) + '0')
-
-/*
- * flags used during conversion.
- */
-#define ALT 0x001 /* alternate form */
-#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
-#define LADJUST 0x004 /* left adjustment */
-#define LONGDBL 0x008 /* long double; unimplemented */
-#define LONGINT 0x010 /* long integer */
-#define QUADINT 0x020 /* quad integer */
-#define SHORTINT 0x040 /* short integer */
-#define MAXINT 0x080 /* intmax_t */
-#define PTRINT 0x100 /* intptr_t */
-#define SIZEINT 0x200 /* size_t */
-#define ZEROPAD 0x400 /* zero (as opposed to blank) pad */
-#define FPT 0x800 /* Floating point number */
-
- /*
- * To extend shorts properly, we need both signed and unsigned
- * argument extraction methods.
- */
-#define SARG() \
- (flags&MAXINT ? va_arg(ap, long long) : \
- flags&PTRINT ? va_arg(ap, long) : \
- flags&SIZEINT ? va_arg(ap, long) : /* XXX */ \
- flags&QUADINT ? va_arg(ap, long long) : \
- flags&LONGINT ? va_arg(ap, long) : \
- flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
- (long)va_arg(ap, int))
-#define UARG() \
- (flags&MAXINT ? va_arg(ap, unsigned long long) : \
- flags&PTRINT ? va_arg(ap, unsigned long) : \
- flags&SIZEINT ? va_arg(ap, unsigned long) : \
- flags&QUADINT ? va_arg(ap, unsigned long long) : \
- flags&LONGINT ? va_arg(ap, unsigned long) : \
- flags&SHORTINT ? (unsigned long)(unsigned long)va_arg(ap, int) : \
- (unsigned long)va_arg(ap, unsigned int))
-
-#define KPRINTF_PUTCHAR(C) { \
- if (oflags == TOBUFONLY) { \
- if (sbuf && ((vp == NULL) || (sbuf < tailp))) \
- *sbuf++ = (C); \
- } else { \
- cons_putchar((C), oflags); \
- } \
-}
-
-/*
- * Guts of kernel printf. Note, we already expect to be in a mutex!
- */
-static int
-kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap)
-{
- int ret = 0; /* return value accumulator */
- const char *fmt; /* format string */
- int ch; /* character from fmt */
- int n; /* handy integer (short term usage) */
- char *cp; /* handy char pointer (short term usage) */
- int flags; /* flags as above */
- int width; /* width from format (%8d), or 0 */
- int prec; /* precision from format (%.3d), or -1 */
- char sign; /* sign prefix (' ', '+', '-', or \0) */
-
- unsigned long long _uquad; /* integer arguments %[diouxX] */
- enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
- int dprec; /* a copy of prec if [diouxX], 0 otherwise */
- int realsz; /* field size expanded by dprec */
- int size; /* size of converted field or string */
- const char *xdigs; /* digits for [xX] conversion */
- char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */
- char *tailp; /* tail pointer for snprintf */
-
- if (oflags == TOBUFONLY && (vp != NULL))
- tailp = *(char **)vp;
- else
- tailp = NULL;
-
- cp = NULL; /* XXX: shutup gcc */
- size = 0; /* XXX: shutup gcc */
-
- fmt = fmt0;
- ret = 0;
-
- xdigs = NULL; /* XXX: shut up gcc warning */
-
- /*
- * Scan the format for conversions (`%' character).
- */
- for (;;) {
- for (; *fmt != '%' && *fmt; fmt++) {
- ret++;
- KPRINTF_PUTCHAR(*fmt);
- }
- if (*fmt == 0)
- goto done;
-
- fmt++; /* skip over '%' */
-
- flags = 0;
- dprec = 0;
- width = 0;
- prec = -1;
- sign = '\0';
-
-rflag: ch = *fmt++;
-reswitch: switch (ch) {
- case ' ':
- /*
- * ``If the space and + flags both appear, the space
- * flag will be ignored.''
- * -- ANSI X3J11
- */
- if (!sign)
- sign = ' ';
- goto rflag;
- case '#':
- flags |= ALT;
- goto rflag;
- case '*':
- /*
- * ``A negative field width argument is taken as a
- * - flag followed by a positive field width.''
- * -- ANSI X3J11
- * They don't exclude field widths read from args.
- */
- if ((width = va_arg(ap, int)) >= 0)
- goto rflag;
- width = -width;
- /* FALLTHROUGH */
- case '-':
- flags |= LADJUST;
- goto rflag;
- case '+':
- sign = '+';
- goto rflag;
- case '.':
- if ((ch = *fmt++) == '*') {
- n = va_arg(ap, int);
- prec = n < 0 ? -1 : n;
- goto rflag;
- }
- n = 0;
- while (is_digit(ch)) {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- }
- prec = n < 0 ? -1 : n;
- goto reswitch;
- case '0':
- /*
- * ``Note that 0 is taken as a flag, not as the
- * beginning of a field width.''
- * -- ANSI X3J11
- */
- flags |= ZEROPAD;
- goto rflag;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- n = 0;
- do {
- n = 10 * n + to_digit(ch);
- ch = *fmt++;
- } while (is_digit(ch));
- width = n;
- goto reswitch;
- case 'h':
- flags |= SHORTINT;
- goto rflag;
- case 'j':
- flags |= MAXINT;
- goto rflag;
- case 'l':
- if (*fmt == 'l') {
- fmt++;
- flags |= QUADINT;
- } else {
- flags |= LONGINT;
- }
- goto rflag;
- case 'q':
- flags |= QUADINT;
- goto rflag;
- case 't':
- flags |= PTRINT;
- goto rflag;
- case 'z':
- flags |= SIZEINT;
- goto rflag;
- case 'c':
- *(cp = bf) = va_arg(ap, int);
- size = 1;
- sign = '\0';
- break;
- case 'D':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'd':
- case 'i':
- _uquad = SARG();
- if ((long long)_uquad < 0) {
- _uquad = -_uquad;
- sign = '-';
- }
- base = DEC;
- goto number;
- case 'n':
- if (flags & MAXINT)
- *va_arg(ap, long long *) = ret;
- else if (flags & PTRINT)
- *va_arg(ap, long *) = ret;
- else if (flags & SIZEINT)
- *va_arg(ap, long *) = ret;
- else if (flags & QUADINT)
- *va_arg(ap, long long *) = ret;
- else if (flags & LONGINT)
- *va_arg(ap, long *) = ret;
- else if (flags & SHORTINT)
- *va_arg(ap, short *) = ret;
- else
- *va_arg(ap, int *) = ret;
- continue; /* no output */
- case 'O':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'o':
- _uquad = UARG();
- base = OCT;
- goto nosign;
- case 'p':
- /*
- * ``The argument shall be a pointer to void. The
- * value of the pointer is converted to a sequence
- * of printable characters, in an implementation-
- * defined manner.''
- * -- ANSI X3J11
- */
- /* NOSTRICT */
- _uquad = (unsigned long)va_arg(ap, void *);
- base = HEX;
- xdigs = hexdigits;
- flags |= HEXPREFIX;
- ch = 'x';
- goto nosign;
- case 's':
- if ((cp = va_arg(ap, char *)) == NULL)
- /*XXXUNCONST*/
- cp = __UNCONST("(null)");
- if (prec >= 0) {
- /*
- * can't use strlen; can only look for the
- * NUL in the first `prec' characters, and
- * strlen() will go further.
- */
- char *p = bmk_memchr(cp, 0, prec);
-
- if (p != NULL) {
- size = p - cp;
- if (size > prec)
- size = prec;
- } else
- size = prec;
- } else
- size = bmk_strlen(cp);
- sign = '\0';
- break;
- case 'U':
- flags |= LONGINT;
- /*FALLTHROUGH*/
- case 'u':
- _uquad = UARG();
- base = DEC;
- goto nosign;
- case 'X':
- xdigs = HEXDIGITS;
- goto hex;
- case 'x':
- xdigs = hexdigits;
-hex: _uquad = UARG();
- base = HEX;
- /* leading 0x/X only if non-zero */
- if (flags & ALT && _uquad != 0)
- flags |= HEXPREFIX;
-
- /* unsigned conversions */
-nosign: sign = '\0';
- /*
- * ``... diouXx conversions ... if a precision is
- * specified, the 0 flag will be ignored.''
- * -- ANSI X3J11
- */
-number: if ((dprec = prec) >= 0)
- flags &= ~ZEROPAD;
-
- /*
- * ``The result of converting a zero value with an
- * explicit precision of zero is no characters.''
- * -- ANSI X3J11
- */
- cp = bf + KPRINTF_BUFSIZE;
- if (_uquad != 0 || prec != 0) {
- /*
- * Unsigned mod is hard, and unsigned mod
- * by a constant is easier than that by
- * a variable; hence this switch.
- */
- switch (base) {
- case OCT:
- do {
- *--cp = to_char(_uquad & 7);
- _uquad >>= 3;
- } while (_uquad);
- /* handle octal leading 0 */
- if (flags & ALT && *cp != '0')
- *--cp = '0';
- break;
-
- case DEC:
- /* many numbers are 1 digit */
- while (_uquad >= 10) {
- *--cp = to_char(_uquad % 10);
- _uquad /= 10;
- }
- *--cp = to_char(_uquad);
- break;
-
- case HEX:
- do {
- *--cp = xdigs[_uquad & 15];
- _uquad >>= 4;
- } while (_uquad);
- break;
-
- default:
- /*XXXUNCONST*/
- cp = __UNCONST("bug in kprintf: bad base");
- size = bmk_strlen(cp);
- goto skipsize;
- }
- }
- size = bf + KPRINTF_BUFSIZE - cp;
- skipsize:
- break;
- default: /* "%?" prints ?, unless ? is NUL */
- if (ch == '\0')
- goto done;
- /* pretend it was %c with argument ch */
- cp = bf;
- *cp = ch;
- size = 1;
- sign = '\0';
- break;
- }
-
- /*
- * All reasonable formats wind up here. At this point, `cp'
- * points to a string which (if not flags&LADJUST) should be
- * padded out to `width' places. If flags&ZEROPAD, it should
- * first be prefixed by any sign or other prefix; otherwise,
- * it should be blank padded before the prefix is emitted.
- * After any left-hand padding and prefixing, emit zeroes
- * required by a decimal [diouxX] precision, then print the
- * string proper, then emit zeroes required by any leftover
- * floating precision; finally, if LADJUST, pad with blanks.
- *
- * Compute actual size, so we know how much to pad.
- * size excludes decimal prec; realsz includes it.
- */
- realsz = dprec > size ? dprec : size;
- if (sign)
- realsz++;
- else if (flags & HEXPREFIX)
- realsz+= 2;
-
- /* adjust ret */
- ret += width > realsz ? width : realsz;
-
- /* right-adjusting blank padding */
- if ((flags & (LADJUST|ZEROPAD)) == 0) {
- n = width - realsz;
- while (n-- > 0)
- KPRINTF_PUTCHAR(' ');
- }
-
- /* prefix */
- if (sign) {
- KPRINTF_PUTCHAR(sign);
- } else if (flags & HEXPREFIX) {
- KPRINTF_PUTCHAR('0');
- KPRINTF_PUTCHAR(ch);
- }
-
- /* right-adjusting zero padding */
- if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) {
- n = width - realsz;
- while (n-- > 0)
- KPRINTF_PUTCHAR('0');
- }
-
- /* leading zeroes from decimal precision */
- n = dprec - size;
- while (n-- > 0)
- KPRINTF_PUTCHAR('0');
-
- /* the string or number proper */
- for (; size--; cp++)
- KPRINTF_PUTCHAR(*cp);
- /* left-adjusting padding (always blank) */
- if (flags & LADJUST) {
- n = width - realsz;
- while (n-- > 0)
- KPRINTF_PUTCHAR(' ');
- }
- }
-
-done:
- if ((oflags == TOBUFONLY) && (vp != NULL))
- *(char **)vp = sbuf;
- (*v_flush)();
-
- return ret;
-}
${LIBS_SYSPROXY} \
-lrumpdev -lrumpvfs -lrump
-COREDIR:= $(shell pwd)/../../lib/librumprun_core
+COREDIR:= $(shell pwd)/../../lib/libbmk_core
BASEDIR:= $(shell pwd)/../../lib/librumprun_base
RUMPUSERDIR:= $(shell pwd)/../../lib/librumprun_rumpuser
OBJS_BMK+= init.o
-LIBS_USER= -L${BASEDIR}/baremetal -L${COREDIR}/baremetal -L${RUMPUSERDIR}/baremetal -lrumprun_rumpuser --start-group -lrumprun_base -lpthread -lc --end-group -lrumprun_core
+LIBS_USER= -L${BASEDIR}/baremetal -L${COREDIR}/baremetal -L${RUMPUSERDIR}/baremetal -lrumprun_rumpuser --start-group -lrumprun_base -lpthread -lc --end-group -lbmk_core
RUMP_LDLIBS= --whole-archive ${RUMPKERN_LIB} --no-whole-archive ${LIBS_USER}
OBJS= ${OBJS_BMK} ${OBJS_APP}
&& ${RUMPMAKE} MAKEOBJDIR=baremetal obj \
&& ${RUMPMAKE} MAKEOBJDIR=baremetal dependall )
-${COREDIR}/baremetal/librumprun_core.a:
+${COREDIR}/baremetal/libbmk_core.a:
( cd ${COREDIR} \
&& ${RUMPMAKE} MAKEOBJDIR=baremetal obj \
&& ${RUMPMAKE} MAKEOBJDIR=baremetal dependall )
&& ${RUMPMAKE} MAKEOBJDIR=baremetal obj \
&& ${RUMPMAKE} MAKEOBJDIR=baremetal dependall )
-rumprun.o: ${OBJS} ${BASEDIR}/baremetal/librumprun_base.a ${COREDIR}/baremetal/librumprun_core.a ${RUMPUSERDIR}/baremetal/librumprun_rumpuser.a
+rumprun.o: ${OBJS} ${BASEDIR}/baremetal/librumprun_base.a ${COREDIR}/baremetal/libbmk_core.a ${RUMPUSERDIR}/baremetal/librumprun_rumpuser.a
${CC} -nostdlib ${CFLAGS} -Wl,-r ${OBJS_BMK} -o $@
tests: rumprun.o app-tools
CFLAGS += -mno-red-zone -fno-reorder-blocks -fno-asynchronous-unwind-tables
endif
-COREDIR:= $(shell pwd)/../../lib/librumprun_core
+COREDIR:= $(shell pwd)/../../lib/libbmk_core
BASEDIR:= $(shell pwd)/../../lib/librumprun_base
RUMPUSERDIR:= $(shell pwd)/../../lib/librumprun_rumpuser
# Define some default flags for linking.
RUMP_LDLIBS = --whole-archive ${RUMP_LIBS_FS} ${RUMP_LIBS_NET} ${RUMP_LIBS_PCI} ${RUMP_LIBS_SYSPROXY} -lrumpxen_tc -lrump --no-whole-archive
-RUMP_LDLIBS := ${RUMP_LDLIBS} -L${BASEDIR}/xen -L${COREDIR}/xen -L${RUMPUSERDIR}/xen -lrumprun_rumpuser --start-group -lrumprun_base -lpthread -lc --end-group -lrumprun_core
+RUMP_LDLIBS := ${RUMP_LDLIBS} -L${BASEDIR}/xen -L${COREDIR}/xen -L${RUMPUSERDIR}/xen -lrumprun_rumpuser --start-group -lrumprun_base -lpthread -lc --end-group -lbmk_core
LDFLAGS := -L$(abspath rump/lib)
&& ${RUMPMAKE} MAKEOBJDIR=xen obj \
&& ${RUMPMAKE} MAKEOBJDIR=xen dependall )
-${COREDIR}/xen/librumprun_core.a:
+${COREDIR}/xen/libbmk_core.a:
( cd ${COREDIR} \
&& ${RUMPMAKE} MAKEOBJDIR=xen obj \
&& ${RUMPMAKE} MAKEOBJDIR=xen dependall )
.PHONY: rumprun
rumprun: $(OBJ_DIR)/rumprun.o
-$(OBJ_DIR)/rumprun.o: $(RUMP_OBJS) ${BASEDIR}/xen/librumprun_base.a ${COREDIR}/xen/librumprun_core.a ${RUMPUSERDIR}/xen/librumprun_rumpuser.a
+$(OBJ_DIR)/rumprun.o: $(RUMP_OBJS) ${BASEDIR}/xen/librumprun_base.a ${COREDIR}/xen/libbmk_core.a ${RUMPUSERDIR}/xen/librumprun_rumpuser.a
$(CC) -Wl,-r $(CFLAGS) $(LDFLAGS) $(RUMP_OBJS) -nostdlib -o $@
APP_TOOLS_TARGETARCH= $(TARGET_ARCH)