Showing preview only (365K chars total). Download the full file or copy to clipboard to get everything.
Repository: Piko-RT/pikoRT
Branch: master
Commit: 569cee508b34
Files: 242
Total size: 316.2 KB
Directory structure:
gitextract_0chc9o9f/
├── .clang-format
├── .gitignore
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── arch/
│ ├── v7m-entry.S
│ ├── v7m-faults.c
│ ├── v7m-head.S
│ └── v7m-svcall.S
├── docs/
│ ├── Makefile
│ ├── api.rst
│ ├── build.rst
│ ├── conf.py
│ ├── contribute.rst
│ ├── debugging.rst
│ ├── emulate.rst
│ ├── index.rst
│ ├── kernel.rst
│ ├── make.bat
│ ├── posix/
│ │ ├── parse.py
│ │ ├── posix_opt/
│ │ │ ├── 01._POSIX_CLOCK_SELECTION
│ │ │ ├── 02._POSIX_FSYNC
│ │ │ ├── 03._POSIX_MEMLOCK
│ │ │ ├── 04.POSIX_MEMLOCK_RANGE
│ │ │ ├── 05._POSIX_MONOTONIC_CLOCK
│ │ │ ├── 06._POSIX_NO_TRUNC
│ │ │ ├── 07._POSIX_REALTIME_SIGNALS
│ │ │ ├── 08._POSIX_SEMAPHORES
│ │ │ ├── 09._POSIX_SHARED_MEMORY_OBJECTS
│ │ │ ├── 10._POSIX_SYNCHRONIZED_IO
│ │ │ ├── 11._POSIX_THREAD_ATTR_STACKADDR
│ │ │ ├── 12._POSIX_THREAD_ATTR_STACKSIZE
│ │ │ ├── 13._POSIX_THREAD_CPUTIME
│ │ │ ├── 14._POSIX_THREAD_PRIO_INHERIT
│ │ │ ├── 15._POSIX_THREAD_PRIO_PROTECT
│ │ │ ├── 16._POSIX_THREAD_PRIORITY_SCHEDULING
│ │ │ ├── 17._POSIX_THREAD_SPORADIC_SERVER
│ │ │ └── 18._POSIX_TIMERS
│ │ └── posix_req/
│ │ ├── 01.POSIX_C_LANG_SUPPORT
│ │ ├── 02.POSIX_DEVICE_IO
│ │ ├── 03.POSIX_FILE_LOCKING
│ │ ├── 04.POSIX_SIGNALS
│ │ ├── 05.POSIX_SINGLE_PROCESS
│ │ ├── 06.POSIX_THREADS_BASE
│ │ ├── 07.XSI_THREAD_MUTEX_EXT
│ │ └── 08.XSI_THREADS_EXT
│ └── test.rst
├── drivers/
│ ├── char/
│ │ ├── mem.c
│ │ └── random.c
│ ├── mtd/
│ │ ├── mtd.h
│ │ ├── mtdchar.c
│ │ ├── mtdcore.c
│ │ └── mtdram.c
│ ├── serial/
│ │ ├── serialchar.c
│ │ ├── serialcore.c
│ │ ├── stm32-uart.c
│ │ └── stm32-uart.h
│ └── timer/
│ ├── systick.c
│ └── timercore.c
├── fs/
│ ├── proc.c
│ ├── romfs.c
│ └── tmpfs.c
├── include/
│ ├── arch/
│ │ ├── semihosting.h
│ │ └── v7m-helper.h
│ ├── fs/
│ │ └── romfs.h
│ ├── kernel/
│ │ ├── bitmap.h
│ │ ├── bitops.h
│ │ ├── cbuf.h
│ │ ├── compiler.h
│ │ ├── cond.h
│ │ ├── errno-base.h
│ │ ├── faults.h
│ │ ├── fs.h
│ │ ├── hash.h
│ │ ├── irq.h
│ │ ├── kernel.h
│ │ ├── linkage.h
│ │ ├── log2.h
│ │ ├── mm/
│ │ │ ├── page.h
│ │ │ └── slab.h
│ │ ├── mutex.h
│ │ ├── sched.h
│ │ ├── serial.h
│ │ ├── signal.h
│ │ ├── softirq.h
│ │ ├── task.h
│ │ ├── thread.h
│ │ ├── time.h
│ │ └── types.h
│ ├── libc/
│ │ ├── pthread.h
│ │ ├── ucontext.h
│ │ └── utils.h
│ ├── linux/
│ │ ├── compiler.h
│ │ ├── list.h
│ │ ├── poison.h
│ │ ├── stddef.h
│ │ └── types.h
│ ├── piko/
│ │ ├── arpa/
│ │ │ └── inet.h
│ │ ├── dirent.h
│ │ ├── signal.h
│ │ └── sys/
│ │ ├── mman.h
│ │ ├── mount.h
│ │ └── resource.h
│ ├── platform/
│ │ └── compiler.h
│ └── version.template.h
├── kernel/
│ ├── cond.c
│ ├── config.c
│ ├── faults.c
│ ├── fs/
│ │ ├── fs.c
│ │ ├── readdir.c
│ │ └── vfs.c
│ ├── irq.c
│ ├── main.c
│ ├── mm/
│ │ ├── mm.c
│ │ ├── page.c
│ │ └── slab.c
│ ├── mutex.c
│ ├── printk.c
│ ├── resource.c
│ ├── sched/
│ │ ├── bitmap.c
│ │ └── rr.c
│ ├── sched.c
│ ├── signal.c
│ ├── softirq.c
│ ├── task.c
│ ├── thread.c
│ └── time.c
├── libc/
│ ├── fcntl.c
│ ├── filesystem.c
│ ├── piko/
│ │ ├── mman.c
│ │ ├── stubs.c
│ │ ├── syscalls.S
│ │ └── syscalls.h
│ ├── pthread.c
│ ├── signal.c
│ ├── stdio.c
│ ├── stdlib.c
│ ├── time.c
│ ├── ucontext.c
│ ├── unistd.c
│ ├── utils.c
│ └── v7m-pthread.S
├── mk/
│ ├── cmsis.mk
│ ├── flags.mk
│ └── rules.mk
├── piko.lds.S
├── platform/
│ ├── f429disco/
│ │ ├── Makefile
│ │ ├── build.mk
│ │ ├── halt.c
│ │ ├── init.c
│ │ ├── platform.h
│ │ └── uart.c
│ └── stm32p103/
│ ├── Makefile
│ ├── build.mk
│ ├── halt.c
│ ├── init.c
│ ├── platform.h
│ └── uart.c
├── scripts/
│ ├── gen-proc-version.py
│ ├── gen-syscalls.py
│ └── rstlint.py
├── tests/
│ ├── Makefile
│ ├── __init__.py
│ ├── __main__.py
│ ├── bitops_1/
│ │ └── main.c
│ ├── cond_1/
│ │ └── main.c
│ ├── cond_2/
│ │ └── main.c
│ ├── cond_3/
│ │ └── main.c
│ ├── fs_1/
│ │ └── main.c
│ ├── fs_2/
│ │ └── main.c
│ ├── fs_3/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── fs_4/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── fs_5/
│ │ └── main.c
│ ├── fs_6/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── fs_7/
│ │ ├── data/
│ │ │ └── .ssh/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── getpid_1/
│ │ └── main.c
│ ├── itoa_1/
│ │ └── main.c
│ ├── lib/
│ │ └── unit.h
│ ├── malloc_1/
│ │ └── main.c
│ ├── mm_1/
│ │ └── main.c
│ ├── mm_2/
│ │ └── main.c
│ ├── mmap_1/
│ │ └── main.c
│ ├── mmap_2/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── msleep_1/
│ │ └── main.c
│ ├── msleep_2/
│ │ └── main.c
│ ├── mtdram_1/
│ │ └── main.c
│ ├── mutex_1/
│ │ └── main.c
│ ├── mutex_2/
│ │ └── main.c
│ ├── mutex_3/
│ │ └── main.c
│ ├── mutex_4/
│ │ └── main.c
│ ├── mutex_5/
│ │ └── main.c
│ ├── page_3/
│ │ └── main.c
│ ├── raise_1/
│ │ └── main.c
│ ├── raise_2/
│ │ └── main.c
│ ├── raise_3/
│ │ └── main.c
│ ├── readdir_1/
│ │ └── main.c
│ ├── runner.py
│ ├── slab_1/
│ │ └── main.c
│ ├── slab_2/
│ │ └── main.c
│ ├── softirq_1/
│ │ └── main.c
│ ├── softirq_2/
│ │ └── main.c
│ ├── softirq_3/
│ │ └── main.c
│ ├── sprintf_1/
│ │ └── main.c
│ ├── stat_1/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── syscall_1/
│ │ ├── main.c
│ │ └── trampoline.S
│ ├── sysconf_1/
│ │ └── main.c
│ ├── test_1/
│ │ └── main.c
│ ├── test_2/
│ │ └── main.c
│ ├── thread_1/
│ │ └── main.c
│ ├── thread_2/
│ │ └── main.c
│ ├── thread_3/
│ │ └── main.c
│ ├── thread_4/
│ │ └── main.c
│ ├── thread_5/
│ │ └── main.c
│ ├── thread_6/
│ │ └── main.c
│ ├── timer_1/
│ │ └── main.c
│ ├── timer_2/
│ │ └── main.c
│ ├── timer_3/
│ │ └── main.c
│ ├── timer_4/
│ │ └── main.c
│ ├── timer_5/
│ │ └── main.c
│ └── ucontext_1/
│ └── main.c
└── user/
├── cat.c
├── echo.c
├── exit.c
├── halt.c
├── ls.c
├── reboot.c
├── sh.c
└── sh.h
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
BasedOnStyle: Chromium
Language: Cpp
MaxEmptyLinesToKeep: 3
IndentCaseLabels: false
AllowShortIfStatementsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
DerivePointerAlignment: false
PointerAlignment: Right
SpaceAfterCStyleCast: true
TabWidth: 4
UseTab: Never
IndentWidth: 4
BreakBeforeBraces: Linux
AccessModifierOffset: -4
================================================
FILE: .gitignore
================================================
# external source
external/
*~
*.o
*.o.d
*.elf
*.map
*.lds
*.hex
*.bin
# generated
fs/version
include/kernel/syscalls.h
kernel/syscall.c
# QEMU generated
DAC_OUT_PUT1.txt
DAC_OUT_PUT2.txt
# Python
__pycache__
*.pyc
# Sphinx
_build
================================================
FILE: .travis.yml
================================================
sudo: required
dist: trusty
os: linux
language: python
cache: pip
stage:
- docs
- core
jobs:
include:
- stage: docs
env: TESTING=docs
python: 3.6
before_install:
- sudo apt-get update -qq
install:
- sudo apt-get install cscope
before_script:
- cd docs
- pip install sphinx
script:
- make check
- make html
- &core-stage
stage: core
python: 3.5
env: TESTING=Piko/RT
before_install:
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
- sudo apt-get update -qq
install:
- sudo apt install build-essential
- sudo apt-get install -y gcc-arm-embedded
# QEMU deps
- sudo apt install libxenstore3.0
- sudo apt install libxen-dev
- sudo apt install genromfs
- wget https://github.com/PikoRT/tools/raw/master/bin/x86_64-linux/qemu-system-arm
- chmod 777 qemu-system-arm
- export PATH=$PWD:$PATH
before_script:
- arm-none-eabi-gcc --version
- python --version
script:
- make PLAT=stm32p103
- make PLAT=stm32p103 check
- <<: *core-stage
python: 3.6
================================================
FILE: LICENSE
================================================
Piko/RT is freely redistributable under the two-clause BSD License:
Copyright (c) 2017 Piko/RT Developers.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
================================================
FILE: Makefile
================================================
NAME = piko
# select QEMU when the platform is unspecified
PLAT ?= f429disco
CMSIS = external/cmsis
# The platform Makefile contains hw details and flags
include platform/$(PLAT)/Makefile
# arch-specific
SSRC += arch/v7m-head.S arch/v7m-entry.S arch/v7m-svcall.S
CSRC += arch/v7m-faults.c
LIBPIKO_CSRC = $(wildcard libc/*.c)
LIBPIKO_SSRC = $(wildcard libc/*.S) $(wildcard libc/piko/*.S)
SSRC += $(LIBPIKO_SSRC)
CSRC += kernel/syscall.c
CSRC += \
$(wildcard kernel/*.c) \
$(wildcard kernel/fs/*.c) \
$(wildcard kernel/mm/*.c) \
$(wildcard kernel/sched/*.c) \
$(wildcard fs/*.c) \
$(wildcard drivers/char/*.c) \
$(wildcard drivers/mtd/*.c) \
$(wildcard drivers/timer/timercore.c) \
$(wildcard drivers/serial/serial*.c) \
$(wildcard user/*.c) \
libc/piko/stubs.c \
libc/piko/mman.c \
$(LIBPIKO_CSRC)
OBJS += $(SSRC:.S=.o) $(CSRC:.c=.o)
OBJS := $(sort $(OBJS))
deps := $(OBJS:%.o=.%.o.d)
.PHONY: all check clean distclean check_cc
all: check_cc $(CMSIS)/$(PLAT) $(NAME).lds $(NAME).bin
# generic build rules
include mk/flags.mk
include mk/rules.mk
include mk/cmsis.mk
prebuild: $(CMSIS)/$(PLAT)
check: check_cc
$(PYTHON) -m tests -p $(PLAT) --qemu $(QEMU_SYSTEM_ARM) --cc $(CC)
check_cc:
@$(eval PYTHON_VERSION=$(shell echo `$(PYTHON) --version 2>&1 | grep -oE '[^ ]+$$'`))
@$(eval PYTHON_VERSION=$(shell echo $(PYTHON_VERSION) | awk -F "." '{print $$1$$2 0}'))
@if [ $(PYTHON_VERSION) -lt 350 ]; then \
echo "Error: Python version must >= 3.5, use PYTHON=/python/binary/path"; \
return 1;\
fi;
clean:
find . -name "*.o" -type f -delete
find . -name "*.o.d" -type f -delete
rm -f $(deps)
ifneq "$(wildcard $(CMSIS) )" ""
find $(CMSIS) -name "*.o" -type f -delete
endif
rm -f $(NAME).map $(NAME).lds
rm -f $(NAME).elf $(NAME).bin
# Remove GEN files
rm -f include/kernel/syscalls.h
rm -f kernel/syscall.c
rm -f fs/version
distclean: clean
rm -f kernel/syscall.c include/kernel/syscalls.h fs/version
rm -rf $(CMSIS)
# platform build contains flashing and running rules
include platform/$(PLAT)/build.mk
-include $(deps)
================================================
FILE: README.md
================================================
# Piko/RT
This is `Piko/RT`, a tiny Linux-like real-time operating system kernel, optimized for ARM Cortex-M series microprocessors.
Prerequisites
-------------
- [QEMU with an STM32 microcontroller implementation](https://beckus.github.io/qemu_stm32/)
## Run test suite
* Run all test
```shell
$ make PLAT=stm32p103 check
```
* Run all test with command line tools
```shell
$ python -m tests
```
* Run specific test cases
```shell
$ python -m tests fs_1 cond_2
```
## External Source
* `scripts/rstlint.py`: written by Georg Brandl
================================================
FILE: arch/v7m-entry.S
================================================
#include <kernel/linkage.h>
.syntax unified
.thumb
@ do the thread-context switch
@
@ r0: struct thread_info *next
@ r1: struct thread_info *prev (i.e. the current thread)
@ (r1), r2, r3, r12: scratch registers
ENTRY(switch_to)
/* save previous thread context */
push {r4-r12, lr}
mov r2, sp
mrs r3, psp
stm r1!, {r2, r3}
ENTRY(thread_restore)
/* restore next task context */
ldm r0!, {r1-r3}
mov sp, r1
msr psp, r2
msr control, r3 @ write to SPSEL is ignored in Handler_Mode
pop {r4-r12, pc}
ENDPROC(thread_restore)
ENDPROC(switch_to)
.macro emulate_iret
ldrd r0, r1, [sp, #24] /* r0 = ret_addr, r1 = xpsr */
orr r0, #1
str r0, [sp, #24]
msr apsr_nzcvq, r1 /* restore flags */
pop {r0-r3, r12, lr}
ldr pc, [sp], #8 /* return into user thread */
.endm
ENTRY(return_from_sigaction)
add sp, #12 /* reclaim siginfo_t storage */
emulate_iret
END(return_from_sigaction)
ENTRY(return_from_sighandler)
emulate_iret
END(return_from_sighandler)
.set MC_SP, 0
.set MC_LR, 4
.set MC_GPRS, 8
.set MC_PC, 15*4
.set UC_MCONTEXT, 16
.set UC_LINK, 0
/* Swap context to a clean context (created from makecontext()):
* - save the non-scratch registers
* - just restore scratch registers (for arguments to entry function)
*
* Swap to a dirty context (inited with getcontext, or return to a
* swapped context):
* - save the non-scratch registers
* - restore all registers
*/
ENTRY(swapcontext)
/* save to oucp */
add r0, #UC_MCONTEXT
str sp, [r0, #MC_SP]
str lr, [r0, #MC_LR]
add r0, #MC_GPRS
stm r0, {r0-r12, lr}
/* retore from ucp */
add r1, #UC_MCONTEXT
ldr sp, [r1, #MC_SP]
ldr lr, [r1, #MC_LR]
add r1, #MC_GPRS
ldm r1, {r0-r12, pc}
ENDPROC(swapcontext)
ENTRY(return_from_makecontext)
/* retrieve the struct& from the top of the stack */
ldr r0, [sp]
/* get the machine struct for the linked context */
ldr r0, [r0, #UC_LINK]
add r0, #UC_MCONTEXT
/* restore the link context */
ldr sp, [r0, #MC_SP]
ldr lr, [r0, #MC_LR]
add r0, #MC_GPRS
//FIXME: return code - the r0 value that is restored from the stack should be 0
ldm r0, {r0-r12, pc}
ENDPROC(return_from_makecontext)
.macro fault_handler f
push {r4-r11} @ save non-scratch registers at time of fault
mov r0, sp
mov r2, lr @ lr contains EXC_RETURN, fault was taken in thread or interrupt?
@ We don't handle faults taken in interrupt handler at the moment.
@ Hence the scratch registers auto pushed to the stack by the CPU
@ on interrupt-entry have been pushed to PSP (MSP is only used by
@ interrupts handler).
mrs r1, psp
b \f
.endm /* fault_handler */
ENTRY(hardf)
fault_handler hardfault
ENDPROC(hardf)
ENTRY(memf)
fault_handler memmanage
ENDPROC(memf)
ENTRY(busf)
fault_handler busfault
ENDPROC(busf)
ENTRY(usgf)
fault_handler usagefault
ENDPROC(usgf)
ENTRY(__do_idle)
wfi
bx lr
ENDPROC(__do_idle)
/* void v7m_semihost_exit(int status); */
ENTRY(v7m_semihost_exit)
tst r0, r0
ite eq
ldreq r1, =0x20026 /* [a] */
movne r1, #0
mov r0, #0x18 /* [b] */
bkpt #0xab
0: b 0b
ENDPROC(v7m_semihost_exit)
/* [a] https://lists.nongnu.org/archive/html/qemu-devel/2014-12/msg01575.html
* ADP_Stopped_ApplicationExit is used for exit(0), anything else is
* implemented as exit(1). */
/* [b] http://git.qemu.org/?p=qemu.git;a=blob_plain;f=target-arm/arm-semi.c;hb=HEAD
* List of supported semihosting calls in Qemu. */
================================================
FILE: arch/v7m-faults.c
================================================
#include <kernel/faults.h>
#include <kernel/thread.h>
#include "kernel.h"
#define UFSR_DIVBYZERO (1 << 9)
#define UFSR_UNALIGNED (1 << 8)
#define UFSR_NOCP (1 << 3)
#define UFSR_INVPC (1 << 2)
#define UFSR_INVSTATE (1 << 1)
#define UFSR_UNDEFINSTR 1
void dump_frame(struct kernel_context_regs *noscratch,
struct thread_context_regs *scratch,
u32 exc_return)
{
printk(" r0: %08x r1: %08x r2: %08x r3: %08x\n",
scratch->r0_r3__r12[0], scratch->r0_r3__r12[1],
scratch->r0_r3__r12[2], scratch->r0_r3__r12[3]);
printk(" r4: %08x r5: %08x r6: %08x r7: %08x\n",
noscratch->r4_r12[0], noscratch->r4_r12[1], noscratch->r4_r12[2],
noscratch->r4_r12[3]);
printk(" r8: %08x r9: %08x r10: %08x r11: %08x\n",
noscratch->r4_r12[4], noscratch->r4_r12[5], noscratch->r4_r12[6],
noscratch->r4_r12[7]);
printk("r12: %08x sp: %08x lr: %08x pc: %08x\n",
scratch->r0_r3__r12[4], (u32) scratch, scratch->lr,
scratch->ret_addr);
printk("\nEXC_RETURN: %08x\n", exc_return);
}
void usagefault(struct kernel_context_regs *noscratch,
struct thread_context_regs *scratch,
u32 exc_return)
{
u32 ufsr = (*((volatile u32 *) 0xe000ed28)) >> 16;
const char *cause = NULL;
fault_enter("UsageFault");
dump_frame(noscratch, scratch, exc_return);
if (ufsr & UFSR_DIVBYZERO)
cause = "DIVBYZERO";
else if (ufsr & UFSR_UNALIGNED)
cause = "UNALIGNED";
else if (ufsr & UFSR_NOCP)
cause = "NOCP";
else if (ufsr & UFSR_INVPC)
cause = "INVPC";
else if (ufsr & UFSR_INVSTATE)
cause = "INVSTATE";
else if (ufsr & UFSR_UNDEFINSTR)
cause = "UNDEFINSTR";
if (cause)
printk(" ufsr: %08x <%s>\n", ufsr, cause);
else
printk(" ufsr: %08x\n", ufsr);
fault_exit();
}
void busfault(struct kernel_context_regs *noscratch,
struct thread_context_regs *scratch,
u32 exc_return)
{
fault_enter("BusFault");
dump_frame(noscratch, scratch, exc_return);
fault_exit();
}
void memmanage(struct kernel_context_regs *noscratch,
struct thread_context_regs *scratch,
u32 exc_return)
{
fault_enter("MemManage");
dump_frame(noscratch, scratch, exc_return);
fault_exit();
}
================================================
FILE: arch/v7m-head.S
================================================
#include <kernel/linkage.h>
.syntax unified
.thumb
.section ".vector", "a"
.long __early_stack_start__ @ SP_main value
.long reset @ Reset
.long 0 @ NMI
.long hardf @ HardFault
.long memf @ MemManage
.long busf @ BusFault
.long usgf @ UsageFault
.long 0 @ Reserved
.long 0 @ Reserved
.long 0 @ Reserved
.long 0 @ Reserved
.long svcall @ SVCall
.long 0 @ Debug Monitor
.long 0 @ Reserved
.long pendsv @ PendSV
.long systick @ SysTick
.long irq_entry @ IRQ 0
.long irq_entry @ IRQ 1
.long irq_entry @ IRQ 2
.long irq_entry @ IRQ 3
.long irq_entry @ IRQ 4
.long irq_entry @ IRQ 5
.long irq_entry @ IRQ 6
.long irq_entry @ IRQ 7
.long irq_entry @ IRQ 8
.long irq_entry @ IRQ 9
.long irq_entry @ IRQ 10
.long irq_entry @ IRQ 11
.long irq_entry @ IRQ 12
.long irq_entry @ IRQ 13
.long irq_entry @ IRQ 14
.long irq_entry @ IRQ 15
.long irq_entry @ IRQ 16
.long irq_entry @ IRQ 17
.long irq_entry @ IRQ 18
.long irq_entry @ IRQ 19
.long irq_entry @ IRQ 20
.long irq_entry @ IRQ 21
.long irq_entry @ IRQ 22
.long irq_entry @ IRQ 23
.long irq_entry @ IRQ 24
.long irq_entry @ IRQ 25
.long irq_entry @ IRQ 26
.long irq_entry @ IRQ 27
.long irq_entry @ IRQ 28
.long irq_entry @ IRQ 29
.long irq_entry @ IRQ 30
.long irq_entry @ IRQ 31
.long irq_entry @ IRQ 32
.long irq_entry @ IRQ 33
.long irq_entry @ IRQ 34
.long irq_entry @ IRQ 35
.long irq_entry @ IRQ 36
.long irq_entry @ IRQ 37
.long irq_entry @ IRQ 38
.long irq_entry @ IRQ 39
.long irq_entry @ IRQ 40
.long irq_entry @ IRQ 41
.long irq_entry @ IRQ 42
.long irq_entry @ IRQ 43
.long irq_entry @ IRQ 44
.long irq_entry @ IRQ 45
.long irq_entry @ IRQ 46
.long irq_entry @ IRQ 47
.long irq_entry @ IRQ 48
.long irq_entry @ IRQ 49
.long irq_entry @ IRQ 50
.long irq_entry @ IRQ 51
.long irq_entry @ IRQ 52
.long irq_entry @ IRQ 53
.long irq_entry @ IRQ 54
.long irq_entry @ IRQ 55
.long irq_entry @ IRQ 56
.long irq_entry @ IRQ 57
.long irq_entry @ IRQ 58
.long irq_entry @ IRQ 59
.long irq_entry @ IRQ 60
.long irq_entry @ IRQ 61
.long irq_entry @ IRQ 62
.long irq_entry @ IRQ 63
.text
/*
* mov32 - loads a 32-bit value into a register without a data access
*/
.macro mov32 rd, imm32
movw \rd, #:lower16:\imm32
.if \imm32 & 0xffff0000
movt \rd, #:upper16:\imm32
.endif
.endm
ENTRY(reset)
ldr r0, =SystemInit /* CMSIS system init */
blx r0
mov32 r0, 0xe000ed00 /* SCB_BASE */
@ switch to Handler_Mode
ldr r1, =__early_stack_end__ /* allocate a temporary vector */
str r1, [r0, #8] /* update VTOR */
ldr r2, =0f
orr r2, #1 /* set thumb bit */
str r2, [r1, #11 * 4] /* offset to SVC entry */
dsb /* [1] */
svc #0
0:
@ restore the early vector
ldr r1, =__vector_start__
str r1, [r0, #8] /* restore VTOR */
dsb /* [1] */
@ copy the initialized data sections
ldr r0, =__data_start__
ldr r1, =__rodata_end__
ldr r2, =__data_size__
bl memcpy
@ zero-fill the non-initialized data sections
ldr r0, =__bss_start__
movs r1, #0
ldr r2, =__bss_size__
bl memset
@ start_kernel procedure returns the first thread to run on the CPU
bl start_kernel
cmp r0, #0
itt ne
ldrne r1, =thread_restore
bxne r1
0: b 0b
ENDPROC(reset)
/* [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0321a/BIHDGBJG.html */
ENTRY(irq_entry)
push {lr}
ldr r0, =irq_handler
mrs r1, ipsr
sub r1, #16
ldr.w r0, [r0, r1, lsl #2]
blx r0
pop {pc}
ENDPROC(irq_entry)
.weak systick
systick:
bx lr
.balign 8
================================================
FILE: arch/v7m-svcall.S
================================================
#include <kernel/linkage.h>
.syntax unified
.thumb
@ offsets in the frame to the registers saved on interrupt-entry
.set R0, 0
.set RET_ADDRESS, 24
.set xPSR, 0x1c
ENTRY(svcall)
push {lr}
mrs lr, psp
ldr r12, [lr, #RET_ADDRESS]
ldrb r12, [r12, #-2] @ address of the SVC call site
tbb [pc, r12]
0: .irpc argc, 0123456
.byte ($\argc - 0b) / 2
.endr
.balign 2
.balign 2
$0: ldr r12, =syscall_vect
ldr.w r12, [r12, r0, lsl #2]
blx r12
b 0f
.balign 2
$1: ldr r12, =syscall_vect
ldr.w r12, [r12, r1, lsl #2]
blx r12
b 0f
.balign 2
$2: ldr r12, =syscall_vect
ldr.w r12, [r12, r2, lsl #2]
blx r12
b 0f
.balign 2
$3: ldr r12, =syscall_vect
ldr.w r12, [r12, r3, lsl #2]
blx r12
b 0f
.balign 2
$4: ldr r12, [lr, #xPSR] @ test stack alignment
tst r12, #1 << 9
ite eq
ldreq lr, [lr, #0x20] @ load syscall id
ldrne lr, [lr, #0x24]
ldr r12, =syscall_vect
ldr.w r12, [r12, lr, lsl #2]
blx r12
b 0f
.balign 2
$5: ldr r12, [lr, #xPSR] @ test stack alignment
tst r12, #1 << 9
ite eq
addeq lr, #0x20
addne lr, #0x24
ldm lr, {r12, lr} @ load syscall id, arg4
push {r12} @ copy arg4 to kernel stack
ldr r12, =syscall_vect
ldr.w r12, [r12, lr, lsl #2]
blx r12
add sp, #4
b 0f
.balign 2
$6: ldr r12, [lr, #xPSR] @ test stack alignment
tst r12, #1 << 9
ite eq
addeq lr, #0x20
addne lr, #0x24
ldm lr, {r11, r12, lr} @ load syscall id, arg4, arg5
push {r11, r12} @ copy arg4, arg5 to kernel stack
ldr r12, =syscall_vect
ldr.w r12, [r12, lr, lsl #2]
blx r12
pop {r11, r12} //FIXME: pop {r11}; add sp, #4;
.global syscall_return
syscall_return:
0: mrs r1, psp
str r0, [r1, #R0] @ update return value in exception frame
pop {pc}
ENDPROC(svcall)
================================================
FILE: docs/Makefile
================================================
# Piko/RT documentation
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = piko
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help clean Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
clean:
-rm -rf _build/* posix/posix_*.rst
check:
python3 ../scripts/rstlint.py
================================================
FILE: docs/api.rst
================================================
.. _api:
Piko/RT POSIX API
=================
``Piko/RT`` aim to fulfill IEEE 1003.13-2003 PSE51 standard, this is the list of
POSIX API that ``Piko/RT`` implemented.
Units of Functionality Requirements
-----------------------------------
.. include:: posix/posix_req.rst
POSIX.1 Option Requirements
---------------------------
.. include:: posix/posix_opt.rst
================================================
FILE: docs/build.rst
================================================
.. _build:
Build Piko/RT
=============
This chapter will help you start to build ``Piko/RT``, you will need to prepare
some pacakge and settings.
Prerequisites
-------------
* svn: used to checkout `CMSIS <https://github.com/ARMmbed/mbed-os/cmsis>`_.
* wget: used to download required files.
* arm-none-eabi-gcc arm-none-eabi-newlib: cross-compile toolchain.
Arch Linux::
$ pacman -S base-devel svn lsb-release wget
$ pacman -S arm-none-eabi-gcc arm-none-eabi-newlib
$ pacman -S python
Ubuntu::
$ add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
$ apt update -qq
$ apt install build-essential svn gcc-arm-embedded
macOS::
# If you didn't build any thing on macOS before
# please install xcode-select first
$ xcode-select --install
# install brew from https://brew.sh
$ brew install subversion wget
$ brew tap PX4/homebrew-px4
$ brew install gcc-arm-none-eabi-49
Build Piko/RT on Linux and macOS
--------------------------------
Default make will build for ``f429disco``::
$ make
You can change the target via ``PLAT``::
$ make PLAT=stm32p103
You can build faster via passing ``-j`` flag::
$ make PLAT=stm32p103 -j8
You can build with verbose output::
$ make PLAT=stm32p103 -j8 VERBOSE=1
Troubleshooting
---------------
If you concur problem when building Piko/RT, please help to fill the issue
on `GitHub <https://github.com/piko-rt/pikoRT/issues>`_,
and maybe help to improve the build process, or improve this troubleshooting
part!
================================================
FILE: docs/conf.py
================================================
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# piko documentation build configuration file, created by
# sphinx-quickstart on Tue Aug 15 18:28:39 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Piko/RT'
copyright = '2017, Piko/RT Developers'
author = 'Piko/RT Developers'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.1'
# The full version, including alpha/beta/rc tags.
release = '0.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'pikodoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'piko.tex', 'piko Documentation',
'Piko/RT Developers', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'piko', 'piko Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'piko', 'piko Documentation',
author, 'piko', 'One line description of project.',
'Miscellaneous'),
]
# -- Generate POSIX API list ----------------------------------------------
import subprocess
subprocess.check_output(['python3', 'posix/parse.py'])
================================================
FILE: docs/contribute.rst
================================================
.. _contribute:
Contribute to Piko/RT
=====================
We welcome everyone to help to develop Piko/RT.
This will help you to find were to help, and how to submit a pull request
to GitHub.
How to contribute
-----------------
There are a variety of ways to contribute to this project.
Here are the list what you may help:
* Write documentation.
* Report issue when you occure.
* Implement new feature.
* Code review -- this is always helpful.
* Make a bug fixed and send the patches.
* Adding new test.
* Integrate new feature -- benchmark, TCP stack, GNU utilt...etc.
* Port to new paltform.
Create your GitHub account
--------------------------
If you have a GitHub account, please skip this section.
If you don't have, please follow these step:
* Click `Join GitHub <https://github.com/join>`_
* Fill the form
* Confirm your email
Fork Piko/RT repo
-----------------
* Go to `Piko/RT repo <https://github.com/piko-rt/pikoRT>`_
* Click the buttom "Fork" at the right top side.
* Done!
Clone the Piko/RT repo
----------------------
You will need a copy of Piko/RT to work on the code::
$ git clone https://github.com/<your-username>/pikoRT
Create a local Git branch
-------------------------
If you make some changed to the project, and want to share with everyone,
you will need to upload to GitHub.
First, create a new branch::
$ git checkout -b <branch-name>
Then commit the changed in this branch::
$ git add <your-changed>
$ git commit
Push it to your fork::
$ git push -u origin <branch-name>
Publish your pull request
-------------------------
You will then need to go to `Piko/RT's repo <https://github.com/piko-rt/pikoRT>`_,
Click ``Pull reuqests``, Click green button ``New pull request``.
Then reference this tutorial from GitHub:
`Creating a pull request from a fork <https://help.github.com/articles/creating-a-pull-request-from-a-fork/>`_
Git remotes
-----------
Your local git repo's origin is your fork. So if you do something like this::
$ git pull
You won't get the latest commit from Piko/RT.
You will need to add a upstream, fetch from it, then rebase::
$ git remote add upstream git@github.com:Piko-RT/pikoRT.git
$ git fetch upstream
$ git rebase upstream/master
.. note::
Before you rebase, you will need to stash all your change via ``git stash``.
After rebase, if you want your stash file back, you can type in
``git stash pop`` to get back your stash.
================================================
FILE: docs/debugging.rst
================================================
.. _debugging:
Piko/RT Debugging
=================
Using tmux
----------
`tmux <https://github.com/tmux/tmux>`_ is a "terminal multiplexer", it allow you
accessed and controllerd multiple terminals inside a signle terminal like this:
.. image:: https://gifyu.com/images/asciicast.json.gif
How to use tmux, please reference these pages:
* `tmux wiki <https://github.com/tmux/tmux/wiki>`_
* `A tmux Crash Course <https://robots.thoughtbot.com/a-tmux-crash-course>`_
* `A Quick and Easy Guide to tmux <http://www.hamvocke.com/blog/a-quick-and-easy-guide-to-tmux/>`_
Using OpenOCD
-------------
XXX
Using gdb scripts
-----------------
Here are some debug scripts for gdb. You can copy and paste to your `.gdbinit`,
then used in gdb.
1. Dump out bitmap scheduler active and expire queue::
define dump_bitmap
set $prio = 0
while $prio < 32
if $arg0 == 1
p (struct thread_info *)((char *)(sched_struct.active->queue[$prio].next) - 0x28)
end
if $arg0 == 0
p (struct thread_info *)((char *)(sched_struct.expire->queue[$prio].next) - 0x28)
end
set $prio = $prio + 1
end
end
how to use::
(gdb) dump_bitmap 1 # Dump active
$1 = (struct thread_info *) 0x20000d2c <vsnprintf_buf+228>
$2 = (struct thread_info *) 0x20000d34 <vsnprintf_buf+236>
$3 = (struct thread_info *) 0x20000d3c <vsnprintf_buf+244>
$4 = (struct thread_info *) 0x20000d44 <vsnprintf_buf+252>
$5 = (struct thread_info *) 0x20000d4c <sched>
$6 = (struct thread_info *) 0x20000d54 <_active+4>
...
(gdb) dump_bitmap 0 # Dump expire
2. Dump out RR scheduler runqueue::
define dump_rr
if list_empty(&rr_runq)
p "empty rr"
else
set $pos = rr_runq->next
while $pos != &rr_runq
p (struct thread_info *)((char *)($pos)-0x28)
set $pos = $pos->next
end
end
end
how to use::
(gdb) dump_rr
================================================
FILE: docs/emulate.rst
================================================
.. _emulate:
Using QEMU to Develop Piko/RT
=============================
Prepare QEMU
------------
You will need to prepare QEMU STM32 emulator from:
`QEMU STM32 v0.1.3 <https://github.com/beckus/qemu_stm32/releases>`_
After download, compile the qemu_stm32 by::
$ ./configure --disable-werror --enable-debug \
--target-list="arm-softmmu" \
--extra-cflags=-DDEBUG_CLKTREE \
--extra-cflags=-DDEBUG_STM32_RCC \
--extra-cflags=-DDEBUG_STM32_UART \
--extra-cflags=-DSTM32_UART_NO_BAUD_DELAY \
--extra-cflags=-DSTM32_UART_ENABLE_OVERRUN --python=python2
$ make -j8
Make sure you have export the ``arm-softmmu`` to ``$PATH````::
$ export PATH=$PATH:~/qemu_stm32-stm32_v0.1.3/arm-softmmu
Run Piko/RT on QEMU STM32-p103
------------------------------
You will need to run these command::
$ make PLAT=stm32p103
$ make PLAT=stm32p103 run
If you run correctly, then you will start Piko/RT and get the shell::
Memory map:
.text = 00000140--0000315a 12314 Bytes
.rodata = 00003190--00003a26 2198 Bytes
.data = 20000000--20000514 1300 Bytes
.bss = 20000518--20001298 3456 Bytes
.heap = 200012a0--200022a0 4096 Bytes
.pgmem = 20008000--2000f000 28672 Bytes
Order Bitmap
0 00000000 00000000 00000000 00000000
1 00000000 00000000
2 00000000
3 00007fff
Created idle_thread at <0x20008200>
Created main_thread at <0x20008800> with priority=31
Reclaim early stack's physical memory (2048 Bytes, order=3).
Creating /proc/version
Creating /proc/meminfo
Creating /dev/mem
Creating /dev/null
Creating /dev/zero
Creating /dev/random
Creating MTD device mtd0
Kernel bootstrap done.
--
$
================================================
FILE: docs/index.rst
================================================
Welcome to piko's documentation!
================================
.. toctree::
:maxdepth: 2
:caption: Contents:
build.rst
emulate.rst
kernel.rst
test.rst
contribute.rst
debugging.rst
.. toctree::
:caption: API:
api.rst
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
================================================
FILE: docs/kernel.rst
================================================
.. _kernel:
Piko/RT Design & Concept
========================
Piko/RT is a tiny Linux-like real-time operating system kernel, optimized for
Arm Cortex-M series microprocessors.
Compatibility with Linux is **NOT** the goal of Piko/RT. Instead, PSE51
(minimal real-time system profile) should be appropriately an analog from
the perspective of design.
================================================
FILE: docs/make.bat
================================================
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=piko
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd
================================================
FILE: docs/posix/parse.py
================================================
# Helper for generate POSIX API table
# XXX: used from docs, not here
import glob
import os
import tempfile
import shutil
import subprocess
CSCOPE = shutil.which('cscope') if shutil.which('cscope') else '/usr/bin/cscope'
CSCOPE_DB = tempfile.NamedTemporaryFile()
BACKTO = '../'
LIBC_PATH = BACKTO + 'libc'
def read_file(path):
# Return list of API
return open(path).read().replace(' ', '').replace('\n', '').strip().split(',')
def build_cscope():
CSCOPE_DB.write(subprocess.check_output("find %s -name '*.c'" % LIBC_PATH, shell=True))
CSCOPE_DB.write(subprocess.check_output("find %s -name '*.h'" % LIBC_PATH, shell=True))
CSCOPE_DB.write(subprocess.check_output("find %s -name '*.S'" % LIBC_PATH, shell=True))
CSCOPE_DB.flush()
return CSCOPE_DB.name
def cscope_search(name):
return subprocess.check_output("%s -i %s -L1%s" % (CSCOPE, CSCOPE_DB.name, name), shell=True)
def parse_path(s):
return s.split('\n')[0].strip(BACKTO).split()[0:3:2] if s and s.startswith(LIBC_PATH) else ('', 0)
def generate_table(name):
header = ['.. table:: %s' % os.path.basename(name), ' :widths: 45 10 35', '']
longest_api_length = 10
apis = read_file(name)
result = []
for api in apis:
if not api:
continue
longest_api_length = max(len(api), longest_api_length)
s = cscope_search(api.strip('()')).decode('utf-8')
result.append([api, s.startswith(LIBC_PATH), *parse_path(s)])
splitline = ' {:=>{}} ===== {}'.format('', longest_api_length, '=' * 30)
header.append(splitline)
header.append(' {:<{}} IMPL Path'.format('API Name', longest_api_length))
header.append(splitline)
for i, r in enumerate(result):
result[i] = (' {:<{}} {}'.format(r[0], longest_api_length, 'O' if r[1] else 'X') +
' {}'.format('{}:{}'.format(r[2], r[3]) if r[1] else ''))
result.append(splitline)
result = header + result
return '\n'.join(result)
if __name__ == '__main__':
build_cscope()
reqs = glob.glob('posix/posix_req/*')
with open('posix/posix_req.rst', 'w') as f:
for req in reqs:
f.write(generate_table(req))
f.write('\n\n')
opts = glob.glob('posix/posix_opt/*')
with open('posix/posix_opt.rst', 'w') as f:
for opt in opts:
f.write(generate_table(opt))
f.write('\n\n')
================================================
FILE: docs/posix/posix_opt/01._POSIX_CLOCK_SELECTION
================================================
clock_nanosleep()
================================================
FILE: docs/posix/posix_opt/02._POSIX_FSYNC
================================================
fsync()
================================================
FILE: docs/posix/posix_opt/03._POSIX_MEMLOCK
================================================
m lockall(), m unlockall()
================================================
FILE: docs/posix/posix_opt/04.POSIX_MEMLOCK_RANGE
================================================
mlock(), munlock()
================================================
FILE: docs/posix/posix_opt/05._POSIX_MONOTONIC_CLOCK
================================================
================================================
FILE: docs/posix/posix_opt/06._POSIX_NO_TRUNC
================================================
================================================
FILE: docs/posix/posix_opt/07._POSIX_REALTIME_SIGNALS
================================================
sigqueue(), sigtim edwait(), sigwaitinfo()
================================================
FILE: docs/posix/posix_opt/08._POSIX_SEMAPHORES
================================================
sem _close(), sem _destroy(), sem _getvalue(), sem _init(), sem _open(), sem _post(),
sem _trywait(), sem _wait(), sem _unlink (),
sem _tim edwait()
================================================
FILE: docs/posix/posix_opt/09._POSIX_SHARED_MEMORY_OBJECTS
================================================
shm _open(), shm _unlink()
================================================
FILE: docs/posix/posix_opt/10._POSIX_SYNCHRONIZED_IO
================================================
fdatasync()
================================================
FILE: docs/posix/posix_opt/11._POSIX_THREAD_ATTR_STACKADDR
================================================
pthread_attr_getstackaddr(), pthread_attr_setstackaddr()
================================================
FILE: docs/posix/posix_opt/12._POSIX_THREAD_ATTR_STACKSIZE
================================================
pthread_attr_getstack (), pthread_attr_setstack()
================================================
FILE: docs/posix/posix_opt/13._POSIX_THREAD_CPUTIME
================================================
pthread_getcpuclockid()
================================================
FILE: docs/posix/posix_opt/14._POSIX_THREAD_PRIO_INHERIT
================================================
pthread_m utexattr_getprotocol(), pthread_m utexattr_setprotocol()
================================================
FILE: docs/posix/posix_opt/15._POSIX_THREAD_PRIO_PROTECT
================================================
pthread_m utex_getprioceiling(), pthread_m utex_setprioceiling(),
pthread_m utexattr_getprioceiling(), pthread_m utexattr_getprotocol(),
pthread_m utexattr_setprioceiling(), pthread_m utexattr_setprotocol()
================================================
FILE: docs/posix/posix_opt/16._POSIX_THREAD_PRIORITY_SCHEDULING
================================================
pthread_attr_getinheritsched(), pthread_attr_getschedpolicy(),
pthread_attr_getscope(), pthread_attr_setinheritsched(),
pthread_attr_setschedpolicy(), pthread_attr_setscope(),
pthread_getschedparam (), pthread_setschedparam (), pthread_setschedprio(),
sched_get_priority_m ax(), sched_get_priority_m in(), sched_rr_get_interval()
================================================
FILE: docs/posix/posix_opt/17._POSIX_THREAD_SPORADIC_SERVER
================================================
================================================
FILE: docs/posix/posix_opt/18._POSIX_TIMERS
================================================
clock_getres(), clock_gettim e(), clock_settim e(), nanosleep(), tim er_create(),
tim er_detele(), tim er_getoverrun(), tim er_gettim e(), tim er_settim e()
================================================
FILE: docs/posix/posix_req/01.POSIX_C_LANG_SUPPORT
================================================
abs(), asctime(), asctime_r(), atof(), atoi(), atol(),
atoll(), bsearch(), calloc(), ctime(), ctime_r(),
difftime(), div(), feclearexcept(), fegetenv(),
fegetexceptflag(), fegetround(), feholdexcept(),
feraiseexcept(), fesetenv(), fesetexceptflag(),
fesetround(), fetestexcept(), feupdateenv(), free(),
gmtime(), gmtime_r(), imaxabs(), imaxdiv(),
isalnum(), isalpha(), isblank(), iscntrl(), isdigit(),
isgraph(), islower(), isprint(), ispunct(), isspace(),
isupper(), isxdigit(), labs(), ldiv(), llabs(), lldiv(),
localeconv(), localtime(), localtime_r(), malloc(),
memchr(), memcmp(), memcpy(), memmove(),
memset(), mktime(), qsort(), rand(), rand_r(),
realloc(), setlocale(), snprintf(), sprintf(), srand(),
sscanf(), strcat(), strchr(), strcmp(), strcoll(), strcpy(),
strcspn(), strerror(), strerror_r(), strftime(), strlen(),
strncat(), strncmp(), strncpy(), strpbrk(), strrchr(),
strspn(), strstr(), strtod(), strtof(), strtoimax(),
strtok(), strtok_r(), strtol(), strtold(), strtoll(),
strtoul(), strtoull(), strtoumax(), strxfrm(), time(),
tolower(), toupper(), tzname, tzset(), va_arg(),
va_copy(), va_end(), va_start(), vsnprintf(), vsprintf(),
vsscanf()
================================================
FILE: docs/posix/posix_req/02.POSIX_DEVICE_IO
================================================
clearerr(), close(), fclose(), fdopen(), feof(), ferror(),
fflush (), fgetc(), fgets(), fileno(), fopen(), fprintf(),
fputc(), fputs(), fread(), freopen(), fscanf(), fwrite(),
getc(), getchar(), gets(), open(), perror(), printf(),
putc(), putchar(), puts(), read(), scanf(), setbuf(),
setvbuf(), stderr, stdin, stdout, ungetc(), vfprintf(),
vfscanf(), vprintf(), vscanf(), write()
================================================
FILE: docs/posix/posix_req/03.POSIX_FILE_LOCKING
================================================
flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(),
getchar_unlocked(), putc_unlocked(),
putchar_unlocked()
================================================
FILE: docs/posix/posix_req/04.POSIX_SIGNALS
================================================
abort(), alarm(), kill(), pause(), raise(), sigaction(),
sigaddset(), sigdelset(), sigemptyset(), sigfillset(),
sigismember(), signal(), sigpending(), sigprocmask(),
sigsuspend(), sigwait()
================================================
FILE: docs/posix/posix_req/05.POSIX_SINGLE_PROCESS
================================================
confstr(), environ, errno, getenv(), setenv(), sysconf(),
uname(), unsetenv()
================================================
FILE: docs/posix/posix_req/06.POSIX_THREADS_BASE
================================================
pthread_atfork(), pthread_attr_destroy(),
pthread_attr_getdetachstate(),
pthread_attr_getschedparam(), pthread_attr_init(),
pthread_attr_setdetachstate(),
pthread_attr_setschedparam(), pthread_cancel(),
pthread_cleanup_pop(), pthread_cleanup_push(),
pthread_cond_broadcast(), pthread_cond_destroy(),
pthread_cond_init(), pthread_cond_signal(),
pthread_cond_timedwait(), pthread_cond_wait(),
pthread_condattr_destroy(), pthread_condattr_init(),
pthread_create(), pthread_detach(), pthread_equal(),
pthread_exit(), pthread_getspecific(), pthread_join(),
pthread_key_create(), pthread_key_delete(),
pthread_kill(), pthread_mutex_destroy(),
pthread_mutex_init(), pthread_mutex_lock(),
pthread_mutex_trylock(), pthread_mutex_unlock(),
pthread_mutexattr_destroy(),
pthread_mutexattr_init(), pthread_once(),
pthread_self(), pthread_setcalcelstate(),
pthread_setcanceltype(), pthread_setspecific(),
pthread_sigmask(), pthread_testcancel()
================================================
FILE: docs/posix/posix_req/07.XSI_THREAD_MUTEX_EXT
================================================
pthread_mutexattr_gettype(),
pthread_mutexattr_settype()
================================================
FILE: docs/posix/posix_req/08.XSI_THREADS_EXT
================================================
pthread_attr_getguardsize(), pthread_attr_getstack(),
pthread_attr_setguardsize(),
pthread_attr_setstack(), pthread_getconcurrency(),
pthread_setconcurrency()
================================================
FILE: docs/test.rst
================================================
.. _test:
Piko/RT Test Suite
==================
Piko/RT test suite is under ``tests`` directory, it contain a makefile, many test
folder and it self is a python package. Each test folder represent a test case.
Run Tests
---------
Test suite can be run by top directory Makefile::
$ make PLAT=stm32p103 check
This will run all test in the test suite, also, you can use ``tests`` as a python
package, to run all test via python command line::
$ python -m tests
You can also run partial via python::
$ python -m tests fs_1 stat_1 thread_5
Python command line tool verbose default is disable, you can pass the flag ``-v``
to enable::
$ python -m tests -v
$ python -m tests fs_1 -v
================================================
FILE: drivers/char/mem.c
================================================
#include <string.h>
#include <kernel/fs.h>
#include <kernel/kernel.h>
static int mem_open(__unused struct inode *inode, __unused struct file *file)
{
return 0;
}
static ssize_t write_mem(__unused struct file *file,
const char *buf,
size_t count,
off_t *offset)
{
memcpy((void *) offset, buf, count);
return count;
}
static ssize_t read_mem(__unused struct file *file,
char *buf,
size_t count,
off_t offset)
{
memcpy(buf, (void *) offset, count);
return count;
}
static ssize_t write_null(__unused struct file *file,
__unused const char *buf,
size_t count,
__unused off_t *offset)
{
return count;
}
static ssize_t read_null(__unused struct file *file,
__unused char *buf,
__unused size_t count,
__unused off_t offset)
{
return 0;
}
static ssize_t read_zero(__unused struct file *file,
char *buf,
size_t count,
__unused off_t offset)
{
memset(buf, 0, count);
return count;
}
static const struct file_operations mem_fops = {
.open = mem_open,
.read = read_mem,
.write = write_mem,
};
static const struct file_operations null_fops = {
.open = mem_open,
.read = read_null,
.write = write_null,
};
static const struct file_operations zero_fops = {
.open = mem_open,
.read = read_zero,
.write = write_null,
};
extern const struct file_operations random_fops;
extern const struct inode_operations tmpfs_iops;
static struct inode memdev_inodes[] = {
{
/* /dev/mem */
.i_ino = 101,
.i_op = &tmpfs_iops,
.i_fop = &mem_fops,
},
{
/* /dev/null */
.i_ino = 102,
.i_op = &tmpfs_iops,
.i_fop = &null_fops,
},
{
/* /dev/zero */
.i_ino = 103,
.i_op = &tmpfs_iops,
.i_fop = &zero_fops,
},
{
/* /dev/random */
.i_ino = 104,
.i_op = &tmpfs_iops,
.i_fop = &random_fops,
},
};
void memdev_init(void)
{
struct dentry dentry;
const char *names[] = {"mem", "null", "zero", "random"};
for (int i = 0; i < 4; i++) {
printk("Creating /dev/%s\n", names[i]);
dentry.d_inode = &memdev_inodes[i], strcpy(dentry.d_name, names[i]);
vfs_link(0, dev_inode(), &dentry);
}
}
================================================
FILE: drivers/char/random.c
================================================
#include <stdint.h>
#include <string.h>
#include <sys/param.h>
//#include <kernel/kernel.h>
#include <kernel/fs.h>
typedef unsigned long long u64;
/* xorshift1024* generator, http://vigna.di.unimi.it/ftp/papers/xorshift.pdf */
static u64 next(void)
{
// clang-format off
static u64 s[16] = {
0x84242f96eca9c41dull, 0xa3c65b8776f96855ull, 0x5b34a39f070b5837ull,
0x4489affce4f31a1eull, 0x2ffeeb0a48316f40ull, 0xdc2d9891fe68c022ull,
0x3659132bb12fea70ull, 0xaac17d8efa43cab8ull, 0xc4cb815590989b13ull,
0x5ee975283d71c93bull, 0x691548c86c1bd540ull, 0x7910c41d10a1e6a5ull,
0x0b5fc64563b3e2a8ull, 0x047f7684e9fc949dull, 0xb99181f2d8f685caull,
0x284600e3f30e38c3ull
};
// clang-format on
static int p;
const u64 s0 = s[p];
u64 s1 = s[p = (p + 1) & 15];
s1 ^= s1 << 31; // a
s[p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c
return s[p] * UINT64_C(1181783497276652981);
}
static int open_random(__unused struct inode *inode, __unused struct file *file)
{
return 0;
}
static ssize_t read_random(__unused struct file *file,
char *buf,
size_t count,
__unused off_t offset)
{
static u64 m;
static int remaining_bytes = 0;
if ((int) count <= remaining_bytes) {
memcpy(buf, (char *) &m + 8 - remaining_bytes, count);
remaining_bytes -= count;
} else {
for (int i = count; i > 0; i -= 8, buf = (char *) buf + 8) {
m = next();
memcpy(buf, &m, MIN(i, 8));
remaining_bytes = 8 - MIN(i, 8);
}
}
return count;
}
const struct file_operations random_fops = {
.open = open_random,
.read = read_random,
};
================================================
FILE: drivers/mtd/mtd.h
================================================
#ifndef _DRIVERS_MTD_MTD_H
#define _DRIVERS_MTD_MTD_H
#include <sys/types.h>
#include <kernel/errno-base.h>
#include <kernel/types.h>
#define MTD_ERASE_PENDING (1 << 0)
#define MTD_ERASING (1 << 1)
#define MTD_ERASE_SUSPEND (1 << 2)
#define MTD_ERASE_DONE (1 << 3)
#define MTD_ERASE_FAILED (1 << 4)
#define MTD_FAIL_ADDR_UNKNOWN -1l
#define MTD_WRITEABLE 0x400 /* Device is writeable */
struct erase_info {
/* struct mtd_info *mtd; */
u32 addr;
u32 len;
u32 fail_addr;
/* u_long time; */
/* u_long retries; */
/* unsigned dev; */
/* unsigned cell; */
void (*callback)(struct erase_info *self);
unsigned long priv;
unsigned char state;
struct erase_info *next;
};
struct mtd_info {
unsigned char type;
u32 flags;
unsigned long size;
unsigned long erasesize;
unsigned long writesize;
const char *name; // can this be a hash?
int (*mtd_erase)(struct mtd_info *mtd, struct erase_info *instr);
int (*mtd_point)(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
void **virt /* , resource_size_t *phys */); // virt -> at
int (*mtd_unpoint)(struct mtd_info *mtd, off_t from, size_t len);
int (*mtd_read)(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
void *buf);
int (*mtd_write)(struct mtd_info *mtd,
off_t to,
size_t len,
size_t *retlen,
const void *buf);
/* struct device *dev; */
void *priv; // can be the physical address of the flash device
};
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
int mtd_point(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
void **virt /* , resource_size_t *phys */);
int mtd_read(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
unsigned char *buf);
int mtd_write(struct mtd_info *mtd,
off_t to,
size_t len,
size_t *retlen,
const unsigned char *buf);
void mtd_erase_callback(struct erase_info *instr);
int mtdram_init_device(struct mtd_info *mtd,
void *mapped_address,
unsigned long size,
const char *name);
void mtdram_init(void);
#endif /* !_DRIVERS_MTD_MTD_H */
================================================
FILE: drivers/mtd/mtdchar.c
================================================
#include <sys/types.h>
#include <kernel/fs.h>
#include <drivers/mtd/mtd.h>
/* romfs depends on mtdchar */
static int mtdchar_open(struct inode *inode, struct file *file)
{
file->f_private = inode->i_private;
return 0;
}
static ssize_t mtdchar_read(struct file *file,
char *buf,
size_t count,
off_t offset)
{
size_t retlen;
struct mtd_info *mtd = file->f_private;
if (mtd_read(mtd, offset, count, &retlen, (unsigned char *) buf) < 0)
return -1;
return retlen;
}
static ssize_t mtdchar_write(struct file *file,
const char *buf,
size_t count,
off_t *offset)
{
size_t retlen;
struct mtd_info *mtd = file->f_private;
if (mtd_write(mtd, *offset, count, &retlen, (const unsigned char *) buf) <
0)
return -1;
return retlen;
}
const struct file_operations mtdchar_fops = {
.open = mtdchar_open,
.read = mtdchar_read,
.write = mtdchar_write,
};
================================================
FILE: drivers/mtd/mtdcore.c
================================================
#include <stddef.h>
#include <drivers/mtd/mtd.h>
void mtd_erase_callback(struct erase_info *instr)
{
if (instr->callback)
instr->callback(instr);
}
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
if ((instr->addr >= mtd->size) || (instr->len > mtd->size - instr->addr))
return -EINVAL;
if (!(mtd->flags & MTD_WRITEABLE))
return -EROFS;
instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
if (!instr->len) {
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return 0;
}
return mtd->mtd_erase(mtd, instr);
}
int mtd_point(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
void **virt /* , resource_size_t *phys */)
{
*retlen = 0;
*virt = NULL;
if (!mtd->mtd_point)
return -1; // return -EOPNOTSUPP;
if ((from < 0) || ((unsigned long) from >= mtd->size) ||
(len > mtd->size - from))
return -EINVAL;
if (!len)
return 0;
return mtd->mtd_point(mtd, from, len, retlen, virt /* , phys */);
}
int mtd_read(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
unsigned char *buf)
{
*retlen = 0;
if ((from < 0) || ((unsigned long) from >= mtd->size) ||
(len > mtd->size - from))
return -EINVAL;
if (!len)
return 0;
return mtd->mtd_read(mtd, from, len, retlen, buf);
}
int mtd_write(struct mtd_info *mtd,
off_t to,
size_t len,
size_t *retlen,
const unsigned char *buf)
{
*retlen = 0;
if ((to < 0) || ((unsigned long) to >= mtd->size) || (len > mtd->size - to))
return -EINVAL;
if (!len)
return 0;
return mtd->mtd_write(mtd, to, len, retlen, buf);
}
================================================
FILE: drivers/mtd/mtdram.c
================================================
#include <string.h>
#include <kernel/fs.h>
#include <kernel/kernel.h>
#include <drivers/mtd/mtd.h>
#define SIZE_1KB 1024
static int mtdram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
memset((char *) mtd->priv + instr->addr, 0xff, instr->len);
instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
return 0;
}
static int mtdram_point(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
void **virt /* , resource_size_t *phys */) // void **at
{
*virt = mtd->priv + from;
*retlen = len;
return 0;
}
static int mtdram_unpoint(struct mtd_info *mtd, off_t from, size_t len)
{
(void) mtd, (void) from, (void) len;
return 0;
}
int mtdram_write(struct mtd_info *mtd,
off_t to,
size_t len,
size_t *retlen,
const void *buf)
{
memcpy((char *) mtd->priv + to, buf, len);
*retlen = len;
return 0;
}
int mtdram_read(struct mtd_info *mtd,
off_t from,
size_t len,
size_t *retlen,
void *buf)
{
memcpy(buf, mtd->priv + from, len);
*retlen = len;
return 0;
}
int mtdram_init_device(struct mtd_info *mtd,
void *mapped_address,
unsigned long size,
const char *name)
{
if (size % SIZE_1KB)
return -1;
mtd->name = name;
mtd->size = size;
mtd->erasesize = SIZE_1KB, mtd->priv = mapped_address;
mtd->mtd_erase = mtdram_erase;
mtd->mtd_point = mtdram_point;
mtd->mtd_unpoint = mtdram_unpoint;
mtd->mtd_read = mtdram_read;
mtd->mtd_write = mtdram_write;
return 0;
}
struct mtd_info mtdram;
extern char __mtdram_start__;
extern char __mtdram_size__;
extern const struct file_operations mtdchar_fops;
static struct inode mtd0_inode = {
.i_fop = &mtdchar_fops,
.i_private = &mtdram,
};
void mtdram_init(void)
{
struct dentry dentry = {.d_inode = &mtd0_inode, .d_name = "mtd0"};
printk("Creating MTD device %s\n", dentry.d_name);
mtdram_init_device(&mtdram, &__mtdram_start__,
(unsigned long) &__mtdram_size__, dentry.d_name);
init_tmpfs_inode(&mtd0_inode);
vfs_link(NULL, dev_inode(), &dentry);
}
================================================
FILE: drivers/serial/serialchar.c
================================================
#include <sys/types.h>
#include <kernel/fs.h>
#include <kernel/sched.h>
#include <kernel/serial.h>
#include <kernel/thread.h>
static void serialchar_callback(struct serial_info *serial)
{
sched_enqueue(serial->owner);
}
static int serialchar_open(struct inode *inode, struct file *file)
{
file->f_private = inode->i_private;
struct serial_info *serial = file->f_private;
CURRENT_THREAD_INFO(cur_thread);
serial->owner = cur_thread;
serial->ops->callback = serialchar_callback;
return 0;
}
static ssize_t serialchar_read(struct file *file,
char *buf,
size_t count,
__unused off_t offset)
{
size_t retlen;
struct serial_info *serial = file->f_private;
while (serial->rx_count < count) {
CURRENT_THREAD_INFO(cur_thread);
sched_dequeue(cur_thread);
sched_elect(0);
}
if (count == 1)
return serial_getc(serial, buf);
if (serial_gets(serial, count, &retlen, buf) < 0)
return -1;
return retlen;
}
static ssize_t serialchar_write(struct file *file,
const char *buf,
size_t count,
__unused off_t *offset)
{
struct serial_info *serial = file->f_private;
return serial_puts(serial, count, buf);
}
const struct file_operations serialchar_fops = {
.open = serialchar_open,
.read = serialchar_read,
.write = serialchar_write,
};
================================================
FILE: drivers/serial/serialcore.c
================================================
#include <sys/types.h>
#include <kernel/serial.h>
void serial_init(void)
{
extern unsigned long __serial_hook_start__;
extern unsigned long __serial_hook_end__;
for (struct serial_hook *hook = (struct serial_hook *) &__serial_hook_start__;
hook < (struct serial_hook *) &__serial_hook_end__; hook++)
hook->init();
}
void serial_activity_callback(struct serial_info *serial)
{
if (serial->ops->callback)
serial->ops->callback(serial);
}
int serial_getc(struct serial_info *serial, char *c)
{
return serial->ops->serial_getc(serial, c);
}
int serial_gets(struct serial_info *serial,
size_t len,
size_t *retlen,
char *buf)
{
return serial->ops->serial_gets(serial, len, retlen, buf);
}
int serial_putc(struct serial_info *serial, char c)
{
return serial->ops->serial_putc(serial, c);
}
int serial_puts(struct serial_info *serial,
size_t len,
const char *buf)
{
return serial->ops->serial_puts(serial, len, buf);
}
================================================
FILE: drivers/serial/stm32-uart.c
================================================
#include <stdio.h>
#include <sys/types.h>
#include <kernel/cbuf.h>
#include <kernel/fs.h>
#include <kernel/irq.h>
#include <kernel/serial.h>
#include <kernel/types.h>
#include <cmsis.h>
#include "platform.h"
static struct cbuf_info cbuf;
static char buf[16];
static int stm32_getc(struct serial_info *serial, char *c)
{
serial->rx_count--;
cbuf_getc(&cbuf, c);
return 0;
}
static int stm32_putc(struct serial_info *serial, char c)
{
if (!serial || c < 0)
return EOF;
USART_TypeDef *uart = serial->priv;
while (!(uart->SR & USART_SR_TXE))
;
uart->DR = c;
return c;
}
static int stm32_puts(struct serial_info *serial,
size_t len,
const char *buf)
{
int i = 0;
for (i = 0; i < len; i++)
if (stm32_putc(serial, buf[i]) == EOF)
return EOF;
return i;
}
static struct serial_ops stm32_ops = {
.serial_getc = stm32_getc,
.serial_putc = stm32_putc,
.serial_puts = stm32_puts,
};
struct serial_info stm32_info = {
.priv = USARTx,
.ops = &stm32_ops,
};
static void stm32_uartx_isr(void)
{
if (USARTx->SR & USART_SR_RXNE) {
char c = (char) USARTx->DR;
cbuf_putc(&cbuf, c);
stm32_info.rx_count++;
serial_activity_callback(&stm32_info);
}
}
extern const struct file_operations serialchar_fops;
static struct inode stm32_inode = {
.i_fop = &serialchar_fops,
.i_private = &stm32_info,
};
static int stm32_serial_init(void)
{
uart_init();
struct dentry dentry = {.d_inode = &stm32_inode, .d_name = "ttyS0"};
cbuf_init(&cbuf, buf, 16);
init_tmpfs_inode(&stm32_inode);
vfs_link(0, dev_inode(), &dentry);
/* enable rx interrupt */
request_irq(USARTx_IRQn, stm32_uartx_isr);
NVIC_SetPriority(USARTx_IRQn, 0xE);
NVIC_EnableIRQ(USARTx_IRQn);
return 0;
}
HOOK_SERIAL_INIT(UART, stm32_serial_init)
================================================
FILE: drivers/serial/stm32-uart.h
================================================
#ifndef _DRIVER_SERIAL_STM32_USART_H
#define _DRIVER_SERIAL_STM32_USART_H
#include "platform.h"
struct stm32_uart_port {
GPIO_TypeDef *gpio_tx;
GPIO_TypeDef *gpio_rx;
GPIO_InitTypeDef gpio_tx_init_info;
GPIO_InitTypeDef gpio_rx_init_info;
UART_HandleTypeDef uart_init_info;
void (*gpio_init)(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
HAL_StatusTypeDef (*uart_init)(UART_HandleTypeDef *huart);
void (*gpio_tx_clk_enable)(void);
void (*gpio_rx_clk_enable)(void);
void (*uart_clk_enable)(void);
};
#endif /* !_DRIVER_SERIAL_STM32_USART_H */
================================================
FILE: drivers/timer/systick.c
================================================
/*
* Low-resolution (1kHz) SysTick-based timers to support the common
* driver's timer interface.
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <kernel/errno-base.h>
#include <kernel/time.h>
#include <kernel/softirq.h>
#include "linux/list.h"
struct systick_timer {
unsigned long start_clocktime;
unsigned long expire_clocktime;
struct list_head list;
struct timer_info *timer; /* backlink */
};
static unsigned long clocktime_in_msec;
static LIST_HEAD(systick_timers);
static int systick_timer_alloc(struct timer_info *timer)
{
struct systick_timer *systick_timer;
systick_timer = malloc(sizeof(struct systick_timer));
if (!systick_timer) {
errno = ENOMEM;
return -1;
}
timer->dev = systick_timer;
systick_timer->timer = timer;
return 0;
}
static int systick_timer_set(struct timer_info *timer,
const struct timespec *value)
{
struct systick_timer *systick_timer = (struct systick_timer *) timer->dev;
if (!value->tv_sec && !value->tv_nsec)
list_del(&systick_timer->list);
if (value->tv_sec || value->tv_nsec) {
systick_timer->start_clocktime = clocktime_in_msec;
systick_timer->expire_clocktime =
clocktime_in_msec + value->tv_sec * 1000 + value->tv_nsec / 1000000;
list_add(&systick_timer->list, &systick_timers);
}
return 0;
}
static int systick_timer_get(struct timer_info *timer,
struct itimerspec *curr_value)
{
struct systick_timer *systick_timer = (struct systick_timer *) timer->dev;
unsigned long msecs = clocktime_in_msec - systick_timer->start_clocktime;
curr_value->it_value.tv_sec = msecs / 1000;
curr_value->it_value.tv_nsec = (msecs % 1000) * 1000000;
return 0;
}
static int systick_timer_free(struct timer_info *timer)
{
free(timer->dev);
return 0;
}
static void systick_bh(void)
{
// XXX: is list_for_each_entry_safe() reentrant?
struct systick_timer *pos, *pos1;
list_for_each_entry_safe(pos, pos1, &systick_timers, list)
{
if (pos->expire_clocktime < clocktime_in_msec) {
list_del(&pos->list);
struct timer_info *timer = pos->timer;
if (timer->type == INTERVAL_TIMER)
systick_timer_set(timer, &timer->value.it_interval);
timer_expire_callback(timer);
}
}
}
#define SYSTICK_FREQ_IN_HZ 1000
#define SYSTICK_PERIOD_IN_MSECS (SYSTICK_FREQ_IN_HZ / 1000)
#include "platform.h"
void systick(void)
{
clocktime_in_msec += SYSTICK_PERIOD_IN_MSECS;
static struct tasklet_struct *tick_tsklet;
if (!tick_tsklet)
tick_tsklet = tasklet_init(systick_bh, NULL, TIMER_SOFTIRQ_PRIO);
tasklet_schedule(tick_tsklet);
SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
}
const struct timer_operations systick_tops = {
.timer_alloc = systick_timer_alloc,
.timer_set = systick_timer_set,
.timer_get = systick_timer_get,
.timer_free = systick_timer_free,
};
void __attribute__((naked)) pendsv(void)
{
__asm__ __volatile__(
"push {lr} \n\t"
"mov r0, #3 \n\t" /*SCHED_OPT_TICK*/
"bl sched_elect \n\t"
"pop {pc}" ::);
}
================================================
FILE: drivers/timer/timercore.c
================================================
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <kernel/errno-base.h>
#include <kernel/time.h>
static struct timer_operations *timer_operations;
void config_timer_operations(struct timer_operations *tops)
{
timer_operations = tops;
}
struct timer_info *timer_alloc(void)
{
struct timer_info *timer;
timer = malloc(sizeof(struct timer_info));
if (!timer) {
errno = ENOMEM;
return NULL;
}
timer->tops = timer_operations; // FIXME: get info from vnode or device
if (timer->tops->timer_alloc(timer)) {
free(timer);
return NULL;
}
return timer;
}
int timer_set(struct timer_info *timer, const struct timespec *value)
{
return timer->tops->timer_set(timer, value);
}
int timer_get(struct timer_info *timer, struct itimerspec *value)
{
return timer->tops->timer_get(timer, value);
}
int timer_free(struct timer_info *timer)
{
if (!timer->disarmed) {
const struct timespec zero_val = {0, 0};
timer_set(timer, &zero_val);
}
timer->tops->timer_free(timer);
free(timer);
return 0;
}
void timer_expire_callback(struct timer_info *timer)
{
if (timer->callback)
timer->callback(timer);
}
================================================
FILE: fs/proc.c
================================================
#include <string.h>
#include <sys/param.h>
#include <kernel/fs.h>
#include <kernel/kernel.h>
// https://linux.die.net/lkmpg/x861.html
// https://lwn.net/Articles/22355/
extern const char _version_ptr;
extern const int _version_len;
static int open_version(__unused struct inode *inode,
__unused struct file *file)
{
return 0;
}
static ssize_t read_version(__unused struct file *file,
char *buf,
size_t count,
off_t offset)
{
size_t n = MIN(count, (int) &_version_len - offset);
strncpy(buf, &_version_ptr + offset, n);
return n;
}
static int open_meminfo(__unused struct inode *inode,
__unused struct file *file)
{
return 0;
}
static ssize_t read_meminfo(__unused struct file *file,
char *buf,
size_t count,
off_t offset)
{
memcpy(buf, (void *) offset, count);
return count;
}
static const struct file_operations version_fops = {
.open = open_version,
.read = read_version,
};
static const struct file_operations meminfo_fops = {
.open = open_meminfo,
.read = read_meminfo,
};
extern const struct inode_operations tmpfs_iops;
static struct inode proc_inodes[] = {
{
/* /proc/version */
.i_ino = 1001,
.i_op = &tmpfs_iops,
.i_fop = &version_fops,
},
{
/* /proc/meminfo */
.i_ino = 1002,
.i_op = &tmpfs_iops,
.i_fop = &meminfo_fops,
},
};
void proc_init(void)
{
struct dentry dentry;
const char *names[] = {
"version", "meminfo",
};
for (int i = 0; i < 2; i++) {
printk("Creating /proc/%s\n", names[i]);
dentry.d_inode = &proc_inodes[i], strcpy(dentry.d_name, names[i]);
vfs_link(0, proc_inode(), &dentry);
}
}
================================================
FILE: fs/romfs.c
================================================
/* https://www.kernel.org/doc/Documentation/filesystems/romfs.txt */
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <piko/arpa/inet.h> /* words are big endian in romfs */
#include <kernel/fs.h>
#include <fs/romfs.h>
#include <kernel/kernel.h>
#include <drivers/mtd/mtd.h>
#include "linux/list.h"
const struct inode_operations romfs_iops;
const struct file_operations romfs_fops;
const struct dentry_operations romfs_dops;
static char *basename(const char *filename)
{
char *p = strrchr(filename, '/');
return p ? p + 1 : (char *) filename;
}
static off_t offsetof_device_inode(struct romfs_inode *rinode,
struct romfs_superblock *super)
{
return (off_t) rinode - (off_t) super;
}
static off_t offsetof_first_device_inode(struct romfs_superblock *super)
{
/* volume_name is a null-terminated string */
int len = align_next(strlen(super->volume_name) + 1, 16);
return offsetof(struct romfs_superblock, volume_name) + len;
}
// mount("/dev/mtd", "/media/flash", "romfs", 0, NULL);
int romfs_mount(const char *source,
const char *target,
__unused const char *filesystemtype,
__unused unsigned long mountflags,
__unused const void *data)
{
struct inode *s_inode = inode_from_pathname(source);
if (!s_inode)
return -1;
// FIXME: Use mkdir() or create()
struct inode *inode = malloc(sizeof(struct inode));
if (!inode)
return -1;
init_tmpfs_inode(inode);
inode->i_op = &romfs_iops;
inode->i_mode = S_IFDIR;
inode->i_size = 0;
// link mounted-over inode to parent directory
struct dentry dentry;
printk("Creating /dev/%s\n", basename(target));
dentry.d_inode = inode;
strcpy(dentry.d_name, basename(target));
vfs_link(0, dev_inode(), &dentry);
/* Allocate a super_block struct that will be released on filesystem
* unmount. */
struct super_block *super_block = malloc(sizeof(struct super_block));
if (!super_block)
return -1;
/* super_block is found at the begining of memory area on MTD dev */
struct mtd_info *mtd = s_inode->i_private;
super_block->s_private = mtd;
super_block->s_iroot =
inode; // FIXME: super_block must point to dentry instead of inode
inode->i_sb = super_block;
struct romfs_superblock *super = mtd->priv;
inode->i_private = (void *) offsetof_first_device_inode(super);
return 0;
}
static struct inode *alloc_inode(struct romfs_inode *ri, struct super_block *sb)
{
struct inode *inode;
static int ino = 0xbeef;
inode = malloc(sizeof(struct inode));
if (!inode)
return NULL;
switch (ntohl(ri->next_filehdr) & ROMFS_FILETYPE_MASK) {
case ROMFS_FILETYPE_DIR:
inode->i_mode = S_IFDIR;
break;
case ROMFS_FILETYPE_REG:
inode->i_mode = S_IFREG;
break;
case ROMFS_FILETYPE_LNK:
inode->i_mode = S_IFLNK;
break;
case ROMFS_FILETYPE_BLK:
inode->i_mode = S_IFBLK;
break;
case ROMFS_FILETYPE_CHR:
inode->i_mode = S_IFCHR;
break;
case ROMFS_FILETYPE_FIFO:
inode->i_mode = S_IFIFO;
break;
default:
inode->i_mode = 0;
}
inode->i_ino = ino++;
inode->i_size = ntohl(ri->size);
inode->i_op = &romfs_iops;
inode->i_fop = &romfs_fops;
inode->i_sb = sb;
/* We store the offset to on-device inode rather than the logical
* address of the on-device inode, because that does not work if
* fs is stored on a SPI flash for instance, and is not directly
* mapped onto logical address space. */
inode->i_private =
(void *) offsetof_device_inode(ri, ROMFS_SUPER_BLOCK(sb));
return inode;
}
struct dentry *romfs_lookup(struct inode *dir, struct dentry *target)
{
__u32 next_filehdr = 0;
struct romfs_superblock *rs;
struct romfs_inode *ri;
/* get current on-device inode */
rs = ROMFS_SUPER_BLOCK(dir->i_sb);
ri = ROMFS_INODE(rs, dir->i_private);
/* enter and walk the directory */
next_filehdr = align(ntohl(ri->spec_info), 16);
ri = ROMFS_INODE(rs, next_filehdr);
for (int i = 0; next_filehdr < rs->full_size; i++) {
if (!strcmp(ri->file_name, target->d_name)) {
struct inode *inode = alloc_inode(ri, dir->i_sb);
if (!inode)
return NULL;
target->d_inode = inode;
target->d_op = &romfs_dops;
return target;
}
/* inspect next file in current directory */
next_filehdr = align(ntohl(ri->next_filehdr), 16);
if (!next_filehdr)
break;
ri = ROMFS_INODE(rs, next_filehdr);
}
return NULL;
}
int romfs_open(struct inode *inode, struct file *file)
{
file->f_private = inode->i_private;
return 0;
}
ssize_t romfs_read(struct file *file, char *buf, size_t count, off_t offset)
{
size_t retlen;
size_t filesize = file->f_dentry->d_inode->i_size;
struct inode *inode = file->f_dentry->d_inode;
struct super_block *sb = inode->i_sb;
struct mtd_info *mtd = sb->s_private;
struct romfs_superblock *rs = ROMFS_SUPER_BLOCK(sb);
struct romfs_inode *ri = ROMFS_INODE(rs, inode->i_private);
int len =
sizeof(struct romfs_inode) + align_next(strlen(ri->file_name) + 1, 16);
if (file->f_pos + count > filesize)
count = filesize - offset;
mtd_read(mtd, (off_t) inode->i_private + len + offset, count, &retlen,
(unsigned char *) buf);
return retlen;
}
int romfs_mmap(struct file *file, off_t offset, void **addr)
{
size_t retlen;
size_t filesize = file->f_dentry->d_inode->i_size;
struct inode *inode = file->f_dentry->d_inode;
struct super_block *sb = inode->i_sb;
struct mtd_info *mtd = sb->s_private;
struct romfs_superblock *rs = ROMFS_SUPER_BLOCK(sb);
struct romfs_inode *ri = ROMFS_INODE(rs, inode->i_private);
int len =
sizeof(struct romfs_inode) + align_next(strlen(ri->file_name) + 1, 16);
return mtd_point(mtd, (off_t) inode->i_private + len + offset, filesize,
&retlen, addr);
}
int romfs_delete(struct dentry *dentry)
{
/* release in-memory inode */
/* the root inode is deleted on unmount(), operation is pointed
* by i_sb->s_op->unmount() */
if (dentry->d_inode != dentry->d_inode->i_sb->s_iroot)
free(dentry->d_inode);
free(dentry);
return 0;
}
const struct inode_operations romfs_iops = {
.lookup = romfs_lookup,
};
const struct file_operations romfs_fops = {
.open = romfs_open,
.read = romfs_read,
.mmap = romfs_mmap,
};
const struct dentry_operations romfs_dops = {
.delete = romfs_delete,
};
================================================
FILE: fs/tmpfs.c
================================================
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <kernel/fs.h>
#include <kernel/kernel.h>
#include "linux/list.h"
struct dirlist {
struct inode *inode;
char name[NAME_MAX];
struct list_head list;
};
int tmpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
dir->i_mode = mode | S_IFDIR;
dentry->d_inode = dir;
struct list_head *dirlist = (struct list_head *) dir->i_private;
INIT_LIST_HEAD(dirlist);
return 0;
}
int tmpfs_link(__unused struct dentry *old_dentry,
struct inode *dir,
struct dentry *dentry)
{
struct dirlist *new = malloc(sizeof(struct dirlist));
if (!new)
return -1;
new->inode = dentry->d_inode;
strncpy(new->name, dentry->d_name, NAME_MAX);
struct list_head *dirlist = (struct list_head *) dir->i_private;
list_add_tail(&new->list, dirlist);
dir->i_size++;
return 0;
}
int tmpfs_iterate(struct file *file, struct dir_context *ctx)
{
int res = -1;
struct inode *inode = file->f_dentry->d_inode;
if (file->f_pos == inode->i_size + 2)
return -1;
switch (file->f_pos) {
case 0:
res = dir_emit_dot(file, ctx);
break;
case 1:
res = dir_emit_dotdot(file, ctx);
break;
default:;
struct dirlist *dirlist;
struct list_head *head = (struct list_head *) inode->i_private;
int i = 2;
list_for_each_entry(dirlist, head, list)
{
if (i++ == file->f_pos) {
res = dir_emit(ctx, dirlist->name, strlen(dirlist->name),
dirlist->inode->i_ino, 0);
break;
}
}
}
file->f_pos++;
return res;
}
const struct dentry_operations tmpfs_dops;
struct dentry *tmpfs_lookup(struct inode *dir, struct dentry *target)
{
struct list_head *head = (struct list_head *) dir->i_private;
struct dirlist *dirlist;
list_for_each_entry(dirlist, head, list)
{
if (!strcmp(target->d_name, dirlist->name)) {
target->d_inode = dirlist->inode;
target->d_op = &tmpfs_dops;
return target;
}
}
return NULL;
}
int tmpfs_delete(struct dentry *dentry)
{
free(dentry);
return 0;
}
const struct inode_operations tmpfs_iops = {
.lookup = tmpfs_lookup,
.link = tmpfs_link,
};
const struct file_operations tmpfs_fops = {
.iterate = tmpfs_iterate,
};
const struct dentry_operations tmpfs_dops = {
.delete = tmpfs_delete,
};
static struct inode tmpfs_inodes[] = {
{
/* / - the root directory */
.i_ino = 1,
.i_op = &tmpfs_iops,
.i_fop = &tmpfs_fops,
.i_mode = S_IFDIR,
.i_size = 2,
.i_private = &((struct list_head){}),
},
{
/* /dev - essential device files */
.i_ino = 2,
.i_op = &tmpfs_iops,
.i_fop = &tmpfs_fops,
.i_mode = S_IFDIR,
.i_private = &((struct list_head){}),
},
{
/* /proc - process and kernel information as files */
.i_ino = 3,
.i_op = &tmpfs_iops,
.i_fop = &tmpfs_fops,
.i_mode = S_IFDIR,
.i_private = &((struct list_head){}),
},
};
struct inode *root_inode(void)
{
return &tmpfs_inodes[0];
}
struct inode *dev_inode(void)
{
return &tmpfs_inodes[1];
}
struct inode *proc_inode(void)
{
return &tmpfs_inodes[2];
}
struct dentry *root_dentry(void)
{
static struct dentry dentry = {
.d_name = "/",
.d_inode = &tmpfs_inodes[0],
.d_parent = &dentry,
.d_op = &tmpfs_dops,
};
return &dentry;
}
struct inode *init_tmpfs_inode(struct inode *inode)
{
static ino_t ino = 9000;
inode->i_ino = ino++;
inode->i_op = &tmpfs_iops;
return inode;
}
void tmpfs_init(void)
{
static struct dirlist entries[] = {
{
.inode = &tmpfs_inodes[1], .name = "dev",
},
{
.inode = &tmpfs_inodes[2], .name = "proc",
},
};
struct list_head *rootdir = (struct list_head *) tmpfs_inodes[0].i_private;
INIT_LIST_HEAD(rootdir);
list_add_tail(&entries[0].list, rootdir);
list_add_tail(&entries[1].list, rootdir);
struct list_head *devdir = (struct list_head *) tmpfs_inodes[1].i_private;
INIT_LIST_HEAD(devdir);
struct list_head *procdir = (struct list_head *) tmpfs_inodes[2].i_private;
INIT_LIST_HEAD(procdir);
}
================================================
FILE: include/arch/semihosting.h
================================================
#ifndef _ARCH_SEMIHOSTING_H
#define _ARCH_SEMIHOSTING_H
void v7m_semihost_exit(int status);
#endif /* !_ARCH_SEMIHOSTING_H */
================================================
FILE: include/arch/v7m-helper.h
================================================
#ifndef _ARCH_V7M_HELPER_H
#define _ARCH_V7M_HELPER_H
#define V7M_EXC_RETURN_HANDLER_MAIN 0xfffffff1
#define V7M_EXC_RETURN_THREAD_MAIN 0xfffffff9
#define V7M_EXC_RETURN_THREAD_PROCESS 0xfffffffd
static inline void *v7m_set_thumb_bit(void *addr)
{
return (void *) ((unsigned long) addr | 1ul);
}
static inline void *v7m_clear_thumb_bit(void *addr)
{
return (void *) ((unsigned long) addr & ~1ul);
}
#endif /* !_ARCH_V7M_HELPER_H */
================================================
FILE: include/fs/romfs.h
================================================
#ifndef _KERNEL_FS_ROMFS_H
#define _KERNEL_FS_ROMFS_H
#include <kernel/types.h>
#include <drivers/mtd/mtd.h>
#define ROMFS_FILETYPE_MASK 0x7
#define ROMFS_FILETYPE_HARD 0
#define ROMFS_FILETYPE_DIR 1
#define ROMFS_FILETYPE_REG 2
#define ROMFS_FILETYPE_LNK 3
#define ROMFS_FILETYPE_BLK 4
#define ROMFS_FILETYPE_CHR 5
#define ROMFS_FILETYPE_SOCKET 6
#define ROMFS_FILETYPE_FIFO 7
struct romfs_superblock {
__u8 magic_number[8];
__u32 full_size;
__u32 checksum;
char volume_name[0];
};
struct romfs_inode {
__u32 next_filehdr;
__u32 spec_info;
__u32 size;
__u32 checksum;
char file_name[0];
};
#define ROMFS_SUPER_BLOCK(sb) \
({ \
struct mtd_info *mtd = (sb)->s_private; \
struct romfs_superblock *rs = mtd->priv; \
rs; \
})
#define ROMFS_INODE(rs, offset) \
({ \
__u32 addr = (__u32)(rs) + (__u32)(offset); \
struct romfs_inode *ri = (struct romfs_inode *) addr; \
ri; \
})
int romfs_mount(const char *source,
const char *target,
const char *filesystemtype,
unsigned long mountflags,
const void *data);
#endif /* !_KERNEL_FS_ROMFS_H */
================================================
FILE: include/kernel/bitmap.h
================================================
#ifndef _LINUX_BITMAP_H
#define _LINUX_BITMAP_H
#include "linux/list.h"
#include "kernel/bitops.h"
struct bitmap_struct {
unsigned long map;
struct list_head queue[32];
};
static inline void INIT_BITMAP(struct bitmap_struct *bm)
{
WRITE_ONCE(bm->map, 0UL);
for (int i = 0; i < 32; i++)
INIT_LIST_HEAD(&bm->queue[i]);
}
static inline void bitmap_queue_add(struct list_head *new,
unsigned long bit,
struct bitmap_struct *bm)
{
list_add_tail(new, &bm->queue[bit]);
bitmap_set_bit(&bm->map, bit);
}
static inline void bitmap_queue_add_first(struct list_head *new,
unsigned long bit,
struct bitmap_struct *bm)
{
list_add(new, &bm->queue[bit]);
bitmap_set_bit(&bm->map, bit);
}
static inline void bitmap_enqueue(struct list_head *new,
unsigned long bit,
struct bitmap_struct *bm)
{
bitmap_queue_add(new, bit, bm);
}
static inline void bitmap_enqueue_first(struct list_head *new,
unsigned long bit,
struct bitmap_struct *bm)
{
bitmap_queue_add_first(new, bit, bm);
}
static inline int bitmap_empty(const struct bitmap_struct *bm)
{
return !(!READ_ONCE(bm->map));
}
static inline int bitmap_queue_empty(struct bitmap_struct *bm,
unsigned long bit)
{
return !bitmap_get_bit(&bm->map, bit);
}
static inline int bitmap_first_bit(const struct bitmap_struct *bm)
{
return find_first_bit(&bm->map, 32);
}
static inline void bitmap_queue_del(struct list_head *queue,
unsigned long bit,
struct bitmap_struct *bm)
{
list_del(queue);
if (list_empty(&bm->queue[bit]))
bitmap_clear_bit(&bm->map, bit);
}
static inline struct list_head *bitmap_dequeue(struct bitmap_struct *bm,
unsigned long bit)
{
struct list_head *first = bm->queue[bit].next;
bitmap_queue_del(first, bit, bm);
return first;
}
static inline struct list_head *bitmap_dequeue_tail(struct bitmap_struct *bm,
unsigned long bit)
{
struct list_head *last = bm->queue[bit].prev;
bitmap_queue_del(last, bit, bm);
return last;
}
#define bitmap_first_entry(bm, bit, type, member) \
list_entry(bm->queue[bit].next, type, member)
#endif
================================================
FILE: include/kernel/bitops.h
================================================
#ifndef KERNEL_BITOPS_H
#define KERNEL_BITOPS_H
#include <sys/param.h>
#include <kernel/bitops.h>
#include <kernel/kernel.h>
#define BITS_PER_CHAR 8
#define BITS_PER_LONG (BITS_PER_CHAR * sizeof(long))
static inline unsigned long flsl(unsigned long word)
{
return word ? sizeof(long) * BITS_PER_CHAR - __builtin_clz(word) : 0;
}
static inline void clear_bit(unsigned long bit, unsigned long *word)
{
*word &= ~(1 << bit);
}
static inline void set_bit(unsigned long bit, unsigned long *word)
{
*word |= (1 << bit);
}
static inline void bitmap_set_bit(unsigned long *map, unsigned long bit)
{
set_bit(bit % BITS_PER_LONG, &map[bit / BITS_PER_LONG]);
}
static inline void bitmap_clear_bit(unsigned long *map, unsigned long bit)
{
clear_bit(bit % BITS_PER_LONG, &map[bit / BITS_PER_LONG]);
}
static inline unsigned long bitmap_get_bit(unsigned long *map,
unsigned long bit)
{
return (map[bit / BITS_PER_LONG] >> (bit % BITS_PER_LONG)) & 1;
}
static inline unsigned long find_first_bit(const unsigned long *addr,
unsigned long size)
{
for (unsigned long i = 0; i * BITS_PER_LONG < size; i++) {
if (addr[i])
return MIN(i * BITS_PER_LONG + __builtin_ffsl(addr[i]) - 1, size);
}
return size;
}
static inline unsigned long find_first_zero_bit(const unsigned long *addr,
unsigned long size)
{
for (unsigned long i = 0; i * BITS_PER_LONG < size; i++) {
if (addr[i] != ~0ul)
return MIN(i * BITS_PER_LONG + __builtin_ffsl(~addr[i]) - 1, size);
}
return size;
}
#endif /* !KERNEL_BITOPS_H */
================================================
FILE: include/kernel/cbuf.h
================================================
#ifndef _KERNEL_CBUF_H
#define _KERNEL_CBUF_H
#include <sys/types.h>
struct cbuf_info {
size_t len;
int pos_begin;
int pos_end;
void *buf;
};
static inline void cbuf_init(struct cbuf_info *cbuf, void *buf, size_t len)
{
cbuf->len = len;
cbuf->pos_begin = 0;
cbuf->pos_end = 0;
cbuf->buf = buf;
}
static inline int cbuf_getc(struct cbuf_info *cbuf, char *c)
{
if (cbuf->pos_begin == cbuf->pos_end)
return 0;
*c = *((char *) cbuf->buf + cbuf->pos_begin);
cbuf->pos_begin = (cbuf->pos_begin + 1) % cbuf->len;
return 1;
}
static inline int cbuf_putc(struct cbuf_info *cbuf, char c)
{
*((char *) cbuf->buf + cbuf->pos_end) = c;
cbuf->pos_end = (cbuf->pos_end + 1) % cbuf->len;
return 0;
}
#endif /* !_KERNEL_CBUF_H */
================================================
FILE: include/kernel/compiler.h
================================================
#ifndef _KERNEL_COMPILER_H
#define _KERNEL_COMPILER_H
/* GCC weak symbol declaration */
#ifndef __weak
#define __weak __attribute__((weak))
#endif
#endif /* !_KERNEL_COMPILER_H */
================================================
FILE: include/kernel/cond.h
================================================
#ifndef KERNEL_COND_H
#define KERNEL_COND_H
#include <sys/types.h>
int sys_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int sys_pthread_cond_signal(pthread_cond_t *cond);
#endif /* !KERNEL_COND_H */
================================================
FILE: include/kernel/errno-base.h
================================================
#ifndef _KERNEL_ERRNO_BASE_H_
#define _KERNEL_ERRNO_BASE_H_
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#endif /* !_KERNEL_ERRNO_BASE_H_ */
================================================
FILE: include/kernel/faults.h
================================================
#ifndef KERNEL_FAULTS_H
#define KERNEL_FAULTS_H
#include <sys/types.h>
#include <kernel/thread.h>
void fault_enter(const char *s);
void fault_exit(void);
/* arch-dependent */
void dump_frame(struct kernel_context_regs *noscratch,
struct thread_context_regs *scratch,
u32 exc_return);
#endif /* !KERNEL_FAULTS_H */
================================================
FILE: include/kernel/fs.h
================================================
#ifndef _KERNEL_FS_H
#define _KERNEL_FS_H
#include <sys/types.h>
#include <unistd.h>
#include <piko/dirent.h>
#include <kernel/types.h>
#define NAME_MAX 32 // FIXME: Include <limits.h>
#define FILE_MAX 8
#define O_DIRECTORY 1
/*
* super_block struct
*/
struct dentry;
struct inode; // FIXME: delete me from here, using s_root dentry
struct super_block {
void *s_private; // for dev, pointing to MTD
struct inode *s_iroot; // FIXME: just use s_root and dentry
};
/*
* inode struct
*/
struct inode_operations;
struct file_operations;
struct inode {
struct list_head i_list; /* list of inodes */
umode_t i_mode; /* access permissions */
// kernel_ino_t
unsigned long i_ino; /* inode number */
atomic_t i_count; /* reference counter */
off_t i_size; /* file size in bytes */
const struct inode_operations *i_op; /* inode ops table */
const struct file_operations *i_fop; /* default inode ops */
struct super_block *i_sb; /* associated superblock */
void *i_private;
char i_data[0];
};
struct inode_operations {
struct dentry *(*lookup)(struct inode *inode, struct dentry *dentry);
int (*link)(struct dentry *old_dentry,
struct inode *dir,
struct dentry *dentry);
};
/*
* file struct
*/
struct file {
struct dentry *f_dentry; /* associated dentry object */
const struct file_operations *f_op; /* file operations table */
off_t f_pos; /* file offset (file pointer) */
void *f_private;
};
struct dir_context;
struct file_operations {
off_t (*lseek)(struct file *file, off_t offset, int origin);
ssize_t (*read)(struct file *file, char *buf, size_t count, off_t offset);
ssize_t (*write)(struct file *file,
const char *buf,
size_t count,
off_t *offset);
int (*iterate)(struct file *file, struct dir_context *ctx);
int (*mmap)(struct file *file,
off_t offset,
void **addr); /* struct vm_area_struct *area */
int (*open)(struct inode *inode, struct file *file);
};
/*
* dentry struct
*/
struct dentry {
_Atomic int d_count; /* usage count */
struct inode *d_inode; /* associated inode */
const struct dentry_operations *d_op; /* dentry operations table */
struct dentry *d_parent; /* dentry object of parent */
char d_name[NAME_MAX]; /* short name */
// struct list_head d_child; /* child of parent list */
// struct list_head d_subdirs; /* our children */
};
struct dentry_operations {
int (*delete)(struct dentry *dentry);
void (*release)(struct dentry *dentry);
};
/* readdir */
typedef int (*filldir_t)(struct dir_context *,
const char *,
int,
off_t,
unsigned int,
unsigned int);
struct dir_context {
const filldir_t actor;
off_t pos; // XXX: unused because piko_dirent has no offset field
};
struct piko_dirent;
struct readdir_callback {
struct dir_context ctx;
struct piko_dirent *dirent;
int result;
};
struct piko_dirent {
ino_t d_ino; /* inode number */
char d_name[NAME_MAX]; /* filename */
};
static inline int dir_emit(struct dir_context *ctx,
const char *name,
int namelen,
unsigned int ino,
unsigned int type)
{
return ctx->actor(ctx, name, namelen, ctx->pos, ino, type);
}
static inline int dir_emit_dot(struct file *file, struct dir_context *ctx)
{
return ctx->actor(ctx, ".", 1, ctx->pos, file->f_dentry->d_inode->i_ino, 0);
}
static inline int dir_emit_dotdot(struct file *file, struct dir_context *ctx)
{
return ctx->actor(ctx, "..", 2, ctx->pos,
file->f_dentry->d_parent->d_inode->i_ino, 0);
}
/* forward declarations */
int vfs_iterate(struct file *file, struct dir_context *ctx);
struct dentry *vfs_lookup(struct inode *dir, struct dentry *target);
int vfs_link(struct dentry *old_dentry,
struct inode *dir,
struct dentry *dentry);
int vfs_delete(struct dentry *dentry);
void vfs_release(struct dentry *dentry);
int vfs_mmap(struct file *file, off_t offset, void **addr);
/* syscall entries */
typedef void DIR;
int sys_opendir(const char *name);
int sys_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
int sys_open(const char *pathname, int flags);
ssize_t sys_read(int fd, void *buf, size_t count);
ssize_t sys_write(int fd, void *buf, size_t count);
off_t sys_seek(int fd, off_t offset, int whence);
int sys_close(int fd);
/* misc functions */
struct inode *root_inode(void);
struct inode *dev_inode(void);
struct inode *proc_inode(void);
struct dentry *root_dentry(void);
struct file *fd_to_file(int fd);
struct inode *init_tmpfs_inode(struct inode *inode);
struct inode *inode_from_pathname(const char *pathname);
void tmpfs_init(void);
void proc_init(void);
#endif /* !_KERNEL_FS_H */
================================================
FILE: include/kernel/hash.h
================================================
#ifndef _KERNEL_HASH_H
#define _KERNEL_HASH_H
#include <stddef.h>
static inline unsigned long hash_djb2(unsigned char *str, size_t len)
{
unsigned long hash = 5381;
for (int i = 0; i < (int) len; i++) {
int c = str[i];
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
return hash;
}
#endif /* _KERNEL_HASH_H */
================================================
FILE: include/kernel/irq.h
================================================
#ifndef KERNEL_IRQ_H
#define KERNEL_IRQ_H
#define NR_IRQS 64
/* irq status */
enum {
IRQ_NOREQUEST = 1,
};
/* irq data state(for per-chip) */
enum {
IRQD_IRQ_DISABLED = 1,
IRQD_INACTIVATED = 1 << 2,
IRQD_ACTIVATED = 1 << 3,
IRQD_PENDING = 1 << 4,
};
/**
* struct irq_data - per chip data
*
* @state: status information for irq chip
* XXX: Thanks for CMSIS. We don't have to impl per chip function and data,
* but this concept should be remained due to more precious description
* of irqs and chips(HW).
*/
struct irq_data {
unsigned int state;
};
struct irqaction;
/**
* struct irq_desc - interrupt descriptor
*
* @action: the irq action chain
* @status: status information
* @irq_state: per irq state information
*/
struct irq_desc {
struct irq_data irq_data;
struct irqaction *action;
unsigned int status;
};
typedef void (*irq_handler_t)(void);
/**
* struct irqaction - per interrupt action descriptor
* @handler: interrupt handler function
* @irq: interrupt number
*/
struct irqaction {
irq_handler_t handler;
unsigned int irq;
};
int request_irq(unsigned int irq, irq_handler_t hdlr);
int free_irq(unsigned int irq);
#endif /* !KERNEL_IRQ_H */
================================================
FILE: include/kernel/kernel.h
================================================
#ifndef _KERNEL_KERNEL_H
#define _KERNEL_KERNEL_H
/* round-down to a power of 2 */
#define align(x, a) align_mask(x, (__typeof__(x))((a) -1))
#define align_mask(x, mask) ((x) & ~(mask))
/* round-up to a power of 2 */
#define align_next(x, a) align_next_mask(x, (__typeof__(x))((a) -1))
#define align_next_mask(x, mask) (((x) + (mask)) & ~(mask))
#define ARRAY_SIZE(arr) ((size_t)(sizeof(arr) / sizeof(*(arr))))
#define ARRAY_INDEX(elt, arr) \
({ \
unsigned int _elt = (unsigned int) (elt); \
unsigned int _arr = (unsigned int) (arr); \
(_elt - _arr) / sizeof(*(elt)); \
})
#define container_of(ptr, type, member) \
({ \
const __typeof__(((type *) 0)->member) *__mptr = (ptr); \
(type *) ((char *) __mptr - offsetof(type, member)); \
})
#define SWAP(x, y) \
{ \
__typeof__(x) tmp = x; \
x = y; \
y = tmp; \
} \
while (0)
int printk(const char *fmt, ...);
#endif /* !_KERNEL_KERNEL_H */
================================================
FILE: include/kernel/linkage.h
================================================
#ifndef _KERNEL_LINKAGE_H
#define _KERNEL_LINKAGE_H
#ifdef __ASSEMBLER__
#define ENTRY(name) \
.globl name; \
.align 4; \
name:
#define END(name) .size name, .- name
#define ENDPROC(name) \
.type name, % function; \
END(name)
#endif /* __ASSEMBLER__ */
#endif /* !_KERNEL_LINKAGE_H */
================================================
FILE: include/kernel/log2.h
================================================
#ifndef KERNEL_LOG2_H
#define KERNEL_LOG2_H
#include <kernel/bitops.h>
// clang-format off
#define ilog2(x) \
( \
__builtin_constant_p(x) ? ( \
(x) < 1 ? __ilog2_NaN() : \
(x) & (1ul << 31) ? 31 : \
(x) & (1ul << 30) ? 30 : \
(x) & (1ul << 29) ? 29 : \
(x) & (1ul << 28) ? 28 : \
(x) & (1ul << 27) ? 27 : \
(x) & (1ul << 26) ? 26 : \
(x) & (1ul << 25) ? 25 : \
(x) & (1ul << 24) ? 24 : \
(x) & (1ul << 23) ? 23 : \
(x) & (1ul << 22) ? 22 : \
(x) & (1ul << 21) ? 21 : \
(x) & (1ul << 20) ? 20 : \
(x) & (1ul << 19) ? 19 : \
(x) & (1ul << 18) ? 18 : \
(x) & (1ul << 17) ? 17 : \
(x) & (1ul << 16) ? 16 : \
(x) & (1ul << 15) ? 15 : \
(x) & (1ul << 14) ? 14 : \
(x) & (1ul << 13) ? 13 : \
(x) & (1ul << 12) ? 12 : \
(x) & (1ul << 11) ? 11 : \
(x) & (1ul << 10) ? 10 : \
(x) & (1ul << 9) ? 9 : \
(x) & (1ul << 8) ? 8 : \
(x) & (1ul << 7) ? 7 : \
(x) & (1ul << 6) ? 6 : \
(x) & (1ul << 5) ? 5 : \
(x) & (1ul << 4) ? 4 : \
(x) & (1ul << 3) ? 3 : \
(x) & (1ul << 2) ? 2 : \
(x) & (1ul << 1) ? 1 : \
(x) & (1ul << 0) ? 0 : \
__ilog2_NaN() \
) : \
__ilog2(x) \
)
// clang-format on
static inline unsigned long __ilog2(unsigned long x)
{
return flsl(x) - 1;
}
static inline __attribute__((noreturn)) unsigned long __ilog2_NaN(void)
{
for (;;)
;
}
#endif /* !KERNEL_LOG2_H */
================================================
FILE: include/kernel/mm/page.h
================================================
#ifndef _KERNEL_MM_PAGE_H
#define _KERNEL_MM_PAGE_H
#define MAX_PAGE_ORDER 3 /* max page size is 2 KB */
#define MIN_PAGE_SIZE 256 /* min page size is 256 bytes */
void *alloc_pages(unsigned long order);
void free_pages(unsigned long addr, unsigned long order);
void show_page_bitmap(void);
long size_to_page_order(unsigned long size);
unsigned long page_alloc_signature(void);
#endif /* !_KERNEL_MM_PAGE_H */
================================================
FILE: include/kernel/mm/slab.h
================================================
#ifndef _KERNEL_MM_SLAB_H
#define _KERNEL_MM_SLAB_H
#include <sys/cdefs.h>
#include "linux/list.h"
#define CACHE_PAGE_SIZE 256
#define CACHE_NAMELEN 16
#define CACHE_OPT_NONE 0
/* OPT_FORCE: create a new cache, even when the object size matches a generic
* cache (i.e. 8B, 16B, 32B...)
* OPT_PERSIST: this cache cannot be destroyed (i.e. when a cache w/o OPT_FORCE
* has been created and silently merged into a general object
* cache and the user try to destroy the cache he created)
*/
struct kmem_cache {
struct list_head slabs_free;
struct list_head slabs_partial;
struct list_head slabs_full;
struct list_head list; /* linked list of caches */
unsigned short objsize; /* size of one object within a slab */
unsigned short objnum; /* number of objects per slab */
int opts;
int alloc_succeed;
int alloc_fail;
char name[CACHE_NAMELEN];
};
struct slab {
unsigned long free_bitmap[1];
int free_objects; /* number of free objects in that slab */
struct list_head list; /* pointer to prev/next slabs for that cache */
char data[0];
/* struct kmem_cache *backlink; // backlink to the cache structure */
};
#define KMEM_CACHE(objtype, name) \
kmem_cache_create(name, sizeof(objtype), 0, CACHE_OPT_NONE, NULL)
struct kmem_cache *kmem_cache_create(const char *name,
size_t size,
__unused size_t align,
__unused unsigned long flags,
__unused void (*ctor)(void *));
void *kmem_cache_alloc(struct kmem_cache *cache, __unused unsigned long flags);
void kmem_cache_free(struct kmem_cache *cache, void *obj);
void kmem_cache_init(void);
#endif /* _KERNEL_MM_SLAB_H */
================================================
FILE: include/kernel/mutex.h
================================================
#ifndef _KERNEL_MUTEX_H
#define _KERNEL_MUTEX_H
typedef _Atomic int atomic_s32;
typedef struct {
atomic_s32 val;
} kernel_mutex_t;
int sys_pthread_mutex_lock(kernel_mutex_t *mutex);
int sys_pthread_mutex_unlock(kernel_mutex_t *mutex);
#endif /* !_KERNEL_MUTEX_H */
================================================
FILE: include/kernel/sched.h
================================================
#ifndef KERNEL_SCHEDULER_H
#define KERNEL_SCHEDULER_H
#include_next <sched.h>
struct thread_info;
/* 0 <= PRI_MAX <= PRI_MIN */
#define PRI_MAX 0
#define PRI_MIN 31
#define SCHED_CLASS_RR 0
#define SCHED_CLASS_BITMAP 1
typedef int sched_class_t;
#define SCHED_OPT_NONE 0
#define SCHED_OPT_RESTORE_ONLY 1
#define SCHED_OPT_RESET 2
#define SCHED_OPT_TICK 3
/* scheduler implementation hooks */
#define HOOK_SCHED_CLASS(name, sched_struct) \
static struct sched *sched_class_##name \
__attribute__((section(".sched.class"), aligned(sizeof(long)), \
used)) = sched_struct;
struct sched {
sched_class_t class_type;
int (*init)(void);
int (*enqueue)(struct thread_info *thread);
int (*dequeue)(struct thread_info *thread);
int (*elect)(int switch_type);
};
int sched_init();
int sched_select(sched_class_t sched_type);
int sched_enqueue(struct thread_info *thread);
int sched_dequeue(struct thread_info *thread);
int sched_elect(int flags);
#endif /* !KERNEL_SCHEDULER_H */
================================================
FILE: include/kernel/serial.h
================================================
/*
* Interface for serial devices (UART, ...)
*/
#ifndef _KERNEL_SERIAL_H
#define _KERNEL_SERIAL_H
#include <stdio.h>
#include <sys/types.h>
struct serial_ops;
struct device;
struct thread_info;
struct serial_info {
void *priv;
unsigned int rx_count;
struct serial_ops *ops;
// XXX: owner thread pointer could go to priv, and device pripheral
// base address should be linked to private data for the device
struct thread_info *owner;
};
struct serial_ops {
int (*serial_init)(struct serial_info *serial);
int (*serial_getc)(struct serial_info *serial, char *c);
int (*serial_gets)(struct serial_info *serial,
size_t len,
size_t *retlen,
char *buf);
int (*serial_putc)(struct serial_info *serial, char c);
int (*serial_puts)(struct serial_info *serial,
size_t len,
const char *buf);
/* callback on device activity, set by ioctl() */
void (*callback)(struct serial_info *self);
};
struct serial_hook {
char name[10];
int (*init)(void);
};
/* serial hooks */
#define HOOK_SERIAL_INIT(dev, init_func) \
static struct serial_hook serial_##dev##_hook \
__attribute__((section(".serial.hook"), aligned(sizeof(long)), \
used)) = {#dev, init_func};
/* Generic uart setup */
void uart_init(void);
/* Generic serial init */
void serial_init(void);
/* XXX: All func below is callback function */
int serial_getc(struct serial_info *serial, char *c);
int serial_gets(struct serial_info *serial,
size_t len,
size_t *retlen,
char *buf);
int serial_putc(struct serial_info *serial, char c);
int serial_puts(struct serial_info *serial,
size_t len,
const char *buf);
void serial_activity_callback(struct serial_info *serial);
#endif /* !_KERNEL_SERIAL_H */
================================================
FILE: include/kernel/signal.h
================================================
#ifndef _KERNEL_SIGNAL_H
#define _KERNEL_SIGNAL_H
#include <signal.h>
#include <piko/signal.h>
#include <kernel/thread.h>
#include "linux/types.h"
#define SIGMAX 31
struct signal_info {
int signo;
struct list_head list;
struct sigaction act_storage;
};
void do_sigevent(const struct sigevent *sigevent, struct thread_info *thread);
#endif /* !_KERNEL_SIGNAL_H */
================================================
FILE: include/kernel/softirq.h
================================================
#ifndef KERNEL_SOFTIRQ_H
#define KERNEL_SOFTIRQ_H
#include "linux/list.h"
#define PRIO_TASKLET_VEC 32
#define PRIO_TASKLET_MAXPRIO 0
#define PRIO_TASKLET_MINPRIO 31
/* softirq */
enum {
TIMER_SOFTIRQ = 0,
};
/* softirq default priority */
enum {
TIMER_SOFTIRQ_PRIO = 0,
};
/* softirq entry */
struct softirq_action {
int (*action)(struct softirq_action *);
};
/* FIXME: re-entrance */
/* dynamic task */
struct tasklet_struct {
struct list_head tsk_q;
unsigned long prio;
// unsigned long state;
void (*func)(void *);
void *data;
};
enum {
TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */
TASKLET_STATE_RUN, /* Tasklet is running (SMP only) */
TASKLET_STATE_PENDING /* Tasklet is pending */
};
#define TASKLET_STATEF_SCHED (1 << TASKLET_STATE_SCHED)
#define TASKLET_STATEF_RUN (1 << TASKLET_STATE_RUN)
#define TASKLET_STATEF_PENDING (1 << TASKLET_STATE_PENDING)
int open_softirq(unsigned int nr, int (*action)(struct softirq_action *));
int raise_softirq(unsigned int nr);
int tasklet_schedule(struct tasklet_struct *task);
struct tasklet_struct *tasklet_init(void(*func),
void *data,
unsigned long prio);
int init_softirq(void);
#endif /* KERNEL_SOFTIRQ_H */
================================================
FILE: include/kernel/task.h
================================================
#ifndef _KERNEL_TASK_H
#define _KERNEL_TASK_H
#include <sys/types.h>
#include <kernel/fs.h>
#include "linux/list.h"
#define PID_BASE 7000
#define PID_MAX 32768
struct task_info {
pid_t pid;
unsigned long filemap;
struct file filetable[FILE_MAX];
struct list_head list;
struct list_head thread_head;
struct list_head signal_head; /* list of installed handlers */
};
struct task_info *task_init(struct task_info *task);
struct task_info *task_create(void *(*start_routine)(void *), void *arg);
void task_exit(struct task_info *task);
struct task_info *current_task_info(void);
#define CURRENT_TASK_INFO(var) struct task_info *var = current_task_info();
#endif /* !_KERNEL_TASK_H */
================================================
FILE: include/kernel/thread.h
================================================
#ifndef _KERNEL_THREAD_H
#define _KERNEL_THREAD_H
#include <sys/types.h>
#include <kernel/kernel.h>
#include "linux/types.h"
#include "linux/list.h"
#define INTR_STACK_ORDER 9 /* 512 Bytes */
#define INTR_STACK_SIZE (1 << INTR_STACK_ORDER)
/* machine-specific thread info on ARM */
struct mthread_info {
u32 mi_msp; /* +0 */
u32 mi_psp; /* +4 */
u32 mi_priv; /* +8 */
} __attribute__((packed));
struct task_info;
struct thread_info {
/* machine-specific thread info */
struct mthread_info ti_mach;
/* thread description data */
int ti_priority;
int ti_id;
int ti_state;
size_t ti_stacksize; /* user thread stacksize */
struct task_info *ti_task;
struct list_head ti_list; /* global list of threads */
struct list_head ti_q; /* shared by sched runq, mutex waitq, thread joinq */
/* http://www.domaigne.com/blog/computing/joinable-and-detached-threads/ */
void *ti_retval;
int ti_detached;
int ti_joinable;
struct thread_info *ti_joining;
/* Pointer to mutually exclusive data: the mutex the thread is blocking
* on, the exit value when thread is not yet joined, etc. */
void *ti_private;
/* /\* local-storage *\/ */
/* struct list_head *ti_lsq; // local-storage queue */
#ifdef CONFIG_KERNEL_STACK_CHECKING
u32 ti_canary[2];
#endif
char ti_storage[0];
};
enum thread_privilege { THREAD_PRIV_SUPERVISOR = 0, THREAD_PRIV_USER = 1 };
enum thread_state {
/* Thread structure allocated but not enqueued in the system scheduler. */
THREAD_STATE_NEW,
/**
* Ready to run in the system scheduler.
*
* XXX: why we need two ready states?
*
* Ans: One is ready for execution in active queue,
* the other one is the state for out of
* timeslice. In order to achieve O(1), we
* adopt specified function to determine
* which one is actived or expired.
*
* XXX: we impl map from `actived` and `expired` to
* `ready1` and `ready2`
*/
THREAD_STATE_READY1, // THREAD_STATE_ACTIVED
THREAD_STATE_READY2, // THREAD_STATE_EXPIRED
/* Running by the system scheduler. */
THREAD_STATE_RUNNING,
/* The thread has normally exited or has called Pthread_exit to exit. Its
* resources have not been freed and will be freed if it is detached or
* joined. */
THREAD_STATE_TERMINATED,
/* Waiting for a mutex or resource. */
THREAD_STATE_BLOCKED
};
#define THREAD_STATE_ACTIVED THREAD_SCHED_STATE[ACTIVED]
#define THREAD_STATE_EXPIRED THREAD_SCHED_STATE[EXPIRED]
enum {
ACTIVED,
EXPIRED,
NR_THREAD_SCHED_STATE,
};
static int THREAD_SCHED_STATE[NR_THREAD_SCHED_STATE] = {
[ACTIVED] = THREAD_STATE_READY1, [EXPIRED] = THREAD_STATE_READY2,
};
static inline void swap_sched_state_map(void)
{
SWAP(THREAD_SCHED_STATE[ACTIVED], THREAD_SCHED_STATE[EXPIRED]);
}
/*
* This stackframe is built to handle the first scheduling of a task on
* the CPU. Running a task for the first time is achieved in two stages.
*
* Stage 1:
* After switch_to() has switched the interrupt stacks for current and
* next tasks the function will restore the kernel-context for the next
* thread. That context is the non-scratch registers r4 to r11. At this
* point we don't care about the values in these registers: they are
* not used after that point during in that interrupt, and the next
* interrupt context will reinitilized them should it need to.
*
* Stage 2:
* After restoring the non-scratch registers we return from switch_to()
* and the value loaded in LR in stage1 is the address of task_kickstart().
* This function is a trampoline that emulate a return 'from interrupt
* sequence' by restoring the non-scratch registers for the tasks as
* well as triggering a switch from Handler_Mode to Thread_Mode in the
* CPU. We initialize the task non-scratch registers to 0.
*/
struct kernel_context_regs {
u32 r4_r12[9]; /* r4 to r12, zero-filled */
u32 lr; /* initially loaded with EXC_RETURN value */
};
struct thread_context_regs {
u32 r0_r3__r12[5]; /* r0 to r3, r12; args or zero-filled */
u32 lr; /* initially loaded with pthread_exit() */
u32 ret_addr; /* thread entry-point function */
u32 xpsr; /* forced to Thumb_Mode */
};
/* forward declarations */
void switch_to(struct thread_info *, struct thread_info *);
void thread_restore(
struct thread_info *); // FIXME: rename to switch_to_restore_only ? meh..
struct thread_info *thread_create(void *(*) (void *),
void *,
enum thread_privilege,
size_t,
struct task_info *);
int thread_yield(void);
int thread_self(void);
void thread_exit(void *);
int thread_set_priority(struct thread_info *thread, int priority);
int thread_detach(pthread_t thread);
static inline struct thread_info *current_thread_info(void)
{
struct thread_info *this;
__asm__ __volatile__(
"mov %0, sp \n\t"
"bfc %0, #0, %1"
: "=r"(this)
: "M"(INTR_STACK_ORDER));
return this;
}
#define CURRENT_THREAD_INFO(var) \
struct thread_info *var = current_thread_info();
#define THREAD_INFO(addr) \
({ (struct thread_info *) align((unsigned long) addr, INTR_STACK_SIZE); })
#define THREAD_CANARY0 0xee48a608
#define THREAD_CANARY1 0x840dc3bc
#ifdef CONFIG_KERNEL_STACK_CHECKING
#define KERNEL_STACK_CHECKING \
({ \
__auto_type cur_thread = current_thread_info(); \
if ((cur_thread->ti_canary[0] != THREAD_CANARY0) || \
(cur_thread->ti_canary[1] != THREAD_CANARY1)) { \
printk("\nkernel panic: Overflow in kernel stack\n"); \
printk(" 0 %08x %08x\n", THREAD_CANARY0, \
cur_thread->ti_canary[0]); \
printk(" 1 %08x %08x\n", THREAD_CANARY1, \
cur_thread->ti_canary[1]); \
for (;;) \
; \
} \
})
#else
#define KERNEL_STACK_CHECKING
#endif
#endif /* !_KERNEL_THREAD_H */
================================================
FILE: include/kernel/time.h
================================================
#ifndef _KERNEL_TIME_H
#define _KERNEL_TIME_H
#include <signal.h>
#include <sys/types.h>
#include <sys/timespec.h> //FIXME: Why including this header explicitly?
#include_next <time.h>
#include <piko/signal.h>
#include <kernel/types.h>
#include "linux/list.h"
struct timer_info;
enum timer_type { ONESHOT_TIMER, INTERVAL_TIMER };
struct timer_operations {
int (*timer_alloc)(struct timer_info *timer /* , int flags */);
int (*timer_free)(struct timer_info *timer);
int (*timer_set)(struct timer_info *timer, const struct timespec *value);
int (*timer_get)(struct timer_info *timer, struct itimerspec *value);
};
struct timer_info {
timer_t id;
u32 flags;
int disarmed;
enum timer_type type;
void (*callback)(struct timer_info *self);
struct thread_info *owner;
struct itimerspec value;
struct sigevent sigev;
struct list_head list;
const struct timer_operations *tops;
void *dev;
};
struct timer_info *timer_alloc(void);
int timer_free(struct timer_info *timer);
int timer_set(struct timer_info *timer, const struct timespec *value);
int timer_get(struct timer_info *timer, struct itimerspec *value);
void timer_expire_callback(struct timer_info *timer);
#endif /* !_KERNEL_TIME_H */
================================================
FILE: include/kernel/types.h
================================================
#ifndef _KERNEL_TYPES_H
#define _KERNEL_TYPES_H
#ifndef _U32
#define _U32
typedef unsigned int u32;
#endif
#ifndef _S32
#define _S32
typedef int s32;
#endif
#ifndef _U16
#define _U16
typedef unsigned short u16;
#endif
#ifndef _S16
#define _S16
typedef short s16;
#endif
#ifndef _U8
#define _U8
typedef unsigned char u8;
#endif
#ifndef _S8
#define _S8
typedef char s8;
#endif
#ifndef _UMODE_T
#define _UMODE_T
typedef unsigned short umode_t;
#endif
typedef u32 __u32;
typedef s32 __s32;
typedef u16 __u16;
typedef s16 __s16;
typedef u8 __u8;
typedef s8 __s8;
/* import struct list_head */
#include "linux/types.h"
#endif /* !_KERNEL_TYPES_H */
================================================
FILE: include/libc/pthread.h
================================================
#ifndef PTHREAD_H
#define PTHREAD_H
#include_next <pthread.h>
extern int pthread_yield(void);
#endif /* PTHREAD_H */
================================================
FILE: include/libc/ucontext.h
================================================
#ifndef UCONTEXT_H
#define UCONTEXT_H
#include <signal.h>
#include "linux/types.h"
/* machine context on ARM */
typedef struct mcontext {
u32 sp; // FIXME: reuse uc_stack.ss_sp
u32 lr;
u32 gprs[13]; /* r0-r12 */
u32 pc;
} __attribute__((packed)) mcontext_t;
typedef struct ucontext {
struct ucontext *uc_link;
/* sigset_t uc_sigmask; */
stack_t uc_stack;
mcontext_t uc_mcontext;
/* ... */
} ucontext_t;
/* forward declarations */
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
int swapcontext(ucontext_t *oucp, ucontext_t *ucp);
#endif /* !UCONTEXT_H */
================================================
FILE: include/libc/utils.h
================================================
#ifndef UTILS_H
#define UTILS_H
#ifndef __LINKER__
static inline void infinite_loop(void)
{
for (;;)
;
}
void strpad(char *buf, char pad_val, int count);
char *itoa_base(int value, char *buf, int base);
#endif /* !__LINKER__ */
#endif /* !UTILS_H */
================================================
FILE: include/linux/compiler.h
================================================
#ifndef _LINUX_COMPILER_H
#define _LINUX_COMPILER_H
#define READ_ONCE(x) (x)
#define WRITE_ONCE(x, val) \
({ \
x = val; \
val; \
})
#endif /* !_LINUX_COMPILER_H */
================================================
FILE: include/linux/list.h
================================================
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
#include <stdbool.h>
#include <kernel/kernel.h>
#include "linux/types.h"
#include "linux/stddef.h"
#include "linux/poison.h"
#include "linux/compiler.h" /* for READ_ONCE and WRITE_ONCE definitions */
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
#define LIST_HEAD_INIT(name) \
{ \
&(name), &(name) \
}
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
WRITE_ONCE(list->next, list);
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
WRITE_ONCE(prev->next, new);
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
WRITE_ONCE(prev->next, next);
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old, struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del_entry(list);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del_entry(list);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return READ_ONCE(head->next) == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_rotate_left - rotate the list to the left
* @head: the head of the list
*/
static inline void list_rotate_left(struct list_head *head)
{
struct list_head *first;
if (!list_empty(head)) {
first = head->next;
list_move_tail(first, head);
}
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
struct list_head *head,
struct list_head *entry)
{
struct list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void list_cut_position(struct list_head *list,
struct list_head *head,
struct list_head *entry)
{
if (list_empty(head))
return;
if (list_is_singular(head) && (head->next != entry && head != entry))
return;
if (entry == head)
INIT_LIST_HEAD(list);
else
__list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_last_entry - get the last element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member)
/**
* list_first_entry_or_null - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*
* Note that if the list is empty, it returns NULL.
*/
#define list_first_entry_or_null(ptr, type, member) \
(!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
/**
* list_next_entry - get the next element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_next_entry(pos, member) \
list_entry((pos)->member.next, __typeof__(*(pos)), member)
/**
* list_prev_entry - get the prev element in list
* @pos: the type * to cursor
* @member: the name of the list_head within the struct.
*/
#define list_prev_entry(pos, member) \
list_entry((pos)->member.prev, __typeof__(*(pos)), member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal
* of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member); \
&pos->member != (head); pos = list_next_entry(pos, member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_last_entry(head, __typeof__(*pos), member); \
&pos->member != (head); pos = list_prev_entry(pos, member))
/**
* list_prepare_entry - prepare a pos entry for use in
* list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_head within the struct.
*
* Prepares a pos entry for use as a start point in
* list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ?: list_entry(head, __typeof__(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_next_entry(pos, member); &pos->member != (head); \
pos = list_next_entry(pos, member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = list_prev_entry(pos, member); &pos->member != (head); \
pos = list_prev_entry(pos, member))
/**
* list_for_each_entry_from - iterate over list of given type from the current
* point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; &pos->member != (head); pos = list_next_entry(pos, member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against
* removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_first_entry(head, __typeof__(*pos), member), \
n = list_next_entry(pos, member); \
&pos->member != (head); pos = n, n = list_next_entry(n, member))
/**
* list_for_each_entry_safe_continue - continue list iteration safe against
* removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_next_entry(pos, member), n = list_next_entry(pos, member); \
&pos->member != (head); pos = n, n = list_next_entry(n, member))
/**
* list_for_each_entry_safe_from - iterate over list from current point safe
* against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_next_entry(pos, member); &pos->member != (head); \
pos = n, n = list_next_entry(n, member))
/**
* list_for_each_entry_safe_reverse - iterate backwards over list safe against
* removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_last_entry(head, __typeof__(*pos), member), \
n = list_prev_entry(pos, member); \
&pos->member != (head); pos = n, n = list_prev_entry(n, member))
/**
* list_safe_reset_next - reset a stale list_for_each_entry_safe loop
* @pos: the loop cursor used in the list_for_each_entry_safe loop
* @n: temporary storage used in list_for_each_entry_safe
* @member: the name of the list_head within the struct.
*
* list_safe_reset_next is not safe to use in general if the list may be
* modified concurrently (eg. the lock is dropped in the loop body). An
* exception to this is if the cursor element (pos) is pinned in the list,
* and list_safe_reset_next is called after re-taking the lock and before
* completing the current iteration of the loop body.
*/
#define list_safe_reset_next(pos, n, member) n = list_next_entry(pos, member)
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
#define HLIST_HEAD_INIT \
{ \
.first = NULL \
}
#define HLIST_HEAD(name) struct hlist_head name = {.first = NULL}
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !READ_ONCE(h->first);
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
WRITE_ONCE(*pprev, next);
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
WRITE_ONCE(h->first, n);
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
WRITE_ONCE(*(n->pprev), n);
}
static inline void hlist_add_behind(struct hlist_node *n,
struct hlist_node *prev)
{
n->next = prev->next;
WRITE_ONCE(prev->next, n);
n->pprev = &prev->next;
if (n->next)
n->next->pprev = &n->next;
}
/* after that we'll appear to be on some hlist and hlist_del will work */
static inline void hlist_add_fake(struct hlist_node *n)
{
n->pprev = &n->next;
}
static inline bool hlist_fake(struct hlist_node *h)
{
return h->pprev == &h->next;
}
/*
* Move a list from one list head to another. Fixup the pprev
* reference of the first entry if it exists.
*/
static inline void hlist_move_list(struct hlist_head *old,
struct hlist_head *new)
{
new->first = old->first;
if (new->first)
new->first->pprev = &new->first;
old->first = NULL;
}
#define hlist_entry(ptr, type, member) container_of(ptr, type, member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos; pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ \
n = pos->next; \
1; \
}); \
pos = n)
#define hlist_entry_safe(ptr, type, member) \
({ \
__typeof__(ptr) ____ptr = (ptr); \
____ptr ? hlist_entry(____ptr, type, member) : NULL; \
})
/**
* hlist_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(pos, head, member) \
for (pos = hlist_entry_safe((head)->first, __typeof__(*(pos)), member); \
pos; pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), \
member))
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current
* point
* @pos: the type * to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(pos, member) \
for (pos = \
hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), member); \
pos; pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), \
member))
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current
* point
* @pos: the type * to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(pos, member) \
for (; pos; pos = hlist_entry_safe((pos)->member.next, __typeof__(*(pos)), \
member))
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against
* removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(pos, n, head, member) \
for (pos = hlist_entry_safe((head)->first, __typeof__(*pos), member); \
pos && ({ \
n = pos->member.next; \
1; \
}); \
pos = hlist_entry_safe(n, __typeof__(*pos), member))
#endif
================================================
FILE: include/linux/poison.h
================================================
#ifndef LINUX_POISON_H
#define LINUX_POISON_H
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
* Make sure the values raise faults when these addresses are
* read/written.
*/
#define LIST_POISON1 ((void *) 0x100)
#define LIST_POISON2 ((void *) 0x200)
#endif /* !LINUX_POISON_H */
================================================
FILE: include/linux/stddef.h
================================================
#ifndef _LINUX_STDDEF_H
#define _LINUX_STDDEF_H
#include <stddef.h>
/**
* offsetofend(TYPE, MEMBER)
*
* @TYPE: The type of the structure
* @MEMBER: The member within the structure to get the end offset of
*/
#define offsetofend(TYPE, MEMBER) \
(offsetof(TYPE, MEMBER) + sizeof(((TYPE *) 0)->MEMBER))
#endif
================================================
FILE: include/linux/types.h
================================================
#ifndef LINUX_TYPES_H
#define LINUX_TYPES_H
#define S32_MAX 2147483647
typedef unsigned int u32;
typedef int s32;
typedef unsigned short u16;
typedef short s16;
typedef unsigned char u8;
typedef char s8;
typedef unsigned int size_t;
struct list_head {
struct list_head *next, *prev;
};
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
typedef struct {
volatile s32 val;
} atomic_t;
#endif /* !LINUX_TYPES_H */
================================================
FILE: include/piko/arpa/inet.h
================================================
#ifndef LIBC_ARPA_INET_H
#define LIBC_ARPA_INET_H
#include <stdint.h>
#include "platform.h"
static inline uint32_t htonl(uint32_t hostlong)
{
return __REV(hostlong);
}
static inline uint16_t htons(uint16_t hostshort)
{
return __REV16(hostshort);
}
static inline uint32_t ntohl(uint32_t netlong)
{
return __REV(netlong);
}
static inline uint16_t ntohs(uint16_t netshort)
{
return __REV16(netshort);
}
#endif /* !LIBC_ARPA_INET_H */
================================================
FILE: include/piko/dirent.h
================================================
#ifndef _LIBPIKO_DIRENT_H
#define _LIBPIKO_DIRENT_H
#include <sys/types.h>
#define NAME_MAX 32 // FIXME: Include <limits.h>
typedef void DIR;
struct dirent {
ino_t d_ino; /* inode number */
char d_name[NAME_MAX]; /* filename */
};
DIR *opendir(const char *dirname);
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
int closedir(DIR *dirp);
#endif /* !_LIBPIKO_DIRENT_H */
================================================
FILE: include/piko/signal.h
================================================
#ifndef LIBC_SIGNAL_H
#define LIBC_SIGNAL_H
#include <sys/types.h>
#include "linux/list.h"
typedef struct {
void *ss_sp; /* Base address of stack */
int ss_flags; /* Flags */
size_t ss_size; /* Number of bytes in stack */
} stack_t;
/* sigevent - structure for notification from asynchronous routines */
union sigval { /* Data passed with notification */
int sival_int; /* Integer value */
void *sival_ptr; /* Pointer value */
};
struct sigevent {
int sigev_notify; /* Notification method */
int sigev_signo; /* Notification signal */
/* Data passed with notification */
union sigval sigev_value;
/* Function used for thread notification (SIGEV_THREAD) */
void (*sigev_notify_function)(union sigval);
/* Attributes for notification thread (SIGEV_THREAD) */
void *sigev_notify_attributes;
/* ID of thread to signal (SIGEV_THREAD_ID) */
pid_t sigev_notify_thread_id;
};
/* sigaction - used to change the action taken by a process on receipt of a
specific signal */
typedef struct {
int si_signo;
/* int si_code; */
union sigval si_value;
/* int si_errno; */
pid_t si_pid;
/* uid_t si_uid; */
/* void *si_addr; */
/* int si_status; */
/* int si_band; */
} siginfo_t;
typedef int sigset_t;
struct sigaction {
union {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
};
sigset_t sa_mask;
int sa_flags;
/* Storage for kernel fields. Not compliant with the POSIX specs. */
struct list_head sa_list;
int sa_signo;
};
#define SA_SIGINFO (1 << 0)
#define SIGKILL 9 /* Kill (can't be caught or ignored) (POSIX) */
#define SIGUSR1 10 /* User defined signal 1 (POSIX) */
#define SIGUSR2 12 /* User defined signal 2 (POSIX) */
#define SIGSTOP 19 /* Stop executing(can't be caught or ignored) (POSIX) */
int sigaction(int sig,
const struct sigaction *restrict act,
struct sigaction *restrict oact);
int raise(int sig);
#endif /* !LIBC_SIGNAL_H */
================================================
FILE: include/piko/sys/mman.h
================================================
#ifndef _SYS_MMAN_H
#define _SYS_MMAN_H
#include <sys/types.h>
#define PROT_NONE 0x00 /* page can not be accessed */
#define PROT_READ 0x01 /* page can be read */
#define PROT_WRITE 0x02 /* page can be written */
#define PROT_EXEC 0x04 /* page can be executed */
#define MAP_FAILED ((void *) -1)
#define MAP_ANONYMOUS 0x01 /* don't use a file */
#define MAP_UNINITIALIZED 0x02 /* anonymous memory can be uninitialized */
void *mmap(void *addr,
size_t length,
int prot,
int flags,
int fd,
off_t offset);
int munmap(void *addr, size_t length);
#endif /* !_SYS_MMAN_H */
================================================
FILE: include/piko/sys/mount.h
================================================
#ifndef _SYS_MOUNT_H
#define _SYS_MOUNT_H
int mount(const char *source,
const char *target,
const char *filesystemtype,
unsigned long mountflags,
const void *data);
#endif /* !_SYS_MOUNT_H */
================================================
FILE: include/piko/sys/resource.h
================================================
#ifndef SYS_RESOURCE_H
#define SYS_RESOURCE_H
/* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_resource.h.html
*/
/* Unsigned integer type used for limit values. */
typedef unsigned int rlim_t;
struct rlimit {
rlim_t rlim_cur; /* Soft limit */
rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur) */
};
#define RLIMIT_STACK 0
#ifdef __KERNEL__
int sys_getrlimit(int resource, struct rlimit *rlim);
int sys_setrlimit(int resource, const struct rlimit *rlim);
#else /* !__KERNEL__ */
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
#endif /* __KERNEL__ */
#endif /* !SYS_RESOURCE_H */
================================================
FILE: include/platform/compiler.h
================================================
#ifndef _PLATFORM_COMPILER_H
#define _PLATFORM_COMPILER_H
#define PLAT_EVAL(macro) \
({ \
void __wrapper__(void) {macro;} \
__wrapper__; \
})
#endif /* !_PLATFORM_COMPILER_H */
================================================
FILE: include/version.template.h
================================================
#ifndef VERSION_H
#define VERSION_H
#define VER_MAJOR "0"
#define VER_MINOR "0"
#define VER_MICRO "0"
#define VER_SLUG "piko-" VER_MAJOR "." VER_MINOR "." VER_MICRO
#endif /* !VERSION_H */
================================================
FILE: kernel/cond.c
================================================
#include <sys/types.h>
#include <kernel/mutex.h>
#include <kernel/sched.h>
#include <kernel/thread.h>
#include "linux/list.h"
static LIST_HEAD(cond_head);
static struct thread_info *find_other_thread(pthread_cond_t *cond)
{
struct thread_info *other;
list_for_each_entry(other, &cond_head, ti_q)
{
if (other->ti_private == cond)
return other;
}
return NULL;
}
int sys_pthread_cond_wait(pthread_cond_t *cond, kernel_mutex_t *mutex)
{
CURRENT_THREAD_INFO(curr_thread);
curr_thread->ti_private = cond;
curr_thread->ti_state = THREAD_STATE_BLOCKED;
list_add_tail(&curr_thread->ti_q, &cond_head);
sys_pthread_mutex_unlock(mutex);
/* contend for the lock */
sys_pthread_mutex_lock(mutex);
return 0;
}
int sys_pthread_cond_signal(pthread_cond_t *cond)
{
struct thread_info *other;
other = find_other_thread(cond);
if (!other)
return 0;
list_del(&other->ti_q);
sched_enqueue(other);
CURRENT_THREAD_INFO(curr_thread);
if (other->ti_priority >= curr_thread->ti_priority) {
sched_enqueue(curr_thread);
sched_elect(SCHED_OPT_NONE);
}
return 0;
}
================================================
FILE: kernel/config.c
================================================
#include <unistd.h>
enum sc_varname {
PAGESIZE,
};
struct sys_param {
const char *name;
long value;
};
struct sys_param sys_params[] = {
{"pagesize", 2048},
{"clock_tick", 0}, // FIXME: set by systick_init()
};
long sys_sysconf(int name)
{
switch (name) {
case PAGESIZE:
return sys_params[0].value;
case _SC_CLK_TCK:
return sys_params[1].value;
}
return -1;
}
================================================
FILE: kernel/faults.c
================================================
#include <kernel/faults.h>
#include <kernel/thread.h>
#include "kernel.h"
#include "utils.h"
#include "platform.h"
void fault_enter(const char *s)
{
printk("\n-------------------------------------------------------------\n");
printk(" #%s\n\n", s);
}
void fault_exit(void)
{
printk("-------------------------------------------------------------\n");
__platform_halt();
}
void hardfault(struct kernel_context_regs *noscratch,
struct thread_context_regs *scratch,
u32 exc_return)
{
fault_enter("HardFault");
dump_frame(noscratch, scratch, exc_return);
fault_exit();
}
================================================
FILE: kernel/fs/fs.c
================================================
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <kernel/bitops.h>
#include <kernel/errno-base.h>
#include <kernel/fs.h>
#include <fs/romfs.h>
#include <kernel/task.h>
struct file *fd_to_file(int fd)
{
CURRENT_TASK_INFO(curr_task);
return &curr_task->filetable[fd];
}
static int getfd(void)
{
int fd;
CURRENT_TASK_INFO(curr_task);
fd = find_first_zero_bit(&curr_task->filemap, FILE_MAX);
if (fd == FILE_MAX)
return -1;
bitmap_set_bit(&curr_task->filemap, fd);
return fd;
}
static void releasefd(int fd)
{
CURRENT_TASK_INFO(curr_task);
bitmap_clear_bit(&curr_task->filemap, fd);
}
int release_dentries(struct dentry *dentry)
{
struct dentry *parent;
for (; dentry != root_dentry(); dentry = parent) {
if (!dentry->d_count)
return -1;
if (--dentry->d_count)
break;
parent = dentry->d_parent;
vfs_release(dentry);
if (!dentry->d_count)
vfs_delete(dentry);
}
return 0;
}
static int path_head(char *buf, const char *pathname)
{
int i, i0 = 0;
if (pathname[0] == '\0')
return -1;
if (pathname[0] == '/')
i0++;
for (i = i0; i < NAME_MAX && pathname[i] != '/' && pathname[i] != '\0'; i++)
;
strncpy(buf, &pathname[i0], i - i0);
buf[i - i0] = '\0';
return i;
}
struct inode *inode_from_pathname(
const char *pathname /* , struct dentry *from */)
{
struct inode *inode = root_inode();
struct dentry *dentry = root_dentry();
struct dentry target;
/* remove the trailing slash, relative path is not supported */
pathname++;
for (size_t i = 0; i < strlen(pathname);) {
i += path_head(target.d_name, &pathname[i]);
dentry = vfs_lookup(inode, &target);
if (!dentry)
return NULL;
inode = dentry->d_inode;
}
return inode;
}
int sys_open(const char *pathname, int flags)
{
struct inode *inode = root_inode();
struct dentry *dentry = root_dentry();
struct dentry *parent = dentry;
struct dentry *target;
/* remove the trailing slash, relative path is not supported */
pathname++;
for (size_t i = 0; i < strlen(pathname);) {
target = malloc(sizeof(struct dentry));
if (!target) {
errno = ENOMEM;
return 0;
}
target->d_count = 1;
target->d_parent = parent;
i += path_head(target->d_name, &pathname[i]);
dentry = vfs_lookup(inode, target);
if (!dentry) {
errno = ENOENT;
release_dentries(target->d_parent);
return 0;
}
inode = dentry->d_inode;
parent = dentry;
}
/* opendir() redirects to sys_open() */
if ((flags & O_DIRECTORY) && !S_ISDIR(inode->i_mode)) {
errno = ENOTDIR;
return 0;
}
int fd = getfd();
if (fd < 0) {
errno = EBADF;
return 0;
}
struct file *file = fd_to_file(fd);
file->f_dentry = dentry;
file->f_op = dentry->d_inode->i_fop;
file->f_pos = 0;
if (file->f_op->open)
file->f_op->open(inode, file);
return fd;
}
ssize_t sys_read(int fd, void *buf, size_t count)
{
struct file *file = fd_to_file(fd);
if (count)
count = file->f_op->read(file, buf, count, file->f_pos);
file->f_pos += count;
return count;
}
ssize_t sys_write(int fd, void *buf, size_t count)
{
struct file *file = fd_to_file(fd);
off_t offset = file->f_pos;
count = file->f_op->write(file, buf, count, &offset);
file->f_pos += count;
return count;
}
off_t sys_lseek(int fd, off_t offset, int whence)
{
struct file *file = fd_to_file(fd);
off_t size = file->f_dentry->d_inode->i_size;
if (file->f_op->lseek)
file->f_op->lseek(file, offset, whence);
switch (whence) {
case SEEK_SET:
if (offset)
offset = size % offset;
break;
case SEEK_CUR:
offset = (file->f_pos + offset) % size;
break;
case SEEK_END:
offset = (size + offset) % size;
break;
default:
return -1;
}
file->f_pos = offset;
return 0;
}
int sys_close(int fd)
{
struct file *file = fd_to_file(fd);
release_dentries(file->f_dentry);
releasefd(fd);
return 0;
}
int sys_stat(const char *pathname, struct stat *buf)
{
struct inode *inode = inode_from_pathname(pathname);
if (!inode) {
errno = ENOENT;
return -1;
}
buf->st_ino = inode->i_ino;
buf->st_mode = inode->i_mode;
buf->st_size = inode->i_size;
return 0;
}
int sys_mount(const char *source,
const char *target,
const char *filesystemtype,
unsigned long mountflags,
const void *data)
{
if (!strcmp("romfs", filesystemtype))
return romfs_mount(source, target, filesystemtype, mountflags, data);
return -1;
}
================================================
FILE: kernel/fs/readdir.c
================================================
#include <stdlib.h>
#include <string.h>
#include <kernel/fs.h>
#include <kernel/kernel.h>
#include "linux/list.h"
static int fillonedir(struct dir_context *ctx,
const char *name,
int namlen,
__unused off_t offset,
unsigned int ino,
__unused unsigned int d_type)
{
struct readdir_callback *buf =
container_of(ctx, struct readdir_callback, ctx);
struct piko_dirent *dirent = buf->dirent;
dirent->d_ino = ino;
strncpy(dirent->d_name, name, namlen);
dirent->d_name[namlen] = '\0';
return 0;
}
int sys_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
{
struct file *file = fd_to_file((int) dirp);
struct readdir_callback buf = {
.ctx = {.actor = fillonedir, .pos = 0},
.dirent = (struct piko_dirent *) entry,
};
if (vfs_iterate(file, &buf.ctx))
*result = NULL;
else
*result = entry;
return 0;
}
================================================
FILE: kernel/fs/vfs.c
================================================
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <kernel/fs.h>
#include <kernel/kernel.h>
#include "linux/list.h"
int vfs_iterate(struct file *file, struct dir_context *ctx)
{
if (!file->f_op->iterate)
return -1;
return file->f_op->iterate(file, ctx);
}
struct dentry *vfs_lookup(struct inode *dir, struct dentry *target)
{
if (!dir->i_op->lookup)
return NULL;
if (!S_ISDIR(dir->i_mode))
return NULL;
return dir->i_op->lookup(dir, target);
}
int vfs_link(struct dentry *old_dentry,
struct inode *dir,
struct dentry *dentry)
{
if (!dir->i_op->link)
return -1;
return dir->i_op->link(old_dentry, dir, dentry);
}
int vfs_delete(struct dentry *dentry)
{
if (!dentry->d_op->delete)
return -1;
return dentry->d_op->delete (dentry);
}
void vfs_release(struct dentry *dentry)
{
if (dentry->d_op->release)
return dentry->d_op->release(dentry);
}
int vfs_mmap(struct file *file, off_t offset, void **addr)
{
if (!file->f_op->mmap)
return -1;
return file->f_op->mmap(file, offset, addr);
}
================================================
FILE: kernel/irq.c
================================================
#include <stddef.h>
#include <stdlib.h>
#include <kernel/types.h>
#include <kernel/irq.h>
#define IRQ_MAX 64
irq_handler_t irq_handler[IRQ_MAX];
// clang-format off
static struct irq_desc irq_desc[NR_IRQS] = {
[0 ... NR_IRQS - 1] = {
.irq_data = {.state = 0x0},
.action = NULL,
.status = 0x0,
}
};
// clang-format on
static struct irq_desc *irq_to_desc(unsigned int irq)
{
if (irq < NR_IRQS)
return irq_desc + irq;
return NULL;
}
int request_irq(unsigned int irq, irq_handler_t hdlr)
{
struct irqaction *action;
struct irq_desc *desc;
desc = irq_to_desc(irq);
if (desc && (desc->status & IRQ_NOREQUEST)) {
action = (struct irqaction *) malloc(sizeof(struct irqaction));
if (!action) {
// WARN_ON(!action, "malloc failed\n");
goto fail;
}
action->irq = irq;
action->handler = hdlr;
/* install to irq_desc */
desc->action = action;
irq_handler[irq] = hdlr;
return 0;
} else
fail:
return -1;
}
int free_irq(unsigned int irq)
{
struct irq_desc *desc;
desc = irq_to_desc(irq);
if (desc && !(desc->status & IRQ_NOREQUEST)) {
free(desc->action);
desc->status |= IRQ_NOREQUEST;
irq_handler[irq] = NULL;
return 0;
}
return -1;
}
void early_irq_init(void)
{
for (int irq = 0; irq < NR_IRQS; irq++)
irq_desc[irq].irq_data.state = IRQD_IRQ_DISABLED;
}
void init_IRQ(void)
{
for (int irq = 0; irq < NR_IRQS; irq++)
irq_desc[irq].status = IRQ_NOREQUEST;
}
================================================
FILE: kernel/main.c
================================================
#include <stdio.h>
#include <stdlib.h>
#include <sys/cdefs.h>
#include <sys/fcntl.h>
#include <kernel/fs.h>
#include <kernel/kernel.h>
#include <kernel/mm/page.h>
#include <kernel/mm/slab.h>
#include <kernel/sched.h>
#include <kernel/task.h>
#include <kernel/thread.h>
#include <kernel/compiler.h>
#include <kernel/softirq.h>
#include <kernel/serial.h>
#include "platform.h"
extern char __early_stack_start__;
extern char __early_stack_end__;
extern char __text_start__;
extern char __text_end__;
extern char __rodata_start__;
extern char __rodata_end__;
extern char __data_start__;
extern char __data_end__;
extern char __bss_start__;
extern char __bss_end__;
extern char __pgmem_start__;
extern char __pgmem_end__;
extern char __pgmem_size__;
extern char __heap_start__;
extern char __heap_end__;
extern char __heap_size__;
void __do_idle(void);
void *do_idle(void *);
void mtdram_init(void);
void __printk_init(void);
int minishell(void *options);
void memdev_init(void);
void kernel_heap_init(void *heap_start, size_t heap_size);
void early_irq_init(void);
void init_IRQ(void);
struct task_info idle_task;
struct task_info main_task;
void print_version(void)
{
char buf[] = {0, 0};
int fd = open("/proc/version", 0);
while (read(fd, &buf, 1))
printk("%s", buf);
close(fd);
printk("\n");
}
void __weak *main(__unused void *arg)
{
print_version();
minishell(NULL);
return 0;
}
struct thread_info *thread_idle;
/* Cortex-M3/4 system initialization */
static void v7m_init(void)
{
/* enable UsageFault, BusFault, MemManage faults */
SCB->SHCSR |= (SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk |
SCB_SHCSR_MEMFAULTENA_Msk);
/* Configure the System Control Register to ensure 8-byte stack
alignment */
SCB->CCR |= SCB_CCR_STKALIGN_Msk;
// NVIC_SetPriority(DebugMonitor_IRQn, 0x0, 0);
NVIC_SetPriority(MemoryManagement_IRQn, 0x1);
NVIC_SetPriority(BusFault_IRQn, 0x1);
NVIC_SetPriority(UsageFault_IRQn, 0x1);
NVIC_SetPriority(SysTick_IRQn, 0x3);
/* Priority 0xF - debug_uart */
NVIC_SetPriority(SVCall_IRQn, 0xF);
NVIC_SetPriority(PendSV_IRQn, 0xF);
/* follow the architectural requirements */
__DSB();
}
void print_linker_sections(void)
{
printk("Memory map:\n");
printk(" .text = %08x--%08x %6d Bytes\n", &__text_start__,
&__text_end__, &__text_end__ - &__text_start__);
printk(" .rodata = %08x--%08x %6d Bytes\n", &__rodata_start__,
&__rodata_end__, &__rodata_end__ - &__rodata_start__);
printk(" .data = %08x--%08x %6d Bytes\n", &__data_start__,
&__data_end__, &__data_end__ - &__data_start__);
printk(" .bss = %08x--%08x %6d Bytes\n", &__bss_start__, &__bss_end__,
&__bss_end__ - &__bss_start__);
printk(" .heap = %08x--%08x %6d Bytes\n", &__heap_start__,
&__heap_end__, &__heap_end__ - &__heap_start__);
printk(" .pgmem = %08x--%08x %6d Bytes\n", &__pgmem_start__,
&__pgmem_end__, &__pgmem_end__ - &__pgmem_start__);
}
struct thread_info *start_kernel(void)
{
v7m_init();
early_irq_init();
init_IRQ();
/* TODO: Early console */
__printk_init();
/* initialize the kernel's malloc */
kernel_heap_init(&__heap_start__, (size_t) &__heap_size__);
print_linker_sections();
/* initialize the physical memory allocator */
show_page_bitmap(); // init_pages();
kmem_cache_init();
/* initialize the scheduler internels */
sched_init();
/* select giving scheduling policy */
sched_select(SCHED_CLASS_BITMAP);
/* idle_thread is not added to the runqueue */
task_init(&idle_task);
thread_idle =
thread_create(do_idle, NULL, THREAD_PRIV_SUPERVISOR, 1024, &idle_task);
if (!thread_idle) {
printk("[!] Could not create system idle thread.\n");
return NULL;
}
printk("Created idle_thread at <%p>\n", thread_idle);
/* The main_thread is the user's entry-point to the system. It is not
* added to the runqueue because it has been implicitly "elected" when
* start_kernel() returns. */
task_init(&main_task);
struct thread_info *thread_main =
thread_create(main, NULL, THREAD_PRIV_USER, 1024, &main_task);
if (!thread_main) {
printk("[!] Could not create user main thread.\n");
return NULL;
}
printk("Created main_thread at <%p> with priority=%d\n", thread_main,
thread_main->ti_priority);
/* Reclaim the early-stack physical memory. In the current context, no
* page allocation after this point are allowed. */
printk("Reclaim early stack's physical memory (%d Bytes, order=%d).\n",
&__early_stack_start__ - &__early_stack_end__,
size_to_page_order(2048));
free_pages((unsigned long) &__early_stack_end__, size_to_page_order(2048));
tmpfs_init();
proc_init();
memdev_init();
mtdram_init(); /* create a test mtdram device */
/* do the platform-specific inits */
__platform_init();
init_softirq();
/* create /dev/ttyS0 */
serial_init();
printk("Kernel bootstrap done.\n--\n");
return thread_main;
}
void *do_idle(__unused void *arg)
{
for (;;)
__do_idle();
}
================================================
FILE: kernel/mm/mm.c
================================================
#include <errno.h>
#include <string.h>
#include <sys/cdefs.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <piko/sys/mman.h>
#include <kernel/fs.h>
#include <kernel/mm/page.h>
#define M_ISANON(f) (((f) &MAP_ANONYMOUS) == MAP_ANONYMOUS)
#define M_ISUNINIT(f) (((f) &MAP_UNINITIALIZED) == MAP_UNINITIALIZED)
static void *map_anon(void *addr, size_t length, __unused int prot, int flags)
{
int order;
order = size_to_page_order(length);
addr = alloc_pages(order);
if (!addr) {
printk("mmap: ENOMEM\n");
errno = ENOMEM;
return MAP_FAILED;
}
if (!M_ISUNINIT(flags))
memset(addr, 0, length);
return addr;
}
static void *map_file(__unused size_t length,
__unused int prot,
__unused int flags,
int fd,
off_t offset)
{
void *addr;
struct file *file;
file = fd_to_file(fd);
if (!file) {
printk("mmap: BADF\n");
errno = EBADF;
return MAP_FAILED;
}
if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
printk("mmap: ACCESS\n");
errno = EACCES;
return MAP_FAILED;
}
if (vfs_mmap(file, offset, &addr)) {
printk("mmap: failed in romfs_map\n");
for (;;)
;
return MAP_FAILED;
}
return addr;
}
void *sys_mmap(void *addr,
size_t length,
int prot,
int flags,
int fd,
off_t offset)
{
if (!length) {
errno = EINVAL;
printk("mmap: length is 0\n");
return MAP_FAILED;
}
if (prot & PROT_NONE) {
errno = EACCES;
printk("mmap: PROT_NONE\n");
return MAP_FAILED;
}
if (M_ISANON(flags))
addr = map_anon(addr, length, prot, flags);
else
addr = map_file(length, prot, flags, fd, offset);
return addr;
}
int sys_munmap(__unused void *addr, __unused size_t length)
{
/* Closing the file descriptor does not unmap the region. */
return 0;
}
================================================
FILE: kernel/mm/page.c
================================================
#include <stddef.h>
#include <kernel/bitops.h>
#include <kernel/hash.h>
#include <kernel/kernel.h>
#include <kernel/log2.h>
#include <kernel/mm/page.h>
/* .pgmem section is 32KB:
* - 128 pages of 256B is a 16 bytes map
* - 64 pages of 512B is a 8 bytes map
* - 32 pages of 1KB is a 4 bytes map
* - 16 pages of 2KB is a 2 bytes map
*
* Last page is reserved by the early stack, and freed after system init.
*/
/* 0 = allocated/undefined, 1 = free */
static unsigned long *const page_bitmap[] = {
(unsigned long[]){0, 0, 0, 0}, (unsigned long[]){0, 0},
(unsigned long[]){0}, (unsigned long[]){0x7fff}};
static const unsigned long page_bitmap_sz[] = {128, 64, 32, 16};
long size_to_page_order(unsigned long size)
{
if (size <= 256)
return 0;
if (size <= 512)
return 1;
if (size <= 1024)
return 2;
if (size <= 2048)
return 3;
return -1;
}
static long find_first_free_page(unsigned long order)
{
unsigned long page_idx =
find_first_bit(page_bitmap[order], page_bitmap_sz[order]);
if (page_idx >= page_bitmap_sz[order])
return -1;
return page_idx;
}
static void split_first_free_page(unsigned long order)
{
unsigned long page_idx =
find_first_bit(page_bitmap[order], page_bitmap_sz[order]);
bitmap_clear_bit(page_bitmap[order], page_idx);
bitmap_set_bit(page_bitmap[order - 1], page_idx * 2);
bitmap_set_bit(page_bitmap[order - 1], page_idx * 2 + 1);
}
extern char __pgmem_start__;
static void *page_idx_to_addr(unsigned long idx, unsigned long order)
{
return &__pgmem_start__ + idx * (1 << (order + ilog2(MIN_PAGE_SIZE)));
}
void *alloc_pages(unsigned long order)
{
unsigned long page_idx, o;
for (o = order; (o <= MAX_PAGE_ORDER) && (find_first_free_page(o) < 0); o++)
;
if (o > MAX_PAGE_ORDER)
return NULL;
for (; o > order; o--)
split_first_free_page(o);
page_idx = find_first_bit(page_bitmap[order], page_bitmap_sz[order]);
bitmap_clear_bit(page_bitmap[order], page_idx);
/* printk("Returning address %p\n", page_idx_to_addr(page_idx, order)); */
return page_idx_to_addr(page_idx, order);
}
static inline unsigned long addr_to_page_idx(unsigned long addr,
unsigned long order)
{
// FIXME: multiple zone to allocate from? use the zone's base address
// instead
return (addr - (unsigned long) &__pgmem_start__) >>
(order + ilog2(MIN_PAGE_SIZE));
}
static inline unsigned long get_buddy_index(unsigned long idx)
{
return idx % 2 ? idx - 1 : idx + 1;
}
/* try to coalesce free buddies */
void free_pages(unsigned long addr, unsigned long order)
{
unsigned long page_idx, buddy_idx, mask;
for (; order < MAX_PAGE_ORDER; order++) {
page_idx = addr_to_page_idx(addr, order);
buddy_idx = get_buddy_index(page_idx);
if (bitmap_get_bit(page_bitmap[order], buddy_idx)) {
bitmap_clear_bit(page_bitmap[order], buddy_idx);
mask = ~((1 << (order + 1 + ilog2(MIN_PAGE_SIZE))) - 1);
addr &= mask;
} else {
bitmap_set_bit(page_bitmap[order], page_idx);
return;
}
}
bitmap_set_bit(page_bitmap[order], addr_to_page_idx(addr, order));
}
void show_page_bitmap(void)
{
printk("Order Bitmap\n");
for (int i = 0; i <= 3; i++) {
printk(" %d ", i);
for (unsigned long j = 0; j < page_bitmap_sz[i]; j += BITS_PER_LONG)
printk("%08x ", *(page_bitmap[i] + j / BITS_PER_LONG));
printk("\n");
}
}
/* Useful function to get a signature of memory fragmentation before and
* after allocating/freeing memory. */
unsigned long page_alloc_signature(void)
{
unsigned long hash = hash_djb2((unsigned char *) page_bitmap[0], 4 * 4) +
hash_djb2((unsigned char *) page_bitmap[1], 2 * 4) +
hash_djb2((unsigned char *) page_bitmap[2], 1 * 4) +
hash_djb2((unsigned char *) page_bitmap[3], 1 * 4);
return hash;
}
================================================
FILE: kernel/mm/slab.c
================================================
#include <stdio.h>
#include <string.h>
#include <sys/cdefs.h>
#include <kernel/bitops.h>
//#include <kernel/kernel.h>
#include <kernel/mm/page.h>
#include <kernel/mm/slab.h>
#include "linux/list.h"
#define OBJECTS_PER_SLAB(objsize) \
((CACHE_PAGE_SIZE - sizeof(struct slab)) / (objsize))
static LIST_HEAD(caches);
static struct kmem_cache cache_caches = {
.objsize = sizeof(struct kmem_cache),
.objnum = OBJECTS_PER_SLAB(sizeof(struct kmem_cache)),
.name = "cache-cache",
.slabs_free = LIST_HEAD_INIT(cache_caches.slabs_free),
.slabs_partial = LIST_HEAD_INIT(cache_caches.slabs_partial),
.slabs_full = LIST_HEAD_INIT(cache_caches.slabs_full),
.alloc_succeed = 0,
.alloc_fail = 0,
.opts = CACHE_OPT_NONE,
};
static inline struct slab *get_slab_from_obj(void *obj, size_t page_size)
{
return (struct slab *) align((unsigned long) obj, page_size);
}
static inline int obj_index_in_slab(void *obj, struct kmem_cache *cache)
{
return (((unsigned long) obj & ((1 << 8) - 1)) - sizeof(struct slab)) /
cache->objsize;
}
struct kmem_cache *kmem_cache_create(const char *name,
size_t size,
__unused size_t align,
__unused unsigned long flags,
__unused void (*ctor)(void *))
{
struct kmem_cache *cache;
if (size < 8) {
printk("error: Use cache for objects with size >= 8 bytes\n");
return NULL;
}
if (size > (256 - sizeof(struct slab)) / 2) {
printk("error: Object size is too big\n");
return NULL;
}
cache = kmem_cache_alloc(&cache_caches, 0);
if (!cache)
return NULL;
cache->objsize = size;
cache->objnum = OBJECTS_PER_SLAB(size);
cache->opts = CACHE_OPT_NONE;
strncpy(cache->name, name, CACHE_NAMELEN);
INIT_LIST_HEAD(&cache->slabs_free);
INIT_LIST_HEAD(&cache->slabs_partial);
INIT_LIST_HEAD(&cache->slabs_full);
list_add(&cache->list, &caches);
return cache;
}
static struct slab *kmem_cache_grow(struct kmem_cache *cache)
{
struct slab *slab = alloc_pages(0);
if (!slab)
return NULL;
slab->free_bitmap[0] = 0;
slab->free_objects = cache->objnum;
list_add(&slab->list, &cache->slabs_free);
return slab;
}
void *kmem_cache_alloc(struct kmem_cache *cache, __unused unsigned long flags)
{
struct slab *slab = NULL;
void *mem;
if (list_empty(&cache->slabs_partial)) {
if (list_empty(&cache->slabs_free)) {
cache->alloc_fail++;
slab = kmem_cache_grow(cache);
if (!slab)
return NULL;
} else {
cache->alloc_succeed++;
slab = list_first_entry(&cache->slabs_free, struct slab, list);
}
list_move(&slab->list, &cache->slabs_partial);
} else {
cache->alloc_succeed++;
slab = list_first_entry(&cache->slabs_partial, struct slab, list);
}
int bit = find_first_zero_bit(slab->free_bitmap, cache->objnum);
bitmap_set_bit(slab->free_bitmap, bit);
mem = slab->data + bit * cache->objsize;
slab->free_objects--;
if (!slab->free_objects)
list_move(&slab->list, &cache->slabs_full);
return mem;
}
static int slab_destroy(__unused struct kmem_cache *cache, struct slab *slab)
{
list_del(&slab->list);
free_pages((unsigned long) slab, 0);
return 0;
}
void kmem_cache_free(struct kmem_cache *cache, void *obj)
{
struct slab *slab;
int bit;
slab = get_slab_from_obj(obj, 256);
bit = obj_index_in_slab(obj, cache);
bitmap_clear_bit(slab->free_bitmap, bit);
slab->free_objects++;
if (slab->free_objects == cache->objnum)
slab_destroy(cache, slab);
else if (slab->free_objects == 1)
list_move(&slab->list, &cache->slabs_partial);
}
void kmem_cache_init(void)
{
list_add(&cache_caches.list, &caches);
kmem_cache_grow(&cache_caches);
}
================================================
FILE: kernel/mutex.c
================================================
#include <kernel/kernel.h>
#include <kernel/mutex.h>
#include <kernel/sched.h>
#include <kernel/thread.h>
#include "linux/list.h"
static LIST_HEAD(mutex_head);
/* The thread owns the mutex on return. We also check the case when the lock
* has been released between the test of the mutex and this syscall. */
int sys_pthread_mutex_lock(kernel_mutex_t *mutex)
{
mutex->val++;
if (!mutex->val)
return 0;
CURRENT_THREAD_INFO(curr_thread);
curr_thread->ti_private = mutex;
curr_thread->ti_state = THREAD_STATE_BLOCKED;
list_add_tail(&curr_thread->ti_q, &mutex_head);
sched_elect(SCHED_OPT_NONE);
return 0;
}
static struct thread_info *find_first_blocking_thread(kernel_mutex_t *mutex)
{
struct thread_info *thread;
list_for_each_entry(thread, &mutex_head, ti_q)
{
if (thread->ti_private == mutex)
return thread;
}
return NULL;
}
int sys_pthread_mutex_unlock(kernel_mutex_t *mutex)
{
struct thread_info *waiter = NULL;
mutex->val--;
if (mutex->val >= 0) {
waiter = find_first_blocking_thread(mutex);
if (!waiter) {
printk("[mutex_unlock] No blocking threads for mutex=<%p>\n",
mutex);
return -1;
}
list_del(&waiter->ti_q);
sched_enqueue(waiter);
}
CURRENT_THREAD_INFO(curr_thread);
if (curr_thread->ti_state == THREAD_STATE_BLOCKED) {
sched_elect(SCHED_OPT_NONE);
} else if (waiter && (curr_thread->ti_priority <= waiter->ti_priority)) {
sched_enqueue(curr_thread);
sched_elect(SCHED_OPT_NONE);
}
return 0;
}
================================================
FILE: kernel/printk.c
================================================
#include <stdarg.h>
#include <stdio.h>
#include <ucontext.h>
#define VSNPRINTF_BUF_SIZE 256
static ucontext_t printk_context;
static ucontext_t vsnprintf_context = {.uc_link = &printk_context};
static unsigned int ctx_stack[128];
static char vsnprintf_buf[VSNPRINTF_BUF_SIZE];
static int retval;
/* not thread-safe, not reentrant */
static void co_vsnprintf(const char *format, va_list ap)
{
retval = vsnprintf(vsnprintf_buf, VSNPRINTF_BUF_SIZE, format, ap);
}
#include <serial.h>
#include "platform.h"
void __printk_init(void)
{
uart_init();
}
void __printk_putchar(char c)
{
if (c == '\n')
__printk_putchar('\r');
while (!(USARTx->SR & USART_SR_TXE))
;
USARTx->DR = (0xff) & c;
}
int printk(const char *format, ...)
{
/*FIXME: should be interruptable*/
__disable_irq();
va_list ap;
va_start(ap, format);
vsnprintf_context.uc_stack.ss_sp = &ctx_stack[128];
makecontext(&vsnprintf_context, co_vsnprintf, 2, format, ap);
swapcontext(&printk_context, &vsnprintf_context);
for (char *c = vsnprintf_buf; *c != '\0'; c++)
__printk_putchar(*c);
va_end(ap);
/*FIXME: should be interruptable*/
__enable_irq();
return retval;
}
================================================
FILE: kernel/resource.c
================================================
#include <piko/sys/resource.h>
// clang-format off
static struct rlimit rlimits[] = {
{ .rlim_cur = 1024, .rlim_max = 1024 } /* RLIMIT_STACK */
};
int sys_getrlimit(int resource, struct rlimit *rlim)
{
rlim->rlim_cur = rlimits[resource].rlim_cur;
rlim->rlim_max = rlimits[resource].rlim_max;
return 0;
}
int sys_setrlimit(int resource, const struct rlimit *rlim)
{
rlimits[resource].rlim_cur = rlim->rlim_cur;
rlimits[resource].rlim_max = rlim->rlim_max;
return 0;
}
================================================
FILE: kernel/sched/bitmap.c
================================================
#include <kernel/bitops.h>
#include <kernel/sched.h>
#include <kernel/thread.h>
#include "linux/list.h"
#include "kernel.h"
#include "kernel/bitmap.h"
extern struct thread_info *thread_idle;
static struct bitmap_struct _active, _expire;
static struct {
struct bitmap_struct *active;
struct bitmap_struct *expire;
} sched_struct = {
.active = &_active,
.expire = &_expire,
};
static int sched_bitmap_init(void)
{
INIT_BITMAP(sched_struct.active);
INIT_BITMAP(sched_struct.expire);
return 0;
}
static struct thread_info *find_next_thread(struct bitmap_struct *bm)
{
int max_prio = find_first_bit(&bm->map, 32);
/* all runqueues are empty, return the idle_thread */
if (max_prio == 32)
return thread_idle; // idle_thread
return bitmap_first_entry(bm, max_prio, struct thread_info, ti_q);
}
static int thread_enqueue(struct thread_info *thread, struct bitmap_struct *bm)
{
bitmap_enqueue(&thread->ti_q, thread->ti_priority, bm);
return 0;
}
static int sched_bitmap_enqueue(struct thread_info *thread)
{
return thread_enqueue(thread, sched_struct.active);
}
static int thread_dequeue(struct thread_info *thread, struct bitmap_struct *bm)
{
CURRENT_THREAD_INFO(current);
/* active thread is not in the runqueue */
if (thread == current)
return -1;
bitmap_queue_del(&thread->ti_q, thread->ti_priority, bm);
return 0;
}
static int sched_bitmap_dequeue(struct thread_info *thread)
{
int state = thread->ti_state;
if (state == THREAD_STATE_ACTIVED)
return thread_dequeue(thread, sched_struct.active);
else if (state == THREAD_STATE_EXPIRED)
return thread_dequeue(thread, sched_struct.expire);
else
return -1;
}
static int sched_bitmap_elect(int flags)
{
CURRENT_THREAD_INFO(current);
struct thread_info *next;
next = find_next_thread(sched_struct.active);
// check each thread timeslice in active queue
// if necessary swap active and expire queue
if (next == thread_idle &&
find_next_thread(sched_struct.expire) != thread_idle) {
SWAP(sched_struct.active, sched_struct.expire);
swap_sched_state_map();
next = find_next_thread(sched_struct.active);
}
if (next != thread_idle) { // idle_thread
list_del(&next->ti_q);
if (list_empty(&sched_struct.active->queue[next->ti_priority]))
bitmap_clear_bit(&sched_struct.active->map, next->ti_priority);
}
if (flags == SCHED_OPT_RESTORE_ONLY)
thread_restore(next); // switch_to_restore_only
else {
if (flags == SCHED_OPT_TICK && current != thread_idle) {
thread_enqueue(current, sched_struct.expire);
current->ti_state = THREAD_STATE_EXPIRED;
}
if (next == current)
return 0;
switch_to(next, current);
}
return 0;
}
// clang-format off
static struct sched sched_bitmap = {
.class_type = SCHED_CLASS_BITMAP,
.init = sched_bitmap_init,
.enqueue = sched_bitmap_enqueue,
.dequeue = sched_bitmap_dequeue,
.elect = sched_bitmap_elect,
};
// clang-format on
HOOK_SCHED_CLASS(bitmap, &sched_bitmap)
================================================
FILE: kernel/sched/rr.c
================================================
#include <kernel/sched.h>
#include <kernel/thread.h>
#include "linux/list.h"
#include "kernel.h"
static LIST_HEAD(rr_runq);
extern struct thread_info *thread_idle;
int sched_rr_init(void)
{
return 0;
}
static struct thread_info *find_next_thread(struct thread_info *thread)
{
if (list_is_last(&thread->ti_q, &rr_runq))
return list_first_entry(&rr_runq, struct thread_info, ti_q);
return list_next_entry(thread, ti_q);
}
int sched_rr_enqueue(struct thread_info *thread)
{
list_add(&thread->ti_q, &rr_runq);
return 0;
}
int sched_rr_dequeue(struct thread_info *thread)
{
CURRENT_THREAD_INFO(current);
if (current == thread) {
struct thread_info *next = thread_idle;
if (!list_is_singular(&rr_runq)) {
next = find_next_thread(current);
}
list_del(&thread->ti_q);
thread_restore(next); // FIXME: rename to switch_to_no_save
} else {
list_del(&thread->ti_q);
}
return 0;
}
/* This function is used when the runqueue has been modified externally, and it
is not possible to fetch the next thread. */
static int sched_rr_elect_reset(void)
{
CURRENT_THREAD_INFO(current);
struct thread_info *next = thread_idle;
if (!list_empty(&rr_runq))
next = list_first_entry(&rr_runq, struct thread_info, ti_q);
switch_to(next, current);
return 0;
}
int sched_rr_elect(int switch_type)
{
CURRENT_THREAD_INFO(current);
struct thread_info *next;
if (switch_type & SCHED_OPT_RESET)
return sched_rr_elect_reset();
if (list_empty(&rr_runq)) {
// go to thread idle.
next = thread_idle;
} else {
next = find_next_thread(current);
}
/* keep running the previous thread */
if (next == current)
return -1;
/* Leave _current_ thread for now. The _current_ thread will be elected
again after _next_ thread has run. Inform the caller function (in
_current_ context) that the thread gently gave way. */
switch_to(next, current);
return 0;
}
// clang-format off
static struct sched sched_rr = {
.class_type = SCHED_CLASS_RR,
.init = sched_rr_init,
.enqueue = sched_rr_enqueue,
.dequeue = sched_rr_dequeue,
.elect = sched_rr_elect,
};
// clang-format on
HOOK_SCHED_CLASS(RR, &sched_rr)
================================================
FILE: kernel/sched.c
================================================
#include <kernel/sched.h>
#include <kernel/thread.h>
extern unsigned long __sched_classes_start__;
extern unsigned long __sched_classes_end__;
/* static vars to repesent sched classes list */
static struct sched **sched_classes =
(struct sched **) &__sched_classes_start__;
static struct sched **sched_classes_end =
(struct sched **) &__sched_classes_end__;
static struct sched *sched;
int sched_init()
{
int ret = 0;
/* Initialize each scheduler class by traversing hooks */
for (struct sched **c = sched_classes;
c < sched_classes_end; c++) {
struct sched *class = *c;
ret |= class->init();
}
return ret;
}
int sched_select(sched_class_t sched_type)
{
int ret = -1;
struct sched *class = NULL;
/* Examine specified sched class in hooks or not */
for (struct sched **c = sched_classes;
c < sched_classes_end; c++)
if (sched_type == (*c)->class_type)
class = *c;
if (class) {
sched = class;
ret = 0;
}
return ret;
}
int sched_enqueue(struct thread_info *thread)
{
thread->ti_state = THREAD_STATE_ACTIVED;
return sched->enqueue(thread);
}
int sched_dequeue(struct thread_info *thread)
{
return sched->dequeue(thread);
}
int sched_elect(int flags)
{
int r;
CURRENT_THREAD_INFO(cur_thread);
KERNEL_STACK_CHECKING;
r = sched->elect(flags);
cur_thread->ti_state = THREAD_STATE_RUNNING;
return r;
}
================================================
FILE: kernel/signal.c
================================================
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <arch/v7m-helper.h>
#include <kernel/bitops.h>
#include <kernel/errno-base.h>
#include <kernel/signal.h>
#include <kernel/task.h>
#include <kernel/thread.h>
#include "kernel.h"
#include "platform.h"
extern void return_from_sighandler(void);
extern void return_from_sigaction(void);
static void *v7m_alloca_thread_context(struct thread_info *tip, size_t len)
{
tip->ti_mach.mi_psp -= len;
return (void *) tip->ti_mach.mi_psp;
}
static void stage_sighandler(struct sigaction *sigaction)
{
CURRENT_THREAD_INFO(curr_thread);
struct thread_context_regs *ctx;
/* update current thread SP_process */
curr_thread->ti_mach.mi_psp = __get_PSP();
/* this is the exception stacked-context */
ctx = (struct thread_context_regs *) curr_thread->ti_mach.mi_psp;
/* return value of syscall, cannot fail after this point */
ctx->r0_r3__r12[0] = 0;
/* the sigaction context will be poped by cpu on exception return */
v7m_alloca_thread_context(curr_thread, sizeof(struct thread_context_regs));
/* build the sigaction trampoline */
ctx = (struct thread_context_regs *) curr_thread->ti_mach.mi_psp;
/* #ifdef SECURE_KERNEL */
ctx->r0_r3__r12[1] = 0;
ctx->r0_r3__r12[2] = 0;
ctx->r0_r3__r12[3] = 0;
ctx->r0_r3__r12[4] = 0;
/* #endif */
ctx->lr = (u32) v7m_set_thumb_bit(return_from_sighandler);
ctx->ret_addr = (u32) v7m_clear_thumb_bit(sigaction->sa_handler);
ctx->xpsr = xPSR_T_Msk;
/* update current thread SP_process */
__set_PSP(curr_thread->ti_mach.mi_psp);
}
static void stage_sigaction(const struct sigaction *sigaction,
int sig,
union sigval value)
{
CURRENT_THREAD_INFO(curr_thread);
struct thread_context_regs *ctx;
/* update current thread SP_process */
curr_thread->ti_mach.mi_psp = __get_PSP();
/* this is the exception stacked-context */
ctx = (struct thread_context_regs *) curr_thread->ti_mach.mi_psp;
/* return value of syscall, cannot fail after this point */
ctx->r0_r3__r12[0] = 0;
/* The siginfo_t struct is allocated on thread's stack; that memory
* will be reclaimed during return_from_sigaction. */
siginfo_t *siginfo_ptr =
v7m_alloca_thread_context(curr_thread, sizeof(siginfo_t));
siginfo_ptr->si_signo = sig;
siginfo_ptr->si_value = value;
siginfo_ptr->si_pid = curr_thread->ti_id;
/* the sigaction context will be poped by cpu on exception return */
v7m_alloca_thread_context(curr_thread, sizeof(struct thread_context_regs));
/* build a sigaction trampoline */
ctx = (struct thread_context_regs *) curr_thread->ti_mach.mi_psp;
ctx->r0_r3__r12[1] = (u32) siginfo_ptr;
ctx->r0_r3__r12[2] = 0; /* ucontext_t *, but commonly unused */
ctx->r0_r3__r12[3] = 0;
ctx->r0_r3__r12[4] = 0;
ctx->lr = (u32) v7m_set_thumb_bit(return_from_sigaction);
ctx->ret_addr = (u32) v7m_clear_thumb_bit(sigaction->sa_sigaction);
ctx->xpsr = xPSR_T_Msk;
/* update current thread SP_process */
__set_PSP(curr_thread->ti_mach.mi_psp);
}
void do_sigevent(const struct sigevent *sigevent, struct thread_info *thread)
{
CURRENT_THREAD_INFO(curr_thread);
struct thread_context_regs *ctx;
// if (sigevent->sigev_notify == SIGEV_THREAD) {
/* update current thread SP_process */
if (thread == curr_thread)
thread->ti_mach.mi_psp = __get_PSP();
/* the sigevent context will be poped by cpu on exception return */
v7m_alloca_thread_context(thread, sizeof(struct thread_context_regs));
/* build a sigevent trampoline */
ctx = (struct thread_context_regs *) thread->ti_mach.mi_psp;
ctx->r0_r3__r12[0] = sigevent->sigev_value.sival_int;
ctx->r0_r3__r12[1] = 0;
ctx->r0_r3__r12[2] = 0;
ctx->r0_r3__r12[3] = 0;
ctx->r0_r3__r12[4] = 0;
ctx->lr = (u32) v7m_set_thumb_bit(return_from_sighandler);
ctx->ret_addr = (u32) v7m_clear_thumb_bit(sigevent->sigev_notify_function);
ctx->xpsr = xPSR_T_Msk;
/* update current thread SP_process */
if (thread == curr_thread)
__set_PSP(thread->ti_mach.mi_psp);
}
static struct sigaction *find_sigaction_by_sig(__unused pid_t pid, int sig)
{
/* FIXME: consider multi-tasking environment */
struct signal_info *signal;
CURRENT_TASK_INFO(curr_task);
list_for_each_entry(signal, &curr_task->signal_head, list)
{
if (signal->signo == sig)
return &signal->act_storage;
}
return NULL;
}
int sys_sigaction(int signo,
const struct sigaction *restrict a
gitextract_0chc9o9f/
├── .clang-format
├── .gitignore
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── arch/
│ ├── v7m-entry.S
│ ├── v7m-faults.c
│ ├── v7m-head.S
│ └── v7m-svcall.S
├── docs/
│ ├── Makefile
│ ├── api.rst
│ ├── build.rst
│ ├── conf.py
│ ├── contribute.rst
│ ├── debugging.rst
│ ├── emulate.rst
│ ├── index.rst
│ ├── kernel.rst
│ ├── make.bat
│ ├── posix/
│ │ ├── parse.py
│ │ ├── posix_opt/
│ │ │ ├── 01._POSIX_CLOCK_SELECTION
│ │ │ ├── 02._POSIX_FSYNC
│ │ │ ├── 03._POSIX_MEMLOCK
│ │ │ ├── 04.POSIX_MEMLOCK_RANGE
│ │ │ ├── 05._POSIX_MONOTONIC_CLOCK
│ │ │ ├── 06._POSIX_NO_TRUNC
│ │ │ ├── 07._POSIX_REALTIME_SIGNALS
│ │ │ ├── 08._POSIX_SEMAPHORES
│ │ │ ├── 09._POSIX_SHARED_MEMORY_OBJECTS
│ │ │ ├── 10._POSIX_SYNCHRONIZED_IO
│ │ │ ├── 11._POSIX_THREAD_ATTR_STACKADDR
│ │ │ ├── 12._POSIX_THREAD_ATTR_STACKSIZE
│ │ │ ├── 13._POSIX_THREAD_CPUTIME
│ │ │ ├── 14._POSIX_THREAD_PRIO_INHERIT
│ │ │ ├── 15._POSIX_THREAD_PRIO_PROTECT
│ │ │ ├── 16._POSIX_THREAD_PRIORITY_SCHEDULING
│ │ │ ├── 17._POSIX_THREAD_SPORADIC_SERVER
│ │ │ └── 18._POSIX_TIMERS
│ │ └── posix_req/
│ │ ├── 01.POSIX_C_LANG_SUPPORT
│ │ ├── 02.POSIX_DEVICE_IO
│ │ ├── 03.POSIX_FILE_LOCKING
│ │ ├── 04.POSIX_SIGNALS
│ │ ├── 05.POSIX_SINGLE_PROCESS
│ │ ├── 06.POSIX_THREADS_BASE
│ │ ├── 07.XSI_THREAD_MUTEX_EXT
│ │ └── 08.XSI_THREADS_EXT
│ └── test.rst
├── drivers/
│ ├── char/
│ │ ├── mem.c
│ │ └── random.c
│ ├── mtd/
│ │ ├── mtd.h
│ │ ├── mtdchar.c
│ │ ├── mtdcore.c
│ │ └── mtdram.c
│ ├── serial/
│ │ ├── serialchar.c
│ │ ├── serialcore.c
│ │ ├── stm32-uart.c
│ │ └── stm32-uart.h
│ └── timer/
│ ├── systick.c
│ └── timercore.c
├── fs/
│ ├── proc.c
│ ├── romfs.c
│ └── tmpfs.c
├── include/
│ ├── arch/
│ │ ├── semihosting.h
│ │ └── v7m-helper.h
│ ├── fs/
│ │ └── romfs.h
│ ├── kernel/
│ │ ├── bitmap.h
│ │ ├── bitops.h
│ │ ├── cbuf.h
│ │ ├── compiler.h
│ │ ├── cond.h
│ │ ├── errno-base.h
│ │ ├── faults.h
│ │ ├── fs.h
│ │ ├── hash.h
│ │ ├── irq.h
│ │ ├── kernel.h
│ │ ├── linkage.h
│ │ ├── log2.h
│ │ ├── mm/
│ │ │ ├── page.h
│ │ │ └── slab.h
│ │ ├── mutex.h
│ │ ├── sched.h
│ │ ├── serial.h
│ │ ├── signal.h
│ │ ├── softirq.h
│ │ ├── task.h
│ │ ├── thread.h
│ │ ├── time.h
│ │ └── types.h
│ ├── libc/
│ │ ├── pthread.h
│ │ ├── ucontext.h
│ │ └── utils.h
│ ├── linux/
│ │ ├── compiler.h
│ │ ├── list.h
│ │ ├── poison.h
│ │ ├── stddef.h
│ │ └── types.h
│ ├── piko/
│ │ ├── arpa/
│ │ │ └── inet.h
│ │ ├── dirent.h
│ │ ├── signal.h
│ │ └── sys/
│ │ ├── mman.h
│ │ ├── mount.h
│ │ └── resource.h
│ ├── platform/
│ │ └── compiler.h
│ └── version.template.h
├── kernel/
│ ├── cond.c
│ ├── config.c
│ ├── faults.c
│ ├── fs/
│ │ ├── fs.c
│ │ ├── readdir.c
│ │ └── vfs.c
│ ├── irq.c
│ ├── main.c
│ ├── mm/
│ │ ├── mm.c
│ │ ├── page.c
│ │ └── slab.c
│ ├── mutex.c
│ ├── printk.c
│ ├── resource.c
│ ├── sched/
│ │ ├── bitmap.c
│ │ └── rr.c
│ ├── sched.c
│ ├── signal.c
│ ├── softirq.c
│ ├── task.c
│ ├── thread.c
│ └── time.c
├── libc/
│ ├── fcntl.c
│ ├── filesystem.c
│ ├── piko/
│ │ ├── mman.c
│ │ ├── stubs.c
│ │ ├── syscalls.S
│ │ └── syscalls.h
│ ├── pthread.c
│ ├── signal.c
│ ├── stdio.c
│ ├── stdlib.c
│ ├── time.c
│ ├── ucontext.c
│ ├── unistd.c
│ ├── utils.c
│ └── v7m-pthread.S
├── mk/
│ ├── cmsis.mk
│ ├── flags.mk
│ └── rules.mk
├── piko.lds.S
├── platform/
│ ├── f429disco/
│ │ ├── Makefile
│ │ ├── build.mk
│ │ ├── halt.c
│ │ ├── init.c
│ │ ├── platform.h
│ │ └── uart.c
│ └── stm32p103/
│ ├── Makefile
│ ├── build.mk
│ ├── halt.c
│ ├── init.c
│ ├── platform.h
│ └── uart.c
├── scripts/
│ ├── gen-proc-version.py
│ ├── gen-syscalls.py
│ └── rstlint.py
├── tests/
│ ├── Makefile
│ ├── __init__.py
│ ├── __main__.py
│ ├── bitops_1/
│ │ └── main.c
│ ├── cond_1/
│ │ └── main.c
│ ├── cond_2/
│ │ └── main.c
│ ├── cond_3/
│ │ └── main.c
│ ├── fs_1/
│ │ └── main.c
│ ├── fs_2/
│ │ └── main.c
│ ├── fs_3/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── fs_4/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── fs_5/
│ │ └── main.c
│ ├── fs_6/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── fs_7/
│ │ ├── data/
│ │ │ └── .ssh/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── getpid_1/
│ │ └── main.c
│ ├── itoa_1/
│ │ └── main.c
│ ├── lib/
│ │ └── unit.h
│ ├── malloc_1/
│ │ └── main.c
│ ├── mm_1/
│ │ └── main.c
│ ├── mm_2/
│ │ └── main.c
│ ├── mmap_1/
│ │ └── main.c
│ ├── mmap_2/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── msleep_1/
│ │ └── main.c
│ ├── msleep_2/
│ │ └── main.c
│ ├── mtdram_1/
│ │ └── main.c
│ ├── mutex_1/
│ │ └── main.c
│ ├── mutex_2/
│ │ └── main.c
│ ├── mutex_3/
│ │ └── main.c
│ ├── mutex_4/
│ │ └── main.c
│ ├── mutex_5/
│ │ └── main.c
│ ├── page_3/
│ │ └── main.c
│ ├── raise_1/
│ │ └── main.c
│ ├── raise_2/
│ │ └── main.c
│ ├── raise_3/
│ │ └── main.c
│ ├── readdir_1/
│ │ └── main.c
│ ├── runner.py
│ ├── slab_1/
│ │ └── main.c
│ ├── slab_2/
│ │ └── main.c
│ ├── softirq_1/
│ │ └── main.c
│ ├── softirq_2/
│ │ └── main.c
│ ├── softirq_3/
│ │ └── main.c
│ ├── sprintf_1/
│ │ └── main.c
│ ├── stat_1/
│ │ ├── data/
│ │ │ ├── id_rsa
│ │ │ └── id_rsa.pub
│ │ └── main.c
│ ├── syscall_1/
│ │ ├── main.c
│ │ └── trampoline.S
│ ├── sysconf_1/
│ │ └── main.c
│ ├── test_1/
│ │ └── main.c
│ ├── test_2/
│ │ └── main.c
│ ├── thread_1/
│ │ └── main.c
│ ├── thread_2/
│ │ └── main.c
│ ├── thread_3/
│ │ └── main.c
│ ├── thread_4/
│ │ └── main.c
│ ├── thread_5/
│ │ └── main.c
│ ├── thread_6/
│ │ └── main.c
│ ├── timer_1/
│ │ └── main.c
│ ├── timer_2/
│ │ └── main.c
│ ├── timer_3/
│ │ └── main.c
│ ├── timer_4/
│ │ └── main.c
│ ├── timer_5/
│ │ └── main.c
│ └── ucontext_1/
│ └── main.c
└── user/
├── cat.c
├── echo.c
├── exit.c
├── halt.c
├── ls.c
├── reboot.c
├── sh.c
└── sh.h
SYMBOL INDEX (808 symbols across 149 files)
FILE: arch/v7m-faults.c
function dump_frame (line 13) | void dump_frame(struct kernel_context_regs *noscratch,
function usagefault (line 32) | void usagefault(struct kernel_context_regs *noscratch,
function busfault (line 60) | void busfault(struct kernel_context_regs *noscratch,
function memmanage (line 69) | void memmanage(struct kernel_context_regs *noscratch,
FILE: docs/posix/parse.py
function read_file (line 16) | def read_file(path):
function build_cscope (line 21) | def build_cscope():
function cscope_search (line 29) | def cscope_search(name):
function parse_path (line 33) | def parse_path(s):
function generate_table (line 37) | def generate_table(name):
FILE: drivers/char/mem.c
function mem_open (line 6) | static int mem_open(__unused struct inode *inode, __unused struct file *...
function write_mem (line 11) | static ssize_t write_mem(__unused struct file *file,
function read_mem (line 21) | static ssize_t read_mem(__unused struct file *file,
function write_null (line 31) | static ssize_t write_null(__unused struct file *file,
function read_null (line 39) | static ssize_t read_null(__unused struct file *file,
function read_zero (line 47) | static ssize_t read_zero(__unused struct file *file,
type file_operations (line 57) | struct file_operations
type file_operations (line 63) | struct file_operations
type file_operations (line 69) | struct file_operations
type file_operations (line 75) | struct file_operations
type inode_operations (line 76) | struct inode_operations
type inode (line 78) | struct inode
function memdev_init (line 105) | void memdev_init(void)
FILE: drivers/char/random.c
type u64 (line 8) | typedef unsigned long long u64;
function u64 (line 11) | static u64 next(void)
function open_random (line 34) | static int open_random(__unused struct inode *inode, __unused struct fil...
function read_random (line 39) | static ssize_t read_random(__unused struct file *file,
type file_operations (line 61) | struct file_operations
FILE: drivers/mtd/mtd.h
type erase_info (line 19) | struct erase_info {
type mtd_info (line 34) | struct mtd_info {
type mtd_info (line 65) | struct mtd_info
type erase_info (line 65) | struct erase_info
type mtd_info (line 66) | struct mtd_info
type mtd_info (line 71) | struct mtd_info
type mtd_info (line 76) | struct mtd_info
type erase_info (line 82) | struct erase_info
type mtd_info (line 84) | struct mtd_info
FILE: drivers/mtd/mtdchar.c
function mtdchar_open (line 7) | static int mtdchar_open(struct inode *inode, struct file *file)
function mtdchar_read (line 14) | static ssize_t mtdchar_read(struct file *file,
function mtdchar_write (line 28) | static ssize_t mtdchar_write(struct file *file,
type file_operations (line 43) | struct file_operations
FILE: drivers/mtd/mtdcore.c
function mtd_erase_callback (line 4) | void mtd_erase_callback(struct erase_info *instr)
function mtd_erase (line 10) | int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
function mtd_point (line 26) | int mtd_point(struct mtd_info *mtd,
function mtd_read (line 45) | int mtd_read(struct mtd_info *mtd,
function mtd_write (line 61) | int mtd_write(struct mtd_info *mtd,
FILE: drivers/mtd/mtdram.c
function mtdram_erase (line 9) | static int mtdram_erase(struct mtd_info *mtd, struct erase_info *instr)
function mtdram_point (line 18) | static int mtdram_point(struct mtd_info *mtd,
function mtdram_unpoint (line 30) | static int mtdram_unpoint(struct mtd_info *mtd, off_t from, size_t len)
function mtdram_write (line 37) | int mtdram_write(struct mtd_info *mtd,
function mtdram_read (line 49) | int mtdram_read(struct mtd_info *mtd,
function mtdram_init_device (line 61) | int mtdram_init_device(struct mtd_info *mtd,
type mtd_info (line 80) | struct mtd_info
type file_operations (line 85) | struct file_operations
type inode (line 87) | struct inode
function mtdram_init (line 92) | void mtdram_init(void)
FILE: drivers/serial/serialchar.c
function serialchar_callback (line 7) | static void serialchar_callback(struct serial_info *serial)
function serialchar_open (line 12) | static int serialchar_open(struct inode *inode, struct file *file)
function serialchar_read (line 23) | static ssize_t serialchar_read(struct file *file,
function serialchar_write (line 44) | static ssize_t serialchar_write(struct file *file,
type file_operations (line 54) | struct file_operations
FILE: drivers/serial/serialcore.c
function serial_init (line 5) | void serial_init(void)
function serial_activity_callback (line 15) | void serial_activity_callback(struct serial_info *serial)
function serial_getc (line 21) | int serial_getc(struct serial_info *serial, char *c)
function serial_gets (line 26) | int serial_gets(struct serial_info *serial,
function serial_putc (line 34) | int serial_putc(struct serial_info *serial, char c)
function serial_puts (line 39) | int serial_puts(struct serial_info *serial,
FILE: drivers/serial/stm32-uart.c
type cbuf_info (line 13) | struct cbuf_info
function stm32_getc (line 16) | static int stm32_getc(struct serial_info *serial, char *c)
function stm32_putc (line 24) | static int stm32_putc(struct serial_info *serial, char c)
function stm32_puts (line 38) | static int stm32_puts(struct serial_info *serial,
type serial_ops (line 51) | struct serial_ops
type serial_info (line 57) | struct serial_info
function stm32_uartx_isr (line 62) | static void stm32_uartx_isr(void)
type file_operations (line 72) | struct file_operations
type inode (line 74) | struct inode
function stm32_serial_init (line 79) | static int stm32_serial_init(void)
FILE: drivers/serial/stm32-uart.h
type stm32_uart_port (line 6) | struct stm32_uart_port {
FILE: drivers/timer/systick.c
type systick_timer (line 18) | struct systick_timer {
function systick_timer_alloc (line 29) | static int systick_timer_alloc(struct timer_info *timer)
function systick_timer_set (line 44) | static int systick_timer_set(struct timer_info *timer,
function systick_timer_get (line 61) | static int systick_timer_get(struct timer_info *timer,
function systick_timer_free (line 73) | static int systick_timer_free(struct timer_info *timer)
function systick_bh (line 80) | static void systick_bh(void)
function systick (line 100) | void systick(void)
type timer_operations (line 113) | struct timer_operations
function pendsv (line 120) | void __attribute__((naked)) pendsv(void)
FILE: drivers/timer/timercore.c
type timer_operations (line 8) | struct timer_operations
function config_timer_operations (line 10) | void config_timer_operations(struct timer_operations *tops)
type timer_info (line 15) | struct timer_info
type timer_info (line 17) | struct timer_info
type timer_info (line 19) | struct timer_info
function timer_set (line 33) | int timer_set(struct timer_info *timer, const struct timespec *value)
function timer_get (line 38) | int timer_get(struct timer_info *timer, struct itimerspec *value)
function timer_free (line 43) | int timer_free(struct timer_info *timer)
function timer_expire_callback (line 55) | void timer_expire_callback(struct timer_info *timer)
FILE: fs/proc.c
function open_version (line 13) | static int open_version(__unused struct inode *inode,
function read_version (line 19) | static ssize_t read_version(__unused struct file *file,
function open_meminfo (line 31) | static int open_meminfo(__unused struct inode *inode,
function read_meminfo (line 37) | static ssize_t read_meminfo(__unused struct file *file,
type file_operations (line 47) | struct file_operations
type file_operations (line 52) | struct file_operations
type inode_operations (line 57) | struct inode_operations
type inode (line 59) | struct inode
function proc_init (line 74) | void proc_init(void)
FILE: fs/romfs.c
type inode_operations (line 19) | struct inode_operations
type file_operations (line 20) | struct file_operations
type dentry_operations (line 21) | struct dentry_operations
function off_t (line 30) | static off_t offsetof_device_inode(struct romfs_inode *rinode,
function off_t (line 36) | static off_t offsetof_first_device_inode(struct romfs_superblock *super)
function romfs_mount (line 45) | int romfs_mount(const char *source,
type inode (line 88) | struct inode
type romfs_inode (line 88) | struct romfs_inode
type super_block (line 88) | struct super_block
type inode (line 90) | struct inode
type inode (line 93) | struct inode
type dentry (line 135) | struct dentry
type inode (line 135) | struct inode
type dentry (line 135) | struct dentry
type romfs_superblock (line 138) | struct romfs_superblock
type romfs_inode (line 139) | struct romfs_inode
type inode (line 151) | struct inode
function romfs_open (line 171) | int romfs_open(struct inode *inode, struct file *file)
function romfs_read (line 178) | ssize_t romfs_read(struct file *file, char *buf, size_t count, off_t off...
function romfs_mmap (line 198) | int romfs_mmap(struct file *file, off_t offset, void **addr)
function romfs_delete (line 214) | int romfs_delete(struct dentry *dentry)
type inode_operations (line 226) | struct inode_operations
type file_operations (line 230) | struct file_operations
type dentry_operations (line 236) | struct dentry_operations
FILE: fs/tmpfs.c
type dirlist (line 10) | struct dirlist {
function tmpfs_mkdir (line 16) | int tmpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
function tmpfs_link (line 27) | int tmpfs_link(__unused struct dentry *old_dentry,
function tmpfs_iterate (line 44) | int tmpfs_iterate(struct file *file, struct dir_context *ctx)
type dentry_operations (line 76) | struct dentry_operations
type dentry (line 78) | struct dentry
type inode (line 78) | struct inode
type dentry (line 78) | struct dentry
type list_head (line 80) | struct list_head
type list_head (line 80) | struct list_head
type dirlist (line 81) | struct dirlist
function tmpfs_delete (line 96) | int tmpfs_delete(struct dentry *dentry)
type inode_operations (line 103) | struct inode_operations
type file_operations (line 108) | struct file_operations
type dentry_operations (line 112) | struct dentry_operations
type inode (line 116) | struct inode
type list_head (line 124) | struct list_head
type list_head (line 132) | struct list_head
type list_head (line 140) | struct list_head
type inode (line 144) | struct inode
type inode (line 149) | struct inode
type inode (line 154) | struct inode
type dentry (line 159) | struct dentry
type dentry (line 161) | struct dentry
type inode (line 171) | struct inode
type inode (line 171) | struct inode
function tmpfs_init (line 181) | void tmpfs_init(void)
FILE: include/fs/romfs.h
type romfs_superblock (line 19) | struct romfs_superblock {
type romfs_inode (line 26) | struct romfs_inode {
FILE: include/kernel/bitmap.h
type bitmap_struct (line 7) | struct bitmap_struct {
function INIT_BITMAP (line 12) | static inline void INIT_BITMAP(struct bitmap_struct *bm)
function bitmap_queue_add (line 19) | static inline void bitmap_queue_add(struct list_head *new,
function bitmap_queue_add_first (line 27) | static inline void bitmap_queue_add_first(struct list_head *new,
function bitmap_enqueue (line 35) | static inline void bitmap_enqueue(struct list_head *new,
function bitmap_enqueue_first (line 42) | static inline void bitmap_enqueue_first(struct list_head *new,
function bitmap_empty (line 49) | static inline int bitmap_empty(const struct bitmap_struct *bm)
function bitmap_queue_empty (line 54) | static inline int bitmap_queue_empty(struct bitmap_struct *bm,
function bitmap_first_bit (line 60) | static inline int bitmap_first_bit(const struct bitmap_struct *bm)
function bitmap_queue_del (line 65) | static inline void bitmap_queue_del(struct list_head *queue,
type list_head (line 74) | struct list_head
type bitmap_struct (line 74) | struct bitmap_struct
type list_head (line 77) | struct list_head
type list_head (line 83) | struct list_head
type bitmap_struct (line 83) | struct bitmap_struct
type list_head (line 86) | struct list_head
FILE: include/kernel/bitops.h
function flsl (line 12) | static inline unsigned long flsl(unsigned long word)
function clear_bit (line 17) | static inline void clear_bit(unsigned long bit, unsigned long *word)
function set_bit (line 22) | static inline void set_bit(unsigned long bit, unsigned long *word)
function bitmap_set_bit (line 27) | static inline void bitmap_set_bit(unsigned long *map, unsigned long bit)
function bitmap_clear_bit (line 32) | static inline void bitmap_clear_bit(unsigned long *map, unsigned long bit)
function bitmap_get_bit (line 37) | static inline unsigned long bitmap_get_bit(unsigned long *map,
function find_first_bit (line 43) | static inline unsigned long find_first_bit(const unsigned long *addr,
function find_first_zero_bit (line 54) | static inline unsigned long find_first_zero_bit(const unsigned long *addr,
FILE: include/kernel/cbuf.h
type cbuf_info (line 6) | struct cbuf_info {
function cbuf_init (line 13) | static inline void cbuf_init(struct cbuf_info *cbuf, void *buf, size_t len)
function cbuf_getc (line 21) | static inline int cbuf_getc(struct cbuf_info *cbuf, char *c)
function cbuf_putc (line 31) | static inline int cbuf_putc(struct cbuf_info *cbuf, char c)
FILE: include/kernel/faults.h
type kernel_context_regs (line 11) | struct kernel_context_regs
type thread_context_regs (line 12) | struct thread_context_regs
FILE: include/kernel/fs.h
type dentry (line 20) | struct dentry
type inode (line 21) | struct inode
type super_block (line 23) | struct super_block {
type inode_operations (line 32) | struct inode_operations
type file_operations (line 33) | struct file_operations
type inode (line 35) | struct inode {
type inode_operations (line 49) | struct inode_operations {
type file (line 60) | struct file {
type dir_context (line 67) | struct dir_context
type file_operations (line 69) | struct file_operations {
type dentry (line 87) | struct dentry {
type dentry_operations (line 98) | struct dentry_operations {
type dir_context (line 105) | struct dir_context
type dir_context (line 112) | struct dir_context {
type piko_dirent (line 117) | struct piko_dirent
type readdir_callback (line 119) | struct readdir_callback {
type piko_dirent (line 125) | struct piko_dirent {
function dir_emit (line 130) | static inline int dir_emit(struct dir_context *ctx,
function dir_emit_dot (line 139) | static inline int dir_emit_dot(struct file *file, struct dir_context *ctx)
function dir_emit_dotdot (line 144) | static inline int dir_emit_dotdot(struct file *file, struct dir_context ...
type file (line 152) | struct file
type dir_context (line 152) | struct dir_context
type dentry (line 153) | struct dentry
type inode (line 153) | struct inode
type dentry (line 153) | struct dentry
type dentry (line 154) | struct dentry
type inode (line 155) | struct inode
type dentry (line 156) | struct dentry
type dentry (line 157) | struct dentry
type dentry (line 158) | struct dentry
type file (line 159) | struct file
type DIR (line 163) | typedef void DIR;
type dirent (line 166) | struct dirent
type dirent (line 166) | struct dirent
type inode (line 175) | struct inode
type inode (line 176) | struct inode
type inode (line 177) | struct inode
type dentry (line 178) | struct dentry
type file (line 179) | struct file
type inode (line 180) | struct inode
type inode (line 180) | struct inode
type inode (line 181) | struct inode
FILE: include/kernel/hash.h
function hash_djb2 (line 6) | static inline unsigned long hash_djb2(unsigned char *str, size_t len)
FILE: include/kernel/irq.h
type irq_data (line 27) | struct irq_data {
type irqaction (line 31) | struct irqaction
type irq_desc (line 40) | struct irq_desc {
type irqaction (line 52) | struct irqaction {
FILE: include/kernel/log2.h
function __ilog2 (line 51) | static inline unsigned long __ilog2(unsigned long x)
function __ilog2_NaN (line 56) | static inline __attribute__((noreturn)) unsigned long __ilog2_NaN(void)
FILE: include/kernel/mm/slab.h
type kmem_cache (line 19) | struct kmem_cache {
type slab (line 32) | struct slab {
type kmem_cache (line 43) | struct kmem_cache
type kmem_cache (line 48) | struct kmem_cache
type kmem_cache (line 49) | struct kmem_cache
FILE: include/kernel/mutex.h
type atomic_s32 (line 4) | typedef _Atomic int atomic_s32;
type kernel_mutex_t (line 6) | typedef struct {
FILE: include/kernel/sched.h
type thread_info (line 6) | struct thread_info
type sched_class_t (line 14) | typedef int sched_class_t;
type sched (line 27) | struct sched {
type thread_info (line 37) | struct thread_info
type thread_info (line 38) | struct thread_info
FILE: include/kernel/serial.h
type serial_ops (line 11) | struct serial_ops
type device (line 12) | struct device
type thread_info (line 13) | struct thread_info
type serial_info (line 15) | struct serial_info {
type serial_ops (line 26) | struct serial_ops {
type serial_hook (line 44) | struct serial_hook {
type serial_info (line 61) | struct serial_info
type serial_info (line 62) | struct serial_info
type serial_info (line 66) | struct serial_info
type serial_info (line 67) | struct serial_info
type serial_info (line 71) | struct serial_info
FILE: include/kernel/signal.h
type signal_info (line 14) | struct signal_info {
type sigevent (line 20) | struct sigevent
type thread_info (line 20) | struct thread_info
FILE: include/kernel/softirq.h
type softirq_action (line 21) | struct softirq_action {
type tasklet_struct (line 27) | struct tasklet_struct {
type softirq_action (line 45) | struct softirq_action
type tasklet_struct (line 48) | struct tasklet_struct
type tasklet_struct (line 49) | struct tasklet_struct
FILE: include/kernel/task.h
type task_info (line 13) | struct task_info {
type task_info (line 22) | struct task_info
type task_info (line 22) | struct task_info
type task_info (line 23) | struct task_info
type task_info (line 24) | struct task_info
type task_info (line 25) | struct task_info
FILE: include/kernel/thread.h
type mthread_info (line 15) | struct mthread_info {
type task_info (line 22) | struct task_info
type thread_info (line 24) | struct thread_info {
type thread_privilege (line 58) | enum thread_privilege { THREAD_PRIV_SUPERVISOR = 0, THREAD_PRIV_USER = 1 }
type thread_state (line 60) | enum thread_state {
function swap_sched_state_map (line 105) | static inline void swap_sched_state_map(void)
type kernel_context_regs (line 131) | struct kernel_context_regs {
type thread_context_regs (line 136) | struct thread_context_regs {
type thread_info (line 145) | struct thread_info
type thread_info (line 145) | struct thread_info
type thread_info (line 147) | struct thread_info
type thread_info (line 149) | struct thread_info
type thread_privilege (line 151) | enum thread_privilege
type task_info (line 153) | struct task_info
type thread_info (line 157) | struct thread_info
type thread_info (line 160) | struct thread_info
type thread_info (line 162) | struct thread_info
FILE: include/kernel/time.h
type timer_info (line 15) | struct timer_info
type timer_type (line 17) | enum timer_type { ONESHOT_TIMER, INTERVAL_TIMER }
type timer_operations (line 19) | struct timer_operations {
type timer_info (line 26) | struct timer_info {
type timer_info (line 41) | struct timer_info
type timer_info (line 42) | struct timer_info
type timer_info (line 43) | struct timer_info
type timespec (line 43) | struct timespec
type timer_info (line 44) | struct timer_info
type itimerspec (line 44) | struct itimerspec
type timer_info (line 46) | struct timer_info
FILE: include/kernel/types.h
type u32 (line 6) | typedef unsigned int u32;
type s32 (line 11) | typedef int s32;
type u16 (line 16) | typedef unsigned short u16;
type s16 (line 21) | typedef short s16;
type u8 (line 26) | typedef unsigned char u8;
type s8 (line 31) | typedef char s8;
type umode_t (line 36) | typedef unsigned short umode_t;
type u32 (line 39) | typedef u32 __u32;
type s32 (line 40) | typedef s32 __s32;
type u16 (line 41) | typedef u16 __u16;
type s16 (line 42) | typedef s16 __s16;
type u8 (line 43) | typedef u8 __u8;
type s8 (line 44) | typedef s8 __s8;
FILE: include/libc/ucontext.h
type mcontext_t (line 9) | typedef struct mcontext {
type ucontext_t (line 16) | typedef struct ucontext {
FILE: include/libc/utils.h
function infinite_loop (line 6) | static inline void infinite_loop(void)
FILE: include/linux/list.h
function INIT_LIST_HEAD (line 30) | static inline void INIT_LIST_HEAD(struct list_head *list)
function __list_add (line 42) | static inline void __list_add(struct list_head *new,
function list_add (line 60) | static inline void list_add(struct list_head *new, struct list_head *head)
function list_add_tail (line 74) | static inline void list_add_tail(struct list_head *new, struct list_head...
function __list_del (line 86) | static inline void __list_del(struct list_head *prev, struct list_head *...
function __list_del_entry (line 98) | static inline void __list_del_entry(struct list_head *entry)
function list_del (line 103) | static inline void list_del(struct list_head *entry)
function list_replace (line 117) | static inline void list_replace(struct list_head *old, struct list_head ...
function list_replace_init (line 125) | static inline void list_replace_init(struct list_head *old,
function list_del_init (line 136) | static inline void list_del_init(struct list_head *entry)
function list_move (line 147) | static inline void list_move(struct list_head *list, struct list_head *h...
function list_move_tail (line 158) | static inline void list_move_tail(struct list_head *list,
function list_is_last (line 170) | static inline int list_is_last(const struct list_head *list,
function list_empty (line 180) | static inline int list_empty(const struct list_head *head)
function list_empty_careful (line 198) | static inline int list_empty_careful(const struct list_head *head)
function list_rotate_left (line 208) | static inline void list_rotate_left(struct list_head *head)
function list_is_singular (line 222) | static inline int list_is_singular(const struct list_head *head)
function __list_cut_position (line 227) | static inline void __list_cut_position(struct list_head *list,
function list_cut_position (line 254) | static inline void list_cut_position(struct list_head *list,
function __list_splice (line 268) | static inline void __list_splice(const struct list_head *list,
function list_splice (line 287) | static inline void list_splice(const struct list_head *list,
function list_splice_tail (line 299) | static inline void list_splice_tail(struct list_head *list,
function list_splice_init (line 313) | static inline void list_splice_init(struct list_head *list,
function list_splice_tail_init (line 330) | static inline void list_splice_tail_init(struct list_head *list,
function INIT_HLIST_NODE (line 589) | static inline void INIT_HLIST_NODE(struct hlist_node *h)
function hlist_unhashed (line 595) | static inline int hlist_unhashed(const struct hlist_node *h)
function hlist_empty (line 600) | static inline int hlist_empty(const struct hlist_head *h)
function __hlist_del (line 605) | static inline void __hlist_del(struct hlist_node *n)
function hlist_del (line 615) | static inline void hlist_del(struct hlist_node *n)
function hlist_del_init (line 622) | static inline void hlist_del_init(struct hlist_node *n)
function hlist_add_head (line 630) | static inline void hlist_add_head(struct hlist_node *n, struct hlist_hea...
function hlist_add_before (line 641) | static inline void hlist_add_before(struct hlist_node *n,
function hlist_add_behind (line 650) | static inline void hlist_add_behind(struct hlist_node *n,
function hlist_add_fake (line 662) | static inline void hlist_add_fake(struct hlist_node *n)
function hlist_fake (line 667) | static inline bool hlist_fake(struct hlist_node *h)
function hlist_move_list (line 676) | static inline void hlist_move_list(struct hlist_head *old,
FILE: include/linux/types.h
type u32 (line 6) | typedef unsigned int u32;
type s32 (line 7) | typedef int s32;
type u16 (line 9) | typedef unsigned short u16;
type s16 (line 10) | typedef short s16;
type u8 (line 12) | typedef unsigned char u8;
type s8 (line 13) | typedef char s8;
type list_head (line 17) | struct list_head {
type hlist_head (line 21) | struct hlist_head {
type hlist_node (line 25) | struct hlist_node {
type atomic_t (line 29) | typedef struct {
FILE: include/piko/arpa/inet.h
function htonl (line 8) | static inline uint32_t htonl(uint32_t hostlong)
function htons (line 13) | static inline uint16_t htons(uint16_t hostshort)
function ntohl (line 18) | static inline uint32_t ntohl(uint32_t netlong)
function ntohs (line 23) | static inline uint16_t ntohs(uint16_t netshort)
FILE: include/piko/dirent.h
type DIR (line 8) | typedef void DIR;
type dirent (line 10) | struct dirent {
type dirent (line 17) | struct dirent
type dirent (line 17) | struct dirent
FILE: include/piko/signal.h
type stack_t (line 8) | typedef struct {
type sigevent (line 21) | struct sigevent {
type siginfo_t (line 41) | typedef struct {
type sigset_t (line 53) | typedef int sigset_t;
type sigaction (line 55) | struct sigaction {
type sigaction (line 76) | struct sigaction
type sigaction (line 77) | struct sigaction
FILE: include/piko/sys/resource.h
type rlim_t (line 8) | typedef unsigned int rlim_t;
type rlimit (line 10) | struct rlimit {
type rlimit (line 19) | struct rlimit
type rlimit (line 21) | struct rlimit
type rlimit (line 25) | struct rlimit
type rlimit (line 27) | struct rlimit
FILE: kernel/cond.c
type thread_info (line 11) | struct thread_info
type thread_info (line 13) | struct thread_info
function sys_pthread_cond_wait (line 24) | int sys_pthread_cond_wait(pthread_cond_t *cond, kernel_mutex_t *mutex)
function sys_pthread_cond_signal (line 38) | int sys_pthread_cond_signal(pthread_cond_t *cond)
FILE: kernel/config.c
type sc_varname (line 3) | enum sc_varname {
type sys_param (line 7) | struct sys_param {
type sys_param (line 12) | struct sys_param
function sys_sysconf (line 17) | long sys_sysconf(int name)
FILE: kernel/faults.c
function fault_enter (line 8) | void fault_enter(const char *s)
function fault_exit (line 14) | void fault_exit(void)
function hardfault (line 20) | void hardfault(struct kernel_context_regs *noscratch,
FILE: kernel/fs/fs.c
type file (line 13) | struct file
function getfd (line 20) | static int getfd(void)
function releasefd (line 33) | static void releasefd(int fd)
function release_dentries (line 40) | int release_dentries(struct dentry *dentry)
function path_head (line 58) | static int path_head(char *buf, const char *pathname)
type inode (line 74) | struct inode
type inode (line 77) | struct inode
type dentry (line 78) | struct dentry
type dentry (line 79) | struct dentry
function sys_open (line 95) | int sys_open(const char *pathname, int flags)
function sys_read (line 147) | ssize_t sys_read(int fd, void *buf, size_t count)
function sys_write (line 158) | ssize_t sys_write(int fd, void *buf, size_t count)
function off_t (line 169) | off_t sys_lseek(int fd, off_t offset, int whence)
function sys_close (line 195) | int sys_close(int fd)
function sys_stat (line 205) | int sys_stat(const char *pathname, struct stat *buf)
function sys_mount (line 220) | int sys_mount(const char *source,
FILE: kernel/fs/readdir.c
function fillonedir (line 9) | static int fillonedir(struct dir_context *ctx,
function sys_readdir_r (line 27) | int sys_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
FILE: kernel/fs/vfs.c
function vfs_iterate (line 10) | int vfs_iterate(struct file *file, struct dir_context *ctx)
type dentry (line 18) | struct dentry
type inode (line 18) | struct inode
type dentry (line 18) | struct dentry
function vfs_link (line 28) | int vfs_link(struct dentry *old_dentry,
function vfs_delete (line 38) | int vfs_delete(struct dentry *dentry)
function vfs_release (line 46) | void vfs_release(struct dentry *dentry)
function vfs_mmap (line 52) | int vfs_mmap(struct file *file, off_t offset, void **addr)
FILE: kernel/irq.c
type irq_desc (line 11) | struct irq_desc
type irq_desc (line 20) | struct irq_desc
function request_irq (line 27) | int request_irq(unsigned int irq, irq_handler_t hdlr)
function free_irq (line 55) | int free_irq(unsigned int irq)
function early_irq_init (line 72) | void early_irq_init(void)
function init_IRQ (line 78) | void init_IRQ(void)
FILE: kernel/main.c
type task_info (line 46) | struct task_info
type task_info (line 47) | struct task_info
function print_version (line 49) | void print_version(void)
type thread_info (line 68) | struct thread_info
function v7m_init (line 71) | static void v7m_init(void)
function print_linker_sections (line 97) | void print_linker_sections(void)
type thread_info (line 115) | struct thread_info
type thread_info (line 153) | struct thread_info
FILE: kernel/mm/mm.c
type file (line 39) | struct file
function sys_munmap (line 87) | int sys_munmap(__unused void *addr, __unused size_t length)
FILE: kernel/mm/page.c
function size_to_page_order (line 25) | long size_to_page_order(unsigned long size)
function find_first_free_page (line 39) | static long find_first_free_page(unsigned long order)
function split_first_free_page (line 50) | static void split_first_free_page(unsigned long order)
function addr_to_page_idx (line 85) | static inline unsigned long addr_to_page_idx(unsigned long addr,
function get_buddy_index (line 94) | static inline unsigned long get_buddy_index(unsigned long idx)
function free_pages (line 100) | void free_pages(unsigned long addr, unsigned long order)
function show_page_bitmap (line 119) | void show_page_bitmap(void)
function page_alloc_signature (line 132) | unsigned long page_alloc_signature(void)
FILE: kernel/mm/slab.c
type kmem_cache (line 17) | struct kmem_cache
type kmem_cache (line 18) | struct kmem_cache
type kmem_cache (line 19) | struct kmem_cache
type slab (line 29) | struct slab
type slab (line 31) | struct slab
function obj_index_in_slab (line 34) | static inline int obj_index_in_slab(void *obj, struct kmem_cache *cache)
type kmem_cache (line 40) | struct kmem_cache
type kmem_cache (line 46) | struct kmem_cache
type slab (line 52) | struct slab
type slab (line 72) | struct slab
type kmem_cache (line 72) | struct kmem_cache
type slab (line 74) | struct slab
type kmem_cache (line 85) | struct kmem_cache
type slab (line 87) | struct slab
function slab_destroy (line 116) | static int slab_destroy(__unused struct kmem_cache *cache, struct slab *...
function kmem_cache_free (line 124) | void kmem_cache_free(struct kmem_cache *cache, void *obj)
function kmem_cache_init (line 139) | void kmem_cache_init(void)
FILE: kernel/mutex.c
function sys_pthread_mutex_lock (line 12) | int sys_pthread_mutex_lock(kernel_mutex_t *mutex)
type thread_info (line 26) | struct thread_info
type thread_info (line 28) | struct thread_info
function sys_pthread_mutex_unlock (line 39) | int sys_pthread_mutex_unlock(kernel_mutex_t *mutex)
FILE: kernel/printk.c
function co_vsnprintf (line 14) | static void co_vsnprintf(const char *format, va_list ap)
function __printk_init (line 22) | void __printk_init(void)
function __printk_putchar (line 27) | void __printk_putchar(char c)
function printk (line 37) | int printk(const char *format, ...)
FILE: kernel/resource.c
type rlimit (line 4) | struct rlimit
function sys_getrlimit (line 8) | int sys_getrlimit(int resource, struct rlimit *rlim)
function sys_setrlimit (line 16) | int sys_setrlimit(int resource, const struct rlimit *rlim)
FILE: kernel/sched.c
type sched (line 8) | struct sched
type sched (line 9) | struct sched
type sched (line 10) | struct sched
type sched (line 11) | struct sched
type sched (line 13) | struct sched
function sched_init (line 15) | int sched_init()
function sched_select (line 29) | int sched_select(sched_class_t sched_type)
function sched_enqueue (line 48) | int sched_enqueue(struct thread_info *thread)
function sched_dequeue (line 55) | int sched_dequeue(struct thread_info *thread)
function sched_elect (line 60) | int sched_elect(int flags)
FILE: kernel/sched/bitmap.c
type thread_info (line 9) | struct thread_info
type bitmap_struct (line 11) | struct bitmap_struct
type bitmap_struct (line 14) | struct bitmap_struct
type bitmap_struct (line 15) | struct bitmap_struct
function sched_bitmap_init (line 21) | static int sched_bitmap_init(void)
type thread_info (line 29) | struct thread_info
type bitmap_struct (line 29) | struct bitmap_struct
function thread_enqueue (line 40) | static int thread_enqueue(struct thread_info *thread, struct bitmap_stru...
function sched_bitmap_enqueue (line 47) | static int sched_bitmap_enqueue(struct thread_info *thread)
function thread_dequeue (line 52) | static int thread_dequeue(struct thread_info *thread, struct bitmap_stru...
function sched_bitmap_dequeue (line 65) | static int sched_bitmap_dequeue(struct thread_info *thread)
function sched_bitmap_elect (line 76) | static int sched_bitmap_elect(int flags)
type sched (line 115) | struct sched
FILE: kernel/sched/rr.c
type thread_info (line 8) | struct thread_info
function sched_rr_init (line 10) | int sched_rr_init(void)
type thread_info (line 15) | struct thread_info
type thread_info (line 15) | struct thread_info
function sched_rr_enqueue (line 23) | int sched_rr_enqueue(struct thread_info *thread)
function sched_rr_dequeue (line 30) | int sched_rr_dequeue(struct thread_info *thread)
function sched_rr_elect_reset (line 50) | static int sched_rr_elect_reset(void)
function sched_rr_elect (line 62) | int sched_rr_elect(int switch_type)
type sched (line 90) | struct sched
FILE: kernel/signal.c
type thread_info (line 21) | struct thread_info
function stage_sighandler (line 28) | static void stage_sighandler(struct sigaction *sigaction)
function stage_sigaction (line 61) | static void stage_sigaction(const struct sigaction *sigaction,
function do_sigevent (line 102) | void do_sigevent(const struct sigevent *sigevent, struct thread_info *th...
type sigaction (line 132) | struct sigaction
type signal_info (line 135) | struct signal_info
function sys_sigaction (line 147) | int sys_sigaction(int signo,
function is_signal_supported (line 184) | static int is_signal_supported(int sig)
function sys_kill (line 202) | int sys_kill(__unused pid_t pid, int sig)
FILE: kernel/softirq.c
type softirq_action (line 18) | struct softirq_action
type bitmap_struct (line 21) | struct bitmap_struct
type task_info (line 24) | struct task_info
type thread_info (line 25) | struct thread_info
function open_softirq (line 27) | int open_softirq(unsigned int nr, int (*action)(struct softirq_action *))
function raise_softirq (line 39) | int raise_softirq(unsigned int nr)
type tasklet_struct (line 53) | struct tasklet_struct
type tasklet_struct (line 55) | struct tasklet_struct
type tasklet_struct (line 56) | struct tasklet_struct
type tasklet_struct (line 56) | struct tasklet_struct
function tasklet_schedule (line 68) | int tasklet_schedule(struct tasklet_struct *task)
function tasklet_action (line 80) | static int tasklet_action(struct softirq_action __unused *a)
function init_softirq_entry (line 112) | static void init_softirq_entry()
function init_softirq (line 137) | int init_softirq(void)
FILE: kernel/task.c
function pid_t (line 10) | static pid_t alloc_pid()
type task_info (line 21) | struct task_info
type task_info (line 21) | struct task_info
function task_exit (line 32) | void task_exit(struct task_info *task)
type task_info (line 40) | struct task_info
function sys_getpid (line 47) | int sys_getpid(void)
FILE: kernel/thread.c
type kernel_context_regs (line 22) | struct kernel_context_regs
type kernel_context_regs (line 25) | struct kernel_context_regs
type kernel_context_regs (line 30) | struct kernel_context_regs
type kernel_context_regs (line 31) | struct kernel_context_regs
type thread_context_regs (line 42) | struct thread_context_regs
type thread_context_regs (line 46) | struct thread_context_regs
type thread_context_regs (line 51) | struct thread_context_regs
type thread_context_regs (line 52) | struct thread_context_regs
type thread_info (line 62) | struct thread_info
type thread_privilege (line 64) | enum thread_privilege
type task_info (line 66) | struct task_info
type thread_info (line 68) | struct thread_info
type kernel_context_regs (line 69) | struct kernel_context_regs
type thread_context_regs (line 70) | struct thread_context_regs
function thread_yield (line 102) | int thread_yield(void)
function thread_self (line 111) | int thread_self(void)
function thread_exit (line 118) | void thread_exit(void *retval)
function thread_set_priority (line 142) | int thread_set_priority(struct thread_info *thread, int priority)
type thread_info (line 150) | struct thread_info
type thread_info (line 152) | struct thread_info
function thread_join (line 164) | int thread_join(pthread_t thread, void **retval)
function thread_detach (line 190) | int thread_detach(pthread_t thread)
function sys_pthread_yield (line 202) | int sys_pthread_yield(void)
function pthread_t (line 207) | pthread_t sys_pthread_self(void)
function sys_pthread_exit (line 212) | void sys_pthread_exit(void *retval)
function sys_pthread_detach (line 217) | int sys_pthread_detach(pthread_t thread)
function sys_pthread_create (line 222) | int sys_pthread_create(pthread_t *thread,
function sys_pthread_join (line 248) | int sys_pthread_join(pthread_t thread, void **retval)
FILE: kernel/time.c
type thread_info (line 17) | struct thread_info
function msleep_callback (line 19) | static void msleep_callback(struct timer_info *timer)
function sys_msleep (line 26) | int sys_msleep(unsigned int msec)
type timer_info (line 51) | struct timer_info
type list_head (line 52) | struct list_head
type timer_info (line 54) | struct timer_info
function reserve_timer_id (line 64) | static int reserve_timer_id(timer_t *timerid)
function timer_callback (line 77) | static void timer_callback(struct timer_info *timer)
function timer_callback_and_link (line 84) | static void timer_callback_and_link(struct timer_info *timer)
function sys_timer_create (line 92) | int sys_timer_create(__unused clockid_t clockid,
function sys_timer_settime (line 113) | int sys_timer_settime(timer_t timerid,
function sys_timer_gettime (line 158) | int sys_timer_gettime(timer_t timerid, struct itimerspec *curr_value)
FILE: libc/fcntl.c
function open (line 9) | int open(const char *pathname, int flag)
function close (line 14) | int close(int fd)
function read (line 19) | int read(int fd, void *buf, size_t count)
function write (line 24) | int write(int fd, void *buf, size_t count)
function lseek (line 29) | int lseek(int fd, off_t offset, int whence)
FILE: libc/filesystem.c
function _open (line 10) | int _open(const char *pathname, int flags)
function _close (line 15) | int _close(int fd)
function _read (line 20) | ssize_t _read(int fd, void *buf, size_t count)
function _write (line 25) | ssize_t _write(int fd, void *buf, size_t count)
function off_t (line 30) | off_t _lseek(int fd, off_t offset, int whence)
function stat (line 36) | int stat(const char *pathname, struct stat *buf)
function mount (line 41) | int mount(const char *source,
function DIR (line 52) | DIR *opendir(const char *name)
function readdir_r (line 57) | int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
function closedir (line 63) | int closedir(DIR *dirp)
FILE: libc/piko/mman.c
function munmap (line 14) | int munmap(__unused void *addr, __unused size_t length)
FILE: libc/piko/stubs.c
function _isatty (line 19) | int _isatty(__unused int file)
function _fstat (line 26) | int _fstat()
function _exit (line 40) | void _exit(__unused int status)
function clock_t (line 45) | clock_t _times()
function _fini (line 52) | void _fini(void)
function _getpid (line 57) | int _getpid(void)
FILE: libc/pthread.c
function pthread_attr_setstacksize (line 7) | int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
function pthread_attr_getstacksize (line 16) | int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacks...
function pthread_attr_init (line 27) | int pthread_attr_init(pthread_attr_t *attr)
function pthread_mutex_init (line 36) | int pthread_mutex_init(pthread_mutex_t *mutex,
function pthread_cond_init (line 44) | int pthread_cond_init(__unused pthread_cond_t *cond,
function sched_yield (line 56) | int sched_yield(void)
function pthread_t (line 63) | pthread_t pthread_self(void)
function pthread_exit (line 68) | void pthread_exit(void *retval)
function pthread_detach (line 77) | int pthread_detach(pthread_t thread)
function pthread_create (line 82) | int pthread_create(pthread_t *thread,
function pthread_join (line 91) | int pthread_join(pthread_t thread, void **retval)
function pthread_cond_wait (line 96) | int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
function pthread_cond_signal (line 101) | int pthread_cond_signal(pthread_cond_t *cond)
FILE: libc/signal.c
function sigaction (line 8) | int sigaction(int sig,
function _kill (line 16) | int _kill(pid_t pid, int sig)
FILE: libc/stdio.c
function vsnprintf (line 6) | int vsnprintf(char *str, size_t size, const char *format, va_list ap)
function vsprintf (line 81) | int vsprintf(char *str, const char *format, va_list ap)
function sprintf (line 86) | int sprintf(char *str, const char *format, ...)
function snprintf (line 98) | int snprintf(char *str, size_t size, const char *format, ...)
FILE: libc/stdlib.c
type malloc_tag (line 11) | struct malloc_tag {
function get_block_length (line 28) | static inline size_t get_block_length(struct malloc_tag *block)
function set_block_length (line 33) | static inline void set_block_length(struct malloc_tag *block, size_t len)
function get_block_free (line 38) | static inline bool get_block_free(struct malloc_tag *block)
function set_block_free (line 43) | static inline void set_block_free(struct malloc_tag *block, bool free)
function kernel_heap_init (line 51) | void kernel_heap_init(void *heap_start, size_t heap_size)
type malloc_tag (line 61) | struct malloc_tag
type malloc_tag (line 64) | struct malloc_tag
type malloc_tag (line 73) | struct malloc_tag
type malloc_tag (line 77) | struct malloc_tag
function free (line 93) | void free(void *ptr)
FILE: libc/time.c
function timer_create (line 10) | int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *time...
function timer_settime (line 16) | int timer_settime(timer_t timerid,
function timer_gettime (line 25) | int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
FILE: libc/ucontext.c
function makecontext (line 8) | void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...)
FILE: libc/unistd.c
function sysconf (line 6) | long sysconf(int name)
function msleep (line 11) | unsigned int msleep(unsigned int msecs)
FILE: libc/utils.c
function strpad (line 26) | void strpad(char *buf, char pad_val, int count)
FILE: platform/f429disco/halt.c
function __platform_halt (line 4) | void __platform_halt(void)
FILE: platform/f429disco/init.c
type timer_operations (line 10) | struct timer_operations
type timer_operations (line 12) | struct timer_operations
type timer_operations (line 14) | struct timer_operations
function __weak (line 16) | __weak void __platform_init(void)
function __weak (line 24) | __weak void __platform_halt(void)
FILE: platform/f429disco/uart.c
function uart_port_setup (line 10) | static void uart_port_setup(struct stm32_uart_port *port)
function uart_port_init (line 21) | static void uart_port_init(struct stm32_uart_port *port)
function uart_init (line 31) | void uart_init(void)
FILE: platform/stm32p103/halt.c
function __platform_halt (line 4) | void __platform_halt(void)
FILE: platform/stm32p103/init.c
type timer_operations (line 9) | struct timer_operations
type timer_operations (line 11) | struct timer_operations
type timer_operations (line 13) | struct timer_operations
function __weak (line 18) | __weak void __platform_init(void)
function __weak (line 26) | __weak void __platform_halt(void)
FILE: platform/stm32p103/uart.c
function uart_port_setup (line 10) | static void uart_port_setup(struct stm32_uart_port *port)
function uart_port_init (line 21) | static void uart_port_init(struct stm32_uart_port *port)
function uart_init (line 32) | void uart_init(void)
FILE: scripts/gen-proc-version.py
function run_cmd (line 6) | def run_cmd(cmd):
function cc_version (line 14) | def cc_version(cc):
FILE: scripts/rstlint.py
function checker (line 54) | def checker(*suffixes, **kwds):
function check_syntax (line 66) | def check_syntax(fn, lines):
function check_suspicious_constructs (line 80) | def check_suspicious_constructs(fn, lines):
function check_whitespace (line 95) | def check_whitespace(fn, lines):
function check_line_length (line 107) | def check_line_length(fn, lines):
function check_leaked_markup (line 121) | def check_leaked_markup(fn, lines):
function main (line 130) | def main(argv):
FILE: tests/bitops_1/main.c
function main (line 5) | int main()
FILE: tests/cond_1/main.c
function main (line 29) | int main()
FILE: tests/cond_2/main.c
function checkResults (line 19) | int checkResults(const char *s, int rc)
function main (line 56) | int main()
FILE: tests/cond_3/main.c
function main (line 60) | int main(void)
FILE: tests/fs_1/main.c
function main (line 10) | int main()
FILE: tests/fs_2/main.c
function main (line 13) | int main()
FILE: tests/fs_3/main.c
type mtd_info (line 17) | struct mtd_info
type inode (line 19) | struct inode
function flash_init (line 23) | void flash_init(void)
function main (line 33) | int main()
FILE: tests/fs_4/main.c
type mtd_info (line 17) | struct mtd_info
type inode (line 19) | struct inode
function flash_init (line 23) | void flash_init(void)
function main (line 33) | int main()
FILE: tests/fs_5/main.c
function main (line 11) | int main()
FILE: tests/fs_6/main.c
type mtd_info (line 15) | struct mtd_info
type inode (line 17) | struct inode
function flash_init (line 21) | void flash_init(void)
function main (line 31) | int main()
FILE: tests/fs_7/main.c
type mtd_info (line 17) | struct mtd_info
type inode (line 19) | struct inode
function flash_init (line 23) | void flash_init(void)
function main (line 33) | int main()
FILE: tests/getpid_1/main.c
function main (line 6) | int main()
FILE: tests/itoa_1/main.c
function itoa_base_00 (line 7) | int itoa_base_00(void)
function itoa_base_01 (line 15) | int itoa_base_01(void)
function itoa_base_02 (line 23) | int itoa_base_02(void)
function itoa_base_03 (line 31) | int itoa_base_03(void)
function itoa_base_04 (line 39) | int itoa_base_04(void)
function itoa_base_05 (line 47) | int itoa_base_05(void)
function itoa_base_06 (line 55) | int itoa_base_06(void)
function itoa_base_07 (line 63) | int itoa_base_07(void)
function itoa_base_08 (line 71) | int itoa_base_08(void)
function itoa_base_09 (line 79) | int itoa_base_09(void)
function itoa_base_10 (line 87) | int itoa_base_10(void)
function main (line 95) | int main()
FILE: tests/malloc_1/main.c
function main (line 7) | int main()
FILE: tests/mm_1/main.c
function main (line 6) | int main()
FILE: tests/mm_2/main.c
function main (line 6) | int main()
FILE: tests/mmap_1/main.c
function main (line 9) | int main()
FILE: tests/mmap_2/main.c
type mtd_info (line 17) | struct mtd_info
type inode (line 19) | struct inode
function flash_init (line 23) | void flash_init(void)
function main (line 33) | int main()
FILE: tests/msleep_1/main.c
function main (line 6) | int main()
FILE: tests/msleep_2/main.c
function main (line 21) | int main()
FILE: tests/mtdram_1/main.c
function main (line 12) | int main()
FILE: tests/mutex_1/main.c
function main (line 7) | int main(void)
FILE: tests/mutex_2/main.c
function main (line 26) | int main(void)
FILE: tests/mutex_3/main.c
function main (line 9) | int main(void)
FILE: tests/mutex_4/main.c
function main (line 29) | int main(void)
FILE: tests/mutex_5/main.c
function main (line 22) | int main()
FILE: tests/page_3/main.c
type alloc_info (line 11) | struct alloc_info {
type alloc_info (line 16) | struct alloc_info
function main (line 18) | int main()
FILE: tests/raise_1/main.c
function handler (line 11) | void handler(int n)
function main (line 20) | int main(void *arg)
FILE: tests/raise_2/main.c
function main (line 10) | int main(void *arg)
FILE: tests/raise_3/main.c
function sigact (line 11) | void sigact(int sig, siginfo_t *siginfo, void *unused)
function main (line 23) | int main(void *arg)
FILE: tests/readdir_1/main.c
function main (line 16) | int main()
FILE: tests/runner.py
function find_all_tests (line 26) | def find_all_tests(excludes=[]):
class PikoTest (line 37) | class PikoTest:
method __init__ (line 41) | def __init__(self):
method format_test_result (line 62) | def format_test_result(self, test_name, result):
method format_duration (line 66) | def format_duration(self, seconds):
method display_progress (line 75) | def display_progress(self, test_index, test):
method display_result (line 94) | def display_result(self):
method display_header (line 122) | def display_header(self):
method accumulate_result (line 138) | def accumulate_result(self, test, result):
method run_tests (line 149) | def run_tests(self):
method run_tests_sequential (line 156) | def run_tests_sequential(self):
method finalize (line 186) | def finalize(self):
method main (line 199) | def main(self, tests, ns):
function print_qemu_version (line 215) | def print_qemu_version(ns):
function print_gcc_version (line 224) | def print_gcc_version(ns):
function print_header (line 233) | def print_header(testname, arch):
function run_single_test (line 240) | def run_single_test(test, ns):
function main (line 294) | def main(ns):
function printlist (line 298) | def printlist(x, width=70, indent=4, file=None):
function count (line 313) | def count(n, word):
FILE: tests/slab_1/main.c
type foo (line 8) | struct foo {
function main (line 13) | int main(void)
FILE: tests/slab_2/main.c
type foo (line 9) | struct foo {
function main (line 14) | int main(void)
FILE: tests/softirq_1/main.c
function fn (line 11) | static void fn(void *arg)
function main (line 16) | int main()
FILE: tests/softirq_2/main.c
function fn (line 11) | static void fn(void *arg)
function main (line 16) | int main()
FILE: tests/softirq_3/main.c
function main (line 20) | int main()
FILE: tests/sprintf_1/main.c
function sprintf_00 (line 7) | int sprintf_00(void)
function sprintf_01 (line 20) | int sprintf_01(void)
function sprintf_02 (line 33) | int sprintf_02(void)
function sprintf_03 (line 46) | int sprintf_03(void)
function sprintf_04 (line 60) | int sprintf_04(void)
function sprintf_05 (line 73) | int sprintf_05(void)
function sprintf_06 (line 86) | int sprintf_06(void)
function sprintf_07 (line 99) | int sprintf_07(void)
function main (line 112) | int main()
FILE: tests/stat_1/main.c
type mtd_info (line 15) | struct mtd_info
type inode (line 17) | struct inode
function flash_init (line 21) | void flash_init(void)
function main (line 31) | int main()
FILE: tests/syscall_1/main.c
function sysarg0_handler (line 16) | int sysarg0_handler(void)
function sysarg1_handler (line 24) | int sysarg1_handler(int a0)
function sysarg2_handler (line 34) | int sysarg2_handler(int a0, int a1)
function sysarg3_handler (line 47) | int sysarg3_handler(int a0, int a1, int a2)
function sysarg4_handler (line 63) | int sysarg4_handler(int a0, int a1, int a2, int a3)
function sysarg5_handler (line 82) | int sysarg5_handler(int a0, int a1, int a2, int a3, int a4)
function sysarg6_handler (line 104) | int sysarg6_handler(int a0, int a1, int a2, int a3, int a4, int a5)
function main (line 137) | int main(void *arg)
FILE: tests/sysconf_1/main.c
function main (line 4) | int main()
FILE: tests/test_1/main.c
function main (line 5) | int main()
FILE: tests/test_2/main.c
function main (line 5) | int main()
FILE: tests/thread_1/main.c
function main (line 18) | int main()
FILE: tests/thread_2/main.c
function main (line 19) | int main()
FILE: tests/thread_3/main.c
function main (line 18) | int main()
FILE: tests/thread_4/main.c
function main (line 23) | int main()
FILE: tests/thread_5/main.c
function main (line 16) | int main()
FILE: tests/thread_6/main.c
function main (line 16) | int main()
FILE: tests/timer_1/main.c
function event (line 12) | static void event(union sigval sival)
function main (line 22) | int main()
FILE: tests/timer_2/main.c
function event (line 12) | static void event(union sigval sival)
function main (line 18) | int main()
FILE: tests/timer_3/main.c
function event (line 8) | static void event(union sigval sival)
function main (line 13) | int main()
FILE: tests/timer_4/main.c
function event (line 13) | static void event(union sigval sival)
function main (line 20) | int main()
FILE: tests/timer_5/main.c
function event_should_not_happen (line 14) | static void event_should_not_happen(union sigval sival)
function event_check (line 21) | static void event_check(union sigval sival)
function main (line 28) | int main()
FILE: tests/ucontext_1/main.c
function pputs (line 11) | static void pputs(const char *s)
function test (line 17) | void test(int a1, int a2, int a3, int a4)
function main (line 27) | int main()
FILE: user/cat.c
function cat (line 9) | static int cat(__unused int argc, char *argv[])
FILE: user/echo.c
function echo (line 5) | static int echo(int argc, char *argv[])
FILE: user/exit.c
function _exit (line 4) | static int _exit(__unused int argc, __unused char *argv[])
FILE: user/halt.c
function halt (line 4) | static int halt(__unused int argc, __unused char *argv[])
FILE: user/ls.c
function ls (line 11) | static int ls(int argc, char *argv[])
FILE: user/reboot.c
function reboot (line 4) | static int reboot(__unused int argc, __unused char *argv[])
FILE: user/sh.c
function parse_command_line (line 17) | static int parse_command_line(char *buf, char *argv[])
function exec_command (line 35) | static void exec_command(char *buf, int fd)
function cursor_backward (line 57) | static void cursor_backward(int n, int fd)
function readline (line 71) | static void readline(int fd)
function minishell (line 137) | int minishell(void *options)
FILE: user/sh.h
type ascii_control_char (line 7) | enum ascii_control_char {
type shell_cmd (line 15) | struct shell_cmd {
Condensed preview — 242 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (352K chars).
[
{
"path": ".clang-format",
"chars": 376,
"preview": "BasedOnStyle: Chromium\nLanguage: Cpp\nMaxEmptyLinesToKeep: 3\nIndentCaseLabels: false\nAllowShortIfStatementsOnASingleLine:"
},
{
"path": ".gitignore",
"chars": 237,
"preview": "# external source\nexternal/\n\n*~\n*.o\n*.o.d\n*.elf\n*.map\n*.lds\n*.hex\n*.bin\n\n# generated\nfs/version\ninclude/kernel/syscalls."
},
{
"path": ".travis.yml",
"chars": 1216,
"preview": "sudo: required\ndist: trusty\nos: linux\nlanguage: python\ncache: pip\nstage:\n - docs\n - core\n\njobs:\n include:\n - stage"
},
{
"path": "LICENSE",
"chars": 1370,
"preview": "Piko/RT is freely redistributable under the two-clause BSD License:\n\nCopyright (c) 2017 Piko/RT Developers.\nAll rights r"
},
{
"path": "Makefile",
"chars": 2103,
"preview": "NAME = piko\n\n# select QEMU when the platform is unspecified\nPLAT ?= f429disco\nCMSIS = external/cmsis\n\n# The platform Mak"
},
{
"path": "README.md",
"chars": 541,
"preview": "# Piko/RT\n\nThis is `Piko/RT`, a tiny Linux-like real-time operating system kernel, optimized for ARM Cortex-M series mic"
},
{
"path": "arch/v7m-entry.S",
"chars": 3406,
"preview": "#include <kernel/linkage.h>\n\n\t.syntax unified\n\t.thumb\n\n\t@ do the thread-context switch\n\t@\n\t@ r0: struct thread_info *nex"
},
{
"path": "arch/v7m-faults.c",
"chars": 2420,
"preview": "#include <kernel/faults.h>\n#include <kernel/thread.h>\n\n#include \"kernel.h\"\n\n#define UFSR_DIVBYZERO (1 << 9)\n#define UFSR"
},
{
"path": "arch/v7m-head.S",
"chars": 3672,
"preview": "#include <kernel/linkage.h>\n\n\t.syntax unified\n\t.thumb\n\n\t.section \".vector\", \"a\"\n\t.long\t__early_stack_start__\t\t@ SP_main "
},
{
"path": "arch/v7m-svcall.S",
"chars": 1712,
"preview": "#include <kernel/linkage.h>\n\n\t.syntax unified\n\t.thumb\n\n\t@ offsets in the frame to the registers saved on interrupt-entry"
},
{
"path": "docs/Makefile",
"chars": 669,
"preview": "# Piko/RT documentation\n\n# You can set these variables from the command line.\nSPHINXOPTS =\nSPHINXBUILD = sphinx-bui"
},
{
"path": "docs/api.rst",
"chars": 367,
"preview": ".. _api:\n\n\nPiko/RT POSIX API\n=================\n\n``Piko/RT`` aim to fulfill IEEE 1003.13-2003 PSE51 standard, this is the"
},
{
"path": "docs/build.rst",
"chars": 1513,
"preview": ".. _build:\n\nBuild Piko/RT\n=============\n\nThis chapter will help you start to build ``Piko/RT``, you will need to prepare"
},
{
"path": "docs/conf.py",
"chars": 4856,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n#\n# piko documentation build configuration file, created by\n# sphinx-quic"
},
{
"path": "docs/contribute.rst",
"chars": 2469,
"preview": ".. _contribute:\n\nContribute to Piko/RT\n=====================\n\nWe welcome everyone to help to develop Piko/RT.\nThis will "
},
{
"path": "docs/debugging.rst",
"chars": 2030,
"preview": ".. _debugging:\n\nPiko/RT Debugging\n=================\n\n\nUsing tmux\n----------\n\n`tmux <https://github.com/tmux/tmux>`_ is a"
},
{
"path": "docs/emulate.rst",
"chars": 1832,
"preview": ".. _emulate:\n\nUsing QEMU to Develop Piko/RT\n=============================\n\n\nPrepare QEMU\n------------\n\nYou will need to "
},
{
"path": "docs/index.rst",
"chars": 346,
"preview": "Welcome to piko's documentation!\n================================\n\n.. toctree::\n :maxdepth: 2\n :caption: Contents:\n\n"
},
{
"path": "docs/kernel.rst",
"chars": 353,
"preview": ".. _kernel:\n\nPiko/RT Design & Concept\n========================\n\nPiko/RT is a tiny Linux-like real-time operating system "
},
{
"path": "docs/make.bat",
"chars": 808,
"preview": "@ECHO OFF\r\n\r\npushd %~dp0\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sp"
},
{
"path": "docs/posix/parse.py",
"chars": 2411,
"preview": "# Helper for generate POSIX API table\n# XXX: used from docs, not here\n\nimport glob\nimport os\nimport tempfile\nimport shut"
},
{
"path": "docs/posix/posix_opt/01._POSIX_CLOCK_SELECTION",
"chars": 18,
"preview": "clock_nanosleep()\n"
},
{
"path": "docs/posix/posix_opt/02._POSIX_FSYNC",
"chars": 8,
"preview": "fsync()\n"
},
{
"path": "docs/posix/posix_opt/03._POSIX_MEMLOCK",
"chars": 27,
"preview": "m lockall(), m unlockall()\n"
},
{
"path": "docs/posix/posix_opt/04.POSIX_MEMLOCK_RANGE",
"chars": 19,
"preview": "mlock(), munlock()\n"
},
{
"path": "docs/posix/posix_opt/05._POSIX_MONOTONIC_CLOCK",
"chars": 0,
"preview": ""
},
{
"path": "docs/posix/posix_opt/06._POSIX_NO_TRUNC",
"chars": 0,
"preview": ""
},
{
"path": "docs/posix/posix_opt/07._POSIX_REALTIME_SIGNALS",
"chars": 43,
"preview": "sigqueue(), sigtim edwait(), sigwaitinfo()\n"
},
{
"path": "docs/posix/posix_opt/08._POSIX_SEMAPHORES",
"chars": 149,
"preview": "sem _close(), sem _destroy(), sem _getvalue(), sem _init(), sem _open(), sem _post(),\nsem _trywait(), sem _wait(), sem _"
},
{
"path": "docs/posix/posix_opt/09._POSIX_SHARED_MEMORY_OBJECTS",
"chars": 27,
"preview": "shm _open(), shm _unlink()\n"
},
{
"path": "docs/posix/posix_opt/10._POSIX_SYNCHRONIZED_IO",
"chars": 12,
"preview": "fdatasync()\n"
},
{
"path": "docs/posix/posix_opt/11._POSIX_THREAD_ATTR_STACKADDR",
"chars": 57,
"preview": "pthread_attr_getstackaddr(), pthread_attr_setstackaddr()\n"
},
{
"path": "docs/posix/posix_opt/12._POSIX_THREAD_ATTR_STACKSIZE",
"chars": 50,
"preview": "pthread_attr_getstack (), pthread_attr_setstack()\n"
},
{
"path": "docs/posix/posix_opt/13._POSIX_THREAD_CPUTIME",
"chars": 24,
"preview": "pthread_getcpuclockid()\n"
},
{
"path": "docs/posix/posix_opt/14._POSIX_THREAD_PRIO_INHERIT",
"chars": 67,
"preview": "pthread_m utexattr_getprotocol(), pthread_m utexattr_setprotocol()\n"
},
{
"path": "docs/posix/posix_opt/15._POSIX_THREAD_PRIO_PROTECT",
"chars": 207,
"preview": "pthread_m utex_getprioceiling(), pthread_m utex_setprioceiling(),\npthread_m utexattr_getprioceiling(), pthread_m utexatt"
},
{
"path": "docs/posix/posix_opt/16._POSIX_THREAD_PRIORITY_SCHEDULING",
"chars": 330,
"preview": "pthread_attr_getinheritsched(), pthread_attr_getschedpolicy(),\npthread_attr_getscope(), pthread_attr_setinheritsched(),\n"
},
{
"path": "docs/posix/posix_opt/17._POSIX_THREAD_SPORADIC_SERVER",
"chars": 0,
"preview": ""
},
{
"path": "docs/posix/posix_opt/18._POSIX_TIMERS",
"chars": 157,
"preview": "clock_getres(), clock_gettim e(), clock_settim e(), nanosleep(), tim er_create(),\ntim er_detele(), tim er_getoverrun(), "
},
{
"path": "docs/posix/posix_req/01.POSIX_C_LANG_SUPPORT",
"chars": 1164,
"preview": "abs(), asctime(), asctime_r(), atof(), atoi(), atol(),\natoll(), bsearch(), calloc(), ctime(), ctime_r(),\ndifftime(), div"
},
{
"path": "docs/posix/posix_req/02.POSIX_DEVICE_IO",
"chars": 381,
"preview": "clearerr(), close(), fclose(), fdopen(), feof(), ferror(),\nfflush (), fgetc(), fgets(), fileno(), fopen(), fprintf(),\nfp"
},
{
"path": "docs/posix/posix_req/03.POSIX_FILE_LOCKING",
"chars": 117,
"preview": "flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(),\ngetchar_unlocked(), putc_unlocked(),\nputchar_unlocked()\n"
},
{
"path": "docs/posix/posix_req/04.POSIX_SIGNALS",
"chars": 190,
"preview": "abort(), alarm(), kill(), pause(), raise(), sigaction(),\nsigaddset(), sigdelset(), sigemptyset(), sigfillset(),\nsigismem"
},
{
"path": "docs/posix/posix_req/05.POSIX_SINGLE_PROCESS",
"chars": 78,
"preview": "confstr(), environ, errno, getenv(), setenv(), sysconf(),\nuname(), unsetenv()\n"
},
{
"path": "docs/posix/posix_req/06.POSIX_THREADS_BASE",
"chars": 931,
"preview": "pthread_atfork(), pthread_attr_destroy(),\npthread_attr_getdetachstate(),\npthread_attr_getschedparam(), pthread_attr_init"
},
{
"path": "docs/posix/posix_req/07.XSI_THREAD_MUTEX_EXT",
"chars": 57,
"preview": "pthread_mutexattr_gettype(),\npthread_mutexattr_settype()\n"
},
{
"path": "docs/posix/posix_req/08.XSI_THREADS_EXT",
"chars": 159,
"preview": "pthread_attr_getguardsize(), pthread_attr_getstack(),\npthread_attr_setguardsize(),\npthread_attr_setstack(), pthread_getc"
},
{
"path": "docs/test.rst",
"chars": 705,
"preview": ".. _test:\n\n\nPiko/RT Test Suite\n==================\n\nPiko/RT test suite is under ``tests`` directory, it contain a makefil"
},
{
"path": "drivers/char/mem.c",
"chars": 2600,
"preview": "#include <string.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n\nstatic int mem_open(__unused struct inode *inode"
},
{
"path": "drivers/char/random.c",
"chars": 1793,
"preview": "#include <stdint.h>\n#include <string.h>\n#include <sys/param.h>\n\n//#include <kernel/kernel.h>\n#include <kernel/fs.h>\n\ntyp"
},
{
"path": "drivers/mtd/mtd.h",
"chars": 2561,
"preview": "#ifndef _DRIVERS_MTD_MTD_H\n#define _DRIVERS_MTD_MTD_H\n\n#include <sys/types.h>\n\n#include <kernel/errno-base.h>\n#include <"
},
{
"path": "drivers/mtd/mtdchar.c",
"chars": 1092,
"preview": "#include <sys/types.h>\n#include <kernel/fs.h>\n#include <drivers/mtd/mtd.h>\n\n/* romfs depends on mtdchar */\n\nstatic int m"
},
{
"path": "drivers/mtd/mtdcore.c",
"chars": 1850,
"preview": "#include <stddef.h>\n#include <drivers/mtd/mtd.h>\n\nvoid mtd_erase_callback(struct erase_info *instr)\n{\n if (instr->cal"
},
{
"path": "drivers/mtd/mtdram.c",
"chars": 2370,
"preview": "#include <string.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n#include <drivers/mtd/mtd.h>\n\n#define SIZE_1KB 10"
},
{
"path": "drivers/serial/serialchar.c",
"chars": 1529,
"preview": "#include <sys/types.h>\n#include <kernel/fs.h>\n#include <kernel/sched.h>\n#include <kernel/serial.h>\n#include <kernel/thre"
},
{
"path": "drivers/serial/serialcore.c",
"chars": 1059,
"preview": "#include <sys/types.h>\n\n#include <kernel/serial.h>\n\nvoid serial_init(void)\n{\n extern unsigned long __serial_hook_star"
},
{
"path": "drivers/serial/stm32-uart.c",
"chars": 1929,
"preview": "#include <stdio.h>\n#include <sys/types.h>\n\n#include <kernel/cbuf.h>\n#include <kernel/fs.h>\n#include <kernel/irq.h>\n#incl"
},
{
"path": "drivers/serial/stm32-uart.h",
"chars": 595,
"preview": "#ifndef _DRIVER_SERIAL_STM32_USART_H\n#define _DRIVER_SERIAL_STM32_USART_H\n\n#include \"platform.h\"\n\nstruct stm32_uart_port"
},
{
"path": "drivers/timer/systick.c",
"chars": 3265,
"preview": "/*\n * Low-resolution (1kHz) SysTick-based timers to support the common\n * driver's timer interface.\n */\n\n#include <errno"
},
{
"path": "drivers/timer/timercore.c",
"chars": 1228,
"preview": "#include <errno.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include <kernel/errno-base.h>\n#include <kernel/time.h>\n\nstati"
},
{
"path": "fs/proc.c",
"chars": 1917,
"preview": "#include <string.h>\n#include <sys/param.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n\n// https://linux.die.net/"
},
{
"path": "fs/romfs.c",
"chars": 6846,
"preview": "/* https://www.kernel.org/doc/Documentation/filesystems/romfs.txt */\n\n#include <stddef.h>\n#include <stdlib.h>\n#include <"
},
{
"path": "fs/tmpfs.c",
"chars": 4482,
"preview": "#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n\n#inclu"
},
{
"path": "include/arch/semihosting.h",
"chars": 128,
"preview": "#ifndef _ARCH_SEMIHOSTING_H\n#define _ARCH_SEMIHOSTING_H\n\nvoid v7m_semihost_exit(int status);\n\n#endif /* !_ARCH_SEMIHOSTI"
},
{
"path": "include/arch/v7m-helper.h",
"chars": 444,
"preview": "#ifndef _ARCH_V7M_HELPER_H\n#define _ARCH_V7M_HELPER_H\n\n#define V7M_EXC_RETURN_HANDLER_MAIN 0xfffffff1\n#define V7M_EXC_RE"
},
{
"path": "include/fs/romfs.h",
"chars": 1452,
"preview": "#ifndef _KERNEL_FS_ROMFS_H\n#define _KERNEL_FS_ROMFS_H\n\n#include <kernel/types.h>\n\n#include <drivers/mtd/mtd.h>\n\n#define "
},
{
"path": "include/kernel/bitmap.h",
"chars": 2606,
"preview": "#ifndef _LINUX_BITMAP_H\n#define _LINUX_BITMAP_H\n\n#include \"linux/list.h\"\n#include \"kernel/bitops.h\"\n\nstruct bitmap_struc"
},
{
"path": "include/kernel/bitops.h",
"chars": 1714,
"preview": "#ifndef KERNEL_BITOPS_H\n#define KERNEL_BITOPS_H\n\n#include <sys/param.h>\n\n#include <kernel/bitops.h>\n#include <kernel/ker"
},
{
"path": "include/kernel/cbuf.h",
"chars": 789,
"preview": "#ifndef _KERNEL_CBUF_H\n#define _KERNEL_CBUF_H\n\n#include <sys/types.h>\n\nstruct cbuf_info {\n size_t len;\n int pos_be"
},
{
"path": "include/kernel/compiler.h",
"chars": 182,
"preview": "#ifndef _KERNEL_COMPILER_H\n#define _KERNEL_COMPILER_H\n\n/* GCC weak symbol declaration */\n#ifndef __weak\n#define __weak _"
},
{
"path": "include/kernel/cond.h",
"chars": 222,
"preview": "#ifndef KERNEL_COND_H\n#define KERNEL_COND_H\n\n#include <sys/types.h>\n\nint sys_pthread_cond_wait(pthread_cond_t *cond, pth"
},
{
"path": "include/kernel/errno-base.h",
"chars": 1582,
"preview": "#ifndef _KERNEL_ERRNO_BASE_H_\n#define _KERNEL_ERRNO_BASE_H_\n\n#define EPERM 1 /* Operation not permitted */\n#define EN"
},
{
"path": "include/kernel/faults.h",
"chars": 350,
"preview": "#ifndef KERNEL_FAULTS_H\n#define KERNEL_FAULTS_H\n\n#include <sys/types.h>\n#include <kernel/thread.h>\n\nvoid fault_enter(con"
},
{
"path": "include/kernel/fs.h",
"chars": 5255,
"preview": "#ifndef _KERNEL_FS_H\n#define _KERNEL_FS_H\n\n#include <sys/types.h>\n#include <unistd.h>\n\n#include <piko/dirent.h>\n\n#includ"
},
{
"path": "include/kernel/hash.h",
"chars": 354,
"preview": "#ifndef _KERNEL_HASH_H\n#define _KERNEL_HASH_H\n\n#include <stddef.h>\n\nstatic inline unsigned long hash_djb2(unsigned char "
},
{
"path": "include/kernel/irq.h",
"chars": 1240,
"preview": "#ifndef KERNEL_IRQ_H\n#define KERNEL_IRQ_H\n\n#define NR_IRQS 64\n\n/* irq status */\nenum {\n IRQ_NOREQUEST = 1,\n};\n\n/* irq"
},
{
"path": "include/kernel/kernel.h",
"chars": 1234,
"preview": "#ifndef _KERNEL_KERNEL_H\n#define _KERNEL_KERNEL_H\n\n/* round-down to a power of 2 */\n#define align(x, a) align_mask(x, (_"
},
{
"path": "include/kernel/linkage.h",
"chars": 326,
"preview": "#ifndef _KERNEL_LINKAGE_H\n#define _KERNEL_LINKAGE_H\n\n#ifdef __ASSEMBLER__\n\n#define ENTRY(name) \\\n .globl name; \\\n "
},
{
"path": "include/kernel/log2.h",
"chars": 1965,
"preview": "#ifndef KERNEL_LOG2_H\n#define KERNEL_LOG2_H\n\n#include <kernel/bitops.h>\n\n// clang-format off\n\n#define ilog2(x) "
},
{
"path": "include/kernel/mm/page.h",
"chars": 414,
"preview": "#ifndef _KERNEL_MM_PAGE_H\n#define _KERNEL_MM_PAGE_H\n\n#define MAX_PAGE_ORDER 3 /* max page size is 2 KB */\n#define MIN_P"
},
{
"path": "include/kernel/mm/slab.h",
"chars": 1826,
"preview": "#ifndef _KERNEL_MM_SLAB_H\n#define _KERNEL_MM_SLAB_H\n\n#include <sys/cdefs.h>\n\n#include \"linux/list.h\"\n\n#define CACHE_PAGE"
},
{
"path": "include/kernel/mutex.h",
"chars": 273,
"preview": "#ifndef _KERNEL_MUTEX_H\n#define _KERNEL_MUTEX_H\n\ntypedef _Atomic int atomic_s32;\n\ntypedef struct {\n atomic_s32 val;\n}"
},
{
"path": "include/kernel/sched.h",
"chars": 1089,
"preview": "#ifndef KERNEL_SCHEDULER_H\n#define KERNEL_SCHEDULER_H\n\n#include_next <sched.h>\n\nstruct thread_info;\n\n/* 0 <= PRI_MAX <= "
},
{
"path": "include/kernel/serial.h",
"chars": 2009,
"preview": "/*\n * Interface for serial devices (UART, ...)\n */\n\n#ifndef _KERNEL_SERIAL_H\n#define _KERNEL_SERIAL_H\n\n#include <stdio.h"
},
{
"path": "include/kernel/signal.h",
"chars": 383,
"preview": "#ifndef _KERNEL_SIGNAL_H\n#define _KERNEL_SIGNAL_H\n\n#include <signal.h>\n\n#include <piko/signal.h>\n\n#include <kernel/threa"
},
{
"path": "include/kernel/softirq.h",
"chars": 1304,
"preview": "#ifndef KERNEL_SOFTIRQ_H\n#define KERNEL_SOFTIRQ_H\n\n#include \"linux/list.h\"\n\n#define PRIO_TASKLET_VEC 32\n#define PRIO_TAS"
},
{
"path": "include/kernel/task.h",
"chars": 712,
"preview": "#ifndef _KERNEL_TASK_H\n#define _KERNEL_TASK_H\n\n#include <sys/types.h>\n\n#include <kernel/fs.h>\n\n#include \"linux/list.h\"\n\n"
},
{
"path": "include/kernel/thread.h",
"chars": 6518,
"preview": "#ifndef _KERNEL_THREAD_H\n#define _KERNEL_THREAD_H\n\n#include <sys/types.h>\n\n#include <kernel/kernel.h>\n\n#include \"linux/t"
},
{
"path": "include/kernel/time.h",
"chars": 1257,
"preview": "#ifndef _KERNEL_TIME_H\n#define _KERNEL_TIME_H\n\n#include <signal.h>\n#include <sys/types.h>\n#include <sys/timespec.h> //F"
},
{
"path": "include/kernel/types.h",
"chars": 653,
"preview": "#ifndef _KERNEL_TYPES_H\n#define _KERNEL_TYPES_H\n\n#ifndef _U32\n#define _U32\ntypedef unsigned int u32;\n#endif\n\n#ifndef _S3"
},
{
"path": "include/libc/pthread.h",
"chars": 120,
"preview": "#ifndef PTHREAD_H\n#define PTHREAD_H\n\n#include_next <pthread.h>\n\nextern int pthread_yield(void);\n\n#endif /* PTHREAD_H */\n"
},
{
"path": "include/libc/ucontext.h",
"chars": 617,
"preview": "#ifndef UCONTEXT_H\n#define UCONTEXT_H\n\n#include <signal.h>\n\n#include \"linux/types.h\"\n\n/* machine context on ARM */\ntyped"
},
{
"path": "include/libc/utils.h",
"chars": 267,
"preview": "#ifndef UTILS_H\n#define UTILS_H\n\n#ifndef __LINKER__\n\nstatic inline void infinite_loop(void)\n{\n for (;;)\n ;\n}\n\n"
},
{
"path": "include/linux/compiler.h",
"chars": 234,
"preview": "#ifndef _LINUX_COMPILER_H\n#define _LINUX_COMPILER_H\n\n#define READ_ONCE(x) (x)\n#define WRITE_ONCE(x, val) \\\n ({ "
},
{
"path": "include/linux/list.h",
"chars": 23641,
"preview": "#ifndef _LINUX_LIST_H\n#define _LINUX_LIST_H\n\n#include <stdbool.h>\n\n#include <kernel/kernel.h>\n\n#include \"linux/types.h\"\n"
},
{
"path": "include/linux/poison.h",
"chars": 398,
"preview": "#ifndef LINUX_POISON_H\n#define LINUX_POISON_H\n\n/*\n * These are non-NULL pointers that will result in page faults\n * unde"
},
{
"path": "include/linux/stddef.h",
"chars": 319,
"preview": "#ifndef _LINUX_STDDEF_H\n#define _LINUX_STDDEF_H\n\n#include <stddef.h>\n\n/**\n * offsetofend(TYPE, MEMBER)\n *\n * @TYPE: The "
},
{
"path": "include/linux/types.h",
"chars": 493,
"preview": "#ifndef LINUX_TYPES_H\n#define LINUX_TYPES_H\n\n#define S32_MAX 2147483647\n\ntypedef unsigned int u32;\ntypedef int s32;\n\ntyp"
},
{
"path": "include/piko/arpa/inet.h",
"chars": 454,
"preview": "#ifndef LIBC_ARPA_INET_H\n#define LIBC_ARPA_INET_H\n\n#include <stdint.h>\n\n#include \"platform.h\"\n\nstatic inline uint32_t ht"
},
{
"path": "include/piko/dirent.h",
"chars": 422,
"preview": "#ifndef _LIBPIKO_DIRENT_H\n#define _LIBPIKO_DIRENT_H\n\n#include <sys/types.h>\n\n#define NAME_MAX 32 // FIXME: Include <lim"
},
{
"path": "include/piko/signal.h",
"chars": 2067,
"preview": "#ifndef LIBC_SIGNAL_H\n#define LIBC_SIGNAL_H\n\n#include <sys/types.h>\n\n#include \"linux/list.h\"\n\ntypedef struct {\n void "
},
{
"path": "include/piko/sys/mman.h",
"chars": 637,
"preview": "#ifndef _SYS_MMAN_H\n#define _SYS_MMAN_H\n\n#include <sys/types.h>\n\n#define PROT_NONE 0x00 /* page can not be accessed */\n"
},
{
"path": "include/piko/sys/mount.h",
"chars": 234,
"preview": "#ifndef _SYS_MOUNT_H\n#define _SYS_MOUNT_H\n\nint mount(const char *source,\n const char *target,\n const c"
},
{
"path": "include/piko/sys/resource.h",
"chars": 678,
"preview": "#ifndef SYS_RESOURCE_H\n#define SYS_RESOURCE_H\n\n/* http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_resource."
},
{
"path": "include/platform/compiler.h",
"chars": 270,
"preview": "#ifndef _PLATFORM_COMPILER_H\n#define _PLATFORM_COMPILER_H\n\n#define PLAT_EVAL(macro) \\\n ({ "
},
{
"path": "include/version.template.h",
"chars": 192,
"preview": "#ifndef VERSION_H\n#define VERSION_H\n\n#define VER_MAJOR \"0\"\n#define VER_MINOR \"0\"\n#define VER_MICRO \"0\"\n\n#define VER_SLUG"
},
{
"path": "kernel/cond.c",
"chars": 1179,
"preview": "#include <sys/types.h>\n\n#include <kernel/mutex.h>\n#include <kernel/sched.h>\n#include <kernel/thread.h>\n\n#include \"linux/"
},
{
"path": "kernel/config.c",
"chars": 422,
"preview": "#include <unistd.h>\n\nenum sc_varname {\n PAGESIZE,\n};\n\nstruct sys_param {\n const char *name;\n long value;\n};\n\nst"
},
{
"path": "kernel/faults.c",
"chars": 628,
"preview": "#include <kernel/faults.h>\n#include <kernel/thread.h>\n\n#include \"kernel.h\"\n#include \"utils.h\"\n#include \"platform.h\"\n\nvoi"
},
{
"path": "kernel/fs/fs.c",
"chars": 5020,
"preview": "#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#include <kerne"
},
{
"path": "kernel/fs/readdir.c",
"chars": 1014,
"preview": "#include <stdlib.h>\n#include <string.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n\n#include \"linux/list.h\"\n\nsta"
},
{
"path": "kernel/fs/vfs.c",
"chars": 1144,
"preview": "#include <stdlib.h>\n#include <string.h>\n#include <sys/stat.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n\n#inclu"
},
{
"path": "kernel/irq.c",
"chars": 1602,
"preview": "#include <stddef.h>\n#include <stdlib.h>\n#include <kernel/types.h>\n#include <kernel/irq.h>\n\n#define IRQ_MAX 64\n\nirq_handl"
},
{
"path": "kernel/main.c",
"chars": 5297,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <sys/cdefs.h>\n#include <sys/fcntl.h>\n\n#include <kernel/fs.h>\n#include <k"
},
{
"path": "kernel/mm/mm.c",
"chars": 2070,
"preview": "#include <errno.h>\n#include <string.h>\n#include <sys/cdefs.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#include <pi"
},
{
"path": "kernel/mm/page.c",
"chars": 4121,
"preview": "#include <stddef.h>\n\n#include <kernel/bitops.h>\n#include <kernel/hash.h>\n#include <kernel/kernel.h>\n#include <kernel/log"
},
{
"path": "kernel/mm/slab.c",
"chars": 4011,
"preview": "#include <stdio.h>\n#include <string.h>\n#include <sys/cdefs.h>\n\n#include <kernel/bitops.h>\n//#include <kernel/kernel.h>\n#"
},
{
"path": "kernel/mutex.c",
"chars": 1637,
"preview": "#include <kernel/kernel.h>\n#include <kernel/mutex.h>\n#include <kernel/sched.h>\n#include <kernel/thread.h>\n\n#include \"lin"
},
{
"path": "kernel/printk.c",
"chars": 1221,
"preview": "#include <stdarg.h>\n#include <stdio.h>\n#include <ucontext.h>\n\n#define VSNPRINTF_BUF_SIZE 256\n\nstatic ucontext_t printk_c"
},
{
"path": "kernel/resource.c",
"chars": 500,
"preview": "#include <piko/sys/resource.h>\n\n// clang-format off\nstatic struct rlimit rlimits[] = {\n { .rlim_cur = 1024, .rlim_max"
},
{
"path": "kernel/sched/bitmap.c",
"chars": 3190,
"preview": "#include <kernel/bitops.h>\n#include <kernel/sched.h>\n#include <kernel/thread.h>\n\n#include \"linux/list.h\"\n#include \"kerne"
},
{
"path": "kernel/sched/rr.c",
"chars": 2334,
"preview": "#include <kernel/sched.h>\n#include <kernel/thread.h>\n\n#include \"linux/list.h\"\n#include \"kernel.h\"\n\nstatic LIST_HEAD(rr_r"
},
{
"path": "kernel/sched.c",
"chars": 1488,
"preview": "#include <kernel/sched.h>\n#include <kernel/thread.h>\n\nextern unsigned long __sched_classes_start__;\nextern unsigned long"
},
{
"path": "kernel/signal.c",
"chars": 6646,
"preview": "#include <errno.h>\n#include <signal.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n\n#include <arch/v7"
},
{
"path": "kernel/softirq.c",
"chars": 3762,
"preview": "#include <kernel/bitops.h>\n#include <kernel/softirq.h>\n#include <kernel/task.h>\n#include <kernel/thread.h>\n#include <ker"
},
{
"path": "kernel/task.c",
"chars": 881,
"preview": "#include <stdlib.h>\n\n#include <kernel/task.h>\n#include <kernel/thread.h>\n\n#include \"linux/list.h\"\n\nstatic LIST_HEAD(task"
},
{
"path": "kernel/thread.c",
"chars": 6737,
"preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/param.h>\n#include <sys/types.h>\n#include <ucont"
},
{
"path": "kernel/time.c",
"chars": 4349,
"preview": "#include <signal.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include <kernel/bitops.h>\n#include <kern"
},
{
"path": "libc/fcntl.c",
"chars": 635,
"preview": "#include <sys/types.h>\n\nextern int _open(const char *pathname, int flag);\nextern int _close(int fd);\nextern int _read(in"
},
{
"path": "libc/filesystem.c",
"chars": 1617,
"preview": "/* syscall wrappers */\n\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#include <kernel/fs.h>\n#include <kernel/syscalls.h"
},
{
"path": "libc/piko/mman.c",
"chars": 491,
"preview": "#include <sys/types.h>\n\n#include <kernel/syscalls.h>\n\n#include \"syscalls.h\"\n\nvoid *mmap(void *addr, size_t length, int p"
},
{
"path": "libc/piko/stubs.c",
"chars": 832,
"preview": "/* Newlib stubs */\n\n#include <stdint.h>\n#include <sys/cdefs.h>\n#include <unistd.h>\n\n#include <kernel/kernel.h>\n#include "
},
{
"path": "libc/piko/syscalls.S",
"chars": 937,
"preview": "#include <kernel/linkage.h>\n#include <kernel/syscalls.h>\n\n\t.syntax unified\n\t.thumb\n\n\t@ int do_syscall0(void, int no)\nENT"
},
{
"path": "libc/piko/syscalls.h",
"chars": 589,
"preview": "/* libc/piko/syscalls.h */\n\n#ifndef LIBC_SYSCALLS_H\n#define LIBC_SYSCALLS_H\n\nint do_syscall0(int no);\nint do_syscall1(vo"
},
{
"path": "libc/pthread.c",
"chars": 2204,
"preview": "#include <pthread.h>\n#include <stddef.h>\n#include <string.h>\n\n#include \"linux/list.h\"\n\nint pthread_attr_setstacksize(pth"
},
{
"path": "libc/signal.c",
"chars": 430,
"preview": "/* syscall wrappers */\n\n#include <signal.h>\n\n#include <kernel/syscalls.h>\n#include \"piko/syscalls.h\"\n\nint sigaction(int "
},
{
"path": "libc/stdio.c",
"chars": 3048,
"preview": "#include <string.h> //XXX: for strlen, strcpy\n#include \"utils.h\"\n#include <stdarg.h>\n#include \"linux/types.h\"\n\nint vsnp"
},
{
"path": "libc/stdlib.c",
"chars": 3549,
"preview": "#include <stdbool.h>\n\n#include <kernel/kernel.h>\n#include <kernel/types.h>\n\n#include \"linux/types.h\"\n#include \"linux/lis"
},
{
"path": "libc/time.c",
"chars": 827,
"preview": "/* syscall wrappers */\n\n#include <signal.h>\n#include <sys/types.h>\n#include <time.h>\n\n#include <kernel/syscalls.h>\n#incl"
},
{
"path": "libc/ucontext.c",
"chars": 1008,
"preview": "#include <stdarg.h>\n#include <ucontext.h>\n\n#include \"linux/types.h\"\n\nvoid return_from_makecontext();\n\nvoid makecontext(u"
},
{
"path": "libc/unistd.c",
"chars": 332,
"preview": "/* syscall wrappers */\n\n#include <kernel/syscalls.h>\n#include \"piko/syscalls.h\"\n\nlong sysconf(int name)\n{\n return do_"
},
{
"path": "libc/utils.c",
"chars": 1034,
"preview": "#include <stdlib.h>\n#include <string.h>\n\nstatic char *strrev(char *s)\n{\n char *t = s;\n char *u = s;\n\n if (!s ||"
},
{
"path": "libc/v7m-pthread.S",
"chars": 1414,
"preview": "#include <kernel/syscalls.h>\n#include <kernel/linkage.h>\n\n\t.syntax unified\n\t.thumb\n\n\t// -1: unlocked, 0: locked, positiv"
},
{
"path": "mk/cmsis.mk",
"chars": 685,
"preview": "SVN_REV = 27441\n\nARM_CMSIS_ASSETS = \\\n\tmbed_toolchain.h \\\n\tmbed_preprocessor.h \\\n\tmbed_assert.h\n\nARM_CMSIS_ASSETS := $(a"
},
{
"path": "mk/flags.mk",
"chars": 940,
"preview": "CROSS_COMPILE ?= arm-none-eabi-\nCC = $(CROSS_COMPILE)gcc\nAS = $(CROSS_COMPILE)as\nAR = $(CROSS_COMPILE)ar\nOBJCOPY = $(CRO"
},
{
"path": "mk/rules.mk",
"chars": 1271,
"preview": "# Control the build verbosity\nifeq (\"$(VERBOSE)\",\"1\")\n Q :=\n VECHO = @true\nelse\n Q := @\n VECHO = @printf\nend"
},
{
"path": "piko.lds.S",
"chars": 2312,
"preview": "OUTPUT_FORMAT(\"elf32-littlearm\")\nOUTPUT_ARCH(arm)\n\n#define RAMORG 0x20000000\n\nMEMORY\n{\n rom (rx) : ORIGIN = 0, LENGT"
},
{
"path": "platform/f429disco/Makefile",
"chars": 1328,
"preview": "CPU = cortex-m4\nARCH = armv7-m\n\nROMSZ = 2048k\nRAMSZ = 192k\n\nCFLAGS += \\\n -Iplatform/f429disco \\\n -I$(CMSIS)\\\n -"
},
{
"path": "platform/f429disco/build.mk",
"chars": 575,
"preview": "run: $(NAME).bin\n\topenocd -f interface/stlink-v2.cfg \\\n\t -f target/stm32f4x_stlink.cfg \\\n\t -c \"init\" \\\n\t -c \"re"
},
{
"path": "platform/f429disco/halt.c",
"chars": 89,
"preview": "\n#include <arch/semihosting.h>\n\nvoid __platform_halt(void)\n{\n v7m_semihost_exit(0);\n}\n"
},
{
"path": "platform/f429disco/init.c",
"chars": 569,
"preview": "#include <serial.h>\n#include <kernel/compiler.h>\n\n#include \"platform.h\"\n\n#define CPU_FREQ_IN_HZ 168000000\n#define SYSTIC"
},
{
"path": "platform/f429disco/platform.h",
"chars": 288,
"preview": "#ifndef _PLATFORM_STM32_PLATFORM_H\n#define _PLATFORM_STM32_PLATFORM_H\n\n#include <cmsis.h>\n\nvoid __platform_init(void);\nv"
},
{
"path": "platform/f429disco/uart.c",
"chars": 3080,
"preview": "#include <serial.h>\n#include <platform/compiler.h>\n\n#include \"platform.h\"\n#include \"kernel/kernel.h\"\n#include \"stm32-uar"
},
{
"path": "platform/stm32p103/Makefile",
"chars": 1236,
"preview": "CPU = cortex-m3\nARCH = armv7-m\n\nROMSZ = 128k\nRAMSZ = 64k\n\nCFLAGS += \\\n -Iplatform/stm32p103 \\\n -I$(CMSIS)\\\n -I$"
},
{
"path": "platform/stm32p103/build.mk",
"chars": 511,
"preview": "ifeq ($(shell lsb_release -c -s),trusty)\n REDIRECT_SERIAL = -serial stdio\nendif\n\nrun: $(NAME).bin\n\t$(Q)$(QEMU_SYSTEM_"
},
{
"path": "platform/stm32p103/halt.c",
"chars": 89,
"preview": "\n#include <arch/semihosting.h>\n\nvoid __platform_halt(void)\n{\n v7m_semihost_exit(0);\n}\n"
},
{
"path": "platform/stm32p103/init.c",
"chars": 602,
"preview": "#include <kernel/compiler.h>\n\n#include \"platform.h\"\n\n#define CPU_FREQ_IN_HZ 72000000\n#define SYSTICK_FREQ_IN_HZ 1000\n#de"
},
{
"path": "platform/stm32p103/platform.h",
"chars": 292,
"preview": "#ifndef _PLATFORM_STM32_PLATFORM_H\n#define _PLATFORM_STM32_PLATFORM_H\n\n#include <cmsis.h>\n\nvoid __platform_init(void);\nv"
},
{
"path": "platform/stm32p103/uart.c",
"chars": 2877,
"preview": "#include <serial.h>\n#include <platform/compiler.h>\n\n#include \"platform.h\"\n#include \"kernel/kernel.h\"\n#include \"stm32-uar"
},
{
"path": "scripts/gen-proc-version.py",
"chars": 1594,
"preview": "import subprocess\nimport string\nfrom datetime import datetime\nimport argparse\n\ndef run_cmd(cmd):\n res = subprocess.ru"
},
{
"path": "scripts/gen-syscalls.py",
"chars": 2128,
"preview": "#!/usr/bin/env python\n\nimport string\nimport argparse\n\nxs = [\n # <pthread.h>\n 'pthread_exit',\n 'pthread_self',\n "
},
{
"path": "scripts/rstlint.py",
"chars": 7583,
"preview": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n#\n# Copyright (C) 2009 Georg Brandl\n#\n# Check for stylistic and formal is"
},
{
"path": "tests/Makefile",
"chars": 1010,
"preview": "CSRC = $(wildcard tests/$(TEST)/*.c)\nSSRC = $(wildcard tests/$(TEST)/*.S)\n\nTEST_OBJ = $(wildcard tests/$(TEST)/*.o)\nLIB_"
},
{
"path": "tests/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/__main__.py",
"chars": 1158,
"preview": "import sys\nif sys.version_info < (3, 5):\n print (\"Only support python version >= 3.5\")\n exit(1)\n\nimport argparse\ni"
},
{
"path": "tests/bitops_1/main.c",
"chars": 625,
"preview": "#include <kernel/bitops.h>\n\n#include \"unit.h\"\n\nint main()\n{\n unsigned long j;\n unsigned long k[2] = {0, 1};\n\n /"
},
{
"path": "tests/cond_1/main.c",
"chars": 1214,
"preview": "/* simple test for condition variable */\n\n#include <pthread.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <sys/cde"
},
{
"path": "tests/cond_2/main.c",
"chars": 2803,
"preview": "/* http://www.ibm.com/support/knowledgecenter/ssw_i5_54/apis/users_76.htm */\n\n#define _MULTI_THREADED\n#include <pthread."
},
{
"path": "tests/cond_3/main.c",
"chars": 1677,
"preview": "/* http://www.qnx.com/developers/docs/660/index.jsp?topic=%2Fcom.qnx.doc.neutrino.getting_started%2Ftopic%2Fs1_procs_con"
},
{
"path": "tests/fs_1/main.c",
"chars": 585,
"preview": "/* test /dev/random */\n\n#include <fcntl.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n\n#include \"unit.h\"\n\nint ma"
},
{
"path": "tests/fs_2/main.c",
"chars": 523,
"preview": "/* test /dev/zero */\n\n#include <fcntl.h>\n#include <string.h>\n\n#include <kernel/fs.h>\n#include <kernel/kernel.h>\n\n#includ"
},
{
"path": "tests/fs_3/data/id_rsa",
"chars": 493,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/WJTcYvsrFML10Z2IBrFi\nfc3Q1x92uTvyFU21cn+/ekU"
},
{
"path": "tests/fs_3/data/id_rsa.pub",
"chars": 182,
"preview": "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/\nWJTcYvsrFML10Z2IBrFifc3Q1x92"
},
{
"path": "tests/fs_3/main.c",
"chars": 1861,
"preview": "/* test simple romFS */\n\n#include <fcntl.h>\n#include <string.h>\n#include <unistd.h>\n\n#include <piko/sys/mount.h>\n\n#inclu"
},
{
"path": "tests/fs_4/data/id_rsa",
"chars": 493,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/WJTcYvsrFML10Z2IBrFi\nfc3Q1x92uTvyFU21cn+/ekU"
},
{
"path": "tests/fs_4/data/id_rsa.pub",
"chars": 182,
"preview": "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/\nWJTcYvsrFML10Z2IBrFifc3Q1x92"
},
{
"path": "tests/fs_4/main.c",
"chars": 1474,
"preview": "/* test overreading a file */\n\n#include <fcntl.h>\n#include <string.h>\n#include <unistd.h>\n\n#include <piko/sys/mount.h>\n\n"
},
{
"path": "tests/fs_5/main.c",
"chars": 565,
"preview": "/* test multiple opening/closing /dev/random */\n\n#include <fcntl.h>\n#include <unistd.h>\n\n#include <kernel/fs.h>\n#include"
},
{
"path": "tests/fs_6/data/id_rsa",
"chars": 493,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/WJTcYvsrFML10Z2IBrFi\nfc3Q1x92uTvyFU21cn+/ekU"
},
{
"path": "tests/fs_6/data/id_rsa.pub",
"chars": 182,
"preview": "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/\nWJTcYvsrFML10Z2IBrFifc3Q1x92"
},
{
"path": "tests/fs_6/main.c",
"chars": 1087,
"preview": "/* open files in romFS multiple times */\n\n#include <fcntl.h>\n\n#include <piko/sys/mount.h>\n\n#include <kernel/fs.h>\n#inclu"
},
{
"path": "tests/fs_7/data/.ssh/id_rsa",
"chars": 493,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/WJTcYvsrFML10Z2IBrFi\nfc3Q1x92uTvyFU21cn+/ekU"
},
{
"path": "tests/fs_7/data/.ssh/id_rsa.pub",
"chars": 182,
"preview": "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/\nWJTcYvsrFML10Z2IBrFifc3Q1x92"
},
{
"path": "tests/fs_7/main.c",
"chars": 1325,
"preview": "/* test directory hierarchy in RomFS */\n\n#include <fcntl.h>\n#include <string.h>\n#include <unistd.h>\n\n#include <piko/sys/"
},
{
"path": "tests/getpid_1/main.c",
"chars": 166,
"preview": "/* simple test for getpid */\n\n#include <unistd.h>\n#include \"unit.h\"\n\nint main()\n{\n pid_t pid = getpid();\n\n if (!pi"
},
{
"path": "tests/itoa_1/main.c",
"chars": 2023,
"preview": "#include \"unit.h\"\n#include \"utils.h\"\n#include <string.h>\n\n#include <kernel/kernel.h>\n\nint itoa_base_00(void)\n{\n char "
},
{
"path": "tests/lib/unit.h",
"chars": 941,
"preview": "#ifndef TEST_LIB_UNIT_H\n#define TEST_LIB_UNIT_H\n\n#include \"kernel.h\"\n\n#define C_GREEN \"\\033[1;32m\"\n#define C_RED \"\\033[1"
},
{
"path": "tests/malloc_1/main.c",
"chars": 1057,
"preview": "#include <stdlib.h>\n#include <string.h>\n\n#include \"unit.h\"\n#include \"kernel.h\"\n\nint main()\n{\n char *p[3], *q[3];\n\n "
},
{
"path": "tests/mm_1/main.c",
"chars": 381,
"preview": "#include <stddef.h>\n\n#include <kernel/mm/page.h>\n#include \"unit.h\"\n\nint main()\n{\n void *p, *q;\n unsigned long orde"
},
{
"path": "tests/mm_2/main.c",
"chars": 571,
"preview": "#include <stddef.h>\n\n#include <kernel/mm/page.h>\n#include \"unit.h\"\n\nint main()\n{\n void *p[14];\n int sz[] = {256, 1"
},
{
"path": "tests/mmap_1/main.c",
"chars": 270,
"preview": "/* simple mmap() test, check non-nil memory is allocated */\n\n#include <stddef.h>\n\n#include <piko/sys/mman.h>\n\n#include \""
},
{
"path": "tests/mmap_2/data/id_rsa",
"chars": 493,
"preview": "-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/WJTcYvsrFML10Z2IBrFi\nfc3Q1x92uTvyFU21cn+/ekU"
},
{
"path": "tests/mmap_2/data/id_rsa.pub",
"chars": 182,
"preview": "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAI/rmTOBknHe2ro+8sUNl1MjNTRopU1/\nWJTcYvsrFML10Z2IBrFifc3Q1x92"
},
{
"path": "tests/mmap_2/main.c",
"chars": 1379,
"preview": "/* test mapping file to memory */\n\n#include <string.h>\n#include <fcntl.h>\n\n#include <piko/sys/mman.h>\n#include <piko/sys"
},
{
"path": "tests/msleep_1/main.c",
"chars": 216,
"preview": "#include \"unit.h\"\n#include \"kernel.h\"\n\nextern void msleep(unsigned int);\n\nint main()\n{\n for (int i = 1; i < 6; i++) {"
},
{
"path": "tests/msleep_2/main.c",
"chars": 583,
"preview": "// simple thread create and thread yield\n\n#include <pthread.h>\n#include <stddef.h>\n#include \"kernel.h\"\n#include \"unit.h\""
},
{
"path": "tests/mtdram_1/main.c",
"chars": 585,
"preview": "/* test simple romFS */\n\n#include <fcntl.h>\n#include <string.h>\n#include <unistd.h>\n\n#include <kernel/fs.h>\n#include <ke"
},
{
"path": "tests/mutex_1/main.c",
"chars": 368,
"preview": "#include <stddef.h>\n\n#include \"kernel.h\"\n#include \"pthread.h\"\n#include \"unit.h\"\n\nint main(void)\n{\n pthread_mutex_t lo"
},
{
"path": "tests/mutex_2/main.c",
"chars": 1152,
"preview": "#include <stddef.h>\n#include <stdlib.h>\n#include <sys/cdefs.h>\n\n#include \"kernel.h\"\n#include \"pthread.h\"\n#include \"unit."
},
{
"path": "tests/mutex_3/main.c",
"chars": 603,
"preview": "/* test the trylock interface */\n\n#include <stddef.h>\n\n#include \"kernel.h\"\n#include \"pthread.h\"\n#include \"unit.h\"\n\nint m"
}
]
// ... and 42 more files (download for full content)
About this extraction
This page contains the full source code of the Piko-RT/pikoRT GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 242 files (316.2 KB), approximately 96.9k tokens, and a symbol index with 808 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.