diff --git a/src/LICENSE b/src/LICENSE deleted file mode 100644 index 8702541a9c913e71669cc6ef62cef16543f688c4..0000000000000000000000000000000000000000 --- a/src/LICENSE +++ /dev/null @@ -1,95 +0,0 @@ -Pintos, including its documentation, is subject to the following -license: - - Copyright (C) 2004, 2005, 2006 Board of Trustees, Leland Stanford - Jr. University. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -A few individual files in Pintos were originally derived from other -projects, but they have been extensively modified for use in Pintos. -The original code falls under the original license, and modifications -for Pintos are additionally covered by the Pintos license above. - -In particular, code derived from Nachos is subject to the following -license: - -/* Copyright (c) 1992-1996 The Regents of the University of California. - All rights reserved. - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose, without fee, and - without written agreement is hereby granted, provided that the - above copyright notice and the following two paragraphs appear - in all copies of this software. - - IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO - ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR - CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE - AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA - HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" - BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -*/ - -Also, code derived from MIT's 6.828 course code is subject to the -following license: - -/* - * Copyright (C) 1997 Massachusetts Institute of Technology - * - * This software is being provided by the copyright holders under the - * following license. By obtaining, using and/or copying this software, - * you agree that you have read, understood, and will comply with the - * following terms and conditions: - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose and without fee or royalty is - * hereby granted, provided that the full text of this NOTICE appears on - * ALL copies of the software and documentation or portions thereof, - * including modifications, that you make. - * - * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO - * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, - * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR - * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR - * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY - * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT - * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR - * DOCUMENTATION. - * - * The name and trademarks of copyright holders may NOT be used in - * advertising or publicity pertaining to the software without specific, - * written prior permission. Title to copyright in this software and any - * associated documentation will at all times remain with copyright - * holders. See the file AUTHORS which should have accompanied this software - * for a list of all copyright holders. - * - * This file may be derived from previously copyrighted software. This - * copyright applies only to those changes made by the copyright - * holders listed in the AUTHORS file. The rest of this file is covered by - * the copyright notices, if any, listed below. - */ diff --git a/src/Make.config b/src/Make.config deleted file mode 100644 index 5b87b7b24ce63a9e0dac0437c4be72b570b51805..0000000000000000000000000000000000000000 --- a/src/Make.config +++ /dev/null @@ -1,63 +0,0 @@ -# -*- makefile -*- - -SHELL = /bin/sh - -VPATH = $(SRCDIR) - -# Binary utilities. -# If the host appears to be x86, use the normal tools. -# If it's x86-64, use the compiler and linker in 32-bit mode. -# Otherwise assume cross-tools are installed as i386-elf-*. -X86 = i.86\|pentium.*\|[pk][56]\|nexgen\|viac3\|6x86\|athlon.*\|i86pc -X86_64 = x86_64 - -# Pintos doesn't compile/run properly using gcc 4.3+. Force 4.1 for now. -CCPROG = /usr/class/cs140/x86_64/bin/i586-elf-gcc -ifeq ($(strip $(shell command -v $(CCPROG) 2> /dev/null)),) - CCPROG = gcc -endif - -ifneq (0, $(shell expr `uname -m` : '$(X86)')) - CC = $(CCPROG) - LD = ld - OBJCOPY = objcopy -else - ifneq (0, $(shell expr `uname -m` : '$(X86_64)')) - CC = $(CCPROG) -m32 - LD = ld -melf_i386 - OBJCOPY = objcopy - else - CC = i386-elf-gcc - LD = i386-elf-ld - OBJCOPY = i386-elf-objcopy - endif -endif - -ifeq ($(strip $(shell command -v $(CC) 2> /dev/null)),) -$(warning *** Compiler ($(CC)) not found. Did you set $$PATH properly? Please refer to the Getting Started section in the documentation for details. ***) -endif - -# Compiler and assembler invocation. -DEFINES = -WARNINGS = -Wall -W -Wstrict-prototypes -Wmissing-prototypes -Wsystem-headers -CFLAGS = -g -msoft-float -O -DBEN_MODS -std=gnu99 -CPPFLAGS = -nostdinc -I$(SRCDIR) -I$(SRCDIR)/lib -ASFLAGS = -Wa,--gstabs -LDFLAGS = -DEPS = -MMD -MF $(@:.o=.d) - -# Turn off -fstack-protector, which we don't support. -ifeq ($(strip $(shell echo | $(CC) -fno-stack-protector -E - > /dev/null 2>&1; echo $$?)),0) -CFLAGS += -fno-stack-protector -endif - -# Turn off --build-id in the linker, which confuses the Pintos loader. -ifeq ($(strip $(shell $(LD) --help | grep -q build-id; echo $$?)),0) -LDFLAGS += -Wl,--build-id=none -endif - -%.o: %.c - $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) $(WARNINGS) $(DEFINES) $(DEPS) - -%.o: %.S - $(CC) -c $< -o $@ $(ASFLAGS) $(CPPFLAGS) $(DEFINES) $(DEPS) diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 229f85d1dcc3deb707c897033bc0327f10eddc4d..0000000000000000000000000000000000000000 --- a/src/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -BUILD_SUBDIRS = threads userprog vm filesys - -all:: - @echo "Run 'make' in subdirectories: $(BUILD_SUBDIRS)." - @echo "This top-level make has only 'clean' targets." - -CLEAN_SUBDIRS = $(BUILD_SUBDIRS) examples utils - -clean:: - for d in $(CLEAN_SUBDIRS); do $(MAKE) -C $$d $@; done - rm -f TAGS tags - -distclean:: clean - find . -name '*~' -exec rm '{}' \; - -TAGS_SUBDIRS = $(BUILD_SUBDIRS) devices lib -TAGS_SOURCES = find $(TAGS_SUBDIRS) -name \*.[chS] -print - -TAGS:: - etags --members `$(TAGS_SOURCES)` - -tags:: - ctags -T --no-warn `$(TAGS_SOURCES)` - -cscope.files:: - $(TAGS_SOURCES) > cscope.files - -cscope:: cscope.files - cscope -b -q -k diff --git a/src/Makefile.build b/src/Makefile.build deleted file mode 100644 index e997d2787543cb4860edff352660dea9ae350bcf..0000000000000000000000000000000000000000 --- a/src/Makefile.build +++ /dev/null @@ -1,109 +0,0 @@ -# -*- makefile -*- - -SRCDIR = ../.. - -all: kernel.bin loader.bin - -include ../../Make.config -include ../Make.vars -include ../../tests/Make.tests - -# Compiler and assembler options. -kernel.bin: CPPFLAGS += -I$(SRCDIR)/lib/kernel - -# Core kernel. -threads_SRC = threads/start.S # Startup code. -threads_SRC += threads/init.c # Main program. -threads_SRC += threads/thread.c # Thread management core. -threads_SRC += threads/switch.S # Thread switch routine. -threads_SRC += threads/interrupt.c # Interrupt core. -threads_SRC += threads/intr-stubs.S # Interrupt stubs. -threads_SRC += threads/synch.c # Synchronization. -threads_SRC += threads/palloc.c # Page allocator. -threads_SRC += threads/malloc.c # Subpage allocator. - -# Device driver code. -devices_SRC = devices/pit.c # Programmable interrupt timer chip. -devices_SRC += devices/timer.c # Periodic timer device. -devices_SRC += devices/kbd.c # Keyboard device. -devices_SRC += devices/vga.c # Video device. -devices_SRC += devices/serial.c # Serial port device. -devices_SRC += devices/block.c # Block device abstraction layer. -devices_SRC += devices/partition.c # Partition block device. -devices_SRC += devices/ide.c # IDE disk block device. -devices_SRC += devices/input.c # Serial and keyboard input. -devices_SRC += devices/intq.c # Interrupt queue. -devices_SRC += devices/rtc.c # Real-time clock. -devices_SRC += devices/shutdown.c # Reboot and power off. -devices_SRC += devices/speaker.c # PC speaker. - -# Library code shared between kernel and user programs. -lib_SRC = lib/debug.c # Debug helpers. -lib_SRC += lib/random.c # Pseudo-random numbers. -lib_SRC += lib/stdio.c # I/O library. -lib_SRC += lib/stdlib.c # Utility functions. -lib_SRC += lib/string.c # String functions. -lib_SRC += lib/arithmetic.c # 64-bit arithmetic for GCC. -lib_SRC += lib/ustar.c # Unix standard tar format utilities. - -# Kernel-specific library code. -lib/kernel_SRC = lib/kernel/debug.c # Debug helpers. -lib/kernel_SRC += lib/kernel/list.c # Doubly-linked lists. -lib/kernel_SRC += lib/kernel/bitmap.c # Bitmaps. -lib/kernel_SRC += lib/kernel/hash.c # Hash tables. -lib/kernel_SRC += lib/kernel/console.c # printf(), putchar(). - -# User process code. -userprog_SRC = userprog/process.c # Process loading. -userprog_SRC += userprog/pagedir.c # Page directories. -userprog_SRC += userprog/exception.c # User exception handler. -userprog_SRC += userprog/syscall.c # System call handler. -userprog_SRC += userprog/gdt.c # GDT initialization. -userprog_SRC += userprog/tss.c # TSS management. - -# No virtual memory code yet. -#vm_SRC = vm/file.c # Some file. - -# Filesystem code. -filesys_SRC = filesys/filesys.c # Filesystem core. -filesys_SRC += filesys/free-map.c # Free sector bitmap. -filesys_SRC += filesys/file.c # Files. -filesys_SRC += filesys/directory.c # Directories. -filesys_SRC += filesys/inode.c # File headers. -filesys_SRC += filesys/fsutil.c # Utilities. - -SOURCES = $(foreach dir,$(KERNEL_SUBDIRS),$($(dir)_SRC)) -OBJECTS = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(SOURCES))) -DEPENDS = $(patsubst %.o,%.d,$(OBJECTS)) - -threads/kernel.lds.s: CPPFLAGS += -P -threads/kernel.lds.s: threads/kernel.lds.S threads/loader.h - -kernel.o: threads/kernel.lds.s $(OBJECTS) - $(LD) -T $< -o $@ $(OBJECTS) - -kernel.bin: kernel.o - $(OBJCOPY) -R .note -R .comment -S $< $@ - -threads/loader.o: threads/loader.S - $(CC) -c $< -o $@ $(ASFLAGS) $(CPPFLAGS) $(DEFINES) - -loader.bin: threads/loader.o - $(LD) -N -e 0 -Ttext 0x7c00 --oformat binary -o $@ $< - -os.dsk: kernel.bin - cat $^ > $@ - -clean:: - rm -f $(OBJECTS) $(DEPENDS) - rm -f threads/loader.o threads/kernel.lds.s threads/loader.d - rm -f kernel.bin.tmp - rm -f kernel.o kernel.lds.s - rm -f kernel.bin loader.bin - rm -f bochsout.txt bochsrc.txt - rm -f results grade - -Makefile: $(SRCDIR)/Makefile.build - cp $< $@ - --include $(DEPENDS) diff --git a/src/Makefile.kernel b/src/Makefile.kernel deleted file mode 100644 index 162a4114256891794606019b106dc6d67353c323..0000000000000000000000000000000000000000 --- a/src/Makefile.kernel +++ /dev/null @@ -1,20 +0,0 @@ -# -*- makefile -*- - -all: - -include Make.vars - -DIRS = $(sort $(addprefix build/,$(KERNEL_SUBDIRS) $(TEST_SUBDIRS) lib/user)) - -all grade check: $(DIRS) build/Makefile - cd build && $(MAKE) $@ -$(DIRS): - mkdir -p $@ -build/Makefile: ../Makefile.build - cp $< $@ - -build/%: $(DIRS) build/Makefile - cd build && $(MAKE) $* - -clean: - rm -rf build diff --git a/src/Makefile.userprog b/src/Makefile.userprog deleted file mode 100644 index 0df391a24ed164db4fc6febe3d44c33443a30769..0000000000000000000000000000000000000000 --- a/src/Makefile.userprog +++ /dev/null @@ -1,52 +0,0 @@ -# -*- makefile -*- - -$(PROGS): CPPFLAGS += -I$(SRCDIR)/lib/user -I. - -# Linker flags. -$(PROGS): LDFLAGS += -nostdlib -static -Wl,-T,$(LDSCRIPT) -$(PROGS): LDSCRIPT = $(SRCDIR)/lib/user/user.lds - -# Library code shared between kernel and user programs. -lib_SRC = lib/debug.c # Debug code. -lib_SRC += lib/random.c # Pseudo-random numbers. -lib_SRC += lib/stdio.c # I/O library. -lib_SRC += lib/stdlib.c # Utility functions. -lib_SRC += lib/string.c # String functions. -lib_SRC += lib/arithmetic.c # 64-bit arithmetic for GCC. -lib_SRC += lib/ustar.c # Unix standard tar format utilities. - -# User level only library code. -lib/user_SRC = lib/user/debug.c # Debug helpers. -lib/user_SRC += lib/user/syscall.c # System calls. -lib/user_SRC += lib/user/console.c # Console code. - -LIB_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(lib_SRC) $(lib/user_SRC))) -LIB_DEP = $(patsubst %.o,%.d,$(LIB_OBJ)) -LIB = lib/user/entry.o libc.a - -PROGS_SRC = $(foreach prog,$(PROGS),$($(prog)_SRC)) -PROGS_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(PROGS_SRC))) -PROGS_DEP = $(patsubst %.o,%.d,$(PROGS_OBJ)) - -all: $(PROGS) - -define TEMPLATE -$(1)_OBJ = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$($(1)_SRC))) -$(1): $$($(1)_OBJ) $$(LIB) $$(LDSCRIPT) - $$(CC) $$(LDFLAGS) $$($(1)_OBJ) $$(LIB) -o $$@ -endef - -$(foreach prog,$(PROGS),$(eval $(call TEMPLATE,$(prog)))) - -libc.a: $(LIB_OBJ) - rm -f $@ - ar r $@ $^ - ranlib $@ - -clean:: - rm -f $(PROGS) $(PROGS_OBJ) $(PROGS_DEP) - rm -f $(LIB_DEP) $(LIB_OBJ) lib/user/entry.[do] libc.a - -.PHONY: all clean - --include $(LIB_DEP) $(PROGS_DEP) diff --git a/src/devices/block.c b/src/devices/block.c deleted file mode 100644 index a3acec16066240cc098f0c31d5a5c53efb99116a..0000000000000000000000000000000000000000 --- a/src/devices/block.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "devices/block.h" -#include <list.h> -#include <string.h> -#include <stdio.h> -#include "devices/ide.h" -#include "threads/malloc.h" - -/* A block device. */ -struct block - { - struct list_elem list_elem; /* Element in all_blocks. */ - - char name[16]; /* Block device name. */ - enum block_type type; /* Type of block device. */ - block_sector_t size; /* Size in sectors. */ - - const struct block_operations *ops; /* Driver operations. */ - void *aux; /* Extra data owned by driver. */ - - unsigned long long read_cnt; /* Number of sectors read. */ - unsigned long long write_cnt; /* Number of sectors written. */ - }; - -/* List of all block devices. */ -static struct list all_blocks = LIST_INITIALIZER (all_blocks); - -/* The block block assigned to each Pintos role. */ -static struct block *block_by_role[BLOCK_ROLE_CNT]; - -static struct block *list_elem_to_block (struct list_elem *); - -/* Returns a human-readable name for the given block device - TYPE. */ -const char * -block_type_name (enum block_type type) -{ - static const char *block_type_names[BLOCK_CNT] = - { - "kernel", - "filesys", - "scratch", - "swap", - "raw", - "foreign", - }; - - ASSERT (type < BLOCK_CNT); - return block_type_names[type]; -} - -/* Returns the block device fulfilling the given ROLE, or a null - pointer if no block device has been assigned that role. */ -struct block * -block_get_role (enum block_type role) -{ - ASSERT (role < BLOCK_ROLE_CNT); - return block_by_role[role]; -} - -/* Assigns BLOCK the given ROLE. */ -void -block_set_role (enum block_type role, struct block *block) -{ - ASSERT (role < BLOCK_ROLE_CNT); - block_by_role[role] = block; -} - -/* Returns the first block device in kernel probe order, or a - null pointer if no block devices are registered. */ -struct block * -block_first (void) -{ - return list_elem_to_block (list_begin (&all_blocks)); -} - -/* Returns the block device following BLOCK in kernel probe - order, or a null pointer if BLOCK is the last block device. */ -struct block * -block_next (struct block *block) -{ - return list_elem_to_block (list_next (&block->list_elem)); -} - -/* Returns the block device with the given NAME, or a null - pointer if no block device has that name. */ -struct block * -block_get_by_name (const char *name) -{ - struct list_elem *e; - - for (e = list_begin (&all_blocks); e != list_end (&all_blocks); - e = list_next (e)) - { - struct block *block = list_entry (e, struct block, list_elem); - if (!strcmp (name, block->name)) - return block; - } - - return NULL; -} - -/* Verifies that SECTOR is a valid offset within BLOCK. - Panics if not. */ -static void -check_sector (struct block *block, block_sector_t sector) -{ - if (sector >= block->size) - { - /* We do not use ASSERT because we want to panic here - regardless of whether NDEBUG is defined. */ - PANIC ("Access past end of device %s (sector=%"PRDSNu", " - "size=%"PRDSNu")\n", block_name (block), sector, block->size); - } -} - -/* Reads sector SECTOR from BLOCK into BUFFER, which must - have room for BLOCK_SECTOR_SIZE bytes. - Internally synchronizes accesses to block devices, so external - per-block device locking is unneeded. */ -void -block_read (struct block *block, block_sector_t sector, void *buffer) -{ - check_sector (block, sector); - block->ops->read (block->aux, sector, buffer); - block->read_cnt++; -} - -/* Write sector SECTOR to BLOCK from BUFFER, which must contain - BLOCK_SECTOR_SIZE bytes. Returns after the block device has - acknowledged receiving the data. - Internally synchronizes accesses to block devices, so external - per-block device locking is unneeded. */ -void -block_write (struct block *block, block_sector_t sector, const void *buffer) -{ - check_sector (block, sector); - ASSERT (block->type != BLOCK_FOREIGN); - block->ops->write (block->aux, sector, buffer); - block->write_cnt++; -} - -/* Returns the number of sectors in BLOCK. */ -block_sector_t -block_size (struct block *block) -{ - return block->size; -} - -/* Returns BLOCK's name (e.g. "hda"). */ -const char * -block_name (struct block *block) -{ - return block->name; -} - -/* Returns BLOCK's type. */ -enum block_type -block_type (struct block *block) -{ - return block->type; -} - -/* Prints statistics for each block device used for a Pintos role. */ -void -block_print_stats (void) -{ - int i; - - for (i = 0; i < BLOCK_ROLE_CNT; i++) - { - struct block *block = block_by_role[i]; - if (block != NULL) - { - printf ("%s (%s): %llu reads, %llu writes\n", - block->name, block_type_name (block->type), - block->read_cnt, block->write_cnt); - } - } -} - -/* Registers a new block device with the given NAME. If - EXTRA_INFO is non-null, it is printed as part of a user - message. The block device's SIZE in sectors and its TYPE must - be provided, as well as the it operation functions OPS, which - will be passed AUX in each function call. */ -struct block * -block_register (const char *name, enum block_type type, - const char *extra_info, block_sector_t size, - const struct block_operations *ops, void *aux) -{ - struct block *block = malloc (sizeof *block); - if (block == NULL) - PANIC ("Failed to allocate memory for block device descriptor"); - - list_push_back (&all_blocks, &block->list_elem); - strlcpy (block->name, name, sizeof block->name); - block->type = type; - block->size = size; - block->ops = ops; - block->aux = aux; - block->read_cnt = 0; - block->write_cnt = 0; - - printf ("%s: %'"PRDSNu" sectors (", block->name, block->size); - print_human_readable_size ((uint64_t) block->size * BLOCK_SECTOR_SIZE); - printf (")"); - if (extra_info != NULL) - printf (", %s", extra_info); - printf ("\n"); - - return block; -} - -/* Returns the block device corresponding to LIST_ELEM, or a null - pointer if LIST_ELEM is the list end of all_blocks. */ -static struct block * -list_elem_to_block (struct list_elem *list_elem) -{ - return (list_elem != list_end (&all_blocks) - ? list_entry (list_elem, struct block, list_elem) - : NULL); -} - diff --git a/src/devices/block.h b/src/devices/block.h deleted file mode 100644 index 21732d6eed68e4f43b00b9c5437da93fd0962c25..0000000000000000000000000000000000000000 --- a/src/devices/block.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef DEVICES_BLOCK_H -#define DEVICES_BLOCK_H - -#include <stddef.h> -#include <inttypes.h> - -/* Size of a block device sector in bytes. - All IDE disks use this sector size, as do most USB and SCSI - disks. It's not worth it to try to cater to other sector - sizes in Pintos (yet). */ -#define BLOCK_SECTOR_SIZE 512 - -/* Index of a block device sector. - Good enough for devices up to 2 TB. */ -typedef uint32_t block_sector_t; - -/* Format specifier for printf(), e.g.: - printf ("sector=%"PRDSNu"\n", sector); */ -#define PRDSNu PRIu32 - -/* Higher-level interface for file systems, etc. */ - -struct block; - -/* Type of a block device. */ -enum block_type - { - /* Block device types that play a role in Pintos. */ - BLOCK_KERNEL, /* Pintos OS kernel. */ - BLOCK_FILESYS, /* File system. */ - BLOCK_SCRATCH, /* Scratch. */ - BLOCK_SWAP, /* Swap. */ - BLOCK_ROLE_CNT, - - /* Other kinds of block devices that Pintos may see but does - not interact with. */ - BLOCK_RAW = BLOCK_ROLE_CNT, /* "Raw" device with unidentified contents. */ - BLOCK_FOREIGN, /* Owned by non-Pintos operating system. */ - BLOCK_CNT /* Number of Pintos block types. */ - }; - -const char *block_type_name (enum block_type); - -/* Finding block devices. */ -struct block *block_get_role (enum block_type); -void block_set_role (enum block_type, struct block *); -struct block *block_get_by_name (const char *name); - -struct block *block_first (void); -struct block *block_next (struct block *); - -/* Block device operations. */ -block_sector_t block_size (struct block *); -void block_read (struct block *, block_sector_t, void *); -void block_write (struct block *, block_sector_t, const void *); -const char *block_name (struct block *); -enum block_type block_type (struct block *); - -/* Statistics. */ -void block_print_stats (void); - -/* Lower-level interface to block device drivers. */ - -struct block_operations - { - void (*read) (void *aux, block_sector_t, void *buffer); - void (*write) (void *aux, block_sector_t, const void *buffer); - }; - -struct block *block_register (const char *name, enum block_type, - const char *extra_info, block_sector_t size, - const struct block_operations *, void *aux); - -#endif /* devices/block.h */ diff --git a/src/devices/ide.c b/src/devices/ide.c deleted file mode 100644 index 2cc02927f24c4e1264e240f18e850447c6ae3c33..0000000000000000000000000000000000000000 --- a/src/devices/ide.c +++ /dev/null @@ -1,527 +0,0 @@ -#include "devices/ide.h" -#include <ctype.h> -#include <debug.h> -#include <stdbool.h> -#include <stdio.h> -#include "devices/block.h" -#include "devices/partition.h" -#include "devices/timer.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "threads/synch.h" - -/* The code in this file is an interface to an ATA (IDE) - controller. It attempts to comply to [ATA-3]. */ - -/* ATA command block port addresses. */ -#define reg_data(CHANNEL) ((CHANNEL)->reg_base + 0) /* Data. */ -#define reg_error(CHANNEL) ((CHANNEL)->reg_base + 1) /* Error. */ -#define reg_nsect(CHANNEL) ((CHANNEL)->reg_base + 2) /* Sector Count. */ -#define reg_lbal(CHANNEL) ((CHANNEL)->reg_base + 3) /* LBA 0:7. */ -#define reg_lbam(CHANNEL) ((CHANNEL)->reg_base + 4) /* LBA 15:8. */ -#define reg_lbah(CHANNEL) ((CHANNEL)->reg_base + 5) /* LBA 23:16. */ -#define reg_device(CHANNEL) ((CHANNEL)->reg_base + 6) /* Device/LBA 27:24. */ -#define reg_status(CHANNEL) ((CHANNEL)->reg_base + 7) /* Status (r/o). */ -#define reg_command(CHANNEL) reg_status (CHANNEL) /* Command (w/o). */ - -/* ATA control block port addresses. - (If we supported non-legacy ATA controllers this would not be - flexible enough, but it's fine for what we do.) */ -#define reg_ctl(CHANNEL) ((CHANNEL)->reg_base + 0x206) /* Control (w/o). */ -#define reg_alt_status(CHANNEL) reg_ctl (CHANNEL) /* Alt Status (r/o). */ - -/* Alternate Status Register bits. */ -#define STA_BSY 0x80 /* Busy. */ -#define STA_DRDY 0x40 /* Device Ready. */ -#define STA_DRQ 0x08 /* Data Request. */ - -/* Control Register bits. */ -#define CTL_SRST 0x04 /* Software Reset. */ - -/* Device Register bits. */ -#define DEV_MBS 0xa0 /* Must be set. */ -#define DEV_LBA 0x40 /* Linear based addressing. */ -#define DEV_DEV 0x10 /* Select device: 0=master, 1=slave. */ - -/* Commands. - Many more are defined but this is the small subset that we - use. */ -#define CMD_IDENTIFY_DEVICE 0xec /* IDENTIFY DEVICE. */ -#define CMD_READ_SECTOR_RETRY 0x20 /* READ SECTOR with retries. */ -#define CMD_WRITE_SECTOR_RETRY 0x30 /* WRITE SECTOR with retries. */ - -/* An ATA device. */ -struct ata_disk - { - char name[8]; /* Name, e.g. "hda". */ - struct channel *channel; /* Channel that disk is attached to. */ - int dev_no; /* Device 0 or 1 for master or slave. */ - bool is_ata; /* Is device an ATA disk? */ - }; - -/* An ATA channel (aka controller). - Each channel can control up to two disks. */ -struct channel - { - char name[8]; /* Name, e.g. "ide0". */ - uint16_t reg_base; /* Base I/O port. */ - uint8_t irq; /* Interrupt in use. */ - - struct lock lock; /* Must acquire to access the controller. */ - bool expecting_interrupt; /* True if an interrupt is expected, false if - any interrupt would be spurious. */ - struct semaphore completion_wait; /* Up'd by interrupt handler. */ - - struct ata_disk devices[2]; /* The devices on this channel. */ - }; - -/* We support the two "legacy" ATA channels found in a standard PC. */ -#define CHANNEL_CNT 2 -static struct channel channels[CHANNEL_CNT]; - -static struct block_operations ide_operations; - -static void reset_channel (struct channel *); -static bool check_device_type (struct ata_disk *); -static void identify_ata_device (struct ata_disk *); - -static void select_sector (struct ata_disk *, block_sector_t); -static void issue_pio_command (struct channel *, uint8_t command); -static void input_sector (struct channel *, void *); -static void output_sector (struct channel *, const void *); - -static void wait_until_idle (const struct ata_disk *); -static bool wait_while_busy (const struct ata_disk *); -static void select_device (const struct ata_disk *); -static void select_device_wait (const struct ata_disk *); - -static void interrupt_handler (struct intr_frame *); - -/* Initialize the disk subsystem and detect disks. */ -void -ide_init (void) -{ - size_t chan_no; - - for (chan_no = 0; chan_no < CHANNEL_CNT; chan_no++) - { - struct channel *c = &channels[chan_no]; - int dev_no; - - /* Initialize channel. */ - snprintf (c->name, sizeof c->name, "ide%zu", chan_no); - switch (chan_no) - { - case 0: - c->reg_base = 0x1f0; - c->irq = 14 + 0x20; - break; - case 1: - c->reg_base = 0x170; - c->irq = 15 + 0x20; - break; - default: - NOT_REACHED (); - } - lock_init (&c->lock); - c->expecting_interrupt = false; - sema_init (&c->completion_wait, 0); - - /* Initialize devices. */ - for (dev_no = 0; dev_no < 2; dev_no++) - { - struct ata_disk *d = &c->devices[dev_no]; - snprintf (d->name, sizeof d->name, - "hd%c", 'a' + chan_no * 2 + dev_no); - d->channel = c; - d->dev_no = dev_no; - d->is_ata = false; - } - - /* Register interrupt handler. */ - intr_register_ext (c->irq, interrupt_handler, c->name); - - /* Reset hardware. */ - reset_channel (c); - - /* Distinguish ATA hard disks from other devices. */ - if (check_device_type (&c->devices[0])) - check_device_type (&c->devices[1]); - - /* Read hard disk identity information. */ - for (dev_no = 0; dev_no < 2; dev_no++) - if (c->devices[dev_no].is_ata) - identify_ata_device (&c->devices[dev_no]); - } -} - -/* Disk detection and identification. */ - -static char *descramble_ata_string (char *, int size); - -/* Resets an ATA channel and waits for any devices present on it - to finish the reset. */ -static void -reset_channel (struct channel *c) -{ - bool present[2]; - int dev_no; - - /* The ATA reset sequence depends on which devices are present, - so we start by detecting device presence. */ - for (dev_no = 0; dev_no < 2; dev_no++) - { - struct ata_disk *d = &c->devices[dev_no]; - - select_device (d); - - outb (reg_nsect (c), 0x55); - outb (reg_lbal (c), 0xaa); - - outb (reg_nsect (c), 0xaa); - outb (reg_lbal (c), 0x55); - - outb (reg_nsect (c), 0x55); - outb (reg_lbal (c), 0xaa); - - present[dev_no] = (inb (reg_nsect (c)) == 0x55 - && inb (reg_lbal (c)) == 0xaa); - } - - /* Issue soft reset sequence, which selects device 0 as a side effect. - Also enable interrupts. */ - outb (reg_ctl (c), 0); - timer_usleep (10); - outb (reg_ctl (c), CTL_SRST); - timer_usleep (10); - outb (reg_ctl (c), 0); - - timer_msleep (150); - - /* Wait for device 0 to clear BSY. */ - if (present[0]) - { - select_device (&c->devices[0]); - wait_while_busy (&c->devices[0]); - } - - /* Wait for device 1 to clear BSY. */ - if (present[1]) - { - int i; - - select_device (&c->devices[1]); - for (i = 0; i < 3000; i++) - { - if (inb (reg_nsect (c)) == 1 && inb (reg_lbal (c)) == 1) - break; - timer_msleep (10); - } - wait_while_busy (&c->devices[1]); - } -} - -/* Checks whether device D is an ATA disk and sets D's is_ata - member appropriately. If D is device 0 (master), returns true - if it's possible that a slave (device 1) exists on this - channel. If D is device 1 (slave), the return value is not - meaningful. */ -static bool -check_device_type (struct ata_disk *d) -{ - struct channel *c = d->channel; - uint8_t error, lbam, lbah, status; - - select_device (d); - - error = inb (reg_error (c)); - lbam = inb (reg_lbam (c)); - lbah = inb (reg_lbah (c)); - status = inb (reg_status (c)); - - if ((error != 1 && (error != 0x81 || d->dev_no == 1)) - || (status & STA_DRDY) == 0 - || (status & STA_BSY) != 0) - { - d->is_ata = false; - return error != 0x81; - } - else - { - d->is_ata = (lbam == 0 && lbah == 0) || (lbam == 0x3c && lbah == 0xc3); - return true; - } -} - -/* Sends an IDENTIFY DEVICE command to disk D and reads the - response. Registers the disk with the block device - layer. */ -static void -identify_ata_device (struct ata_disk *d) -{ - struct channel *c = d->channel; - char id[BLOCK_SECTOR_SIZE]; - block_sector_t capacity; - char *model, *serial; - char extra_info[128]; - struct block *block; - - ASSERT (d->is_ata); - - /* Send the IDENTIFY DEVICE command, wait for an interrupt - indicating the device's response is ready, and read the data - into our buffer. */ - select_device_wait (d); - issue_pio_command (c, CMD_IDENTIFY_DEVICE); - sema_down (&c->completion_wait); - if (!wait_while_busy (d)) - { - d->is_ata = false; - return; - } - input_sector (c, id); - - /* Calculate capacity. - Read model name and serial number. */ - capacity = *(uint32_t *) &id[60 * 2]; - model = descramble_ata_string (&id[10 * 2], 20); - serial = descramble_ata_string (&id[27 * 2], 40); - snprintf (extra_info, sizeof extra_info, - "model \"%s\", serial \"%s\"", model, serial); - - /* Disable access to IDE disks over 1 GB, which are likely - physical IDE disks rather than virtual ones. If we don't - allow access to those, we're less likely to scribble on - someone's important data. You can disable this check by - hand if you really want to do so. */ - if (capacity >= 1024 * 1024 * 1024 / BLOCK_SECTOR_SIZE) - { - printf ("%s: ignoring ", d->name); - print_human_readable_size (capacity * 512); - printf ("disk for safety\n"); - d->is_ata = false; - return; - } - - /* Register. */ - block = block_register (d->name, BLOCK_RAW, extra_info, capacity, - &ide_operations, d); - partition_scan (block); -} - -/* Translates STRING, which consists of SIZE bytes in a funky - format, into a null-terminated string in-place. Drops - trailing whitespace and null bytes. Returns STRING. */ -static char * -descramble_ata_string (char *string, int size) -{ - int i; - - /* Swap all pairs of bytes. */ - for (i = 0; i + 1 < size; i += 2) - { - char tmp = string[i]; - string[i] = string[i + 1]; - string[i + 1] = tmp; - } - - /* Find the last non-white, non-null character. */ - for (size--; size > 0; size--) - { - int c = string[size - 1]; - if (c != '\0' && !isspace (c)) - break; - } - string[size] = '\0'; - - return string; -} - -/* Reads sector SEC_NO from disk D into BUFFER, which must have - room for BLOCK_SECTOR_SIZE bytes. - Internally synchronizes accesses to disks, so external - per-disk locking is unneeded. */ -static void -ide_read (void *d_, block_sector_t sec_no, void *buffer) -{ - struct ata_disk *d = d_; - struct channel *c = d->channel; - lock_acquire (&c->lock); - select_sector (d, sec_no); - issue_pio_command (c, CMD_READ_SECTOR_RETRY); - sema_down (&c->completion_wait); - if (!wait_while_busy (d)) - PANIC ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no); - input_sector (c, buffer); - lock_release (&c->lock); -} - -/* Write sector SEC_NO to disk D from BUFFER, which must contain - BLOCK_SECTOR_SIZE bytes. Returns after the disk has - acknowledged receiving the data. - Internally synchronizes accesses to disks, so external - per-disk locking is unneeded. */ -static void -ide_write (void *d_, block_sector_t sec_no, const void *buffer) -{ - struct ata_disk *d = d_; - struct channel *c = d->channel; - lock_acquire (&c->lock); - select_sector (d, sec_no); - issue_pio_command (c, CMD_WRITE_SECTOR_RETRY); - if (!wait_while_busy (d)) - PANIC ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no); - output_sector (c, buffer); - sema_down (&c->completion_wait); - lock_release (&c->lock); -} - -static struct block_operations ide_operations = - { - ide_read, - ide_write - }; - -/* Selects device D, waiting for it to become ready, and then - writes SEC_NO to the disk's sector selection registers. (We - use LBA mode.) */ -static void -select_sector (struct ata_disk *d, block_sector_t sec_no) -{ - struct channel *c = d->channel; - - ASSERT (sec_no < (1UL << 28)); - - select_device_wait (d); - outb (reg_nsect (c), 1); - outb (reg_lbal (c), sec_no); - outb (reg_lbam (c), sec_no >> 8); - outb (reg_lbah (c), (sec_no >> 16)); - outb (reg_device (c), - DEV_MBS | DEV_LBA | (d->dev_no == 1 ? DEV_DEV : 0) | (sec_no >> 24)); -} - -/* Writes COMMAND to channel C and prepares for receiving a - completion interrupt. */ -static void -issue_pio_command (struct channel *c, uint8_t command) -{ - /* Interrupts must be enabled or our semaphore will never be - up'd by the completion handler. */ - ASSERT (intr_get_level () == INTR_ON); - - c->expecting_interrupt = true; - outb (reg_command (c), command); -} - -/* Reads a sector from channel C's data register in PIO mode into - SECTOR, which must have room for BLOCK_SECTOR_SIZE bytes. */ -static void -input_sector (struct channel *c, void *sector) -{ - insw (reg_data (c), sector, BLOCK_SECTOR_SIZE / 2); -} - -/* Writes SECTOR to channel C's data register in PIO mode. - SECTOR must contain BLOCK_SECTOR_SIZE bytes. */ -static void -output_sector (struct channel *c, const void *sector) -{ - outsw (reg_data (c), sector, BLOCK_SECTOR_SIZE / 2); -} - -/* Low-level ATA primitives. */ - -/* Wait up to 10 seconds for the controller to become idle, that - is, for the BSY and DRQ bits to clear in the status register. - - As a side effect, reading the status register clears any - pending interrupt. */ -static void -wait_until_idle (const struct ata_disk *d) -{ - int i; - - for (i = 0; i < 1000; i++) - { - if ((inb (reg_status (d->channel)) & (STA_BSY | STA_DRQ)) == 0) - return; - timer_usleep (10); - } - - printf ("%s: idle timeout\n", d->name); -} - -/* Wait up to 30 seconds for disk D to clear BSY, - and then return the status of the DRQ bit. - The ATA standards say that a disk may take as long as that to - complete its reset. */ -static bool -wait_while_busy (const struct ata_disk *d) -{ - struct channel *c = d->channel; - int i; - - for (i = 0; i < 3000; i++) - { - if (i == 700) - printf ("%s: busy, waiting...", d->name); - if (!(inb (reg_alt_status (c)) & STA_BSY)) - { - if (i >= 700) - printf ("ok\n"); - return (inb (reg_alt_status (c)) & STA_DRQ) != 0; - } - timer_msleep (10); - } - - printf ("failed\n"); - return false; -} - -/* Program D's channel so that D is now the selected disk. */ -static void -select_device (const struct ata_disk *d) -{ - struct channel *c = d->channel; - uint8_t dev = DEV_MBS; - if (d->dev_no == 1) - dev |= DEV_DEV; - outb (reg_device (c), dev); - inb (reg_alt_status (c)); - timer_nsleep (400); -} - -/* Select disk D in its channel, as select_device(), but wait for - the channel to become idle before and after. */ -static void -select_device_wait (const struct ata_disk *d) -{ - wait_until_idle (d); - select_device (d); - wait_until_idle (d); -} - -/* ATA interrupt handler. */ -static void -interrupt_handler (struct intr_frame *f) -{ - struct channel *c; - - for (c = channels; c < channels + CHANNEL_CNT; c++) - if (f->vec_no == c->irq) - { - if (c->expecting_interrupt) - { - inb (reg_status (c)); /* Acknowledge interrupt. */ - sema_up (&c->completion_wait); /* Wake up waiter. */ - } - else - printf ("%s: unexpected interrupt\n", c->name); - return; - } - - NOT_REACHED (); -} - - diff --git a/src/devices/ide.h b/src/devices/ide.h deleted file mode 100644 index b35da5e8875eef92f4cb49a441d57977ea8e4f51..0000000000000000000000000000000000000000 --- a/src/devices/ide.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEVICES_IDE_H -#define DEVICES_IDE_H - -void ide_init (void); - -#endif /* devices/ide.h */ diff --git a/src/devices/input.c b/src/devices/input.c deleted file mode 100644 index 4a12160ec721ec4bbeb7bc215ef6dd9afa0b37a8..0000000000000000000000000000000000000000 --- a/src/devices/input.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "devices/input.h" -#include <debug.h> -#include "devices/intq.h" -#include "devices/serial.h" - -/* Stores keys from the keyboard and serial port. */ -static struct intq buffer; - -/* Initializes the input buffer. */ -void -input_init (void) -{ - intq_init (&buffer); -} - -/* Adds a key to the input buffer. - Interrupts must be off and the buffer must not be full. */ -void -input_putc (uint8_t key) -{ - ASSERT (intr_get_level () == INTR_OFF); - ASSERT (!intq_full (&buffer)); - - intq_putc (&buffer, key); - serial_notify (); -} - -/* Retrieves a key from the input buffer. - If the buffer is empty, waits for a key to be pressed. */ -uint8_t -input_getc (void) -{ - enum intr_level old_level; - uint8_t key; - - old_level = intr_disable (); - key = intq_getc (&buffer); - serial_notify (); - intr_set_level (old_level); - - return key; -} - -/* Returns true if the input buffer is full, - false otherwise. - Interrupts must be off. */ -bool -input_full (void) -{ - ASSERT (intr_get_level () == INTR_OFF); - return intq_full (&buffer); -} diff --git a/src/devices/input.h b/src/devices/input.h deleted file mode 100644 index a2f50e938f168d704a945cfbd1d0f9a04aae235d..0000000000000000000000000000000000000000 --- a/src/devices/input.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef DEVICES_INPUT_H -#define DEVICES_INPUT_H - -#include <stdbool.h> -#include <stdint.h> - -void input_init (void); -void input_putc (uint8_t); -uint8_t input_getc (void); -bool input_full (void); - -#endif /* devices/input.h */ diff --git a/src/devices/intq.c b/src/devices/intq.c deleted file mode 100644 index 40b23ae6a48fe5bd0dfd3d1ed65b9ad97c31c505..0000000000000000000000000000000000000000 --- a/src/devices/intq.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "devices/intq.h" -#include <debug.h> -#include "threads/thread.h" - -static int next (int pos); -static void wait (struct intq *q, struct thread **waiter); -static void signal (struct intq *q, struct thread **waiter); - -/* Initializes interrupt queue Q. */ -void -intq_init (struct intq *q) -{ - lock_init (&q->lock); - q->not_full = q->not_empty = NULL; - q->head = q->tail = 0; -} - -/* Returns true if Q is empty, false otherwise. */ -bool -intq_empty (const struct intq *q) -{ - ASSERT (intr_get_level () == INTR_OFF); - return q->head == q->tail; -} - -/* Returns true if Q is full, false otherwise. */ -bool -intq_full (const struct intq *q) -{ - ASSERT (intr_get_level () == INTR_OFF); - return next (q->head) == q->tail; -} - -/* Removes a byte from Q and returns it. - If Q is empty, sleeps until a byte is added. - When called from an interrupt handler, Q must not be empty. */ -uint8_t -intq_getc (struct intq *q) -{ - uint8_t byte; - - ASSERT (intr_get_level () == INTR_OFF); - while (intq_empty (q)) - { - ASSERT (!intr_context ()); - lock_acquire (&q->lock); - wait (q, &q->not_empty); - lock_release (&q->lock); - } - - byte = q->buf[q->tail]; - q->tail = next (q->tail); - signal (q, &q->not_full); - return byte; -} - -/* Adds BYTE to the end of Q. - If Q is full, sleeps until a byte is removed. - When called from an interrupt handler, Q must not be full. */ -void -intq_putc (struct intq *q, uint8_t byte) -{ - ASSERT (intr_get_level () == INTR_OFF); - while (intq_full (q)) - { - ASSERT (!intr_context ()); - lock_acquire (&q->lock); - wait (q, &q->not_full); - lock_release (&q->lock); - } - - q->buf[q->head] = byte; - q->head = next (q->head); - signal (q, &q->not_empty); -} - -/* Returns the position after POS within an intq. */ -static int -next (int pos) -{ - return (pos + 1) % INTQ_BUFSIZE; -} - -/* WAITER must be the address of Q's not_empty or not_full - member. Waits until the given condition is true. */ -static void -wait (struct intq *q UNUSED, struct thread **waiter) -{ - ASSERT (!intr_context ()); - ASSERT (intr_get_level () == INTR_OFF); - ASSERT ((waiter == &q->not_empty && intq_empty (q)) - || (waiter == &q->not_full && intq_full (q))); - - *waiter = thread_current (); - thread_block (); -} - -/* WAITER must be the address of Q's not_empty or not_full - member, and the associated condition must be true. If a - thread is waiting for the condition, wakes it up and resets - the waiting thread. */ -static void -signal (struct intq *q UNUSED, struct thread **waiter) -{ - ASSERT (intr_get_level () == INTR_OFF); - ASSERT ((waiter == &q->not_empty && !intq_empty (q)) - || (waiter == &q->not_full && !intq_full (q))); - - if (*waiter != NULL) - { - thread_unblock (*waiter); - *waiter = NULL; - } -} diff --git a/src/devices/intq.h b/src/devices/intq.h deleted file mode 100644 index 2312b129e1fd984240bc5813d56da9760eb9bd3b..0000000000000000000000000000000000000000 --- a/src/devices/intq.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef DEVICES_INTQ_H -#define DEVICES_INTQ_H - -#include "threads/interrupt.h" -#include "threads/synch.h" - -/* An "interrupt queue", a circular buffer shared between - kernel threads and external interrupt handlers. - - Interrupt queue functions can be called from kernel threads or - from external interrupt handlers. Except for intq_init(), - interrupts must be off in either case. - - The interrupt queue has the structure of a "monitor". Locks - and condition variables from threads/synch.h cannot be used in - this case, as they normally would, because they can only - protect kernel threads from one another, not from interrupt - handlers. */ - -/* Queue buffer size, in bytes. */ -#define INTQ_BUFSIZE 64 - -/* A circular queue of bytes. */ -struct intq - { - /* Waiting threads. */ - struct lock lock; /* Only one thread may wait at once. */ - struct thread *not_full; /* Thread waiting for not-full condition. */ - struct thread *not_empty; /* Thread waiting for not-empty condition. */ - - /* Queue. */ - uint8_t buf[INTQ_BUFSIZE]; /* Buffer. */ - int head; /* New data is written here. */ - int tail; /* Old data is read here. */ - }; - -void intq_init (struct intq *); -bool intq_empty (const struct intq *); -bool intq_full (const struct intq *); -uint8_t intq_getc (struct intq *); -void intq_putc (struct intq *, uint8_t); - -#endif /* devices/intq.h */ diff --git a/src/devices/kbd.c b/src/devices/kbd.c deleted file mode 100644 index fcc82bed0680dee0a9b511b9284ec15b7b328b01..0000000000000000000000000000000000000000 --- a/src/devices/kbd.c +++ /dev/null @@ -1,213 +0,0 @@ -#include "devices/kbd.h" -#include <ctype.h> -#include <debug.h> -#include <stdio.h> -#include <string.h> -#include "devices/input.h" -#include "devices/shutdown.h" -#include "threads/interrupt.h" -#include "threads/io.h" - -/* Keyboard data register port. */ -#define DATA_REG 0x60 - -/* Current state of shift keys. - True if depressed, false otherwise. */ -static bool left_shift, right_shift; /* Left and right Shift keys. */ -static bool left_alt, right_alt; /* Left and right Alt keys. */ -static bool left_ctrl, right_ctrl; /* Left and right Ctl keys. */ - -/* Status of Caps Lock. - True when on, false when off. */ -static bool caps_lock; - -/* Number of keys pressed. */ -static int64_t key_cnt; - -static intr_handler_func keyboard_interrupt; - -/* Initializes the keyboard. */ -void -kbd_init (void) -{ - intr_register_ext (0x21, keyboard_interrupt, "8042 Keyboard"); -} - -/* Prints keyboard statistics. */ -void -kbd_print_stats (void) -{ - printf ("Keyboard: %lld keys pressed\n", key_cnt); -} - -/* Maps a set of contiguous scancodes into characters. */ -struct keymap - { - uint8_t first_scancode; /* First scancode. */ - const char *chars; /* chars[0] has scancode first_scancode, - chars[1] has scancode first_scancode + 1, - and so on to the end of the string. */ - }; - -/* Keys that produce the same characters regardless of whether - the Shift keys are down. Case of letters is an exception - that we handle elsewhere. */ -static const struct keymap invariant_keymap[] = - { - {0x01, "\033"}, /* Escape. */ - {0x0e, "\b"}, - {0x0f, "\tQWERTYUIOP"}, - {0x1c, "\r"}, - {0x1e, "ASDFGHJKL"}, - {0x2c, "ZXCVBNM"}, - {0x37, "*"}, - {0x39, " "}, - {0x53, "\177"}, /* Delete. */ - {0, NULL}, - }; - -/* Characters for keys pressed without Shift, for those keys - where it matters. */ -static const struct keymap unshifted_keymap[] = - { - {0x02, "1234567890-="}, - {0x1a, "[]"}, - {0x27, ";'`"}, - {0x2b, "\\"}, - {0x33, ",./"}, - {0, NULL}, - }; - -/* Characters for keys pressed with Shift, for those keys where - it matters. */ -static const struct keymap shifted_keymap[] = - { - {0x02, "!@#$%^&*()_+"}, - {0x1a, "{}"}, - {0x27, ":\"~"}, - {0x2b, "|"}, - {0x33, "<>?"}, - {0, NULL}, - }; - -static bool map_key (const struct keymap[], unsigned scancode, uint8_t *); - -static void -keyboard_interrupt (struct intr_frame *args UNUSED) -{ - /* Status of shift keys. */ - bool shift = left_shift || right_shift; - bool alt = left_alt || right_alt; - bool ctrl = left_ctrl || right_ctrl; - - /* Keyboard scancode. */ - unsigned code; - - /* False if key pressed, true if key released. */ - bool release; - - /* Character that corresponds to `code'. */ - uint8_t c; - - /* Read scancode, including second byte if prefix code. */ - code = inb (DATA_REG); - if (code == 0xe0) - code = (code << 8) | inb (DATA_REG); - - /* Bit 0x80 distinguishes key press from key release - (even if there's a prefix). */ - release = (code & 0x80) != 0; - code &= ~0x80u; - - /* Interpret key. */ - if (code == 0x3a) - { - /* Caps Lock. */ - if (!release) - caps_lock = !caps_lock; - } - else if (map_key (invariant_keymap, code, &c) - || (!shift && map_key (unshifted_keymap, code, &c)) - || (shift && map_key (shifted_keymap, code, &c))) - { - /* Ordinary character. */ - if (!release) - { - /* Reboot if Ctrl+Alt+Del pressed. */ - if (c == 0177 && ctrl && alt) - shutdown_reboot (); - - /* Handle Ctrl, Shift. - Note that Ctrl overrides Shift. */ - if (ctrl && c >= 0x40 && c < 0x60) - { - /* A is 0x41, Ctrl+A is 0x01, etc. */ - c -= 0x40; - } - else if (shift == caps_lock) - c = tolower (c); - - /* Handle Alt by setting the high bit. - This 0x80 is unrelated to the one used to - distinguish key press from key release. */ - if (alt) - c += 0x80; - - /* Append to keyboard buffer. */ - if (!input_full ()) - { - key_cnt++; - input_putc (c); - } - } - } - else - { - /* Maps a keycode into a shift state variable. */ - struct shift_key - { - unsigned scancode; - bool *state_var; - }; - - /* Table of shift keys. */ - static const struct shift_key shift_keys[] = - { - { 0x2a, &left_shift}, - { 0x36, &right_shift}, - { 0x38, &left_alt}, - {0xe038, &right_alt}, - { 0x1d, &left_ctrl}, - {0xe01d, &right_ctrl}, - {0, NULL}, - }; - - const struct shift_key *key; - - /* Scan the table. */ - for (key = shift_keys; key->scancode != 0; key++) - if (key->scancode == code) - { - *key->state_var = !release; - break; - } - } -} - -/* Scans the array of keymaps K for SCANCODE. - If found, sets *C to the corresponding character and returns - true. - If not found, returns false and C is ignored. */ -static bool -map_key (const struct keymap k[], unsigned scancode, uint8_t *c) -{ - for (; k->first_scancode != 0; k++) - if (scancode >= k->first_scancode - && scancode < k->first_scancode + strlen (k->chars)) - { - *c = k->chars[scancode - k->first_scancode]; - return true; - } - - return false; -} diff --git a/src/devices/kbd.h b/src/devices/kbd.h deleted file mode 100644 index ed9c06bc90d2a03fd9f48c6d245bdcc22770d859..0000000000000000000000000000000000000000 --- a/src/devices/kbd.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef DEVICES_KBD_H -#define DEVICES_KBD_H - -#include <stdint.h> - -void kbd_init (void); -void kbd_print_stats (void); - -#endif /* devices/kbd.h */ diff --git a/src/devices/partition.c b/src/devices/partition.c deleted file mode 100644 index 7e97332da2611580b7e911384ec1978d320520bc..0000000000000000000000000000000000000000 --- a/src/devices/partition.c +++ /dev/null @@ -1,324 +0,0 @@ -#include "devices/partition.h" -#include <packed.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include "devices/block.h" -#include "threads/malloc.h" - -/* A partition of a block device. */ -struct partition - { - struct block *block; /* Underlying block device. */ - block_sector_t start; /* First sector within device. */ - }; - -static struct block_operations partition_operations; - -static void read_partition_table (struct block *, block_sector_t sector, - block_sector_t primary_extended_sector, - int *part_nr); -static void found_partition (struct block *, uint8_t type, - block_sector_t start, block_sector_t size, - int part_nr); -static const char *partition_type_name (uint8_t); - -/* Scans BLOCK for partitions of interest to Pintos. */ -void -partition_scan (struct block *block) -{ - int part_nr = 0; - read_partition_table (block, 0, 0, &part_nr); - if (part_nr == 0) - printf ("%s: Device contains no partitions\n", block_name (block)); -} - -/* Reads the partition table in the given SECTOR of BLOCK and - scans it for partitions of interest to Pintos. - - If SECTOR is 0, so that this is the top-level partition table - on BLOCK, then PRIMARY_EXTENDED_SECTOR is not meaningful; - otherwise, it should designate the sector of the top-level - extended partition table that was traversed to arrive at - SECTOR, for use in finding logical partitions (see the large - comment below). - - PART_NR points to the number of non-empty primary or logical - partitions already encountered on BLOCK. It is incremented as - partitions are found. */ -static void -read_partition_table (struct block *block, block_sector_t sector, - block_sector_t primary_extended_sector, - int *part_nr) -{ - /* Format of a partition table entry. See [Partitions]. */ - struct partition_table_entry - { - uint8_t bootable; /* 0x00=not bootable, 0x80=bootable. */ - uint8_t start_chs[3]; /* Encoded starting cylinder, head, sector. */ - uint8_t type; /* Partition type (see partition_type_name). */ - uint8_t end_chs[3]; /* Encoded ending cylinder, head, sector. */ - uint32_t offset; /* Start sector offset from partition table. */ - uint32_t size; /* Number of sectors. */ - } - PACKED; - - /* Partition table sector. */ - struct partition_table - { - uint8_t loader[446]; /* Loader, in top-level partition table. */ - struct partition_table_entry partitions[4]; /* Table entries. */ - uint16_t signature; /* Should be 0xaa55. */ - } - PACKED; - - struct partition_table *pt; - size_t i; - - /* Check SECTOR validity. */ - if (sector >= block_size (block)) - { - printf ("%s: Partition table at sector %"PRDSNu" past end of device.\n", - block_name (block), sector); - return; - } - - /* Read sector. */ - ASSERT (sizeof *pt == BLOCK_SECTOR_SIZE); - pt = malloc (sizeof *pt); - if (pt == NULL) - PANIC ("Failed to allocate memory for partition table."); - block_read (block, 0, pt); - - /* Check signature. */ - if (pt->signature != 0xaa55) - { - if (primary_extended_sector == 0) - printf ("%s: Invalid partition table signature\n", block_name (block)); - else - printf ("%s: Invalid extended partition table in sector %"PRDSNu"\n", - block_name (block), sector); - free (pt); - return; - } - - /* Parse partitions. */ - for (i = 0; i < sizeof pt->partitions / sizeof *pt->partitions; i++) - { - struct partition_table_entry *e = &pt->partitions[i]; - - if (e->size == 0 || e->type == 0) - { - /* Ignore empty partition. */ - } - else if (e->type == 0x05 /* Extended partition. */ - || e->type == 0x0f /* Windows 98 extended partition. */ - || e->type == 0x85 /* Linux extended partition. */ - || e->type == 0xc5) /* DR-DOS extended partition. */ - { - printf ("%s: Extended partition in sector %"PRDSNu"\n", - block_name (block), sector); - - /* The interpretation of the offset field for extended - partitions is bizarre. When the extended partition - table entry is in the master boot record, that is, - the device's primary partition table in sector 0, then - the offset is an absolute sector number. Otherwise, - no matter how deep the partition table we're reading - is nested, the offset is relative to the start of - the extended partition that the MBR points to. */ - if (sector == 0) - read_partition_table (block, e->offset, e->offset, part_nr); - else - read_partition_table (block, e->offset + primary_extended_sector, - primary_extended_sector, part_nr); - } - else - { - ++*part_nr; - - found_partition (block, e->type, e->offset + sector, - e->size, *part_nr); - } - } - - free (pt); -} - -/* We have found a primary or logical partition of the given TYPE - on BLOCK, starting at sector START and continuing for SIZE - sectors, which we are giving the partition number PART_NR. - Check whether this is a partition of interest to Pintos, and - if so then add it to the proper element of partitions[]. */ -static void -found_partition (struct block *block, uint8_t part_type, - block_sector_t start, block_sector_t size, - int part_nr) -{ - if (start >= block_size (block)) - printf ("%s%d: Partition starts past end of device (sector %"PRDSNu")\n", - block_name (block), part_nr, start); - else if (start + size < start || start + size > block_size (block)) - printf ("%s%d: Partition end (%"PRDSNu") past end of device (%"PRDSNu")\n", - block_name (block), part_nr, start + size, block_size (block)); - else - { - enum block_type type = (part_type == 0x20 ? BLOCK_KERNEL - : part_type == 0x21 ? BLOCK_FILESYS - : part_type == 0x22 ? BLOCK_SCRATCH - : part_type == 0x23 ? BLOCK_SWAP - : BLOCK_FOREIGN); - struct partition *p; - char extra_info[128]; - char name[16]; - - p = malloc (sizeof *p); - if (p == NULL) - PANIC ("Failed to allocate memory for partition descriptor"); - p->block = block; - p->start = start; - - snprintf (name, sizeof name, "%s%d", block_name (block), part_nr); - snprintf (extra_info, sizeof extra_info, "%s (%02x)", - partition_type_name (part_type), part_type); - block_register (name, type, extra_info, size, &partition_operations, p); - } -} - -/* Returns a human-readable name for the given partition TYPE. */ -static const char * -partition_type_name (uint8_t type) -{ - /* Name of each known type of partition. - From util-linux-2.12r/fdisk/i386_sys_types.c. - This initializer makes use of a C99 feature that allows - array elements to be initialized by index. */ - static const char *type_names[256] = - { - [0x00] = "Empty", - [0x01] = "FAT12", - [0x02] = "XENIX root", - [0x03] = "XENIX usr", - [0x04] = "FAT16 <32M", - [0x05] = "Extended", - [0x06] = "FAT16", - [0x07] = "HPFS/NTFS", - [0x08] = "AIX", - [0x09] = "AIX bootable", - [0x0a] = "OS/2 Boot Manager", - [0x0b] = "W95 FAT32", - [0x0c] = "W95 FAT32 (LBA)", - [0x0e] = "W95 FAT16 (LBA)", - [0x0f] = "W95 Ext'd (LBA)", - [0x10] = "OPUS", - [0x11] = "Hidden FAT12", - [0x12] = "Compaq diagnostics", - [0x14] = "Hidden FAT16 <32M", - [0x16] = "Hidden FAT16", - [0x17] = "Hidden HPFS/NTFS", - [0x18] = "AST SmartSleep", - [0x1b] = "Hidden W95 FAT32", - [0x1c] = "Hidden W95 FAT32 (LBA)", - [0x1e] = "Hidden W95 FAT16 (LBA)", - [0x20] = "Pintos OS kernel", - [0x21] = "Pintos file system", - [0x22] = "Pintos scratch", - [0x23] = "Pintos swap", - [0x24] = "NEC DOS", - [0x39] = "Plan 9", - [0x3c] = "PartitionMagic recovery", - [0x40] = "Venix 80286", - [0x41] = "PPC PReP Boot", - [0x42] = "SFS", - [0x4d] = "QNX4.x", - [0x4e] = "QNX4.x 2nd part", - [0x4f] = "QNX4.x 3rd part", - [0x50] = "OnTrack DM", - [0x51] = "OnTrack DM6 Aux1", - [0x52] = "CP/M", - [0x53] = "OnTrack DM6 Aux3", - [0x54] = "OnTrackDM6", - [0x55] = "EZ-Drive", - [0x56] = "Golden Bow", - [0x5c] = "Priam Edisk", - [0x61] = "SpeedStor", - [0x63] = "GNU HURD or SysV", - [0x64] = "Novell Netware 286", - [0x65] = "Novell Netware 386", - [0x70] = "DiskSecure Multi-Boot", - [0x75] = "PC/IX", - [0x80] = "Old Minix", - [0x81] = "Minix / old Linux", - [0x82] = "Linux swap / Solaris", - [0x83] = "Linux", - [0x84] = "OS/2 hidden C: drive", - [0x85] = "Linux extended", - [0x86] = "NTFS volume set", - [0x87] = "NTFS volume set", - [0x88] = "Linux plaintext", - [0x8e] = "Linux LVM", - [0x93] = "Amoeba", - [0x94] = "Amoeba BBT", - [0x9f] = "BSD/OS", - [0xa0] = "IBM Thinkpad hibernation", - [0xa5] = "FreeBSD", - [0xa6] = "OpenBSD", - [0xa7] = "NeXTSTEP", - [0xa8] = "Darwin UFS", - [0xa9] = "NetBSD", - [0xab] = "Darwin boot", - [0xb7] = "BSDI fs", - [0xb8] = "BSDI swap", - [0xbb] = "Boot Wizard hidden", - [0xbe] = "Solaris boot", - [0xbf] = "Solaris", - [0xc1] = "DRDOS/sec (FAT-12)", - [0xc4] = "DRDOS/sec (FAT-16 < 32M)", - [0xc6] = "DRDOS/sec (FAT-16)", - [0xc7] = "Syrinx", - [0xda] = "Non-FS data", - [0xdb] = "CP/M / CTOS / ...", - [0xde] = "Dell Utility", - [0xdf] = "BootIt", - [0xe1] = "DOS access", - [0xe3] = "DOS R/O", - [0xe4] = "SpeedStor", - [0xeb] = "BeOS fs", - [0xee] = "EFI GPT", - [0xef] = "EFI (FAT-12/16/32)", - [0xf0] = "Linux/PA-RISC boot", - [0xf1] = "SpeedStor", - [0xf4] = "SpeedStor", - [0xf2] = "DOS secondary", - [0xfd] = "Linux raid autodetect", - [0xfe] = "LANstep", - [0xff] = "BBT", - }; - - return type_names[type] != NULL ? type_names[type] : "Unknown"; -} - -/* Reads sector SECTOR from partition P into BUFFER, which must - have room for BLOCK_SECTOR_SIZE bytes. */ -static void -partition_read (void *p_, block_sector_t sector, void *buffer) -{ - struct partition *p = p_; - block_read (p->block, p->start + sector, buffer); -} - -/* Write sector SECTOR to partition P from BUFFER, which must - contain BLOCK_SECTOR_SIZE bytes. Returns after the block has - acknowledged receiving the data. */ -static void -partition_write (void *p_, block_sector_t sector, const void *buffer) -{ - struct partition *p = p_; - block_write (p->block, p->start + sector, buffer); -} - -static struct block_operations partition_operations = - { - partition_read, - partition_write - }; diff --git a/src/devices/partition.h b/src/devices/partition.h deleted file mode 100644 index 47fea4dc704f6f214c54e794053bc19ad9d28c41..0000000000000000000000000000000000000000 --- a/src/devices/partition.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEVICES_PARTITION_H -#define DEVICES_PARTITION_H - -struct block; - -void partition_scan (struct block *); - -#endif /* devices/partition.h */ diff --git a/src/devices/pit.c b/src/devices/pit.c deleted file mode 100644 index bfb188932b0009bb1bbf36d842394a87f7d16b4b..0000000000000000000000000000000000000000 --- a/src/devices/pit.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "devices/pit.h" -#include <debug.h> -#include <stdint.h> -#include "threads/interrupt.h" -#include "threads/io.h" - -/* Interface to 8254 Programmable Interrupt Timer (PIT). - Refer to [8254] for details. */ - -/* 8254 registers. */ -#define PIT_PORT_CONTROL 0x43 /* Control port. */ -#define PIT_PORT_COUNTER(CHANNEL) (0x40 + (CHANNEL)) /* Counter port. */ - -/* PIT cycles per second. */ -#define PIT_HZ 1193180 - -/* Configure the given CHANNEL in the PIT. In a PC, the PIT's - three output channels are hooked up like this: - - - Channel 0 is connected to interrupt line 0, so that it can - be used as a periodic timer interrupt, as implemented in - Pintos in devices/timer.c. - - - Channel 1 is used for dynamic RAM refresh (in older PCs). - No good can come of messing with this. - - - Channel 2 is connected to the PC speaker, so that it can - be used to play a tone, as implemented in Pintos in - devices/speaker.c. - - MODE specifies the form of output: - - - Mode 2 is a periodic pulse: the channel's output is 1 for - most of the period, but drops to 0 briefly toward the end - of the period. This is useful for hooking up to an - interrupt controller to generate a periodic interrupt. - - - Mode 3 is a square wave: for the first half of the period - it is 1, for the second half it is 0. This is useful for - generating a tone on a speaker. - - - Other modes are less useful. - - FREQUENCY is the number of periods per second, in Hz. */ -void -pit_configure_channel (int channel, int mode, int frequency) -{ - uint16_t count; - enum intr_level old_level; - - ASSERT (channel == 0 || channel == 2); - ASSERT (mode == 2 || mode == 3); - - /* Convert FREQUENCY to a PIT counter value. The PIT has a - clock that runs at PIT_HZ cycles per second. We must - translate FREQUENCY into a number of these cycles. */ - if (frequency < 19) - { - /* Frequency is too low: the quotient would overflow the - 16-bit counter. Force it to 0, which the PIT treats as - 65536, the highest possible count. This yields a 18.2 - Hz timer, approximately. */ - count = 0; - } - else if (frequency > PIT_HZ) - { - /* Frequency is too high: the quotient would underflow to - 0, which the PIT would interpret as 65536. A count of 1 - is illegal in mode 2, so we force it to 2, which yields - a 596.590 kHz timer, approximately. (This timer rate is - probably too fast to be useful anyhow.) */ - count = 2; - } - else - count = (PIT_HZ + frequency / 2) / frequency; - - /* Configure the PIT mode and load its counters. */ - old_level = intr_disable (); - outb (PIT_PORT_CONTROL, (channel << 6) | 0x30 | (mode << 1)); - outb (PIT_PORT_COUNTER (channel), count); - outb (PIT_PORT_COUNTER (channel), count >> 8); - intr_set_level (old_level); -} diff --git a/src/devices/pit.h b/src/devices/pit.h deleted file mode 100644 index dff36ae38e957cf89b2bcb2799c3dfe97859487e..0000000000000000000000000000000000000000 --- a/src/devices/pit.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEVICES_PIT_H -#define DEVICES_PIT_H - -#include <stdint.h> - -void pit_configure_channel (int channel, int mode, int frequency); - -#endif /* devices/pit.h */ diff --git a/src/devices/rtc.c b/src/devices/rtc.c deleted file mode 100644 index d99eb4679f1c9da0eed03412062f84209666cfd3..0000000000000000000000000000000000000000 --- a/src/devices/rtc.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "devices/rtc.h" -#include <stdio.h> -#include "threads/io.h" - -/* This code is an interface to the MC146818A-compatible real - time clock found on PC motherboards. See [MC146818A] for - hardware details. */ - -/* I/O register addresses. */ -#define CMOS_REG_SET 0x70 /* Selects CMOS register exposed by REG_IO. */ -#define CMOS_REG_IO 0x71 /* Contains the selected data byte. */ - -/* Indexes of CMOS registers with real-time clock functions. - Note that all of these registers are in BCD format, - so that 0x59 means 59, not 89. */ -#define RTC_REG_SEC 0 /* Second: 0x00...0x59. */ -#define RTC_REG_MIN 2 /* Minute: 0x00...0x59. */ -#define RTC_REG_HOUR 4 /* Hour: 0x00...0x23. */ -#define RTC_REG_MDAY 7 /* Day of the month: 0x01...0x31. */ -#define RTC_REG_MON 8 /* Month: 0x01...0x12. */ -#define RTC_REG_YEAR 9 /* Year: 0x00...0x99. */ - -/* Indexes of CMOS control registers. */ -#define RTC_REG_A 0x0a /* Register A: update-in-progress. */ -#define RTC_REG_B 0x0b /* Register B: 24/12 hour time, irq enables. */ -#define RTC_REG_C 0x0c /* Register C: pending interrupts. */ -#define RTC_REG_D 0x0d /* Register D: valid time? */ - -/* Register A. */ -#define RTCSA_UIP 0x80 /* Set while time update in progress. */ - -/* Register B. */ -#define RTCSB_SET 0x80 /* Disables update to let time be set. */ -#define RTCSB_DM 0x04 /* 0 = BCD time format, 1 = binary format. */ -#define RTCSB_24HR 0x02 /* 0 = 12-hour format, 1 = 24-hour format. */ - -static int bcd_to_bin (uint8_t); -static uint8_t cmos_read (uint8_t index); - -/* Returns number of seconds since Unix epoch of January 1, - 1970. */ -time_t -rtc_get_time (void) -{ - static const int days_per_month[12] = - { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - int sec, min, hour, mday, mon, year; - time_t time; - int i; - - /* Get time components. - - We repeatedly read the time until it is stable from one read - to another, in case we start our initial read in the middle - of an update. This strategy is not recommended by the - MC146818A datasheet, but it is simpler than any of their - suggestions and, furthermore, it is also used by Linux. - - The MC146818A can be configured for BCD or binary format, - but for historical reasons everyone always uses BCD format - except on obscure non-PC platforms, so we don't bother - trying to detect the format in use. */ - do - { - sec = bcd_to_bin (cmos_read (RTC_REG_SEC)); - min = bcd_to_bin (cmos_read (RTC_REG_MIN)); - hour = bcd_to_bin (cmos_read (RTC_REG_HOUR)); - mday = bcd_to_bin (cmos_read (RTC_REG_MDAY)); - mon = bcd_to_bin (cmos_read (RTC_REG_MON)); - year = bcd_to_bin (cmos_read (RTC_REG_YEAR)); - } - while (sec != bcd_to_bin (cmos_read (RTC_REG_SEC))); - - /* Translate years-since-1900 into years-since-1970. - If it's before the epoch, assume that it has passed 2000. - This will break at 2070, but that's long after our 31-bit - time_t breaks in 2038. */ - if (year < 70) - year += 100; - year -= 70; - - /* Break down all components into seconds. */ - time = (year * 365 + (year - 1) / 4) * 24 * 60 * 60; - for (i = 1; i <= mon; i++) - time += days_per_month[i - 1] * 24 * 60 * 60; - if (mon > 2 && year % 4 == 0) - time += 24 * 60 * 60; - time += (mday - 1) * 24 * 60 * 60; - time += hour * 60 * 60; - time += min * 60; - time += sec; - - return time; -} - -/* Returns the integer value of the given BCD byte. */ -static int -bcd_to_bin (uint8_t x) -{ - return (x & 0x0f) + ((x >> 4) * 10); -} - -/* Reads a byte from the CMOS register with the given INDEX and - returns the byte read. */ -static uint8_t -cmos_read (uint8_t index) -{ - outb (CMOS_REG_SET, index); - return inb (CMOS_REG_IO); -} diff --git a/src/devices/rtc.h b/src/devices/rtc.h deleted file mode 100644 index 96a822f2726706a91e05192f0c02bbaf3e8bf45c..0000000000000000000000000000000000000000 --- a/src/devices/rtc.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RTC_H -#define RTC_H - -typedef unsigned long time_t; - -time_t rtc_get_time (void); - -#endif diff --git a/src/devices/serial.c b/src/devices/serial.c deleted file mode 100644 index df770a724ac95c6825ed8ba7793bf99a1612c5df..0000000000000000000000000000000000000000 --- a/src/devices/serial.c +++ /dev/null @@ -1,228 +0,0 @@ -#include "devices/serial.h" -#include <debug.h> -#include "devices/input.h" -#include "devices/intq.h" -#include "devices/timer.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "threads/synch.h" -#include "threads/thread.h" - -/* Register definitions for the 16550A UART used in PCs. - The 16550A has a lot more going on than shown here, but this - is all we need. - - Refer to [PC16650D] for hardware information. */ - -/* I/O port base address for the first serial port. */ -#define IO_BASE 0x3f8 - -/* DLAB=0 registers. */ -#define RBR_REG (IO_BASE + 0) /* Receiver Buffer Reg. (read-only). */ -#define THR_REG (IO_BASE + 0) /* Transmitter Holding Reg. (write-only). */ -#define IER_REG (IO_BASE + 1) /* Interrupt Enable Reg.. */ - -/* DLAB=1 registers. */ -#define LS_REG (IO_BASE + 0) /* Divisor Latch (LSB). */ -#define MS_REG (IO_BASE + 1) /* Divisor Latch (MSB). */ - -/* DLAB-insensitive registers. */ -#define IIR_REG (IO_BASE + 2) /* Interrupt Identification Reg. (read-only) */ -#define FCR_REG (IO_BASE + 2) /* FIFO Control Reg. (write-only). */ -#define LCR_REG (IO_BASE + 3) /* Line Control Register. */ -#define MCR_REG (IO_BASE + 4) /* MODEM Control Register. */ -#define LSR_REG (IO_BASE + 5) /* Line Status Register (read-only). */ - -/* Interrupt Enable Register bits. */ -#define IER_RECV 0x01 /* Interrupt when data received. */ -#define IER_XMIT 0x02 /* Interrupt when transmit finishes. */ - -/* Line Control Register bits. */ -#define LCR_N81 0x03 /* No parity, 8 data bits, 1 stop bit. */ -#define LCR_DLAB 0x80 /* Divisor Latch Access Bit (DLAB). */ - -/* MODEM Control Register. */ -#define MCR_OUT2 0x08 /* Output line 2. */ - -/* Line Status Register. */ -#define LSR_DR 0x01 /* Data Ready: received data byte is in RBR. */ -#define LSR_THRE 0x20 /* THR Empty. */ - -/* Transmission mode. */ -static enum { UNINIT, POLL, QUEUE } mode; - -/* Data to be transmitted. */ -static struct intq txq; - -static void set_serial (int bps); -static void putc_poll (uint8_t); -static void write_ier (void); -static intr_handler_func serial_interrupt; - -/* Initializes the serial port device for polling mode. - Polling mode busy-waits for the serial port to become free - before writing to it. It's slow, but until interrupts have - been initialized it's all we can do. */ -static void -init_poll (void) -{ - ASSERT (mode == UNINIT); - outb (IER_REG, 0); /* Turn off all interrupts. */ - outb (FCR_REG, 0); /* Disable FIFO. */ - set_serial (9600); /* 9.6 kbps, N-8-1. */ - outb (MCR_REG, MCR_OUT2); /* Required to enable interrupts. */ - intq_init (&txq); - mode = POLL; -} - -/* Initializes the serial port device for queued interrupt-driven - I/O. With interrupt-driven I/O we don't waste CPU time - waiting for the serial device to become ready. */ -void -serial_init_queue (void) -{ - enum intr_level old_level; - - if (mode == UNINIT) - init_poll (); - ASSERT (mode == POLL); - - intr_register_ext (0x20 + 4, serial_interrupt, "serial"); - mode = QUEUE; - old_level = intr_disable (); - write_ier (); - intr_set_level (old_level); -} - -/* Sends BYTE to the serial port. */ -void -serial_putc (uint8_t byte) -{ - enum intr_level old_level = intr_disable (); - - if (mode != QUEUE) - { - /* If we're not set up for interrupt-driven I/O yet, - use dumb polling to transmit a byte. */ - if (mode == UNINIT) - init_poll (); - putc_poll (byte); - } - else - { - /* Otherwise, queue a byte and update the interrupt enable - register. */ - if (old_level == INTR_OFF && intq_full (&txq)) - { - /* Interrupts are off and the transmit queue is full. - If we wanted to wait for the queue to empty, - we'd have to reenable interrupts. - That's impolite, so we'll send a character via - polling instead. */ - putc_poll (intq_getc (&txq)); - } - - intq_putc (&txq, byte); - write_ier (); - } - - intr_set_level (old_level); -} - -/* Flushes anything in the serial buffer out the port in polling - mode. */ -void -serial_flush (void) -{ - enum intr_level old_level = intr_disable (); - while (!intq_empty (&txq)) - putc_poll (intq_getc (&txq)); - intr_set_level (old_level); -} - -/* The fullness of the input buffer may have changed. Reassess - whether we should block receive interrupts. - Called by the input buffer routines when characters are added - to or removed from the buffer. */ -void -serial_notify (void) -{ - ASSERT (intr_get_level () == INTR_OFF); - if (mode == QUEUE) - write_ier (); -} - -/* Configures the serial port for BPS bits per second. */ -static void -set_serial (int bps) -{ - int base_rate = 1843200 / 16; /* Base rate of 16550A, in Hz. */ - uint16_t divisor = base_rate / bps; /* Clock rate divisor. */ - - ASSERT (bps >= 300 && bps <= 115200); - - /* Enable DLAB. */ - outb (LCR_REG, LCR_N81 | LCR_DLAB); - - /* Set data rate. */ - outb (LS_REG, divisor & 0xff); - outb (MS_REG, divisor >> 8); - - /* Reset DLAB. */ - outb (LCR_REG, LCR_N81); -} - -/* Update interrupt enable register. */ -static void -write_ier (void) -{ - uint8_t ier = 0; - - ASSERT (intr_get_level () == INTR_OFF); - - /* Enable transmit interrupt if we have any characters to - transmit. */ - if (!intq_empty (&txq)) - ier |= IER_XMIT; - - /* Enable receive interrupt if we have room to store any - characters we receive. */ - if (!input_full ()) - ier |= IER_RECV; - - outb (IER_REG, ier); -} - -/* Polls the serial port until it's ready, - and then transmits BYTE. */ -static void -putc_poll (uint8_t byte) -{ - ASSERT (intr_get_level () == INTR_OFF); - - while ((inb (LSR_REG) & LSR_THRE) == 0) - continue; - outb (THR_REG, byte); -} - -/* Serial interrupt handler. */ -static void -serial_interrupt (struct intr_frame *f UNUSED) -{ - /* Inquire about interrupt in UART. Without this, we can - occasionally miss an interrupt running under QEMU. */ - inb (IIR_REG); - - /* As long as we have room to receive a byte, and the hardware - has a byte for us, receive a byte. */ - while (!input_full () && (inb (LSR_REG) & LSR_DR) != 0) - input_putc (inb (RBR_REG)); - - /* As long as we have a byte to transmit, and the hardware is - ready to accept a byte for transmission, transmit a byte. */ - while (!intq_empty (&txq) && (inb (LSR_REG) & LSR_THRE) != 0) - outb (THR_REG, intq_getc (&txq)); - - /* Update interrupt enable register based on queue status. */ - write_ier (); -} diff --git a/src/devices/serial.h b/src/devices/serial.h deleted file mode 100644 index 6e0477850b0b25ae384f033c7a0610c52113af8c..0000000000000000000000000000000000000000 --- a/src/devices/serial.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef DEVICES_SERIAL_H -#define DEVICES_SERIAL_H - -#include <stdint.h> - -void serial_init_queue (void); -void serial_putc (uint8_t); -void serial_flush (void); -void serial_notify (void); - -#endif /* devices/serial.h */ diff --git a/src/devices/shutdown.c b/src/devices/shutdown.c deleted file mode 100644 index f79af1a279bacb1e707fa6843a13077ddd418fab..0000000000000000000000000000000000000000 --- a/src/devices/shutdown.c +++ /dev/null @@ -1,138 +0,0 @@ -#include "devices/shutdown.h" -#include <console.h> -#include <stdio.h> -#include "devices/kbd.h" -#include "devices/serial.h" -#include "devices/timer.h" -#include "threads/io.h" -#include "threads/thread.h" -#ifdef USERPROG -#include "userprog/exception.h" -#endif -#ifdef FILESYS -#include "devices/block.h" -#include "filesys/filesys.h" -#endif - -/* Keyboard control register port. */ -#define CONTROL_REG 0x64 - -/* How to shut down when shutdown() is called. */ -static enum shutdown_type how = SHUTDOWN_NONE; - -static void print_stats (void); - -/* Shuts down the machine in the way configured by - shutdown_configure(). If the shutdown type is SHUTDOWN_NONE - (which is the default), returns without doing anything. */ -void -shutdown (void) -{ - switch (how) - { - case SHUTDOWN_POWER_OFF: - shutdown_power_off (); - break; - - case SHUTDOWN_REBOOT: - shutdown_reboot (); - break; - - default: - /* Nothing to do. */ - break; - } -} - -/* Sets TYPE as the way that machine will shut down when Pintos - execution is complete. */ -void -shutdown_configure (enum shutdown_type type) -{ - how = type; -} - -/* Reboots the machine via the keyboard controller. */ -void -shutdown_reboot (void) -{ - printf ("Rebooting...\n"); - - /* See [kbd] for details on how to program the keyboard - * controller. */ - for (;;) - { - int i; - - /* Poll keyboard controller's status byte until - * 'input buffer empty' is reported. */ - for (i = 0; i < 0x10000; i++) - { - if ((inb (CONTROL_REG) & 0x02) == 0) - break; - timer_udelay (2); - } - - timer_udelay (50); - - /* Pulse bit 0 of the output port P2 of the keyboard controller. - * This will reset the CPU. */ - outb (CONTROL_REG, 0xfe); - timer_udelay (50); - } -} - -/* Powers down the machine we're running on, - as long as we're running on Bochs or QEMU. */ -void -shutdown_power_off (void) -{ - const char s[] = "Shutdown"; - const char *p; - -#ifdef FILESYS - filesys_done (); -#endif - - print_stats (); - - printf ("Powering off...\n"); - serial_flush (); - - /* This is a special power-off sequence supported by Bochs and - QEMU, but not by physical hardware. */ - for (p = s; *p != '\0'; p++) - outb (0x8900, *p); - - /* For newer versions of qemu, you must run with -device - * isa-debug-exit, which exits on any write to an IO port (by - * default 0x501). Qemu's exit code is double the value plus one, - * so there is no way to exit cleanly. We use 0x31 which should - * result in a qemu exit code of 0x63. */ - outb (0x501, 0x31); - - /* This will power off a VMware VM if "gui.exitOnCLIHLT = TRUE" - is set in its configuration file. (The "pintos" script does - that automatically.) */ - asm volatile ("cli; hlt" : : : "memory"); - - /* None of those worked. */ - printf ("still running...\n"); - for (;;); -} - -/* Print statistics about Pintos execution. */ -static void -print_stats (void) -{ - timer_print_stats (); - thread_print_stats (); -#ifdef FILESYS - block_print_stats (); -#endif - console_print_stats (); - kbd_print_stats (); -#ifdef USERPROG - exception_print_stats (); -#endif -} diff --git a/src/devices/shutdown.h b/src/devices/shutdown.h deleted file mode 100644 index dc4f942384d44f210469b83b4b412799bb86213f..0000000000000000000000000000000000000000 --- a/src/devices/shutdown.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef DEVICES_SHUTDOWN_H -#define DEVICES_SHUTDOWN_H - -#include <debug.h> - -/* How to shut down when Pintos has nothing left to do. */ -enum shutdown_type - { - SHUTDOWN_NONE, /* Loop forever. */ - SHUTDOWN_POWER_OFF, /* Power off the machine (if possible). */ - SHUTDOWN_REBOOT, /* Reboot the machine (if possible). */ - }; - -void shutdown (void); -void shutdown_configure (enum shutdown_type); -void shutdown_reboot (void) NO_RETURN; -void shutdown_power_off (void) NO_RETURN; - -#endif /* devices/shutdown.h */ diff --git a/src/devices/speaker.c b/src/devices/speaker.c deleted file mode 100644 index 50520056469944b80fe75169f4d3ef1a2d3e072c..0000000000000000000000000000000000000000 --- a/src/devices/speaker.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "devices/speaker.h" -#include "devices/pit.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "devices/timer.h" - -/* Speaker port enable I/O register. */ -#define SPEAKER_PORT_GATE 0x61 - -/* Speaker port enable bits. */ -#define SPEAKER_GATE_ENABLE 0x03 - -/* Sets the PC speaker to emit a tone at the given FREQUENCY, in - Hz. */ -void -speaker_on (int frequency) -{ - if (frequency >= 20 && frequency <= 20000) - { - /* Set the timer channel that's connected to the speaker to - output a square wave at the given FREQUENCY, then - connect the timer channel output to the speaker. */ - enum intr_level old_level = intr_disable (); - pit_configure_channel (2, 3, frequency); - outb (SPEAKER_PORT_GATE, inb (SPEAKER_PORT_GATE) | SPEAKER_GATE_ENABLE); - intr_set_level (old_level); - } - else - { - /* FREQUENCY is outside the range of normal human hearing. - Just turn off the speaker. */ - speaker_off (); - } -} - -/* Turn off the PC speaker, by disconnecting the timer channel's - output from the speaker. */ -void -speaker_off (void) -{ - enum intr_level old_level = intr_disable (); - outb (SPEAKER_PORT_GATE, inb (SPEAKER_PORT_GATE) & ~SPEAKER_GATE_ENABLE); - intr_set_level (old_level); -} - -/* Briefly beep the PC speaker. */ -void -speaker_beep (void) -{ - /* Only attempt to beep the speaker if interrupts are enabled, - because we don't want to freeze the machine during the beep. - We could add a hook to the timer interrupt to avoid that - problem, but then we'd risk failing to ever stop the beep if - Pintos crashes for some unrelated reason. There's nothing - more annoying than a machine whose beeping you can't stop - without a power cycle. - - We can't just enable interrupts while we sleep. For one - thing, we get called (indirectly) from printf, which should - always work, even during boot before we're ready to enable - interrupts. */ - if (intr_get_level () == INTR_ON) - { - speaker_on (440); - timer_msleep (250); - speaker_off (); - } -} diff --git a/src/devices/speaker.h b/src/devices/speaker.h deleted file mode 100644 index 98cef7b1f7aa2e018f8bce15ac879b9dc5429b82..0000000000000000000000000000000000000000 --- a/src/devices/speaker.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DEVICES_SPEAKER_H -#define DEVICES_SPEAKER_H - -void speaker_on (int frequency); -void speaker_off (void); -void speaker_beep (void); - -#endif /* devices/speaker.h */ diff --git a/src/devices/timer.c b/src/devices/timer.c deleted file mode 100644 index befaaaed5a9a1ac0cd25ab76f8afd96fe6865127..0000000000000000000000000000000000000000 --- a/src/devices/timer.c +++ /dev/null @@ -1,246 +0,0 @@ -#include "devices/timer.h" -#include <debug.h> -#include <inttypes.h> -#include <round.h> -#include <stdio.h> -#include "devices/pit.h" -#include "threads/interrupt.h" -#include "threads/synch.h" -#include "threads/thread.h" - -/* See [8254] for hardware details of the 8254 timer chip. */ - -#if TIMER_FREQ < 19 -#error 8254 timer requires TIMER_FREQ >= 19 -#endif -#if TIMER_FREQ > 1000 -#error TIMER_FREQ <= 1000 recommended -#endif - -/* Number of timer ticks since OS booted. */ -static int64_t ticks; - -/* Number of loops per timer tick. - Initialized by timer_calibrate(). */ -static unsigned loops_per_tick; - -static intr_handler_func timer_interrupt; -static bool too_many_loops (unsigned loops); -static void busy_wait (int64_t loops); -static void real_time_sleep (int64_t num, int32_t denom); -static void real_time_delay (int64_t num, int32_t denom); - -/* Sets up the timer to interrupt TIMER_FREQ times per second, - and registers the corresponding interrupt. */ -void -timer_init (void) -{ - pit_configure_channel (0, 2, TIMER_FREQ); - intr_register_ext (0x20, timer_interrupt, "8254 Timer"); -} - -/* Calibrates loops_per_tick, used to implement brief delays. */ -void -timer_calibrate (void) -{ - unsigned high_bit, test_bit; - - ASSERT (intr_get_level () == INTR_ON); - printf ("Calibrating timer... "); - - /* Approximate loops_per_tick as the largest power-of-two - still less than one timer tick. */ - loops_per_tick = 1u << 10; - while (!too_many_loops (loops_per_tick << 1)) - { - loops_per_tick <<= 1; - ASSERT (loops_per_tick != 0); - } - - /* Refine the next 8 bits of loops_per_tick. */ - high_bit = loops_per_tick; - for (test_bit = high_bit >> 1; test_bit != high_bit >> 10; test_bit >>= 1) - if (!too_many_loops (high_bit | test_bit)) - loops_per_tick |= test_bit; - - printf ("%'"PRIu64" loops/s.\n", (uint64_t) loops_per_tick * TIMER_FREQ); -} - -/* Returns the number of timer ticks since the OS booted. */ -int64_t -timer_ticks (void) -{ - enum intr_level old_level = intr_disable (); - int64_t t = ticks; - intr_set_level (old_level); - return t; -} - -/* Returns the number of timer ticks elapsed since THEN, which - should be a value once returned by timer_ticks(). */ -int64_t -timer_elapsed (int64_t then) -{ - return timer_ticks () - then; -} - -/* Sleeps for approximately TICKS timer ticks. Interrupts must - be turned on. */ -void -timer_sleep (int64_t ticks) -{ - int64_t start = timer_ticks (); - - ASSERT (intr_get_level () == INTR_ON); - while (timer_elapsed (start) < ticks) - thread_yield (); -} - -/* Sleeps for approximately MS milliseconds. Interrupts must be - turned on. */ -void -timer_msleep (int64_t ms) -{ - real_time_sleep (ms, 1000); -} - -/* Sleeps for approximately US microseconds. Interrupts must be - turned on. */ -void -timer_usleep (int64_t us) -{ - real_time_sleep (us, 1000 * 1000); -} - -/* Sleeps for approximately NS nanoseconds. Interrupts must be - turned on. */ -void -timer_nsleep (int64_t ns) -{ - real_time_sleep (ns, 1000 * 1000 * 1000); -} - -/* Busy-waits for approximately MS milliseconds. Interrupts need - not be turned on. - - Busy waiting wastes CPU cycles, and busy waiting with - interrupts off for the interval between timer ticks or longer - will cause timer ticks to be lost. Thus, use timer_msleep() - instead if interrupts are enabled. */ -void -timer_mdelay (int64_t ms) -{ - real_time_delay (ms, 1000); -} - -/* Sleeps for approximately US microseconds. Interrupts need not - be turned on. - - Busy waiting wastes CPU cycles, and busy waiting with - interrupts off for the interval between timer ticks or longer - will cause timer ticks to be lost. Thus, use timer_usleep() - instead if interrupts are enabled. */ -void -timer_udelay (int64_t us) -{ - real_time_delay (us, 1000 * 1000); -} - -/* Sleeps execution for approximately NS nanoseconds. Interrupts - need not be turned on. - - Busy waiting wastes CPU cycles, and busy waiting with - interrupts off for the interval between timer ticks or longer - will cause timer ticks to be lost. Thus, use timer_nsleep() - instead if interrupts are enabled.*/ -void -timer_ndelay (int64_t ns) -{ - real_time_delay (ns, 1000 * 1000 * 1000); -} - -/* Prints timer statistics. */ -void -timer_print_stats (void) -{ - printf ("Timer: %"PRId64" ticks\n", timer_ticks ()); -} - -/* Timer interrupt handler. */ -static void -timer_interrupt (struct intr_frame *args UNUSED) -{ - ticks++; - thread_tick (); -} - -/* Returns true if LOOPS iterations waits for more than one timer - tick, otherwise false. */ -static bool -too_many_loops (unsigned loops) -{ - /* Wait for a timer tick. */ - int64_t start = ticks; - while (ticks == start) - barrier (); - - /* Run LOOPS loops. */ - start = ticks; - busy_wait (loops); - - /* If the tick count changed, we iterated too long. */ - barrier (); - return start != ticks; -} - -/* Iterates through a simple loop LOOPS times, for implementing - brief delays. - - Marked NO_INLINE because code alignment can significantly - affect timings, so that if this function was inlined - differently in different places the results would be difficult - to predict. */ -static void NO_INLINE -busy_wait (int64_t loops) -{ - while (loops-- > 0) - barrier (); -} - -/* Sleep for approximately NUM/DENOM seconds. */ -static void -real_time_sleep (int64_t num, int32_t denom) -{ - /* Convert NUM/DENOM seconds into timer ticks, rounding down. - - (NUM / DENOM) s - ---------------------- = NUM * TIMER_FREQ / DENOM ticks. - 1 s / TIMER_FREQ ticks - */ - int64_t ticks = num * TIMER_FREQ / denom; - - ASSERT (intr_get_level () == INTR_ON); - if (ticks > 0) - { - /* We're waiting for at least one full timer tick. Use - timer_sleep() because it will yield the CPU to other - processes. */ - timer_sleep (ticks); - } - else - { - /* Otherwise, use a busy-wait loop for more accurate - sub-tick timing. */ - real_time_delay (num, denom); - } -} - -/* Busy-wait for approximately NUM/DENOM seconds. */ -static void -real_time_delay (int64_t num, int32_t denom) -{ - /* Scale the numerator and denominator down by 1000 to avoid - the possibility of overflow. */ - ASSERT (denom % 1000 == 0); - busy_wait (loops_per_tick * num / 1000 * TIMER_FREQ / (denom / 1000)); -} diff --git a/src/devices/timer.h b/src/devices/timer.h deleted file mode 100644 index cd3d6bbfeb8d94046224d2676326705247f4a710..0000000000000000000000000000000000000000 --- a/src/devices/timer.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef DEVICES_TIMER_H -#define DEVICES_TIMER_H - -#include <round.h> -#include <stdint.h> - -/* Number of timer interrupts per second. */ -#define TIMER_FREQ 100 - -void timer_init (void); -void timer_calibrate (void); - -int64_t timer_ticks (void); -int64_t timer_elapsed (int64_t); - -/* Sleep and yield the CPU to other threads. */ -void timer_sleep (int64_t ticks); -void timer_msleep (int64_t milliseconds); -void timer_usleep (int64_t microseconds); -void timer_nsleep (int64_t nanoseconds); - -/* Busy waits. */ -void timer_mdelay (int64_t milliseconds); -void timer_udelay (int64_t microseconds); -void timer_ndelay (int64_t nanoseconds); - -void timer_print_stats (void); - -#endif /* devices/timer.h */ diff --git a/src/devices/vga.c b/src/devices/vga.c deleted file mode 100644 index f421b617bd3706858d2536eb21866531b1fd9b85..0000000000000000000000000000000000000000 --- a/src/devices/vga.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "devices/vga.h" -#include <round.h> -#include <stdint.h> -#include <stddef.h> -#include <string.h> -#include "devices/speaker.h" -#include "threads/io.h" -#include "threads/interrupt.h" -#include "threads/vaddr.h" - -/* VGA text screen support. See [FREEVGA] for more information. */ - -/* Number of columns and rows on the text display. */ -#define COL_CNT 80 -#define ROW_CNT 25 - -/* Current cursor position. (0,0) is in the upper left corner of - the display. */ -static size_t cx, cy; - -/* Attribute value for gray text on a black background. */ -#define GRAY_ON_BLACK 0x07 - -/* Framebuffer. See [FREEVGA] under "VGA Text Mode Operation". - The character at (x,y) is fb[y][x][0]. - The attribute at (x,y) is fb[y][x][1]. */ -static uint8_t (*fb)[COL_CNT][2]; - -static void clear_row (size_t y); -static void cls (void); -static void newline (void); -static void move_cursor (void); -static void find_cursor (size_t *x, size_t *y); - -/* Initializes the VGA text display. */ -static void -init (void) -{ - /* Already initialized? */ - static bool inited; - if (!inited) - { - fb = ptov (0xb8000); - find_cursor (&cx, &cy); - inited = true; - } -} - -/* Writes C to the VGA text display, interpreting control - characters in the conventional ways. */ -void -vga_putc (int c) -{ - /* Disable interrupts to lock out interrupt handlers - that might write to the console. */ - enum intr_level old_level = intr_disable (); - - init (); - - switch (c) - { - case '\n': - newline (); - break; - - case '\f': - cls (); - break; - - case '\b': - if (cx > 0) - cx--; - break; - - case '\r': - cx = 0; - break; - - case '\t': - cx = ROUND_UP (cx + 1, 8); - if (cx >= COL_CNT) - newline (); - break; - - case '\a': - intr_set_level (old_level); - speaker_beep (); - intr_disable (); - break; - - default: - fb[cy][cx][0] = c; - fb[cy][cx][1] = GRAY_ON_BLACK; - if (++cx >= COL_CNT) - newline (); - break; - } - - /* Update cursor position. */ - move_cursor (); - - intr_set_level (old_level); -} - -/* Clears the screen and moves the cursor to the upper left. */ -static void -cls (void) -{ - size_t y; - - for (y = 0; y < ROW_CNT; y++) - clear_row (y); - - cx = cy = 0; - move_cursor (); -} - -/* Clears row Y to spaces. */ -static void -clear_row (size_t y) -{ - size_t x; - - for (x = 0; x < COL_CNT; x++) - { - fb[y][x][0] = ' '; - fb[y][x][1] = GRAY_ON_BLACK; - } -} - -/* Advances the cursor to the first column in the next line on - the screen. If the cursor is already on the last line on the - screen, scrolls the screen upward one line. */ -static void -newline (void) -{ - cx = 0; - cy++; - if (cy >= ROW_CNT) - { - cy = ROW_CNT - 1; - memmove (&fb[0], &fb[1], sizeof fb[0] * (ROW_CNT - 1)); - clear_row (ROW_CNT - 1); - } -} - -/* Moves the hardware cursor to (cx,cy). */ -static void -move_cursor (void) -{ - /* See [FREEVGA] under "Manipulating the Text-mode Cursor". */ - uint16_t cp = cx + COL_CNT * cy; - outw (0x3d4, 0x0e | (cp & 0xff00)); - outw (0x3d4, 0x0f | (cp << 8)); -} - -/* Reads the current hardware cursor position into (*X,*Y). */ -static void -find_cursor (size_t *x, size_t *y) -{ - /* See [FREEVGA] under "Manipulating the Text-mode Cursor". */ - uint16_t cp; - - outb (0x3d4, 0x0e); - cp = inb (0x3d5) << 8; - - outb (0x3d4, 0x0f); - cp |= inb (0x3d5); - - *x = cp % COL_CNT; - *y = cp / COL_CNT; -} diff --git a/src/devices/vga.h b/src/devices/vga.h deleted file mode 100644 index 59690fb734a1c3abf8e1cc35fff916c6633aa3a6..0000000000000000000000000000000000000000 --- a/src/devices/vga.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEVICES_VGA_H -#define DEVICES_VGA_H - -void vga_putc (int); - -#endif /* devices/vga.h */ diff --git a/src/examples/.gitignore b/src/examples/.gitignore deleted file mode 100644 index a9e09d73308ea73514230cc3b437b5435c85b268..0000000000000000000000000000000000000000 --- a/src/examples/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -cat -cmp -cp -echo -halt -hex-dump -ls -mcat -mcp -mkdir -pwd -rm -shell -bubsort -insult -lineup -matmult -recursor -*.d diff --git a/src/examples/Makefile b/src/examples/Makefile deleted file mode 100644 index 41a663d610cb89d30b7aa0277a644b0f63a2c0c5..0000000000000000000000000000000000000000 --- a/src/examples/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -SRCDIR = .. - -# Test programs to compile, and a list of sources for each. -# To add a new test, put its name on the PROGS list -# and then add a name_SRC line that lists its source files. -PROGS = cat cmp cp echo halt hex-dump ls mcat mcp mkdir pwd rm shell \ - bubsort insult lineup matmult recursor my - -# Should work from project 2 onward. -cat_SRC = cat.c -cmp_SRC = cmp.c -cp_SRC = cp.c -echo_SRC = echo.c -halt_SRC = halt.c -hex-dump_SRC = hex-dump.c -insult_SRC = insult.c -lineup_SRC = lineup.c -ls_SRC = ls.c -recursor_SRC = recursor.c -rm_SRC = rm.c -my_SRC = my.c - -# Should work in project 3; also in project 4 if VM is included. -bubsort_SRC = bubsort.c -matmult_SRC = matmult.c -mcat_SRC = mcat.c -mcp_SRC = mcp.c - -# Should work in project 4. -mkdir_SRC = mkdir.c -pwd_SRC = pwd.c -shell_SRC = shell.c - -include $(SRCDIR)/Make.config -include $(SRCDIR)/Makefile.userprog diff --git a/src/examples/bubsort.c b/src/examples/bubsort.c deleted file mode 100644 index 343219ec26d39d54514aa91b876a87e765c28b3b..0000000000000000000000000000000000000000 --- a/src/examples/bubsort.c +++ /dev/null @@ -1,38 +0,0 @@ -/* sort.c - - Test program to sort a large number of integers. - - Intention is to stress virtual memory system. - - Ideally, we could read the unsorted array off of the file - system, and store the result back to the file system! */ -#include <stdio.h> - -/* Size of array to sort. */ -#define SORT_SIZE 128 - -int -main (void) -{ - /* Array to sort. Static to reduce stack usage. */ - static int array[SORT_SIZE]; - - int i, j, tmp; - - /* First initialize the array in descending order. */ - for (i = 0; i < SORT_SIZE; i++) - array[i] = SORT_SIZE - i - 1; - - /* Then sort in ascending order. */ - for (i = 0; i < SORT_SIZE - 1; i++) - for (j = 0; j < SORT_SIZE - 1 - i; j++) - if (array[j] > array[j + 1]) - { - tmp = array[j]; - array[j] = array[j + 1]; - array[j + 1] = tmp; - } - - printf ("sort exiting with code %d\n", array[0]); - return array[0]; -} diff --git a/src/examples/cat.c b/src/examples/cat.c deleted file mode 100644 index c8d229da8266847c15ccc1d3af7afd19c3ebc07f..0000000000000000000000000000000000000000 --- a/src/examples/cat.c +++ /dev/null @@ -1,34 +0,0 @@ -/* cat.c - - Prints files specified on command line to the console. */ - -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - bool success = true; - int i; - - for (i = 1; i < argc; i++) - { - int fd = open (argv[i]); - if (fd < 0) - { - printf ("%s: open failed\n", argv[i]); - success = false; - continue; - } - for (;;) - { - char buffer[1024]; - int bytes_read = read (fd, buffer, sizeof buffer); - if (bytes_read == 0) - break; - write (STDOUT_FILENO, buffer, bytes_read); - } - close (fd); - } - return success ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/src/examples/cmp.c b/src/examples/cmp.c deleted file mode 100644 index 94b406d1518431bc17dd36625bbcb803fe80abc2..0000000000000000000000000000000000000000 --- a/src/examples/cmp.c +++ /dev/null @@ -1,68 +0,0 @@ -/* cat.c - - Compares two files. */ - -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - int fd[2]; - - if (argc != 3) - { - printf ("usage: cmp A B\n"); - return EXIT_FAILURE; - } - - /* Open files. */ - fd[0] = open (argv[1]); - if (fd[0] < 0) - { - printf ("%s: open failed\n", argv[1]); - return EXIT_FAILURE; - } - fd[1] = open (argv[2]); - if (fd[1] < 0) - { - printf ("%s: open failed\n", argv[1]); - return EXIT_FAILURE; - } - - /* Compare data. */ - for (;;) - { - int pos; - char buffer[2][1024]; - int bytes_read[2]; - int min_read; - int i; - - pos = tell (fd[0]); - bytes_read[0] = read (fd[0], buffer[0], sizeof buffer[0]); - bytes_read[1] = read (fd[1], buffer[1], sizeof buffer[1]); - min_read = bytes_read[0] < bytes_read[1] ? bytes_read[0] : bytes_read[1]; - if (min_read == 0) - break; - - for (i = 0; i < min_read; i++) - if (buffer[0][i] != buffer[1][i]) - { - printf ("Byte %d is %02hhx ('%c') in %s but %02hhx ('%c') in %s\n", - pos + i, - buffer[0][i], buffer[0][i], argv[1], - buffer[1][i], buffer[1][i], argv[2]); - return EXIT_FAILURE; - } - - if (min_read < bytes_read[1]) - printf ("%s is shorter than %s\n", argv[1], argv[2]); - else if (min_read < bytes_read[0]) - printf ("%s is shorter than %s\n", argv[2], argv[1]); - } - - printf ("%s and %s are identical\n", argv[1], argv[2]); - - return EXIT_SUCCESS; -} diff --git a/src/examples/cp.c b/src/examples/cp.c deleted file mode 100644 index 86a5cd7562fcf633d65206ac9e5be7873859f741..0000000000000000000000000000000000000000 --- a/src/examples/cp.c +++ /dev/null @@ -1,55 +0,0 @@ -/* cat.c - -Copies one file to another. */ - -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - int in_fd, out_fd; - - if (argc != 3) - { - printf ("usage: cp OLD NEW\n"); - return EXIT_FAILURE; - } - - /* Open input file. */ - in_fd = open (argv[1]); - if (in_fd < 0) - { - printf ("%s: open failed\n", argv[1]); - return EXIT_FAILURE; - } - - /* Create and open output file. */ - if (!create (argv[2], filesize (in_fd))) - { - printf ("%s: create failed\n", argv[2]); - return EXIT_FAILURE; - } - out_fd = open (argv[2]); - if (out_fd < 0) - { - printf ("%s: open failed\n", argv[2]); - return EXIT_FAILURE; - } - - /* Copy data. */ - for (;;) - { - char buffer[1024]; - int bytes_read = read (in_fd, buffer, sizeof buffer); - if (bytes_read == 0) - break; - if (write (out_fd, buffer, bytes_read) != bytes_read) - { - printf ("%s: write failed\n", argv[2]); - return EXIT_FAILURE; - } - } - - return EXIT_SUCCESS; -} diff --git a/src/examples/echo.c b/src/examples/echo.c deleted file mode 100644 index 5621b69f409eaf1f180461fbc963922393538730..0000000000000000000000000000000000000000 --- a/src/examples/echo.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char **argv) -{ - int i,j; - - for (i = 0; i < argc; i++) - printf ("%s ", argv[i]); - printf ("\n"); - - return EXIT_SUCCESS; -} diff --git a/src/examples/halt.c b/src/examples/halt.c deleted file mode 100644 index bad7250772f2856db66dd455231705483e27bb67..0000000000000000000000000000000000000000 --- a/src/examples/halt.c +++ /dev/null @@ -1,14 +0,0 @@ -/* halt.c - - Simple program to test whether running a user program works. - - Just invokes a system call that shuts down the OS. */ - -#include <syscall.h> - -int -main (void) -{ - halt (); - /* not reached */ -} diff --git a/src/examples/hex-dump.c b/src/examples/hex-dump.c deleted file mode 100644 index ee313f2e84d2790ce173653e4f786389346e4551..0000000000000000000000000000000000000000 --- a/src/examples/hex-dump.c +++ /dev/null @@ -1,35 +0,0 @@ -/* hex-dump.c - - Prints files specified on command line to the console in hex. */ - -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - bool success = true; - int i; - - for (i = 1; i < argc; i++) - { - int fd = open (argv[i]); - if (fd < 0) - { - printf ("%s: open failed\n", argv[i]); - success = false; - continue; - } - for (;;) - { - char buffer[1024]; - int pos = tell (fd); - int bytes_read = read (fd, buffer, sizeof buffer); - if (bytes_read == 0) - break; - hex_dump (pos, buffer, bytes_read, true); - } - close (fd); - } - return success ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/src/examples/insult.c b/src/examples/insult.c deleted file mode 100644 index 98c4e6aebae157c63794b3aaf9c2c6e5c33468b7..0000000000000000000000000000000000000000 --- a/src/examples/insult.c +++ /dev/null @@ -1,369 +0,0 @@ -/* Insult.c - - This is a version of the famous CS 107 random sentence - generator. I wrote a program that reads a grammar definition - file and writes a C file containing that grammar as hard code - static C strings. Thus the majority of the code below in - machine generated and totally unreadable. The arrays created - are specially designed to make generating the sentences as - easy as possible. - - Originally by Greg Hutchins, March 1998. - Modified by Ben Pfaff for Pintos, Sept 2004. */ -char *start[] = - { "You", "1", "5", ".", "May", "13", ".", "With", "the", "19", "of", "18", -",", "may", "13", "." -}; -char startLoc[] = { 3, 0, 4, 7, 16 }; -char *adj[] = { "3", "4", "2", ",", "1" }; -char adjLoc[] = { 3, 0, 1, 2, 5 }; -char *adj3[] = { "3", "4" }; -char adj3Loc[] = { 2, 0, 1, 2 }; -char *adj1[] = - { "lame", "dried", "up", "par-broiled", "bloated", "half-baked", "spiteful", -"egotistical", "ungrateful", "stupid", "moronic", "fat", "ugly", "puny", "pitiful", -"insignificant", "blithering", "repulsive", "worthless", "blundering", "retarded", -"useless", "obnoxious", "low-budget", "assinine", "neurotic", "subhuman", "crochety", -"indescribable", "contemptible", "unspeakable", "sick", "lazy", "good-for-nothing", -"slutty", "mentally-deficient", "creepy", "sloppy", "dismal", "pompous", "pathetic", -"friendless", "revolting", "slovenly", "cantankerous", "uncultured", "insufferable", -"gross", "unkempt", "defective", "crumby" -}; -char adj1Loc[] = - { 50, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, -43, 44, 45, 46, 47, 48, 49, 50, 51 }; -char *adj2[] = - { "putrefied", "festering", "funky", "moldy", "leprous", "curdled", "fetid", -"slimy", "crusty", "sweaty", "damp", "deranged", "smelly", "stenchy", "malignant", -"noxious", "grimy", "reeky", "nasty", "mutilated", "sloppy", "gruesome", "grisly", -"sloshy", "wormy", "mealy", "spoiled", "contaminated", "rancid", "musty", -"fly-covered", "moth-eaten", "decaying", "decomposed", "freeze-dried", "defective", -"petrified", "rotting", "scabrous", "hirsute" -}; -char adj2Loc[] = - { 40, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 }; -char *name[] = - { "10", ",", "bad", "excuse", "for", "6", ",", "6", "for", "brains", ",", -"4", "11", "8", "for", "brains", "offspring", "of", "a", "motherless", "10", "7", "6", -"7", "4", "11", "8" -}; -char nameLoc[] = { 7, 0, 1, 6, 10, 16, 21, 23, 27 }; -char *stuff[] = - { "shit", "toe", "jam", "filth", "puss", "earwax", "leaf", "clippings", -"bat", "guano", "mucus", "fungus", "mung", "refuse", "earwax", "spittoon", "spittle", -"phlegm" -}; -char stuffLoc[] = { 14, 0, 1, 3, 4, 5, 6, 8, 10, 11, 12, 13, 14, 15, 17, 18 }; -char *noun_and_prep[] = - { "bit", "of", "piece", "of", "vat", "of", "lump", "of", "crock", "of", -"ball", "of", "tub", "of", "load", "of", "bucket", "of", "mound", "of", "glob", "of", "bag", -"of", "heap", "of", "mountain", "of", "load", "of", "barrel", "of", "sack", "of", "blob", "of", -"pile", "of", "truckload", "of", "vat", "of" -}; -char noun_and_prepLoc[] = - { 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, -38, 40, 42 }; -char *organics[] = - { "droppings", "mung", "zits", "puckies", "tumors", "cysts", "tumors", -"livers", "froth", "parts", "scabs", "guts", "entrails", "blubber", "carcuses", "gizards", -"9" -}; -char organicsLoc[] = - { 17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }; -char *body_parts[] = - { "kidneys", "genitals", "buttocks", "earlobes", "innards", "feet" -}; -char body_partsLoc[] = { 6, 0, 1, 2, 3, 4, 5, 6 }; -char *noun[] = - { "pop", "tart", "warthog", "twinkie", "barnacle", "fondue", "pot", -"cretin", "fuckwad", "moron", "ass", "neanderthal", "nincompoop", "simpleton", "11" -}; -char nounLoc[] = { 13, 0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; -char *animal[] = - { "donkey", "llama", "dingo", "lizard", "gekko", "lemur", "moose", "camel", -"goat", "eel" -}; -char animalLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; -char *good_verb[] = - { "love", "cuddle", "fondle", "adore", "smooch", "hug", "caress", "worship", -"look", "at", "touch" -}; -char good_verbLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11 }; -char *curse[] = - { "14", "20", "23", "14", "17", "20", "23", "14", "find", "your", "9", -"suddenly", "delectable", "14", "and", "14", "seek", "a", "battleground", "23" -}; -char curseLoc[] = { 4, 0, 3, 7, 13, 20 }; -char *afflictors[] = - { "15", "21", "15", "21", "15", "21", "15", "21", "a", "22", "Rush", -"Limbaugh", "the", "hosts", "of", "Hades" -}; -char afflictorsLoc[] = { 6, 0, 2, 4, 6, 8, 12, 16 }; -char *quantity[] = - { "a", "4", "hoard", "of", "a", "4", "pack", "of", "a", "truckload", "of", -"a", "swarm", "of", "many", "an", "army", "of", "a", "4", "heard", "of", "a", "4", -"platoon", "of", "a", "4", "and", "4", "group", "of", "16" -}; -char quantityLoc[] = { 10, 0, 4, 8, 11, 14, 15, 18, 22, 26, 32, 33 }; -char *numbers[] = - { "a", "thousand", "three", "million", "ninty-nine", "nine-hundred,", -"ninty-nine", "forty-two", "a", "gazillion", "sixty-eight", "times", "thirty-three" -}; -char numbersLoc[] = { 7, 0, 2, 4, 5, 7, 8, 10, 13 }; -char *adv[] = - { "viciously", "manicly", "merrily", "happily", ",", "with", "the", "19", -"of", "18", ",", "gleefully", ",", "with", "much", "ritualistic", "celebration", ",", -"franticly" -}; -char advLoc[] = { 8, 0, 1, 2, 3, 4, 11, 12, 18, 19 }; -char *metaphor[] = - { "an", "irate", "manticore", "Thor's", "belch", "Alah's", "fist", "16", -"titans", "a", "particularly", "vicious", "she-bear", "in", "the", "midst", "of", "her", -"menstrual", "cycle", "a", "pissed-off", "Jabberwock" -}; -char metaphorLoc[] = { 6, 0, 3, 5, 7, 9, 20, 23 }; -char *force[] = { "force", "fury", "power", "rage" }; -char forceLoc[] = { 4, 0, 1, 2, 3, 4 }; -char *bad_action[] = - { "spit", "shimmy", "slobber", "find", "refuge", "find", "shelter", "dance", -"retch", "vomit", "defecate", "erect", "a", "strip", "mall", "build", "a", "26", "have", "a", -"religious", "experience", "discharge", "bodily", "waste", "fart", "dance", "drool", -"lambada", "spill", "16", "rusty", "tacks", "bite", "you", "sneeze", "sing", "16", -"campfire", "songs", "smite", "you", "16", "times", "construct", "a", "new", "home", "throw", -"a", "party", "procreate" -}; -char bad_actionLoc[] = - { 25, 0, 1, 2, 3, 5, 7, 8, 9, 10, 11, 15, 18, 22, 25, 26, 27, 28, 29, 33, -35, 36, 40, 44, 48, 51, 52 }; -char *beasties[] = - { "yaks", "22", "maggots", "22", "cockroaches", "stinging", "scorpions", -"fleas", "22", "weasels", "22", "gnats", "South", "American", "killer", "bees", "spiders", -"4", "monkeys", "22", "wiener-dogs", "22", "rats", "22", "wolverines", "4", ",", "22", -"pit-fiends" -}; -char beastiesLoc[] = - { 14, 0, 1, 3, 5, 7, 8, 10, 12, 16, 17, 19, 21, 23, 25, 29 }; -char *condition[] = - { "frothing", "manic", "crazed", "plague-ridden", "disease-carrying", -"biting", "rabid", "blood-thirsty", "ravaging", "slavering" -}; -char conditionLoc[] = { 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; -char *place[] = - { "in", "24", "25", "upon", "your", "mother's", "grave", "on", "24", "best", -"rug", "in", "the", "26", "you", "call", "home", "upon", "your", "heinie" -}; -char placeLoc[] = { 5, 0, 3, 7, 11, 17, 20 }; -char *relation[] = - { "your", "your", "your", "your", "father's", "your", "mother's", "your", -"grandma's" -}; -char relationLoc[] = { 6, 0, 1, 2, 3, 5, 7, 9 }; -char *in_something[] = - { "entrails", "anal", "cavity", "shoes", "house", "pantry", "general", -"direction", "pants", "bed" -}; -char in_somethingLoc[] = { 8, 0, 1, 3, 4, 5, 6, 8, 9, 10 }; -char *bad_place[] = - { "rat", "hole", "sewer", "toxic", "dump", "oil", "refinery", "landfill", -"porto-pottie" -}; -char bad_placeLoc[] = { 6, 0, 2, 3, 5, 7, 8, 9 }; -char **daGrammar[27]; -char *daGLoc[27]; - -static void -init_grammar (void) -{ - daGrammar[0] = start; - daGLoc[0] = startLoc; - daGrammar[1] = adj; - daGLoc[1] = adjLoc; - daGrammar[2] = adj3; - daGLoc[2] = adj3Loc; - daGrammar[3] = adj1; - daGLoc[3] = adj1Loc; - daGrammar[4] = adj2; - daGLoc[4] = adj2Loc; - daGrammar[5] = name; - daGLoc[5] = nameLoc; - daGrammar[6] = stuff; - daGLoc[6] = stuffLoc; - daGrammar[7] = noun_and_prep; - daGLoc[7] = noun_and_prepLoc; - daGrammar[8] = organics; - daGLoc[8] = organicsLoc; - daGrammar[9] = body_parts; - daGLoc[9] = body_partsLoc; - daGrammar[10] = noun; - daGLoc[10] = nounLoc; - daGrammar[11] = animal; - daGLoc[11] = animalLoc; - daGrammar[12] = good_verb; - daGLoc[12] = good_verbLoc; - daGrammar[13] = curse; - daGLoc[13] = curseLoc; - daGrammar[14] = afflictors; - daGLoc[14] = afflictorsLoc; - daGrammar[15] = quantity; - daGLoc[15] = quantityLoc; - daGrammar[16] = numbers; - daGLoc[16] = numbersLoc; - daGrammar[17] = adv; - daGLoc[17] = advLoc; - daGrammar[18] = metaphor; - daGLoc[18] = metaphorLoc; - daGrammar[19] = force; - daGLoc[19] = forceLoc; - daGrammar[20] = bad_action; - daGLoc[20] = bad_actionLoc; - daGrammar[21] = beasties; - daGLoc[21] = beastiesLoc; - daGrammar[22] = condition; - daGLoc[22] = conditionLoc; - daGrammar[23] = place; - daGLoc[23] = placeLoc; - daGrammar[24] = relation; - daGLoc[24] = relationLoc; - daGrammar[25] = in_something; - daGLoc[25] = in_somethingLoc; - daGrammar[26] = bad_place; - daGLoc[26] = bad_placeLoc; -} - -#include <ctype.h> -#include <debug.h> -#include <random.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syscall.h> - -void expand (int num, char **grammar[], char *location[], int handle); - -static void -usage (int ret_code, const char *message, ...) PRINTF_FORMAT (2, 3); - -static void -usage (int ret_code, const char *message, ...) -{ - va_list args; - - if (message != NULL) - { - va_start (args, message); - vprintf (message, args); - va_end (args); - } - - printf ("\n" - "Usage: insult [OPTION]...\n" - "Prints random insults to screen.\n\n" - " -h: this help message\n" - " -s <integer>: set the random seed (default 4951)\n" - " -n <integer>: choose number of insults (default 4)\n" - " -f <file>: redirect output to <file>\n"); - - exit (ret_code); -} - -int -main (int argc, char *argv[]) -{ - int sentence_cnt, new_seed, i, file_flag, sent_flag, seed_flag; - int handle; - - new_seed = 4951; - sentence_cnt = 4; - file_flag = 0; - seed_flag = 0; - sent_flag = 0; - handle = STDOUT_FILENO; - - for (i = 1; i < argc; i++) - { - if (strcmp (argv[1], "-h") == 0) - usage (0, NULL); - else if (strcmp (argv[i], "-s") == 0) - { - if (seed_flag++) - usage (-1, "Can't have more than one seed"); - if (++i >= argc) - usage (-1, "Missing value for -s"); - new_seed = atoi (argv[i]); - } - else if (strcmp (argv[i], "-n") == 0) - { - if (sent_flag++) - usage (-1, "Can't have more than one sentence option"); - if (++i >= argc) - usage (-1, "Missing value for -n"); - sentence_cnt = atoi (argv[i]); - if (sentence_cnt < 1) - usage (-1, "Must have at least one sentence"); - } - else if (strcmp (argv[i], "-f") == 0) - { - if (file_flag++) - usage (-1, "Can't have more than one output file"); - if (++i >= argc) - usage (-1, "Missing value for -f"); - - /* Because files have fixed length in the basic Pintos - file system, the 0 argument means that this option - will not be useful until project 4 is - implemented. */ - create (argv[i], 0); - handle = open (argv[i]); - if (handle < 0) - { - printf ("%s: open failed\n", argv[i]); - return EXIT_FAILURE; - } - } - else - usage (-1, "Unrecognized flag"); - } - - init_grammar (); - - random_init (new_seed); - hprintf (handle, "\n"); - - for (i = 0; i < sentence_cnt; i++) - { - hprintf (handle, "\n"); - expand (0, daGrammar, daGLoc, handle); - hprintf (handle, "\n\n"); - } - - if (file_flag) - close (handle); - - return EXIT_SUCCESS; -} - -void -expand (int num, char **grammar[], char *location[], int handle) -{ - char *word; - int i, which, listStart, listEnd; - - which = random_ulong () % location[num][0] + 1; - listStart = location[num][which]; - listEnd = location[num][which + 1]; - for (i = listStart; i < listEnd; i++) - { - word = grammar[num][i]; - if (!isdigit (*word)) - { - if (!ispunct (*word)) - hprintf (handle, " "); - hprintf (handle, "%s", word); - } - else - expand (atoi (word), grammar, location, handle); - } - -} diff --git a/src/examples/lib/.gitignore b/src/examples/lib/.gitignore deleted file mode 100644 index a4383358ec72fb4d15f30791cb5265a6e06c5416..0000000000000000000000000000000000000000 --- a/src/examples/lib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.d diff --git a/src/examples/lib/user/.dummy b/src/examples/lib/user/.dummy deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/examples/lib/user/.gitignore b/src/examples/lib/user/.gitignore deleted file mode 100644 index a4383358ec72fb4d15f30791cb5265a6e06c5416..0000000000000000000000000000000000000000 --- a/src/examples/lib/user/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.d diff --git a/src/examples/lineup.c b/src/examples/lineup.c deleted file mode 100644 index 60402d0a90b20895060b0af9d7b08c0121cdd154..0000000000000000000000000000000000000000 --- a/src/examples/lineup.c +++ /dev/null @@ -1,46 +0,0 @@ -/* lineup.c - - Converts a file to uppercase in-place. - - Incidentally, another way to do this while avoiding the seeks - would be to open the input file, then remove() it and reopen - it under another handle. Because of Unix deletion semantics - this works fine. */ - -#include <ctype.h> -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - char buf[1024]; - int handle; - - if (argc != 2) - exit (1); - - handle = open (argv[1]); - if (handle < 0) - exit (2); - - for (;;) - { - int n, i; - - n = read (handle, buf, sizeof buf); - if (n <= 0) - break; - - for (i = 0; i < n; i++) - buf[i] = toupper ((unsigned char) buf[i]); - - seek (handle, tell (handle) - n); - if (write (handle, buf, n) != n) - printf ("write failed\n"); - } - - close (handle); - - return EXIT_SUCCESS; -} diff --git a/src/examples/ls.c b/src/examples/ls.c deleted file mode 100644 index fbe27a1e5023312bf0a421969ed8989f9d24b4c6..0000000000000000000000000000000000000000 --- a/src/examples/ls.c +++ /dev/null @@ -1,90 +0,0 @@ -/* ls.c - - Lists the contents of the directory or directories named on - the command line, or of the current directory if none are - named. - - By default, only the name of each file is printed. If "-l" is - given as the first argument, the type, size, and inumber of - each file is also printed. This won't work until project 4. */ - -#include <syscall.h> -#include <stdio.h> -#include <string.h> - -static bool -list_dir (const char *dir, bool verbose) -{ - int dir_fd = open (dir); - if (dir_fd == -1) - { - printf ("%s: not found\n", dir); - return false; - } - - if (isdir (dir_fd)) - { - char name[READDIR_MAX_LEN]; - - printf ("%s", dir); - if (verbose) - printf (" (inumber %d)", inumber (dir_fd)); - printf (":\n"); - - while (readdir (dir_fd, name)) - { - printf ("%s", name); - if (verbose) - { - char full_name[128]; - int entry_fd; - - snprintf (full_name, sizeof full_name, "%s/%s", dir, name); - entry_fd = open (full_name); - - printf (": "); - if (entry_fd != -1) - { - if (isdir (entry_fd)) - printf ("directory"); - else - printf ("%d-byte file", filesize (entry_fd)); - printf (", inumber %d", inumber (entry_fd)); - } - else - printf ("open failed"); - close (entry_fd); - } - printf ("\n"); - } - } - else - printf ("%s: not a directory\n", dir); - close (dir_fd); - return true; -} - -int -main (int argc, char *argv[]) -{ - bool success = true; - bool verbose = false; - - if (argc > 1 && !strcmp (argv[1], "-l")) - { - verbose = true; - argv++; - argc--; - } - - if (argc <= 1) - success = list_dir (".", verbose); - else - { - int i; - for (i = 1; i < argc; i++) - if (!list_dir (argv[i], verbose)) - success = false; - } - return success ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/src/examples/matmult.c b/src/examples/matmult.c deleted file mode 100644 index 4f0615fa06fa642a531309dd0644fe60cccf9d44..0000000000000000000000000000000000000000 --- a/src/examples/matmult.c +++ /dev/null @@ -1,57 +0,0 @@ -/* matmult.c - - Test program to do matrix multiplication on large arrays. - - Intended to stress virtual memory system. - - Ideally, we could read the matrices off of the file system, - and store the result back to the file system! - */ - -#include <stdio.h> -#include <syscall.h> - -/* You should define DIM to be large enough that the arrays - don't fit in physical memory. - - Dim Memory - ------ -------- - 16 3 kB - 64 48 kB - 128 192 kB - 256 768 kB - 512 3,072 kB - 1,024 12,288 kB - 2,048 49,152 kB - 4,096 196,608 kB - 8,192 786,432 kB - 16,384 3,145,728 kB */ -#define DIM 128 - -int A[DIM][DIM]; -int B[DIM][DIM]; -int C[DIM][DIM]; - -int -main (void) -{ - int i, j, k; - - /* Initialize the matrices. */ - for (i = 0; i < DIM; i++) - for (j = 0; j < DIM; j++) - { - A[i][j] = i; - B[i][j] = j; - C[i][j] = 0; - } - - /* Multiply matrices. */ - for (i = 0; i < DIM; i++) - for (j = 0; j < DIM; j++) - for (k = 0; k < DIM; k++) - C[i][j] += A[i][k] * B[k][j]; - - /* Done. */ - exit (C[DIM - 1][DIM - 1]); -} diff --git a/src/examples/mcat.c b/src/examples/mcat.c deleted file mode 100644 index 7b397601045cb8f24c4b00e055b26fbc851ebf91..0000000000000000000000000000000000000000 --- a/src/examples/mcat.c +++ /dev/null @@ -1,45 +0,0 @@ -/* mcat.c - - Prints files specified on command line to the console, using - mmap. */ - -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - int i; - - for (i = 1; i < argc; i++) - { - int fd; - mapid_t map; - void *data = (void *) 0x10000000; - int size; - - /* Open input file. */ - fd = open (argv[i]); - if (fd < 0) - { - printf ("%s: open failed\n", argv[i]); - return EXIT_FAILURE; - } - size = filesize (fd); - - /* Map files. */ - map = mmap (fd, data); - if (map == MAP_FAILED) - { - printf ("%s: mmap failed\n", argv[i]); - return EXIT_FAILURE; - } - - /* Write file to console. */ - write (STDOUT_FILENO, data, size); - - /* Unmap files (optional). */ - munmap (map); - } - return EXIT_SUCCESS; -} diff --git a/src/examples/mcp.c b/src/examples/mcp.c deleted file mode 100644 index 6091dc88c12f897bfb10f769480fed0c6d5e85ef..0000000000000000000000000000000000000000 --- a/src/examples/mcp.c +++ /dev/null @@ -1,68 +0,0 @@ -/* mcp.c - - Copies one file to another, using mmap. */ - -#include <stdio.h> -#include <string.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - int in_fd, out_fd; - mapid_t in_map, out_map; - void *in_data = (void *) 0x10000000; - void *out_data = (void *) 0x20000000; - int size; - - if (argc != 3) - { - printf ("usage: cp OLD NEW\n"); - return EXIT_FAILURE; - } - - /* Open input file. */ - in_fd = open (argv[1]); - if (in_fd < 0) - { - printf ("%s: open failed\n", argv[1]); - return EXIT_FAILURE; - } - size = filesize (in_fd); - - /* Create and open output file. */ - if (!create (argv[2], size)) - { - printf ("%s: create failed\n", argv[2]); - return EXIT_FAILURE; - } - out_fd = open (argv[2]); - if (out_fd < 0) - { - printf ("%s: open failed\n", argv[2]); - return EXIT_FAILURE; - } - - /* Map files. */ - in_map = mmap (in_fd, in_data); - if (in_map == MAP_FAILED) - { - printf ("%s: mmap failed\n", argv[1]); - return EXIT_FAILURE; - } - out_map = mmap (out_fd, out_data); - if (out_map == MAP_FAILED) - { - printf ("%s: mmap failed\n", argv[2]); - return EXIT_FAILURE; - } - - /* Copy files. */ - memcpy (out_data, in_data, size); - - /* Unmap files (optional). */ - munmap (in_map); - munmap (out_map); - - return EXIT_SUCCESS; -} diff --git a/src/examples/mkdir.c b/src/examples/mkdir.c deleted file mode 100644 index 7ddbc3f9d38e2d90d5895553a12a982da3966128..0000000000000000000000000000000000000000 --- a/src/examples/mkdir.c +++ /dev/null @@ -1,24 +0,0 @@ -/* mkdir.c - - Creates a directory. */ - -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - if (argc != 2) - { - printf ("usage: %s DIRECTORY\n", argv[0]); - return EXIT_FAILURE; - } - - if (!mkdir (argv[1])) - { - printf ("%s: mkdir failed\n", argv[1]); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/src/examples/my.c b/src/examples/my.c deleted file mode 100644 index 30c2b27f85ad79f149d01a57da1fd83ac3eee645..0000000000000000000000000000000000000000 --- a/src/examples/my.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <stdio.h> -#include <syscall.h> - -int -main (void) -{ - printf("Hello, World\n"); - - return EXIT_SUCCESS; -} diff --git a/src/examples/pwd.c b/src/examples/pwd.c deleted file mode 100644 index d2305cfd5ba4c974fa39bfda983593f0c92bd234..0000000000000000000000000000000000000000 --- a/src/examples/pwd.c +++ /dev/null @@ -1,152 +0,0 @@ -/* pwd.c - - Prints the absolute name of the present working directory. */ - -#include <syscall.h> -#include <stdbool.h> -#include <stdio.h> -#include <string.h> - -static bool getcwd (char *cwd, size_t cwd_size); - -int -main (void) -{ - char cwd[128]; - if (getcwd (cwd, sizeof cwd)) - { - printf ("%s\n", cwd); - return EXIT_SUCCESS; - } - else - { - printf ("error\n"); - return EXIT_FAILURE; - } -} - -/* Stores the inode number for FILE_NAME in *INUM. - Returns true if successful, false if the file could not be - opened. */ -static bool -get_inumber (const char *file_name, int *inum) -{ - int fd = open (file_name); - if (fd >= 0) - { - *inum = inumber (fd); - close (fd); - return true; - } - else - return false; -} - -/* Prepends PREFIX to the characters stored in the final *DST_LEN - bytes of the DST_SIZE-byte buffer that starts at DST. - Returns true if successful, false if adding that many - characters, plus a null terminator, would overflow the buffer. - (No null terminator is actually added or depended upon, but - its space is accounted for.) */ -static bool -prepend (const char *prefix, - char *dst, size_t *dst_len, size_t dst_size) -{ - size_t prefix_len = strlen (prefix); - if (prefix_len + *dst_len + 1 <= dst_size) - { - *dst_len += prefix_len; - memcpy ((dst + dst_size) - *dst_len, prefix, prefix_len); - return true; - } - else - return false; -} - -/* Stores the current working directory, as a null-terminated - string, in the CWD_SIZE bytes in CWD. - Returns true if successful, false on error. Errors include - system errors, directory trees deeper than MAX_LEVEL levels, - and insufficient space in CWD. */ -static bool -getcwd (char *cwd, size_t cwd_size) -{ - size_t cwd_len = 0; - -#define MAX_LEVEL 20 - char name[MAX_LEVEL * 3 + 1 + READDIR_MAX_LEN + 1]; - char *namep; - - int child_inum; - - /* Make sure there's enough space for at least "/". */ - if (cwd_size < 2) - return false; - - /* Get inumber for current directory. */ - if (!get_inumber (".", &child_inum)) - return false; - - namep = name; - for (;;) - { - int parent_inum, parent_fd; - - /* Compose "../../../..", etc., in NAME. */ - if ((namep - name) > MAX_LEVEL * 3) - return false; - *namep++ = '.'; - *namep++ = '.'; - *namep = '\0'; - - /* Open directory. */ - parent_fd = open (name); - if (parent_fd < 0) - return false; - *namep++ = '/'; - - /* If parent and child have the same inumber, - then we've arrived at the root. */ - parent_inum = inumber (parent_fd); - if (parent_inum == child_inum) - break; - - /* Find name of file in parent directory with the child's - inumber. */ - for (;;) - { - int test_inum; - if (!readdir (parent_fd, namep) || !get_inumber (name, &test_inum)) - { - close (parent_fd); - return false; - } - if (test_inum == child_inum) - break; - } - close (parent_fd); - - /* Prepend "/name" to CWD. */ - if (!prepend (namep - 1, cwd, &cwd_len, cwd_size)) - return false; - - /* Move up. */ - child_inum = parent_inum; - } - - /* Finalize CWD. */ - if (cwd_len > 0) - { - /* Move the string to the beginning of CWD, - and null-terminate it. */ - memmove (cwd, (cwd + cwd_size) - cwd_len, cwd_len); - cwd[cwd_len] = '\0'; - } - else - { - /* Special case for the root. */ - strlcpy (cwd, "/", cwd_size); - } - - return true; -} diff --git a/src/examples/recursor.c b/src/examples/recursor.c deleted file mode 100644 index 79c784a991b3d10414e76dfc6ed4af245e483ad4..0000000000000000000000000000000000000000 --- a/src/examples/recursor.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - char buffer[128]; - pid_t pid; - int retval = 0; - - if (argc != 4) - { - printf ("usage: recursor <string> <depth> <waitp>\n"); - exit (1); - } - - /* Print args. */ - printf ("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]); - - /* Execute child and wait for it to finish if requested. */ - if (atoi (argv[2]) != 0) - { - snprintf (buffer, sizeof buffer, - "recursor %s %d %s", argv[1], atoi (argv[2]) - 1, argv[3]); - pid = exec (buffer); - if (atoi (argv[3])) - retval = wait (pid); - } - - /* Done. */ - printf ("%s %s: dying, retval=%d\n", argv[1], argv[2], retval); - exit (retval); -} diff --git a/src/examples/rm.c b/src/examples/rm.c deleted file mode 100644 index 0db7f7b2aedfa8e98a221d3c685f67ca393a18fc..0000000000000000000000000000000000000000 --- a/src/examples/rm.c +++ /dev/null @@ -1,21 +0,0 @@ -/* rm.c - - Removes files specified on command line. */ - -#include <stdio.h> -#include <syscall.h> - -int -main (int argc, char *argv[]) -{ - bool success = true; - int i; - - for (i = 1; i < argc; i++) - if (!remove (argv[i])) - { - printf ("%s: remove failed\n", argv[i]); - success = false; - } - return success ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/src/examples/shell.c b/src/examples/shell.c deleted file mode 100644 index 93641b45b8c3250ff3dd3582fc731668d34ebbe7..0000000000000000000000000000000000000000 --- a/src/examples/shell.c +++ /dev/null @@ -1,104 +0,0 @@ -#include <stdbool.h> -#include <stdio.h> -#include <string.h> -#include <syscall.h> - -static void read_line (char line[], size_t); -static bool backspace (char **pos, char line[]); - -int -main (void) -{ - printf ("Shell starting...\n"); - for (;;) - { - char command[80]; - - /* Read command. */ - printf ("--"); - read_line (command, sizeof command); - - /* Execute command. */ - if (!strcmp (command, "exit")) - break; - else if (!memcmp (command, "cd ", 3)) - { - if (!chdir (command + 3)) - printf ("\"%s\": chdir failed\n", command + 3); - } - else if (command[0] == '\0') - { - /* Empty command. */ - } - else - { - pid_t pid = exec (command); - if (pid != PID_ERROR) - printf ("\"%s\": exit code %d\n", command, wait (pid)); - else - printf ("exec failed\n"); - } - } - - printf ("Shell exiting."); - return EXIT_SUCCESS; -} - -/* Reads a line of input from the user into LINE, which has room - for SIZE bytes. Handles backspace and Ctrl+U in the ways - expected by Unix users. On return, LINE will always be - null-terminated and will not end in a new-line character. */ -static void -read_line (char line[], size_t size) -{ - char *pos = line; - for (;;) - { - char c; - read (STDIN_FILENO, &c, 1); - - switch (c) - { - case '\r': - *pos = '\0'; - putchar ('\n'); - return; - - case '\b': - backspace (&pos, line); - break; - - case ('U' - 'A') + 1: /* Ctrl+U. */ - while (backspace (&pos, line)) - continue; - break; - - default: - /* Add character to line. */ - if (pos < line + size - 1) - { - putchar (c); - *pos++ = c; - } - break; - } - } -} - -/* If *POS is past the beginning of LINE, backs up one character - position. Returns true if successful, false if nothing was - done. */ -static bool -backspace (char **pos, char line[]) -{ - if (*pos > line) - { - /* Back up cursor, overwrite character, back up - again. */ - printf ("\b \b"); - (*pos)--; - return true; - } - else - return false; -} diff --git a/src/filesys/.gitignore b/src/filesys/.gitignore deleted file mode 100644 index 6d5357c015ab6f0b7ee7074381afdd3da82e06eb..0000000000000000000000000000000000000000 --- a/src/filesys/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -build -bochsrc.txt -bochsout.txt diff --git a/src/filesys/Make.vars b/src/filesys/Make.vars deleted file mode 100644 index b3aa0059bd15f7245ae14abf9eb4cc56bc931c87..0000000000000000000000000000000000000000 --- a/src/filesys/Make.vars +++ /dev/null @@ -1,13 +0,0 @@ -# -*- makefile -*- - -kernel.bin: DEFINES = -DUSERPROG -DFILESYS -KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys -TEST_SUBDIRS = tests/userprog tests/filesys/base tests/filesys/extended -GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.no-vm -SIMULATOR = --qemu - -# Uncomment the lines below to enable VM. -#kernel.bin: DEFINES += -DVM -#KERNEL_SUBDIRS += vm -#TEST_SUBDIRS += tests/vm -#GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.with-vm diff --git a/src/filesys/Makefile b/src/filesys/Makefile deleted file mode 100644 index 34c10aa4f508714da040e81389fa51e56ba2d97a..0000000000000000000000000000000000000000 --- a/src/filesys/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.kernel diff --git a/src/filesys/directory.c b/src/filesys/directory.c deleted file mode 100644 index 030c1c9b0dbaf9b3a41a4decaadd7c76793b1d63..0000000000000000000000000000000000000000 --- a/src/filesys/directory.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "filesys/directory.h" -#include <stdio.h> -#include <string.h> -#include <list.h> -#include "filesys/filesys.h" -#include "filesys/inode.h" -#include "threads/malloc.h" - -/* A directory. */ -struct dir - { - struct inode *inode; /* Backing store. */ - off_t pos; /* Current position. */ - }; - -/* A single directory entry. */ -struct dir_entry - { - block_sector_t inode_sector; /* Sector number of header. */ - char name[NAME_MAX + 1]; /* Null terminated file name. */ - bool in_use; /* In use or free? */ - }; - -/* Creates a directory with space for ENTRY_CNT entries in the - given SECTOR. Returns true if successful, false on failure. */ -bool -dir_create (block_sector_t sector, size_t entry_cnt) -{ - return inode_create (sector, entry_cnt * sizeof (struct dir_entry)); -} - -/* Opens and returns the directory for the given INODE, of which - it takes ownership. Returns a null pointer on failure. */ -struct dir * -dir_open (struct inode *inode) -{ - struct dir *dir = calloc (1, sizeof *dir); - if (inode != NULL && dir != NULL) - { - dir->inode = inode; - dir->pos = 0; - return dir; - } - else - { - inode_close (inode); - free (dir); - return NULL; - } -} - -/* Opens the root directory and returns a directory for it. - Return true if successful, false on failure. */ -struct dir * -dir_open_root (void) -{ - return dir_open (inode_open (ROOT_DIR_SECTOR)); -} - -/* Opens and returns a new directory for the same inode as DIR. - Returns a null pointer on failure. */ -struct dir * -dir_reopen (struct dir *dir) -{ - return dir_open (inode_reopen (dir->inode)); -} - -/* Destroys DIR and frees associated resources. */ -void -dir_close (struct dir *dir) -{ - if (dir != NULL) - { - inode_close (dir->inode); - free (dir); - } -} - -/* Returns the inode encapsulated by DIR. */ -struct inode * -dir_get_inode (struct dir *dir) -{ - return dir->inode; -} - -/* Searches DIR for a file with the given NAME. - If successful, returns true, sets *EP to the directory entry - if EP is non-null, and sets *OFSP to the byte offset of the - directory entry if OFSP is non-null. - otherwise, returns false and ignores EP and OFSP. */ -static bool -lookup (const struct dir *dir, const char *name, - struct dir_entry *ep, off_t *ofsp) -{ - struct dir_entry e; - size_t ofs; - - ASSERT (dir != NULL); - ASSERT (name != NULL); - - for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e; - ofs += sizeof e) - if (e.in_use && !strcmp (name, e.name)) - { - if (ep != NULL) - *ep = e; - if (ofsp != NULL) - *ofsp = ofs; - return true; - } - return false; -} - -/* Searches DIR for a file with the given NAME - and returns true if one exists, false otherwise. - On success, sets *INODE to an inode for the file, otherwise to - a null pointer. The caller must close *INODE. */ -bool -dir_lookup (const struct dir *dir, const char *name, - struct inode **inode) -{ - struct dir_entry e; - - ASSERT (dir != NULL); - ASSERT (name != NULL); - - if (lookup (dir, name, &e, NULL)) - *inode = inode_open (e.inode_sector); - else - *inode = NULL; - - return *inode != NULL; -} - -/* Adds a file named NAME to DIR, which must not already contain a - file by that name. The file's inode is in sector - INODE_SECTOR. - Returns true if successful, false on failure. - Fails if NAME is invalid (i.e. too long) or a disk or memory - error occurs. */ -bool -dir_add (struct dir *dir, const char *name, block_sector_t inode_sector) -{ - struct dir_entry e; - off_t ofs; - bool success = false; - - ASSERT (dir != NULL); - ASSERT (name != NULL); - - /* Check NAME for validity. */ - if (*name == '\0' || strlen (name) > NAME_MAX) - return false; - - /* Check that NAME is not in use. */ - if (lookup (dir, name, NULL, NULL)) - goto done; - - /* Set OFS to offset of free slot. - If there are no free slots, then it will be set to the - current end-of-file. - - inode_read_at() will only return a short read at end of file. - Otherwise, we'd need to verify that we didn't get a short - read due to something intermittent such as low memory. */ - for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e; - ofs += sizeof e) - if (!e.in_use) - break; - - /* Write slot. */ - e.in_use = true; - strlcpy (e.name, name, sizeof e.name); - e.inode_sector = inode_sector; - success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e; - - done: - return success; -} - -/* Removes any entry for NAME in DIR. - Returns true if successful, false on failure, - which occurs only if there is no file with the given NAME. */ -bool -dir_remove (struct dir *dir, const char *name) -{ - struct dir_entry e; - struct inode *inode = NULL; - bool success = false; - off_t ofs; - - ASSERT (dir != NULL); - ASSERT (name != NULL); - - /* Find directory entry. */ - if (!lookup (dir, name, &e, &ofs)) - goto done; - - /* Open inode. */ - inode = inode_open (e.inode_sector); - if (inode == NULL) - goto done; - - /* Erase directory entry. */ - e.in_use = false; - if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) - goto done; - - /* Remove inode. */ - inode_remove (inode); - success = true; - - done: - inode_close (inode); - return success; -} - -/* Reads the next directory entry in DIR and stores the name in - NAME. Returns true if successful, false if the directory - contains no more entries. */ -bool -dir_readdir (struct dir *dir, char name[NAME_MAX + 1]) -{ - struct dir_entry e; - - while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e) - { - dir->pos += sizeof e; - if (e.in_use) - { - strlcpy (name, e.name, NAME_MAX + 1); - return true; - } - } - return false; -} diff --git a/src/filesys/directory.h b/src/filesys/directory.h deleted file mode 100644 index 930acf986df4b1a647cb8d7cbd01c522d1b2b786..0000000000000000000000000000000000000000 --- a/src/filesys/directory.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef FILESYS_DIRECTORY_H -#define FILESYS_DIRECTORY_H - -#include <stdbool.h> -#include <stddef.h> -#include "devices/block.h" - -/* Maximum length of a file name component. - This is the traditional UNIX maximum length. - After directories are implemented, this maximum length may be - retained, but much longer full path names must be allowed. */ -#define NAME_MAX 14 - -struct inode; - -/* Opening and closing directories. */ -bool dir_create (block_sector_t sector, size_t entry_cnt); -struct dir *dir_open (struct inode *); -struct dir *dir_open_root (void); -struct dir *dir_reopen (struct dir *); -void dir_close (struct dir *); -struct inode *dir_get_inode (struct dir *); - -/* Reading and writing. */ -bool dir_lookup (const struct dir *, const char *name, struct inode **); -bool dir_add (struct dir *, const char *name, block_sector_t); -bool dir_remove (struct dir *, const char *name); -bool dir_readdir (struct dir *, char name[NAME_MAX + 1]); - -#endif /* filesys/directory.h */ diff --git a/src/filesys/file.c b/src/filesys/file.c deleted file mode 100644 index d5fc10de15004e98d4f8490aa8a7ec8a4c7efcff..0000000000000000000000000000000000000000 --- a/src/filesys/file.c +++ /dev/null @@ -1,168 +0,0 @@ -#include "filesys/file.h" -#include <debug.h> -#include "filesys/inode.h" -#include "threads/malloc.h" - -/* An open file. */ -struct file - { - struct inode *inode; /* File's inode. */ - off_t pos; /* Current position. */ - bool deny_write; /* Has file_deny_write() been called? */ - }; - -/* Opens a file for the given INODE, of which it takes ownership, - and returns the new file. Returns a null pointer if an - allocation fails or if INODE is null. */ -struct file * -file_open (struct inode *inode) -{ - struct file *file = calloc (1, sizeof *file); - if (inode != NULL && file != NULL) - { - file->inode = inode; - file->pos = 0; - file->deny_write = false; - return file; - } - else - { - inode_close (inode); - free (file); - return NULL; - } -} - -/* Opens and returns a new file for the same inode as FILE. - Returns a null pointer if unsuccessful. */ -struct file * -file_reopen (struct file *file) -{ - return file_open (inode_reopen (file->inode)); -} - -/* Closes FILE. */ -void -file_close (struct file *file) -{ - if (file != NULL) - { - file_allow_write (file); - inode_close (file->inode); - free (file); - } -} - -/* Returns the inode encapsulated by FILE. */ -struct inode * -file_get_inode (struct file *file) -{ - return file->inode; -} - -/* Reads SIZE bytes from FILE into BUFFER, - starting at the file's current position. - Returns the number of bytes actually read, - which may be less than SIZE if end of file is reached. - Advances FILE's position by the number of bytes read. */ -off_t -file_read (struct file *file, void *buffer, off_t size) -{ - off_t bytes_read = inode_read_at (file->inode, buffer, size, file->pos); - file->pos += bytes_read; - return bytes_read; -} - -/* Reads SIZE bytes from FILE into BUFFER, - starting at offset FILE_OFS in the file. - Returns the number of bytes actually read, - which may be less than SIZE if end of file is reached. - The file's current position is unaffected. */ -off_t -file_read_at (struct file *file, void *buffer, off_t size, off_t file_ofs) -{ - return inode_read_at (file->inode, buffer, size, file_ofs); -} - -/* Writes SIZE bytes from BUFFER into FILE, - starting at the file's current position. - Returns the number of bytes actually written, - which may be less than SIZE if end of file is reached. - (Normally we'd grow the file in that case, but file growth is - not yet implemented.) - Advances FILE's position by the number of bytes read. */ -off_t -file_write (struct file *file, const void *buffer, off_t size) -{ - off_t bytes_written = inode_write_at (file->inode, buffer, size, file->pos); - file->pos += bytes_written; - return bytes_written; -} - -/* Writes SIZE bytes from BUFFER into FILE, - starting at offset FILE_OFS in the file. - Returns the number of bytes actually written, - which may be less than SIZE if end of file is reached. - (Normally we'd grow the file in that case, but file growth is - not yet implemented.) - The file's current position is unaffected. */ -off_t -file_write_at (struct file *file, const void *buffer, off_t size, - off_t file_ofs) -{ - return inode_write_at (file->inode, buffer, size, file_ofs); -} - -/* Prevents write operations on FILE's underlying inode - until file_allow_write() is called or FILE is closed. */ -void -file_deny_write (struct file *file) -{ - ASSERT (file != NULL); - if (!file->deny_write) - { - file->deny_write = true; - inode_deny_write (file->inode); - } -} - -/* Re-enables write operations on FILE's underlying inode. - (Writes might still be denied by some other file that has the - same inode open.) */ -void -file_allow_write (struct file *file) -{ - ASSERT (file != NULL); - if (file->deny_write) - { - file->deny_write = false; - inode_allow_write (file->inode); - } -} - -/* Returns the size of FILE in bytes. */ -off_t -file_length (struct file *file) -{ - ASSERT (file != NULL); - return inode_length (file->inode); -} - -/* Sets the current position in FILE to NEW_POS bytes from the - start of the file. */ -void -file_seek (struct file *file, off_t new_pos) -{ - ASSERT (file != NULL); - ASSERT (new_pos >= 0); - file->pos = new_pos; -} - -/* Returns the current position in FILE as a byte offset from the - start of the file. */ -off_t -file_tell (struct file *file) -{ - ASSERT (file != NULL); - return file->pos; -} diff --git a/src/filesys/file.h b/src/filesys/file.h deleted file mode 100644 index a33c5af49f7c9c29142b234290e7c1969b9f54cb..0000000000000000000000000000000000000000 --- a/src/filesys/file.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef FILESYS_FILE_H -#define FILESYS_FILE_H - -#include "filesys/off_t.h" - -struct inode; - -/* Opening and closing files. */ -struct file *file_open (struct inode *); -struct file *file_reopen (struct file *); -void file_close (struct file *); -struct inode *file_get_inode (struct file *); - -/* Reading and writing. */ -off_t file_read (struct file *, void *, off_t); -off_t file_read_at (struct file *, void *, off_t size, off_t start); -off_t file_write (struct file *, const void *, off_t); -off_t file_write_at (struct file *, const void *, off_t size, off_t start); - -/* Preventing writes. */ -void file_deny_write (struct file *); -void file_allow_write (struct file *); - -/* File position. */ -void file_seek (struct file *, off_t); -off_t file_tell (struct file *); -off_t file_length (struct file *); - -#endif /* filesys/file.h */ diff --git a/src/filesys/filesys.c b/src/filesys/filesys.c deleted file mode 100644 index 7a53f5ffd924ca7b1b384fd9b46b3256e14f30e6..0000000000000000000000000000000000000000 --- a/src/filesys/filesys.c +++ /dev/null @@ -1,103 +0,0 @@ -#include "filesys/filesys.h" -#include <debug.h> -#include <stdio.h> -#include <string.h> -#include "filesys/file.h" -#include "filesys/free-map.h" -#include "filesys/inode.h" -#include "filesys/directory.h" - -/* Partition that contains the file system. */ -struct block *fs_device; - -static void do_format (void); - -/* Initializes the file system module. - If FORMAT is true, reformats the file system. */ -void -filesys_init (bool format) -{ - fs_device = block_get_role (BLOCK_FILESYS); - if (fs_device == NULL) - PANIC ("No file system device found, can't initialize file system."); - - inode_init (); - free_map_init (); - - if (format) - do_format (); - - free_map_open (); -} - -/* Shuts down the file system module, writing any unwritten data - to disk. */ -void -filesys_done (void) -{ - free_map_close (); -} - -/* Creates a file named NAME with the given INITIAL_SIZE. - Returns true if successful, false otherwise. - Fails if a file named NAME already exists, - or if internal memory allocation fails. */ -bool -filesys_create (const char *name, off_t initial_size) -{ - block_sector_t inode_sector = 0; - struct dir *dir = dir_open_root (); - bool success = (dir != NULL - && free_map_allocate (1, &inode_sector) - && inode_create (inode_sector, initial_size) - && dir_add (dir, name, inode_sector)); - if (!success && inode_sector != 0) - free_map_release (inode_sector, 1); - dir_close (dir); - - return success; -} - -/* Opens the file with the given NAME. - Returns the new file if successful or a null pointer - otherwise. - Fails if no file named NAME exists, - or if an internal memory allocation fails. */ -struct file * -filesys_open (const char *name) -{ - struct dir *dir = dir_open_root (); - struct inode *inode = NULL; - - if (dir != NULL) - dir_lookup (dir, name, &inode); - dir_close (dir); - - return file_open (inode); -} - -/* Deletes the file named NAME. - Returns true if successful, false on failure. - Fails if no file named NAME exists, - or if an internal memory allocation fails. */ -bool -filesys_remove (const char *name) -{ - struct dir *dir = dir_open_root (); - bool success = dir != NULL && dir_remove (dir, name); - dir_close (dir); - - return success; -} - -/* Formats the file system. */ -static void -do_format (void) -{ - printf ("Formatting file system..."); - free_map_create (); - if (!dir_create (ROOT_DIR_SECTOR, 16)) - PANIC ("root directory creation failed"); - free_map_close (); - printf ("done.\n"); -} diff --git a/src/filesys/filesys.h b/src/filesys/filesys.h deleted file mode 100644 index c1cda84ecc324fbe70b4e9e3e729ed9ade89c24b..0000000000000000000000000000000000000000 --- a/src/filesys/filesys.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef FILESYS_FILESYS_H -#define FILESYS_FILESYS_H - -#include <stdbool.h> -#include "filesys/off_t.h" - -/* Sectors of system file inodes. */ -#define FREE_MAP_SECTOR 0 /* Free map file inode sector. */ -#define ROOT_DIR_SECTOR 1 /* Root directory file inode sector. */ - -/* Block device that contains the file system. */ -struct block *fs_device; - -void filesys_init (bool format); -void filesys_done (void); -bool filesys_create (const char *name, off_t initial_size); -struct file *filesys_open (const char *name); -bool filesys_remove (const char *name); - -#endif /* filesys/filesys.h */ diff --git a/src/filesys/free-map.c b/src/filesys/free-map.c deleted file mode 100644 index 29ea4df8d2a64876ea8f2a384f4ad6f44ce1659b..0000000000000000000000000000000000000000 --- a/src/filesys/free-map.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "filesys/free-map.h" -#include <bitmap.h> -#include <debug.h> -#include "filesys/file.h" -#include "filesys/filesys.h" -#include "filesys/inode.h" - -static struct file *free_map_file; /* Free map file. */ -static struct bitmap *free_map; /* Free map, one bit per sector. */ - -/* Initializes the free map. */ -void -free_map_init (void) -{ - free_map = bitmap_create (block_size (fs_device)); - if (free_map == NULL) - PANIC ("bitmap creation failed--file system device is too large"); - bitmap_mark (free_map, FREE_MAP_SECTOR); - bitmap_mark (free_map, ROOT_DIR_SECTOR); -} - -/* Allocates CNT consecutive sectors from the free map and stores - the first into *SECTORP. - Returns true if successful, false if not enough consecutive - sectors were available or if the free_map file could not be - written. */ -bool -free_map_allocate (size_t cnt, block_sector_t *sectorp) -{ - block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false); - if (sector != BITMAP_ERROR - && free_map_file != NULL - && !bitmap_write (free_map, free_map_file)) - { - bitmap_set_multiple (free_map, sector, cnt, false); - sector = BITMAP_ERROR; - } - if (sector != BITMAP_ERROR) - *sectorp = sector; - return sector != BITMAP_ERROR; -} - -/* Makes CNT sectors starting at SECTOR available for use. */ -void -free_map_release (block_sector_t sector, size_t cnt) -{ - ASSERT (bitmap_all (free_map, sector, cnt)); - bitmap_set_multiple (free_map, sector, cnt, false); - bitmap_write (free_map, free_map_file); -} - -/* Opens the free map file and reads it from disk. */ -void -free_map_open (void) -{ - free_map_file = file_open (inode_open (FREE_MAP_SECTOR)); - if (free_map_file == NULL) - PANIC ("can't open free map"); - if (!bitmap_read (free_map, free_map_file)) - PANIC ("can't read free map"); -} - -/* Writes the free map to disk and closes the free map file. */ -void -free_map_close (void) -{ - file_close (free_map_file); -} - -/* Creates a new free map file on disk and writes the free map to - it. */ -void -free_map_create (void) -{ - /* Create inode. */ - if (!inode_create (FREE_MAP_SECTOR, bitmap_file_size (free_map))) - PANIC ("free map creation failed"); - - /* Write bitmap to file. */ - free_map_file = file_open (inode_open (FREE_MAP_SECTOR)); - if (free_map_file == NULL) - PANIC ("can't open free map"); - if (!bitmap_write (free_map, free_map_file)) - PANIC ("can't write free map"); -} diff --git a/src/filesys/free-map.h b/src/filesys/free-map.h deleted file mode 100644 index 316cd1c8cb851c6652a8910a861826d8c2a95230..0000000000000000000000000000000000000000 --- a/src/filesys/free-map.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef FILESYS_FREE_MAP_H -#define FILESYS_FREE_MAP_H - -#include <stdbool.h> -#include <stddef.h> -#include "devices/block.h" - -void free_map_init (void); -void free_map_read (void); -void free_map_create (void); -void free_map_open (void); -void free_map_close (void); - -bool free_map_allocate (size_t, block_sector_t *); -void free_map_release (block_sector_t, size_t); - -#endif /* filesys/free-map.h */ diff --git a/src/filesys/fsutil.c b/src/filesys/fsutil.c deleted file mode 100644 index 5f045d64a5ad076f02d686007687d0a93a082f90..0000000000000000000000000000000000000000 --- a/src/filesys/fsutil.c +++ /dev/null @@ -1,223 +0,0 @@ -#include "filesys/fsutil.h" -#include <debug.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ustar.h> -#include "filesys/directory.h" -#include "filesys/file.h" -#include "filesys/filesys.h" -#include "threads/malloc.h" -#include "threads/palloc.h" -#include "threads/vaddr.h" - -/* List files in the root directory. */ -void -fsutil_ls (char **argv UNUSED) -{ - struct dir *dir; - char name[NAME_MAX + 1]; - - printf ("Files in the root directory:\n"); - dir = dir_open_root (); - if (dir == NULL) - PANIC ("root dir open failed"); - while (dir_readdir (dir, name)) - printf ("%s\n", name); - dir_close (dir); - printf ("End of listing.\n"); -} - -/* Prints the contents of file ARGV[1] to the system console as - hex and ASCII. */ -void -fsutil_cat (char **argv) -{ - const char *file_name = argv[1]; - - struct file *file; - char *buffer; - - printf ("Printing '%s' to the console...\n", file_name); - file = filesys_open (file_name); - if (file == NULL) - PANIC ("%s: open failed", file_name); - buffer = palloc_get_page (PAL_ASSERT); - for (;;) - { - off_t pos = file_tell (file); - off_t n = file_read (file, buffer, PGSIZE); - if (n == 0) - break; - - hex_dump (pos, buffer, n, true); - } - palloc_free_page (buffer); - file_close (file); -} - -/* Deletes file ARGV[1]. */ -void -fsutil_rm (char **argv) -{ - const char *file_name = argv[1]; - - printf ("Deleting '%s'...\n", file_name); - if (!filesys_remove (file_name)) - PANIC ("%s: delete failed\n", file_name); -} - -/* Extracts a ustar-format tar archive from the scratch block - device into the Pintos file system. */ -void -fsutil_extract (char **argv UNUSED) -{ - static block_sector_t sector = 0; - - struct block *src; - void *header, *data; - - /* Allocate buffers. */ - header = malloc (BLOCK_SECTOR_SIZE); - data = malloc (BLOCK_SECTOR_SIZE); - if (header == NULL || data == NULL) - PANIC ("couldn't allocate buffers"); - - /* Open source block device. */ - src = block_get_role (BLOCK_SCRATCH); - if (src == NULL) - PANIC ("couldn't open scratch device"); - - printf ("Extracting ustar archive from scratch device " - "into file system...\n"); - - for (;;) - { - const char *file_name; - const char *error; - enum ustar_type type; - int size; - - /* Read and parse ustar header. */ - block_read (src, sector++, header); - error = ustar_parse_header (header, &file_name, &type, &size); - if (error != NULL) - PANIC ("bad ustar header in sector %"PRDSNu" (%s)", sector - 1, error); - - if (type == USTAR_EOF) - { - /* End of archive. */ - break; - } - else if (type == USTAR_DIRECTORY) - printf ("ignoring directory %s\n", file_name); - else if (type == USTAR_REGULAR) - { - struct file *dst; - - printf ("Putting '%s' into the file system...\n", file_name); - - /* Create destination file. */ - if (!filesys_create (file_name, size)) - PANIC ("%s: create failed", file_name); - dst = filesys_open (file_name); - if (dst == NULL) - PANIC ("%s: open failed", file_name); - - /* Do copy. */ - while (size > 0) - { - int chunk_size = (size > BLOCK_SECTOR_SIZE - ? BLOCK_SECTOR_SIZE - : size); - block_read (src, sector++, data); - if (file_write (dst, data, chunk_size) != chunk_size) - PANIC ("%s: write failed with %d bytes unwritten", - file_name, size); - size -= chunk_size; - } - - /* Finish up. */ - file_close (dst); - } - } - - /* Erase the ustar header from the start of the block device, - so that the extraction operation is idempotent. We erase - two blocks because two blocks of zeros are the ustar - end-of-archive marker. */ - printf ("Erasing ustar archive...\n"); - memset (header, 0, BLOCK_SECTOR_SIZE); - block_write (src, 0, header); - block_write (src, 1, header); - - free (data); - free (header); -} - -/* Copies file FILE_NAME from the file system to the scratch - device, in ustar format. - - The first call to this function will write starting at the - beginning of the scratch device. Later calls advance across - the device. This position is independent of that used for - fsutil_extract(), so `extract' should precede all - `append's. */ -void -fsutil_append (char **argv) -{ - static block_sector_t sector = 0; - - const char *file_name = argv[1]; - void *buffer; - struct file *src; - struct block *dst; - off_t size; - - printf ("Appending '%s' to ustar archive on scratch device...\n", file_name); - - /* Allocate buffer. */ - buffer = malloc (BLOCK_SECTOR_SIZE); - if (buffer == NULL) - PANIC ("couldn't allocate buffer"); - - /* Open source file. */ - src = filesys_open (file_name); - if (src == NULL) - PANIC ("%s: open failed", file_name); - size = file_length (src); - - /* Open target block device. */ - dst = block_get_role (BLOCK_SCRATCH); - if (dst == NULL) - PANIC ("couldn't open scratch device"); - - /* Write ustar header to first sector. */ - if (!ustar_make_header (file_name, USTAR_REGULAR, size, buffer)) - PANIC ("%s: name too long for ustar format", file_name); - block_write (dst, sector++, buffer); - - /* Do copy. */ - while (size > 0) - { - int chunk_size = size > BLOCK_SECTOR_SIZE ? BLOCK_SECTOR_SIZE : size; - if (sector >= block_size (dst)) - PANIC ("%s: out of space on scratch device", file_name); - if (file_read (src, buffer, chunk_size) != chunk_size) - PANIC ("%s: read failed with %"PROTd" bytes unread", file_name, size); - memset (buffer + chunk_size, 0, BLOCK_SECTOR_SIZE - chunk_size); - block_write (dst, sector++, buffer); - size -= chunk_size; - } - - /* Write ustar end-of-archive marker, which is two consecutive - sectors full of zeros. Don't advance our position past - them, though, in case we have more files to append. */ - memset (buffer, 0, BLOCK_SECTOR_SIZE); - block_write (dst, sector, buffer); - block_write (dst, sector, buffer + 1); - - /* Finish up. */ - file_close (src); - free (buffer); -} diff --git a/src/filesys/fsutil.h b/src/filesys/fsutil.h deleted file mode 100644 index cc7370568b23eb69e2f51fb8cd057139c0822511..0000000000000000000000000000000000000000 --- a/src/filesys/fsutil.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef FILESYS_FSUTIL_H -#define FILESYS_FSUTIL_H - -void fsutil_ls (char **argv); -void fsutil_cat (char **argv); -void fsutil_rm (char **argv); -void fsutil_extract (char **argv); -void fsutil_append (char **argv); - -#endif /* filesys/fsutil.h */ diff --git a/src/filesys/inode.c b/src/filesys/inode.c deleted file mode 100644 index 34635637114212a54a5fb1313a6f4a1484b57ff2..0000000000000000000000000000000000000000 --- a/src/filesys/inode.c +++ /dev/null @@ -1,345 +0,0 @@ -#include "filesys/inode.h" -#include <list.h> -#include <debug.h> -#include <round.h> -#include <string.h> -#include "filesys/filesys.h" -#include "filesys/free-map.h" -#include "threads/malloc.h" - -/* Identifies an inode. */ -#define INODE_MAGIC 0x494e4f44 - -/* On-disk inode. - Must be exactly BLOCK_SECTOR_SIZE bytes long. */ -struct inode_disk - { - block_sector_t start; /* First data sector. */ - off_t length; /* File size in bytes. */ - unsigned magic; /* Magic number. */ - uint32_t unused[125]; /* Not used. */ - }; - -/* Returns the number of sectors to allocate for an inode SIZE - bytes long. */ -static inline size_t -bytes_to_sectors (off_t size) -{ - return DIV_ROUND_UP (size, BLOCK_SECTOR_SIZE); -} - -/* In-memory inode. */ -struct inode - { - struct list_elem elem; /* Element in inode list. */ - block_sector_t sector; /* Sector number of disk location. */ - int open_cnt; /* Number of openers. */ - bool removed; /* True if deleted, false otherwise. */ - int deny_write_cnt; /* 0: writes ok, >0: deny writes. */ - struct inode_disk data; /* Inode content. */ - }; - -/* Returns the block device sector that contains byte offset POS - within INODE. - Returns -1 if INODE does not contain data for a byte at offset - POS. */ -static block_sector_t -byte_to_sector (const struct inode *inode, off_t pos) -{ - ASSERT (inode != NULL); - if (pos < inode->data.length) - return inode->data.start + pos / BLOCK_SECTOR_SIZE; - else - return -1; -} - -/* List of open inodes, so that opening a single inode twice - returns the same `struct inode'. */ -static struct list open_inodes; - -/* Initializes the inode module. */ -void -inode_init (void) -{ - list_init (&open_inodes); -} - -/* Initializes an inode with LENGTH bytes of data and - writes the new inode to sector SECTOR on the file system - device. - Returns true if successful. - Returns false if memory or disk allocation fails. */ -bool -inode_create (block_sector_t sector, off_t length) -{ - struct inode_disk *disk_inode = NULL; - bool success = false; - - ASSERT (length >= 0); - - /* If this assertion fails, the inode structure is not exactly - one sector in size, and you should fix that. */ - ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE); - - disk_inode = calloc (1, sizeof *disk_inode); - if (disk_inode != NULL) - { - size_t sectors = bytes_to_sectors (length); - disk_inode->length = length; - disk_inode->magic = INODE_MAGIC; - if (free_map_allocate (sectors, &disk_inode->start)) - { - block_write (fs_device, sector, disk_inode); - if (sectors > 0) - { - static char zeros[BLOCK_SECTOR_SIZE]; - size_t i; - - for (i = 0; i < sectors; i++) - block_write (fs_device, disk_inode->start + i, zeros); - } - success = true; - } - free (disk_inode); - } - return success; -} - -/* Reads an inode from SECTOR - and returns a `struct inode' that contains it. - Returns a null pointer if memory allocation fails. */ -struct inode * -inode_open (block_sector_t sector) -{ - struct list_elem *e; - struct inode *inode; - - /* Check whether this inode is already open. */ - for (e = list_begin (&open_inodes); e != list_end (&open_inodes); - e = list_next (e)) - { - inode = list_entry (e, struct inode, elem); - if (inode->sector == sector) - { - inode_reopen (inode); - return inode; - } - } - - /* Allocate memory. */ - inode = malloc (sizeof *inode); - if (inode == NULL) - return NULL; - - /* Initialize. */ - list_push_front (&open_inodes, &inode->elem); - inode->sector = sector; - inode->open_cnt = 1; - inode->deny_write_cnt = 0; - inode->removed = false; - block_read (fs_device, inode->sector, &inode->data); - return inode; -} - -/* Reopens and returns INODE. */ -struct inode * -inode_reopen (struct inode *inode) -{ - if (inode != NULL) - inode->open_cnt++; - return inode; -} - -/* Returns INODE's inode number. */ -block_sector_t -inode_get_inumber (const struct inode *inode) -{ - return inode->sector; -} - -/* Closes INODE and writes it to disk. - If this was the last reference to INODE, frees its memory. - If INODE was also a removed inode, frees its blocks. */ -void -inode_close (struct inode *inode) -{ - /* Ignore null pointer. */ - if (inode == NULL) - return; - - /* Release resources if this was the last opener. */ - if (--inode->open_cnt == 0) - { - /* Remove from inode list and release lock. */ - list_remove (&inode->elem); - - /* Deallocate blocks if removed. */ - if (inode->removed) - { - free_map_release (inode->sector, 1); - free_map_release (inode->data.start, - bytes_to_sectors (inode->data.length)); - } - - free (inode); - } -} - -/* Marks INODE to be deleted when it is closed by the last caller who - has it open. */ -void -inode_remove (struct inode *inode) -{ - ASSERT (inode != NULL); - inode->removed = true; -} - -/* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET. - Returns the number of bytes actually read, which may be less - than SIZE if an error occurs or end of file is reached. */ -off_t -inode_read_at (struct inode *inode, void *buffer_, off_t size, off_t offset) -{ - uint8_t *buffer = buffer_; - off_t bytes_read = 0; - uint8_t *bounce = NULL; - - while (size > 0) - { - /* Disk sector to read, starting byte offset within sector. */ - block_sector_t sector_idx = byte_to_sector (inode, offset); - int sector_ofs = offset % BLOCK_SECTOR_SIZE; - - /* Bytes left in inode, bytes left in sector, lesser of the two. */ - off_t inode_left = inode_length (inode) - offset; - int sector_left = BLOCK_SECTOR_SIZE - sector_ofs; - int min_left = inode_left < sector_left ? inode_left : sector_left; - - /* Number of bytes to actually copy out of this sector. */ - int chunk_size = size < min_left ? size : min_left; - if (chunk_size <= 0) - break; - - if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE) - { - /* Read full sector directly into caller's buffer. */ - block_read (fs_device, sector_idx, buffer + bytes_read); - } - else - { - /* Read sector into bounce buffer, then partially copy - into caller's buffer. */ - if (bounce == NULL) - { - bounce = malloc (BLOCK_SECTOR_SIZE); - if (bounce == NULL) - break; - } - block_read (fs_device, sector_idx, bounce); - memcpy (buffer + bytes_read, bounce + sector_ofs, chunk_size); - } - - /* Advance. */ - size -= chunk_size; - offset += chunk_size; - bytes_read += chunk_size; - } - free (bounce); - - return bytes_read; -} - -/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET. - Returns the number of bytes actually written, which may be - less than SIZE if end of file is reached or an error occurs. - (Normally a write at end of file would extend the inode, but - growth is not yet implemented.) */ -off_t -inode_write_at (struct inode *inode, const void *buffer_, off_t size, - off_t offset) -{ - const uint8_t *buffer = buffer_; - off_t bytes_written = 0; - uint8_t *bounce = NULL; - - if (inode->deny_write_cnt) - return 0; - - while (size > 0) - { - /* Sector to write, starting byte offset within sector. */ - block_sector_t sector_idx = byte_to_sector (inode, offset); - int sector_ofs = offset % BLOCK_SECTOR_SIZE; - - /* Bytes left in inode, bytes left in sector, lesser of the two. */ - off_t inode_left = inode_length (inode) - offset; - int sector_left = BLOCK_SECTOR_SIZE - sector_ofs; - int min_left = inode_left < sector_left ? inode_left : sector_left; - - /* Number of bytes to actually write into this sector. */ - int chunk_size = size < min_left ? size : min_left; - if (chunk_size <= 0) - break; - - if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE) - { - /* Write full sector directly to disk. */ - block_write (fs_device, sector_idx, buffer + bytes_written); - } - else - { - /* We need a bounce buffer. */ - if (bounce == NULL) - { - bounce = malloc (BLOCK_SECTOR_SIZE); - if (bounce == NULL) - break; - } - - /* If the sector contains data before or after the chunk - we're writing, then we need to read in the sector - first. Otherwise we start with a sector of all zeros. */ - if (sector_ofs > 0 || chunk_size < sector_left) - block_read (fs_device, sector_idx, bounce); - else - memset (bounce, 0, BLOCK_SECTOR_SIZE); - memcpy (bounce + sector_ofs, buffer + bytes_written, chunk_size); - block_write (fs_device, sector_idx, bounce); - } - - /* Advance. */ - size -= chunk_size; - offset += chunk_size; - bytes_written += chunk_size; - } - free (bounce); - - return bytes_written; -} - -/* Disables writes to INODE. - May be called at most once per inode opener. */ -void -inode_deny_write (struct inode *inode) -{ - inode->deny_write_cnt++; - ASSERT (inode->deny_write_cnt <= inode->open_cnt); -} - -/* Re-enables writes to INODE. - Must be called once by each inode opener who has called - inode_deny_write() on the inode, before closing the inode. */ -void -inode_allow_write (struct inode *inode) -{ - ASSERT (inode->deny_write_cnt > 0); - ASSERT (inode->deny_write_cnt <= inode->open_cnt); - inode->deny_write_cnt--; -} - -/* Returns the length, in bytes, of INODE's data. */ -off_t -inode_length (const struct inode *inode) -{ - return inode->data.length; -} diff --git a/src/filesys/inode.h b/src/filesys/inode.h deleted file mode 100644 index cb42310fa8d77dcc438a4cd689361b1e126bacbe..0000000000000000000000000000000000000000 --- a/src/filesys/inode.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef FILESYS_INODE_H -#define FILESYS_INODE_H - -#include <stdbool.h> -#include "filesys/off_t.h" -#include "devices/block.h" - -struct bitmap; - -void inode_init (void); -bool inode_create (block_sector_t, off_t); -struct inode *inode_open (block_sector_t); -struct inode *inode_reopen (struct inode *); -block_sector_t inode_get_inumber (const struct inode *); -void inode_close (struct inode *); -void inode_remove (struct inode *); -off_t inode_read_at (struct inode *, void *, off_t size, off_t offset); -off_t inode_write_at (struct inode *, const void *, off_t size, off_t offset); -void inode_deny_write (struct inode *); -void inode_allow_write (struct inode *); -off_t inode_length (const struct inode *); - -#endif /* filesys/inode.h */ diff --git a/src/filesys/off_t.h b/src/filesys/off_t.h deleted file mode 100644 index 9caff4dbae88823f109b1d3ee99c7535f79a55ce..0000000000000000000000000000000000000000 --- a/src/filesys/off_t.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef FILESYS_OFF_T_H -#define FILESYS_OFF_T_H - -#include <stdint.h> - -/* An offset within a file. - This is a separate header because multiple headers want this - definition but not any others. */ -typedef int32_t off_t; - -/* Format specifier for printf(), e.g.: - printf ("offset=%"PROTd"\n", offset); */ -#define PROTd PRId32 - -#endif /* filesys/off_t.h */ diff --git a/src/lib/#syscall-nr.h# b/src/lib/#syscall-nr.h# deleted file mode 100644 index 21a7af952f8728f93b77d6867ebbf60a7699864c..0000000000000000000000000000000000000000 --- a/src/lib/#syscall-nr.h# +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __LIB_SYSCALL_NR_H -#define __LIB_SYSCALL_NR_H - -/* System call numbers. */ -enum - { - /* Projects 2 and later. */ - SYS_HALT, /* Halt the operating system. */ - SYS_EXIT, /* Terminate this process. */ - SYS_EXEC, /* Start another process. */ - SYS_WAIT, /* Wait for a child process to die. */ - SYS_CREATE, /* Create a file. */ - SYS_REMOVE, /* Delete a file. */ - SYS_OPEN, /* Open a file. */ - SYS_FILESIZE, /* Obtain a file's size. */ - SYS_READ, /* Read from a file. */ - SYS_WRITE, /* Write to a file. */ - SYS_SEEK, /* Change position in a file. */ - SYS_TELL, /* Report current position in a file. */ - SYS_CLOSE, /* Close a file. */ - - /* Project 3 and optionally project 4. */ - SYS_MMAP, /* Map a file into memory. */ - SYS_MUNMAP, /* Remove a memory mapping. */ - - /* Project 4 only. */ - SYS_CHDIR, /* Change the current directory. */ - SYS_MKDIR, /* Create a directory. */ - SYS_READDIR, /* Reads a directory entry. */ - SYS_ISDIR, /* Tests if a fd represents a directory. */ - SYS_INUMBER /* Returns the inode number for a fd. */ - }; - -#endif /* lib/syscall-nr.h */ diff --git a/src/lib/arithmetic.c b/src/lib/arithmetic.c deleted file mode 100644 index bfc9b5a4bd044b930093f5dc6d34c707cc63db89..0000000000000000000000000000000000000000 --- a/src/lib/arithmetic.c +++ /dev/null @@ -1,189 +0,0 @@ -#include <stdint.h> - -/* On x86, division of one 64-bit integer by another cannot be - done with a single instruction or a short sequence. Thus, GCC - implements 64-bit division and remainder operations through - function calls. These functions are normally obtained from - libgcc, which is automatically included by GCC in any link - that it does. - - Some x86-64 machines, however, have a compiler and utilities - that can generate 32-bit x86 code without having any of the - necessary libraries, including libgcc. Thus, we can make - Pintos work on these machines by simply implementing our own - 64-bit division routines, which are the only routines from - libgcc that Pintos requires. - - Completeness is another reason to include these routines. If - Pintos is completely self-contained, then that makes it that - much less mysterious. */ - -/* Uses x86 DIVL instruction to divide 64-bit N by 32-bit D to - yield a 32-bit quotient. Returns the quotient. - Traps with a divide error (#DE) if the quotient does not fit - in 32 bits. */ -static inline uint32_t -divl (uint64_t n, uint32_t d) -{ - uint32_t n1 = n >> 32; - uint32_t n0 = n; - uint32_t q, r; - - asm ("divl %4" - : "=d" (r), "=a" (q) - : "0" (n1), "1" (n0), "rm" (d)); - - return q; -} - -/* Returns the number of leading zero bits in X, - which must be nonzero. */ -static int -nlz (uint32_t x) -{ - /* This technique is portable, but there are better ways to do - it on particular systems. With sufficiently new enough GCC, - you can use __builtin_clz() to take advantage of GCC's - knowledge of how to do it. Or you can use the x86 BSR - instruction directly. */ - int n = 0; - if (x <= 0x0000FFFF) - { - n += 16; - x <<= 16; - } - if (x <= 0x00FFFFFF) - { - n += 8; - x <<= 8; - } - if (x <= 0x0FFFFFFF) - { - n += 4; - x <<= 4; - } - if (x <= 0x3FFFFFFF) - { - n += 2; - x <<= 2; - } - if (x <= 0x7FFFFFFF) - n++; - return n; -} - -/* Divides unsigned 64-bit N by unsigned 64-bit D and returns the - quotient. */ -static uint64_t -udiv64 (uint64_t n, uint64_t d) -{ - if ((d >> 32) == 0) - { - /* Proof of correctness: - - Let n, d, b, n1, and n0 be defined as in this function. - Let [x] be the "floor" of x. Let T = b[n1/d]. Assume d - nonzero. Then: - [n/d] = [n/d] - T + T - = [n/d - T] + T by (1) below - = [(b*n1 + n0)/d - T] + T by definition of n - = [(b*n1 + n0)/d - dT/d] + T - = [(b(n1 - d[n1/d]) + n0)/d] + T - = [(b[n1 % d] + n0)/d] + T, by definition of % - which is the expression calculated below. - - (1) Note that for any real x, integer i: [x] + i = [x + i]. - - To prevent divl() from trapping, [(b[n1 % d] + n0)/d] must - be less than b. Assume that [n1 % d] and n0 take their - respective maximum values of d - 1 and b - 1: - [(b(d - 1) + (b - 1))/d] < b - <=> [(bd - 1)/d] < b - <=> [b - 1/d] < b - which is a tautology. - - Therefore, this code is correct and will not trap. */ - uint64_t b = 1ULL << 32; - uint32_t n1 = n >> 32; - uint32_t n0 = n; - uint32_t d0 = d; - - return divl (b * (n1 % d0) + n0, d0) + b * (n1 / d0); - } - else - { - /* Based on the algorithm and proof available from - http://www.hackersdelight.org/revisions.pdf. */ - if (n < d) - return 0; - else - { - uint32_t d1 = d >> 32; - int s = nlz (d1); - uint64_t q = divl (n >> 1, (d << s) >> 32) >> (31 - s); - return n - (q - 1) * d < d ? q - 1 : q; - } - } -} - -/* Divides unsigned 64-bit N by unsigned 64-bit D and returns the - remainder. */ -static uint32_t -umod64 (uint64_t n, uint64_t d) -{ - return n - d * udiv64 (n, d); -} - -/* Divides signed 64-bit N by signed 64-bit D and returns the - quotient. */ -static int64_t -sdiv64 (int64_t n, int64_t d) -{ - uint64_t n_abs = n >= 0 ? (uint64_t) n : -(uint64_t) n; - uint64_t d_abs = d >= 0 ? (uint64_t) d : -(uint64_t) d; - uint64_t q_abs = udiv64 (n_abs, d_abs); - return (n < 0) == (d < 0) ? (int64_t) q_abs : -(int64_t) q_abs; -} - -/* Divides signed 64-bit N by signed 64-bit D and returns the - remainder. */ -static int32_t -smod64 (int64_t n, int64_t d) -{ - return n - d * sdiv64 (n, d); -} - -/* These are the routines that GCC calls. */ - -long long __divdi3 (long long n, long long d); -long long __moddi3 (long long n, long long d); -unsigned long long __udivdi3 (unsigned long long n, unsigned long long d); -unsigned long long __umoddi3 (unsigned long long n, unsigned long long d); - -/* Signed 64-bit division. */ -long long -__divdi3 (long long n, long long d) -{ - return sdiv64 (n, d); -} - -/* Signed 64-bit remainder. */ -long long -__moddi3 (long long n, long long d) -{ - return smod64 (n, d); -} - -/* Unsigned 64-bit division. */ -unsigned long long -__udivdi3 (unsigned long long n, unsigned long long d) -{ - return udiv64 (n, d); -} - -/* Unsigned 64-bit remainder. */ -unsigned long long -__umoddi3 (unsigned long long n, unsigned long long d) -{ - return umod64 (n, d); -} diff --git a/src/lib/ctype.h b/src/lib/ctype.h deleted file mode 100644 index 9096aca4dbc7f0cded660d624dd364b831cdbfc5..0000000000000000000000000000000000000000 --- a/src/lib/ctype.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __LIB_CTYPE_H -#define __LIB_CTYPE_H - -static inline int islower (int c) { return c >= 'a' && c <= 'z'; } -static inline int isupper (int c) { return c >= 'A' && c <= 'Z'; } -static inline int isalpha (int c) { return islower (c) || isupper (c); } -static inline int isdigit (int c) { return c >= '0' && c <= '9'; } -static inline int isalnum (int c) { return isalpha (c) || isdigit (c); } -static inline int isxdigit (int c) { - return isdigit (c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} -static inline int isspace (int c) { - return (c == ' ' || c == '\f' || c == '\n' - || c == '\r' || c == '\t' || c == '\v'); -} -static inline int isblank (int c) { return c == ' ' || c == '\t'; } -static inline int isgraph (int c) { return c > 32 && c < 127; } -static inline int isprint (int c) { return c >= 32 && c < 127; } -static inline int iscntrl (int c) { return (c >= 0 && c < 32) || c == 127; } -static inline int isascii (int c) { return c >= 0 && c < 128; } -static inline int ispunct (int c) { - return isprint (c) && !isalnum (c) && !isspace (c); -} - -static inline int tolower (int c) { return isupper (c) ? c - 'A' + 'a' : c; } -static inline int toupper (int c) { return islower (c) ? c - 'a' + 'A' : c; } - -#endif /* lib/ctype.h */ diff --git a/src/lib/debug.c b/src/lib/debug.c deleted file mode 100644 index b4f8c2d0b66ff0fc5542d213dc829101afdc0358..0000000000000000000000000000000000000000 --- a/src/lib/debug.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <debug.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> - -/* Prints the call stack, that is, a list of addresses, one in - each of the functions we are nested within. gdb or addr2line - may be applied to kernel.o to translate these into file names, - line numbers, and function names. */ -void -debug_backtrace (void) -{ - static bool explained; - void **frame; - - printf ("Call stack: %p", __builtin_return_address (0)); - for (frame = __builtin_frame_address (1); - (uintptr_t) frame >= 0x1000 && frame[0] != NULL; - frame = frame[0]) - printf (" %p", frame[1]); - printf (".\n"); - - if (!explained) - { - explained = true; - printf ("The `backtrace' program can make call stacks useful.\n" - "Read \"Backtraces\" in the \"Debugging Tools\" chapter\n" - "of the Pintos documentation for more information.\n"); - } -} diff --git a/src/lib/debug.h b/src/lib/debug.h deleted file mode 100644 index 888ab7b9d985d96033f9ee3c00a2876476256a7c..0000000000000000000000000000000000000000 --- a/src/lib/debug.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __LIB_DEBUG_H -#define __LIB_DEBUG_H - -/* GCC lets us add "attributes" to functions, function - parameters, etc. to indicate their properties. - See the GCC manual for details. */ -#define UNUSED __attribute__ ((unused)) -#define NO_RETURN __attribute__ ((noreturn)) -#define NO_INLINE __attribute__ ((noinline)) -#define PRINTF_FORMAT(FMT, FIRST) __attribute__ ((format (printf, FMT, FIRST))) - -/* Halts the OS, printing the source file name, line number, and - function name, plus a user-specific message. */ -#define PANIC(...) debug_panic (__FILE__, __LINE__, __func__, __VA_ARGS__) - -void debug_panic (const char *file, int line, const char *function, - const char *message, ...) PRINTF_FORMAT (4, 5) NO_RETURN; -void debug_backtrace (void); -void debug_backtrace_all (void); - -#endif - - - -/* This is outside the header guard so that debug.h may be - included multiple times with different settings of NDEBUG. */ -#undef ASSERT -#undef NOT_REACHED - -#ifndef NDEBUG -#define ASSERT(CONDITION) \ - if (CONDITION) { } else { \ - PANIC ("assertion `%s' failed.", #CONDITION); \ - } -#define NOT_REACHED() PANIC ("executed an unreachable statement"); -#else -#define ASSERT(CONDITION) ((void) 0) -#define NOT_REACHED() for (;;) -#endif /* lib/debug.h */ diff --git a/src/lib/inttypes.h b/src/lib/inttypes.h deleted file mode 100644 index f7037255c8d5249b35cd72a47747b12f0789a532..0000000000000000000000000000000000000000 --- a/src/lib/inttypes.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __LIB_INTTYPES_H -#define __LIB_INTTYPES_H - -#include <stdint.h> - -#define PRId8 "hhd" -#define PRIi8 "hhi" -#define PRIo8 "hho" -#define PRIu8 "hhu" -#define PRIx8 "hhx" -#define PRIX8 "hhX" - -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" - -#define PRId32 "d" -#define PRIi32 "i" -#define PRIo32 "o" -#define PRIu32 "u" -#define PRIx32 "x" -#define PRIX32 "X" - -#define PRId64 "lld" -#define PRIi64 "lli" -#define PRIo64 "llo" -#define PRIu64 "llu" -#define PRIx64 "llx" -#define PRIX64 "llX" - -#define PRIdMAX "jd" -#define PRIiMAX "ji" -#define PRIoMAX "jo" -#define PRIuMAX "ju" -#define PRIxMAX "jx" -#define PRIXMAX "jX" - -#define PRIdPTR "td" -#define PRIiPTR "ti" -#define PRIoPTR "to" -#define PRIuPTR "tu" -#define PRIxPTR "tx" -#define PRIXPTR "tX" - -#endif /* lib/inttypes.h */ diff --git a/src/lib/kernel/bitmap.c b/src/lib/kernel/bitmap.c deleted file mode 100644 index d14a98cf343e935a390d9fd5702980ea50640dc6..0000000000000000000000000000000000000000 --- a/src/lib/kernel/bitmap.c +++ /dev/null @@ -1,371 +0,0 @@ -#include "bitmap.h" -#include <debug.h> -#include <limits.h> -#include <round.h> -#include <stdio.h> -#include "threads/malloc.h" -#ifdef FILESYS -#include "filesys/file.h" -#endif - -/* Element type. - - This must be an unsigned integer type at least as wide as int. - - Each bit represents one bit in the bitmap. - If bit 0 in an element represents bit K in the bitmap, - then bit 1 in the element represents bit K+1 in the bitmap, - and so on. */ -typedef unsigned long elem_type; - -/* Number of bits in an element. */ -#define ELEM_BITS (sizeof (elem_type) * CHAR_BIT) - -/* From the outside, a bitmap is an array of bits. From the - inside, it's an array of elem_type (defined above) that - simulates an array of bits. */ -struct bitmap - { - size_t bit_cnt; /* Number of bits. */ - elem_type *bits; /* Elements that represent bits. */ - }; - -/* Returns the index of the element that contains the bit - numbered BIT_IDX. */ -static inline size_t -elem_idx (size_t bit_idx) -{ - return bit_idx / ELEM_BITS; -} - -/* Returns an elem_type where only the bit corresponding to - BIT_IDX is turned on. */ -static inline elem_type -bit_mask (size_t bit_idx) -{ - return (elem_type) 1 << (bit_idx % ELEM_BITS); -} - -/* Returns the number of elements required for BIT_CNT bits. */ -static inline size_t -elem_cnt (size_t bit_cnt) -{ - return DIV_ROUND_UP (bit_cnt, ELEM_BITS); -} - -/* Returns the number of bytes required for BIT_CNT bits. */ -static inline size_t -byte_cnt (size_t bit_cnt) -{ - return sizeof (elem_type) * elem_cnt (bit_cnt); -} - -/* Returns a bit mask in which the bits actually used in the last - element of B's bits are set to 1 and the rest are set to 0. */ -static inline elem_type -last_mask (const struct bitmap *b) -{ - int last_bits = b->bit_cnt % ELEM_BITS; - return last_bits ? ((elem_type) 1 << last_bits) - 1 : (elem_type) -1; -} - -/* Creation and destruction. */ - -/* Creates and returns a pointer to a newly allocated bitmap with room for - BIT_CNT (or more) bits. Returns a null pointer if memory allocation fails. - The caller is responsible for freeing the bitmap, with bitmap_destroy(), - when it is no longer needed. */ -struct bitmap * -bitmap_create (size_t bit_cnt) -{ - struct bitmap *b = malloc (sizeof *b); - if (b != NULL) - { - b->bit_cnt = bit_cnt; - b->bits = malloc (byte_cnt (bit_cnt)); - if (b->bits != NULL || bit_cnt == 0) - { - bitmap_set_all (b, false); - return b; - } - free (b); - } - return NULL; -} - -/* Creates and returns a bitmap with BIT_CNT bits in the - BLOCK_SIZE bytes of storage preallocated at BLOCK. - BLOCK_SIZE must be at least bitmap_needed_bytes(BIT_CNT). */ -struct bitmap * -bitmap_create_in_buf (size_t bit_cnt, void *block, size_t block_size UNUSED) -{ - struct bitmap *b = block; - - ASSERT (block_size >= bitmap_buf_size (bit_cnt)); - - b->bit_cnt = bit_cnt; - b->bits = (elem_type *) (b + 1); - bitmap_set_all (b, false); - return b; -} - -/* Returns the number of bytes required to accomodate a bitmap - with BIT_CNT bits (for use with bitmap_create_in_buf()). */ -size_t -bitmap_buf_size (size_t bit_cnt) -{ - return sizeof (struct bitmap) + byte_cnt (bit_cnt); -} - -/* Destroys bitmap B, freeing its storage. - Not for use on bitmaps created by bitmap_create_in_buf(). */ -void -bitmap_destroy (struct bitmap *b) -{ - if (b != NULL) - { - free (b->bits); - free (b); - } -} - -/* Bitmap size. */ - -/* Returns the number of bits in B. */ -size_t -bitmap_size (const struct bitmap *b) -{ - return b->bit_cnt; -} - -/* Setting and testing single bits. */ - -/* Atomically sets the bit numbered IDX in B to VALUE. */ -void -bitmap_set (struct bitmap *b, size_t idx, bool value) -{ - ASSERT (b != NULL); - ASSERT (idx < b->bit_cnt); - if (value) - bitmap_mark (b, idx); - else - bitmap_reset (b, idx); -} - -/* Atomically sets the bit numbered BIT_IDX in B to true. */ -void -bitmap_mark (struct bitmap *b, size_t bit_idx) -{ - size_t idx = elem_idx (bit_idx); - elem_type mask = bit_mask (bit_idx); - - /* This is equivalent to `b->bits[idx] |= mask' except that it - is guaranteed to be atomic on a uniprocessor machine. See - the description of the OR instruction in [IA32-v2b]. */ - asm ("orl %1, %0" : "=m" (b->bits[idx]) : "r" (mask) : "cc"); -} - -/* Atomically sets the bit numbered BIT_IDX in B to false. */ -void -bitmap_reset (struct bitmap *b, size_t bit_idx) -{ - size_t idx = elem_idx (bit_idx); - elem_type mask = bit_mask (bit_idx); - - /* This is equivalent to `b->bits[idx] &= ~mask' except that it - is guaranteed to be atomic on a uniprocessor machine. See - the description of the AND instruction in [IA32-v2a]. */ - asm ("andl %1, %0" : "=m" (b->bits[idx]) : "r" (~mask) : "cc"); -} - -/* Atomically toggles the bit numbered IDX in B; - that is, if it is true, makes it false, - and if it is false, makes it true. */ -void -bitmap_flip (struct bitmap *b, size_t bit_idx) -{ - size_t idx = elem_idx (bit_idx); - elem_type mask = bit_mask (bit_idx); - - /* This is equivalent to `b->bits[idx] ^= mask' except that it - is guaranteed to be atomic on a uniprocessor machine. See - the description of the XOR instruction in [IA32-v2b]. */ - asm ("xorl %1, %0" : "=m" (b->bits[idx]) : "r" (mask) : "cc"); -} - -/* Returns the value of the bit numbered IDX in B. */ -bool -bitmap_test (const struct bitmap *b, size_t idx) -{ - ASSERT (b != NULL); - ASSERT (idx < b->bit_cnt); - return (b->bits[elem_idx (idx)] & bit_mask (idx)) != 0; -} - -/* Setting and testing multiple bits. */ - -/* Sets all bits in B to VALUE. */ -void -bitmap_set_all (struct bitmap *b, bool value) -{ - ASSERT (b != NULL); - - bitmap_set_multiple (b, 0, bitmap_size (b), value); -} - -/* Sets the CNT bits starting at START in B to VALUE. */ -void -bitmap_set_multiple (struct bitmap *b, size_t start, size_t cnt, bool value) -{ - size_t i; - - ASSERT (b != NULL); - ASSERT (start <= b->bit_cnt); - ASSERT (start + cnt <= b->bit_cnt); - - for (i = 0; i < cnt; i++) - bitmap_set (b, start + i, value); -} - -/* Returns the number of bits in B between START and START + CNT, - exclusive, that are set to VALUE. */ -size_t -bitmap_count (const struct bitmap *b, size_t start, size_t cnt, bool value) -{ - size_t i, value_cnt; - - ASSERT (b != NULL); - ASSERT (start <= b->bit_cnt); - ASSERT (start + cnt <= b->bit_cnt); - - value_cnt = 0; - for (i = 0; i < cnt; i++) - if (bitmap_test (b, start + i) == value) - value_cnt++; - return value_cnt; -} - -/* Returns true if any bits in B between START and START + CNT, - exclusive, are set to VALUE, and false otherwise. */ -bool -bitmap_contains (const struct bitmap *b, size_t start, size_t cnt, bool value) -{ - size_t i; - - ASSERT (b != NULL); - ASSERT (start <= b->bit_cnt); - ASSERT (start + cnt <= b->bit_cnt); - - for (i = 0; i < cnt; i++) - if (bitmap_test (b, start + i) == value) - return true; - return false; -} - -/* Returns true if any bits in B between START and START + CNT, - exclusive, are set to true, and false otherwise.*/ -bool -bitmap_any (const struct bitmap *b, size_t start, size_t cnt) -{ - return bitmap_contains (b, start, cnt, true); -} - -/* Returns true if no bits in B between START and START + CNT, - exclusive, are set to true, and false otherwise.*/ -bool -bitmap_none (const struct bitmap *b, size_t start, size_t cnt) -{ - return !bitmap_contains (b, start, cnt, true); -} - -/* Returns true if every bit in B between START and START + CNT, - exclusive, is set to true, and false otherwise. */ -bool -bitmap_all (const struct bitmap *b, size_t start, size_t cnt) -{ - return !bitmap_contains (b, start, cnt, false); -} - -/* Finding set or unset bits. */ - -/* Finds and returns the starting index of the first group of CNT - consecutive bits in B at or after START that are all set to - VALUE. - If there is no such group, returns BITMAP_ERROR. */ -size_t -bitmap_scan (const struct bitmap *b, size_t start, size_t cnt, bool value) -{ - ASSERT (b != NULL); - ASSERT (start <= b->bit_cnt); - - if (cnt <= b->bit_cnt) - { - size_t last = b->bit_cnt - cnt; - size_t i; - for (i = start; i <= last; i++) - if (!bitmap_contains (b, i, cnt, !value)) - return i; - } - return BITMAP_ERROR; -} - -/* Finds the first group of CNT consecutive bits in B at or after - START that are all set to VALUE, flips them all to !VALUE, - and returns the index of the first bit in the group. - If there is no such group, returns BITMAP_ERROR. - If CNT is zero, returns 0. - Bits are set atomically, but testing bits is not atomic with - setting them. */ -size_t -bitmap_scan_and_flip (struct bitmap *b, size_t start, size_t cnt, bool value) -{ - size_t idx = bitmap_scan (b, start, cnt, value); - if (idx != BITMAP_ERROR) - bitmap_set_multiple (b, idx, cnt, !value); - return idx; -} - -/* File input and output. */ - -#ifdef FILESYS -/* Returns the number of bytes needed to store B in a file. */ -size_t -bitmap_file_size (const struct bitmap *b) -{ - return byte_cnt (b->bit_cnt); -} - -/* Reads B from FILE. Returns true if successful, false - otherwise. */ -bool -bitmap_read (struct bitmap *b, struct file *file) -{ - bool success = true; - if (b->bit_cnt > 0) - { - off_t size = byte_cnt (b->bit_cnt); - success = file_read_at (file, b->bits, size, 0) == size; - b->bits[elem_cnt (b->bit_cnt) - 1] &= last_mask (b); - } - return success; -} - -/* Writes B to FILE. Return true if successful, false - otherwise. */ -bool -bitmap_write (const struct bitmap *b, struct file *file) -{ - off_t size = byte_cnt (b->bit_cnt); - return file_write_at (file, b->bits, size, 0) == size; -} -#endif /* FILESYS */ - -/* Debugging. */ - -/* Dumps the contents of B to the console as hexadecimal. */ -void -bitmap_dump (const struct bitmap *b) -{ - hex_dump (0, b->bits, byte_cnt (b->bit_cnt), false); -} - diff --git a/src/lib/kernel/bitmap.h b/src/lib/kernel/bitmap.h deleted file mode 100644 index a50593c9f291d56a80ac81c5b5362a17eb1d7b00..0000000000000000000000000000000000000000 --- a/src/lib/kernel/bitmap.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __LIB_KERNEL_BITMAP_H -#define __LIB_KERNEL_BITMAP_H - -#include <stdbool.h> -#include <stddef.h> -#include <inttypes.h> - -/* Bitmap abstract data type. */ - -/* Creation and destruction. */ -struct bitmap *bitmap_create (size_t bit_cnt); -struct bitmap *bitmap_create_in_buf (size_t bit_cnt, void *, size_t byte_cnt); -size_t bitmap_buf_size (size_t bit_cnt); -void bitmap_destroy (struct bitmap *); - -/* Bitmap size. */ -size_t bitmap_size (const struct bitmap *); - -/* Setting and testing single bits. */ -void bitmap_set (struct bitmap *, size_t idx, bool); -void bitmap_mark (struct bitmap *, size_t idx); -void bitmap_reset (struct bitmap *, size_t idx); -void bitmap_flip (struct bitmap *, size_t idx); -bool bitmap_test (const struct bitmap *, size_t idx); - -/* Setting and testing multiple bits. */ -void bitmap_set_all (struct bitmap *, bool); -void bitmap_set_multiple (struct bitmap *, size_t start, size_t cnt, bool); -size_t bitmap_count (const struct bitmap *, size_t start, size_t cnt, bool); -bool bitmap_contains (const struct bitmap *, size_t start, size_t cnt, bool); -bool bitmap_any (const struct bitmap *, size_t start, size_t cnt); -bool bitmap_none (const struct bitmap *, size_t start, size_t cnt); -bool bitmap_all (const struct bitmap *, size_t start, size_t cnt); - -/* Finding set or unset bits. */ -#define BITMAP_ERROR SIZE_MAX -size_t bitmap_scan (const struct bitmap *, size_t start, size_t cnt, bool); -size_t bitmap_scan_and_flip (struct bitmap *, size_t start, size_t cnt, bool); - -/* File input and output. */ -#ifdef FILESYS -struct file; -size_t bitmap_file_size (const struct bitmap *); -bool bitmap_read (struct bitmap *, struct file *); -bool bitmap_write (const struct bitmap *, struct file *); -#endif - -/* Debugging. */ -void bitmap_dump (const struct bitmap *); - -#endif /* lib/kernel/bitmap.h */ diff --git a/src/lib/kernel/console.c b/src/lib/kernel/console.c deleted file mode 100644 index 844b18468bde5c3b828bb4455213aed6949f0f13..0000000000000000000000000000000000000000 --- a/src/lib/kernel/console.c +++ /dev/null @@ -1,191 +0,0 @@ -#include <console.h> -#include <stdarg.h> -#include <stdio.h> -#include "devices/serial.h" -#include "devices/vga.h" -#include "threads/init.h" -#include "threads/interrupt.h" -#include "threads/synch.h" - -static void vprintf_helper (char, void *); -static void putchar_have_lock (uint8_t c); - -/* The console lock. - Both the vga and serial layers do their own locking, so it's - safe to call them at any time. - But this lock is useful to prevent simultaneous printf() calls - from mixing their output, which looks confusing. */ -static struct lock console_lock; - -/* True in ordinary circumstances: we want to use the console - lock to avoid mixing output between threads, as explained - above. - - False in early boot before the point that locks are functional - or the console lock has been initialized, or after a kernel - panics. In the former case, taking the lock would cause an - assertion failure, which in turn would cause a panic, turning - it into the latter case. In the latter case, if it is a buggy - lock_acquire() implementation that caused the panic, we'll - likely just recurse. */ -static bool use_console_lock; - -/* It's possible, if you add enough debug output to Pintos, to - try to recursively grab console_lock from a single thread. As - a real example, I added a printf() call to palloc_free(). - Here's a real backtrace that resulted: - - lock_console() - vprintf() - printf() - palloc() tries to grab the lock again - palloc_free() - thread_schedule_tail() - another thread dying as we switch threads - schedule() - thread_yield() - intr_handler() - timer interrupt - intr_set_level() - serial_putc() - putchar_have_lock() - putbuf() - sys_write() - one process writing to the console - syscall_handler() - intr_handler() - - This kind of thing is very difficult to debug, so we avoid the - problem by simulating a recursive lock with a depth - counter. */ -static int console_lock_depth; - -/* Number of characters written to console. */ -static int64_t write_cnt; - -/* Enable console locking. */ -void -console_init (void) -{ - lock_init (&console_lock); - use_console_lock = true; -} - -/* Notifies the console that a kernel panic is underway, - which warns it to avoid trying to take the console lock from - now on. */ -void -console_panic (void) -{ - use_console_lock = false; -} - -/* Prints console statistics. */ -void -console_print_stats (void) -{ - printf ("Console: %lld characters output\n", write_cnt); -} - -/* Acquires the console lock. */ -static void -acquire_console (void) -{ - if (!intr_context () && use_console_lock) - { - if (lock_held_by_current_thread (&console_lock)) - console_lock_depth++; - else - lock_acquire (&console_lock); - } -} - -/* Releases the console lock. */ -static void -release_console (void) -{ - if (!intr_context () && use_console_lock) - { - if (console_lock_depth > 0) - console_lock_depth--; - else - lock_release (&console_lock); - } -} - -/* Returns true if the current thread has the console lock, - false otherwise. */ -static bool -console_locked_by_current_thread (void) -{ - return (intr_context () - || !use_console_lock - || lock_held_by_current_thread (&console_lock)); -} - -/* The standard vprintf() function, - which is like printf() but uses a va_list. - Writes its output to both vga display and serial port. */ -int -vprintf (const char *format, va_list args) -{ - int char_cnt = 0; - - acquire_console (); - __vprintf (format, args, vprintf_helper, &char_cnt); - release_console (); - - return char_cnt; -} - -/* Writes string S to the console, followed by a new-line - character. */ -int -puts (const char *s) -{ - acquire_console (); - while (*s != '\0') - putchar_have_lock (*s++); - putchar_have_lock ('\n'); - release_console (); - - return 0; -} - -/* Writes the N characters in BUFFER to the console. */ -void -putbuf (const char *buffer, size_t n) -{ - acquire_console (); - while (n-- > 0) - putchar_have_lock (*buffer++); - release_console (); -} - -/* Writes C to the vga display and serial port. */ -int -putchar (int c) -{ - acquire_console (); - putchar_have_lock (c); - release_console (); - - return c; -} - -/* Helper function for vprintf(). */ -static void -vprintf_helper (char c, void *char_cnt_) -{ - int *char_cnt = char_cnt_; - (*char_cnt)++; - putchar_have_lock (c); -} - -/* Writes C to the vga display and serial port. - The caller has already acquired the console lock if - appropriate. */ -static void -putchar_have_lock (uint8_t c) -{ - ASSERT (console_locked_by_current_thread ()); - write_cnt++; - serial_putc (c); - vga_putc (c); -} diff --git a/src/lib/kernel/console.h b/src/lib/kernel/console.h deleted file mode 100644 index ab992498bcf4e338948741641ff9a53645ec9c75..0000000000000000000000000000000000000000 --- a/src/lib/kernel/console.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __LIB_KERNEL_CONSOLE_H -#define __LIB_KERNEL_CONSOLE_H - -void console_init (void); -void console_panic (void); -void console_print_stats (void); - -#endif /* lib/kernel/console.h */ diff --git a/src/lib/kernel/debug.c b/src/lib/kernel/debug.c deleted file mode 100644 index b12f4f9aacd343adb593f048892bb5646577461f..0000000000000000000000000000000000000000 --- a/src/lib/kernel/debug.c +++ /dev/null @@ -1,123 +0,0 @@ -#include <debug.h> -#include <console.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include "threads/init.h" -#include "threads/interrupt.h" -#include "threads/thread.h" -#include "threads/switch.h" -#include "threads/vaddr.h" -#include "devices/serial.h" -#include "devices/shutdown.h" - -/* Halts the OS, printing the source file name, line number, and - function name, plus a user-specific message. */ -void -debug_panic (const char *file, int line, const char *function, - const char *message, ...) -{ - static int level; - va_list args; - - intr_disable (); - console_panic (); - - level++; - if (level == 1) - { - printf ("Kernel PANIC at %s:%d in %s(): ", file, line, function); - - va_start (args, message); - vprintf (message, args); - printf ("\n"); - va_end (args); - - debug_backtrace (); - } - else if (level == 2) - printf ("Kernel PANIC recursion at %s:%d in %s().\n", - file, line, function); - else - { - /* Don't print anything: that's probably why we recursed. */ - } - - serial_flush (); - shutdown (); - for (;;); -} - -/* Print call stack of a thread. - The thread may be running, ready, or blocked. */ -static void -print_stacktrace(struct thread *t, void *aux UNUSED) -{ - void *retaddr = NULL, **frame = NULL; - const char *status = "UNKNOWN"; - - switch (t->status) { - case THREAD_RUNNING: - status = "RUNNING"; - break; - - case THREAD_READY: - status = "READY"; - break; - - case THREAD_BLOCKED: - status = "BLOCKED"; - break; - - default: - break; - } - - printf ("Call stack of thread `%s' (status %s):", t->name, status); - - if (t == thread_current()) - { - frame = __builtin_frame_address (1); - retaddr = __builtin_return_address (0); - } - else - { - /* Retrieve the values of the base and instruction pointers - as they were saved when this thread called switch_threads. */ - struct switch_threads_frame * saved_frame; - - saved_frame = (struct switch_threads_frame *)t->stack; - - /* Skip threads if they have been added to the all threads - list, but have never been scheduled. - We can identify because their `stack' member either points - at the top of their kernel stack page, or the - switch_threads_frame's 'eip' member points at switch_entry. - See also threads.c. */ - if (t->stack == (uint8_t *)t + PGSIZE || saved_frame->eip == switch_entry) - { - printf (" thread was never scheduled.\n"); - return; - } - - frame = (void **) saved_frame->ebp; - retaddr = (void *) saved_frame->eip; - } - - printf (" %p", retaddr); - for (; (uintptr_t) frame >= 0x1000 && frame[0] != NULL; frame = frame[0]) - printf (" %p", frame[1]); - printf (".\n"); -} - -/* Prints call stack of all threads. */ -void -debug_backtrace_all (void) -{ - enum intr_level oldlevel = intr_disable (); - - thread_foreach (print_stacktrace, 0); - intr_set_level (oldlevel); -} diff --git a/src/lib/kernel/hash.c b/src/lib/kernel/hash.c deleted file mode 100644 index 57eed450c91cc5dbae214445d16b72f52d7a7c3c..0000000000000000000000000000000000000000 --- a/src/lib/kernel/hash.c +++ /dev/null @@ -1,430 +0,0 @@ -/* Hash table. - - This data structure is thoroughly documented in the Tour of - Pintos for Project 3. - - See hash.h for basic information. */ - -#include "hash.h" -#include "../debug.h" -#include "threads/malloc.h" - -#define list_elem_to_hash_elem(LIST_ELEM) \ - list_entry(LIST_ELEM, struct hash_elem, list_elem) - -static struct list *find_bucket (struct hash *, struct hash_elem *); -static struct hash_elem *find_elem (struct hash *, struct list *, - struct hash_elem *); -static void insert_elem (struct hash *, struct list *, struct hash_elem *); -static void remove_elem (struct hash *, struct hash_elem *); -static void rehash (struct hash *); - -/* Initializes hash table H to compute hash values using HASH and - compare hash elements using LESS, given auxiliary data AUX. */ -bool -hash_init (struct hash *h, - hash_hash_func *hash, hash_less_func *less, void *aux) -{ - h->elem_cnt = 0; - h->bucket_cnt = 4; - h->buckets = malloc (sizeof *h->buckets * h->bucket_cnt); - h->hash = hash; - h->less = less; - h->aux = aux; - - if (h->buckets != NULL) - { - hash_clear (h, NULL); - return true; - } - else - return false; -} - -/* Removes all the elements from H. - - If DESTRUCTOR is non-null, then it is called for each element - in the hash. DESTRUCTOR may, if appropriate, deallocate the - memory used by the hash element. However, modifying hash - table H while hash_clear() is running, using any of the - functions hash_clear(), hash_destroy(), hash_insert(), - hash_replace(), or hash_delete(), yields undefined behavior, - whether done in DESTRUCTOR or elsewhere. */ -void -hash_clear (struct hash *h, hash_action_func *destructor) -{ - size_t i; - - for (i = 0; i < h->bucket_cnt; i++) - { - struct list *bucket = &h->buckets[i]; - - if (destructor != NULL) - while (!list_empty (bucket)) - { - struct list_elem *list_elem = list_pop_front (bucket); - struct hash_elem *hash_elem = list_elem_to_hash_elem (list_elem); - destructor (hash_elem, h->aux); - } - - list_init (bucket); - } - - h->elem_cnt = 0; -} - -/* Destroys hash table H. - - If DESTRUCTOR is non-null, then it is first called for each - element in the hash. DESTRUCTOR may, if appropriate, - deallocate the memory used by the hash element. However, - modifying hash table H while hash_clear() is running, using - any of the functions hash_clear(), hash_destroy(), - hash_insert(), hash_replace(), or hash_delete(), yields - undefined behavior, whether done in DESTRUCTOR or - elsewhere. */ -void -hash_destroy (struct hash *h, hash_action_func *destructor) -{ - if (destructor != NULL) - hash_clear (h, destructor); - free (h->buckets); -} - -/* Inserts NEW into hash table H and returns a null pointer, if - no equal element is already in the table. - If an equal element is already in the table, returns it - without inserting NEW. */ -struct hash_elem * -hash_insert (struct hash *h, struct hash_elem *new) -{ - struct list *bucket = find_bucket (h, new); - struct hash_elem *old = find_elem (h, bucket, new); - - if (old == NULL) - insert_elem (h, bucket, new); - - rehash (h); - - return old; -} - -/* Inserts NEW into hash table H, replacing any equal element - already in the table, which is returned. */ -struct hash_elem * -hash_replace (struct hash *h, struct hash_elem *new) -{ - struct list *bucket = find_bucket (h, new); - struct hash_elem *old = find_elem (h, bucket, new); - - if (old != NULL) - remove_elem (h, old); - insert_elem (h, bucket, new); - - rehash (h); - - return old; -} - -/* Finds and returns an element equal to E in hash table H, or a - null pointer if no equal element exists in the table. */ -struct hash_elem * -hash_find (struct hash *h, struct hash_elem *e) -{ - return find_elem (h, find_bucket (h, e), e); -} - -/* Finds, removes, and returns an element equal to E in hash - table H. Returns a null pointer if no equal element existed - in the table. - - If the elements of the hash table are dynamically allocated, - or own resources that are, then it is the caller's - responsibility to deallocate them. */ -struct hash_elem * -hash_delete (struct hash *h, struct hash_elem *e) -{ - struct hash_elem *found = find_elem (h, find_bucket (h, e), e); - if (found != NULL) - { - remove_elem (h, found); - rehash (h); - } - return found; -} - -/* Calls ACTION for each element in hash table H in arbitrary - order. - Modifying hash table H while hash_apply() is running, using - any of the functions hash_clear(), hash_destroy(), - hash_insert(), hash_replace(), or hash_delete(), yields - undefined behavior, whether done from ACTION or elsewhere. */ -void -hash_apply (struct hash *h, hash_action_func *action) -{ - size_t i; - - ASSERT (action != NULL); - - for (i = 0; i < h->bucket_cnt; i++) - { - struct list *bucket = &h->buckets[i]; - struct list_elem *elem, *next; - - for (elem = list_begin (bucket); elem != list_end (bucket); elem = next) - { - next = list_next (elem); - action (list_elem_to_hash_elem (elem), h->aux); - } - } -} - -/* Initializes I for iterating hash table H. - - Iteration idiom: - - struct hash_iterator i; - - hash_first (&i, h); - while (hash_next (&i)) - { - struct foo *f = hash_entry (hash_cur (&i), struct foo, elem); - ...do something with f... - } - - Modifying hash table H during iteration, using any of the - functions hash_clear(), hash_destroy(), hash_insert(), - hash_replace(), or hash_delete(), invalidates all - iterators. */ -void -hash_first (struct hash_iterator *i, struct hash *h) -{ - ASSERT (i != NULL); - ASSERT (h != NULL); - - i->hash = h; - i->bucket = i->hash->buckets; - i->elem = list_elem_to_hash_elem (list_head (i->bucket)); -} - -/* Advances I to the next element in the hash table and returns - it. Returns a null pointer if no elements are left. Elements - are returned in arbitrary order. - - Modifying a hash table H during iteration, using any of the - functions hash_clear(), hash_destroy(), hash_insert(), - hash_replace(), or hash_delete(), invalidates all - iterators. */ -struct hash_elem * -hash_next (struct hash_iterator *i) -{ - ASSERT (i != NULL); - - i->elem = list_elem_to_hash_elem (list_next (&i->elem->list_elem)); - while (i->elem == list_elem_to_hash_elem (list_end (i->bucket))) - { - if (++i->bucket >= i->hash->buckets + i->hash->bucket_cnt) - { - i->elem = NULL; - break; - } - i->elem = list_elem_to_hash_elem (list_begin (i->bucket)); - } - - return i->elem; -} - -/* Returns the current element in the hash table iteration, or a - null pointer at the end of the table. Undefined behavior - after calling hash_first() but before hash_next(). */ -struct hash_elem * -hash_cur (struct hash_iterator *i) -{ - return i->elem; -} - -/* Returns the number of elements in H. */ -size_t -hash_size (struct hash *h) -{ - return h->elem_cnt; -} - -/* Returns true if H contains no elements, false otherwise. */ -bool -hash_empty (struct hash *h) -{ - return h->elem_cnt == 0; -} - -/* Fowler-Noll-Vo hash constants, for 32-bit word sizes. */ -#define FNV_32_PRIME 16777619u -#define FNV_32_BASIS 2166136261u - -/* Returns a hash of the SIZE bytes in BUF. */ -unsigned -hash_bytes (const void *buf_, size_t size) -{ - /* Fowler-Noll-Vo 32-bit hash, for bytes. */ - const unsigned char *buf = buf_; - unsigned hash; - - ASSERT (buf != NULL); - - hash = FNV_32_BASIS; - while (size-- > 0) - hash = (hash * FNV_32_PRIME) ^ *buf++; - - return hash; -} - -/* Returns a hash of string S. */ -unsigned -hash_string (const char *s_) -{ - const unsigned char *s = (const unsigned char *) s_; - unsigned hash; - - ASSERT (s != NULL); - - hash = FNV_32_BASIS; - while (*s != '\0') - hash = (hash * FNV_32_PRIME) ^ *s++; - - return hash; -} - -/* Returns a hash of integer I. */ -unsigned -hash_int (int i) -{ - return hash_bytes (&i, sizeof i); -} - -/* Returns the bucket in H that E belongs in. */ -static struct list * -find_bucket (struct hash *h, struct hash_elem *e) -{ - size_t bucket_idx = h->hash (e, h->aux) & (h->bucket_cnt - 1); - return &h->buckets[bucket_idx]; -} - -/* Searches BUCKET in H for a hash element equal to E. Returns - it if found or a null pointer otherwise. */ -static struct hash_elem * -find_elem (struct hash *h, struct list *bucket, struct hash_elem *e) -{ - struct list_elem *i; - - for (i = list_begin (bucket); i != list_end (bucket); i = list_next (i)) - { - struct hash_elem *hi = list_elem_to_hash_elem (i); - if (!h->less (hi, e, h->aux) && !h->less (e, hi, h->aux)) - return hi; - } - return NULL; -} - -/* Returns X with its lowest-order bit set to 1 turned off. */ -static inline size_t -turn_off_least_1bit (size_t x) -{ - return x & (x - 1); -} - -/* Returns true if X is a power of 2, otherwise false. */ -static inline size_t -is_power_of_2 (size_t x) -{ - return x != 0 && turn_off_least_1bit (x) == 0; -} - -/* Element per bucket ratios. */ -#define MIN_ELEMS_PER_BUCKET 1 /* Elems/bucket < 1: reduce # of buckets. */ -#define BEST_ELEMS_PER_BUCKET 2 /* Ideal elems/bucket. */ -#define MAX_ELEMS_PER_BUCKET 4 /* Elems/bucket > 4: increase # of buckets. */ - -/* Changes the number of buckets in hash table H to match the - ideal. This function can fail because of an out-of-memory - condition, but that'll just make hash accesses less efficient; - we can still continue. */ -static void -rehash (struct hash *h) -{ - size_t old_bucket_cnt, new_bucket_cnt; - struct list *new_buckets, *old_buckets; - size_t i; - - ASSERT (h != NULL); - - /* Save old bucket info for later use. */ - old_buckets = h->buckets; - old_bucket_cnt = h->bucket_cnt; - - /* Calculate the number of buckets to use now. - We want one bucket for about every BEST_ELEMS_PER_BUCKET. - We must have at least four buckets, and the number of - buckets must be a power of 2. */ - new_bucket_cnt = h->elem_cnt / BEST_ELEMS_PER_BUCKET; - if (new_bucket_cnt < 4) - new_bucket_cnt = 4; - while (!is_power_of_2 (new_bucket_cnt)) - new_bucket_cnt = turn_off_least_1bit (new_bucket_cnt); - - /* Don't do anything if the bucket count wouldn't change. */ - if (new_bucket_cnt == old_bucket_cnt) - return; - - /* Allocate new buckets and initialize them as empty. */ - new_buckets = malloc (sizeof *new_buckets * new_bucket_cnt); - if (new_buckets == NULL) - { - /* Allocation failed. This means that use of the hash table will - be less efficient. However, it is still usable, so - there's no reason for it to be an error. */ - return; - } - for (i = 0; i < new_bucket_cnt; i++) - list_init (&new_buckets[i]); - - /* Install new bucket info. */ - h->buckets = new_buckets; - h->bucket_cnt = new_bucket_cnt; - - /* Move each old element into the appropriate new bucket. */ - for (i = 0; i < old_bucket_cnt; i++) - { - struct list *old_bucket; - struct list_elem *elem, *next; - - old_bucket = &old_buckets[i]; - for (elem = list_begin (old_bucket); - elem != list_end (old_bucket); elem = next) - { - struct list *new_bucket - = find_bucket (h, list_elem_to_hash_elem (elem)); - next = list_next (elem); - list_remove (elem); - list_push_front (new_bucket, elem); - } - } - - free (old_buckets); -} - -/* Inserts E into BUCKET (in hash table H). */ -static void -insert_elem (struct hash *h, struct list *bucket, struct hash_elem *e) -{ - h->elem_cnt++; - list_push_front (bucket, &e->list_elem); -} - -/* Removes E from hash table H. */ -static void -remove_elem (struct hash *h, struct hash_elem *e) -{ - h->elem_cnt--; - list_remove (&e->list_elem); -} - diff --git a/src/lib/kernel/hash.h b/src/lib/kernel/hash.h deleted file mode 100644 index db9f6746431a4aa24f60baf762b2c37fb965275e..0000000000000000000000000000000000000000 --- a/src/lib/kernel/hash.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef __LIB_KERNEL_HASH_H -#define __LIB_KERNEL_HASH_H - -/* Hash table. - - This data structure is thoroughly documented in the Tour of - Pintos for Project 3. - - This is a standard hash table with chaining. To locate an - element in the table, we compute a hash function over the - element's data and use that as an index into an array of - doubly linked lists, then linearly search the list. - - The chain lists do not use dynamic allocation. Instead, each - structure that can potentially be in a hash must embed a - struct hash_elem member. All of the hash functions operate on - these `struct hash_elem's. The hash_entry macro allows - conversion from a struct hash_elem back to a structure object - that contains it. This is the same technique used in the - linked list implementation. Refer to lib/kernel/list.h for a - detailed explanation. */ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include "list.h" - -/* Hash element. */ -struct hash_elem - { - struct list_elem list_elem; - }; - -/* Converts pointer to hash element HASH_ELEM into a pointer to - the structure that HASH_ELEM is embedded inside. Supply the - name of the outer structure STRUCT and the member name MEMBER - of the hash element. See the big comment at the top of the - file for an example. */ -#define hash_entry(HASH_ELEM, STRUCT, MEMBER) \ - ((STRUCT *) ((uint8_t *) &(HASH_ELEM)->list_elem \ - - offsetof (STRUCT, MEMBER.list_elem))) - -/* Computes and returns the hash value for hash element E, given - auxiliary data AUX. */ -typedef unsigned hash_hash_func (const struct hash_elem *e, void *aux); - -/* Compares the value of two hash elements A and B, given - auxiliary data AUX. Returns true if A is less than B, or - false if A is greater than or equal to B. */ -typedef bool hash_less_func (const struct hash_elem *a, - const struct hash_elem *b, - void *aux); - -/* Performs some operation on hash element E, given auxiliary - data AUX. */ -typedef void hash_action_func (struct hash_elem *e, void *aux); - -/* Hash table. */ -struct hash - { - size_t elem_cnt; /* Number of elements in table. */ - size_t bucket_cnt; /* Number of buckets, a power of 2. */ - struct list *buckets; /* Array of `bucket_cnt' lists. */ - hash_hash_func *hash; /* Hash function. */ - hash_less_func *less; /* Comparison function. */ - void *aux; /* Auxiliary data for `hash' and `less'. */ - }; - -/* A hash table iterator. */ -struct hash_iterator - { - struct hash *hash; /* The hash table. */ - struct list *bucket; /* Current bucket. */ - struct hash_elem *elem; /* Current hash element in current bucket. */ - }; - -/* Basic life cycle. */ -bool hash_init (struct hash *, hash_hash_func *, hash_less_func *, void *aux); -void hash_clear (struct hash *, hash_action_func *); -void hash_destroy (struct hash *, hash_action_func *); - -/* Search, insertion, deletion. */ -struct hash_elem *hash_insert (struct hash *, struct hash_elem *); -struct hash_elem *hash_replace (struct hash *, struct hash_elem *); -struct hash_elem *hash_find (struct hash *, struct hash_elem *); -struct hash_elem *hash_delete (struct hash *, struct hash_elem *); - -/* Iteration. */ -void hash_apply (struct hash *, hash_action_func *); -void hash_first (struct hash_iterator *, struct hash *); -struct hash_elem *hash_next (struct hash_iterator *); -struct hash_elem *hash_cur (struct hash_iterator *); - -/* Information. */ -size_t hash_size (struct hash *); -bool hash_empty (struct hash *); - -/* Sample hash functions. */ -unsigned hash_bytes (const void *, size_t); -unsigned hash_string (const char *); -unsigned hash_int (int); - -#endif /* lib/kernel/hash.h */ diff --git a/src/lib/kernel/list.c b/src/lib/kernel/list.c deleted file mode 100644 index 316d9ef64cd166e6422117f9c914efde5c5fdfde..0000000000000000000000000000000000000000 --- a/src/lib/kernel/list.c +++ /dev/null @@ -1,524 +0,0 @@ -#include "list.h" -#include "../debug.h" - -/* Our doubly linked lists have two header elements: the "head" - just before the first element and the "tail" just after the - last element. The `prev' link of the front header is null, as - is the `next' link of the back header. Their other two links - point toward each other via the interior elements of the list. - - An empty list looks like this: - - +------+ +------+ - <---| head |<--->| tail |---> - +------+ +------+ - - A list with two elements in it looks like this: - - +------+ +-------+ +-------+ +------+ - <---| head |<--->| 1 |<--->| 2 |<--->| tail |<---> - +------+ +-------+ +-------+ +------+ - - The symmetry of this arrangement eliminates lots of special - cases in list processing. For example, take a look at - list_remove(): it takes only two pointer assignments and no - conditionals. That's a lot simpler than the code would be - without header elements. - - (Because only one of the pointers in each header element is used, - we could in fact combine them into a single header element - without sacrificing this simplicity. But using two separate - elements allows us to do a little bit of checking on some - operations, which can be valuable.) */ - -static bool is_sorted (struct list_elem *a, struct list_elem *b, - list_less_func *less, void *aux) UNUSED; - -/* Returns true if ELEM is a head, false otherwise. */ -static inline bool -is_head (struct list_elem *elem) -{ - return elem != NULL && elem->prev == NULL && elem->next != NULL; -} - -/* Returns true if ELEM is an interior element, - false otherwise. */ -static inline bool -is_interior (struct list_elem *elem) -{ - return elem != NULL && elem->prev != NULL && elem->next != NULL; -} - -/* Returns true if ELEM is a tail, false otherwise. */ -static inline bool -is_tail (struct list_elem *elem) -{ - return elem != NULL && elem->prev != NULL && elem->next == NULL; -} - -/* Initializes LIST as an empty list. */ -void -list_init (struct list *list) -{ - ASSERT (list != NULL); - list->head.prev = NULL; - list->head.next = &list->tail; - list->tail.prev = &list->head; - list->tail.next = NULL; -} - -/* Returns the beginning of LIST. */ -struct list_elem * -list_begin (struct list *list) -{ - ASSERT (list != NULL); - return list->head.next; -} - -/* Returns the element after ELEM in its list. If ELEM is the - last element in its list, returns the list tail. Results are - undefined if ELEM is itself a list tail. */ -struct list_elem * -list_next (struct list_elem *elem) -{ - ASSERT (is_head (elem) || is_interior (elem)); - return elem->next; -} - -/* Returns LIST's tail. - - list_end() is often used in iterating through a list from - front to back. See the big comment at the top of list.h for - an example. */ -struct list_elem * -list_end (struct list *list) -{ - ASSERT (list != NULL); - return &list->tail; -} - -/* Returns the LIST's reverse beginning, for iterating through - LIST in reverse order, from back to front. */ -struct list_elem * -list_rbegin (struct list *list) -{ - ASSERT (list != NULL); - return list->tail.prev; -} - -/* Returns the element before ELEM in its list. If ELEM is the - first element in its list, returns the list head. Results are - undefined if ELEM is itself a list head. */ -struct list_elem * -list_prev (struct list_elem *elem) -{ - ASSERT (is_interior (elem) || is_tail (elem)); - return elem->prev; -} - -/* Returns LIST's head. - - list_rend() is often used in iterating through a list in - reverse order, from back to front. Here's typical usage, - following the example from the top of list.h: - - for (e = list_rbegin (&foo_list); e != list_rend (&foo_list); - e = list_prev (e)) - { - struct foo *f = list_entry (e, struct foo, elem); - ...do something with f... - } -*/ -struct list_elem * -list_rend (struct list *list) -{ - ASSERT (list != NULL); - return &list->head; -} - -/* Return's LIST's head. - - list_head() can be used for an alternate style of iterating - through a list, e.g.: - - e = list_head (&list); - while ((e = list_next (e)) != list_end (&list)) - { - ... - } -*/ -struct list_elem * -list_head (struct list *list) -{ - ASSERT (list != NULL); - return &list->head; -} - -/* Return's LIST's tail. */ -struct list_elem * -list_tail (struct list *list) -{ - ASSERT (list != NULL); - return &list->tail; -} - -/* Inserts ELEM just before BEFORE, which may be either an - interior element or a tail. The latter case is equivalent to - list_push_back(). */ -void -list_insert (struct list_elem *before, struct list_elem *elem) -{ - ASSERT (is_interior (before) || is_tail (before)); - ASSERT (elem != NULL); - - elem->prev = before->prev; - elem->next = before; - before->prev->next = elem; - before->prev = elem; -} - -/* Removes elements FIRST though LAST (exclusive) from their - current list, then inserts them just before BEFORE, which may - be either an interior element or a tail. */ -void -list_splice (struct list_elem *before, - struct list_elem *first, struct list_elem *last) -{ - ASSERT (is_interior (before) || is_tail (before)); - if (first == last) - return; - last = list_prev (last); - - ASSERT (is_interior (first)); - ASSERT (is_interior (last)); - - /* Cleanly remove FIRST...LAST from its current list. */ - first->prev->next = last->next; - last->next->prev = first->prev; - - /* Splice FIRST...LAST into new list. */ - first->prev = before->prev; - last->next = before; - before->prev->next = first; - before->prev = last; -} - -/* Inserts ELEM at the beginning of LIST, so that it becomes the - front in LIST. */ -void -list_push_front (struct list *list, struct list_elem *elem) -{ - list_insert (list_begin (list), elem); -} - -/* Inserts ELEM at the end of LIST, so that it becomes the - back in LIST. */ -void -list_push_back (struct list *list, struct list_elem *elem) -{ - list_insert (list_end (list), elem); -} - -/* Removes ELEM from its list and returns the element that - followed it. Undefined behavior if ELEM is not in a list. - - A list element must be treated very carefully after removing - it from its list. Calling list_next() or list_prev() on ELEM - will return the item that was previously before or after ELEM, - but, e.g., list_prev(list_next(ELEM)) is no longer ELEM! - - The list_remove() return value provides a convenient way to - iterate and remove elements from a list: - - for (e = list_begin (&list); e != list_end (&list); e = list_remove (e)) - { - ...do something with e... - } - - If you need to free() elements of the list then you need to be - more conservative. Here's an alternate strategy that works - even in that case: - - while (!list_empty (&list)) - { - struct list_elem *e = list_pop_front (&list); - ...do something with e... - } -*/ -struct list_elem * -list_remove (struct list_elem *elem) -{ - ASSERT (is_interior (elem)); - elem->prev->next = elem->next; - elem->next->prev = elem->prev; - return elem->next; -} - -/* Removes the front element from LIST and returns it. - Undefined behavior if LIST is empty before removal. */ -struct list_elem * -list_pop_front (struct list *list) -{ - struct list_elem *front = list_front (list); - list_remove (front); - return front; -} - -/* Removes the back element from LIST and returns it. - Undefined behavior if LIST is empty before removal. */ -struct list_elem * -list_pop_back (struct list *list) -{ - struct list_elem *back = list_back (list); - list_remove (back); - return back; -} - -/* Returns the front element in LIST. - Undefined behavior if LIST is empty. */ -struct list_elem * -list_front (struct list *list) -{ - ASSERT (!list_empty (list)); - return list->head.next; -} - -/* Returns the back element in LIST. - Undefined behavior if LIST is empty. */ -struct list_elem * -list_back (struct list *list) -{ - ASSERT (!list_empty (list)); - return list->tail.prev; -} - -/* Returns the number of elements in LIST. - Runs in O(n) in the number of elements. */ -size_t -list_size (struct list *list) -{ - struct list_elem *e; - size_t cnt = 0; - - for (e = list_begin (list); e != list_end (list); e = list_next (e)) - cnt++; - return cnt; -} - -/* Returns true if LIST is empty, false otherwise. */ -bool -list_empty (struct list *list) -{ - return list_begin (list) == list_end (list); -} - -/* Swaps the `struct list_elem *'s that A and B point to. */ -static void -swap (struct list_elem **a, struct list_elem **b) -{ - struct list_elem *t = *a; - *a = *b; - *b = t; -} - -/* Reverses the order of LIST. */ -void -list_reverse (struct list *list) -{ - if (!list_empty (list)) - { - struct list_elem *e; - - for (e = list_begin (list); e != list_end (list); e = e->prev) - swap (&e->prev, &e->next); - swap (&list->head.next, &list->tail.prev); - swap (&list->head.next->prev, &list->tail.prev->next); - } -} - -/* Returns true only if the list elements A through B (exclusive) - are in order according to LESS given auxiliary data AUX. */ -static bool -is_sorted (struct list_elem *a, struct list_elem *b, - list_less_func *less, void *aux) -{ - if (a != b) - while ((a = list_next (a)) != b) - if (less (a, list_prev (a), aux)) - return false; - return true; -} - -/* Finds a run, starting at A and ending not after B, of list - elements that are in nondecreasing order according to LESS - given auxiliary data AUX. Returns the (exclusive) end of the - run. - A through B (exclusive) must form a non-empty range. */ -static struct list_elem * -find_end_of_run (struct list_elem *a, struct list_elem *b, - list_less_func *less, void *aux) -{ - ASSERT (a != NULL); - ASSERT (b != NULL); - ASSERT (less != NULL); - ASSERT (a != b); - - do - { - a = list_next (a); - } - while (a != b && !less (a, list_prev (a), aux)); - return a; -} - -/* Merges A0 through A1B0 (exclusive) with A1B0 through B1 - (exclusive) to form a combined range also ending at B1 - (exclusive). Both input ranges must be nonempty and sorted in - nondecreasing order according to LESS given auxiliary data - AUX. The output range will be sorted the same way. */ -static void -inplace_merge (struct list_elem *a0, struct list_elem *a1b0, - struct list_elem *b1, - list_less_func *less, void *aux) -{ - ASSERT (a0 != NULL); - ASSERT (a1b0 != NULL); - ASSERT (b1 != NULL); - ASSERT (less != NULL); - ASSERT (is_sorted (a0, a1b0, less, aux)); - ASSERT (is_sorted (a1b0, b1, less, aux)); - - while (a0 != a1b0 && a1b0 != b1) - if (!less (a1b0, a0, aux)) - a0 = list_next (a0); - else - { - a1b0 = list_next (a1b0); - list_splice (a0, list_prev (a1b0), a1b0); - } -} - -/* Sorts LIST according to LESS given auxiliary data AUX, using a - natural iterative merge sort that runs in O(n lg n) time and - O(1) space in the number of elements in LIST. */ -void -list_sort (struct list *list, list_less_func *less, void *aux) -{ - size_t output_run_cnt; /* Number of runs output in current pass. */ - - ASSERT (list != NULL); - ASSERT (less != NULL); - - /* Pass over the list repeatedly, merging adjacent runs of - nondecreasing elements, until only one run is left. */ - do - { - struct list_elem *a0; /* Start of first run. */ - struct list_elem *a1b0; /* End of first run, start of second. */ - struct list_elem *b1; /* End of second run. */ - - output_run_cnt = 0; - for (a0 = list_begin (list); a0 != list_end (list); a0 = b1) - { - /* Each iteration produces one output run. */ - output_run_cnt++; - - /* Locate two adjacent runs of nondecreasing elements - A0...A1B0 and A1B0...B1. */ - a1b0 = find_end_of_run (a0, list_end (list), less, aux); - if (a1b0 == list_end (list)) - break; - b1 = find_end_of_run (a1b0, list_end (list), less, aux); - - /* Merge the runs. */ - inplace_merge (a0, a1b0, b1, less, aux); - } - } - while (output_run_cnt > 1); - - ASSERT (is_sorted (list_begin (list), list_end (list), less, aux)); -} - -/* Inserts ELEM in the proper position in LIST, which must be - sorted according to LESS given auxiliary data AUX. - Runs in O(n) average case in the number of elements in LIST. */ -void -list_insert_ordered (struct list *list, struct list_elem *elem, - list_less_func *less, void *aux) -{ - struct list_elem *e; - - ASSERT (list != NULL); - ASSERT (elem != NULL); - ASSERT (less != NULL); - - for (e = list_begin (list); e != list_end (list); e = list_next (e)) - if (less (elem, e, aux)) - break; - return list_insert (e, elem); -} - -/* Iterates through LIST and removes all but the first in each - set of adjacent elements that are equal according to LESS - given auxiliary data AUX. If DUPLICATES is non-null, then the - elements from LIST are appended to DUPLICATES. */ -void -list_unique (struct list *list, struct list *duplicates, - list_less_func *less, void *aux) -{ - struct list_elem *elem, *next; - - ASSERT (list != NULL); - ASSERT (less != NULL); - if (list_empty (list)) - return; - - elem = list_begin (list); - while ((next = list_next (elem)) != list_end (list)) - if (!less (elem, next, aux) && !less (next, elem, aux)) - { - list_remove (next); - if (duplicates != NULL) - list_push_back (duplicates, next); - } - else - elem = next; -} - -/* Returns the element in LIST with the largest value according - to LESS given auxiliary data AUX. If there is more than one - maximum, returns the one that appears earlier in the list. If - the list is empty, returns its tail. */ -struct list_elem * -list_max (struct list *list, list_less_func *less, void *aux) -{ - struct list_elem *max = list_begin (list); - if (max != list_end (list)) - { - struct list_elem *e; - - for (e = list_next (max); e != list_end (list); e = list_next (e)) - if (less (max, e, aux)) - max = e; - } - return max; -} - -/* Returns the element in LIST with the smallest value according - to LESS given auxiliary data AUX. If there is more than one - minimum, returns the one that appears earlier in the list. If - the list is empty, returns its tail. */ -struct list_elem * -list_min (struct list *list, list_less_func *less, void *aux) -{ - struct list_elem *min = list_begin (list); - if (min != list_end (list)) - { - struct list_elem *e; - - for (e = list_next (min); e != list_end (list); e = list_next (e)) - if (less (e, min, aux)) - min = e; - } - return min; -} diff --git a/src/lib/kernel/list.h b/src/lib/kernel/list.h deleted file mode 100644 index 82efbb5b1c19053a4b7c68723f358bb413ece4c2..0000000000000000000000000000000000000000 --- a/src/lib/kernel/list.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef __LIB_KERNEL_LIST_H -#define __LIB_KERNEL_LIST_H - -/* Doubly linked list. - - This implementation of a doubly linked list does not require - use of dynamically allocated memory. Instead, each structure - that is a potential list element must embed a struct list_elem - member. All of the list functions operate on these `struct - list_elem's. The list_entry macro allows conversion from a - struct list_elem back to a structure object that contains it. - - For example, suppose there is a needed for a list of `struct - foo'. `struct foo' should contain a `struct list_elem' - member, like so: - - struct foo - { - struct list_elem elem; - int bar; - ...other members... - }; - - Then a list of `struct foo' can be be declared and initialized - like so: - - struct list foo_list; - - list_init (&foo_list); - - Iteration is a typical situation where it is necessary to - convert from a struct list_elem back to its enclosing - structure. Here's an example using foo_list: - - struct list_elem *e; - - for (e = list_begin (&foo_list); e != list_end (&foo_list); - e = list_next (e)) - { - struct foo *f = list_entry (e, struct foo, elem); - ...do something with f... - } - - You can find real examples of list usage throughout the - source; for example, malloc.c, palloc.c, and thread.c in the - threads directory all use lists. - - The interface for this list is inspired by the list<> template - in the C++ STL. If you're familiar with list<>, you should - find this easy to use. However, it should be emphasized that - these lists do *no* type checking and can't do much other - correctness checking. If you screw up, it will bite you. - - Glossary of list terms: - - - "front": The first element in a list. Undefined in an - empty list. Returned by list_front(). - - - "back": The last element in a list. Undefined in an empty - list. Returned by list_back(). - - - "tail": The element figuratively just after the last - element of a list. Well defined even in an empty list. - Returned by list_end(). Used as the end sentinel for an - iteration from front to back. - - - "beginning": In a non-empty list, the front. In an empty - list, the tail. Returned by list_begin(). Used as the - starting point for an iteration from front to back. - - - "head": The element figuratively just before the first - element of a list. Well defined even in an empty list. - Returned by list_rend(). Used as the end sentinel for an - iteration from back to front. - - - "reverse beginning": In a non-empty list, the back. In an - empty list, the head. Returned by list_rbegin(). Used as - the starting point for an iteration from back to front. - - - "interior element": An element that is not the head or - tail, that is, a real list element. An empty list does - not have any interior elements. -*/ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* List element. */ -struct list_elem - { - struct list_elem *prev; /* Previous list element. */ - struct list_elem *next; /* Next list element. */ - }; - -/* List. */ -struct list - { - struct list_elem head; /* List head. */ - struct list_elem tail; /* List tail. */ - }; - -/* Converts pointer to list element LIST_ELEM into a pointer to - the structure that LIST_ELEM is embedded inside. Supply the - name of the outer structure STRUCT and the member name MEMBER - of the list element. See the big comment at the top of the - file for an example. */ -#define list_entry(LIST_ELEM, STRUCT, MEMBER) \ - ((STRUCT *) ((uint8_t *) &(LIST_ELEM)->next \ - - offsetof (STRUCT, MEMBER.next))) - -/* List initialization. - - A list may be initialized by calling list_init(): - - struct list my_list; - list_init (&my_list); - - or with an initializer using LIST_INITIALIZER: - - struct list my_list = LIST_INITIALIZER (my_list); */ -#define LIST_INITIALIZER(NAME) { { NULL, &(NAME).tail }, \ - { &(NAME).head, NULL } } - -void list_init (struct list *); - -/* List traversal. */ -struct list_elem *list_begin (struct list *); -struct list_elem *list_next (struct list_elem *); -struct list_elem *list_end (struct list *); - -struct list_elem *list_rbegin (struct list *); -struct list_elem *list_prev (struct list_elem *); -struct list_elem *list_rend (struct list *); - -struct list_elem *list_head (struct list *); -struct list_elem *list_tail (struct list *); - -/* List insertion. */ -void list_insert (struct list_elem *, struct list_elem *); -void list_splice (struct list_elem *before, - struct list_elem *first, struct list_elem *last); -void list_push_front (struct list *, struct list_elem *); -void list_push_back (struct list *, struct list_elem *); - -/* List removal. */ -struct list_elem *list_remove (struct list_elem *); -struct list_elem *list_pop_front (struct list *); -struct list_elem *list_pop_back (struct list *); - -/* List elements. */ -struct list_elem *list_front (struct list *); -struct list_elem *list_back (struct list *); - -/* List properties. */ -size_t list_size (struct list *); -bool list_empty (struct list *); - -/* Miscellaneous. */ -void list_reverse (struct list *); - -/* Compares the value of two list elements A and B, given - auxiliary data AUX. Returns true if A is less than B, or - false if A is greater than or equal to B. */ -typedef bool list_less_func (const struct list_elem *a, - const struct list_elem *b, - void *aux); - -/* Operations on lists with ordered elements. */ -void list_sort (struct list *, - list_less_func *, void *aux); -void list_insert_ordered (struct list *, struct list_elem *, - list_less_func *, void *aux); -void list_unique (struct list *, struct list *duplicates, - list_less_func *, void *aux); - -/* Max and min. */ -struct list_elem *list_max (struct list *, list_less_func *, void *aux); -struct list_elem *list_min (struct list *, list_less_func *, void *aux); - -#endif /* lib/kernel/list.h */ diff --git a/src/lib/kernel/stdio.h b/src/lib/kernel/stdio.h deleted file mode 100644 index 3e5bae9b65b27d6008ee758df692da91e2b00b58..0000000000000000000000000000000000000000 --- a/src/lib/kernel/stdio.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __LIB_KERNEL_STDIO_H -#define __LIB_KERNEL_STDIO_H - -void putbuf (const char *, size_t); - -#endif /* lib/kernel/stdio.h */ diff --git a/src/lib/limits.h b/src/lib/limits.h deleted file mode 100644 index c957ec43e5075bcdc26230e20a93ef6f013bfa58..0000000000000000000000000000000000000000 --- a/src/lib/limits.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __LIB_LIMITS_H -#define __LIB_LIMITS_H - -#define CHAR_BIT 8 - -#define SCHAR_MAX 127 -#define SCHAR_MIN (-SCHAR_MAX - 1) -#define UCHAR_MAX 255 - -#ifdef __CHAR_UNSIGNED__ -#define CHAR_MIN 0 -#define CHAR_MAX UCHAR_MAX -#else -#define CHAR_MIN SCHAR_MIN -#define CHAR_MAX SCHAR_MAX -#endif - -#define SHRT_MAX 32767 -#define SHRT_MIN (-SHRT_MAX - 1) -#define USHRT_MAX 65535 - -#define INT_MAX 2147483647 -#define INT_MIN (-INT_MAX - 1) -#define UINT_MAX 4294967295U - -#define LONG_MAX 2147483647L -#define LONG_MIN (-LONG_MAX - 1) -#define ULONG_MAX 4294967295UL - -#define LLONG_MAX 9223372036854775807LL -#define LLONG_MIN (-LLONG_MAX - 1) -#define ULLONG_MAX 18446744073709551615ULL - -#endif /* lib/limits.h */ diff --git a/src/lib/packed.h b/src/lib/packed.h deleted file mode 100644 index 9a9b6e23e96b66ab2a1a6538207a87e806cd46b9..0000000000000000000000000000000000000000 --- a/src/lib/packed.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __LIB_PACKED_H -#define __LIB_PACKED_H - -/* The "packed" attribute, when applied to a structure, prevents - GCC from inserting padding bytes between or after structure - members. It must be specified at the time of the structure's - definition, normally just after the closing brace. */ -#define PACKED __attribute__ ((packed)) - -#endif /* lib/packed.h */ diff --git a/src/lib/random.c b/src/lib/random.c deleted file mode 100644 index a4761b6b52c14d3202a783d1e7eb1ab64baba767..0000000000000000000000000000000000000000 --- a/src/lib/random.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "random.h" -#include <stdbool.h> -#include <stdint.h> -#include "debug.h" - -/* RC4-based pseudo-random number generator (PRNG). - - RC4 is a stream cipher. We're not using it here for its - cryptographic properties, but because it is easy to implement - and its output is plenty random for non-cryptographic - purposes. - - See http://en.wikipedia.org/wiki/RC4_(cipher) for information - on RC4.*/ - -/* RC4 state. */ -static uint8_t s[256]; /* S[]. */ -static uint8_t s_i, s_j; /* i, j. */ - -/* Already initialized? */ -static bool inited; - -/* Swaps the bytes pointed to by A and B. */ -static inline void -swap_byte (uint8_t *a, uint8_t *b) -{ - uint8_t t = *a; - *a = *b; - *b = t; -} - -/* Initializes or reinitializes the PRNG with the given SEED. */ -void -random_init (unsigned seed) -{ - uint8_t *seedp = (uint8_t *) &seed; - int i; - uint8_t j; - - for (i = 0; i < 256; i++) - s[i] = i; - for (i = j = 0; i < 256; i++) - { - j += s[i] + seedp[i % sizeof seed]; - swap_byte (s + i, s + j); - } - - s_i = s_j = 0; - inited = true; -} - -/* Writes SIZE random bytes into BUF. */ -void -random_bytes (void *buf_, size_t size) -{ - uint8_t *buf; - - if (!inited) - random_init (0); - - for (buf = buf_; size-- > 0; buf++) - { - uint8_t s_k; - - s_i++; - s_j += s[s_i]; - swap_byte (s + s_i, s + s_j); - - s_k = s[s_i] + s[s_j]; - *buf = s[s_k]; - } -} - -/* Returns a pseudo-random unsigned long. - Use random_ulong() % n to obtain a random number in the range - 0...n (exclusive). */ -unsigned long -random_ulong (void) -{ - unsigned long ul; - random_bytes (&ul, sizeof ul); - return ul; -} diff --git a/src/lib/random.h b/src/lib/random.h deleted file mode 100644 index 0950ae2e0e76f54f6f018c457d14d6a3e2daf5e0..0000000000000000000000000000000000000000 --- a/src/lib/random.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __LIB_RANDOM_H -#define __LIB_RANDOM_H - -#include <stddef.h> - -void random_init (unsigned seed); -void random_bytes (void *, size_t); -unsigned long random_ulong (void); - -#endif /* lib/random.h */ diff --git a/src/lib/round.h b/src/lib/round.h deleted file mode 100644 index 3aa66427409c4e3be1e061a8d910cba38b4766f3..0000000000000000000000000000000000000000 --- a/src/lib/round.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __LIB_ROUND_H -#define __LIB_ROUND_H - -/* Yields X rounded up to the nearest multiple of STEP. - For X >= 0, STEP >= 1 only. */ -#define ROUND_UP(X, STEP) (((X) + (STEP) - 1) / (STEP) * (STEP)) - -/* Yields X divided by STEP, rounded up. - For X >= 0, STEP >= 1 only. */ -#define DIV_ROUND_UP(X, STEP) (((X) + (STEP) - 1) / (STEP)) - -/* Yields X rounded down to the nearest multiple of STEP. - For X >= 0, STEP >= 1 only. */ -#define ROUND_DOWN(X, STEP) ((X) / (STEP) * (STEP)) - -/* There is no DIV_ROUND_DOWN. It would be simply X / STEP. */ - -#endif /* lib/round.h */ diff --git a/src/lib/stdarg.h b/src/lib/stdarg.h deleted file mode 100644 index 32622b5ab70a6065b091eaf0d14542f09eae1882..0000000000000000000000000000000000000000 --- a/src/lib/stdarg.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __LIB_STDARG_H -#define __LIB_STDARG_H - -/* GCC has <stdarg.h> functionality as built-ins, - so all we need is to use it. */ - -typedef __builtin_va_list va_list; - -#define va_start(LIST, ARG) __builtin_va_start (LIST, ARG) -#define va_end(LIST) __builtin_va_end (LIST) -#define va_arg(LIST, TYPE) __builtin_va_arg (LIST, TYPE) -#define va_copy(DST, SRC) __builtin_va_copy (DST, SRC) - -#endif /* lib/stdarg.h */ diff --git a/src/lib/stdbool.h b/src/lib/stdbool.h deleted file mode 100644 index f173a912ad086ac0189191240fc728f5c8d81ece..0000000000000000000000000000000000000000 --- a/src/lib/stdbool.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __LIB_STDBOOL_H -#define __LIB_STDBOOL_H - -#define bool _Bool -#define true 1 -#define false 0 -#define __bool_true_false_are_defined 1 - -#endif /* lib/stdbool.h */ diff --git a/src/lib/stddef.h b/src/lib/stddef.h deleted file mode 100644 index 4e74fa6178e80b155a776b77b2c90d3d9e7d1b4b..0000000000000000000000000000000000000000 --- a/src/lib/stddef.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __LIB_STDDEF_H -#define __LIB_STDDEF_H - -#define NULL ((void *) 0) -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER) - -/* GCC predefines the types we need for ptrdiff_t and size_t, - so that we don't have to guess. */ -typedef __PTRDIFF_TYPE__ ptrdiff_t; -typedef __SIZE_TYPE__ size_t; - -#endif /* lib/stddef.h */ diff --git a/src/lib/stdint.h b/src/lib/stdint.h deleted file mode 100644 index ef5f214e150a59102dc313c6702483b6e26d7a9f..0000000000000000000000000000000000000000 --- a/src/lib/stdint.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __LIB_STDINT_H -#define __LIB_STDINT_H - -typedef signed char int8_t; -#define INT8_MAX 127 -#define INT8_MIN (-INT8_MAX - 1) - -typedef signed short int int16_t; -#define INT16_MAX 32767 -#define INT16_MIN (-INT16_MAX - 1) - -typedef signed int int32_t; -#define INT32_MAX 2147483647 -#define INT32_MIN (-INT32_MAX - 1) - -typedef signed long long int int64_t; -#define INT64_MAX 9223372036854775807LL -#define INT64_MIN (-INT64_MAX - 1) - -typedef unsigned char uint8_t; -#define UINT8_MAX 255 - -typedef unsigned short int uint16_t; -#define UINT16_MAX 65535 - -typedef unsigned int uint32_t; -#define UINT32_MAX 4294967295U - -typedef unsigned long long int uint64_t; -#define UINT64_MAX 18446744073709551615ULL - -typedef int32_t intptr_t; -#define INTPTR_MIN INT32_MIN -#define INTPTR_MAX INT32_MAX - -typedef uint32_t uintptr_t; -#define UINTPTR_MAX UINT32_MAX - -typedef int64_t intmax_t; -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX - -typedef uint64_t uintmax_t; -#define UINTMAX_MAX UINT64_MAX - -#define PTRDIFF_MIN INT32_MIN -#define PTRDIFF_MAX INT32_MAX - -#define SIZE_MAX UINT32_MAX - -#endif /* lib/stdint.h */ diff --git a/src/lib/stdio.c b/src/lib/stdio.c deleted file mode 100644 index 8927c50555d9993ae1ac952e21bc3fe7deb93f7e..0000000000000000000000000000000000000000 --- a/src/lib/stdio.c +++ /dev/null @@ -1,655 +0,0 @@ -#include <stdio.h> -#include <ctype.h> -#include <inttypes.h> -#include <round.h> -#include <stdint.h> -#include <string.h> - -/* Auxiliary data for vsnprintf_helper(). */ -struct vsnprintf_aux - { - char *p; /* Current output position. */ - int length; /* Length of output string. */ - int max_length; /* Max length of output string. */ - }; - -static void vsnprintf_helper (char, void *); - -/* Like vprintf(), except that output is stored into BUFFER, - which must have space for BUF_SIZE characters. Writes at most - BUF_SIZE - 1 characters to BUFFER, followed by a null - terminator. BUFFER will always be null-terminated unless - BUF_SIZE is zero. Returns the number of characters that would - have been written to BUFFER, not including a null terminator, - had there been enough room. */ -int -vsnprintf (char *buffer, size_t buf_size, const char *format, va_list args) -{ - /* Set up aux data for vsnprintf_helper(). */ - struct vsnprintf_aux aux; - aux.p = buffer; - aux.length = 0; - aux.max_length = buf_size > 0 ? buf_size - 1 : 0; - - /* Do most of the work. */ - __vprintf (format, args, vsnprintf_helper, &aux); - - /* Add null terminator. */ - if (buf_size > 0) - *aux.p = '\0'; - - return aux.length; -} - -/* Helper function for vsnprintf(). */ -static void -vsnprintf_helper (char ch, void *aux_) -{ - struct vsnprintf_aux *aux = aux_; - - if (aux->length++ < aux->max_length) - *aux->p++ = ch; -} - -/* Like printf(), except that output is stored into BUFFER, - which must have space for BUF_SIZE characters. Writes at most - BUF_SIZE - 1 characters to BUFFER, followed by a null - terminator. BUFFER will always be null-terminated unless - BUF_SIZE is zero. Returns the number of characters that would - have been written to BUFFER, not including a null terminator, - had there been enough room. */ -int -snprintf (char *buffer, size_t buf_size, const char *format, ...) -{ - va_list args; - int retval; - - va_start (args, format); - retval = vsnprintf (buffer, buf_size, format, args); - va_end (args); - - return retval; -} - -/* Writes formatted output to the console. - In the kernel, the console is both the video display and first - serial port. - In userspace, the console is file descriptor 1. */ -int -printf (const char *format, ...) -{ - va_list args; - int retval; - - va_start (args, format); - retval = vprintf (format, args); - va_end (args); - - return retval; -} - -/* printf() formatting internals. */ - -/* A printf() conversion. */ -struct printf_conversion - { - /* Flags. */ - enum - { - MINUS = 1 << 0, /* '-' */ - PLUS = 1 << 1, /* '+' */ - SPACE = 1 << 2, /* ' ' */ - POUND = 1 << 3, /* '#' */ - ZERO = 1 << 4, /* '0' */ - GROUP = 1 << 5 /* '\'' */ - } - flags; - - /* Minimum field width. */ - int width; - - /* Numeric precision. - -1 indicates no precision was specified. */ - int precision; - - /* Type of argument to format. */ - enum - { - CHAR = 1, /* hh */ - SHORT = 2, /* h */ - INT = 3, /* (none) */ - INTMAX = 4, /* j */ - LONG = 5, /* l */ - LONGLONG = 6, /* ll */ - PTRDIFFT = 7, /* t */ - SIZET = 8 /* z */ - } - type; - }; - -struct integer_base - { - int base; /* Base. */ - const char *digits; /* Collection of digits. */ - int x; /* `x' character to use, for base 16 only. */ - int group; /* Number of digits to group with ' flag. */ - }; - -static const struct integer_base base_d = {10, "0123456789", 0, 3}; -static const struct integer_base base_o = {8, "01234567", 0, 3}; -static const struct integer_base base_x = {16, "0123456789abcdef", 'x', 4}; -static const struct integer_base base_X = {16, "0123456789ABCDEF", 'X', 4}; - -static const char *parse_conversion (const char *format, - struct printf_conversion *, - va_list *); -static void format_integer (uintmax_t value, bool is_signed, bool negative, - const struct integer_base *, - const struct printf_conversion *, - void (*output) (char, void *), void *aux); -static void output_dup (char ch, size_t cnt, - void (*output) (char, void *), void *aux); -static void format_string (const char *string, int length, - struct printf_conversion *, - void (*output) (char, void *), void *aux); - -void -__vprintf (const char *format, va_list args, - void (*output) (char, void *), void *aux) -{ - for (; *format != '\0'; format++) - { - struct printf_conversion c; - - /* Literally copy non-conversions to output. */ - if (*format != '%') - { - output (*format, aux); - continue; - } - format++; - - /* %% => %. */ - if (*format == '%') - { - output ('%', aux); - continue; - } - - /* Parse conversion specifiers. */ - format = parse_conversion (format, &c, &args); - - /* Do conversion. */ - switch (*format) - { - case 'd': - case 'i': - { - /* Signed integer conversions. */ - intmax_t value; - - switch (c.type) - { - case CHAR: - value = (signed char) va_arg (args, int); - break; - case SHORT: - value = (short) va_arg (args, int); - break; - case INT: - value = va_arg (args, int); - break; - case INTMAX: - value = va_arg (args, intmax_t); - break; - case LONG: - value = va_arg (args, long); - break; - case LONGLONG: - value = va_arg (args, long long); - break; - case PTRDIFFT: - value = va_arg (args, ptrdiff_t); - break; - case SIZET: - value = va_arg (args, size_t); - if (value > SIZE_MAX / 2) - value = value - SIZE_MAX - 1; - break; - default: - NOT_REACHED (); - } - - format_integer (value < 0 ? -value : value, - true, value < 0, &base_d, &c, output, aux); - } - break; - - case 'o': - case 'u': - case 'x': - case 'X': - { - /* Unsigned integer conversions. */ - uintmax_t value; - const struct integer_base *b; - - switch (c.type) - { - case CHAR: - value = (unsigned char) va_arg (args, unsigned); - break; - case SHORT: - value = (unsigned short) va_arg (args, unsigned); - break; - case INT: - value = va_arg (args, unsigned); - break; - case INTMAX: - value = va_arg (args, uintmax_t); - break; - case LONG: - value = va_arg (args, unsigned long); - break; - case LONGLONG: - value = va_arg (args, unsigned long long); - break; - case PTRDIFFT: - value = va_arg (args, ptrdiff_t); -#if UINTMAX_MAX != PTRDIFF_MAX - value &= ((uintmax_t) PTRDIFF_MAX << 1) | 1; -#endif - break; - case SIZET: - value = va_arg (args, size_t); - break; - default: - NOT_REACHED (); - } - - switch (*format) - { - case 'o': b = &base_o; break; - case 'u': b = &base_d; break; - case 'x': b = &base_x; break; - case 'X': b = &base_X; break; - default: NOT_REACHED (); - } - - format_integer (value, false, false, b, &c, output, aux); - } - break; - - case 'c': - { - /* Treat character as single-character string. */ - char ch = va_arg (args, int); - format_string (&ch, 1, &c, output, aux); - } - break; - - case 's': - { - /* String conversion. */ - const char *s = va_arg (args, char *); - if (s == NULL) - s = "(null)"; - - /* Limit string length according to precision. - Note: if c.precision == -1 then strnlen() will get - SIZE_MAX for MAXLEN, which is just what we want. */ - format_string (s, strnlen (s, c.precision), &c, output, aux); - } - break; - - case 'p': - { - /* Pointer conversion. - Format pointers as %#x. */ - void *p = va_arg (args, void *); - - c.flags = POUND; - format_integer ((uintptr_t) p, false, false, - &base_x, &c, output, aux); - } - break; - - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - case 'n': - /* We don't support floating-point arithmetic, - and %n can be part of a security hole. */ - __printf ("<<no %%%c in kernel>>", output, aux, *format); - break; - - default: - __printf ("<<no %%%c conversion>>", output, aux, *format); - break; - } - } -} - -/* Parses conversion option characters starting at FORMAT and - initializes C appropriately. Returns the character in FORMAT - that indicates the conversion (e.g. the `d' in `%d'). Uses - *ARGS for `*' field widths and precisions. */ -static const char * -parse_conversion (const char *format, struct printf_conversion *c, - va_list *args) -{ - /* Parse flag characters. */ - c->flags = 0; - for (;;) - { - switch (*format++) - { - case '-': - c->flags |= MINUS; - break; - case '+': - c->flags |= PLUS; - break; - case ' ': - c->flags |= SPACE; - break; - case '#': - c->flags |= POUND; - break; - case '0': - c->flags |= ZERO; - break; - case '\'': - c->flags |= GROUP; - break; - default: - format--; - goto not_a_flag; - } - } - not_a_flag: - if (c->flags & MINUS) - c->flags &= ~ZERO; - if (c->flags & PLUS) - c->flags &= ~SPACE; - - /* Parse field width. */ - c->width = 0; - if (*format == '*') - { - format++; - c->width = va_arg (*args, int); - } - else - { - for (; isdigit (*format); format++) - c->width = c->width * 10 + *format - '0'; - } - if (c->width < 0) - { - c->width = -c->width; - c->flags |= MINUS; - } - - /* Parse precision. */ - c->precision = -1; - if (*format == '.') - { - format++; - if (*format == '*') - { - format++; - c->precision = va_arg (*args, int); - } - else - { - c->precision = 0; - for (; isdigit (*format); format++) - c->precision = c->precision * 10 + *format - '0'; - } - if (c->precision < 0) - c->precision = -1; - } - if (c->precision >= 0) - c->flags &= ~ZERO; - - /* Parse type. */ - c->type = INT; - switch (*format++) - { - case 'h': - if (*format == 'h') - { - format++; - c->type = CHAR; - } - else - c->type = SHORT; - break; - - case 'j': - c->type = INTMAX; - break; - - case 'l': - if (*format == 'l') - { - format++; - c->type = LONGLONG; - } - else - c->type = LONG; - break; - - case 't': - c->type = PTRDIFFT; - break; - - case 'z': - c->type = SIZET; - break; - - default: - format--; - break; - } - - return format; -} - -/* Performs an integer conversion, writing output to OUTPUT with - auxiliary data AUX. The integer converted has absolute value - VALUE. If IS_SIGNED is true, does a signed conversion with - NEGATIVE indicating a negative value; otherwise does an - unsigned conversion and ignores NEGATIVE. The output is done - according to the provided base B. Details of the conversion - are in C. */ -static void -format_integer (uintmax_t value, bool is_signed, bool negative, - const struct integer_base *b, - const struct printf_conversion *c, - void (*output) (char, void *), void *aux) -{ - char buf[64], *cp; /* Buffer and current position. */ - int x; /* `x' character to use or 0 if none. */ - int sign; /* Sign character or 0 if none. */ - int precision; /* Rendered precision. */ - int pad_cnt; /* # of pad characters to fill field width. */ - int digit_cnt; /* # of digits output so far. */ - - /* Determine sign character, if any. - An unsigned conversion will never have a sign character, - even if one of the flags requests one. */ - sign = 0; - if (is_signed) - { - if (c->flags & PLUS) - sign = negative ? '-' : '+'; - else if (c->flags & SPACE) - sign = negative ? '-' : ' '; - else if (negative) - sign = '-'; - } - - /* Determine whether to include `0x' or `0X'. - It will only be included with a hexadecimal conversion of a - nonzero value with the # flag. */ - x = (c->flags & POUND) && value ? b->x : 0; - - /* Accumulate digits into buffer. - This algorithm produces digits in reverse order, so later we - will output the buffer's content in reverse. */ - cp = buf; - digit_cnt = 0; - while (value > 0) - { - if ((c->flags & GROUP) && digit_cnt > 0 && digit_cnt % b->group == 0) - *cp++ = ','; - *cp++ = b->digits[value % b->base]; - value /= b->base; - digit_cnt++; - } - - /* Append enough zeros to match precision. - If requested precision is 0, then a value of zero is - rendered as a null string, otherwise as "0". - If the # flag is used with base 8, the result must always - begin with a zero. */ - precision = c->precision < 0 ? 1 : c->precision; - while (cp - buf < precision && cp < buf + sizeof buf - 1) - *cp++ = '0'; - if ((c->flags & POUND) && b->base == 8 && (cp == buf || cp[-1] != '0')) - *cp++ = '0'; - - /* Calculate number of pad characters to fill field width. */ - pad_cnt = c->width - (cp - buf) - (x ? 2 : 0) - (sign != 0); - if (pad_cnt < 0) - pad_cnt = 0; - - /* Do output. */ - if ((c->flags & (MINUS | ZERO)) == 0) - output_dup (' ', pad_cnt, output, aux); - if (sign) - output (sign, aux); - if (x) - { - output ('0', aux); - output (x, aux); - } - if (c->flags & ZERO) - output_dup ('0', pad_cnt, output, aux); - while (cp > buf) - output (*--cp, aux); - if (c->flags & MINUS) - output_dup (' ', pad_cnt, output, aux); -} - -/* Writes CH to OUTPUT with auxiliary data AUX, CNT times. */ -static void -output_dup (char ch, size_t cnt, void (*output) (char, void *), void *aux) -{ - while (cnt-- > 0) - output (ch, aux); -} - -/* Formats the LENGTH characters starting at STRING according to - the conversion specified in C. Writes output to OUTPUT with - auxiliary data AUX. */ -static void -format_string (const char *string, int length, - struct printf_conversion *c, - void (*output) (char, void *), void *aux) -{ - int i; - if (c->width > length && (c->flags & MINUS) == 0) - output_dup (' ', c->width - length, output, aux); - for (i = 0; i < length; i++) - output (string[i], aux); - if (c->width > length && (c->flags & MINUS) != 0) - output_dup (' ', c->width - length, output, aux); -} - -/* Wrapper for __vprintf() that converts varargs into a - va_list. */ -void -__printf (const char *format, - void (*output) (char, void *), void *aux, ...) -{ - va_list args; - - va_start (args, aux); - __vprintf (format, args, output, aux); - va_end (args); -} - -/* Dumps the SIZE bytes in BUF to the console as hex bytes - arranged 16 per line. Numeric offsets are also included, - starting at OFS for the first byte in BUF. If ASCII is true - then the corresponding ASCII characters are also rendered - alongside. */ -void -hex_dump (uintptr_t ofs, const void *buf_, size_t size, bool ascii) -{ - const uint8_t *buf = buf_; - const size_t per_line = 16; /* Maximum bytes per line. */ - - while (size > 0) - { - size_t start, end, n; - size_t i; - - /* Number of bytes on this line. */ - start = ofs % per_line; - end = per_line; - if (end - start > size) - end = start + size; - n = end - start; - - /* Print line. */ - printf ("%08jx ", (uintmax_t) ROUND_DOWN (ofs, per_line)); - for (i = 0; i < start; i++) - printf (" "); - for (; i < end; i++) - printf ("%02hhx%c", - buf[i - start], i == per_line / 2 - 1? '-' : ' '); - if (ascii) - { - for (; i < per_line; i++) - printf (" "); - printf ("|"); - for (i = 0; i < start; i++) - printf (" "); - for (; i < end; i++) - printf ("%c", - isprint (buf[i - start]) ? buf[i - start] : '.'); - for (; i < per_line; i++) - printf (" "); - printf ("|"); - } - printf ("\n"); - - ofs += n; - buf += n; - size -= n; - } -} - -/* Prints SIZE, which represents a number of bytes, in a - human-readable format, e.g. "256 kB". */ -void -print_human_readable_size (uint64_t size) -{ - if (size == 1) - printf ("1 byte"); - else - { - static const char *factors[] = {"bytes", "kB", "MB", "GB", "TB", NULL}; - const char **fp; - - for (fp = factors; size >= 1024 && fp[1] != NULL; fp++) - size /= 1024; - printf ("%"PRIu64" %s", size, *fp); - } -} diff --git a/src/lib/stdio.h b/src/lib/stdio.h deleted file mode 100644 index 2739c0a2959de450fc348554f1730c2a0decc22c..0000000000000000000000000000000000000000 --- a/src/lib/stdio.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __LIB_STDIO_H -#define __LIB_STDIO_H - -#include <debug.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* Include lib/user/stdio.h or lib/kernel/stdio.h, as - appropriate. */ -#include_next <stdio.h> - -/* Predefined file handles. */ -#define STDIN_FILENO 0 -#define STDOUT_FILENO 1 - -/* Standard functions. */ -int printf (const char *, ...) PRINTF_FORMAT (1, 2); -int snprintf (char *, size_t, const char *, ...) PRINTF_FORMAT (3, 4); -int vprintf (const char *, va_list) PRINTF_FORMAT (1, 0); -int vsnprintf (char *, size_t, const char *, va_list) PRINTF_FORMAT (3, 0); -int putchar (int); -int puts (const char *); - -/* Nonstandard functions. */ -void hex_dump (uintptr_t ofs, const void *, size_t size, bool ascii); -void print_human_readable_size (uint64_t sz); - -/* Internal functions. */ -void __vprintf (const char *format, va_list args, - void (*output) (char, void *), void *aux); -void __printf (const char *format, - void (*output) (char, void *), void *aux, ...); - -/* Try to be helpful. */ -#define sprintf dont_use_sprintf_use_snprintf -#define vsprintf dont_use_vsprintf_use_vsnprintf - -#endif /* lib/stdio.h */ diff --git a/src/lib/stdlib.c b/src/lib/stdlib.c deleted file mode 100644 index 84c7f616716e2a71bce250c9dad86b966a5ee012..0000000000000000000000000000000000000000 --- a/src/lib/stdlib.c +++ /dev/null @@ -1,208 +0,0 @@ -#include <ctype.h> -#include <debug.h> -#include <random.h> -#include <stdlib.h> -#include <stdbool.h> - -/* Converts a string representation of a signed decimal integer - in S into an `int', which is returned. */ -int -atoi (const char *s) -{ - bool negative; - int value; - - ASSERT (s != NULL); - - /* Skip white space. */ - while (isspace ((unsigned char) *s)) - s++; - - /* Parse sign. */ - negative = false; - if (*s == '+') - s++; - else if (*s == '-') - { - negative = true; - s++; - } - - /* Parse digits. We always initially parse the value as - negative, and then make it positive later, because the - negative range of an int is bigger than the positive range - on a 2's complement system. */ - for (value = 0; isdigit (*s); s++) - value = value * 10 - (*s - '0'); - if (!negative) - value = -value; - - return value; -} - -/* Compares A and B by calling the AUX function. */ -static int -compare_thunk (const void *a, const void *b, void *aux) -{ - int (**compare) (const void *, const void *) = aux; - return (*compare) (a, b); -} - -/* Sorts ARRAY, which contains CNT elements of SIZE bytes each, - using COMPARE. When COMPARE is passed a pair of elements A - and B, respectively, it must return a strcmp()-type result, - i.e. less than zero if A < B, zero if A == B, greater than - zero if A > B. Runs in O(n lg n) time and O(1) space in - CNT. */ -void -qsort (void *array, size_t cnt, size_t size, - int (*compare) (const void *, const void *)) -{ - sort (array, cnt, size, compare_thunk, &compare); -} - -/* Swaps elements with 1-based indexes A_IDX and B_IDX in ARRAY - with elements of SIZE bytes each. */ -static void -do_swap (unsigned char *array, size_t a_idx, size_t b_idx, size_t size) -{ - unsigned char *a = array + (a_idx - 1) * size; - unsigned char *b = array + (b_idx - 1) * size; - size_t i; - - for (i = 0; i < size; i++) - { - unsigned char t = a[i]; - a[i] = b[i]; - b[i] = t; - } -} - -/* Compares elements with 1-based indexes A_IDX and B_IDX in - ARRAY with elements of SIZE bytes each, using COMPARE to - compare elements, passing AUX as auxiliary data, and returns a - strcmp()-type result. */ -static int -do_compare (unsigned char *array, size_t a_idx, size_t b_idx, size_t size, - int (*compare) (const void *, const void *, void *aux), - void *aux) -{ - return compare (array + (a_idx - 1) * size, array + (b_idx - 1) * size, aux); -} - -/* "Float down" the element with 1-based index I in ARRAY of CNT - elements of SIZE bytes each, using COMPARE to compare - elements, passing AUX as auxiliary data. */ -static void -heapify (unsigned char *array, size_t i, size_t cnt, size_t size, - int (*compare) (const void *, const void *, void *aux), - void *aux) -{ - for (;;) - { - /* Set `max' to the index of the largest element among I - and its children (if any). */ - size_t left = 2 * i; - size_t right = 2 * i + 1; - size_t max = i; - if (left <= cnt && do_compare (array, left, max, size, compare, aux) > 0) - max = left; - if (right <= cnt - && do_compare (array, right, max, size, compare, aux) > 0) - max = right; - - /* If the maximum value is already in element I, we're - done. */ - if (max == i) - break; - - /* Swap and continue down the heap. */ - do_swap (array, i, max, size); - i = max; - } -} - -/* Sorts ARRAY, which contains CNT elements of SIZE bytes each, - using COMPARE to compare elements, passing AUX as auxiliary - data. When COMPARE is passed a pair of elements A and B, - respectively, it must return a strcmp()-type result, i.e. less - than zero if A < B, zero if A == B, greater than zero if A > - B. Runs in O(n lg n) time and O(1) space in CNT. */ -void -sort (void *array, size_t cnt, size_t size, - int (*compare) (const void *, const void *, void *aux), - void *aux) -{ - size_t i; - - ASSERT (array != NULL || cnt == 0); - ASSERT (compare != NULL); - ASSERT (size > 0); - - /* Build a heap. */ - for (i = cnt / 2; i > 0; i--) - heapify (array, i, cnt, size, compare, aux); - - /* Sort the heap. */ - for (i = cnt; i > 1; i--) - { - do_swap (array, 1, i, size); - heapify (array, 1, i - 1, size, compare, aux); - } -} - -/* Searches ARRAY, which contains CNT elements of SIZE bytes - each, for the given KEY. Returns a match is found, otherwise - a null pointer. If there are multiple matches, returns an - arbitrary one of them. - - ARRAY must be sorted in order according to COMPARE. - - Uses COMPARE to compare elements. When COMPARE is passed a - pair of elements A and B, respectively, it must return a - strcmp()-type result, i.e. less than zero if A < B, zero if A - == B, greater than zero if A > B. */ -void * -bsearch (const void *key, const void *array, size_t cnt, - size_t size, int (*compare) (const void *, const void *)) -{ - return binary_search (key, array, cnt, size, compare_thunk, &compare); -} - -/* Searches ARRAY, which contains CNT elements of SIZE bytes - each, for the given KEY. Returns a match is found, otherwise - a null pointer. If there are multiple matches, returns an - arbitrary one of them. - - ARRAY must be sorted in order according to COMPARE. - - Uses COMPARE to compare elements, passing AUX as auxiliary - data. When COMPARE is passed a pair of elements A and B, - respectively, it must return a strcmp()-type result, i.e. less - than zero if A < B, zero if A == B, greater than zero if A > - B. */ -void * -binary_search (const void *key, const void *array, size_t cnt, size_t size, - int (*compare) (const void *, const void *, void *aux), - void *aux) -{ - const unsigned char *first = array; - const unsigned char *last = array + size * cnt; - - while (first < last) - { - size_t range = (last - first) / size; - const unsigned char *middle = first + (range / 2) * size; - int cmp = compare (key, middle, aux); - - if (cmp < 0) - last = middle; - else if (cmp > 0) - first = middle + size; - else - return (void *) middle; - } - - return NULL; -} - diff --git a/src/lib/stdlib.h b/src/lib/stdlib.h deleted file mode 100644 index d14afa38384e599969135d7178342a0624f47e2a..0000000000000000000000000000000000000000 --- a/src/lib/stdlib.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __LIB_STDLIB_H -#define __LIB_STDLIB_H - -#include <stddef.h> - -/* Standard functions. */ -int atoi (const char *); -void qsort (void *array, size_t cnt, size_t size, - int (*compare) (const void *, const void *)); -void *bsearch (const void *key, const void *array, size_t cnt, - size_t size, int (*compare) (const void *, const void *)); - -/* Nonstandard functions. */ -void sort (void *array, size_t cnt, size_t size, - int (*compare) (const void *, const void *, void *aux), - void *aux); -void *binary_search (const void *key, const void *array, size_t cnt, - size_t size, - int (*compare) (const void *, const void *, void *aux), - void *aux); - -#endif /* lib/stdlib.h */ diff --git a/src/lib/string.c b/src/lib/string.c deleted file mode 100644 index d223c89f48493793c52dc45dbcf288328776fd6f..0000000000000000000000000000000000000000 --- a/src/lib/string.c +++ /dev/null @@ -1,375 +0,0 @@ -#include <string.h> -#include <debug.h> - -/* Copies SIZE bytes from SRC to DST, which must not overlap. - Returns DST. */ -void * -memcpy (void *dst_, const void *src_, size_t size) -{ - unsigned char *dst = dst_; - const unsigned char *src = src_; - - ASSERT (dst != NULL || size == 0); - ASSERT (src != NULL || size == 0); - - while (size-- > 0) - *dst++ = *src++; - - return dst_; -} - -/* Copies SIZE bytes from SRC to DST, which are allowed to - overlap. Returns DST. */ -void * -memmove (void *dst_, const void *src_, size_t size) -{ - unsigned char *dst = dst_; - const unsigned char *src = src_; - - ASSERT (dst != NULL || size == 0); - ASSERT (src != NULL || size == 0); - - if (dst < src) - { - while (size-- > 0) - *dst++ = *src++; - } - else - { - dst += size; - src += size; - while (size-- > 0) - *--dst = *--src; - } - - return dst; -} - -/* Find the first differing byte in the two blocks of SIZE bytes - at A and B. Returns a positive value if the byte in A is - greater, a negative value if the byte in B is greater, or zero - if blocks A and B are equal. */ -int -memcmp (const void *a_, const void *b_, size_t size) -{ - const unsigned char *a = a_; - const unsigned char *b = b_; - - ASSERT (a != NULL || size == 0); - ASSERT (b != NULL || size == 0); - - for (; size-- > 0; a++, b++) - if (*a != *b) - return *a > *b ? +1 : -1; - return 0; -} - -/* Finds the first differing characters in strings A and B. - Returns a positive value if the character in A (as an unsigned - char) is greater, a negative value if the character in B (as - an unsigned char) is greater, or zero if strings A and B are - equal. */ -int -strcmp (const char *a_, const char *b_) -{ - const unsigned char *a = (const unsigned char *) a_; - const unsigned char *b = (const unsigned char *) b_; - - ASSERT (a != NULL); - ASSERT (b != NULL); - - while (*a != '\0' && *a == *b) - { - a++; - b++; - } - - return *a < *b ? -1 : *a > *b; -} - -/* Returns a pointer to the first occurrence of CH in the first - SIZE bytes starting at BLOCK. Returns a null pointer if CH - does not occur in BLOCK. */ -void * -memchr (const void *block_, int ch_, size_t size) -{ - const unsigned char *block = block_; - unsigned char ch = ch_; - - ASSERT (block != NULL || size == 0); - - for (; size-- > 0; block++) - if (*block == ch) - return (void *) block; - - return NULL; -} - -/* Finds and returns the first occurrence of C in STRING, or a - null pointer if C does not appear in STRING. If C == '\0' - then returns a pointer to the null terminator at the end of - STRING. */ -char * -strchr (const char *string, int c_) -{ - char c = c_; - - ASSERT (string != NULL); - - for (;;) - if (*string == c) - return (char *) string; - else if (*string == '\0') - return NULL; - else - string++; -} - -/* Returns the length of the initial substring of STRING that - consists of characters that are not in STOP. */ -size_t -strcspn (const char *string, const char *stop) -{ - size_t length; - - for (length = 0; string[length] != '\0'; length++) - if (strchr (stop, string[length]) != NULL) - break; - return length; -} - -/* Returns a pointer to the first character in STRING that is - also in STOP. If no character in STRING is in STOP, returns a - null pointer. */ -char * -strpbrk (const char *string, const char *stop) -{ - for (; *string != '\0'; string++) - if (strchr (stop, *string) != NULL) - return (char *) string; - return NULL; -} - -/* Returns a pointer to the last occurrence of C in STRING. - Returns a null pointer if C does not occur in STRING. */ -char * -strrchr (const char *string, int c_) -{ - char c = c_; - const char *p = NULL; - - for (; *string != '\0'; string++) - if (*string == c) - p = string; - return (char *) p; -} - -/* Returns the length of the initial substring of STRING that - consists of characters in SKIP. */ -size_t -strspn (const char *string, const char *skip) -{ - size_t length; - - for (length = 0; string[length] != '\0'; length++) - if (strchr (skip, string[length]) == NULL) - break; - return length; -} - -/* Returns a pointer to the first occurrence of NEEDLE within - HAYSTACK. Returns a null pointer if NEEDLE does not exist - within HAYSTACK. */ -char * -strstr (const char *haystack, const char *needle) -{ - size_t haystack_len = strlen (haystack); - size_t needle_len = strlen (needle); - - if (haystack_len >= needle_len) - { - size_t i; - - for (i = 0; i <= haystack_len - needle_len; i++) - if (!memcmp (haystack + i, needle, needle_len)) - return (char *) haystack + i; - } - - return NULL; -} - -/* Breaks a string into tokens separated by DELIMITERS. The - first time this function is called, S should be the string to - tokenize, and in subsequent calls it must be a null pointer. - SAVE_PTR is the address of a `char *' variable used to keep - track of the tokenizer's position. The return value each time - is the next token in the string, or a null pointer if no - tokens remain. - - This function treats multiple adjacent delimiters as a single - delimiter. The returned tokens will never be length 0. - DELIMITERS may change from one call to the next within a - single string. - - strtok_r() modifies the string S, changing delimiters to null - bytes. Thus, S must be a modifiable string. String literals, - in particular, are *not* modifiable in C, even though for - backward compatibility they are not `const'. - - Example usage: - - char s[] = " String to tokenize. "; - char *token, *save_ptr; - - for (token = strtok_r (s, " ", &save_ptr); token != NULL; - token = strtok_r (NULL, " ", &save_ptr)) - printf ("'%s'\n", token); - - outputs: - - 'String' - 'to' - 'tokenize.' -*/ -char * -strtok_r (char *s, const char *delimiters, char **save_ptr) -{ - char *token; - - ASSERT (delimiters != NULL); - ASSERT (save_ptr != NULL); - - /* If S is nonnull, start from it. - If S is null, start from saved position. */ - if (s == NULL) - s = *save_ptr; - ASSERT (s != NULL); - - /* Skip any DELIMITERS at our current position. */ - while (strchr (delimiters, *s) != NULL) - { - /* strchr() will always return nonnull if we're searching - for a null byte, because every string contains a null - byte (at the end). */ - if (*s == '\0') - { - *save_ptr = s; - return NULL; - } - - s++; - } - - /* Skip any non-DELIMITERS up to the end of the string. */ - token = s; - while (strchr (delimiters, *s) == NULL) - s++; - if (*s != '\0') - { - *s = '\0'; - *save_ptr = s + 1; - } - else - *save_ptr = s; - return token; -} - -/* Sets the SIZE bytes in DST to VALUE. */ -void * -memset (void *dst_, int value, size_t size) -{ - unsigned char *dst = dst_; - - ASSERT (dst != NULL || size == 0); - - while (size-- > 0) - *dst++ = value; - - return dst_; -} - -/* Returns the length of STRING. */ -size_t -strlen (const char *string) -{ - const char *p; - - ASSERT (string != NULL); - - for (p = string; *p != '\0'; p++) - continue; - return p - string; -} - -/* If STRING is less than MAXLEN characters in length, returns - its actual length. Otherwise, returns MAXLEN. */ -size_t -strnlen (const char *string, size_t maxlen) -{ - size_t length; - - for (length = 0; string[length] != '\0' && length < maxlen; length++) - continue; - return length; -} - -/* Copies string SRC to DST. If SRC is longer than SIZE - 1 - characters, only SIZE - 1 characters are copied. A null - terminator is always written to DST, unless SIZE is 0. - Returns the length of SRC, not including the null terminator. - - strlcpy() is not in the standard C library, but it is an - increasingly popular extension. See - http://www.courtesan.com/todd/papers/strlcpy.html for - information on strlcpy(). */ -size_t -strlcpy (char *dst, const char *src, size_t size) -{ - size_t src_len; - - ASSERT (dst != NULL); - ASSERT (src != NULL); - - src_len = strlen (src); - if (size > 0) - { - size_t dst_len = size - 1; - if (src_len < dst_len) - dst_len = src_len; - memcpy (dst, src, dst_len); - dst[dst_len] = '\0'; - } - return src_len; -} - -/* Concatenates string SRC to DST. The concatenated string is - limited to SIZE - 1 characters. A null terminator is always - written to DST, unless SIZE is 0. Returns the length that the - concatenated string would have assuming that there was - sufficient space, not including a null terminator. - - strlcat() is not in the standard C library, but it is an - increasingly popular extension. See - http://www.courtesan.com/todd/papers/strlcpy.html for - information on strlcpy(). */ -size_t -strlcat (char *dst, const char *src, size_t size) -{ - size_t src_len, dst_len; - - ASSERT (dst != NULL); - ASSERT (src != NULL); - - src_len = strlen (src); - dst_len = strlen (dst); - if (size > 0 && dst_len < size) - { - size_t copy_cnt = size - dst_len - 1; - if (src_len < copy_cnt) - copy_cnt = src_len; - memcpy (dst + dst_len, src, copy_cnt); - dst[dst_len + copy_cnt] = '\0'; - } - return src_len + dst_len; -} - diff --git a/src/lib/string.h b/src/lib/string.h deleted file mode 100644 index 1fff82a060c32080a99810c4d9413dc97a441910..0000000000000000000000000000000000000000 --- a/src/lib/string.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __LIB_STRING_H -#define __LIB_STRING_H - -#include <stddef.h> - -/* Standard. */ -void *memcpy (void *, const void *, size_t); -void *memmove (void *, const void *, size_t); -char *strncat (char *, const char *, size_t); -int memcmp (const void *, const void *, size_t); -int strcmp (const char *, const char *); -void *memchr (const void *, int, size_t); -char *strchr (const char *, int); -size_t strcspn (const char *, const char *); -char *strpbrk (const char *, const char *); -char *strrchr (const char *, int); -size_t strspn (const char *, const char *); -char *strstr (const char *, const char *); -void *memset (void *, int, size_t); -size_t strlen (const char *); - -/* Extensions. */ -size_t strlcpy (char *, const char *, size_t); -size_t strlcat (char *, const char *, size_t); -char *strtok_r (char *, const char *, char **); -size_t strnlen (const char *, size_t); - -/* Try to be helpful. */ -#define strcpy dont_use_strcpy_use_strlcpy -#define strncpy dont_use_strncpy_use_strlcpy -#define strcat dont_use_strcat_use_strlcat -#define strncat dont_use_strncat_use_strlcat -#define strtok dont_use_strtok_use_strtok_r - -#endif /* lib/string.h */ diff --git a/src/lib/syscall-nr.h b/src/lib/syscall-nr.h deleted file mode 100644 index 21a7af952f8728f93b77d6867ebbf60a7699864c..0000000000000000000000000000000000000000 --- a/src/lib/syscall-nr.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __LIB_SYSCALL_NR_H -#define __LIB_SYSCALL_NR_H - -/* System call numbers. */ -enum - { - /* Projects 2 and later. */ - SYS_HALT, /* Halt the operating system. */ - SYS_EXIT, /* Terminate this process. */ - SYS_EXEC, /* Start another process. */ - SYS_WAIT, /* Wait for a child process to die. */ - SYS_CREATE, /* Create a file. */ - SYS_REMOVE, /* Delete a file. */ - SYS_OPEN, /* Open a file. */ - SYS_FILESIZE, /* Obtain a file's size. */ - SYS_READ, /* Read from a file. */ - SYS_WRITE, /* Write to a file. */ - SYS_SEEK, /* Change position in a file. */ - SYS_TELL, /* Report current position in a file. */ - SYS_CLOSE, /* Close a file. */ - - /* Project 3 and optionally project 4. */ - SYS_MMAP, /* Map a file into memory. */ - SYS_MUNMAP, /* Remove a memory mapping. */ - - /* Project 4 only. */ - SYS_CHDIR, /* Change the current directory. */ - SYS_MKDIR, /* Create a directory. */ - SYS_READDIR, /* Reads a directory entry. */ - SYS_ISDIR, /* Tests if a fd represents a directory. */ - SYS_INUMBER /* Returns the inode number for a fd. */ - }; - -#endif /* lib/syscall-nr.h */ diff --git a/src/lib/user/console.c b/src/lib/user/console.c deleted file mode 100644 index 22bdc8c8b23dbd4a4b70df662738cb7c282ce7a1..0000000000000000000000000000000000000000 --- a/src/lib/user/console.c +++ /dev/null @@ -1,94 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <syscall.h> -#include <syscall-nr.h> - -/* The standard vprintf() function, - which is like printf() but uses a va_list. */ -int -vprintf (const char *format, va_list args) -{ - return vhprintf (STDOUT_FILENO, format, args); -} - -/* Like printf(), but writes output to the given HANDLE. */ -int -hprintf (int handle, const char *format, ...) -{ - va_list args; - int retval; - - va_start (args, format); - retval = vhprintf (handle, format, args); - va_end (args); - - return retval; -} - -/* Writes string S to the console, followed by a new-line - character. */ -int -puts (const char *s) -{ - write (STDOUT_FILENO, s, strlen (s)); - putchar ('\n'); - - return 0; -} - -/* Writes C to the console. */ -int -putchar (int c) -{ - char c2 = c; - write (STDOUT_FILENO, &c2, 1); - return c; -} - -/* Auxiliary data for vhprintf_helper(). */ -struct vhprintf_aux - { - char buf[64]; /* Character buffer. */ - char *p; /* Current position in buffer. */ - int char_cnt; /* Total characters written so far. */ - int handle; /* Output file handle. */ - }; - -static void add_char (char, void *); -static void flush (struct vhprintf_aux *); - -/* Formats the printf() format specification FORMAT with - arguments given in ARGS and writes the output to the given - HANDLE. */ -int -vhprintf (int handle, const char *format, va_list args) -{ - struct vhprintf_aux aux; - aux.p = aux.buf; - aux.char_cnt = 0; - aux.handle = handle; - __vprintf (format, args, add_char, &aux); - flush (&aux); - return aux.char_cnt; -} - -/* Adds C to the buffer in AUX, flushing it if the buffer fills - up. */ -static void -add_char (char c, void *aux_) -{ - struct vhprintf_aux *aux = aux_; - *aux->p++ = c; - if (aux->p >= aux->buf + sizeof aux->buf) - flush (aux); - aux->char_cnt++; -} - -/* Flushes the buffer in AUX. */ -static void -flush (struct vhprintf_aux *aux) -{ - if (aux->p > aux->buf) - write (aux->handle, aux->buf, aux->p - aux->buf); - aux->p = aux->buf; -} diff --git a/src/lib/user/debug.c b/src/lib/user/debug.c deleted file mode 100644 index f49b8749bd0fae9336fca588f0044d8ebeac6374..0000000000000000000000000000000000000000 --- a/src/lib/user/debug.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <debug.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdio.h> -#include <syscall.h> - -/* Aborts the user program, printing the source file name, line - number, and function name, plus a user-specific message. */ -void -debug_panic (const char *file, int line, const char *function, - const char *message, ...) -{ - va_list args; - - printf ("User process ABORT at %s:%d in %s(): ", file, line, function); - - va_start (args, message); - vprintf (message, args); - printf ("\n"); - va_end (args); - - debug_backtrace (); - - exit (1); -} diff --git a/src/lib/user/entry.c b/src/lib/user/entry.c deleted file mode 100644 index a707c70ae8bfb075b0ef37f3b4100a0be1b26133..0000000000000000000000000000000000000000 --- a/src/lib/user/entry.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <syscall.h> - -int main (int, char *[]); -void _start (int argc, char *argv[]); - -void -_start (int argc, char *argv[]) -{ - exit (main (argc, argv)); -} diff --git a/src/lib/user/stdio.h b/src/lib/user/stdio.h deleted file mode 100644 index b9f3cc6c96e2246d04703796ec05417d5e26b1a8..0000000000000000000000000000000000000000 --- a/src/lib/user/stdio.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __LIB_USER_STDIO_H -#define __LIB_USER_STDIO_H - -int hprintf (int, const char *, ...) PRINTF_FORMAT (2, 3); -int vhprintf (int, const char *, va_list) PRINTF_FORMAT (2, 0); - -#endif /* lib/user/stdio.h */ diff --git a/src/lib/user/syscall.c b/src/lib/user/syscall.c deleted file mode 100644 index c8385bc3364b1eabc57e68bae885fe458537b42a..0000000000000000000000000000000000000000 --- a/src/lib/user/syscall.c +++ /dev/null @@ -1,184 +0,0 @@ -#include <syscall.h> -#include "../syscall-nr.h" - -/* Invokes syscall NUMBER, passing no arguments, and returns the - return value as an `int'. */ -#define syscall0(NUMBER) \ - ({ \ - int retval; \ - asm volatile \ - ("pushl %[number]; int $0x30; addl $4, %%esp" \ - : "=a" (retval) \ - : [number] "i" (NUMBER) \ - : "memory"); \ - retval; \ - }) - -/* Invokes syscall NUMBER, passing argument ARG0, and returns the - return value as an `int'. */ -#define syscall1(NUMBER, ARG0) \ - ({ \ - int retval; \ - asm volatile \ - ("pushl %[arg0]; pushl %[number]; int $0x30; addl $8, %%esp" \ - : "=a" (retval) \ - : [number] "i" (NUMBER), \ - [arg0] "g" (ARG0) \ - : "memory"); \ - retval; \ - }) - -/* Invokes syscall NUMBER, passing arguments ARG0 and ARG1, and - returns the return value as an `int'. */ -#define syscall2(NUMBER, ARG0, ARG1) \ - ({ \ - int retval; \ - asm volatile \ - ("pushl %[arg1]; pushl %[arg0]; " \ - "pushl %[number]; int $0x30; addl $12, %%esp" \ - : "=a" (retval) \ - : [number] "i" (NUMBER), \ - [arg0] "r" (ARG0), \ - [arg1] "r" (ARG1) \ - : "memory"); \ - retval; \ - }) - -/* Invokes syscall NUMBER, passing arguments ARG0, ARG1, and - ARG2, and returns the return value as an `int'. */ -#define syscall3(NUMBER, ARG0, ARG1, ARG2) \ - ({ \ - int retval; \ - asm volatile \ - ("pushl %[arg2]; pushl %[arg1]; pushl %[arg0]; " \ - "pushl %[number]; int $0x30; addl $16, %%esp" \ - : "=a" (retval) \ - : [number] "i" (NUMBER), \ - [arg0] "r" (ARG0), \ - [arg1] "r" (ARG1), \ - [arg2] "r" (ARG2) \ - : "memory"); \ - retval; \ - }) - -void -halt (void) -{ - syscall0 (SYS_HALT); - NOT_REACHED (); -} - -void -exit (int status) -{ - syscall1 (SYS_EXIT, status); - NOT_REACHED (); -} - -pid_t -exec (const char *file) -{ - return (pid_t) syscall1 (SYS_EXEC, file); -} - -int -wait (pid_t pid) -{ - return syscall1 (SYS_WAIT, pid); -} - -bool -create (const char *file, unsigned initial_size) -{ - return syscall2 (SYS_CREATE, file, initial_size); -} - -bool -remove (const char *file) -{ - return syscall1 (SYS_REMOVE, file); -} - -int -open (const char *file) -{ - return syscall1 (SYS_OPEN, file); -} - -int -filesize (int fd) -{ - return syscall1 (SYS_FILESIZE, fd); -} - -int -read (int fd, void *buffer, unsigned size) -{ - return syscall3 (SYS_READ, fd, buffer, size); -} - -int -write (int fd, const void *buffer, unsigned size) -{ - return syscall3 (SYS_WRITE, fd, buffer, size); -} - -void -seek (int fd, unsigned position) -{ - syscall2 (SYS_SEEK, fd, position); -} - -unsigned -tell (int fd) -{ - return syscall1 (SYS_TELL, fd); -} - -void -close (int fd) -{ - syscall1 (SYS_CLOSE, fd); -} - -mapid_t -mmap (int fd, void *addr) -{ - return syscall2 (SYS_MMAP, fd, addr); -} - -void -munmap (mapid_t mapid) -{ - syscall1 (SYS_MUNMAP, mapid); -} - -bool -chdir (const char *dir) -{ - return syscall1 (SYS_CHDIR, dir); -} - -bool -mkdir (const char *dir) -{ - return syscall1 (SYS_MKDIR, dir); -} - -bool -readdir (int fd, char name[READDIR_MAX_LEN + 1]) -{ - return syscall2 (SYS_READDIR, fd, name); -} - -bool -isdir (int fd) -{ - return syscall1 (SYS_ISDIR, fd); -} - -int -inumber (int fd) -{ - return syscall1 (SYS_INUMBER, fd); -} diff --git a/src/lib/user/syscall.h b/src/lib/user/syscall.h deleted file mode 100644 index 8a9e0c013e91a74bb87b318b7f2f3f094c341bd6..0000000000000000000000000000000000000000 --- a/src/lib/user/syscall.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __LIB_USER_SYSCALL_H -#define __LIB_USER_SYSCALL_H - -#include <stdbool.h> -#include <debug.h> - -/* Process identifier. */ -typedef int pid_t; -#define PID_ERROR ((pid_t) -1) - -/* Map region identifier. */ -typedef int mapid_t; -#define MAP_FAILED ((mapid_t) -1) - -/* Maximum characters in a filename written by readdir(). */ -#define READDIR_MAX_LEN 14 - -/* Typical return values from main() and arguments to exit(). */ -#define EXIT_SUCCESS 0 /* Successful execution. */ -#define EXIT_FAILURE 1 /* Unsuccessful execution. */ - -/* Projects 2 and later. */ -void halt (void) NO_RETURN; -void exit (int status) NO_RETURN; -pid_t exec (const char *file); -int wait (pid_t); -bool create (const char *file, unsigned initial_size); -bool remove (const char *file); -int open (const char *file); -int filesize (int fd); -int read (int fd, void *buffer, unsigned length); -int write (int fd, const void *buffer, unsigned length); -void seek (int fd, unsigned position); -unsigned tell (int fd); -void close (int fd); - -/* Project 3 and optionally project 4. */ -mapid_t mmap (int fd, void *addr); -void munmap (mapid_t); - -/* Project 4 only. */ -bool chdir (const char *dir); -bool mkdir (const char *dir); -bool readdir (int fd, char name[READDIR_MAX_LEN + 1]); -bool isdir (int fd); -int inumber (int fd); - -#endif /* lib/user/syscall.h */ diff --git a/src/lib/user/user.lds b/src/lib/user/user.lds deleted file mode 100644 index cc6d6c03a60791071ba91663cfdaaebee67dbb78..0000000000000000000000000000000000000000 --- a/src/lib/user/user.lds +++ /dev/null @@ -1,57 +0,0 @@ -OUTPUT_FORMAT("elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(_start) - -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - __executable_start = 0x08048000 + SIZEOF_HEADERS; - . = 0x08048000 + SIZEOF_HEADERS; - .text : { *(.text) } = 0x90 - .rodata : { *(.rodata) } - - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); - . = DATA_SEGMENT_ALIGN (0x1000, 0x1000); - - .data : { *(.data) } - .bss : { *(.bss) } - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /DISCARD/ : { *(.note.GNU-stack) } - /DISCARD/ : { *(.eh_frame) } -} diff --git a/src/lib/ustar.c b/src/lib/ustar.c deleted file mode 100644 index 49af69a1116fb738b275acfcd6c3ceba39049b25..0000000000000000000000000000000000000000 --- a/src/lib/ustar.c +++ /dev/null @@ -1,228 +0,0 @@ -#include <ustar.h> -#include <limits.h> -#include <packed.h> -#include <stdio.h> -#include <string.h> - -/* Header for ustar-format tar archive. See the documentation of - the "pax" utility in [SUSv3] for the the "ustar" format - specification. */ -struct ustar_header - { - char name[100]; /* File name. Null-terminated if room. */ - char mode[8]; /* Permissions as octal string. */ - char uid[8]; /* User ID as octal string. */ - char gid[8]; /* Group ID as octal string. */ - char size[12]; /* File size in bytes as octal string. */ - char mtime[12]; /* Modification time in seconds - from Jan 1, 1970, as octal string. */ - char chksum[8]; /* Sum of octets in header as octal string. */ - char typeflag; /* An enum ustar_type value. */ - char linkname[100]; /* Name of link target. - Null-terminated if room. */ - char magic[6]; /* "ustar\0" */ - char version[2]; /* "00" */ - char uname[32]; /* User name, always null-terminated. */ - char gname[32]; /* Group name, always null-terminated. */ - char devmajor[8]; /* Device major number as octal string. */ - char devminor[8]; /* Device minor number as octal string. */ - char prefix[155]; /* Prefix to file name. - Null-terminated if room. */ - char padding[12]; /* Pad to 512 bytes. */ - } -PACKED; - -/* Returns the checksum for the given ustar format HEADER. */ -static unsigned int -calculate_chksum (const struct ustar_header *h) -{ - const uint8_t *header = (const uint8_t *) h; - unsigned int chksum; - size_t i; - - chksum = 0; - for (i = 0; i < USTAR_HEADER_SIZE; i++) - { - /* The ustar checksum is calculated as if the chksum field - were all spaces. */ - const size_t chksum_start = offsetof (struct ustar_header, chksum); - const size_t chksum_end = chksum_start + sizeof h->chksum; - bool in_chksum_field = i >= chksum_start && i < chksum_end; - chksum += in_chksum_field ? ' ' : header[i]; - } - return chksum; -} - -/* Drop possibly dangerous prefixes from FILE_NAME and return the - stripped name. An archive with file names that start with "/" - or "../" could cause a naive tar extractor to write to - arbitrary parts of the file system, not just the destination - directory. We don't want to create such archives or be such a - naive extractor. - - The return value can be a suffix of FILE_NAME or a string - literal. */ -static const char * -strip_antisocial_prefixes (const char *file_name) -{ - while (*file_name == '/' - || !memcmp (file_name, "./", 2) - || !memcmp (file_name, "../", 3)) - file_name = strchr (file_name, '/') + 1; - return *file_name == '\0' || !strcmp (file_name, "..") ? "." : file_name; -} - -/* Composes HEADER as a USTAR_HEADER_SIZE (512)-byte archive - header in ustar format for a SIZE-byte file named FILE_NAME of - the given TYPE. The caller is responsible for writing the - header to a file or device. - - If successful, returns true. On failure (due to an - excessively long file name), returns false. */ -bool -ustar_make_header (const char *file_name, enum ustar_type type, - int size, char header[USTAR_HEADER_SIZE]) -{ - struct ustar_header *h = (struct ustar_header *) header; - - ASSERT (sizeof (struct ustar_header) == USTAR_HEADER_SIZE); - ASSERT (type == USTAR_REGULAR || type == USTAR_DIRECTORY); - - /* Check file name. */ - file_name = strip_antisocial_prefixes (file_name); - if (strlen (file_name) > 99) - { - printf ("%s: file name too long\n", file_name); - return false; - } - - /* Fill in header except for final checksum. */ - memset (h, 0, sizeof *h); - strlcpy (h->name, file_name, sizeof h->name); - snprintf (h->mode, sizeof h->mode, "%07o", - type == USTAR_REGULAR ? 0644 : 0755); - strlcpy (h->uid, "0000000", sizeof h->uid); - strlcpy (h->gid, "0000000", sizeof h->gid); - snprintf (h->size, sizeof h->size, "%011o", size); - snprintf (h->mtime, sizeof h->size, "%011o", 1136102400); - h->typeflag = type; - strlcpy (h->magic, "ustar", sizeof h->magic); - h->version[0] = h->version[1] = '0'; - strlcpy (h->gname, "root", sizeof h->gname); - strlcpy (h->uname, "root", sizeof h->uname); - - /* Compute and fill in final checksum. */ - snprintf (h->chksum, sizeof h->chksum, "%07o", calculate_chksum (h)); - - return true; -} - -/* Parses a SIZE-byte octal field in S in the format used by - ustar format. If successful, stores the field's value in - *VALUE and returns true; on failure, returns false. - - ustar octal fields consist of a sequence of octal digits - terminated by a space or a null byte. The ustar specification - seems ambiguous as to whether these fields must be padded on - the left with '0's, so we accept any field that fits in the - available space, regardless of whether it fills the space. */ -static bool -parse_octal_field (const char *s, size_t size, unsigned long int *value) -{ - size_t ofs; - - *value = 0; - for (ofs = 0; ofs < size; ofs++) - { - char c = s[ofs]; - if (c >= '0' && c <= '7') - { - if (*value > ULONG_MAX / 8) - { - /* Overflow. */ - return false; - } - *value = c - '0' + *value * 8; - } - else if (c == ' ' || c == '\0') - { - /* End of field, but disallow completely empty - fields. */ - return ofs > 0; - } - else - { - /* Bad character. */ - return false; - } - } - - /* Field did not end in space or null byte. */ - return false; -} - -/* Returns true if the CNT bytes starting at BLOCK are all zero, - false otherwise. */ -static bool -is_all_zeros (const char *block, size_t cnt) -{ - while (cnt-- > 0) - if (*block++ != 0) - return false; - return true; -} - -/* Parses HEADER as a ustar-format archive header for a regular - file or directory. If successful, stores the archived file's - name in *FILE_NAME (as a pointer into HEADER or a string - literal), its type in *TYPE, and its size in bytes in *SIZE, - and returns a null pointer. On failure, returns a - human-readable error message. */ -const char * -ustar_parse_header (const char header[USTAR_HEADER_SIZE], - const char **file_name, enum ustar_type *type, int *size) -{ - const struct ustar_header *h = (const struct ustar_header *) header; - unsigned long int chksum, size_ul; - - ASSERT (sizeof (struct ustar_header) == USTAR_HEADER_SIZE); - - /* Detect end of archive. */ - if (is_all_zeros (header, USTAR_HEADER_SIZE)) - { - *file_name = NULL; - *type = USTAR_EOF; - *size = 0; - return NULL; - } - - /* Validate ustar header. */ - if (memcmp (h->magic, "ustar", 6)) - return "not a ustar archive"; - else if (h->version[0] != '0' || h->version[1] != '0') - return "invalid ustar version"; - else if (!parse_octal_field (h->chksum, sizeof h->chksum, &chksum)) - return "corrupt chksum field"; - else if (chksum != calculate_chksum (h)) - return "checksum mismatch"; - else if (h->name[sizeof h->name - 1] != '\0' || h->prefix[0] != '\0') - return "file name too long"; - else if (h->typeflag != USTAR_REGULAR && h->typeflag != USTAR_DIRECTORY) - return "unimplemented file type"; - if (h->typeflag == USTAR_REGULAR) - { - if (!parse_octal_field (h->size, sizeof h->size, &size_ul)) - return "corrupt file size field"; - else if (size_ul > INT_MAX) - return "file too large"; - } - else - size_ul = 0; - - /* Success. */ - *file_name = strip_antisocial_prefixes (h->name); - *type = h->typeflag; - *size = size_ul; - return NULL; -} - diff --git a/src/lib/ustar.h b/src/lib/ustar.h deleted file mode 100644 index 43a5513535e39a282ee53f38207c3a1f9c5221c5..0000000000000000000000000000000000000000 --- a/src/lib/ustar.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __LIB_USTAR_H -#define __LIB_USTAR_H - -/* Support for the standard Posix "ustar" format. See the - documentation of the "pax" utility in [SUSv3] for the the - "ustar" format specification. */ - -#include <stdbool.h> - -/* Type of a file entry in an archive. - The values here are the bytes that appear in the file format. - Only types of interest to Pintos are listed here. */ -enum ustar_type - { - USTAR_REGULAR = '0', /* Ordinary file. */ - USTAR_DIRECTORY = '5', /* Directory. */ - USTAR_EOF = -1 /* End of archive (not an official value). */ - }; - -/* Size of a ustar archive header, in bytes. */ -#define USTAR_HEADER_SIZE 512 - -bool ustar_make_header (const char *file_name, enum ustar_type, - int size, char header[USTAR_HEADER_SIZE]); -const char *ustar_parse_header (const char header[USTAR_HEADER_SIZE], - const char **file_name, - enum ustar_type *, int *size); - -#endif /* lib/ustar.h */ diff --git a/src/misc/bochs-2.2.6-big-endian.patch b/src/misc/bochs-2.2.6-big-endian.patch deleted file mode 100644 index 420f69b5d5ed3052d1435f4f1ca9cb3ac6aa76fa..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-big-endian.patch +++ /dev/null @@ -1,63 +0,0 @@ -diff -urp bochs-2.2.6/gdbstub.cc bochs-2.2.6.orig/gdbstub.cc ---- bochs-2.2.6.orig/gdbstub.cc 2006-01-17 09:15:29.000000000 -0800 -+++ bochs-2.2.6/gdbstub.cc 2006-04-03 13:47:39.000000000 -0700 -@@ -672,35 +672,36 @@ - - case 'g': - #if !BX_SUPPORT_X86_64 -- registers[0] = EAX; -- registers[1] = ECX; -- registers[2] = EDX; -- registers[3] = EBX; -- registers[4] = ESP; -- registers[5] = EBP; -- registers[6] = ESI; -- registers[7] = EDI; -+ WriteHostDWordToLittleEndian(registers + 0, EAX); -+ WriteHostDWordToLittleEndian(registers + 1, ECX); -+ WriteHostDWordToLittleEndian(registers + 2, EDX); -+ WriteHostDWordToLittleEndian(registers + 3, EBX); -+ WriteHostDWordToLittleEndian(registers + 4, ESP); -+ WriteHostDWordToLittleEndian(registers + 5, EBP); -+ WriteHostDWordToLittleEndian(registers + 6, ESI); -+ WriteHostDWordToLittleEndian(registers + 7, EDI); - if (last_stop_reason == GDBSTUB_EXECUTION_BREAKPOINT) - { -- registers[8] = EIP + 1; -+ WriteHostDWordToLittleEndian(registers + 8, EIP + 1); - } - else - { -- registers[8] = EIP; -+ WriteHostDWordToLittleEndian(registers + 8, EIP); - } -- registers[9] = BX_CPU_THIS_PTR read_eflags(); -- registers[10] = -- BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value; -- registers[11] = -- BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value; -- registers[12] = -- BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value; -- registers[13] = -- BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value; -- registers[14] = -- BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value; -- registers[15] = -- BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value; -+ WriteHostDWordToLittleEndian(registers + 9, -+ BX_CPU_THIS_PTR read_eflags()); -+ WriteHostDWordToLittleEndian(registers + 10, -+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); -+ WriteHostDWordToLittleEndian(registers + 11, -+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value); -+ WriteHostDWordToLittleEndian(registers + 12, -+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value); -+ WriteHostDWordToLittleEndian(registers + 13, -+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value); -+ WriteHostDWordToLittleEndian(registers + 14, -+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value); -+ WriteHostDWordToLittleEndian(registers + 15, -+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value); - mem2hex((char *)registers, obuf, NUMREGSBYTES); - #else - #define PUTREG(buf, val, len) do { \ diff --git a/src/misc/bochs-2.2.6-build.sh b/src/misc/bochs-2.2.6-build.sh deleted file mode 100755 index befe3b4c922f42386ea98c43e441bf2cff72df71..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-build.sh +++ /dev/null @@ -1,41 +0,0 @@ -#! /bin/sh -e - -if test -z "$SRCDIR" || test -z "$PINTOSDIR" || test -z "$DSTDIR"; then - echo "usage: env SRCDIR=<srcdir> PINTOSDIR=<srcdir> DSTDIR=<dstdir> sh $0" - echo " where <srcdir> contains bochs-2.2.6.tar.gz" - echo " and <pintosdir> is the root of the pintos source tree" - echo " and <dstdir> is the installation prefix (e.g. /usr/local)" - exit 1 -fi - -cd /tmp -mkdir $$ -cd $$ -mkdir bochs-2.2.6 -tar xzf $SRCDIR/bochs-2.2.6.tar.gz -cd bochs-2.2.6 -cat $PINTOSDIR/src/misc/bochs-2.2.6-ms-extensions.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-big-endian.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-jitter.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-triple-fault.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-solaris-tty.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-page-fault-segv.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-paranoia.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-gdbstub-ENN.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.2.6-namespace.patch | patch -p1 -if test "`uname -s`" = "SunOS"; then - cat $PINTOSDIR/src/misc/bochs-2.2.6-solaris-link.patch | patch -p1 -fi -CFGOPTS="--with-x --with-x11 --with-term --with-nogui --prefix=$DSTDIR --enable-cpu-level=6" -mkdir plain && - cd plain && - ../configure $CFGOPTS --enable-gdb-stub && - make && - make install && - cd .. -mkdir with-dbg && - cd with-dbg && - ../configure --enable-debugger $CFGOPTS && - make && - cp bochs $DSTDIR/bin/bochs-dbg && - cd .. diff --git a/src/misc/bochs-2.2.6-gdbstub-ENN.patch b/src/misc/bochs-2.2.6-gdbstub-ENN.patch deleted file mode 100644 index 88a814562cb6366db6f708736545592ab9cd045b..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-gdbstub-ENN.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- bochs-2.2.6/gdbstub.cc 2006-01-17 12:15:29.000000000 -0500 -+++ bochs-2.2.6-patched/gdbstub.cc 2007-02-06 23:04:51.095523904 -0500 -@@ -515,7 +515,7 @@ - } - else - { -- put_reply("ENN"); -+ put_reply("Eff"); - } - } - break; -@@ -761,7 +761,7 @@ - } - else - { -- put_reply("ENN"); -+ put_reply("Eff"); - } - break; - -@@ -782,7 +782,7 @@ - } - else - { -- put_reply("ENN"); -+ put_reply("Eff"); - } - break; - diff --git a/src/misc/bochs-2.2.6-jitter.patch b/src/misc/bochs-2.2.6-jitter.patch deleted file mode 100644 index 48917e06b1a638f7b424938753302f22d0a6dfd3..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-jitter.patch +++ /dev/null @@ -1,61 +0,0 @@ -diff -urp bochs-2.2.6/iodev/pit82c54.cc bochs-2.2.6.orig/iodev/pit82c54.cc ---- bochs-2.2.6.orig/iodev/pit82c54.cc 2006-01-08 12:39:08.000000000 -0800 -+++ bochs-2.2.6/iodev/pit82c54.cc 2006-04-03 14:00:27.000000000 -0700 -@@ -28,6 +28,7 @@ - - #include "iodev.h" - #include "pit82c54.h" -+#include <stdlib.h> - #define LOG_THIS this-> - - -@@ -359,7 +360,13 @@ - case 2: - if(thisctr.count_written) { - if(thisctr.triggerGATE || thisctr.first_pass) { -- set_count(thisctr, thisctr.inlatch); -+ unsigned n = thisctr.inlatch; -+ if (jitter && n > 5) { -+ n *= (double) rand() / RAND_MAX; -+ if (n < 5) -+ n = 5; -+ } -+ set_count(thisctr, n); - thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; - thisctr.null_count=0; - if(thisctr.inlatch==1) { -diff -urp bochs-2.2.6/main.cc bochs-2.2.6.orig/main.cc ---- bochs-2.2.6.orig/main.cc 2006-01-22 04:31:15.000000000 -0800 -+++ bochs-2.2.6/main.cc 2006-04-03 14:00:54.000000000 -0700 -@@ -105,6 +105,7 @@ - #endif - - char *bochsrc_filename = NULL; -+int jitter = 0; - - void bx_print_header () - { -@@ -459,6 +460,13 @@ - else if (!strcmp ("-q", argv[arg])) { - SIM->get_param_enum(BXP_BOCHS_START)->set (BX_QUICK_START); - } -+ else if (!strcmp ("-j", argv[arg])) { -+ if (++arg >= argc) BX_PANIC(("-j must be followed by a number")); -+ else { -+ jitter = 1; -+ srand (atoi (argv[arg])); -+ } -+ } - else if (!strcmp ("-f", argv[arg])) { - if (++arg >= argc) BX_PANIC(("-f must be followed by a filename")); - else bochsrc_filename = argv[arg]; -diff -up /home/blp/cs140/bochs-2.2.6/bochs.h\~ /home/blp/cs140/bochs-2.2.6/bochs.h ---- bochs-2.2.6/bochs.h.orig 2006-01-28 08:16:02.000000000 -0800 -+++ bochs-2.2.6/bochs.h 2006-04-03 14:03:54.000000000 -0700 -@@ -698,4 +698,6 @@ int bx_init_hardware (); - - #endif - -+extern int jitter; -+ - #endif /* BX_BOCHS_H */ diff --git a/src/misc/bochs-2.2.6-ms-extensions.patch b/src/misc/bochs-2.2.6-ms-extensions.patch deleted file mode 100644 index a6e50a0aa48a782383b1d6a2b0dcc1817ec1c4cc..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-ms-extensions.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -urp orig/bochs-2.1.1/gui/Makefile.in bochs-2.1.1/gui/Makefile.in ---- orig/bochs-2.1.1/gui/Makefile.in 2003-11-28 07:07:28.000000000 -0800 -+++ bochs-2.1.1/gui/Makefile.in 2004-09-13 15:05:09.402039000 -0700 -@@ -44,7 +44,7 @@ SHELL = /bin/sh - @SET_MAKE@ - - CXX = @CXX@ --CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ -+CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ -fms-extensions - LOCAL_CXXFLAGS = - LDFLAGS = @LDFLAGS@ - LIBS = @LIBS@ - - diff --git a/src/misc/bochs-2.2.6-namespace.patch b/src/misc/bochs-2.2.6-namespace.patch deleted file mode 100644 index 5f0381466d2bd56b55f75f911b5f04dc9bc23e48..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-namespace.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- bochs-2.2.6/bx_debug/symbols.cc 2011-08-19 11:04:11.760139836 -0600 -+++ bochs-2.2.6-patched/bx_debug/symbols.cc 2011-08-19 11:04:04.980139837 -0600 -@@ -92,6 +92,7 @@ - #endif - - using namespace std; -+namespace std { using namespace __gnu_cxx; } - - struct symbol_entry_t - { diff --git a/src/misc/bochs-2.2.6-page-fault-segv.patch b/src/misc/bochs-2.2.6-page-fault-segv.patch deleted file mode 100644 index 7c61a375060504e4103be65377cbc9542519494b..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-page-fault-segv.patch +++ /dev/null @@ -1,79 +0,0 @@ -Index: bochs-2.2.6/cpu/exception.cc -diff -u bochs-2.2.6/cpu/exception.cc\~ bochs-2.2.6/cpu/exception.cc ---- bochs-2.2.6/cpu/exception.cc~ 2006-09-28 15:51:39.000000000 -0700 -+++ bochs-2.2.6/cpu/exception.cc 2006-12-08 11:14:33.000000000 -0800 -@@ -1033,6 +1033,10 @@ void BX_CPU_C::exception(unsigned vector - BX_CPU_THIS_PTR curr_exception[0] = exception_type; - } - -+#if BX_GDBSTUB -+ bx_gdbstub_exception(vector); -+#endif -+ - #if BX_CPU_LEVEL >= 2 - if (!real_mode()) { - BX_CPU_THIS_PTR interrupt(vector, 0, push_error, error_code); -Index: bochs-2.2.6/gdbstub.cc -diff -u bochs-2.2.6/gdbstub.cc\~ bochs-2.2.6/gdbstub.cc ---- bochs-2.2.6/gdbstub.cc~ 2006-09-28 15:51:39.000000000 -0700 -+++ bochs-2.2.6/gdbstub.cc 2006-12-08 11:12:03.000000000 -0800 -@@ -26,6 +26,7 @@ static int last_stop_reason = GDBSTUB_ST - #define GDBSTUB_EXECUTION_BREAKPOINT (0xac1) - #define GDBSTUB_TRACE (0xac2) - #define GDBSTUB_USER_BREAK (0xac3) -+#define GDBSTUB_EXCEPTION_0E (0xac4) - - static int listen_socket_fd; - static int socket_fd; -@@ -271,6 +272,12 @@ int bx_gdbstub_check(unsigned int eip) - return(GDBSTUB_STOP_NO_REASON); - } - -+void bx_gdbstub_exception(unsigned int nr) -+{ -+ if (nr == 0x0e) -+ last_stop_reason = GDBSTUB_EXCEPTION_0E; -+} -+ - static int remove_breakpoint(unsigned int addr, int len) - { - unsigned int i; -@@ -452,6 +459,10 @@ static void debug_loop(void) - { - write_signal(&buf[1], SIGTRAP); - } -+ else if (last_stop_reason == GDBSTUB_EXCEPTION_0E) -+ { -+ write_signal(&buf[1], SIGSEGV); -+ } - else - { - write_signal(&buf[1], 0); -@@ -476,10 +487,14 @@ static void debug_loop(void) - { - write_signal(&buf[1], SIGTRAP); - } -- else -+ else if (last_stop_reason == GDBSTUB_EXCEPTION_0E) - { - write_signal(&buf[1], SIGSEGV); - } -+ else -+ { -+ write_signal(&buf[1], 0); -+ } - put_reply(buf); - break; - } -Index: bochs-2.2.6/bochs.h -diff -u bochs-2.2.6/bochs.h\~ bochs-2.2.6/bochs.h ---- bochs-2.2.6/bochs.h~ 2006-09-28 15:51:39.000000000 -0700 -+++ bochs-2.2.6/bochs.h 2006-12-08 11:14:19.000000000 -0800 -@@ -375,6 +375,7 @@ BOCHSAPI extern logfunc_t *genlog; - // defines for GDB stub - void bx_gdbstub_init(int argc, char* argv[]); - int bx_gdbstub_check(unsigned int eip); -+void bx_gdbstub_exception(unsigned int nr); - #define GDBSTUB_STOP_NO_REASON (0xac0) - - #if BX_SUPPORT_SMP diff --git a/src/misc/bochs-2.2.6-paranoia.patch b/src/misc/bochs-2.2.6-paranoia.patch deleted file mode 100644 index ff8d736ad755a54cdfa408c46ac3ad2d1877a1ee..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-paranoia.patch +++ /dev/null @@ -1,19 +0,0 @@ -Index: bochs-2.2.6/iodev/hdimage.h -diff -u bochs-2.2.6/iodev/hdimage.h\~ bochs-2.2.6/iodev/hdimage.h ---- bochs-2.2.6/iodev/hdimage.h~ 2005-11-06 03:07:01.000000000 -0800 -+++ bochs-2.2.6/iodev/hdimage.h 2006-09-28 15:55:50.000000000 -0700 -@@ -273,14 +273,8 @@ class sparse_image_t : public device_ima - - void panic(const char * message); - off_t --#ifndef PARANOID -- sparse_image_t:: --#endif - get_physical_offset(); - void --#ifndef PARANOID -- sparse_image_t:: --#endif - set_virtual_page(Bit32u new_virtual_page); - void read_header(); - ssize_t read_page_fragment(Bit32u read_virtual_page, Bit32u read_page_offset, size_t read_size, void * buf); diff --git a/src/misc/bochs-2.2.6-solaris-link.patch b/src/misc/bochs-2.2.6-solaris-link.patch deleted file mode 100644 index 5afef49a9cdd7675e75e87e6fc5e356d42957cc7..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-solaris-link.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- bochs-2.2.6.orig/Makefile.in 2006-04-03 16:34:51.170387000 -0700 -+++ bochs-2.2.6/Makefile.in 2006-04-03 16:34:57.480303000 -0700 -@@ -93,7 +93,7 @@ - CFLAGS = @CFLAGS@ @GUI_CFLAGS@ $(MCH_CFLAGS) $(FLA_FLAGS) @DEFINE_PLUGIN_PATH@ -DBX_SHARE_PATH='"$(sharedir)"' - CXXFLAGS = @CXXFLAGS@ @GUI_CXXFLAGS@ $(MCH_CFLAGS) $(FLA_FLAGS) @DEFINE_PLUGIN_PATH@ -DBX_SHARE_PATH='"$(sharedir)"' - --LDFLAGS = @LDFLAGS@ -+LDFLAGS = @LDFLAGS@ -lsocket - LIBS = @LIBS@ - # To compile with readline: - # linux needs just -lreadline diff --git a/src/misc/bochs-2.2.6-solaris-tty.patch b/src/misc/bochs-2.2.6-solaris-tty.patch deleted file mode 100644 index a9725dc63e9f410d78a4fd4b70d1f88da0d38d9e..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-solaris-tty.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- bochs-2.2.6/iodev/serial.cc 2005-07-11 09:24:47.000000000 -0700 -+++ bochs-2.2.6.patch/iodev/serial.cc 2006-05-28 16:41:33.278938000 -0700 -@@ -245,8 +245,13 @@ - BX_SER_THIS s[i].io_mode = BX_SER_MODE_TERM; - BX_DEBUG(("com%d tty_id: %d", i+1, BX_SER_THIS s[i].tty_id)); - tcgetattr(BX_SER_THIS s[i].tty_id, &BX_SER_THIS s[i].term_orig); -- bcopy((caddr_t) &BX_SER_THIS s[i].term_orig, (caddr_t) &BX_SER_THIS s[i].term_new, sizeof(struct termios)); -- cfmakeraw(&BX_SER_THIS s[i].term_new); -+ memcpy((caddr_t) &BX_SER_THIS s[i].term_new, (caddr_t) &BX_SER_THIS s[i].term_orig, sizeof(struct termios)); -+ BX_SER_THIS s[i].term_new.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP -+ |INLCR|IGNCR|ICRNL|IXON); -+ BX_SER_THIS s[i].term_new.c_oflag &= ~OPOST; -+ BX_SER_THIS s[i].term_new.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); -+ BX_SER_THIS s[i].term_new.c_cflag &= ~(CSIZE|PARENB); -+ BX_SER_THIS s[i].term_new.c_cflag |= CS8; - BX_SER_THIS s[i].term_new.c_oflag |= OPOST | ONLCR; // Enable NL to CR-NL translation - #ifndef TRUE_CTLC - // ctl-C will exit Bochs, or trap to the debugger - - ---- bochs-2.2.6/iodev/serial.h 2005-07-10 09:51:09.000000000 -0700 -+++ bochs-2.2.6.patch/iodev/serial.h 2006-05-28 16:39:03.757839000 -0700 -@@ -40,7 +40,7 @@ - #define SERIAL_ENABLE - #endif - --#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || defined(__APPLE__) -+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || defined(__APPLE__) || defined(__sun__) - #define SERIAL_ENABLE - extern "C" { - #include <termios.h> diff --git a/src/misc/bochs-2.2.6-triple-fault.patch b/src/misc/bochs-2.2.6-triple-fault.patch deleted file mode 100644 index f6d08716d61db1d7973ee1be86d18cf631f5da89..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.2.6-triple-fault.patch +++ /dev/null @@ -1,57 +0,0 @@ -diff -u bochs-2.2.6.orig/cpu/exception.cc bochs-2.2.6/cpu/exception.cc ---- bochs-2.2.6.orig/cpu/exception.cc -+++ bochs-2.2.6/cpu/exception.cc -@@ -841,6 +841,13 @@ void BX_CPU_C::exception(unsigned vector - - BX_CPU_THIS_PTR errorno++; - if (BX_CPU_THIS_PTR errorno >= 3) { -+#if BX_GDBSTUB -+ if (bx_dbg.gdbstub_enabled) { -+ fprintf(stderr, "Triple fault: stopping for gdb\n"); -+ BX_CPU_THIS_PTR ispanic = 1; -+ longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); -+ } -+#endif - #if BX_RESET_ON_TRIPLE_FAULT - BX_ERROR(("exception(): 3rd (%d) exception with no resolution, shutdown status is %02xh, resetting", vector, DEV_cmos_get_reg(0x0f))); - debug(BX_CPU_THIS_PTR prev_eip); -@@ -860,6 +867,13 @@ void BX_CPU_C::exception(unsigned vector - - /* if 1st was a double fault (software INT?), then shutdown */ - if ( (BX_CPU_THIS_PTR errorno==2) && (BX_CPU_THIS_PTR curr_exception[0]==BX_ET_DOUBLE_FAULT) ) { -+#if BX_GDBSTUB -+ if (bx_dbg.gdbstub_enabled) { -+ fprintf(stderr, "Triple fault: stopping for gdb\n"); -+ BX_CPU_THIS_PTR ispanic = 1; -+ longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); -+ } -+#endif - #if BX_RESET_ON_TRIPLE_FAULT - BX_INFO(("exception(): triple fault encountered, shutdown status is %02xh, resetting", DEV_cmos_get_reg(0x0f))); - debug(BX_CPU_THIS_PTR prev_eip); -diff -u bochs-2.2.6.orig/gdbstub.cc bochs-2.2.6/gdbstub.cc ---- bochs-2.2.6.orig/gdbstub.cc -+++ bochs-2.2.6/gdbstub.cc -@@ -466,19 +466,19 @@ static void debug_loop(void) - - BX_INFO (("stepping")); - stub_trace_flag = 1; -+ bx_cpu.ispanic = 0; - bx_cpu.cpu_loop(-1); - DEV_vga_refresh(); - stub_trace_flag = 0; - BX_INFO (("stopped with %x", last_stop_reason)); - buf[0] = 'S'; -- if (last_stop_reason == GDBSTUB_EXECUTION_BREAKPOINT || -- last_stop_reason == GDBSTUB_TRACE) -+ if (last_stop_reason == GDBSTUB_TRACE && !bx_cpu.ispanic) - { - write_signal(&buf[1], SIGTRAP); - } - else - { -- write_signal(&buf[1], SIGTRAP); -+ write_signal(&buf[1], SIGSEGV); - } - put_reply(buf); - break; diff --git a/src/misc/bochs-2.6.2-build.sh b/src/misc/bochs-2.6.2-build.sh deleted file mode 100755 index 1868b3b7a1e60550867a0e89e4cb4ac1a2014d5f..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.6.2-build.sh +++ /dev/null @@ -1,31 +0,0 @@ -#! /bin/sh -e - -if test -z "$SRCDIR" || test -z "$PINTOSDIR" || test -z "$DSTDIR"; then - echo "usage: env SRCDIR=<srcdir> PINTOSDIR=<srcdir> DSTDIR=<dstdir> sh $0" - echo " where <srcdir> contains bochs-2.6.2.tar.gz" - echo " and <pintosdir> is the root of the pintos source tree" - echo " and <dstdir> is the installation prefix (e.g. /usr/local)" - exit 1 -fi - -cd /tmp -mkdir $$ -cd $$ -mkdir bochs-2.6.2 -tar xzf $SRCDIR/bochs-2.6.2.tar.gz -cd bochs-2.6.2 -cat $PINTOSDIR/src/misc/bochs-2.6.2-jitter-plus-segv.patch | patch -p1 -cat $PINTOSDIR/src/misc/bochs-2.6.2-xrandr-pkgconfig.patch | patch -p1 -CFGOPTS="--with-x --with-x11 --with-term --with-nogui --prefix=$DSTDIR --enable-cpu-level=6" -mkdir plain && - cd plain && - ../configure $CFGOPTS --enable-gdb-stub && - make && - make install && - cd .. -mkdir with-dbg && - cd with-dbg && - ../configure --enable-debugger $CFGOPTS && - make && - cp bochs $DSTDIR/bin/bochs-dbg && - cd .. diff --git a/src/misc/bochs-2.6.2-jitter-plus-segv.patch b/src/misc/bochs-2.6.2-jitter-plus-segv.patch deleted file mode 100644 index b6ad247fcc243272b36d4002ee0ef3e55c73ac15..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.6.2-jitter-plus-segv.patch +++ /dev/null @@ -1,135 +0,0 @@ -diff --git a/bochs.h b/bochs.h -index c2d6c6b..d37cf12 100644 ---- a/bochs.h -+++ b/bochs.h -@@ -392,6 +392,7 @@ BOCHSAPI extern logfunc_t *genlog; - void bx_gdbstub_init(void); - void bx_gdbstub_break(void); - int bx_gdbstub_check(unsigned int eip); -+void bx_gdbstub_exception(unsigned int nr); - #define GDBSTUB_STOP_NO_REASON (0xac0) - - #if BX_SUPPORT_SMP -@@ -589,4 +590,6 @@ BX_CPP_INLINE Bit64u bx_bswap64(Bit64u val64) - #define CopyHostQWordLittleEndian(hostAddrDst, hostAddrSrc) \ - (* (Bit64u *)(hostAddrDst)) = (* (Bit64u *)(hostAddrSrc)); - -+extern int jitter; -+ - #endif /* BX_BOCHS_H */ -diff --git a/cpu/exception.cc b/cpu/exception.cc -index db38d1b..b2c5f29 100644 ---- a/cpu/exception.cc -+++ b/cpu/exception.cc -@@ -914,6 +914,10 @@ void BX_CPU_C::exception(unsigned vector, Bit16u error_code) - - BX_CPU_THIS_PTR last_exception_type = exception_type; - -+#if BX_GDBSTUB -+ bx_gdbstub_exception(vector); -+#endif -+ - if (real_mode()) { - push_error = 0; // not INT, no error code pushed - error_code = 0; -diff --git a/gdbstub.cc b/gdbstub.cc -index da600b4..577938d 100644 ---- a/gdbstub.cc -+++ b/gdbstub.cc -@@ -49,6 +49,7 @@ static int last_stop_reason = GDBSTUB_STOP_NO_REASON; - #define GDBSTUB_EXECUTION_BREAKPOINT (0xac1) - #define GDBSTUB_TRACE (0xac2) - #define GDBSTUB_USER_BREAK (0xac3) -+#define GDBSTUB_EXCEPTION_0E (0xac4) - - static bx_list_c *gdbstub_list; - static int listen_socket_fd; -@@ -317,6 +318,12 @@ int bx_gdbstub_check(unsigned int eip) - return GDBSTUB_STOP_NO_REASON; - } - -+void bx_gdbstub_exception(unsigned int nr) -+{ -+ if (nr == 0x0e) -+ last_stop_reason = GDBSTUB_EXCEPTION_0E; -+} -+ - static int remove_breakpoint(unsigned addr, int len) - { - if (len != 1) -@@ -487,6 +494,10 @@ static void debug_loop(void) - { - write_signal(&buf[1], SIGTRAP); - } -+ else if (last_stop_reason == GDBSTUB_EXCEPTION_0E) -+ { -+ write_signal(&buf[1], SIGSEGV); -+ } - else - { - write_signal(&buf[1], 0); -@@ -514,6 +525,10 @@ static void debug_loop(void) - { - write_signal(&buf[1], SIGTRAP); - } -+ else if (last_stop_reason == GDBSTUB_EXCEPTION_0E) -+ { -+ write_signal(&buf[1], SIGSEGV); -+ } - else - { - write_signal(&buf[1], SIGTRAP); -diff --git a/iodev/pit82c54.cc b/iodev/pit82c54.cc -index 09dcd8e..7e335d4 100644 ---- a/iodev/pit82c54.cc -+++ b/iodev/pit82c54.cc -@@ -49,6 +49,7 @@ - - #include "iodev.h" - #include "pit82c54.h" -+#include <stdlib.h> - #define LOG_THIS this-> - - -@@ -410,7 +411,14 @@ void BX_CPP_AttrRegparmN(1) pit_82C54::clock(Bit8u cnum) - case 2: - if (thisctr.count_written) { - if (thisctr.triggerGATE || thisctr.first_pass) { -- set_count(thisctr, thisctr.inlatch); -+ //set_count(thisctr, thisctr.inlatch); -+ unsigned n = thisctr.inlatch; -+ if (jitter && n > 5) { -+ n *= (double) rand() / RAND_MAX; -+ if (n < 5) -+ n = 5; -+ } -+ set_count(thisctr, n); - thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; - thisctr.null_count=0; - if (thisctr.inlatch==1) { -diff --git a/main.cc b/main.cc -index 0f11e31..008f05f 100644 ---- a/main.cc -+++ b/main.cc -@@ -101,6 +101,7 @@ BOCHSAPI BX_CPU_C bx_cpu; - BOCHSAPI BX_MEM_C bx_mem; - - char *bochsrc_filename = NULL; -+int jitter = 0; - - void bx_print_header() - { -@@ -639,6 +640,13 @@ int bx_init_main(int argc, char *argv[]) - else SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME)->set(argv[arg]); - } - #endif -+ else if (!strcmp ("-j", argv[arg])) { -+ if (++arg >= argc) BX_PANIC(("-j must be followed by a number")); -+ else { -+ jitter = 1; -+ srand (atoi (argv[arg])); -+ } -+ } - else if (!strcmp("-f", argv[arg])) { - if (++arg >= argc) BX_PANIC(("-f must be followed by a filename")); - else bochsrc_filename = argv[arg]; diff --git a/src/misc/bochs-2.6.2-xrandr-pkgconfig.patch b/src/misc/bochs-2.6.2-xrandr-pkgconfig.patch deleted file mode 100644 index b92f81412343e2631a3c6add712a704bedcba6de..0000000000000000000000000000000000000000 --- a/src/misc/bochs-2.6.2-xrandr-pkgconfig.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -Naur bochs-2.6.2.orig/configure bochs-2.6.2/configure ---- bochs-2.6.2.orig/configure 2014-01-06 16:39:03.000000000 -0800 -+++ bochs-2.6.2/configure 2014-01-06 16:39:23.000000000 -0800 -@@ -24202,8 +24202,8 @@ - fi - - if test "$PKGCONFIG" != not_found; then -- X_CFLAGS="`pkg-config --cflags x11`" -- X_LIBS="`pkg-config --libs x11` $XPM_LIB -lXrandr" -+ X_CFLAGS="`pkg-config --cflags x11 xrandr`" -+ X_LIBS="`pkg-config --libs x11 xrandr` $XPM_LIB" - else - X_LIBS="$X_LIBS -lX11 $XPM_LIB -lXrandr" - fi diff --git a/src/misc/gcc-3.3.6-cross-howto b/src/misc/gcc-3.3.6-cross-howto deleted file mode 100644 index ad25173c86693ee2e2fff530436c49c4bd0f57df..0000000000000000000000000000000000000000 --- a/src/misc/gcc-3.3.6-cross-howto +++ /dev/null @@ -1,39 +0,0 @@ -Here are the commands we used to build and install the SPARC -cross-compiler: - -PINTOSROOT=$HOME/private/pintos - -PREFIX=/usr/class/cs140/`uname -m` -PATH=$PATH:$PREFIX/bin -TMP=`pwd` - -wget ftp://ftp.gnu.org/pub/gnu/binutils/binutils-2.15.tar.bz2 -wget ftp://sources.redhat.com/pub/newlib/newlib-1.13.0.tar.gz -wget ftp://ftp.gnu.org/pub/gnu/gcc/gcc-3.3.6/gcc-core-3.3.6.tar.bz2 -wget ftp://ftp.gnu.org/pub/gnu/gdb/gdb-6.3.tar.bz2 - -bzcat binutils-2.15.tar.bz2 | tar x -tar xzf newlib-1.13.0.tar.gz -bzcat gcc-core-3.3.6.tar.bz2 | tar x -bzcat gdb-6.3.tar.bz2 | tar x - -cd $TMP/binutils-2.15 -mkdir i386 -cd i386 -../configure --target=i386-elf --prefix=$PREFIX -make LDFLAGS=-lintl -make install - -cd $TMP/gcc-3.3.6 -mkdir i386 -cd i386 -../configure --target=i386-elf --prefix=$PREFIX --with-gnu-as --with-as=$PREFIX/bin/i386-elf-as --with-gnu-ld --with-ld=$PREFIX/bin/i386-elf-ld --with-headers=$TMP/newlib-1.13.0/newlib/libc/include --with-newlib -make -make install - -cd $TMP/gdb-6.3 -mkdir i386 -cd i386 -../configure --target=i386-elf --prefix=$PREFIX --disable-tui -make LDFLAGS=-lintl -make install diff --git a/src/misc/gdb-macros b/src/misc/gdb-macros deleted file mode 100644 index a0b68c304ff595b13ab3f07c1d5939bf292a2f86..0000000000000000000000000000000000000000 --- a/src/misc/gdb-macros +++ /dev/null @@ -1,140 +0,0 @@ -# -# A set of useful macros that can help debug Pintos. -# -# Include with "source" cmd in gdb. -# Use "help user-defined" for help. -# -# Author: Godmar Back <gback@cs.vt.edu>, Feb 2006 -# -# $Id: gdb-macros,v 1.1 2006-04-07 18:29:34 blp Exp $ -# - -# for internal use -define offsetof - set $rc = (char*)&((struct $arg0 *)0)->$arg1 - (char*)0 -end - -define list_entry - offsetof $arg1 $arg2 - set $rc = ((struct $arg1 *) ((uint8_t *) ($arg0) - $rc)) -end - -# dump a Pintos list -define dumplist - set $list = $arg0 - set $e = $list->head.next - set $i = 0 - while $e != &(($arg0).tail) - list_entry $e $arg1 $arg2 - set $l = $rc - printf "pintos-debug: dumplist #%d: %p ", $i++, $l - output *$l - set $e = $e->next - printf "\n" - end -end - -document dumplist - Dump the content of a Pintos list, - invoke as dumplist name_of_list name_of_struct name_of_elem_in_list_struct -end - -# print a thread's backtrace, given a pointer to the struct thread * -define btthread - if $arg0 == ($esp - ((unsigned)$esp % 4096)) - bt - else - set $saveEIP = $eip - set $saveESP = $esp - set $saveEBP = $ebp - - set $esp = ((struct thread *)$arg0)->stack - set $ebp = ((void**)$esp)[2] - set $eip = ((void**)$esp)[4] - - bt - - set $eip = $saveEIP - set $esp = $saveESP - set $ebp = $saveEBP - end -end -document btthread - Show the backtrace of a thread, - invoke as btthread pointer_to_struct_thread -end - -# print backtraces associated with all threads in a list -define btthreadlist - set $list = $arg0 - set $e = $list->head.next - while $e != &(($arg0).tail) - list_entry $e thread $arg1 - printf "pintos-debug: dumping backtrace of thread '%s' @%p\n", \ - ((struct thread*)$rc)->name, $rc - btthread $rc - set $e = $e->next - printf "\n" - end -end -document btthreadlist - Given a list of threads, print each thread's backtrace - invoke as btthreadlist name_of_list name_of_elem_in_list_struct -end - -# print backtraces of all threads (based on 'all_list' all threads list) -define btthreadall - btthreadlist all_list allelem -end -document btthreadall - Print backtraces of all threads -end - -# print a correct backtrace by adjusting $eip -# this works best right at intr0e_stub -define btpagefault - set $saveeip = $eip - set $eip = ((void**)$esp)[1] - backtrace - set $eip = $saveeip -end -document btpagefault - Print a backtrace of the current thread after a pagefault -end - -# invoked whenever the program stops -define hook-stop - # stopped at stub #0E = #14 (page fault exception handler stub) - if ($eip == intr0e_stub) - set $savedeip = ((void**)$esp)[1] - # if this was in user mode, the OS should handle it - # either handle the page fault or terminate the process - if ($savedeip < 0xC0000000) - printf "pintos-debug: a page fault exception occurred in user mode\n" - printf "pintos-debug: hit 'c' to continue, or 's' to step to intr_handler\n" - else - # if this was in kernel mode, a stack trace might be useful - printf "pintos-debug: a page fault occurred in kernel mode\n" - btpagefault - end - end -end - -# load symbols for a Pintos user program -define loadusersymbols - shell objdump -h $arg0 | awk '/.text/ { print "add-symbol-file $arg0 0x"$4 }' > .loadsymbols - source .loadsymbols - shell rm -f .loadsymbols -end -document loadusersymbols - Load the symbols contained in a user program's executable. - Example: - loadusersymbols tests/userprog/exec-multiple -end - -define debugpintos - target remote localhost:1234 -end -document debugpintos - Attach debugger to pintos process -end diff --git a/src/tests/Algorithm/Diff.pm b/src/tests/Algorithm/Diff.pm deleted file mode 100644 index 904c530ab0997f3e776e6f83549649c6f1f596cd..0000000000000000000000000000000000000000 --- a/src/tests/Algorithm/Diff.pm +++ /dev/null @@ -1,1713 +0,0 @@ -package Algorithm::Diff; -# Skip to first "=head" line for documentation. -use strict; - -use integer; # see below in _replaceNextLargerWith() for mod to make - # if you don't use this -use vars qw( $VERSION @EXPORT_OK ); -$VERSION = 1.19_01; -# ^ ^^ ^^-- Incremented at will -# | \+----- Incremented for non-trivial changes to features -# \-------- Incremented for fundamental changes -require Exporter; -*import = \&Exporter::import; -@EXPORT_OK = qw( - prepare LCS LCDidx LCS_length - diff sdiff compact_diff - traverse_sequences traverse_balanced -); - -# McIlroy-Hunt diff algorithm -# Adapted from the Smalltalk code of Mario I. Wolczko, <mario@wolczko.com> -# by Ned Konz, perl@bike-nomad.com -# Updates by Tye McQueen, http://perlmonks.org/?node=tye - -# Create a hash that maps each element of $aCollection to the set of -# positions it occupies in $aCollection, restricted to the elements -# within the range of indexes specified by $start and $end. -# The fourth parameter is a subroutine reference that will be called to -# generate a string to use as a key. -# Additional parameters, if any, will be passed to this subroutine. -# -# my $hashRef = _withPositionsOfInInterval( \@array, $start, $end, $keyGen ); - -sub _withPositionsOfInInterval -{ - my $aCollection = shift; # array ref - my $start = shift; - my $end = shift; - my $keyGen = shift; - my %d; - my $index; - for ( $index = $start ; $index <= $end ; $index++ ) - { - my $element = $aCollection->[$index]; - my $key = &$keyGen( $element, @_ ); - if ( exists( $d{$key} ) ) - { - unshift ( @{ $d{$key} }, $index ); - } - else - { - $d{$key} = [$index]; - } - } - return wantarray ? %d : \%d; -} - -# Find the place at which aValue would normally be inserted into the -# array. If that place is already occupied by aValue, do nothing, and -# return undef. If the place does not exist (i.e., it is off the end of -# the array), add it to the end, otherwise replace the element at that -# point with aValue. It is assumed that the array's values are numeric. -# This is where the bulk (75%) of the time is spent in this module, so -# try to make it fast! - -sub _replaceNextLargerWith -{ - my ( $array, $aValue, $high ) = @_; - $high ||= $#$array; - - # off the end? - if ( $high == -1 || $aValue > $array->[-1] ) - { - push ( @$array, $aValue ); - return $high + 1; - } - - # binary search for insertion point... - my $low = 0; - my $index; - my $found; - while ( $low <= $high ) - { - $index = ( $high + $low ) / 2; - - # $index = int(( $high + $low ) / 2); # without 'use integer' - $found = $array->[$index]; - - if ( $aValue == $found ) - { - return undef; - } - elsif ( $aValue > $found ) - { - $low = $index + 1; - } - else - { - $high = $index - 1; - } - } - - # now insertion point is in $low. - $array->[$low] = $aValue; # overwrite next larger - return $low; -} - -# This method computes the longest common subsequence in $a and $b. - -# Result is array or ref, whose contents is such that -# $a->[ $i ] == $b->[ $result[ $i ] ] -# foreach $i in ( 0 .. $#result ) if $result[ $i ] is defined. - -# An additional argument may be passed; this is a hash or key generating -# function that should return a string that uniquely identifies the given -# element. It should be the case that if the key is the same, the elements -# will compare the same. If this parameter is undef or missing, the key -# will be the element as a string. - -# By default, comparisons will use "eq" and elements will be turned into keys -# using the default stringizing operator '""'. - -# Additional parameters, if any, will be passed to the key generation -# routine. - -sub _longestCommonSubsequence -{ - my $a = shift; # array ref or hash ref - my $b = shift; # array ref or hash ref - my $counting = shift; # scalar - my $keyGen = shift; # code ref - my $compare; # code ref - - if ( ref($a) eq 'HASH' ) - { # prepared hash must be in $b - my $tmp = $b; - $b = $a; - $a = $tmp; - } - - # Check for bogus (non-ref) argument values - if ( !ref($a) || !ref($b) ) - { - my @callerInfo = caller(1); - die 'error: must pass array or hash references to ' . $callerInfo[3]; - } - - # set up code refs - # Note that these are optimized. - if ( !defined($keyGen) ) # optimize for strings - { - $keyGen = sub { $_[0] }; - $compare = sub { my ( $a, $b ) = @_; $a eq $b }; - } - else - { - $compare = sub { - my $a = shift; - my $b = shift; - &$keyGen( $a, @_ ) eq &$keyGen( $b, @_ ); - }; - } - - my ( $aStart, $aFinish, $matchVector ) = ( 0, $#$a, [] ); - my ( $prunedCount, $bMatches ) = ( 0, {} ); - - if ( ref($b) eq 'HASH' ) # was $bMatches prepared for us? - { - $bMatches = $b; - } - else - { - my ( $bStart, $bFinish ) = ( 0, $#$b ); - - # First we prune off any common elements at the beginning - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aStart], $b->[$bStart], @_ ) ) - { - $matchVector->[ $aStart++ ] = $bStart++; - $prunedCount++; - } - - # now the end - while ( $aStart <= $aFinish - and $bStart <= $bFinish - and &$compare( $a->[$aFinish], $b->[$bFinish], @_ ) ) - { - $matchVector->[ $aFinish-- ] = $bFinish--; - $prunedCount++; - } - - # Now compute the equivalence classes of positions of elements - $bMatches = - _withPositionsOfInInterval( $b, $bStart, $bFinish, $keyGen, @_ ); - } - my $thresh = []; - my $links = []; - - my ( $i, $ai, $j, $k ); - for ( $i = $aStart ; $i <= $aFinish ; $i++ ) - { - $ai = &$keyGen( $a->[$i], @_ ); - if ( exists( $bMatches->{$ai} ) ) - { - $k = 0; - for $j ( @{ $bMatches->{$ai} } ) - { - - # optimization: most of the time this will be true - if ( $k and $thresh->[$k] > $j and $thresh->[ $k - 1 ] < $j ) - { - $thresh->[$k] = $j; - } - else - { - $k = _replaceNextLargerWith( $thresh, $j, $k ); - } - - # oddly, it's faster to always test this (CPU cache?). - if ( defined($k) ) - { - $links->[$k] = - [ ( $k ? $links->[ $k - 1 ] : undef ), $i, $j ]; - } - } - } - } - - if (@$thresh) - { - return $prunedCount + @$thresh if $counting; - for ( my $link = $links->[$#$thresh] ; $link ; $link = $link->[0] ) - { - $matchVector->[ $link->[1] ] = $link->[2]; - } - } - elsif ($counting) - { - return $prunedCount; - } - - return wantarray ? @$matchVector : $matchVector; -} - -sub traverse_sequences -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $finishedACallback = $callbacks->{'A_FINISHED'}; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $finishedBCallback = $callbacks->{'B_FINISHED'}; - my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ ); - - # Process all the lines in @$matchVector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai; - - for ( $ai = 0 ; $ai <= $#$matchVector ; $ai++ ) - { - my $bLine = $matchVector->[$ai]; - if ( defined($bLine) ) # matched - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi < $bLine; - &$matchCallback( $ai, $bi++, @_ ); - } - else - { - &$discardACallback( $ai, $bi, @_ ); - } - } - - # The last entry (if any) processed was a match. - # $ai and $bi point just past the last matching lines in their sequences. - - while ( $ai <= $lastA or $bi <= $lastB ) - { - - # last A? - if ( $ai == $lastA + 1 and $bi <= $lastB ) - { - if ( defined($finishedACallback) ) - { - &$finishedACallback( $lastA, @_ ); - $finishedACallback = undef; - } - else - { - &$discardBCallback( $ai, $bi++, @_ ) while $bi <= $lastB; - } - } - - # last B? - if ( $bi == $lastB + 1 and $ai <= $lastA ) - { - if ( defined($finishedBCallback) ) - { - &$finishedBCallback( $lastB, @_ ); - $finishedBCallback = undef; - } - else - { - &$discardACallback( $ai++, $bi, @_ ) while $ai <= $lastA; - } - } - - &$discardACallback( $ai++, $bi, @_ ) if $ai <= $lastA; - &$discardBCallback( $ai, $bi++, @_ ) if $bi <= $lastB; - } - - return 1; -} - -sub traverse_balanced -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $callbacks = shift || {}; - my $keyGen = shift; - my $matchCallback = $callbacks->{'MATCH'} || sub { }; - my $discardACallback = $callbacks->{'DISCARD_A'} || sub { }; - my $discardBCallback = $callbacks->{'DISCARD_B'} || sub { }; - my $changeCallback = $callbacks->{'CHANGE'}; - my $matchVector = _longestCommonSubsequence( $a, $b, 0, $keyGen, @_ ); - - # Process all the lines in match vector - my $lastA = $#$a; - my $lastB = $#$b; - my $bi = 0; - my $ai = 0; - my $ma = -1; - my $mb; - - while (1) - { - - # Find next match indices $ma and $mb - do { - $ma++; - } while( - $ma <= $#$matchVector - && !defined $matchVector->[$ma] - ); - - last if $ma > $#$matchVector; # end of matchVector? - $mb = $matchVector->[$ma]; - - # Proceed with discard a/b or change events until - # next match - while ( $ai < $ma || $bi < $mb ) - { - - if ( $ai < $ma && $bi < $mb ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai < $ma ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi < $mb - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - # Match - &$matchCallback( $ai++, $bi++, @_ ); - } - - while ( $ai <= $lastA || $bi <= $lastB ) - { - if ( $ai <= $lastA && $bi <= $lastB ) - { - - # Change - if ( defined $changeCallback ) - { - &$changeCallback( $ai++, $bi++, @_ ); - } - else - { - &$discardACallback( $ai++, $bi, @_ ); - &$discardBCallback( $ai, $bi++, @_ ); - } - } - elsif ( $ai <= $lastA ) - { - &$discardACallback( $ai++, $bi, @_ ); - } - else - { - - # $bi <= $lastB - &$discardBCallback( $ai, $bi++, @_ ); - } - } - - return 1; -} - -sub prepare -{ - my $a = shift; # array ref - my $keyGen = shift; # code ref - - # set up code ref - $keyGen = sub { $_[0] } unless defined($keyGen); - - return scalar _withPositionsOfInInterval( $a, 0, $#$a, $keyGen, @_ ); -} - -sub LCS -{ - my $a = shift; # array ref - my $b = shift; # array ref or hash ref - my $matchVector = _longestCommonSubsequence( $a, $b, 0, @_ ); - my @retval; - my $i; - for ( $i = 0 ; $i <= $#$matchVector ; $i++ ) - { - if ( defined( $matchVector->[$i] ) ) - { - push ( @retval, $a->[$i] ); - } - } - return wantarray ? @retval : \@retval; -} - -sub LCS_length -{ - my $a = shift; # array ref - my $b = shift; # array ref or hash ref - return _longestCommonSubsequence( $a, $b, 1, @_ ); -} - -sub LCSidx -{ - my $a= shift @_; - my $b= shift @_; - my $match= _longestCommonSubsequence( $a, $b, 0, @_ ); - my @am= grep defined $match->[$_], 0..$#$match; - my @bm= @{$match}[@am]; - return \@am, \@bm; -} - -sub compact_diff -{ - my $a= shift @_; - my $b= shift @_; - my( $am, $bm )= LCSidx( $a, $b, @_ ); - my @cdiff; - my( $ai, $bi )= ( 0, 0 ); - push @cdiff, $ai, $bi; - while( 1 ) { - while( @$am && $ai == $am->[0] && $bi == $bm->[0] ) { - shift @$am; - shift @$bm; - ++$ai, ++$bi; - } - push @cdiff, $ai, $bi; - last if ! @$am; - $ai = $am->[0]; - $bi = $bm->[0]; - push @cdiff, $ai, $bi; - } - push @cdiff, 0+@$a, 0+@$b - if $ai < @$a || $bi < @$b; - return wantarray ? @cdiff : \@cdiff; -} - -sub diff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $hunk = []; - my $discard = sub { - push @$hunk, [ '-', $_[0], $a->[ $_[0] ] ]; - }; - my $add = sub { - push @$hunk, [ '+', $_[1], $b->[ $_[1] ] ]; - }; - my $match = sub { - push @$retval, $hunk - if 0 < @$hunk; - $hunk = [] - }; - traverse_sequences( $a, $b, - { MATCH => $match, DISCARD_A => $discard, DISCARD_B => $add }, @_ ); - &$match(); - return wantarray ? @$retval : $retval; -} - -sub sdiff -{ - my $a = shift; # array ref - my $b = shift; # array ref - my $retval = []; - my $discard = sub { push ( @$retval, [ '-', $a->[ $_[0] ], "" ] ) }; - my $add = sub { push ( @$retval, [ '+', "", $b->[ $_[1] ] ] ) }; - my $change = sub { - push ( @$retval, [ 'c', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - my $match = sub { - push ( @$retval, [ 'u', $a->[ $_[0] ], $b->[ $_[1] ] ] ); - }; - traverse_balanced( - $a, - $b, - { - MATCH => $match, - DISCARD_A => $discard, - DISCARD_B => $add, - CHANGE => $change, - }, - @_ - ); - return wantarray ? @$retval : $retval; -} - -######################################## -my $Root= __PACKAGE__; -package Algorithm::Diff::_impl; -use strict; - -sub _Idx() { 0 } # $me->[_Idx]: Ref to array of hunk indices - # 1 # $me->[1]: Ref to first sequence - # 2 # $me->[2]: Ref to second sequence -sub _End() { 3 } # $me->[_End]: Diff between forward and reverse pos -sub _Same() { 4 } # $me->[_Same]: 1 if pos 1 contains unchanged items -sub _Base() { 5 } # $me->[_Base]: Added to range's min and max -sub _Pos() { 6 } # $me->[_Pos]: Which hunk is currently selected -sub _Off() { 7 } # $me->[_Off]: Offset into _Idx for current position -sub _Min() { -2 } # Added to _Off to get min instead of max+1 - -sub Die -{ - require Carp; - Carp::confess( @_ ); -} - -sub _ChkPos -{ - my( $me )= @_; - return if $me->[_Pos]; - my $meth= ( caller(1) )[3]; - Die( "Called $meth on 'reset' object" ); -} - -sub _ChkSeq -{ - my( $me, $seq )= @_; - return $seq + $me->[_Off] - if 1 == $seq || 2 == $seq; - my $meth= ( caller(1) )[3]; - Die( "$meth: Invalid sequence number ($seq); must be 1 or 2" ); -} - -sub getObjPkg -{ - my( $us )= @_; - return ref $us if ref $us; - return $us . "::_obj"; -} - -sub new -{ - my( $us, $seq1, $seq2, $opts ) = @_; - my @args; - for( $opts->{keyGen} ) { - push @args, $_ if $_; - } - for( $opts->{keyGenArgs} ) { - push @args, @$_ if $_; - } - my $cdif= Algorithm::Diff::compact_diff( $seq1, $seq2, @args ); - my $same= 1; - if( 0 == $cdif->[2] && 0 == $cdif->[3] ) { - $same= 0; - splice @$cdif, 0, 2; - } - my @obj= ( $cdif, $seq1, $seq2 ); - $obj[_End] = (1+@$cdif)/2; - $obj[_Same] = $same; - $obj[_Base] = 0; - my $me = bless \@obj, $us->getObjPkg(); - $me->Reset( 0 ); - return $me; -} - -sub Reset -{ - my( $me, $pos )= @_; - $pos= int( $pos || 0 ); - $pos += $me->[_End] - if $pos < 0; - $pos= 0 - if $pos < 0 || $me->[_End] <= $pos; - $me->[_Pos]= $pos || !1; - $me->[_Off]= 2*$pos - 1; - return $me; -} - -sub Base -{ - my( $me, $base )= @_; - my $oldBase= $me->[_Base]; - $me->[_Base]= 0+$base if defined $base; - return $oldBase; -} - -sub Copy -{ - my( $me, $pos, $base )= @_; - my @obj= @$me; - my $you= bless \@obj, ref($me); - $you->Reset( $pos ) if defined $pos; - $you->Base( $base ); - return $you; -} - -sub Next { - my( $me, $steps )= @_; - $steps= 1 if ! defined $steps; - if( $steps ) { - my $pos= $me->[_Pos]; - my $new= $pos + $steps; - $new= 0 if $pos && $new < 0; - $me->Reset( $new ) - } - return $me->[_Pos]; -} - -sub Prev { - my( $me, $steps )= @_; - $steps= 1 if ! defined $steps; - my $pos= $me->Next(-$steps); - $pos -= $me->[_End] if $pos; - return $pos; -} - -sub Diff { - my( $me )= @_; - $me->_ChkPos(); - return 0 if $me->[_Same] == ( 1 & $me->[_Pos] ); - my $ret= 0; - my $off= $me->[_Off]; - for my $seq ( 1, 2 ) { - $ret |= $seq - if $me->[_Idx][ $off + $seq + _Min ] - < $me->[_Idx][ $off + $seq ]; - } - return $ret; -} - -sub Min { - my( $me, $seq, $base )= @_; - $me->_ChkPos(); - my $off= $me->_ChkSeq($seq); - $base= $me->[_Base] if !defined $base; - return $base + $me->[_Idx][ $off + _Min ]; -} - -sub Max { - my( $me, $seq, $base )= @_; - $me->_ChkPos(); - my $off= $me->_ChkSeq($seq); - $base= $me->[_Base] if !defined $base; - return $base + $me->[_Idx][ $off ] -1; -} - -sub Range { - my( $me, $seq, $base )= @_; - $me->_ChkPos(); - my $off = $me->_ChkSeq($seq); - if( !wantarray ) { - return $me->[_Idx][ $off ] - - $me->[_Idx][ $off + _Min ]; - } - $base= $me->[_Base] if !defined $base; - return ( $base + $me->[_Idx][ $off + _Min ] ) - .. ( $base + $me->[_Idx][ $off ] - 1 ); -} - -sub Items { - my( $me, $seq )= @_; - $me->_ChkPos(); - my $off = $me->_ChkSeq($seq); - if( !wantarray ) { - return $me->[_Idx][ $off ] - - $me->[_Idx][ $off + _Min ]; - } - return - @{$me->[$seq]}[ - $me->[_Idx][ $off + _Min ] - .. ( $me->[_Idx][ $off ] - 1 ) - ]; -} - -sub Same { - my( $me )= @_; - $me->_ChkPos(); - return wantarray ? () : 0 - if $me->[_Same] != ( 1 & $me->[_Pos] ); - return $me->Items(1); -} - -my %getName; -BEGIN { - %getName= ( - same => \&Same, - diff => \&Diff, - base => \&Base, - min => \&Min, - max => \&Max, - range=> \&Range, - items=> \&Items, # same thing - ); -} - -sub Get -{ - my $me= shift @_; - $me->_ChkPos(); - my @value; - for my $arg ( @_ ) { - for my $word ( split ' ', $arg ) { - my $meth; - if( $word !~ /^(-?\d+)?([a-zA-Z]+)([12])?$/ - || not $meth= $getName{ lc $2 } - ) { - Die( $Root, ", Get: Invalid request ($word)" ); - } - my( $base, $name, $seq )= ( $1, $2, $3 ); - push @value, scalar( - 4 == length($name) - ? $meth->( $me ) - : $meth->( $me, $seq, $base ) - ); - } - } - if( wantarray ) { - return @value; - } elsif( 1 == @value ) { - return $value[0]; - } - Die( 0+@value, " values requested from ", - $Root, "'s Get in scalar context" ); -} - - -my $Obj= getObjPkg($Root); -no strict 'refs'; - -for my $meth ( qw( new getObjPkg ) ) { - *{$Root."::".$meth} = \&{$meth}; - *{$Obj ."::".$meth} = \&{$meth}; -} -for my $meth ( qw( - Next Prev Reset Copy Base Diff - Same Items Range Min Max Get - _ChkPos _ChkSeq -) ) { - *{$Obj."::".$meth} = \&{$meth}; -} - -1; -__END__ - -=head1 NAME - -Algorithm::Diff - Compute `intelligent' differences between two files / lists - -=head1 SYNOPSIS - - require Algorithm::Diff; - - # This example produces traditional 'diff' output: - - my $diff = Algorithm::Diff->new( \@seq1, \@seq2 ); - - $diff->Base( 1 ); # Return line numbers, not indices - while( $diff->Next() ) { - next if $diff->Same(); - my $sep = ''; - if( ! $diff->Items(2) ) { - sprintf "%d,%dd%d\n", - $diff->Get(qw( Min1 Max1 Max2 )); - } elsif( ! $diff->Items(1) ) { - sprint "%da%d,%d\n", - $diff->Get(qw( Max1 Min2 Max2 )); - } else { - $sep = "---\n"; - sprintf "%d,%dc%d,%d\n", - $diff->Get(qw( Min1 Max1 Min2 Max2 )); - } - print "< $_" for $diff->Items(1); - print $sep; - print "> $_" for $diff->Items(2); - } - - - # Alternate interfaces: - - use Algorithm::Diff qw( - LCS LCS_length LCSidx - diff sdiff compact_diff - traverse_sequences traverse_balanced ); - - @lcs = LCS( \@seq1, \@seq2 ); - $lcsref = LCS( \@seq1, \@seq2 ); - $count = LCS_length( \@seq1, \@seq2 ); - - ( $seq1idxref, $seq2idxref ) = LCSidx( \@seq1, \@seq2 ); - - - # Complicated interfaces: - - @diffs = diff( \@seq1, \@seq2 ); - - @sdiffs = sdiff( \@seq1, \@seq2 ); - - @cdiffs = compact_diff( \@seq1, \@seq2 ); - - traverse_sequences( - \@seq1, - \@seq2, - { MATCH => \&callback1, - DISCARD_A => \&callback2, - DISCARD_B => \&callback3, - }, - \&key_generator, - @extra_args, - ); - - traverse_balanced( - \@seq1, - \@seq2, - { MATCH => \&callback1, - DISCARD_A => \&callback2, - DISCARD_B => \&callback3, - CHANGE => \&callback4, - }, - \&key_generator, - @extra_args, - ); - - -=head1 INTRODUCTION - -(by Mark-Jason Dominus) - -I once read an article written by the authors of C<diff>; they said -that they worked very hard on the algorithm until they found the -right one. - -I think what they ended up using (and I hope someone will correct me, -because I am not very confident about this) was the `longest common -subsequence' method. In the LCS problem, you have two sequences of -items: - - a b c d f g h j q z - - a b c d e f g i j k r x y z - -and you want to find the longest sequence of items that is present in -both original sequences in the same order. That is, you want to find -a new sequence I<S> which can be obtained from the first sequence by -deleting some items, and from the secend sequence by deleting other -items. You also want I<S> to be as long as possible. In this case I<S> -is - - a b c d f g j z - -From there it's only a small step to get diff-like output: - - e h i k q r x y - + - + + - + + + - -This module solves the LCS problem. It also includes a canned function -to generate C<diff>-like output. - -It might seem from the example above that the LCS of two sequences is -always pretty obvious, but that's not always the case, especially when -the two sequences have many repeated elements. For example, consider - - a x b y c z p d q - a b c a x b y c z - -A naive approach might start by matching up the C<a> and C<b> that -appear at the beginning of each sequence, like this: - - a x b y c z p d q - a b c a b y c z - -This finds the common subsequence C<a b c z>. But actually, the LCS -is C<a x b y c z>: - - a x b y c z p d q - a b c a x b y c z - -or - - a x b y c z p d q - a b c a x b y c z - -=head1 USAGE - -(See also the README file and several example -scripts include with this module.) - -This module now provides an object-oriented interface that uses less -memory and is easier to use than most of the previous procedural -interfaces. It also still provides several exportable functions. We'll -deal with these in ascending order of difficulty: C<LCS>, -C<LCS_length>, C<LCSidx>, OO interface, C<prepare>, C<diff>, C<sdiff>, -C<traverse_sequences>, and C<traverse_balanced>. - -=head2 C<LCS> - -Given references to two lists of items, LCS returns an array containing -their longest common subsequence. In scalar context, it returns a -reference to such a list. - - @lcs = LCS( \@seq1, \@seq2 ); - $lcsref = LCS( \@seq1, \@seq2 ); - -C<LCS> may be passed an optional third parameter; this is a CODE -reference to a key generation function. See L</KEY GENERATION -FUNCTIONS>. - - @lcs = LCS( \@seq1, \@seq2, \&keyGen, @args ); - $lcsref = LCS( \@seq1, \@seq2, \&keyGen, @args ); - -Additional parameters, if any, will be passed to the key generation -routine. - -=head2 C<LCS_length> - -This is just like C<LCS> except it only returns the length of the -longest common subsequence. This provides a performance gain of about -9% compared to C<LCS>. - -=head2 C<LCSidx> - -Like C<LCS> except it returns references to two arrays. The first array -contains the indices into @seq1 where the LCS items are located. The -second array contains the indices into @seq2 where the LCS items are located. - -Therefore, the following three lists will contain the same values: - - my( $idx1, $idx2 ) = LCSidx( \@seq1, \@seq2 ); - my @list1 = @seq1[ @$idx1 ]; - my @list2 = @seq2[ @$idx2 ]; - my @list3 = LCS( \@seq1, \@seq2 ); - -=head2 C<new> - - $diff = Algorithm::Diffs->new( \@seq1, \@seq2 ); - $diff = Algorithm::Diffs->new( \@seq1, \@seq2, \%opts ); - -C<new> computes the smallest set of additions and deletions necessary -to turn the first sequence into the second and compactly records them -in the object. - -You use the object to iterate over I<hunks>, where each hunk represents -a contiguous section of items which should be added, deleted, replaced, -or left unchanged. - -=over 4 - -The following summary of all of the methods looks a lot like Perl code -but some of the symbols have different meanings: - - [ ] Encloses optional arguments - : Is followed by the default value for an optional argument - | Separates alternate return results - -Method summary: - - $obj = Algorithm::Diff->new( \@seq1, \@seq2, [ \%opts ] ); - $pos = $obj->Next( [ $count : 1 ] ); - $revPos = $obj->Prev( [ $count : 1 ] ); - $obj = $obj->Reset( [ $pos : 0 ] ); - $copy = $obj->Copy( [ $pos, [ $newBase ] ] ); - $oldBase = $obj->Base( [ $newBase ] ); - -Note that all of the following methods C<die> if used on an object that -is "reset" (not currently pointing at any hunk). - - $bits = $obj->Diff( ); - @items|$cnt = $obj->Same( ); - @items|$cnt = $obj->Items( $seqNum ); - @idxs |$cnt = $obj->Range( $seqNum, [ $base ] ); - $minIdx = $obj->Min( $seqNum, [ $base ] ); - $maxIdx = $obj->Max( $seqNum, [ $base ] ); - @values = $obj->Get( @names ); - -Passing in C<undef> for an optional argument is always treated the same -as if no argument were passed in. - -=item C<Next> - - $pos = $diff->Next(); # Move forward 1 hunk - $pos = $diff->Next( 2 ); # Move forward 2 hunks - $pos = $diff->Next(-5); # Move backward 5 hunks - -C<Next> moves the object to point at the next hunk. The object starts -out "reset", which means it isn't pointing at any hunk. If the object -is reset, then C<Next()> moves to the first hunk. - -C<Next> returns a true value iff the move didn't go past the last hunk. -So C<Next(0)> will return true iff the object is not reset. - -Actually, C<Next> returns the object's new position, which is a number -between 1 and the number of hunks (inclusive), or returns a false value. - -=item C<Prev> - -C<Prev($N)> is almost identical to C<Next(-$N)>; it moves to the $Nth -previous hunk. On a 'reset' object, C<Prev()> [and C<Next(-1)>] move -to the last hunk. - -The position returned by C<Prev> is relative to the I<end> of the -hunks; -1 for the last hunk, -2 for the second-to-last, etc. - -=item C<Reset> - - $diff->Reset(); # Reset the object's position - $diff->Reset($pos); # Move to the specified hunk - $diff->Reset(1); # Move to the first hunk - $diff->Reset(-1); # Move to the last hunk - -C<Reset> returns the object, so, for example, you could use -C<< $diff->Reset()->Next(-1) >> to get the number of hunks. - -=item C<Copy> - - $copy = $diff->Copy( $newPos, $newBase ); - -C<Copy> returns a copy of the object. The copy and the orignal object -share most of their data, so making copies takes very little memory. -The copy maintains its own position (separate from the original), which -is the main purpose of copies. It also maintains its own base. - -By default, the copy's position starts out the same as the original -object's position. But C<Copy> takes an optional first argument to set the -new position, so the following three snippets are equivalent: - - $copy = $diff->Copy($pos); - - $copy = $diff->Copy(); - $copy->Reset($pos); - - $copy = $diff->Copy()->Reset($pos); - -C<Copy> takes an optional second argument to set the base for -the copy. If you wish to change the base of the copy but leave -the position the same as in the original, here are two -equivalent ways: - - $copy = $diff->Copy(); - $copy->Base( 0 ); - - $copy = $diff->Copy(undef,0); - -Here are two equivalent way to get a "reset" copy: - - $copy = $diff->Copy(0); - - $copy = $diff->Copy()->Reset(); - -=item C<Diff> - - $bits = $obj->Diff(); - -C<Diff> returns a true value iff the current hunk contains items that are -different between the two sequences. It actually returns one of the -follow 4 values: - -=over 4 - -=item 3 - -C<3==(1|2)>. This hunk contains items from @seq1 and the items -from @seq2 that should replace them. Both sequence 1 and 2 -contain changed items so both the 1 and 2 bits are set. - -=item 2 - -This hunk only contains items from @seq2 that should be inserted (not -items from @seq1). Only sequence 2 contains changed items so only the 2 -bit is set. - -=item 1 - -This hunk only contains items from @seq1 that should be deleted (not -items from @seq2). Only sequence 1 contains changed items so only the 1 -bit is set. - -=item 0 - -This means that the items in this hunk are the same in both sequences. -Neither sequence 1 nor 2 contain changed items so neither the 1 nor the -2 bits are set. - -=back - -=item C<Same> - -C<Same> returns a true value iff the current hunk contains items that -are the same in both sequences. It actually returns the list of items -if they are the same or an emty list if they aren't. In a scalar -context, it returns the size of the list. - -=item C<Items> - - $count = $diff->Items(2); - @items = $diff->Items($seqNum); - -C<Items> returns the (number of) items from the specified sequence that -are part of the current hunk. - -If the current hunk contains only insertions, then -C<< $diff->Items(1) >> will return an empty list (0 in a scalar conext). -If the current hunk contains only deletions, then C<< $diff->Items(2) >> -will return an empty list (0 in a scalar conext). - -If the hunk contains replacements, then both C<< $diff->Items(1) >> and -C<< $diff->Items(2) >> will return different, non-empty lists. - -Otherwise, the hunk contains identical items and all of the following -will return the same lists: - - @items = $diff->Items(1); - @items = $diff->Items(2); - @items = $diff->Same(); - -=item C<Range> - - $count = $diff->Range( $seqNum ); - @indices = $diff->Range( $seqNum ); - @indices = $diff->Range( $seqNum, $base ); - -C<Range> is like C<Items> except that it returns a list of I<indices> to -the items rather than the items themselves. By default, the index of -the first item (in each sequence) is 0 but this can be changed by -calling the C<Base> method. So, by default, the following two snippets -return the same lists: - - @list = $diff->Items(2); - @list = @seq2[ $diff->Range(2) ]; - -You can also specify the base to use as the second argument. So the -following two snippets I<always> return the same lists: - - @list = $diff->Items(1); - @list = @seq1[ $diff->Range(1,0) ]; - -=item C<Base> - - $curBase = $diff->Base(); - $oldBase = $diff->Base($newBase); - -C<Base> sets and/or returns the current base (usually 0 or 1) that is -used when you request range information. The base defaults to 0 so -that range information is returned as array indices. You can set the -base to 1 if you want to report traditional line numbers instead. - -=item C<Min> - - $min1 = $diff->Min(1); - $min = $diff->Min( $seqNum, $base ); - -C<Min> returns the first value that C<Range> would return (given the -same arguments) or returns C<undef> if C<Range> would return an empty -list. - -=item C<Max> - -C<Max> returns the last value that C<Range> would return or C<undef>. - -=item C<Get> - - ( $n, $x, $r ) = $diff->Get(qw( min1 max1 range1 )); - @values = $diff->Get(qw( 0min2 1max2 range2 same base )); - -C<Get> returns one or more scalar values. You pass in a list of the -names of the values you want returned. Each name must match one of the -following regexes: - - /^(-?\d+)?(min|max)[12]$/i - /^(range[12]|same|diff|base)$/i - -The 1 or 2 after a name says which sequence you want the information -for (and where allowed, it is required). The optional number before -"min" or "max" is the base to use. So the following equalities hold: - - $diff->Get('min1') == $diff->Min(1) - $diff->Get('0min2') == $diff->Min(2,0) - -Using C<Get> in a scalar context when you've passed in more than one -name is a fatal error (C<die> is called). - -=back - -=head2 C<prepare> - -Given a reference to a list of items, C<prepare> returns a reference -to a hash which can be used when comparing this sequence to other -sequences with C<LCS> or C<LCS_length>. - - $prep = prepare( \@seq1 ); - for $i ( 0 .. 10_000 ) - { - @lcs = LCS( $prep, $seq[$i] ); - # do something useful with @lcs - } - -C<prepare> may be passed an optional third parameter; this is a CODE -reference to a key generation function. See L</KEY GENERATION -FUNCTIONS>. - - $prep = prepare( \@seq1, \&keyGen ); - for $i ( 0 .. 10_000 ) - { - @lcs = LCS( $seq[$i], $prep, \&keyGen ); - # do something useful with @lcs - } - -Using C<prepare> provides a performance gain of about 50% when calling LCS -many times compared with not preparing. - -=head2 C<diff> - - @diffs = diff( \@seq1, \@seq2 ); - $diffs_ref = diff( \@seq1, \@seq2 ); - -C<diff> computes the smallest set of additions and deletions necessary -to turn the first sequence into the second, and returns a description -of these changes. The description is a list of I<hunks>; each hunk -represents a contiguous section of items which should be added, -deleted, or replaced. (Hunks containing unchanged items are not -included.) - -The return value of C<diff> is a list of hunks, or, in scalar context, a -reference to such a list. If there are no differences, the list will be -empty. - -Here is an example. Calling C<diff> for the following two sequences: - - a b c e h j l m n p - b c d e f j k l m r s t - -would produce the following list: - - ( - [ [ '-', 0, 'a' ] ], - - [ [ '+', 2, 'd' ] ], - - [ [ '-', 4, 'h' ], - [ '+', 4, 'f' ] ], - - [ [ '+', 6, 'k' ] ], - - [ [ '-', 8, 'n' ], - [ '-', 9, 'p' ], - [ '+', 9, 'r' ], - [ '+', 10, 's' ], - [ '+', 11, 't' ] ], - ) - -There are five hunks here. The first hunk says that the C<a> at -position 0 of the first sequence should be deleted (C<->). The second -hunk says that the C<d> at position 2 of the second sequence should -be inserted (C<+>). The third hunk says that the C<h> at position 4 -of the first sequence should be removed and replaced with the C<f> -from position 4 of the second sequence. And so on. - -C<diff> may be passed an optional third parameter; this is a CODE -reference to a key generation function. See L</KEY GENERATION -FUNCTIONS>. - -Additional parameters, if any, will be passed to the key generation -routine. - -=head2 C<sdiff> - - @sdiffs = sdiff( \@seq1, \@seq2 ); - $sdiffs_ref = sdiff( \@seq1, \@seq2 ); - -C<sdiff> computes all necessary components to show two sequences -and their minimized differences side by side, just like the -Unix-utility I<sdiff> does: - - same same - before | after - old < - - - > new - -It returns a list of array refs, each pointing to an array of -display instructions. In scalar context it returns a reference -to such a list. If there are no differences, the list will have one -entry per item, each indicating that the item was unchanged. - -Display instructions consist of three elements: A modifier indicator -(C<+>: Element added, C<->: Element removed, C<u>: Element unmodified, -C<c>: Element changed) and the value of the old and new elements, to -be displayed side-by-side. - -An C<sdiff> of the following two sequences: - - a b c e h j l m n p - b c d e f j k l m r s t - -results in - - ( [ '-', 'a', '' ], - [ 'u', 'b', 'b' ], - [ 'u', 'c', 'c' ], - [ '+', '', 'd' ], - [ 'u', 'e', 'e' ], - [ 'c', 'h', 'f' ], - [ 'u', 'j', 'j' ], - [ '+', '', 'k' ], - [ 'u', 'l', 'l' ], - [ 'u', 'm', 'm' ], - [ 'c', 'n', 'r' ], - [ 'c', 'p', 's' ], - [ '+', '', 't' ], - ) - -C<sdiff> may be passed an optional third parameter; this is a CODE -reference to a key generation function. See L</KEY GENERATION -FUNCTIONS>. - -Additional parameters, if any, will be passed to the key generation -routine. - -=head2 C<compact_diff> - -C<compact_diff> is much like C<sdiff> except it returns a much more -compact description consisting of just one flat list of indices. An -example helps explain the format: - - my @a = qw( a b c e h j l m n p ); - my @b = qw( b c d e f j k l m r s t ); - @cdiff = compact_diff( \@a, \@b ); - # Returns: - # @a @b @a @b - # start start values values - ( 0, 0, # = - 0, 0, # a ! - 1, 0, # b c = b c - 3, 2, # ! d - 3, 3, # e = e - 4, 4, # f ! h - 5, 5, # j = j - 6, 6, # ! k - 6, 7, # l m = l m - 8, 9, # n p ! r s t - 10, 12, # - ); - -The 0th, 2nd, 4th, etc. entries are all indices into @seq1 (@a in the -above example) indicating where a hunk begins. The 1st, 3rd, 5th, etc. -entries are all indices into @seq2 (@b in the above example) indicating -where the same hunk begins. - -So each pair of indices (except the last pair) describes where a hunk -begins (in each sequence). Since each hunk must end at the item just -before the item that starts the next hunk, the next pair of indices can -be used to determine where the hunk ends. - -So, the first 4 entries (0..3) describe the first hunk. Entries 0 and 1 -describe where the first hunk begins (and so are always both 0). -Entries 2 and 3 describe where the next hunk begins, so subtracting 1 -from each tells us where the first hunk ends. That is, the first hunk -contains items C<$diff[0]> through C<$diff[2] - 1> of the first sequence -and contains items C<$diff[1]> through C<$diff[3] - 1> of the second -sequence. - -In other words, the first hunk consists of the following two lists of items: - - # 1st pair 2nd pair - # of indices of indices - @list1 = @a[ $cdiff[0] .. $cdiff[2]-1 ]; - @list2 = @b[ $cdiff[1] .. $cdiff[3]-1 ]; - # Hunk start Hunk end - -Note that the hunks will always alternate between those that are part of -the LCS (those that contain unchanged items) and those that contain -changes. This means that all we need to be told is whether the first -hunk is a 'same' or 'diff' hunk and we can determine which of the other -hunks contain 'same' items or 'diff' items. - -By convention, we always make the first hunk contain unchanged items. -So the 1st, 3rd, 5th, etc. hunks (all odd-numbered hunks if you start -counting from 1) all contain unchanged items. And the 2nd, 4th, 6th, -etc. hunks (all even-numbered hunks if you start counting from 1) all -contain changed items. - -Since @a and @b don't begin with the same value, the first hunk in our -example is empty (otherwise we'd violate the above convention). Note -that the first 4 index values in our example are all zero. Plug these -values into our previous code block and we get: - - @hunk1a = @a[ 0 .. 0-1 ]; - @hunk1b = @b[ 0 .. 0-1 ]; - -And C<0..-1> returns the empty list. - -Move down one pair of indices (2..5) and we get the offset ranges for -the second hunk, which contains changed items. - -Since C<@diff[2..5]> contains (0,0,1,0) in our example, the second hunk -consists of these two lists of items: - - @hunk2a = @a[ $cdiff[2] .. $cdiff[4]-1 ]; - @hunk2b = @b[ $cdiff[3] .. $cdiff[5]-1 ]; - # or - @hunk2a = @a[ 0 .. 1-1 ]; - @hunk2b = @b[ 0 .. 0-1 ]; - # or - @hunk2a = @a[ 0 .. 0 ]; - @hunk2b = @b[ 0 .. -1 ]; - # or - @hunk2a = ( 'a' ); - @hunk2b = ( ); - -That is, we would delete item 0 ('a') from @a. - -Since C<@diff[4..7]> contains (1,0,3,2) in our example, the third hunk -consists of these two lists of items: - - @hunk3a = @a[ $cdiff[4] .. $cdiff[6]-1 ]; - @hunk3a = @b[ $cdiff[5] .. $cdiff[7]-1 ]; - # or - @hunk3a = @a[ 1 .. 3-1 ]; - @hunk3a = @b[ 0 .. 2-1 ]; - # or - @hunk3a = @a[ 1 .. 2 ]; - @hunk3a = @b[ 0 .. 1 ]; - # or - @hunk3a = qw( b c ); - @hunk3a = qw( b c ); - -Note that this third hunk contains unchanged items as our convention demands. - -You can continue this process until you reach the last two indices, -which will always be the number of items in each sequence. This is -required so that subtracting one from each will give you the indices to -the last items in each sequence. - -=head2 C<traverse_sequences> - -C<traverse_sequences> used to be the most general facility provided by -this module (the new OO interface is more powerful and much easier to -use). - -Imagine that there are two arrows. Arrow A points to an element of -sequence A, and arrow B points to an element of the sequence B. -Initially, the arrows point to the first elements of the respective -sequences. C<traverse_sequences> will advance the arrows through the -sequences one element at a time, calling an appropriate user-specified -callback function before each advance. It willadvance the arrows in -such a way that if there are equal elements C<$A[$i]> and C<$B[$j]> -which are equal and which are part of the LCS, there will be some moment -during the execution of C<traverse_sequences> when arrow A is pointing -to C<$A[$i]> and arrow B is pointing to C<$B[$j]>. When this happens, -C<traverse_sequences> will call the C<MATCH> callback function and then -it will advance both arrows. - -Otherwise, one of the arrows is pointing to an element of its sequence -that is not part of the LCS. C<traverse_sequences> will advance that -arrow and will call the C<DISCARD_A> or the C<DISCARD_B> callback, -depending on which arrow it advanced. If both arrows point to elements -that are not part of the LCS, then C<traverse_sequences> will advance -one of them and call the appropriate callback, but it is not specified -which it will call. - -The arguments to C<traverse_sequences> are the two sequences to -traverse, and a hash which specifies the callback functions, like this: - - traverse_sequences( - \@seq1, \@seq2, - { MATCH => $callback_1, - DISCARD_A => $callback_2, - DISCARD_B => $callback_3, - } - ); - -Callbacks for MATCH, DISCARD_A, and DISCARD_B are invoked with at least -the indices of the two arrows as their arguments. They are not expected -to return any values. If a callback is omitted from the table, it is -not called. - -Callbacks for A_FINISHED and B_FINISHED are invoked with at least the -corresponding index in A or B. - -If arrow A reaches the end of its sequence, before arrow B does, -C<traverse_sequences> will call the C<A_FINISHED> callback when it -advances arrow B, if there is such a function; if not it will call -C<DISCARD_B> instead. Similarly if arrow B finishes first. -C<traverse_sequences> returns when both arrows are at the ends of their -respective sequences. It returns true on success and false on failure. -At present there is no way to fail. - -C<traverse_sequences> may be passed an optional fourth parameter; this -is a CODE reference to a key generation function. See L</KEY GENERATION -FUNCTIONS>. - -Additional parameters, if any, will be passed to the key generation function. - -If you want to pass additional parameters to your callbacks, but don't -need a custom key generation function, you can get the default by -passing undef: - - traverse_sequences( - \@seq1, \@seq2, - { MATCH => $callback_1, - DISCARD_A => $callback_2, - DISCARD_B => $callback_3, - }, - undef, # default key-gen - $myArgument1, - $myArgument2, - $myArgument3, - ); - -C<traverse_sequences> does not have a useful return value; you are -expected to plug in the appropriate behavior with the callback -functions. - -=head2 C<traverse_balanced> - -C<traverse_balanced> is an alternative to C<traverse_sequences>. It -uses a different algorithm to iterate through the entries in the -computed LCS. Instead of sticking to one side and showing element changes -as insertions and deletions only, it will jump back and forth between -the two sequences and report I<changes> occurring as deletions on one -side followed immediatly by an insertion on the other side. - -In addition to the C<DISCARD_A>, C<DISCARD_B>, and C<MATCH> callbacks -supported by C<traverse_sequences>, C<traverse_balanced> supports -a C<CHANGE> callback indicating that one element got C<replaced> by another: - - traverse_balanced( - \@seq1, \@seq2, - { MATCH => $callback_1, - DISCARD_A => $callback_2, - DISCARD_B => $callback_3, - CHANGE => $callback_4, - } - ); - -If no C<CHANGE> callback is specified, C<traverse_balanced> -will map C<CHANGE> events to C<DISCARD_A> and C<DISCARD_B> actions, -therefore resulting in a similar behaviour as C<traverse_sequences> -with different order of events. - -C<traverse_balanced> might be a bit slower than C<traverse_sequences>, -noticable only while processing huge amounts of data. - -The C<sdiff> function of this module -is implemented as call to C<traverse_balanced>. - -C<traverse_balanced> does not have a useful return value; you are expected to -plug in the appropriate behavior with the callback functions. - -=head1 KEY GENERATION FUNCTIONS - -Most of the functions accept an optional extra parameter. This is a -CODE reference to a key generating (hashing) function that should return -a string that uniquely identifies a given element. It should be the -case that if two elements are to be considered equal, their keys should -be the same (and the other way around). If no key generation function -is provided, the key will be the element as a string. - -By default, comparisons will use "eq" and elements will be turned into keys -using the default stringizing operator '""'. - -Where this is important is when you're comparing something other than -strings. If it is the case that you have multiple different objects -that should be considered to be equal, you should supply a key -generation function. Otherwise, you have to make sure that your arrays -contain unique references. - -For instance, consider this example: - - package Person; - - sub new - { - my $package = shift; - return bless { name => '', ssn => '', @_ }, $package; - } - - sub clone - { - my $old = shift; - my $new = bless { %$old }, ref($old); - } - - sub hash - { - return shift()->{'ssn'}; - } - - my $person1 = Person->new( name => 'Joe', ssn => '123-45-6789' ); - my $person2 = Person->new( name => 'Mary', ssn => '123-47-0000' ); - my $person3 = Person->new( name => 'Pete', ssn => '999-45-2222' ); - my $person4 = Person->new( name => 'Peggy', ssn => '123-45-9999' ); - my $person5 = Person->new( name => 'Frank', ssn => '000-45-9999' ); - -If you did this: - - my $array1 = [ $person1, $person2, $person4 ]; - my $array2 = [ $person1, $person3, $person4, $person5 ]; - Algorithm::Diff::diff( $array1, $array2 ); - -everything would work out OK (each of the objects would be converted -into a string like "Person=HASH(0x82425b0)" for comparison). - -But if you did this: - - my $array1 = [ $person1, $person2, $person4 ]; - my $array2 = [ $person1, $person3, $person4->clone(), $person5 ]; - Algorithm::Diff::diff( $array1, $array2 ); - -$person4 and $person4->clone() (which have the same name and SSN) -would be seen as different objects. If you wanted them to be considered -equivalent, you would have to pass in a key generation function: - - my $array1 = [ $person1, $person2, $person4 ]; - my $array2 = [ $person1, $person3, $person4->clone(), $person5 ]; - Algorithm::Diff::diff( $array1, $array2, \&Person::hash ); - -This would use the 'ssn' field in each Person as a comparison key, and -so would consider $person4 and $person4->clone() as equal. - -You may also pass additional parameters to the key generation function -if you wish. - -=head1 ERROR CHECKING - -If you pass these routines a non-reference and they expect a reference, -they will die with a message. - -=head1 AUTHOR - -This version released by Tye McQueen (http://perlmonks.org/?node=tye). - -=head1 LICENSE - -Parts Copyright (c) 2000-2004 Ned Konz. All rights reserved. -Parts by Tye McQueen. - -This program is free software; you can redistribute it and/or modify it -under the same terms as Perl. - -=head1 MAILING LIST - -Mark-Jason still maintains a mailing list. To join a low-volume mailing -list for announcements related to diff and Algorithm::Diff, send an -empty mail message to mjd-perl-diff-request@plover.com. - -=head1 CREDITS - -Versions through 0.59 (and much of this documentation) were written by: - -Mark-Jason Dominus, mjd-perl-diff@plover.com - -This version borrows some documentation and routine names from -Mark-Jason's, but Diff.pm's code was completely replaced. - -This code was adapted from the Smalltalk code of Mario Wolczko -<mario@wolczko.com>, which is available at -ftp://st.cs.uiuc.edu/pub/Smalltalk/MANCHESTER/manchester/4.0/diff.st - -C<sdiff> and C<traverse_balanced> were written by Mike Schilli -<m@perlmeister.com>. - -The algorithm is that described in -I<A Fast Algorithm for Computing Longest Common Subsequences>, -CACM, vol.20, no.5, pp.350-353, May 1977, with a few -minor improvements to improve the speed. - -Much work was done by Ned Konz (perl@bike-nomad.com). - -The OO interface and some other changes are by Tye McQueen. - -=cut diff --git a/src/tests/Make.tests b/src/tests/Make.tests deleted file mode 100644 index 358e69724b156b15dc98c76301367015ee3b6a59..0000000000000000000000000000000000000000 --- a/src/tests/Make.tests +++ /dev/null @@ -1,76 +0,0 @@ -# -*- makefile -*- - -include $(patsubst %,$(SRCDIR)/%/Make.tests,$(TEST_SUBDIRS)) - -PROGS = $(foreach subdir,$(TEST_SUBDIRS),$($(subdir)_PROGS)) -TESTS = $(foreach subdir,$(TEST_SUBDIRS),$($(subdir)_TESTS)) -EXTRA_GRADES = $(foreach subdir,$(TEST_SUBDIRS),$($(subdir)_EXTRA_GRADES)) - -OUTPUTS = $(addsuffix .output,$(TESTS) $(EXTRA_GRADES)) -ERRORS = $(addsuffix .errors,$(TESTS) $(EXTRA_GRADES)) -RESULTS = $(addsuffix .result,$(TESTS) $(EXTRA_GRADES)) - -ifdef PROGS -include ../../Makefile.userprog -endif - -TIMEOUT = 60 - -clean:: - rm -f $(OUTPUTS) $(ERRORS) $(RESULTS) - -grade:: results - $(SRCDIR)/tests/make-grade $(SRCDIR) $< $(GRADING_FILE) | tee $@ - -check:: results - @cat $< - @COUNT="`egrep '^(pass|FAIL) ' $< | wc -l | sed 's/[ ]//g;'`"; \ - FAILURES="`egrep '^FAIL ' $< | wc -l | sed 's/[ ]//g;'`"; \ - if [ $$FAILURES = 0 ]; then \ - echo "All $$COUNT tests passed."; \ - else \ - echo "$$FAILURES of $$COUNT tests failed."; \ - exit 1; \ - fi - -results: $(RESULTS) - @for d in $(TESTS) $(EXTRA_GRADES); do \ - if echo PASS | cmp -s $$d.result -; then \ - echo "pass $$d"; \ - else \ - echo "FAIL $$d"; \ - fi; \ - done > $@ - -outputs:: $(OUTPUTS) - -$(foreach prog,$(PROGS),$(eval $(prog).output: $(prog))) -$(foreach test,$(TESTS),$(eval $(test).output: $($(test)_PUTFILES))) -$(foreach test,$(TESTS),$(eval $(test).output: TEST = $(test))) - -# Prevent an environment variable VERBOSE from surprising us. -VERBOSE = - -TESTCMD = pintos -v -k -T $(TIMEOUT) -TESTCMD += $(SIMULATOR) -TESTCMD += $(PINTOSOPTS) -ifeq ($(filter userprog, $(KERNEL_SUBDIRS)), userprog) -TESTCMD += $(FILESYSSOURCE) -TESTCMD += $(foreach file,$(PUTFILES),-p $(file) -a $(notdir $(file))) -endif -ifeq ($(filter vm, $(KERNEL_SUBDIRS)), vm) -TESTCMD += --swap-size=4 -endif -TESTCMD += -- -q -TESTCMD += $(KERNELFLAGS) -ifeq ($(filter userprog, $(KERNEL_SUBDIRS)), userprog) -TESTCMD += -f -endif -TESTCMD += $(if $($(TEST)_ARGS),run '$(*F) $($(TEST)_ARGS)',run $(*F)) -TESTCMD += < /dev/null -TESTCMD += 2> $(TEST).errors $(if $(VERBOSE),|tee,>) $(TEST).output -%.output: kernel.bin loader.bin - $(TESTCMD) - -%.result: %.ck %.output - perl -I$(SRCDIR) $< $* $@ diff --git a/src/tests/arc4.c b/src/tests/arc4.c deleted file mode 100644 index b033cc641133f917ff0903ad05389af6d39f87f9..0000000000000000000000000000000000000000 --- a/src/tests/arc4.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <stdint.h> -#include "tests/arc4.h" - -/* Swap bytes. */ -static inline void -swap_byte (uint8_t *a, uint8_t *b) -{ - uint8_t t = *a; - *a = *b; - *b = t; -} - -void -arc4_init (struct arc4 *arc4, const void *key_, size_t size) -{ - const uint8_t *key = key_; - size_t key_idx; - uint8_t *s; - int i, j; - - s = arc4->s; - arc4->i = arc4->j = 0; - for (i = 0; i < 256; i++) - s[i] = i; - for (key_idx = 0, i = j = 0; i < 256; i++) - { - j = (j + s[i] + key[key_idx]) & 255; - swap_byte (s + i, s + j); - if (++key_idx >= size) - key_idx = 0; - } -} - -void -arc4_crypt (struct arc4 *arc4, void *buf_, size_t size) -{ - uint8_t *buf = buf_; - uint8_t *s; - uint8_t i, j; - - s = arc4->s; - i = arc4->i; - j = arc4->j; - while (size-- > 0) - { - i += 1; - j += s[i]; - swap_byte (s + i, s + j); - *buf++ ^= s[(s[i] + s[j]) & 255]; - } - arc4->i = i; - arc4->j = j; -} diff --git a/src/tests/arc4.h b/src/tests/arc4.h deleted file mode 100644 index 61c533a2f9d9fa20951c06caa9f004455b33ca96..0000000000000000000000000000000000000000 --- a/src/tests/arc4.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef TESTS_ARC4_H -#define TESTS_ARC4_H - -#include <stddef.h> -#include <stdint.h> - -/* Alleged RC4 algorithm encryption state. */ -struct arc4 - { - uint8_t s[256]; - uint8_t i, j; - }; - -void arc4_init (struct arc4 *, const void *, size_t); -void arc4_crypt (struct arc4 *, void *, size_t); - -#endif /* tests/arc4.h */ diff --git a/src/tests/arc4.pm b/src/tests/arc4.pm deleted file mode 100644 index df19216cead5d9feafc9da6a10cfcb7362e1649a..0000000000000000000000000000000000000000 --- a/src/tests/arc4.pm +++ /dev/null @@ -1,29 +0,0 @@ -use strict; -use warnings; - -sub arc4_init { - my ($key) = @_; - my (@s) = 0...255; - my ($j) = 0; - for my $i (0...255) { - $j = ($j + $s[$i] + ord (substr ($key, $i % length ($key), 1))) & 0xff; - @s[$i, $j] = @s[$j, $i]; - } - return (0, 0, @s); -} - -sub arc4_crypt { - my ($arc4, $buf) = @_; - my ($i, $j, @s) = @$arc4; - my ($out) = ""; - for my $c (split (//, $buf)) { - $i = ($i + 1) & 0xff; - $j = ($j + $s[$i]) & 0xff; - @s[$i, $j] = @s[$j, $i]; - $out .= chr (ord ($c) ^ $s[($s[$i] + $s[$j]) & 0xff]); - } - @$arc4 = ($i, $j, @s); - return $out; -} - -1; diff --git a/src/tests/cksum.c b/src/tests/cksum.c deleted file mode 100644 index 92a2995f7eb986dcab1e0348c10fff8b9a6bcee5..0000000000000000000000000000000000000000 --- a/src/tests/cksum.c +++ /dev/null @@ -1,92 +0,0 @@ -/* crctab[] and cksum() are from the `cksum' entry in SUSv3. */ - -#include <stdint.h> -#include "tests/cksum.h" - -static unsigned long crctab[] = { - 0x00000000, - 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, - 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, - 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, - 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, - 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, - 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, - 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, - 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, - 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, - 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, - 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, - 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, - 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, - 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, - 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, - 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, - 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, - 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, - 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, - 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, - 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, - 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, - 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, - 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, - 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, - 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, - 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, - 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, - 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, - 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, - 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, - 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, - 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, - 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, - 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, - 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, - 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, - 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, - 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, - 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, - 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, - 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 -}; - -/* This is the algorithm used by the Posix `cksum' utility. */ -unsigned long -cksum (const void *b_, size_t n) -{ - const unsigned char *b = b_; - uint32_t s = 0; - size_t i; - for (i = n; i > 0; --i) - { - unsigned char c = *b++; - s = (s << 8) ^ crctab[(s >> 24) ^ c]; - } - while (n != 0) - { - unsigned char c = n; - n >>= 8; - s = (s << 8) ^ crctab[(s >> 24) ^ c]; - } - return ~s; -} - -#ifdef STANDALONE_TEST -#include <stdio.h> -int -main (void) -{ - char buf[65536]; - int n = fread (buf, 1, sizeof buf, stdin); - printf ("%lu\n", cksum (buf, n)); - return 0; -} -#endif diff --git a/src/tests/cksum.h b/src/tests/cksum.h deleted file mode 100644 index 23a1fe963c5ef4192f278d51e0b16ba95d335780..0000000000000000000000000000000000000000 --- a/src/tests/cksum.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef TESTS_CKSUM_H -#define TESTS_CKSUM_H - -#include <stddef.h> - -unsigned long cksum(const void *, size_t); - -#endif /* tests/cksum.h */ diff --git a/src/tests/cksum.pm b/src/tests/cksum.pm deleted file mode 100644 index 73be5f2e0c3723b28f1590cb662d1a1b70ed5296..0000000000000000000000000000000000000000 --- a/src/tests/cksum.pm +++ /dev/null @@ -1,87 +0,0 @@ -# From the `cksum' entry in SUSv3. - -use strict; -use warnings; - -my (@crctab) = - (0x00000000, - 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, - 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, - 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, - 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f, - 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, - 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, - 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, - 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe, - 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, - 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, - 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, - 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, - 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07, - 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, - 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, - 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, - 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, - 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, - 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, - 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f, - 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, - 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, - 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, - 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629, - 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, - 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, - 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, - 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8, - 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, - 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, - 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, - 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, - 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21, - 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, - 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087, - 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, - 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, - 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, - 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, - 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09, - 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, - 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4); - -sub cksum { - my ($b) = @_; - my ($n) = length ($b); - my ($s) = 0; - for my $i (0...$n - 1) { - my ($c) = ord (substr ($b, $i, 1)); - $s = ($s << 8) ^ $crctab[($s >> 24) ^ $c]; - $s &= 0xffff_ffff; - } - while ($n != 0) { - my ($c) = $n & 0xff; - $n >>= 8; - $s = ($s << 8) ^ $crctab[($s >> 24) ^ $c]; - $s &= 0xffff_ffff; - } - return ~$s & 0xffff_ffff; -} - -sub cksum_file { - my ($file) = @_; - open (FILE, '<', $file) or die "$file: open: $!\n"; - my ($data); - sysread (FILE, $data, -s FILE) == -s FILE or die "$file: read: $!\n"; - close (FILE); - return cksum ($data); -} - -1; diff --git a/src/tests/filesys/Grading.no-vm b/src/tests/filesys/Grading.no-vm deleted file mode 100644 index ee98fc1f2827b320940e27d90e399b9f98e48396..0000000000000000000000000000000000000000 --- a/src/tests/filesys/Grading.no-vm +++ /dev/null @@ -1,18 +0,0 @@ -# Percentage of the testing point total designated for each set of -# tests. - -# This project is primarily about implementing the file system, but -# all the previous functionality should work too. It's not too easy -# to screw it up, thus the emphasis. - -# 65% for extended file system features. -30% tests/filesys/extended/Rubric.functionality -15% tests/filesys/extended/Rubric.robustness -20% tests/filesys/extended/Rubric.persistence - -# 20% to not break the provided file system features. -20% tests/filesys/base/Rubric - -# 15% for the rest. -10% tests/userprog/Rubric.functionality -5% tests/userprog/Rubric.robustness diff --git a/src/tests/filesys/Grading.with-vm b/src/tests/filesys/Grading.with-vm deleted file mode 100644 index e7c041e497c887c998d89901dd28874f03f2fc5a..0000000000000000000000000000000000000000 --- a/src/tests/filesys/Grading.with-vm +++ /dev/null @@ -1,22 +0,0 @@ -# Percentage of the testing point total designated for each set of -# tests. - -# This project is primarily about implementing the file system, but -# all the previous functionality should work too. It's not too easy -# to screw it up, thus the emphasis. - -# 65% for extended file system features. -30% tests/filesys/extended/Rubric.functionality -15% tests/filesys/extended/Rubric.robustness -20% tests/filesys/extended/Rubric.persistence - -# 20% to not break the provided file system features. -20% tests/filesys/base/Rubric - -# 15% for the rest. -10% tests/userprog/Rubric.functionality -5% tests/userprog/Rubric.robustness - -# Up to 10% bonus for working VM functionality. -8% tests/vm/Rubric.functionality -2% tests/vm/Rubric.robustness diff --git a/src/tests/filesys/base/Make.tests b/src/tests/filesys/base/Make.tests deleted file mode 100644 index e475222a4c9d7a1a1d5cc218e58210509a484add..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/Make.tests +++ /dev/null @@ -1,18 +0,0 @@ -# -*- makefile -*- - -tests/filesys/base_TESTS = $(addprefix tests/filesys/base/,lg-create \ -lg-full lg-random lg-seq-block lg-seq-random sm-create sm-full \ -sm-random sm-seq-block sm-seq-random syn-read syn-remove syn-write) - -tests/filesys/base_PROGS = $(tests/filesys/base_TESTS) $(addprefix \ -tests/filesys/base/,child-syn-read child-syn-wrt) - -$(foreach prog,$(tests/filesys/base_PROGS), \ - $(eval $(prog)_SRC += $(prog).c tests/lib.c tests/filesys/seq-test.c)) -$(foreach prog,$(tests/filesys/base_TESTS), \ - $(eval $(prog)_SRC += tests/main.c)) - -tests/filesys/base/syn-read_PUTFILES = tests/filesys/base/child-syn-read -tests/filesys/base/syn-write_PUTFILES = tests/filesys/base/child-syn-wrt - -tests/filesys/base/syn-read.output: TIMEOUT = 300 diff --git a/src/tests/filesys/base/Rubric b/src/tests/filesys/base/Rubric deleted file mode 100644 index 49a9d15949ee31350fec402b4ca195602d62606a..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/Rubric +++ /dev/null @@ -1,19 +0,0 @@ -Functionality of base file system: -- Test basic support for small files. -1 sm-create -2 sm-full -2 sm-random -2 sm-seq-block -3 sm-seq-random - -- Test basic support for large files. -1 lg-create -2 lg-full -2 lg-random -2 lg-seq-block -3 lg-seq-random - -- Test synchronized multiprogram access to files. -4 syn-read -4 syn-write -2 syn-remove diff --git a/src/tests/filesys/base/child-syn-read.c b/src/tests/filesys/base/child-syn-read.c deleted file mode 100644 index 77a5e26252f6116cb2b25e2c7add0bb5e9787cb1..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/child-syn-read.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Child process for syn-read test. - Reads the contents of a test file a byte at a time, in the - hope that this will take long enough that we can get a - significant amount of contention in the kernel file system - code. */ - -#include <random.h> -#include <stdio.h> -#include <stdlib.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/filesys/base/syn-read.h" - -const char *test_name = "child-syn-read"; - -static char buf[BUF_SIZE]; - -int -main (int argc, const char *argv[]) -{ - int child_idx; - int fd; - size_t i; - - quiet = true; - - CHECK (argc == 2, "argc must be 2, actually %d", argc); - child_idx = atoi (argv[1]); - - random_init (0); - random_bytes (buf, sizeof buf); - - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - for (i = 0; i < sizeof buf; i++) - { - char c; - CHECK (read (fd, &c, 1) > 0, "read \"%s\"", file_name); - compare_bytes (&c, buf + i, 1, i, file_name); - } - close (fd); - - return child_idx; -} - diff --git a/src/tests/filesys/base/child-syn-wrt.c b/src/tests/filesys/base/child-syn-wrt.c deleted file mode 100644 index 1b5258449ac708a042818a114a5dff137fd9cb17..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/child-syn-wrt.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Child process for syn-read test. - Writes into part of a test file. Other processes will be - writing into other parts at the same time. */ - -#include <random.h> -#include <stdlib.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/filesys/base/syn-write.h" - -char buf[BUF_SIZE]; - -int -main (int argc, char *argv[]) -{ - int child_idx; - int fd; - - quiet = true; - - CHECK (argc == 2, "argc must be 2, actually %d", argc); - child_idx = atoi (argv[1]); - - random_init (0); - random_bytes (buf, sizeof buf); - - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - seek (fd, CHUNK_SIZE * child_idx); - CHECK (write (fd, buf + CHUNK_SIZE * child_idx, CHUNK_SIZE) > 0, - "write \"%s\"", file_name); - msg ("close \"%s\"", file_name); - close (fd); - - return child_idx; -} diff --git a/src/tests/filesys/base/full.inc b/src/tests/filesys/base/full.inc deleted file mode 100644 index 38a03969045f050540c258440775211a378180c8..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/full.inc +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- c -*- */ - -#include "tests/filesys/seq-test.h" -#include "tests/main.h" - -static char buf[TEST_SIZE]; - -static size_t -return_test_size (void) -{ - return TEST_SIZE; -} - -void -test_main (void) -{ - seq_test ("quux", - buf, sizeof buf, sizeof buf, - return_test_size, NULL); -} diff --git a/src/tests/filesys/base/lg-create.c b/src/tests/filesys/base/lg-create.c deleted file mode 100644 index 5c45eee49ee562832e9fc7d365ab33a8e1c23ab1..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-create.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Tests that create properly zeros out the contents of a fairly - large file. */ - -#define TEST_SIZE 75678 -#include "tests/filesys/create.inc" diff --git a/src/tests/filesys/base/lg-create.ck b/src/tests/filesys/base/lg-create.ck deleted file mode 100644 index 86b2c513b778a0176c10eca37f44ec08112d3afd..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-create.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(lg-create) begin -(lg-create) create "blargle" -(lg-create) open "blargle" for verification -(lg-create) verified contents of "blargle" -(lg-create) close "blargle" -(lg-create) end -EOF -pass; diff --git a/src/tests/filesys/base/lg-full.c b/src/tests/filesys/base/lg-full.c deleted file mode 100644 index 5f7234d087b742a4ae153abcd7a5f478f8c40501..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-full.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Writes out the contents of a fairly large file all at once, - and then reads it back to make sure that it was written - properly. */ - -#define TEST_SIZE 75678 -#include "tests/filesys/base/full.inc" diff --git a/src/tests/filesys/base/lg-full.ck b/src/tests/filesys/base/lg-full.ck deleted file mode 100644 index ee6c7f9e66ed5204a0937d9630d21250880abf4d..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-full.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(lg-full) begin -(lg-full) create "quux" -(lg-full) open "quux" -(lg-full) writing "quux" -(lg-full) close "quux" -(lg-full) open "quux" for verification -(lg-full) verified contents of "quux" -(lg-full) close "quux" -(lg-full) end -EOF -pass; diff --git a/src/tests/filesys/base/lg-random.c b/src/tests/filesys/base/lg-random.c deleted file mode 100644 index b6f887351a0ad8b007d20e863cd85faf60792a8f..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-random.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Writes out the content of a fairly large file in random order, - then reads it back in random order to verify that it was - written properly. */ - -#define BLOCK_SIZE 512 -#define TEST_SIZE (512 * 150) -#include "tests/filesys/base/random.inc" diff --git a/src/tests/filesys/base/lg-random.ck b/src/tests/filesys/base/lg-random.ck deleted file mode 100644 index dd9f1dd0f590ed6ca95181cb327e6f4a85333ac7..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-random.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(lg-random) begin -(lg-random) create "bazzle" -(lg-random) open "bazzle" -(lg-random) write "bazzle" in random order -(lg-random) read "bazzle" in random order -(lg-random) close "bazzle" -(lg-random) end -EOF -pass; diff --git a/src/tests/filesys/base/lg-seq-block.c b/src/tests/filesys/base/lg-seq-block.c deleted file mode 100644 index 580c30bd9040a9bbcc8195022dd48363ad558926..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-seq-block.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Writes out a fairly large file sequentially, one fixed-size - block at a time, then reads it back to verify that it was - written properly. */ - -#define TEST_SIZE 75678 -#define BLOCK_SIZE 513 -#include "tests/filesys/base/seq-block.inc" diff --git a/src/tests/filesys/base/lg-seq-block.ck b/src/tests/filesys/base/lg-seq-block.ck deleted file mode 100644 index b78908119e73409581dd3161976a94ee50e9712f..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-seq-block.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(lg-seq-block) begin -(lg-seq-block) create "noodle" -(lg-seq-block) open "noodle" -(lg-seq-block) writing "noodle" -(lg-seq-block) close "noodle" -(lg-seq-block) open "noodle" for verification -(lg-seq-block) verified contents of "noodle" -(lg-seq-block) close "noodle" -(lg-seq-block) end -EOF -pass; diff --git a/src/tests/filesys/base/lg-seq-random.c b/src/tests/filesys/base/lg-seq-random.c deleted file mode 100644 index fbb6bba1f86767d19fd34960a3d878864da45fc5..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-seq-random.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Writes out a fairly large file sequentially, one random-sized - block at a time, then reads it back to verify that it was - written properly. */ - -#define TEST_SIZE 75678 -#include "tests/filesys/base/seq-random.inc" diff --git a/src/tests/filesys/base/lg-seq-random.ck b/src/tests/filesys/base/lg-seq-random.ck deleted file mode 100644 index 6b2dc82a199faa93df8e627fce9981ef31b5bb49..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/lg-seq-random.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(lg-seq-random) begin -(lg-seq-random) create "nibble" -(lg-seq-random) open "nibble" -(lg-seq-random) writing "nibble" -(lg-seq-random) close "nibble" -(lg-seq-random) open "nibble" for verification -(lg-seq-random) verified contents of "nibble" -(lg-seq-random) close "nibble" -(lg-seq-random) end -EOF -pass; diff --git a/src/tests/filesys/base/random.inc b/src/tests/filesys/base/random.inc deleted file mode 100644 index eeeea68656408efc8e29e7bad8ba4ff013ead40d..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/random.inc +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- c -*- */ - -#include <random.h> -#include <stdio.h> -#include <string.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -#if TEST_SIZE % BLOCK_SIZE != 0 -#error TEST_SIZE must be a multiple of BLOCK_SIZE -#endif - -#define BLOCK_CNT (TEST_SIZE / BLOCK_SIZE) - -char buf[TEST_SIZE]; -int order[BLOCK_CNT]; - -void -test_main (void) -{ - const char *file_name = "bazzle"; - int fd; - size_t i; - - random_init (57); - random_bytes (buf, sizeof buf); - - for (i = 0; i < BLOCK_CNT; i++) - order[i] = i; - - CHECK (create (file_name, TEST_SIZE), "create \"%s\"", file_name); - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - - msg ("write \"%s\" in random order", file_name); - shuffle (order, BLOCK_CNT, sizeof *order); - for (i = 0; i < BLOCK_CNT; i++) - { - size_t ofs = BLOCK_SIZE * order[i]; - seek (fd, ofs); - if (write (fd, buf + ofs, BLOCK_SIZE) != BLOCK_SIZE) - fail ("write %d bytes at offset %zu failed", (int) BLOCK_SIZE, ofs); - } - - msg ("read \"%s\" in random order", file_name); - shuffle (order, BLOCK_CNT, sizeof *order); - for (i = 0; i < BLOCK_CNT; i++) - { - char block[BLOCK_SIZE]; - size_t ofs = BLOCK_SIZE * order[i]; - seek (fd, ofs); - if (read (fd, block, BLOCK_SIZE) != BLOCK_SIZE) - fail ("read %d bytes at offset %zu failed", (int) BLOCK_SIZE, ofs); - compare_bytes (block, buf + ofs, BLOCK_SIZE, ofs, file_name); - } - - msg ("close \"%s\"", file_name); - close (fd); -} diff --git a/src/tests/filesys/base/seq-block.inc b/src/tests/filesys/base/seq-block.inc deleted file mode 100644 index d4c1f57415bff3bb4890461fd7c59e3f0b9d0b8e..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/seq-block.inc +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- c -*- */ - -#include "tests/filesys/seq-test.h" -#include "tests/main.h" - -static char buf[TEST_SIZE]; - -static size_t -return_block_size (void) -{ - return BLOCK_SIZE; -} - -void -test_main (void) -{ - seq_test ("noodle", - buf, sizeof buf, sizeof buf, - return_block_size, NULL); -} diff --git a/src/tests/filesys/base/seq-random.inc b/src/tests/filesys/base/seq-random.inc deleted file mode 100644 index a4da4c5e36ac2f3f85c38b3497f7f2e8ee154254..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/seq-random.inc +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- c -*- */ - -#include <random.h> -#include "tests/filesys/seq-test.h" -#include "tests/main.h" - -static char buf[TEST_SIZE]; - -static size_t -return_random (void) -{ - return random_ulong () % 1031 + 1; -} - -void -test_main (void) -{ - random_init (-1); - seq_test ("nibble", - buf, sizeof buf, sizeof buf, - return_random, NULL); -} diff --git a/src/tests/filesys/base/sm-create.c b/src/tests/filesys/base/sm-create.c deleted file mode 100644 index 6b97ac1eb8843bb4d4d53e175e2f52bc1aa678cb..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-create.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Tests that create properly zeros out the contents of a fairly - small file. */ - -#define TEST_SIZE 5678 -#include "tests/filesys/create.inc" diff --git a/src/tests/filesys/base/sm-create.ck b/src/tests/filesys/base/sm-create.ck deleted file mode 100644 index 8ca80dc30d5bd3cf051cfd5b794c0e5a80f3a77b..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-create.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(sm-create) begin -(sm-create) create "blargle" -(sm-create) open "blargle" for verification -(sm-create) verified contents of "blargle" -(sm-create) close "blargle" -(sm-create) end -EOF -pass; diff --git a/src/tests/filesys/base/sm-full.c b/src/tests/filesys/base/sm-full.c deleted file mode 100644 index 23ff3d4dc9a9417e0650553b6a8efc768e61eabe..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-full.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Writes out the contents of a fairly small file all at once, - and then reads it back to make sure that it was written - properly. */ - -#define TEST_SIZE 5678 -#include "tests/filesys/base/full.inc" diff --git a/src/tests/filesys/base/sm-full.ck b/src/tests/filesys/base/sm-full.ck deleted file mode 100644 index 2e0eb3676b3ac1961d17acabb4daa3fdc5ba8505..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-full.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(sm-full) begin -(sm-full) create "quux" -(sm-full) open "quux" -(sm-full) writing "quux" -(sm-full) close "quux" -(sm-full) open "quux" for verification -(sm-full) verified contents of "quux" -(sm-full) close "quux" -(sm-full) end -EOF -pass; diff --git a/src/tests/filesys/base/sm-random.c b/src/tests/filesys/base/sm-random.c deleted file mode 100644 index 42d670f5d3a150643d598e77c8e2239a46e89953..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-random.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Writes out the content of a fairly small file in random order, - then reads it back in random order to verify that it was - written properly. */ - -#define BLOCK_SIZE 13 -#define TEST_SIZE (13 * 123) -#include "tests/filesys/base/random.inc" diff --git a/src/tests/filesys/base/sm-random.ck b/src/tests/filesys/base/sm-random.ck deleted file mode 100644 index bda049de53e88a83ee7ea8a1cea2883ec1e2e57b..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-random.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(sm-random) begin -(sm-random) create "bazzle" -(sm-random) open "bazzle" -(sm-random) write "bazzle" in random order -(sm-random) read "bazzle" in random order -(sm-random) close "bazzle" -(sm-random) end -EOF -pass; diff --git a/src/tests/filesys/base/sm-seq-block.c b/src/tests/filesys/base/sm-seq-block.c deleted file mode 100644 index e3683277048168cbff3c0d3f8a63dd6789271af4..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-seq-block.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Writes out a fairly small file sequentially, one fixed-size - block at a time, then reads it back to verify that it was - written properly. */ - -#define TEST_SIZE 5678 -#define BLOCK_SIZE 513 -#include "tests/filesys/base/seq-block.inc" diff --git a/src/tests/filesys/base/sm-seq-block.ck b/src/tests/filesys/base/sm-seq-block.ck deleted file mode 100644 index 0e2939d81d1deffb48e81603b184f5a265bd1e9d..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-seq-block.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(sm-seq-block) begin -(sm-seq-block) create "noodle" -(sm-seq-block) open "noodle" -(sm-seq-block) writing "noodle" -(sm-seq-block) close "noodle" -(sm-seq-block) open "noodle" for verification -(sm-seq-block) verified contents of "noodle" -(sm-seq-block) close "noodle" -(sm-seq-block) end -EOF -pass; diff --git a/src/tests/filesys/base/sm-seq-random.c b/src/tests/filesys/base/sm-seq-random.c deleted file mode 100644 index 89e5b719fa98106066245972038a04854e5abee5..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-seq-random.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Writes out a fairly large file sequentially, one random-sized - block at a time, then reads it back to verify that it was - written properly. */ - -#define TEST_SIZE 5678 -#include "tests/filesys/base/seq-random.inc" diff --git a/src/tests/filesys/base/sm-seq-random.ck b/src/tests/filesys/base/sm-seq-random.ck deleted file mode 100644 index 2fb368bcca5e8ec7392a3c7be9759758b256f171..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/sm-seq-random.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(sm-seq-random) begin -(sm-seq-random) create "nibble" -(sm-seq-random) open "nibble" -(sm-seq-random) writing "nibble" -(sm-seq-random) close "nibble" -(sm-seq-random) open "nibble" for verification -(sm-seq-random) verified contents of "nibble" -(sm-seq-random) close "nibble" -(sm-seq-random) end -EOF -pass; diff --git a/src/tests/filesys/base/syn-read.c b/src/tests/filesys/base/syn-read.c deleted file mode 100644 index 7c36a429e4f1a6b4bdd282c6481bec1ad6820e47..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-read.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Spawns 10 child processes, all of which read from the same - file and make sure that the contents are what they should - be. */ - -#include <random.h> -#include <stdio.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" -#include "tests/filesys/base/syn-read.h" - -static char buf[BUF_SIZE]; - -#define CHILD_CNT 10 - -void -test_main (void) -{ - pid_t children[CHILD_CNT]; - int fd; - - CHECK (create (file_name, sizeof buf), "create \"%s\"", file_name); - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - random_bytes (buf, sizeof buf); - CHECK (write (fd, buf, sizeof buf) > 0, "write \"%s\"", file_name); - msg ("close \"%s\"", file_name); - close (fd); - - exec_children ("child-syn-read", children, CHILD_CNT); - wait_children (children, CHILD_CNT); -} diff --git a/src/tests/filesys/base/syn-read.ck b/src/tests/filesys/base/syn-read.ck deleted file mode 100644 index e2f68e80a2fe142fc6fbd039d9bddb7e1f890784..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-read.ck +++ /dev/null @@ -1,33 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(syn-read) begin -(syn-read) create "data" -(syn-read) open "data" -(syn-read) write "data" -(syn-read) close "data" -(syn-read) exec child 1 of 10: "child-syn-read 0" -(syn-read) exec child 2 of 10: "child-syn-read 1" -(syn-read) exec child 3 of 10: "child-syn-read 2" -(syn-read) exec child 4 of 10: "child-syn-read 3" -(syn-read) exec child 5 of 10: "child-syn-read 4" -(syn-read) exec child 6 of 10: "child-syn-read 5" -(syn-read) exec child 7 of 10: "child-syn-read 6" -(syn-read) exec child 8 of 10: "child-syn-read 7" -(syn-read) exec child 9 of 10: "child-syn-read 8" -(syn-read) exec child 10 of 10: "child-syn-read 9" -(syn-read) wait for child 1 of 10 returned 0 (expected 0) -(syn-read) wait for child 2 of 10 returned 1 (expected 1) -(syn-read) wait for child 3 of 10 returned 2 (expected 2) -(syn-read) wait for child 4 of 10 returned 3 (expected 3) -(syn-read) wait for child 5 of 10 returned 4 (expected 4) -(syn-read) wait for child 6 of 10 returned 5 (expected 5) -(syn-read) wait for child 7 of 10 returned 6 (expected 6) -(syn-read) wait for child 8 of 10 returned 7 (expected 7) -(syn-read) wait for child 9 of 10 returned 8 (expected 8) -(syn-read) wait for child 10 of 10 returned 9 (expected 9) -(syn-read) end -EOF -pass; diff --git a/src/tests/filesys/base/syn-read.h b/src/tests/filesys/base/syn-read.h deleted file mode 100644 index bff80828324acf78df7f5f9fde0b6afcfd21731a..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-read.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef TESTS_FILESYS_BASE_SYN_READ_H -#define TESTS_FILESYS_BASE_SYN_READ_H - -#define BUF_SIZE 1024 -static const char file_name[] = "data"; - -#endif /* tests/filesys/base/syn-read.h */ diff --git a/src/tests/filesys/base/syn-remove.c b/src/tests/filesys/base/syn-remove.c deleted file mode 100644 index c9ba1109e316c23f1c73211a760c30d770735dd3..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-remove.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Verifies that a deleted file may still be written to and read - from. */ - -#include <random.h> -#include <string.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -char buf1[1234]; -char buf2[1234]; - -void -test_main (void) -{ - const char *file_name = "deleteme"; - int fd; - - CHECK (create (file_name, sizeof buf1), "create \"%s\"", file_name); - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - CHECK (remove (file_name), "remove \"%s\"", file_name); - random_bytes (buf1, sizeof buf1); - CHECK (write (fd, buf1, sizeof buf1) > 0, "write \"%s\"", file_name); - msg ("seek \"%s\" to 0", file_name); - seek (fd, 0); - CHECK (read (fd, buf2, sizeof buf2) > 0, "read \"%s\"", file_name); - compare_bytes (buf2, buf1, sizeof buf1, 0, file_name); - msg ("close \"%s\"", file_name); - close (fd); -} diff --git a/src/tests/filesys/base/syn-remove.ck b/src/tests/filesys/base/syn-remove.ck deleted file mode 100644 index 16ff11e550451ec5e4041d4bf82d1a5367cfcbfe..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-remove.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(syn-remove) begin -(syn-remove) create "deleteme" -(syn-remove) open "deleteme" -(syn-remove) remove "deleteme" -(syn-remove) write "deleteme" -(syn-remove) seek "deleteme" to 0 -(syn-remove) read "deleteme" -(syn-remove) close "deleteme" -(syn-remove) end -EOF -pass; diff --git a/src/tests/filesys/base/syn-write.c b/src/tests/filesys/base/syn-write.c deleted file mode 100644 index 1439862dd2ddf1aba0816deaad0e13014aaa4a91..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-write.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Spawns several child processes to write out different parts of - the contents of a file and waits for them to finish. Then - reads back the file and verifies its contents. */ - -#include <random.h> -#include <stdio.h> -#include <string.h> -#include <syscall.h> -#include "tests/filesys/base/syn-write.h" -#include "tests/lib.h" -#include "tests/main.h" - -char buf1[BUF_SIZE]; -char buf2[BUF_SIZE]; - -void -test_main (void) -{ - pid_t children[CHILD_CNT]; - int fd; - - CHECK (create (file_name, sizeof buf1), "create \"%s\"", file_name); - - exec_children ("child-syn-wrt", children, CHILD_CNT); - wait_children (children, CHILD_CNT); - - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - CHECK (read (fd, buf1, sizeof buf1) > 0, "read \"%s\"", file_name); - random_bytes (buf2, sizeof buf2); - compare_bytes (buf1, buf2, sizeof buf1, 0, file_name); -} diff --git a/src/tests/filesys/base/syn-write.ck b/src/tests/filesys/base/syn-write.ck deleted file mode 100644 index 629a7a2b793486577ce04e0e55733b2d967a1434..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-write.ck +++ /dev/null @@ -1,32 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(syn-write) begin -(syn-write) create "stuff" -(syn-write) exec child 1 of 10: "child-syn-wrt 0" -(syn-write) exec child 2 of 10: "child-syn-wrt 1" -(syn-write) exec child 3 of 10: "child-syn-wrt 2" -(syn-write) exec child 4 of 10: "child-syn-wrt 3" -(syn-write) exec child 5 of 10: "child-syn-wrt 4" -(syn-write) exec child 6 of 10: "child-syn-wrt 5" -(syn-write) exec child 7 of 10: "child-syn-wrt 6" -(syn-write) exec child 8 of 10: "child-syn-wrt 7" -(syn-write) exec child 9 of 10: "child-syn-wrt 8" -(syn-write) exec child 10 of 10: "child-syn-wrt 9" -(syn-write) wait for child 1 of 10 returned 0 (expected 0) -(syn-write) wait for child 2 of 10 returned 1 (expected 1) -(syn-write) wait for child 3 of 10 returned 2 (expected 2) -(syn-write) wait for child 4 of 10 returned 3 (expected 3) -(syn-write) wait for child 5 of 10 returned 4 (expected 4) -(syn-write) wait for child 6 of 10 returned 5 (expected 5) -(syn-write) wait for child 7 of 10 returned 6 (expected 6) -(syn-write) wait for child 8 of 10 returned 7 (expected 7) -(syn-write) wait for child 9 of 10 returned 8 (expected 8) -(syn-write) wait for child 10 of 10 returned 9 (expected 9) -(syn-write) open "stuff" -(syn-write) read "stuff" -(syn-write) end -EOF -pass; diff --git a/src/tests/filesys/base/syn-write.h b/src/tests/filesys/base/syn-write.h deleted file mode 100644 index 07a6d5a015beac3cdce3fd8d05730884c383acc4..0000000000000000000000000000000000000000 --- a/src/tests/filesys/base/syn-write.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef TESTS_FILESYS_BASE_SYN_WRITE_H -#define TESTS_FILESYS_BASE_SYN_WRITE_H - -#define CHILD_CNT 10 -#define CHUNK_SIZE 512 -#define BUF_SIZE (CHILD_CNT * CHUNK_SIZE) -static const char file_name[] = "stuff"; - -#endif /* tests/filesys/base/syn-write.h */ diff --git a/src/tests/filesys/create.inc b/src/tests/filesys/create.inc deleted file mode 100644 index 4baf7718bdbd0d1a3b162b9a93ef936d0dedca5a..0000000000000000000000000000000000000000 --- a/src/tests/filesys/create.inc +++ /dev/null @@ -1,15 +0,0 @@ -/* -*- c -*- */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -static char buf[TEST_SIZE]; - -void -test_main (void) -{ - const char *file_name = "blargle"; - CHECK (create (file_name, TEST_SIZE), "create \"%s\"", file_name); - check_file (file_name, buf, TEST_SIZE); -} diff --git a/src/tests/filesys/extended/Make.tests b/src/tests/filesys/extended/Make.tests deleted file mode 100644 index e03b98dc4fbfc69f1808ba2e8f13a902e75e1ea7..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/Make.tests +++ /dev/null @@ -1,61 +0,0 @@ -# -*- makefile -*- - -raw_tests = dir-empty-name dir-mk-tree dir-mkdir dir-open \ -dir-over-file dir-rm-cwd dir-rm-parent dir-rm-root dir-rm-tree \ -dir-rmdir dir-under-file dir-vine grow-create grow-dir-lg \ -grow-file-size grow-root-lg grow-root-sm grow-seq-lg grow-seq-sm \ -grow-sparse grow-tell grow-two-files syn-rw - -tests/filesys/extended_TESTS = $(patsubst %,tests/filesys/extended/%,$(raw_tests)) -tests/filesys/extended_EXTRA_GRADES = $(patsubst %,tests/filesys/extended/%-persistence,$(raw_tests)) - -tests/filesys/extended_PROGS = $(tests/filesys/extended_TESTS) \ -tests/filesys/extended/child-syn-rw tests/filesys/extended/tar - -$(foreach prog,$(tests/filesys/extended_PROGS), \ - $(eval $(prog)_SRC += $(prog).c tests/lib.c tests/filesys/seq-test.c)) -$(foreach prog,$(tests/filesys/extended_TESTS), \ - $(eval $(prog)_SRC += tests/main.c)) -$(foreach prog,$(tests/filesys/extended_TESTS), \ - $(eval $(prog)_PUTFILES += tests/filesys/extended/tar)) -# The version of GNU make 3.80 on vine barfs if this is split at -# the last comma. -$(foreach test,$(tests/filesys/extended_TESTS),$(eval $(test).output: FILESYSSOURCE = --disk=tmp.dsk)) - -tests/filesys/extended/dir-mk-tree_SRC += tests/filesys/extended/mk-tree.c -tests/filesys/extended/dir-rm-tree_SRC += tests/filesys/extended/mk-tree.c - -tests/filesys/extended/syn-rw_PUTFILES += tests/filesys/extended/child-syn-rw - -tests/filesys/extended/dir-vine.output: TIMEOUT = 150 - -GETTIMEOUT = 60 - -GETCMD = pintos -v -k -T $(GETTIMEOUT) -GETCMD += $(PINTOSOPTS) -GETCMD += $(SIMULATOR) -GETCMD += $(FILESYSSOURCE) -GETCMD += -g fs.tar -a $(TEST).tar -ifeq ($(filter vm, $(KERNEL_SUBDIRS)), vm) -GETCMD += --swap-size=4 -endif -GETCMD += -- -q -GETCMD += $(KERNELFLAGS) -GETCMD += run 'tar fs.tar /' -GETCMD += < /dev/null -GETCMD += 2> $(TEST)-persistence.errors $(if $(VERBOSE),|tee,>) $(TEST)-persistence.output - -tests/filesys/extended/%.output: kernel.bin - rm -f tmp.dsk - pintos-mkdisk tmp.dsk --filesys-size=2 - $(TESTCMD) - $(GETCMD) - rm -f tmp.dsk -$(foreach raw_test,$(raw_tests),$(eval tests/filesys/extended/$(raw_test)-persistence.output: tests/filesys/extended/$(raw_test).output)) -$(foreach raw_test,$(raw_tests),$(eval tests/filesys/extended/$(raw_test)-persistence.result: tests/filesys/extended/$(raw_test).result)) - -TARS = $(addsuffix .tar,$(tests/filesys/extended_TESTS)) - -clean:: - rm -f $(TARS) - rm -f tests/filesys/extended/can-rmdir-cwd diff --git a/src/tests/filesys/extended/Rubric.functionality b/src/tests/filesys/extended/Rubric.functionality deleted file mode 100644 index 91ed6f08cb658bb9b1444ad4ca83c21f71da9f71..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/Rubric.functionality +++ /dev/null @@ -1,26 +0,0 @@ -Functionality of extended file system: -- Test directory support. -1 dir-mkdir -3 dir-mk-tree - -1 dir-rmdir -3 dir-rm-tree - -5 dir-vine - -- Test file growth. -1 grow-create -1 grow-seq-sm -3 grow-seq-lg -3 grow-sparse -3 grow-two-files -1 grow-tell -1 grow-file-size - -- Test directory growth. -1 grow-dir-lg -1 grow-root-sm -1 grow-root-lg - -- Test writing from multiple processes. -5 syn-rw diff --git a/src/tests/filesys/extended/Rubric.persistence b/src/tests/filesys/extended/Rubric.persistence deleted file mode 100644 index 405620a073f037e58b16b8fc12deae28df18e9cf..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/Rubric.persistence +++ /dev/null @@ -1,24 +0,0 @@ -Persistence of file system: -1 dir-empty-name-persistence -1 dir-mk-tree-persistence -1 dir-mkdir-persistence -1 dir-open-persistence -1 dir-over-file-persistence -1 dir-rm-cwd-persistence -1 dir-rm-parent-persistence -1 dir-rm-root-persistence -1 dir-rm-tree-persistence -1 dir-rmdir-persistence -1 dir-under-file-persistence -1 dir-vine-persistence -1 grow-create-persistence -1 grow-dir-lg-persistence -1 grow-file-size-persistence -1 grow-root-lg-persistence -1 grow-root-sm-persistence -1 grow-seq-lg-persistence -1 grow-seq-sm-persistence -1 grow-sparse-persistence -1 grow-tell-persistence -1 grow-two-files-persistence -1 syn-rw-persistence diff --git a/src/tests/filesys/extended/Rubric.robustness b/src/tests/filesys/extended/Rubric.robustness deleted file mode 100644 index fb9f32fe2cd7880b0a8304f0e6fe0e9a19f5c2db..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/Rubric.robustness +++ /dev/null @@ -1,9 +0,0 @@ -Robustness of file system: -1 dir-empty-name -1 dir-open -1 dir-over-file -1 dir-under-file - -3 dir-rm-cwd -2 dir-rm-parent -1 dir-rm-root diff --git a/src/tests/filesys/extended/child-syn-rw.c b/src/tests/filesys/extended/child-syn-rw.c deleted file mode 100644 index 0e2217df58da7e4272ffd9ce40a0926d099213d1..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/child-syn-rw.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Child process for syn-rw. - Reads from a file created by our parent process, which is - growing it. We loop until we've read the whole file - successfully. Many iterations through the loop will return 0 - bytes, because the file has not grown in the meantime. That - is, we are "busy waiting" for the file to grow. - (This test could be improved by adding a "yield" system call - and calling yield whenever we receive a 0-byte read.) */ - -#include <random.h> -#include <stdlib.h> -#include <syscall.h> -#include "tests/filesys/extended/syn-rw.h" -#include "tests/lib.h" - -const char *test_name = "child-syn-rw"; - -static char buf1[BUF_SIZE]; -static char buf2[BUF_SIZE]; - -int -main (int argc, const char *argv[]) -{ - int child_idx; - int fd; - size_t ofs; - - quiet = true; - - CHECK (argc == 2, "argc must be 2, actually %d", argc); - child_idx = atoi (argv[1]); - - random_init (0); - random_bytes (buf1, sizeof buf1); - - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - ofs = 0; - while (ofs < sizeof buf2) - { - int bytes_read = read (fd, buf2 + ofs, sizeof buf2 - ofs); - CHECK (bytes_read >= -1 && bytes_read <= (int) (sizeof buf2 - ofs), - "%zu-byte read on \"%s\" returned invalid value of %d", - sizeof buf2 - ofs, file_name, bytes_read); - if (bytes_read > 0) - { - compare_bytes (buf2 + ofs, buf1 + ofs, bytes_read, ofs, file_name); - ofs += bytes_read; - } - } - close (fd); - - return child_idx; -} diff --git a/src/tests/filesys/extended/dir-empty-name-persistence.ck b/src/tests/filesys/extended/dir-empty-name-persistence.ck deleted file mode 100644 index 562c45102a6fbc2fea2733100ddeba700eaa06d9..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-empty-name-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({}); -pass; diff --git a/src/tests/filesys/extended/dir-empty-name.c b/src/tests/filesys/extended/dir-empty-name.c deleted file mode 100644 index c4859d20c77ec296f9cbcbb87d3419b1bb9c6eed..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-empty-name.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Tries to create a directory named as the empty string, - which must return failure. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (!mkdir (""), "mkdir \"\" (must return false)"); -} diff --git a/src/tests/filesys/extended/dir-empty-name.ck b/src/tests/filesys/extended/dir-empty-name.ck deleted file mode 100644 index d6c5621eb5ff0147606384a3a08d1054a85d56a0..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-empty-name.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-empty-name) begin -(dir-empty-name) mkdir "" (must return false) -(dir-empty-name) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-mk-tree-persistence.ck b/src/tests/filesys/extended/dir-mk-tree-persistence.ck deleted file mode 100644 index fb16afd2cefd945fdf515fcefef35f1efcb992b7..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-mk-tree-persistence.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -my ($tree); -for my $a (0...3) { - for my $b (0...2) { - for my $c (0...2) { - for my $d (0...3) { - $tree->{$a}{$b}{$c}{$d} = ['']; - } - } - } -} -check_archive ($tree); -pass; diff --git a/src/tests/filesys/extended/dir-mk-tree.c b/src/tests/filesys/extended/dir-mk-tree.c deleted file mode 100644 index a714ff379a28254e16d1b918a6a8141a62543875..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-mk-tree.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Creates directories /0/0/0 through /3/2/2 and creates files in - the leaf directories. */ - -#include "tests/filesys/extended/mk-tree.h" -#include "tests/main.h" - -void -test_main (void) -{ - make_tree (4, 3, 3, 4); -} - diff --git a/src/tests/filesys/extended/dir-mk-tree.ck b/src/tests/filesys/extended/dir-mk-tree.ck deleted file mode 100644 index a8507e23fc68d2482e17b478a26bf59e7357f59b..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-mk-tree.ck +++ /dev/null @@ -1,12 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-mk-tree) begin -(dir-mk-tree) creating /0/0/0/0 through /3/2/2/3... -(dir-mk-tree) open "/0/2/0/3" -(dir-mk-tree) close "/0/2/0/3" -(dir-mk-tree) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-mkdir-persistence.ck b/src/tests/filesys/extended/dir-mkdir-persistence.ck deleted file mode 100644 index 768290032c395bce235e73fb7bf663412c944445..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-mkdir-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({'a' => {'b' => ["\0" x 512]}}); -pass; diff --git a/src/tests/filesys/extended/dir-mkdir.c b/src/tests/filesys/extended/dir-mkdir.c deleted file mode 100644 index 994f41ce967bb5336732175555f6f22ed78f97e1..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-mkdir.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Tests mkdir(). */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (mkdir ("a"), "mkdir \"a\""); - CHECK (create ("a/b", 512), "create \"a/b\""); - CHECK (chdir ("a"), "chdir \"a\""); - CHECK (open ("b") > 1, "open \"b\""); -} - diff --git a/src/tests/filesys/extended/dir-mkdir.ck b/src/tests/filesys/extended/dir-mkdir.ck deleted file mode 100644 index 4644f802387c21cae6a486294cd765aeab22911d..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-mkdir.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-mkdir) begin -(dir-mkdir) mkdir "a" -(dir-mkdir) create "a/b" -(dir-mkdir) chdir "a" -(dir-mkdir) open "b" -(dir-mkdir) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-open-persistence.ck b/src/tests/filesys/extended/dir-open-persistence.ck deleted file mode 100644 index 26ff2f16743f55f7cf826bf791d3e3c6164157c6..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-open-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({"xyzzy" => {}}); -pass; diff --git a/src/tests/filesys/extended/dir-open.c b/src/tests/filesys/extended/dir-open.c deleted file mode 100644 index 29d18b8580eb5a48fe59d1a77a1758dfb9a8c363..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-open.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Opens a directory, then tries to write to it, which must - fail. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int fd; - int retval; - - CHECK (mkdir ("xyzzy"), "mkdir \"xyzzy\""); - CHECK ((fd = open ("xyzzy")) > 1, "open \"xyzzy\""); - - msg ("write \"xyzzy\""); - retval = write (fd, "foobar", 6); - CHECK (retval == -1, - "write \"xyzzy\" (must return -1, actually %d)", retval); -} diff --git a/src/tests/filesys/extended/dir-open.ck b/src/tests/filesys/extended/dir-open.ck deleted file mode 100644 index fccc56352fc7b6bc9f299b66e818c6c168a7f613..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-open.ck +++ /dev/null @@ -1,20 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(dir-open) begin -(dir-open) mkdir "xyzzy" -(dir-open) open "xyzzy" -(dir-open) write "xyzzy" -(dir-open) write "xyzzy" (must return -1, actually -1) -(dir-open) end -dir-open: exit(0) -EOF -(dir-open) begin -(dir-open) mkdir "xyzzy" -(dir-open) open "xyzzy" -(dir-open) write "xyzzy" -dir-open: exit(-1) -EOF -pass; diff --git a/src/tests/filesys/extended/dir-over-file-persistence.ck b/src/tests/filesys/extended/dir-over-file-persistence.ck deleted file mode 100644 index 56b4ed29683f07f7798055b3a848846bcc9d94d6..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-over-file-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({"abc" => {}}); -pass; diff --git a/src/tests/filesys/extended/dir-over-file.c b/src/tests/filesys/extended/dir-over-file.c deleted file mode 100644 index cdd2c62a27b30fcd4a647f679bb47c16caf3c584..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-over-file.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Tries to create a file with the same name as an existing - directory, which must return failure. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (mkdir ("abc"), "mkdir \"abc\""); - CHECK (!create ("abc", 0), "create \"abc\" (must return false)"); -} diff --git a/src/tests/filesys/extended/dir-over-file.ck b/src/tests/filesys/extended/dir-over-file.ck deleted file mode 100644 index aae1c1e8589d8c04ec4186517752feac5d7ede2c..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-over-file.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-over-file) begin -(dir-over-file) mkdir "abc" -(dir-over-file) create "abc" (must return false) -(dir-over-file) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-rm-cwd-persistence.ck b/src/tests/filesys/extended/dir-rm-cwd-persistence.ck deleted file mode 100644 index 75335702802317d5ef47d56f22162b09fa9e5a5f..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-cwd-persistence.ck +++ /dev/null @@ -1,8 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -my ($cwd_removable) = read_text_file ("tests/filesys/extended/can-rmdir-cwd"); -$cwd_removable eq 'YES' || $cwd_removable eq 'NO' or die; -check_archive ($cwd_removable eq 'YES' ? {} : {"a" => {}}); -pass; diff --git a/src/tests/filesys/extended/dir-rm-cwd.c b/src/tests/filesys/extended/dir-rm-cwd.c deleted file mode 100644 index 78e13dea23492dd5f69953220c53d25b898f2b95..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-cwd.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Tries to remove the current directory, which may succeed or - fail. The requirements in each case are different; refer to - the assignment for details. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -static int -wrap_open (const char *name) -{ - static int fds[8], fd_cnt; - int fd, i; - - CHECK ((fd = open (name)) > 1, "open \"%s\"", name); - for (i = 0; i < fd_cnt; i++) - if (fds[i] == fd) - fail ("fd returned is not unique"); - fds[fd_cnt++] = fd; - return fd; -} - -void -test_main (void) -{ - int root_fd, a_fd0; - char name[READDIR_MAX_LEN + 1]; - - root_fd = wrap_open ("/"); - CHECK (mkdir ("a"), "mkdir \"a\""); - - a_fd0 = wrap_open ("/a"); - CHECK (!readdir (a_fd0, name), "verify \"/a\" is empty"); - CHECK (inumber (root_fd) != inumber (a_fd0), - "\"/\" and \"/a\" must have different inumbers"); - - CHECK (chdir ("a"), "chdir \"a\""); - - msg ("try to remove \"/a\""); - if (remove ("/a")) - { - msg ("remove successful"); - - CHECK (open ("/a") == -1, "open \"/a\" (must fail)"); - CHECK (open (".") == -1, "open \".\" (must fail)"); - CHECK (open ("..") == -1, "open \"..\" (must fail)"); - CHECK (!create ("x", 512), "create \"x\" (must fail)"); - } - else - { - int a_fd1, a_fd2, a_fd3; - - msg ("remove failed"); - - CHECK (!remove ("../a"), "try to remove \"../a\" (must fail)"); - CHECK (!remove (".././a"), "try to remove \".././a\" (must fail)"); - CHECK (!remove ("/./a"), "try to remove \"/./a\" (must fail)"); - - a_fd1 = wrap_open ("/a"); - a_fd2 = wrap_open ("."); - CHECK (inumber (a_fd1) == inumber (a_fd2), - "\"/a\" and \".\" must have same inumber"); - CHECK (inumber (root_fd) != inumber (a_fd1), - "\"/\" and \"/a\" must have different inumbers"); - - CHECK (chdir ("/a"), "chdir \"/a\""); - a_fd3 = wrap_open ("."); - CHECK (inumber (a_fd3) == inumber (a_fd1), - "\".\" must have same inumber as before"); - - CHECK (chdir ("/"), "chdir \"/\""); - CHECK (!remove ("a"), "try to remove \"a\" (must fail: still open)"); - } - CHECK (!readdir (a_fd0, name), "verify \"/a\" is empty"); -} diff --git a/src/tests/filesys/extended/dir-rm-cwd.ck b/src/tests/filesys/extended/dir-rm-cwd.ck deleted file mode 100644 index 6fa47395f62338c98878d178b93ffae0351b8dda..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-cwd.ck +++ /dev/null @@ -1,51 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -my ($cwd_removable) = check_expected (IGNORE_EXIT_CODES => 1, - {NO => <<'EOF', YES => <<'EOF'}); -(dir-rm-cwd) begin -(dir-rm-cwd) open "/" -(dir-rm-cwd) mkdir "a" -(dir-rm-cwd) open "/a" -(dir-rm-cwd) verify "/a" is empty -(dir-rm-cwd) "/" and "/a" must have different inumbers -(dir-rm-cwd) chdir "a" -(dir-rm-cwd) try to remove "/a" -(dir-rm-cwd) remove failed -(dir-rm-cwd) try to remove "../a" (must fail) -(dir-rm-cwd) try to remove ".././a" (must fail) -(dir-rm-cwd) try to remove "/./a" (must fail) -(dir-rm-cwd) open "/a" -(dir-rm-cwd) open "." -(dir-rm-cwd) "/a" and "." must have same inumber -(dir-rm-cwd) "/" and "/a" must have different inumbers -(dir-rm-cwd) chdir "/a" -(dir-rm-cwd) open "." -(dir-rm-cwd) "." must have same inumber as before -(dir-rm-cwd) chdir "/" -(dir-rm-cwd) try to remove "a" (must fail: still open) -(dir-rm-cwd) verify "/a" is empty -(dir-rm-cwd) end -EOF -(dir-rm-cwd) begin -(dir-rm-cwd) open "/" -(dir-rm-cwd) mkdir "a" -(dir-rm-cwd) open "/a" -(dir-rm-cwd) verify "/a" is empty -(dir-rm-cwd) "/" and "/a" must have different inumbers -(dir-rm-cwd) chdir "a" -(dir-rm-cwd) try to remove "/a" -(dir-rm-cwd) remove successful -(dir-rm-cwd) open "/a" (must fail) -(dir-rm-cwd) open "." (must fail) -(dir-rm-cwd) open ".." (must fail) -(dir-rm-cwd) create "x" (must fail) -(dir-rm-cwd) verify "/a" is empty -(dir-rm-cwd) end -EOF -open (CAN_RMDIR_CWD, ">tests/filesys/extended/can-rmdir-cwd") - or die "tests/filesys/extended/can-rmdir-cwd: create: $!\n"; -print CAN_RMDIR_CWD "$cwd_removable"; -close (CAN_RMDIR_CWD); -pass; diff --git a/src/tests/filesys/extended/dir-rm-parent-persistence.ck b/src/tests/filesys/extended/dir-rm-parent-persistence.ck deleted file mode 100644 index f30b04aac291dea3e6f58b0869c63a0c32f7c4fe..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-parent-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({"a" => {"b" => {}}}); -pass; diff --git a/src/tests/filesys/extended/dir-rm-parent.c b/src/tests/filesys/extended/dir-rm-parent.c deleted file mode 100644 index eb43f5b6cf6070b9767bafa315165ffc3afa8786..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-parent.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Tries to remove a parent of the current directory. This must - fail, because that directory is non-empty. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (mkdir ("a"), "mkdir \"a\""); - CHECK (chdir ("a"), "chdir \"a\""); - CHECK (mkdir ("b"), "mkdir \"b\""); - CHECK (chdir ("b"), "chdir \"b\""); - CHECK (!remove ("/a"), "remove \"/a\" (must fail)"); -} diff --git a/src/tests/filesys/extended/dir-rm-parent.ck b/src/tests/filesys/extended/dir-rm-parent.ck deleted file mode 100644 index 9fea8f23c79348a51c8804b2d582a79619f56257..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-parent.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-rm-parent) begin -(dir-rm-parent) mkdir "a" -(dir-rm-parent) chdir "a" -(dir-rm-parent) mkdir "b" -(dir-rm-parent) chdir "b" -(dir-rm-parent) remove "/a" (must fail) -(dir-rm-parent) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-rm-root-persistence.ck b/src/tests/filesys/extended/dir-rm-root-persistence.ck deleted file mode 100644 index 631510736f95d7aa72361bc80f23f285523dcabd..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-root-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({"a" => ["\0" x 243]}); -pass; diff --git a/src/tests/filesys/extended/dir-rm-root.c b/src/tests/filesys/extended/dir-rm-root.c deleted file mode 100644 index c47f1eb7b47f6c135c80291a1ec5ebee4e7fd52f..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-root.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Try to remove the root directory. - This must fail. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (!remove ("/"), "remove \"/\" (must fail)"); - CHECK (create ("/a", 243), "create \"/a\""); -} diff --git a/src/tests/filesys/extended/dir-rm-root.ck b/src/tests/filesys/extended/dir-rm-root.ck deleted file mode 100644 index 8a69ff3c1f943b167bb18480ddcf390bd69007c5..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-root.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-rm-root) begin -(dir-rm-root) remove "/" (must fail) -(dir-rm-root) create "/a" -(dir-rm-root) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-rm-tree-persistence.ck b/src/tests/filesys/extended/dir-rm-tree-persistence.ck deleted file mode 100644 index 562c45102a6fbc2fea2733100ddeba700eaa06d9..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-tree-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({}); -pass; diff --git a/src/tests/filesys/extended/dir-rm-tree.c b/src/tests/filesys/extended/dir-rm-tree.c deleted file mode 100644 index bab41a66d184670f79bdd7e64c7840a0a42f52dc..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-tree.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Creates directories /0/0/0 through /3/2/2 and files in the - leaf directories, then removes them. */ - -#include <stdarg.h> -#include <stdio.h> -#include <syscall.h> -#include "tests/filesys/extended/mk-tree.h" -#include "tests/lib.h" -#include "tests/main.h" - -static void remove_tree (int at, int bt, int ct, int dt); - -void -test_main (void) -{ - make_tree (4, 3, 3, 4); - remove_tree (4, 3, 3, 4); -} - -static void do_remove (const char *format, ...) PRINTF_FORMAT (1, 2); - -static void -remove_tree (int at, int bt, int ct, int dt) -{ - char try[128]; - int a, b, c, d; - - msg ("removing /0/0/0/0 through /%d/%d/%d/%d...", - at - 1, bt - 1, ct - 1, dt - 1); - quiet = true; - for (a = 0; a < at; a++) - { - for (b = 0; b < bt; b++) - { - for (c = 0; c < ct; c++) - { - for (d = 0; d < dt; d++) - do_remove ("/%d/%d/%d/%d", a, b, c, d); - do_remove ("/%d/%d/%d", a, b, c); - } - do_remove ("/%d/%d", a, b); - } - do_remove ("/%d", a); - } - quiet = false; - - snprintf (try, sizeof (try), "/%d/%d/%d/%d", at - 1, 0, ct - 1, 0); - CHECK (open (try) == -1, "open \"%s\" (must return -1)", try); -} - -static void -do_remove (const char *format, ...) -{ - char name[128]; - va_list args; - - va_start (args, format); - vsnprintf (name, sizeof name, format, args); - va_end (args); - - CHECK (remove (name), "remove \"%s\"", name); -} diff --git a/src/tests/filesys/extended/dir-rm-tree.ck b/src/tests/filesys/extended/dir-rm-tree.ck deleted file mode 100644 index 587b4935a52accb5fd2683c2f5dd7e054c12b4fa..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rm-tree.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-rm-tree) begin -(dir-rm-tree) creating /0/0/0/0 through /3/2/2/3... -(dir-rm-tree) open "/0/2/0/3" -(dir-rm-tree) close "/0/2/0/3" -(dir-rm-tree) removing /0/0/0/0 through /3/2/2/3... -(dir-rm-tree) open "/3/0/2/0" (must return -1) -(dir-rm-tree) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-rmdir-persistence.ck b/src/tests/filesys/extended/dir-rmdir-persistence.ck deleted file mode 100644 index 562c45102a6fbc2fea2733100ddeba700eaa06d9..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rmdir-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({}); -pass; diff --git a/src/tests/filesys/extended/dir-rmdir.c b/src/tests/filesys/extended/dir-rmdir.c deleted file mode 100644 index b3cbc6f2699af9f74a24419cf00796656095c7dc..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rmdir.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Creates and removes a directory, then makes sure that it's - really gone. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (mkdir ("a"), "mkdir \"a\""); - CHECK (remove ("a"), "rmdir \"a\""); - CHECK (!chdir ("a"), "chdir \"a\" (must return false)"); -} diff --git a/src/tests/filesys/extended/dir-rmdir.ck b/src/tests/filesys/extended/dir-rmdir.ck deleted file mode 100644 index e0d892251e02c4573000e56f11e56ac11b422eb0..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-rmdir.ck +++ /dev/null @@ -1,12 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-rmdir) begin -(dir-rmdir) mkdir "a" -(dir-rmdir) rmdir "a" -(dir-rmdir) chdir "a" (must return false) -(dir-rmdir) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-under-file-persistence.ck b/src/tests/filesys/extended/dir-under-file-persistence.ck deleted file mode 100644 index 67ca528ac06a890e8428e52961fc78d7b052a84f..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-under-file-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({"abc" => ['']}); -pass; diff --git a/src/tests/filesys/extended/dir-under-file.c b/src/tests/filesys/extended/dir-under-file.c deleted file mode 100644 index 973a8b1e9b3703db11aba83071d2d3f2c79bdfb4..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-under-file.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Tries to create a directory with the same name as an existing - file, which must return failure. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (create ("abc", 0), "create \"abc\""); - CHECK (!mkdir ("abc"), "mkdir \"abc\" (must return false)"); -} diff --git a/src/tests/filesys/extended/dir-under-file.ck b/src/tests/filesys/extended/dir-under-file.ck deleted file mode 100644 index cce23b42e2a052dd502e9e0dc264d269b41568bc..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-under-file.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-under-file) begin -(dir-under-file) create "abc" -(dir-under-file) mkdir "abc" (must return false) -(dir-under-file) end -EOF -pass; diff --git a/src/tests/filesys/extended/dir-vine-persistence.ck b/src/tests/filesys/extended/dir-vine-persistence.ck deleted file mode 100644 index 698ef01e0925152bd35525785308c3e640bb3086..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-vine-persistence.ck +++ /dev/null @@ -1,37 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -# The archive should look like this: -# -# 40642 dir-vine -# 42479 tar -# 0 start -# 11 start/file0 -# 0 start/dir0 -# 11 start/dir0/file1 -# 0 start/dir0/dir1 -# 11 start/dir0/dir1/file2 -# 0 start/dir0/dir1/dir2 -# 11 start/dir0/dir1/dir2/file3 -# 0 start/dir0/dir1/dir2/dir3 -# 11 start/dir0/dir1/dir2/dir3/file4 -# 0 start/dir0/dir1/dir2/dir3/dir4 -# 11 start/dir0/dir1/dir2/dir3/dir4/file5 -# 0 start/dir0/dir1/dir2/dir3/dir4/dir5 -# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/file6 -# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6 -# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/file7 -# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7 -# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file8 -# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8 -# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file9 -# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9 -my ($dir) = {}; -my ($root) = {"start" => $dir}; -for (my ($i) = 0; $i < 10; $i++) { - $dir->{"file$i"} = ["contents $i\n"]; - $dir = $dir->{"dir$i"} = {}; -} -check_archive ($root); -pass; diff --git a/src/tests/filesys/extended/dir-vine.c b/src/tests/filesys/extended/dir-vine.c deleted file mode 100644 index 8a31c38921a6b04db5c07f9a8412b17ced99c73c..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-vine.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Create a very deep "vine" of directories: /dir0/dir1/dir2/... - and an ordinary file in each of them, until we fill up the - disk. - - Then delete most of them, for two reasons. First, "tar" - limits file names to 100 characters (which could be extended - to 256 without much trouble). Second, a full disk has no room - for the tar archive. */ - -#include <string.h> -#include <stdio.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int i; - - msg ("creating many levels of files and directories..."); - quiet = true; - CHECK (mkdir ("start"), "mkdir \"start\""); - CHECK (chdir ("start"), "chdir \"start\""); - for (i = 0; ; i++) - { - char name[3][READDIR_MAX_LEN + 1]; - char file_name[16], dir_name[16]; - char contents[128]; - int fd; - - /* Create file. */ - snprintf (file_name, sizeof file_name, "file%d", i); - if (!create (file_name, 0)) - break; - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - snprintf (contents, sizeof contents, "contents %d\n", i); - if (write (fd, contents, strlen (contents)) != (int) strlen (contents)) - { - CHECK (remove (file_name), "remove \"%s\"", file_name); - close (fd); - break; - } - close (fd); - - /* Create directory. */ - snprintf (dir_name, sizeof dir_name, "dir%d", i); - if (!mkdir (dir_name)) - { - CHECK (remove (file_name), "remove \"%s\"", file_name); - break; - } - - /* Check for file and directory. */ - CHECK ((fd = open (".")) > 1, "open \".\""); - CHECK (readdir (fd, name[0]), "readdir \".\""); - CHECK (readdir (fd, name[1]), "readdir \".\""); - CHECK (!readdir (fd, name[2]), "readdir \".\" (should fail)"); - CHECK ((!strcmp (name[0], dir_name) && !strcmp (name[1], file_name)) - || (!strcmp (name[1], dir_name) && !strcmp (name[0], file_name)), - "names should be \"%s\" and \"%s\", " - "actually \"%s\" and \"%s\"", - file_name, dir_name, name[0], name[1]); - close (fd); - - /* Descend into directory. */ - CHECK (chdir (dir_name), "chdir \"%s\"", dir_name); - } - CHECK (i > 200, "created files and directories only to level %d", i); - quiet = false; - - msg ("removing all but top 10 levels of files and directories..."); - quiet = true; - while (i-- > 10) - { - char file_name[16], dir_name[16]; - - snprintf (file_name, sizeof file_name, "file%d", i); - snprintf (dir_name, sizeof dir_name, "dir%d", i); - CHECK (chdir (".."), "chdir \"..\""); - CHECK (remove (dir_name), "remove \"%s\"", dir_name); - CHECK (remove (file_name), "remove \"%s\"", file_name); - } - quiet = false; -} diff --git a/src/tests/filesys/extended/dir-vine.ck b/src/tests/filesys/extended/dir-vine.ck deleted file mode 100644 index db452b0917621798578d14c3f2115943969c37eb..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/dir-vine.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(dir-vine) begin -(dir-vine) creating many levels of files and directories... -(dir-vine) removing all but top 10 levels of files and directories... -(dir-vine) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-create-persistence.ck b/src/tests/filesys/extended/grow-create-persistence.ck deleted file mode 100644 index bbcb24f1d2e2e0f9c015ee7e6f7a8ba90376e160..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-create-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({"blargle" => ['']}); -pass; diff --git a/src/tests/filesys/extended/grow-create.c b/src/tests/filesys/extended/grow-create.c deleted file mode 100644 index 9ccc4ea31b6a775634b1ca52d818602dbe7d39bd..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-create.c +++ /dev/null @@ -1,4 +0,0 @@ -/* Create a file of size 0. */ - -#define TEST_SIZE 0 -#include "tests/filesys/create.inc" diff --git a/src/tests/filesys/extended/grow-create.ck b/src/tests/filesys/extended/grow-create.ck deleted file mode 100644 index b2e69d1cf35e0a91d8ec0d0dad1a1b12167dc86f..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-create.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-create) begin -(grow-create) create "blargle" -(grow-create) open "blargle" for verification -(grow-create) verified contents of "blargle" -(grow-create) close "blargle" -(grow-create) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-dir-lg-persistence.ck b/src/tests/filesys/extended/grow-dir-lg-persistence.ck deleted file mode 100644 index 989a322445837aa4f3d1f9d2fe5bdbb171980b79..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-dir-lg-persistence.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -my ($fs); -$fs->{'x'}{"file$_"} = [random_bytes (512)] foreach 0...49; -check_archive ($fs); -pass; diff --git a/src/tests/filesys/extended/grow-dir-lg.c b/src/tests/filesys/extended/grow-dir-lg.c deleted file mode 100644 index 20a194b32fda248e66b0e33f6b301bf9dfac0d71..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-dir-lg.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Creates a directory, - then creates 50 files in that directory. */ - -#define FILE_CNT 50 -#define DIRECTORY "/x" -#include "tests/filesys/extended/grow-dir.inc" diff --git a/src/tests/filesys/extended/grow-dir-lg.ck b/src/tests/filesys/extended/grow-dir-lg.ck deleted file mode 100644 index ec58bd3fd2187140641e67d2a1aa9fa984c14fc7..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-dir-lg.ck +++ /dev/null @@ -1,61 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-dir-lg) begin -(grow-dir-lg) mkdir /x -(grow-dir-lg) creating and checking "/x/file0" -(grow-dir-lg) creating and checking "/x/file1" -(grow-dir-lg) creating and checking "/x/file2" -(grow-dir-lg) creating and checking "/x/file3" -(grow-dir-lg) creating and checking "/x/file4" -(grow-dir-lg) creating and checking "/x/file5" -(grow-dir-lg) creating and checking "/x/file6" -(grow-dir-lg) creating and checking "/x/file7" -(grow-dir-lg) creating and checking "/x/file8" -(grow-dir-lg) creating and checking "/x/file9" -(grow-dir-lg) creating and checking "/x/file10" -(grow-dir-lg) creating and checking "/x/file11" -(grow-dir-lg) creating and checking "/x/file12" -(grow-dir-lg) creating and checking "/x/file13" -(grow-dir-lg) creating and checking "/x/file14" -(grow-dir-lg) creating and checking "/x/file15" -(grow-dir-lg) creating and checking "/x/file16" -(grow-dir-lg) creating and checking "/x/file17" -(grow-dir-lg) creating and checking "/x/file18" -(grow-dir-lg) creating and checking "/x/file19" -(grow-dir-lg) creating and checking "/x/file20" -(grow-dir-lg) creating and checking "/x/file21" -(grow-dir-lg) creating and checking "/x/file22" -(grow-dir-lg) creating and checking "/x/file23" -(grow-dir-lg) creating and checking "/x/file24" -(grow-dir-lg) creating and checking "/x/file25" -(grow-dir-lg) creating and checking "/x/file26" -(grow-dir-lg) creating and checking "/x/file27" -(grow-dir-lg) creating and checking "/x/file28" -(grow-dir-lg) creating and checking "/x/file29" -(grow-dir-lg) creating and checking "/x/file30" -(grow-dir-lg) creating and checking "/x/file31" -(grow-dir-lg) creating and checking "/x/file32" -(grow-dir-lg) creating and checking "/x/file33" -(grow-dir-lg) creating and checking "/x/file34" -(grow-dir-lg) creating and checking "/x/file35" -(grow-dir-lg) creating and checking "/x/file36" -(grow-dir-lg) creating and checking "/x/file37" -(grow-dir-lg) creating and checking "/x/file38" -(grow-dir-lg) creating and checking "/x/file39" -(grow-dir-lg) creating and checking "/x/file40" -(grow-dir-lg) creating and checking "/x/file41" -(grow-dir-lg) creating and checking "/x/file42" -(grow-dir-lg) creating and checking "/x/file43" -(grow-dir-lg) creating and checking "/x/file44" -(grow-dir-lg) creating and checking "/x/file45" -(grow-dir-lg) creating and checking "/x/file46" -(grow-dir-lg) creating and checking "/x/file47" -(grow-dir-lg) creating and checking "/x/file48" -(grow-dir-lg) creating and checking "/x/file49" -(grow-dir-lg) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-dir.inc b/src/tests/filesys/extended/grow-dir.inc deleted file mode 100644 index bee0ba0dd45b1472d1c0ccabcf8129f374ceb606..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-dir.inc +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- c -*- */ - -#include <syscall.h> -#include <stdio.h> -#include "tests/filesys/seq-test.h" -#include "tests/lib.h" -#include "tests/main.h" - -static char buf[512]; - -static size_t -return_block_size (void) -{ - return sizeof buf; -} - -void -test_main (void) -{ - size_t i; - -#ifdef DIRECTORY - CHECK (mkdir (DIRECTORY), "mkdir %s", DIRECTORY); -#define DIR_PREFIX DIRECTORY "/" -#else -#define DIR_PREFIX "" -#endif - for (i = 0; i < FILE_CNT; i++) - { - char file_name[128]; - snprintf (file_name, sizeof file_name, "%sfile%zu", DIR_PREFIX, i); - - msg ("creating and checking \"%s\"", file_name); - - quiet = true; - seq_test (file_name, - buf, sizeof buf, sizeof buf, - return_block_size, NULL); - quiet = false; - } -} diff --git a/src/tests/filesys/extended/grow-file-size-persistence.ck b/src/tests/filesys/extended/grow-file-size-persistence.ck deleted file mode 100644 index 150f383d0d4df217d5cc30fc91c3b77a3e134895..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-file-size-persistence.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_archive ({"testfile" => [random_bytes (2134)]}); -pass; diff --git a/src/tests/filesys/extended/grow-file-size.c b/src/tests/filesys/extended/grow-file-size.c deleted file mode 100644 index 3ce858876d3be943978e9cecaf69a1722b12b71f..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-file-size.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Grows a file from 0 bytes to 2,134 bytes, 37 bytes at a time, - and checks that the file's size is reported correctly at each - step. */ - -#include <syscall.h> -#include "tests/filesys/seq-test.h" -#include "tests/lib.h" -#include "tests/main.h" - -static char buf[2134]; - -static size_t -return_block_size (void) -{ - return 37; -} - -static void -check_file_size (int fd, long ofs) -{ - long size = filesize (fd); - if (size != ofs) - fail ("filesize not updated properly: should be %ld, actually %ld", - ofs, size); -} - -void -test_main (void) -{ - seq_test ("testfile", - buf, sizeof buf, 0, - return_block_size, check_file_size); -} diff --git a/src/tests/filesys/extended/grow-file-size.ck b/src/tests/filesys/extended/grow-file-size.ck deleted file mode 100644 index d81feff594fa9d5dcfc7fba54c53d0a3ec465eef..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-file-size.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-file-size) begin -(grow-file-size) create "testfile" -(grow-file-size) open "testfile" -(grow-file-size) writing "testfile" -(grow-file-size) close "testfile" -(grow-file-size) open "testfile" for verification -(grow-file-size) verified contents of "testfile" -(grow-file-size) close "testfile" -(grow-file-size) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-root-lg-persistence.ck b/src/tests/filesys/extended/grow-root-lg-persistence.ck deleted file mode 100644 index 1692f46c1a6e7cd35d79910deeb56a9e1bff8d93..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-root-lg-persistence.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -my ($fs); -$fs->{"file$_"} = [random_bytes (512)] foreach 0...49; -check_archive ($fs); -pass; diff --git a/src/tests/filesys/extended/grow-root-lg.c b/src/tests/filesys/extended/grow-root-lg.c deleted file mode 100644 index d8d6c0900e18476d22ce8c1c2153256de79ca12d..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-root-lg.c +++ /dev/null @@ -1,4 +0,0 @@ -/* Creates 50 files in the root directory. */ - -#define FILE_CNT 50 -#include "tests/filesys/extended/grow-dir.inc" diff --git a/src/tests/filesys/extended/grow-root-lg.ck b/src/tests/filesys/extended/grow-root-lg.ck deleted file mode 100644 index b174bc9c0332ef514561b5d94b0f9a072e4bbfa3..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-root-lg.ck +++ /dev/null @@ -1,60 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-root-lg) begin -(grow-root-lg) creating and checking "file0" -(grow-root-lg) creating and checking "file1" -(grow-root-lg) creating and checking "file2" -(grow-root-lg) creating and checking "file3" -(grow-root-lg) creating and checking "file4" -(grow-root-lg) creating and checking "file5" -(grow-root-lg) creating and checking "file6" -(grow-root-lg) creating and checking "file7" -(grow-root-lg) creating and checking "file8" -(grow-root-lg) creating and checking "file9" -(grow-root-lg) creating and checking "file10" -(grow-root-lg) creating and checking "file11" -(grow-root-lg) creating and checking "file12" -(grow-root-lg) creating and checking "file13" -(grow-root-lg) creating and checking "file14" -(grow-root-lg) creating and checking "file15" -(grow-root-lg) creating and checking "file16" -(grow-root-lg) creating and checking "file17" -(grow-root-lg) creating and checking "file18" -(grow-root-lg) creating and checking "file19" -(grow-root-lg) creating and checking "file20" -(grow-root-lg) creating and checking "file21" -(grow-root-lg) creating and checking "file22" -(grow-root-lg) creating and checking "file23" -(grow-root-lg) creating and checking "file24" -(grow-root-lg) creating and checking "file25" -(grow-root-lg) creating and checking "file26" -(grow-root-lg) creating and checking "file27" -(grow-root-lg) creating and checking "file28" -(grow-root-lg) creating and checking "file29" -(grow-root-lg) creating and checking "file30" -(grow-root-lg) creating and checking "file31" -(grow-root-lg) creating and checking "file32" -(grow-root-lg) creating and checking "file33" -(grow-root-lg) creating and checking "file34" -(grow-root-lg) creating and checking "file35" -(grow-root-lg) creating and checking "file36" -(grow-root-lg) creating and checking "file37" -(grow-root-lg) creating and checking "file38" -(grow-root-lg) creating and checking "file39" -(grow-root-lg) creating and checking "file40" -(grow-root-lg) creating and checking "file41" -(grow-root-lg) creating and checking "file42" -(grow-root-lg) creating and checking "file43" -(grow-root-lg) creating and checking "file44" -(grow-root-lg) creating and checking "file45" -(grow-root-lg) creating and checking "file46" -(grow-root-lg) creating and checking "file47" -(grow-root-lg) creating and checking "file48" -(grow-root-lg) creating and checking "file49" -(grow-root-lg) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-root-sm-persistence.ck b/src/tests/filesys/extended/grow-root-sm-persistence.ck deleted file mode 100644 index 2b0b8abe157101b5be555b13374b68645d0c0a8b..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-root-sm-persistence.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -my ($fs); -$fs->{"file$_"} = [random_bytes (512)] foreach 0...19; -check_archive ($fs); -pass; diff --git a/src/tests/filesys/extended/grow-root-sm.c b/src/tests/filesys/extended/grow-root-sm.c deleted file mode 100644 index ee375d50996ef3eba6bf021b175ae6cb17344341..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-root-sm.c +++ /dev/null @@ -1,4 +0,0 @@ -/* Creates 20 files in the root directory. */ - -#define FILE_CNT 20 -#include "tests/filesys/extended/grow-dir.inc" diff --git a/src/tests/filesys/extended/grow-root-sm.ck b/src/tests/filesys/extended/grow-root-sm.ck deleted file mode 100644 index 1aac7e9cac77c8f7d6a6c279c8631fe59c3641a7..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-root-sm.ck +++ /dev/null @@ -1,30 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-root-sm) begin -(grow-root-sm) creating and checking "file0" -(grow-root-sm) creating and checking "file1" -(grow-root-sm) creating and checking "file2" -(grow-root-sm) creating and checking "file3" -(grow-root-sm) creating and checking "file4" -(grow-root-sm) creating and checking "file5" -(grow-root-sm) creating and checking "file6" -(grow-root-sm) creating and checking "file7" -(grow-root-sm) creating and checking "file8" -(grow-root-sm) creating and checking "file9" -(grow-root-sm) creating and checking "file10" -(grow-root-sm) creating and checking "file11" -(grow-root-sm) creating and checking "file12" -(grow-root-sm) creating and checking "file13" -(grow-root-sm) creating and checking "file14" -(grow-root-sm) creating and checking "file15" -(grow-root-sm) creating and checking "file16" -(grow-root-sm) creating and checking "file17" -(grow-root-sm) creating and checking "file18" -(grow-root-sm) creating and checking "file19" -(grow-root-sm) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-seq-lg-persistence.ck b/src/tests/filesys/extended/grow-seq-lg-persistence.ck deleted file mode 100644 index 41aaae0a8256df4694d8cf011ea603a9677a25fa..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-seq-lg-persistence.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_archive ({"testme" => [random_bytes (72943)]}); -pass; diff --git a/src/tests/filesys/extended/grow-seq-lg.c b/src/tests/filesys/extended/grow-seq-lg.c deleted file mode 100644 index 3108d172a59dfec78dfcf1e39c4fe731797952d4..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-seq-lg.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Grows a file from 0 bytes to 72,943 bytes, 1,234 bytes at a - time. */ - -#define TEST_SIZE 72943 -#include "tests/filesys/extended/grow-seq.inc" diff --git a/src/tests/filesys/extended/grow-seq-lg.ck b/src/tests/filesys/extended/grow-seq-lg.ck deleted file mode 100644 index 90fcd8cceadf478b1272cf6ece651747497e8bb7..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-seq-lg.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-seq-lg) begin -(grow-seq-lg) create "testme" -(grow-seq-lg) open "testme" -(grow-seq-lg) writing "testme" -(grow-seq-lg) close "testme" -(grow-seq-lg) open "testme" for verification -(grow-seq-lg) verified contents of "testme" -(grow-seq-lg) close "testme" -(grow-seq-lg) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-seq-sm-persistence.ck b/src/tests/filesys/extended/grow-seq-sm-persistence.ck deleted file mode 100644 index 6cb0bd8656d5861ee0593f441c17fc6b2dab339d..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-seq-sm-persistence.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_archive ({"testme" => [random_bytes (5678)]}); -pass; diff --git a/src/tests/filesys/extended/grow-seq-sm.c b/src/tests/filesys/extended/grow-seq-sm.c deleted file mode 100644 index 3656e2ee13c5c14986a1060f74ae8bb2d39e9b85..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-seq-sm.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Grows a file from 0 bytes to 5,678 bytes, 1,234 bytes at a - time. */ - -#define TEST_SIZE 5678 -#include "tests/filesys/extended/grow-seq.inc" diff --git a/src/tests/filesys/extended/grow-seq-sm.ck b/src/tests/filesys/extended/grow-seq-sm.ck deleted file mode 100644 index 5cf451850addaf0edb83e2b422beded39687a5cf..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-seq-sm.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-seq-sm) begin -(grow-seq-sm) create "testme" -(grow-seq-sm) open "testme" -(grow-seq-sm) writing "testme" -(grow-seq-sm) close "testme" -(grow-seq-sm) open "testme" for verification -(grow-seq-sm) verified contents of "testme" -(grow-seq-sm) close "testme" -(grow-seq-sm) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-seq.inc b/src/tests/filesys/extended/grow-seq.inc deleted file mode 100644 index 1b7710c9c1d4d8a91867b17e8e5f4365fc4cd0d3..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-seq.inc +++ /dev/null @@ -1,20 +0,0 @@ -/* -*- c -*- */ - -#include "tests/filesys/seq-test.h" -#include "tests/main.h" - -static char buf[TEST_SIZE]; - -static size_t -return_block_size (void) -{ - return 1234; -} - -void -test_main (void) -{ - seq_test ("testme", - buf, sizeof buf, 0, - return_block_size, NULL); -} diff --git a/src/tests/filesys/extended/grow-sparse-persistence.ck b/src/tests/filesys/extended/grow-sparse-persistence.ck deleted file mode 100644 index 3f06a5b81e98113fdd11e13b85fc24a0440f21bb..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-sparse-persistence.ck +++ /dev/null @@ -1,6 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_archive ({"testfile" => ["\0" x 76543]}); -pass; diff --git a/src/tests/filesys/extended/grow-sparse.c b/src/tests/filesys/extended/grow-sparse.c deleted file mode 100644 index 6eab210bd135045071b09e3f84c8aa78a433df14..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-sparse.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Tests that seeking past the end of a file and writing will - properly zero out the region in between. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -static char buf[76543]; - -void -test_main (void) -{ - const char *file_name = "testfile"; - char zero = 0; - int fd; - - CHECK (create (file_name, 0), "create \"%s\"", file_name); - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - msg ("seek \"%s\"", file_name); - seek (fd, sizeof buf - 1); - CHECK (write (fd, &zero, 1) > 0, "write \"%s\"", file_name); - msg ("close \"%s\"", file_name); - close (fd); - check_file (file_name, buf, sizeof buf); -} diff --git a/src/tests/filesys/extended/grow-sparse.ck b/src/tests/filesys/extended/grow-sparse.ck deleted file mode 100644 index 379ba2c7e2552b594f3eb2cffb8dbb381d2e056e..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-sparse.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-sparse) begin -(grow-sparse) create "testfile" -(grow-sparse) open "testfile" -(grow-sparse) seek "testfile" -(grow-sparse) write "testfile" -(grow-sparse) close "testfile" -(grow-sparse) open "testfile" for verification -(grow-sparse) verified contents of "testfile" -(grow-sparse) close "testfile" -(grow-sparse) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-tell-persistence.ck b/src/tests/filesys/extended/grow-tell-persistence.ck deleted file mode 100644 index d93a422709c68bbb4582c6de876d336d5162cac2..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-tell-persistence.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_archive ({"foobar" => [random_bytes (2134)]}); -pass; diff --git a/src/tests/filesys/extended/grow-tell.c b/src/tests/filesys/extended/grow-tell.c deleted file mode 100644 index 5f5da5b930e88b9a3a9ecc02270cebc1431b1718..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-tell.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Checks that growing a file updates the file position - correctly. */ - -#include <syscall.h> -#include "tests/filesys/seq-test.h" -#include "tests/lib.h" -#include "tests/main.h" - -static char buf[2134]; - -static size_t -return_block_size (void) -{ - return 37; -} - -static void -check_tell (int fd, long ofs) -{ - long pos = tell (fd); - if (pos != ofs) - fail ("file position not updated properly: should be %ld, actually %ld", - ofs, pos); -} - -void -test_main (void) -{ - seq_test ("foobar", - buf, sizeof buf, 0, - return_block_size, check_tell); -} diff --git a/src/tests/filesys/extended/grow-tell.ck b/src/tests/filesys/extended/grow-tell.ck deleted file mode 100644 index fe94707cbbbbbf7c69987cb3a4b4163d76a9fb08..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-tell.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-tell) begin -(grow-tell) create "foobar" -(grow-tell) open "foobar" -(grow-tell) writing "foobar" -(grow-tell) close "foobar" -(grow-tell) open "foobar" for verification -(grow-tell) verified contents of "foobar" -(grow-tell) close "foobar" -(grow-tell) end -EOF -pass; diff --git a/src/tests/filesys/extended/grow-two-files-persistence.ck b/src/tests/filesys/extended/grow-two-files-persistence.ck deleted file mode 100644 index 1c4ced18ee018afc22716cea279fa8c5aec375f2..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-two-files-persistence.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -my ($a) = random_bytes (8143); -my ($b) = random_bytes (8143); -check_archive ({"a" => [$a], "b" => [$b]}); -pass; diff --git a/src/tests/filesys/extended/grow-two-files.c b/src/tests/filesys/extended/grow-two-files.c deleted file mode 100644 index 6a8fb1c96fc7600ebaeb6abe125be5c9af5bb6f4..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-two-files.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Grows two files in parallel and checks that their contents are - correct. */ - -#include <random.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -#define FILE_SIZE 8143 -static char buf_a[FILE_SIZE]; -static char buf_b[FILE_SIZE]; - -static void -write_some_bytes (const char *file_name, int fd, const char *buf, size_t *ofs) -{ - if (*ofs < FILE_SIZE) - { - size_t block_size = random_ulong () % (FILE_SIZE / 8) + 1; - size_t ret_val; - if (block_size > FILE_SIZE - *ofs) - block_size = FILE_SIZE - *ofs; - - ret_val = write (fd, buf + *ofs, block_size); - if (ret_val != block_size) - fail ("write %zu bytes at offset %zu in \"%s\" returned %zu", - block_size, *ofs, file_name, ret_val); - *ofs += block_size; - } -} - -void -test_main (void) -{ - int fd_a, fd_b; - size_t ofs_a = 0, ofs_b = 0; - - random_init (0); - random_bytes (buf_a, sizeof buf_a); - random_bytes (buf_b, sizeof buf_b); - - CHECK (create ("a", 0), "create \"a\""); - CHECK (create ("b", 0), "create \"b\""); - - CHECK ((fd_a = open ("a")) > 1, "open \"a\""); - CHECK ((fd_b = open ("b")) > 1, "open \"b\""); - - msg ("write \"a\" and \"b\" alternately"); - while (ofs_a < FILE_SIZE || ofs_b < FILE_SIZE) - { - write_some_bytes ("a", fd_a, buf_a, &ofs_a); - write_some_bytes ("b", fd_b, buf_b, &ofs_b); - } - - msg ("close \"a\""); - close (fd_a); - - msg ("close \"b\""); - close (fd_b); - - check_file ("a", buf_a, FILE_SIZE); - check_file ("b", buf_b, FILE_SIZE); -} diff --git a/src/tests/filesys/extended/grow-two-files.ck b/src/tests/filesys/extended/grow-two-files.ck deleted file mode 100644 index b5e754ab42be6a36820e76f889f34373a29fee61..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/grow-two-files.ck +++ /dev/null @@ -1,23 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(grow-two-files) begin -(grow-two-files) create "a" -(grow-two-files) create "b" -(grow-two-files) open "a" -(grow-two-files) open "b" -(grow-two-files) write "a" and "b" alternately -(grow-two-files) close "a" -(grow-two-files) close "b" -(grow-two-files) open "a" for verification -(grow-two-files) verified contents of "a" -(grow-two-files) close "a" -(grow-two-files) open "b" for verification -(grow-two-files) verified contents of "b" -(grow-two-files) close "b" -(grow-two-files) end -EOF -pass; diff --git a/src/tests/filesys/extended/mk-tree.c b/src/tests/filesys/extended/mk-tree.c deleted file mode 100644 index a36bb8815d18d2a6674449aada49746330854f36..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/mk-tree.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Library function for creating a tree of directories. */ - -#include <stdio.h> -#include <syscall.h> -#include "tests/filesys/extended/mk-tree.h" -#include "tests/lib.h" - -static void do_mkdir (const char *format, ...) PRINTF_FORMAT (1, 2); -static void do_touch (const char *format, ...) PRINTF_FORMAT (1, 2); - -void -make_tree (int at, int bt, int ct, int dt) -{ - char try[128]; - int a, b, c, d; - int fd; - - msg ("creating /0/0/0/0 through /%d/%d/%d/%d...", - at - 1, bt - 1, ct - 1, dt - 1); - quiet = true; - for (a = 0; a < at; a++) - { - do_mkdir ("/%d", a); - for (b = 0; b < bt; b++) - { - do_mkdir ("/%d/%d", a, b); - for (c = 0; c < ct; c++) - { - do_mkdir ("/%d/%d/%d", a, b, c); - for (d = 0; d < dt; d++) - do_touch ("/%d/%d/%d/%d", a, b, c, d); - } - } - } - quiet = false; - - snprintf (try, sizeof try, "/%d/%d/%d/%d", 0, bt - 1, 0, dt - 1); - CHECK ((fd = open (try)) > 1, "open \"%s\"", try); - msg ("close \"%s\"", try); - close (fd); -} - -static void -do_mkdir (const char *format, ...) -{ - char dir[128]; - va_list args; - - va_start (args, format); - vsnprintf (dir, sizeof dir, format, args); - va_end (args); - - CHECK (mkdir (dir), "mkdir \"%s\"", dir); -} - -static void -do_touch (const char *format, ...) -{ - char file[128]; - va_list args; - - va_start (args, format); - vsnprintf (file, sizeof file, format, args); - va_end (args); - - CHECK (create (file, 0), "create \"%s\"", file); -} diff --git a/src/tests/filesys/extended/mk-tree.h b/src/tests/filesys/extended/mk-tree.h deleted file mode 100644 index df0d5a636a05a3b5f9d2d5d074b94910430c2165..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/mk-tree.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TESTS_FILESYS_EXTENDED_MK_TREE_H -#define TESTS_FILESYS_EXTENDED_MK_TREE_H - -void make_tree (int at, int bt, int ct, int dt); - -#endif /* tests/filesys/extended/mk-tree.h */ diff --git a/src/tests/filesys/extended/syn-rw-persistence.ck b/src/tests/filesys/extended/syn-rw-persistence.ck deleted file mode 100644 index 62d57ee995ffee2e10a081e0100bb2e404b54522..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/syn-rw-persistence.ck +++ /dev/null @@ -1,8 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_archive ({"child-syn-rw" => "tests/filesys/extended/child-syn-rw", - "logfile" => [random_bytes (8 * 512)]}); -pass; diff --git a/src/tests/filesys/extended/syn-rw.c b/src/tests/filesys/extended/syn-rw.c deleted file mode 100644 index 657dfb56c0acd8aef6cf7eedff4ee65a2d81f329..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/syn-rw.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Grows a file in chunks while subprocesses read the growing - file. */ - -#include <random.h> -#include <syscall.h> -#include "tests/filesys/extended/syn-rw.h" -#include "tests/lib.h" -#include "tests/main.h" - -char buf[BUF_SIZE]; - -#define CHILD_CNT 4 - -void -test_main (void) -{ - pid_t children[CHILD_CNT]; - size_t ofs; - int fd; - - CHECK (create (file_name, 0), "create \"%s\"", file_name); - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - - exec_children ("child-syn-rw", children, CHILD_CNT); - - random_bytes (buf, sizeof buf); - quiet = true; - for (ofs = 0; ofs < BUF_SIZE; ofs += CHUNK_SIZE) - CHECK (write (fd, buf + ofs, CHUNK_SIZE) > 0, - "write %d bytes at offset %zu in \"%s\"", - (int) CHUNK_SIZE, ofs, file_name); - quiet = false; - - wait_children (children, CHILD_CNT); -} diff --git a/src/tests/filesys/extended/syn-rw.ck b/src/tests/filesys/extended/syn-rw.ck deleted file mode 100644 index ac82aa8c77915d9b21499cac7287100b1f0338cd..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/syn-rw.ck +++ /dev/null @@ -1,20 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::random; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(syn-rw) begin -(syn-rw) create "logfile" -(syn-rw) open "logfile" -(syn-rw) exec child 1 of 4: "child-syn-rw 0" -(syn-rw) exec child 2 of 4: "child-syn-rw 1" -(syn-rw) exec child 3 of 4: "child-syn-rw 2" -(syn-rw) exec child 4 of 4: "child-syn-rw 3" -(syn-rw) wait for child 1 of 4 returned 0 (expected 0) -(syn-rw) wait for child 2 of 4 returned 1 (expected 1) -(syn-rw) wait for child 3 of 4 returned 2 (expected 2) -(syn-rw) wait for child 4 of 4 returned 3 (expected 3) -(syn-rw) end -EOF -pass; diff --git a/src/tests/filesys/extended/syn-rw.h b/src/tests/filesys/extended/syn-rw.h deleted file mode 100644 index 170aeb470385bb0bd08b1c94a63cbaa02e21a196..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/syn-rw.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef TESTS_FILESYS_EXTENDED_SYN_RW_H -#define TESTS_FILESYS_EXTENDED_SYN_RW_H - -#define CHUNK_SIZE 8 -#define CHUNK_CNT 512 -#define BUF_SIZE (CHUNK_SIZE * CHUNK_CNT) -static const char file_name[] = "logfile"; - -#endif /* tests/filesys/extended/syn-rw.h */ diff --git a/src/tests/filesys/extended/tar.c b/src/tests/filesys/extended/tar.c deleted file mode 100644 index 9801484da64251b733d19a55800b287e6c74a9bb..0000000000000000000000000000000000000000 --- a/src/tests/filesys/extended/tar.c +++ /dev/null @@ -1,208 +0,0 @@ -/* tar.c - - Creates a tar archive. */ - -#include <ustar.h> -#include <syscall.h> -#include <stdio.h> -#include <string.h> - -static void usage (void); -static bool make_tar_archive (const char *archive_name, - char *files[], size_t file_cnt); - -int -main (int argc, char *argv[]) -{ - if (argc < 3) - usage (); - - return (make_tar_archive (argv[1], argv + 2, argc - 2) - ? EXIT_SUCCESS : EXIT_FAILURE); -} - -static void -usage (void) -{ - printf ("tar, tar archive creator\n" - "Usage: tar ARCHIVE FILE...\n" - "where ARCHIVE is the tar archive to create\n" - " and FILE... is a list of files or directories to put into it.\n" - "(ARCHIVE itself will not be included in the archive, even if it\n" - "is in a directory to be archived.)\n"); - exit (EXIT_FAILURE); -} - -static bool archive_file (char file_name[], size_t file_name_size, - int archive_fd, bool *write_error); - -static bool archive_ordinary_file (const char *file_name, int file_fd, - int archive_fd, bool *write_error); -static bool archive_directory (char file_name[], size_t file_name_size, - int file_fd, int archive_fd, bool *write_error); -static bool write_header (const char *file_name, enum ustar_type, int size, - int archive_fd, bool *write_error); - -static bool do_write (int fd, const char *buffer, int size, bool *write_error); - -static bool -make_tar_archive (const char *archive_name, char *files[], size_t file_cnt) -{ - static const char zeros[512]; - int archive_fd; - bool success = true; - bool write_error = false; - size_t i; - - if (!create (archive_name, 0)) - { - printf ("%s: create failed\n", archive_name); - return false; - } - archive_fd = open (archive_name); - if (archive_fd < 0) - { - printf ("%s: open failed\n", archive_name); - return false; - } - - for (i = 0; i < file_cnt; i++) - { - char file_name[128]; - - strlcpy (file_name, files[i], sizeof file_name); - if (!archive_file (file_name, sizeof file_name, - archive_fd, &write_error)) - success = false; - } - - if (!do_write (archive_fd, zeros, 512, &write_error) - || !do_write (archive_fd, zeros, 512, &write_error)) - success = false; - - close (archive_fd); - - return success; -} - -static bool -archive_file (char file_name[], size_t file_name_size, - int archive_fd, bool *write_error) -{ - int file_fd = open (file_name); - if (file_fd >= 0) - { - bool success; - - if (inumber (file_fd) != inumber (archive_fd)) - { - if (!isdir (file_fd)) - success = archive_ordinary_file (file_name, file_fd, - archive_fd, write_error); - else - success = archive_directory (file_name, file_name_size, file_fd, - archive_fd, write_error); - } - else - { - /* Nothing to do: don't try to archive the archive file. */ - success = true; - } - - close (file_fd); - - return success; - } - else - { - printf ("%s: open failed\n", file_name); - return false; - } -} - -static bool -archive_ordinary_file (const char *file_name, int file_fd, - int archive_fd, bool *write_error) -{ - bool read_error = false; - bool success = true; - int file_size = filesize (file_fd); - - if (!write_header (file_name, USTAR_REGULAR, file_size, - archive_fd, write_error)) - return false; - - while (file_size > 0) - { - static char buf[512]; - int chunk_size = file_size > 512 ? 512 : file_size; - int read_retval = read (file_fd, buf, chunk_size); - int bytes_read = read_retval > 0 ? read_retval : 0; - - if (bytes_read != chunk_size && !read_error) - { - printf ("%s: read error\n", file_name); - read_error = true; - success = false; - } - - memset (buf + bytes_read, 0, 512 - bytes_read); - if (!do_write (archive_fd, buf, 512, write_error)) - success = false; - - file_size -= chunk_size; - } - - return success; -} - -static bool -archive_directory (char file_name[], size_t file_name_size, int file_fd, - int archive_fd, bool *write_error) -{ - size_t dir_len; - bool success = true; - - dir_len = strlen (file_name); - if (dir_len + 1 + READDIR_MAX_LEN + 1 > file_name_size) - { - printf ("%s: file name too long\n", file_name); - return false; - } - - if (!write_header (file_name, USTAR_DIRECTORY, 0, archive_fd, write_error)) - return false; - - file_name[dir_len] = '/'; - while (readdir (file_fd, &file_name[dir_len + 1])) - if (!archive_file (file_name, file_name_size, archive_fd, write_error)) - success = false; - file_name[dir_len] = '\0'; - - return success; -} - -static bool -write_header (const char *file_name, enum ustar_type type, int size, - int archive_fd, bool *write_error) -{ - static char header[512]; - return (ustar_make_header (file_name, type, size, header) - && do_write (archive_fd, header, 512, write_error)); -} - -static bool -do_write (int fd, const char *buffer, int size, bool *write_error) -{ - if (write (fd, buffer, size) == size) - return true; - else - { - if (!*write_error) - { - printf ("error writing archive\n"); - *write_error = true; - } - return false; - } -} diff --git a/src/tests/filesys/seq-test.c b/src/tests/filesys/seq-test.c deleted file mode 100644 index 8ce222c156b0692e5847ea81a4f487ca51211214..0000000000000000000000000000000000000000 --- a/src/tests/filesys/seq-test.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "tests/filesys/seq-test.h" -#include <random.h> -#include <syscall.h> -#include "tests/lib.h" - -void -seq_test (const char *file_name, void *buf, size_t size, size_t initial_size, - size_t (*block_size_func) (void), - void (*check_func) (int fd, long ofs)) -{ - size_t ofs; - int fd; - - random_bytes (buf, size); - CHECK (create (file_name, initial_size), "create \"%s\"", file_name); - CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); - - ofs = 0; - msg ("writing \"%s\"", file_name); - while (ofs < size) - { - size_t block_size = block_size_func (); - if (block_size > size - ofs) - block_size = size - ofs; - - if (write (fd, buf + ofs, block_size) != (int) block_size) - fail ("write %zu bytes at offset %zu in \"%s\" failed", - block_size, ofs, file_name); - - ofs += block_size; - if (check_func != NULL) - check_func (fd, ofs); - } - msg ("close \"%s\"", file_name); - close (fd); - check_file (file_name, buf, size); -} diff --git a/src/tests/filesys/seq-test.h b/src/tests/filesys/seq-test.h deleted file mode 100644 index 0697381f633d2d89ef8d780216b2cb6ba452b1d2..0000000000000000000000000000000000000000 --- a/src/tests/filesys/seq-test.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef TESTS_FILESYS_SEQ_TEST_H -#define TESTS_FILESYS_SEQ_TEST_H - -#include <stddef.h> - -void seq_test (const char *file_name, - void *buf, size_t size, size_t initial_size, - size_t (*block_size_func) (void), - void (*check_func) (int fd, long ofs)); - -#endif /* tests/filesys/seq-test.h */ diff --git a/src/tests/internal/list.c b/src/tests/internal/list.c deleted file mode 100644 index 836c69ef3fe9644edec51b7552bef56cc4b0fb94..0000000000000000000000000000000000000000 --- a/src/tests/internal/list.c +++ /dev/null @@ -1,174 +0,0 @@ -/* Test program for lib/kernel/list.c. - - Attempts to test the list functionality that is not - sufficiently tested elsewhere in Pintos. - - This is not a test we will run on your submitted projects. - It is here for completeness. -*/ - -#undef NDEBUG -#include <debug.h> -#include <list.h> -#include <random.h> -#include <stdio.h> -#include "threads/test.h" - -/* Maximum number of elements in a linked list that we will - test. */ -#define MAX_SIZE 64 - -/* A linked list element. */ -struct value - { - struct list_elem elem; /* List element. */ - int value; /* Item value. */ - }; - -static void shuffle (struct value[], size_t); -static bool value_less (const struct list_elem *, const struct list_elem *, - void *); -static void verify_list_fwd (struct list *, int size); -static void verify_list_bkwd (struct list *, int size); - -/* Test the linked list implementation. */ -void -test (void) -{ - int size; - - printf ("testing various size lists:"); - for (size = 0; size < MAX_SIZE; size++) - { - int repeat; - - printf (" %d", size); - for (repeat = 0; repeat < 10; repeat++) - { - static struct value values[MAX_SIZE * 4]; - struct list list; - struct list_elem *e; - int i, ofs; - - /* Put values 0...SIZE in random order in VALUES. */ - for (i = 0; i < size; i++) - values[i].value = i; - shuffle (values, size); - - /* Assemble list. */ - list_init (&list); - for (i = 0; i < size; i++) - list_push_back (&list, &values[i].elem); - - /* Verify correct minimum and maximum elements. */ - e = list_min (&list, value_less, NULL); - ASSERT (size ? list_entry (e, struct value, elem)->value == 0 - : e == list_begin (&list)); - e = list_max (&list, value_less, NULL); - ASSERT (size ? list_entry (e, struct value, elem)->value == size - 1 - : e == list_begin (&list)); - - /* Sort and verify list. */ - list_sort (&list, value_less, NULL); - verify_list_fwd (&list, size); - - /* Reverse and verify list. */ - list_reverse (&list); - verify_list_bkwd (&list, size); - - /* Shuffle, insert using list_insert_ordered(), - and verify ordering. */ - shuffle (values, size); - list_init (&list); - for (i = 0; i < size; i++) - list_insert_ordered (&list, &values[i].elem, - value_less, NULL); - verify_list_fwd (&list, size); - - /* Duplicate some items, uniquify, and verify. */ - ofs = size; - for (e = list_begin (&list); e != list_end (&list); - e = list_next (e)) - { - struct value *v = list_entry (e, struct value, elem); - int copies = random_ulong () % 4; - while (copies-- > 0) - { - values[ofs].value = v->value; - list_insert (e, &values[ofs++].elem); - } - } - ASSERT ((size_t) ofs < sizeof values / sizeof *values); - list_unique (&list, NULL, value_less, NULL); - verify_list_fwd (&list, size); - } - } - - printf (" done\n"); - printf ("list: PASS\n"); -} - -/* Shuffles the CNT elements in ARRAY into random order. */ -static void -shuffle (struct value *array, size_t cnt) -{ - size_t i; - - for (i = 0; i < cnt; i++) - { - size_t j = i + random_ulong () % (cnt - i); - struct value t = array[j]; - array[j] = array[i]; - array[i] = t; - } -} - -/* Returns true if value A is less than value B, false - otherwise. */ -static bool -value_less (const struct list_elem *a_, const struct list_elem *b_, - void *aux UNUSED) -{ - const struct value *a = list_entry (a_, struct value, elem); - const struct value *b = list_entry (b_, struct value, elem); - - return a->value < b->value; -} - -/* Verifies that LIST contains the values 0...SIZE when traversed - in forward order. */ -static void -verify_list_fwd (struct list *list, int size) -{ - struct list_elem *e; - int i; - - for (i = 0, e = list_begin (list); - i < size && e != list_end (list); - i++, e = list_next (e)) - { - struct value *v = list_entry (e, struct value, elem); - ASSERT (i == v->value); - } - ASSERT (i == size); - ASSERT (e == list_end (list)); -} - -/* Verifies that LIST contains the values 0...SIZE when traversed - in reverse order. */ -static void -verify_list_bkwd (struct list *list, int size) -{ - struct list_elem *e; - int i; - - for (i = 0, e = list_rbegin (list); - i < size && e != list_rend (list); - i++, e = list_prev (e)) - { - struct value *v = list_entry (e, struct value, elem); - ASSERT (i == v->value); - } - ASSERT (i == size); - ASSERT (e == list_rend (list)); -} diff --git a/src/tests/internal/stdio.c b/src/tests/internal/stdio.c deleted file mode 100644 index fb60cda156d45706e853f08df09f0407e488d1d3..0000000000000000000000000000000000000000 --- a/src/tests/internal/stdio.c +++ /dev/null @@ -1,208 +0,0 @@ -/* Test program for printf() in lib/stdio.c. - - Attempts to test printf() functionality that is not - sufficiently tested elsewhere in Pintos. - - This is not a test we will run on your submitted projects. - It is here for completeness. -*/ - -#undef NDEBUG -#include <limits.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "threads/test.h" - -/* Number of failures so far. */ -static int failure_cnt; - -static void -checkf (const char *expect, const char *format, ...) -{ - char output[128]; - va_list args; - - printf ("\"%s\" -> \"%s\": ", format, expect); - - va_start (args, format); - vsnprintf (output, sizeof output, format, args); - va_end (args); - - if (strcmp (expect, output)) - { - printf ("\nFAIL: actual output \"%s\"\n", output); - failure_cnt++; - } - else - printf ("okay\n"); -} - -/* Test printf() implementation. */ -void -test (void) -{ - printf ("Testing formats:"); - - /* Check that commas show up in the right places, for positive - numbers. */ - checkf ("1", "%'d", 1); - checkf ("12", "%'d", 12); - checkf ("123", "%'d", 123); - checkf ("1,234", "%'d", 1234); - checkf ("12,345", "%'d", 12345); - checkf ("123,456", "%'ld", 123456L); - checkf ("1,234,567", "%'ld", 1234567L); - checkf ("12,345,678", "%'ld", 12345678L); - checkf ("123,456,789", "%'ld", 123456789L); - checkf ("1,234,567,890", "%'ld", 1234567890L); - checkf ("12,345,678,901", "%'lld", 12345678901LL); - checkf ("123,456,789,012", "%'lld", 123456789012LL); - checkf ("1,234,567,890,123", "%'lld", 1234567890123LL); - checkf ("12,345,678,901,234", "%'lld", 12345678901234LL); - checkf ("123,456,789,012,345", "%'lld", 123456789012345LL); - checkf ("1,234,567,890,123,456", "%'lld", 1234567890123456LL); - checkf ("12,345,678,901,234,567", "%'lld", 12345678901234567LL); - checkf ("123,456,789,012,345,678", "%'lld", 123456789012345678LL); - checkf ("1,234,567,890,123,456,789", "%'lld", 1234567890123456789LL); - - /* Check that commas show up in the right places, for positive - numbers. */ - checkf ("-1", "%'d", -1); - checkf ("-12", "%'d", -12); - checkf ("-123", "%'d", -123); - checkf ("-1,234", "%'d", -1234); - checkf ("-12,345", "%'d", -12345); - checkf ("-123,456", "%'ld", -123456L); - checkf ("-1,234,567", "%'ld", -1234567L); - checkf ("-12,345,678", "%'ld", -12345678L); - checkf ("-123,456,789", "%'ld", -123456789L); - checkf ("-1,234,567,890", "%'ld", -1234567890L); - checkf ("-12,345,678,901", "%'lld", -12345678901LL); - checkf ("-123,456,789,012", "%'lld", -123456789012LL); - checkf ("-1,234,567,890,123", "%'lld", -1234567890123LL); - checkf ("-12,345,678,901,234", "%'lld", -12345678901234LL); - checkf ("-123,456,789,012,345", "%'lld", -123456789012345LL); - checkf ("-1,234,567,890,123,456", "%'lld", -1234567890123456LL); - checkf ("-12,345,678,901,234,567", "%'lld", -12345678901234567LL); - checkf ("-123,456,789,012,345,678", "%'lld", -123456789012345678LL); - checkf ("-1,234,567,890,123,456,789", "%'lld", -1234567890123456789LL); - - /* Check signed integer conversions. */ - checkf (" 0", "%5d", 0); - checkf ("0 ", "%-5d", 0); - checkf (" +0", "%+5d", 0); - checkf ("+0 ", "%+-5d", 0); - checkf (" 0", "% 5d", 0); - checkf ("00000", "%05d", 0); - checkf (" ", "%5.0d", 0); - checkf (" 00", "%5.2d", 0); - checkf ("0", "%d", 0); - - checkf (" 1", "%5d", 1); - checkf ("1 ", "%-5d", 1); - checkf (" +1", "%+5d", 1); - checkf ("+1 ", "%+-5d", 1); - checkf (" 1", "% 5d", 1); - checkf ("00001", "%05d", 1); - checkf (" 1", "%5.0d", 1); - checkf (" 01", "%5.2d", 1); - checkf ("1", "%d", 1); - - checkf (" -1", "%5d", -1); - checkf ("-1 ", "%-5d", -1); - checkf (" -1", "%+5d", -1); - checkf ("-1 ", "%+-5d", -1); - checkf (" -1", "% 5d", -1); - checkf ("-0001", "%05d", -1); - checkf (" -1", "%5.0d", -1); - checkf (" -01", "%5.2d", -1); - checkf ("-1", "%d", -1); - - checkf ("12345", "%5d", 12345); - checkf ("12345", "%-5d", 12345); - checkf ("+12345", "%+5d", 12345); - checkf ("+12345", "%+-5d", 12345); - checkf (" 12345", "% 5d", 12345); - checkf ("12345", "%05d", 12345); - checkf ("12345", "%5.0d", 12345); - checkf ("12345", "%5.2d", 12345); - checkf ("12345", "%d", 12345); - - checkf ("123456", "%5d", 123456); - checkf ("123456", "%-5d", 123456); - checkf ("+123456", "%+5d", 123456); - checkf ("+123456", "%+-5d", 123456); - checkf (" 123456", "% 5d", 123456); - checkf ("123456", "%05d", 123456); - checkf ("123456", "%5.0d", 123456); - checkf ("123456", "%5.2d", 123456); - checkf ("123456", "%d", 123456); - - /* Check unsigned integer conversions. */ - checkf (" 0", "%5u", 0); - checkf (" 0", "%5o", 0); - checkf (" 0", "%5x", 0); - checkf (" 0", "%5X", 0); - checkf (" 0", "%#5o", 0); - checkf (" 0", "%#5x", 0); - checkf (" 0", "%#5X", 0); - checkf (" 00000000", "%#10.8x", 0); - - checkf (" 1", "%5u", 1); - checkf (" 1", "%5o", 1); - checkf (" 1", "%5x", 1); - checkf (" 1", "%5X", 1); - checkf (" 01", "%#5o", 1); - checkf (" 0x1", "%#5x", 1); - checkf (" 0X1", "%#5X", 1); - checkf ("0x00000001", "%#10.8x", 1); - - checkf ("123456", "%5u", 123456); - checkf ("361100", "%5o", 123456); - checkf ("1e240", "%5x", 123456); - checkf ("1E240", "%5X", 123456); - checkf ("0361100", "%#5o", 123456); - checkf ("0x1e240", "%#5x", 123456); - checkf ("0X1E240", "%#5X", 123456); - checkf ("0x0001e240", "%#10.8x", 123456); - - /* Character and string conversions. */ - checkf ("foobar", "%c%c%c%c%c%c", 'f', 'o', 'o', 'b', 'a', 'r'); - checkf (" left-right ", "%6s%s%-7s", "left", "-", "right"); - checkf ("trim", "%.4s", "trimoff"); - checkf ("%%", "%%%%"); - - /* From Cristian Cadar's automatic test case generator. */ - checkf (" abcdefgh", "%9s", "abcdefgh"); - checkf ("36657730000", "%- o", (unsigned) 036657730000); - checkf ("4139757568", "%- u", (unsigned) 4139757568UL); - checkf ("f6bfb000", "%- x", (unsigned) 0xf6bfb000); - checkf ("36657730000", "%-to", (ptrdiff_t) 036657730000); - checkf ("4139757568", "%-tu", (ptrdiff_t) 4139757568UL); - checkf ("-155209728", "%-zi", (size_t) -155209728); - checkf ("-155209728", "%-zd", (size_t) -155209728); - checkf ("036657730000", "%+#o", (unsigned) 036657730000); - checkf ("0xf6bfb000", "%+#x", (unsigned) 0xf6bfb000); - checkf ("-155209728", "% zi", (size_t) -155209728); - checkf ("-155209728", "% zd", (size_t) -155209728); - checkf ("4139757568", "% tu", (ptrdiff_t) 4139757568UL); - checkf ("036657730000", "% #o", (unsigned) 036657730000); - checkf ("0xf6bfb000", "% #x", (unsigned) 0xf6bfb000); - checkf ("0xf6bfb000", "%# x", (unsigned) 0xf6bfb000); - checkf ("-155209728", "%#zd", (size_t) -155209728); - checkf ("-155209728", "%0zi", (size_t) -155209728); - checkf ("4,139,757,568", "%'tu", (ptrdiff_t) 4139757568UL); - checkf ("-155,209,728", "%-'d", -155209728); - checkf ("-155209728", "%.zi", (size_t) -155209728); - checkf ("-155209728", "%zi", (size_t) -155209728); - checkf ("-155209728", "%zd", (size_t) -155209728); - checkf ("-155209728", "%+zi", (size_t) -155209728); - - if (failure_cnt == 0) - printf ("\nstdio: PASS\n"); - else - printf ("\nstdio: FAIL: %d tests failed\n", failure_cnt); -} diff --git a/src/tests/internal/stdlib.c b/src/tests/internal/stdlib.c deleted file mode 100644 index ad0f0f9a82816cd991300ed97f6740a94f7a3386..0000000000000000000000000000000000000000 --- a/src/tests/internal/stdlib.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Test program for sorting and searching in lib/stdlib.c. - - Attempts to test the sorting and searching functionality that - is not sufficiently tested elsewhere in Pintos. - - This is not a test we will run on your submitted projects. - It is here for completeness. -*/ - -#undef NDEBUG -#include <debug.h> -#include <limits.h> -#include <random.h> -#include <stdlib.h> -#include <stdio.h> -#include "threads/test.h" - -/* Maximum number of elements in an array that we will test. */ -#define MAX_CNT 4096 - -static void shuffle (int[], size_t); -static int compare_ints (const void *, const void *); -static void verify_order (const int[], size_t); -static void verify_bsearch (const int[], size_t); - -/* Test sorting and searching implementations. */ -void -test (void) -{ - int cnt; - - printf ("testing various size arrays:"); - for (cnt = 0; cnt < MAX_CNT; cnt = cnt * 4 / 3 + 1) - { - int repeat; - - printf (" %zu", cnt); - for (repeat = 0; repeat < 10; repeat++) - { - static int values[MAX_CNT]; - int i; - - /* Put values 0...CNT in random order in VALUES. */ - for (i = 0; i < cnt; i++) - values[i] = i; - shuffle (values, cnt); - - /* Sort VALUES, then verify ordering. */ - qsort (values, cnt, sizeof *values, compare_ints); - verify_order (values, cnt); - verify_bsearch (values, cnt); - } - } - - printf (" done\n"); - printf ("stdlib: PASS\n"); -} - -/* Shuffles the CNT elements in ARRAY into random order. */ -static void -shuffle (int *array, size_t cnt) -{ - size_t i; - - for (i = 0; i < cnt; i++) - { - size_t j = i + random_ulong () % (cnt - i); - int t = array[j]; - array[j] = array[i]; - array[i] = t; - } -} - -/* Returns 1 if *A is greater than *B, - 0 if *A equals *B, - -1 if *A is less than *B. */ -static int -compare_ints (const void *a_, const void *b_) -{ - const int *a = a_; - const int *b = b_; - - return *a < *b ? -1 : *a > *b; -} - -/* Verifies that ARRAY contains the CNT ints 0...CNT-1. */ -static void -verify_order (const int *array, size_t cnt) -{ - int i; - - for (i = 0; (size_t) i < cnt; i++) - ASSERT (array[i] == i); -} - -/* Checks that bsearch() works properly in ARRAY. ARRAY must - contain the values 0...CNT-1. */ -static void -verify_bsearch (const int *array, size_t cnt) -{ - int not_in_array[] = {0, -1, INT_MAX, MAX_CNT, MAX_CNT + 1, MAX_CNT * 2}; - int i; - - /* Check that all the values in the array are found properly. */ - for (i = 0; (size_t) i < cnt; i++) - ASSERT (bsearch (&i, array, cnt, sizeof *array, compare_ints) - == array + i); - - /* Check that some values not in the array are not found. */ - not_in_array[0] = cnt; - for (i = 0; (size_t) i < sizeof not_in_array / sizeof *not_in_array; i++) - ASSERT (bsearch (¬_in_array[i], array, cnt, sizeof *array, compare_ints) - == NULL); -} diff --git a/src/tests/lib.c b/src/tests/lib.c deleted file mode 100644 index ee36505caf726c3fa6ed304b536ce309a71529a7..0000000000000000000000000000000000000000 --- a/src/tests/lib.c +++ /dev/null @@ -1,196 +0,0 @@ -#include "tests/lib.h" -#include <random.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <syscall.h> - -const char *test_name; -bool quiet = false; - -static void -vmsg (const char *format, va_list args, const char *suffix) -{ - /* We go to some trouble to stuff the entire message into a - single buffer and output it in a single system call, because - that'll (typically) ensure that it gets sent to the console - atomically. Otherwise kernel messages like "foo: exit(0)" - can end up being interleaved if we're unlucky. */ - static char buf[1024]; - - snprintf (buf, sizeof buf, "(%s) ", test_name); - vsnprintf (buf + strlen (buf), sizeof buf - strlen (buf), format, args); - strlcpy (buf + strlen (buf), suffix, sizeof buf - strlen (buf)); - write (STDOUT_FILENO, buf, strlen (buf)); -} - -void -msg (const char *format, ...) -{ - va_list args; - - if (quiet) - return; - va_start (args, format); - vmsg (format, args, "\n"); - va_end (args); -} - -void -fail (const char *format, ...) -{ - va_list args; - - va_start (args, format); - vmsg (format, args, ": FAILED\n"); - va_end (args); - - exit (1); -} - -static void -swap (void *a_, void *b_, size_t size) -{ - uint8_t *a = a_; - uint8_t *b = b_; - size_t i; - - for (i = 0; i < size; i++) - { - uint8_t t = a[i]; - a[i] = b[i]; - b[i] = t; - } -} - -void -shuffle (void *buf_, size_t cnt, size_t size) -{ - char *buf = buf_; - size_t i; - - for (i = 0; i < cnt; i++) - { - size_t j = i + random_ulong () % (cnt - i); - swap (buf + i * size, buf + j * size, size); - } -} - -void -exec_children (const char *child_name, pid_t pids[], size_t child_cnt) -{ - size_t i; - - for (i = 0; i < child_cnt; i++) - { - char cmd_line[128]; - snprintf (cmd_line, sizeof cmd_line, "%s %zu", child_name, i); - CHECK ((pids[i] = exec (cmd_line)) != PID_ERROR, - "exec child %zu of %zu: \"%s\"", i + 1, child_cnt, cmd_line); - } -} - -void -wait_children (pid_t pids[], size_t child_cnt) -{ - size_t i; - - for (i = 0; i < child_cnt; i++) - { - int status = wait (pids[i]); - CHECK (status == (int) i, - "wait for child %zu of %zu returned %d (expected %zu)", - i + 1, child_cnt, status, i); - } -} - -void -check_file_handle (int fd, - const char *file_name, const void *buf_, size_t size) -{ - const char *buf = buf_; - size_t ofs = 0; - size_t file_size; - - /* Warn about file of wrong size. Don't fail yet because we - may still be able to get more information by reading the - file. */ - file_size = filesize (fd); - if (file_size != size) - msg ("size of %s (%zu) differs from expected (%zu)", - file_name, file_size, size); - - /* Read the file block-by-block, comparing data as we go. */ - while (ofs < size) - { - char block[512]; - size_t block_size, ret_val; - - block_size = size - ofs; - if (block_size > sizeof block) - block_size = sizeof block; - - ret_val = read (fd, block, block_size); - if (ret_val != block_size) - fail ("read of %zu bytes at offset %zu in \"%s\" returned %zu", - block_size, ofs, file_name, ret_val); - - compare_bytes (block, buf + ofs, block_size, ofs, file_name); - ofs += block_size; - } - - /* Now fail due to wrong file size. */ - if (file_size != size) - fail ("size of %s (%zu) differs from expected (%zu)", - file_name, file_size, size); - - msg ("verified contents of \"%s\"", file_name); -} - -void -check_file (const char *file_name, const void *buf, size_t size) -{ - int fd; - - CHECK ((fd = open (file_name)) > 1, "open \"%s\" for verification", - file_name); - check_file_handle (fd, file_name, buf, size); - msg ("close \"%s\"", file_name); - close (fd); -} - -void -compare_bytes (const void *read_data_, const void *expected_data_, size_t size, - size_t ofs, const char *file_name) -{ - const uint8_t *read_data = read_data_; - const uint8_t *expected_data = expected_data_; - size_t i, j; - size_t show_cnt; - - if (!memcmp (read_data, expected_data, size)) - return; - - for (i = 0; i < size; i++) - if (read_data[i] != expected_data[i]) - break; - for (j = i + 1; j < size; j++) - if (read_data[j] == expected_data[j]) - break; - - quiet = false; - msg ("%zu bytes read starting at offset %zu in \"%s\" differ " - "from expected.", j - i, ofs + i, file_name); - show_cnt = j - i; - if (j - i > 64) - { - show_cnt = 64; - msg ("Showing first differing %zu bytes.", show_cnt); - } - msg ("Data actually read:"); - hex_dump (ofs + i, read_data + i, show_cnt, true); - msg ("Expected data:"); - hex_dump (ofs + i, expected_data + i, show_cnt, true); - fail ("%zu bytes read starting at offset %zu in \"%s\" differ " - "from expected", j - i, ofs + i, file_name); -} diff --git a/src/tests/lib.h b/src/tests/lib.h deleted file mode 100644 index 648327b90027aaf896f77bf7fdd787cba9a3f258..0000000000000000000000000000000000000000 --- a/src/tests/lib.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef TESTS_LIB_H -#define TESTS_LIB_H - -#include <debug.h> -#include <stdbool.h> -#include <stddef.h> -#include <syscall.h> - -extern const char *test_name; -extern bool quiet; - -void msg (const char *, ...) PRINTF_FORMAT (1, 2); -void fail (const char *, ...) PRINTF_FORMAT (1, 2) NO_RETURN; - -/* Takes an expression to test for SUCCESS and a message, which - may include printf-style arguments. Logs the message, then - tests the expression. If it is zero, indicating failure, - emits the message as a failure. - - Somewhat tricky to use: - - - SUCCESS must not have side effects that affect the - message, because that will cause the original message and - the failure message to differ. - - - The message must not have side effects of its own, because - it will be printed twice on failure, or zero times on - success if quiet is set. */ -#define CHECK(SUCCESS, ...) \ - do \ - { \ - msg (__VA_ARGS__); \ - if (!(SUCCESS)) \ - fail (__VA_ARGS__); \ - } \ - while (0) - -void shuffle (void *, size_t cnt, size_t size); - -void exec_children (const char *child_name, pid_t pids[], size_t child_cnt); -void wait_children (pid_t pids[], size_t child_cnt); - -void check_file_handle (int fd, const char *file_name, - const void *buf_, size_t filesize); -void check_file (const char *file_name, const void *buf, size_t filesize); - -void compare_bytes (const void *read_data, const void *expected_data, - size_t size, size_t ofs, const char *file_name); - -#endif /* test/lib.h */ diff --git a/src/tests/lib.pm b/src/tests/lib.pm deleted file mode 100644 index bc37ae5245f043452af7718d1c4b0336a302801f..0000000000000000000000000000000000000000 --- a/src/tests/lib.pm +++ /dev/null @@ -1,19 +0,0 @@ -use strict; -use warnings; - -use tests::random; - -sub shuffle { - my ($in, $cnt, $sz) = @_; - $cnt * $sz == length $in or die; - my (@a) = 0...$cnt - 1; - for my $i (0...$cnt - 1) { - my ($j) = $i + random_ulong () % ($cnt - $i); - @a[$i, $j] = @a[$j, $i]; - } - my ($out) = ""; - $out .= substr ($in, $_ * $sz, $sz) foreach @a; - return $out; -} - -1; diff --git a/src/tests/main.c b/src/tests/main.c deleted file mode 100644 index ad1b0f13fd17f9db46db6e1a7a03e35faa5b02e2..0000000000000000000000000000000000000000 --- a/src/tests/main.c +++ /dev/null @@ -1,15 +0,0 @@ -#include <random.h> -#include "tests/lib.h" -#include "tests/main.h" - -int -main (int argc UNUSED, char *argv[]) -{ - test_name = argv[0]; - - msg ("begin"); - random_init (0); - test_main (); - msg ("end"); - return 0; -} diff --git a/src/tests/main.h b/src/tests/main.h deleted file mode 100644 index f0e8818f2860a76abb813e317f066fe3d3368851..0000000000000000000000000000000000000000 --- a/src/tests/main.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TESTS_MAIN_H -#define TESTS_MAIN_H - -void test_main (void); - -#endif /* tests/main.h */ diff --git a/src/tests/make-grade b/src/tests/make-grade deleted file mode 100755 index a3faa0ebd560ac1f5af6b1180a50f489125860ca..0000000000000000000000000000000000000000 --- a/src/tests/make-grade +++ /dev/null @@ -1,152 +0,0 @@ -#! /usr/bin/perl - -use strict; -use warnings; - -@ARGV == 3 || die; -my ($src_dir, $results_file, $grading_file) = @ARGV; - -# Read pass/file verdicts from $results_file. -open (RESULTS, '<', $results_file) || die "$results_file: open: $!\n"; -my (%verdicts, %verdict_counts); -while (<RESULTS>) { - my ($verdict, $test) = /^(pass|FAIL) (.*)$/ or die; - $verdicts{$test} = $verdict eq 'pass'; -} -close RESULTS; - -my (@failures); -my (@overall, @rubrics, @summary); -my ($pct_actual, $pct_possible) = (0, 0); - -# Read grading file. -my (@items); -open (GRADING, '<', $grading_file) || die "$grading_file: open: $!\n"; -while (<GRADING>) { - s/#.*//; - next if /^\s*$/; - my ($max_pct, $rubric_suffix) = /^\s*(\d+(?:\.\d+)?)%\t(.*)/ or die; - my ($dir) = $rubric_suffix =~ /^(.*)\//; - my ($rubric_file) = "$src_dir/$rubric_suffix"; - open (RUBRIC, '<', $rubric_file) or die "$rubric_file: open: $!\n"; - - # Rubric file must begin with title line. - my $title = <RUBRIC>; - chomp $title; - $title =~ s/:$// or die; - $title .= " ($rubric_suffix):"; - push (@rubrics, $title); - - my ($score, $possible) = (0, 0); - my ($cnt, $passed) = (0, 0); - my ($was_score) = 0; - while (<RUBRIC>) { - chomp; - push (@rubrics, "\t$_"), next if /^-/; - push (@rubrics, ""), next if /^\s*$/; - my ($poss, $name) = /^(\d+)\t(.*)$/ or die; - my ($test) = "$dir/$name"; - my ($points) = 0; - if (!defined $verdicts{$test}) { - push (@overall, "warning: $test not tested, assuming failure"); - } elsif ($verdicts{$test}) { - $points = $poss; - $passed++; - } - push (@failures, $test) if !$points; - $verdict_counts{$test}++; - push (@rubrics, sprintf ("\t%4s%2d/%2d %s", - $points ? '' : '**', $points, $poss, $test)); - $score += $points; - $possible += $poss; - $cnt++; - } - close (RUBRIC); - - push (@rubrics, ""); - push (@rubrics, "\t- Section summary."); - push (@rubrics, sprintf ("\t%4s%3d/%3d %s", - '', $passed, $cnt, 'tests passed')); - push (@rubrics, sprintf ("\t%4s%3d/%3d %s", - '', $score, $possible, 'points subtotal')); - push (@rubrics, ''); - - my ($pct) = ($score / $possible) * $max_pct; - push (@summary, sprintf ("%-45s %3d/%3d %5.1f%%/%5.1f%%", - $rubric_suffix, - $score, $possible, - $pct, $max_pct)); - $pct_actual += $pct; - $pct_possible += $max_pct; -} -close GRADING; - -my ($sum_line) - = "--------------------------------------------- --- --- ------ ------"; -unshift (@summary, - "SUMMARY BY TEST SET", - '', - sprintf ("%-45s %3s %3s %6s %6s", - "Test Set", "Pts", "Max", "% Ttl", "% Max"), - $sum_line); -push (@summary, - $sum_line, - sprintf ("%-45s %3s %3s %5.1f%%/%5.1f%%", - 'Total', '', '', $pct_actual, $pct_possible)); - -unshift (@rubrics, - "SUMMARY OF INDIVIDUAL TESTS", - ''); - -foreach my $name (keys (%verdicts)) { - my ($count) = $verdict_counts{$name}; - if (!defined ($count) || $count != 1) { - if (!defined ($count) || !$count) { - push (@overall, "warning: test $name doesn't count for grading"); - } else { - push (@overall, - "warning: test $name counted $count times in grading"); - } - } -} -push (@overall, sprintf ("TOTAL TESTING SCORE: %.1f%%", $pct_actual)); -if (sprintf ("%.1f", $pct_actual) eq sprintf ("%.1f", $pct_possible)) { - push (@overall, "ALL TESTED PASSED -- PERFECT SCORE"); -} - -my (@divider) = ('', '- ' x 38, ''); - -print map ("$_\n", @overall, @divider, @summary, @divider, @rubrics); - -for my $test (@failures) { - print map ("$_\n", @divider); - print "DETAILS OF $test FAILURE:\n\n"; - - if (open (RESULT, '<', "$test.result")) { - my $first_line = <RESULT>; - my ($cnt) = 0; - while (<RESULT>) { - print; - $cnt++; - } - close (RESULT); - } - - if (open (OUTPUT, '<', "$test.output")) { - print "\nOUTPUT FROM $test:\n\n"; - - my ($panics, $boots) = (0, 0); - while (<OUTPUT>) { - if (/PANIC/ && ++$panics > 2) { - print "[...details of additional panic(s) omitted...]\n"; - last; - } - print; - if (/Pintos booting/ && ++$boots > 1) { - print "[...details of reboot(s) omitted...]\n"; - last; - } - } - close (OUTPUT); - } -} diff --git a/src/tests/random.pm b/src/tests/random.pm deleted file mode 100644 index be008ffc1adcc102f5907b236fc99b839d59d6a6..0000000000000000000000000000000000000000 --- a/src/tests/random.pm +++ /dev/null @@ -1,27 +0,0 @@ -use strict; -use warnings; - -use tests::arc4; - -my (@arc4); - -sub random_init { - if (@arc4 == 0) { - my ($seed) = @_; - $seed = 0 if !defined $seed; - @arc4 = arc4_init (pack ("V", $seed)); - } -} - -sub random_bytes { - random_init (); - my ($n) = @_; - return arc4_crypt (\@arc4, "\0" x $n); -} - -sub random_ulong { - random_init (); - return unpack ("V", random_bytes (4)); -} - -1; diff --git a/src/tests/tests.pm b/src/tests/tests.pm deleted file mode 100644 index 4599cb98fe49d7627173d182f48ce2ef072f03ab..0000000000000000000000000000000000000000 --- a/src/tests/tests.pm +++ /dev/null @@ -1,625 +0,0 @@ -use strict; -use warnings; -use tests::Algorithm::Diff; -use File::Temp 'tempfile'; -use Fcntl qw(SEEK_SET SEEK_CUR); - -sub fail; -sub pass; - -die if @ARGV != 2; -our ($test, $src_dir) = @ARGV; - -my ($msg_file) = tempfile (); -select ($msg_file); - -our (@prereq_tests) = (); -if ($test =~ /^(.*)-persistence$/) { - push (@prereq_tests, $1); -} -for my $prereq_test (@prereq_tests) { - my (@result) = read_text_file ("$prereq_test.result"); - fail "Prerequisite test $prereq_test failed.\n" if $result[0] ne 'PASS'; -} - - -# Generic testing. - -sub check_expected { - my ($expected) = pop @_; - my (@options) = @_; - my (@output) = read_text_file ("$test.output"); - common_checks ("run", @output); - compare_output ("run", @options, \@output, $expected); -} - -sub common_checks { - my ($run, @output) = @_; - - fail "\u$run produced no output at all\n" if @output == 0; - - check_for_panic ($run, @output); - check_for_keyword ($run, "FAIL", @output); - check_for_triple_fault ($run, @output); - check_for_keyword ($run, "TIMEOUT", @output); - - fail "\u$run didn't start up properly: no \"Pintos booting\" message\n" - if !grep (/Pintos booting with.*kB RAM\.\.\./, @output); - fail "\u$run didn't start up properly: no \"Boot complete\" message\n" - if !grep (/Boot complete/, @output); - fail "\u$run didn't shut down properly: no \"Timer: # ticks\" message\n" - if !grep (/Timer: \d+ ticks/, @output); - fail "\u$run didn't shut down properly: no \"Powering off\" message\n" - if !grep (/Powering off/, @output); -} - -sub check_for_panic { - my ($run, @output) = @_; - - my ($panic) = grep (/PANIC/, @output); - return unless defined $panic; - - print "Kernel panic in $run: ", substr ($panic, index ($panic, "PANIC")), - "\n"; - - my (@stack_line) = grep (/Call stack:/, @output); - if (@stack_line != 0) { - my ($addrs) = $stack_line[0] =~ /Call stack:((?: 0x[0-9a-f]+)+)/; - - # Find a user program to translate user virtual addresses. - my ($userprog) = ""; - $userprog = "$test" - if grep (hex ($_) < 0xc0000000, split (' ', $addrs)) > 0 && -e $test; - - # Get and print the backtrace. - my ($trace) = scalar (`backtrace kernel.o $userprog $addrs`); - print "Call stack:$addrs\n"; - print "Translation of call stack:\n"; - print $trace; - - # Print disclaimer. - if ($userprog ne '' && index ($trace, $userprog) >= 0) { - print <<EOF; -Translations of user virtual addresses above are based on a guess at -the binary to use. If this guess is incorrect, then those -translations will be misleading. -EOF - } - } - - if ($panic =~ /sec_no \< d-\>capacity/) { - print <<EOF; -\nThis assertion commonly fails when accessing a file via an inode that -has been closed and freed. Freeing an inode clears all its sector -indexes to 0xcccccccc, which is not a valid sector number for disks -smaller than about 1.6 TB. -EOF - } - - fail; -} - -sub check_for_keyword { - my ($run, $keyword, @output) = @_; - - my ($kw_line) = grep (/$keyword/, @output); - return unless defined $kw_line; - - # Most output lines are prefixed by (test-name). Eliminate this - # from our message for brevity. - $kw_line =~ s/^\([^\)]+\)\s+//; - print "$run: $kw_line\n"; - - fail; -} - -sub check_for_triple_fault { - my ($run, @output) = @_; - - my ($reboots) = grep (/Pintos booting/, @output) - 1; - return unless $reboots > 0; - - print <<EOF; -\u$run spontaneously rebooted $reboots times. -This is most often caused by unhandled page faults. -Read the Triple Faults section in the Debugging chapter -of the Pintos manual for more information. -EOF - - fail; -} - -# Get @output without header or trailer. -sub get_core_output { - my ($run, @output) = @_; - my ($p); - - my ($process); - my ($start); - for my $i (0...$#_) { - $start = $i + 1, last - if ($process) = $output[$i] =~ /^Executing '(\S+).*':$/; - } - - my ($end); - for my $i ($start...$#output) { - $end = $i - 1, last if $output[$i] =~ /^Execution of '.*' complete.$/; - } - - fail "\u$run didn't start a thread or process\n" if !defined $start; - fail "\u$run started '$process' but it never finished\n" if !defined $end; - - return @output[$start...$end]; -} - -sub compare_output { - my ($run) = shift @_; - my ($expected) = pop @_; - my ($output) = pop @_; - my (%options) = @_; - - my (@output) = get_core_output ($run, @$output); - fail "\u$run didn't produce any output" if !@output; - - my $ignore_exit_codes = exists $options{IGNORE_EXIT_CODES}; - if ($ignore_exit_codes) { - delete $options{IGNORE_EXIT_CODES}; - @output = grep (!/^[a-zA-Z0-9-_]+: exit\(\-?\d+\)$/, @output); - } - my $ignore_user_faults = exists $options{IGNORE_USER_FAULTS}; - if ($ignore_user_faults) { - delete $options{IGNORE_USER_FAULTS}; - @output = grep (!/^Page fault at.*in user context\.$/ - && !/: dying due to interrupt 0x0e \(.*\).$/ - && !/^Interrupt 0x0e \(.*\) at eip=/ - && !/^ cr2=.* error=.*/ - && !/^ eax=.* ebx=.* ecx=.* edx=.*/ - && !/^ esi=.* edi=.* esp=.* ebp=.*/ - && !/^ cs=.* ds=.* es=.* ss=.*/, @output); - } - die "unknown option " . (keys (%options))[0] . "\n" if %options; - - my ($msg); - - # Compare actual output against each allowed output. - if (ref ($expected) eq 'ARRAY') { - my ($i) = 0; - $expected = {map ((++$i => $_), @$expected)}; - } - foreach my $key (keys %$expected) { - my (@expected) = split ("\n", $expected->{$key}); - - $msg .= "Acceptable output:\n"; - $msg .= join ('', map (" $_\n", @expected)); - - # Check whether actual and expected match. - # If it's a perfect match, we're done. - if ($#output == $#expected) { - my ($eq) = 1; - for (my ($i) = 0; $i <= $#expected; $i++) { - $eq = 0 if $output[$i] ne $expected[$i]; - } - return $key if $eq; - } - - # They differ. Output a diff. - my (@diff) = ""; - my ($d) = Algorithm::Diff->new (\@expected, \@output); - while ($d->Next ()) { - my ($ef, $el, $af, $al) = $d->Get (qw (min1 max1 min2 max2)); - if ($d->Same ()) { - push (@diff, map (" $_\n", $d->Items (1))); - } else { - push (@diff, map ("- $_\n", $d->Items (1))) if $d->Items (1); - push (@diff, map ("+ $_\n", $d->Items (2))) if $d->Items (2); - } - } - - $msg .= "Differences in `diff -u' format:\n"; - $msg .= join ('', @diff); - } - - # Failed to match. Report failure. - $msg .= "\n(Process exit codes are excluded for matching purposes.)\n" - if $ignore_exit_codes; - $msg .= "\n(User fault messages are excluded for matching purposes.)\n" - if $ignore_user_faults; - fail "Test output failed to match any acceptable form.\n\n$msg"; -} - -# File system extraction. - -# check_archive (\%CONTENTS) -# -# Checks that the extracted file system's contents match \%CONTENTS. -# Each key in the hash is a file name. Each value may be: -# -# - $FILE: Name of a host file containing the expected contents. -# -# - [$FILE, $OFFSET, $LENGTH]: An excerpt of host file $FILE -# comprising the $LENGTH bytes starting at $OFFSET. -# -# - [$CONTENTS]: The literal expected file contents, as a string. -# -# - {SUBDIR}: A subdirectory, in the same form described here, -# recursively. -sub check_archive { - my ($expected_hier) = @_; - - my (@output) = read_text_file ("$test.output"); - common_checks ("file system extraction run", @output); - - @output = get_core_output ("file system extraction run", @output); - @output = grep (!/^[a-zA-Z0-9-_]+: exit\(\d+\)$/, @output); - fail join ("\n", "Error extracting file system:", @output) if @output; - - my ($test_base_name) = $test; - $test_base_name =~ s%.*/%%; - $test_base_name =~ s%-persistence$%%; - $expected_hier->{$test_base_name} = $prereq_tests[0]; - $expected_hier->{'tar'} = 'tests/filesys/extended/tar'; - - my (%expected) = normalize_fs (flatten_hierarchy ($expected_hier, "")); - my (%actual) = read_tar ("$prereq_tests[0].tar"); - - my ($errors) = 0; - foreach my $name (sort keys %expected) { - if (exists $actual{$name}) { - if (is_dir ($actual{$name}) && !is_dir ($expected{$name})) { - print "$name is a directory but should be an ordinary file.\n"; - $errors++; - } elsif (!is_dir ($actual{$name}) && is_dir ($expected{$name})) { - print "$name is an ordinary file but should be a directory.\n"; - $errors++; - } - } else { - print "$name is missing from the file system.\n"; - $errors++; - } - } - foreach my $name (sort keys %actual) { - if (!exists $expected{$name}) { - if ($name =~ /^[[:print:]]+$/) { - print "$name exists in the file system but it should not.\n"; - } else { - my ($esc_name) = $name; - $esc_name =~ s/[^[:print:]]/./g; - print <<EOF; -$esc_name exists in the file system but should not. (The name -of this file contains unusual characters that were printed as `.'.) -EOF - } - $errors++; - } - } - if ($errors) { - print "\nActual contents of file system:\n"; - print_fs (%actual); - print "\nExpected contents of file system:\n"; - print_fs (%expected); - } else { - foreach my $name (sort keys %expected) { - if (!is_dir ($expected{$name})) { - my ($exp_file, $exp_length) = open_file ($expected{$name}); - my ($act_file, $act_length) = open_file ($actual{$name}); - $errors += !compare_files ($exp_file, $exp_length, - $act_file, $act_length, $name, - !$errors); - close ($exp_file); - close ($act_file); - } - } - } - fail "Extracted file system contents are not correct.\n" if $errors; -} - -# open_file ([$FILE, $OFFSET, $LENGTH]) -# open_file ([$CONTENTS]) -# -# Opens a file for the contents passed in, which must be in one of -# the two above forms that correspond to check_archive() arguments. -# -# Returns ($HANDLE, $LENGTH), where $HANDLE is the file's handle and -# $LENGTH is the number of bytes in the file's content. -sub open_file { - my ($value) = @_; - die if ref ($value) ne 'ARRAY'; - - my ($file) = tempfile (); - my ($length); - if (@$value == 1) { - $length = length ($value->[0]); - $file = tempfile (); - syswrite ($file, $value->[0]) == $length - or die "writing temporary file: $!\n"; - sysseek ($file, 0, SEEK_SET); - } elsif (@$value == 3) { - $length = $value->[2]; - open ($file, '<', $value->[0]) or die "$value->[0]: open: $!\n"; - die "$value->[0]: file is smaller than expected\n" - if -s $file < $value->[1] + $length; - sysseek ($file, $value->[1], SEEK_SET); - } else { - die; - } - return ($file, $length); -} - -# compare_files ($A, $A_SIZE, $B, $B_SIZE, $NAME, $VERBOSE) -# -# Compares $A_SIZE bytes in $A to $B_SIZE bytes in $B. -# ($A and $B are handles.) -# If their contents differ, prints a brief message describing -# the differences, using $NAME to identify the file. -# The message contains more detail if $VERBOSE is nonzero. -# Returns 1 if the contents are identical, 0 otherwise. -sub compare_files { - my ($a, $a_size, $b, $b_size, $name, $verbose) = @_; - my ($ofs) = 0; - select(STDOUT); - for (;;) { - my ($a_amt) = $a_size >= 1024 ? 1024 : $a_size; - my ($b_amt) = $b_size >= 1024 ? 1024 : $b_size; - my ($a_data, $b_data); - if (!defined (sysread ($a, $a_data, $a_amt)) - || !defined (sysread ($b, $b_data, $b_amt))) { - die "reading $name: $!\n"; - } - - my ($a_len) = length $a_data; - my ($b_len) = length $b_data; - last if $a_len == 0 && $b_len == 0; - - if ($a_data ne $b_data) { - my ($min_len) = $a_len < $b_len ? $a_len : $b_len; - my ($diff_ofs); - for ($diff_ofs = 0; $diff_ofs < $min_len; $diff_ofs++) { - last if (substr ($a_data, $diff_ofs, 1) - ne substr ($b_data, $diff_ofs, 1)); - } - - printf "\nFile $name differs from expected " - . "starting at offset 0x%x.\n", $ofs + $diff_ofs; - if ($verbose ) { - print "Expected contents:\n"; - hex_dump (substr ($a_data, $diff_ofs, 64), $ofs + $diff_ofs); - print "Actual contents:\n"; - hex_dump (substr ($b_data, $diff_ofs, 64), $ofs + $diff_ofs); - } - return 0; - } - - $ofs += $a_len; - $a_size -= $a_len; - $b_size -= $b_len; - } - return 1; -} - -# hex_dump ($DATA, $OFS) -# -# Prints $DATA in hex and text formats. -# The first byte of $DATA corresponds to logical offset $OFS -# in whatever file the data comes from. -sub hex_dump { - my ($data, $ofs) = @_; - - if ($data eq '') { - printf " (File ends at offset %08x.)\n", $ofs; - return; - } - - my ($per_line) = 16; - while ((my $size = length ($data)) > 0) { - my ($start) = $ofs % $per_line; - my ($end) = $per_line; - $end = $start + $size if $end - $start > $size; - my ($n) = $end - $start; - - printf "0x%08x ", int ($ofs / $per_line) * $per_line; - - # Hex version. - print " " x $start; - for my $i ($start...$end - 1) { - printf "%02x", ord (substr ($data, $i - $start, 1)); - print $i == $per_line / 2 - 1 ? '-' : ' '; - } - print " " x ($per_line - $end); - - # Character version. - my ($esc_data) = substr ($data, 0, $n); - $esc_data =~ s/[^[:print:]]/./g; - print "|", " " x $start, $esc_data, " " x ($per_line - $end), "|"; - - print "\n"; - - $data = substr ($data, $n); - $ofs += $n; - } -} - -# print_fs (%FS) -# -# Prints a list of files in %FS, which must be a file system -# as flattened by flatten_hierarchy() and normalized by -# normalize_fs(). -sub print_fs { - my (%fs) = @_; - foreach my $name (sort keys %fs) { - my ($esc_name) = $name; - $esc_name =~ s/[^[:print:]]/./g; - print "$esc_name: "; - if (!is_dir ($fs{$name})) { - print +file_size ($fs{$name}), "-byte file"; - } else { - print "directory"; - } - print "\n"; - } - print "(empty)\n" if !@_; -} - -# normalize_fs (%FS) -# -# Takes a file system as flattened by flatten_hierarchy(). -# Returns a similar file system in which values of the form $FILE -# are replaced by those of the form [$FILE, $OFFSET, $LENGTH]. -sub normalize_fs { - my (%fs) = @_; - foreach my $name (keys %fs) { - my ($value) = $fs{$name}; - next if is_dir ($value) || ref ($value) ne ''; - die "can't open $value\n" if !stat $value; - $fs{$name} = [$value, 0, -s _]; - } - return %fs; -} - -# is_dir ($VALUE) -# -# Takes a value like one in the hash returned by flatten_hierarchy() -# and returns 1 if it represents a directory, 0 otherwise. -sub is_dir { - my ($value) = @_; - return ref ($value) eq '' && $value eq 'directory'; -} - -# file_size ($VALUE) -# -# Takes a value like one in the hash returned by flatten_hierarchy() -# and returns the size of the file it represents. -sub file_size { - my ($value) = @_; - die if is_dir ($value); - die if ref ($value) ne 'ARRAY'; - return @$value > 1 ? $value->[2] : length ($value->[0]); -} - -# flatten_hierarchy ($HIER_FS, $PREFIX) -# -# Takes a file system in the format expected by check_archive() and -# returns a "flattened" version in which file names include all parent -# directory names and the value of directories is just "directory". -sub flatten_hierarchy { - my (%hier_fs) = %{$_[0]}; - my ($prefix) = $_[1]; - my (%flat_fs); - for my $name (keys %hier_fs) { - my ($value) = $hier_fs{$name}; - if (ref $value eq 'HASH') { - %flat_fs = (%flat_fs, flatten_hierarchy ($value, "$prefix$name/")); - $flat_fs{"$prefix$name"} = 'directory'; - } else { - $flat_fs{"$prefix$name"} = $value; - } - } - return %flat_fs; -} - -# read_tar ($ARCHIVE) -# -# Reads the ustar-format tar file in $ARCHIVE -# and returns a flattened file system for it. -sub read_tar { - my ($archive) = @_; - my (%content); - open (ARCHIVE, '<', $archive) or fail "$archive: open: $!\n"; - for (;;) { - my ($header); - if ((my $retval = sysread (ARCHIVE, $header, 512)) != 512) { - fail "$archive: unexpected end of file\n" if $retval >= 0; - fail "$archive: read: $!\n"; - } - - last if $header eq "\0" x 512; - - # Verify magic numbers. - if (substr ($header, 257, 6) ne "ustar\0" - || substr ($header, 263, 2) ne '00') { - fail "$archive: corrupt ustar header\n"; - } - - # Verify checksum. - my ($chksum) = oct (unpack ("Z*", substr ($header, 148, 8, ' ' x 8))); - my ($correct_chksum) = unpack ("%32a*", $header); - fail "$archive: bad header checksum\n" if $chksum != $correct_chksum; - - # Get file name. - my ($name) = unpack ("Z100", $header); - my ($prefix) = unpack ("Z*", substr ($header, 345)); - $name = "$prefix/$name" if $prefix ne ''; - fail "$archive: contains file with empty name" if $name eq ''; - - # Get type. - my ($typeflag) = substr ($header, 156, 1); - $typeflag = '0' if $typeflag eq "\0"; - fail "unknown file type '$typeflag'\n" if $typeflag !~ /[05]/; - - # Get size. - my ($size) = oct (unpack ("Z*", substr ($header, 124, 12))); - fail "bad size $size\n" if $size < 0; - $size = 0 if $typeflag eq '5'; - - # Store content. - $name =~ s%^(/|\./|\.\./)*%%; # Strip leading "/", "./", "../". - $name = '' if $name eq '.' || $name eq '..'; - if (exists $content{$name}) { - fail "$archive: contains multiple entries for $name\n"; - } - if ($typeflag eq '5') { - $content{$name} = 'directory' if $name ne ''; - } else { - fail "$archive: contains file with empty name\n" if $name eq ''; - my ($position) = sysseek (ARCHIVE, 0, SEEK_CUR); - $content{$name} = [$archive, $position, $size]; - sysseek (ARCHIVE, int (($size + 511) / 512) * 512, SEEK_CUR); - } - } - close (ARCHIVE); - return %content; -} - -# Utilities. - -sub fail { - finish ("FAIL", @_); -} - -sub pass { - finish ("PASS", @_); -} - -sub finish { - my ($verdict, @messages) = @_; - - seek ($msg_file, 0, 0); - push (@messages, <$msg_file>); - close ($msg_file); - chomp (@messages); - - my ($result_fn) = "$test.result"; - open (RESULT, '>', $result_fn) or die "$result_fn: create: $!\n"; - print RESULT "$verdict\n"; - print RESULT "$_\n" foreach @messages; - close (RESULT); - - if ($verdict eq 'PASS') { - print STDOUT "pass $test\n"; - } else { - print STDOUT "FAIL $test\n"; - } - print STDOUT "$_\n" foreach @messages; - - exit 0; -} - -sub read_text_file { - my ($file_name) = @_; - open (FILE, '<', $file_name) or die "$file_name: open: $!\n"; - my (@content) = <FILE>; - chomp (@content); - close (FILE); - return @content; -} - -1; diff --git a/src/tests/threads/Grading b/src/tests/threads/Grading deleted file mode 100644 index c9be35f379dfc8241b489eb28966617629cdbd76..0000000000000000000000000000000000000000 --- a/src/tests/threads/Grading +++ /dev/null @@ -1,6 +0,0 @@ -# Percentage of the testing point total designated for each set of -# tests. - -20.0% tests/threads/Rubric.alarm -40.0% tests/threads/Rubric.priority -40.0% tests/threads/Rubric.mlfqs diff --git a/src/tests/threads/Make.tests b/src/tests/threads/Make.tests deleted file mode 100644 index 456903538990dedcdc15bfef32dc6e0112033ef1..0000000000000000000000000000000000000000 --- a/src/tests/threads/Make.tests +++ /dev/null @@ -1,53 +0,0 @@ -# -*- makefile -*- - -# Test names. -tests/threads_TESTS = $(addprefix tests/threads/,alarm-single \ -alarm-multiple alarm-simultaneous alarm-priority alarm-zero \ -alarm-negative priority-change priority-donate-one \ -priority-donate-multiple priority-donate-multiple2 \ -priority-donate-nest priority-donate-sema priority-donate-lower \ -priority-fifo priority-preempt priority-sema priority-condvar \ -priority-donate-chain \ -mlfqs-load-1 mlfqs-load-60 mlfqs-load-avg mlfqs-recent-1 mlfqs-fair-2 \ -mlfqs-fair-20 mlfqs-nice-2 mlfqs-nice-10 mlfqs-block) - -# Sources for tests. -tests/threads_SRC = tests/threads/tests.c -tests/threads_SRC += tests/threads/alarm-wait.c -tests/threads_SRC += tests/threads/alarm-simultaneous.c -tests/threads_SRC += tests/threads/alarm-priority.c -tests/threads_SRC += tests/threads/alarm-zero.c -tests/threads_SRC += tests/threads/alarm-negative.c -tests/threads_SRC += tests/threads/priority-change.c -tests/threads_SRC += tests/threads/priority-donate-one.c -tests/threads_SRC += tests/threads/priority-donate-multiple.c -tests/threads_SRC += tests/threads/priority-donate-multiple2.c -tests/threads_SRC += tests/threads/priority-donate-nest.c -tests/threads_SRC += tests/threads/priority-donate-sema.c -tests/threads_SRC += tests/threads/priority-donate-lower.c -tests/threads_SRC += tests/threads/priority-fifo.c -tests/threads_SRC += tests/threads/priority-preempt.c -tests/threads_SRC += tests/threads/priority-sema.c -tests/threads_SRC += tests/threads/priority-condvar.c -tests/threads_SRC += tests/threads/priority-donate-chain.c -tests/threads_SRC += tests/threads/mlfqs-load-1.c -tests/threads_SRC += tests/threads/mlfqs-load-60.c -tests/threads_SRC += tests/threads/mlfqs-load-avg.c -tests/threads_SRC += tests/threads/mlfqs-recent-1.c -tests/threads_SRC += tests/threads/mlfqs-fair.c -tests/threads_SRC += tests/threads/mlfqs-block.c - -MLFQS_OUTPUTS = \ -tests/threads/mlfqs-load-1.output \ -tests/threads/mlfqs-load-60.output \ -tests/threads/mlfqs-load-avg.output \ -tests/threads/mlfqs-recent-1.output \ -tests/threads/mlfqs-fair-2.output \ -tests/threads/mlfqs-fair-20.output \ -tests/threads/mlfqs-nice-2.output \ -tests/threads/mlfqs-nice-10.output \ -tests/threads/mlfqs-block.output - -$(MLFQS_OUTPUTS): KERNELFLAGS += -mlfqs -$(MLFQS_OUTPUTS): TIMEOUT = 480 - diff --git a/src/tests/threads/Rubric.alarm b/src/tests/threads/Rubric.alarm deleted file mode 100644 index 61abe85e348350b37082760997b8936dce55bc66..0000000000000000000000000000000000000000 --- a/src/tests/threads/Rubric.alarm +++ /dev/null @@ -1,8 +0,0 @@ -Functionality and robustness of alarm clock: -4 alarm-single -4 alarm-multiple -4 alarm-simultaneous -4 alarm-priority - -1 alarm-zero -1 alarm-negative diff --git a/src/tests/threads/Rubric.mlfqs b/src/tests/threads/Rubric.mlfqs deleted file mode 100644 index f2600916205eccba338346f243b1c2eb9939bf71..0000000000000000000000000000000000000000 --- a/src/tests/threads/Rubric.mlfqs +++ /dev/null @@ -1,14 +0,0 @@ -Functionality of advanced scheduler: -5 mlfqs-load-1 -5 mlfqs-load-60 -3 mlfqs-load-avg - -5 mlfqs-recent-1 - -5 mlfqs-fair-2 -3 mlfqs-fair-20 - -4 mlfqs-nice-2 -2 mlfqs-nice-10 - -5 mlfqs-block diff --git a/src/tests/threads/Rubric.priority b/src/tests/threads/Rubric.priority deleted file mode 100644 index 652bc99eff1f34d1c40e34259af31291d4069d85..0000000000000000000000000000000000000000 --- a/src/tests/threads/Rubric.priority +++ /dev/null @@ -1,15 +0,0 @@ -Functionality of priority scheduler: -3 priority-change -3 priority-preempt - -3 priority-fifo -3 priority-sema -3 priority-condvar - -3 priority-donate-one -3 priority-donate-multiple -3 priority-donate-multiple2 -3 priority-donate-nest -5 priority-donate-chain -3 priority-donate-sema -3 priority-donate-lower diff --git a/src/tests/threads/alarm-multiple.ck b/src/tests/threads/alarm-multiple.ck deleted file mode 100644 index fd83bcd4087f5edacbf2bf81b82e83d49c9c049b..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-multiple.ck +++ /dev/null @@ -1,4 +0,0 @@ -# -*- perl -*- -use tests::tests; -use tests::threads::alarm; -check_alarm (7); diff --git a/src/tests/threads/alarm-negative.c b/src/tests/threads/alarm-negative.c deleted file mode 100644 index aec52cf302fda17cf9557855a35e29dd2ed5497f..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-negative.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Tests timer_sleep(-100). Only requirement is that it not crash. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -void -test_alarm_negative (void) -{ - timer_sleep (-100); - pass (); -} diff --git a/src/tests/threads/alarm-negative.ck b/src/tests/threads/alarm-negative.ck deleted file mode 100644 index 0d2bab07aefecada5942ae1e3ca9e2d4a993820d..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-negative.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(alarm-negative) begin -(alarm-negative) PASS -(alarm-negative) end -EOF -pass; diff --git a/src/tests/threads/alarm-priority.c b/src/tests/threads/alarm-priority.c deleted file mode 100644 index 2288ff6d6950034db2eedadf3b44c04d60377103..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-priority.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Checks that when the alarm clock wakes up threads, the - higher-priority threads run first. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static thread_func alarm_priority_thread; -static int64_t wake_time; -static struct semaphore wait_sema; - -void -test_alarm_priority (void) -{ - int i; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - wake_time = timer_ticks () + 5 * TIMER_FREQ; - sema_init (&wait_sema, 0); - - for (i = 0; i < 10; i++) - { - int priority = PRI_DEFAULT - (i + 5) % 10 - 1; - char name[16]; - snprintf (name, sizeof name, "priority %d", priority); - thread_create (name, priority, alarm_priority_thread, NULL); - } - - thread_set_priority (PRI_MIN); - - for (i = 0; i < 10; i++) - sema_down (&wait_sema); -} - -static void -alarm_priority_thread (void *aux UNUSED) -{ - /* Busy-wait until the current time changes. */ - int64_t start_time = timer_ticks (); - while (timer_elapsed (start_time) == 0) - continue; - - /* Now we know we're at the very beginning of a timer tick, so - we can call timer_sleep() without worrying about races - between checking the time and a timer interrupt. */ - timer_sleep (wake_time - timer_ticks ()); - - /* Print a message on wake-up. */ - msg ("Thread %s woke up.", thread_name ()); - - sema_up (&wait_sema); -} diff --git a/src/tests/threads/alarm-priority.ck b/src/tests/threads/alarm-priority.ck deleted file mode 100644 index b57c78b38163c97d84ba82e73058df1876e207f0..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-priority.ck +++ /dev/null @@ -1,19 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(alarm-priority) begin -(alarm-priority) Thread priority 30 woke up. -(alarm-priority) Thread priority 29 woke up. -(alarm-priority) Thread priority 28 woke up. -(alarm-priority) Thread priority 27 woke up. -(alarm-priority) Thread priority 26 woke up. -(alarm-priority) Thread priority 25 woke up. -(alarm-priority) Thread priority 24 woke up. -(alarm-priority) Thread priority 23 woke up. -(alarm-priority) Thread priority 22 woke up. -(alarm-priority) Thread priority 21 woke up. -(alarm-priority) end -EOF -pass; diff --git a/src/tests/threads/alarm-simultaneous.c b/src/tests/threads/alarm-simultaneous.c deleted file mode 100644 index 844eea47f9cb2f4e3120fa68a60c54bb4c6c6c4e..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-simultaneous.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Creates N threads, each of which sleeps a different, fixed - duration, M times. Records the wake-up order and verifies - that it is valid. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static void test_sleep (int thread_cnt, int iterations); - -void -test_alarm_simultaneous (void) -{ - test_sleep (3, 5); -} - -/* Information about the test. */ -struct sleep_test - { - int64_t start; /* Current time at start of test. */ - int iterations; /* Number of iterations per thread. */ - int *output_pos; /* Current position in output buffer. */ - }; - -static void sleeper (void *); - -/* Runs THREAD_CNT threads thread sleep ITERATIONS times each. */ -static void -test_sleep (int thread_cnt, int iterations) -{ - struct sleep_test test; - int *output; - int i; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - msg ("Creating %d threads to sleep %d times each.", thread_cnt, iterations); - msg ("Each thread sleeps 10 ticks each time."); - msg ("Within an iteration, all threads should wake up on the same tick."); - - /* Allocate memory. */ - output = malloc (sizeof *output * iterations * thread_cnt * 2); - if (output == NULL) - PANIC ("couldn't allocate memory for test"); - - /* Initialize test. */ - test.start = timer_ticks () + 100; - test.iterations = iterations; - test.output_pos = output; - - /* Start threads. */ - ASSERT (output != NULL); - for (i = 0; i < thread_cnt; i++) - { - char name[16]; - snprintf (name, sizeof name, "thread %d", i); - thread_create (name, PRI_DEFAULT, sleeper, &test); - } - - /* Wait long enough for all the threads to finish. */ - timer_sleep (100 + iterations * 10 + 100); - - /* Print completion order. */ - msg ("iteration 0, thread 0: woke up after %d ticks", output[0]); - for (i = 1; i < test.output_pos - output; i++) - msg ("iteration %d, thread %d: woke up %d ticks later", - i / thread_cnt, i % thread_cnt, output[i] - output[i - 1]); - - free (output); -} - -/* Sleeper thread. */ -static void -sleeper (void *test_) -{ - struct sleep_test *test = test_; - int i; - - /* Make sure we're at the beginning of a timer tick. */ - timer_sleep (1); - - for (i = 1; i <= test->iterations; i++) - { - int64_t sleep_until = test->start + i * 10; - timer_sleep (sleep_until - timer_ticks ()); - *test->output_pos++ = timer_ticks () - test->start; - thread_yield (); - } -} diff --git a/src/tests/threads/alarm-simultaneous.ck b/src/tests/threads/alarm-simultaneous.ck deleted file mode 100644 index 406b8b0414defc8544b6d29f24ba22e5a99eb123..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-simultaneous.ck +++ /dev/null @@ -1,27 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(alarm-simultaneous) begin -(alarm-simultaneous) Creating 3 threads to sleep 5 times each. -(alarm-simultaneous) Each thread sleeps 10 ticks each time. -(alarm-simultaneous) Within an iteration, all threads should wake up on the same tick. -(alarm-simultaneous) iteration 0, thread 0: woke up after 10 ticks -(alarm-simultaneous) iteration 0, thread 1: woke up 0 ticks later -(alarm-simultaneous) iteration 0, thread 2: woke up 0 ticks later -(alarm-simultaneous) iteration 1, thread 0: woke up 10 ticks later -(alarm-simultaneous) iteration 1, thread 1: woke up 0 ticks later -(alarm-simultaneous) iteration 1, thread 2: woke up 0 ticks later -(alarm-simultaneous) iteration 2, thread 0: woke up 10 ticks later -(alarm-simultaneous) iteration 2, thread 1: woke up 0 ticks later -(alarm-simultaneous) iteration 2, thread 2: woke up 0 ticks later -(alarm-simultaneous) iteration 3, thread 0: woke up 10 ticks later -(alarm-simultaneous) iteration 3, thread 1: woke up 0 ticks later -(alarm-simultaneous) iteration 3, thread 2: woke up 0 ticks later -(alarm-simultaneous) iteration 4, thread 0: woke up 10 ticks later -(alarm-simultaneous) iteration 4, thread 1: woke up 0 ticks later -(alarm-simultaneous) iteration 4, thread 2: woke up 0 ticks later -(alarm-simultaneous) end -EOF -pass; diff --git a/src/tests/threads/alarm-single.ck b/src/tests/threads/alarm-single.ck deleted file mode 100644 index 31215dffe754d3b5d8ab7b48aa00f7e6e489e655..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-single.ck +++ /dev/null @@ -1,4 +0,0 @@ -# -*- perl -*- -use tests::tests; -use tests::threads::alarm; -check_alarm (1); diff --git a/src/tests/threads/alarm-wait.c b/src/tests/threads/alarm-wait.c deleted file mode 100644 index 37d3afcea74243abcce4ccde4cb8a3590985c7c6..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-wait.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Creates N threads, each of which sleeps a different, fixed - duration, M times. Records the wake-up order and verifies - that it is valid. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static void test_sleep (int thread_cnt, int iterations); - -void -test_alarm_single (void) -{ - test_sleep (5, 1); -} - -void -test_alarm_multiple (void) -{ - test_sleep (5, 7); -} - -/* Information about the test. */ -struct sleep_test - { - int64_t start; /* Current time at start of test. */ - int iterations; /* Number of iterations per thread. */ - - /* Output. */ - struct lock output_lock; /* Lock protecting output buffer. */ - int *output_pos; /* Current position in output buffer. */ - }; - -/* Information about an individual thread in the test. */ -struct sleep_thread - { - struct sleep_test *test; /* Info shared between all threads. */ - int id; /* Sleeper ID. */ - int duration; /* Number of ticks to sleep. */ - int iterations; /* Iterations counted so far. */ - }; - -static void sleeper (void *); - -/* Runs THREAD_CNT threads thread sleep ITERATIONS times each. */ -static void -test_sleep (int thread_cnt, int iterations) -{ - struct sleep_test test; - struct sleep_thread *threads; - int *output, *op; - int product; - int i; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - msg ("Creating %d threads to sleep %d times each.", thread_cnt, iterations); - msg ("Thread 0 sleeps 10 ticks each time,"); - msg ("thread 1 sleeps 20 ticks each time, and so on."); - msg ("If successful, product of iteration count and"); - msg ("sleep duration will appear in nondescending order."); - - /* Allocate memory. */ - threads = malloc (sizeof *threads * thread_cnt); - output = malloc (sizeof *output * iterations * thread_cnt * 2); - if (threads == NULL || output == NULL) - PANIC ("couldn't allocate memory for test"); - - /* Initialize test. */ - test.start = timer_ticks () + 100; - test.iterations = iterations; - lock_init (&test.output_lock); - test.output_pos = output; - - /* Start threads. */ - ASSERT (output != NULL); - for (i = 0; i < thread_cnt; i++) - { - struct sleep_thread *t = threads + i; - char name[16]; - - t->test = &test; - t->id = i; - t->duration = (i + 1) * 10; - t->iterations = 0; - - snprintf (name, sizeof name, "thread %d", i); - thread_create (name, PRI_DEFAULT, sleeper, t); - } - - /* Wait long enough for all the threads to finish. */ - timer_sleep (100 + thread_cnt * iterations * 10 + 100); - - /* Acquire the output lock in case some rogue thread is still - running. */ - lock_acquire (&test.output_lock); - - /* Print completion order. */ - product = 0; - for (op = output; op < test.output_pos; op++) - { - struct sleep_thread *t; - int new_prod; - - ASSERT (*op >= 0 && *op < thread_cnt); - t = threads + *op; - - new_prod = ++t->iterations * t->duration; - - msg ("thread %d: duration=%d, iteration=%d, product=%d", - t->id, t->duration, t->iterations, new_prod); - - if (new_prod >= product) - product = new_prod; - else - fail ("thread %d woke up out of order (%d > %d)!", - t->id, product, new_prod); - } - - /* Verify that we had the proper number of wakeups. */ - for (i = 0; i < thread_cnt; i++) - if (threads[i].iterations != iterations) - fail ("thread %d woke up %d times instead of %d", - i, threads[i].iterations, iterations); - - lock_release (&test.output_lock); - free (output); - free (threads); -} - -/* Sleeper thread. */ -static void -sleeper (void *t_) -{ - struct sleep_thread *t = t_; - struct sleep_test *test = t->test; - int i; - - for (i = 1; i <= test->iterations; i++) - { - int64_t sleep_until = test->start + i * t->duration; - timer_sleep (sleep_until - timer_ticks ()); - lock_acquire (&test->output_lock); - *test->output_pos++ = t->id; - lock_release (&test->output_lock); - } -} diff --git a/src/tests/threads/alarm-zero.c b/src/tests/threads/alarm-zero.c deleted file mode 100644 index c8a3ee2849fe04ab8776f6e961cf2adf5abb6f50..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-zero.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Tests timer_sleep(0), which should return immediately. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -void -test_alarm_zero (void) -{ - timer_sleep (0); - pass (); -} diff --git a/src/tests/threads/alarm-zero.ck b/src/tests/threads/alarm-zero.ck deleted file mode 100644 index a6b1a3cd77920604c6c9ff41854be7a1b347abfa..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm-zero.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(alarm-zero) begin -(alarm-zero) PASS -(alarm-zero) end -EOF -pass; diff --git a/src/tests/threads/alarm.pm b/src/tests/threads/alarm.pm deleted file mode 100644 index 84b3b7f741de84841614b22b956876179f738dff..0000000000000000000000000000000000000000 --- a/src/tests/threads/alarm.pm +++ /dev/null @@ -1,32 +0,0 @@ -sub check_alarm { - my ($iterations) = @_; - our ($test); - - @output = read_text_file ("$test.output"); - common_checks ("run", @output); - - my (@products); - for (my ($i) = 0; $i < $iterations; $i++) { - for (my ($t) = 0; $t < 5; $t++) { - push (@products, ($i + 1) * ($t + 1) * 10); - } - } - @products = sort {$a <=> $b} @products; - - local ($_); - foreach (@output) { - fail $_ if /out of order/i; - - my ($p) = /product=(\d+)$/; - next if !defined $p; - - my ($q) = shift (@products); - fail "Too many wakeups.\n" if !defined $q; - fail "Out of order wakeups ($p vs. $q).\n" if $p != $q; # FIXME - } - fail scalar (@products) . " fewer wakeups than expected.\n" - if @products != 0; - pass; -} - -1; diff --git a/src/tests/threads/mlfqs-block.c b/src/tests/threads/mlfqs-block.c deleted file mode 100644 index 6d4992da31866946e9d39e427f613d376616dc14..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-block.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Checks that recent_cpu and priorities are updated for blocked - threads. - - The main thread sleeps for 25 seconds, spins for 5 seconds, - then releases a lock. The "block" thread spins for 20 seconds - then attempts to acquire the lock, which will block for 10 - seconds (until the main thread releases it). If recent_cpu - decays properly while the "block" thread sleeps, then the - block thread should be immediately scheduled when the main - thread releases the lock. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static void block_thread (void *lock_); - -void -test_mlfqs_block (void) -{ - int64_t start_time; - struct lock lock; - - ASSERT (thread_mlfqs); - - msg ("Main thread acquiring lock."); - lock_init (&lock); - lock_acquire (&lock); - - msg ("Main thread creating block thread, sleeping 25 seconds..."); - thread_create ("block", PRI_DEFAULT, block_thread, &lock); - timer_sleep (25 * TIMER_FREQ); - - msg ("Main thread spinning for 5 seconds..."); - start_time = timer_ticks (); - while (timer_elapsed (start_time) < 5 * TIMER_FREQ) - continue; - - msg ("Main thread releasing lock."); - lock_release (&lock); - - msg ("Block thread should have already acquired lock."); -} - -static void -block_thread (void *lock_) -{ - struct lock *lock = lock_; - int64_t start_time; - - msg ("Block thread spinning for 20 seconds..."); - start_time = timer_ticks (); - while (timer_elapsed (start_time) < 20 * TIMER_FREQ) - continue; - - msg ("Block thread acquiring lock..."); - lock_acquire (lock); - - msg ("...got it."); -} diff --git a/src/tests/threads/mlfqs-block.ck b/src/tests/threads/mlfqs-block.ck deleted file mode 100644 index 8833a3affc0069b4c34fcd8a92f1bbdb76fae989..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-block.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(mlfqs-block) begin -(mlfqs-block) Main thread acquiring lock. -(mlfqs-block) Main thread creating block thread, sleeping 25 seconds... -(mlfqs-block) Block thread spinning for 20 seconds... -(mlfqs-block) Block thread acquiring lock... -(mlfqs-block) Main thread spinning for 5 seconds... -(mlfqs-block) Main thread releasing lock. -(mlfqs-block) ...got it. -(mlfqs-block) Block thread should have already acquired lock. -(mlfqs-block) end -EOF -pass; diff --git a/src/tests/threads/mlfqs-fair-2.ck b/src/tests/threads/mlfqs-fair-2.ck deleted file mode 100644 index 5b19ff1391301a8174c2fd0f4bb268595c76223b..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-fair-2.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::threads::mlfqs; - -check_mlfqs_fair ([0, 0], 50); diff --git a/src/tests/threads/mlfqs-fair-20.ck b/src/tests/threads/mlfqs-fair-20.ck deleted file mode 100644 index bb4d051e7b4a3b0b48a81fa91bfc0fb3848745e1..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-fair-20.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::threads::mlfqs; - -check_mlfqs_fair ([(0) x 20], 20); diff --git a/src/tests/threads/mlfqs-fair.c b/src/tests/threads/mlfqs-fair.c deleted file mode 100644 index 3b1bea5a177301abb2d6b28b9887a3baf2a1a1ae..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-fair.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Measures the correctness of the "nice" implementation. - - The "fair" tests run either 2 or 20 threads all niced to 0. - The threads should all receive approximately the same number - of ticks. Each test runs for 30 seconds, so the ticks should - also sum to approximately 30 * 100 == 3000 ticks. - - The mlfqs-nice-2 test runs 2 threads, one with nice 0, the - other with nice 5, which should receive 1,904 and 1,096 ticks, - respectively, over 30 seconds. - - The mlfqs-nice-10 test runs 10 threads with nice 0 through 9. - They should receive 672, 588, 492, 408, 316, 232, 152, 92, 40, - and 8 ticks, respectively, over 30 seconds. - - (The above are computed via simulation in mlfqs.pm.) */ - -#include <stdio.h> -#include <inttypes.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/palloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static void test_mlfqs_fair (int thread_cnt, int nice_min, int nice_step); - -void -test_mlfqs_fair_2 (void) -{ - test_mlfqs_fair (2, 0, 0); -} - -void -test_mlfqs_fair_20 (void) -{ - test_mlfqs_fair (20, 0, 0); -} - -void -test_mlfqs_nice_2 (void) -{ - test_mlfqs_fair (2, 0, 5); -} - -void -test_mlfqs_nice_10 (void) -{ - test_mlfqs_fair (10, 0, 1); -} - -#define MAX_THREAD_CNT 20 - -struct thread_info - { - int64_t start_time; - int tick_count; - int nice; - }; - -static void load_thread (void *aux); - -static void -test_mlfqs_fair (int thread_cnt, int nice_min, int nice_step) -{ - struct thread_info info[MAX_THREAD_CNT]; - int64_t start_time; - int nice; - int i; - - ASSERT (thread_mlfqs); - ASSERT (thread_cnt <= MAX_THREAD_CNT); - ASSERT (nice_min >= -10); - ASSERT (nice_step >= 0); - ASSERT (nice_min + nice_step * (thread_cnt - 1) <= 20); - - thread_set_nice (-20); - - start_time = timer_ticks (); - msg ("Starting %d threads...", thread_cnt); - nice = nice_min; - for (i = 0; i < thread_cnt; i++) - { - struct thread_info *ti = &info[i]; - char name[16]; - - ti->start_time = start_time; - ti->tick_count = 0; - ti->nice = nice; - - snprintf(name, sizeof name, "load %d", i); - thread_create (name, PRI_DEFAULT, load_thread, ti); - - nice += nice_step; - } - msg ("Starting threads took %"PRId64" ticks.", timer_elapsed (start_time)); - - msg ("Sleeping 40 seconds to let threads run, please wait..."); - timer_sleep (40 * TIMER_FREQ); - - for (i = 0; i < thread_cnt; i++) - msg ("Thread %d received %d ticks.", i, info[i].tick_count); -} - -static void -load_thread (void *ti_) -{ - struct thread_info *ti = ti_; - int64_t sleep_time = 5 * TIMER_FREQ; - int64_t spin_time = sleep_time + 30 * TIMER_FREQ; - int64_t last_time = 0; - - thread_set_nice (ti->nice); - timer_sleep (sleep_time - timer_elapsed (ti->start_time)); - while (timer_elapsed (ti->start_time) < spin_time) - { - int64_t cur_time = timer_ticks (); - if (cur_time != last_time) - ti->tick_count++; - last_time = cur_time; - } -} diff --git a/src/tests/threads/mlfqs-load-1.c b/src/tests/threads/mlfqs-load-1.c deleted file mode 100644 index a39eea27ff32ff60540b5017959a95274b80c03a..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-load-1.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Verifies that a single busy thread raises the load average to - 0.5 in 38 to 45 seconds. The expected time is 42 seconds, as - you can verify: - perl -e '$i++,$a=(59*$a+1)/60while$a<=.5;print "$i\n"' - - Then, verifies that 10 seconds of inactivity drop the load - average back below 0.5 again. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -void -test_mlfqs_load_1 (void) -{ - int64_t start_time; - int elapsed; - int load_avg; - - ASSERT (thread_mlfqs); - - msg ("spinning for up to 45 seconds, please wait..."); - - start_time = timer_ticks (); - for (;;) - { - load_avg = thread_get_load_avg (); - ASSERT (load_avg >= 0); - elapsed = timer_elapsed (start_time) / TIMER_FREQ; - if (load_avg > 100) - fail ("load average is %d.%02d " - "but should be between 0 and 1 (after %d seconds)", - load_avg / 100, load_avg % 100, elapsed); - else if (load_avg > 50) - break; - else if (elapsed > 45) - fail ("load average stayed below 0.5 for more than 45 seconds"); - } - - if (elapsed < 38) - fail ("load average took only %d seconds to rise above 0.5", elapsed); - msg ("load average rose to 0.5 after %d seconds", elapsed); - - msg ("sleeping for another 10 seconds, please wait..."); - timer_sleep (TIMER_FREQ * 10); - - load_avg = thread_get_load_avg (); - if (load_avg < 0) - fail ("load average fell below 0"); - if (load_avg > 50) - fail ("load average stayed above 0.5 for more than 10 seconds"); - msg ("load average fell back below 0.5 (to %d.%02d)", - load_avg / 100, load_avg % 100); - - pass (); -} diff --git a/src/tests/threads/mlfqs-load-1.ck b/src/tests/threads/mlfqs-load-1.ck deleted file mode 100644 index faf0ffac0fcdf25f1ad93654b254ca04d8079fd7..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-load-1.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; - -our ($test); -my (@output) = read_text_file ("$test.output"); - -common_checks ("run", @output); - -@output = get_core_output ("run", @output); -fail "missing PASS in output" - unless grep ($_ eq '(mlfqs-load-1) PASS', @output); - -pass; diff --git a/src/tests/threads/mlfqs-load-60.c b/src/tests/threads/mlfqs-load-60.c deleted file mode 100644 index b6a3eb68cb4f2e761a081b6cdbf61704e9ba5bd5..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-load-60.c +++ /dev/null @@ -1,155 +0,0 @@ -/* Starts 60 threads that each sleep for 10 seconds, then spin in - a tight loop for 60 seconds, and sleep for another 60 seconds. - Every 2 seconds after the initial sleep, the main thread - prints the load average. - - The expected output is this (some margin of error is allowed): - - After 0 seconds, load average=1.00. - After 2 seconds, load average=2.95. - After 4 seconds, load average=4.84. - After 6 seconds, load average=6.66. - After 8 seconds, load average=8.42. - After 10 seconds, load average=10.13. - After 12 seconds, load average=11.78. - After 14 seconds, load average=13.37. - After 16 seconds, load average=14.91. - After 18 seconds, load average=16.40. - After 20 seconds, load average=17.84. - After 22 seconds, load average=19.24. - After 24 seconds, load average=20.58. - After 26 seconds, load average=21.89. - After 28 seconds, load average=23.15. - After 30 seconds, load average=24.37. - After 32 seconds, load average=25.54. - After 34 seconds, load average=26.68. - After 36 seconds, load average=27.78. - After 38 seconds, load average=28.85. - After 40 seconds, load average=29.88. - After 42 seconds, load average=30.87. - After 44 seconds, load average=31.84. - After 46 seconds, load average=32.77. - After 48 seconds, load average=33.67. - After 50 seconds, load average=34.54. - After 52 seconds, load average=35.38. - After 54 seconds, load average=36.19. - After 56 seconds, load average=36.98. - After 58 seconds, load average=37.74. - After 60 seconds, load average=37.48. - After 62 seconds, load average=36.24. - After 64 seconds, load average=35.04. - After 66 seconds, load average=33.88. - After 68 seconds, load average=32.76. - After 70 seconds, load average=31.68. - After 72 seconds, load average=30.63. - After 74 seconds, load average=29.62. - After 76 seconds, load average=28.64. - After 78 seconds, load average=27.69. - After 80 seconds, load average=26.78. - After 82 seconds, load average=25.89. - After 84 seconds, load average=25.04. - After 86 seconds, load average=24.21. - After 88 seconds, load average=23.41. - After 90 seconds, load average=22.64. - After 92 seconds, load average=21.89. - After 94 seconds, load average=21.16. - After 96 seconds, load average=20.46. - After 98 seconds, load average=19.79. - After 100 seconds, load average=19.13. - After 102 seconds, load average=18.50. - After 104 seconds, load average=17.89. - After 106 seconds, load average=17.30. - After 108 seconds, load average=16.73. - After 110 seconds, load average=16.17. - After 112 seconds, load average=15.64. - After 114 seconds, load average=15.12. - After 116 seconds, load average=14.62. - After 118 seconds, load average=14.14. - After 120 seconds, load average=13.67. - After 122 seconds, load average=13.22. - After 124 seconds, load average=12.78. - After 126 seconds, load average=12.36. - After 128 seconds, load average=11.95. - After 130 seconds, load average=11.56. - After 132 seconds, load average=11.17. - After 134 seconds, load average=10.80. - After 136 seconds, load average=10.45. - After 138 seconds, load average=10.10. - After 140 seconds, load average=9.77. - After 142 seconds, load average=9.45. - After 144 seconds, load average=9.13. - After 146 seconds, load average=8.83. - After 148 seconds, load average=8.54. - After 150 seconds, load average=8.26. - After 152 seconds, load average=7.98. - After 154 seconds, load average=7.72. - After 156 seconds, load average=7.47. - After 158 seconds, load average=7.22. - After 160 seconds, load average=6.98. - After 162 seconds, load average=6.75. - After 164 seconds, load average=6.53. - After 166 seconds, load average=6.31. - After 168 seconds, load average=6.10. - After 170 seconds, load average=5.90. - After 172 seconds, load average=5.70. - After 174 seconds, load average=5.52. - After 176 seconds, load average=5.33. - After 178 seconds, load average=5.16. -*/ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static int64_t start_time; - -static void load_thread (void *aux); - -#define THREAD_CNT 60 - -void -test_mlfqs_load_60 (void) -{ - int i; - - ASSERT (thread_mlfqs); - - start_time = timer_ticks (); - msg ("Starting %d niced load threads...", THREAD_CNT); - for (i = 0; i < THREAD_CNT; i++) - { - char name[16]; - snprintf(name, sizeof name, "load %d", i); - thread_create (name, PRI_DEFAULT, load_thread, NULL); - } - msg ("Starting threads took %d seconds.", - timer_elapsed (start_time) / TIMER_FREQ); - - for (i = 0; i < 90; i++) - { - int64_t sleep_until = start_time + TIMER_FREQ * (2 * i + 10); - int load_avg; - timer_sleep (sleep_until - timer_ticks ()); - load_avg = thread_get_load_avg (); - msg ("After %d seconds, load average=%d.%02d.", - i * 2, load_avg / 100, load_avg % 100); - } -} - -static void -load_thread (void *aux UNUSED) -{ - int64_t sleep_time = 10 * TIMER_FREQ; - int64_t spin_time = sleep_time + 60 * TIMER_FREQ; - int64_t exit_time = spin_time + 60 * TIMER_FREQ; - - thread_set_nice (20); - timer_sleep (sleep_time - timer_elapsed (start_time)); - while (timer_elapsed (start_time) < spin_time) - continue; - timer_sleep (exit_time - timer_elapsed (start_time)); -} diff --git a/src/tests/threads/mlfqs-load-60.ck b/src/tests/threads/mlfqs-load-60.ck deleted file mode 100644 index cb69220024ef7973a3218623a372f2e1ab3477e9..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-load-60.ck +++ /dev/null @@ -1,36 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::threads::mlfqs; - -our ($test); - -my (@output) = read_text_file ("$test.output"); -common_checks ("run", @output); -@output = get_core_output ("run", @output); - -# Get actual values. -local ($_); -my (@actual); -foreach (@output) { - my ($t, $load_avg) = /After (\d+) seconds, load average=(\d+\.\d+)\./ - or next; - $actual[$t] = $load_avg; -} - -# Calculate expected values. -my ($load_avg) = 0; -my ($recent) = 0; -my (@expected); -for (my ($t) = 0; $t < 180; $t++) { - my ($ready) = $t < 60 ? 60 : 0; - $load_avg = (59/60) * $load_avg + (1/60) * $ready; - $expected[$t] = $load_avg; -} - -mlfqs_compare ("time", "%.2f", \@actual, \@expected, 3.5, [2, 178, 2], - "Some load average values were missing or " - . "differed from those expected " - . "by more than 3.5."); -pass; diff --git a/src/tests/threads/mlfqs-load-avg.c b/src/tests/threads/mlfqs-load-avg.c deleted file mode 100644 index 50e83e276406714b03ab8d199a16259ee574ffbf..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-load-avg.c +++ /dev/null @@ -1,167 +0,0 @@ -/* Starts 60 threads numbered 0 through 59. Thread #i sleeps for - (10+i) seconds, then spins in a loop for 60 seconds, then - sleeps until a total of 120 seconds have passed. Every 2 - seconds, starting 10 seconds in, the main thread prints the - load average. - - The expected output is listed below. Some margin of error is - allowed. - - If your implementation fails this test but passes most other - tests, then consider whether you are doing too much work in - the timer interrupt. If the timer interrupt handler takes too - long, then the test's main thread will not have enough time to - do its own work (printing a message) and go back to sleep - before the next tick arrives. Then the main thread will be - ready, instead of sleeping, when the tick arrives, - artificially driving up the load average. - - After 0 seconds, load average=0.00. - After 2 seconds, load average=0.05. - After 4 seconds, load average=0.16. - After 6 seconds, load average=0.34. - After 8 seconds, load average=0.58. - After 10 seconds, load average=0.87. - After 12 seconds, load average=1.22. - After 14 seconds, load average=1.63. - After 16 seconds, load average=2.09. - After 18 seconds, load average=2.60. - After 20 seconds, load average=3.16. - After 22 seconds, load average=3.76. - After 24 seconds, load average=4.42. - After 26 seconds, load average=5.11. - After 28 seconds, load average=5.85. - After 30 seconds, load average=6.63. - After 32 seconds, load average=7.46. - After 34 seconds, load average=8.32. - After 36 seconds, load average=9.22. - After 38 seconds, load average=10.15. - After 40 seconds, load average=11.12. - After 42 seconds, load average=12.13. - After 44 seconds, load average=13.16. - After 46 seconds, load average=14.23. - After 48 seconds, load average=15.33. - After 50 seconds, load average=16.46. - After 52 seconds, load average=17.62. - After 54 seconds, load average=18.81. - After 56 seconds, load average=20.02. - After 58 seconds, load average=21.26. - After 60 seconds, load average=22.52. - After 62 seconds, load average=23.71. - After 64 seconds, load average=24.80. - After 66 seconds, load average=25.78. - After 68 seconds, load average=26.66. - After 70 seconds, load average=27.45. - After 72 seconds, load average=28.14. - After 74 seconds, load average=28.75. - After 76 seconds, load average=29.27. - After 78 seconds, load average=29.71. - After 80 seconds, load average=30.06. - After 82 seconds, load average=30.34. - After 84 seconds, load average=30.55. - After 86 seconds, load average=30.68. - After 88 seconds, load average=30.74. - After 90 seconds, load average=30.73. - After 92 seconds, load average=30.66. - After 94 seconds, load average=30.52. - After 96 seconds, load average=30.32. - After 98 seconds, load average=30.06. - After 100 seconds, load average=29.74. - After 102 seconds, load average=29.37. - After 104 seconds, load average=28.95. - After 106 seconds, load average=28.47. - After 108 seconds, load average=27.94. - After 110 seconds, load average=27.36. - After 112 seconds, load average=26.74. - After 114 seconds, load average=26.07. - After 116 seconds, load average=25.36. - After 118 seconds, load average=24.60. - After 120 seconds, load average=23.81. - After 122 seconds, load average=23.02. - After 124 seconds, load average=22.26. - After 126 seconds, load average=21.52. - After 128 seconds, load average=20.81. - After 130 seconds, load average=20.12. - After 132 seconds, load average=19.46. - After 134 seconds, load average=18.81. - After 136 seconds, load average=18.19. - After 138 seconds, load average=17.59. - After 140 seconds, load average=17.01. - After 142 seconds, load average=16.45. - After 144 seconds, load average=15.90. - After 146 seconds, load average=15.38. - After 148 seconds, load average=14.87. - After 150 seconds, load average=14.38. - After 152 seconds, load average=13.90. - After 154 seconds, load average=13.44. - After 156 seconds, load average=13.00. - After 158 seconds, load average=12.57. - After 160 seconds, load average=12.15. - After 162 seconds, load average=11.75. - After 164 seconds, load average=11.36. - After 166 seconds, load average=10.99. - After 168 seconds, load average=10.62. - After 170 seconds, load average=10.27. - After 172 seconds, load average=9.93. - After 174 seconds, load average=9.61. - After 176 seconds, load average=9.29. - After 178 seconds, load average=8.98. -*/ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static int64_t start_time; - -static void load_thread (void *seq_no); - -#define THREAD_CNT 60 - -void -test_mlfqs_load_avg (void) -{ - int i; - - ASSERT (thread_mlfqs); - - start_time = timer_ticks (); - msg ("Starting %d load threads...", THREAD_CNT); - for (i = 0; i < THREAD_CNT; i++) - { - char name[16]; - snprintf(name, sizeof name, "load %d", i); - thread_create (name, PRI_DEFAULT, load_thread, (void *) i); - } - msg ("Starting threads took %d seconds.", - timer_elapsed (start_time) / TIMER_FREQ); - thread_set_nice (-20); - - for (i = 0; i < 90; i++) - { - int64_t sleep_until = start_time + TIMER_FREQ * (2 * i + 10); - int load_avg; - timer_sleep (sleep_until - timer_ticks ()); - load_avg = thread_get_load_avg (); - msg ("After %d seconds, load average=%d.%02d.", - i * 2, load_avg / 100, load_avg % 100); - } -} - -static void -load_thread (void *seq_no_) -{ - int seq_no = (int) seq_no_; - int sleep_time = TIMER_FREQ * (10 + seq_no); - int spin_time = sleep_time + TIMER_FREQ * THREAD_CNT; - int exit_time = TIMER_FREQ * (THREAD_CNT * 2); - - timer_sleep (sleep_time - timer_elapsed (start_time)); - while (timer_elapsed (start_time) < spin_time) - continue; - timer_sleep (exit_time - timer_elapsed (start_time)); -} diff --git a/src/tests/threads/mlfqs-load-avg.ck b/src/tests/threads/mlfqs-load-avg.ck deleted file mode 100644 index 2254d05467ee7a8bce10994ff10f98a91919f7f4..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-load-avg.ck +++ /dev/null @@ -1,36 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::threads::mlfqs; - -our ($test); -my (@output) = read_text_file ("$test.output"); - -common_checks ("run", @output); -@output = get_core_output ("run", @output); - -# Get actual values. -local ($_); -my (@actual); -foreach (@output) { - my ($t, $load_avg) = /After (\d+) seconds, load average=(\d+\.\d+)\./ - or next; - $actual[$t] = $load_avg; -} - -# Calculate expected values. -my ($load_avg) = 0; -my ($recent) = 0; -my (@expected); -for (my ($t) = 0; $t < 180; $t++) { - my ($ready) = $t < 60 ? $t : $t < 120 ? 120 - $t : 0; - $load_avg = (59/60) * $load_avg + (1/60) * $ready; - $expected[$t] = $load_avg; -} - -mlfqs_compare ("time", "%.2f", \@actual, \@expected, 2.5, [2, 178, 2], - "Some load average values were missing or " - . "differed from those expected " - . "by more than 2.5."); -pass; diff --git a/src/tests/threads/mlfqs-nice-10.ck b/src/tests/threads/mlfqs-nice-10.ck deleted file mode 100644 index 53e0abe9f16337ba81f14caf127ef6a9a8f5a7e3..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-nice-10.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::threads::mlfqs; - -check_mlfqs_fair ([0...9], 25); diff --git a/src/tests/threads/mlfqs-nice-2.ck b/src/tests/threads/mlfqs-nice-2.ck deleted file mode 100644 index ada366ba53578a228fc31bd6d2053ddce80f30f4..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-nice-2.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::threads::mlfqs; - -check_mlfqs_fair ([0, 5], 50); diff --git a/src/tests/threads/mlfqs-recent-1.c b/src/tests/threads/mlfqs-recent-1.c deleted file mode 100644 index 425867145c79b2e54f892e51d8f0da33473cf53a..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-recent-1.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Checks that recent_cpu is calculated properly for the case of - a single ready process. - - The expected output is this (some margin of error is allowed): - - After 2 seconds, recent_cpu is 6.40, load_avg is 0.03. - After 4 seconds, recent_cpu is 12.60, load_avg is 0.07. - After 6 seconds, recent_cpu is 18.61, load_avg is 0.10. - After 8 seconds, recent_cpu is 24.44, load_avg is 0.13. - After 10 seconds, recent_cpu is 30.08, load_avg is 0.15. - After 12 seconds, recent_cpu is 35.54, load_avg is 0.18. - After 14 seconds, recent_cpu is 40.83, load_avg is 0.21. - After 16 seconds, recent_cpu is 45.96, load_avg is 0.24. - After 18 seconds, recent_cpu is 50.92, load_avg is 0.26. - After 20 seconds, recent_cpu is 55.73, load_avg is 0.29. - After 22 seconds, recent_cpu is 60.39, load_avg is 0.31. - After 24 seconds, recent_cpu is 64.90, load_avg is 0.33. - After 26 seconds, recent_cpu is 69.27, load_avg is 0.35. - After 28 seconds, recent_cpu is 73.50, load_avg is 0.38. - After 30 seconds, recent_cpu is 77.60, load_avg is 0.40. - After 32 seconds, recent_cpu is 81.56, load_avg is 0.42. - After 34 seconds, recent_cpu is 85.40, load_avg is 0.44. - After 36 seconds, recent_cpu is 89.12, load_avg is 0.45. - After 38 seconds, recent_cpu is 92.72, load_avg is 0.47. - After 40 seconds, recent_cpu is 96.20, load_avg is 0.49. - After 42 seconds, recent_cpu is 99.57, load_avg is 0.51. - After 44 seconds, recent_cpu is 102.84, load_avg is 0.52. - After 46 seconds, recent_cpu is 106.00, load_avg is 0.54. - After 48 seconds, recent_cpu is 109.06, load_avg is 0.55. - After 50 seconds, recent_cpu is 112.02, load_avg is 0.57. - After 52 seconds, recent_cpu is 114.89, load_avg is 0.58. - After 54 seconds, recent_cpu is 117.66, load_avg is 0.60. - After 56 seconds, recent_cpu is 120.34, load_avg is 0.61. - After 58 seconds, recent_cpu is 122.94, load_avg is 0.62. - After 60 seconds, recent_cpu is 125.46, load_avg is 0.64. - After 62 seconds, recent_cpu is 127.89, load_avg is 0.65. - After 64 seconds, recent_cpu is 130.25, load_avg is 0.66. - After 66 seconds, recent_cpu is 132.53, load_avg is 0.67. - After 68 seconds, recent_cpu is 134.73, load_avg is 0.68. - After 70 seconds, recent_cpu is 136.86, load_avg is 0.69. - After 72 seconds, recent_cpu is 138.93, load_avg is 0.70. - After 74 seconds, recent_cpu is 140.93, load_avg is 0.71. - After 76 seconds, recent_cpu is 142.86, load_avg is 0.72. - After 78 seconds, recent_cpu is 144.73, load_avg is 0.73. - After 80 seconds, recent_cpu is 146.54, load_avg is 0.74. - After 82 seconds, recent_cpu is 148.29, load_avg is 0.75. - After 84 seconds, recent_cpu is 149.99, load_avg is 0.76. - After 86 seconds, recent_cpu is 151.63, load_avg is 0.76. - After 88 seconds, recent_cpu is 153.21, load_avg is 0.77. - After 90 seconds, recent_cpu is 154.75, load_avg is 0.78. - After 92 seconds, recent_cpu is 156.23, load_avg is 0.79. - After 94 seconds, recent_cpu is 157.67, load_avg is 0.79. - After 96 seconds, recent_cpu is 159.06, load_avg is 0.80. - After 98 seconds, recent_cpu is 160.40, load_avg is 0.81. - After 100 seconds, recent_cpu is 161.70, load_avg is 0.81. - After 102 seconds, recent_cpu is 162.96, load_avg is 0.82. - After 104 seconds, recent_cpu is 164.18, load_avg is 0.83. - After 106 seconds, recent_cpu is 165.35, load_avg is 0.83. - After 108 seconds, recent_cpu is 166.49, load_avg is 0.84. - After 110 seconds, recent_cpu is 167.59, load_avg is 0.84. - After 112 seconds, recent_cpu is 168.66, load_avg is 0.85. - After 114 seconds, recent_cpu is 169.69, load_avg is 0.85. - After 116 seconds, recent_cpu is 170.69, load_avg is 0.86. - After 118 seconds, recent_cpu is 171.65, load_avg is 0.86. - After 120 seconds, recent_cpu is 172.58, load_avg is 0.87. - After 122 seconds, recent_cpu is 173.49, load_avg is 0.87. - After 124 seconds, recent_cpu is 174.36, load_avg is 0.88. - After 126 seconds, recent_cpu is 175.20, load_avg is 0.88. - After 128 seconds, recent_cpu is 176.02, load_avg is 0.88. - After 130 seconds, recent_cpu is 176.81, load_avg is 0.89. - After 132 seconds, recent_cpu is 177.57, load_avg is 0.89. - After 134 seconds, recent_cpu is 178.31, load_avg is 0.89. - After 136 seconds, recent_cpu is 179.02, load_avg is 0.90. - After 138 seconds, recent_cpu is 179.72, load_avg is 0.90. - After 140 seconds, recent_cpu is 180.38, load_avg is 0.90. - After 142 seconds, recent_cpu is 181.03, load_avg is 0.91. - After 144 seconds, recent_cpu is 181.65, load_avg is 0.91. - After 146 seconds, recent_cpu is 182.26, load_avg is 0.91. - After 148 seconds, recent_cpu is 182.84, load_avg is 0.92. - After 150 seconds, recent_cpu is 183.41, load_avg is 0.92. - After 152 seconds, recent_cpu is 183.96, load_avg is 0.92. - After 154 seconds, recent_cpu is 184.49, load_avg is 0.92. - After 156 seconds, recent_cpu is 185.00, load_avg is 0.93. - After 158 seconds, recent_cpu is 185.49, load_avg is 0.93. - After 160 seconds, recent_cpu is 185.97, load_avg is 0.93. - After 162 seconds, recent_cpu is 186.43, load_avg is 0.93. - After 164 seconds, recent_cpu is 186.88, load_avg is 0.94. - After 166 seconds, recent_cpu is 187.31, load_avg is 0.94. - After 168 seconds, recent_cpu is 187.73, load_avg is 0.94. - After 170 seconds, recent_cpu is 188.14, load_avg is 0.94. - After 172 seconds, recent_cpu is 188.53, load_avg is 0.94. - After 174 seconds, recent_cpu is 188.91, load_avg is 0.95. - After 176 seconds, recent_cpu is 189.27, load_avg is 0.95. - After 178 seconds, recent_cpu is 189.63, load_avg is 0.95. - After 180 seconds, recent_cpu is 189.97, load_avg is 0.95. -*/ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -/* Sensitive to assumption that recent_cpu updates happen exactly - when timer_ticks() % TIMER_FREQ == 0. */ - -void -test_mlfqs_recent_1 (void) -{ - int64_t start_time; - int last_elapsed = 0; - - ASSERT (thread_mlfqs); - - do - { - msg ("Sleeping 10 seconds to allow recent_cpu to decay, please wait..."); - start_time = timer_ticks (); - timer_sleep (DIV_ROUND_UP (start_time, TIMER_FREQ) - start_time - + 10 * TIMER_FREQ); - } - while (thread_get_recent_cpu () > 700); - - start_time = timer_ticks (); - for (;;) - { - int elapsed = timer_elapsed (start_time); - if (elapsed % (TIMER_FREQ * 2) == 0 && elapsed > last_elapsed) - { - int recent_cpu = thread_get_recent_cpu (); - int load_avg = thread_get_load_avg (); - int elapsed_seconds = elapsed / TIMER_FREQ; - msg ("After %d seconds, recent_cpu is %d.%02d, load_avg is %d.%02d.", - elapsed_seconds, - recent_cpu / 100, recent_cpu % 100, - load_avg / 100, load_avg % 100); - if (elapsed_seconds >= 180) - break; - } - last_elapsed = elapsed; - } -} diff --git a/src/tests/threads/mlfqs-recent-1.ck b/src/tests/threads/mlfqs-recent-1.ck deleted file mode 100644 index a2ba44d375987e7d3504adce66f1dd78efbfddf6..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs-recent-1.ck +++ /dev/null @@ -1,31 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::threads::mlfqs; - -our ($test); -my (@output) = read_text_file ("$test.output"); -common_checks ("run", @output); -@output = get_core_output ("run", @output); - -# Get actual values. -local ($_); -my (@actual); -foreach (@output) { - my ($t, $recent_cpu) = /After (\d+) seconds, recent_cpu is (\d+\.\d+),/ - or next; - $actual[$t] = $recent_cpu; -} - -# Calculate expected values. -my ($expected_load_avg, $expected_recent_cpu) - = mlfqs_expected_load ([(1) x 180], [(100) x 180]); -my (@expected) = @$expected_recent_cpu; - -# Compare actual and expected values. -mlfqs_compare ("time", "%.2f", \@actual, \@expected, 2.5, [2, 178, 2], - "Some recent_cpu values were missing or " - . "differed from those expected " - . "by more than 2.5."); -pass; diff --git a/src/tests/threads/mlfqs.pm b/src/tests/threads/mlfqs.pm deleted file mode 100644 index 184ac16a0a1c2c45304ca7580145eb067e3416a9..0000000000000000000000000000000000000000 --- a/src/tests/threads/mlfqs.pm +++ /dev/null @@ -1,146 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; - -sub mlfqs_expected_load { - my ($ready, $recent_delta) = @_; - my (@load_avg) = 0; - my (@recent_cpu) = 0; - my ($load_avg) = 0; - my ($recent_cpu) = 0; - for my $i (0...$#$ready) { - $load_avg = (59/60) * $load_avg + (1/60) * $ready->[$i]; - push (@load_avg, $load_avg); - - if (defined $recent_delta->[$i]) { - my ($twice_load) = $load_avg * 2; - my ($load_factor) = $twice_load / ($twice_load + 1); - $recent_cpu = ($recent_cpu + $recent_delta->[$i]) * $load_factor; - push (@recent_cpu, $recent_cpu); - } - } - return (\@load_avg, \@recent_cpu); -} - -sub mlfqs_expected_ticks { - my (@nice) = @_; - my ($thread_cnt) = scalar (@nice); - my (@recent_cpu) = (0) x $thread_cnt; - my (@slices) = (0) x $thread_cnt; - my (@fifo) = (0) x $thread_cnt; - my ($next_fifo) = 1; - my ($load_avg) = 0; - for my $i (1...750) { - if ($i % 25 == 0) { - # Update load average. - $load_avg = (59/60) * $load_avg + (1/60) * $thread_cnt; - - # Update recent_cpu. - my ($twice_load) = $load_avg * 2; - my ($load_factor) = $twice_load / ($twice_load + 1); - $recent_cpu[$_] = $recent_cpu[$_] * $load_factor + $nice[$_] - foreach 0...($thread_cnt - 1); - } - - # Update priorities. - my (@priority); - foreach my $j (0...($thread_cnt - 1)) { - my ($priority) = int ($recent_cpu[$j] / 4 + $nice[$j] * 2); - $priority = 0 if $priority < 0; - $priority = 63 if $priority > 63; - push (@priority, $priority); - } - - # Choose thread to run. - my $max = 0; - for my $j (1...$#priority) { - if ($priority[$j] < $priority[$max] - || ($priority[$j] == $priority[$max] - && $fifo[$j] < $fifo[$max])) { - $max = $j; - } - } - $fifo[$max] = $next_fifo++; - - # Run thread. - $recent_cpu[$max] += 4; - $slices[$max] += 4; - } - return @slices; -} - -sub check_mlfqs_fair { - my ($nice, $maxdiff) = @_; - our ($test); - my (@output) = read_text_file ("$test.output"); - common_checks ("run", @output); - @output = get_core_output ("run", @output); - - my (@actual); - local ($_); - foreach (@output) { - my ($id, $count) = /Thread (\d+) received (\d+) ticks\./ or next; - $actual[$id] = $count; - } - - my (@expected) = mlfqs_expected_ticks (@$nice); - mlfqs_compare ("thread", "%d", - \@actual, \@expected, $maxdiff, [0, $#$nice, 1], - "Some tick counts were missing or differed from those " - . "expected by more than $maxdiff."); - pass; -} - -sub mlfqs_compare { - my ($indep_var, $format, - $actual_ref, $expected_ref, $maxdiff, $t_range, $message) = @_; - my ($t_min, $t_max, $t_step) = @$t_range; - - my ($ok) = 1; - for (my ($t) = $t_min; $t <= $t_max; $t += $t_step) { - my ($actual) = $actual_ref->[$t]; - my ($expected) = $expected_ref->[$t]; - $ok = 0, last - if !defined ($actual) || abs ($actual - $expected) > $maxdiff + .01; - } - return if $ok; - - print "$message\n"; - mlfqs_row ($indep_var, "actual", "<->", "expected", "explanation"); - mlfqs_row ("------", "--------", "---", "--------", '-' x 40); - for (my ($t) = $t_min; $t <= $t_max; $t += $t_step) { - my ($actual) = $actual_ref->[$t]; - my ($expected) = $expected_ref->[$t]; - my ($diff, $rationale); - if (!defined $actual) { - $actual = 'undef' ; - $diff = ''; - $rationale = 'Missing value.'; - } else { - my ($delta) = abs ($actual - $expected); - if ($delta > $maxdiff + .01) { - my ($excess) = $delta - $maxdiff; - if ($actual > $expected) { - $diff = '>>>'; - $rationale = sprintf "Too big, by $format.", $excess; - } else { - $diff = '<<<'; - $rationale = sprintf "Too small, by $format.", $excess; - } - } else { - $diff = ' = '; - $rationale = ''; - } - $actual = sprintf ($format, $actual); - } - $expected = sprintf ($format, $expected); - mlfqs_row ($t, $actual, $diff, $expected, $rationale); - } - fail; -} - -sub mlfqs_row { - printf "%6s %8s %3s %-8s %s\n", @_; -} - -1; diff --git a/src/tests/threads/priority-change.c b/src/tests/threads/priority-change.c deleted file mode 100644 index 810b05a1d76973ebdf28f914d03c91318c021e85..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-change.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Verifies that lowering a thread's priority so that it is no - longer the highest-priority thread in the system causes it to - yield immediately. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/thread.h" - -static thread_func changing_thread; - -void -test_priority_change (void) -{ - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - msg ("Creating a high-priority thread 2."); - thread_create ("thread 2", PRI_DEFAULT + 1, changing_thread, NULL); - msg ("Thread 2 should have just lowered its priority."); - thread_set_priority (PRI_DEFAULT - 2); - msg ("Thread 2 should have just exited."); -} - -static void -changing_thread (void *aux UNUSED) -{ - msg ("Thread 2 now lowering priority."); - thread_set_priority (PRI_DEFAULT - 1); - msg ("Thread 2 exiting."); -} diff --git a/src/tests/threads/priority-change.ck b/src/tests/threads/priority-change.ck deleted file mode 100644 index f4d9b2f34f1fdc6a3910f83b43f33ca826f1ae20..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-change.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-change) begin -(priority-change) Creating a high-priority thread 2. -(priority-change) Thread 2 now lowering priority. -(priority-change) Thread 2 should have just lowered its priority. -(priority-change) Thread 2 exiting. -(priority-change) Thread 2 should have just exited. -(priority-change) end -EOF -pass; diff --git a/src/tests/threads/priority-condvar.c b/src/tests/threads/priority-condvar.c deleted file mode 100644 index c1efb1bdee871759fb05b3ca5267bf24f7cd0a98..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-condvar.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Tests that cond_signal() wakes up the highest-priority thread - waiting in cond_wait(). */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static thread_func priority_condvar_thread; -static struct lock lock; -static struct condition condition; - -void -test_priority_condvar (void) -{ - int i; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - lock_init (&lock); - cond_init (&condition); - - thread_set_priority (PRI_MIN); - for (i = 0; i < 10; i++) - { - int priority = PRI_DEFAULT - (i + 7) % 10 - 1; - char name[16]; - snprintf (name, sizeof name, "priority %d", priority); - thread_create (name, priority, priority_condvar_thread, NULL); - } - - for (i = 0; i < 10; i++) - { - lock_acquire (&lock); - msg ("Signaling..."); - cond_signal (&condition, &lock); - lock_release (&lock); - } -} - -static void -priority_condvar_thread (void *aux UNUSED) -{ - msg ("Thread %s starting.", thread_name ()); - lock_acquire (&lock); - cond_wait (&condition, &lock); - msg ("Thread %s woke up.", thread_name ()); - lock_release (&lock); -} diff --git a/src/tests/threads/priority-condvar.ck b/src/tests/threads/priority-condvar.ck deleted file mode 100644 index 195c1ab4753cd22f92a86eb6291e10cb9216eca7..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-condvar.ck +++ /dev/null @@ -1,39 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-condvar) begin -(priority-condvar) Thread priority 23 starting. -(priority-condvar) Thread priority 22 starting. -(priority-condvar) Thread priority 21 starting. -(priority-condvar) Thread priority 30 starting. -(priority-condvar) Thread priority 29 starting. -(priority-condvar) Thread priority 28 starting. -(priority-condvar) Thread priority 27 starting. -(priority-condvar) Thread priority 26 starting. -(priority-condvar) Thread priority 25 starting. -(priority-condvar) Thread priority 24 starting. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 30 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 29 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 28 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 27 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 26 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 25 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 24 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 23 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 22 woke up. -(priority-condvar) Signaling... -(priority-condvar) Thread priority 21 woke up. -(priority-condvar) end -EOF -pass; diff --git a/src/tests/threads/priority-donate-chain.c b/src/tests/threads/priority-donate-chain.c deleted file mode 100644 index 3ffabca9dd9b0b3281d169f0b4edb92a246b18c6..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-chain.c +++ /dev/null @@ -1,114 +0,0 @@ -/* The main thread set its priority to PRI_MIN and creates 7 threads - (thread 1..7) with priorities PRI_MIN + 3, 6, 9, 12, ... - The main thread initializes 8 locks: lock 0..7 and acquires lock 0. - - When thread[i] starts, it first acquires lock[i] (unless i == 7.) - Subsequently, thread[i] attempts to acquire lock[i-1], which is held by - thread[i-1], except for lock[0], which is held by the main thread. - Because the lock is held, thread[i] donates its priority to thread[i-1], - which donates to thread[i-2], and so on until the main thread - receives the donation. - - After threads[1..7] have been created and are blocked on locks[0..7], - the main thread releases lock[0], unblocking thread[1], and being - preempted by it. - Thread[1] then completes acquiring lock[0], then releases lock[0], - then releases lock[1], unblocking thread[2], etc. - Thread[7] finally acquires & releases lock[7] and exits, allowing - thread[6], then thread[5] etc. to run and exit until finally the - main thread exits. - - In addition, interloper threads are created at priority levels - p = PRI_MIN + 2, 5, 8, 11, ... which should not be run until the - corresponding thread with priority p + 1 has finished. - - Written by Godmar Back <gback@cs.vt.edu> */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -#define NESTING_DEPTH 8 - -struct lock_pair - { - struct lock *second; - struct lock *first; - }; - -static thread_func donor_thread_func; -static thread_func interloper_thread_func; - -void -test_priority_donate_chain (void) -{ - int i; - struct lock locks[NESTING_DEPTH - 1]; - struct lock_pair lock_pairs[NESTING_DEPTH]; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - thread_set_priority (PRI_MIN); - - for (i = 0; i < NESTING_DEPTH - 1; i++) - lock_init (&locks[i]); - - lock_acquire (&locks[0]); - msg ("%s got lock.", thread_name ()); - - for (i = 1; i < NESTING_DEPTH; i++) - { - char name[16]; - int thread_priority; - - snprintf (name, sizeof name, "thread %d", i); - thread_priority = PRI_MIN + i * 3; - lock_pairs[i].first = i < NESTING_DEPTH - 1 ? locks + i: NULL; - lock_pairs[i].second = locks + i - 1; - - thread_create (name, thread_priority, donor_thread_func, lock_pairs + i); - msg ("%s should have priority %d. Actual priority: %d.", - thread_name (), thread_priority, thread_get_priority ()); - - snprintf (name, sizeof name, "interloper %d", i); - thread_create (name, thread_priority - 1, interloper_thread_func, NULL); - } - - lock_release (&locks[0]); - msg ("%s finishing with priority %d.", thread_name (), - thread_get_priority ()); -} - -static void -donor_thread_func (void *locks_) -{ - struct lock_pair *locks = locks_; - - if (locks->first) - lock_acquire (locks->first); - - lock_acquire (locks->second); - msg ("%s got lock", thread_name ()); - - lock_release (locks->second); - msg ("%s should have priority %d. Actual priority: %d", - thread_name (), (NESTING_DEPTH - 1) * 3, - thread_get_priority ()); - - if (locks->first) - lock_release (locks->first); - - msg ("%s finishing with priority %d.", thread_name (), - thread_get_priority ()); -} - -static void -interloper_thread_func (void *arg_ UNUSED) -{ - msg ("%s finished.", thread_name ()); -} - -// vim: sw=2 diff --git a/src/tests/threads/priority-donate-chain.ck b/src/tests/threads/priority-donate-chain.ck deleted file mode 100644 index 213e64968c83b48c27678f5076d84844e24bd61a..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-chain.ck +++ /dev/null @@ -1,46 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-donate-chain) begin -(priority-donate-chain) main got lock. -(priority-donate-chain) main should have priority 3. Actual priority: 3. -(priority-donate-chain) main should have priority 6. Actual priority: 6. -(priority-donate-chain) main should have priority 9. Actual priority: 9. -(priority-donate-chain) main should have priority 12. Actual priority: 12. -(priority-donate-chain) main should have priority 15. Actual priority: 15. -(priority-donate-chain) main should have priority 18. Actual priority: 18. -(priority-donate-chain) main should have priority 21. Actual priority: 21. -(priority-donate-chain) thread 1 got lock -(priority-donate-chain) thread 1 should have priority 21. Actual priority: 21 -(priority-donate-chain) thread 2 got lock -(priority-donate-chain) thread 2 should have priority 21. Actual priority: 21 -(priority-donate-chain) thread 3 got lock -(priority-donate-chain) thread 3 should have priority 21. Actual priority: 21 -(priority-donate-chain) thread 4 got lock -(priority-donate-chain) thread 4 should have priority 21. Actual priority: 21 -(priority-donate-chain) thread 5 got lock -(priority-donate-chain) thread 5 should have priority 21. Actual priority: 21 -(priority-donate-chain) thread 6 got lock -(priority-donate-chain) thread 6 should have priority 21. Actual priority: 21 -(priority-donate-chain) thread 7 got lock -(priority-donate-chain) thread 7 should have priority 21. Actual priority: 21 -(priority-donate-chain) thread 7 finishing with priority 21. -(priority-donate-chain) interloper 7 finished. -(priority-donate-chain) thread 6 finishing with priority 18. -(priority-donate-chain) interloper 6 finished. -(priority-donate-chain) thread 5 finishing with priority 15. -(priority-donate-chain) interloper 5 finished. -(priority-donate-chain) thread 4 finishing with priority 12. -(priority-donate-chain) interloper 4 finished. -(priority-donate-chain) thread 3 finishing with priority 9. -(priority-donate-chain) interloper 3 finished. -(priority-donate-chain) thread 2 finishing with priority 6. -(priority-donate-chain) interloper 2 finished. -(priority-donate-chain) thread 1 finishing with priority 3. -(priority-donate-chain) interloper 1 finished. -(priority-donate-chain) main finishing with priority 0. -(priority-donate-chain) end -EOF -pass; diff --git a/src/tests/threads/priority-donate-lower.c b/src/tests/threads/priority-donate-lower.c deleted file mode 100644 index 4965d756c47700a82663e1140862f66486c47c3f..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-lower.c +++ /dev/null @@ -1,51 +0,0 @@ -/* The main thread acquires a lock. Then it creates a - higher-priority thread that blocks acquiring the lock, causing - it to donate their priorities to the main thread. The main - thread attempts to lower its priority, which should not take - effect until the donation is released. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -static thread_func acquire_thread_func; - -void -test_priority_donate_lower (void) -{ - struct lock lock; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - lock_init (&lock); - lock_acquire (&lock); - thread_create ("acquire", PRI_DEFAULT + 10, acquire_thread_func, &lock); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 10, thread_get_priority ()); - - msg ("Lowering base priority..."); - thread_set_priority (PRI_DEFAULT - 10); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 10, thread_get_priority ()); - lock_release (&lock); - msg ("acquire must already have finished."); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT - 10, thread_get_priority ()); -} - -static void -acquire_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("acquire: got the lock"); - lock_release (lock); - msg ("acquire: done"); -} diff --git a/src/tests/threads/priority-donate-lower.ck b/src/tests/threads/priority-donate-lower.ck deleted file mode 100644 index c9bb61b170e43ed6ebaddd7905334b837680f643..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-lower.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-donate-lower) begin -(priority-donate-lower) Main thread should have priority 41. Actual priority: 41. -(priority-donate-lower) Lowering base priority... -(priority-donate-lower) Main thread should have priority 41. Actual priority: 41. -(priority-donate-lower) acquire: got the lock -(priority-donate-lower) acquire: done -(priority-donate-lower) acquire must already have finished. -(priority-donate-lower) Main thread should have priority 21. Actual priority: 21. -(priority-donate-lower) end -EOF -pass; diff --git a/src/tests/threads/priority-donate-multiple.c b/src/tests/threads/priority-donate-multiple.c deleted file mode 100644 index df4689cecc602a17bc6dfbe183dd23504a8970b1..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-multiple.c +++ /dev/null @@ -1,77 +0,0 @@ -/* The main thread acquires locks A and B, then it creates two - higher-priority threads. Each of these threads blocks - acquiring one of the locks and thus donate their priority to - the main thread. The main thread releases the locks in turn - and relinquishes its donated priorities. - - Based on a test originally submitted for Stanford's CS 140 in - winter 1999 by Matt Franklin <startled@leland.stanford.edu>, - Greg Hutchins <gmh@leland.stanford.edu>, Yu Ping Hu - <yph@cs.stanford.edu>. Modified by arens. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -static thread_func a_thread_func; -static thread_func b_thread_func; - -void -test_priority_donate_multiple (void) -{ - struct lock a, b; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - lock_init (&a); - lock_init (&b); - - lock_acquire (&a); - lock_acquire (&b); - - thread_create ("a", PRI_DEFAULT + 1, a_thread_func, &a); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 1, thread_get_priority ()); - - thread_create ("b", PRI_DEFAULT + 2, b_thread_func, &b); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 2, thread_get_priority ()); - - lock_release (&b); - msg ("Thread b should have just finished."); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 1, thread_get_priority ()); - - lock_release (&a); - msg ("Thread a should have just finished."); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT, thread_get_priority ()); -} - -static void -a_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("Thread a acquired lock a."); - lock_release (lock); - msg ("Thread a finished."); -} - -static void -b_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("Thread b acquired lock b."); - lock_release (lock); - msg ("Thread b finished."); -} diff --git a/src/tests/threads/priority-donate-multiple.ck b/src/tests/threads/priority-donate-multiple.ck deleted file mode 100644 index 0afd20bd1397fbd1aac7b84b9eccba48ae9e42c9..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-multiple.ck +++ /dev/null @@ -1,19 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-donate-multiple) begin -(priority-donate-multiple) Main thread should have priority 32. Actual priority: 32. -(priority-donate-multiple) Main thread should have priority 33. Actual priority: 33. -(priority-donate-multiple) Thread b acquired lock b. -(priority-donate-multiple) Thread b finished. -(priority-donate-multiple) Thread b should have just finished. -(priority-donate-multiple) Main thread should have priority 32. Actual priority: 32. -(priority-donate-multiple) Thread a acquired lock a. -(priority-donate-multiple) Thread a finished. -(priority-donate-multiple) Thread a should have just finished. -(priority-donate-multiple) Main thread should have priority 31. Actual priority: 31. -(priority-donate-multiple) end -EOF -pass; diff --git a/src/tests/threads/priority-donate-multiple2.c b/src/tests/threads/priority-donate-multiple2.c deleted file mode 100644 index 7f65fefc8de03dd9d219da356df8aad44cc85216..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-multiple2.c +++ /dev/null @@ -1,90 +0,0 @@ -/* The main thread acquires locks A and B, then it creates three - higher-priority threads. The first two of these threads block - acquiring one of the locks and thus donate their priority to - the main thread. The main thread releases the locks in turn - and relinquishes its donated priorities, allowing the third thread - to run. - - In this test, the main thread releases the locks in a different - order compared to priority-donate-multiple.c. - - Written by Godmar Back <gback@cs.vt.edu>. - Based on a test originally submitted for Stanford's CS 140 in - winter 1999 by Matt Franklin <startled@leland.stanford.edu>, - Greg Hutchins <gmh@leland.stanford.edu>, Yu Ping Hu - <yph@cs.stanford.edu>. Modified by arens. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -static thread_func a_thread_func; -static thread_func b_thread_func; -static thread_func c_thread_func; - -void -test_priority_donate_multiple2 (void) -{ - struct lock a, b; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - lock_init (&a); - lock_init (&b); - - lock_acquire (&a); - lock_acquire (&b); - - thread_create ("a", PRI_DEFAULT + 3, a_thread_func, &a); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 3, thread_get_priority ()); - - thread_create ("c", PRI_DEFAULT + 1, c_thread_func, NULL); - - thread_create ("b", PRI_DEFAULT + 5, b_thread_func, &b); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 5, thread_get_priority ()); - - lock_release (&a); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 5, thread_get_priority ()); - - lock_release (&b); - msg ("Threads b, a, c should have just finished, in that order."); - msg ("Main thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT, thread_get_priority ()); -} - -static void -a_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("Thread a acquired lock a."); - lock_release (lock); - msg ("Thread a finished."); -} - -static void -b_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("Thread b acquired lock b."); - lock_release (lock); - msg ("Thread b finished."); -} - -static void -c_thread_func (void *a_ UNUSED) -{ - msg ("Thread c finished."); -} diff --git a/src/tests/threads/priority-donate-multiple2.ck b/src/tests/threads/priority-donate-multiple2.ck deleted file mode 100644 index b23533ae938b3832767c721fbc8d7e523cc9165e..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-multiple2.ck +++ /dev/null @@ -1,19 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-donate-multiple2) begin -(priority-donate-multiple2) Main thread should have priority 34. Actual priority: 34. -(priority-donate-multiple2) Main thread should have priority 36. Actual priority: 36. -(priority-donate-multiple2) Main thread should have priority 36. Actual priority: 36. -(priority-donate-multiple2) Thread b acquired lock b. -(priority-donate-multiple2) Thread b finished. -(priority-donate-multiple2) Thread a acquired lock a. -(priority-donate-multiple2) Thread a finished. -(priority-donate-multiple2) Thread c finished. -(priority-donate-multiple2) Threads b, a, c should have just finished, in that order. -(priority-donate-multiple2) Main thread should have priority 31. Actual priority: 31. -(priority-donate-multiple2) end -EOF -pass; diff --git a/src/tests/threads/priority-donate-nest.c b/src/tests/threads/priority-donate-nest.c deleted file mode 100644 index 3a3a9a590a2b677031524ad351f6e20e88216b8d..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-nest.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Low-priority main thread L acquires lock A. Medium-priority - thread M then acquires lock B then blocks on acquiring lock A. - High-priority thread H then blocks on acquiring lock B. Thus, - thread H donates its priority to M, which in turn donates it - to thread L. - - Based on a test originally submitted for Stanford's CS 140 in - winter 1999 by Matt Franklin <startled@leland.stanford.edu>, - Greg Hutchins <gmh@leland.stanford.edu>, Yu Ping Hu - <yph@cs.stanford.edu>. Modified by arens. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -struct locks - { - struct lock *a; - struct lock *b; - }; - -static thread_func medium_thread_func; -static thread_func high_thread_func; - -void -test_priority_donate_nest (void) -{ - struct lock a, b; - struct locks locks; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - lock_init (&a); - lock_init (&b); - - lock_acquire (&a); - - locks.a = &a; - locks.b = &b; - thread_create ("medium", PRI_DEFAULT + 1, medium_thread_func, &locks); - thread_yield (); - msg ("Low thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 1, thread_get_priority ()); - - thread_create ("high", PRI_DEFAULT + 2, high_thread_func, &b); - thread_yield (); - msg ("Low thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 2, thread_get_priority ()); - - lock_release (&a); - thread_yield (); - msg ("Medium thread should just have finished."); - msg ("Low thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT, thread_get_priority ()); -} - -static void -medium_thread_func (void *locks_) -{ - struct locks *locks = locks_; - - lock_acquire (locks->b); - lock_acquire (locks->a); - - msg ("Medium thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 2, thread_get_priority ()); - msg ("Medium thread got the lock."); - - lock_release (locks->a); - thread_yield (); - - lock_release (locks->b); - thread_yield (); - - msg ("High thread should have just finished."); - msg ("Middle thread finished."); -} - -static void -high_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("High thread got the lock."); - lock_release (lock); - msg ("High thread finished."); -} diff --git a/src/tests/threads/priority-donate-nest.ck b/src/tests/threads/priority-donate-nest.ck deleted file mode 100644 index 923460ed14a7d20ab84ffa2fdcd60bda110e7cc4..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-nest.ck +++ /dev/null @@ -1,19 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-donate-nest) begin -(priority-donate-nest) Low thread should have priority 32. Actual priority: 32. -(priority-donate-nest) Low thread should have priority 33. Actual priority: 33. -(priority-donate-nest) Medium thread should have priority 33. Actual priority: 33. -(priority-donate-nest) Medium thread got the lock. -(priority-donate-nest) High thread got the lock. -(priority-donate-nest) High thread finished. -(priority-donate-nest) High thread should have just finished. -(priority-donate-nest) Middle thread finished. -(priority-donate-nest) Medium thread should just have finished. -(priority-donate-nest) Low thread should have priority 31. Actual priority: 31. -(priority-donate-nest) end -EOF -pass; diff --git a/src/tests/threads/priority-donate-one.c b/src/tests/threads/priority-donate-one.c deleted file mode 100644 index 3189f3a0b94a030290b286ea4a78623ddd5ea2e3..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-one.c +++ /dev/null @@ -1,65 +0,0 @@ -/* The main thread acquires a lock. Then it creates two - higher-priority threads that block acquiring the lock, causing - them to donate their priorities to the main thread. When the - main thread releases the lock, the other threads should - acquire it in priority order. - - Based on a test originally submitted for Stanford's CS 140 in - winter 1999 by Matt Franklin <startled@leland.stanford.edu>, - Greg Hutchins <gmh@leland.stanford.edu>, Yu Ping Hu - <yph@cs.stanford.edu>. Modified by arens. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -static thread_func acquire1_thread_func; -static thread_func acquire2_thread_func; - -void -test_priority_donate_one (void) -{ - struct lock lock; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - lock_init (&lock); - lock_acquire (&lock); - thread_create ("acquire1", PRI_DEFAULT + 1, acquire1_thread_func, &lock); - msg ("This thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 1, thread_get_priority ()); - thread_create ("acquire2", PRI_DEFAULT + 2, acquire2_thread_func, &lock); - msg ("This thread should have priority %d. Actual priority: %d.", - PRI_DEFAULT + 2, thread_get_priority ()); - lock_release (&lock); - msg ("acquire2, acquire1 must already have finished, in that order."); - msg ("This should be the last line before finishing this test."); -} - -static void -acquire1_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("acquire1: got the lock"); - lock_release (lock); - msg ("acquire1: done"); -} - -static void -acquire2_thread_func (void *lock_) -{ - struct lock *lock = lock_; - - lock_acquire (lock); - msg ("acquire2: got the lock"); - lock_release (lock); - msg ("acquire2: done"); -} diff --git a/src/tests/threads/priority-donate-one.ck b/src/tests/threads/priority-donate-one.ck deleted file mode 100644 index b7c8e6fe7f599bad767af5225748fd9baf7aca00..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-one.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-donate-one) begin -(priority-donate-one) This thread should have priority 32. Actual priority: 32. -(priority-donate-one) This thread should have priority 33. Actual priority: 33. -(priority-donate-one) acquire2: got the lock -(priority-donate-one) acquire2: done -(priority-donate-one) acquire1: got the lock -(priority-donate-one) acquire1: done -(priority-donate-one) acquire2, acquire1 must already have finished, in that order. -(priority-donate-one) This should be the last line before finishing this test. -(priority-donate-one) end -EOF -pass; diff --git a/src/tests/threads/priority-donate-sema.c b/src/tests/threads/priority-donate-sema.c deleted file mode 100644 index b33cb721ed77daa5c88df8f8995d22044a1a8f41..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-sema.c +++ /dev/null @@ -1,82 +0,0 @@ -/* Low priority thread L acquires a lock, then blocks downing a - semaphore. Medium priority thread M then blocks waiting on - the same semaphore. Next, high priority thread H attempts to - acquire the lock, donating its priority to L. - - Next, the main thread ups the semaphore, waking up L. L - releases the lock, which wakes up H. H "up"s the semaphore, - waking up M. H terminates, then M, then L, and finally the - main thread. - - Written by Godmar Back <gback@cs.vt.edu>. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -struct lock_and_sema - { - struct lock lock; - struct semaphore sema; - }; - -static thread_func l_thread_func; -static thread_func m_thread_func; -static thread_func h_thread_func; - -void -test_priority_donate_sema (void) -{ - struct lock_and_sema ls; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - lock_init (&ls.lock); - sema_init (&ls.sema, 0); - thread_create ("low", PRI_DEFAULT + 1, l_thread_func, &ls); - thread_create ("med", PRI_DEFAULT + 3, m_thread_func, &ls); - thread_create ("high", PRI_DEFAULT + 5, h_thread_func, &ls); - sema_up (&ls.sema); - msg ("Main thread finished."); -} - -static void -l_thread_func (void *ls_) -{ - struct lock_and_sema *ls = ls_; - - lock_acquire (&ls->lock); - msg ("Thread L acquired lock."); - sema_down (&ls->sema); - msg ("Thread L downed semaphore."); - lock_release (&ls->lock); - msg ("Thread L finished."); -} - -static void -m_thread_func (void *ls_) -{ - struct lock_and_sema *ls = ls_; - - sema_down (&ls->sema); - msg ("Thread M finished."); -} - -static void -h_thread_func (void *ls_) -{ - struct lock_and_sema *ls = ls_; - - lock_acquire (&ls->lock); - msg ("Thread H acquired lock."); - - sema_up (&ls->sema); - lock_release (&ls->lock); - msg ("Thread H finished."); -} diff --git a/src/tests/threads/priority-donate-sema.ck b/src/tests/threads/priority-donate-sema.ck deleted file mode 100644 index 92b8d07d7b4fdfa38defe8790873711ffa4b4a04..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-donate-sema.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-donate-sema) begin -(priority-donate-sema) Thread L acquired lock. -(priority-donate-sema) Thread L downed semaphore. -(priority-donate-sema) Thread H acquired lock. -(priority-donate-sema) Thread H finished. -(priority-donate-sema) Thread M finished. -(priority-donate-sema) Thread L finished. -(priority-donate-sema) Main thread finished. -(priority-donate-sema) end -EOF -pass; diff --git a/src/tests/threads/priority-fifo.c b/src/tests/threads/priority-fifo.c deleted file mode 100644 index 3af98a30ac217e7e7978c87ce1327771c42b10b7..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-fifo.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Creates several threads all at the same priority and ensures - that they consistently run in the same round-robin order. - - Based on a test originally submitted for Stanford's CS 140 in - winter 1999 by by Matt Franklin - <startled@leland.stanford.edu>, Greg Hutchins - <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>. - Modified by arens. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "devices/timer.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" - -struct simple_thread_data - { - int id; /* Sleeper ID. */ - int iterations; /* Iterations so far. */ - struct lock *lock; /* Lock on output. */ - int **op; /* Output buffer position. */ - }; - -#define THREAD_CNT 16 -#define ITER_CNT 16 - -static thread_func simple_thread_func; - -void -test_priority_fifo (void) -{ - struct simple_thread_data data[THREAD_CNT]; - struct lock lock; - int *output, *op; - int i, cnt; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - msg ("%d threads will iterate %d times in the same order each time.", - THREAD_CNT, ITER_CNT); - msg ("If the order varies then there is a bug."); - - output = op = malloc (sizeof *output * THREAD_CNT * ITER_CNT * 2); - ASSERT (output != NULL); - lock_init (&lock); - - thread_set_priority (PRI_DEFAULT + 2); - for (i = 0; i < THREAD_CNT; i++) - { - char name[16]; - struct simple_thread_data *d = data + i; - snprintf (name, sizeof name, "%d", i); - d->id = i; - d->iterations = 0; - d->lock = &lock; - d->op = &op; - thread_create (name, PRI_DEFAULT + 1, simple_thread_func, d); - } - - thread_set_priority (PRI_DEFAULT); - /* All the other threads now run to termination here. */ - ASSERT (lock.holder == NULL); - - cnt = 0; - for (; output < op; output++) - { - struct simple_thread_data *d; - - ASSERT (*output >= 0 && *output < THREAD_CNT); - d = data + *output; - if (cnt % THREAD_CNT == 0) - printf ("(priority-fifo) iteration:"); - printf (" %d", d->id); - if (++cnt % THREAD_CNT == 0) - printf ("\n"); - d->iterations++; - } -} - -static void -simple_thread_func (void *data_) -{ - struct simple_thread_data *data = data_; - int i; - - for (i = 0; i < ITER_CNT; i++) - { - lock_acquire (data->lock); - *(*data->op)++ = data->id; - lock_release (data->lock); - thread_yield (); - } -} diff --git a/src/tests/threads/priority-fifo.ck b/src/tests/threads/priority-fifo.ck deleted file mode 100644 index 11f1dd3e31b305be45b61643a42a0d742abd688a..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-fifo.ck +++ /dev/null @@ -1,63 +0,0 @@ -# -*- perl -*- - -# The expected output looks like this: -# -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# (priority-fifo) iteration: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -# -# A different permutation of 0...15 is acceptable, but every line must -# be in the same order. - -use strict; -use warnings; -use tests::tests; - -our ($test); -my (@output) = read_text_file ("$test.output"); - -common_checks ("run", @output); - -my ($thread_cnt) = 16; -my ($iter_cnt) = 16; -my (@order); -my (@t) = (-1) x $thread_cnt; - -my (@iterations) = grep (/iteration:/, @output); -fail "No iterations found in output.\n" if !@iterations; - -my (@numbering) = $iterations[0] =~ /(\d+)/g; -fail "First iteration does not list exactly $thread_cnt threads.\n" - if @numbering != $thread_cnt; - -my (@sorted_numbering) = sort { $a <=> $b } @numbering; -for my $i (0...$#sorted_numbering) { - if ($sorted_numbering[$i] != $i) { - fail "First iteration does not list all threads " - . "0...$#sorted_numbering\n"; - } -} - -for my $i (1...$#iterations) { - if ($iterations[$i] ne $iterations[0]) { - fail "Iteration $i differs from iteration 0\n"; - } -} - -fail "$iter_cnt iterations expected but " . scalar (@iterations) . " found\n" - if $iter_cnt != @iterations; - -pass; diff --git a/src/tests/threads/priority-preempt.c b/src/tests/threads/priority-preempt.c deleted file mode 100644 index 3c3aacbd0336f41fb69d386c9576cb18f07c00ae..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-preempt.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Ensures that a high-priority thread really preempts. - - Based on a test originally submitted for Stanford's CS 140 in - winter 1999 by by Matt Franklin - <startled@leland.stanford.edu>, Greg Hutchins - <gmh@leland.stanford.edu>, Yu Ping Hu <yph@cs.stanford.edu>. - Modified by arens. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/synch.h" -#include "threads/thread.h" - -static thread_func simple_thread_func; - -void -test_priority_preempt (void) -{ - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - /* Make sure our priority is the default. */ - ASSERT (thread_get_priority () == PRI_DEFAULT); - - thread_create ("high-priority", PRI_DEFAULT + 1, simple_thread_func, NULL); - msg ("The high-priority thread should have already completed."); -} - -static void -simple_thread_func (void *aux UNUSED) -{ - int i; - - for (i = 0; i < 5; i++) - { - msg ("Thread %s iteration %d", thread_name (), i); - thread_yield (); - } - msg ("Thread %s done!", thread_name ()); -} diff --git a/src/tests/threads/priority-preempt.ck b/src/tests/threads/priority-preempt.ck deleted file mode 100644 index 43a26ee66c3ac2e2277ae7faa1053b72e7ace63e..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-preempt.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-preempt) begin -(priority-preempt) Thread high-priority iteration 0 -(priority-preempt) Thread high-priority iteration 1 -(priority-preempt) Thread high-priority iteration 2 -(priority-preempt) Thread high-priority iteration 3 -(priority-preempt) Thread high-priority iteration 4 -(priority-preempt) Thread high-priority done! -(priority-preempt) The high-priority thread should have already completed. -(priority-preempt) end -EOF -pass; diff --git a/src/tests/threads/priority-sema.c b/src/tests/threads/priority-sema.c deleted file mode 100644 index 2834a880be25c92aa9989c6e3e828c13fb0fc107..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-sema.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Tests that the highest-priority thread waiting on a semaphore - is the first to wake up. */ - -#include <stdio.h> -#include "tests/threads/tests.h" -#include "threads/init.h" -#include "threads/malloc.h" -#include "threads/synch.h" -#include "threads/thread.h" -#include "devices/timer.h" - -static thread_func priority_sema_thread; -static struct semaphore sema; - -void -test_priority_sema (void) -{ - int i; - - /* This test does not work with the MLFQS. */ - ASSERT (!thread_mlfqs); - - sema_init (&sema, 0); - thread_set_priority (PRI_MIN); - for (i = 0; i < 10; i++) - { - int priority = PRI_DEFAULT - (i + 3) % 10 - 1; - char name[16]; - snprintf (name, sizeof name, "priority %d", priority); - thread_create (name, priority, priority_sema_thread, NULL); - } - - for (i = 0; i < 10; i++) - { - sema_up (&sema); - msg ("Back in main thread."); - } -} - -static void -priority_sema_thread (void *aux UNUSED) -{ - sema_down (&sema); - msg ("Thread %s woke up.", thread_name ()); -} diff --git a/src/tests/threads/priority-sema.ck b/src/tests/threads/priority-sema.ck deleted file mode 100644 index 559988d7346abc29958909573a577611323f434f..0000000000000000000000000000000000000000 --- a/src/tests/threads/priority-sema.ck +++ /dev/null @@ -1,29 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(priority-sema) begin -(priority-sema) Thread priority 30 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 29 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 28 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 27 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 26 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 25 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 24 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 23 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 22 woke up. -(priority-sema) Back in main thread. -(priority-sema) Thread priority 21 woke up. -(priority-sema) Back in main thread. -(priority-sema) end -EOF -pass; diff --git a/src/tests/threads/tests.c b/src/tests/threads/tests.c deleted file mode 100644 index af15aee1e4a0c4911acb750ddd586659d402285b..0000000000000000000000000000000000000000 --- a/src/tests/threads/tests.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "tests/threads/tests.h" -#include <debug.h> -#include <string.h> -#include <stdio.h> - -struct test - { - const char *name; - test_func *function; - }; - -static const struct test tests[] = - { - {"alarm-single", test_alarm_single}, - {"alarm-multiple", test_alarm_multiple}, - {"alarm-simultaneous", test_alarm_simultaneous}, - {"alarm-priority", test_alarm_priority}, - {"alarm-zero", test_alarm_zero}, - {"alarm-negative", test_alarm_negative}, - {"priority-change", test_priority_change}, - {"priority-donate-one", test_priority_donate_one}, - {"priority-donate-multiple", test_priority_donate_multiple}, - {"priority-donate-multiple2", test_priority_donate_multiple2}, - {"priority-donate-nest", test_priority_donate_nest}, - {"priority-donate-sema", test_priority_donate_sema}, - {"priority-donate-lower", test_priority_donate_lower}, - {"priority-donate-chain", test_priority_donate_chain}, - {"priority-fifo", test_priority_fifo}, - {"priority-preempt", test_priority_preempt}, - {"priority-sema", test_priority_sema}, - {"priority-condvar", test_priority_condvar}, - {"mlfqs-load-1", test_mlfqs_load_1}, - {"mlfqs-load-60", test_mlfqs_load_60}, - {"mlfqs-load-avg", test_mlfqs_load_avg}, - {"mlfqs-recent-1", test_mlfqs_recent_1}, - {"mlfqs-fair-2", test_mlfqs_fair_2}, - {"mlfqs-fair-20", test_mlfqs_fair_20}, - {"mlfqs-nice-2", test_mlfqs_nice_2}, - {"mlfqs-nice-10", test_mlfqs_nice_10}, - {"mlfqs-block", test_mlfqs_block}, - }; - -static const char *test_name; - -/* Runs the test named NAME. */ -void -run_test (const char *name) -{ - const struct test *t; - - for (t = tests; t < tests + sizeof tests / sizeof *tests; t++) - if (!strcmp (name, t->name)) - { - test_name = name; - msg ("begin"); - t->function (); - msg ("end"); - return; - } - PANIC ("no test named \"%s\"", name); -} - -/* Prints FORMAT as if with printf(), - prefixing the output by the name of the test - and following it with a new-line character. */ -void -msg (const char *format, ...) -{ - va_list args; - - printf ("(%s) ", test_name); - va_start (args, format); - vprintf (format, args); - va_end (args); - putchar ('\n'); -} - -/* Prints failure message FORMAT as if with printf(), - prefixing the output by the name of the test and FAIL: - and following it with a new-line character, - and then panics the kernel. */ -void -fail (const char *format, ...) -{ - va_list args; - - printf ("(%s) FAIL: ", test_name); - va_start (args, format); - vprintf (format, args); - va_end (args); - putchar ('\n'); - - PANIC ("test failed"); -} - -/* Prints a message indicating the current test passed. */ -void -pass (void) -{ - printf ("(%s) PASS\n", test_name); -} - diff --git a/src/tests/threads/tests.h b/src/tests/threads/tests.h deleted file mode 100644 index cd9d4895409fbb0f5f36533c4a5e8af8c3fbafad..0000000000000000000000000000000000000000 --- a/src/tests/threads/tests.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef TESTS_THREADS_TESTS_H -#define TESTS_THREADS_TESTS_H - -void run_test (const char *); - -typedef void test_func (void); - -extern test_func test_alarm_single; -extern test_func test_alarm_multiple; -extern test_func test_alarm_simultaneous; -extern test_func test_alarm_priority; -extern test_func test_alarm_zero; -extern test_func test_alarm_negative; -extern test_func test_priority_change; -extern test_func test_priority_donate_one; -extern test_func test_priority_donate_multiple; -extern test_func test_priority_donate_multiple2; -extern test_func test_priority_donate_sema; -extern test_func test_priority_donate_nest; -extern test_func test_priority_donate_lower; -extern test_func test_priority_donate_chain; -extern test_func test_priority_fifo; -extern test_func test_priority_preempt; -extern test_func test_priority_sema; -extern test_func test_priority_condvar; -extern test_func test_mlfqs_load_1; -extern test_func test_mlfqs_load_60; -extern test_func test_mlfqs_load_avg; -extern test_func test_mlfqs_recent_1; -extern test_func test_mlfqs_fair_2; -extern test_func test_mlfqs_fair_20; -extern test_func test_mlfqs_nice_2; -extern test_func test_mlfqs_nice_10; -extern test_func test_mlfqs_block; - -void msg (const char *, ...); -void fail (const char *, ...); -void pass (void); - -#endif /* tests/threads/tests.h */ - diff --git a/src/tests/userprog/Grading b/src/tests/userprog/Grading deleted file mode 100644 index f70dc99acef673fc5a6408c0f7498dc7b027468f..0000000000000000000000000000000000000000 --- a/src/tests/userprog/Grading +++ /dev/null @@ -1,11 +0,0 @@ -# Percentage of the testing point total designated for each set of -# tests. - -# This project is primarily about implementing system calls. -# If you do so properly, the base file system functionality -# should come "for free". Thus, the points emphasis below. - -35% tests/userprog/Rubric.functionality -25% tests/userprog/Rubric.robustness -10% tests/userprog/no-vm/Rubric -30% tests/filesys/base/Rubric diff --git a/src/tests/userprog/Make.tests b/src/tests/userprog/Make.tests deleted file mode 100644 index caadd90edbef093b184e682841f182b335eef99e..0000000000000000000000000000000000000000 --- a/src/tests/userprog/Make.tests +++ /dev/null @@ -1,133 +0,0 @@ -# -*- makefile -*- - -tests/%.output: FILESYSSOURCE = --filesys-size=2 -tests/%.output: PUTFILES = $(filter-out kernel.bin loader.bin, $^) - -tests/userprog_TESTS = $(addprefix tests/userprog/,args-none \ -args-single args-multiple args-many args-dbl-space sc-bad-sp \ -sc-bad-arg sc-boundary sc-boundary-2 halt exit create-normal \ -create-empty create-null create-bad-ptr create-long create-exists \ -create-bound open-normal open-missing open-boundary open-empty \ -open-null open-bad-ptr open-twice close-normal close-twice close-stdin \ -close-stdout close-bad-fd read-normal read-bad-ptr read-boundary \ -read-zero read-stdout read-bad-fd write-normal write-bad-ptr \ -write-boundary write-zero write-stdin write-bad-fd exec-once exec-arg \ -exec-multiple exec-missing exec-bad-ptr wait-simple wait-twice \ -wait-killed wait-bad-pid multi-recurse multi-child-fd rox-simple \ -rox-child rox-multichild bad-read bad-write bad-read2 bad-write2 \ -bad-jump bad-jump2) - -tests/userprog_PROGS = $(tests/userprog_TESTS) $(addprefix \ -tests/userprog/,child-simple child-args child-bad child-close child-rox) - -tests/userprog/args-none_SRC = tests/userprog/args.c -tests/userprog/args-single_SRC = tests/userprog/args.c -tests/userprog/args-multiple_SRC = tests/userprog/args.c -tests/userprog/args-many_SRC = tests/userprog/args.c -tests/userprog/args-dbl-space_SRC = tests/userprog/args.c -tests/userprog/sc-bad-sp_SRC = tests/userprog/sc-bad-sp.c tests/main.c -tests/userprog/sc-bad-arg_SRC = tests/userprog/sc-bad-arg.c tests/main.c -tests/userprog/bad-read_SRC = tests/userprog/bad-read.c tests/main.c -tests/userprog/bad-write_SRC = tests/userprog/bad-write.c tests/main.c -tests/userprog/bad-jump_SRC = tests/userprog/bad-jump.c tests/main.c -tests/userprog/bad-read2_SRC = tests/userprog/bad-read2.c tests/main.c -tests/userprog/bad-write2_SRC = tests/userprog/bad-write2.c tests/main.c -tests/userprog/bad-jump2_SRC = tests/userprog/bad-jump2.c tests/main.c -tests/userprog/sc-boundary_SRC = tests/userprog/sc-boundary.c \ -tests/userprog/boundary.c tests/main.c -tests/userprog/sc-boundary-2_SRC = tests/userprog/sc-boundary-2.c \ -tests/userprog/boundary.c tests/main.c -tests/userprog/halt_SRC = tests/userprog/halt.c tests/main.c -tests/userprog/exit_SRC = tests/userprog/exit.c tests/main.c -tests/userprog/create-normal_SRC = tests/userprog/create-normal.c tests/main.c -tests/userprog/create-empty_SRC = tests/userprog/create-empty.c tests/main.c -tests/userprog/create-null_SRC = tests/userprog/create-null.c tests/main.c -tests/userprog/create-bad-ptr_SRC = tests/userprog/create-bad-ptr.c \ -tests/main.c -tests/userprog/create-long_SRC = tests/userprog/create-long.c tests/main.c -tests/userprog/create-exists_SRC = tests/userprog/create-exists.c tests/main.c -tests/userprog/create-bound_SRC = tests/userprog/create-bound.c \ -tests/userprog/boundary.c tests/main.c -tests/userprog/open-normal_SRC = tests/userprog/open-normal.c tests/main.c -tests/userprog/open-missing_SRC = tests/userprog/open-missing.c tests/main.c -tests/userprog/open-boundary_SRC = tests/userprog/open-boundary.c \ -tests/userprog/boundary.c tests/main.c -tests/userprog/open-empty_SRC = tests/userprog/open-empty.c tests/main.c -tests/userprog/open-null_SRC = tests/userprog/open-null.c tests/main.c -tests/userprog/open-bad-ptr_SRC = tests/userprog/open-bad-ptr.c tests/main.c -tests/userprog/open-twice_SRC = tests/userprog/open-twice.c tests/main.c -tests/userprog/close-normal_SRC = tests/userprog/close-normal.c tests/main.c -tests/userprog/close-twice_SRC = tests/userprog/close-twice.c tests/main.c -tests/userprog/close-stdin_SRC = tests/userprog/close-stdin.c tests/main.c -tests/userprog/close-stdout_SRC = tests/userprog/close-stdout.c tests/main.c -tests/userprog/close-bad-fd_SRC = tests/userprog/close-bad-fd.c tests/main.c -tests/userprog/read-normal_SRC = tests/userprog/read-normal.c tests/main.c -tests/userprog/read-bad-ptr_SRC = tests/userprog/read-bad-ptr.c tests/main.c -tests/userprog/read-boundary_SRC = tests/userprog/read-boundary.c \ -tests/userprog/boundary.c tests/main.c -tests/userprog/read-zero_SRC = tests/userprog/read-zero.c tests/main.c -tests/userprog/read-stdout_SRC = tests/userprog/read-stdout.c tests/main.c -tests/userprog/read-bad-fd_SRC = tests/userprog/read-bad-fd.c tests/main.c -tests/userprog/write-normal_SRC = tests/userprog/write-normal.c tests/main.c -tests/userprog/write-bad-ptr_SRC = tests/userprog/write-bad-ptr.c tests/main.c -tests/userprog/write-boundary_SRC = tests/userprog/write-boundary.c \ -tests/userprog/boundary.c tests/main.c -tests/userprog/write-zero_SRC = tests/userprog/write-zero.c tests/main.c -tests/userprog/write-stdin_SRC = tests/userprog/write-stdin.c tests/main.c -tests/userprog/write-bad-fd_SRC = tests/userprog/write-bad-fd.c tests/main.c -tests/userprog/exec-once_SRC = tests/userprog/exec-once.c tests/main.c -tests/userprog/exec-arg_SRC = tests/userprog/exec-arg.c tests/main.c -tests/userprog/exec-multiple_SRC = tests/userprog/exec-multiple.c tests/main.c -tests/userprog/exec-missing_SRC = tests/userprog/exec-missing.c tests/main.c -tests/userprog/exec-bad-ptr_SRC = tests/userprog/exec-bad-ptr.c tests/main.c -tests/userprog/wait-simple_SRC = tests/userprog/wait-simple.c tests/main.c -tests/userprog/wait-twice_SRC = tests/userprog/wait-twice.c tests/main.c -tests/userprog/wait-killed_SRC = tests/userprog/wait-killed.c tests/main.c -tests/userprog/wait-bad-pid_SRC = tests/userprog/wait-bad-pid.c tests/main.c -tests/userprog/multi-recurse_SRC = tests/userprog/multi-recurse.c -tests/userprog/multi-child-fd_SRC = tests/userprog/multi-child-fd.c \ -tests/main.c -tests/userprog/rox-simple_SRC = tests/userprog/rox-simple.c tests/main.c -tests/userprog/rox-child_SRC = tests/userprog/rox-child.c tests/main.c -tests/userprog/rox-multichild_SRC = tests/userprog/rox-multichild.c \ -tests/main.c - -tests/userprog/child-simple_SRC = tests/userprog/child-simple.c -tests/userprog/child-args_SRC = tests/userprog/args.c -tests/userprog/child-bad_SRC = tests/userprog/child-bad.c tests/main.c -tests/userprog/child-close_SRC = tests/userprog/child-close.c -tests/userprog/child-rox_SRC = tests/userprog/child-rox.c - -$(foreach prog,$(tests/userprog_PROGS),$(eval $(prog)_SRC += tests/lib.c)) - -tests/userprog/args-single_ARGS = onearg -tests/userprog/args-multiple_ARGS = some arguments for you! -tests/userprog/args-many_ARGS = a b c d e f g h i j k l m n o p q r s t u v -tests/userprog/args-dbl-space_ARGS = two spaces! -tests/userprog/multi-recurse_ARGS = 15 - -tests/userprog/open-normal_PUTFILES += tests/userprog/sample.txt -tests/userprog/open-boundary_PUTFILES += tests/userprog/sample.txt -tests/userprog/open-twice_PUTFILES += tests/userprog/sample.txt -tests/userprog/close-normal_PUTFILES += tests/userprog/sample.txt -tests/userprog/close-twice_PUTFILES += tests/userprog/sample.txt -tests/userprog/read-normal_PUTFILES += tests/userprog/sample.txt -tests/userprog/read-bad-ptr_PUTFILES += tests/userprog/sample.txt -tests/userprog/read-boundary_PUTFILES += tests/userprog/sample.txt -tests/userprog/read-zero_PUTFILES += tests/userprog/sample.txt -tests/userprog/write-normal_PUTFILES += tests/userprog/sample.txt -tests/userprog/write-bad-ptr_PUTFILES += tests/userprog/sample.txt -tests/userprog/write-boundary_PUTFILES += tests/userprog/sample.txt -tests/userprog/write-zero_PUTFILES += tests/userprog/sample.txt -tests/userprog/multi-child-fd_PUTFILES += tests/userprog/sample.txt - -tests/userprog/exec-once_PUTFILES += tests/userprog/child-simple -tests/userprog/exec-multiple_PUTFILES += tests/userprog/child-simple -tests/userprog/wait-simple_PUTFILES += tests/userprog/child-simple -tests/userprog/wait-twice_PUTFILES += tests/userprog/child-simple - -tests/userprog/exec-arg_PUTFILES += tests/userprog/child-args -tests/userprog/multi-child-fd_PUTFILES += tests/userprog/child-close -tests/userprog/wait-killed_PUTFILES += tests/userprog/child-bad -tests/userprog/rox-child_PUTFILES += tests/userprog/child-rox -tests/userprog/rox-multichild_PUTFILES += tests/userprog/child-rox diff --git a/src/tests/userprog/Rubric.functionality b/src/tests/userprog/Rubric.functionality deleted file mode 100644 index ea76c44d6561e43e3598acfde440150ffb600fd7..0000000000000000000000000000000000000000 --- a/src/tests/userprog/Rubric.functionality +++ /dev/null @@ -1,52 +0,0 @@ -Functionality of system calls: -- Test argument passing on Pintos command line. -3 args-none -3 args-single -3 args-multiple -3 args-many -3 args-dbl-space - -- Test "create" system call. -3 create-empty -3 create-long -3 create-normal -3 create-exists - -- Test "open" system call. -3 open-missing -3 open-normal -3 open-twice - -- Test "read" system call. -3 read-normal -3 read-zero - -- Test "write" system call. -3 write-normal -3 write-zero - -- Test "close" system call. -3 close-normal - -- Test "exec" system call. -5 exec-once -5 exec-multiple -5 exec-arg - -- Test "wait" system call. -5 wait-simple -5 wait-twice - -- Test "exit" system call. -5 exit - -- Test "halt" system call. -3 halt - -- Test recursive execution of user programs. -15 multi-recurse - -- Test read-only executable feature. -3 rox-simple -3 rox-child -3 rox-multichild diff --git a/src/tests/userprog/Rubric.robustness b/src/tests/userprog/Rubric.robustness deleted file mode 100644 index b7d1035a745bb18b140e5a6aa6c9e32ba63acac5..0000000000000000000000000000000000000000 --- a/src/tests/userprog/Rubric.robustness +++ /dev/null @@ -1,48 +0,0 @@ -Robustness of system calls: -- Test robustness of file descriptor handling. -2 close-stdin -2 close-stdout -2 close-bad-fd -2 close-twice -2 read-bad-fd -2 read-stdout -2 write-bad-fd -2 write-stdin -2 multi-child-fd - -- Test robustness of pointer handling. -3 create-bad-ptr -3 exec-bad-ptr -3 open-bad-ptr -3 read-bad-ptr -3 write-bad-ptr - -- Test robustness of buffer copying across page boundaries. -3 create-bound -3 open-boundary -3 read-boundary -3 write-boundary - -- Test handling of null pointer and empty strings. -2 create-null -2 open-null -2 open-empty - -- Test robustness of system call implementation. -3 sc-bad-arg -3 sc-bad-sp -5 sc-boundary -5 sc-boundary-2 - -- Test robustness of "exec" and "wait" system calls. -5 exec-missing -5 wait-bad-pid -5 wait-killed - -- Test robustness of exception handling. -1 bad-read -1 bad-write -1 bad-jump -1 bad-read2 -1 bad-write2 -1 bad-jump2 diff --git a/src/tests/userprog/args-dbl-space.ck b/src/tests/userprog/args-dbl-space.ck deleted file mode 100644 index dfbcf4b878dc452455038e71a0406c8eac570a16..0000000000000000000000000000000000000000 --- a/src/tests/userprog/args-dbl-space.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(args) begin -(args) argc = 3 -(args) argv[0] = 'args-dbl-space' -(args) argv[1] = 'two' -(args) argv[2] = 'spaces!' -(args) argv[3] = null -(args) end -args-dbl-space: exit(0) -EOF -pass; diff --git a/src/tests/userprog/args-many.ck b/src/tests/userprog/args-many.ck deleted file mode 100644 index 214574a828a4c67a17f7d7b7996866325d08888c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/args-many.ck +++ /dev/null @@ -1,35 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(args) begin -(args) argc = 23 -(args) argv[0] = 'args-many' -(args) argv[1] = 'a' -(args) argv[2] = 'b' -(args) argv[3] = 'c' -(args) argv[4] = 'd' -(args) argv[5] = 'e' -(args) argv[6] = 'f' -(args) argv[7] = 'g' -(args) argv[8] = 'h' -(args) argv[9] = 'i' -(args) argv[10] = 'j' -(args) argv[11] = 'k' -(args) argv[12] = 'l' -(args) argv[13] = 'm' -(args) argv[14] = 'n' -(args) argv[15] = 'o' -(args) argv[16] = 'p' -(args) argv[17] = 'q' -(args) argv[18] = 'r' -(args) argv[19] = 's' -(args) argv[20] = 't' -(args) argv[21] = 'u' -(args) argv[22] = 'v' -(args) argv[23] = null -(args) end -args-many: exit(0) -EOF -pass; diff --git a/src/tests/userprog/args-multiple.ck b/src/tests/userprog/args-multiple.ck deleted file mode 100644 index 227e6cc97ffc8c0230cd748bd20fcc1a612e411a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/args-multiple.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(args) begin -(args) argc = 5 -(args) argv[0] = 'args-multiple' -(args) argv[1] = 'some' -(args) argv[2] = 'arguments' -(args) argv[3] = 'for' -(args) argv[4] = 'you!' -(args) argv[5] = null -(args) end -args-multiple: exit(0) -EOF -pass; diff --git a/src/tests/userprog/args-none.ck b/src/tests/userprog/args-none.ck deleted file mode 100644 index 146318e0c330cf7e65cb1dede2462251b60c8d37..0000000000000000000000000000000000000000 --- a/src/tests/userprog/args-none.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(args) begin -(args) argc = 1 -(args) argv[0] = 'args-none' -(args) argv[1] = null -(args) end -args-none: exit(0) -EOF -pass; diff --git a/src/tests/userprog/args-single.ck b/src/tests/userprog/args-single.ck deleted file mode 100644 index 24582b4da4b7e8d8ca00968cbe4986c4fe21a0ad..0000000000000000000000000000000000000000 --- a/src/tests/userprog/args-single.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(args) begin -(args) argc = 2 -(args) argv[0] = 'args-single' -(args) argv[1] = 'onearg' -(args) argv[2] = null -(args) end -args-single: exit(0) -EOF -pass; diff --git a/src/tests/userprog/args.c b/src/tests/userprog/args.c deleted file mode 100644 index 20eda447c4998883f693b011f930cc05ca8950e0..0000000000000000000000000000000000000000 --- a/src/tests/userprog/args.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Prints the command-line arguments. - This program is used for all of the args-* tests. Grading is - done differently for each of the args-* tests based on the - output. */ - -#include "tests/lib.h" - -int -main (int argc, char *argv[]) -{ - int i; - - test_name = "args"; - - msg ("begin"); - msg ("argc = %d", argc); - for (i = 0; i <= argc; i++) - if (argv[i] != NULL) - msg ("argv[%d] = '%s'", i, argv[i]); - else - msg ("argv[%d] = null", i); - msg ("end"); - - return 0; -} diff --git a/src/tests/userprog/bad-jump.c b/src/tests/userprog/bad-jump.c deleted file mode 100644 index 51b7c9f57ea6a15cfe60a254a7fb3cd04fae87ea..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-jump.c +++ /dev/null @@ -1,13 +0,0 @@ -/* This program attempts to execute code at address 0, which is not mapped. - This should terminate the process with a -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("Congratulations - you have successfully called NULL: %d", - ((int (*)(void))NULL)()); - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/bad-jump.ck b/src/tests/userprog/bad-jump.ck deleted file mode 100644 index e1c178b4427f6aa7bae76e9bd41ef74c78248d36..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-jump.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(bad-jump) begin -bad-jump: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/bad-jump2.c b/src/tests/userprog/bad-jump2.c deleted file mode 100644 index dc7c2a7c06b7c38349b11b1df81a0b0e07976091..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-jump2.c +++ /dev/null @@ -1,13 +0,0 @@ -/* This program attempts to execute code at a kernel virtual address. - This should terminate the process with a -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("Congratulations - you have successfully called kernel code: %d", - ((int (*)(void))0xC0000000)()); - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/bad-jump2.ck b/src/tests/userprog/bad-jump2.ck deleted file mode 100644 index 35f0f9790ba4f64bc1200411a8f660568f8d559f..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-jump2.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(bad-jump2) begin -bad-jump2: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/bad-read.c b/src/tests/userprog/bad-read.c deleted file mode 100644 index 904c278a0e307d1ebc22fdbdb77da74e64849818..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-read.c +++ /dev/null @@ -1,13 +0,0 @@ -/* This program attempts to read memory at an address that is not mapped. - This should terminate the process with a -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("Congratulations - you have successfully dereferenced NULL: %d", - *(int *)NULL); - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/bad-read.ck b/src/tests/userprog/bad-read.ck deleted file mode 100644 index 4d4d9266646fe2b275a5ded0aac32e8695fa3a56..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-read.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(bad-read) begin -bad-read: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/bad-read2.c b/src/tests/userprog/bad-read2.c deleted file mode 100644 index a2fc23725cd6da1dda4d35be78f411966150150a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-read2.c +++ /dev/null @@ -1,13 +0,0 @@ -/* This program attempts to read kernel memory. - This should terminate the process with a -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("Congratulations - you have successfully read kernel memory: %d", - *(int *)0xC0000000); - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/bad-read2.ck b/src/tests/userprog/bad-read2.ck deleted file mode 100644 index fa27c7dc70ffd80dab51e1258be5ecd6eee86c9a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-read2.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(bad-read2) begin -bad-read2: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/bad-write.c b/src/tests/userprog/bad-write.c deleted file mode 100644 index 000c26b315a88179cca360dc75b55eeffd91d01d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-write.c +++ /dev/null @@ -1,12 +0,0 @@ -/* This program attempts to write to memory at an address that is not mapped. - This should terminate the process with a -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - *(int *)NULL = 42; - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/bad-write.ck b/src/tests/userprog/bad-write.ck deleted file mode 100644 index d213b49a91afcd4995de560404e41be5557e9a63..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-write.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(bad-write) begin -bad-write: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/bad-write2.c b/src/tests/userprog/bad-write2.c deleted file mode 100644 index 753da1e97c87aa5e8da052b5e9faa03ba44547c0..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-write2.c +++ /dev/null @@ -1,12 +0,0 @@ -/* This program attempts to write to kernel memory. - This should terminate the process with a -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - *(int *)0xC0000000 = 42; - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/bad-write2.ck b/src/tests/userprog/bad-write2.ck deleted file mode 100644 index c6a34200ca6658368300c054b8faae57699c304f..0000000000000000000000000000000000000000 --- a/src/tests/userprog/bad-write2.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(bad-write2) begin -bad-write2: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/boundary.c b/src/tests/userprog/boundary.c deleted file mode 100644 index 59907ec935d36d8e498766730138741f0143e89d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/boundary.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Utility function for tests that try to break system calls by - passing them data that crosses from one virtual page to - another. */ - -#include <inttypes.h> -#include <round.h> -#include <string.h> -#include "tests/userprog/boundary.h" - -static char dst[8192]; - -/* Returns the beginning of a page. There are at least 2048 - modifiable bytes on either side of the pointer returned. */ -void * -get_boundary_area (void) -{ - char *p = (char *) ROUND_UP ((uintptr_t) dst, 4096); - if (p - dst < 2048) - p += 4096; - return p; -} - -/* Returns a copy of SRC split across the boundary between two - pages. */ -char * -copy_string_across_boundary (const char *src) -{ - char *p = get_boundary_area (); - p -= strlen (src) < 4096 ? strlen (src) / 2 : 4096; - strlcpy (p, src, 4096); - return p; -} - diff --git a/src/tests/userprog/boundary.h b/src/tests/userprog/boundary.h deleted file mode 100644 index c8e4b3ba01f23270b7f8afc6804b7e0eb3c964e5..0000000000000000000000000000000000000000 --- a/src/tests/userprog/boundary.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef TESTS_USERPROG_BOUNDARY_H -#define TESTS_USERPROG_BOUNDARY_H - -void *get_boundary_area (void); -char *copy_string_across_boundary (const char *); - -#endif /* tests/userprog/boundary.h */ diff --git a/src/tests/userprog/child-bad.c b/src/tests/userprog/child-bad.c deleted file mode 100644 index 77d7a69d25013ffdd51aaa3290bfd228c9cb74af..0000000000000000000000000000000000000000 --- a/src/tests/userprog/child-bad.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Child process run by wait-killed test. - Sets the stack pointer (%esp) to an invalid value and invokes - a system call, which should then terminate the process with a - -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - asm volatile ("movl $0x20101234, %esp; int $0x30"); - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/child-close.c b/src/tests/userprog/child-close.c deleted file mode 100644 index ac948c8efe6978e98960fceda85218b84a3c3415..0000000000000000000000000000000000000000 --- a/src/tests/userprog/child-close.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Child process run by multi-child-fd test. - - Attempts to close the file descriptor passed as the first - command-line argument. This is invalid, because file - descriptors are not inherited in Pintos. Two results are - allowed: either the system call should return without taking - any action, or the kernel should terminate the process with a - -1 exit code. */ - -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <syscall.h> -#include "tests/lib.h" - -const char *test_name = "child-close"; - -int -main (int argc UNUSED, char *argv[]) -{ - msg ("begin"); - if (!isdigit (*argv[1])) - fail ("bad command-line arguments"); - close (atoi (argv[1])); - msg ("end"); - - return 0; -} diff --git a/src/tests/userprog/child-rox.c b/src/tests/userprog/child-rox.c deleted file mode 100644 index aba808bde2b52dde3b559d31fd3e9e75771140da..0000000000000000000000000000000000000000 --- a/src/tests/userprog/child-rox.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Child process run by rox-child and rox-multichild tests. - Opens and tries to write to its own executable, verifying that - that is disallowed. - Then recursively executes itself to the depth indicated by the - first command-line argument. */ - -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <syscall.h> -#include "tests/lib.h" - -const char *test_name = "child-rox"; - -static void -try_write (void) -{ - int handle; - char buffer[19]; - - quiet = true; - CHECK ((handle = open ("child-rox")) > 1, "open \"child-rox\""); - quiet = false; - - CHECK (write (handle, buffer, sizeof buffer) == 0, - "try to write \"child-rox\""); - - close (handle); -} - -int -main (int argc UNUSED, char *argv[]) -{ - msg ("begin"); - try_write (); - - if (!isdigit (*argv[1])) - fail ("bad command-line arguments"); - if (atoi (argv[1]) > 1) - { - char cmd[128]; - int child; - - snprintf (cmd, sizeof cmd, "child-rox %d", atoi (argv[1]) - 1); - CHECK ((child = exec (cmd)) != -1, "exec \"%s\"", cmd); - quiet = true; - CHECK (wait (child) == 12, "wait for \"child-rox\""); - quiet = false; - } - - try_write (); - msg ("end"); - - return 12; -} diff --git a/src/tests/userprog/child-simple.c b/src/tests/userprog/child-simple.c deleted file mode 100644 index 0d2dacf704f253d352c55288f48156370528c510..0000000000000000000000000000000000000000 --- a/src/tests/userprog/child-simple.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Child process run by exec-multiple, exec-one, wait-simple, and - wait-twice tests. - Just prints a single message and terminates. */ - -#include <stdio.h> -#include "tests/lib.h" - -const char *test_name = "child-simple"; - -int -main (void) -{ - msg ("run"); - return 81; -} diff --git a/src/tests/userprog/close-bad-fd.c b/src/tests/userprog/close-bad-fd.c deleted file mode 100644 index f63bb9abe870769582db3c501dd4c721752221fe..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-bad-fd.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Tries to close an invalid fd, which must either fail silently - or terminate with exit code -1. */ - -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - close (0x20101234); -} diff --git a/src/tests/userprog/close-bad-fd.ck b/src/tests/userprog/close-bad-fd.ck deleted file mode 100644 index 497b17c1156806128b59c8859b37168133210f2f..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-bad-fd.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(close-bad-fd) begin -(close-bad-fd) end -close-bad-fd: exit(0) -EOF -(close-bad-fd) begin -close-bad-fd: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/close-normal.c b/src/tests/userprog/close-normal.c deleted file mode 100644 index 8ce04e39ff6b6067a601cc8af888d14276d9f39a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-normal.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Opens a file and then closes it. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - msg ("close \"sample.txt\""); - close (handle); -} diff --git a/src/tests/userprog/close-normal.ck b/src/tests/userprog/close-normal.ck deleted file mode 100644 index fe4134287aa673826e87cb40807e2ad62d81bd0c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-normal.ck +++ /dev/null @@ -1,12 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(close-normal) begin -(close-normal) open "sample.txt" -(close-normal) close "sample.txt" -(close-normal) end -close-normal: exit(0) -EOF -pass; diff --git a/src/tests/userprog/close-stdin.c b/src/tests/userprog/close-stdin.c deleted file mode 100644 index 9bbf9f2fd282d207973f68c0d2ffe2b4c87757df..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-stdin.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Tries to close the keyboard input stream, which must either - fail silently or terminate with exit code -1. */ - -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - close (0); -} diff --git a/src/tests/userprog/close-stdin.ck b/src/tests/userprog/close-stdin.ck deleted file mode 100644 index 3d285074f505fd82fe9a3028bc2f4e9c1883f267..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-stdin.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(close-stdin) begin -(close-stdin) end -close-stdin: exit(0) -EOF -(close-stdin) begin -close-stdin: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/close-stdout.c b/src/tests/userprog/close-stdout.c deleted file mode 100644 index 886523fc45808168d5020572763b6bbc7adc4a1f..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-stdout.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Tries to close the console output stream, which must either - fail silently or terminate with exit code -1. */ - -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - close (1); -} diff --git a/src/tests/userprog/close-stdout.ck b/src/tests/userprog/close-stdout.ck deleted file mode 100644 index 3cbbcff5c5407785be4ce34a89f0ff29709914c9..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-stdout.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(close-stdout) begin -(close-stdout) end -close-stdout: exit(0) -EOF -(close-stdout) begin -close-stdout: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/close-twice.c b/src/tests/userprog/close-twice.c deleted file mode 100644 index 830bccf38be9ddf4df11d4014ac43cc527831206..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-twice.c +++ /dev/null @@ -1,18 +0,0 @@ -/* Opens a file and then tries to close it twice. The second - close must either fail silently or terminate with exit code - -1. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - msg ("close \"sample.txt\""); - close (handle); - msg ("close \"sample.txt\" again"); - close (handle); -} diff --git a/src/tests/userprog/close-twice.ck b/src/tests/userprog/close-twice.ck deleted file mode 100644 index deb55a6d3c613d6917808e9b4ec9d02020189fd1..0000000000000000000000000000000000000000 --- a/src/tests/userprog/close-twice.ck +++ /dev/null @@ -1,19 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(close-twice) begin -(close-twice) open "sample.txt" -(close-twice) close "sample.txt" -(close-twice) close "sample.txt" again -(close-twice) end -close-twice: exit(0) -EOF -(close-twice) begin -(close-twice) open "sample.txt" -(close-twice) close "sample.txt" -(close-twice) close "sample.txt" again -close-twice: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/create-bad-ptr.c b/src/tests/userprog/create-bad-ptr.c deleted file mode 100644 index 4a07bb3b7f807c10e42254d155990f325cb8e108..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-bad-ptr.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Passes a bad pointer to the create system call, - which must cause the process to be terminated with exit code - -1. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("create(0x20101234): %d", create ((char *) 0x20101234, 0)); -} diff --git a/src/tests/userprog/create-bad-ptr.ck b/src/tests/userprog/create-bad-ptr.ck deleted file mode 100644 index ac134056634333f8ddd7d11274a17f7c91caf29b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-bad-ptr.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(create-bad-ptr) begin -create-bad-ptr: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/create-bound.c b/src/tests/userprog/create-bound.c deleted file mode 100644 index 0a829f3cb7c67cfe1e7fd9e854ef615c211361fe..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-bound.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Opens a file whose name spans the boundary between two pages. - This is valid, so it must succeed. */ - -#include <syscall.h> -#include "tests/userprog/boundary.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("create(\"quux.dat\"): %d", - create (copy_string_across_boundary ("quux.dat"), 0)); -} diff --git a/src/tests/userprog/create-bound.ck b/src/tests/userprog/create-bound.ck deleted file mode 100644 index 7656b7fe8e50d57b2637e02f5797683ae5660144..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-bound.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(create-bound) begin -(create-bound) create("quux.dat"): 1 -(create-bound) end -create-bound: exit(0) -EOF -pass; diff --git a/src/tests/userprog/create-empty.c b/src/tests/userprog/create-empty.c deleted file mode 100644 index fa26b43e37bf791b81d92ca789d293fe8c8109e1..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-empty.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Tries to create a file with the empty string as its name. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("create(\"\"): %d", create ("", 0)); -} diff --git a/src/tests/userprog/create-empty.ck b/src/tests/userprog/create-empty.ck deleted file mode 100644 index 93a10588453b20446e9a26eb8fc838e22791cf67..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-empty.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(create-empty) begin -(create-empty) create(""): 0 -(create-empty) end -create-empty: exit(0) -EOF -(create-empty) begin -create-empty: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/create-exists.c b/src/tests/userprog/create-exists.c deleted file mode 100644 index d395008138b3700aab17eb3efdbf769e3c3e72b4..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-exists.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Verifies that trying to create a file under a name that - already exists will fail. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (create ("quux.dat", 0), "create quux.dat"); - CHECK (create ("warble.dat", 0), "create warble.dat"); - CHECK (!create ("quux.dat", 0), "try to re-create quux.dat"); - CHECK (create ("baffle.dat", 0), "create baffle.dat"); - CHECK (!create ("warble.dat", 0), "try to re-create quux.dat"); -} diff --git a/src/tests/userprog/create-exists.ck b/src/tests/userprog/create-exists.ck deleted file mode 100644 index 006885ef82e49efcc10a7147fece62dec86a882a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-exists.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(create-exists) begin -(create-exists) create quux.dat -(create-exists) create warble.dat -(create-exists) try to re-create quux.dat -(create-exists) create baffle.dat -(create-exists) try to re-create quux.dat -(create-exists) end -create-exists: exit(0) -EOF -pass; diff --git a/src/tests/userprog/create-long.c b/src/tests/userprog/create-long.c deleted file mode 100644 index 16b31bd5e227e0d314d569888c926d665b840cba..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-long.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Tries to create a file with a name that is much too long, - which must fail. */ - -#include <string.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - static char name[512]; - memset (name, 'x', sizeof name); - name[sizeof name - 1] = '\0'; - - msg ("create(\"x...\"): %d", create (name, 0)); -} diff --git a/src/tests/userprog/create-long.ck b/src/tests/userprog/create-long.ck deleted file mode 100644 index 628411cd53cd081460613fbfbbaa095e73366b1b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-long.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(create-long) begin -(create-long) create("x..."): 0 -(create-long) end -create-long: exit(0) -EOF -pass; diff --git a/src/tests/userprog/create-normal.c b/src/tests/userprog/create-normal.c deleted file mode 100644 index 3cbc4636b821647dccc895de56c48cb018594883..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-normal.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Creates an ordinary empty file. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (create ("quux.dat", 0), "create quux.dat"); -} diff --git a/src/tests/userprog/create-normal.ck b/src/tests/userprog/create-normal.ck deleted file mode 100644 index ca74a6eac7a40514bafaaeb3048c9458ed24aa98..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-normal.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(create-normal) begin -(create-normal) create quux.dat -(create-normal) end -create-normal: exit(0) -EOF -pass; diff --git a/src/tests/userprog/create-null.c b/src/tests/userprog/create-null.c deleted file mode 100644 index 287cb23fe338c899eca63e2d7231d89469e02c99..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-null.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Tries to create a file with the null pointer as its name. - The process must be terminated with exit code -1. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("create(NULL): %d", create (NULL, 0)); -} diff --git a/src/tests/userprog/create-null.ck b/src/tests/userprog/create-null.ck deleted file mode 100644 index 09b7872aa67cf9cecfe9908eff7ed7a77cd53a77..0000000000000000000000000000000000000000 --- a/src/tests/userprog/create-null.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(create-null) begin -create-null: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/exec-arg.c b/src/tests/userprog/exec-arg.c deleted file mode 100644 index 82d074457bce0a259b88970510ae6569d402ca29..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-arg.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Tests argument passing to child processes. */ - -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - wait (exec ("child-args childarg")); -} diff --git a/src/tests/userprog/exec-arg.ck b/src/tests/userprog/exec-arg.ck deleted file mode 100644 index b7533ed9d81499d33bf090c61dc75426ffc82266..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-arg.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(exec-arg) begin -(args) begin -(args) argc = 2 -(args) argv[0] = 'child-args' -(args) argv[1] = 'childarg' -(args) argv[2] = null -(args) end -child-args: exit(0) -(exec-arg) end -exec-arg: exit(0) -EOF -pass; diff --git a/src/tests/userprog/exec-bad-ptr.c b/src/tests/userprog/exec-bad-ptr.c deleted file mode 100644 index 0abadd30f141913977806fc6892cb34810d7359b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-bad-ptr.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Passes an invalid pointer to the exec system call. - The process must be terminated with -1 exit code. */ - -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - exec ((char *) 0x20101234); -} diff --git a/src/tests/userprog/exec-bad-ptr.ck b/src/tests/userprog/exec-bad-ptr.ck deleted file mode 100644 index 63f5f78cc2d6be86d3fac76aa1d8f7fd6628f0d1..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-bad-ptr.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(exec-bad-ptr) begin -(exec-bad-ptr) end -exec-bad-ptr: exit(0) -EOF -(exec-bad-ptr) begin -exec-bad-ptr: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/exec-missing.c b/src/tests/userprog/exec-missing.c deleted file mode 100644 index bf08cad14678c17fbcc611578f8e56c5f7948235..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-missing.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Tries to execute a nonexistent process. - The exec system call must return -1. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("exec(\"no-such-file\"): %d", exec ("no-such-file")); -} diff --git a/src/tests/userprog/exec-missing.ck b/src/tests/userprog/exec-missing.ck deleted file mode 100644 index 0ef7aaa76d4728a67ac571058ad33daad3466ac2..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-missing.ck +++ /dev/null @@ -1,31 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF', <<'EOF', <<'EOF']); -(exec-missing) begin -load: no-such-file: open failed -(exec-missing) exec("no-such-file"): -1 -(exec-missing) end -exec-missing: exit(0) -EOF -(exec-missing) begin -(exec-missing) exec("no-such-file"): -1 -(exec-missing) end -exec-missing: exit(0) -EOF -(exec-missing) begin -load: no-such-file: open failed -no-such-file: exit(-1) -(exec-missing) exec("no-such-file"): -1 -(exec-missing) end -exec-missing: exit(0) -EOF -(exec-missing) begin -load: no-such-file: open failed -(exec-missing) exec("no-such-file"): -1 -no-such-file: exit(-1) -(exec-missing) end -exec-missing: exit(0) -EOF -pass; diff --git a/src/tests/userprog/exec-multiple.c b/src/tests/userprog/exec-multiple.c deleted file mode 100644 index ba4c26ecbd862a46ce39cd8f24ac281fa1c20b3c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-multiple.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Executes and waits for multiple child processes. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - wait (exec ("child-simple")); - wait (exec ("child-simple")); - wait (exec ("child-simple")); - wait (exec ("child-simple")); -} diff --git a/src/tests/userprog/exec-multiple.ck b/src/tests/userprog/exec-multiple.ck deleted file mode 100644 index 99624cd7bd87174462fb6dc1635485e1b7b2557d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-multiple.ck +++ /dev/null @@ -1,18 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(exec-multiple) begin -(child-simple) run -child-simple: exit(81) -(child-simple) run -child-simple: exit(81) -(child-simple) run -child-simple: exit(81) -(child-simple) run -child-simple: exit(81) -(exec-multiple) end -exec-multiple: exit(0) -EOF -pass; diff --git a/src/tests/userprog/exec-once.c b/src/tests/userprog/exec-once.c deleted file mode 100644 index 7bae5a159d61053839dd7788fe546665ed50164d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-once.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Executes and waits for a single child process. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - wait (exec ("child-simple")); -} diff --git a/src/tests/userprog/exec-once.ck b/src/tests/userprog/exec-once.ck deleted file mode 100644 index 00b59ededcc1fde171a5b58ed013ae5fd19ac4b4..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exec-once.ck +++ /dev/null @@ -1,12 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(exec-once) begin -(child-simple) run -child-simple: exit(81) -(exec-once) end -exec-once: exit(0) -EOF -pass; diff --git a/src/tests/userprog/exit.c b/src/tests/userprog/exit.c deleted file mode 100644 index cb4eb8fc2769ae240ebd089e76a2a4b87c7841e6..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exit.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Tests the exit system call. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - exit (57); - fail ("should have called exit(57)"); -} diff --git a/src/tests/userprog/exit.ck b/src/tests/userprog/exit.ck deleted file mode 100644 index a552702b61a9a880471746dad64b17787b9b2941..0000000000000000000000000000000000000000 --- a/src/tests/userprog/exit.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(exit) begin -exit: exit(57) -EOF -pass; diff --git a/src/tests/userprog/halt.c b/src/tests/userprog/halt.c deleted file mode 100644 index 4a99bce04600aca879d1c46bc8380d799c80d100..0000000000000000000000000000000000000000 --- a/src/tests/userprog/halt.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Tests the halt system call. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - halt (); - fail ("should have halted"); -} diff --git a/src/tests/userprog/halt.ck b/src/tests/userprog/halt.ck deleted file mode 100644 index 1b701ed9076f8192e3e4e0247b2817ea10341dfb..0000000000000000000000000000000000000000 --- a/src/tests/userprog/halt.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; - -our ($test); -my (@output) = read_text_file ("$test.output"); - -common_checks ("run", @output); - -fail "missing 'begin' message\n" - if !grep ($_ eq '(halt) begin', @output); -fail "found 'fail' message--halt didn't really halt\n" - if grep ($_ eq '(halt) fail', @output); -pass; diff --git a/src/tests/userprog/lib/.gitignore b/src/tests/userprog/lib/.gitignore deleted file mode 100644 index a4383358ec72fb4d15f30791cb5265a6e06c5416..0000000000000000000000000000000000000000 --- a/src/tests/userprog/lib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.d diff --git a/src/tests/userprog/lib/user/.dummy b/src/tests/userprog/lib/user/.dummy deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/tests/userprog/lib/user/.gitignore b/src/tests/userprog/lib/user/.gitignore deleted file mode 100644 index a4383358ec72fb4d15f30791cb5265a6e06c5416..0000000000000000000000000000000000000000 --- a/src/tests/userprog/lib/user/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.d diff --git a/src/tests/userprog/multi-child-fd.c b/src/tests/userprog/multi-child-fd.c deleted file mode 100644 index 48de4b4afae62427a63e3d56d08ac02f9718693b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/multi-child-fd.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Opens a file and then runs a subprocess that tries to close - the file. (Pintos does not have inheritance of file handles, - so this must fail.) The parent process then attempts to use - the file handle, which must succeed. */ - -#include <stdio.h> -#include <syscall.h> -#include "tests/userprog/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char child_cmd[128]; - int handle; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - - snprintf (child_cmd, sizeof child_cmd, "child-close %d", handle); - - msg ("wait(exec()) = %d", wait (exec (child_cmd))); - - check_file_handle (handle, "sample.txt", sample, sizeof sample - 1); -} diff --git a/src/tests/userprog/multi-child-fd.ck b/src/tests/userprog/multi-child-fd.ck deleted file mode 100644 index d0b3a33922258bb1c310294db3eba63d2bcedf9a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/multi-child-fd.ck +++ /dev/null @@ -1,25 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(multi-child-fd) begin -(multi-child-fd) open "sample.txt" -(child-close) begin -(child-close) end -child-close: exit(0) -(multi-child-fd) wait(exec()) = 0 -(multi-child-fd) verified contents of "sample.txt" -(multi-child-fd) end -multi-child-fd: exit(0) -EOF -(multi-child-fd) begin -(multi-child-fd) open "sample.txt" -(child-close) begin -child-close: exit(-1) -(multi-child-fd) wait(exec()) = -1 -(multi-child-fd) verified contents of "sample.txt" -(multi-child-fd) end -multi-child-fd: exit(0) -EOF -pass; diff --git a/src/tests/userprog/multi-recurse.c b/src/tests/userprog/multi-recurse.c deleted file mode 100644 index 7172ec3cb6ce83c7df082c483cbaa9545f57e8f9..0000000000000000000000000000000000000000 --- a/src/tests/userprog/multi-recurse.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Executes itself recursively to the depth indicated by the - first command-line argument. */ - -#include <debug.h> -#include <stdlib.h> -#include <stdio.h> -#include <syscall.h> -#include "tests/lib.h" - -const char *test_name = "multi-recurse"; - -int -main (int argc UNUSED, char *argv[]) -{ - int n = atoi (argv[1]); - - msg ("begin %d", n); - if (n != 0) - { - char child_cmd[128]; - pid_t child_pid; - int code; - - snprintf (child_cmd, sizeof child_cmd, "multi-recurse %d", n - 1); - CHECK ((child_pid = exec (child_cmd)) != -1, "exec(\"%s\")", child_cmd); - - code = wait (child_pid); - if (code != n - 1) - fail ("wait(exec(\"%s\")) returned %d", child_cmd, code); - } - - msg ("end %d", n); - return n; -} diff --git a/src/tests/userprog/multi-recurse.ck b/src/tests/userprog/multi-recurse.ck deleted file mode 100644 index 41eb4a6e5a325e7b3da7a93b232399b9cca75ec3..0000000000000000000000000000000000000000 --- a/src/tests/userprog/multi-recurse.ck +++ /dev/null @@ -1,70 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(multi-recurse) begin 15 -(multi-recurse) exec("multi-recurse 14") -(multi-recurse) begin 14 -(multi-recurse) exec("multi-recurse 13") -(multi-recurse) begin 13 -(multi-recurse) exec("multi-recurse 12") -(multi-recurse) begin 12 -(multi-recurse) exec("multi-recurse 11") -(multi-recurse) begin 11 -(multi-recurse) exec("multi-recurse 10") -(multi-recurse) begin 10 -(multi-recurse) exec("multi-recurse 9") -(multi-recurse) begin 9 -(multi-recurse) exec("multi-recurse 8") -(multi-recurse) begin 8 -(multi-recurse) exec("multi-recurse 7") -(multi-recurse) begin 7 -(multi-recurse) exec("multi-recurse 6") -(multi-recurse) begin 6 -(multi-recurse) exec("multi-recurse 5") -(multi-recurse) begin 5 -(multi-recurse) exec("multi-recurse 4") -(multi-recurse) begin 4 -(multi-recurse) exec("multi-recurse 3") -(multi-recurse) begin 3 -(multi-recurse) exec("multi-recurse 2") -(multi-recurse) begin 2 -(multi-recurse) exec("multi-recurse 1") -(multi-recurse) begin 1 -(multi-recurse) exec("multi-recurse 0") -(multi-recurse) begin 0 -(multi-recurse) end 0 -multi-recurse: exit(0) -(multi-recurse) end 1 -multi-recurse: exit(1) -(multi-recurse) end 2 -multi-recurse: exit(2) -(multi-recurse) end 3 -multi-recurse: exit(3) -(multi-recurse) end 4 -multi-recurse: exit(4) -(multi-recurse) end 5 -multi-recurse: exit(5) -(multi-recurse) end 6 -multi-recurse: exit(6) -(multi-recurse) end 7 -multi-recurse: exit(7) -(multi-recurse) end 8 -multi-recurse: exit(8) -(multi-recurse) end 9 -multi-recurse: exit(9) -(multi-recurse) end 10 -multi-recurse: exit(10) -(multi-recurse) end 11 -multi-recurse: exit(11) -(multi-recurse) end 12 -multi-recurse: exit(12) -(multi-recurse) end 13 -multi-recurse: exit(13) -(multi-recurse) end 14 -multi-recurse: exit(14) -(multi-recurse) end 15 -multi-recurse: exit(15) -EOF -pass; diff --git a/src/tests/userprog/no-vm/Make.tests b/src/tests/userprog/no-vm/Make.tests deleted file mode 100644 index a545e18eff1f159522e2ad9fb719279e176a85ca..0000000000000000000000000000000000000000 --- a/src/tests/userprog/no-vm/Make.tests +++ /dev/null @@ -1,8 +0,0 @@ -# -*- makefile -*- - -tests/userprog/no-vm_TESTS = tests/userprog/no-vm/multi-oom -tests/userprog/no-vm_PROGS = $(tests/userprog/no-vm_TESTS) -tests/userprog/no-vm/multi-oom_SRC = tests/userprog/no-vm/multi-oom.c \ -tests/lib.c - -tests/userprog/no-vm/multi-oom.output: TIMEOUT = 360 diff --git a/src/tests/userprog/no-vm/Rubric b/src/tests/userprog/no-vm/Rubric deleted file mode 100644 index c3816c660fa087f64d8af500a3c5cb6f71a5b72d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/no-vm/Rubric +++ /dev/null @@ -1,3 +0,0 @@ -Functionality of features that VM might break: - -1 multi-oom diff --git a/src/tests/userprog/no-vm/multi-oom.c b/src/tests/userprog/no-vm/multi-oom.c deleted file mode 100644 index 6a4472daed7575a319e0ee57cdf26836af34f5bd..0000000000000000000000000000000000000000 --- a/src/tests/userprog/no-vm/multi-oom.c +++ /dev/null @@ -1,179 +0,0 @@ -/* Recursively executes itself until the child fails to execute. - We expect that at least 30 copies can run. - - We count how many children your kernel was able to execute - before it fails to start a new process. We require that, - if a process doesn't actually get to start, exec() must - return -1, not a valid PID. - - We repeat this process 10 times, checking that your kernel - allows for the same level of depth every time. - - In addition, some processes will spawn children that terminate - abnormally after allocating some resources. - - Written by Godmar Back <godmar@gmail.com> - */ - -#include <debug.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <stdbool.h> -#include <syscall.h> -#include <random.h> -#include "tests/lib.h" - -static const int EXPECTED_DEPTH_TO_PASS = 30; -static const int EXPECTED_REPETITIONS = 10; - -const char *test_name = "multi-oom"; - -enum child_termination_mode { RECURSE, CRASH }; - -/* Spawn a recursive copy of ourselves, passing along instructions - for the child. */ -static pid_t -spawn_child (int c, enum child_termination_mode mode) -{ - char child_cmd[128]; - snprintf (child_cmd, sizeof child_cmd, - "%s %d %s", test_name, c, mode == CRASH ? "-k" : ""); - return exec (child_cmd); -} - -/* Open a number of files (and fail to close them). - The kernel must free any kernel resources associated - with these file descriptors. */ -static void -consume_some_resources (void) -{ - int fd, fdmax = 126; - - /* Open as many files as we can, up to fdmax. - Depending on how file descriptors are allocated inside - the kernel, open() may fail if the kernel is low on memory. - A low-memory condition in open() should not lead to the - termination of the process. */ - for (fd = 0; fd < fdmax; fd++) - if (open (test_name) == -1) - break; -} - -/* Consume some resources, then terminate this process - in some abnormal way. */ -static int NO_INLINE -consume_some_resources_and_die (int seed) -{ - consume_some_resources (); - random_init (seed); - int *PHYS_BASE = (int *)0xC0000000; - - switch (random_ulong () % 5) - { - case 0: - *(int *) NULL = 42; - - case 1: - return *(int *) NULL; - - case 2: - return *PHYS_BASE; - - case 3: - *PHYS_BASE = 42; - - case 4: - open ((char *)PHYS_BASE); - exit (-1); - - default: - NOT_REACHED (); - } - return 0; -} - -/* The first copy is invoked without command line arguments. - Subsequent copies are invoked with a parameter 'depth' - that describes how many parent processes preceded them. - Each process spawns one or multiple recursive copies of - itself, passing 'depth+1' as depth. - - Some children are started with the '-k' flag, which will - result in abnormal termination. - */ -int -main (int argc, char *argv[]) -{ - int n; - - n = argc > 1 ? atoi (argv[1]) : 0; - bool is_at_root = (n == 0); - if (is_at_root) - msg ("begin"); - - /* If -k is passed, crash this process. */ - if (argc > 2 && !strcmp(argv[2], "-k")) - { - consume_some_resources_and_die (n); - NOT_REACHED (); - } - - int howmany = is_at_root ? EXPECTED_REPETITIONS : 1; - int i, expected_depth = -1; - - for (i = 0; i < howmany; i++) - { - pid_t child_pid; - - /* Spawn a child that will be abnormally terminated. - To speed the test up, do this only for processes - spawned at a certain depth. */ - if (n > EXPECTED_DEPTH_TO_PASS/2) - { - child_pid = spawn_child (n + 1, CRASH); - if (child_pid != -1) - { - if (wait (child_pid) != -1) - fail ("crashed child should return -1."); - } - /* If spawning this child failed, so should - the next spawn_child below. */ - } - - /* Now spawn the child that will recurse. */ - child_pid = spawn_child (n + 1, RECURSE); - - /* If maximum depth is reached, return result. */ - if (child_pid == -1) - return n; - - /* Else wait for child to report how deeply it was able to recurse. */ - int reached_depth = wait (child_pid); - if (reached_depth == -1) - fail ("wait returned -1."); - - /* Record the depth reached during the first run; on subsequent - runs, fail if those runs do not match the depth achieved on the - first run. */ - if (i == 0) - expected_depth = reached_depth; - else if (expected_depth != reached_depth) - fail ("after run %d/%d, expected depth %d, actual depth %d.", - i, howmany, expected_depth, reached_depth); - ASSERT (expected_depth == reached_depth); - } - - consume_some_resources (); - - if (n == 0) - { - if (expected_depth < EXPECTED_DEPTH_TO_PASS) - fail ("should have forked at least %d times.", EXPECTED_DEPTH_TO_PASS); - msg ("success. program forked %d times.", howmany); - msg ("end"); - } - - return expected_depth; -} -// vim: sw=2 diff --git a/src/tests/userprog/no-vm/multi-oom.ck b/src/tests/userprog/no-vm/multi-oom.ck deleted file mode 100644 index 59a0bcd5324c899fc093a7fd24505d615d4ba778..0000000000000000000000000000000000000000 --- a/src/tests/userprog/no-vm/multi-oom.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, IGNORE_EXIT_CODES => 1, [<<'EOF']); -(multi-oom) begin -(multi-oom) success. program forked 10 times. -(multi-oom) end -EOF -pass; diff --git a/src/tests/userprog/null.ck b/src/tests/userprog/null.ck deleted file mode 100644 index 980de35ca6cb582cd8f0cad26465569dd021e74c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/null.ck +++ /dev/null @@ -1,8 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -system call! -EOF -pass; diff --git a/src/tests/userprog/open-bad-ptr.c b/src/tests/userprog/open-bad-ptr.c deleted file mode 100644 index 9cd4edf5c66d3d429a5874937ee73270cb065238..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-bad-ptr.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Passes an invalid pointer to the open system call. - The process must be terminated with -1 exit code. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("open(0x20101234): %d", open ((char *) 0x20101234)); - fail ("should have called exit(-1)"); -} diff --git a/src/tests/userprog/open-bad-ptr.ck b/src/tests/userprog/open-bad-ptr.ck deleted file mode 100644 index 45349e2c91537b8034c1089a6a721c3360867410..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-bad-ptr.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(open-bad-ptr) begin -(open-bad-ptr) end -open-bad-ptr: exit(0) -EOF -(open-bad-ptr) begin -open-bad-ptr: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/open-boundary.c b/src/tests/userprog/open-boundary.c deleted file mode 100644 index cc8ff8b4b37e0f594eb21bbd6980cdd130b84b47..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-boundary.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Creates a file whose name spans the boundary between two pages. - This is valid, so it must succeed. */ - -#include <syscall.h> -#include "tests/userprog/boundary.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (open (copy_string_across_boundary ("sample.txt")) > 1, - "open \"sample.txt\""); -} diff --git a/src/tests/userprog/open-boundary.ck b/src/tests/userprog/open-boundary.ck deleted file mode 100644 index 8060d223c2436831785a8591f8bb3dbc0a8540f1..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-boundary.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(open-boundary) begin -(open-boundary) open "sample.txt" -(open-boundary) end -open-boundary: exit(0) -EOF -pass; diff --git a/src/tests/userprog/open-empty.c b/src/tests/userprog/open-empty.c deleted file mode 100644 index 3ea99074acf473d512e344844574d354ff35c4c1..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-empty.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Tries to open a file with the empty string as its name. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle = open (""); - if (handle != -1) - fail ("open() returned %d instead of -1", handle); -} diff --git a/src/tests/userprog/open-empty.ck b/src/tests/userprog/open-empty.ck deleted file mode 100644 index 885fb415cd84fdb2adb69c60fa65c2b50124b11b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-empty.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(open-empty) begin -(open-empty) end -open-empty: exit(0) -EOF -pass; diff --git a/src/tests/userprog/open-missing.c b/src/tests/userprog/open-missing.c deleted file mode 100644 index 13ecbda488fc3b7fbebe1be19716f7381e9561c4..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-missing.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Tries to open a nonexistent file. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle = open ("no-such-file"); - if (handle != -1) - fail ("open() returned %d", handle); -} diff --git a/src/tests/userprog/open-missing.ck b/src/tests/userprog/open-missing.ck deleted file mode 100644 index d72d87868c8e31edce579f852ee9de9999cbff4c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-missing.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(open-missing) begin -(open-missing) end -open-missing: exit(0) -EOF -pass; diff --git a/src/tests/userprog/open-normal.c b/src/tests/userprog/open-normal.c deleted file mode 100644 index 5132465335d17f1302689910aff9bffe7bef1c0a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-normal.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Open a file. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle = open ("sample.txt"); - if (handle < 2) - fail ("open() returned %d", handle); -} diff --git a/src/tests/userprog/open-normal.ck b/src/tests/userprog/open-normal.ck deleted file mode 100644 index 4f6c34250f94d8bfa8ad92c83efba8b631fba460..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-normal.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(open-normal) begin -(open-normal) end -open-normal: exit(0) -EOF -pass; diff --git a/src/tests/userprog/open-null.c b/src/tests/userprog/open-null.c deleted file mode 100644 index bb418b88b33c20109ec74f4501ffa48c41daa45f..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-null.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Tries to open a file with the null pointer as its name. - The process must be terminated with exit code -1. */ - -#include <stddef.h> -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - open (NULL); -} diff --git a/src/tests/userprog/open-null.ck b/src/tests/userprog/open-null.ck deleted file mode 100644 index b4a3bcb4853b0908a52e2db38bde5e41938fbf24..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-null.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(open-null) begin -(open-null) end -open-null: exit(0) -EOF -(open-null) begin -open-null: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/open-twice.c b/src/tests/userprog/open-twice.c deleted file mode 100644 index dd333af1c1ad3ec91757736d75d3948d5366896a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-twice.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Tries to open the same file twice, - which must succeed and must return a different file descriptor - in each case. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int h1 = open ("sample.txt"); - int h2 = open ("sample.txt"); - - CHECK ((h1 = open ("sample.txt")) > 1, "open \"sample.txt\" once"); - CHECK ((h2 = open ("sample.txt")) > 1, "open \"sample.txt\" again"); - if (h1 == h2) - fail ("open() returned %d both times", h1); -} diff --git a/src/tests/userprog/open-twice.ck b/src/tests/userprog/open-twice.ck deleted file mode 100644 index 64fa805b277434a2b7a48c5d6ffa73dad64f812d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/open-twice.ck +++ /dev/null @@ -1,12 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(open-twice) begin -(open-twice) open "sample.txt" once -(open-twice) open "sample.txt" again -(open-twice) end -open-twice: exit(0) -EOF -pass; diff --git a/src/tests/userprog/read-bad-fd.c b/src/tests/userprog/read-bad-fd.c deleted file mode 100644 index a8b190d0d4b6092609ba0826eb2a49c4b4936f36..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-bad-fd.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Tries to read from an invalid fd, - which must either fail silently or terminate the process with - exit code -1. */ - -#include <limits.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char buf; - read (0x20101234, &buf, 1); - read (5, &buf, 1); - read (1234, &buf, 1); - read (-1, &buf, 1); - read (-1024, &buf, 1); - read (INT_MIN, &buf, 1); - read (INT_MAX, &buf, 1); -} diff --git a/src/tests/userprog/read-bad-fd.ck b/src/tests/userprog/read-bad-fd.ck deleted file mode 100644 index 5fedcc7c7f6600ec87df48f65851c01322c31f50..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-bad-fd.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(read-bad-fd) begin -(read-bad-fd) end -read-bad-fd: exit(0) -EOF -(read-bad-fd) begin -read-bad-fd: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/read-bad-ptr.c b/src/tests/userprog/read-bad-ptr.c deleted file mode 100644 index 8fe756ec6e640c3e50f6cf301a99c89253a1abb5..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-bad-ptr.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Passes an invalid pointer to the read system call. - The process must be terminated with -1 exit code. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - - read (handle, (char *) 0xc0100000, 123); - fail ("should not have survived read()"); -} diff --git a/src/tests/userprog/read-bad-ptr.ck b/src/tests/userprog/read-bad-ptr.ck deleted file mode 100644 index d10accfd599805b4e3768c0dc4d9df7ead3df416..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-bad-ptr.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(read-bad-ptr) begin -(read-bad-ptr) open "sample.txt" -(read-bad-ptr) end -read-bad-ptr: exit(0) -EOF -(read-bad-ptr) begin -(read-bad-ptr) open "sample.txt" -read-bad-ptr: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/read-boundary.c b/src/tests/userprog/read-boundary.c deleted file mode 100644 index 9c19966fa5cde0e997a005cfe3d97c9e6e170f5c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-boundary.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Reads data spanning two pages in virtual address space, - which must succeed. */ - -#include <string.h> -#include <syscall.h> -#include "tests/userprog/boundary.h" -#include "tests/userprog/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - int byte_cnt; - char *buffer; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - - buffer = get_boundary_area () - sizeof sample / 2; - byte_cnt = read (handle, buffer, sizeof sample - 1); - if (byte_cnt != sizeof sample - 1) - fail ("read() returned %d instead of %zu", byte_cnt, sizeof sample - 1); - else if (strcmp (sample, buffer)) - { - msg ("expected text:\n%s", sample); - msg ("text actually read:\n%s", buffer); - fail ("expected text differs from actual"); - } -} diff --git a/src/tests/userprog/read-boundary.ck b/src/tests/userprog/read-boundary.ck deleted file mode 100644 index 08dc1612734966f0ad460ffb5a589e9e6aa8583c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-boundary.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(read-boundary) begin -(read-boundary) open "sample.txt" -(read-boundary) end -read-boundary: exit(0) -EOF -pass; diff --git a/src/tests/userprog/read-normal.c b/src/tests/userprog/read-normal.c deleted file mode 100644 index 16d15cc20f71e088587ef07a92dcf726789dbe20..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-normal.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Try reading a file in the most normal way. */ - -#include "tests/userprog/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - check_file ("sample.txt", sample, sizeof sample - 1); -} diff --git a/src/tests/userprog/read-normal.ck b/src/tests/userprog/read-normal.ck deleted file mode 100644 index 0ed299828315945e98eb39e3b4ca3525d4837e6b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-normal.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(read-normal) begin -(read-normal) open "sample.txt" for verification -(read-normal) verified contents of "sample.txt" -(read-normal) close "sample.txt" -(read-normal) end -read-normal: exit(0) -EOF -pass; diff --git a/src/tests/userprog/read-stdout.c b/src/tests/userprog/read-stdout.c deleted file mode 100644 index d0630b961d17130f7117e669d43b62b2a59dac71..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-stdout.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Try reading from fd 1 (stdout), - which may just fail or terminate the process with -1 exit - code. */ - -#include <stdio.h> -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - char buf; - read (STDOUT_FILENO, &buf, 1); -} diff --git a/src/tests/userprog/read-stdout.ck b/src/tests/userprog/read-stdout.ck deleted file mode 100644 index 7d87b52b316aaad180da2035679a3a466eacc3b4..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-stdout.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(read-stdout) begin -(read-stdout) end -read-stdout: exit(0) -EOF -(read-stdout) begin -read-stdout: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/read-zero.c b/src/tests/userprog/read-zero.c deleted file mode 100644 index e441817d13f8b0c4f969d49489de95bb748b050d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-zero.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Try a 0-byte read, which should return 0 without reading - anything. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle, byte_cnt; - char buf; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - - buf = 123; - byte_cnt = read (handle, &buf, 0); - if (byte_cnt != 0) - fail ("read() returned %d instead of 0", byte_cnt); - else if (buf != 123) - fail ("0-byte read() modified buffer"); -} diff --git a/src/tests/userprog/read-zero.ck b/src/tests/userprog/read-zero.ck deleted file mode 100644 index 8346dbc325a2d74887ab6837c294e024643bd928..0000000000000000000000000000000000000000 --- a/src/tests/userprog/read-zero.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(read-zero) begin -(read-zero) open "sample.txt" -(read-zero) end -read-zero: exit(0) -EOF -pass; diff --git a/src/tests/userprog/rox-child.c b/src/tests/userprog/rox-child.c deleted file mode 100644 index 30afba25933d403c51de14af0be2311a78bd5b3d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/rox-child.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Ensure that the executable of a running process cannot be - modified, even by a child process. */ - -#define CHILD_CNT "1" -#include "tests/userprog/rox-child.inc" diff --git a/src/tests/userprog/rox-child.ck b/src/tests/userprog/rox-child.ck deleted file mode 100644 index e6363fb6104437513ed564e13a0842ae2afabf1b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/rox-child.ck +++ /dev/null @@ -1,20 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(rox-child) begin -(rox-child) open "child-rox" -(rox-child) read "child-rox" -(rox-child) write "child-rox" -(rox-child) exec "child-rox 1" -(child-rox) begin -(child-rox) try to write "child-rox" -(child-rox) try to write "child-rox" -(child-rox) end -child-rox: exit(12) -(rox-child) write "child-rox" -(rox-child) end -rox-child: exit(0) -EOF -pass; diff --git a/src/tests/userprog/rox-child.inc b/src/tests/userprog/rox-child.inc deleted file mode 100644 index 1e2ade9c5fd89e3c159adc18a863113002215308..0000000000000000000000000000000000000000 --- a/src/tests/userprog/rox-child.inc +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- c -*- */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - const char *child_cmd = "child-rox " CHILD_CNT; - int handle; - pid_t child; - char buffer[16]; - - /* Open child-rox, read from it, write back same data. */ - CHECK ((handle = open ("child-rox")) > 1, "open \"child-rox\""); - CHECK (read (handle, buffer, sizeof buffer) == (int) sizeof buffer, - "read \"child-rox\""); - seek (handle, 0); - CHECK (write (handle, buffer, sizeof buffer) == (int) sizeof buffer, - "write \"child-rox\""); - - /* Execute child-rox and wait for it. */ - CHECK ((child = exec (child_cmd)) != -1, "exec \"%s\"", child_cmd); - quiet = true; - CHECK (wait (child) == 12, "wait for child"); - quiet = false; - - /* Write to child-rox again. */ - seek (handle, 0); - CHECK (write (handle, buffer, sizeof buffer) == (int) sizeof buffer, - "write \"child-rox\""); -} diff --git a/src/tests/userprog/rox-multichild.c b/src/tests/userprog/rox-multichild.c deleted file mode 100644 index 8e74dab244d4405a320b4266ad6a1902a71f187d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/rox-multichild.c +++ /dev/null @@ -1,5 +0,0 @@ -/* Ensure that the executable of a running process cannot be - modified, even in the presence of multiple children. */ - -#define CHILD_CNT "5" -#include "tests/userprog/rox-child.inc" diff --git a/src/tests/userprog/rox-multichild.ck b/src/tests/userprog/rox-multichild.ck deleted file mode 100644 index 14b27db7e1d2246ffd606c77db987e8e1de61532..0000000000000000000000000000000000000000 --- a/src/tests/userprog/rox-multichild.ck +++ /dev/null @@ -1,44 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(rox-multichild) begin -(rox-multichild) open "child-rox" -(rox-multichild) read "child-rox" -(rox-multichild) write "child-rox" -(rox-multichild) exec "child-rox 5" -(child-rox) begin -(child-rox) try to write "child-rox" -(child-rox) exec "child-rox 4" -(child-rox) begin -(child-rox) try to write "child-rox" -(child-rox) exec "child-rox 3" -(child-rox) begin -(child-rox) try to write "child-rox" -(child-rox) exec "child-rox 2" -(child-rox) begin -(child-rox) try to write "child-rox" -(child-rox) exec "child-rox 1" -(child-rox) begin -(child-rox) try to write "child-rox" -(child-rox) try to write "child-rox" -(child-rox) end -child-rox: exit(12) -(child-rox) try to write "child-rox" -(child-rox) end -child-rox: exit(12) -(child-rox) try to write "child-rox" -(child-rox) end -child-rox: exit(12) -(child-rox) try to write "child-rox" -(child-rox) end -child-rox: exit(12) -(child-rox) try to write "child-rox" -(child-rox) end -child-rox: exit(12) -(rox-multichild) write "child-rox" -(rox-multichild) end -rox-multichild: exit(0) -EOF -pass; diff --git a/src/tests/userprog/rox-simple.c b/src/tests/userprog/rox-simple.c deleted file mode 100644 index e84a064cb9d602d740fd14de8635f794dd031932..0000000000000000000000000000000000000000 --- a/src/tests/userprog/rox-simple.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Ensure that the executable of a running process cannot be - modified. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - char buffer[16]; - - CHECK ((handle = open ("rox-simple")) > 1, "open \"rox-simple\""); - CHECK (read (handle, buffer, sizeof buffer) == (int) sizeof buffer, - "read \"rox-simple\""); - CHECK (write (handle, buffer, sizeof buffer) == 0, - "try to write \"rox-simple\""); -} diff --git a/src/tests/userprog/rox-simple.ck b/src/tests/userprog/rox-simple.ck deleted file mode 100644 index c9dcc663743cb3b1635e6e9c6b6813ed55ae08bd..0000000000000000000000000000000000000000 --- a/src/tests/userprog/rox-simple.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(rox-simple) begin -(rox-simple) open "rox-simple" -(rox-simple) read "rox-simple" -(rox-simple) try to write "rox-simple" -(rox-simple) end -rox-simple: exit(0) -EOF -pass; diff --git a/src/tests/userprog/sample.inc b/src/tests/userprog/sample.inc deleted file mode 100644 index 59f2bcb6c493673fe6b4cfa90067e60dfbf6bb36..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sample.inc +++ /dev/null @@ -1,6 +0,0 @@ -char sample[] = { - "\"Amazing Electronic Fact: If you scuffed your feet long enough without\n" - " touching anything, you would build up so many electrons that your\n" - " finger would explode! But this is nothing to worry about unless you\n" - " have carpeting.\" --Dave Barry\n" -}; diff --git a/src/tests/userprog/sample.txt b/src/tests/userprog/sample.txt deleted file mode 100644 index 5050fec989ccb23041ed7010d2973f834fd35123..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sample.txt +++ /dev/null @@ -1,4 +0,0 @@ -"Amazing Electronic Fact: If you scuffed your feet long enough without - touching anything, you would build up so many electrons that your - finger would explode! But this is nothing to worry about unless you - have carpeting." --Dave Barry diff --git a/src/tests/userprog/sc-bad-arg.c b/src/tests/userprog/sc-bad-arg.c deleted file mode 100644 index 0b512a0e59797e0e7e3ae006d44dea83710d2508..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-bad-arg.c +++ /dev/null @@ -1,17 +0,0 @@ -/* Sticks a system call number (SYS_EXIT) at the very top of the - stack, then invokes a system call with the stack pointer - (%esp) set to its address. The process must be terminated - with -1 exit code because the argument to the system call - would be above the top of the user address space. */ - -#include <syscall-nr.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - asm volatile ("movl $0xbffffffc, %%esp; movl %0, (%%esp); int $0x30" - : : "i" (SYS_EXIT)); - fail ("should have called exit(-1)"); -} diff --git a/src/tests/userprog/sc-bad-arg.ck b/src/tests/userprog/sc-bad-arg.ck deleted file mode 100644 index 89811056338ef199208fbf48d5a3471f1cf64266..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-bad-arg.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(sc-bad-arg) begin -sc-bad-arg: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/sc-bad-sp.c b/src/tests/userprog/sc-bad-sp.c deleted file mode 100644 index 39cce84ebb9d70ce2536f480a4d7142585ee20ea..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-bad-sp.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Invokes a system call with the stack pointer (%esp) set to a - bad address. The process must be terminated with -1 exit - code. - - For Project 3: The bad address lies approximately 64MB below - the code segment, so there is no ambiguity that this attempt - must be rejected even after stack growth is implemented. - Moreover, a good stack growth heuristics should probably not - grow the stack for the purpose of reading the system call - number and arguments. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - asm volatile ("movl $.-(64*1024*1024), %esp; int $0x30"); - fail ("should have called exit(-1)"); -} diff --git a/src/tests/userprog/sc-bad-sp.ck b/src/tests/userprog/sc-bad-sp.ck deleted file mode 100644 index 498cec141f15846a071dd4fdf8b42eca3d91d32b..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-bad-sp.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(sc-bad-sp) begin -sc-bad-sp: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/sc-boundary-2.c b/src/tests/userprog/sc-boundary-2.c deleted file mode 100644 index 8acf0361e3e7a392f3c9a5143632c134ca646109..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-boundary-2.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Invokes a system call with one byte of the system call's - argument on a separate page from the rest of the bytes. This - must work. */ - -#include <syscall-nr.h> -#include "tests/userprog/boundary.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - /* Make one byte of a syscall argument hang over into a second - page. */ - int *p = (int *) ((char *) get_boundary_area () - 7); - p[0] = SYS_EXIT; - p[1] = 67; - - /* Invoke the system call. */ - asm volatile ("movl %0, %%esp; int $0x30" : : "g" (p)); - fail ("should have called exit(67)"); -} diff --git a/src/tests/userprog/sc-boundary-2.ck b/src/tests/userprog/sc-boundary-2.ck deleted file mode 100644 index 43766bf1b5ebfc0c67e4d8a0a45616e4568d81c5..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-boundary-2.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(sc-boundary-2) begin -sc-boundary-2: exit(67) -EOF -pass; diff --git a/src/tests/userprog/sc-boundary.c b/src/tests/userprog/sc-boundary.c deleted file mode 100644 index d889535cf279f9af2d5688fd0ef21a5c1caf0719..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-boundary.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Invokes a system call with the system call number and its - argument on separate pages. This must work. */ - -#include <syscall-nr.h> -#include "tests/userprog/boundary.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - /* Put a syscall number at the end of one page - and its argument at the beginning of another. */ - int *p = get_boundary_area (); - p--; - p[0] = SYS_EXIT; - p[1] = 42; - - /* Invoke the system call. */ - asm volatile ("movl %0, %%esp; int $0x30" : : "g" (p)); - fail ("should have called exit(42)"); -} diff --git a/src/tests/userprog/sc-boundary.ck b/src/tests/userprog/sc-boundary.ck deleted file mode 100644 index 3f7cbaf1ed41ad0df47d616e9d929562d3e8042d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/sc-boundary.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(sc-boundary) begin -sc-boundary: exit(42) -EOF -pass; diff --git a/src/tests/userprog/wait-bad-pid.c b/src/tests/userprog/wait-bad-pid.c deleted file mode 100644 index 3fe8ee4b3709f127e7a652fe593f7b7c2718c01c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-bad-pid.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Waits for an invalid pid. This may fail or terminate the - process with -1 exit code. */ - -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - wait ((pid_t) 0x0c020301); -} diff --git a/src/tests/userprog/wait-bad-pid.ck b/src/tests/userprog/wait-bad-pid.ck deleted file mode 100644 index db63fb990c0f921e9ae3ff8ab4accbefbfc0991c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-bad-pid.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(wait-bad-pid) begin -(wait-bad-pid) end -wait-bad-pid: exit(0) -EOF -(wait-bad-pid) begin -wait-bad-pid: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/wait-killed.c b/src/tests/userprog/wait-killed.c deleted file mode 100644 index 6a2a6b52d1c82112e184f29c23b7fc0eec6e37df..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-killed.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Wait for a process that will be killed for bad behavior. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("wait(exec()) = %d", wait (exec ("child-bad"))); -} diff --git a/src/tests/userprog/wait-killed.ck b/src/tests/userprog/wait-killed.ck deleted file mode 100644 index 5df0e9c1330f5376e41241fe63a98692820d9bd2..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-killed.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(wait-killed) begin -(child-bad) begin -child-bad: exit(-1) -(wait-killed) wait(exec()) = -1 -(wait-killed) end -wait-killed: exit(0) -EOF -pass; diff --git a/src/tests/userprog/wait-simple.c b/src/tests/userprog/wait-simple.c deleted file mode 100644 index d3afcf3c63f671b65fbfcaa4538e9accd6878a81..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-simple.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Wait for a subprocess to finish. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - msg ("wait(exec()) = %d", wait (exec ("child-simple"))); -} diff --git a/src/tests/userprog/wait-simple.ck b/src/tests/userprog/wait-simple.ck deleted file mode 100644 index 93dd577667e053f61d10e6d48d0b8437da863256..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-simple.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(wait-simple) begin -(child-simple) run -child-simple: exit(81) -(wait-simple) wait(exec()) = 81 -(wait-simple) end -wait-simple: exit(0) -EOF -pass; diff --git a/src/tests/userprog/wait-twice.c b/src/tests/userprog/wait-twice.c deleted file mode 100644 index 785e684939d31dcfa1994ed586f07e3aab39834a..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-twice.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Wait for a subprocess to finish, twice. - The first call must wait in the usual way and return the exit code. - The second wait call must return -1 immediately. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - pid_t child = exec ("child-simple"); - msg ("wait(exec()) = %d", wait (child)); - msg ("wait(exec()) = %d", wait (child)); -} diff --git a/src/tests/userprog/wait-twice.ck b/src/tests/userprog/wait-twice.ck deleted file mode 100644 index 6d5384319a2c91078a397aa83fd8d1f0d75dcc9c..0000000000000000000000000000000000000000 --- a/src/tests/userprog/wait-twice.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(wait-twice) begin -(child-simple) run -child-simple: exit(81) -(wait-twice) wait(exec()) = 81 -(wait-twice) wait(exec()) = -1 -(wait-twice) end -wait-twice: exit(0) -EOF -pass; diff --git a/src/tests/userprog/write-bad-fd.c b/src/tests/userprog/write-bad-fd.c deleted file mode 100644 index f3b11517e6a0ee9293f695857fdd4c77ec674d22..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-bad-fd.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Tries to write to an invalid fd, - which must either fail silently or terminate the process with - exit code -1. */ - -#include <limits.h> -#include <syscall.h> -#include "tests/main.h" - -void -test_main (void) -{ - char buf = 123; - write (0x01012342, &buf, 1); - write (7, &buf, 1); - write (2546, &buf, 1); - write (-5, &buf, 1); - write (-8192, &buf, 1); - write (INT_MIN + 1, &buf, 1); - write (INT_MAX - 1, &buf, 1); -} diff --git a/src/tests/userprog/write-bad-fd.ck b/src/tests/userprog/write-bad-fd.ck deleted file mode 100644 index 8da7a8bbe79a5c1f0520ebc0d4c62318b70e73fa..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-bad-fd.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(write-bad-fd) begin -(write-bad-fd) end -write-bad-fd: exit(0) -EOF -(write-bad-fd) begin -write-bad-fd: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/write-bad-ptr.c b/src/tests/userprog/write-bad-ptr.c deleted file mode 100644 index 533647900bfd21a8b7b09b6f32e0dee4fb62c8f7..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-bad-ptr.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Passes an invalid pointer to the write system call. - The process must be terminated with -1 exit code. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - - write (handle, (char *) 0x10123420, 123); - fail ("should have exited with -1"); -} diff --git a/src/tests/userprog/write-bad-ptr.ck b/src/tests/userprog/write-bad-ptr.ck deleted file mode 100644 index ad9f399c81bb1c4d87306d2266ec555d96cfec45..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-bad-ptr.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(write-bad-ptr) begin -(write-bad-ptr) open "sample.txt" -(write-bad-ptr) end -write-bad-ptr: exit(0) -EOF -(write-bad-ptr) begin -(write-bad-ptr) open "sample.txt" -write-bad-ptr: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/write-boundary.c b/src/tests/userprog/write-boundary.c deleted file mode 100644 index d2de1d428383fb8e925098566ec85815911fd6ba..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-boundary.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Writes data spanning two pages in virtual address space, - which must succeed. */ - -#include <string.h> -#include <syscall.h> -#include "tests/userprog/boundary.h" -#include "tests/userprog/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - int byte_cnt; - char *sample_p; - - sample_p = copy_string_across_boundary (sample); - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - - byte_cnt = write (handle, sample_p, sizeof sample - 1); - if (byte_cnt != sizeof sample - 1) - fail ("write() returned %d instead of %zu", byte_cnt, sizeof sample - 1); -} diff --git a/src/tests/userprog/write-boundary.ck b/src/tests/userprog/write-boundary.ck deleted file mode 100644 index 788378179c57064823ab362c2176edafdc1b3c3f..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-boundary.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(write-boundary) begin -(write-boundary) open "sample.txt" -(write-boundary) end -write-boundary: exit(0) -EOF -pass; diff --git a/src/tests/userprog/write-normal.c b/src/tests/userprog/write-normal.c deleted file mode 100644 index e0297aa38475f5adcf41562be33f20a4f9a159e8..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-normal.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Try writing a file in the most normal way. */ - -#include <syscall.h> -#include "tests/userprog/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle, byte_cnt; - - CHECK (create ("test.txt", sizeof sample - 1), "create \"test.txt\""); - CHECK ((handle = open ("test.txt")) > 1, "open \"test.txt\""); - - byte_cnt = write (handle, sample, sizeof sample - 1); - if (byte_cnt != sizeof sample - 1) - fail ("write() returned %d instead of %zu", byte_cnt, sizeof sample - 1); -} - diff --git a/src/tests/userprog/write-normal.ck b/src/tests/userprog/write-normal.ck deleted file mode 100644 index 9fa6024c09a679df06bcef847f2132fc07e39c35..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-normal.ck +++ /dev/null @@ -1,12 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(write-normal) begin -(write-normal) create "test.txt" -(write-normal) open "test.txt" -(write-normal) end -write-normal: exit(0) -EOF -pass; diff --git a/src/tests/userprog/write-stdin.c b/src/tests/userprog/write-stdin.c deleted file mode 100644 index 491ea5380d8d23aeed355f7fcfba66cd495675d9..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-stdin.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Try writing to fd 0 (stdin), - which may just fail or terminate the process with -1 exit - code. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char buf = 123; - write (0, &buf, 1); -} diff --git a/src/tests/userprog/write-stdin.ck b/src/tests/userprog/write-stdin.ck deleted file mode 100644 index a6caf81edd6a213c5bd97c907247d2954865d50d..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-stdin.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(write-stdin) begin -(write-stdin) end -write-stdin: exit(0) -EOF -(write-stdin) begin -write-stdin: exit(-1) -EOF -pass; diff --git a/src/tests/userprog/write-zero.c b/src/tests/userprog/write-zero.c deleted file mode 100644 index d8dac9bc1058c8378e638214403e30ca50d66aa1..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-zero.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Try a 0-byte write, which should return 0 without writing - anything. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle, byte_cnt; - char buf; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - - buf = 123; - byte_cnt = write (handle, &buf, 0); - if (byte_cnt != 0) - fail("write() returned %d instead of 0", byte_cnt); -} diff --git a/src/tests/userprog/write-zero.ck b/src/tests/userprog/write-zero.ck deleted file mode 100644 index cc4cd609f4e402ad5fa77e19c438a0edde02bcd6..0000000000000000000000000000000000000000 --- a/src/tests/userprog/write-zero.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(write-zero) begin -(write-zero) open "sample.txt" -(write-zero) end -write-zero: exit(0) -EOF -pass; diff --git a/src/tests/vm/Grading b/src/tests/vm/Grading deleted file mode 100644 index f0c2c13251154fc10c08090c0f2120b2c84847c3..0000000000000000000000000000000000000000 --- a/src/tests/vm/Grading +++ /dev/null @@ -1,12 +0,0 @@ -# Percentage of the testing point total designated for each set of -# tests. - -# This project is primarily about virtual memory, but all the previous -# functionality should work too, and it's easy to screw it up, thus -# the equal weight placed on each. - -50% tests/vm/Rubric.functionality -15% tests/vm/Rubric.robustness -10% tests/userprog/Rubric.functionality -5% tests/userprog/Rubric.robustness -20% tests/filesys/base/Rubric diff --git a/src/tests/vm/Make.tests b/src/tests/vm/Make.tests deleted file mode 100644 index 04b1b81666ac0407ffd05a7157048eabc6e6f911..0000000000000000000000000000000000000000 --- a/src/tests/vm/Make.tests +++ /dev/null @@ -1,103 +0,0 @@ -# -*- makefile -*- - -tests/vm_TESTS = $(addprefix tests/vm/,pt-grow-stack pt-grow-pusha \ -pt-grow-bad pt-big-stk-obj pt-bad-addr pt-bad-read pt-write-code \ -pt-write-code2 pt-grow-stk-sc page-linear page-parallel page-merge-seq \ -page-merge-par page-merge-stk page-merge-mm page-shuffle mmap-read \ -mmap-close mmap-unmap mmap-overlap mmap-twice mmap-write mmap-exit \ -mmap-shuffle mmap-bad-fd mmap-clean mmap-inherit mmap-misalign \ -mmap-null mmap-over-code mmap-over-data mmap-over-stk mmap-remove \ -mmap-zero) - -tests/vm_PROGS = $(tests/vm_TESTS) $(addprefix tests/vm/,child-linear \ -child-sort child-qsort child-qsort-mm child-mm-wrt child-inherit) - -tests/vm/pt-grow-stack_SRC = tests/vm/pt-grow-stack.c tests/arc4.c \ -tests/cksum.c tests/lib.c tests/main.c -tests/vm/pt-grow-pusha_SRC = tests/vm/pt-grow-pusha.c tests/lib.c \ -tests/main.c -tests/vm/pt-grow-bad_SRC = tests/vm/pt-grow-bad.c tests/lib.c tests/main.c -tests/vm/pt-big-stk-obj_SRC = tests/vm/pt-big-stk-obj.c tests/arc4.c \ -tests/cksum.c tests/lib.c tests/main.c -tests/vm/pt-bad-addr_SRC = tests/vm/pt-bad-addr.c tests/lib.c tests/main.c -tests/vm/pt-bad-read_SRC = tests/vm/pt-bad-read.c tests/lib.c tests/main.c -tests/vm/pt-write-code_SRC = tests/vm/pt-write-code.c tests/lib.c tests/main.c -tests/vm/pt-write-code2_SRC = tests/vm/pt-write-code-2.c tests/lib.c tests/main.c -tests/vm/pt-grow-stk-sc_SRC = tests/vm/pt-grow-stk-sc.c tests/lib.c tests/main.c -tests/vm/page-linear_SRC = tests/vm/page-linear.c tests/arc4.c \ -tests/lib.c tests/main.c -tests/vm/page-parallel_SRC = tests/vm/page-parallel.c tests/lib.c tests/main.c -tests/vm/page-merge-seq_SRC = tests/vm/page-merge-seq.c tests/arc4.c \ -tests/lib.c tests/main.c -tests/vm/page-merge-par_SRC = tests/vm/page-merge-par.c \ -tests/vm/parallel-merge.c tests/arc4.c tests/lib.c tests/main.c -tests/vm/page-merge-stk_SRC = tests/vm/page-merge-stk.c \ -tests/vm/parallel-merge.c tests/arc4.c tests/lib.c tests/main.c -tests/vm/page-merge-mm_SRC = tests/vm/page-merge-mm.c \ -tests/vm/parallel-merge.c tests/arc4.c tests/lib.c tests/main.c -tests/vm/page-shuffle_SRC = tests/vm/page-shuffle.c tests/arc4.c \ -tests/cksum.c tests/lib.c tests/main.c -tests/vm/mmap-read_SRC = tests/vm/mmap-read.c tests/lib.c tests/main.c -tests/vm/mmap-close_SRC = tests/vm/mmap-close.c tests/lib.c tests/main.c -tests/vm/mmap-unmap_SRC = tests/vm/mmap-unmap.c tests/lib.c tests/main.c -tests/vm/mmap-overlap_SRC = tests/vm/mmap-overlap.c tests/lib.c tests/main.c -tests/vm/mmap-twice_SRC = tests/vm/mmap-twice.c tests/lib.c tests/main.c -tests/vm/mmap-write_SRC = tests/vm/mmap-write.c tests/lib.c tests/main.c -tests/vm/mmap-exit_SRC = tests/vm/mmap-exit.c tests/lib.c tests/main.c -tests/vm/mmap-shuffle_SRC = tests/vm/mmap-shuffle.c tests/arc4.c \ -tests/cksum.c tests/lib.c tests/main.c -tests/vm/mmap-bad-fd_SRC = tests/vm/mmap-bad-fd.c tests/lib.c tests/main.c -tests/vm/mmap-clean_SRC = tests/vm/mmap-clean.c tests/lib.c tests/main.c -tests/vm/mmap-inherit_SRC = tests/vm/mmap-inherit.c tests/lib.c tests/main.c -tests/vm/mmap-misalign_SRC = tests/vm/mmap-misalign.c tests/lib.c \ -tests/main.c -tests/vm/mmap-null_SRC = tests/vm/mmap-null.c tests/lib.c tests/main.c -tests/vm/mmap-over-code_SRC = tests/vm/mmap-over-code.c tests/lib.c \ -tests/main.c -tests/vm/mmap-over-data_SRC = tests/vm/mmap-over-data.c tests/lib.c \ -tests/main.c -tests/vm/mmap-over-stk_SRC = tests/vm/mmap-over-stk.c tests/lib.c tests/main.c -tests/vm/mmap-remove_SRC = tests/vm/mmap-remove.c tests/lib.c tests/main.c -tests/vm/mmap-zero_SRC = tests/vm/mmap-zero.c tests/lib.c tests/main.c - -tests/vm/child-linear_SRC = tests/vm/child-linear.c tests/arc4.c tests/lib.c -tests/vm/child-qsort_SRC = tests/vm/child-qsort.c tests/vm/qsort.c tests/lib.c -tests/vm/child-qsort-mm_SRC = tests/vm/child-qsort-mm.c tests/vm/qsort.c \ -tests/lib.c -tests/vm/child-sort_SRC = tests/vm/child-sort.c tests/lib.c -tests/vm/child-mm-wrt_SRC = tests/vm/child-mm-wrt.c tests/lib.c tests/main.c -tests/vm/child-inherit_SRC = tests/vm/child-inherit.c tests/lib.c tests/main.c - -tests/vm/pt-bad-read_PUTFILES = tests/vm/sample.txt -tests/vm/pt-write-code2_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-close_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-read_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-unmap_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-twice_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-overlap_PUTFILES = tests/vm/zeros -tests/vm/mmap-exit_PUTFILES = tests/vm/child-mm-wrt -tests/vm/page-parallel_PUTFILES = tests/vm/child-linear -tests/vm/page-merge-seq_PUTFILES = tests/vm/child-sort -tests/vm/page-merge-par_PUTFILES = tests/vm/child-sort -tests/vm/page-merge-stk_PUTFILES = tests/vm/child-qsort -tests/vm/page-merge-mm_PUTFILES = tests/vm/child-qsort-mm -tests/vm/mmap-clean_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-inherit_PUTFILES = tests/vm/sample.txt tests/vm/child-inherit -tests/vm/mmap-misalign_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-null_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-over-code_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-over-data_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-over-stk_PUTFILES = tests/vm/sample.txt -tests/vm/mmap-remove_PUTFILES = tests/vm/sample.txt - -tests/vm/page-linear.output: TIMEOUT = 300 -tests/vm/page-shuffle.output: TIMEOUT = 600 -tests/vm/mmap-shuffle.output: TIMEOUT = 600 -tests/vm/page-merge-seq.output: TIMEOUT = 600 -tests/vm/page-merge-par.output: TIMEOUT = 600 - -tests/vm/zeros: - dd if=/dev/zero of=$@ bs=1024 count=6 - -clean:: - rm -f tests/vm/zeros diff --git a/src/tests/vm/Rubric.functionality b/src/tests/vm/Rubric.functionality deleted file mode 100644 index 8a8661290c6e31a1937418ea0d5b33b1038b18ab..0000000000000000000000000000000000000000 --- a/src/tests/vm/Rubric.functionality +++ /dev/null @@ -1,30 +0,0 @@ -Functionality of virtual memory subsystem: -- Test stack growth. -3 pt-grow-stack -3 pt-grow-stk-sc -3 pt-big-stk-obj -3 pt-grow-pusha - -- Test paging behavior. -3 page-linear -3 page-parallel -3 page-shuffle -4 page-merge-seq -4 page-merge-par -4 page-merge-mm -4 page-merge-stk - -- Test "mmap" system call. -2 mmap-read -2 mmap-write -2 mmap-shuffle - -2 mmap-twice - -2 mmap-unmap -1 mmap-exit - -3 mmap-clean - -2 mmap-close -2 mmap-remove diff --git a/src/tests/vm/Rubric.robustness b/src/tests/vm/Rubric.robustness deleted file mode 100644 index 0b2552f29852e4e1121d99ddd8ed7537aa414abc..0000000000000000000000000000000000000000 --- a/src/tests/vm/Rubric.robustness +++ /dev/null @@ -1,21 +0,0 @@ -Robustness of virtual memory subsystem: -- Test robustness of page table support. -2 pt-bad-addr -3 pt-bad-read -2 pt-write-code -3 pt-write-code2 -4 pt-grow-bad - -- Test robustness of "mmap" system call. -1 mmap-bad-fd -1 mmap-inherit -1 mmap-null -1 mmap-zero - -2 mmap-misalign - -2 mmap-over-code -2 mmap-over-data -2 mmap-over-stk -2 mmap-overlap - diff --git a/src/tests/vm/child-inherit.c b/src/tests/vm/child-inherit.c deleted file mode 100644 index d3186a1bfbf72ab8a677f5d306b447f8a2d79b08..0000000000000000000000000000000000000000 --- a/src/tests/vm/child-inherit.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Child process for mmap-inherit test. - Tries to write to a mapping present in the parent. - The process must be terminated with -1 exit code. */ - -#include <string.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - memset ((char *) 0x54321000, 0, 4096); - fail ("child can modify parent's memory mappings"); -} - diff --git a/src/tests/vm/child-linear.c b/src/tests/vm/child-linear.c deleted file mode 100644 index eca3e3f5a19dac0305319104ae15f5e8cb0e7ea5..0000000000000000000000000000000000000000 --- a/src/tests/vm/child-linear.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Child process of page-parallel. - Encrypts 1 MB of zeros, then decrypts it, and ensures that - the zeros are back. */ - -#include <string.h> -#include "tests/arc4.h" -#include "tests/lib.h" -#include "tests/main.h" - -const char *test_name = "child-linear"; - -#define SIZE (1024 * 1024) -static char buf[SIZE]; - -int -main (int argc, char *argv[]) -{ - const char *key = argv[argc - 1]; - struct arc4 arc4; - size_t i; - - /* Encrypt zeros. */ - arc4_init (&arc4, key, strlen (key)); - arc4_crypt (&arc4, buf, SIZE); - - /* Decrypt back to zeros. */ - arc4_init (&arc4, key, strlen (key)); - arc4_crypt (&arc4, buf, SIZE); - - /* Check that it's all zeros. */ - for (i = 0; i < SIZE; i++) - if (buf[i] != '\0') - fail ("byte %zu != 0", i); - - return 0x42; -} diff --git a/src/tests/vm/child-mm-wrt.c b/src/tests/vm/child-mm-wrt.c deleted file mode 100644 index 8419788f79866df3db1f2b396e8c2092ebfdf1f2..0000000000000000000000000000000000000000 --- a/src/tests/vm/child-mm-wrt.c +++ /dev/null @@ -1,24 +0,0 @@ -/* Child process of mmap-exit. - Mmaps a file and writes to it via the mmap'ing, then exits - without calling munmap. The data in the mapped region must be - written out at program termination. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -#define ACTUAL ((void *) 0x10000000) - -void -test_main (void) -{ - int handle; - - CHECK (create ("sample.txt", sizeof sample), "create \"sample.txt\""); - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (mmap (handle, ACTUAL) != MAP_FAILED, "mmap \"sample.txt\""); - memcpy (ACTUAL, sample, sizeof sample); -} - diff --git a/src/tests/vm/child-qsort-mm.c b/src/tests/vm/child-qsort-mm.c deleted file mode 100644 index db45499615db12f6bf0c2fb8c081b22c3f7cb3ef..0000000000000000000000000000000000000000 --- a/src/tests/vm/child-qsort-mm.c +++ /dev/null @@ -1,25 +0,0 @@ -/* Mmaps a 128 kB file "sorts" the bytes in it, using quick sort, - a multi-pass divide and conquer algorithm. */ - -#include <debug.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" -#include "tests/vm/qsort.h" - -const char *test_name = "child-qsort-mm"; - -int -main (int argc UNUSED, char *argv[]) -{ - int handle; - unsigned char *p = (unsigned char *) 0x10000000; - - quiet = true; - - CHECK ((handle = open (argv[1])) > 1, "open \"%s\"", argv[1]); - CHECK (mmap (handle, p) != MAP_FAILED, "mmap \"%s\"", argv[1]); - qsort_bytes (p, 1024 * 128); - - return 80; -} diff --git a/src/tests/vm/child-qsort.c b/src/tests/vm/child-qsort.c deleted file mode 100644 index 355f4ebfb2b3f5dd62cb8b83575d8296059a852b..0000000000000000000000000000000000000000 --- a/src/tests/vm/child-qsort.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Reads a 128 kB file onto the stack and "sorts" the bytes in - it, using quick sort, a multi-pass divide and conquer - algorithm. The sorted data is written back to the same file - in-place. */ - -#include <debug.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" -#include "tests/vm/qsort.h" - -const char *test_name = "child-qsort"; - -int -main (int argc UNUSED, char *argv[]) -{ - int handle; - unsigned char buf[128 * 1024]; - size_t size; - - quiet = true; - - CHECK ((handle = open (argv[1])) > 1, "open \"%s\"", argv[1]); - - size = read (handle, buf, sizeof buf); - qsort_bytes (buf, sizeof buf); - seek (handle, 0); - write (handle, buf, size); - close (handle); - - return 72; -} diff --git a/src/tests/vm/child-sort.c b/src/tests/vm/child-sort.c deleted file mode 100644 index dff2c772050167e4227f314e6fdea2e34b5c4437..0000000000000000000000000000000000000000 --- a/src/tests/vm/child-sort.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Reads a 128 kB file into static data and "sorts" the bytes in - it, using counting sort, a single-pass algorithm. The sorted - data is written back to the same file in-place. */ - -#include <debug.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -const char *test_name = "child-sort"; - -unsigned char buf[128 * 1024]; -size_t histogram[256]; - -int -main (int argc UNUSED, char *argv[]) -{ - int handle; - unsigned char *p; - size_t size; - size_t i; - - quiet = true; - - CHECK ((handle = open (argv[1])) > 1, "open \"%s\"", argv[1]); - - size = read (handle, buf, sizeof buf); - for (i = 0; i < size; i++) - histogram[buf[i]]++; - p = buf; - for (i = 0; i < sizeof histogram / sizeof *histogram; i++) - { - size_t j = histogram[i]; - while (j-- > 0) - *p++ = i; - } - seek (handle, 0); - write (handle, buf, size); - close (handle); - - return 123; -} diff --git a/src/tests/vm/mmap-bad-fd.c b/src/tests/vm/mmap-bad-fd.c deleted file mode 100644 index 76a7b50e1092bc95f29d067c353a470dd5fac368..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-bad-fd.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Tries to mmap an invalid fd, - which must either fail silently or terminate the process with - exit code -1. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - CHECK (mmap (0x5678, (void *) 0x10000000) == MAP_FAILED, - "try to mmap invalid fd"); -} - diff --git a/src/tests/vm/mmap-bad-fd.ck b/src/tests/vm/mmap-bad-fd.ck deleted file mode 100644 index f3f58d577994d2a05bda9396eae9df81d4cd110f..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-bad-fd.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF', <<'EOF']); -(mmap-bad-fd) begin -(mmap-bad-fd) try to mmap invalid fd -(mmap-bad-fd) end -mmap-bad-fd: exit(0) -EOF -(mmap-bad-fd) begin -(mmap-bad-fd) try to mmap invalid fd -mmap-bad-fd: exit(-1) -EOF -pass; diff --git a/src/tests/vm/mmap-clean.c b/src/tests/vm/mmap-clean.c deleted file mode 100644 index ea1dc9cb09ba54c795ee298c03eca32cfce4928c..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-clean.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Verifies that mmap'd regions are only written back on munmap - if the data was actually modified in memory. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - static const char overwrite[] = "Now is the time for all good..."; - static char buffer[sizeof sample - 1]; - char *actual = (char *) 0x54321000; - int handle; - mapid_t map; - - /* Open file, map, verify data. */ - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK ((map = mmap (handle, actual)) != MAP_FAILED, "mmap \"sample.txt\""); - if (memcmp (actual, sample, strlen (sample))) - fail ("read of mmap'd file reported bad data"); - - /* Modify file. */ - CHECK (write (handle, overwrite, strlen (overwrite)) - == (int) strlen (overwrite), - "write \"sample.txt\""); - - /* Close mapping. Data should not be written back, because we - didn't modify it via the mapping. */ - msg ("munmap \"sample.txt\""); - munmap (map); - - /* Read file back. */ - msg ("seek \"sample.txt\""); - seek (handle, 0); - CHECK (read (handle, buffer, sizeof buffer) == sizeof buffer, - "read \"sample.txt\""); - - /* Verify that file overwrite worked. */ - if (memcmp (buffer, overwrite, strlen (overwrite)) - || memcmp (buffer + strlen (overwrite), sample + strlen (overwrite), - strlen (sample) - strlen (overwrite))) - { - if (!memcmp (buffer, sample, strlen (sample))) - fail ("munmap wrote back clean page"); - else - fail ("read surprising data from file"); - } - else - msg ("file change was retained after munmap"); -} diff --git a/src/tests/vm/mmap-clean.ck b/src/tests/vm/mmap-clean.ck deleted file mode 100644 index 1666d6cd469b93d1190681cae13bd8b51f24a221..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-clean.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-clean) begin -(mmap-clean) open "sample.txt" -(mmap-clean) mmap "sample.txt" -(mmap-clean) write "sample.txt" -(mmap-clean) munmap "sample.txt" -(mmap-clean) seek "sample.txt" -(mmap-clean) read "sample.txt" -(mmap-clean) file change was retained after munmap -(mmap-clean) end -EOF -pass; diff --git a/src/tests/vm/mmap-close.c b/src/tests/vm/mmap-close.c deleted file mode 100644 index d016ee304cdd2ddc86ae399d744866dbe8caf9f7..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-close.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Verifies that memory mappings persist after file close. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/arc4.h" -#include "tests/lib.h" -#include "tests/main.h" - -#define ACTUAL ((void *) 0x10000000) - -void -test_main (void) -{ - int handle; - mapid_t map; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK ((map = mmap (handle, ACTUAL)) != MAP_FAILED, "mmap \"sample.txt\""); - - close (handle); - - if (memcmp (ACTUAL, sample, strlen (sample))) - fail ("read of mmap'd file reported bad data"); - - munmap (map); -} diff --git a/src/tests/vm/mmap-close.ck b/src/tests/vm/mmap-close.ck deleted file mode 100644 index d15e41ae7ba255217ed947ccf95f87d4693456ff..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-close.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-close) begin -(mmap-close) open "sample.txt" -(mmap-close) mmap "sample.txt" -(mmap-close) end -EOF -pass; diff --git a/src/tests/vm/mmap-exit.c b/src/tests/vm/mmap-exit.c deleted file mode 100644 index 7a2278a516a88b6ffba0749e041069f50bef3a36..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-exit.c +++ /dev/null @@ -1,22 +0,0 @@ -/* Executes child-mm-wrt and verifies that the writes that should - have occurred really did. */ - -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - pid_t child; - - /* Make child write file. */ - quiet = true; - CHECK ((child = exec ("child-mm-wrt")) != -1, "exec \"child-mm-wrt\""); - CHECK (wait (child) == 0, "wait for child (should return 0)"); - quiet = false; - - /* Check file contents. */ - check_file ("sample.txt", sample, sizeof sample); -} diff --git a/src/tests/vm/mmap-exit.ck b/src/tests/vm/mmap-exit.ck deleted file mode 100644 index 457d34a029b8854a31690d9b12000ad09b2f71e4..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-exit.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-exit) begin -(child-mm-wrt) begin -(child-mm-wrt) create "sample.txt" -(child-mm-wrt) open "sample.txt" -(child-mm-wrt) mmap "sample.txt" -(child-mm-wrt) end -(mmap-exit) open "sample.txt" for verification -(mmap-exit) verified contents of "sample.txt" -(mmap-exit) close "sample.txt" -(mmap-exit) end -EOF -pass; diff --git a/src/tests/vm/mmap-inherit.c b/src/tests/vm/mmap-inherit.c deleted file mode 100644 index 7fa9607c41f78c495e75d2a8be30be9647d7e7b5..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-inherit.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Maps a file into memory and runs child-inherit to verify that - mappings are not inherited. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char *actual = (char *) 0x54321000; - int handle; - pid_t child; - - /* Open file, map, verify data. */ - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (mmap (handle, actual) != MAP_FAILED, "mmap \"sample.txt\""); - if (memcmp (actual, sample, strlen (sample))) - fail ("read of mmap'd file reported bad data"); - - /* Spawn child and wait. */ - CHECK ((child = exec ("child-inherit")) != -1, "exec \"child-inherit\""); - quiet = true; - CHECK (wait (child) == -1, "wait for child (should return -1)"); - quiet = false; - - /* Verify data again. */ - CHECK (!memcmp (actual, sample, strlen (sample)), - "checking that mmap'd file still has same data"); -} diff --git a/src/tests/vm/mmap-inherit.ck b/src/tests/vm/mmap-inherit.ck deleted file mode 100644 index c54638a0f928645dd904032b55079d0d123510b2..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-inherit.ck +++ /dev/null @@ -1,16 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(mmap-inherit) begin -(mmap-inherit) open "sample.txt" -(mmap-inherit) mmap "sample.txt" -(mmap-inherit) exec "child-inherit" -(child-inherit) begin -child-inherit: exit(-1) -(mmap-inherit) checking that mmap'd file still has same data -(mmap-inherit) end -mmap-inherit: exit(0) -EOF -pass; diff --git a/src/tests/vm/mmap-misalign.c b/src/tests/vm/mmap-misalign.c deleted file mode 100644 index 34141a9e027f1b9d85ae94d548a52bd6bcbb383c..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-misalign.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Verifies that misaligned memory mappings are disallowed. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (mmap (handle, (void *) 0x10001234) == MAP_FAILED, - "try to mmap at misaligned address"); -} - diff --git a/src/tests/vm/mmap-misalign.ck b/src/tests/vm/mmap-misalign.ck deleted file mode 100644 index 145a2e895db69ce129677e816156d620af54189c..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-misalign.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-misalign) begin -(mmap-misalign) open "sample.txt" -(mmap-misalign) try to mmap at misaligned address -(mmap-misalign) end -EOF -pass; diff --git a/src/tests/vm/mmap-null.c b/src/tests/vm/mmap-null.c deleted file mode 100644 index f8ef075a0e59273b13ad4a2cded6e834ac4d7857..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-null.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Verifies that memory mappings at address 0 are disallowed. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (mmap (handle, NULL) == MAP_FAILED, "try to mmap at address 0"); -} - diff --git a/src/tests/vm/mmap-null.ck b/src/tests/vm/mmap-null.ck deleted file mode 100644 index aacdd65f524be22822f80dd485e9879984303faf..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-null.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-null) begin -(mmap-null) open "sample.txt" -(mmap-null) try to mmap at address 0 -(mmap-null) end -EOF -pass; diff --git a/src/tests/vm/mmap-over-code.c b/src/tests/vm/mmap-over-code.c deleted file mode 100644 index d3619a3ecc6b2048369b4020eec303545f11a7ad..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-over-code.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Verifies that mapping over the code segment is disallowed. */ - -#include <stdint.h> -#include <round.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - uintptr_t test_main_page = ROUND_DOWN ((uintptr_t) test_main, 4096); - int handle; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (mmap (handle, (void *) test_main_page) == MAP_FAILED, - "try to mmap over code segment"); -} - diff --git a/src/tests/vm/mmap-over-code.ck b/src/tests/vm/mmap-over-code.ck deleted file mode 100644 index b5b23c7b9930f458cff3ae209e64bd41d46c7499..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-over-code.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-over-code) begin -(mmap-over-code) open "sample.txt" -(mmap-over-code) try to mmap over code segment -(mmap-over-code) end -EOF -pass; diff --git a/src/tests/vm/mmap-over-data.c b/src/tests/vm/mmap-over-data.c deleted file mode 100644 index 9ea5d492e631f0049959e9740a459896197a7bcc..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-over-data.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Verifies that mapping over the data segment is disallowed. */ - -#include <stdint.h> -#include <round.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -static char x; - -void -test_main (void) -{ - uintptr_t x_page = ROUND_DOWN ((uintptr_t) &x, 4096); - int handle; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (mmap (handle, (void *) x_page) == MAP_FAILED, - "try to mmap over data segment"); -} - diff --git a/src/tests/vm/mmap-over-data.ck b/src/tests/vm/mmap-over-data.ck deleted file mode 100644 index 98770cccf6e66faa49d2e4c73bc7ad5ac152a8b5..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-over-data.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-over-data) begin -(mmap-over-data) open "sample.txt" -(mmap-over-data) try to mmap over data segment -(mmap-over-data) end -EOF -pass; diff --git a/src/tests/vm/mmap-over-stk.c b/src/tests/vm/mmap-over-stk.c deleted file mode 100644 index 4e241e8b15ba9abf83faa2806275bb0e97e1a4ee..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-over-stk.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Verifies that mapping over the stack segment is disallowed. */ - -#include <stdint.h> -#include <round.h> -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - uintptr_t handle_page = ROUND_DOWN ((uintptr_t) &handle, 4096); - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (mmap (handle, (void *) handle_page) == MAP_FAILED, - "try to mmap over stack segment"); -} - diff --git a/src/tests/vm/mmap-over-stk.ck b/src/tests/vm/mmap-over-stk.ck deleted file mode 100644 index e6880cfbe58497e8020edfc595598176efd6e0a7..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-over-stk.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-over-stk) begin -(mmap-over-stk) open "sample.txt" -(mmap-over-stk) try to mmap over stack segment -(mmap-over-stk) end -EOF -pass; diff --git a/src/tests/vm/mmap-overlap.c b/src/tests/vm/mmap-overlap.c deleted file mode 100644 index 668ae5f0f69fe163c6157c2c46d60f76749cd3bf..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-overlap.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Verifies that overlapping memory mappings are disallowed. */ - -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char *start = (char *) 0x10000000; - int fd[2]; - - CHECK ((fd[0] = open ("zeros")) > 1, "open \"zeros\" once"); - CHECK (mmap (fd[0], start) != MAP_FAILED, "mmap \"zeros\""); - CHECK ((fd[1] = open ("zeros")) > 1 && fd[0] != fd[1], - "open \"zeros\" again"); - CHECK (mmap (fd[1], start + 4096) == MAP_FAILED, - "try to mmap \"zeros\" again"); -} diff --git a/src/tests/vm/mmap-overlap.ck b/src/tests/vm/mmap-overlap.ck deleted file mode 100644 index f13801e7a806226ce90d88bb3bd8926591c9ef57..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-overlap.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-overlap) begin -(mmap-overlap) open "zeros" once -(mmap-overlap) mmap "zeros" -(mmap-overlap) open "zeros" again -(mmap-overlap) try to mmap "zeros" again -(mmap-overlap) end -EOF -pass; diff --git a/src/tests/vm/mmap-read.c b/src/tests/vm/mmap-read.c deleted file mode 100644 index c0f23a1a3111cdbb113c152789a052852238ecdb..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-read.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Uses a memory mapping to read a file. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char *actual = (char *) 0x10000000; - int handle; - mapid_t map; - size_t i; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK ((map = mmap (handle, actual)) != MAP_FAILED, "mmap \"sample.txt\""); - - /* Check that data is correct. */ - if (memcmp (actual, sample, strlen (sample))) - fail ("read of mmap'd file reported bad data"); - - /* Verify that data is followed by zeros. */ - for (i = strlen (sample); i < 4096; i++) - if (actual[i] != 0) - fail ("byte %zu of mmap'd region has value %02hhx (should be 0)", - i, actual[i]); - - munmap (map); - close (handle); -} diff --git a/src/tests/vm/mmap-read.ck b/src/tests/vm/mmap-read.ck deleted file mode 100644 index 95ab7901abfe297f10b9c5eb6f67a6525bad05f9..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-read.ck +++ /dev/null @@ -1,11 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-read) begin -(mmap-read) open "sample.txt" -(mmap-read) mmap "sample.txt" -(mmap-read) end -EOF -pass; diff --git a/src/tests/vm/mmap-remove.c b/src/tests/vm/mmap-remove.c deleted file mode 100644 index 5f7444d99b7a25ccc8260d0d9cd6e05a95c287d5..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-remove.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Deletes and closes file that is mapped into memory - and verifies that it can still be read through the mapping. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char *actual = (char *) 0x10000000; - int handle; - mapid_t map; - size_t i; - - /* Map file. */ - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK ((map = mmap (handle, actual)) != MAP_FAILED, "mmap \"sample.txt\""); - - /* Close file and delete it. */ - close (handle); - CHECK (remove ("sample.txt"), "remove \"sample.txt\""); - CHECK (open ("sample.txt") == -1, "try to open \"sample.txt\""); - - /* Create a new file in hopes of overwriting data from the old - one, in case the file system has incorrectly freed the - file's data. */ - CHECK (create ("another", 4096 * 10), "create \"another\""); - - /* Check that mapped data is correct. */ - if (memcmp (actual, sample, strlen (sample))) - fail ("read of mmap'd file reported bad data"); - - /* Verify that data is followed by zeros. */ - for (i = strlen (sample); i < 4096; i++) - if (actual[i] != 0) - fail ("byte %zu of mmap'd region has value %02hhx (should be 0)", - i, actual[i]); - - munmap (map); -} diff --git a/src/tests/vm/mmap-remove.ck b/src/tests/vm/mmap-remove.ck deleted file mode 100644 index d3cc93847d0e0a64b0214d4ac47c5968361600fe..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-remove.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-remove) begin -(mmap-remove) open "sample.txt" -(mmap-remove) mmap "sample.txt" -(mmap-remove) remove "sample.txt" -(mmap-remove) try to open "sample.txt" -(mmap-remove) create "another" -(mmap-remove) end -EOF -pass; diff --git a/src/tests/vm/mmap-shuffle.c b/src/tests/vm/mmap-shuffle.c deleted file mode 100644 index 29921ad2919e74257428efe628d344e954fdcde2..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-shuffle.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Creates a 128 kB file and repeatedly shuffles data in it - through a memory mapping. */ - -#include <stdio.h> -#include <string.h> -#include <syscall.h> -#include "tests/arc4.h" -#include "tests/cksum.h" -#include "tests/lib.h" -#include "tests/main.h" - -#define SIZE (128 * 1024) - -static char *buf = (char *) 0x10000000; - -void -test_main (void) -{ - size_t i; - int handle; - - /* Create file, mmap. */ - CHECK (create ("buffer", SIZE), "create \"buffer\""); - CHECK ((handle = open ("buffer")) > 1, "open \"buffer\""); - CHECK (mmap (handle, buf) != MAP_FAILED, "mmap \"buffer\""); - - /* Initialize. */ - for (i = 0; i < SIZE; i++) - buf[i] = i * 257; - msg ("init: cksum=%lu", cksum (buf, SIZE)); - - /* Shuffle repeatedly. */ - for (i = 0; i < 10; i++) - { - shuffle (buf, SIZE, 1); - msg ("shuffle %zu: cksum=%lu", i, cksum (buf, SIZE)); - } -} diff --git a/src/tests/vm/mmap-shuffle.ck b/src/tests/vm/mmap-shuffle.ck deleted file mode 100644 index c15830170311a2dc78429351b2f1ef963b30a74e..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-shuffle.ck +++ /dev/null @@ -1,47 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::cksum; -use tests::lib; - -my ($init, @shuffle); -if (1) { - # Use precalculated values. - $init = 3115322833; - @shuffle = (1691062564, 1973575879, 1647619479, 96566261, 3885786467, - 3022003332, 3614934266, 2704001777, 735775156, 1864109763); -} else { - # Recalculate values. - my ($buf) = ""; - for my $i (0...128 * 1024 - 1) { - $buf .= chr (($i * 257) & 0xff); - } - $init = cksum ($buf); - - random_init (0); - for my $i (1...10) { - $buf = shuffle ($buf, length ($buf), 1); - push (@shuffle, cksum ($buf)); - } -} - -check_expected (IGNORE_EXIT_CODES => 1, [<<EOF]); -(mmap-shuffle) begin -(mmap-shuffle) create "buffer" -(mmap-shuffle) open "buffer" -(mmap-shuffle) mmap "buffer" -(mmap-shuffle) init: cksum=$init -(mmap-shuffle) shuffle 0: cksum=$shuffle[0] -(mmap-shuffle) shuffle 1: cksum=$shuffle[1] -(mmap-shuffle) shuffle 2: cksum=$shuffle[2] -(mmap-shuffle) shuffle 3: cksum=$shuffle[3] -(mmap-shuffle) shuffle 4: cksum=$shuffle[4] -(mmap-shuffle) shuffle 5: cksum=$shuffle[5] -(mmap-shuffle) shuffle 6: cksum=$shuffle[6] -(mmap-shuffle) shuffle 7: cksum=$shuffle[7] -(mmap-shuffle) shuffle 8: cksum=$shuffle[8] -(mmap-shuffle) shuffle 9: cksum=$shuffle[9] -(mmap-shuffle) end -EOF -pass; diff --git a/src/tests/vm/mmap-twice.c b/src/tests/vm/mmap-twice.c deleted file mode 100644 index d277a37272fa61bfce5b60f72d50909612084be1..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-twice.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Maps the same file into memory twice and verifies that the - same data is readable in both. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char *actual[2] = {(char *) 0x10000000, (char *) 0x20000000}; - size_t i; - int handle[2]; - - for (i = 0; i < 2; i++) - { - CHECK ((handle[i] = open ("sample.txt")) > 1, - "open \"sample.txt\" #%zu", i); - CHECK (mmap (handle[i], actual[i]) != MAP_FAILED, - "mmap \"sample.txt\" #%zu at %p", i, (void *) actual[i]); - } - - for (i = 0; i < 2; i++) - CHECK (!memcmp (actual[i], sample, strlen (sample)), - "compare mmap'd file %zu against data", i); -} diff --git a/src/tests/vm/mmap-twice.ck b/src/tests/vm/mmap-twice.ck deleted file mode 100644 index 05e972459e7e83c9eea89a9c81153200a303873f..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-twice.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-twice) begin -(mmap-twice) open "sample.txt" #0 -(mmap-twice) mmap "sample.txt" #0 at 0x10000000 -(mmap-twice) open "sample.txt" #1 -(mmap-twice) mmap "sample.txt" #1 at 0x20000000 -(mmap-twice) compare mmap'd file 0 against data -(mmap-twice) compare mmap'd file 1 against data -(mmap-twice) end -EOF -pass; diff --git a/src/tests/vm/mmap-unmap.c b/src/tests/vm/mmap-unmap.c deleted file mode 100644 index d35a79efc128c1a5be38cc13f0def7f0f953669e..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-unmap.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Maps and unmaps a file and verifies that the mapped region is - inaccessible afterward. */ - -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -#define ACTUAL ((void *) 0x10000000) - -void -test_main (void) -{ - int handle; - mapid_t map; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK ((map = mmap (handle, ACTUAL)) != MAP_FAILED, "mmap \"sample.txt\""); - - munmap (map); - - fail ("unmapped memory is readable (%d)", *(int *) ACTUAL); -} diff --git a/src/tests/vm/mmap-unmap.ck b/src/tests/vm/mmap-unmap.ck deleted file mode 100644 index 119658c68108451aa1964298cd8e8f513b275bc8..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-unmap.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::vm::process_death; - -check_process_death ('mmap-unmap'); diff --git a/src/tests/vm/mmap-write.c b/src/tests/vm/mmap-write.c deleted file mode 100644 index 46e804349367aab3c0259bdf1f5ff87dddc1d2be..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-write.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Writes to a file through a mapping, and unmaps the file, - then reads the data in the file back using the read system - call to verify. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -#define ACTUAL ((void *) 0x10000000) - -void -test_main (void) -{ - int handle; - mapid_t map; - char buf[1024]; - - /* Write file via mmap. */ - CHECK (create ("sample.txt", strlen (sample)), "create \"sample.txt\""); - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK ((map = mmap (handle, ACTUAL)) != MAP_FAILED, "mmap \"sample.txt\""); - memcpy (ACTUAL, sample, strlen (sample)); - munmap (map); - - /* Read back via read(). */ - read (handle, buf, strlen (sample)); - CHECK (!memcmp (buf, sample, strlen (sample)), - "compare read data against written data"); - close (handle); -} diff --git a/src/tests/vm/mmap-write.ck b/src/tests/vm/mmap-write.ck deleted file mode 100644 index d2c9cc511f43da3eb8f0910477925757310efd6d..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-write.ck +++ /dev/null @@ -1,13 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(mmap-write) begin -(mmap-write) create "sample.txt" -(mmap-write) open "sample.txt" -(mmap-write) mmap "sample.txt" -(mmap-write) compare read data against written data -(mmap-write) end -EOF -pass; diff --git a/src/tests/vm/mmap-zero.c b/src/tests/vm/mmap-zero.c deleted file mode 100644 index 368b759d48e0d989253a145de2c55c3f7b6ad066..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-zero.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Tries to map a zero-length file, which may or may not work but - should not terminate the process or crash. - Then dereferences the address that we tried to map, - and the process must be terminated with -1 exit code. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char *data = (char *) 0x7f000000; - int handle; - - CHECK (create ("empty", 0), "create empty file \"empty\""); - CHECK ((handle = open ("empty")) > 1, "open \"empty\""); - - /* Calling mmap() might succeed or fail. We don't care. */ - msg ("mmap \"empty\""); - mmap (handle, data); - - /* Regardless of whether the call worked, *data should cause - the process to be terminated. */ - fail ("unmapped memory is readable (%d)", *data); -} - diff --git a/src/tests/vm/mmap-zero.ck b/src/tests/vm/mmap-zero.ck deleted file mode 100644 index 6033d5d34f0404784bb3d379229fdf14eeed5516..0000000000000000000000000000000000000000 --- a/src/tests/vm/mmap-zero.ck +++ /dev/null @@ -1,12 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(mmap-zero) begin -(mmap-zero) create empty file "empty" -(mmap-zero) open "empty" -(mmap-zero) mmap "empty" -mmap-zero: exit(-1) -EOF -pass; diff --git a/src/tests/vm/page-linear.c b/src/tests/vm/page-linear.c deleted file mode 100644 index 652a47b36c8e83e203b9dfe968b1aae67a113fcb..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-linear.c +++ /dev/null @@ -1,44 +0,0 @@ -/* Encrypts, then decrypts, 2 MB of memory and verifies that the - values are as they should be. */ - -#include <string.h> -#include "tests/arc4.h" -#include "tests/lib.h" -#include "tests/main.h" - -#define SIZE (2 * 1024 * 1024) - -static char buf[SIZE]; - -void -test_main (void) -{ - struct arc4 arc4; - size_t i; - - /* Initialize to 0x5a. */ - msg ("initialize"); - memset (buf, 0x5a, sizeof buf); - - /* Check that it's all 0x5a. */ - msg ("read pass"); - for (i = 0; i < SIZE; i++) - if (buf[i] != 0x5a) - fail ("byte %zu != 0x5a", i); - - /* Encrypt zeros. */ - msg ("read/modify/write pass one"); - arc4_init (&arc4, "foobar", 6); - arc4_crypt (&arc4, buf, SIZE); - - /* Decrypt back to zeros. */ - msg ("read/modify/write pass two"); - arc4_init (&arc4, "foobar", 6); - arc4_crypt (&arc4, buf, SIZE); - - /* Check that it's all 0x5a. */ - msg ("read pass"); - for (i = 0; i < SIZE; i++) - if (buf[i] != 0x5a) - fail ("byte %zu != 0x5a", i); -} diff --git a/src/tests/vm/page-linear.ck b/src/tests/vm/page-linear.ck deleted file mode 100644 index dcbc8843efa2571e63f99a7c9530b004010d2e4c..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-linear.ck +++ /dev/null @@ -1,14 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(page-linear) begin -(page-linear) initialize -(page-linear) read pass -(page-linear) read/modify/write pass one -(page-linear) read/modify/write pass two -(page-linear) read pass -(page-linear) end -EOF -pass; diff --git a/src/tests/vm/page-merge-mm.c b/src/tests/vm/page-merge-mm.c deleted file mode 100644 index 908c71c61d916fcf25317c0072ff9c5eb6496930..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-mm.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "tests/main.h" -#include "tests/vm/parallel-merge.h" - -void -test_main (void) -{ - parallel_merge ("child-qsort-mm", 80); -} diff --git a/src/tests/vm/page-merge-mm.ck b/src/tests/vm/page-merge-mm.ck deleted file mode 100644 index 74fa980fb73d8e102a2cd61503a1ddcd6b7aa471..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-mm.ck +++ /dev/null @@ -1,29 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(page-merge-mm) begin -(page-merge-mm) init -(page-merge-mm) sort chunk 0 -(page-merge-mm) sort chunk 1 -(page-merge-mm) sort chunk 2 -(page-merge-mm) sort chunk 3 -(page-merge-mm) sort chunk 4 -(page-merge-mm) sort chunk 5 -(page-merge-mm) sort chunk 6 -(page-merge-mm) sort chunk 7 -(page-merge-mm) wait for child 0 -(page-merge-mm) wait for child 1 -(page-merge-mm) wait for child 2 -(page-merge-mm) wait for child 3 -(page-merge-mm) wait for child 4 -(page-merge-mm) wait for child 5 -(page-merge-mm) wait for child 6 -(page-merge-mm) wait for child 7 -(page-merge-mm) merge -(page-merge-mm) verify -(page-merge-mm) success, buf_idx=1,048,576 -(page-merge-mm) end -EOF -pass; diff --git a/src/tests/vm/page-merge-par.c b/src/tests/vm/page-merge-par.c deleted file mode 100644 index e7e16093ce12c3ca1cd3aac33ebf46afba34f4a6..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-par.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "tests/main.h" -#include "tests/vm/parallel-merge.h" - -void -test_main (void) -{ - parallel_merge ("child-sort", 123); -} diff --git a/src/tests/vm/page-merge-par.ck b/src/tests/vm/page-merge-par.ck deleted file mode 100644 index 31f8aa7dc3f7cb3b02fa6ed40336f6de25c074fb..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-par.ck +++ /dev/null @@ -1,29 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(page-merge-par) begin -(page-merge-par) init -(page-merge-par) sort chunk 0 -(page-merge-par) sort chunk 1 -(page-merge-par) sort chunk 2 -(page-merge-par) sort chunk 3 -(page-merge-par) sort chunk 4 -(page-merge-par) sort chunk 5 -(page-merge-par) sort chunk 6 -(page-merge-par) sort chunk 7 -(page-merge-par) wait for child 0 -(page-merge-par) wait for child 1 -(page-merge-par) wait for child 2 -(page-merge-par) wait for child 3 -(page-merge-par) wait for child 4 -(page-merge-par) wait for child 5 -(page-merge-par) wait for child 6 -(page-merge-par) wait for child 7 -(page-merge-par) merge -(page-merge-par) verify -(page-merge-par) success, buf_idx=1,048,576 -(page-merge-par) end -EOF -pass; diff --git a/src/tests/vm/page-merge-seq.c b/src/tests/vm/page-merge-seq.c deleted file mode 100644 index 12e388093fd9b77b2f09e31ac70e4f1829bf72d4..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-seq.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Generates about 1 MB of random data that is then divided into - 16 chunks. A separate subprocess sorts each chunk in - sequence. Then we merge the chunks and verify that the result - is what it should be. */ - -#include <syscall.h> -#include "tests/arc4.h" -#include "tests/lib.h" -#include "tests/main.h" - -/* This is the max file size for an older version of the Pintos - file system that had 126 direct blocks each pointing to a - single disk sector. We could raise it now. */ -#define CHUNK_SIZE (126 * 512) -#define CHUNK_CNT 16 /* Number of chunks. */ -#define DATA_SIZE (CHUNK_CNT * CHUNK_SIZE) /* Buffer size. */ - -unsigned char buf1[DATA_SIZE], buf2[DATA_SIZE]; -size_t histogram[256]; - -/* Initialize buf1 with random data, - then count the number of instances of each value within it. */ -static void -init (void) -{ - struct arc4 arc4; - size_t i; - - msg ("init"); - - arc4_init (&arc4, "foobar", 6); - arc4_crypt (&arc4, buf1, sizeof buf1); - for (i = 0; i < sizeof buf1; i++) - histogram[buf1[i]]++; -} - -/* Sort each chunk of buf1 using a subprocess. */ -static void -sort_chunks (void) -{ - size_t i; - - create ("buffer", CHUNK_SIZE); - for (i = 0; i < CHUNK_CNT; i++) - { - pid_t child; - int handle; - - msg ("sort chunk %zu", i); - - /* Write this chunk to a file. */ - quiet = true; - CHECK ((handle = open ("buffer")) > 1, "open \"buffer\""); - write (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE); - close (handle); - - /* Sort with subprocess. */ - CHECK ((child = exec ("child-sort buffer")) != -1, - "exec \"child-sort buffer\""); - CHECK (wait (child) == 123, "wait for child-sort"); - - /* Read chunk back from file. */ - CHECK ((handle = open ("buffer")) > 1, "open \"buffer\""); - read (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE); - close (handle); - - quiet = false; - } -} - -/* Merge the sorted chunks in buf1 into a fully sorted buf2. */ -static void -merge (void) -{ - unsigned char *mp[CHUNK_CNT]; - size_t mp_left; - unsigned char *op; - size_t i; - - msg ("merge"); - - /* Initialize merge pointers. */ - mp_left = CHUNK_CNT; - for (i = 0; i < CHUNK_CNT; i++) - mp[i] = buf1 + CHUNK_SIZE * i; - - /* Merge. */ - op = buf2; - while (mp_left > 0) - { - /* Find smallest value. */ - size_t min = 0; - for (i = 1; i < mp_left; i++) - if (*mp[i] < *mp[min]) - min = i; - - /* Append value to buf2. */ - *op++ = *mp[min]; - - /* Advance merge pointer. - Delete this chunk from the set if it's emptied. */ - if ((++mp[min] - buf1) % CHUNK_SIZE == 0) - mp[min] = mp[--mp_left]; - } -} - -static void -verify (void) -{ - size_t buf_idx; - size_t hist_idx; - - msg ("verify"); - - buf_idx = 0; - for (hist_idx = 0; hist_idx < sizeof histogram / sizeof *histogram; - hist_idx++) - { - while (histogram[hist_idx]-- > 0) - { - if (buf2[buf_idx] != hist_idx) - fail ("bad value %d in byte %zu", buf2[buf_idx], buf_idx); - buf_idx++; - } - } - - msg ("success, buf_idx=%'zu", buf_idx); -} - -void -test_main (void) -{ - init (); - sort_chunks (); - merge (); - verify (); -} diff --git a/src/tests/vm/page-merge-seq.ck b/src/tests/vm/page-merge-seq.ck deleted file mode 100644 index d78f69da534a19813ba9d7bb3ab28b6095f3563f..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-seq.ck +++ /dev/null @@ -1,29 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(page-merge-seq) begin -(page-merge-seq) init -(page-merge-seq) sort chunk 0 -(page-merge-seq) sort chunk 1 -(page-merge-seq) sort chunk 2 -(page-merge-seq) sort chunk 3 -(page-merge-seq) sort chunk 4 -(page-merge-seq) sort chunk 5 -(page-merge-seq) sort chunk 6 -(page-merge-seq) sort chunk 7 -(page-merge-seq) sort chunk 8 -(page-merge-seq) sort chunk 9 -(page-merge-seq) sort chunk 10 -(page-merge-seq) sort chunk 11 -(page-merge-seq) sort chunk 12 -(page-merge-seq) sort chunk 13 -(page-merge-seq) sort chunk 14 -(page-merge-seq) sort chunk 15 -(page-merge-seq) merge -(page-merge-seq) verify -(page-merge-seq) success, buf_idx=1,032,192 -(page-merge-seq) end -EOF -pass; diff --git a/src/tests/vm/page-merge-stk.c b/src/tests/vm/page-merge-stk.c deleted file mode 100644 index 5eb1069575e7acfe94641deb49af6063a809f098..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-stk.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "tests/main.h" -#include "tests/vm/parallel-merge.h" - -void -test_main (void) -{ - parallel_merge ("child-qsort", 72); -} diff --git a/src/tests/vm/page-merge-stk.ck b/src/tests/vm/page-merge-stk.ck deleted file mode 100644 index c5bc1ae05db6efc3e1f7a87cab995bb91af367ff..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-merge-stk.ck +++ /dev/null @@ -1,29 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(page-merge-stk) begin -(page-merge-stk) init -(page-merge-stk) sort chunk 0 -(page-merge-stk) sort chunk 1 -(page-merge-stk) sort chunk 2 -(page-merge-stk) sort chunk 3 -(page-merge-stk) sort chunk 4 -(page-merge-stk) sort chunk 5 -(page-merge-stk) sort chunk 6 -(page-merge-stk) sort chunk 7 -(page-merge-stk) wait for child 0 -(page-merge-stk) wait for child 1 -(page-merge-stk) wait for child 2 -(page-merge-stk) wait for child 3 -(page-merge-stk) wait for child 4 -(page-merge-stk) wait for child 5 -(page-merge-stk) wait for child 6 -(page-merge-stk) wait for child 7 -(page-merge-stk) merge -(page-merge-stk) verify -(page-merge-stk) success, buf_idx=1,048,576 -(page-merge-stk) end -EOF -pass; diff --git a/src/tests/vm/page-parallel.c b/src/tests/vm/page-parallel.c deleted file mode 100644 index 9d619e0d644de8b7342f1300a9829a068eb14e86..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-parallel.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Runs 4 child-linear processes at once. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -#define CHILD_CNT 4 - -void -test_main (void) -{ - pid_t children[CHILD_CNT]; - int i; - - for (i = 0; i < CHILD_CNT; i++) - CHECK ((children[i] = exec ("child-linear")) != -1, - "exec \"child-linear\""); - - for (i = 0; i < CHILD_CNT; i++) - CHECK (wait (children[i]) == 0x42, "wait for child %d", i); -} diff --git a/src/tests/vm/page-parallel.ck b/src/tests/vm/page-parallel.ck deleted file mode 100644 index 90c14ef035e6e1a0db6d017c970bf9b179045ab8..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-parallel.ck +++ /dev/null @@ -1,17 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(page-parallel) begin -(page-parallel) exec "child-linear" -(page-parallel) exec "child-linear" -(page-parallel) exec "child-linear" -(page-parallel) exec "child-linear" -(page-parallel) wait for child 0 -(page-parallel) wait for child 1 -(page-parallel) wait for child 2 -(page-parallel) wait for child 3 -(page-parallel) end -EOF -pass; diff --git a/src/tests/vm/page-shuffle.c b/src/tests/vm/page-shuffle.c deleted file mode 100644 index 095a9da37909dd51ffe8d6271edd3349c30c8424..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-shuffle.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Shuffles a 128 kB data buffer 10 times, printing the checksum - after each time. */ - -#include <stdbool.h> -#include "tests/arc4.h" -#include "tests/cksum.h" -#include "tests/lib.h" -#include "tests/main.h" - -#define SIZE (128 * 1024) - -static char buf[SIZE]; - -void -test_main (void) -{ - size_t i; - - /* Initialize. */ - for (i = 0; i < sizeof buf; i++) - buf[i] = i * 257; - msg ("init: cksum=%lu", cksum (buf, sizeof buf)); - - /* Shuffle repeatedly. */ - for (i = 0; i < 10; i++) - { - shuffle (buf, sizeof buf, 1); - msg ("shuffle %zu: cksum=%lu", i, cksum (buf, sizeof buf)); - } -} diff --git a/src/tests/vm/page-shuffle.ck b/src/tests/vm/page-shuffle.ck deleted file mode 100644 index 6447d380eba51719547768c6702835e383d80340..0000000000000000000000000000000000000000 --- a/src/tests/vm/page-shuffle.ck +++ /dev/null @@ -1,44 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::cksum; -use tests::lib; - -my ($init, @shuffle); -if (1) { - # Use precalculated values. - $init = 3115322833; - @shuffle = (1691062564, 1973575879, 1647619479, 96566261, 3885786467, - 3022003332, 3614934266, 2704001777, 735775156, 1864109763); -} else { - # Recalculate values. - my ($buf) = ""; - for my $i (0...128 * 1024 - 1) { - $buf .= chr (($i * 257) & 0xff); - } - $init = cksum ($buf); - - random_init (0); - for my $i (1...10) { - $buf = shuffle ($buf, length ($buf), 1); - push (@shuffle, cksum ($buf)); - } -} - -check_expected (IGNORE_EXIT_CODES => 1, [<<EOF]); -(page-shuffle) begin -(page-shuffle) init: cksum=$init -(page-shuffle) shuffle 0: cksum=$shuffle[0] -(page-shuffle) shuffle 1: cksum=$shuffle[1] -(page-shuffle) shuffle 2: cksum=$shuffle[2] -(page-shuffle) shuffle 3: cksum=$shuffle[3] -(page-shuffle) shuffle 4: cksum=$shuffle[4] -(page-shuffle) shuffle 5: cksum=$shuffle[5] -(page-shuffle) shuffle 6: cksum=$shuffle[6] -(page-shuffle) shuffle 7: cksum=$shuffle[7] -(page-shuffle) shuffle 8: cksum=$shuffle[8] -(page-shuffle) shuffle 9: cksum=$shuffle[9] -(page-shuffle) end -EOF -pass; diff --git a/src/tests/vm/parallel-merge.c b/src/tests/vm/parallel-merge.c deleted file mode 100644 index cc09bb13a05effb3628bc1ce48f2d4673646b57f..0000000000000000000000000000000000000000 --- a/src/tests/vm/parallel-merge.c +++ /dev/null @@ -1,149 +0,0 @@ -/* Generates about 1 MB of random data that is then divided into - 16 chunks. A separate subprocess sorts each chunk; the - subprocesses run in parallel. Then we merge the chunks and - verify that the result is what it should be. */ - -#include "tests/vm/parallel-merge.h" -#include <stdio.h> -#include <syscall.h> -#include "tests/arc4.h" -#include "tests/lib.h" -#include "tests/main.h" - -#define CHUNK_SIZE (128 * 1024) -#define CHUNK_CNT 8 /* Number of chunks. */ -#define DATA_SIZE (CHUNK_CNT * CHUNK_SIZE) /* Buffer size. */ - -unsigned char buf1[DATA_SIZE], buf2[DATA_SIZE]; -size_t histogram[256]; - -/* Initialize buf1 with random data, - then count the number of instances of each value within it. */ -static void -init (void) -{ - struct arc4 arc4; - size_t i; - - msg ("init"); - - arc4_init (&arc4, "foobar", 6); - arc4_crypt (&arc4, buf1, sizeof buf1); - for (i = 0; i < sizeof buf1; i++) - histogram[buf1[i]]++; -} - -/* Sort each chunk of buf1 using SUBPROCESS, - which is expected to return EXIT_STATUS. */ -static void -sort_chunks (const char *subprocess, int exit_status) -{ - pid_t children[CHUNK_CNT]; - size_t i; - - for (i = 0; i < CHUNK_CNT; i++) - { - char fn[128]; - char cmd[128]; - int handle; - - msg ("sort chunk %zu", i); - - /* Write this chunk to a file. */ - snprintf (fn, sizeof fn, "buf%zu", i); - create (fn, CHUNK_SIZE); - quiet = true; - CHECK ((handle = open (fn)) > 1, "open \"%s\"", fn); - write (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE); - close (handle); - - /* Sort with subprocess. */ - snprintf (cmd, sizeof cmd, "%s %s", subprocess, fn); - CHECK ((children[i] = exec (cmd)) != -1, "exec \"%s\"", cmd); - quiet = false; - } - - for (i = 0; i < CHUNK_CNT; i++) - { - char fn[128]; - int handle; - - CHECK (wait (children[i]) == exit_status, "wait for child %zu", i); - - /* Read chunk back from file. */ - quiet = true; - snprintf (fn, sizeof fn, "buf%zu", i); - CHECK ((handle = open (fn)) > 1, "open \"%s\"", fn); - read (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE); - close (handle); - quiet = false; - } -} - -/* Merge the sorted chunks in buf1 into a fully sorted buf2. */ -static void -merge (void) -{ - unsigned char *mp[CHUNK_CNT]; - size_t mp_left; - unsigned char *op; - size_t i; - - msg ("merge"); - - /* Initialize merge pointers. */ - mp_left = CHUNK_CNT; - for (i = 0; i < CHUNK_CNT; i++) - mp[i] = buf1 + CHUNK_SIZE * i; - - /* Merge. */ - op = buf2; - while (mp_left > 0) - { - /* Find smallest value. */ - size_t min = 0; - for (i = 1; i < mp_left; i++) - if (*mp[i] < *mp[min]) - min = i; - - /* Append value to buf2. */ - *op++ = *mp[min]; - - /* Advance merge pointer. - Delete this chunk from the set if it's emptied. */ - if ((++mp[min] - buf1) % CHUNK_SIZE == 0) - mp[min] = mp[--mp_left]; - } -} - -static void -verify (void) -{ - size_t buf_idx; - size_t hist_idx; - - msg ("verify"); - - buf_idx = 0; - for (hist_idx = 0; hist_idx < sizeof histogram / sizeof *histogram; - hist_idx++) - { - while (histogram[hist_idx]-- > 0) - { - if (buf2[buf_idx] != hist_idx) - fail ("bad value %d in byte %zu", buf2[buf_idx], buf_idx); - buf_idx++; - } - } - - msg ("success, buf_idx=%'zu", buf_idx); -} - -void -parallel_merge (const char *child_name, int exit_status) -{ - init (); - sort_chunks (child_name, exit_status); - merge (); - verify (); -} diff --git a/src/tests/vm/parallel-merge.h b/src/tests/vm/parallel-merge.h deleted file mode 100644 index a6b6431c1de6e39d7a9ae312ad9d3b2f2df57b81..0000000000000000000000000000000000000000 --- a/src/tests/vm/parallel-merge.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TESTS_VM_PARALLEL_MERGE -#define TESTS_VM_PARALLEL_MERGE 1 - -void parallel_merge (const char *child_name, int exit_status); - -#endif /* tests/vm/parallel-merge.h */ diff --git a/src/tests/vm/process_death.pm b/src/tests/vm/process_death.pm deleted file mode 100644 index 52039a1a1986939c52e074d2faf8d200bef508ac..0000000000000000000000000000000000000000 --- a/src/tests/vm/process_death.pm +++ /dev/null @@ -1,22 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; - -sub check_process_death { - my ($proc_name) = @_; - our ($test); - my (@output) = read_text_file ("$test.output"); - - common_checks ("run", @output); - @output = get_core_output ("run", @output); - fail "First line of output is not `($proc_name) begin' message.\n" - if $output[0] ne "($proc_name) begin"; - fail "Output missing '$proc_name: exit(-1)' message.\n" - if !grep ("$proc_name: exit(-1)" eq $_, @output); - fail "Output contains '($proc_name) end' message.\n" - if grep (/\($proc_name\) end/, @output); - pass; -} - -1; diff --git a/src/tests/vm/pt-bad-addr.c b/src/tests/vm/pt-bad-addr.c deleted file mode 100644 index 3ca408409c6c53134d3047d9f17c24795102ab42..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-bad-addr.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Accesses a bad address. - The process must be terminated with -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - fail ("bad addr read as %d", *(int *) 0x04000000); -} diff --git a/src/tests/vm/pt-bad-addr.ck b/src/tests/vm/pt-bad-addr.ck deleted file mode 100644 index 09ea039d45e2772075c7c195c5341d6506c1df8d..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-bad-addr.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::vm::process_death; - -check_process_death ('pt-bad-addr'); diff --git a/src/tests/vm/pt-bad-read.c b/src/tests/vm/pt-bad-read.c deleted file mode 100644 index ee791ffe79433a946b41276333950a6e3c33188f..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-bad-read.c +++ /dev/null @@ -1,16 +0,0 @@ -/* Reads from a file into a bad address. - The process must be terminated with -1 exit code. */ - -#include <syscall.h> -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - read (handle, (char *) &handle - 4096, 1); - fail ("survived reading data into bad address"); -} diff --git a/src/tests/vm/pt-bad-read.ck b/src/tests/vm/pt-bad-read.ck deleted file mode 100644 index 1f96bb445d8869b5976b7a75f248476ee308ea20..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-bad-read.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(pt-bad-read) begin -(pt-bad-read) open "sample.txt" -pt-bad-read: exit(-1) -EOF -pass; diff --git a/src/tests/vm/pt-big-stk-obj.c b/src/tests/vm/pt-big-stk-obj.c deleted file mode 100644 index 6b630ecec0255068c020eb6afd1eab1b731d719c..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-big-stk-obj.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Allocates and writes to a 64 kB object on the stack. - This must succeed. */ - -#include <string.h> -#include "tests/arc4.h" -#include "tests/cksum.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char stk_obj[65536]; - struct arc4 arc4; - - arc4_init (&arc4, "foobar", 6); - memset (stk_obj, 0, sizeof stk_obj); - arc4_crypt (&arc4, stk_obj, sizeof stk_obj); - msg ("cksum: %lu", cksum (stk_obj, sizeof stk_obj)); -} diff --git a/src/tests/vm/pt-big-stk-obj.ck b/src/tests/vm/pt-big-stk-obj.ck deleted file mode 100644 index eb5853a23576ba65428d10251331c5672ac0dd2e..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-big-stk-obj.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(pt-big-stk-obj) begin -(pt-big-stk-obj) cksum: 3256410166 -(pt-big-stk-obj) end -EOF -pass; diff --git a/src/tests/vm/pt-grow-bad.c b/src/tests/vm/pt-grow-bad.c deleted file mode 100644 index d4beba22ff50e06ff6a31bc4783061ce2abd92b3..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-bad.c +++ /dev/null @@ -1,14 +0,0 @@ -/* Read from an address 4,096 bytes below the stack pointer. - The process must be terminated with -1 exit code. */ - -#include <string.h> -#include "tests/arc4.h" -#include "tests/cksum.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - asm volatile ("movl -4096(%esp), %eax"); -} diff --git a/src/tests/vm/pt-grow-bad.ck b/src/tests/vm/pt-grow-bad.ck deleted file mode 100644 index 4c0ab8a2bc7c146bb6322204803a92af82153ec2..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-bad.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); -(pt-grow-bad) begin -pt-grow-bad: exit(-1) -EOF -pass; diff --git a/src/tests/vm/pt-grow-pusha.c b/src/tests/vm/pt-grow-pusha.c deleted file mode 100644 index f9762a512d1c5791bea793ad65f9d930e8f700c7..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-pusha.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Expand the stack by 32 bytes all at once using the PUSHA - instruction. - This must succeed. */ - -#include <string.h> -#include "tests/arc4.h" -#include "tests/cksum.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - asm volatile - ("movl %%esp, %%eax;" /* Save a copy of the stack pointer. */ - "andl $0xfffff000, %%esp;" /* Move stack pointer to bottom of page. */ - "pushal;" /* Push 32 bytes on stack at once. */ - "movl %%eax, %%esp" /* Restore copied stack pointer. */ - : : : "eax"); /* Tell GCC we destroyed eax. */ -} diff --git a/src/tests/vm/pt-grow-pusha.ck b/src/tests/vm/pt-grow-pusha.ck deleted file mode 100644 index 5000966ed473eaaad125bc8879f4e47202b71414..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-pusha.ck +++ /dev/null @@ -1,9 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(pt-grow-pusha) begin -(pt-grow-pusha) end -EOF -pass; diff --git a/src/tests/vm/pt-grow-stack.c b/src/tests/vm/pt-grow-stack.c deleted file mode 100644 index 0997a00e4f4069084948e3869079f90541d64298..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-stack.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Demonstrate that the stack can grow. - This must succeed. */ - -#include <string.h> -#include "tests/arc4.h" -#include "tests/cksum.h" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - char stack_obj[4096]; - struct arc4 arc4; - - arc4_init (&arc4, "foobar", 6); - memset (stack_obj, 0, sizeof stack_obj); - arc4_crypt (&arc4, stack_obj, sizeof stack_obj); - msg ("cksum: %lu", cksum (stack_obj, sizeof stack_obj)); -} diff --git a/src/tests/vm/pt-grow-stack.ck b/src/tests/vm/pt-grow-stack.ck deleted file mode 100644 index 1e669db94c360f64295857ad83f6d04e24122b2c..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-stack.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(pt-grow-stack) begin -(pt-grow-stack) cksum: 3424492700 -(pt-grow-stack) end -EOF -pass; diff --git a/src/tests/vm/pt-grow-stk-sc.c b/src/tests/vm/pt-grow-stk-sc.c deleted file mode 100644 index 3efbb5f7e43a6abfc785d92d3cf19b29b310be31..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-stk-sc.c +++ /dev/null @@ -1,32 +0,0 @@ -/* This test checks that the stack is properly extended even if - the first access to a stack location occurs inside a system - call. - - From Godmar Back. */ - -#include <string.h> -#include <syscall.h> -#include "tests/vm/sample.inc" -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - int slen = strlen (sample); - char buf2[65536]; - - /* Write file via write(). */ - CHECK (create ("sample.txt", slen), "create \"sample.txt\""); - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - CHECK (write (handle, sample, slen) == slen, "write \"sample.txt\""); - close (handle); - - /* Read back via read(). */ - CHECK ((handle = open ("sample.txt")) > 1, "2nd open \"sample.txt\""); - CHECK (read (handle, buf2 + 32768, slen) == slen, "read \"sample.txt\""); - - CHECK (!memcmp (sample, buf2 + 32768, slen), "compare written data against read data"); - close (handle); -} diff --git a/src/tests/vm/pt-grow-stk-sc.ck b/src/tests/vm/pt-grow-stk-sc.ck deleted file mode 100644 index 23d3b02e8af0d6d6cc6b7a8fc149b43a1c7c14a1..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-grow-stk-sc.ck +++ /dev/null @@ -1,15 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); -(pt-grow-stk-sc) begin -(pt-grow-stk-sc) create "sample.txt" -(pt-grow-stk-sc) open "sample.txt" -(pt-grow-stk-sc) write "sample.txt" -(pt-grow-stk-sc) 2nd open "sample.txt" -(pt-grow-stk-sc) read "sample.txt" -(pt-grow-stk-sc) compare written data against read data -(pt-grow-stk-sc) end -EOF -pass; diff --git a/src/tests/vm/pt-write-code-2.c b/src/tests/vm/pt-write-code-2.c deleted file mode 100644 index 83bcc2c3b620e416f4736d013f3ce8b7af89b564..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-write-code-2.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Try to write to the code segment using a system call. - The process must be terminated with -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - int handle; - - CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); - read (handle, (void *) test_main, 1); - fail ("survived reading data into code segment"); -} diff --git a/src/tests/vm/pt-write-code.c b/src/tests/vm/pt-write-code.c deleted file mode 100644 index 5072cec10ea5914b3ed68e6f60dae23361f252e3..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-write-code.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Try to write to the code segment. - The process must be terminated with -1 exit code. */ - -#include "tests/lib.h" -#include "tests/main.h" - -void -test_main (void) -{ - *(int *) test_main = 0; - fail ("writing the code segment succeeded"); -} diff --git a/src/tests/vm/pt-write-code.ck b/src/tests/vm/pt-write-code.ck deleted file mode 100644 index 65610fb505b7330bc92b4284878462b076ff7f9c..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-write-code.ck +++ /dev/null @@ -1,7 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -use tests::vm::process_death; - -check_process_death ('pt-write-code'); diff --git a/src/tests/vm/pt-write-code2.ck b/src/tests/vm/pt-write-code2.ck deleted file mode 100644 index 69ffc77ca4b3a7960adcdb91b66da10b0bb4fd96..0000000000000000000000000000000000000000 --- a/src/tests/vm/pt-write-code2.ck +++ /dev/null @@ -1,10 +0,0 @@ -# -*- perl -*- -use strict; -use warnings; -use tests::tests; -check_expected ([<<'EOF']); -(pt-write-code2) begin -(pt-write-code2) open "sample.txt" -pt-write-code2: exit(-1) -EOF -pass; diff --git a/src/tests/vm/qsort.c b/src/tests/vm/qsort.c deleted file mode 100644 index 922572c8fa4bab0def739058f0b0ac2a4a6c74ec..0000000000000000000000000000000000000000 --- a/src/tests/vm/qsort.c +++ /dev/null @@ -1,136 +0,0 @@ -#include "tests/vm/qsort.h" -#include <stdbool.h> -#include <debug.h> -#include <random.h> - -/* Picks a pivot for the quicksort from the SIZE bytes in BUF. */ -static unsigned char -pick_pivot (unsigned char *buf, size_t size) -{ - ASSERT (size >= 1); - return buf[random_ulong () % size]; -} - -/* Checks whether the SIZE bytes in ARRAY are divided into an - initial LEFT_SIZE elements all less than PIVOT followed by - SIZE - LEFT_SIZE elements all greater than or equal to - PIVOT. */ -static bool -is_partitioned (const unsigned char *array, size_t size, - unsigned char pivot, size_t left_size) -{ - size_t i; - - for (i = 0; i < left_size; i++) - if (array[i] >= pivot) - return false; - - for (; i < size; i++) - if (array[i] < pivot) - return false; - - return true; -} - -/* Swaps the bytes at *A and *B. */ -static void -swap (unsigned char *a, unsigned char *b) -{ - unsigned char t = *a; - *a = *b; - *b = t; -} - -/* Partitions ARRAY in-place in an initial run of bytes all less - than PIVOT, followed by a run of bytes all greater than or - equal to PIVOT. Returns the length of the initial run. */ -static size_t -partition (unsigned char *array, size_t size, int pivot) -{ - size_t left_size = size; - unsigned char *first = array; - unsigned char *last = first + left_size; - - for (;;) - { - /* Move FIRST forward to point to first element greater than - PIVOT. */ - for (;;) - { - if (first == last) - { - ASSERT (is_partitioned (array, size, pivot, left_size)); - return left_size; - } - else if (*first >= pivot) - break; - - first++; - } - left_size--; - - /* Move LAST backward to point to last element no bigger - than PIVOT. */ - for (;;) - { - last--; - - if (first == last) - { - ASSERT (is_partitioned (array, size, pivot, left_size)); - return left_size; - } - else if (*last < pivot) - break; - else - left_size--; - } - - /* By swapping FIRST and LAST we extend the starting and - ending sequences that pass and fail, respectively, - PREDICATE. */ - swap (first, last); - first++; - } -} - -/* Returns true if the SIZE bytes in BUF are in nondecreasing - order, false otherwise. */ -static bool -is_sorted (const unsigned char *buf, size_t size) -{ - size_t i; - - for (i = 1; i < size; i++) - if (buf[i - 1] > buf[i]) - return false; - - return true; -} - -/* Sorts the SIZE bytes in BUF into nondecreasing order, using - the quick-sort algorithm. */ -void -qsort_bytes (unsigned char *buf, size_t size) -{ - if (!is_sorted (buf, size)) - { - int pivot = pick_pivot (buf, size); - - unsigned char *left_half = buf; - size_t left_size = partition (buf, size, pivot); - unsigned char *right_half = left_half + left_size; - size_t right_size = size - left_size; - - if (left_size <= right_size) - { - qsort_bytes (left_half, left_size); - qsort_bytes (right_half, right_size); - } - else - { - qsort_bytes (right_half, right_size); - qsort_bytes (left_half, left_size); - } - } -} diff --git a/src/tests/vm/qsort.h b/src/tests/vm/qsort.h deleted file mode 100644 index 61b65f3e914694c6de1833399ac8be32972b326f..0000000000000000000000000000000000000000 --- a/src/tests/vm/qsort.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef TESTS_VM_QSORT_H -#define TESTS_VM_QSORT_H 1 - -#include <stddef.h> - -void qsort_bytes (unsigned char *buf, size_t size); - -#endif /* tests/vm/qsort.h */ diff --git a/src/tests/vm/sample.inc b/src/tests/vm/sample.inc deleted file mode 100644 index a60a139a94e1bdb1dea9a76c1a70005b9c67869d..0000000000000000000000000000000000000000 --- a/src/tests/vm/sample.inc +++ /dev/null @@ -1,19 +0,0 @@ -char sample[] = { - "=== ALL USERS PLEASE NOTE ========================\n" - "\n" - "CAR and CDR now return extra values.\n" - "\n" - "The function CAR now returns two values. Since it has to go to the\n" - "trouble to figure out if the object is carcdr-able anyway, we figured\n" - "you might as well get both halves at once. For example, the following\n" - "code shows how to destructure a cons (SOME-CONS) into its two slots\n" - "(THE-CAR and THE-CDR):\n" - "\n" - " (MULTIPLE-VALUE-BIND (THE-CAR THE-CDR) (CAR SOME-CONS) ...)\n" - "\n" - "For symmetry with CAR, CDR returns a second value which is the CAR of\n" - "the object. In a related change, the functions MAKE-ARRAY and CONS\n" - "have been fixed so they don't allocate any storage except on the\n" - "stack. This should hopefully help people who don't like using the\n" - "garbage collector because it cold boots the machine so often.\n" -}; diff --git a/src/tests/vm/sample.txt b/src/tests/vm/sample.txt deleted file mode 100644 index c4468305e5790f5fe0c525b363161a4dacb5a786..0000000000000000000000000000000000000000 --- a/src/tests/vm/sample.txt +++ /dev/null @@ -1,17 +0,0 @@ -=== ALL USERS PLEASE NOTE ======================== - -CAR and CDR now return extra values. - -The function CAR now returns two values. Since it has to go to the -trouble to figure out if the object is carcdr-able anyway, we figured -you might as well get both halves at once. For example, the following -code shows how to destructure a cons (SOME-CONS) into its two slots -(THE-CAR and THE-CDR): - - (MULTIPLE-VALUE-BIND (THE-CAR THE-CDR) (CAR SOME-CONS) ...) - -For symmetry with CAR, CDR returns a second value which is the CAR of -the object. In a related change, the functions MAKE-ARRAY and CONS -have been fixed so they don't allocate any storage except on the -stack. This should hopefully help people who don't like using the -garbage collector because it cold boots the machine so often. diff --git a/src/threads/.gitignore b/src/threads/.gitignore deleted file mode 100644 index 6d5357c015ab6f0b7ee7074381afdd3da82e06eb..0000000000000000000000000000000000000000 --- a/src/threads/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -build -bochsrc.txt -bochsout.txt diff --git a/src/threads/Make.vars b/src/threads/Make.vars deleted file mode 100644 index 545cc251440ba3212558874836dea64ebf668d01..0000000000000000000000000000000000000000 --- a/src/threads/Make.vars +++ /dev/null @@ -1,7 +0,0 @@ -# -*- makefile -*- - -kernel.bin: DEFINES = -KERNEL_SUBDIRS = threads devices lib lib/kernel $(TEST_SUBDIRS) -TEST_SUBDIRS = tests/threads -GRADING_FILE = $(SRCDIR)/tests/threads/Grading -SIMULATOR = --qemu diff --git a/src/threads/Makefile b/src/threads/Makefile deleted file mode 100644 index 2020101d9b0a666a6162a6a849c0833cc61edfee..0000000000000000000000000000000000000000 --- a/src/threads/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.kernel diff --git a/src/threads/flags.h b/src/threads/flags.h deleted file mode 100644 index 5654ac789201e8c70a5c39c84c64aa1e02d520d1..0000000000000000000000000000000000000000 --- a/src/threads/flags.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef THREADS_FLAGS_H -#define THREADS_FLAGS_H - -/* EFLAGS Register. */ -#define FLAG_MBS 0x00000002 /* Must be set. */ -#define FLAG_IF 0x00000200 /* Interrupt Flag. */ - -#endif /* threads/flags.h */ diff --git a/src/threads/init.c b/src/threads/init.c deleted file mode 100644 index cebec2c817f5954b9accf9558dbd36822c1fb8f4..0000000000000000000000000000000000000000 --- a/src/threads/init.c +++ /dev/null @@ -1,429 +0,0 @@ -#include "threads/init.h" -#include <console.h> -#include <debug.h> -#include <inttypes.h> -#include <limits.h> -#include <random.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "devices/kbd.h" -#include "devices/input.h" -#include "devices/serial.h" -#include "devices/shutdown.h" -#include "devices/timer.h" -#include "devices/vga.h" -#include "devices/rtc.h" -#include "threads/interrupt.h" -#include "threads/io.h" -#include "threads/loader.h" -#include "threads/malloc.h" -#include "threads/palloc.h" -#include "threads/pte.h" -#include "threads/thread.h" -#ifdef USERPROG -#include "userprog/process.h" -#include "userprog/exception.h" -#include "userprog/gdt.h" -#include "userprog/syscall.h" -#include "userprog/tss.h" -#else -#include "tests/threads/tests.h" -#endif -#ifdef FILESYS -#include "devices/block.h" -#include "devices/ide.h" -#include "filesys/filesys.h" -#include "filesys/fsutil.h" -#endif - -/* Page directory with kernel mappings only. */ -uint32_t *init_page_dir; - -#ifdef FILESYS -/* -f: Format the file system? */ -static bool format_filesys; - -/* -filesys, -scratch, -swap: Names of block devices to use, - overriding the defaults. */ -static const char *filesys_bdev_name; -static const char *scratch_bdev_name; -#ifdef VM -static const char *swap_bdev_name; -#endif -#endif /* FILESYS */ - -/* -ul: Maximum number of pages to put into palloc's user pool. */ -static size_t user_page_limit = SIZE_MAX; - -static void bss_init (void); -static void paging_init (void); - -static char **read_command_line (void); -static char **parse_options (char **argv); -static void run_actions (char **argv); -static void usage (void); - -#ifdef FILESYS -static void locate_block_devices (void); -static void locate_block_device (enum block_type, const char *name); -#endif - -int main (void) NO_RETURN; - -/* Pintos main program. */ -int -main (void) -{ - char **argv; - - /* Clear BSS. */ - bss_init (); - - /* Break command line into arguments and parse options. */ - argv = read_command_line (); - argv = parse_options (argv); - - /* Initialize ourselves as a thread so we can use locks, - then enable console locking. */ - thread_init (); - console_init (); - - /* Greet user. */ - printf ("Pintos booting with %'"PRIu32" kB RAM...\n", - init_ram_pages * PGSIZE / 1024); - - /* Initialize memory system. */ - palloc_init (user_page_limit); - malloc_init (); - paging_init (); - - /* Segmentation. */ -#ifdef USERPROG - tss_init (); - gdt_init (); -#endif - - /* Initialize interrupt handlers. */ - intr_init (); - timer_init (); - kbd_init (); - input_init (); -#ifdef USERPROG - exception_init (); - syscall_init (); -#endif - - /* Start thread scheduler and enable interrupts. */ - thread_start (); - serial_init_queue (); - timer_calibrate (); - -#ifdef FILESYS - /* Initialize file system. */ - ide_init (); - locate_block_devices (); - filesys_init (format_filesys); -#endif - - printf ("Boot complete.\n"); - - /* Run actions specified on kernel command line. */ - run_actions (argv); - - /* Finish up. */ - shutdown (); - thread_exit (); -} - -/* Clear the "BSS", a segment that should be initialized to - zeros. It isn't actually stored on disk or zeroed by the - kernel loader, so we have to zero it ourselves. - - The start and end of the BSS segment is recorded by the - linker as _start_bss and _end_bss. See kernel.lds. */ -static void -bss_init (void) -{ - extern char _start_bss, _end_bss; - memset (&_start_bss, 0, &_end_bss - &_start_bss); -} - -/* Populates the base page directory and page table with the - kernel virtual mapping, and then sets up the CPU to use the - new page directory. Points init_page_dir to the page - directory it creates. */ -static void -paging_init (void) -{ - uint32_t *pd, *pt; - size_t page; - extern char _start, _end_kernel_text; - - pd = init_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO); - pt = NULL; - for (page = 0; page < init_ram_pages; page++) - { - uintptr_t paddr = page * PGSIZE; - char *vaddr = ptov (paddr); - size_t pde_idx = pd_no (vaddr); - size_t pte_idx = pt_no (vaddr); - bool in_kernel_text = &_start <= vaddr && vaddr < &_end_kernel_text; - - if (pd[pde_idx] == 0) - { - pt = palloc_get_page (PAL_ASSERT | PAL_ZERO); - pd[pde_idx] = pde_create (pt); - } - - pt[pte_idx] = pte_create_kernel (vaddr, !in_kernel_text); - } - - /* Store the physical address of the page directory into CR3 - aka PDBR (page directory base register). This activates our - new page tables immediately. See [IA32-v2a] "MOV--Move - to/from Control Registers" and [IA32-v3a] 3.7.5 "Base Address - of the Page Directory". */ - asm volatile ("movl %0, %%cr3" : : "r" (vtop (init_page_dir))); -} - -/* Breaks the kernel command line into words and returns them as - an argv-like array. */ -static char ** -read_command_line (void) -{ - static char *argv[LOADER_ARGS_LEN / 2 + 1]; - char *p, *end; - int argc; - int i; - - argc = *(uint32_t *) ptov (LOADER_ARG_CNT); - p = ptov (LOADER_ARGS); - end = p + LOADER_ARGS_LEN; - for (i = 0; i < argc; i++) - { - if (p >= end) - PANIC ("command line arguments overflow"); - - argv[i] = p; - p += strnlen (p, end - p) + 1; - } - argv[argc] = NULL; - - /* Print kernel command line. */ - printf ("Kernel command line:"); - for (i = 0; i < argc; i++) - if (strchr (argv[i], ' ') == NULL) - printf (" %s", argv[i]); - else - printf (" '%s'", argv[i]); - printf ("\n"); - - return argv; -} - -/* Parses options in ARGV[] - and returns the first non-option argument. */ -static char ** -parse_options (char **argv) -{ - for (; *argv != NULL && **argv == '-'; argv++) - { - char *save_ptr; - char *name = strtok_r (*argv, "=", &save_ptr); - char *value = strtok_r (NULL, "", &save_ptr); - - if (!strcmp (name, "-h")) - usage (); - else if (!strcmp (name, "-q")) - shutdown_configure (SHUTDOWN_POWER_OFF); - else if (!strcmp (name, "-r")) - shutdown_configure (SHUTDOWN_REBOOT); -#ifdef FILESYS - else if (!strcmp (name, "-f")) - format_filesys = true; - else if (!strcmp (name, "-filesys")) - filesys_bdev_name = value; - else if (!strcmp (name, "-scratch")) - scratch_bdev_name = value; -#ifdef VM - else if (!strcmp (name, "-swap")) - swap_bdev_name = value; -#endif -#endif - else if (!strcmp (name, "-rs")) - random_init (atoi (value)); - else if (!strcmp (name, "-mlfqs")) - thread_mlfqs = true; -#ifdef USERPROG - else if (!strcmp (name, "-ul")) - user_page_limit = atoi (value); -#endif - else - PANIC ("unknown option `%s' (use -h for help)", name); - } - - /* Initialize the random number generator based on the system - time. This has no effect if an "-rs" option was specified. - - When running under Bochs, this is not enough by itself to - get a good seed value, because the pintos script sets the - initial time to a predictable value, not to the local time, - for reproducibility. To fix this, give the "-r" option to - the pintos script to request real-time execution. */ - random_init (rtc_get_time ()); - - return argv; -} - -/* Runs the task specified in ARGV[1]. */ -static void -run_task (char **argv) -{ - const char *task = argv[1]; - - printf ("Executing '%s':\n", task); -#ifdef USERPROG - process_wait (process_execute (task)); -#else - run_test (task); -#endif - printf ("Execution of '%s' complete.\n", task); -} - -/* Executes all of the actions specified in ARGV[] - up to the null pointer sentinel. */ -static void -run_actions (char **argv) -{ - /* An action. */ - struct action - { - char *name; /* Action name. */ - int argc; /* # of args, including action name. */ - void (*function) (char **argv); /* Function to execute action. */ - }; - - /* Table of supported actions. */ - static const struct action actions[] = - { - {"run", 2, run_task}, -#ifdef FILESYS - {"ls", 1, fsutil_ls}, - {"cat", 2, fsutil_cat}, - {"rm", 2, fsutil_rm}, - {"extract", 1, fsutil_extract}, - {"append", 2, fsutil_append}, -#endif - {NULL, 0, NULL}, - }; - - while (*argv != NULL) - { - const struct action *a; - int i; - - /* Find action name. */ - for (a = actions; ; a++) - if (a->name == NULL) - PANIC ("unknown action `%s' (use -h for help)", *argv); - else if (!strcmp (*argv, a->name)) - break; - - /* Check for required arguments. */ - for (i = 1; i < a->argc; i++) - if (argv[i] == NULL) - PANIC ("action `%s' requires %d argument(s)", *argv, a->argc - 1); - - /* Invoke action and advance. */ - a->function (argv); - argv += a->argc; - } - -} - -/* Prints a kernel command line help message and powers off the - machine. */ -static void -usage (void) -{ - printf ("\nCommand line syntax: [OPTION...] [ACTION...]\n" - "Options must precede actions.\n" - "Actions are executed in the order specified.\n" - "\nAvailable actions:\n" -#ifdef USERPROG - " run 'PROG [ARG...]' Run PROG and wait for it to complete.\n" -#else - " run TEST Run TEST.\n" -#endif -#ifdef FILESYS - " ls List files in the root directory.\n" - " cat FILE Print FILE to the console.\n" - " rm FILE Delete FILE.\n" - "Use these actions indirectly via `pintos' -g and -p options:\n" - " extract Untar from scratch device into file system.\n" - " append FILE Append FILE to tar file on scratch device.\n" -#endif - "\nOptions:\n" - " -h Print this help message and power off.\n" - " -q Power off VM after actions or on panic.\n" - " -r Reboot after actions.\n" -#ifdef FILESYS - " -f Format file system device during startup.\n" - " -filesys=BDEV Use BDEV for file system instead of default.\n" - " -scratch=BDEV Use BDEV for scratch instead of default.\n" -#ifdef VM - " -swap=BDEV Use BDEV for swap instead of default.\n" -#endif -#endif - " -rs=SEED Set random number seed to SEED.\n" - " -mlfqs Use multi-level feedback queue scheduler.\n" -#ifdef USERPROG - " -ul=COUNT Limit user memory to COUNT pages.\n" -#endif - ); - shutdown_power_off (); -} - -#ifdef FILESYS -/* Figure out what block devices to cast in the various Pintos roles. */ -static void -locate_block_devices (void) -{ - locate_block_device (BLOCK_FILESYS, filesys_bdev_name); - locate_block_device (BLOCK_SCRATCH, scratch_bdev_name); -#ifdef VM - locate_block_device (BLOCK_SWAP, swap_bdev_name); -#endif -} - -/* Figures out what block device to use for the given ROLE: the - block device with the given NAME, if NAME is non-null, - otherwise the first block device in probe order of type - ROLE. */ -static void -locate_block_device (enum block_type role, const char *name) -{ - struct block *block = NULL; - - if (name != NULL) - { - block = block_get_by_name (name); - if (block == NULL) - PANIC ("No such block device \"%s\"", name); - } - else - { - for (block = block_first (); block != NULL; block = block_next (block)) - if (block_type (block) == role) - break; - } - - if (block != NULL) - { - printf ("%s: using %s\n", block_type_name (role), block_name (block)); - block_set_role (role, block); - } -} -#endif diff --git a/src/threads/init.h b/src/threads/init.h deleted file mode 100644 index 8a3df903481dacab972dbe1a8a31b49a2f04f739..0000000000000000000000000000000000000000 --- a/src/threads/init.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef THREADS_INIT_H -#define THREADS_INIT_H - -#include <debug.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -/* Page directory with kernel mappings only. */ -extern uint32_t *init_page_dir; - -#endif /* threads/init.h */ diff --git a/src/threads/interrupt.c b/src/threads/interrupt.c deleted file mode 100644 index e3b90dcb566e3512b8ea1b9e69d2544d64e5933b..0000000000000000000000000000000000000000 --- a/src/threads/interrupt.c +++ /dev/null @@ -1,438 +0,0 @@ -#include "threads/interrupt.h" -#include <debug.h> -#include <inttypes.h> -#include <stdint.h> -#include <stdio.h> -#include "threads/flags.h" -#include "threads/intr-stubs.h" -#include "threads/io.h" -#include "threads/thread.h" -#include "threads/vaddr.h" -#include "devices/timer.h" - -/* Programmable Interrupt Controller (PIC) registers. - A PC has two PICs, called the master and slave PICs, with the - slave attached ("cascaded") to the master IRQ line 2. */ -#define PIC0_CTRL 0x20 /* Master PIC control register address. */ -#define PIC0_DATA 0x21 /* Master PIC data register address. */ -#define PIC1_CTRL 0xa0 /* Slave PIC control register address. */ -#define PIC1_DATA 0xa1 /* Slave PIC data register address. */ - -/* Number of x86 interrupts. */ -#define INTR_CNT 256 - -/* The Interrupt Descriptor Table (IDT). The format is fixed by - the CPU. See [IA32-v3a] sections 5.10 "Interrupt Descriptor - Table (IDT)", 5.11 "IDT Descriptors", 5.12.1.2 "Flag Usage By - Exception- or Interrupt-Handler Procedure". */ -static uint64_t idt[INTR_CNT]; - -/* Interrupt handler functions for each interrupt. */ -static intr_handler_func *intr_handlers[INTR_CNT]; - -/* Names for each interrupt, for debugging purposes. */ -static const char *intr_names[INTR_CNT]; - -/* Number of unexpected interrupts for each vector. An - unexpected interrupt is one that has no registered handler. */ -static unsigned int unexpected_cnt[INTR_CNT]; - -/* External interrupts are those generated by devices outside the - CPU, such as the timer. External interrupts run with - interrupts turned off, so they never nest, nor are they ever - pre-empted. Handlers for external interrupts also may not - sleep, although they may invoke intr_yield_on_return() to - request that a new process be scheduled just before the - interrupt returns. */ -static bool in_external_intr; /* Are we processing an external interrupt? */ -static bool yield_on_return; /* Should we yield on interrupt return? */ - -/* Programmable Interrupt Controller helpers. */ -static void pic_init (void); -static void pic_end_of_interrupt (int irq); - -/* Interrupt Descriptor Table helpers. */ -static uint64_t make_intr_gate (void (*) (void), int dpl); -static uint64_t make_trap_gate (void (*) (void), int dpl); -static inline uint64_t make_idtr_operand (uint16_t limit, void *base); - -/* Interrupt handlers. */ -void intr_handler (struct intr_frame *args); -static void unexpected_interrupt (const struct intr_frame *); - -/* Returns the current interrupt status. */ -enum intr_level -intr_get_level (void) -{ - uint32_t flags; - - /* Push the flags register on the processor stack, then pop the - value off the stack into `flags'. See [IA32-v2b] "PUSHF" - and "POP" and [IA32-v3a] 5.8.1 "Masking Maskable Hardware - Interrupts". */ - asm volatile ("pushfl; popl %0" : "=g" (flags)); - - return flags & FLAG_IF ? INTR_ON : INTR_OFF; -} - -/* Enables or disables interrupts as specified by LEVEL and - returns the previous interrupt status. */ -enum intr_level -intr_set_level (enum intr_level level) -{ - return level == INTR_ON ? intr_enable () : intr_disable (); -} - -/* Enables interrupts and returns the previous interrupt status. */ -enum intr_level -intr_enable (void) -{ - enum intr_level old_level = intr_get_level (); - ASSERT (!intr_context ()); - - /* Enable interrupts by setting the interrupt flag. - - See [IA32-v2b] "STI" and [IA32-v3a] 5.8.1 "Masking Maskable - Hardware Interrupts". */ - asm volatile ("sti"); - - return old_level; -} - -/* Disables interrupts and returns the previous interrupt status. */ -enum intr_level -intr_disable (void) -{ - enum intr_level old_level = intr_get_level (); - - /* Disable interrupts by clearing the interrupt flag. - See [IA32-v2b] "CLI" and [IA32-v3a] 5.8.1 "Masking Maskable - Hardware Interrupts". */ - asm volatile ("cli" : : : "memory"); - - return old_level; -} - -/* Initializes the interrupt system. */ -void -intr_init (void) -{ - uint64_t idtr_operand; - int i; - - /* Initialize interrupt controller. */ - pic_init (); - - /* Initialize IDT. */ - for (i = 0; i < INTR_CNT; i++) - idt[i] = make_intr_gate (intr_stubs[i], 0); - - /* Load IDT register. - See [IA32-v2a] "LIDT" and [IA32-v3a] 5.10 "Interrupt - Descriptor Table (IDT)". */ - idtr_operand = make_idtr_operand (sizeof idt - 1, idt); - asm volatile ("lidt %0" : : "m" (idtr_operand)); - - /* Initialize intr_names. */ - for (i = 0; i < INTR_CNT; i++) - intr_names[i] = "unknown"; - intr_names[0] = "#DE Divide Error"; - intr_names[1] = "#DB Debug Exception"; - intr_names[2] = "NMI Interrupt"; - intr_names[3] = "#BP Breakpoint Exception"; - intr_names[4] = "#OF Overflow Exception"; - intr_names[5] = "#BR BOUND Range Exceeded Exception"; - intr_names[6] = "#UD Invalid Opcode Exception"; - intr_names[7] = "#NM Device Not Available Exception"; - intr_names[8] = "#DF Double Fault Exception"; - intr_names[9] = "Coprocessor Segment Overrun"; - intr_names[10] = "#TS Invalid TSS Exception"; - intr_names[11] = "#NP Segment Not Present"; - intr_names[12] = "#SS Stack Fault Exception"; - intr_names[13] = "#GP General Protection Exception"; - intr_names[14] = "#PF Page-Fault Exception"; - intr_names[16] = "#MF x87 FPU Floating-Point Error"; - intr_names[17] = "#AC Alignment Check Exception"; - intr_names[18] = "#MC Machine-Check Exception"; - intr_names[19] = "#XF SIMD Floating-Point Exception"; -} - -/* Registers interrupt VEC_NO to invoke HANDLER with descriptor - privilege level DPL. Names the interrupt NAME for debugging - purposes. The interrupt handler will be invoked with - interrupt status set to LEVEL. */ -static void -register_handler (uint8_t vec_no, int dpl, enum intr_level level, - intr_handler_func *handler, const char *name) -{ - ASSERT (intr_handlers[vec_no] == NULL); - if (level == INTR_ON) - idt[vec_no] = make_trap_gate (intr_stubs[vec_no], dpl); - else - idt[vec_no] = make_intr_gate (intr_stubs[vec_no], dpl); - intr_handlers[vec_no] = handler; - intr_names[vec_no] = name; -} - -/* Registers external interrupt VEC_NO to invoke HANDLER, which - is named NAME for debugging purposes. The handler will - execute with interrupts disabled. */ -void -intr_register_ext (uint8_t vec_no, intr_handler_func *handler, - const char *name) -{ - ASSERT (vec_no >= 0x20 && vec_no <= 0x2f); - register_handler (vec_no, 0, INTR_OFF, handler, name); -} - -/* Registers internal interrupt VEC_NO to invoke HANDLER, which - is named NAME for debugging purposes. The interrupt handler - will be invoked with interrupt status LEVEL. - - The handler will have descriptor privilege level DPL, meaning - that it can be invoked intentionally when the processor is in - the DPL or lower-numbered ring. In practice, DPL==3 allows - user mode to invoke the interrupts and DPL==0 prevents such - invocation. Faults and exceptions that occur in user mode - still cause interrupts with DPL==0 to be invoked. See - [IA32-v3a] sections 4.5 "Privilege Levels" and 4.8.1.1 - "Accessing Nonconforming Code Segments" for further - discussion. */ -void -intr_register_int (uint8_t vec_no, int dpl, enum intr_level level, - intr_handler_func *handler, const char *name) -{ - ASSERT (vec_no < 0x20 || vec_no > 0x2f); - register_handler (vec_no, dpl, level, handler, name); -} - -/* Returns true during processing of an external interrupt - and false at all other times. */ -bool -intr_context (void) -{ - return in_external_intr; -} - -/* During processing of an external interrupt, directs the - interrupt handler to yield to a new process just before - returning from the interrupt. May not be called at any other - time. */ -void -intr_yield_on_return (void) -{ - ASSERT (intr_context ()); - yield_on_return = true; -} - -/* 8259A Programmable Interrupt Controller. */ - -/* Initializes the PICs. Refer to [8259A] for details. - - By default, interrupts 0...15 delivered by the PICs will go to - interrupt vectors 0...15. Those vectors are also used for CPU - traps and exceptions, so we reprogram the PICs so that - interrupts 0...15 are delivered to interrupt vectors 32...47 - (0x20...0x2f) instead. */ -static void -pic_init (void) -{ - /* Mask all interrupts on both PICs. */ - outb (PIC0_DATA, 0xff); - outb (PIC1_DATA, 0xff); - - /* Initialize master. */ - outb (PIC0_CTRL, 0x11); /* ICW1: single mode, edge triggered, expect ICW4. */ - outb (PIC0_DATA, 0x20); /* ICW2: line IR0...7 -> irq 0x20...0x27. */ - outb (PIC0_DATA, 0x04); /* ICW3: slave PIC on line IR2. */ - outb (PIC0_DATA, 0x01); /* ICW4: 8086 mode, normal EOI, non-buffered. */ - - /* Initialize slave. */ - outb (PIC1_CTRL, 0x11); /* ICW1: single mode, edge triggered, expect ICW4. */ - outb (PIC1_DATA, 0x28); /* ICW2: line IR0...7 -> irq 0x28...0x2f. */ - outb (PIC1_DATA, 0x02); /* ICW3: slave ID is 2. */ - outb (PIC1_DATA, 0x01); /* ICW4: 8086 mode, normal EOI, non-buffered. */ - - /* Unmask all interrupts. */ - outb (PIC0_DATA, 0x00); - outb (PIC1_DATA, 0x00); -} - -/* Sends an end-of-interrupt signal to the PIC for the given IRQ. - If we don't acknowledge the IRQ, it will never be delivered to - us again, so this is important. */ -static void -pic_end_of_interrupt (int irq) -{ - ASSERT (irq >= 0x20 && irq < 0x30); - - /* Acknowledge master PIC. */ - outb (0x20, 0x20); - - /* Acknowledge slave PIC if this is a slave interrupt. */ - if (irq >= 0x28) - outb (0xa0, 0x20); -} - -/* Creates an gate that invokes FUNCTION. - - The gate has descriptor privilege level DPL, meaning that it - can be invoked intentionally when the processor is in the DPL - or lower-numbered ring. In practice, DPL==3 allows user mode - to call into the gate and DPL==0 prevents such calls. Faults - and exceptions that occur in user mode still cause gates with - DPL==0 to be invoked. See [IA32-v3a] sections 4.5 "Privilege - Levels" and 4.8.1.1 "Accessing Nonconforming Code Segments" - for further discussion. - - TYPE must be either 14 (for an interrupt gate) or 15 (for a - trap gate). The difference is that entering an interrupt gate - disables interrupts, but entering a trap gate does not. See - [IA32-v3a] section 5.12.1.2 "Flag Usage By Exception- or - Interrupt-Handler Procedure" for discussion. */ -static uint64_t -make_gate (void (*function) (void), int dpl, int type) -{ - uint32_t e0, e1; - - ASSERT (function != NULL); - ASSERT (dpl >= 0 && dpl <= 3); - ASSERT (type >= 0 && type <= 15); - - e0 = (((uint32_t) function & 0xffff) /* Offset 15:0. */ - | (SEL_KCSEG << 16)); /* Target code segment. */ - - e1 = (((uint32_t) function & 0xffff0000) /* Offset 31:16. */ - | (1 << 15) /* Present. */ - | ((uint32_t) dpl << 13) /* Descriptor privilege level. */ - | (0 << 12) /* System. */ - | ((uint32_t) type << 8)); /* Gate type. */ - - return e0 | ((uint64_t) e1 << 32); -} - -/* Creates an interrupt gate that invokes FUNCTION with the given - DPL. */ -static uint64_t -make_intr_gate (void (*function) (void), int dpl) -{ - return make_gate (function, dpl, 14); -} - -/* Creates a trap gate that invokes FUNCTION with the given - DPL. */ -static uint64_t -make_trap_gate (void (*function) (void), int dpl) -{ - return make_gate (function, dpl, 15); -} - -/* Returns a descriptor that yields the given LIMIT and BASE when - used as an operand for the LIDT instruction. */ -static inline uint64_t -make_idtr_operand (uint16_t limit, void *base) -{ - return limit | ((uint64_t) (uint32_t) base << 16); -} - -/* Interrupt handlers. */ - -/* Handler for all interrupts, faults, and exceptions. This - function is called by the assembly language interrupt stubs in - intr-stubs.S. FRAME describes the interrupt and the - interrupted thread's registers. */ -void -intr_handler (struct intr_frame *frame) -{ - bool external; - intr_handler_func *handler; - - /* External interrupts are special. - We only handle one at a time (so interrupts must be off) - and they need to be acknowledged on the PIC (see below). - An external interrupt handler cannot sleep. */ - external = frame->vec_no >= 0x20 && frame->vec_no < 0x30; - if (external) - { - ASSERT (intr_get_level () == INTR_OFF); - ASSERT (!intr_context ()); - - in_external_intr = true; - yield_on_return = false; - } - - /* Invoke the interrupt's handler. */ - handler = intr_handlers[frame->vec_no]; - if (handler != NULL) - handler (frame); - else if (frame->vec_no == 0x27 || frame->vec_no == 0x2f) - { - /* There is no handler, but this interrupt can trigger - spuriously due to a hardware fault or hardware race - condition. Ignore it. */ - } - else - unexpected_interrupt (frame); - - /* Complete the processing of an external interrupt. */ - if (external) - { - ASSERT (intr_get_level () == INTR_OFF); - ASSERT (intr_context ()); - - in_external_intr = false; - pic_end_of_interrupt (frame->vec_no); - - if (yield_on_return) - thread_yield (); - } -} - -/* Handles an unexpected interrupt with interrupt frame F. An - unexpected interrupt is one that has no registered handler. */ -static void -unexpected_interrupt (const struct intr_frame *f) -{ - /* Count the number so far. */ - unsigned int n = ++unexpected_cnt[f->vec_no]; - - /* If the number is a power of 2, print a message. This rate - limiting means that we get information about an uncommon - unexpected interrupt the first time and fairly often after - that, but one that occurs many times will not overwhelm the - console. */ - if ((n & (n - 1)) == 0) - printf ("Unexpected interrupt %#04x (%s)\n", - f->vec_no, intr_names[f->vec_no]); -} - -/* Dumps interrupt frame F to the console, for debugging. */ -void -intr_dump_frame (const struct intr_frame *f) -{ - uint32_t cr2; - - /* Store current value of CR2 into `cr2'. - CR2 is the linear address of the last page fault. - See [IA32-v2a] "MOV--Move to/from Control Registers" and - [IA32-v3a] 5.14 "Interrupt 14--Page Fault Exception - (#PF)". */ - asm ("movl %%cr2, %0" : "=r" (cr2)); - - printf ("Interrupt %#04x (%s) at eip=%p\n", - f->vec_no, intr_names[f->vec_no], f->eip); - printf (" cr2=%08"PRIx32" error=%08"PRIx32"\n", cr2, f->error_code); - printf (" eax=%08"PRIx32" ebx=%08"PRIx32" ecx=%08"PRIx32" edx=%08"PRIx32"\n", - f->eax, f->ebx, f->ecx, f->edx); - printf (" esi=%08"PRIx32" edi=%08"PRIx32" esp=%08"PRIx32" ebp=%08"PRIx32"\n", - f->esi, f->edi, (uint32_t) f->esp, f->ebp); - printf (" cs=%04"PRIx16" ds=%04"PRIx16" es=%04"PRIx16" ss=%04"PRIx16"\n", - f->cs, f->ds, f->es, f->ss); -} - -/* Returns the name of interrupt VEC. */ -const char * -intr_name (uint8_t vec) -{ - return intr_names[vec]; -} diff --git a/src/threads/interrupt.h b/src/threads/interrupt.h deleted file mode 100644 index d43e06d90831f76d54e04c4693765565f96ded7c..0000000000000000000000000000000000000000 --- a/src/threads/interrupt.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef THREADS_INTERRUPT_H -#define THREADS_INTERRUPT_H - -#include <stdbool.h> -#include <stdint.h> - -/* Interrupts on or off? */ -enum intr_level - { - INTR_OFF, /* Interrupts disabled. */ - INTR_ON /* Interrupts enabled. */ - }; - -enum intr_level intr_get_level (void); -enum intr_level intr_set_level (enum intr_level); -enum intr_level intr_enable (void); -enum intr_level intr_disable (void); - -/* Interrupt stack frame. */ -struct intr_frame - { - /* Pushed by intr_entry in intr-stubs.S. - These are the interrupted task's saved registers. */ - uint32_t edi; /* Saved EDI. */ - uint32_t esi; /* Saved ESI. */ - uint32_t ebp; /* Saved EBP. */ - uint32_t esp_dummy; /* Not used. */ - uint32_t ebx; /* Saved EBX. */ - uint32_t edx; /* Saved EDX. */ - uint32_t ecx; /* Saved ECX. */ - uint32_t eax; /* Saved EAX. */ - uint16_t gs, :16; /* Saved GS segment register. */ - uint16_t fs, :16; /* Saved FS segment register. */ - uint16_t es, :16; /* Saved ES segment register. */ - uint16_t ds, :16; /* Saved DS segment register. */ - - /* Pushed by intrNN_stub in intr-stubs.S. */ - uint32_t vec_no; /* Interrupt vector number. */ - - /* Sometimes pushed by the CPU, - otherwise for consistency pushed as 0 by intrNN_stub. - The CPU puts it just under `eip', but we move it here. */ - uint32_t error_code; /* Error code. */ - - /* Pushed by intrNN_stub in intr-stubs.S. - This frame pointer eases interpretation of backtraces. */ - void *frame_pointer; /* Saved EBP (frame pointer). */ - - /* Pushed by the CPU. - These are the interrupted task's saved registers. */ - void (*eip) (void); /* Next instruction to execute. */ - uint16_t cs, :16; /* Code segment for eip. */ - uint32_t eflags; /* Saved CPU flags. */ - void *esp; /* Saved stack pointer. */ - uint16_t ss, :16; /* Data segment for esp. */ - }; - -typedef void intr_handler_func (struct intr_frame *); - -void intr_init (void); -void intr_register_ext (uint8_t vec, intr_handler_func *, const char *name); -void intr_register_int (uint8_t vec, int dpl, enum intr_level, - intr_handler_func *, const char *name); -bool intr_context (void); -void intr_yield_on_return (void); - -void intr_dump_frame (const struct intr_frame *); -const char *intr_name (uint8_t vec); - -#endif /* threads/interrupt.h */ diff --git a/src/threads/intr-stubs.S b/src/threads/intr-stubs.S deleted file mode 100644 index adb674e0f2e36755d95066e2156f53c2876d2ca4..0000000000000000000000000000000000000000 --- a/src/threads/intr-stubs.S +++ /dev/null @@ -1,203 +0,0 @@ -#include "threads/loader.h" - - .text - -/* Main interrupt entry point. - - An internal or external interrupt starts in one of the - intrNN_stub routines, which push the `struct intr_frame' - frame_pointer, error_code, and vec_no members on the stack, - then jump here. - - We save the rest of the `struct intr_frame' members to the - stack, set up some registers as needed by the kernel, and then - call intr_handler(), which actually handles the interrupt. - - We "fall through" to intr_exit to return from the interrupt. -*/ -.func intr_entry -intr_entry: - /* Save caller's registers. */ - pushl %ds - pushl %es - pushl %fs - pushl %gs - pushal - - /* Set up kernel environment. */ - cld /* String instructions go upward. */ - mov $SEL_KDSEG, %eax /* Initialize segment registers. */ - mov %eax, %ds - mov %eax, %es - leal 56(%esp), %ebp /* Set up frame pointer. */ - - /* Call interrupt handler. */ - pushl %esp -.globl intr_handler - call intr_handler - addl $4, %esp -.endfunc - -/* Interrupt exit. - - Restores the caller's registers, discards extra data on the - stack, and returns to the caller. - - This is a separate function because it is called directly when - we launch a new user process (see start_process() in - userprog/process.c). */ -.globl intr_exit -.func intr_exit -intr_exit: - /* Restore caller's registers. */ - popal - popl %gs - popl %fs - popl %es - popl %ds - - /* Discard `struct intr_frame' vec_no, error_code, - frame_pointer members. */ - addl $12, %esp - - /* Return to caller. */ - iret -.endfunc - -/* Interrupt stubs. - - This defines 256 fragments of code, named `intr00_stub' - through `intrff_stub', each of which is used as the entry - point for the corresponding interrupt vector. It also puts - the address of each of these functions in the correct spot in - `intr_stubs', an array of function pointers. - - Most of the stubs do this: - - 1. Push %ebp on the stack (frame_pointer in `struct intr_frame'). - - 2. Push 0 on the stack (error_code). - - 3. Push the interrupt number on the stack (vec_no). - - The CPU pushes an extra "error code" on the stack for a few - interrupts. Because we want %ebp to be where the error code - is, we follow a different path: - - 1. Push a duplicate copy of the error code on the stack. - - 2. Replace the original copy of the error code by %ebp. - - 3. Push the interrupt number on the stack. */ - - .data -.globl intr_stubs -intr_stubs: - -/* This implements steps 1 and 2, described above, in the common - case where we just push a 0 error code. */ -#define zero \ - pushl %ebp; \ - pushl $0 - -/* This implements steps 1 and 2, described above, in the case - where the CPU already pushed an error code. */ -#define REAL \ - pushl (%esp); \ - movl %ebp, 4(%esp) - -/* Emits a stub for interrupt vector NUMBER. - TYPE is `zero', for the case where we push a 0 error code, - or `REAL', if the CPU pushes an error code for us. */ -#define STUB(NUMBER, TYPE) \ - .text; \ -.func intr##NUMBER##_stub; \ -intr##NUMBER##_stub: \ - TYPE; \ - push $0x##NUMBER; \ - jmp intr_entry; \ -.endfunc; \ - \ - .data; \ - .long intr##NUMBER##_stub; - -/* All the stubs. */ -STUB(00, zero) STUB(01, zero) STUB(02, zero) STUB(03, zero) -STUB(04, zero) STUB(05, zero) STUB(06, zero) STUB(07, zero) -STUB(08, REAL) STUB(09, zero) STUB(0a, REAL) STUB(0b, REAL) -STUB(0c, zero) STUB(0d, REAL) STUB(0e, REAL) STUB(0f, zero) - -STUB(10, zero) STUB(11, REAL) STUB(12, zero) STUB(13, zero) -STUB(14, zero) STUB(15, zero) STUB(16, zero) STUB(17, zero) -STUB(18, REAL) STUB(19, zero) STUB(1a, REAL) STUB(1b, REAL) -STUB(1c, zero) STUB(1d, REAL) STUB(1e, REAL) STUB(1f, zero) - -STUB(20, zero) STUB(21, zero) STUB(22, zero) STUB(23, zero) -STUB(24, zero) STUB(25, zero) STUB(26, zero) STUB(27, zero) -STUB(28, zero) STUB(29, zero) STUB(2a, zero) STUB(2b, zero) -STUB(2c, zero) STUB(2d, zero) STUB(2e, zero) STUB(2f, zero) - -STUB(30, zero) STUB(31, zero) STUB(32, zero) STUB(33, zero) -STUB(34, zero) STUB(35, zero) STUB(36, zero) STUB(37, zero) -STUB(38, zero) STUB(39, zero) STUB(3a, zero) STUB(3b, zero) -STUB(3c, zero) STUB(3d, zero) STUB(3e, zero) STUB(3f, zero) - -STUB(40, zero) STUB(41, zero) STUB(42, zero) STUB(43, zero) -STUB(44, zero) STUB(45, zero) STUB(46, zero) STUB(47, zero) -STUB(48, zero) STUB(49, zero) STUB(4a, zero) STUB(4b, zero) -STUB(4c, zero) STUB(4d, zero) STUB(4e, zero) STUB(4f, zero) - -STUB(50, zero) STUB(51, zero) STUB(52, zero) STUB(53, zero) -STUB(54, zero) STUB(55, zero) STUB(56, zero) STUB(57, zero) -STUB(58, zero) STUB(59, zero) STUB(5a, zero) STUB(5b, zero) -STUB(5c, zero) STUB(5d, zero) STUB(5e, zero) STUB(5f, zero) - -STUB(60, zero) STUB(61, zero) STUB(62, zero) STUB(63, zero) -STUB(64, zero) STUB(65, zero) STUB(66, zero) STUB(67, zero) -STUB(68, zero) STUB(69, zero) STUB(6a, zero) STUB(6b, zero) -STUB(6c, zero) STUB(6d, zero) STUB(6e, zero) STUB(6f, zero) - -STUB(70, zero) STUB(71, zero) STUB(72, zero) STUB(73, zero) -STUB(74, zero) STUB(75, zero) STUB(76, zero) STUB(77, zero) -STUB(78, zero) STUB(79, zero) STUB(7a, zero) STUB(7b, zero) -STUB(7c, zero) STUB(7d, zero) STUB(7e, zero) STUB(7f, zero) - -STUB(80, zero) STUB(81, zero) STUB(82, zero) STUB(83, zero) -STUB(84, zero) STUB(85, zero) STUB(86, zero) STUB(87, zero) -STUB(88, zero) STUB(89, zero) STUB(8a, zero) STUB(8b, zero) -STUB(8c, zero) STUB(8d, zero) STUB(8e, zero) STUB(8f, zero) - -STUB(90, zero) STUB(91, zero) STUB(92, zero) STUB(93, zero) -STUB(94, zero) STUB(95, zero) STUB(96, zero) STUB(97, zero) -STUB(98, zero) STUB(99, zero) STUB(9a, zero) STUB(9b, zero) -STUB(9c, zero) STUB(9d, zero) STUB(9e, zero) STUB(9f, zero) - -STUB(a0, zero) STUB(a1, zero) STUB(a2, zero) STUB(a3, zero) -STUB(a4, zero) STUB(a5, zero) STUB(a6, zero) STUB(a7, zero) -STUB(a8, zero) STUB(a9, zero) STUB(aa, zero) STUB(ab, zero) -STUB(ac, zero) STUB(ad, zero) STUB(ae, zero) STUB(af, zero) - -STUB(b0, zero) STUB(b1, zero) STUB(b2, zero) STUB(b3, zero) -STUB(b4, zero) STUB(b5, zero) STUB(b6, zero) STUB(b7, zero) -STUB(b8, zero) STUB(b9, zero) STUB(ba, zero) STUB(bb, zero) -STUB(bc, zero) STUB(bd, zero) STUB(be, zero) STUB(bf, zero) - -STUB(c0, zero) STUB(c1, zero) STUB(c2, zero) STUB(c3, zero) -STUB(c4, zero) STUB(c5, zero) STUB(c6, zero) STUB(c7, zero) -STUB(c8, zero) STUB(c9, zero) STUB(ca, zero) STUB(cb, zero) -STUB(cc, zero) STUB(cd, zero) STUB(ce, zero) STUB(cf, zero) - -STUB(d0, zero) STUB(d1, zero) STUB(d2, zero) STUB(d3, zero) -STUB(d4, zero) STUB(d5, zero) STUB(d6, zero) STUB(d7, zero) -STUB(d8, zero) STUB(d9, zero) STUB(da, zero) STUB(db, zero) -STUB(dc, zero) STUB(dd, zero) STUB(de, zero) STUB(df, zero) - -STUB(e0, zero) STUB(e1, zero) STUB(e2, zero) STUB(e3, zero) -STUB(e4, zero) STUB(e5, zero) STUB(e6, zero) STUB(e7, zero) -STUB(e8, zero) STUB(e9, zero) STUB(ea, zero) STUB(eb, zero) -STUB(ec, zero) STUB(ed, zero) STUB(ee, zero) STUB(ef, zero) - -STUB(f0, zero) STUB(f1, zero) STUB(f2, zero) STUB(f3, zero) -STUB(f4, zero) STUB(f5, zero) STUB(f6, zero) STUB(f7, zero) -STUB(f8, zero) STUB(f9, zero) STUB(fa, zero) STUB(fb, zero) -STUB(fc, zero) STUB(fd, zero) STUB(fe, zero) STUB(ff, zero) diff --git a/src/threads/intr-stubs.h b/src/threads/intr-stubs.h deleted file mode 100644 index 9ceba157e27e57d74a9096a2f35f0ff3008ffb10..0000000000000000000000000000000000000000 --- a/src/threads/intr-stubs.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef THREADS_INTR_STUBS_H -#define THREADS_INTR_STUBS_H - -/* Interrupt stubs. - - These are little snippets of code in intr-stubs.S, one for - each of the 256 possible x86 interrupts. Each one does a - little bit of stack manipulation, then jumps to intr_entry(). - See intr-stubs.S for more information. - - This array points to each of the interrupt stub entry points - so that intr_init() can easily find them. */ -typedef void intr_stub_func (void); -extern intr_stub_func *intr_stubs[256]; - -/* Interrupt return path. */ -void intr_exit (void); - -#endif /* threads/intr-stubs.h */ diff --git a/src/threads/io.h b/src/threads/io.h deleted file mode 100644 index 30d52da046ee2faa2d0caac142f67a3730cb9c5f..0000000000000000000000000000000000000000 --- a/src/threads/io.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef THREADS_IO_H -#define THREADS_IO_H - -#include <stddef.h> -#include <stdint.h> - -/* Reads and returns a byte from PORT. */ -static inline uint8_t -inb (uint16_t port) -{ - /* See [IA32-v2a] "IN". */ - uint8_t data; - asm volatile ("inb %w1, %b0" : "=a" (data) : "Nd" (port)); - return data; -} - -/* Reads CNT bytes from PORT, one after another, and stores them - into the buffer starting at ADDR. */ -static inline void -insb (uint16_t port, void *addr, size_t cnt) -{ - /* See [IA32-v2a] "INS". */ - asm volatile ("rep insb" : "+D" (addr), "+c" (cnt) : "d" (port) : "memory"); -} - -/* Reads and returns 16 bits from PORT. */ -static inline uint16_t -inw (uint16_t port) -{ - uint16_t data; - /* See [IA32-v2a] "IN". */ - asm volatile ("inw %w1, %w0" : "=a" (data) : "Nd" (port)); - return data; -} - -/* Reads CNT 16-bit (halfword) units from PORT, one after - another, and stores them into the buffer starting at ADDR. */ -static inline void -insw (uint16_t port, void *addr, size_t cnt) -{ - /* See [IA32-v2a] "INS". */ - asm volatile ("rep insw" : "+D" (addr), "+c" (cnt) : "d" (port) : "memory"); -} - -/* Reads and returns 32 bits from PORT. */ -static inline uint32_t -inl (uint16_t port) -{ - /* See [IA32-v2a] "IN". */ - uint32_t data; - asm volatile ("inl %w1, %0" : "=a" (data) : "Nd" (port)); - return data; -} - -/* Reads CNT 32-bit (word) units from PORT, one after another, - and stores them into the buffer starting at ADDR. */ -static inline void -insl (uint16_t port, void *addr, size_t cnt) -{ - /* See [IA32-v2a] "INS". */ - asm volatile ("rep insl" : "+D" (addr), "+c" (cnt) : "d" (port) : "memory"); -} - -/* Writes byte DATA to PORT. */ -static inline void -outb (uint16_t port, uint8_t data) -{ - /* See [IA32-v2b] "OUT". */ - asm volatile ("outb %b0, %w1" : : "a" (data), "Nd" (port)); -} - -/* Writes to PORT each byte of data in the CNT-byte buffer - starting at ADDR. */ -static inline void -outsb (uint16_t port, const void *addr, size_t cnt) -{ - /* See [IA32-v2b] "OUTS". */ - asm volatile ("rep outsb" : "+S" (addr), "+c" (cnt) : "d" (port)); -} - -/* Writes the 16-bit DATA to PORT. */ -static inline void -outw (uint16_t port, uint16_t data) -{ - /* See [IA32-v2b] "OUT". */ - asm volatile ("outw %w0, %w1" : : "a" (data), "Nd" (port)); -} - -/* Writes to PORT each 16-bit unit (halfword) of data in the - CNT-halfword buffer starting at ADDR. */ -static inline void -outsw (uint16_t port, const void *addr, size_t cnt) -{ - /* See [IA32-v2b] "OUTS". */ - asm volatile ("rep outsw" : "+S" (addr), "+c" (cnt) : "d" (port)); -} - -/* Writes the 32-bit DATA to PORT. */ -static inline void -outl (uint16_t port, uint32_t data) -{ - /* See [IA32-v2b] "OUT". */ - asm volatile ("outl %0, %w1" : : "a" (data), "Nd" (port)); -} - -/* Writes to PORT each 32-bit unit (word) of data in the CNT-word - buffer starting at ADDR. */ -static inline void -outsl (uint16_t port, const void *addr, size_t cnt) -{ - /* See [IA32-v2b] "OUTS". */ - asm volatile ("rep outsl" : "+S" (addr), "+c" (cnt) : "d" (port)); -} - -#endif /* threads/io.h */ diff --git a/src/threads/kernel.lds.S b/src/threads/kernel.lds.S deleted file mode 100644 index 19082d5d3896111dae63de572d7ef5649e8220d3..0000000000000000000000000000000000000000 --- a/src/threads/kernel.lds.S +++ /dev/null @@ -1,30 +0,0 @@ -#include "threads/loader.h" - -OUTPUT_FORMAT("elf32-i386") -OUTPUT_ARCH("i386") -ENTRY(start) /* Kernel starts at "start" symbol. */ -SECTIONS -{ - /* Specify the kernel base address. */ - _start = LOADER_PHYS_BASE + LOADER_KERN_BASE; - - /* Make room for the ELF headers. */ - . = _start + SIZEOF_HEADERS; - - /* Kernel starts with code, followed by read-only data and writable data. */ - .text : { *(.start) *(.text) } = 0x90 - .rodata : { *(.rodata) *(.rodata.*) - . = ALIGN(0x1000); - _end_kernel_text = .; } - .data : { *(.data) - _signature = .; LONG(0xaa55aa55) } - - /* BSS (zero-initialized data) is after everything else. */ - _start_bss = .; - .bss : { *(.bss) } - _end_bss = .; - - _end = .; - - ASSERT (_end - _start <= 512K, "Kernel image is too big.") -} diff --git a/src/threads/loader.S b/src/threads/loader.S deleted file mode 100644 index dd87ea1c794bc1759ceca654fc953eaea082d763..0000000000000000000000000000000000000000 --- a/src/threads/loader.S +++ /dev/null @@ -1,263 +0,0 @@ -#include "threads/loader.h" - -#### Kernel loader. - -#### This code should be stored in the first sector of a hard disk. -#### When the BIOS runs, it loads this code at physical address -#### 0x7c00-0x7e00 (512 bytes) and jumps to the beginning of it, -#### in real mode. The loader loads the kernel into memory and jumps -#### to its entry point, which is the start function in start.S. -#### -#### The BIOS passes in the drive that the loader was read from as -#### DL, with floppy drives numbered 0x00, 0x01, ... and hard drives -#### numbered 0x80, 0x81, ... We want to support booting a kernel on -#### a different drive from the loader, so we don't take advantage of -#### this. - -# Runs in real mode, which is a 16-bit segment. - .code16 - -# Set up segment registers. -# Set stack to grow downward from 60 kB (after boot, the kernel -# continues to use this stack for its initial thread). - - sub %ax, %ax - mov %ax, %ds - mov %ax, %ss - mov $0xf000, %esp - -# Configure serial port so we can report progress without connected VGA. -# See [IntrList] for details. - sub %dx, %dx # Serial port 0. - mov $0xe3, %al # 9600 bps, N-8-1. - # AH is already 0 (Initialize Port). - int $0x14 # Destroys AX. - - call puts - .string "PiLo" - -#### Read the partition table on each system hard disk and scan for a -#### partition of type 0x20, which is the type that we use for a -#### Pintos kernel. -#### -#### Read [Partitions] for a description of the partition table format -#### that we parse. -#### -#### We print out status messages to show the disk and partition being -#### scanned, e.g. hda1234 as we scan four partitions on the first -#### hard disk. - - mov $0x80, %dl # Hard disk 0. -read_mbr: - sub %ebx, %ebx # Sector 0. - mov $0x2000, %ax # Use 0x20000 for buffer. - mov %ax, %es - call read_sector - jc no_such_drive - - # Print hd[a-z]. - call puts - .string " hd" - mov %dl, %al - add $'a' - 0x80, %al - call putc - - # Check for MBR signature--if not present, it's not a - # partitioned hard disk. - cmpw $0xaa55, %es:510 - jne next_drive - - mov $446, %si # Offset of partition table entry 1. - mov $'1', %al -check_partition: - # Is it an unused partition? - cmpl $0, %es:(%si) - je next_partition - - # Print [1-4]. - call putc - - # Is it a Pintos kernel partition? - cmpb $0x20, %es:4(%si) - jne next_partition - - # Is it a bootable partition? - cmpb $0x80, %es:(%si) - je load_kernel - -next_partition: - # No match for this partition, go on to the next one. - add $16, %si # Offset to next partition table entry. - inc %al - cmp $510, %si - jb check_partition - -next_drive: - # No match on this drive, go on to the next one. - inc %dl - jnc read_mbr - -no_such_drive: -no_boot_partition: - # Didn't find a Pintos kernel partition anywhere, give up. - call puts - .string "\rNot found\r" - - # Notify BIOS that boot failed. See [IntrList]. - int $0x18 - -#### We found a kernel. The kernel's drive is in DL. The partition -#### table entry for the kernel's partition is at ES:SI. Our job now -#### is to read the kernel from disk and jump to its start address. - -load_kernel: - call puts - .string "\rLoading" - - # Figure out number of sectors to read. A Pintos kernel is - # just an ELF format object, which doesn't have an - # easy-to-read field to identify its own size (see [ELF1]). - # But we limit Pintos kernels to 512 kB for other reasons, so - # it's easy enough to just read the entire contents of the - # partition or 512 kB from disk, whichever is smaller. - mov %es:12(%si), %ecx # EBP = number of sectors - cmp $1024, %ecx # Cap size at 512 kB - jbe 1f - mov $1024, %cx -1: - - mov %es:8(%si), %ebx # EBX = first sector - mov $0x2000, %ax # Start load address: 0x20000 - -next_sector: - # Read one sector into memory. - mov %ax, %es # ES:0000 -> load address - call read_sector - jc read_failed - - # Print '.' as progress indicator once every 16 sectors == 8 kB. - test $15, %bl - jnz 1f - call puts - .string "." -1: - - # Advance memory pointer and disk sector. - add $0x20, %ax - inc %bx - loop next_sector - - call puts - .string "\r" - -#### Transfer control to the kernel that we loaded. We read the start -#### address out of the ELF header (see [ELF1]) and convert it from a -#### 32-bit linear address into a 16:16 segment:offset address for -#### real mode, then jump to the converted address. The 80x86 doesn't -#### have an instruction to jump to an absolute segment:offset kept in -#### registers, so in fact we store the address in a temporary memory -#### location, then jump indirectly through that location. To save 4 -#### bytes in the loader, we reuse 4 bytes of the loader's code for -#### this temporary pointer. - - mov $0x2000, %ax - mov %ax, %es - mov %es:0x18, %dx - mov %dx, start - movw $0x2000, start + 2 - ljmp *start - -read_failed: -start: - # Disk sector read failed. - call puts -1: .string "\rBad read\r" - - # Notify BIOS that boot failed. See [IntrList]. - int $0x18 - -#### Print string subroutine. To save space in the loader, this -#### subroutine takes its null-terminated string argument from the -#### code stream just after the call, and then returns to the byte -#### just after the terminating null. This subroutine preserves all -#### general-purpose registers. - -puts: xchg %si, %ss:(%esp) - push %ax -next_char: - mov %cs:(%si), %al - inc %si - test %al, %al - jz 1f - call putc - jmp next_char -1: pop %ax - xchg %si, %ss:(%esp) - ret - -#### Character output subroutine. Prints the character in AL to the -#### VGA display and serial port 0, using BIOS services (see -#### [IntrList]). Preserves all general-purpose registers. -#### -#### If called upon to output a carriage return, this subroutine -#### automatically supplies the following line feed. - -putc: pusha - -1: sub %bh, %bh # Page 0. - mov $0x0e, %ah # Teletype output service. - int $0x10 - - mov $0x01, %ah # Serial port output service. - sub %dx, %dx # Serial port 0. -2: int $0x14 # Destroys AH. - test $0x80, %ah # Output timed out? - jz 3f - movw $0x9090, 2b # Turn "int $0x14" above into NOPs. - -3: - cmp $'\r', %al - jne popa_ret - mov $'\n', %al - jmp 1b - -#### Sector read subroutine. Takes a drive number in DL (0x80 = hard -#### disk 0, 0x81 = hard disk 1, ...) and a sector number in EBX, and -#### reads the specified sector into memory at ES:0000. Returns with -#### carry set on error, clear otherwise. Preserves all -#### general-purpose registers. - -read_sector: - pusha - sub %ax, %ax - push %ax # LBA sector number [48:63] - push %ax # LBA sector number [32:47] - push %ebx # LBA sector number [0:31] - push %es # Buffer segment - push %ax # Buffer offset (always 0) - push $1 # Number of sectors to read - push $16 # Packet size - mov $0x42, %ah # Extended read - mov %sp, %si # DS:SI -> packet - int $0x13 # Error code in CF - popa # Pop 16 bytes, preserve flags -popa_ret: - popa - ret # Error code still in CF - -#### Command-line arguments and their count. -#### This is written by the `pintos' utility and read by the kernel. -#### The loader itself does not do anything with the command line. - .org LOADER_ARG_CNT - LOADER_BASE - .fill LOADER_ARG_CNT_LEN, 1, 0 - - .org LOADER_ARGS - LOADER_BASE - .fill LOADER_ARGS_LEN, 1, 0 - -#### Partition table. - .org LOADER_PARTS - LOADER_BASE - .fill LOADER_PARTS_LEN, 1, 0 - -#### Boot-sector signature for BIOS inspection. - .org LOADER_SIG - LOADER_BASE - .word 0xaa55 diff --git a/src/threads/loader.h b/src/threads/loader.h deleted file mode 100644 index 1bfe111185d0f777f5cadf83824d5abe03b64b00..0000000000000000000000000000000000000000 --- a/src/threads/loader.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef THREADS_LOADER_H -#define THREADS_LOADER_H - -/* Constants fixed by the PC BIOS. */ -#define LOADER_BASE 0x7c00 /* Physical address of loader's base. */ -#define LOADER_END 0x7e00 /* Physical address of end of loader. */ - -/* Physical address of kernel base. */ -#define LOADER_KERN_BASE 0x20000 /* 128 kB. */ - -/* Kernel virtual address at which all physical memory is mapped. - Must be aligned on a 4 MB boundary. */ -#define LOADER_PHYS_BASE 0xc0000000 /* 3 GB. */ - -/* Important loader physical addresses. */ -#define LOADER_SIG (LOADER_END - LOADER_SIG_LEN) /* 0xaa55 BIOS signature. */ -#define LOADER_PARTS (LOADER_SIG - LOADER_PARTS_LEN) /* Partition table. */ -#define LOADER_ARGS (LOADER_PARTS - LOADER_ARGS_LEN) /* Command-line args. */ -#define LOADER_ARG_CNT (LOADER_ARGS - LOADER_ARG_CNT_LEN) /* Number of args. */ - -/* Sizes of loader data structures. */ -#define LOADER_SIG_LEN 2 -#define LOADER_PARTS_LEN 64 -#define LOADER_ARGS_LEN 128 -#define LOADER_ARG_CNT_LEN 4 - -/* GDT selectors defined by loader. - More selectors are defined by userprog/gdt.h. */ -#define SEL_NULL 0x00 /* Null selector. */ -#define SEL_KCSEG 0x08 /* Kernel code selector. */ -#define SEL_KDSEG 0x10 /* Kernel data selector. */ - -#ifndef __ASSEMBLER__ -#include <stdint.h> - -/* Amount of physical memory, in 4 kB pages. */ -extern uint32_t init_ram_pages; -#endif - -#endif /* threads/loader.h */ diff --git a/src/threads/malloc.c b/src/threads/malloc.c deleted file mode 100644 index f6f803b9b6dc437a25876928679ab393176c086d..0000000000000000000000000000000000000000 --- a/src/threads/malloc.c +++ /dev/null @@ -1,294 +0,0 @@ -#include "threads/malloc.h" -#include <debug.h> -#include <list.h> -#include <round.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include "threads/palloc.h" -#include "threads/synch.h" -#include "threads/vaddr.h" - -/* A simple implementation of malloc(). - - The size of each request, in bytes, is rounded up to a power - of 2 and assigned to the "descriptor" that manages blocks of - that size. The descriptor keeps a list of free blocks. If - the free list is nonempty, one of its blocks is used to - satisfy the request. - - Otherwise, a new page of memory, called an "arena", is - obtained from the page allocator (if none is available, - malloc() returns a null pointer). The new arena is divided - into blocks, all of which are added to the descriptor's free - list. Then we return one of the new blocks. - - When we free a block, we add it to its descriptor's free list. - But if the arena that the block was in now has no in-use - blocks, we remove all of the arena's blocks from the free list - and give the arena back to the page allocator. - - We can't handle blocks bigger than 2 kB using this scheme, - because they're too big to fit in a single page with a - descriptor. We handle those by allocating contiguous pages - with the page allocator and sticking the allocation size at - the beginning of the allocated block's arena header. */ - -/* Descriptor. */ -struct desc - { - size_t block_size; /* Size of each element in bytes. */ - size_t blocks_per_arena; /* Number of blocks in an arena. */ - struct list free_list; /* List of free blocks. */ - struct lock lock; /* Lock. */ - }; - -/* Magic number for detecting arena corruption. */ -#define ARENA_MAGIC 0x9a548eed - -/* Arena. */ -struct arena - { - unsigned magic; /* Always set to ARENA_MAGIC. */ - struct desc *desc; /* Owning descriptor, null for big block. */ - size_t free_cnt; /* Free blocks; pages in big block. */ - }; - -/* Free block. */ -struct block - { - struct list_elem free_elem; /* Free list element. */ - }; - -/* Our set of descriptors. */ -static struct desc descs[10]; /* Descriptors. */ -static size_t desc_cnt; /* Number of descriptors. */ - -static struct arena *block_to_arena (struct block *); -static struct block *arena_to_block (struct arena *, size_t idx); - -/* Initializes the malloc() descriptors. */ -void -malloc_init (void) -{ - size_t block_size; - - for (block_size = 16; block_size < PGSIZE / 2; block_size *= 2) - { - struct desc *d = &descs[desc_cnt++]; - ASSERT (desc_cnt <= sizeof descs / sizeof *descs); - d->block_size = block_size; - d->blocks_per_arena = (PGSIZE - sizeof (struct arena)) / block_size; - list_init (&d->free_list); - lock_init (&d->lock); - } -} - -/* Obtains and returns a new block of at least SIZE bytes. - Returns a null pointer if memory is not available. */ -void * -malloc (size_t size) -{ - struct desc *d; - struct block *b; - struct arena *a; - - /* A null pointer satisfies a request for 0 bytes. */ - if (size == 0) - return NULL; - - /* Find the smallest descriptor that satisfies a SIZE-byte - request. */ - for (d = descs; d < descs + desc_cnt; d++) - if (d->block_size >= size) - break; - if (d == descs + desc_cnt) - { - /* SIZE is too big for any descriptor. - Allocate enough pages to hold SIZE plus an arena. */ - size_t page_cnt = DIV_ROUND_UP (size + sizeof *a, PGSIZE); - a = palloc_get_multiple (0, page_cnt); - if (a == NULL) - return NULL; - - /* Initialize the arena to indicate a big block of PAGE_CNT - pages, and return it. */ - a->magic = ARENA_MAGIC; - a->desc = NULL; - a->free_cnt = page_cnt; - return a + 1; - } - - lock_acquire (&d->lock); - - /* If the free list is empty, create a new arena. */ - if (list_empty (&d->free_list)) - { - size_t i; - - /* Allocate a page. */ - a = palloc_get_page (0); - if (a == NULL) - { - lock_release (&d->lock); - return NULL; - } - - /* Initialize arena and add its blocks to the free list. */ - a->magic = ARENA_MAGIC; - a->desc = d; - a->free_cnt = d->blocks_per_arena; - for (i = 0; i < d->blocks_per_arena; i++) - { - struct block *b = arena_to_block (a, i); - list_push_back (&d->free_list, &b->free_elem); - } - } - - /* Get a block from free list and return it. */ - b = list_entry (list_pop_front (&d->free_list), struct block, free_elem); - a = block_to_arena (b); - a->free_cnt--; - lock_release (&d->lock); - return b; -} - -/* Allocates and return A times B bytes initialized to zeroes. - Returns a null pointer if memory is not available. */ -void * -calloc (size_t a, size_t b) -{ - void *p; - size_t size; - - /* Calculate block size and make sure it fits in size_t. */ - size = a * b; - if (size < a || size < b) - return NULL; - - /* Allocate and zero memory. */ - p = malloc (size); - if (p != NULL) - memset (p, 0, size); - - return p; -} - -/* Returns the number of bytes allocated for BLOCK. */ -static size_t -block_size (void *block) -{ - struct block *b = block; - struct arena *a = block_to_arena (b); - struct desc *d = a->desc; - - return d != NULL ? d->block_size : PGSIZE * a->free_cnt - pg_ofs (block); -} - -/* Attempts to resize OLD_BLOCK to NEW_SIZE bytes, possibly - moving it in the process. - If successful, returns the new block; on failure, returns a - null pointer. - A call with null OLD_BLOCK is equivalent to malloc(NEW_SIZE). - A call with zero NEW_SIZE is equivalent to free(OLD_BLOCK). */ -void * -realloc (void *old_block, size_t new_size) -{ - if (new_size == 0) - { - free (old_block); - return NULL; - } - else - { - void *new_block = malloc (new_size); - if (old_block != NULL && new_block != NULL) - { - size_t old_size = block_size (old_block); - size_t min_size = new_size < old_size ? new_size : old_size; - memcpy (new_block, old_block, min_size); - free (old_block); - } - return new_block; - } -} - -/* Frees block P, which must have been previously allocated with - malloc(), calloc(), or realloc(). */ -void -free (void *p) -{ - if (p != NULL) - { - struct block *b = p; - struct arena *a = block_to_arena (b); - struct desc *d = a->desc; - - if (d != NULL) - { - /* It's a normal block. We handle it here. */ - -#ifndef NDEBUG - /* Clear the block to help detect use-after-free bugs. */ - memset (b, 0xcc, d->block_size); -#endif - - lock_acquire (&d->lock); - - /* Add block to free list. */ - list_push_front (&d->free_list, &b->free_elem); - - /* If the arena is now entirely unused, free it. */ - if (++a->free_cnt >= d->blocks_per_arena) - { - size_t i; - - ASSERT (a->free_cnt == d->blocks_per_arena); - for (i = 0; i < d->blocks_per_arena; i++) - { - struct block *b = arena_to_block (a, i); - list_remove (&b->free_elem); - } - palloc_free_page (a); - } - - lock_release (&d->lock); - } - else - { - /* It's a big block. Free its pages. */ - palloc_free_multiple (a, a->free_cnt); - return; - } - } -} - -/* Returns the arena that block B is inside. */ -static struct arena * -block_to_arena (struct block *b) -{ - struct arena *a = pg_round_down (b); - - /* Check that the arena is valid. */ - ASSERT (a != NULL); - ASSERT (a->magic == ARENA_MAGIC); - - /* Check that the block is properly aligned for the arena. */ - ASSERT (a->desc == NULL - || (pg_ofs (b) - sizeof *a) % a->desc->block_size == 0); - ASSERT (a->desc != NULL || pg_ofs (b) == sizeof *a); - - return a; -} - -/* Returns the (IDX - 1)'th block within arena A. */ -static struct block * -arena_to_block (struct arena *a, size_t idx) -{ - ASSERT (a != NULL); - ASSERT (a->magic == ARENA_MAGIC); - ASSERT (idx < a->desc->blocks_per_arena); - return (struct block *) ((uint8_t *) a - + sizeof *a - + idx * a->desc->block_size); -} diff --git a/src/threads/malloc.h b/src/threads/malloc.h deleted file mode 100644 index bc55d362b0c7276eb335b8d5d898c508db48675f..0000000000000000000000000000000000000000 --- a/src/threads/malloc.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef THREADS_MALLOC_H -#define THREADS_MALLOC_H - -#include <debug.h> -#include <stddef.h> - -void malloc_init (void); -void *malloc (size_t) __attribute__ ((malloc)); -void *calloc (size_t, size_t) __attribute__ ((malloc)); -void *realloc (void *, size_t); -void free (void *); - -#endif /* threads/malloc.h */ diff --git a/src/threads/palloc.c b/src/threads/palloc.c deleted file mode 100644 index 4fc8394c8f078a20c5a48722c36e3e022658620e..0000000000000000000000000000000000000000 --- a/src/threads/palloc.c +++ /dev/null @@ -1,182 +0,0 @@ -#include "threads/palloc.h" -#include <bitmap.h> -#include <debug.h> -#include <inttypes.h> -#include <round.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include "threads/loader.h" -#include "threads/synch.h" -#include "threads/vaddr.h" - -/* Page allocator. Hands out memory in page-size (or - page-multiple) chunks. See malloc.h for an allocator that - hands out smaller chunks. - - System memory is divided into two "pools" called the kernel - and user pools. The user pool is for user (virtual) memory - pages, the kernel pool for everything else. The idea here is - that the kernel needs to have memory for its own operations - even if user processes are swapping like mad. - - By default, half of system RAM is given to the kernel pool and - half to the user pool. That should be huge overkill for the - kernel pool, but that's just fine for demonstration purposes. */ - -/* A memory pool. */ -struct pool - { - struct lock lock; /* Mutual exclusion. */ - struct bitmap *used_map; /* Bitmap of free pages. */ - uint8_t *base; /* Base of pool. */ - }; - -/* Two pools: one for kernel data, one for user pages. */ -static struct pool kernel_pool, user_pool; - -static void init_pool (struct pool *, void *base, size_t page_cnt, - const char *name); -static bool page_from_pool (const struct pool *, void *page); - -/* Initializes the page allocator. At most USER_PAGE_LIMIT - pages are put into the user pool. */ -void -palloc_init (size_t user_page_limit) -{ - /* Free memory starts at 1 MB and runs to the end of RAM. */ - uint8_t *free_start = ptov (1024 * 1024); - uint8_t *free_end = ptov (init_ram_pages * PGSIZE); - size_t free_pages = (free_end - free_start) / PGSIZE; - size_t user_pages = free_pages / 2; - size_t kernel_pages; - if (user_pages > user_page_limit) - user_pages = user_page_limit; - kernel_pages = free_pages - user_pages; - - /* Give half of memory to kernel, half to user. */ - init_pool (&kernel_pool, free_start, kernel_pages, "kernel pool"); - init_pool (&user_pool, free_start + kernel_pages * PGSIZE, - user_pages, "user pool"); -} - -/* Obtains and returns a group of PAGE_CNT contiguous free pages. - If PAL_USER is set, the pages are obtained from the user pool, - otherwise from the kernel pool. If PAL_ZERO is set in FLAGS, - then the pages are filled with zeros. If too few pages are - available, returns a null pointer, unless PAL_ASSERT is set in - FLAGS, in which case the kernel panics. */ -void * -palloc_get_multiple (enum palloc_flags flags, size_t page_cnt) -{ - struct pool *pool = flags & PAL_USER ? &user_pool : &kernel_pool; - void *pages; - size_t page_idx; - - if (page_cnt == 0) - return NULL; - - lock_acquire (&pool->lock); - page_idx = bitmap_scan_and_flip (pool->used_map, 0, page_cnt, false); - lock_release (&pool->lock); - - if (page_idx != BITMAP_ERROR) - pages = pool->base + PGSIZE * page_idx; - else - pages = NULL; - - if (pages != NULL) - { - if (flags & PAL_ZERO) - memset (pages, 0, PGSIZE * page_cnt); - } - else - { - if (flags & PAL_ASSERT) - PANIC ("palloc_get: out of pages"); - } - - return pages; -} - -/* Obtains a single free page and returns its kernel virtual - address. - If PAL_USER is set, the page is obtained from the user pool, - otherwise from the kernel pool. If PAL_ZERO is set in FLAGS, - then the page is filled with zeros. If no pages are - available, returns a null pointer, unless PAL_ASSERT is set in - FLAGS, in which case the kernel panics. */ -void * -palloc_get_page (enum palloc_flags flags) -{ - return palloc_get_multiple (flags, 1); -} - -/* Frees the PAGE_CNT pages starting at PAGES. */ -void -palloc_free_multiple (void *pages, size_t page_cnt) -{ - struct pool *pool; - size_t page_idx; - - ASSERT (pg_ofs (pages) == 0); - if (pages == NULL || page_cnt == 0) - return; - - if (page_from_pool (&kernel_pool, pages)) - pool = &kernel_pool; - else if (page_from_pool (&user_pool, pages)) - pool = &user_pool; - else - NOT_REACHED (); - - page_idx = pg_no (pages) - pg_no (pool->base); - -#ifndef NDEBUG - memset (pages, 0xcc, PGSIZE * page_cnt); -#endif - - ASSERT (bitmap_all (pool->used_map, page_idx, page_cnt)); - bitmap_set_multiple (pool->used_map, page_idx, page_cnt, false); -} - -/* Frees the page at PAGE. */ -void -palloc_free_page (void *page) -{ - palloc_free_multiple (page, 1); -} - -/* Initializes pool P as starting at START and ending at END, - naming it NAME for debugging purposes. */ -static void -init_pool (struct pool *p, void *base, size_t page_cnt, const char *name) -{ - /* We'll put the pool's used_map at its base. - Calculate the space needed for the bitmap - and subtract it from the pool's size. */ - size_t bm_pages = DIV_ROUND_UP (bitmap_buf_size (page_cnt), PGSIZE); - if (bm_pages > page_cnt) - PANIC ("Not enough memory in %s for bitmap.", name); - page_cnt -= bm_pages; - - printf ("%zu pages available in %s.\n", page_cnt, name); - - /* Initialize the pool. */ - lock_init (&p->lock); - p->used_map = bitmap_create_in_buf (page_cnt, base, bm_pages * PGSIZE); - p->base = base + bm_pages * PGSIZE; -} - -/* Returns true if PAGE was allocated from POOL, - false otherwise. */ -static bool -page_from_pool (const struct pool *pool, void *page) -{ - size_t page_no = pg_no (page); - size_t start_page = pg_no (pool->base); - size_t end_page = start_page + bitmap_size (pool->used_map); - - return page_no >= start_page && page_no < end_page; -} diff --git a/src/threads/palloc.h b/src/threads/palloc.h deleted file mode 100644 index cb3b70e94c93b6642ae35b74eee636da594c2d8d..0000000000000000000000000000000000000000 --- a/src/threads/palloc.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef THREADS_PALLOC_H -#define THREADS_PALLOC_H - -#include <stddef.h> - -/* How to allocate pages. */ -enum palloc_flags - { - PAL_ASSERT = 001, /* Panic on failure. */ - PAL_ZERO = 002, /* Zero page contents. */ - PAL_USER = 004 /* User page. */ - }; - -void palloc_init (size_t user_page_limit); -void *palloc_get_page (enum palloc_flags); -void *palloc_get_multiple (enum palloc_flags, size_t page_cnt); -void palloc_free_page (void *); -void palloc_free_multiple (void *, size_t page_cnt); - -#endif /* threads/palloc.h */ diff --git a/src/threads/pte.h b/src/threads/pte.h deleted file mode 100644 index 1660727108385418a2cf07edba939f2a77ed9399..0000000000000000000000000000000000000000 --- a/src/threads/pte.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef THREADS_PTE_H -#define THREADS_PTE_H - -#include "threads/vaddr.h" - -/* Functions and macros for working with x86 hardware page - tables. - - See vaddr.h for more generic functions and macros for virtual - addresses. - - Virtual addresses are structured as follows: - - 31 22 21 12 11 0 - +----------------------+----------------------+----------------------+ - | Page Directory Index | Page Table Index | Page Offset | - +----------------------+----------------------+----------------------+ -*/ - -/* Page table index (bits 12:21). */ -#define PTSHIFT PGBITS /* First page table bit. */ -#define PTBITS 10 /* Number of page table bits. */ -#define PTSPAN (1 << PTBITS << PGBITS) /* Bytes covered by a page table. */ -#define PTMASK BITMASK(PTSHIFT, PTBITS) /* Page table bits (12:21). */ - -/* Page directory index (bits 22:31). */ -#define PDSHIFT (PTSHIFT + PTBITS) /* First page directory bit. */ -#define PDBITS 10 /* Number of page dir bits. */ -#define PDMASK BITMASK(PDSHIFT, PDBITS) /* Page directory bits (22:31). */ - -/* Obtains page table index from a virtual address. */ -static inline unsigned pt_no (const void *va) { - return ((uintptr_t) va & PTMASK) >> PTSHIFT; -} - -/* Obtains page directory index from a virtual address. */ -static inline uintptr_t pd_no (const void *va) { - return (uintptr_t) va >> PDSHIFT; -} - -/* Page directory and page table entries. - - For more information see the section on page tables in the - Pintos reference guide chapter, or [IA32-v3a] 3.7.6 - "Page-Directory and Page-Table Entries". - - PDEs and PTEs share a common format: - - 31 12 11 0 - +------------------------------------+------------------------+ - | Physical Address | Flags | - +------------------------------------+------------------------+ - - In a PDE, the physical address points to a page table. - In a PTE, the physical address points to a data or code page. - The important flags are listed below. - When a PDE or PTE is not "present", the other flags are - ignored. - A PDE or PTE that is initialized to 0 will be interpreted as - "not present", which is just fine. */ -#define PTE_FLAGS 0x00000fff /* Flag bits. */ -#define PTE_ADDR 0xfffff000 /* Address bits. */ -#define PTE_AVL 0x00000e00 /* Bits available for OS use. */ -#define PTE_P 0x1 /* 1=present, 0=not present. */ -#define PTE_W 0x2 /* 1=read/write, 0=read-only. */ -#define PTE_U 0x4 /* 1=user/kernel, 0=kernel only. */ -#define PTE_A 0x20 /* 1=accessed, 0=not acccessed. */ -#define PTE_D 0x40 /* 1=dirty, 0=not dirty (PTEs only). */ - -/* Returns a PDE that points to page table PT. */ -static inline uint32_t pde_create (uint32_t *pt) { - ASSERT (pg_ofs (pt) == 0); - return vtop (pt) | PTE_U | PTE_P | PTE_W; -} - -/* Returns a pointer to the page table that page directory entry - PDE, which must "present", points to. */ -static inline uint32_t *pde_get_pt (uint32_t pde) { - ASSERT (pde & PTE_P); - return ptov (pde & PTE_ADDR); -} - -/* Returns a PTE that points to PAGE. - The PTE's page is readable. - If WRITABLE is true then it will be writable as well. - The page will be usable only by ring 0 code (the kernel). */ -static inline uint32_t pte_create_kernel (void *page, bool writable) { - ASSERT (pg_ofs (page) == 0); - return vtop (page) | PTE_P | (writable ? PTE_W : 0); -} - -/* Returns a PTE that points to PAGE. - The PTE's page is readable. - If WRITABLE is true then it will be writable as well. - The page will be usable by both user and kernel code. */ -static inline uint32_t pte_create_user (void *page, bool writable) { - return pte_create_kernel (page, writable) | PTE_U; -} - -/* Returns a pointer to the page that page table entry PTE points - to. */ -static inline void *pte_get_page (uint32_t pte) { - return ptov (pte & PTE_ADDR); -} - -#endif /* threads/pte.h */ - diff --git a/src/threads/start.S b/src/threads/start.S deleted file mode 100644 index 29ffa7a42f3ed45a948befce9bceb9bd3c518ff5..0000000000000000000000000000000000000000 --- a/src/threads/start.S +++ /dev/null @@ -1,204 +0,0 @@ - #include "threads/loader.h" - -#### Kernel startup code. - -#### The loader (in loader.S) loads the kernel at physical address -#### 0x20000 (128 kB) and jumps to "start", defined here. This code -#### switches from real mode to 32-bit protected mode and calls -#### main(). - -/* Flags in control register 0. */ -#define CR0_PE 0x00000001 /* Protection Enable. */ -#define CR0_EM 0x00000004 /* (Floating-point) Emulation. */ -#define CR0_PG 0x80000000 /* Paging. */ -#define CR0_WP 0x00010000 /* Write-Protect enable in kernel mode. */ - - .section .start - -# The following code runs in real mode, which is a 16-bit code segment. - .code16 - -.func start -.globl start -start: - -# The loader called into us with CS = 0x2000, SS = 0x0000, ESP = 0xf000, -# but we should initialize the other segment registers. - - mov $0x2000, %ax - mov %ax, %ds - mov %ax, %es - -# Set string instructions to go upward. - cld - -#### Get memory size, via interrupt 15h function 88h (see [IntrList]), -#### which returns AX = (kB of physical memory) - 1024. This only -#### works for memory sizes <= 65 MB, which should be fine for our -#### purposes. We cap memory at 64 MB because that's all we prepare -#### page tables for, below. - - movb $0x88, %ah - int $0x15 - addl $1024, %eax # Total kB memory - cmp $0x10000, %eax # Cap at 64 MB - jbe 1f - mov $0x10000, %eax -1: shrl $2, %eax # Total 4 kB pages - addr32 movl %eax, init_ram_pages - LOADER_PHYS_BASE - 0x20000 - -#### Enable A20. Address line 20 is tied low when the machine boots, -#### which prevents addressing memory about 1 MB. This code fixes it. - -# Poll status register while busy. - -1: inb $0x64, %al - testb $0x2, %al - jnz 1b - -# Send command for writing output port. - - movb $0xd1, %al - outb %al, $0x64 - -# Poll status register while busy. - -1: inb $0x64, %al - testb $0x2, %al - jnz 1b - -# Enable A20 line. - - movb $0xdf, %al - outb %al, $0x60 - -# Poll status register while busy. - -1: inb $0x64, %al - testb $0x2, %al - jnz 1b - -#### Create temporary page directory and page table and set page -#### directory base register. - -# Create page directory at 0xf000 (60 kB) and fill with zeroes. - mov $0xf00, %ax - mov %ax, %es - subl %eax, %eax - subl %edi, %edi - movl $0x400, %ecx - rep stosl - -# Add PDEs to point to page tables for the first 64 MB of RAM. -# Also add identical PDEs starting at LOADER_PHYS_BASE. -# See [IA32-v3a] section 3.7.6 "Page-Directory and Page-Table Entries" -# for a description of the bits in %eax. - - movl $0x10007, %eax - movl $0x11, %ecx - subl %edi, %edi -1: movl %eax, %es:(%di) - movl %eax, %es:LOADER_PHYS_BASE >> 20(%di) - addw $4, %di - addl $0x1000, %eax - loop 1b - -# Set up page tables for one-to-map linear to physical map for the -# first 64 MB of RAM. -# See [IA32-v3a] section 3.7.6 "Page-Directory and Page-Table Entries" -# for a description of the bits in %eax. - - movw $0x1000, %ax - movw %ax, %es - movl $0x7, %eax - movl $0x4000, %ecx - subl %edi, %edi -1: movl %eax, %es:(%di) - addw $4, %di - addl $0x1000, %eax - loop 1b - -# Set page directory base register. - - movl $0xf000, %eax - movl %eax, %cr3 - -#### Switch to protected mode. - -# First, disable interrupts. We won't set up the IDT until we get -# into C code, so any interrupt would blow us away. - - cli - -# Protected mode requires a GDT, so point the GDTR to our GDT. -# We need a data32 prefix to ensure that all 32 bits of the GDT -# descriptor are loaded (default is to load only 24 bits). -# The CPU doesn't need an addr32 prefix but ELF doesn't do 16-bit -# relocations. - - data32 addr32 lgdt gdtdesc - LOADER_PHYS_BASE - 0x20000 - -# Then we turn on the following bits in CR0: -# PE (Protect Enable): this turns on protected mode. -# PG (Paging): turns on paging. -# WP (Write Protect): if unset, ring 0 code ignores -# write-protect bits in page tables (!). -# EM (Emulation): forces floating-point instructions to trap. -# We don't support floating point. - - movl %cr0, %eax - orl $CR0_PE | CR0_PG | CR0_WP | CR0_EM, %eax - movl %eax, %cr0 - -# We're now in protected mode in a 16-bit segment. The CPU still has -# the real-mode code segment cached in %cs's segment descriptor. We -# need to reload %cs, and the easiest way is to use a far jump. -# Because we're not running in a 32-bit segment the data32 prefix is -# needed to jump to a 32-bit offset in the target segment. - - data32 ljmp $SEL_KCSEG, $1f - -# We're now in protected mode in a 32-bit segment. -# Let the assembler know. - - .code32 - -# Reload all the other segment registers and the stack pointer to -# point into our new GDT. - -1: mov $SEL_KDSEG, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - addl $LOADER_PHYS_BASE, %esp - movl $0, %ebp # Null-terminate main()'s backtrace - -#### Call main(). - - call main - -# main() shouldn't ever return. If it does, spin. - -1: jmp 1b -.endfunc - -#### GDT - - .align 8 -gdt: - .quad 0x0000000000000000 # Null segment. Not used by CPU. - .quad 0x00cf9a000000ffff # System code, base 0, limit 4 GB. - .quad 0x00cf92000000ffff # System data, base 0, limit 4 GB. - -gdtdesc: - .word gdtdesc - gdt - 1 # Size of the GDT, minus 1 byte. - .long gdt # Address of the GDT. - -#### Physical memory size in 4 kB pages. This is exported to the rest -#### of the kernel. -.globl init_ram_pages -init_ram_pages: - .long 0 - diff --git a/src/threads/switch.S b/src/threads/switch.S deleted file mode 100644 index feca86cd16d02e3d6f31d1dde25cff379c0861a4..0000000000000000000000000000000000000000 --- a/src/threads/switch.S +++ /dev/null @@ -1,65 +0,0 @@ -#include "threads/switch.h" - -#### struct thread *switch_threads (struct thread *cur, struct thread *next); -#### -#### Switches from CUR, which must be the running thread, to NEXT, -#### which must also be running switch_threads(), returning CUR in -#### NEXT's context. -#### -#### This function works by assuming that the thread we're switching -#### into is also running switch_threads(). Thus, all it has to do is -#### preserve a few registers on the stack, then switch stacks and -#### restore the registers. As part of switching stacks we record the -#### current stack pointer in CUR's thread structure. - -.globl switch_threads -.func switch_threads -switch_threads: - # Save caller's register state. - # - # Note that the SVR4 ABI allows us to destroy %eax, %ecx, %edx, - # but requires us to preserve %ebx, %ebp, %esi, %edi. See - # [SysV-ABI-386] pages 3-11 and 3-12 for details. - # - # This stack frame must match the one set up by thread_create() - # in size. - pushl %ebx - pushl %ebp - pushl %esi - pushl %edi - - # Get offsetof (struct thread, stack). -.globl thread_stack_ofs - mov thread_stack_ofs, %edx - - # Save current stack pointer to old thread's stack, if any. - movl SWITCH_CUR(%esp), %eax - movl %esp, (%eax,%edx,1) - - # Restore stack pointer from new thread's stack. - movl SWITCH_NEXT(%esp), %ecx - movl (%ecx,%edx,1), %esp - - # Restore caller's register state. - popl %edi - popl %esi - popl %ebp - popl %ebx - ret -.endfunc - -.globl switch_entry -.func switch_entry -switch_entry: - # Discard switch_threads() arguments. - addl $8, %esp - - # Call thread_schedule_tail(prev). - pushl %eax -.globl thread_schedule_tail - call thread_schedule_tail - addl $4, %esp - - # Start thread proper. - ret -.endfunc diff --git a/src/threads/switch.h b/src/threads/switch.h deleted file mode 100644 index cc156b6d5eddd8e52378be5e17952d6e650ea5c8..0000000000000000000000000000000000000000 --- a/src/threads/switch.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef THREADS_SWITCH_H -#define THREADS_SWITCH_H - -#ifndef __ASSEMBLER__ -/* switch_thread()'s stack frame. */ -struct switch_threads_frame - { - uint32_t edi; /* 0: Saved %edi. */ - uint32_t esi; /* 4: Saved %esi. */ - uint32_t ebp; /* 8: Saved %ebp. */ - uint32_t ebx; /* 12: Saved %ebx. */ - void (*eip) (void); /* 16: Return address. */ - struct thread *cur; /* 20: switch_threads()'s CUR argument. */ - struct thread *next; /* 24: switch_threads()'s NEXT argument. */ - }; - -/* Switches from CUR, which must be the running thread, to NEXT, - which must also be running switch_threads(), returning CUR in - NEXT's context. */ -struct thread *switch_threads (struct thread *cur, struct thread *next); - -/* Stack frame for switch_entry(). */ -struct switch_entry_frame - { - void (*eip) (void); - }; - -void switch_entry (void); - -/* Pops the CUR and NEXT arguments off the stack, for use in - initializing threads. */ -void switch_thunk (void); -#endif - -/* Offsets used by switch.S. */ -#define SWITCH_CUR 20 -#define SWITCH_NEXT 24 - -#endif /* threads/switch.h */ diff --git a/src/threads/synch.c b/src/threads/synch.c deleted file mode 100644 index 317c68ad501301538f47a697df7a8eaf02d4e077..0000000000000000000000000000000000000000 --- a/src/threads/synch.c +++ /dev/null @@ -1,338 +0,0 @@ -/* This file is derived from source code for the Nachos - instructional operating system. The Nachos copyright notice - is reproduced in full below. */ - -/* Copyright (c) 1992-1996 The Regents of the University of California. - All rights reserved. - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose, without fee, and - without written agreement is hereby granted, provided that the - above copyright notice and the following two paragraphs appear - in all copies of this software. - - IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO - ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR - CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE - AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA - HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" - BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO - PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -*/ - -#include "threads/synch.h" -#include <stdio.h> -#include <string.h> -#include "threads/interrupt.h" -#include "threads/thread.h" - -/* Initializes semaphore SEMA to VALUE. A semaphore is a - nonnegative integer along with two atomic operators for - manipulating it: - - - down or "P": wait for the value to become positive, then - decrement it. - - - up or "V": increment the value (and wake up one waiting - thread, if any). */ -void -sema_init (struct semaphore *sema, unsigned value) -{ - ASSERT (sema != NULL); - - sema->value = value; - list_init (&sema->waiters); -} - -/* Down or "P" operation on a semaphore. Waits for SEMA's value - to become positive and then atomically decrements it. - - This function may sleep, so it must not be called within an - interrupt handler. This function may be called with - interrupts disabled, but if it sleeps then the next scheduled - thread will probably turn interrupts back on. */ -void -sema_down (struct semaphore *sema) -{ - enum intr_level old_level; - - ASSERT (sema != NULL); - ASSERT (!intr_context ()); - - old_level = intr_disable (); - while (sema->value == 0) - { - list_push_back (&sema->waiters, &thread_current ()->elem); - thread_block (); - } - sema->value--; - intr_set_level (old_level); -} - -/* Down or "P" operation on a semaphore, but only if the - semaphore is not already 0. Returns true if the semaphore is - decremented, false otherwise. - - This function may be called from an interrupt handler. */ -bool -sema_try_down (struct semaphore *sema) -{ - enum intr_level old_level; - bool success; - - ASSERT (sema != NULL); - - old_level = intr_disable (); - if (sema->value > 0) - { - sema->value--; - success = true; - } - else - success = false; - intr_set_level (old_level); - - return success; -} - -/* Up or "V" operation on a semaphore. Increments SEMA's value - and wakes up one thread of those waiting for SEMA, if any. - - This function may be called from an interrupt handler. */ -void -sema_up (struct semaphore *sema) -{ - enum intr_level old_level; - - ASSERT (sema != NULL); - - old_level = intr_disable (); - if (!list_empty (&sema->waiters)) - thread_unblock (list_entry (list_pop_front (&sema->waiters), - struct thread, elem)); - sema->value++; - intr_set_level (old_level); -} - -static void sema_test_helper (void *sema_); - -/* Self-test for semaphores that makes control "ping-pong" - between a pair of threads. Insert calls to printf() to see - what's going on. */ -void -sema_self_test (void) -{ - struct semaphore sema[2]; - int i; - - printf ("Testing semaphores..."); - sema_init (&sema[0], 0); - sema_init (&sema[1], 0); - thread_create ("sema-test", PRI_DEFAULT, sema_test_helper, &sema); - for (i = 0; i < 10; i++) - { - sema_up (&sema[0]); - sema_down (&sema[1]); - } - printf ("done.\n"); -} - -/* Thread function used by sema_self_test(). */ -static void -sema_test_helper (void *sema_) -{ - struct semaphore *sema = sema_; - int i; - - for (i = 0; i < 10; i++) - { - sema_down (&sema[0]); - sema_up (&sema[1]); - } -} - -/* Initializes LOCK. A lock can be held by at most a single - thread at any given time. Our locks are not "recursive", that - is, it is an error for the thread currently holding a lock to - try to acquire that lock. - - A lock is a specialization of a semaphore with an initial - value of 1. The difference between a lock and such a - semaphore is twofold. First, a semaphore can have a value - greater than 1, but a lock can only be owned by a single - thread at a time. Second, a semaphore does not have an owner, - meaning that one thread can "down" the semaphore and then - another one "up" it, but with a lock the same thread must both - acquire and release it. When these restrictions prove - onerous, it's a good sign that a semaphore should be used, - instead of a lock. */ -void -lock_init (struct lock *lock) -{ - ASSERT (lock != NULL); - - lock->holder = NULL; - sema_init (&lock->semaphore, 1); -} - -/* Acquires LOCK, sleeping until it becomes available if - necessary. The lock must not already be held by the current - thread. - - This function may sleep, so it must not be called within an - interrupt handler. This function may be called with - interrupts disabled, but interrupts will be turned back on if - we need to sleep. */ -void -lock_acquire (struct lock *lock) -{ - ASSERT (lock != NULL); - ASSERT (!intr_context ()); - ASSERT (!lock_held_by_current_thread (lock)); - - sema_down (&lock->semaphore); - lock->holder = thread_current (); -} - -/* Tries to acquires LOCK and returns true if successful or false - on failure. The lock must not already be held by the current - thread. - - This function will not sleep, so it may be called within an - interrupt handler. */ -bool -lock_try_acquire (struct lock *lock) -{ - bool success; - - ASSERT (lock != NULL); - ASSERT (!lock_held_by_current_thread (lock)); - - success = sema_try_down (&lock->semaphore); - if (success) - lock->holder = thread_current (); - return success; -} - -/* Releases LOCK, which must be owned by the current thread. - - An interrupt handler cannot acquire a lock, so it does not - make sense to try to release a lock within an interrupt - handler. */ -void -lock_release (struct lock *lock) -{ - ASSERT (lock != NULL); - ASSERT (lock_held_by_current_thread (lock)); - - lock->holder = NULL; - sema_up (&lock->semaphore); -} - -/* Returns true if the current thread holds LOCK, false - otherwise. (Note that testing whether some other thread holds - a lock would be racy.) */ -bool -lock_held_by_current_thread (const struct lock *lock) -{ - ASSERT (lock != NULL); - - return lock->holder == thread_current (); -} - -/* One semaphore in a list. */ -struct semaphore_elem - { - struct list_elem elem; /* List element. */ - struct semaphore semaphore; /* This semaphore. */ - }; - -/* Initializes condition variable COND. A condition variable - allows one piece of code to signal a condition and cooperating - code to receive the signal and act upon it. */ -void -cond_init (struct condition *cond) -{ - ASSERT (cond != NULL); - - list_init (&cond->waiters); -} - -/* Atomically releases LOCK and waits for COND to be signaled by - some other piece of code. After COND is signaled, LOCK is - reacquired before returning. LOCK must be held before calling - this function. - - The monitor implemented by this function is "Mesa" style, not - "Hoare" style, that is, sending and receiving a signal are not - an atomic operation. Thus, typically the caller must recheck - the condition after the wait completes and, if necessary, wait - again. - - A given condition variable is associated with only a single - lock, but one lock may be associated with any number of - condition variables. That is, there is a one-to-many mapping - from locks to condition variables. - - This function may sleep, so it must not be called within an - interrupt handler. This function may be called with - interrupts disabled, but interrupts will be turned back on if - we need to sleep. */ -void -cond_wait (struct condition *cond, struct lock *lock) -{ - struct semaphore_elem waiter; - - ASSERT (cond != NULL); - ASSERT (lock != NULL); - ASSERT (!intr_context ()); - ASSERT (lock_held_by_current_thread (lock)); - - sema_init (&waiter.semaphore, 0); - list_push_back (&cond->waiters, &waiter.elem); - lock_release (lock); - sema_down (&waiter.semaphore); - lock_acquire (lock); -} - -/* If any threads are waiting on COND (protected by LOCK), then - this function signals one of them to wake up from its wait. - LOCK must be held before calling this function. - - An interrupt handler cannot acquire a lock, so it does not - make sense to try to signal a condition variable within an - interrupt handler. */ -void -cond_signal (struct condition *cond, struct lock *lock UNUSED) -{ - ASSERT (cond != NULL); - ASSERT (lock != NULL); - ASSERT (!intr_context ()); - ASSERT (lock_held_by_current_thread (lock)); - - if (!list_empty (&cond->waiters)) - sema_up (&list_entry (list_pop_front (&cond->waiters), - struct semaphore_elem, elem)->semaphore); -} - -/* Wakes up all threads, if any, waiting on COND (protected by - LOCK). LOCK must be held before calling this function. - - An interrupt handler cannot acquire a lock, so it does not - make sense to try to signal a condition variable within an - interrupt handler. */ -void -cond_broadcast (struct condition *cond, struct lock *lock) -{ - ASSERT (cond != NULL); - ASSERT (lock != NULL); - - while (!list_empty (&cond->waiters)) - cond_signal (cond, lock); -} diff --git a/src/threads/synch.h b/src/threads/synch.h deleted file mode 100644 index a19e88b181dff1208839ff890154aa69b299ce91..0000000000000000000000000000000000000000 --- a/src/threads/synch.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef THREADS_SYNCH_H -#define THREADS_SYNCH_H - -#include <list.h> -#include <stdbool.h> - -/* A counting semaphore. */ -struct semaphore - { - unsigned value; /* Current value. */ - struct list waiters; /* List of waiting threads. */ - }; - -void sema_init (struct semaphore *, unsigned value); -void sema_down (struct semaphore *); -bool sema_try_down (struct semaphore *); -void sema_up (struct semaphore *); -void sema_self_test (void); - -/* Lock. */ -struct lock - { - struct thread *holder; /* Thread holding lock (for debugging). */ - struct semaphore semaphore; /* Binary semaphore controlling access. */ - }; - -void lock_init (struct lock *); -void lock_acquire (struct lock *); -bool lock_try_acquire (struct lock *); -void lock_release (struct lock *); -bool lock_held_by_current_thread (const struct lock *); - -/* Condition variable. */ -struct condition - { - struct list waiters; /* List of waiting threads. */ - }; - -void cond_init (struct condition *); -void cond_wait (struct condition *, struct lock *); -void cond_signal (struct condition *, struct lock *); -void cond_broadcast (struct condition *, struct lock *); - -/* Optimization barrier. - - The compiler will not reorder operations across an - optimization barrier. See "Optimization Barriers" in the - reference guide for more information.*/ -#define barrier() asm volatile ("" : : : "memory") - -#endif /* threads/synch.h */ diff --git a/src/threads/thread.c b/src/threads/thread.c deleted file mode 100644 index 052302f8d417bbcce955ae4216fc297d956316a6..0000000000000000000000000000000000000000 --- a/src/threads/thread.c +++ /dev/null @@ -1,595 +0,0 @@ -#include "threads/thread.h" -#include <debug.h> -#include <stddef.h> -#include <random.h> -#include <stdio.h> -#include <string.h> -#include "threads/flags.h" -#include "threads/interrupt.h" -#include "threads/intr-stubs.h" -#include "threads/palloc.h" -#include "threads/switch.h" -#include "threads/synch.h" -#include "threads/vaddr.h" - -#ifdef USERPROG -#include "userprog/process.h" -#endif - -/* Random value for struct thread's `magic' member. - Used to detect stack overflow. See the big comment at the top - of thread.h for details. */ -#define THREAD_MAGIC 0xcd6abf4b - -/* List of processes in THREAD_READY state, that is, processes - that are ready to run but not actually running. */ -static struct list ready_list; - -/* List of all processes. Processes are added to this list - when they are first scheduled and removed when they exit. */ -static struct list all_list; - -/* Idle thread. */ -static struct thread *idle_thread; - -/* Initial thread, the thread running init.c:main(). */ -static struct thread *initial_thread; - -/* Lock used by allocate_tid(). */ -static struct lock tid_lock; - -/* Stack frame for kernel_thread(). */ -struct kernel_thread_frame - { - void *eip; /* Return address. */ - thread_func *function; /* Function to call. */ - void *aux; /* Auxiliary data for function. */ - }; - -/* Statistics. */ -static long long idle_ticks; /* # of timer ticks spent idle. */ -static long long kernel_ticks; /* # of timer ticks in kernel threads. */ -static long long user_ticks; /* # of timer ticks in user programs. */ - -/* Scheduling. */ -#define TIME_SLICE 4 /* # of timer ticks to give each thread. */ -static unsigned thread_ticks; /* # of timer ticks since last yield. */ - -/* If false (default), use round-robin scheduler. - If true, use multi-level feedback queue scheduler. - Controlled by kernel command-line option "-o mlfqs". */ -bool thread_mlfqs; - -static void kernel_thread (thread_func *, void *aux); - -static void idle (void *aux UNUSED); -static struct thread *running_thread (void); -static struct thread *next_thread_to_run (void); - -static void init_thread (struct thread *, const char *name, int priority); - -static bool is_thread (struct thread *) UNUSED; -static void *alloc_frame (struct thread *, size_t size); -static void schedule (void); -void thread_schedule_tail (struct thread *prev); -static tid_t allocate_tid (void); - -/* Initializes the threading system by transforming the code - that's currently running into a thread. This can't work in - general and it is possible in this case only because loader.S - was careful to put the bottom of the stack at a page boundary. - - Also initializes the run queue and the tid lock. - - After calling this function, be sure to initialize the page - allocator before trying to create any threads with - thread_create(). - - It is not safe to call thread_current() until this function - finishes. */ -void -thread_init (void) -{ - ASSERT (intr_get_level () == INTR_OFF); - - lock_init (&tid_lock); - list_init (&ready_list); - list_init (&all_list); - - /* Set up a thread structure for the running thread. */ - initial_thread = running_thread (); - - init_thread (initial_thread, "main", PRI_DEFAULT); - - initial_thread->status = THREAD_RUNNING; - initial_thread->tid = allocate_tid (); -} - -/* Starts preemptive thread scheduling by enabling interrupts. - Also creates the idle thread. */ -void -thread_start (void) -{ - /* Create the idle thread. */ - struct semaphore idle_started; - - //init_info (initial_thread, initial_thread->tid); - - sema_init (&idle_started, 0); - thread_create ("idle", PRI_MIN, idle, &idle_started); - - /* Start preemptive thread scheduling. */ - intr_enable (); - - /* Wait for the idle thread to initialize idle_thread. */ - sema_down (&idle_started); -} - -/* Called by the timer interrupt handler at each timer tick. - Thus, this function runs in an external interrupt context. */ -void -thread_tick (void) -{ - struct thread *t = thread_current (); - - /* Update statistics. */ - if (t == idle_thread) - idle_ticks++; -#ifdef USERPROG - else if (t->pagedir != NULL) - user_ticks++; -#endif - else - kernel_ticks++; - - /* Enforce preemption. */ - if (++thread_ticks >= TIME_SLICE) - intr_yield_on_return (); -} - -/* Prints thread statistics. */ -void -thread_print_stats (void) -{ - printf ("Thread: %lld idle ticks, %lld kernel ticks, %lld user ticks\n", - idle_ticks, kernel_ticks, user_ticks); -} - -/* Creates a new kernel thread named NAME with the given initial - PRIORITY, which executes FUNCTION passing AUX as the argument, - and adds it to the ready queue. Returns the thread identifier - for the new thread, or TID_ERROR if creation fails. - - If thread_start() has been called, then the new thread may be - scheduled before thread_create() returns. It could even exit - before thread_create() returns. Contrariwise, the original - thread may run for any amount of time before the new thread is - scheduled. Use a semaphore or some other form of - synchronization if you need to ensure ordering. - - The code provided sets the new thread's `priority' member to - PRIORITY, but no actual priority scheduling is implemented. - Priority scheduling is the goal of Problem 1-3. */ -tid_t -thread_create (const char *name, int priority, - thread_func *function, void *aux) -{ - struct thread *t; - struct kernel_thread_frame *kf; - struct switch_entry_frame *ef; - struct switch_threads_frame *sf; - tid_t tid; - - ASSERT (function != NULL); - - /* Allocate thread. */ - t = palloc_get_page (PAL_ZERO); - if (t == NULL) - return TID_ERROR; - - /* Initialize thread. */ - init_thread (t, name, priority); - tid = t->tid = allocate_tid (); - - /* Stack frame for kernel_thread(). */ - kf = alloc_frame (t, sizeof *kf); - kf->eip = NULL; - kf->function = function; - kf->aux = aux; - - /* Stack frame for switch_entry(). */ - ef = alloc_frame (t, sizeof *ef); - ef->eip = (void (*) (void)) kernel_thread; - - /* Stack frame for switch_threads(). */ - sf = alloc_frame (t, sizeof *sf); - sf->eip = switch_entry; - sf->ebp = 0; - - /* Add to run queue. */ - thread_unblock (t); - - return tid; -} - -/* Puts the current thread to sleep. It will not be scheduled - again until awoken by thread_unblock(). - - This function must be called with interrupts turned off. It - is usually a better idea to use one of the synchronization - primitives in synch.h. */ -void -thread_block (void) -{ - ASSERT (!intr_context ()); - ASSERT (intr_get_level () == INTR_OFF); - - thread_current ()->status = THREAD_BLOCKED; - schedule (); -} - -/* Transitions a blocked thread T to the ready-to-run state. - This is an error if T is not blocked. (Use thread_yield() to - make the running thread ready.) - - This function does not preempt the running thread. This can - be important: if the caller had disabled interrupts itself, - it may expect that it can atomically unblock a thread and - update other data. */ -void -thread_unblock (struct thread *t) -{ - enum intr_level old_level; - - ASSERT (is_thread (t)); - - old_level = intr_disable (); - ASSERT (t->status == THREAD_BLOCKED); - list_push_back (&ready_list, &t->elem); - t->status = THREAD_READY; - intr_set_level (old_level); -} - -/* Returns the name of the running thread. */ -const char * -thread_name (void) -{ - return thread_current ()->name; -} - -/* Returns the running thread. - This is running_thread() plus a couple of sanity checks. - See the big comment at the top of thread.h for details. */ -struct thread * -thread_current (void) -{ - struct thread *t = running_thread (); - - /* Make sure T is really a thread. - If either of these assertions fire, then your thread may - have overflowed its stack. Each thread has less than 4 kB - of stack, so a few big automatic arrays or moderate - recursion can cause stack overflow. */ - ASSERT (is_thread (t)); - ASSERT (t->status == THREAD_RUNNING); - - return t; -} - -/* Returns the running thread's tid. */ -tid_t -thread_tid (void) -{ - return thread_current ()->tid; -} - -/* Deschedules the current thread and destroys it. Never - returns to the caller. */ -void -thread_exit (void) -{ - ASSERT (!intr_context ()); - -#ifdef USERPROG - process_exit (); -#endif - - /* Remove thread from all threads list, set our status to dying, - and schedule another process. That process will destroy us - when it calls thread_schedule_tail(). */ - intr_disable (); - list_remove (&thread_current()->allelem); - thread_current ()->status = THREAD_DYING; - schedule (); - NOT_REACHED (); -} - -/* Yields the CPU. The current thread is not put to sleep and - may be scheduled again immediately at the scheduler's whim. */ -void -thread_yield (void) -{ - struct thread *cur = thread_current (); - enum intr_level old_level; - - ASSERT (!intr_context ()); - - old_level = intr_disable (); - if (cur != idle_thread) - list_push_back (&ready_list, &cur->elem); - cur->status = THREAD_READY; - schedule (); - intr_set_level (old_level); -} - -/* Invoke function 'func' on all threads, passing along 'aux'. - This function must be called with interrupts off. */ -void -thread_foreach (thread_action_func *func, void *aux) -{ - struct list_elem *e; - - ASSERT (intr_get_level () == INTR_OFF); - - for (e = list_begin (&all_list); e != list_end (&all_list); - e = list_next (e)) - { - struct thread *t = list_entry (e, struct thread, allelem); - func (t, aux); - } -} - -/* Sets the current thread's priority to NEW_PRIORITY. */ -void -thread_set_priority (int new_priority) -{ - thread_current ()->priority = new_priority; -} - -/* Returns the current thread's priority. */ -int -thread_get_priority (void) -{ - return thread_current ()->priority; -} - -/* Sets the current thread's nice value to NICE. */ -void -thread_set_nice (int nice UNUSED) -{ - /* Not yet implemented. */ -} - -/* Returns the current thread's nice value. */ -int -thread_get_nice (void) -{ - /* Not yet implemented. */ - return 0; -} - -/* Returns 100 times the system load average. */ -int -thread_get_load_avg (void) -{ - /* Not yet implemented. */ - return 0; -} - -/* Returns 100 times the current thread's recent_cpu value. */ -int -thread_get_recent_cpu (void) -{ - /* Not yet implemented. */ - return 0; -} - -/* Idle thread. Executes when no other thread is ready to run. - - The idle thread is initially put on the ready list by - thread_start(). It will be scheduled once initially, at which - point it initializes idle_thread, "up"s the semaphore passed - to it to enable thread_start() to continue, and immediately - blocks. After that, the idle thread never appears in the - ready list. It is returned by next_thread_to_run() as a - special case when the ready list is empty. */ -static void -idle (void *idle_started_ UNUSED) -{ - struct semaphore *idle_started = idle_started_; - idle_thread = thread_current (); - sema_up (idle_started); - - for (;;) - { - /* Let someone else run. */ - intr_disable (); - thread_block (); - - /* Re-enable interrupts and wait for the next one. - - The `sti' instruction disables interrupts until the - completion of the next instruction, so these two - instructions are executed atomically. This atomicity is - important; otherwise, an interrupt could be handled - between re-enabling interrupts and waiting for the next - one to occur, wasting as much as one clock tick worth of - time. - - See [IA32-v2a] "HLT", [IA32-v2b] "STI", and [IA32-v3a] - 7.11.1 "HLT Instruction". */ - asm volatile ("sti; hlt" : : : "memory"); - } -} - -/* Function used as the basis for a kernel thread. */ -static void -kernel_thread (thread_func *function, void *aux) -{ - ASSERT (function != NULL); - - intr_enable (); /* The scheduler runs with interrupts off. */ - function (aux); /* Execute the thread function. */ - thread_exit (); /* If function() returns, kill the thread. */ -} - -/* Returns the running thread. */ -struct thread * -running_thread (void) -{ - uint32_t *esp; - - /* Copy the CPU's stack pointer into `esp', and then round that - down to the start of a page. Because `struct thread' is - always at the beginning of a page and the stack pointer is - somewhere in the middle, this locates the curent thread. */ - asm ("mov %%esp, %0" : "=g" (esp)); - return pg_round_down (esp); -} - -/* Returns true if T appears to point to a valid thread. */ -static bool -is_thread (struct thread *t) -{ - return t != NULL && t->magic == THREAD_MAGIC; -} - -/* Does basic initialization of T as a blocked thread named - NAME. */ -static void -init_thread (struct thread *t, const char *name, int priority) -{ - enum intr_level old_level; - - ASSERT (t != NULL); - ASSERT (PRI_MIN <= priority && priority <= PRI_MAX); - ASSERT (name != NULL); - - memset (t, 0, sizeof *t); - t->status = THREAD_BLOCKED; - strlcpy (t->name, name, sizeof t->name); - t->stack = (uint8_t *) t + PGSIZE; - t->priority = priority; - t->magic = THREAD_MAGIC; - - //t->is_kernel = is_kernel; - - old_level = intr_disable (); - list_push_back (&all_list, &t->allelem); - intr_set_level (old_level); -} - - -/* Allocates a SIZE-byte frame at the top of thread T's stack and - returns a pointer to the frame's base. */ -static void * -alloc_frame (struct thread *t, size_t size) -{ - /* Stack data is always allocated in word-size units. */ - ASSERT (is_thread (t)); - ASSERT (size % sizeof (uint32_t) == 0); - - t->stack -= size; - return t->stack; -} - -/* Chooses and returns the next thread to be scheduled. Should - return a thread from the run queue, unless the run queue is - empty. (If the running thread can continue running, then it - will be in the run queue.) If the run queue is empty, return - idle_thread. */ -static struct thread * -next_thread_to_run (void) -{ - if (list_empty (&ready_list)) - return idle_thread; - else - return list_entry (list_pop_front (&ready_list), struct thread, elem); -} - -/* Completes a thread switch by activating the new thread's page - tables, and, if the previous thread is dying, destroying it. - - At this function's invocation, we just switched from thread - PREV, the new thread is already running, and interrupts are - still disabled. This function is normally invoked by - thread_schedule() as its final action before returning, but - the first time a thread is scheduled it is called by - switch_entry() (see switch.S). - - It's not safe to call printf() until the thread switch is - complete. In practice that means that printf()s should be - added at the end of the function. - - After this function and its caller returns, the thread switch - is complete. */ -void -thread_schedule_tail (struct thread *prev) -{ - struct thread *cur = running_thread (); - - ASSERT (intr_get_level () == INTR_OFF); - - /* Mark us as running. */ - cur->status = THREAD_RUNNING; - - /* Start new time slice. */ - thread_ticks = 0; - -#ifdef USERPROG - /* Activate the new address space. */ - process_activate (); -#endif - - /* If the thread we switched from is dying, destroy its struct - thread. This must happen late so that thread_exit() doesn't - pull out the rug under itself. (We don't free - initial_thread because its memory was not obtained via - palloc().) */ - if (prev != NULL && prev->status == THREAD_DYING && prev != initial_thread) - { - ASSERT (prev != cur); - palloc_free_page (prev); - } -} - -/* Schedules a new process. At entry, interrupts must be off and - the running process's state must have been changed from - running to some other state. This function finds another - thread to run and switches to it. - - It's not safe to call printf() until thread_schedule_tail() - has completed. */ -static void -schedule (void) -{ - struct thread *cur = running_thread (); - struct thread *next = next_thread_to_run (); - struct thread *prev = NULL; - - ASSERT (intr_get_level () == INTR_OFF); - ASSERT (cur->status != THREAD_RUNNING); - ASSERT (is_thread (next)); - - if (cur != next) - prev = switch_threads (cur, next); - thread_schedule_tail (prev); -} - -/* Returns a tid to use for a new thread. */ -static tid_t -allocate_tid (void) -{ - static tid_t next_tid = 1; - tid_t tid; - - lock_acquire (&tid_lock); - tid = next_tid++; - lock_release (&tid_lock); - - return tid; -} - -/* Offset of `stack' member within `struct thread'. - Used by switch.S, which can't figure it out on its own. */ -uint32_t thread_stack_ofs = offsetof (struct thread, stack); diff --git a/src/threads/thread.h b/src/threads/thread.h deleted file mode 100644 index 093bcddeb82e3c52182ff182c8c832d90f695908..0000000000000000000000000000000000000000 --- a/src/threads/thread.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef THREADS_THREAD_H -#define THREADS_THREAD_H - -#include <debug.h> -#include <list.h> -#include <stdint.h> - -/* States in a thread's life cycle. */ -enum thread_status - { - THREAD_RUNNING, /* Running thread. */ - THREAD_READY, /* Not running but ready to run. */ - THREAD_BLOCKED, /* Waiting for an event to trigger. */ - THREAD_DYING /* About to be destroyed. */ - }; - -/* Thread identifier type. - You can redefine this to whatever type you like. */ -typedef int tid_t; -#define TID_ERROR ((tid_t) -1) /* Error value for tid_t. */ - -/* Thread priorities. */ -#define PRI_MIN 0 /* Lowest priority. */ -#define PRI_DEFAULT 31 /* Default priority. */ -#define PRI_MAX 63 /* Highest priority. */ - -/* A kernel thread or user process. - - Each thread structure is stored in its own 4 kB page. The - thread structure itself sits at the very bottom of the page - (at offset 0). The rest of the page is reserved for the - thread's kernel stack, which grows downward from the top of - the page (at offset 4 kB). Here's an illustration: - - 4 kB +---------------------------------+ - | kernel stack | - | | | - | | | - | V | - | grows downward | - | | - | | - | | - | | - | | - | | - | | - | | - +---------------------------------+ - | magic | - | : | - | : | - | name | - | status | - 0 kB +---------------------------------+ - - The upshot of this is twofold: - - 1. First, `struct thread' must not be allowed to grow too - big. If it does, then there will not be enough room for - the kernel stack. Our base `struct thread' is only a - few bytes in size. It probably should stay well under 1 - kB. - - 2. Second, kernel stacks must not be allowed to grow too - large. If a stack overflows, it will corrupt the thread - state. Thus, kernel functions should not allocate large - structures or arrays as non-static local variables. Use - dynamic allocation with malloc() or palloc_get_page() - instead. - - The first symptom of either of these problems will probably be - an assertion failure in thread_current(), which checks that - the `magic' member of the running thread's `struct thread' is - set to THREAD_MAGIC. Stack overflow will normally change this - value, triggering the assertion. */ -/* The `elem' member has a dual purpose. It can be an element in - the run queue (thread.c), or it can be an element in a - semaphore wait list (synch.c). It can be used these two ways - only because they are mutually exclusive: only a thread in the - ready state is on the run queue, whereas only a thread in the - blocked state is on a semaphore wait list. */ -struct thread - { - /* Owned by thread.c. */ - tid_t tid; /* Thread identifier. */ - enum thread_status status; /* Thread state. */ - char name[16]; /* Name (for debugging purposes). */ - uint8_t *stack; /* Saved stack pointer. */ - int priority; /* Priority. */ - struct list_elem allelem; /* List element for all threads list. */ - - /* Shared between thread.c and synch.c. */ - struct list_elem elem; /* List element. */ - -#ifdef USERPROG - /* Owned by userprog/process.c. */ - uint32_t *pagedir; /* Page directory. */ -#endif - - /* Owned by thread.c. */ - unsigned magic; /* Detects stack overflow. */ - }; - -/* If false (default), use round-robin scheduler. - If true, use multi-level feedback queue scheduler. - Controlled by kernel command-line option "-o mlfqs". */ -extern bool thread_mlfqs; - -void thread_init (void); -void thread_start (void); - -void thread_tick (void); -void thread_print_stats (void); - -typedef void thread_func (void *aux); -tid_t thread_create (const char *name, int priority, thread_func *, void *); - -void thread_block (void); -void thread_unblock (struct thread *); - -struct thread *thread_current (void); -tid_t thread_tid (void); -const char *thread_name (void); - -void thread_exit (void) NO_RETURN; -void thread_yield (void); - -/* Performs some operation on thread t, given auxiliary data AUX. */ -typedef void thread_action_func (struct thread *t, void *aux); -void thread_foreach (thread_action_func *, void *); - -int thread_get_priority (void); -void thread_set_priority (int); - -int thread_get_nice (void); -void thread_set_nice (int); -int thread_get_recent_cpu (void); -int thread_get_load_avg (void); - -#endif /* threads/thread.h */ diff --git a/src/threads/vaddr.h b/src/threads/vaddr.h deleted file mode 100644 index 184c8241c832a6705031b3a1f785eece8e380455..0000000000000000000000000000000000000000 --- a/src/threads/vaddr.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef THREADS_VADDR_H -#define THREADS_VADDR_H - -#include <debug.h> -#include <stdint.h> -#include <stdbool.h> - -#include "threads/loader.h" - -/* Functions and macros for working with virtual addresses. - - See pte.h for functions and macros specifically for x86 - hardware page tables. */ - -#define BITMASK(SHIFT, CNT) (((1ul << (CNT)) - 1) << (SHIFT)) - -/* Page offset (bits 0:12). */ -#define PGSHIFT 0 /* Index of first offset bit. */ -#define PGBITS 12 /* Number of offset bits. */ -#define PGSIZE (1 << PGBITS) /* Bytes in a page. */ -#define PGMASK BITMASK(PGSHIFT, PGBITS) /* Page offset bits (0:12). */ - -/* Offset within a page. */ -static inline unsigned pg_ofs (const void *va) { - return (uintptr_t) va & PGMASK; -} - -/* Virtual page number. */ -static inline uintptr_t pg_no (const void *va) { - return (uintptr_t) va >> PGBITS; -} - -/* Round up to nearest page boundary. */ -static inline void *pg_round_up (const void *va) { - return (void *) (((uintptr_t) va + PGSIZE - 1) & ~PGMASK); -} - -/* Round down to nearest page boundary. */ -static inline void *pg_round_down (const void *va) { - return (void *) ((uintptr_t) va & ~PGMASK); -} - -/* Base address of the 1:1 physical-to-virtual mapping. Physical - memory is mapped starting at this virtual address. Thus, - physical address 0 is accessible at PHYS_BASE, physical - address address 0x1234 at (uint8_t *) PHYS_BASE + 0x1234, and - so on. - - This address also marks the end of user programs' address - space. Up to this point in memory, user programs are allowed - to map whatever they like. At this point and above, the - virtual address space belongs to the kernel. */ -#define PHYS_BASE ((void *) LOADER_PHYS_BASE) - -/* Returns true if VADDR is a user virtual address. */ -static inline bool -is_user_vaddr (const void *vaddr) -{ - return vaddr < PHYS_BASE; -} - -/* Returns true if VADDR is a kernel virtual address. */ -static inline bool -is_kernel_vaddr (const void *vaddr) -{ - return vaddr >= PHYS_BASE; -} - -/* Returns kernel virtual address at which physical address PADDR - is mapped. */ -static inline void * -ptov (uintptr_t paddr) -{ - ASSERT ((void *) paddr < PHYS_BASE); - - return (void *) (paddr + PHYS_BASE); -} - -/* Returns physical address at which kernel virtual address VADDR - is mapped. */ -static inline uintptr_t -vtop (const void *vaddr) -{ - ASSERT (is_kernel_vaddr (vaddr)); - - return (uintptr_t) vaddr - (uintptr_t) PHYS_BASE; -} - -#endif /* threads/vaddr.h */ diff --git a/src/userprog/.gitignore b/src/userprog/.gitignore deleted file mode 100644 index 6d5357c015ab6f0b7ee7074381afdd3da82e06eb..0000000000000000000000000000000000000000 --- a/src/userprog/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -build -bochsrc.txt -bochsout.txt diff --git a/src/userprog/Make.vars b/src/userprog/Make.vars deleted file mode 100644 index e4dbb087c332564db792a930c06dfbac6d2d4eb4..0000000000000000000000000000000000000000 --- a/src/userprog/Make.vars +++ /dev/null @@ -1,7 +0,0 @@ -# -*- makefile -*- - -kernel.bin: DEFINES = -DUSERPROG -DFILESYS -KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys -TEST_SUBDIRS = tests/userprog tests/userprog/no-vm tests/filesys/base -GRADING_FILE = $(SRCDIR)/tests/userprog/Grading -SIMULATOR = --qemu diff --git a/src/userprog/Makefile b/src/userprog/Makefile deleted file mode 100644 index 34c10aa4f508714da040e81389fa51e56ba2d97a..0000000000000000000000000000000000000000 --- a/src/userprog/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.kernel diff --git a/src/userprog/exception.c b/src/userprog/exception.c deleted file mode 100644 index 19aca125e331783bad87330e8e7213f72072e580..0000000000000000000000000000000000000000 --- a/src/userprog/exception.c +++ /dev/null @@ -1,161 +0,0 @@ -#include "userprog/exception.h" -#include <inttypes.h> -#include <stdio.h> -#include "userprog/gdt.h" -#include "threads/interrupt.h" -#include "threads/thread.h" - -/* Number of page faults processed. */ -static long long page_fault_cnt; - -static void kill (struct intr_frame *); -static void page_fault (struct intr_frame *); - -/* Registers handlers for interrupts that can be caused by user - programs. - - In a real Unix-like OS, most of these interrupts would be - passed along to the user process in the form of signals, as - described in [SV-386] 3-24 and 3-25, but we don't implement - signals. Instead, we'll make them simply kill the user - process. - - Page faults are an exception. Here they are treated the same - way as other exceptions, but this will need to change to - implement virtual memory. - - Refer to [IA32-v3a] section 5.15 "Exception and Interrupt - Reference" for a description of each of these exceptions. */ -void -exception_init (void) -{ - /* These exceptions can be raised explicitly by a user program, - e.g. via the INT, INT3, INTO, and BOUND instructions. Thus, - we set DPL==3, meaning that user programs are allowed to - invoke them via these instructions. */ - intr_register_int (3, 3, INTR_ON, kill, "#BP Breakpoint Exception"); - intr_register_int (4, 3, INTR_ON, kill, "#OF Overflow Exception"); - intr_register_int (5, 3, INTR_ON, kill, - "#BR BOUND Range Exceeded Exception"); - - /* These exceptions have DPL==0, preventing user processes from - invoking them via the INT instruction. They can still be - caused indirectly, e.g. #DE can be caused by dividing by - 0. */ - intr_register_int (0, 0, INTR_ON, kill, "#DE Divide Error"); - intr_register_int (1, 0, INTR_ON, kill, "#DB Debug Exception"); - intr_register_int (6, 0, INTR_ON, kill, "#UD Invalid Opcode Exception"); - intr_register_int (7, 0, INTR_ON, kill, - "#NM Device Not Available Exception"); - intr_register_int (11, 0, INTR_ON, kill, "#NP Segment Not Present"); - intr_register_int (12, 0, INTR_ON, kill, "#SS Stack Fault Exception"); - intr_register_int (13, 0, INTR_ON, kill, "#GP General Protection Exception"); - intr_register_int (16, 0, INTR_ON, kill, "#MF x87 FPU Floating-Point Error"); - intr_register_int (19, 0, INTR_ON, kill, - "#XF SIMD Floating-Point Exception"); - - /* Most exceptions can be handled with interrupts turned on. - We need to disable interrupts for page faults because the - fault address is stored in CR2 and needs to be preserved. */ - intr_register_int (14, 0, INTR_OFF, page_fault, "#PF Page-Fault Exception"); -} - -/* Prints exception statistics. */ -void -exception_print_stats (void) -{ - printf ("Exception: %lld page faults\n", page_fault_cnt); -} - -/* Handler for an exception (probably) caused by a user process. */ -static void -kill (struct intr_frame *f) -{ - /* This interrupt is one (probably) caused by a user process. - For example, the process might have tried to access unmapped - virtual memory (a page fault). For now, we simply kill the - user process. Later, we'll want to handle page faults in - the kernel. Real Unix-like operating systems pass most - exceptions back to the process via signals, but we don't - implement them. */ - - /* The interrupt frame's code segment value tells us where the - exception originated. */ - switch (f->cs) - { - case SEL_UCSEG: - /* User's code segment, so it's a user exception, as we - expected. Kill the user process. */ - printf ("%s: dying due to interrupt %#04x (%s).\n", - thread_name (), f->vec_no, intr_name (f->vec_no)); - intr_dump_frame (f); - thread_exit (); - - case SEL_KCSEG: - /* Kernel's code segment, which indicates a kernel bug. - Kernel code shouldn't throw exceptions. (Page faults - may cause kernel exceptions--but they shouldn't arrive - here.) Panic the kernel to make the point. */ - intr_dump_frame (f); - PANIC ("Kernel bug - unexpected interrupt in kernel"); - - default: - /* Some other code segment? Shouldn't happen. Panic the - kernel. */ - printf ("Interrupt %#04x (%s) in unknown segment %04x\n", - f->vec_no, intr_name (f->vec_no), f->cs); - thread_exit (); - } -} - -/* Page fault handler. This is a skeleton that must be filled in - to implement virtual memory. Some solutions to project 2 may - also require modifying this code. - - At entry, the address that faulted is in CR2 (Control Register - 2) and information about the fault, formatted as described in - the PF_* macros in exception.h, is in F's error_code member. The - example code here shows how to parse that information. You - can find more information about both of these in the - description of "Interrupt 14--Page Fault Exception (#PF)" in - [IA32-v3a] section 5.15 "Exception and Interrupt Reference". */ -static void -page_fault (struct intr_frame *f) -{ - bool not_present; /* True: not-present page, false: writing r/o page. */ - bool write; /* True: access was write, false: access was read. */ - bool user; /* True: access by user, false: access by kernel. */ - void *fault_addr; /* Fault address. */ - - /* Obtain faulting address, the virtual address that was - accessed to cause the fault. It may point to code or to - data. It is not necessarily the address of the instruction - that caused the fault (that's f->eip). - See [IA32-v2a] "MOV--Move to/from Control Registers" and - [IA32-v3a] 5.15 "Interrupt 14--Page Fault Exception - (#PF)". */ - asm ("movl %%cr2, %0" : "=r" (fault_addr)); - - /* Turn interrupts back on (they were only off so that we could - be assured of reading CR2 before it changed). */ - intr_enable (); - - /* Count page faults. */ - page_fault_cnt++; - - /* Determine cause. */ - not_present = (f->error_code & PF_P) == 0; - write = (f->error_code & PF_W) != 0; - user = (f->error_code & PF_U) != 0; - - /* To implement virtual memory, delete the rest of the function - body, and replace it with code that brings in the page to - which fault_addr refers. */ - printf ("Page fault at %p: %s error %s page in %s context.\n", - fault_addr, - not_present ? "not present" : "rights violation", - write ? "writing" : "reading", - user ? "user" : "kernel"); - kill (f); -} - diff --git a/src/userprog/exception.h b/src/userprog/exception.h deleted file mode 100644 index f83e615bb1e010c8723510a99abb01d714c0f275..0000000000000000000000000000000000000000 --- a/src/userprog/exception.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef USERPROG_EXCEPTION_H -#define USERPROG_EXCEPTION_H - -/* Page fault error code bits that describe the cause of the exception. */ -#define PF_P 0x1 /* 0: not-present page. 1: access rights violation. */ -#define PF_W 0x2 /* 0: read, 1: write. */ -#define PF_U 0x4 /* 0: kernel, 1: user process. */ - -void exception_init (void); -void exception_print_stats (void); - -#endif /* userprog/exception.h */ diff --git a/src/userprog/gdt.c b/src/userprog/gdt.c deleted file mode 100644 index e866037e2a24dc412da2f2068d4fe69476260756..0000000000000000000000000000000000000000 --- a/src/userprog/gdt.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "userprog/gdt.h" -#include <debug.h> -#include "userprog/tss.h" -#include "threads/palloc.h" -#include "threads/vaddr.h" - -/* The Global Descriptor Table (GDT). - - The GDT, an x86-specific structure, defines segments that can - potentially be used by all processes in a system, subject to - their permissions. There is also a per-process Local - Descriptor Table (LDT) but that is not used by modern - operating systems. - - Each entry in the GDT, which is known by its byte offset in - the table, identifies a segment. For our purposes only three - types of segments are of interest: code, data, and TSS or - Task-State Segment descriptors. The former two types are - exactly what they sound like. The TSS is used primarily for - stack switching on interrupts. - - For more information on the GDT as used here, refer to - [IA32-v3a] 3.2 "Using Segments" through 3.5 "System Descriptor - Types". */ -static uint64_t gdt[SEL_CNT]; - -/* GDT helpers. */ -static uint64_t make_code_desc (int dpl); -static uint64_t make_data_desc (int dpl); -static uint64_t make_tss_desc (void *laddr); -static uint64_t make_gdtr_operand (uint16_t limit, void *base); - -/* Sets up a proper GDT. The bootstrap loader's GDT didn't - include user-mode selectors or a TSS, but we need both now. */ -void -gdt_init (void) -{ - uint64_t gdtr_operand; - - /* Initialize GDT. */ - gdt[SEL_NULL / sizeof *gdt] = 0; - gdt[SEL_KCSEG / sizeof *gdt] = make_code_desc (0); - gdt[SEL_KDSEG / sizeof *gdt] = make_data_desc (0); - gdt[SEL_UCSEG / sizeof *gdt] = make_code_desc (3); - gdt[SEL_UDSEG / sizeof *gdt] = make_data_desc (3); - gdt[SEL_TSS / sizeof *gdt] = make_tss_desc (tss_get ()); - - /* Load GDTR, TR. See [IA32-v3a] 2.4.1 "Global Descriptor - Table Register (GDTR)", 2.4.4 "Task Register (TR)", and - 6.2.4 "Task Register". */ - gdtr_operand = make_gdtr_operand (sizeof gdt - 1, gdt); - asm volatile ("lgdt %0" : : "m" (gdtr_operand)); - asm volatile ("ltr %w0" : : "q" (SEL_TSS)); -} - -/* System segment or code/data segment? */ -enum seg_class - { - CLS_SYSTEM = 0, /* System segment. */ - CLS_CODE_DATA = 1 /* Code or data segment. */ - }; - -/* Limit has byte or 4 kB page granularity? */ -enum seg_granularity - { - GRAN_BYTE = 0, /* Limit has 1-byte granularity. */ - GRAN_PAGE = 1 /* Limit has 4 kB granularity. */ - }; - -/* Returns a segment descriptor with the given 32-bit BASE and - 20-bit LIMIT (whose interpretation depends on GRANULARITY). - The descriptor represents a system or code/data segment - according to CLASS, and TYPE is its type (whose interpretation - depends on the class). - - The segment has descriptor privilege level DPL, meaning that - it can be used in rings numbered DPL or lower. In practice, - DPL==3 means that user processes can use the segment and - DPL==0 means that only the kernel can use the segment. See - [IA32-v3a] 4.5 "Privilege Levels" for further discussion. */ -static uint64_t -make_seg_desc (uint32_t base, - uint32_t limit, - enum seg_class class, - int type, - int dpl, - enum seg_granularity granularity) -{ - uint32_t e0, e1; - - ASSERT (limit <= 0xfffff); - ASSERT (class == CLS_SYSTEM || class == CLS_CODE_DATA); - ASSERT (type >= 0 && type <= 15); - ASSERT (dpl >= 0 && dpl <= 3); - ASSERT (granularity == GRAN_BYTE || granularity == GRAN_PAGE); - - e0 = ((limit & 0xffff) /* Limit 15:0. */ - | (base << 16)); /* Base 15:0. */ - - e1 = (((base >> 16) & 0xff) /* Base 23:16. */ - | (type << 8) /* Segment type. */ - | (class << 12) /* 0=system, 1=code/data. */ - | (dpl << 13) /* Descriptor privilege. */ - | (1 << 15) /* Present. */ - | (limit & 0xf0000) /* Limit 16:19. */ - | (1 << 22) /* 32-bit segment. */ - | (granularity << 23) /* Byte/page granularity. */ - | (base & 0xff000000)); /* Base 31:24. */ - - return e0 | ((uint64_t) e1 << 32); -} - -/* Returns a descriptor for a readable code segment with base at - 0, a limit of 4 GB, and the given DPL. */ -static uint64_t -make_code_desc (int dpl) -{ - return make_seg_desc (0, 0xfffff, CLS_CODE_DATA, 10, dpl, GRAN_PAGE); -} - -/* Returns a descriptor for a writable data segment with base at - 0, a limit of 4 GB, and the given DPL. */ -static uint64_t -make_data_desc (int dpl) -{ - return make_seg_desc (0, 0xfffff, CLS_CODE_DATA, 2, dpl, GRAN_PAGE); -} - -/* Returns a descriptor for an "available" 32-bit Task-State - Segment with its base at the given linear address, a limit of - 0x67 bytes (the size of a 32-bit TSS), and a DPL of 0. - See [IA32-v3a] 6.2.2 "TSS Descriptor". */ -static uint64_t -make_tss_desc (void *laddr) -{ - return make_seg_desc ((uint32_t) laddr, 0x67, CLS_SYSTEM, 9, 0, GRAN_BYTE); -} - - -/* Returns a descriptor that yields the given LIMIT and BASE when - used as an operand for the LGDT instruction. */ -static uint64_t -make_gdtr_operand (uint16_t limit, void *base) -{ - return limit | ((uint64_t) (uint32_t) base << 16); -} diff --git a/src/userprog/gdt.h b/src/userprog/gdt.h deleted file mode 100644 index 81fe50cbd39c9a0a40642e5ed741001dac726b43..0000000000000000000000000000000000000000 --- a/src/userprog/gdt.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef USERPROG_GDT_H -#define USERPROG_GDT_H - -#include "threads/loader.h" - -/* Segment selectors. - More selectors are defined by the loader in loader.h. */ -#define SEL_UCSEG 0x1B /* User code selector. */ -#define SEL_UDSEG 0x23 /* User data selector. */ -#define SEL_TSS 0x28 /* Task-state segment. */ -#define SEL_CNT 6 /* Number of segments. */ - -void gdt_init (void); - -#endif /* userprog/gdt.h */ diff --git a/src/userprog/myrun b/src/userprog/myrun deleted file mode 100644 index ec01a3c21f87d00f1fffc5078e06761c5607e630..0000000000000000000000000000000000000000 --- a/src/userprog/myrun +++ /dev/null @@ -1,7 +0,0 @@ -rm -f build/filesys.dsk -cd build -pintos-mkdisk filesys.dsk --filesys-size=2 -pintos --qemu -- -f -q -pintos --qemu -p ../../examples/my -a my -- -q -pintos --qemu -- -q run 'my' -cd .. diff --git a/src/userprog/pagedir.c b/src/userprog/pagedir.c deleted file mode 100644 index a6a87b827ba16a12157d94df6f2a7233b7c59e8e..0000000000000000000000000000000000000000 --- a/src/userprog/pagedir.c +++ /dev/null @@ -1,263 +0,0 @@ -#include "userprog/pagedir.h" -#include <stdbool.h> -#include <stddef.h> -#include <string.h> -#include "threads/init.h" -#include "threads/pte.h" -#include "threads/palloc.h" - -static uint32_t *active_pd (void); -static void invalidate_pagedir (uint32_t *); - -/* Creates a new page directory that has mappings for kernel - virtual addresses, but none for user virtual addresses. - Returns the new page directory, or a null pointer if memory - allocation fails. */ -uint32_t * -pagedir_create (void) -{ - uint32_t *pd = palloc_get_page (0); - if (pd != NULL) - memcpy (pd, init_page_dir, PGSIZE); - return pd; -} - -/* Destroys page directory PD, freeing all the pages it - references. */ -void -pagedir_destroy (uint32_t *pd) -{ - uint32_t *pde; - - if (pd == NULL) - return; - - ASSERT (pd != init_page_dir); - for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++) - if (*pde & PTE_P) - { - uint32_t *pt = pde_get_pt (*pde); - uint32_t *pte; - - for (pte = pt; pte < pt + PGSIZE / sizeof *pte; pte++) - if (*pte & PTE_P) - palloc_free_page (pte_get_page (*pte)); - palloc_free_page (pt); - } - palloc_free_page (pd); -} - -/* Returns the address of the page table entry for virtual - address VADDR in page directory PD. - If PD does not have a page table for VADDR, behavior depends - on CREATE. If CREATE is true, then a new page table is - created and a pointer into it is returned. Otherwise, a null - pointer is returned. */ -static uint32_t * -lookup_page (uint32_t *pd, const void *vaddr, bool create) -{ - uint32_t *pt, *pde; - - ASSERT (pd != NULL); - - /* Shouldn't create new kernel virtual mappings. */ - ASSERT (!create || is_user_vaddr (vaddr)); - - /* Check for a page table for VADDR. - If one is missing, create one if requested. */ - pde = pd + pd_no (vaddr); - if (*pde == 0) - { - if (create) - { - pt = palloc_get_page (PAL_ZERO); - if (pt == NULL) - return NULL; - - *pde = pde_create (pt); - } - else - return NULL; - } - - /* Return the page table entry. */ - pt = pde_get_pt (*pde); - return &pt[pt_no (vaddr)]; -} - -/* Adds a mapping in page directory PD from user virtual page - UPAGE to the physical frame identified by kernel virtual - address KPAGE. - UPAGE must not already be mapped. - KPAGE should probably be a page obtained from the user pool - with palloc_get_page(). - If WRITABLE is true, the new page is read/write; - otherwise it is read-only. - Returns true if successful, false if memory allocation - failed. */ -bool -pagedir_set_page (uint32_t *pd, void *upage, void *kpage, bool writable) -{ - uint32_t *pte; - - ASSERT (pg_ofs (upage) == 0); - ASSERT (pg_ofs (kpage) == 0); - ASSERT (is_user_vaddr (upage)); - ASSERT (vtop (kpage) >> PTSHIFT < init_ram_pages); - ASSERT (pd != init_page_dir); - - pte = lookup_page (pd, upage, true); - - if (pte != NULL) - { - ASSERT ((*pte & PTE_P) == 0); - *pte = pte_create_user (kpage, writable); - return true; - } - else - return false; -} - -/* Looks up the physical address that corresponds to user virtual - address UADDR in PD. Returns the kernel virtual address - corresponding to that physical address, or a null pointer if - UADDR is unmapped. */ -void * -pagedir_get_page (uint32_t *pd, const void *uaddr) -{ - uint32_t *pte; - - ASSERT (is_user_vaddr (uaddr)); - - pte = lookup_page (pd, uaddr, false); - if (pte != NULL && (*pte & PTE_P) != 0) - return pte_get_page (*pte) + pg_ofs (uaddr); - else - return NULL; -} - -/* Marks user virtual page UPAGE "not present" in page - directory PD. Later accesses to the page will fault. Other - bits in the page table entry are preserved. - UPAGE need not be mapped. */ -void -pagedir_clear_page (uint32_t *pd, void *upage) -{ - uint32_t *pte; - - ASSERT (pg_ofs (upage) == 0); - ASSERT (is_user_vaddr (upage)); - - pte = lookup_page (pd, upage, false); - if (pte != NULL && (*pte & PTE_P) != 0) - { - *pte &= ~PTE_P; - invalidate_pagedir (pd); - } -} - -/* Returns true if the PTE for virtual page VPAGE in PD is dirty, - that is, if the page has been modified since the PTE was - installed. - Returns false if PD contains no PTE for VPAGE. */ -bool -pagedir_is_dirty (uint32_t *pd, const void *vpage) -{ - uint32_t *pte = lookup_page (pd, vpage, false); - return pte != NULL && (*pte & PTE_D) != 0; -} - -/* Set the dirty bit to DIRTY in the PTE for virtual page VPAGE - in PD. */ -void -pagedir_set_dirty (uint32_t *pd, const void *vpage, bool dirty) -{ - uint32_t *pte = lookup_page (pd, vpage, false); - if (pte != NULL) - { - if (dirty) - *pte |= PTE_D; - else - { - *pte &= ~(uint32_t) PTE_D; - invalidate_pagedir (pd); - } - } -} - -/* Returns true if the PTE for virtual page VPAGE in PD has been - accessed recently, that is, between the time the PTE was - installed and the last time it was cleared. Returns false if - PD contains no PTE for VPAGE. */ -bool -pagedir_is_accessed (uint32_t *pd, const void *vpage) -{ - uint32_t *pte = lookup_page (pd, vpage, false); - return pte != NULL && (*pte & PTE_A) != 0; -} - -/* Sets the accessed bit to ACCESSED in the PTE for virtual page - VPAGE in PD. */ -void -pagedir_set_accessed (uint32_t *pd, const void *vpage, bool accessed) -{ - uint32_t *pte = lookup_page (pd, vpage, false); - if (pte != NULL) - { - if (accessed) - *pte |= PTE_A; - else - { - *pte &= ~(uint32_t) PTE_A; - invalidate_pagedir (pd); - } - } -} - -/* Loads page directory PD into the CPU's page directory base - register. */ -void -pagedir_activate (uint32_t *pd) -{ - if (pd == NULL) - pd = init_page_dir; - - /* Store the physical address of the page directory into CR3 - aka PDBR (page directory base register). This activates our - new page tables immediately. See [IA32-v2a] "MOV--Move - to/from Control Registers" and [IA32-v3a] 3.7.5 "Base - Address of the Page Directory". */ - asm volatile ("movl %0, %%cr3" : : "r" (vtop (pd)) : "memory"); -} - -/* Returns the currently active page directory. */ -static uint32_t * -active_pd (void) -{ - /* Copy CR3, the page directory base register (PDBR), into - `pd'. - See [IA32-v2a] "MOV--Move to/from Control Registers" and - [IA32-v3a] 3.7.5 "Base Address of the Page Directory". */ - uintptr_t pd; - asm volatile ("movl %%cr3, %0" : "=r" (pd)); - return ptov (pd); -} - -/* Seom page table changes can cause the CPU's translation - lookaside buffer (TLB) to become out-of-sync with the page - table. When this happens, we have to "invalidate" the TLB by - re-activating it. - - This function invalidates the TLB if PD is the active page - directory. (If PD is not active then its entries are not in - the TLB, so there is no need to invalidate anything.) */ -static void -invalidate_pagedir (uint32_t *pd) -{ - if (active_pd () == pd) - { - /* Re-activating PD clears the TLB. See [IA32-v3a] 3.12 - "Translation Lookaside Buffers (TLBs)". */ - pagedir_activate (pd); - } -} diff --git a/src/userprog/pagedir.h b/src/userprog/pagedir.h deleted file mode 100644 index cd92447c2290bf4d0410a20b6a56af183922b429..0000000000000000000000000000000000000000 --- a/src/userprog/pagedir.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef USERPROG_PAGEDIR_H -#define USERPROG_PAGEDIR_H - -#include <stdbool.h> -#include <stdint.h> - -uint32_t *pagedir_create (void); -void pagedir_destroy (uint32_t *pd); -bool pagedir_set_page (uint32_t *pd, void *upage, void *kpage, bool rw); -void *pagedir_get_page (uint32_t *pd, const void *upage); -void pagedir_clear_page (uint32_t *pd, void *upage); -bool pagedir_is_dirty (uint32_t *pd, const void *upage); -void pagedir_set_dirty (uint32_t *pd, const void *upage, bool dirty); -bool pagedir_is_accessed (uint32_t *pd, const void *upage); -void pagedir_set_accessed (uint32_t *pd, const void *upage, bool accessed); -void pagedir_activate (uint32_t *pd); - -#endif /* userprog/pagedir.h */ diff --git a/src/userprog/process.c b/src/userprog/process.c deleted file mode 100644 index d51339a4aff8ec7aae340ae87035ef64358853fd..0000000000000000000000000000000000000000 --- a/src/userprog/process.c +++ /dev/null @@ -1,473 +0,0 @@ -#include "userprog/process.h" -#include <debug.h> -#include <inttypes.h> -#include <round.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "userprog/gdt.h" -#include "userprog/pagedir.h" -#include "userprog/tss.h" -#include "filesys/directory.h" -#include "filesys/file.h" -#include "filesys/filesys.h" -#include "threads/flags.h" -#include "threads/init.h" -#include "threads/interrupt.h" -#include "threads/palloc.h" -#include "threads/thread.h" -#include "threads/vaddr.h" - -static thread_func start_process NO_RETURN; -static bool load (const char *cmdline, void (**eip) (void), void **esp); - -/* Starts a new thread running a user program loaded from - FILENAME. The new thread may be scheduled (and may even exit) - before process_execute() returns. Returns the new process's - thread id, or TID_ERROR if the thread cannot be created. */ -tid_t -process_execute (const char *file_name) -{ - char *fn_copy; - tid_t tid; - - /* Make a copy of FILE_NAME. - Otherwise there's a race between the caller and load(). */ - fn_copy = palloc_get_page (0); - if (fn_copy == NULL) - return TID_ERROR; - strlcpy (fn_copy, file_name, PGSIZE); - - /* Create a new thread to execute FILE_NAME. */ - tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy); - - if (tid == TID_ERROR) - palloc_free_page (fn_copy); - return tid; -} - -/* A thread function that loads a user process and starts it - running. */ -static void -start_process (void *file_name_) -{ - char *file_name = file_name_; - struct intr_frame if_; - bool success; - - /* Initialize interrupt frame and load executable. */ - memset (&if_, 0, sizeof if_); - if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; - if_.cs = SEL_UCSEG; - if_.eflags = FLAG_IF | FLAG_MBS; - - success = load (file_name, &if_.eip, &if_.esp); - - /* If load failed, quit. */ - palloc_free_page (file_name); - if (!success) - thread_exit (); - - /* Start the user process by simulating a return from an - interrupt, implemented by intr_exit (in - threads/intr-stubs.S). Because intr_exit takes all of its - arguments on the stack in the form of a `struct intr_frame', - we just point the stack pointer (%esp) to our stack frame - and jump to it. */ - asm volatile ("movl %0, %%esp; jmp intr_exit" : : "g" (&if_) : "memory"); - NOT_REACHED (); -} - -/* Waits for thread TID to die and returns its exit status. If - it was terminated by the kernel (i.e. killed due to an - exception), returns -1. If TID is invalid or if it was not a - child of the calling process, or if process_wait() has already - been successfully called for the given TID, returns -1 - immediately, without waiting. - - This function will be implemented in problem 2-2. For now, it - does nothing. */ -int -process_wait (tid_t child_tid UNUSED) -{ - // FIXME: @bgaster --- quick hack to make sure processes execute! - for(;;) ; - - return -1; -} - -/* Free the current process's resources. */ -void -process_exit (void) -{ - struct thread *cur = thread_current (); - uint32_t *pd; - - /* Destroy the current process's page directory and switch back - to the kernel-only page directory. */ - pd = cur->pagedir; - if (pd != NULL) - { - /* Correct ordering here is crucial. We must set - cur->pagedir to NULL before switching page directories, - so that a timer interrupt can't switch back to the - process page directory. We must activate the base page - directory before destroying the process's page - directory, or our active page directory will be one - that's been freed (and cleared). */ - cur->pagedir = NULL; - pagedir_activate (NULL); - pagedir_destroy (pd); - } -} - -/* Sets up the CPU for running user code in the current - thread. - This function is called on every context switch. */ -void -process_activate (void) -{ - struct thread *t = thread_current (); - - /* Activate thread's page tables. */ - pagedir_activate (t->pagedir); - - /* Set thread's kernel stack for use in processing - interrupts. */ - tss_update (); -} - -/* We load ELF binaries. The following definitions are taken - from the ELF specification, [ELF1], more-or-less verbatim. */ - -/* ELF types. See [ELF1] 1-2. */ -typedef uint32_t Elf32_Word, Elf32_Addr, Elf32_Off; -typedef uint16_t Elf32_Half; - -/* For use with ELF types in printf(). */ -#define PE32Wx PRIx32 /* Print Elf32_Word in hexadecimal. */ -#define PE32Ax PRIx32 /* Print Elf32_Addr in hexadecimal. */ -#define PE32Ox PRIx32 /* Print Elf32_Off in hexadecimal. */ -#define PE32Hx PRIx16 /* Print Elf32_Half in hexadecimal. */ - -/* Executable header. See [ELF1] 1-4 to 1-8. - This appears at the very beginning of an ELF binary. */ -struct Elf32_Ehdr - { - unsigned char e_ident[16]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; - }; - -/* Program header. See [ELF1] 2-2 to 2-4. - There are e_phnum of these, starting at file offset e_phoff - (see [ELF1] 1-6). */ -struct Elf32_Phdr - { - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; - }; - -/* Values for p_type. See [ELF1] 2-3. */ -#define PT_NULL 0 /* Ignore. */ -#define PT_LOAD 1 /* Loadable segment. */ -#define PT_DYNAMIC 2 /* Dynamic linking info. */ -#define PT_INTERP 3 /* Name of dynamic loader. */ -#define PT_NOTE 4 /* Auxiliary info. */ -#define PT_SHLIB 5 /* Reserved. */ -#define PT_PHDR 6 /* Program header table. */ -#define PT_STACK 0x6474e551 /* Stack segment. */ - -/* Flags for p_flags. See [ELF3] 2-3 and 2-4. */ -#define PF_X 1 /* Executable. */ -#define PF_W 2 /* Writable. */ -#define PF_R 4 /* Readable. */ - -static bool setup_stack (void **esp); -static bool validate_segment (const struct Elf32_Phdr *, struct file *); -static bool load_segment (struct file *file, off_t ofs, uint8_t *upage, - uint32_t read_bytes, uint32_t zero_bytes, - bool writable); - -/* Loads an ELF executable from FILE_NAME into the current thread. - Stores the executable's entry point into *EIP - and its initial stack pointer into *ESP. - Returns true if successful, false otherwise. */ -bool -load (const char *file_name, void (**eip) (void), void **esp) -{ - struct thread *t = thread_current (); - struct Elf32_Ehdr ehdr; - struct file *file = NULL; - off_t file_ofs; - bool success = false; - int i; - - /* Allocate and activate page directory. */ - t->pagedir = pagedir_create (); - if (t->pagedir == NULL) - goto done; - process_activate (); - - /* Open executable file. */ - file = filesys_open (file_name); - - if (file == NULL) - { - printf ("load: %s: open failed\n", file_name); - goto done; - } - - /* Read and verify executable header. */ - if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr - || memcmp (ehdr.e_ident, "\177ELF\1\1\1", 7) - || ehdr.e_type != 2 - || ehdr.e_machine != 3 - || ehdr.e_version != 1 - || ehdr.e_phentsize != sizeof (struct Elf32_Phdr) - || ehdr.e_phnum > 1024) - { - printf ("load: %s: error loading executable\n", file_name); - goto done; - } - - /* Read program headers. */ - file_ofs = ehdr.e_phoff; - for (i = 0; i < ehdr.e_phnum; i++) - { - struct Elf32_Phdr phdr; - - if (file_ofs < 0 || file_ofs > file_length (file)) - goto done; - file_seek (file, file_ofs); - - if (file_read (file, &phdr, sizeof phdr) != sizeof phdr) - goto done; - file_ofs += sizeof phdr; - switch (phdr.p_type) - { - case PT_NULL: - case PT_NOTE: - case PT_PHDR: - case PT_STACK: - default: - /* Ignore this segment. */ - break; - case PT_DYNAMIC: - case PT_INTERP: - case PT_SHLIB: - goto done; - case PT_LOAD: - if (validate_segment (&phdr, file)) - { - bool writable = (phdr.p_flags & PF_W) != 0; - uint32_t file_page = phdr.p_offset & ~PGMASK; - uint32_t mem_page = phdr.p_vaddr & ~PGMASK; - uint32_t page_offset = phdr.p_vaddr & PGMASK; - uint32_t read_bytes, zero_bytes; - if (phdr.p_filesz > 0) - { - /* Normal segment. - Read initial part from disk and zero the rest. */ - read_bytes = page_offset + phdr.p_filesz; - zero_bytes = (ROUND_UP (page_offset + phdr.p_memsz, PGSIZE) - - read_bytes); - } - else - { - /* Entirely zero. - Don't read anything from disk. */ - read_bytes = 0; - zero_bytes = ROUND_UP (page_offset + phdr.p_memsz, PGSIZE); - } - if (!load_segment (file, file_page, (void *) mem_page, - read_bytes, zero_bytes, writable)) - goto done; - } - else - goto done; - break; - } - } - - /* Set up stack. */ - if (!setup_stack (esp)) - goto done; - - /* Start address. */ - *eip = (void (*) (void)) ehdr.e_entry; - - success = true; - - done: - /* We arrive here whether the load is successful or not. */ - file_close (file); - return success; -} - -/* load() helpers. */ - -static bool install_page (void *upage, void *kpage, bool writable); - -/* Checks whether PHDR describes a valid, loadable segment in - FILE and returns true if so, false otherwise. */ -static bool -validate_segment (const struct Elf32_Phdr *phdr, struct file *file) -{ - /* p_offset and p_vaddr must have the same page offset. */ - if ((phdr->p_offset & PGMASK) != (phdr->p_vaddr & PGMASK)) - return false; - - /* p_offset must point within FILE. */ - if (phdr->p_offset > (Elf32_Off) file_length (file)) - return false; - - /* p_memsz must be at least as big as p_filesz. */ - if (phdr->p_memsz < phdr->p_filesz) - return false; - - /* The segment must not be empty. */ - if (phdr->p_memsz == 0) - return false; - - /* The virtual memory region must both start and end within the - user address space range. */ - if (!is_user_vaddr ((void *) phdr->p_vaddr)) - return false; - if (!is_user_vaddr ((void *) (phdr->p_vaddr + phdr->p_memsz))) - return false; - - /* The region cannot "wrap around" across the kernel virtual - address space. */ - if (phdr->p_vaddr + phdr->p_memsz < phdr->p_vaddr) - return false; - - /* Disallow mapping page 0. - Not only is it a bad idea to map page 0, but if we allowed - it then user code that passed a null pointer to system calls - could quite likely panic the kernel by way of null pointer - assertions in memcpy(), etc. */ - if (phdr->p_vaddr < PGSIZE) - return false; - - /* It's okay. */ - return true; -} - -/* Loads a segment starting at offset OFS in FILE at address - UPAGE. In total, READ_BYTES + ZERO_BYTES bytes of virtual - memory are initialized, as follows: - - - READ_BYTES bytes at UPAGE must be read from FILE - starting at offset OFS. - - - ZERO_BYTES bytes at UPAGE + READ_BYTES must be zeroed. - - The pages initialized by this function must be writable by the - user process if WRITABLE is true, read-only otherwise. - - Return true if successful, false if a memory allocation error - or disk read error occurs. */ -static bool -load_segment (struct file *file, off_t ofs, uint8_t *upage, - uint32_t read_bytes, uint32_t zero_bytes, bool writable) -{ - ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0); - ASSERT (pg_ofs (upage) == 0); - ASSERT (ofs % PGSIZE == 0); - - file_seek (file, ofs); - while (read_bytes > 0 || zero_bytes > 0) - { - /* Calculate how to fill this page. - We will read PAGE_READ_BYTES bytes from FILE - and zero the final PAGE_ZERO_BYTES bytes. */ - size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE; - size_t page_zero_bytes = PGSIZE - page_read_bytes; - - /* Get a page of memory. */ - uint8_t *kpage = palloc_get_page (PAL_USER); - if (kpage == NULL) - return false; - - /* Load this page. */ - if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) - { - palloc_free_page (kpage); - return false; - } - memset (kpage + page_read_bytes, 0, page_zero_bytes); - - /* Add the page to the process's address space. */ - if (!install_page (upage, kpage, writable)) - { - palloc_free_page (kpage); - return false; - } - - /* Advance. */ - read_bytes -= page_read_bytes; - zero_bytes -= page_zero_bytes; - upage += PGSIZE; - } - return true; -} - -/* Create a minimal stack by mapping a zeroed page at the top of - user virtual memory. */ -static bool -setup_stack (void **esp) -{ - uint8_t *kpage; - bool success = false; - - kpage = palloc_get_page (PAL_USER | PAL_ZERO); - if (kpage != NULL) - { - success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true); - if (success) { - *esp = PHYS_BASE; - } else - palloc_free_page (kpage); - } - return success; -} - -/* Adds a mapping from user virtual address UPAGE to kernel - virtual address KPAGE to the page table. - If WRITABLE is true, the user process may modify the page; - otherwise, it is read-only. - UPAGE must not already be mapped. - KPAGE should probably be a page obtained from the user pool - with palloc_get_page(). - Returns true on success, false if UPAGE is already mapped or - if memory allocation fails. */ -static bool -install_page (void *upage, void *kpage, bool writable) -{ - struct thread *t = thread_current (); - - /* Verify that there's not already a page at that virtual - address, then map our page there. */ - return (pagedir_get_page (t->pagedir, upage) == NULL - && pagedir_set_page (t->pagedir, upage, kpage, writable)); -} - -//-------------------------------------------------------------------- diff --git a/src/userprog/process.h b/src/userprog/process.h deleted file mode 100644 index 688cd2a37fd2c1bd7fdcb417f834026a25fa4945..0000000000000000000000000000000000000000 --- a/src/userprog/process.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef USERPROG_PROCESS_H -#define USERPROG_PROCESS_H - -#include "threads/thread.h" - -tid_t process_execute (const char *file_name); -int process_wait (tid_t); -void process_exit (void); -void process_activate (void); - -#endif /* userprog/process.h */ diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c deleted file mode 100644 index 04635159d30520fa11296dc922e622f2ad2553d5..0000000000000000000000000000000000000000 --- a/src/userprog/syscall.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "userprog/syscall.h" -#include <stdio.h> -#include <syscall-nr.h> -#include "threads/interrupt.h" -#include "threads/thread.h" - -static void syscall_handler (struct intr_frame *); - -void -syscall_init (void) -{ - intr_register_int (0x30, 3, INTR_ON, syscall_handler, "syscall"); -} - - -static void -syscall_handler (struct intr_frame *f UNUSED) -{ - printf ("system call!\n"); - thread_exit (); -} diff --git a/src/userprog/syscall.h b/src/userprog/syscall.h deleted file mode 100644 index 90590967a9f96f9ea359d15c672b815dfb4379cb..0000000000000000000000000000000000000000 --- a/src/userprog/syscall.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef USERPROG_SYSCALL_H -#define USERPROG_SYSCALL_H - -void syscall_init (void); - -#endif /* userprog/syscall.h */ diff --git a/src/userprog/tss.c b/src/userprog/tss.c deleted file mode 100644 index f8ed9a90ab0d7cf0cad855842cac8570a1e720f6..0000000000000000000000000000000000000000 --- a/src/userprog/tss.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "userprog/tss.h" -#include <debug.h> -#include <stddef.h> -#include "userprog/gdt.h" -#include "threads/thread.h" -#include "threads/palloc.h" -#include "threads/vaddr.h" - -/* The Task-State Segment (TSS). - - Instances of the TSS, an x86-specific structure, are used to - define "tasks", a form of support for multitasking built right - into the processor. However, for various reasons including - portability, speed, and flexibility, most x86 OSes almost - completely ignore the TSS. We are no exception. - - Unfortunately, there is one thing that can only be done using - a TSS: stack switching for interrupts that occur in user mode. - When an interrupt occurs in user mode (ring 3), the processor - consults the ss0 and esp0 members of the current TSS to - determine the stack to use for handling the interrupt. Thus, - we must create a TSS and initialize at least these fields, and - this is precisely what this file does. - - When an interrupt is handled by an interrupt or trap gate - (which applies to all interrupts we handle), an x86 processor - works like this: - - - If the code interrupted by the interrupt is in the same - ring as the interrupt handler, then no stack switch takes - place. This is the case for interrupts that happen when - we're running in the kernel. The contents of the TSS are - irrelevant for this case. - - - If the interrupted code is in a different ring from the - handler, then the processor switches to the stack - specified in the TSS for the new ring. This is the case - for interrupts that happen when we're in user space. It's - important that we switch to a stack that's not already in - use, to avoid corruption. Because we're running in user - space, we know that the current process's kernel stack is - not in use, so we can always use that. Thus, when the - scheduler switches threads, it also changes the TSS's - stack pointer to point to the new thread's kernel stack. - (The call is in thread_schedule_tail() in thread.c.) - - See [IA32-v3a] 6.2.1 "Task-State Segment (TSS)" for a - description of the TSS. See [IA32-v3a] 5.12.1 "Exception- or - Interrupt-Handler Procedures" for a description of when and - how stack switching occurs during an interrupt. */ -struct tss - { - uint16_t back_link, :16; - void *esp0; /* Ring 0 stack virtual address. */ - uint16_t ss0, :16; /* Ring 0 stack segment selector. */ - void *esp1; - uint16_t ss1, :16; - void *esp2; - uint16_t ss2, :16; - uint32_t cr3; - void (*eip) (void); - uint32_t eflags; - uint32_t eax, ecx, edx, ebx; - uint32_t esp, ebp, esi, edi; - uint16_t es, :16; - uint16_t cs, :16; - uint16_t ss, :16; - uint16_t ds, :16; - uint16_t fs, :16; - uint16_t gs, :16; - uint16_t ldt, :16; - uint16_t trace, bitmap; - }; - -/* Kernel TSS. */ -static struct tss *tss; - -/* Initializes the kernel TSS. */ -void -tss_init (void) -{ - /* Our TSS is never used in a call gate or task gate, so only a - few fields of it are ever referenced, and those are the only - ones we initialize. */ - tss = palloc_get_page (PAL_ASSERT | PAL_ZERO); - tss->ss0 = SEL_KDSEG; - tss->bitmap = 0xdfff; - tss_update (); -} - -/* Returns the kernel TSS. */ -struct tss * -tss_get (void) -{ - ASSERT (tss != NULL); - return tss; -} - -/* Sets the ring 0 stack pointer in the TSS to point to the end - of the thread stack. */ -void -tss_update (void) -{ - ASSERT (tss != NULL); - tss->esp0 = (uint8_t *) thread_current () + PGSIZE; -} diff --git a/src/userprog/tss.h b/src/userprog/tss.h deleted file mode 100644 index 467bd19e51ffc4f1bce00ea88496302c9ae9d6f2..0000000000000000000000000000000000000000 --- a/src/userprog/tss.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef USERPROG_TSS_H -#define USERPROG_TSS_H - -#include <stdint.h> - -struct tss; -void tss_init (void); -struct tss *tss_get (void); -void tss_update (void); - -#endif /* userprog/tss.h */ diff --git a/src/utils/.gitignore b/src/utils/.gitignore deleted file mode 100644 index b96f2786cf76cac1b6e75505b89b3635de3c84c2..0000000000000000000000000000000000000000 --- a/src/utils/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -setitimer-helper -squish-pty -squish-unix diff --git a/src/utils/Makefile b/src/utils/Makefile deleted file mode 100644 index e38eb1f3dfa2972035eee486247e40e939a0be38..0000000000000000000000000000000000000000 --- a/src/utils/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -all: setitimer-helper squish-pty squish-unix - -CC = gcc -CFLAGS = -Wall -W -LOADLIBES = -lm -setitimer-helper: setitimer-helper.o -squish-pty: squish-pty.o -squish-unix: squish-unix.o - -clean: - rm -f *.o setitimer-helper squish-pty squish-unix diff --git a/src/utils/Pintos.pm b/src/utils/Pintos.pm deleted file mode 100644 index 70df40d2309d234bd989667aa0f11647ba696969..0000000000000000000000000000000000000000 --- a/src/utils/Pintos.pm +++ /dev/null @@ -1,491 +0,0 @@ -# Pintos helper subroutines. - -# Number of bytes available for the loader at the beginning of the MBR. -# Kernel command-line arguments follow the loader. -our $LOADER_SIZE = 314; - -# Partition types. -my (%role2type) = (KERNEL => 0x20, - FILESYS => 0x21, - SCRATCH => 0x22, - SWAP => 0x23); -my (%type2role) = reverse %role2type; - -# Order of roles within a given disk. -our (@role_order) = qw (KERNEL FILESYS SCRATCH SWAP); - -# Partitions. -# -# Valid keys are KERNEL, FILESYS, SCRATCH, SWAP. Only those -# partitions which are in use are included. -# -# Each value is a reference to a hash. If the partition's contents -# are to be obtained from a file (that will be copied into a new -# virtual disk), then the hash contains: -# -# FILE => name of file from which the partition's contents are copied -# (perhaps "/dev/zero"), -# OFFSET => offset in bytes in FILE, -# BYTES => size in bytes of contents from FILE, -# -# If the partition is taken from a virtual disk directly, then it -# contains the following. The same keys are also filled in once a -# file-based partition has been copied into a new virtual disk: -# -# DISK => name of virtual disk file, -# START => sector offset of start of partition within DISK, -# SECTORS => number of sectors of partition within DISK, which is usually -# greater than round_up (BYTES, 512) due to padding. -our (%parts); - -# set_part($opt, $arg) -# -# For use as a helper function for Getopt::Long::GetOptions to set -# disk sources. -sub set_part { - my ($opt, $arg) = @_; - my ($role, $source) = $opt =~ /^([a-z]+)(?:-([a-z]+))?/ or die; - - $role = uc $role; - $source = 'FILE' if $source eq ''; - - die "can't have two sources for \L$role\E partition" - if exists $parts{$role}; - - do_set_part ($role, $source, $arg); -} - -# do_set_part($role, $source, $arg) -# -# Sets partition $role as coming from $source (one of 'file', 'from', -# or 'size'). $arg is a file name for 'file' or 'from', a size in -# megabytes for 'size'. -sub do_set_part { - my ($role, $source, $arg) = @_; - - my ($p) = $parts{$role} = {}; - if ($source eq 'file') { - if (read_mbr ($arg)) { - print STDERR "warning: $arg looks like a partitioned disk "; - print STDERR "(did you want --$role-from=$arg or --disk=$arg?)\n" - } - - $p->{FILE} = $arg; - $p->{OFFSET} = 0; - $p->{BYTES} = -s $arg; - } elsif ($source eq 'from') { - my (%pt) = read_partition_table ($arg); - my ($sp) = $pt{$role}; - die "$arg: does not contain \L$role\E partition\n" if !defined $sp; - - $p->{FILE} = $arg; - $p->{OFFSET} = $sp->{START} * 512; - $p->{BYTES} = $sp->{SECTORS} * 512; - } elsif ($source eq 'size') { - $arg =~ /^\d+(\.\d+)?|\.\d+$/ or die "$arg: not a valid size in MB\n"; - - $p->{FILE} = "/dev/zero"; - $p->{OFFSET} = 0; - $p->{BYTES} = ceil ($arg * 1024 * 1024); - } else { - die; - } -} - -# set_geometry('HEADS,SPT') -# set_geometry('zip') -# -# For use as a helper function for Getopt::Long::GetOptions to set -# disk geometry. -sub set_geometry { - local ($_) = $_[1]; - if ($_ eq 'zip') { - @geometry{'H', 'S'} = (64, 32); - } else { - @geometry{'H', 'S'} = /^(\d+)[,\s]+(\d+)$/ - or die "bad syntax for geometry\n"; - $geometry{H} <= 255 or die "heads limited to 255\n"; - $geometry{S} <= 63 or die "sectors per track limited to 63\n"; - } -} - -# set_align('bochs|full|none') -# -# For use as a helper function for Getopt::Long::GetOptions to set -# partition alignment. -sub set_align { - $align = $_[1]; - die "unknown alignment type \"$align\"\n" - if $align ne 'bochs' && $align ne 'full' && $align ne 'none'; -} - -# assemble_disk(%args) -# -# Creates a virtual disk $args{DISK} containing the partitions -# described by @args{KERNEL, FILESYS, SCRATCH, SWAP}. -# -# Required arguments: -# DISK => output disk file name -# HANDLE => output file handle (will be closed) -# -# Normally at least one of the following is included: -# KERNEL, FILESYS, SCRATCH, SWAP => {input: -# FILE => file to read, -# OFFSET => byte offset in file, -# BYTES => byte count from file, -# -# output: -# DISK => output disk file name, -# START => sector offset in DISK, -# SECTORS => sector count in DISK}, -# -# Optional arguments: -# ALIGN => 'bochs' (default), 'full', or 'none' -# GEOMETRY => {H => heads, S => sectors per track} (default 16, 63) -# FORMAT => 'partitioned' (default) or 'raw' -# LOADER => $LOADER_SIZE-byte string containing the loader binary -# ARGS => ['arg 1', 'arg 2', ...] -sub assemble_disk { - my (%args) = @_; - - my (%geometry) = $args{GEOMETRY} || (H => 16, S => 63); - - my ($align); # Align partition start, end to cylinder boundary? - my ($pad); # Pad end of disk out to cylinder boundary? - if (!defined ($args{ALIGN}) || $args{ALIGN} eq 'bochs') { - $align = 0; - $pad = 1; - } elsif ($args{ALIGN} eq 'full') { - $align = 1; - $pad = 0; - } elsif ($args{ALIGN} eq 'none') { - $align = $pad = 0; - } else { - die; - } - - my ($format) = $args{FORMAT} || 'partitioned'; - die if $format ne 'partitioned' && $format ne 'raw'; - - # Check that we have apartitions to copy in. - my $part_cnt = grep (defined ($args{$_}), keys %role2type); - die "must have exactly one partition for raw output\n" - if $format eq 'raw' && $part_cnt != 1; - - # Calculate the disk size. - my ($total_sectors) = 0; - if ($format eq 'partitioned') { - $total_sectors += $align ? $geometry{S} : 1; - } - for my $role (@role_order) { - my ($p) = $args{$role}; - next if !defined $p; - - die if $p->{DISK}; - - my ($bytes) = $p->{BYTES}; - my ($start) = $total_sectors; - my ($end) = $start + div_round_up ($bytes, 512); - $end = round_up ($end, cyl_sectors (%geometry)) if $align; - - $p->{DISK} = $args{DISK}; - $p->{START} = $start; - $p->{SECTORS} = $end - $start; - $total_sectors = $end; - } - - # Write the disk. - my ($disk_fn) = $args{DISK}; - my ($disk) = $args{HANDLE}; - if ($format eq 'partitioned') { - # Pack loader into MBR. - my ($loader) = $args{LOADER} || "\xcd\x18"; - my ($mbr) = pack ("a$LOADER_SIZE", $loader); - - $mbr .= make_kernel_command_line (@{$args{ARGS}}); - - # Pack partition table into MBR. - $mbr .= make_partition_table (\%geometry, \%args); - - # Add signature to MBR. - $mbr .= pack ("v", 0xaa55); - - die if length ($mbr) != 512; - write_fully ($disk, $disk_fn, $mbr); - write_zeros ($disk, $disk_fn, 512 * ($geometry{S} - 1)) if $align; - } - for my $role (@role_order) { - my ($p) = $args{$role}; - next if !defined $p; - - my ($source); - my ($fn) = $p->{FILE}; - open ($source, '<', $fn) or die "$fn: open: $!\n"; - if ($p->{OFFSET}) { - sysseek ($source, $p->{OFFSET}, 0) == $p->{OFFSET} - or die "$fn: seek: $!\n"; - } - copy_file ($source, $fn, $disk, $disk_fn, $p->{BYTES}); - close ($source) or die "$fn: close: $!\n"; - - write_zeros ($disk, $disk_fn, $p->{SECTORS} * 512 - $p->{BYTES}); - } - if ($pad) { - my ($pad_sectors) = round_up ($total_sectors, cyl_sectors (%geometry)); - write_zeros ($disk, $disk_fn, ($pad_sectors - $total_sectors) * 512); - } - close ($disk) or die "$disk: close: $!\n"; -} - -# make_partition_table({H => heads, S => sectors}, {KERNEL => ..., ...}) -# -# Creates and returns a partition table for the given partitions and -# disk geometry. -sub make_partition_table { - my ($geometry, $partitions) = @_; - my ($table) = ''; - for my $role (@role_order) { - defined (my $p = $partitions->{$role}) or next; - - my $end = $p->{START} + $p->{SECTORS} - 1; - my $bootable = $role eq 'KERNEL'; - - $table .= pack ("C", $bootable ? 0x80 : 0); # Bootable? - $table .= pack_chs ($p->{START}, $geometry); # CHS of partition start - $table .= pack ("C", $role2type{$role}); # Partition type - $table .= pack_chs($end, $geometry); # CHS of partition end - $table .= pack ("V", $p->{START}); # LBA of partition start - $table .= pack ("V", $p->{SECTORS}); # Length in sectors - die if length ($table) % 16; - } - return pack ("a64", $table); -} - -# make_kernel_command_line(@args) -# -# Returns the raw bytes to write to an MBR at offset $LOADER_SIZE to -# set a Pintos kernel command line. -sub make_kernel_command_line { - my (@args) = @_; - my ($args) = join ('', map ("$_\0", @args)); - die "command line exceeds 128 bytes" if length ($args) > 128; - return pack ("V a128", scalar (@args), $args); -} - -# copy_file($from_handle, $from_file_name, $to_handle, $to_file_name, $size) -# -# Copies $size bytes from $from_handle to $to_handle. -# $from_file_name and $to_file_name are used in error messages. -sub copy_file { - my ($from_handle, $from_file_name, $to_handle, $to_file_name, $size) = @_; - - while ($size > 0) { - my ($chunk_size) = 4096; - $chunk_size = $size if $chunk_size > $size; - $size -= $chunk_size; - - my ($data) = read_fully ($from_handle, $from_file_name, $chunk_size); - write_fully ($to_handle, $to_file_name, $data); - } -} - -# read_fully($handle, $file_name, $bytes) -# -# Reads exactly $bytes bytes from $handle and returns the data read. -# $file_name is used in error messages. -sub read_fully { - my ($handle, $file_name, $bytes) = @_; - my ($data); - my ($read_bytes) = sysread ($handle, $data, $bytes); - die "$file_name: read: $!\n" if !defined $read_bytes; - die "$file_name: unexpected end of file\n" if $read_bytes != $bytes; - return $data; -} - -# write_fully($handle, $file_name, $data) -# -# Write $data to $handle. -# $file_name is used in error messages. -sub write_fully { - my ($handle, $file_name, $data) = @_; - my ($written_bytes) = syswrite ($handle, $data); - die "$file_name: write: $!\n" if !defined $written_bytes; - die "$file_name: short write\n" if $written_bytes != length $data; -} - -sub write_zeros { - my ($handle, $file_name, $size) = @_; - - while ($size > 0) { - my ($chunk_size) = 4096; - $chunk_size = $size if $chunk_size > $size; - $size -= $chunk_size; - - write_fully ($handle, $file_name, "\0" x $chunk_size); - } -} - -# div_round_up($x,$y) -# -# Returns $x / $y, rounded up to the nearest integer. -# $y must be an integer. -sub div_round_up { - my ($x, $y) = @_; - return int ((ceil ($x) + $y - 1) / $y); -} - -# round_up($x, $y) -# -# Returns $x rounded up to the nearest multiple of $y. -# $y must be an integer. -sub round_up { - my ($x, $y) = @_; - return div_round_up ($x, $y) * $y; -} - -# cyl_sectors(H => heads, S => sectors) -# -# Returns the number of sectors in a cylinder of a disk with the given -# geometry. -sub cyl_sectors { - my (%geometry) = @_; - return $geometry{H} * $geometry{S}; -} - -# read_loader($file_name) -# -# Reads and returns the first $LOADER_SIZE bytes in $file_name. -# If $file_name is undefined, tries to find the default loader. -# Makes sure that the loader is a reasonable size. -sub read_loader { - my ($name) = @_; - $name = find_file ("loader.bin") if !defined $name; - die "Cannot find loader\n" if !defined $name; - - my ($handle); - open ($handle, '<', $name) or die "$name: open: $!\n"; - -s $handle == $LOADER_SIZE || -s $handle == 512 - or die "$name: must be exactly $LOADER_SIZE or 512 bytes long\n"; - $loader = read_fully ($handle, $name, $LOADER_SIZE); - close ($handle) or die "$name: close: $!\n"; - return $loader; -} - -# pack_chs($lba, {H => heads, S => sectors}) -# -# Converts logical sector $lba to a 3-byte packed geometrical sector -# in the format used in PC partition tables (see [Partitions]) and -# returns the geometrical sector as a 3-byte string. -sub pack_chs { - my ($lba, $geometry) = @_; - my ($cyl, $head, $sect) = lba_to_chs ($lba, $geometry); - return pack ("CCC", $head, $sect | (($cyl >> 2) & 0xc0), $cyl & 0xff); -} - -# lba_to_chs($lba, {H => heads, S => sectors}) -# -# Returns the geometrical sector corresponding to logical sector $lba -# given the specified geometry. -sub lba_to_chs { - my ($lba, $geometry) = @_; - my ($hpc) = $geometry->{H}; - my ($spt) = $geometry->{S}; - - # Source: - # http://en.wikipedia.org/wiki/CHS_conversion - use integer; - my $cyl = $lba / ($hpc * $spt); - my $temp = $lba % ($hpc * $spt); - my $head = $temp / $spt; - my $sect = $temp % $spt + 1; - - # Source: - # http://www.cgsecurity.org/wiki/Intel_Partition_Table - if ($cyl <= 1023) { - return ($cyl, $head, $sect); - } else { - return (1023, 254, 63); ## or should this be (1023, $hpc, $spt)? - } -} - -# read_mbr($file) -# -# Tries to read an MBR from $file. Returns the 512-byte MBR if -# successful, otherwise numeric 0. -sub read_mbr { - my ($file) = @_; - my ($retval) = 0; - open (FILE, '<', $file) or die "$file: open: $!\n"; - if (-s FILE == 0) { - die "$file: file has zero size\n"; - } elsif (-s FILE >= 512) { - my ($mbr); - sysread (FILE, $mbr, 512) == 512 or die "$file: read: $!\n"; - $retval = $mbr if unpack ("v", substr ($mbr, 510)) == 0xaa55; - } - close (FILE); - return $retval; -} - -# interpret_partition_table($mbr, $disk) -# -# Parses the partition-table in the specified 512-byte $mbr and -# returns the partitions. $disk is used for error messages. -sub interpret_partition_table { - my ($mbr, $disk) = @_; - my (%parts); - for my $i (0...3) { - my ($bootable, $valid, $type, $lba_start, $lba_length) - = unpack ("C X V C x3 V V", substr ($mbr, 446 + 16 * $i, 16)); - next if !$valid; - - (print STDERR "warning: invalid partition entry $i in $disk\n"), - next if $bootable != 0 && $bootable != 0x80; - - my ($role) = $type2role{$type}; - (printf STDERR "warning: non-Pintos partition type 0x%02x in %s\n", - $type, $disk), - next if !defined $role; - - (print STDERR "warning: duplicate \L$role\E partition in $disk\n"), - next if exists $parts{$role}; - - $parts{$role} = {START => $lba_start, - SECTORS => $lba_length}; - } - return %parts; -} - -# find_file($base_name) -# -# Looks for a file named $base_name in a couple of likely spots. If -# found, returns the name; otherwise, returns undef. -sub find_file { - my ($base_name) = @_; - -e && return $_ foreach $base_name, "build/$base_name"; - return undef; -} - -# read_partition_table($file) -# -# Reads a partition table from $file and returns the parsed -# partitions. Dies if partitions can't be read. -sub read_partition_table { - my ($file) = @_; - my ($mbr) = read_mbr ($file); - die "$file: not a partitioned disk\n" if !$mbr; - return interpret_partition_table ($mbr, $file); -} - -# max(@args) -# -# Returns the numerically largest value in @args. -sub max { - my ($max) = $_[0]; - foreach (@_[1..$#_]) { - $max = $_ if $_ > $max; - } - return $max; -} - -1; diff --git a/src/utils/backtrace b/src/utils/backtrace deleted file mode 100755 index 95e422f04793610960414529f543ae6d82132c6c..0000000000000000000000000000000000000000 --- a/src/utils/backtrace +++ /dev/null @@ -1,106 +0,0 @@ -#! /usr/bin/perl -w - -use strict; - -# Check command line. -if (grep ($_ eq '-h' || $_ eq '--help', @ARGV)) { - print <<'EOF'; -backtrace, for converting raw addresses into symbolic backtraces -usage: backtrace [BINARY]... ADDRESS... -where BINARY is the binary file or files from which to obtain symbols - and ADDRESS is a raw address to convert to a symbol name. - -If no BINARY is unspecified, the default is the first of kernel.o or -build/kernel.o that exists. If multiple binaries are specified, each -symbol printed is from the first binary that contains a match. - -The ADDRESS list should be taken from the "Call stack:" printed by the -kernel. Read "Backtraces" in the "Debugging Tools" chapter of the -Pintos documentation for more information. -EOF - exit 0; -} -die "backtrace: at least one argument required (use --help for help)\n" - if @ARGV == 0; - -# Drop garbage inserted by kernel. -@ARGV = grep (!/^(call|stack:?|[-+])$/i, @ARGV); -s/\.$// foreach @ARGV; - -# Find binaries. -my (@binaries); -while ($ARGV[0] !~ /^0x/) { - my ($bin) = shift @ARGV; - die "backtrace: $bin: not found (use --help for help)\n" if ! -e $bin; - push (@binaries, $bin); -} -if (!@binaries) { - my ($bin); - if (-e 'kernel.o') { - $bin = 'kernel.o'; - } elsif (-e 'build/kernel.o') { - $bin = 'build/kernel.o'; - } else { - die "backtrace: no binary specified and neither \"kernel.o\" nor \"build/kernel.o\" exists (use --help for help)\n"; - } - push (@binaries, $bin); -} - -# Find addr2line. -my ($a2l) = search_path ("i386-elf-addr2line") || search_path ("addr2line"); -if (!$a2l) { - die "backtrace: neither `i386-elf-addr2line' nor `addr2line' in PATH\n"; -} -sub search_path { - my ($target) = @_; - for my $dir (split (':', $ENV{PATH})) { - my ($file) = "$dir/$target"; - return $file if -e $file; - } - return undef; -} - -# Figure out backtrace. -my (@locs) = map ({ADDR => $_}, @ARGV); -for my $bin (@binaries) { - open (A2L, "$a2l -fe $bin " . join (' ', map ($_->{ADDR}, @locs)) . "|"); - for (my ($i) = 0; <A2L>; $i++) { - my ($function, $line); - chomp ($function = $_); - chomp ($line = <A2L>); - next if defined $locs[$i]{BINARY}; - - if ($function ne '??' || $line ne '??:0') { - $locs[$i]{FUNCTION} = $function; - $locs[$i]{LINE} = $line; - $locs[$i]{BINARY} = $bin; - } - } - close (A2L); -} - -# Print backtrace. -my ($cur_binary); -for my $loc (@locs) { - if (defined ($loc->{BINARY}) - && @binaries > 1 - && (!defined ($cur_binary) || $loc->{BINARY} ne $cur_binary)) { - $cur_binary = $loc->{BINARY}; - print "In $cur_binary:\n"; - } - - my ($addr) = $loc->{ADDR}; - $addr = sprintf ("0x%08x", hex ($addr)) if $addr =~ /^0x[0-9a-f]+$/i; - - print $addr, ": "; - if (defined ($loc->{BINARY})) { - my ($function) = $loc->{FUNCTION}; - my ($line) = $loc->{LINE}; - $line =~ s/^(\.\.\/)*//; - $line = "..." . substr ($line, -25) if length ($line) > 28; - print "$function ($line)"; - } else { - print "(unknown)"; - } - print "\n"; -} diff --git a/src/utils/pintos b/src/utils/pintos deleted file mode 100755 index 16a725a9ef4dd44351f9b82e911eca1841cd50b1..0000000000000000000000000000000000000000 --- a/src/utils/pintos +++ /dev/null @@ -1,950 +0,0 @@ -#! /usr/bin/perl -w - -use strict; -use POSIX; -use Fcntl; -use File::Temp 'tempfile'; -use Getopt::Long qw(:config bundling); -use Fcntl qw(SEEK_SET SEEK_CUR); - -# Read Pintos.pm from the same directory as this program. -BEGIN { my $self = $0; $self =~ s%/+[^/]*$%%; require "$self/Pintos.pm"; } - -# Command-line options. -our ($start_time) = time (); -our ($sim); # Simulator: bochs, qemu, or player. -our ($debug) = "none"; # Debugger: none, monitor, or gdb. -our ($mem) = 4; # Physical RAM in MB. -our ($serial) = 1; # Use serial port for input and output? -our ($vga); # VGA output: window, terminal, or none. -our ($jitter); # Seed for random timer interrupts, if set. -our ($realtime); # Synchronize timer interrupts with real time? -our ($timeout); # Maximum runtime in seconds, if set. -our ($kill_on_failure); # Abort quickly on test failure? -our (@puts); # Files to copy into the VM. -our (@gets); # Files to copy out of the VM. -our ($as_ref); # Reference to last addition to @gets or @puts. -our (@kernel_args); # Arguments to pass to kernel. -our (%parts); # Partitions. -our ($make_disk); # Name of disk to create. -our ($tmp_disk) = 1; # Delete $make_disk after run? -our (@disks); # Extra disk images to pass to simulator. -our ($loader_fn); # Bootstrap loader. -our (%geometry); # IDE disk geometry. -our ($align); # Partition alignment. - -parse_command_line (); -prepare_scratch_disk (); -find_disks (); -run_vm (); -finish_scratch_disk (); - -exit 0; - -# Parses the command line. -sub parse_command_line { - usage (0) if @ARGV == 0 || (@ARGV == 1 && $ARGV[0] eq '--help'); - - @kernel_args = @ARGV; - if (grep ($_ eq '--', @kernel_args)) { - @ARGV = (); - while ((my $arg = shift (@kernel_args)) ne '--') { - push (@ARGV, $arg); - } - GetOptions ("sim=s" => sub { set_sim ($_[1]) }, - "bochs" => sub { set_sim ("bochs") }, - "qemu" => sub { set_sim ("qemu") }, - "player" => sub { set_sim ("player") }, - - "debug=s" => sub { set_debug ($_[1]) }, - "no-debug" => sub { set_debug ("none") }, - "monitor" => sub { set_debug ("monitor") }, - "gdb" => sub { set_debug ("gdb") }, - - "m|memory=i" => \$mem, - "j|jitter=i" => sub { set_jitter ($_[1]) }, - "r|realtime" => sub { set_realtime () }, - - "T|timeout=i" => \$timeout, - "k|kill-on-failure" => \$kill_on_failure, - - "v|no-vga" => sub { set_vga ('none'); }, - "s|no-serial" => sub { $serial = 0; }, - "t|terminal" => sub { set_vga ('terminal'); }, - - "p|put-file=s" => sub { add_file (\@puts, $_[1]); }, - "g|get-file=s" => sub { add_file (\@gets, $_[1]); }, - "a|as=s" => sub { set_as ($_[1]); }, - - "h|help" => sub { usage (0); }, - - "kernel=s" => \&set_part, - "filesys=s" => \&set_part, - "swap=s" => \&set_part, - - "filesys-size=s" => \&set_part, - "scratch-size=s" => \&set_part, - "swap-size=s" => \&set_part, - - "kernel-from=s" => \&set_part, - "filesys-from=s" => \&set_part, - "swap-from=s" => \&set_part, - - "make-disk=s" => sub { $make_disk = $_[1]; - $tmp_disk = 0; }, - "disk=s" => sub { set_disk ($_[1]); }, - "loader=s" => \$loader_fn, - - "geometry=s" => \&set_geometry, - "align=s" => \&set_align) - or exit 1; - } - - $sim = "qemu" if !defined $sim; - $debug = "none" if !defined $debug; - $vga = exists ($ENV{DISPLAY}) ? "window" : "none" if !defined $vga; - - undef $timeout, print "warning: disabling timeout with --$debug\n" - if defined ($timeout) && $debug ne 'none'; - - print "warning: enabling serial port for -k or --kill-on-failure\n" - if $kill_on_failure && !$serial; - - $align = "bochs", - print STDERR "warning: setting --align=bochs for Bochs support\n" - if $sim eq 'bochs' && defined ($align) && $align eq 'none'; - - $kill_on_failure = 0; -} - -# usage($exitcode). -# Prints a usage message and exits with $exitcode. -sub usage { - my ($exitcode) = @_; - $exitcode = 1 unless defined $exitcode; - print <<'EOF'; -pintos, a utility for running Pintos in a simulator -Usage: pintos [OPTION...] -- [ARGUMENT...] -where each OPTION is one of the following options - and each ARGUMENT is passed to Pintos kernel verbatim. -Simulator selection: - --bochs (default) Use Bochs as simulator - --qemu Use QEMU as simulator - --player Use VMware Player as simulator -Debugger selection: - --no-debug (default) No debugger - --monitor Debug with simulator's monitor - --gdb Debug with gdb -Display options: (default is both VGA and serial) - -v, --no-vga No VGA display or keyboard - -s, --no-serial No serial input or output - -t, --terminal Display VGA in terminal (Bochs only) -Timing options: (Bochs only) - -j SEED Randomize timer interrupts - -r, --realtime Use realistic, not reproducible, timings -Testing options: - -T, --timeout=N Kill Pintos after N seconds CPU time or N*load_avg - seconds wall-clock time (whichever comes first) - -k, --kill-on-failure Kill Pintos a few seconds after a kernel or user - panic, test failure, or triple fault -Configuration options: - -m, --mem=N Give Pintos N MB physical RAM (default: 4) -File system commands: - -p, --put-file=HOSTFN Copy HOSTFN into VM, by default under same name - -g, --get-file=GUESTFN Copy GUESTFN out of VM, by default under same name - -a, --as=FILENAME Specifies guest (for -p) or host (for -g) file name -Partition options: (where PARTITION is one of: kernel filesys scratch swap) - --PARTITION=FILE Use a copy of FILE for the given PARTITION - --PARTITION-size=SIZE Create an empty PARTITION of the given SIZE in MB - --PARTITION-from=DISK Use of a copy of the given PARTITION in DISK - (There is no --kernel-size, --scratch, or --scratch-from option.) -Disk configuration options: - --make-disk=DISK Name the new DISK and don't delete it after the run - --disk=DISK Also use existing DISK (may be used multiple times) -Advanced disk configuration options: - --loader=FILE Use FILE as bootstrap loader (default: loader.bin) - --geometry=H,S Use H head, S sector geometry (default: 16,63) - --geometry=zip Use 64 head, 32 sector geometry for USB-ZIP boot - (see http://syslinux.zytor.com/usbkey.php) - --align=bochs Pad out disk to cylinder to support Bochs (default) - --align=full Align partition boundaries to cylinder boundary to - let fdisk guess correct geometry and quiet warnings - --align=none Don't align partitions at all, to save space -Other options: - -h, --help Display this help message. -EOF - exit $exitcode; -} - -# Sets the simulator. -sub set_sim { - my ($new_sim) = @_; - die "--$new_sim conflicts with --$sim\n" - if defined ($sim) && $sim ne $new_sim; - $sim = $new_sim; -} - -# Sets the debugger. -sub set_debug { - my ($new_debug) = @_; - die "--$new_debug conflicts with --$debug\n" - if $debug ne 'none' && $new_debug ne 'none' && $debug ne $new_debug; - $debug = $new_debug; -} - -# Sets VGA output destination. -sub set_vga { - my ($new_vga) = @_; - if (defined ($vga) && $vga ne $new_vga) { - print "warning: conflicting vga display options\n"; - } - $vga = $new_vga; -} - -# Sets randomized timer interrupts. -sub set_jitter { - my ($new_jitter) = @_; - die "--realtime conflicts with --jitter\n" if defined $realtime; - die "different --jitter already defined\n" - if defined $jitter && $jitter != $new_jitter; - $jitter = $new_jitter; -} - -# Sets real-time timer interrupts. -sub set_realtime { - die "--realtime conflicts with --jitter\n" if defined $jitter; - $realtime = 1; -} - -# add_file(\@list, $file) -# -# Adds [$file] to @list, which should be @puts or @gets. -# Sets $as_ref to point to the added element. -sub add_file { - my ($list, $file) = @_; - $as_ref = [$file]; - push (@$list, $as_ref); -} - -# Sets the guest/host name for the previous put/get. -sub set_as { - my ($as) = @_; - die "-a (or --as) is only allowed after -p or -g\n" if !defined $as_ref; - die "Only one -a (or --as) is allowed after -p or -g\n" - if defined $as_ref->[1]; - $as_ref->[1] = $as; -} - -# Sets $disk as a disk to be included in the VM to run. -sub set_disk { - my ($disk) = @_; - - push (@disks, $disk); - - my (%pt) = read_partition_table ($disk); - for my $role (keys %pt) { - die "can't have two sources for \L$role\E partition" - if exists $parts{$role}; - $parts{$role}{DISK} = $disk; - $parts{$role}{START} = $pt{$role}{START}; - $parts{$role}{SECTORS} = $pt{$role}{SECTORS}; - } -} - -# Locates the files used to back each of the virtual disks, -# and creates temporary disks. -sub find_disks { - # Find kernel, if we don't already have one. - if (!exists $parts{KERNEL}) { - my $name = find_file ('kernel.bin'); - die "Cannot find kernel\n" if !defined $name; - do_set_part ('KERNEL', 'file', $name); - } - - # Try to find file system and swap disks, if we don't already have - # partitions. - if (!exists $parts{FILESYS}) { - my $name = find_file ('filesys.dsk'); - set_disk ($name) if defined $name; - } - if (!exists $parts{SWAP}) { - my $name = find_file ('swap.dsk'); - set_disk ($name) if defined $name; - } - - # Warn about (potentially) missing partitions. - if (my ($project) = `pwd` =~ /\b(threads|userprog|vm|filesys)\b/) { - if ((grep ($project eq $_, qw (userprog vm filesys))) - && !defined $parts{FILESYS}) { - print STDERR "warning: it looks like you're running the $project "; - print STDERR "project, but no file system partition is present\n"; - } - if ($project eq 'vm' && !defined $parts{SWAP}) { - print STDERR "warning: it looks like you're running the $project "; - print STDERR "project, but no swap partition is present\n"; - } - } - - # Open disk handle. - my ($handle); - if (!defined $make_disk) { - ($handle, $make_disk) = tempfile (UNLINK => $tmp_disk, - SUFFIX => '.dsk'); - } else { - die "$make_disk: already exists\n" if -e $make_disk; - open ($handle, '>', $make_disk) or die "$make_disk: create: $!\n"; - } - - # Prepare the arguments to pass to the Pintos kernel. - my (@args); - push (@args, shift (@kernel_args)) - while @kernel_args && $kernel_args[0] =~ /^-/; - push (@args, 'extract') if @puts; - push (@args, @kernel_args); - push (@args, 'append', $_->[0]) foreach @gets; - - # Make disk. - my (%disk); - our (@role_order); - for my $role (@role_order) { - my $p = $parts{$role}; - next if !defined $p; - next if exists $p->{DISK}; - $disk{$role} = $p; - } - $disk{DISK} = $make_disk; - $disk{HANDLE} = $handle; - $disk{ALIGN} = $align; - $disk{GEOMETRY} = %geometry; - $disk{FORMAT} = 'partitioned'; - $disk{LOADER} = read_loader ($loader_fn); - $disk{ARGS} = \@args; - assemble_disk (%disk); - - # Put the disk at the front of the list of disks. - unshift (@disks, $make_disk); - die "can't use more than " . scalar (@disks) . "disks\n" if @disks > 4; -} - -# Prepare the scratch disk for gets and puts. -sub prepare_scratch_disk { - return if !@gets && !@puts; - - my ($p) = $parts{SCRATCH}; - # Create temporary partition and write the files to put to it, - # then write an end-of-archive marker. - my ($part_handle, $part_fn) = tempfile (UNLINK => 1, SUFFIX => '.part'); - put_scratch_file ($_->[0], defined $_->[1] ? $_->[1] : $_->[0], - $part_handle, $part_fn) - foreach @puts; - write_fully ($part_handle, $part_fn, "\0" x 1024); - - # Make sure the scratch disk is big enough to get big files - # and at least as big as any requested size. - my ($size) = round_up (max (@gets * 1024 * 1024, $p->{BYTES} || 0), 512); - extend_file ($part_handle, $part_fn, $size); - close ($part_handle); - - if (exists $p->{DISK}) { - # Copy the scratch partition to the disk. - die "$p->{DISK}: scratch partition too small\n" - if $p->{SECTORS} * 512 < $size; - - my ($disk_handle); - open ($part_handle, '<', $part_fn) or die "$part_fn: open: $!\n"; - open ($disk_handle, '+<', $p->{DISK}) or die "$p->{DISK}: open: $!\n"; - my ($start) = $p->{START} * 512; - sysseek ($disk_handle, $start, SEEK_SET) == $start - or die "$p->{DISK}: seek: $!\n"; - copy_file ($part_handle, $part_fn, $disk_handle, $p->{DISK}, $size); - close ($disk_handle) or die "$p->{DISK}: close: $!\n"; - close ($part_handle) or die "$part_fn: close: $!\n"; - } else { - # Set $part_fn as the source for the scratch partition. - do_set_part ('SCRATCH', 'file', $part_fn); - } -} - -# Read "get" files from the scratch disk. -sub finish_scratch_disk { - return if !@gets; - - # Open scratch partition. - my ($p) = $parts{SCRATCH}; - my ($part_handle); - my ($part_fn) = $p->{DISK}; - open ($part_handle, '<', $part_fn) or die "$part_fn: open: $!\n"; - sysseek ($part_handle, $p->{START} * 512, SEEK_SET) == $p->{START} * 512 - or die "$part_fn: seek: $!\n"; - - # Read each file. - # If reading fails, delete that file and all subsequent files, but - # don't die with an error, because that's a guest error not a host - # error. (If we do exit with an error code, it fouls up the - # grading process.) Instead, just make sure that the host file(s) - # we were supposed to retrieve is unlinked. - my ($ok) = 1; - my ($part_end) = ($p->{START} + $p->{SECTORS}) * 512; - foreach my $get (@gets) { - my ($name) = defined ($get->[1]) ? $get->[1] : $get->[0]; - if ($ok) { - my ($error) = get_scratch_file ($name, $part_handle, $part_fn); - if (!$error && sysseek ($part_handle, 0, SEEK_CUR) > $part_end) { - $error = "$part_fn: scratch data overflows partition"; - } - if ($error) { - print STDERR "getting $name failed ($error)\n"; - $ok = 0; - } - } - die "$name: unlink: $!\n" if !$ok && !unlink ($name) && !$!{ENOENT}; - } -} - -# mk_ustar_field($number, $size) -# -# Returns $number in a $size-byte numeric field in the format used by -# the standard ustar archive header. -sub mk_ustar_field { - my ($number, $size) = @_; - my ($len) = $size - 1; - my ($out) = sprintf ("%0${len}o", $number) . "\0"; - die "$number: too large for $size-byte octal ustar field\n" - if length ($out) != $size; - return $out; -} - -# calc_ustar_chksum($s) -# -# Calculates and returns the ustar checksum of 512-byte ustar archive -# header $s. -sub calc_ustar_chksum { - my ($s) = @_; - die if length ($s) != 512; - substr ($s, 148, 8, ' ' x 8); - return unpack ("%32a*", $s); -} - -# put_scratch_file($src_file_name, $dst_file_name, -# $disk_handle, $disk_file_name). -# -# Copies $src_file_name into $disk_handle for extraction as -# $dst_file_name. $disk_file_name is used for error messages. -sub put_scratch_file { - my ($src_file_name, $dst_file_name, $disk_handle, $disk_file_name) = @_; - - print "Copying $src_file_name to scratch partition...\n"; - - # ustar format supports up to 100 characters for a file name, and - # even longer names given some common properties, but our code in - # the Pintos kernel only supports at most 99 characters. - die "$dst_file_name: name too long (max 99 characters)\n" - if length ($dst_file_name) > 99; - - # Compose and write ustar header. - stat $src_file_name or die "$src_file_name: stat: $!\n"; - my ($size) = -s _; - my ($header) = (pack ("a100", $dst_file_name) # name - . mk_ustar_field (0644, 8) # mode - . mk_ustar_field (0, 8) # uid - . mk_ustar_field (0, 8) # gid - . mk_ustar_field ($size, 12) # size - . mk_ustar_field (1136102400, 12) # mtime - . (' ' x 8) # chksum - . '0' # typeflag - . ("\0" x 100) # linkname - . "ustar\0" # magic - . "00" # version - . "root" . ("\0" x 28) # uname - . "root" . ("\0" x 28) # gname - . "\0" x 8 # devmajor - . "\0" x 8 # devminor - . ("\0" x 155)) # prefix - . "\0" x 12; # pad to 512 bytes - substr ($header, 148, 8) = mk_ustar_field (calc_ustar_chksum ($header), 8); - write_fully ($disk_handle, $disk_file_name, $header); - - # Copy file data. - my ($put_handle); - sysopen ($put_handle, $src_file_name, O_RDONLY) - or die "$src_file_name: open: $!\n"; - copy_file ($put_handle, $src_file_name, $disk_handle, $disk_file_name, - $size); - die "$src_file_name: changed size while being read\n" - if $size != -s $put_handle; - close ($put_handle); - - # Round up disk data to beginning of next sector. - write_fully ($disk_handle, $disk_file_name, "\0" x (512 - $size % 512)) - if $size % 512; -} - -# get_scratch_file($get_file_name, $disk_handle, $disk_file_name) -# -# Copies from $disk_handle to $get_file_name (which is created). -# $disk_file_name is used for error messages. -# Returns 1 if successful, 0 on failure. -sub get_scratch_file { - my ($get_file_name, $disk_handle, $disk_file_name) = @_; - - print "Copying $get_file_name out of $disk_file_name...\n"; - - # Read ustar header sector. - my ($header) = read_fully ($disk_handle, $disk_file_name, 512); - return "scratch disk tar archive ends unexpectedly" - if $header eq ("\0" x 512); - - # Verify magic numbers. - return "corrupt ustar signature" if substr ($header, 257, 6) ne "ustar\0"; - return "invalid ustar version" if substr ($header, 263, 2) ne '00'; - - # Verify checksum. - my ($chksum) = oct (unpack ("Z*", substr ($header, 148, 8))); - my ($correct_chksum) = calc_ustar_chksum ($header); - return "checksum mismatch" if $chksum != $correct_chksum; - - # Get type. - my ($typeflag) = substr ($header, 156, 1); - return "not a regular file" if $typeflag ne '0' && $typeflag ne "\0"; - - # Get size. - my ($size) = oct (unpack ("Z*", substr ($header, 124, 12))); - return "bad size $size\n" if $size < 0; - - # Copy file data. - my ($get_handle); - sysopen ($get_handle, $get_file_name, O_WRONLY | O_CREAT, 0666) - or die "$get_file_name: create: $!\n"; - copy_file ($disk_handle, $disk_file_name, $get_handle, $get_file_name, - $size); - close ($get_handle); - - # Skip forward in disk up to beginning of next sector. - read_fully ($disk_handle, $disk_file_name, 512 - $size % 512) - if $size % 512; - - return 0; -} - -# Running simulators. - -# Runs the selected simulator. -sub run_vm { - if ($sim eq 'bochs') { - run_bochs (); - } elsif ($sim eq 'qemu') { - run_qemu (); - } elsif ($sim eq 'player') { - run_player (); - } else { - die "unknown simulator `$sim'\n"; - } -} - -# Runs Bochs. -sub run_bochs { - # Select Bochs binary based on the chosen debugger. - my ($bin) = $debug eq 'monitor' ? 'bochs-dbg' : 'bochs'; - - my ($squish_pty); - if ($serial) { - $squish_pty = find_in_path ("squish-pty"); - print "warning: can't find squish-pty, so terminal input will fail\n" - if !defined $squish_pty; - } - - # Write bochsrc.txt configuration file. - open (BOCHSRC, ">", "bochsrc.txt") or die "bochsrc.txt: create: $!\n"; - print BOCHSRC <<EOF; -romimage: file=\$BXSHARE/BIOS-bochs-latest -vgaromimage: file=\$BXSHARE/VGABIOS-lgpl-latest -boot: disk -cpu: ips=1000000 -megs: $mem -log: bochsout.txt -panic: action=fatal -user_shortcut: keys=ctrlaltdel -EOF - print BOCHSRC "gdbstub: enabled=1\n" if $debug eq 'gdb'; - print BOCHSRC "clock: sync=", $realtime ? 'realtime' : 'none', - ", time0=0\n"; - print BOCHSRC "ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15\n" - if @disks > 2; - print_bochs_disk_line ("ata0-master", $disks[0]); - print_bochs_disk_line ("ata0-slave", $disks[1]); - print_bochs_disk_line ("ata1-master", $disks[2]); - print_bochs_disk_line ("ata1-slave", $disks[3]); - if ($vga ne 'terminal') { - if ($serial) { - my $mode = defined ($squish_pty) ? "term" : "file"; - print BOCHSRC "com1: enabled=1, mode=$mode, dev=/dev/stdout\n"; - } - print BOCHSRC "display_library: nogui\n" if $vga eq 'none'; - } else { - print BOCHSRC "display_library: term\n"; - } - close (BOCHSRC); - - # Compose Bochs command line. - my (@cmd) = ($bin, '-q'); - unshift (@cmd, $squish_pty) if defined $squish_pty; - push (@cmd, '-j', $jitter) if defined $jitter; - - # Run Bochs. - print join (' ', @cmd), "\n"; - my ($exit) = xsystem (@cmd); - if (WIFEXITED ($exit)) { - # Bochs exited normally. - # Ignore the exit code; Bochs normally exits with status 1, - # which is weird. - } elsif (WIFSIGNALED ($exit)) { - die "Bochs died with signal ", WTERMSIG ($exit), "\n"; - } else { - die "Bochs died: code $exit\n"; - } -} - -sub print_bochs_disk_line { - my ($device, $disk) = @_; - if (defined $disk) { - my (%geom) = disk_geometry ($disk); - print BOCHSRC "$device: type=disk, path=$disk, mode=flat, "; - print BOCHSRC "cylinders=$geom{C}, heads=$geom{H}, spt=$geom{S}, "; - print BOCHSRC "translation=none\n"; - } -} - -# Runs QEMU. -sub run_qemu { - print "warning: qemu doesn't support --terminal\n" - if $vga eq 'terminal'; - print "warning: qemu doesn't support jitter\n" - if defined $jitter; - my (@cmd) = ('qemu-system-i386'); - push (@cmd, '-device', 'isa-debug-exit'); - push (@cmd, '-hda', $disks[0]) if defined $disks[0]; - push (@cmd, '-hdb', $disks[1]) if defined $disks[1]; - push (@cmd, '-hdc', $disks[2]) if defined $disks[2]; - push (@cmd, '-hdd', $disks[3]) if defined $disks[3]; - push (@cmd, '-m', $mem); - push (@cmd, '-net', 'none'); - push (@cmd, '-nographic') if $vga eq 'none'; - push (@cmd, '-serial', 'stdio') if $serial && $vga ne 'none'; - push (@cmd, '-S') if $debug eq 'monitor'; - push (@cmd, '-s', '-S') if $debug eq 'gdb'; - push (@cmd, '-monitor', 'null') if $vga eq 'none' && $debug eq 'none'; - run_command (@cmd); -} - -# player_unsup($flag) -# -# Prints a message that $flag is unsupported by VMware Player. -sub player_unsup { - my ($flag) = @_; - print "warning: no support for $flag with VMware Player\n"; -} - -# Runs VMware Player. -sub run_player { - player_unsup ("--$debug") if $debug ne 'none'; - player_unsup ("--no-vga") if $vga eq 'none'; - player_unsup ("--terminal") if $vga eq 'terminal'; - player_unsup ("--jitter") if defined $jitter; - player_unsup ("--timeout"), undef $timeout if defined $timeout; - player_unsup ("--kill-on-failure"), undef $kill_on_failure - if defined $kill_on_failure; - - $mem = round_up ($mem, 4); # Memory must be multiple of 4 MB. - - open (VMX, ">", "pintos.vmx") or die "pintos.vmx: create: $!\n"; - chmod 0777 & ~umask, "pintos.vmx"; - print VMX <<EOF; -#! /usr/bin/vmware -G -config.version = 8 -guestOS = "linux" -memsize = $mem -floppy0.present = FALSE -usb.present = FALSE -sound.present = FALSE -gui.exitAtPowerOff = TRUE -gui.exitOnCLIHLT = TRUE -gui.powerOnAtStartUp = TRUE -EOF - - print VMX <<EOF if $serial; -serial0.present = TRUE -serial0.fileType = "pipe" -serial0.fileName = "pintos.socket" -serial0.pipe.endPoint = "client" -serial0.tryNoRxLoss = "TRUE" -EOF - - for (my ($i) = 0; $i < 4; $i++) { - my ($dsk) = $disks[$i]; - last if !defined $dsk; - - my ($device) = "ide" . int ($i / 2) . ":" . ($i % 2); - my ($pln) = "$device.pln"; - print VMX <<EOF; - -$device.present = TRUE -$device.deviceType = "plainDisk" -$device.fileName = "$pln" -EOF - - open (URANDOM, '<', '/dev/urandom') or die "/dev/urandom: open: $!\n"; - my ($bytes); - sysread (URANDOM, $bytes, 4) == 4 or die "/dev/urandom: read: $!\n"; - close (URANDOM); - my ($cid) = unpack ("L", $bytes); - - my (%geom) = disk_geometry ($dsk); - open (PLN, ">", $pln) or die "$pln: create: $!\n"; - print PLN <<EOF; -version=1 -CID=$cid -parentCID=ffffffff -createType="monolithicFlat" - -RW $geom{CAPACITY} FLAT "$dsk" 0 - -# The Disk Data Base -#DDB - -ddb.adapterType = "ide" -ddb.virtualHWVersion = "4" -ddb.toolsVersion = "2" -ddb.geometry.cylinders = "$geom{C}" -ddb.geometry.heads = "$geom{H}" -ddb.geometry.sectors = "$geom{S}" -EOF - close (PLN); - } - close (VMX); - - my ($squish_unix); - if ($serial) { - $squish_unix = find_in_path ("squish-unix"); - print "warning: can't find squish-unix, so terminal input ", - "and output will fail\n" if !defined $squish_unix; - } - - my ($vmx) = getcwd () . "/pintos.vmx"; - my (@cmd) = ("vmplayer", $vmx); - unshift (@cmd, $squish_unix, "pintos.socket") if $squish_unix; - print join (' ', @cmd), "\n"; - xsystem (@cmd); -} - -# Disk utilities. - -sub extend_file { - my ($handle, $file_name, $size) = @_; - if (-s ($handle) < $size) { - sysseek ($handle, $size - 1, 0) == $size - 1 - or die "$file_name: seek: $!\n"; - syswrite ($handle, "\0") == 1 - or die "$file_name: write: $!\n"; - } -} - -# disk_geometry($file) -# -# Examines $file and returns a valid IDE disk geometry for it, as a -# hash. -sub disk_geometry { - my ($file) = @_; - my ($size) = -s $file; - die "$file: stat: $!\n" if !defined $size; - die "$file: size $size not a multiple of 512 bytes\n" if $size % 512; - my ($cyl_size) = 512 * 16 * 63; - my ($cylinders) = ceil ($size / $cyl_size); - - return (CAPACITY => $size / 512, - C => $cylinders, - H => 16, - S => 63); -} - -# Subprocess utilities. - -# run_command(@args) -# -# Runs xsystem(@args). -# Also prints the command it's running and checks that it succeeded. -sub run_command { - print join (' ', @_), "\n"; - die "command failed\n" if xsystem (@_); -} - -# xsystem(@args) -# -# Creates a subprocess via exec(@args) and waits for it to complete. -# Relays common signals to the subprocess. -# If $timeout is set then the subprocess will be killed after that long. -sub xsystem { - # QEMU turns off local echo and does not restore it if killed by a signal. - # We compensate by restoring it ourselves. - my $cleanup = sub {}; - if (isatty (0)) { - my $termios = POSIX::Termios->new; - $termios->getattr (0); - $cleanup = sub { $termios->setattr (0, &POSIX::TCSANOW); } - } - - # Create pipe for filtering output. - pipe (my $in, my $out) or die "pipe: $!\n" if $kill_on_failure; - - my ($pid) = fork; - if (!defined ($pid)) { - # Fork failed. - die "fork: $!\n"; - } elsif (!$pid) { - # Running in child process. - dup2 (fileno ($out), STDOUT_FILENO) or die "dup2: $!\n" - if $kill_on_failure; - exec_setitimer (@_); - } else { - # Running in parent process. - close $out if $kill_on_failure; - - my ($cause); - local $SIG{ALRM} = sub { timeout ($pid, $cause, $cleanup); }; - local $SIG{INT} = sub { relay_signal ($pid, "INT", $cleanup); }; - local $SIG{TERM} = sub { relay_signal ($pid, "TERM", $cleanup); }; - alarm ($timeout * get_load_average () + 1) if defined ($timeout); - - if ($kill_on_failure) { - # Filter output. - my ($buf) = ""; - my ($boots) = 0; - local ($|) = 1; - for (;;) { - if (waitpid ($pid, WNOHANG) != 0) { - # Subprocess died. Pass through any remaining data. - do { print $buf } while sysread ($in, $buf, 4096) > 0; - last; - } - - # Read and print out pipe data. - my ($len) = length ($buf); - waitpid ($pid, 0), last - if sysread ($in, $buf, 4096, $len) <= 0; - print substr ($buf, $len); - - # Remove full lines from $buf and scan them for keywords. - while ((my $idx = index ($buf, "\n")) >= 0) { - local $_ = substr ($buf, 0, $idx + 1, ''); - next if defined ($cause); - if (/(Kernel PANIC|User process ABORT)/ ) { - $cause = "\L$1\E"; - alarm (5); - } elsif (/Pintos booting/ && ++$boots > 1) { - $cause = "triple fault"; - alarm (5); - } elsif (/FAILED/) { - $cause = "test failure"; - alarm (5); - } - } - } - } else { - waitpid ($pid, 0); - } - alarm (0); - &$cleanup (); - - if (WIFSIGNALED ($?) && WTERMSIG ($?) == SIGVTALRM ()) { - seek (STDOUT, 0, 2); - print "\nTIMEOUT after $timeout seconds of host CPU time\n"; - exit 0; - } - - # Kind of a gross hack, because qemu's isa-debug-exit device - # only allows odd-numbered exit values, so we can't exit - # cleanly with 0. We use exit status 0x63 as an alternate - # "clean" exit status. - return ($? != 0x6300) && $?; - } -} - -# relay_signal($pid, $signal, &$cleanup) -# -# Relays $signal to $pid and then reinvokes it for us with the default -# handler. Also cleans up temporary files and invokes $cleanup. -sub relay_signal { - my ($pid, $signal, $cleanup) = @_; - kill $signal, $pid; - eval { File::Temp::cleanup() }; # Not defined in old File::Temp. - &$cleanup (); - $SIG{$signal} = 'DEFAULT'; - kill $signal, getpid (); -} - -# timeout($pid, $cause, &$cleanup) -# -# Interrupts $pid and dies with a timeout error message, -# after invoking $cleanup. -sub timeout { - my ($pid, $cause, $cleanup) = @_; - kill "INT", $pid; - waitpid ($pid, 0); - &$cleanup (); - seek (STDOUT, 0, 2); - if (!defined ($cause)) { - my ($load_avg) = `uptime` =~ /(load average:.*)$/i; - print "\nTIMEOUT after ", time () - $start_time, - " seconds of wall-clock time"; - print " - $load_avg" if defined $load_avg; - print "\n"; - } else { - print "Simulation terminated due to $cause.\n"; - } - exit 0; -} - -# Returns the system load average over the last minute. -# If the load average is less than 1.0 or cannot be determined, returns 1.0. -sub get_load_average { - my ($avg) = `uptime` =~ /load average:\s*([^,]+),/; - return $avg >= 1.0 ? $avg : 1.0; -} - -# Calls setitimer to set a timeout, then execs what was passed to us. -sub exec_setitimer { - if (defined $timeout) { - if (${"\cV"} ge 5.8.0) { - eval " - use Time::HiRes qw(setitimer ITIMER_VIRTUAL); - setitimer (ITIMER_VIRTUAL, $timeout, 0); - "; - } else { - { exec ("setitimer-helper", $timeout, @_); }; - exit 1 if !$!{ENOENT}; - print STDERR "warning: setitimer-helper is not installed, so ", - "CPU time limit will not be enforced\n"; - } - } - exec (@_); - exit (1); -} - -sub SIGVTALRM { - use Config; - my $i = 0; - foreach my $name (split(' ', $Config{sig_name})) { - return $i if $name eq 'VTALRM'; - $i++; - } - return 0; -} - -# find_in_path ($program) -# -# Searches for $program in $ENV{PATH}. -# Returns $program if found, otherwise undef. -sub find_in_path { - my ($program) = @_; - -x "$_/$program" and return $program foreach split (':', $ENV{PATH}); - return; -} diff --git a/src/utils/pintos-gdb b/src/utils/pintos-gdb deleted file mode 100755 index 4ef38d3f177f1c9b694d422c14efdd2df98809d9..0000000000000000000000000000000000000000 --- a/src/utils/pintos-gdb +++ /dev/null @@ -1,20 +0,0 @@ -#! /bin/sh - -# Path to GDB macros file. Customize for your site. -GDBMACROS=/usr/class/cs140/pintos/pintos/src/misc/gdb-macros - -# Choose correct GDB. -if command -v i386-elf-gdb >/dev/null 2>&1; then - GDB=i386-elf-gdb -else - GDB=gdb -fi - -# Run GDB. -if test -f "$GDBMACROS"; then - exec $GDB -x "$GDBMACROS" "$@" -else - echo "*** $GDBMACROS does not exist ***" - echo "*** Pintos GDB macros will not be available ***" - exec $GDB "$@" -fi diff --git a/src/utils/pintos-mkdisk b/src/utils/pintos-mkdisk deleted file mode 100755 index 87b1563e69c517070e81ad32c36adfabdf6df2a5..0000000000000000000000000000000000000000 --- a/src/utils/pintos-mkdisk +++ /dev/null @@ -1,134 +0,0 @@ -#! /usr/bin/perl - -use strict; -use warnings; -use POSIX; -use Getopt::Long qw(:config bundling); -use Fcntl 'SEEK_SET'; - -# Read Pintos.pm from the same directory as this program. -BEGIN { my $self = $0; $self =~ s%/+[^/]*$%%; require "$self/Pintos.pm"; } - -our ($disk_fn); # Output disk file name. -our (%parts); # Partitions. -our ($format); # "partitioned" (default) or "raw" -our (%geometry); # IDE disk geometry. -our ($align); # Align partitions on cylinders? -our ($loader_fn); # File name of loader. -our ($include_loader); # Include loader? -our (@kernel_args); # Kernel arguments. - -if (grep ($_ eq '--', @ARGV)) { - @kernel_args = @ARGV; - @ARGV = (); - while ((my $arg = shift (@kernel_args)) ne '--') { - push (@ARGV, $arg); - } -} - -GetOptions ("h|help" => sub { usage (0); }, - - "kernel=s" => \&set_part, - "filesys=s" => \&set_part, - "scratch=s" => \&set_part, - "swap=s" => \&set_part, - - "filesys-size=s" => \&set_part, - "scratch-size=s" => \&set_part, - "swap-size=s" => \&set_part, - - "kernel-from=s" => \&set_part, - "filesys-from=s" => \&set_part, - "scratch-from=s" => \&set_part, - "swap-from=s" => \&set_part, - - "format=s" => \$format, - "loader:s" => \&set_loader, - "no-loader" => \&set_no_loader, - "geometry=s" => \&set_geometry, - "align=s" => \&set_align) - or exit 1; -usage (1) if @ARGV != 1; - -$disk_fn = $ARGV[0]; -die "$disk_fn: already exists\n" if -e $disk_fn; - -# Sets the loader to copy to the MBR. -sub set_loader { - die "can't specify both --loader and --no-loader\n" - if defined ($include_loader) && !$include_loader; - $include_loader = 1; - $loader_fn = $_[1] if $_[1] ne ''; -} - -# Disables copying a loader to the MBR. -sub set_no_loader { - die "can't specify both --loader and --no-loader\n" - if defined ($include_loader) && $include_loader; - $include_loader = 0; -} - -# Figure out whether to include a loader. -$include_loader = exists ($parts{KERNEL}) && $format eq 'partitioned' - if !defined ($include_loader); -die "can't write loader to raw disk\n" if $include_loader && $format eq 'raw'; -die "can't write command-line arguments without --loader or --kernel\n" - if @kernel_args && !$include_loader; -print STDERR "warning: --loader only makes sense without --kernel " - . "if this disk will be used to load a kernel from another disk\n" - if $include_loader && !exists ($parts{KERNEL}); - -# Open disk. -my ($disk_handle); -open ($disk_handle, '>', $disk_fn) or die "$disk_fn: create: $!\n"; - -# Read loader. -my ($loader); -$loader = read_loader ($loader_fn) if $include_loader; - -# Write disk. -my (%disk) = %parts; -$disk{DISK} = $disk_fn; -$disk{HANDLE} = $disk_handle; -$disk{ALIGN} = $align; -$disk{GEOMETRY} = %geometry; -$disk{FORMAT} = $format; -$disk{LOADER} = $loader; -$disk{ARGS} = \@kernel_args; -assemble_disk (%disk); - -# Done. -exit 0; - -sub usage { - print <<'EOF'; -pintos-mkdisk, a utility for creating Pintos virtual disks -Usage: pintos-mkdisk [OPTIONS] DISK [-- ARGUMENT...] -where DISK is the virtual disk to create, - each ARGUMENT is inserted into the command line written to DISK, - and each OPTION is one of the following options. -Partition options: (where PARTITION is one of: kernel filesys scratch swap) - --PARTITION=FILE Use a copy of FILE for the given PARTITION - --PARTITION-size=SIZE Create an empty PARTITION of the given SIZE in MB - --PARTITION-from=DISK Use of a copy of the given PARTITION in DISK - (There is no --kernel-size option.) -Output disk options: - --format=partitioned Write partition table to output (default) - --format=raw Do not write partition table to output - (Pintos can only use partitioned disks.) -Partitioned format output options: - --loader[=FILE] Get bootstrap loader from FILE (default: loader.bin - if --kernel option is specified, empty otherwise) - --no-loader Do not include a bootstrap loader - --geometry=H,S Use H head, S sector geometry (default: 16, 63) - --geometry=zip Use 64 head, 32 sector geometry for USB-ZIP boot - per http://syslinux.zytor.com/usbkey.php - --align=bochs Round size to cylinder for Bochs support (default) - --align=full Align partition boundaries to cylinder boundary to - let fdisk guess correct geometry and quiet warnings - --align=none Don't align partitions at all, to save space -Other options: - -h, --help Display this help message. -EOF - exit ($_[0]); -} diff --git a/src/utils/pintos-set-cmdline b/src/utils/pintos-set-cmdline deleted file mode 100644 index 8c8f702435ba718786f662b3ceda5b2a1bd7519e..0000000000000000000000000000000000000000 --- a/src/utils/pintos-set-cmdline +++ /dev/null @@ -1,42 +0,0 @@ -#! /usr/bin/perl -w - -use strict; -use Fcntl 'SEEK_SET'; - -# Read Pintos.pm from the same directory as this program. -BEGIN { my $self = $0; $self =~ s%/+[^/]*$%%; require "$self/Pintos.pm"; } - -# Get command-line arguments. -usage (0) if @ARGV == 1 && $ARGV[0] eq '--help'; -usage (1) if @ARGV < 2 || $ARGV[1] ne '--'; -my ($disk, undef, @kernel_args) = @ARGV; - -# Open disk. -my ($handle); -open ($handle, '+<', $disk) or die "$disk: open: $!\n"; - -# Check that it's a partitioned disk with a Pintos loader. -my ($buffer) = read_fully ($handle, $disk, 512); -unpack ("x510 v", $buffer) == 0xaa55 or die "$disk: not a partitioned disk\n"; -$buffer =~ /Pintos/ or die "$disk: does not contain Pintos loader\n"; - -# Write the command line. -our ($LOADER_SIZE); -sysseek ($handle, $LOADER_SIZE, SEEK_SET) == $LOADER_SIZE - or die "$disk: seek: $!\n"; -write_fully ($handle, $disk, make_kernel_command_line (@kernel_args)); - -# Close disk. -close ($handle) or die "$disk: close: $!\n"; - -exit 0; - -sub usage { - print <<'EOF'; -pintos-set-cmdline, a utility for changing the command line in Pintos disks -Usage: pintos-set-cmdline DISK -- [ARGUMENT...] -where DISK is a bootable disk containing a Pintos loader - and each ARGUMENT is inserted into the command line written to DISK. -EOF - exit ($_[0]); -} diff --git a/src/utils/setitimer-helper.c b/src/utils/setitimer-helper.c deleted file mode 100644 index 772d736a26057ff095581a41c6b320e96b30a80f..0000000000000000000000000000000000000000 --- a/src/utils/setitimer-helper.c +++ /dev/null @@ -1,49 +0,0 @@ -#include <errno.h> -#include <limits.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/time.h> -#include <unistd.h> - -int -main (int argc, char *argv[]) -{ - const char *program_name = argv[0]; - double timeout; - - if (argc < 3) - { - fprintf (stderr, - "setitimer-helper: runs a program with a virtual CPU limit\n" - "usage: %s TIMEOUT PROGRAM [ARG...]\n" - " where TIMEOUT is the virtual CPU limit, in seconds,\n" - " and remaining arguments specify the program to run\n" - " and its argument.\n", - program_name); - return EXIT_FAILURE; - } - - timeout = strtod (argv[1], NULL); - if (timeout >= 0.0 && timeout < LONG_MAX) - { - struct itimerval it; - - it.it_interval.tv_sec = 0; - it.it_interval.tv_usec = 0; - it.it_value.tv_sec = timeout; - it.it_value.tv_usec = (timeout - floor (timeout)) * 1000000; - if (setitimer (ITIMER_VIRTUAL, &it, NULL) < 0) - fprintf (stderr, "%s: setitimer: %s\n", - program_name, strerror (errno)); - } - else - fprintf (stderr, "%s: invalid timeout value \"%s\"\n", - program_name, argv[1]); - - execvp (argv[2], &argv[2]); - fprintf (stderr, "%s: couldn't exec \"%s\": %s\n", - program_name, argv[2], strerror (errno)); - return EXIT_FAILURE; -} diff --git a/src/utils/squish-pty.c b/src/utils/squish-pty.c deleted file mode 100644 index e81043db68ddb13940cb3d311a7c352d7f8993a5..0000000000000000000000000000000000000000 --- a/src/utils/squish-pty.c +++ /dev/null @@ -1,351 +0,0 @@ -#define _GNU_SOURCE 1 -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stropts.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <termios.h> -#include <unistd.h> - -static void -fail_io (const char *msg, ...) - __attribute__ ((noreturn)) - __attribute__ ((format (printf, 1, 2))); - -/* Prints MSG, formatting as with printf(), - plus an error message based on errno, - and exits. */ -static void -fail_io (const char *msg, ...) -{ - va_list args; - - va_start (args, msg); - vfprintf (stderr, msg, args); - va_end (args); - - if (errno != 0) - fprintf (stderr, ": %s", strerror (errno)); - putc ('\n', stderr); - exit (EXIT_FAILURE); -} - -/* If FD is a terminal, configures it for noncanonical input mode - with VMIN and VTIME set as indicated. - If FD is not a terminal, has no effect. */ -static void -make_noncanon (int fd, int vmin, int vtime) -{ - if (isatty (fd)) - { - struct termios termios; - if (tcgetattr (fd, &termios) < 0) - fail_io ("tcgetattr"); - termios.c_lflag &= ~(ICANON | ECHO); - termios.c_cc[VMIN] = vmin; - termios.c_cc[VTIME] = vtime; - if (tcsetattr (fd, TCSANOW, &termios) < 0) - fail_io ("tcsetattr"); - } -} - -/* Make FD non-blocking if NONBLOCKING is true, - or blocking if NONBLOCKING is false. */ -static void -make_nonblocking (int fd, bool nonblocking) -{ - int flags = fcntl (fd, F_GETFL); - if (flags < 0) - fail_io ("fcntl"); - if (nonblocking) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - if (fcntl (fd, F_SETFL, flags) < 0) - fail_io ("fcntl"); -} - -/* Handle a read or write on *FD, which is the pty if FD_IS_PTY - is true, that returned end-of-file or error indication RETVAL. - The system call is named CALL, for use in error messages. - Sets *FD to -1 if the fd is no longer readable or writable. */ -static void -handle_error (ssize_t retval, int *fd, bool fd_is_pty, const char *call) -{ - if (fd_is_pty) - { - if (retval < 0) - { - if (errno == EIO) - { - /* Slave side of pty has been closed. */ - *fd = -1; - } - else - fail_io (call); - } - } - else - { - if (retval == 0) - { - close (*fd); - *fd = -1; - } - else - fail_io (call); - } -} - -/* Copies data from stdin to PTY and from PTY to stdout until no - more data can be read or written. */ -static void -relay (int pty, int dead_child_fd) -{ - struct pipe - { - int in, out; - char buf[BUFSIZ]; - size_t size, ofs; - bool active; - }; - struct pipe pipes[2]; - - /* Make PTY, stdin, and stdout non-blocking. */ - make_nonblocking (pty, true); - make_nonblocking (STDIN_FILENO, true); - make_nonblocking (STDOUT_FILENO, true); - - /* Configure noncanonical mode on PTY and stdin to avoid - waiting for end-of-line. We want to minimize context - switching on PTY (for efficiency) and minimize latency on - stdin to avoid a laggy user experience. */ - make_noncanon (pty, 16, 1); - make_noncanon (STDIN_FILENO, 1, 0); - - memset (pipes, 0, sizeof pipes); - pipes[0].in = STDIN_FILENO; - pipes[0].out = pty; - pipes[1].in = pty; - pipes[1].out = STDOUT_FILENO; - - while (pipes[1].in != -1) - { - fd_set read_fds, write_fds; - int retval; - int i; - - FD_ZERO (&read_fds); - FD_ZERO (&write_fds); - for (i = 0; i < 2; i++) - { - struct pipe *p = &pipes[i]; - - /* Don't do anything with the stdin->pty pipe until we - have some data for the pty->stdout pipe. If we get - too eager, Bochs will throw away our input. */ - if (i == 0 && !pipes[1].active) - continue; - - if (p->in != -1 && p->size + p->ofs < sizeof p->buf) - FD_SET (p->in, &read_fds); - if (p->out != -1 && p->size > 0) - FD_SET (p->out, &write_fds); - } - FD_SET (dead_child_fd, &read_fds); - - do - { - retval = select (FD_SETSIZE, &read_fds, &write_fds, NULL, NULL); - } - while (retval < 0 && errno == EINTR); - if (retval < 0) - fail_io ("select"); - - if (FD_ISSET (dead_child_fd, &read_fds)) - break; - - for (i = 0; i < 2; i++) - { - struct pipe *p = &pipes[i]; - if (p->in != -1 && FD_ISSET (p->in, &read_fds)) - { - ssize_t n = read (p->in, p->buf + p->ofs + p->size, - sizeof p->buf - p->ofs - p->size); - if (n > 0) - { - p->active = true; - p->size += n; - if (p->size == BUFSIZ && p->ofs != 0) - { - memmove (p->buf, p->buf + p->ofs, p->size); - p->ofs = 0; - } - } - else - handle_error (n, &p->in, p->in == pty, "read"); - } - if (p->out != -1 && FD_ISSET (p->out, &write_fds)) - { - ssize_t n = write (p->out, p->buf + p->ofs, p->size); - if (n > 0) - { - p->ofs += n; - p->size -= n; - if (p->size == 0) - p->ofs = 0; - } - else - handle_error (n, &p->out, p->out == pty, "write"); - } - } - } - - if (pipes[1].out == -1) - return; - - make_nonblocking (STDOUT_FILENO, false); - for (;;) - { - struct pipe *p = &pipes[1]; - ssize_t n; - - /* Write buffer. */ - while (p->size > 0) - { - n = write (p->out, p->buf + p->ofs, p->size); - if (n < 0) - fail_io ("write"); - else if (n == 0) - fail_io ("zero-length write"); - p->ofs += n; - p->size -= n; - } - p->ofs = 0; - - p->size = n = read (p->in, p->buf, sizeof p->buf); - if (n <= 0) - return; - } -} - -static int dead_child_fd; - -static void -sigchld_handler (int signo __attribute__ ((unused))) -{ - if (write (dead_child_fd, "", 1) < 0) - _exit (1); -} - -int -main (int argc __attribute__ ((unused)), char *argv[]) -{ - int master, slave; - char *name; - pid_t pid; - struct sigaction sa; - int pipe_fds[2]; - struct itimerval zero_itimerval, old_itimerval; - - if (argc < 2) - { - fprintf (stderr, - "usage: squish-pty COMMAND [ARG]...\n" - "Squishes both stdin and stdout into a single pseudoterminal,\n" - "which is passed as stdout to run the specified COMMAND.\n"); - return EXIT_FAILURE; - } - - /* Open master side of pty and get ready to open slave. */ - master = open ("/dev/ptmx", O_RDWR | O_NOCTTY); - if (master < 0) - fail_io ("open \"/dev/ptmx\""); - if (grantpt (master) < 0) - fail_io ("grantpt"); - if (unlockpt (master) < 0) - fail_io ("unlockpt"); - - /* Open slave side of pty. */ - name = ptsname (master); - if (name == NULL) - fail_io ("ptsname"); - slave = open (name, O_RDWR); - if (slave < 0) - fail_io ("open \"%s\"", name); - - /* System V implementations need STREAMS configuration for the - slave. */ - if (isastream (slave)) - { - if (ioctl (slave, I_PUSH, "ptem") < 0 - || ioctl (slave, I_PUSH, "ldterm") < 0) - fail_io ("ioctl"); - } - - /* Arrange to get notified when a child dies, by writing a byte - to a pipe fd. We really want to use pselect() and - sigprocmask(), but Solaris 2.7 doesn't have it. */ - if (pipe (pipe_fds) < 0) - fail_io ("pipe"); - dead_child_fd = pipe_fds[1]; - - memset (&sa, 0, sizeof sa); - sa.sa_handler = sigchld_handler; - sigemptyset (&sa.sa_mask); - sa.sa_flags = SA_RESTART; - if (sigaction (SIGCHLD, &sa, NULL) < 0) - fail_io ("sigaction"); - - /* Save the virtual interval timer, which might have been set - by the process that ran us. It really should be applied to - our child process. */ - memset (&zero_itimerval, 0, sizeof zero_itimerval); - if (setitimer (ITIMER_VIRTUAL, &zero_itimerval, &old_itimerval) < 0) - fail_io ("setitimer"); - - pid = fork (); - if (pid < 0) - fail_io ("fork"); - else if (pid != 0) - { - /* Running in parent process. */ - int status; - close (slave); - relay (master, pipe_fds[0]); - - /* If the subprocess has died, die in the same fashion. - In particular, dying from SIGVTALRM tells the pintos - script that we ran out of CPU time. */ - if (waitpid (pid, &status, WNOHANG) > 0) - { - if (WIFEXITED (status)) - return WEXITSTATUS (status); - else if (WIFSIGNALED (status)) - raise (WTERMSIG (status)); - } - return 0; - } - else - { - /* Running in child process. */ - if (setitimer (ITIMER_VIRTUAL, &old_itimerval, NULL) < 0) - fail_io ("setitimer"); - if (dup2 (slave, STDOUT_FILENO) < 0) - fail_io ("dup2"); - if (close (pipe_fds[0]) < 0 || close (pipe_fds[1]) < 0 - || close (slave) < 0 || close (master) < 0) - fail_io ("close"); - execvp (argv[1], argv + 1); - fail_io ("exec"); - } -} diff --git a/src/utils/squish-unix.c b/src/utils/squish-unix.c deleted file mode 100644 index 805205b2a2d4e96430cfd5c286994c2e7cb79bb4..0000000000000000000000000000000000000000 --- a/src/utils/squish-unix.c +++ /dev/null @@ -1,338 +0,0 @@ -#define _GNU_SOURCE 1 -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stropts.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <termios.h> -#include <unistd.h> - -static void -fail_io (const char *msg, ...) - __attribute__ ((noreturn)) - __attribute__ ((format (printf, 1, 2))); - -/* Prints MSG, formatting as with printf(), - plus an error message based on errno, - and exits. */ -static void -fail_io (const char *msg, ...) -{ - va_list args; - - va_start (args, msg); - vfprintf (stderr, msg, args); - va_end (args); - - if (errno != 0) - fprintf (stderr, ": %s", strerror (errno)); - putc ('\n', stderr); - exit (EXIT_FAILURE); -} - -/* If FD is a terminal, configures it for noncanonical input mode - with VMIN and VTIME set as indicated. - If FD is not a terminal, has no effect. */ -static void -make_noncanon (int fd, int vmin, int vtime) -{ - if (isatty (fd)) - { - struct termios termios; - if (tcgetattr (fd, &termios) < 0) - fail_io ("tcgetattr"); - termios.c_lflag &= ~(ICANON | ECHO); - termios.c_cc[VMIN] = vmin; - termios.c_cc[VTIME] = vtime; - if (tcsetattr (fd, TCSANOW, &termios) < 0) - fail_io ("tcsetattr"); - } -} - -/* Make FD non-blocking if NONBLOCKING is true, - or blocking if NONBLOCKING is false. */ -static void -make_nonblocking (int fd, bool nonblocking) -{ - int flags = fcntl (fd, F_GETFL); - if (flags < 0) - fail_io ("fcntl"); - if (nonblocking) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - if (fcntl (fd, F_SETFL, flags) < 0) - fail_io ("fcntl"); -} - -/* Handle a read or write on *FD, which is the socket if - FD_IS_SOCK is true, that returned end-of-file or error - indication RETVAL. The system call is named CALL, for use in - error messages. Returns true if processing may continue, - false if we're all done. */ -static bool -handle_error (ssize_t retval, int *fd, bool fd_is_sock, const char *call) -{ - if (retval == 0) - { - if (fd_is_sock) - return false; - else - { - *fd = -1; - return true; - } - } - else - fail_io (call); -} - -/* Copies data from stdin to SOCK and from SOCK to stdout until no - more data can be read or written. */ -static void -relay (int sock) -{ - struct pipe - { - int in, out; - char buf[BUFSIZ]; - size_t size, ofs; - bool active; - }; - struct pipe pipes[2]; - - /* In case stdin is a file, go back to the beginning. - This allows replaying the input on reset. */ - lseek (STDIN_FILENO, 0, SEEK_SET); - - /* Make SOCK, stdin, and stdout non-blocking. */ - make_nonblocking (sock, true); - make_nonblocking (STDIN_FILENO, true); - make_nonblocking (STDOUT_FILENO, true); - - /* Configure noncanonical mode on stdin to avoid waiting for - end-of-line. */ - make_noncanon (STDIN_FILENO, 1, 0); - - memset (pipes, 0, sizeof pipes); - pipes[0].in = STDIN_FILENO; - pipes[0].out = sock; - pipes[1].in = sock; - pipes[1].out = STDOUT_FILENO; - - while (pipes[0].in != -1 || pipes[1].in != -1 - || (pipes[1].size && pipes[1].out != -1)) - { - fd_set read_fds, write_fds; - sigset_t empty_set; - int retval; - int i; - - FD_ZERO (&read_fds); - FD_ZERO (&write_fds); - for (i = 0; i < 2; i++) - { - struct pipe *p = &pipes[i]; - - /* Don't do anything with the stdin->sock pipe until we - have some data for the sock->stdout pipe. If we get - too eager, vmplayer will throw away our input. */ - if (i == 0 && !pipes[1].active) - continue; - - if (p->in != -1 && p->size + p->ofs < sizeof p->buf) - FD_SET (p->in, &read_fds); - if (p->out != -1 && p->size > 0) - FD_SET (p->out, &write_fds); - } - sigemptyset (&empty_set); - retval = pselect (FD_SETSIZE, &read_fds, &write_fds, NULL, NULL, - &empty_set); - if (retval < 0) - { - if (errno == EINTR) - { - /* Child died. Do final relaying. */ - struct pipe *p = &pipes[1]; - if (p->out == -1) - exit (0); - make_nonblocking (STDOUT_FILENO, false); - for (;;) - { - ssize_t n; - - /* Write buffer. */ - while (p->size > 0) - { - n = write (p->out, p->buf + p->ofs, p->size); - if (n < 0) - fail_io ("write"); - else if (n == 0) - fail_io ("zero-length write"); - p->ofs += n; - p->size -= n; - } - p->ofs = 0; - - p->size = n = read (p->in, p->buf, sizeof p->buf); - if (n <= 0) - exit (0); - } - } - fail_io ("select"); - } - - for (i = 0; i < 2; i++) - { - struct pipe *p = &pipes[i]; - if (p->in != -1 && FD_ISSET (p->in, &read_fds)) - { - ssize_t n = read (p->in, p->buf + p->ofs + p->size, - sizeof p->buf - p->ofs - p->size); - if (n > 0) - { - p->active = true; - p->size += n; - if (p->size == BUFSIZ && p->ofs != 0) - { - memmove (p->buf, p->buf + p->ofs, p->size); - p->ofs = 0; - } - } - else if (!handle_error (n, &p->in, p->in == sock, "read")) - return; - } - if (p->out != -1 && FD_ISSET (p->out, &write_fds)) - { - ssize_t n = write (p->out, p->buf + p->ofs, p->size); - if (n > 0) - { - p->ofs += n; - p->size -= n; - if (p->size == 0) - p->ofs = 0; - } - else if (!handle_error (n, &p->out, p->out == sock, "write")) - return; - } - } - } -} - -static void -sigchld_handler (int signo __attribute__ ((unused))) -{ - /* Nothing to do. */ -} - -int -main (int argc __attribute__ ((unused)), char *argv[]) -{ - pid_t pid; - struct itimerval zero_itimerval; - struct sockaddr_un sun; - sigset_t sigchld_set; - int sock; - - if (argc < 3) - { - fprintf (stderr, - "usage: squish-unix SOCKET COMMAND [ARG]...\n" - "Squishes both stdin and stdout into a single Unix domain\n" - "socket named SOCKET, and runs COMMAND as a subprocess.\n"); - return EXIT_FAILURE; - } - - /* Create socket. */ - sock = socket (PF_LOCAL, SOCK_STREAM, 0); - if (sock < 0) - fail_io ("socket"); - - /* Configure socket. */ - sun.sun_family = AF_LOCAL; - strncpy (sun.sun_path, argv[1], sizeof sun.sun_path); - sun.sun_path[sizeof sun.sun_path - 1] = '\0'; - if (unlink (sun.sun_path) < 0 && errno != ENOENT) - fail_io ("unlink"); - if (bind (sock, (struct sockaddr *) &sun, - (offsetof (struct sockaddr_un, sun_path) - + strlen (sun.sun_path) + 1)) < 0) - fail_io ("bind"); - - /* Listen on socket. */ - if (listen (sock, 1) < 0) - fail_io ("listen"); - - /* Block SIGCHLD and set up a handler for it. */ - sigemptyset (&sigchld_set); - sigaddset (&sigchld_set, SIGCHLD); - if (sigprocmask (SIG_BLOCK, &sigchld_set, NULL) < 0) - fail_io ("sigprocmask"); - if (signal (SIGCHLD, sigchld_handler) == SIG_ERR) - fail_io ("signal"); - - /* Save the virtual interval timer, which might have been set - by the process that ran us. It really should be applied to - our child process. */ - memset (&zero_itimerval, 0, sizeof zero_itimerval); - if (setitimer (ITIMER_VIRTUAL, &zero_itimerval, NULL) < 0) - fail_io ("setitimer"); - - pid = fork (); - if (pid < 0) - fail_io ("fork"); - else if (pid != 0) - { - /* Running in parent process. */ - make_nonblocking (sock, true); - for (;;) - { - fd_set read_fds; - sigset_t empty_set; - int retval; - int conn; - - /* Wait for connection. */ - FD_ZERO (&read_fds); - FD_SET (sock, &read_fds); - sigemptyset (&empty_set); - retval = pselect (sock + 1, &read_fds, NULL, NULL, NULL, &empty_set); - if (retval < 0) - { - if (errno == EINTR) - break; - fail_io ("select"); - } - - /* Accept connection. */ - conn = accept (sock, NULL, NULL); - if (conn < 0) - fail_io ("accept"); - - /* Relay connection. */ - relay (conn); - close (conn); - } - return 0; - } - else - { - /* Running in child process. */ - if (close (sock) < 0) - fail_io ("close"); - execvp (argv[2], argv + 2); - fail_io ("exec"); - } -} diff --git a/src/vm/.gitignore b/src/vm/.gitignore deleted file mode 100644 index 6d5357c015ab6f0b7ee7074381afdd3da82e06eb..0000000000000000000000000000000000000000 --- a/src/vm/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -build -bochsrc.txt -bochsout.txt diff --git a/src/vm/Make.vars b/src/vm/Make.vars deleted file mode 100644 index e3c33a755b4ffcfc5236ddea4cb6524630712bae..0000000000000000000000000000000000000000 --- a/src/vm/Make.vars +++ /dev/null @@ -1,7 +0,0 @@ -# -*- makefile -*- - -kernel.bin: DEFINES = -DUSERPROG -DFILESYS -DVM -KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys vm -TEST_SUBDIRS = tests/userprog tests/vm tests/filesys/base -GRADING_FILE = $(SRCDIR)/tests/vm/Grading -SIMULATOR = --qemu diff --git a/src/vm/Makefile b/src/vm/Makefile deleted file mode 100644 index 34c10aa4f508714da040e81389fa51e56ba2d97a..0000000000000000000000000000000000000000 --- a/src/vm/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.kernel