Revert "Merging in 1.0.2."
This reverts commit 50cf3276e747c545b4ae53853d9b911731dc463e.
This commit is contained in:
parent
50cf3276e7
commit
e318e3171e
1
Makefile
1
Makefile
@ -46,7 +46,6 @@ tools:
|
|||||||
build:
|
build:
|
||||||
(cd userland && $(MAKE) build)
|
(cd userland && $(MAKE) build)
|
||||||
(cd man && $(MAKE) install-staging)
|
(cd man && $(MAKE) install-staging)
|
||||||
(cd testscripts && $(MAKE) build)
|
|
||||||
|
|
||||||
includes tags depend:
|
includes tags depend:
|
||||||
(cd kern && $(MAKE) $@)
|
(cd kern && $(MAKE) $@)
|
||||||
|
1
configure
vendored
1
configure
vendored
@ -134,7 +134,6 @@ else
|
|||||||
HOST_CFLAGS="${HOST_CFLAGS} -DDECLARE_NTOHLL"
|
HOST_CFLAGS="${HOST_CFLAGS} -DDECLARE_NTOHLL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
||||||
# Now generate defs.mk.
|
# Now generate defs.mk.
|
||||||
|
@ -126,6 +126,21 @@ free_kpages(vaddr_t addr)
|
|||||||
(void)addr;
|
(void)addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
int
|
||||||
|
coremap_used_bytes() {
|
||||||
|
|
||||||
|
/* dumbvm doesn't track page allocations. Return 0 so that khu works. */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vm_tlbshootdown_all(void)
|
||||||
|
{
|
||||||
|
panic("dumbvm tried to do tlb shootdown?!\n");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vm_tlbshootdown(const struct tlbshootdown *ts)
|
vm_tlbshootdown(const struct tlbshootdown *ts)
|
||||||
{
|
{
|
||||||
|
@ -30,3 +30,4 @@ options sfs # Always use the file system
|
|||||||
#options netfs # You might write this as a project.
|
#options netfs # You might write this as a project.
|
||||||
|
|
||||||
options dumbvm # Chewing gum and baling wire.
|
options dumbvm # Chewing gum and baling wire.
|
||||||
|
#options synchprobs # Uncomment to enable ASST1 synchronization problems
|
||||||
|
@ -309,6 +309,14 @@ file ../common/libc/string/strlen.c
|
|||||||
file ../common/libc/string/strrchr.c
|
file ../common/libc/string/strrchr.c
|
||||||
file ../common/libc/string/strtok_r.c
|
file ../common/libc/string/strtok_r.c
|
||||||
|
|
||||||
|
#
|
||||||
|
# libtest161 shared code and security functions
|
||||||
|
#
|
||||||
|
|
||||||
|
file ../common/libtest161/test161.c
|
||||||
|
file ../common/libtest161/secure.c
|
||||||
|
file ../common/libtest161/sha256.c
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
# #
|
# #
|
||||||
# Core kernel source files #
|
# Core kernel source files #
|
||||||
@ -434,7 +442,19 @@ file test/threadlisttest.c
|
|||||||
file test/threadtest.c
|
file test/threadtest.c
|
||||||
file test/tt3.c
|
file test/tt3.c
|
||||||
file test/synchtest.c
|
file test/synchtest.c
|
||||||
|
file test/rwtest.c
|
||||||
file test/semunit.c
|
file test/semunit.c
|
||||||
|
file test/hmacunit.c
|
||||||
file test/kmalloctest.c
|
file test/kmalloctest.c
|
||||||
file test/fstest.c
|
file test/fstest.c
|
||||||
|
file test/lib.c
|
||||||
|
|
||||||
optfile net test/nettest.c
|
optfile net test/nettest.c
|
||||||
|
|
||||||
|
defoption synchprobs
|
||||||
|
optfile synchprobs synchprobs/whalemating.c
|
||||||
|
optfile synchprobs synchprobs/stoplight.c
|
||||||
|
optfile synchprobs test/synchprobs.c
|
||||||
|
|
||||||
|
defoption automationtest
|
||||||
|
optfile automationtest test/automationtest.c
|
||||||
|
@ -206,7 +206,7 @@ echo "$CONFNAME" $CONFTMP | awk '
|
|||||||
#
|
#
|
||||||
|
|
||||||
if [ ! -d "$COMPILEDIR" ]; then
|
if [ ! -d "$COMPILEDIR" ]; then
|
||||||
mkdir $COMPILEDIR
|
mkdir -p $COMPILEDIR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -n 'Generating files...'
|
echo -n 'Generating files...'
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <threadlist.h>
|
#include <threadlist.h>
|
||||||
#include <machine/vm.h> /* for TLBSHOOTDOWN_MAX */
|
#include <machine/vm.h> /* for TLBSHOOTDOWN_MAX */
|
||||||
|
|
||||||
|
extern unsigned num_cpus;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Per-cpu structure
|
* Per-cpu structure
|
||||||
@ -74,21 +75,24 @@ struct cpu {
|
|||||||
* Accessed by other cpus.
|
* Accessed by other cpus.
|
||||||
* Protected by the IPI lock.
|
* Protected by the IPI lock.
|
||||||
*
|
*
|
||||||
* TLB shootdown requests made to this CPU are queued in
|
* If c_numshootdown is -1 (TLBSHOOTDOWN_ALL), all mappings
|
||||||
* c_shootdown[], with c_numshootdown holding the number of
|
* should be invalidated. This is used if more than
|
||||||
* requests. TLBSHOOTDOWN_MAX is the maximum number that can
|
* TLBSHOOTDOWN_MAX mappings are going to be invalidated at
|
||||||
* be queued at once, which is machine-dependent.
|
* once. TLBSHOOTDOWN_MAX is MD and chosen based on when it
|
||||||
|
* becomes more efficient just to flush the whole TLB.
|
||||||
*
|
*
|
||||||
* The contents of struct tlbshootdown are also machine-
|
* struct tlbshootdown is machine-dependent and might
|
||||||
* dependent and might reasonably be either an address space
|
* reasonably be either an address space and vaddr pair, or a
|
||||||
* and vaddr pair, or a paddr, or something else.
|
* paddr, or something else.
|
||||||
*/
|
*/
|
||||||
uint32_t c_ipi_pending; /* One bit for each IPI number */
|
uint32_t c_ipi_pending; /* One bit for each IPI number */
|
||||||
struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX];
|
struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX];
|
||||||
unsigned c_numshootdown;
|
int c_numshootdown;
|
||||||
struct spinlock c_ipi_lock;
|
struct spinlock c_ipi_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TLBSHOOTDOWN_ALL (-1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialization functions.
|
* Initialization functions.
|
||||||
*
|
*
|
||||||
|
@ -129,6 +129,8 @@ uint32_t random(void);
|
|||||||
void *kmalloc(size_t size);
|
void *kmalloc(size_t size);
|
||||||
void kfree(void *ptr);
|
void kfree(void *ptr);
|
||||||
void kheap_printstats(void);
|
void kheap_printstats(void);
|
||||||
|
void kheap_printused(void);
|
||||||
|
unsigned long kheap_getused(void);
|
||||||
void kheap_nextgeneration(void);
|
void kheap_nextgeneration(void);
|
||||||
void kheap_dump(void);
|
void kheap_dump(void);
|
||||||
void kheap_dumpall(void);
|
void kheap_dumpall(void);
|
||||||
|
@ -44,10 +44,10 @@
|
|||||||
* internally.
|
* internally.
|
||||||
*/
|
*/
|
||||||
struct semaphore {
|
struct semaphore {
|
||||||
char *sem_name;
|
char *sem_name;
|
||||||
struct wchan *sem_wchan;
|
struct wchan *sem_wchan;
|
||||||
struct spinlock sem_lock;
|
struct spinlock sem_lock;
|
||||||
volatile unsigned sem_count;
|
volatile unsigned sem_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct semaphore *sem_create(const char *name, unsigned initial_count);
|
struct semaphore *sem_create(const char *name, unsigned initial_count);
|
||||||
@ -137,5 +137,40 @@ void cv_wait(struct cv *cv, struct lock *lock);
|
|||||||
void cv_signal(struct cv *cv, struct lock *lock);
|
void cv_signal(struct cv *cv, struct lock *lock);
|
||||||
void cv_broadcast(struct cv *cv, struct lock *lock);
|
void cv_broadcast(struct cv *cv, struct lock *lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reader-writer locks.
|
||||||
|
*
|
||||||
|
* When the lock is created, no thread should be holding it. Likewise,
|
||||||
|
* when the lock is destroyed, no thread should be holding it.
|
||||||
|
*
|
||||||
|
* The name field is for easier debugging. A copy of the name is
|
||||||
|
* (should be) made internally.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct rwlock {
|
||||||
|
char *rwlock_name;
|
||||||
|
// add what you need here
|
||||||
|
// (don't forget to mark things volatile as needed)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rwlock * rwlock_create(const char *);
|
||||||
|
void rwlock_destroy(struct rwlock *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Operations:
|
||||||
|
* rwlock_acquire_read - Get the lock for reading. Multiple threads can
|
||||||
|
* hold the lock for reading at the same time.
|
||||||
|
* rwlock_release_read - Free the lock.
|
||||||
|
* rwlock_acquire_write - Get the lock for writing. Only one thread can
|
||||||
|
* hold the write lock at one time.
|
||||||
|
* rwlock_release_write - Free the write lock.
|
||||||
|
*
|
||||||
|
* These operations must be atomic. You get to write them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void rwlock_acquire_read(struct rwlock *);
|
||||||
|
void rwlock_release_read(struct rwlock *);
|
||||||
|
void rwlock_acquire_write(struct rwlock *);
|
||||||
|
void rwlock_release_write(struct rwlock *);
|
||||||
|
|
||||||
#endif /* _SYNCH_H_ */
|
#endif /* _SYNCH_H_ */
|
||||||
|
@ -30,6 +30,13 @@
|
|||||||
#ifndef _TEST_H_
|
#ifndef _TEST_H_
|
||||||
#define _TEST_H_
|
#define _TEST_H_
|
||||||
|
|
||||||
|
/* Get __PF() for declaring printf-like functions. */
|
||||||
|
#include <cdefs.h>
|
||||||
|
#include <kern/secret.h>
|
||||||
|
|
||||||
|
#include "opt-synchprobs.h"
|
||||||
|
#include "opt-automationtest.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Declarations for test code and other miscellaneous high-level
|
* Declarations for test code and other miscellaneous high-level
|
||||||
* functions.
|
* functions.
|
||||||
@ -52,8 +59,18 @@ int threadtest2(int, char **);
|
|||||||
int threadtest3(int, char **);
|
int threadtest3(int, char **);
|
||||||
int semtest(int, char **);
|
int semtest(int, char **);
|
||||||
int locktest(int, char **);
|
int locktest(int, char **);
|
||||||
|
int locktest2(int, char **);
|
||||||
|
int locktest3(int, char **);
|
||||||
int cvtest(int, char **);
|
int cvtest(int, char **);
|
||||||
int cvtest2(int, char **);
|
int cvtest2(int, char **);
|
||||||
|
int cvtest3(int, char **);
|
||||||
|
int cvtest4(int, char **);
|
||||||
|
int cvtest5(int, char **);
|
||||||
|
int rwtest(int, char **);
|
||||||
|
int rwtest2(int, char **);
|
||||||
|
int rwtest3(int, char **);
|
||||||
|
int rwtest4(int, char **);
|
||||||
|
int rwtest5(int, char **);
|
||||||
|
|
||||||
/* semaphore unit tests */
|
/* semaphore unit tests */
|
||||||
int semu1(int, char **);
|
int semu1(int, char **);
|
||||||
@ -88,11 +105,15 @@ int longstress(int, char **);
|
|||||||
int createstress(int, char **);
|
int createstress(int, char **);
|
||||||
int printfile(int, char **);
|
int printfile(int, char **);
|
||||||
|
|
||||||
|
/* HMAC/hash tests */
|
||||||
|
int hmacu1(int, char**);
|
||||||
|
|
||||||
/* other tests */
|
/* other tests */
|
||||||
int kmalloctest(int, char **);
|
int kmalloctest(int, char **);
|
||||||
int kmallocstress(int, char **);
|
int kmallocstress(int, char **);
|
||||||
int kmalloctest3(int, char **);
|
int kmalloctest3(int, char **);
|
||||||
int kmalloctest4(int, char **);
|
int kmalloctest4(int, char **);
|
||||||
|
int kmalloctest5(int, char **);
|
||||||
int nettest(int, char **);
|
int nettest(int, char **);
|
||||||
|
|
||||||
/* Routine for running a user-level program. */
|
/* Routine for running a user-level program. */
|
||||||
@ -104,5 +125,75 @@ void menu(char *argstr);
|
|||||||
/* The main function, called from start.S. */
|
/* The main function, called from start.S. */
|
||||||
void kmain(char *bootstring);
|
void kmain(char *bootstring);
|
||||||
|
|
||||||
|
#if OPT_SYNCHPROBS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Synchronization driver primitives.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void male_start(uint32_t);
|
||||||
|
void male_end(uint32_t);
|
||||||
|
void female_start(uint32_t);
|
||||||
|
void female_end(uint32_t);
|
||||||
|
void matchmaker_start(uint32_t);
|
||||||
|
void matchmaker_end(uint32_t);
|
||||||
|
int whalemating(int, char **);
|
||||||
|
|
||||||
|
void inQuadrant(int, uint32_t);
|
||||||
|
void leaveIntersection(uint32_t);
|
||||||
|
int stoplight(int, char **);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Synchronization problem primitives.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* whalemating.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void whalemating_init(void);
|
||||||
|
void whalemating_cleanup(void);
|
||||||
|
void male(uint32_t);
|
||||||
|
void female(uint32_t);
|
||||||
|
void matchmaker(uint32_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* stoplight.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void gostraight(uint32_t, uint32_t);
|
||||||
|
void turnleft(uint32_t, uint32_t);
|
||||||
|
void turnright(uint32_t, uint32_t);
|
||||||
|
void stoplight_init(void);
|
||||||
|
void stoplight_cleanup(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Automation tests for detecting kernel deadlocks and livelocks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if OPT_AUTOMATIONTEST
|
||||||
|
int dltest(int, char **);
|
||||||
|
int ll1test(int, char **);
|
||||||
|
int ll16test(int, char **);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void random_yielder(uint32_t);
|
||||||
|
void random_spinner(uint32_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kprintf variants that do not (or only) print during automated testing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef SECRET_TESTING
|
||||||
|
#define kprintf_t(...) kprintf(__VA_ARGS__)
|
||||||
|
#define kprintf_n(...) silent(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define kprintf_t(...) silent(__VA_ARGS__)
|
||||||
|
#define kprintf_n(...) kprintf(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void silent(const char * fmt, ...) { (void)fmt; };
|
||||||
|
|
||||||
#endif /* _TEST_H_ */
|
#endif /* _TEST_H_ */
|
||||||
|
@ -48,6 +48,7 @@ struct cpu;
|
|||||||
|
|
||||||
/* Size of kernel stacks; must be power of 2 */
|
/* Size of kernel stacks; must be power of 2 */
|
||||||
#define STACK_SIZE 4096
|
#define STACK_SIZE 4096
|
||||||
|
#define MAX_NAME_LENGTH 64
|
||||||
|
|
||||||
/* Mask for extracting the stack base address of a kernel stack pointer */
|
/* Mask for extracting the stack base address of a kernel stack pointer */
|
||||||
#define STACK_MASK (~(vaddr_t)(STACK_SIZE-1))
|
#define STACK_MASK (~(vaddr_t)(STACK_SIZE-1))
|
||||||
@ -70,7 +71,16 @@ struct thread {
|
|||||||
* These go up front so they're easy to get to even if the
|
* These go up front so they're easy to get to even if the
|
||||||
* debugger is messed up.
|
* debugger is messed up.
|
||||||
*/
|
*/
|
||||||
char *t_name; /* Name of this thread */
|
|
||||||
|
/*
|
||||||
|
* Name of this thread. Used to be dynamically allocated using kmalloc, but
|
||||||
|
* this can cause small changes in the amount of available memory due to the
|
||||||
|
* fact that it was cleaned up in exorcise. This produces more predictable
|
||||||
|
* behavior at the cost of a small amount of memory overhead and the
|
||||||
|
* inability to give threads huge names.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char t_name[MAX_NAME_LENGTH];
|
||||||
const char *t_wchan_name; /* Name of wait channel, if sleeping */
|
const char *t_wchan_name; /* Name of wait channel, if sleeping */
|
||||||
threadstate_t t_state; /* State this thread is in */
|
threadstate_t t_state; /* State this thread is in */
|
||||||
|
|
||||||
@ -168,5 +178,7 @@ void schedule(void);
|
|||||||
*/
|
*/
|
||||||
void thread_consider_migration(void);
|
void thread_consider_migration(void);
|
||||||
|
|
||||||
|
extern unsigned thread_count;
|
||||||
|
void thread_wait_for_count(unsigned);
|
||||||
|
|
||||||
#endif /* _THREAD_H_ */
|
#endif /* _THREAD_H_ */
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
* Leave this alone, so we can tell what version of the OS/161 base
|
* Leave this alone, so we can tell what version of the OS/161 base
|
||||||
* code we gave you.
|
* code we gave you.
|
||||||
*/
|
*/
|
||||||
#define BASE_VERSION "2.0.2"
|
#define BASE_VERSION "2.0.1"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change this as you see fit in the course of hacking the system.
|
* Change this as you see fit in the course of hacking the system.
|
||||||
|
@ -156,13 +156,6 @@ int vfs_getcwd(struct uio *buf);
|
|||||||
* vfs_unmount - Unmount the filesystem presently mounted on the
|
* vfs_unmount - Unmount the filesystem presently mounted on the
|
||||||
* specified device.
|
* specified device.
|
||||||
*
|
*
|
||||||
* vfs_swapon - Look up DEVNAME and mark it as a swap device,
|
|
||||||
* returning a vnode. Similar to vfs_mount.
|
|
||||||
*
|
|
||||||
* vfs_swapoff - Unmark DEVNAME as a swap device. The vnode
|
|
||||||
* previously returned by vfs_swapon should be
|
|
||||||
* decref'd first. Similar to vfs_unmount.
|
|
||||||
*
|
|
||||||
* vfs_unmountall - Unmount all mounted filesystems.
|
* vfs_unmountall - Unmount all mounted filesystems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -179,8 +172,6 @@ int vfs_mount(const char *devname, void *data,
|
|||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct fs **result));
|
struct fs **result));
|
||||||
int vfs_unmount(const char *devname);
|
int vfs_unmount(const char *devname);
|
||||||
int vfs_swapon(const char *devname, struct vnode **result);
|
|
||||||
int vfs_swapoff(const char *devname);
|
|
||||||
int vfs_unmountall(void);
|
int vfs_unmountall(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -55,7 +55,15 @@ int vm_fault(int faulttype, vaddr_t faultaddress);
|
|||||||
vaddr_t alloc_kpages(unsigned npages);
|
vaddr_t alloc_kpages(unsigned npages);
|
||||||
void free_kpages(vaddr_t addr);
|
void free_kpages(vaddr_t addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return amount of memory (in bytes) used by allocated coremap pages. If
|
||||||
|
* there are ongoing allocations, this value could change after it is returned
|
||||||
|
* to the caller. But it should have been correct at some point in time.
|
||||||
|
*/
|
||||||
|
unsigned int coremap_used_bytes(void);
|
||||||
|
|
||||||
/* TLB shootdown handling called from interprocessor_interrupt */
|
/* TLB shootdown handling called from interprocessor_interrupt */
|
||||||
|
void vm_tlbshootdown_all(void);
|
||||||
void vm_tlbshootdown(const struct tlbshootdown *);
|
void vm_tlbshootdown(const struct tlbshootdown *);
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#include <mainbus.h>
|
#include <mainbus.h>
|
||||||
#include <vfs.h> // for vfs_sync()
|
#include <vfs.h> // for vfs_sync()
|
||||||
#include <lamebus/ltrace.h> // for ltrace_stop()
|
#include <lamebus/ltrace.h> // for ltrace_stop()
|
||||||
|
#include <kern/secret.h>
|
||||||
|
#include <test.h>
|
||||||
|
|
||||||
|
|
||||||
/* Flags word for DEBUG() macro. */
|
/* Flags word for DEBUG() macro. */
|
||||||
@ -90,13 +92,14 @@ console_send(void *junk, const char *data, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Printf to the console.
|
* kprintf and tprintf helper function.
|
||||||
*/
|
*/
|
||||||
|
static
|
||||||
|
inline
|
||||||
int
|
int
|
||||||
kprintf(const char *fmt, ...)
|
__kprintf(const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
int chars;
|
int chars;
|
||||||
va_list ap;
|
|
||||||
bool dolock;
|
bool dolock;
|
||||||
|
|
||||||
dolock = kprintf_lock != NULL
|
dolock = kprintf_lock != NULL
|
||||||
@ -111,9 +114,7 @@ kprintf(const char *fmt, ...)
|
|||||||
spinlock_acquire(&kprintf_spinlock);
|
spinlock_acquire(&kprintf_spinlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
chars = __vprintf(console_send, NULL, fmt, ap);
|
chars = __vprintf(console_send, NULL, fmt, ap);
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (dolock) {
|
if (dolock) {
|
||||||
lock_release(kprintf_lock);
|
lock_release(kprintf_lock);
|
||||||
@ -125,6 +126,22 @@ kprintf(const char *fmt, ...)
|
|||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Printf to the console.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
kprintf(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
int chars;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
chars = __kprintf(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* panic() is for fatal errors. It prints the printf arguments it's
|
* panic() is for fatal errors. It prints the printf arguments it's
|
||||||
* passed and then halts the system.
|
* passed and then halts the system.
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include <device.h>
|
#include <device.h>
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
#include <test.h>
|
#include <test.h>
|
||||||
|
#include <kern/test161.h>
|
||||||
#include <version.h>
|
#include <version.h>
|
||||||
#include "autoconf.h" // for pseudoconfig
|
#include "autoconf.h" // for pseudoconfig
|
||||||
|
|
||||||
@ -127,6 +128,7 @@ boot(void)
|
|||||||
vm_bootstrap();
|
vm_bootstrap();
|
||||||
kprintf_bootstrap();
|
kprintf_bootstrap();
|
||||||
thread_start_cpus();
|
thread_start_cpus();
|
||||||
|
test161_bootstrap();
|
||||||
|
|
||||||
/* Default bootfs - but ignore failure, in case emu0 doesn't exist */
|
/* Default bootfs - but ignore failure, in case emu0 doesn't exist */
|
||||||
vfs_setbootfs("emu0");
|
vfs_setbootfs("emu0");
|
||||||
|
115
kern/main/menu.c
115
kern/main/menu.c
@ -41,8 +41,11 @@
|
|||||||
#include <sfs.h>
|
#include <sfs.h>
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
#include <test.h>
|
#include <test.h>
|
||||||
|
#include <prompt.h>
|
||||||
#include "opt-sfs.h"
|
#include "opt-sfs.h"
|
||||||
#include "opt-net.h"
|
#include "opt-net.h"
|
||||||
|
#include "opt-synchprobs.h"
|
||||||
|
#include "opt-automationtest.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In-kernel menu and command dispatcher.
|
* In-kernel menu and command dispatcher.
|
||||||
@ -114,6 +117,7 @@ common_prog(int nargs, char **args)
|
|||||||
{
|
{
|
||||||
struct proc *proc;
|
struct proc *proc;
|
||||||
int result;
|
int result;
|
||||||
|
unsigned tc;
|
||||||
|
|
||||||
/* Create a process for the new program to run in. */
|
/* Create a process for the new program to run in. */
|
||||||
proc = proc_create_runprogram(args[0] /* name */);
|
proc = proc_create_runprogram(args[0] /* name */);
|
||||||
@ -121,6 +125,8 @@ common_prog(int nargs, char **args)
|
|||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tc = thread_count;
|
||||||
|
|
||||||
result = thread_fork(args[0] /* thread name */,
|
result = thread_fork(args[0] /* thread name */,
|
||||||
proc /* new process */,
|
proc /* new process */,
|
||||||
cmd_progthread /* thread function */,
|
cmd_progthread /* thread function */,
|
||||||
@ -136,6 +142,10 @@ common_prog(int nargs, char **args)
|
|||||||
* once you write the code for handling that.
|
* once you write the code for handling that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Wait for all threads to finish cleanup, otherwise khu be a bit behind,
|
||||||
|
// especially once swapping is enabled.
|
||||||
|
thread_wait_for_count(tc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +383,18 @@ cmd_kheapstats(int nargs, char **args)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
cmd_kheapused(int nargs, char **args)
|
||||||
|
{
|
||||||
|
(void)nargs;
|
||||||
|
(void)args;
|
||||||
|
|
||||||
|
kheap_printused();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
cmd_kheapgeneration(int nargs, char **args)
|
cmd_kheapgeneration(int nargs, char **args)
|
||||||
@ -466,16 +488,31 @@ static const char *testmenu[] = {
|
|||||||
"[km2] kmalloc stress test ",
|
"[km2] kmalloc stress test ",
|
||||||
"[km3] Large kmalloc test ",
|
"[km3] Large kmalloc test ",
|
||||||
"[km4] Multipage kmalloc test ",
|
"[km4] Multipage kmalloc test ",
|
||||||
|
"[km5] kmalloc coremap alloc test ",
|
||||||
"[tt1] Thread test 1 ",
|
"[tt1] Thread test 1 ",
|
||||||
"[tt2] Thread test 2 ",
|
"[tt2] Thread test 2 ",
|
||||||
"[tt3] Thread test 3 ",
|
"[tt3] Thread test 3 ",
|
||||||
#if OPT_NET
|
#if OPT_NET
|
||||||
"[net] Network test ",
|
"[net] Network test ",
|
||||||
#endif
|
#endif
|
||||||
"[sy1] Semaphore test ",
|
"[sem1] Semaphore test ",
|
||||||
"[sy2] Lock test (1) ",
|
"[lt1] Lock test 1 (1) ",
|
||||||
"[sy3] CV test (1) ",
|
"[lt2] Lock test 2 (1*) ",
|
||||||
"[sy4] CV test #2 (1) ",
|
"[lt3] Lock test 3 (1*) ",
|
||||||
|
"[cvt1] CV test 1 (1) ",
|
||||||
|
"[cvt2] CV test 2 (1) ",
|
||||||
|
"[cvt3] CV test 3 (1*) ",
|
||||||
|
"[cvt4] CV test 4 (1*) ",
|
||||||
|
"[cvt5] CV test 5 (1) ",
|
||||||
|
"[rwt1] RW lock test (1?) ",
|
||||||
|
"[rwt2] RW lock test 2 (1?) ",
|
||||||
|
"[rwt3] RW lock test 3 (1?) ",
|
||||||
|
"[rwt4] RW lock test 4 (1?) ",
|
||||||
|
"[rwt5] RW lock test 5 (1?) ",
|
||||||
|
#if OPT_SYNCHPROBS
|
||||||
|
"[sp1] Whalemating test (1) ",
|
||||||
|
"[sp2] Stoplight test (1) ",
|
||||||
|
#endif
|
||||||
"[semu1-22] Semaphore unit tests ",
|
"[semu1-22] Semaphore unit tests ",
|
||||||
"[fs1] Filesystem test ",
|
"[fs1] Filesystem test ",
|
||||||
"[fs2] FS read stress ",
|
"[fs2] FS read stress ",
|
||||||
@ -483,6 +520,7 @@ static const char *testmenu[] = {
|
|||||||
"[fs4] FS write stress 2 ",
|
"[fs4] FS write stress 2 ",
|
||||||
"[fs5] FS long stress ",
|
"[fs5] FS long stress ",
|
||||||
"[fs6] FS create stress ",
|
"[fs6] FS create stress ",
|
||||||
|
"[hm1] HMAC unit test ",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -496,15 +534,41 @@ cmd_testmenu(int n, char **a)
|
|||||||
showmenu("OS/161 tests menu", testmenu);
|
showmenu("OS/161 tests menu", testmenu);
|
||||||
kprintf(" (1) These tests will fail until you finish the "
|
kprintf(" (1) These tests will fail until you finish the "
|
||||||
"synch assignment.\n");
|
"synch assignment.\n");
|
||||||
|
kprintf(" (*) These tests will panic on success.\n");
|
||||||
|
kprintf(" (?) These tests are left to you to implement.\n");
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPT_AUTOMATIONTEST
|
||||||
|
static const char *automationmenu[] = {
|
||||||
|
"[dl] Deadlock test (*) ",
|
||||||
|
"[ll1] Livelock test (1 thread) ",
|
||||||
|
"[ll16] Livelock test (16 threads) ",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
cmd_automationmenu(int n, char **a)
|
||||||
|
{
|
||||||
|
(void)n;
|
||||||
|
(void)a;
|
||||||
|
|
||||||
|
showmenu("OS/161 automation tests menu", automationmenu);
|
||||||
|
kprintf(" (*) These tests require locks.\n");
|
||||||
|
kprintf("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *mainmenu[] = {
|
static const char *mainmenu[] = {
|
||||||
"[?o] Operations menu ",
|
"[?o] Operations menu ",
|
||||||
"[?t] Tests menu ",
|
"[?t] Tests menu ",
|
||||||
"[kh] Kernel heap stats ",
|
"[kh] Kernel heap stats ",
|
||||||
|
"[khu] Kernel heap usage ",
|
||||||
"[khgen] Next kernel heap generation ",
|
"[khgen] Next kernel heap generation ",
|
||||||
"[khdump] Dump kernel heap ",
|
"[khdump] Dump kernel heap ",
|
||||||
"[q] Quit and shut down ",
|
"[q] Quit and shut down ",
|
||||||
@ -536,6 +600,9 @@ static struct {
|
|||||||
{ "help", cmd_mainmenu },
|
{ "help", cmd_mainmenu },
|
||||||
{ "?o", cmd_opsmenu },
|
{ "?o", cmd_opsmenu },
|
||||||
{ "?t", cmd_testmenu },
|
{ "?t", cmd_testmenu },
|
||||||
|
#if OPT_AUTOMATIONTEST
|
||||||
|
{ "?a", cmd_automationmenu },
|
||||||
|
#endif
|
||||||
|
|
||||||
/* operations */
|
/* operations */
|
||||||
{ "s", cmd_shell },
|
{ "s", cmd_shell },
|
||||||
@ -554,6 +621,7 @@ static struct {
|
|||||||
|
|
||||||
/* stats */
|
/* stats */
|
||||||
{ "kh", cmd_kheapstats },
|
{ "kh", cmd_kheapstats },
|
||||||
|
{ "khu", cmd_kheapused },
|
||||||
{ "khgen", cmd_kheapgeneration },
|
{ "khgen", cmd_kheapgeneration },
|
||||||
{ "khdump", cmd_kheapdump },
|
{ "khdump", cmd_kheapdump },
|
||||||
|
|
||||||
@ -566,18 +634,33 @@ static struct {
|
|||||||
{ "km2", kmallocstress },
|
{ "km2", kmallocstress },
|
||||||
{ "km3", kmalloctest3 },
|
{ "km3", kmalloctest3 },
|
||||||
{ "km4", kmalloctest4 },
|
{ "km4", kmalloctest4 },
|
||||||
|
{ "km5", kmalloctest5 },
|
||||||
#if OPT_NET
|
#if OPT_NET
|
||||||
{ "net", nettest },
|
{ "net", nettest },
|
||||||
#endif
|
#endif
|
||||||
{ "tt1", threadtest },
|
{ "tt1", threadtest },
|
||||||
{ "tt2", threadtest2 },
|
{ "tt2", threadtest2 },
|
||||||
{ "tt3", threadtest3 },
|
{ "tt3", threadtest3 },
|
||||||
{ "sy1", semtest },
|
|
||||||
|
|
||||||
/* synchronization assignment tests */
|
/* synchronization assignment tests */
|
||||||
{ "sy2", locktest },
|
{ "sem1", semtest },
|
||||||
{ "sy3", cvtest },
|
{ "lt1", locktest },
|
||||||
{ "sy4", cvtest2 },
|
{ "lt2", locktest2 },
|
||||||
|
{ "lt3", locktest3 },
|
||||||
|
{ "cvt1", cvtest },
|
||||||
|
{ "cvt2", cvtest2 },
|
||||||
|
{ "cvt3", cvtest3 },
|
||||||
|
{ "cvt4", cvtest4 },
|
||||||
|
{ "cvt5", cvtest5 },
|
||||||
|
{ "rwt1", rwtest },
|
||||||
|
{ "rwt2", rwtest2 },
|
||||||
|
{ "rwt3", rwtest3 },
|
||||||
|
{ "rwt4", rwtest4 },
|
||||||
|
{ "rwt5", rwtest5 },
|
||||||
|
#if OPT_SYNCHPROBS
|
||||||
|
{ "sp1", whalemating },
|
||||||
|
{ "sp2", stoplight },
|
||||||
|
#endif
|
||||||
|
|
||||||
/* semaphore unit tests */
|
/* semaphore unit tests */
|
||||||
{ "semu1", semu1 },
|
{ "semu1", semu1 },
|
||||||
@ -611,6 +694,16 @@ static struct {
|
|||||||
{ "fs5", longstress },
|
{ "fs5", longstress },
|
||||||
{ "fs6", createstress },
|
{ "fs6", createstress },
|
||||||
|
|
||||||
|
/* HMAC unit tests */
|
||||||
|
{ "hm1", hmacu1 },
|
||||||
|
|
||||||
|
#if OPT_AUTOMATIONTEST
|
||||||
|
/* automation tests */
|
||||||
|
{ "dl", dltest },
|
||||||
|
{ "ll1", ll1test },
|
||||||
|
{ "ll16", ll16test },
|
||||||
|
#endif
|
||||||
|
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -724,7 +817,11 @@ menu(char *args)
|
|||||||
menu_execute(args, 1);
|
menu_execute(args, 1);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
kprintf("OS/161 kernel [? for menu]: ");
|
/*
|
||||||
|
* Defined in overwrite.h. If you want to change the kernel prompt, please
|
||||||
|
* do it in that file. Otherwise automated test testing will break.
|
||||||
|
*/
|
||||||
|
kprintf(KERNEL_PROMPT);
|
||||||
kgets(buf, sizeof(buf));
|
kgets(buf, sizeof(buf));
|
||||||
menu_execute(buf, 0);
|
menu_execute(buf, 0);
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,19 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <kern/errno.h>
|
#include <kern/errno.h>
|
||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
|
#include <cpu.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <synch.h>
|
#include <synch.h>
|
||||||
#include <vm.h> /* for PAGE_SIZE */
|
#include <vm.h> /* for PAGE_SIZE */
|
||||||
#include <test.h>
|
#include <test.h>
|
||||||
|
#include <kern/test161.h>
|
||||||
|
#include <mainbus.h>
|
||||||
|
|
||||||
#include "opt-dumbvm.h"
|
#include "opt-dumbvm.h"
|
||||||
|
|
||||||
|
// from arch/mips/vm/ram.c
|
||||||
|
extern vaddr_t firstfree;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// km1/km2
|
// km1/km2
|
||||||
|
|
||||||
@ -58,6 +64,12 @@
|
|||||||
#define ITEMSIZE 997
|
#define ITEMSIZE 997
|
||||||
#define NTHREADS 8
|
#define NTHREADS 8
|
||||||
|
|
||||||
|
#define PROGRESS(iter) do { \
|
||||||
|
if ((iter % 100) == 0) { \
|
||||||
|
kprintf("."); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
kmallocthread(void *sm, unsigned long num)
|
kmallocthread(void *sm, unsigned long num)
|
||||||
@ -69,15 +81,16 @@ kmallocthread(void *sm, unsigned long num)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i=0; i<NTRIES; i++) {
|
for (i=0; i<NTRIES; i++) {
|
||||||
|
PROGRESS(i);
|
||||||
ptr = kmalloc(ITEMSIZE);
|
ptr = kmalloc(ITEMSIZE);
|
||||||
if (ptr==NULL) {
|
if (ptr==NULL) {
|
||||||
if (sem) {
|
if (sem) {
|
||||||
kprintf("thread %lu: kmalloc returned NULL\n",
|
kprintf("thread %lu: kmalloc returned NULL\n",
|
||||||
num);
|
num);
|
||||||
goto done;
|
panic("kmalloc test failed");
|
||||||
}
|
}
|
||||||
kprintf("kmalloc returned null; test failed.\n");
|
kprintf("kmalloc returned null; test failed.\n");
|
||||||
goto done;
|
panic("kmalloc test failed");
|
||||||
}
|
}
|
||||||
if (oldptr2) {
|
if (oldptr2) {
|
||||||
kfree(oldptr2);
|
kfree(oldptr2);
|
||||||
@ -85,7 +98,7 @@ kmallocthread(void *sm, unsigned long num)
|
|||||||
oldptr2 = oldptr;
|
oldptr2 = oldptr;
|
||||||
oldptr = ptr;
|
oldptr = ptr;
|
||||||
}
|
}
|
||||||
done:
|
|
||||||
if (oldptr2) {
|
if (oldptr2) {
|
||||||
kfree(oldptr2);
|
kfree(oldptr2);
|
||||||
}
|
}
|
||||||
@ -105,7 +118,8 @@ kmalloctest(int nargs, char **args)
|
|||||||
|
|
||||||
kprintf("Starting kmalloc test...\n");
|
kprintf("Starting kmalloc test...\n");
|
||||||
kmallocthread(NULL, 0);
|
kmallocthread(NULL, 0);
|
||||||
kprintf("kmalloc test done\n");
|
kprintf("\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "km1");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -140,7 +154,8 @@ kmallocstress(int nargs, char **args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sem_destroy(sem);
|
sem_destroy(sem);
|
||||||
kprintf("kmalloc stress test done\n");
|
kprintf("\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "km2");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -252,6 +267,7 @@ kmalloctest3(int nargs, char **args)
|
|||||||
curpos = 0;
|
curpos = 0;
|
||||||
cursizeindex = 0;
|
cursizeindex = 0;
|
||||||
for (i=0; i<numptrs; i++) {
|
for (i=0; i<numptrs; i++) {
|
||||||
|
PROGRESS(i);
|
||||||
cursize = sizes[cursizeindex];
|
cursize = sizes[cursizeindex];
|
||||||
ptr = ptrblocks[curblock][curpos];
|
ptr = ptrblocks[curblock][curpos];
|
||||||
KASSERT(ptr != NULL);
|
KASSERT(ptr != NULL);
|
||||||
@ -282,13 +298,15 @@ kmalloctest3(int nargs, char **args)
|
|||||||
|
|
||||||
/* Free the lower tier. */
|
/* Free the lower tier. */
|
||||||
for (i=0; i<numptrblocks; i++) {
|
for (i=0; i<numptrblocks; i++) {
|
||||||
|
PROGRESS(i);
|
||||||
KASSERT(ptrblocks[i] != NULL);
|
KASSERT(ptrblocks[i] != NULL);
|
||||||
kfree(ptrblocks[i]);
|
kfree(ptrblocks[i]);
|
||||||
}
|
}
|
||||||
/* Free the upper tier. */
|
/* Free the upper tier. */
|
||||||
kfree(ptrblocks);
|
kfree(ptrblocks);
|
||||||
|
|
||||||
kprintf("kmalloctest3: passed\n");
|
kprintf("\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "km3");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,20 +318,24 @@ void
|
|||||||
kmalloctest4thread(void *sm, unsigned long num)
|
kmalloctest4thread(void *sm, unsigned long num)
|
||||||
{
|
{
|
||||||
#define NUM_KM4_SIZES 5
|
#define NUM_KM4_SIZES 5
|
||||||
|
#define ITERATIONS 50
|
||||||
static const unsigned sizes[NUM_KM4_SIZES] = { 1, 3, 5, 2, 4 };
|
static const unsigned sizes[NUM_KM4_SIZES] = { 1, 3, 5, 2, 4 };
|
||||||
|
|
||||||
struct semaphore *sem = sm;
|
struct semaphore *sem = sm;
|
||||||
void *ptrs[NUM_KM4_SIZES];
|
void *ptrs[NUM_KM4_SIZES];
|
||||||
unsigned p, q;
|
unsigned p, q;
|
||||||
unsigned i;
|
unsigned i, j, k;
|
||||||
|
uint32_t magic;
|
||||||
|
|
||||||
for (i=0; i<NUM_KM4_SIZES; i++) {
|
for (i=0; i<NUM_KM4_SIZES; i++) {
|
||||||
ptrs[i] = NULL;
|
ptrs[i] = NULL;
|
||||||
}
|
}
|
||||||
p = 0;
|
p = 0;
|
||||||
q = NUM_KM4_SIZES / 2;
|
q = NUM_KM4_SIZES / 2;
|
||||||
|
magic = random();
|
||||||
|
|
||||||
for (i=0; i<NTRIES; i++) {
|
for (i=0; i<NTRIES; i++) {
|
||||||
|
PROGRESS(i);
|
||||||
if (ptrs[q] != NULL) {
|
if (ptrs[q] != NULL) {
|
||||||
kfree(ptrs[q]);
|
kfree(ptrs[q]);
|
||||||
ptrs[q] = NULL;
|
ptrs[q] = NULL;
|
||||||
@ -324,6 +346,24 @@ kmalloctest4thread(void *sm, unsigned long num)
|
|||||||
"allocating %u pages failed\n",
|
"allocating %u pages failed\n",
|
||||||
num, sizes[p]);
|
num, sizes[p]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write to each page of the allocated memory and make sure nothing
|
||||||
|
// overwrites it.
|
||||||
|
for (k = 0; k < sizes[p]; k++) {
|
||||||
|
*((uint32_t *)ptrs[p] + k*PAGE_SIZE/sizeof(uint32_t)) = magic;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < ITERATIONS; j++) {
|
||||||
|
random_yielder(4);
|
||||||
|
for (k = 0; k < sizes[p]; k++) {
|
||||||
|
uint32_t actual = *((uint32_t *)ptrs[p] + k*PAGE_SIZE/sizeof(uint32_t));
|
||||||
|
if (actual != magic) {
|
||||||
|
panic("km4: expected %u got %u. Your VM is broken!",
|
||||||
|
magic, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
magic++;
|
||||||
p = (p + 1) % NUM_KM4_SIZES;
|
p = (p + 1) % NUM_KM4_SIZES;
|
||||||
q = (q + 1) % NUM_KM4_SIZES;
|
q = (q + 1) % NUM_KM4_SIZES;
|
||||||
}
|
}
|
||||||
@ -375,6 +415,193 @@ kmalloctest4(int nargs, char **args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sem_destroy(sem);
|
sem_destroy(sem);
|
||||||
kprintf("Multipage kmalloc test done\n");
|
|
||||||
|
kprintf("\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "km4");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void
|
||||||
|
km5_usage()
|
||||||
|
{
|
||||||
|
kprintf("usage: km5 [--avail <num_pages>] [--kernel <num_pages>]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and free all physical memory a number of times. Along the we, we
|
||||||
|
* check coremap_used_bytes to make sure it's reporting the number we're
|
||||||
|
* expecting.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
kmalloctest5(int nargs, char **args)
|
||||||
|
{
|
||||||
|
#define KM5_ITERATIONS 5
|
||||||
|
|
||||||
|
// We're expecting an even number of arguments, less arg[0].
|
||||||
|
if (nargs > 5 || (nargs % 2) == 0) {
|
||||||
|
km5_usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned avail_page_slack = 0, kernel_page_limit = 0;
|
||||||
|
int arg = 1;
|
||||||
|
|
||||||
|
while (arg < nargs) {
|
||||||
|
if (strcmp(args[arg], "--avail") == 0) {
|
||||||
|
arg++;
|
||||||
|
avail_page_slack = atoi(args[arg++]);
|
||||||
|
} else if (strcmp(args[arg], "--kernel") == 0) {
|
||||||
|
arg++;
|
||||||
|
kernel_page_limit = atoi(args[arg++]);
|
||||||
|
} else {
|
||||||
|
km5_usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if OPT_DUMBVM
|
||||||
|
kprintf("(This test will not work with dumbvm)\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// First, we need to figure out how much memory we're running with and how
|
||||||
|
// much space it will take up if we maintain a pointer to each allocated
|
||||||
|
// page. We do something similar to km3 - for 32 bit systems with
|
||||||
|
// PAGE_SIZE == 4096, we can store 1024 pointers on a page. We keep an array
|
||||||
|
// of page size blocks of pointers which in total can hold enough pointers
|
||||||
|
// for each page of available physical memory.
|
||||||
|
unsigned orig_used, ptrs_per_page, num_ptr_blocks, max_pages;
|
||||||
|
unsigned total_ram, avail_ram, magic, orig_magic, known_pages;
|
||||||
|
|
||||||
|
ptrs_per_page = PAGE_SIZE / sizeof(void *);
|
||||||
|
total_ram = mainbus_ramsize();
|
||||||
|
avail_ram = total_ram - (uint32_t)(firstfree - MIPS_KSEG0);
|
||||||
|
max_pages = (avail_ram + PAGE_SIZE-1) / PAGE_SIZE;
|
||||||
|
num_ptr_blocks = (max_pages + ptrs_per_page-1) / ptrs_per_page;
|
||||||
|
|
||||||
|
// The array can go on the stack, we won't have that many
|
||||||
|
// (sys161 16M max => 4 blocks)
|
||||||
|
void **ptrs[num_ptr_blocks];
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < num_ptr_blocks; i++) {
|
||||||
|
ptrs[i] = kmalloc(PAGE_SIZE);
|
||||||
|
if (ptrs[i] == NULL) {
|
||||||
|
panic("Can't allocate ptr page!");
|
||||||
|
}
|
||||||
|
bzero(ptrs[i], PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("km5 --> phys ram: %uk avail ram: %uk (%u pages) ptr blocks: %u\n", total_ram/1024,
|
||||||
|
avail_ram/1024, max_pages, num_ptr_blocks);
|
||||||
|
|
||||||
|
// Initially, there must be at least 1 page allocated for each thread stack,
|
||||||
|
// one page for kmalloc for this thread struct, plus what we just allocated).
|
||||||
|
// This probably isn't the GLB, but its a decent lower bound.
|
||||||
|
orig_used = coremap_used_bytes();
|
||||||
|
known_pages = num_cpus + num_ptr_blocks + 1;
|
||||||
|
if (orig_used < known_pages * PAGE_SIZE) {
|
||||||
|
panic ("Not enough pages initially allocated");
|
||||||
|
}
|
||||||
|
if ((orig_used % PAGE_SIZE) != 0) {
|
||||||
|
panic("Coremap used bytes should be a multiple of PAGE_SIZE");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for kernel bloat.
|
||||||
|
if (kernel_page_limit > 0) {
|
||||||
|
uint32_t kpages = (total_ram - avail_ram + PAGE_SIZE) / PAGE_SIZE;
|
||||||
|
if (kpages > kernel_page_limit) {
|
||||||
|
panic("You're kernel is bloated! Max allowed pages: %d, used pages: %d",
|
||||||
|
kernel_page_limit, kpages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
orig_magic = magic = random();
|
||||||
|
|
||||||
|
for (int i = 0; i < KM5_ITERATIONS; i++) {
|
||||||
|
// Step 1: allocate all physical memory, with checks along the way
|
||||||
|
unsigned int block, pos, oom, pages, used, prev;
|
||||||
|
void *page;
|
||||||
|
|
||||||
|
block = pos = oom = pages = used = 0;
|
||||||
|
prev = orig_used;
|
||||||
|
|
||||||
|
while (pages < max_pages+1) {
|
||||||
|
PROGRESS(pages);
|
||||||
|
page = kmalloc(PAGE_SIZE);
|
||||||
|
if (page == NULL) {
|
||||||
|
oom = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we can write to the page
|
||||||
|
*(uint32_t *)page = magic++;
|
||||||
|
|
||||||
|
// Make sure the number of used bytes is going up, and by increments of PAGE_SIZE
|
||||||
|
used = coremap_used_bytes();
|
||||||
|
if (used != prev + PAGE_SIZE) {
|
||||||
|
panic("Allocation not equal to PAGE_SIZE. prev: %u used: %u", prev, used);
|
||||||
|
}
|
||||||
|
prev = used;
|
||||||
|
|
||||||
|
ptrs[block][pos] = page;
|
||||||
|
pos++;
|
||||||
|
if (pos >= ptrs_per_page) {
|
||||||
|
pos = 0;
|
||||||
|
block++;
|
||||||
|
}
|
||||||
|
pages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Check that we were able to allocate a reasonable number of pages
|
||||||
|
unsigned expected;
|
||||||
|
if (avail_page_slack > 0 ) {
|
||||||
|
// max avail pages + what we can prove we allocated + some slack
|
||||||
|
expected = max_pages - (known_pages + avail_page_slack);
|
||||||
|
} else {
|
||||||
|
// At the very least, just so we know things are working.
|
||||||
|
expected = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pages < expected) {
|
||||||
|
panic("Expected to allocate at least %d pages, only allocated %d",
|
||||||
|
expected, pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We tried to allocate 1 more page than is available in physical memory. That
|
||||||
|
// should fail unless you're swapping out kernel pages, which you should
|
||||||
|
// probably not be doing.
|
||||||
|
if (!oom) {
|
||||||
|
panic("Allocated more pages than physical memory. Are you swapping kernel pages?");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: free everything and check that we're back to where we started
|
||||||
|
for (block = 0; block < num_ptr_blocks; block++) {
|
||||||
|
for (pos = 0; pos < ptrs_per_page; pos++) {
|
||||||
|
if (ptrs[block][pos] != NULL) {
|
||||||
|
// Make sure we got unique addresses
|
||||||
|
if ((*(uint32_t *)ptrs[block][pos]) != orig_magic++) {
|
||||||
|
panic("km5: expected %u got %u - your VM is broken!",
|
||||||
|
orig_magic-1, (*(uint32_t *)ptrs[block][pos]));
|
||||||
|
}
|
||||||
|
kfree(ptrs[block][pos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we're back to where we started
|
||||||
|
used = coremap_used_bytes();
|
||||||
|
if (used != orig_used) {
|
||||||
|
panic("orig (%u) != used (%u)", orig_used, used);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Clean up the pointer blocks
|
||||||
|
for (unsigned i = 0; i < num_ptr_blocks; i++) {
|
||||||
|
kfree(ptrs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "km5");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,9 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Synchronization test code.
|
* Synchronization test code.
|
||||||
|
*
|
||||||
|
* All the contents of this file are overwritten during automated
|
||||||
|
* testing. Please consider this before changing anything in this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
@ -37,185 +40,303 @@
|
|||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <synch.h>
|
#include <synch.h>
|
||||||
#include <test.h>
|
#include <test.h>
|
||||||
|
#include <kern/test161.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
|
||||||
|
#define CREATELOOPS 8
|
||||||
#define NSEMLOOPS 63
|
#define NSEMLOOPS 63
|
||||||
#define NLOCKLOOPS 120
|
#define NLOCKLOOPS 120
|
||||||
#define NCVLOOPS 5
|
#define NCVLOOPS 5
|
||||||
#define NTHREADS 32
|
#define NTHREADS 32
|
||||||
|
#define SYNCHTEST_YIELDER_MAX 16
|
||||||
|
|
||||||
static volatile unsigned long testval1;
|
static volatile unsigned long testval1;
|
||||||
static volatile unsigned long testval2;
|
static volatile unsigned long testval2;
|
||||||
static volatile unsigned long testval3;
|
static volatile unsigned long testval3;
|
||||||
static struct semaphore *testsem;
|
static volatile int32_t testval4;
|
||||||
static struct lock *testlock;
|
|
||||||
static struct cv *testcv;
|
static struct semaphore *testsem = NULL;
|
||||||
static struct semaphore *donesem;
|
static struct semaphore *testsem2 = NULL;
|
||||||
|
static struct lock *testlock = NULL;
|
||||||
|
static struct lock *testlock2 = NULL;
|
||||||
|
static struct cv *testcv = NULL;
|
||||||
|
static struct semaphore *donesem = NULL;
|
||||||
|
|
||||||
|
struct spinlock status_lock;
|
||||||
|
static bool test_status = TEST161_FAIL;
|
||||||
|
|
||||||
|
static unsigned long semtest_current;
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
bool
|
||||||
inititems(void)
|
failif(bool condition) {
|
||||||
{
|
if (condition) {
|
||||||
if (testsem==NULL) {
|
spinlock_acquire(&status_lock);
|
||||||
testsem = sem_create("testsem", 2);
|
test_status = TEST161_FAIL;
|
||||||
if (testsem == NULL) {
|
spinlock_release(&status_lock);
|
||||||
panic("synchtest: sem_create failed\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (testlock==NULL) {
|
|
||||||
testlock = lock_create("testlock");
|
|
||||||
if (testlock == NULL) {
|
|
||||||
panic("synchtest: lock_create failed\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (testcv==NULL) {
|
|
||||||
testcv = cv_create("testlock");
|
|
||||||
if (testcv == NULL) {
|
|
||||||
panic("synchtest: cv_create failed\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (donesem==NULL) {
|
|
||||||
donesem = sem_create("donesem", 0);
|
|
||||||
if (donesem == NULL) {
|
|
||||||
panic("synchtest: sem_create failed\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
semtestthread(void *junk, unsigned long num)
|
semtestthread(void *junk, unsigned long num)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
(void)junk;
|
(void)junk;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only one of these should print at a time.
|
* Only one of these should print at a time.
|
||||||
*/
|
*/
|
||||||
P(testsem);
|
P(testsem);
|
||||||
kprintf("Thread %2lu: ", num);
|
semtest_current = num;
|
||||||
|
|
||||||
|
kprintf_n("Thread %2lu: ", num);
|
||||||
for (i=0; i<NSEMLOOPS; i++) {
|
for (i=0; i<NSEMLOOPS; i++) {
|
||||||
kprintf("%c", (int)num+64);
|
kprintf_t(".");
|
||||||
|
kprintf_n("%2lu", num);
|
||||||
|
random_yielder(4);
|
||||||
|
failif((semtest_current != num));
|
||||||
}
|
}
|
||||||
kprintf("\n");
|
kprintf_n("\n");
|
||||||
|
|
||||||
V(donesem);
|
V(donesem);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
semtest(int nargs, char **args)
|
semtest(int nargs, char **args)
|
||||||
{
|
{
|
||||||
int i, result;
|
|
||||||
|
|
||||||
(void)nargs;
|
(void)nargs;
|
||||||
(void)args;
|
(void)args;
|
||||||
|
|
||||||
inititems();
|
int i, result;
|
||||||
kprintf("Starting semaphore test...\n");
|
|
||||||
kprintf("If this hangs, it's broken: ");
|
kprintf_n("Starting sem1...\n");
|
||||||
|
for (i=0; i<CREATELOOPS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
|
testsem = sem_create("testsem", 2);
|
||||||
|
if (testsem == NULL) {
|
||||||
|
panic("sem1: sem_create failed\n");
|
||||||
|
}
|
||||||
|
donesem = sem_create("donesem", 0);
|
||||||
|
if (donesem == NULL) {
|
||||||
|
panic("sem1: sem_create failed\n");
|
||||||
|
}
|
||||||
|
if (i != CREATELOOPS - 1) {
|
||||||
|
sem_destroy(testsem);
|
||||||
|
sem_destroy(donesem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spinlock_init(&status_lock);
|
||||||
|
test_status = TEST161_SUCCESS;
|
||||||
|
|
||||||
|
kprintf_n("If this hangs, it's broken: ");
|
||||||
P(testsem);
|
P(testsem);
|
||||||
P(testsem);
|
P(testsem);
|
||||||
kprintf("ok\n");
|
kprintf_n("OK\n");
|
||||||
|
kprintf_t(".");
|
||||||
|
|
||||||
for (i=0; i<NTHREADS; i++) {
|
for (i=0; i<NTHREADS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
result = thread_fork("semtest", NULL, semtestthread, NULL, i);
|
result = thread_fork("semtest", NULL, semtestthread, NULL, i);
|
||||||
if (result) {
|
if (result) {
|
||||||
panic("semtest: thread_fork failed: %s\n",
|
panic("sem1: thread_fork failed: %s\n",
|
||||||
strerror(result));
|
strerror(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<NTHREADS; i++) {
|
for (i=0; i<NTHREADS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
V(testsem);
|
V(testsem);
|
||||||
P(donesem);
|
P(donesem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* so we can run it again */
|
sem_destroy(testsem);
|
||||||
V(testsem);
|
sem_destroy(donesem);
|
||||||
V(testsem);
|
testsem = donesem = NULL;
|
||||||
|
|
||||||
|
kprintf_t("\n");
|
||||||
|
success(test_status, SECRET, "sem1");
|
||||||
|
|
||||||
kprintf("Semaphore test done.\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
fail(unsigned long num, const char *msg)
|
|
||||||
{
|
|
||||||
kprintf("thread %lu: Mismatch on %s\n", num, msg);
|
|
||||||
kprintf("Test failed\n");
|
|
||||||
|
|
||||||
lock_release(testlock);
|
|
||||||
|
|
||||||
V(donesem);
|
|
||||||
thread_exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
locktestthread(void *junk, unsigned long num)
|
locktestthread(void *junk, unsigned long num)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
(void)junk;
|
(void)junk;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
for (i=0; i<NLOCKLOOPS; i++) {
|
for (i=0; i<NLOCKLOOPS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
lock_acquire(testlock);
|
lock_acquire(testlock);
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
testval1 = num;
|
testval1 = num;
|
||||||
testval2 = num*num;
|
testval2 = num*num;
|
||||||
testval3 = num%3;
|
testval3 = num%3;
|
||||||
|
|
||||||
if (testval2 != testval1*testval1) {
|
if (testval2 != testval1*testval1) {
|
||||||
fail(num, "testval2/testval1");
|
goto fail;
|
||||||
}
|
}
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
if (testval2%3 != (testval3*testval3)%3) {
|
if (testval2%3 != (testval3*testval3)%3) {
|
||||||
fail(num, "testval2/testval3");
|
goto fail;
|
||||||
}
|
}
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
if (testval3 != testval1%3) {
|
if (testval3 != testval1%3) {
|
||||||
fail(num, "testval3/testval1");
|
goto fail;
|
||||||
}
|
}
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
if (testval1 != num) {
|
if (testval1 != num) {
|
||||||
fail(num, "testval1/num");
|
goto fail;
|
||||||
}
|
}
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
if (testval2 != num*num) {
|
if (testval2 != num*num) {
|
||||||
fail(num, "testval2/num");
|
goto fail;
|
||||||
}
|
}
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
if (testval3 != num%3) {
|
if (testval3 != num%3) {
|
||||||
fail(num, "testval3/num");
|
goto fail;
|
||||||
}
|
}
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
|
if (!(lock_do_i_hold(testlock))) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
lock_release(testlock);
|
lock_release(testlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for solutions that don't track ownership properly */
|
||||||
|
|
||||||
|
for (i=0; i<NLOCKLOOPS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
|
if (lock_do_i_hold(testlock)) {
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
V(donesem);
|
V(donesem);
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
lock_release(testlock);
|
||||||
|
fail2:
|
||||||
|
failif(true);
|
||||||
|
V(donesem);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
locktest(int nargs, char **args)
|
locktest(int nargs, char **args)
|
||||||
{
|
{
|
||||||
int i, result;
|
|
||||||
|
|
||||||
(void)nargs;
|
(void)nargs;
|
||||||
(void)args;
|
(void)args;
|
||||||
|
|
||||||
inititems();
|
int i, result;
|
||||||
kprintf("Starting lock test...\n");
|
|
||||||
|
kprintf_n("Starting lt1...\n");
|
||||||
|
for (i=0; i<CREATELOOPS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
|
testlock = lock_create("testlock");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("lt1: lock_create failed\n");
|
||||||
|
}
|
||||||
|
donesem = sem_create("donesem", 0);
|
||||||
|
if (donesem == NULL) {
|
||||||
|
panic("lt1: sem_create failed\n");
|
||||||
|
}
|
||||||
|
if (i != CREATELOOPS - 1) {
|
||||||
|
lock_destroy(testlock);
|
||||||
|
sem_destroy(donesem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spinlock_init(&status_lock);
|
||||||
|
test_status = TEST161_SUCCESS;
|
||||||
|
|
||||||
for (i=0; i<NTHREADS; i++) {
|
for (i=0; i<NTHREADS; i++) {
|
||||||
result = thread_fork("synchtest", NULL, locktestthread,
|
kprintf_t(".");
|
||||||
NULL, i);
|
result = thread_fork("synchtest", NULL, locktestthread, NULL, i);
|
||||||
if (result) {
|
if (result) {
|
||||||
panic("locktest: thread_fork failed: %s\n",
|
panic("lt1: thread_fork failed: %s\n", strerror(result));
|
||||||
strerror(result));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i=0; i<NTHREADS; i++) {
|
for (i=0; i<NTHREADS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
P(donesem);
|
P(donesem);
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("Lock test done.\n");
|
lock_destroy(testlock);
|
||||||
|
sem_destroy(donesem);
|
||||||
|
testlock = NULL;
|
||||||
|
donesem = NULL;
|
||||||
|
|
||||||
|
kprintf_t("\n");
|
||||||
|
success(test_status, SECRET, "lt1");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
locktest2(int nargs, char **args) {
|
||||||
|
(void)nargs;
|
||||||
|
(void)args;
|
||||||
|
|
||||||
|
kprintf_n("Starting lt2...\n");
|
||||||
|
kprintf_n("(This test panics on success!)\n");
|
||||||
|
|
||||||
|
testlock = lock_create("testlock");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("lt2: lock_create failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
secprintf(SECRET, "Should panic...", "lt2");
|
||||||
|
lock_release(testlock);
|
||||||
|
|
||||||
|
/* Should not get here on success. */
|
||||||
|
|
||||||
|
success(TEST161_FAIL, SECRET, "lt2");
|
||||||
|
|
||||||
|
lock_destroy(testlock);
|
||||||
|
testlock = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
locktest3(int nargs, char **args) {
|
||||||
|
(void)nargs;
|
||||||
|
(void)args;
|
||||||
|
|
||||||
|
kprintf_n("Starting lt3...\n");
|
||||||
|
kprintf_n("(This test panics on success!)\n");
|
||||||
|
|
||||||
|
testlock = lock_create("testlock");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("lt3: lock_create failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
secprintf(SECRET, "Should panic...", "lt3");
|
||||||
|
lock_acquire(testlock);
|
||||||
|
lock_destroy(testlock);
|
||||||
|
|
||||||
|
/* Should not get here on success. */
|
||||||
|
|
||||||
|
success(TEST161_FAIL, SECRET, "lt3");
|
||||||
|
|
||||||
|
testlock = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -224,35 +345,38 @@ static
|
|||||||
void
|
void
|
||||||
cvtestthread(void *junk, unsigned long num)
|
cvtestthread(void *junk, unsigned long num)
|
||||||
{
|
{
|
||||||
|
(void)junk;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
volatile int j;
|
volatile int j;
|
||||||
struct timespec ts1, ts2;
|
struct timespec ts1, ts2;
|
||||||
|
|
||||||
(void)junk;
|
|
||||||
|
|
||||||
for (i=0; i<NCVLOOPS; i++) {
|
for (i=0; i<NCVLOOPS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
lock_acquire(testlock);
|
lock_acquire(testlock);
|
||||||
while (testval1 != num) {
|
while (testval1 != num) {
|
||||||
|
testval2 = 0;
|
||||||
|
random_yielder(4);
|
||||||
gettime(&ts1);
|
gettime(&ts1);
|
||||||
cv_wait(testcv, testlock);
|
cv_wait(testcv, testlock);
|
||||||
gettime(&ts2);
|
gettime(&ts2);
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
/* ts2 -= ts1 */
|
/* ts2 -= ts1 */
|
||||||
timespec_sub(&ts2, &ts1, &ts2);
|
timespec_sub(&ts2, &ts1, &ts2);
|
||||||
|
|
||||||
/* Require at least 2000 cpu cycles (we're 25mhz) */
|
/* Require at least 2000 cpu cycles (we're 25mhz) */
|
||||||
if (ts2.tv_sec == 0 && ts2.tv_nsec < 40*2000) {
|
if (ts2.tv_sec == 0 && ts2.tv_nsec < 40*2000) {
|
||||||
kprintf("cv_wait took only %u ns\n",
|
kprintf_n("cv_wait took only %u ns\n", ts2.tv_nsec);
|
||||||
ts2.tv_nsec);
|
kprintf_n("That's too fast... you must be busy-looping\n");
|
||||||
kprintf("That's too fast... you must be "
|
failif(true);
|
||||||
"busy-looping\n");
|
|
||||||
V(donesem);
|
V(donesem);
|
||||||
thread_exit();
|
thread_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testval2 = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
kprintf("Thread %lu\n", num);
|
testval2 = num;
|
||||||
testval1 = (testval1 + NTHREADS - 1)%NTHREADS;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* loop a little while to make sure we can measure the
|
* loop a little while to make sure we can measure the
|
||||||
@ -260,7 +384,13 @@ cvtestthread(void *junk, unsigned long num)
|
|||||||
*/
|
*/
|
||||||
for (j=0; j<3000; j++);
|
for (j=0; j<3000; j++);
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
cv_broadcast(testcv, testlock);
|
cv_broadcast(testcv, testlock);
|
||||||
|
random_yielder(4);
|
||||||
|
failif((testval1 != testval2));
|
||||||
|
|
||||||
|
kprintf_n("Thread %lu\n", testval2);
|
||||||
|
testval1 = (testval1 + NTHREADS - 1) % NTHREADS;
|
||||||
lock_release(testlock);
|
lock_release(testlock);
|
||||||
}
|
}
|
||||||
V(donesem);
|
V(donesem);
|
||||||
@ -269,30 +399,57 @@ cvtestthread(void *junk, unsigned long num)
|
|||||||
int
|
int
|
||||||
cvtest(int nargs, char **args)
|
cvtest(int nargs, char **args)
|
||||||
{
|
{
|
||||||
|
|
||||||
int i, result;
|
|
||||||
|
|
||||||
(void)nargs;
|
(void)nargs;
|
||||||
(void)args;
|
(void)args;
|
||||||
|
|
||||||
inititems();
|
int i, result;
|
||||||
kprintf("Starting CV test...\n");
|
|
||||||
kprintf("Threads should print out in reverse order.\n");
|
kprintf_n("Starting cvt1...\n");
|
||||||
|
for (i=0; i<CREATELOOPS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
|
testlock = lock_create("testlock");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("cvt1: lock_create failed\n");
|
||||||
|
}
|
||||||
|
testcv = cv_create("testcv");
|
||||||
|
if (testcv == NULL) {
|
||||||
|
panic("cvt1: cv_create failed\n");
|
||||||
|
}
|
||||||
|
donesem = sem_create("donesem", 0);
|
||||||
|
if (donesem == NULL) {
|
||||||
|
panic("cvt1: sem_create failed\n");
|
||||||
|
}
|
||||||
|
if (i != CREATELOOPS - 1) {
|
||||||
|
lock_destroy(testlock);
|
||||||
|
cv_destroy(testcv);
|
||||||
|
sem_destroy(donesem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spinlock_init(&status_lock);
|
||||||
|
test_status = TEST161_SUCCESS;
|
||||||
|
|
||||||
testval1 = NTHREADS-1;
|
testval1 = NTHREADS-1;
|
||||||
|
|
||||||
for (i=0; i<NTHREADS; i++) {
|
for (i=0; i<NTHREADS; i++) {
|
||||||
result = thread_fork("synchtest", NULL, cvtestthread, NULL, i);
|
kprintf_t(".");
|
||||||
|
result = thread_fork("cvt1", NULL, cvtestthread, NULL, (long unsigned) i);
|
||||||
if (result) {
|
if (result) {
|
||||||
panic("cvtest: thread_fork failed: %s\n",
|
panic("cvt1: thread_fork failed: %s\n", strerror(result));
|
||||||
strerror(result));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i=0; i<NTHREADS; i++) {
|
for (i=0; i<NTHREADS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
P(donesem);
|
P(donesem);
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("CV test done\n");
|
lock_destroy(testlock);
|
||||||
|
cv_destroy(testcv);
|
||||||
|
sem_destroy(donesem);
|
||||||
|
testlock = NULL;
|
||||||
|
testcv = NULL;
|
||||||
|
donesem = NULL;
|
||||||
|
|
||||||
|
kprintf_t("\n");
|
||||||
|
success(test_status, SECRET, "cvt1");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -318,19 +475,28 @@ static
|
|||||||
void
|
void
|
||||||
sleepthread(void *junk1, unsigned long junk2)
|
sleepthread(void *junk1, unsigned long junk2)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
|
||||||
|
|
||||||
(void)junk1;
|
(void)junk1;
|
||||||
(void)junk2;
|
(void)junk2;
|
||||||
|
|
||||||
|
unsigned i, j;
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
for (j=0; j<NLOOPS; j++) {
|
for (j=0; j<NLOOPS; j++) {
|
||||||
|
kprintf_t(".");
|
||||||
for (i=0; i<NCVS; i++) {
|
for (i=0; i<NCVS; i++) {
|
||||||
lock_acquire(testlocks[i]);
|
lock_acquire(testlocks[i]);
|
||||||
|
random_yielder(4);
|
||||||
V(gatesem);
|
V(gatesem);
|
||||||
|
random_yielder(4);
|
||||||
|
spinlock_acquire(&status_lock);
|
||||||
|
testval4++;
|
||||||
|
spinlock_release(&status_lock);
|
||||||
cv_wait(testcvs[i], testlocks[i]);
|
cv_wait(testcvs[i], testlocks[i]);
|
||||||
|
random_yielder(4);
|
||||||
lock_release(testlocks[i]);
|
lock_release(testlocks[i]);
|
||||||
}
|
}
|
||||||
kprintf("sleepthread: %u\n", j);
|
kprintf_n("sleepthread: %u\n", j);
|
||||||
}
|
}
|
||||||
V(exitsem);
|
V(exitsem);
|
||||||
}
|
}
|
||||||
@ -339,19 +505,28 @@ static
|
|||||||
void
|
void
|
||||||
wakethread(void *junk1, unsigned long junk2)
|
wakethread(void *junk1, unsigned long junk2)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
|
||||||
|
|
||||||
(void)junk1;
|
(void)junk1;
|
||||||
(void)junk2;
|
(void)junk2;
|
||||||
|
|
||||||
|
unsigned i, j;
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
for (j=0; j<NLOOPS; j++) {
|
for (j=0; j<NLOOPS; j++) {
|
||||||
|
kprintf_t(".");
|
||||||
for (i=0; i<NCVS; i++) {
|
for (i=0; i<NCVS; i++) {
|
||||||
|
random_yielder(4);
|
||||||
P(gatesem);
|
P(gatesem);
|
||||||
|
random_yielder(4);
|
||||||
lock_acquire(testlocks[i]);
|
lock_acquire(testlocks[i]);
|
||||||
|
random_yielder(4);
|
||||||
|
testval4--;
|
||||||
|
failif((testval4 != 0));
|
||||||
cv_signal(testcvs[i], testlocks[i]);
|
cv_signal(testcvs[i], testlocks[i]);
|
||||||
|
random_yielder(4);
|
||||||
lock_release(testlocks[i]);
|
lock_release(testlocks[i]);
|
||||||
}
|
}
|
||||||
kprintf("wakethread: %u\n", j);
|
kprintf_n("wakethread: %u\n", j);
|
||||||
}
|
}
|
||||||
V(exitsem);
|
V(exitsem);
|
||||||
}
|
}
|
||||||
@ -359,30 +534,44 @@ wakethread(void *junk1, unsigned long junk2)
|
|||||||
int
|
int
|
||||||
cvtest2(int nargs, char **args)
|
cvtest2(int nargs, char **args)
|
||||||
{
|
{
|
||||||
unsigned i;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
(void)nargs;
|
(void)nargs;
|
||||||
(void)args;
|
(void)args;
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
kprintf_n("Starting cvt2...\n");
|
||||||
|
for (i=0; i<CREATELOOPS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
|
gatesem = sem_create("gatesem", 0);
|
||||||
|
if (gatesem == NULL) {
|
||||||
|
panic("cvt2: sem_create failed\n");
|
||||||
|
}
|
||||||
|
exitsem = sem_create("exitsem", 0);
|
||||||
|
if (exitsem == NULL) {
|
||||||
|
panic("cvt2: sem_create failed\n");
|
||||||
|
}
|
||||||
|
if (i != CREATELOOPS - 1) {
|
||||||
|
sem_destroy(gatesem);
|
||||||
|
sem_destroy(exitsem);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (i=0; i<NCVS; i++) {
|
for (i=0; i<NCVS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
testlocks[i] = lock_create("cvtest2 lock");
|
testlocks[i] = lock_create("cvtest2 lock");
|
||||||
testcvs[i] = cv_create("cvtest2 cv");
|
testcvs[i] = cv_create("cvtest2 cv");
|
||||||
}
|
}
|
||||||
gatesem = sem_create("gatesem", 0);
|
spinlock_init(&status_lock);
|
||||||
exitsem = sem_create("exitsem", 0);
|
test_status = TEST161_SUCCESS;
|
||||||
|
|
||||||
kprintf("cvtest2...\n");
|
result = thread_fork("cvt2", NULL, sleepthread, NULL, 0);
|
||||||
|
|
||||||
result = thread_fork("cvtest2", NULL, sleepthread, NULL, 0);
|
|
||||||
if (result) {
|
if (result) {
|
||||||
panic("cvtest2: thread_fork failed\n");
|
panic("cvt2: thread_fork failed\n");
|
||||||
}
|
}
|
||||||
result = thread_fork("cvtest2", NULL, wakethread, NULL, 0);
|
result = thread_fork("cvt2", NULL, wakethread, NULL, 0);
|
||||||
if (result) {
|
if (result) {
|
||||||
panic("cvtest2: thread_fork failed\n");
|
panic("cvt2: thread_fork failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
P(exitsem);
|
P(exitsem);
|
||||||
P(exitsem);
|
P(exitsem);
|
||||||
|
|
||||||
@ -390,12 +579,194 @@ cvtest2(int nargs, char **args)
|
|||||||
sem_destroy(gatesem);
|
sem_destroy(gatesem);
|
||||||
exitsem = gatesem = NULL;
|
exitsem = gatesem = NULL;
|
||||||
for (i=0; i<NCVS; i++) {
|
for (i=0; i<NCVS; i++) {
|
||||||
|
kprintf_t(".");
|
||||||
lock_destroy(testlocks[i]);
|
lock_destroy(testlocks[i]);
|
||||||
cv_destroy(testcvs[i]);
|
cv_destroy(testcvs[i]);
|
||||||
testlocks[i] = NULL;
|
testlocks[i] = NULL;
|
||||||
testcvs[i] = NULL;
|
testcvs[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("cvtest2 done\n");
|
kprintf_t("\n");
|
||||||
|
success(test_status, SECRET, "cvt2");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cvtest3(int nargs, char **args) {
|
||||||
|
(void)nargs;
|
||||||
|
(void)args;
|
||||||
|
|
||||||
|
kprintf_n("Starting cvt3...\n");
|
||||||
|
kprintf_n("(This test panics on success!)\n");
|
||||||
|
|
||||||
|
testlock = lock_create("testlock");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("cvt3: lock_create failed\n");
|
||||||
|
}
|
||||||
|
testcv = cv_create("testcv");
|
||||||
|
if (testcv == NULL) {
|
||||||
|
panic("cvt3: cv_create failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
secprintf(SECRET, "Should panic...", "cvt3");
|
||||||
|
cv_wait(testcv, testlock);
|
||||||
|
|
||||||
|
/* Should not get here on success. */
|
||||||
|
|
||||||
|
success(TEST161_FAIL, SECRET, "cvt3");
|
||||||
|
|
||||||
|
lock_destroy(testlock);
|
||||||
|
cv_destroy(testcv);
|
||||||
|
testcv = NULL;
|
||||||
|
testlock = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cvtest4(int nargs, char **args) {
|
||||||
|
(void)nargs;
|
||||||
|
(void)args;
|
||||||
|
|
||||||
|
kprintf_n("Starting cvt4...\n");
|
||||||
|
kprintf_n("(This test panics on success!)\n");
|
||||||
|
|
||||||
|
testlock = lock_create("testlock");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("cvt4: lock_create failed\n");
|
||||||
|
}
|
||||||
|
testcv = cv_create("testcv");
|
||||||
|
if (testcv == NULL) {
|
||||||
|
panic("cvt4: cv_create failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
secprintf(SECRET, "Should panic...", "cvt4");
|
||||||
|
cv_broadcast(testcv, testlock);
|
||||||
|
|
||||||
|
/* Should not get here on success. */
|
||||||
|
|
||||||
|
success(TEST161_FAIL, SECRET, "cvt4");
|
||||||
|
|
||||||
|
lock_destroy(testlock);
|
||||||
|
cv_destroy(testcv);
|
||||||
|
testcv = NULL;
|
||||||
|
testlock = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
sleeperthread(void *junk1, unsigned long junk2) {
|
||||||
|
(void)junk1;
|
||||||
|
(void)junk2;
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
lock_acquire(testlock);
|
||||||
|
random_yielder(4);
|
||||||
|
failif((testval1 != 0));
|
||||||
|
testval1 = 1;
|
||||||
|
cv_signal(testcv, testlock);
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
cv_wait(testcv, testlock);
|
||||||
|
failif((testval1 != 3));
|
||||||
|
testval1 = 4;
|
||||||
|
random_yielder(4);
|
||||||
|
lock_release(testlock);
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
|
V(exitsem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
wakerthread(void *junk1, unsigned long junk2) {
|
||||||
|
(void)junk1;
|
||||||
|
(void)junk2;
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
lock_acquire(testlock2);
|
||||||
|
failif((testval1 != 2));
|
||||||
|
testval1 = 3;
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
cv_signal(testcv, testlock2);
|
||||||
|
random_yielder(4);
|
||||||
|
lock_release(testlock2);
|
||||||
|
random_yielder(4);
|
||||||
|
|
||||||
|
V(exitsem);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cvtest5(int nargs, char **args) {
|
||||||
|
(void)nargs;
|
||||||
|
(void)args;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
|
||||||
|
kprintf_n("Starting cvt5...\n");
|
||||||
|
|
||||||
|
testlock = lock_create("testlock");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("cvt5: lock_create failed\n");
|
||||||
|
}
|
||||||
|
testlock2 = lock_create("testlock2");
|
||||||
|
if (testlock == NULL) {
|
||||||
|
panic("cvt5: lock_create failed\n");
|
||||||
|
}
|
||||||
|
testcv = cv_create("testcv");
|
||||||
|
if (testcv == NULL) {
|
||||||
|
panic("cvt5: cv_create failed\n");
|
||||||
|
}
|
||||||
|
exitsem = sem_create("exitsem", 0);
|
||||||
|
if (exitsem == NULL) {
|
||||||
|
panic("cvt5: sem_create failed\n");
|
||||||
|
}
|
||||||
|
spinlock_init(&status_lock);
|
||||||
|
test_status = TEST161_SUCCESS;
|
||||||
|
testval1 = 0;
|
||||||
|
|
||||||
|
lock_acquire(testlock);
|
||||||
|
lock_acquire(testlock2);
|
||||||
|
|
||||||
|
result = thread_fork("cvt5", NULL, sleeperthread, NULL, 0);
|
||||||
|
if (result) {
|
||||||
|
panic("cvt5: thread_fork failed\n");
|
||||||
|
}
|
||||||
|
result = thread_fork("cvt5", NULL, wakerthread, NULL, 0);
|
||||||
|
if (result) {
|
||||||
|
panic("cvt5: thread_fork failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
random_yielder(4);
|
||||||
|
cv_wait(testcv, testlock);
|
||||||
|
failif((testval1 != 1));
|
||||||
|
testval1 = 2;
|
||||||
|
random_yielder(4);
|
||||||
|
lock_release(testlock);
|
||||||
|
random_yielder(4);
|
||||||
|
lock_release(testlock2);
|
||||||
|
|
||||||
|
P(exitsem);
|
||||||
|
P(exitsem);
|
||||||
|
failif((testval1 != 4));
|
||||||
|
|
||||||
|
sem_destroy(exitsem);
|
||||||
|
cv_destroy(testcv);
|
||||||
|
lock_destroy(testlock2);
|
||||||
|
lock_destroy(testlock);
|
||||||
|
|
||||||
|
success(test_status, SECRET, "cvt5");
|
||||||
|
|
||||||
|
exitsem = NULL;
|
||||||
|
testcv = NULL;
|
||||||
|
testlock2 = NULL;
|
||||||
|
testlock = NULL;
|
||||||
|
testsem2 = NULL;
|
||||||
|
testsem = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,7 @@ fakethread_create(const char *name)
|
|||||||
}
|
}
|
||||||
/* ignore most of the fields, zero everything for tidiness */
|
/* ignore most of the fields, zero everything for tidiness */
|
||||||
bzero(t, sizeof(*t));
|
bzero(t, sizeof(*t));
|
||||||
t->t_name = kstrdup(name);
|
strcpy(t->t_name, name);
|
||||||
if (t->t_name == NULL) {
|
|
||||||
panic("threadlisttest: Out of memory\n");
|
|
||||||
}
|
|
||||||
t->t_stack = FAKE_MAGIC;
|
t->t_stack = FAKE_MAGIC;
|
||||||
threadlistnode_init(&t->t_listnode, t);
|
threadlistnode_init(&t->t_listnode, t);
|
||||||
return t;
|
return t;
|
||||||
@ -84,7 +81,6 @@ fakethread_destroy(struct thread *t)
|
|||||||
{
|
{
|
||||||
KASSERT(t->t_stack == FAKE_MAGIC);
|
KASSERT(t->t_stack == FAKE_MAGIC);
|
||||||
threadlistnode_cleanup(&t->t_listnode);
|
threadlistnode_cleanup(&t->t_listnode);
|
||||||
kfree(t->t_name);
|
|
||||||
kfree(t);
|
kfree(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,18 +47,18 @@
|
|||||||
struct semaphore *
|
struct semaphore *
|
||||||
sem_create(const char *name, unsigned initial_count)
|
sem_create(const char *name, unsigned initial_count)
|
||||||
{
|
{
|
||||||
struct semaphore *sem;
|
struct semaphore *sem;
|
||||||
|
|
||||||
sem = kmalloc(sizeof(*sem));
|
sem = kmalloc(sizeof(*sem));
|
||||||
if (sem == NULL) {
|
if (sem == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sem->sem_name = kstrdup(name);
|
sem->sem_name = kstrdup(name);
|
||||||
if (sem->sem_name == NULL) {
|
if (sem->sem_name == NULL) {
|
||||||
kfree(sem);
|
kfree(sem);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sem->sem_wchan = wchan_create(sem->sem_name);
|
sem->sem_wchan = wchan_create(sem->sem_name);
|
||||||
if (sem->sem_wchan == NULL) {
|
if (sem->sem_wchan == NULL) {
|
||||||
@ -68,39 +68,39 @@ sem_create(const char *name, unsigned initial_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spinlock_init(&sem->sem_lock);
|
spinlock_init(&sem->sem_lock);
|
||||||
sem->sem_count = initial_count;
|
sem->sem_count = initial_count;
|
||||||
|
|
||||||
return sem;
|
return sem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sem_destroy(struct semaphore *sem)
|
sem_destroy(struct semaphore *sem)
|
||||||
{
|
{
|
||||||
KASSERT(sem != NULL);
|
KASSERT(sem != NULL);
|
||||||
|
|
||||||
/* wchan_cleanup will assert if anyone's waiting on it */
|
/* wchan_cleanup will assert if anyone's waiting on it */
|
||||||
spinlock_cleanup(&sem->sem_lock);
|
spinlock_cleanup(&sem->sem_lock);
|
||||||
wchan_destroy(sem->sem_wchan);
|
wchan_destroy(sem->sem_wchan);
|
||||||
kfree(sem->sem_name);
|
kfree(sem->sem_name);
|
||||||
kfree(sem);
|
kfree(sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
P(struct semaphore *sem)
|
P(struct semaphore *sem)
|
||||||
{
|
{
|
||||||
KASSERT(sem != NULL);
|
KASSERT(sem != NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* May not block in an interrupt handler.
|
* May not block in an interrupt handler.
|
||||||
*
|
*
|
||||||
* For robustness, always check, even if we can actually
|
* For robustness, always check, even if we can actually
|
||||||
* complete the P without blocking.
|
* complete the P without blocking.
|
||||||
*/
|
*/
|
||||||
KASSERT(curthread->t_in_interrupt == false);
|
KASSERT(curthread->t_in_interrupt == false);
|
||||||
|
|
||||||
/* Use the semaphore spinlock to protect the wchan as well. */
|
/* Use the semaphore spinlock to protect the wchan as well. */
|
||||||
spinlock_acquire(&sem->sem_lock);
|
spinlock_acquire(&sem->sem_lock);
|
||||||
while (sem->sem_count == 0) {
|
while (sem->sem_count == 0) {
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Note that we don't maintain strict FIFO ordering of
|
* Note that we don't maintain strict FIFO ordering of
|
||||||
@ -114,21 +114,21 @@ P(struct semaphore *sem)
|
|||||||
* ordering?
|
* ordering?
|
||||||
*/
|
*/
|
||||||
wchan_sleep(sem->sem_wchan, &sem->sem_lock);
|
wchan_sleep(sem->sem_wchan, &sem->sem_lock);
|
||||||
}
|
}
|
||||||
KASSERT(sem->sem_count > 0);
|
KASSERT(sem->sem_count > 0);
|
||||||
sem->sem_count--;
|
sem->sem_count--;
|
||||||
spinlock_release(&sem->sem_lock);
|
spinlock_release(&sem->sem_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
V(struct semaphore *sem)
|
V(struct semaphore *sem)
|
||||||
{
|
{
|
||||||
KASSERT(sem != NULL);
|
KASSERT(sem != NULL);
|
||||||
|
|
||||||
spinlock_acquire(&sem->sem_lock);
|
spinlock_acquire(&sem->sem_lock);
|
||||||
|
|
||||||
sem->sem_count++;
|
sem->sem_count++;
|
||||||
KASSERT(sem->sem_count > 0);
|
KASSERT(sem->sem_count > 0);
|
||||||
wchan_wakeone(sem->sem_wchan, &sem->sem_lock);
|
wchan_wakeone(sem->sem_wchan, &sem->sem_lock);
|
||||||
|
|
||||||
spinlock_release(&sem->sem_lock);
|
spinlock_release(&sem->sem_lock);
|
||||||
@ -141,59 +141,59 @@ V(struct semaphore *sem)
|
|||||||
struct lock *
|
struct lock *
|
||||||
lock_create(const char *name)
|
lock_create(const char *name)
|
||||||
{
|
{
|
||||||
struct lock *lock;
|
struct lock *lock;
|
||||||
|
|
||||||
lock = kmalloc(sizeof(*lock));
|
lock = kmalloc(sizeof(*lock));
|
||||||
if (lock == NULL) {
|
if (lock == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock->lk_name = kstrdup(name);
|
lock->lk_name = kstrdup(name);
|
||||||
if (lock->lk_name == NULL) {
|
if (lock->lk_name == NULL) {
|
||||||
kfree(lock);
|
kfree(lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add stuff here as needed
|
// add stuff here as needed
|
||||||
|
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lock_destroy(struct lock *lock)
|
lock_destroy(struct lock *lock)
|
||||||
{
|
{
|
||||||
KASSERT(lock != NULL);
|
KASSERT(lock != NULL);
|
||||||
|
|
||||||
// add stuff here as needed
|
// add stuff here as needed
|
||||||
|
|
||||||
kfree(lock->lk_name);
|
kfree(lock->lk_name);
|
||||||
kfree(lock);
|
kfree(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lock_acquire(struct lock *lock)
|
lock_acquire(struct lock *lock)
|
||||||
{
|
{
|
||||||
// Write this
|
// Write this
|
||||||
|
|
||||||
(void)lock; // suppress warning until code gets written
|
(void)lock; // suppress warning until code gets written
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lock_release(struct lock *lock)
|
lock_release(struct lock *lock)
|
||||||
{
|
{
|
||||||
// Write this
|
// Write this
|
||||||
|
|
||||||
(void)lock; // suppress warning until code gets written
|
(void)lock; // suppress warning until code gets written
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
lock_do_i_hold(struct lock *lock)
|
lock_do_i_hold(struct lock *lock)
|
||||||
{
|
{
|
||||||
// Write this
|
// Write this
|
||||||
|
|
||||||
(void)lock; // suppress warning until code gets written
|
(void)lock; // suppress warning until code gets written
|
||||||
|
|
||||||
return true; // dummy until code gets written
|
return true; // dummy until code gets written
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -204,47 +204,47 @@ lock_do_i_hold(struct lock *lock)
|
|||||||
struct cv *
|
struct cv *
|
||||||
cv_create(const char *name)
|
cv_create(const char *name)
|
||||||
{
|
{
|
||||||
struct cv *cv;
|
struct cv *cv;
|
||||||
|
|
||||||
cv = kmalloc(sizeof(*cv));
|
cv = kmalloc(sizeof(*cv));
|
||||||
if (cv == NULL) {
|
if (cv == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cv->cv_name = kstrdup(name);
|
cv->cv_name = kstrdup(name);
|
||||||
if (cv->cv_name==NULL) {
|
if (cv->cv_name==NULL) {
|
||||||
kfree(cv);
|
kfree(cv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add stuff here as needed
|
// add stuff here as needed
|
||||||
|
|
||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cv_destroy(struct cv *cv)
|
cv_destroy(struct cv *cv)
|
||||||
{
|
{
|
||||||
KASSERT(cv != NULL);
|
KASSERT(cv != NULL);
|
||||||
|
|
||||||
// add stuff here as needed
|
// add stuff here as needed
|
||||||
|
|
||||||
kfree(cv->cv_name);
|
kfree(cv->cv_name);
|
||||||
kfree(cv);
|
kfree(cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cv_wait(struct cv *cv, struct lock *lock)
|
cv_wait(struct cv *cv, struct lock *lock)
|
||||||
{
|
{
|
||||||
// Write this
|
// Write this
|
||||||
(void)cv; // suppress warning until code gets written
|
(void)cv; // suppress warning until code gets written
|
||||||
(void)lock; // suppress warning until code gets written
|
(void)lock; // suppress warning until code gets written
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cv_signal(struct cv *cv, struct lock *lock)
|
cv_signal(struct cv *cv, struct lock *lock)
|
||||||
{
|
{
|
||||||
// Write this
|
// Write this
|
||||||
(void)cv; // suppress warning until code gets written
|
(void)cv; // suppress warning until code gets written
|
||||||
(void)lock; // suppress warning until code gets written
|
(void)lock; // suppress warning until code gets written
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,16 @@ struct wchan {
|
|||||||
DECLARRAY(cpu, static __UNUSED inline);
|
DECLARRAY(cpu, static __UNUSED inline);
|
||||||
DEFARRAY(cpu, static __UNUSED inline);
|
DEFARRAY(cpu, static __UNUSED inline);
|
||||||
static struct cpuarray allcpus;
|
static struct cpuarray allcpus;
|
||||||
|
unsigned num_cpus;
|
||||||
|
|
||||||
/* Used to wait for secondary CPUs to come online. */
|
/* Used to wait for secondary CPUs to come online. */
|
||||||
static struct semaphore *cpu_startup_sem;
|
static struct semaphore *cpu_startup_sem;
|
||||||
|
|
||||||
|
/* Used to synchronize exit cleanup. */
|
||||||
|
unsigned thread_count = 0;
|
||||||
|
static struct spinlock thread_count_lock = SPINLOCK_INITIALIZER;
|
||||||
|
static struct wchan *thread_count_wchan;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -119,17 +125,16 @@ thread_create(const char *name)
|
|||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
|
|
||||||
DEBUGASSERT(name != NULL);
|
DEBUGASSERT(name != NULL);
|
||||||
|
if (strlen(name) > MAX_NAME_LENGTH) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
thread = kmalloc(sizeof(*thread));
|
thread = kmalloc(sizeof(*thread));
|
||||||
if (thread == NULL) {
|
if (thread == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->t_name = kstrdup(name);
|
strcpy(thread->t_name, name);
|
||||||
if (thread->t_name == NULL) {
|
|
||||||
kfree(thread);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
thread->t_wchan_name = "NEW";
|
thread->t_wchan_name = "NEW";
|
||||||
thread->t_state = S_READY;
|
thread->t_state = S_READY;
|
||||||
|
|
||||||
@ -256,6 +261,9 @@ cpu_create(unsigned hardware_number)
|
|||||||
* Nor can it be called on a running thread.
|
* Nor can it be called on a running thread.
|
||||||
*
|
*
|
||||||
* (Freeing the stack you're actually using to run is ... inadvisable.)
|
* (Freeing the stack you're actually using to run is ... inadvisable.)
|
||||||
|
*
|
||||||
|
* Thread destroy should finish the process of cleaning up a thread started by
|
||||||
|
* thread_exit.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
@ -264,11 +272,6 @@ thread_destroy(struct thread *thread)
|
|||||||
KASSERT(thread != curthread);
|
KASSERT(thread != curthread);
|
||||||
KASSERT(thread->t_state != S_RUN);
|
KASSERT(thread->t_state != S_RUN);
|
||||||
|
|
||||||
/*
|
|
||||||
* If you add things to struct thread, be sure to clean them up
|
|
||||||
* either here or in thread_exit(). (And not both...)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Thread subsystem fields */
|
/* Thread subsystem fields */
|
||||||
KASSERT(thread->t_proc == NULL);
|
KASSERT(thread->t_proc == NULL);
|
||||||
if (thread->t_stack != NULL) {
|
if (thread->t_stack != NULL) {
|
||||||
@ -280,7 +283,6 @@ thread_destroy(struct thread *thread)
|
|||||||
/* sheer paranoia */
|
/* sheer paranoia */
|
||||||
thread->t_wchan_name = "DESTROYED";
|
thread->t_wchan_name = "DESTROYED";
|
||||||
|
|
||||||
kfree(thread->t_name);
|
|
||||||
kfree(thread);
|
kfree(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,8 +413,6 @@ cpu_hatch(unsigned software_number)
|
|||||||
spl0();
|
spl0();
|
||||||
cpu_identify(buf, sizeof(buf));
|
cpu_identify(buf, sizeof(buf));
|
||||||
|
|
||||||
kprintf("cpu%u: %s\n", software_number, buf);
|
|
||||||
|
|
||||||
V(cpu_startup_sem);
|
V(cpu_startup_sem);
|
||||||
thread_exit();
|
thread_exit();
|
||||||
}
|
}
|
||||||
@ -430,13 +430,26 @@ thread_start_cpus(void)
|
|||||||
kprintf("cpu0: %s\n", buf);
|
kprintf("cpu0: %s\n", buf);
|
||||||
|
|
||||||
cpu_startup_sem = sem_create("cpu_hatch", 0);
|
cpu_startup_sem = sem_create("cpu_hatch", 0);
|
||||||
|
thread_count_wchan = wchan_create("thread_count");
|
||||||
mainbus_start_cpus();
|
mainbus_start_cpus();
|
||||||
|
|
||||||
for (i=0; i<cpuarray_num(&allcpus) - 1; i++) {
|
num_cpus = cpuarray_num(&allcpus);
|
||||||
|
for (i=0; i<num_cpus - 1; i++) {
|
||||||
P(cpu_startup_sem);
|
P(cpu_startup_sem);
|
||||||
}
|
}
|
||||||
sem_destroy(cpu_startup_sem);
|
sem_destroy(cpu_startup_sem);
|
||||||
|
if (i == 0) {
|
||||||
|
kprintf("1 CPU online\n");
|
||||||
|
} else {
|
||||||
|
kprintf("%d CPUs online\n", i + 1);
|
||||||
|
}
|
||||||
cpu_startup_sem = NULL;
|
cpu_startup_sem = NULL;
|
||||||
|
|
||||||
|
// Gross hack to deal with os/161 "idle" threads. Hardcode the thread count
|
||||||
|
// to 1 so the inc/dec properly works in thread_[fork/exit]. The one thread
|
||||||
|
// is the cpu0 boot thread (menu), which is the only thread that hasn't
|
||||||
|
// exited yet.
|
||||||
|
thread_count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -465,7 +478,7 @@ thread_make_runnable(struct thread *target, bool already_have_lock)
|
|||||||
target->t_state = S_READY;
|
target->t_state = S_READY;
|
||||||
threadlist_addtail(&targetcpu->c_runqueue, target);
|
threadlist_addtail(&targetcpu->c_runqueue, target);
|
||||||
|
|
||||||
if (targetcpu->c_isidle && targetcpu != curcpu->c_self) {
|
if (targetcpu->c_isidle) {
|
||||||
/*
|
/*
|
||||||
* Other processor is idle; send interrupt to make
|
* Other processor is idle; send interrupt to make
|
||||||
* sure it unidles.
|
* sure it unidles.
|
||||||
@ -535,6 +548,11 @@ thread_fork(const char *name,
|
|||||||
*/
|
*/
|
||||||
newthread->t_iplhigh_count++;
|
newthread->t_iplhigh_count++;
|
||||||
|
|
||||||
|
spinlock_acquire(&thread_count_lock);
|
||||||
|
++thread_count;
|
||||||
|
wchan_wakeall(thread_count_wchan, &thread_count_lock);
|
||||||
|
spinlock_release(&thread_count_lock);
|
||||||
|
|
||||||
/* Set up the switchframe so entrypoint() gets called */
|
/* Set up the switchframe so entrypoint() gets called */
|
||||||
switchframe_init(newthread, entrypoint, data1, data2);
|
switchframe_init(newthread, entrypoint, data1, data2);
|
||||||
|
|
||||||
@ -770,6 +788,13 @@ thread_startup(void (*entrypoint)(void *data1, unsigned long data2),
|
|||||||
* should be cleaned up right away. The rest has to wait until
|
* should be cleaned up right away. The rest has to wait until
|
||||||
* thread_destroy is called from exorcise().
|
* thread_destroy is called from exorcise().
|
||||||
*
|
*
|
||||||
|
* Note that any dynamically-allocated structures that can vary in size from
|
||||||
|
* thread to thread should be cleaned up here, not in thread_destroy. This is
|
||||||
|
* because the last thread left on each core runs the idle loop and does not
|
||||||
|
* get cleaned up until new threads are created. Differences in the amount of
|
||||||
|
* memory used by different threads after thread_exit will make it look like
|
||||||
|
* your kernel in leaking memory and cause some of the test161 checks to fail.
|
||||||
|
*
|
||||||
* Does not return.
|
* Does not return.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -791,8 +816,16 @@ thread_exit(void)
|
|||||||
/* Check the stack guard band. */
|
/* Check the stack guard band. */
|
||||||
thread_checkstack(cur);
|
thread_checkstack(cur);
|
||||||
|
|
||||||
|
// Decrement the thread count and notify anyone interested.
|
||||||
|
if (thread_count) {
|
||||||
|
spinlock_acquire(&thread_count_lock);
|
||||||
|
--thread_count;
|
||||||
|
wchan_wakeall(thread_count_wchan, &thread_count_lock);
|
||||||
|
spinlock_release(&thread_count_lock);
|
||||||
|
}
|
||||||
|
|
||||||
/* Interrupts off on this processor */
|
/* Interrupts off on this processor */
|
||||||
splhigh();
|
splhigh();
|
||||||
thread_switch(S_ZOMBIE, NULL, NULL);
|
thread_switch(S_ZOMBIE, NULL, NULL);
|
||||||
panic("braaaaaaaiiiiiiiiiiinssssss\n");
|
panic("braaaaaaaiiiiiiiiiiinssssss\n");
|
||||||
}
|
}
|
||||||
@ -1106,9 +1139,6 @@ ipi_send(struct cpu *target, int code)
|
|||||||
spinlock_release(&target->c_ipi_lock);
|
spinlock_release(&target->c_ipi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Send an IPI to all CPUs.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
ipi_broadcast(int code)
|
ipi_broadcast(int code)
|
||||||
{
|
{
|
||||||
@ -1123,28 +1153,16 @@ ipi_broadcast(int code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Send a TLB shootdown IPI to the specified CPU.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
|
ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
|
||||||
{
|
{
|
||||||
unsigned n;
|
int n;
|
||||||
|
|
||||||
spinlock_acquire(&target->c_ipi_lock);
|
spinlock_acquire(&target->c_ipi_lock);
|
||||||
|
|
||||||
n = target->c_numshootdown;
|
n = target->c_numshootdown;
|
||||||
if (n == TLBSHOOTDOWN_MAX) {
|
if (n == TLBSHOOTDOWN_MAX) {
|
||||||
/*
|
target->c_numshootdown = TLBSHOOTDOWN_ALL;
|
||||||
* If you have problems with this panic going off,
|
|
||||||
* consider: (1) increasing the maximum, (2) putting
|
|
||||||
* logic here to sleep until space appears (may
|
|
||||||
* interact awkwardly with VM system locking), (3)
|
|
||||||
* putting logic here to coalesce requests together,
|
|
||||||
* and/or (4) improving VM system state tracking to
|
|
||||||
* reduce the number of unnecessary shootdowns.
|
|
||||||
*/
|
|
||||||
panic("ipi_tlbshootdown: Too many shootdowns queued\n");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
target->c_shootdown[n] = *mapping;
|
target->c_shootdown[n] = *mapping;
|
||||||
@ -1157,14 +1175,11 @@ ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping)
|
|||||||
spinlock_release(&target->c_ipi_lock);
|
spinlock_release(&target->c_ipi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle an incoming interprocessor interrupt.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
interprocessor_interrupt(void)
|
interprocessor_interrupt(void)
|
||||||
{
|
{
|
||||||
uint32_t bits;
|
uint32_t bits;
|
||||||
unsigned i;
|
int i;
|
||||||
|
|
||||||
spinlock_acquire(&curcpu->c_ipi_lock);
|
spinlock_acquire(&curcpu->c_ipi_lock);
|
||||||
bits = curcpu->c_ipi_pending;
|
bits = curcpu->c_ipi_pending;
|
||||||
@ -1183,7 +1198,6 @@ interprocessor_interrupt(void)
|
|||||||
curcpu->c_number);
|
curcpu->c_number);
|
||||||
}
|
}
|
||||||
spinlock_release(&curcpu->c_runqueue_lock);
|
spinlock_release(&curcpu->c_runqueue_lock);
|
||||||
kprintf("cpu%d: offline.\n", curcpu->c_number);
|
|
||||||
cpu_halt();
|
cpu_halt();
|
||||||
}
|
}
|
||||||
if (bits & (1U << IPI_UNIDLE)) {
|
if (bits & (1U << IPI_UNIDLE)) {
|
||||||
@ -1193,13 +1207,13 @@ interprocessor_interrupt(void)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (bits & (1U << IPI_TLBSHOOTDOWN)) {
|
if (bits & (1U << IPI_TLBSHOOTDOWN)) {
|
||||||
/*
|
if (curcpu->c_numshootdown == TLBSHOOTDOWN_ALL) {
|
||||||
* Note: depending on your VM system locking you might
|
vm_tlbshootdown_all();
|
||||||
* need to release the ipi lock while calling
|
}
|
||||||
* vm_tlbshootdown.
|
else {
|
||||||
*/
|
for (i=0; i<curcpu->c_numshootdown; i++) {
|
||||||
for (i=0; i<curcpu->c_numshootdown; i++) {
|
vm_tlbshootdown(&curcpu->c_shootdown[i]);
|
||||||
vm_tlbshootdown(&curcpu->c_shootdown[i]);
|
}
|
||||||
}
|
}
|
||||||
curcpu->c_numshootdown = 0;
|
curcpu->c_numshootdown = 0;
|
||||||
}
|
}
|
||||||
@ -1207,3 +1221,15 @@ interprocessor_interrupt(void)
|
|||||||
curcpu->c_ipi_pending = 0;
|
curcpu->c_ipi_pending = 0;
|
||||||
spinlock_release(&curcpu->c_ipi_lock);
|
spinlock_release(&curcpu->c_ipi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for the thread count to equal tc.
|
||||||
|
*/
|
||||||
|
void thread_wait_for_count(unsigned tc)
|
||||||
|
{
|
||||||
|
spinlock_acquire(&thread_count_lock);
|
||||||
|
while (thread_count != tc) {
|
||||||
|
wchan_sleep(thread_count_wchan, &thread_count_lock);
|
||||||
|
}
|
||||||
|
spinlock_release(&thread_count_lock);
|
||||||
|
}
|
||||||
|
@ -82,9 +82,6 @@ struct knowndev {
|
|||||||
struct fs *kd_fs;
|
struct fs *kd_fs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A placeholder for kd_fs for devices used as swap */
|
|
||||||
#define SWAP_FS ((struct fs *)-1)
|
|
||||||
|
|
||||||
DECLARRAY(knowndev, static __UNUSED inline);
|
DECLARRAY(knowndev, static __UNUSED inline);
|
||||||
DEFARRAY(knowndev, static __UNUSED inline);
|
DEFARRAY(knowndev, static __UNUSED inline);
|
||||||
|
|
||||||
@ -163,7 +160,7 @@ vfs_sync(void)
|
|||||||
num = knowndevarray_num(knowndevs);
|
num = knowndevarray_num(knowndevs);
|
||||||
for (i=0; i<num; i++) {
|
for (i=0; i<num; i++) {
|
||||||
dev = knowndevarray_get(knowndevs, i);
|
dev = knowndevarray_get(knowndevs, i);
|
||||||
if (dev->kd_fs != NULL && dev->kd_fs != SWAP_FS) {
|
if (dev->kd_fs != NULL) {
|
||||||
/*result =*/ FSOP_SYNC(dev->kd_fs);
|
/*result =*/ FSOP_SYNC(dev->kd_fs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,7 +195,7 @@ vfs_getroot(const char *devname, struct vnode **ret)
|
|||||||
* and DEVNAME names the device, return ENXIO.
|
* and DEVNAME names the device, return ENXIO.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (kd->kd_fs != NULL && kd->kd_fs != SWAP_FS) {
|
if (kd->kd_fs!=NULL) {
|
||||||
const char *volname;
|
const char *volname;
|
||||||
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
||||||
|
|
||||||
@ -347,7 +344,7 @@ badnames(const char *n1, const char *n2, const char *n3)
|
|||||||
for (i=0; i<num; i++) {
|
for (i=0; i<num; i++) {
|
||||||
kd = knowndevarray_get(knowndevs, i);
|
kd = knowndevarray_get(knowndevs, i);
|
||||||
|
|
||||||
if (kd->kd_fs != NULL && kd->kd_fs != SWAP_FS) {
|
if (kd->kd_fs) {
|
||||||
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
volname = FSOP_GETVOLNAME(kd->kd_fs);
|
||||||
if (samestring3(volname, n1, n2, n3)) {
|
if (samestring3(volname, n1, n2, n3)) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -545,7 +542,6 @@ vfs_mount(const char *devname, void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
KASSERT(fs != NULL);
|
KASSERT(fs != NULL);
|
||||||
KASSERT(fs != SWAP_FS);
|
|
||||||
|
|
||||||
kd->kd_fs = fs;
|
kd->kd_fs = fs;
|
||||||
|
|
||||||
@ -557,59 +553,6 @@ vfs_mount(const char *devname, void *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Like mount, but for attaching swap. Hands back the raw device
|
|
||||||
* vnode. Unlike mount tolerates a trailing colon on the device name,
|
|
||||||
* to avoid student-facing confusion.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
vfs_swapon(const char *devname, struct vnode **ret)
|
|
||||||
{
|
|
||||||
char *myname = NULL;
|
|
||||||
size_t len;
|
|
||||||
struct knowndev *kd;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
len = strlen(devname);
|
|
||||||
if (len > 0 && devname[len - 1] == ':') {
|
|
||||||
/* tolerate trailing :, e.g. lhd0: rather than lhd0 */
|
|
||||||
myname = kstrdup(devname);
|
|
||||||
if (myname == NULL) {
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
myname[len - 1] = 0;
|
|
||||||
devname = myname;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfs_biglock_acquire();
|
|
||||||
|
|
||||||
result = findmount(devname, &kd);
|
|
||||||
if (result) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kd->kd_fs != NULL) {
|
|
||||||
result = EBUSY;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
KASSERT(kd->kd_rawname != NULL);
|
|
||||||
KASSERT(kd->kd_device != NULL);
|
|
||||||
|
|
||||||
kprintf("vfs: Swap attached to %s\n", kd->kd_name);
|
|
||||||
|
|
||||||
kd->kd_fs = SWAP_FS;
|
|
||||||
VOP_INCREF(kd->kd_vnode);
|
|
||||||
*ret = kd->kd_vnode;
|
|
||||||
|
|
||||||
out:
|
|
||||||
vfs_biglock_release();
|
|
||||||
if (myname != NULL) {
|
|
||||||
kfree(myname);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unmount a filesystem/device by name.
|
* Unmount a filesystem/device by name.
|
||||||
* First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT.
|
* First calls FSOP_SYNC on the filesystem; then calls FSOP_UNMOUNT.
|
||||||
@ -627,7 +570,7 @@ vfs_unmount(const char *devname)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kd->kd_fs == NULL || kd->kd_fs == SWAP_FS) {
|
if (kd->kd_fs == NULL) {
|
||||||
result = EINVAL;
|
result = EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -657,43 +600,6 @@ vfs_unmount(const char *devname)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Detach swap. Like unmount.
|
|
||||||
*
|
|
||||||
* (Provided for completeness; there is no real need to remove swap
|
|
||||||
* explicitly prior to shutting down, except perhaps when swapping to
|
|
||||||
* things that themselves want a clean shutdown, like RAIDs.)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
vfs_swapoff(const char *devname)
|
|
||||||
{
|
|
||||||
struct knowndev *kd;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
vfs_biglock_acquire();
|
|
||||||
|
|
||||||
result = findmount(devname, &kd);
|
|
||||||
if (result) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kd->kd_fs != SWAP_FS) {
|
|
||||||
result = EINVAL;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
kprintf("vfs: Swap detached from %s:\n", kd->kd_name);
|
|
||||||
|
|
||||||
/* drop it */
|
|
||||||
kd->kd_fs = NULL;
|
|
||||||
|
|
||||||
KASSERT(result==0);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
vfs_biglock_release();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global unmount function.
|
* Global unmount function.
|
||||||
*/
|
*/
|
||||||
@ -717,11 +623,6 @@ vfs_unmountall(void)
|
|||||||
/* not mounted */
|
/* not mounted */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (dev->kd_fs == SWAP_FS) {
|
|
||||||
/* just drop it */
|
|
||||||
dev->kd_fs = NULL;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
kprintf("vfs: Unmounting %s:\n", dev->kd_name);
|
kprintf("vfs: Unmounting %s:\n", dev->kd_name);
|
||||||
|
|
||||||
|
@ -129,8 +129,7 @@ vnode_decref(struct vnode *vn)
|
|||||||
void
|
void
|
||||||
vnode_check(struct vnode *v, const char *opstr)
|
vnode_check(struct vnode *v, const char *opstr)
|
||||||
{
|
{
|
||||||
/* not safe, and not really needed to check constant fields */
|
vfs_biglock_acquire();
|
||||||
/*vfs_biglock_acquire();*/
|
|
||||||
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
panic("vnode_check: vop_%s: null vnode\n", opstr);
|
panic("vnode_check: vop_%s: null vnode\n", opstr);
|
||||||
@ -174,5 +173,5 @@ vnode_check(struct vnode *v, const char *opstr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&v->vn_countlock);
|
spinlock_release(&v->vn_countlock);
|
||||||
/*vfs_biglock_release();*/
|
vfs_biglock_release();
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include <lib.h>
|
#include <lib.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <vm.h>
|
#include <vm.h>
|
||||||
|
#include <kern/test161.h>
|
||||||
|
#include <test.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel malloc.
|
* Kernel malloc.
|
||||||
@ -743,8 +745,8 @@ kheap_dumpall(void)
|
|||||||
* Print the allocated/freed map of a single kernel heap page.
|
* Print the allocated/freed map of a single kernel heap page.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void
|
unsigned long
|
||||||
subpage_stats(struct pageref *pr)
|
subpage_stats(struct pageref *pr, bool quiet)
|
||||||
{
|
{
|
||||||
vaddr_t prpage, fla;
|
vaddr_t prpage, fla;
|
||||||
struct freelist *fl;
|
struct freelist *fl;
|
||||||
@ -780,18 +782,21 @@ subpage_stats(struct pageref *pr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("at 0x%08lx: size %-4lu %u/%u free\n",
|
if (!quiet) {
|
||||||
(unsigned long)prpage, (unsigned long) sizes[blktype],
|
kprintf("at 0x%08lx: size %-4lu %u/%u free\n",
|
||||||
(unsigned) pr->nfree, n);
|
(unsigned long)prpage, (unsigned long) sizes[blktype],
|
||||||
kprintf(" ");
|
(unsigned) pr->nfree, n);
|
||||||
for (i=0; i<n; i++) {
|
kprintf(" ");
|
||||||
int val = (freemap[i/32] & (1<<(i%32)))!=0;
|
for (i=0; i<n; i++) {
|
||||||
kprintf("%c", val ? '.' : '*');
|
int val = (freemap[i/32] & (1<<(i%32)))!=0;
|
||||||
if (i%64==63 && i<n-1) {
|
kprintf("%c", val ? '.' : '*');
|
||||||
kprintf("\n ");
|
if (i%64==63 && i<n-1) {
|
||||||
|
kprintf("\n ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
kprintf("\n");
|
||||||
}
|
}
|
||||||
kprintf("\n");
|
return ((unsigned long)sizes[blktype] * (n - (unsigned) pr->nfree));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -808,12 +813,55 @@ kheap_printstats(void)
|
|||||||
kprintf("Subpage allocator status:\n");
|
kprintf("Subpage allocator status:\n");
|
||||||
|
|
||||||
for (pr = allbase; pr != NULL; pr = pr->next_all) {
|
for (pr = allbase; pr != NULL; pr = pr->next_all) {
|
||||||
subpage_stats(pr);
|
subpage_stats(pr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&kmalloc_spinlock);
|
spinlock_release(&kmalloc_spinlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the number of used bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
kheap_getused(void) {
|
||||||
|
struct pageref *pr;
|
||||||
|
unsigned long total = 0;
|
||||||
|
unsigned int num_pages = 0, coremap_bytes = 0;
|
||||||
|
|
||||||
|
/* compute with interrupts off */
|
||||||
|
spinlock_acquire(&kmalloc_spinlock);
|
||||||
|
for (pr = allbase; pr != NULL; pr = pr->next_all) {
|
||||||
|
total += subpage_stats(pr, true);
|
||||||
|
num_pages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
coremap_bytes = coremap_used_bytes();
|
||||||
|
|
||||||
|
// Don't double-count the pages we're using for subpage allocation;
|
||||||
|
// we've already accounted for the used portion.
|
||||||
|
if (coremap_bytes > 0) {
|
||||||
|
total += coremap_bytes - (num_pages * PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release(&kmalloc_spinlock);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print number of used bytes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
kheap_printused(void)
|
||||||
|
{
|
||||||
|
char total_string[32];
|
||||||
|
snprintf(total_string, sizeof(total_string), "%lu", kheap_getused());
|
||||||
|
secprintf(SECRET, total_string, "khu");
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -967,7 +1015,7 @@ subpage_kmalloc(size_t sz
|
|||||||
prpage = alloc_kpages(1);
|
prpage = alloc_kpages(1);
|
||||||
if (prpage==0) {
|
if (prpage==0) {
|
||||||
/* Out of memory. */
|
/* Out of memory. */
|
||||||
kprintf("kmalloc: Subpage allocator couldn't get a page\n");
|
silent("kmalloc: Subpage allocator couldn't get a page\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
KASSERT(prpage % PAGE_SIZE == 0);
|
KASSERT(prpage % PAGE_SIZE == 0);
|
||||||
|
@ -87,15 +87,6 @@
|
|||||||
# These build variables can be set explicitly for further control if
|
# These build variables can be set explicitly for further control if
|
||||||
# desired, but should in general not need attention.
|
# desired, but should in general not need attention.
|
||||||
#
|
#
|
||||||
# (Tools.)
|
|
||||||
#
|
|
||||||
# PYTHON_INTERPRETER Location of Python interpreter.
|
|
||||||
# Default is "/usr/bin/env python".
|
|
||||||
#
|
|
||||||
# This may need to be changed on some platforms; but the configure
|
|
||||||
# script is supposed to take care of it for you. If that fails, or
|
|
||||||
# picks the wrong thing, please file a bug report.
|
|
||||||
#
|
|
||||||
# (Locations.)
|
# (Locations.)
|
||||||
#
|
#
|
||||||
# BUILDTOP Top of tree where .o files go.
|
# BUILDTOP Top of tree where .o files go.
|
||||||
@ -105,7 +96,7 @@
|
|||||||
# the build. Default is $(WORKDIR)/tooldir.
|
# the build. Default is $(WORKDIR)/tooldir.
|
||||||
#
|
#
|
||||||
# INSTALLTOP Staging directory for installation.
|
# INSTALLTOP Staging directory for installation.
|
||||||
# Default is $(WORKDIR)/install.
|
# Default is $(WORKDIR)/install
|
||||||
#
|
#
|
||||||
# Probably the only reason to change these would be if you're short on
|
# Probably the only reason to change these would be if you're short on
|
||||||
# diskspace in $(WORKDIR).
|
# diskspace in $(WORKDIR).
|
||||||
@ -479,7 +470,7 @@ MORECFLAGS+=-I$(INSTALLTOP)/include
|
|||||||
LDFLAGS+=-nostdlib -L$(INSTALLTOP)/lib $(INSTALLTOP)/lib/crt0.o
|
LDFLAGS+=-nostdlib -L$(INSTALLTOP)/lib $(INSTALLTOP)/lib/crt0.o
|
||||||
MORELIBS+=-lc
|
MORELIBS+=-lc
|
||||||
LIBDEPS+=$(INSTALLTOP)/lib/crt0.o $(INSTALLTOP)/lib/libc.a
|
LIBDEPS+=$(INSTALLTOP)/lib/crt0.o $(INSTALLTOP)/lib/libc.a
|
||||||
|
LIBS+=-ltest161
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
# end.
|
# end.
|
||||||
|
@ -56,7 +56,7 @@ all-local: $(MYBUILDDIR) .WAIT $(MYBUILDDIR)/$(_LIB_)
|
|||||||
install-staging-local: $(TOOLDIR)/hostlib .WAIT $(TOOLDIR)/hostlib/$(_LIB_)
|
install-staging-local: $(TOOLDIR)/hostlib .WAIT $(TOOLDIR)/hostlib/$(_LIB_)
|
||||||
$(TOOLDIR)/hostlib/$(_LIB_): $(MYBUILDDIR)/$(_LIB_)
|
$(TOOLDIR)/hostlib/$(_LIB_): $(MYBUILDDIR)/$(_LIB_)
|
||||||
rm -f $(.TARGET)
|
rm -f $(.TARGET)
|
||||||
ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) || \
|
ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) >/dev/null 2>&1 || \
|
||||||
cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET)
|
cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET)
|
||||||
|
|
||||||
install-local:
|
install-local:
|
||||||
|
@ -76,14 +76,14 @@ cleanhostprog:
|
|||||||
install-staging-local: $(_INSTALLDIR_) .WAIT $(_INSTALLDIR_)/$(_PROG_)
|
install-staging-local: $(_INSTALLDIR_) .WAIT $(_INSTALLDIR_)/$(_PROG_)
|
||||||
$(_INSTALLDIR_)/$(_PROG_): $(MYBUILDDIR)/$(_PROG_)
|
$(_INSTALLDIR_)/$(_PROG_): $(MYBUILDDIR)/$(_PROG_)
|
||||||
rm -f $(.TARGET)
|
rm -f $(.TARGET)
|
||||||
ln $(MYBUILDDIR)/$(_PROG_) $(.TARGET) || \
|
ln $(MYBUILDDIR)/$(_PROG_) $(.TARGET) >/dev/null 2>&1 || \
|
||||||
cp $(MYBUILDDIR)/$(_PROG_) $(.TARGET)
|
cp $(MYBUILDDIR)/$(_PROG_) $(.TARGET)
|
||||||
|
|
||||||
.if defined(HOSTBINDIR)
|
.if defined(HOSTBINDIR)
|
||||||
install-local: install-hostprog
|
install-local: install-hostprog
|
||||||
install-hostprog: $(OSTREE)$(HOSTBINDIR) $(MYBUILDDIR)/$(_PROG_)
|
install-hostprog: $(OSTREE)$(HOSTBINDIR) $(MYBUILDDIR)/$(_PROG_)
|
||||||
rm -f $(OSTREE)$(HOSTBINDIR)/$(_PROG_)
|
rm -f $(OSTREE)$(HOSTBINDIR)/$(_PROG_)
|
||||||
ln $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) || \
|
ln $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) >/dev/null 2>&1 || \
|
||||||
cp $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_)
|
cp $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_)
|
||||||
.else
|
.else
|
||||||
install-local:
|
install-local:
|
||||||
|
@ -163,6 +163,9 @@ includelinks:
|
|||||||
clean:
|
clean:
|
||||||
rm -f *.o *.a tags $(KERNEL)
|
rm -f *.o *.a tags $(KERNEL)
|
||||||
rm -rf includelinks
|
rm -rf includelinks
|
||||||
|
@ABSTOP=$$(readlink -f $(TOP))
|
||||||
|
rm -f $(OSTREE)/.src
|
||||||
|
rm -f $(TOP)/.root
|
||||||
|
|
||||||
distclean cleandir: clean
|
distclean cleandir: clean
|
||||||
rm -f .depend
|
rm -f .depend
|
||||||
@ -188,6 +191,9 @@ install:
|
|||||||
cp $(KERNEL) $(OSTREE)/$(KERNEL)-$(CONFNAME)
|
cp $(KERNEL) $(OSTREE)/$(KERNEL)-$(CONFNAME)
|
||||||
-rm -f $(OSTREE)/$(KERNEL)
|
-rm -f $(OSTREE)/$(KERNEL)
|
||||||
ln -s $(KERNEL)-$(CONFNAME) $(OSTREE)/$(KERNEL)
|
ln -s $(KERNEL)-$(CONFNAME) $(OSTREE)/$(KERNEL)
|
||||||
|
@ABSTOP=$$(readlink -f $(TOP))
|
||||||
|
ln -Tsf $(ABSTOP) $(OSTREE)/.src
|
||||||
|
ln -Tsf $(OSTREE) $(ABSTOP)/.root
|
||||||
|
|
||||||
#
|
#
|
||||||
# Run tags on all the sources and header files. This is probably not
|
# Run tags on all the sources and header files. This is probably not
|
||||||
|
@ -59,13 +59,13 @@ all-local: $(MYBUILDDIR) .WAIT $(MYBUILDDIR)/$(_LIB_)
|
|||||||
install-staging-local: $(INSTALLTOP)$(LIBDIR) .WAIT $(INSTALLTOP)$(LIBDIR)/$(_LIB_)
|
install-staging-local: $(INSTALLTOP)$(LIBDIR) .WAIT $(INSTALLTOP)$(LIBDIR)/$(_LIB_)
|
||||||
$(INSTALLTOP)$(LIBDIR)/$(_LIB_): $(MYBUILDDIR)/$(_LIB_)
|
$(INSTALLTOP)$(LIBDIR)/$(_LIB_): $(MYBUILDDIR)/$(_LIB_)
|
||||||
rm -f $(.TARGET)
|
rm -f $(.TARGET)
|
||||||
ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) || \
|
ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) >/dev/null 2>&1 || \
|
||||||
cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET)
|
cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET)
|
||||||
|
|
||||||
install-local: $(OSTREE)$(LIBDIR) $(MYBUILDDIR)/$(_LIB_)
|
install-local: $(OSTREE)$(LIBDIR) $(MYBUILDDIR)/$(_LIB_)
|
||||||
@echo "Warning: manually installing library without relinking anything"
|
@echo "Warning: manually installing library without relinking anything"
|
||||||
rm -f $(OSTREE)$(LIBDIR)/$(_LIB_)
|
rm -f $(OSTREE)$(LIBDIR)/$(_LIB_)
|
||||||
ln $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) || \
|
ln $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) >/dev/null 2>&1 || \
|
||||||
cp $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_)
|
cp $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_)
|
||||||
|
|
||||||
# Build the library.
|
# Build the library.
|
||||||
|
@ -44,24 +44,21 @@ install-staging-local: $(INSTALLTOP)$(MANDIR) .WAIT
|
|||||||
install-staging-local: $(INSTALLTOP)$(MANDIR)/$(_F_)
|
install-staging-local: $(INSTALLTOP)$(MANDIR)/$(_F_)
|
||||||
$(INSTALLTOP)$(MANDIR)/$(_F_): $(_F_)
|
$(INSTALLTOP)$(MANDIR)/$(_F_): $(_F_)
|
||||||
rm -f $(.TARGET)
|
rm -f $(.TARGET)
|
||||||
ln $(_F_) $(.TARGET) || cp $(_F_) $(.TARGET)
|
ln $(_F_) $(.TARGET) >/dev/null 2>&1 || cp $(_F_) $(.TARGET)
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
install-local: $(OSTREE)$(MANDIR) .WAIT installmanpages
|
install-local: $(OSTREE)$(MANDIR) .WAIT installmanpages
|
||||||
installmanpages:
|
installmanpages:
|
||||||
.for _F_ in $(MANFILES)
|
.for _F_ in $(MANFILES)
|
||||||
rm -f $(OSTREE)$(MANDIR)/$(_F_)
|
rm -f $(OSTREE)$(MANDIR)/$(_F_)
|
||||||
ln $(_F_) $(OSTREE)$(MANDIR)/$(_F_) || \
|
ln $(_F_) $(OSTREE)$(MANDIR)/$(_F_) >/dev/null 2>&1 || \
|
||||||
cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_)
|
cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_)
|
||||||
.endfor
|
.endfor
|
||||||
|
|
||||||
# clean: remove build products (nothing to do)
|
|
||||||
clean-local: ;
|
|
||||||
|
|
||||||
# Mark targets that don't represent files PHONY, to prevent various
|
# Mark targets that don't represent files PHONY, to prevent various
|
||||||
# lossage if files by those names appear.
|
# lossage if files by those names appear.
|
||||||
.PHONY: all all-local install-staging-local install-local installmanpages
|
.PHONY: all all-local install-staging-local install-local installmanpages
|
||||||
.PHONY: clean-local
|
|
||||||
|
|
||||||
# Finally, get the shared definitions for the most basic rules.
|
# Finally, get the shared definitions for the most basic rules.
|
||||||
.include "$(TOP)/mk/os161.baserules.mk"
|
.include "$(TOP)/mk/os161.baserules.mk"
|
||||||
|
@ -61,13 +61,13 @@ cleanprog:
|
|||||||
install-staging-local: $(INSTALLTOP)$(BINDIR) .WAIT $(INSTALLTOP)$(BINDIR)/$(PROG)
|
install-staging-local: $(INSTALLTOP)$(BINDIR) .WAIT $(INSTALLTOP)$(BINDIR)/$(PROG)
|
||||||
$(INSTALLTOP)$(BINDIR)/$(PROG): $(MYBUILDDIR)/$(PROG)
|
$(INSTALLTOP)$(BINDIR)/$(PROG): $(MYBUILDDIR)/$(PROG)
|
||||||
rm -f $(.TARGET)
|
rm -f $(.TARGET)
|
||||||
ln $(MYBUILDDIR)/$(PROG) $(.TARGET) || \
|
ln $(MYBUILDDIR)/$(PROG) $(.TARGET) >/dev/null 2>&1 || \
|
||||||
cp $(MYBUILDDIR)/$(PROG) $(.TARGET)
|
cp $(MYBUILDDIR)/$(PROG) $(.TARGET)
|
||||||
|
|
||||||
install-local: install-prog
|
install-local: install-prog
|
||||||
install-prog: $(OSTREE)$(BINDIR) $(MYBUILDDIR)/$(PROG)
|
install-prog: $(OSTREE)$(BINDIR) $(MYBUILDDIR)/$(PROG)
|
||||||
rm -f $(OSTREE)$(BINDIR)/$(PROG)
|
rm -f $(OSTREE)$(BINDIR)/$(PROG)
|
||||||
ln $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) || \
|
ln $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) >/dev/null 2>&1 || \
|
||||||
cp $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG)
|
cp $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG)
|
||||||
|
|
||||||
# Link the program.
|
# Link the program.
|
||||||
|
@ -12,6 +12,7 @@ INCLUDES=\
|
|||||||
include include \
|
include include \
|
||||||
include/sys include/sys \
|
include/sys include/sys \
|
||||||
include/test include/test \
|
include/test include/test \
|
||||||
|
include/test161 include/test161 \
|
||||||
include/types include/types
|
include/types include/types
|
||||||
|
|
||||||
INCLUDELINKS=\
|
INCLUDELINKS=\
|
||||||
|
@ -56,6 +56,11 @@ int vprintf(const char *fmt, __va_list ap);
|
|||||||
int snprintf(char *buf, size_t len, const char *fmt, ...);
|
int snprintf(char *buf, size_t len, const char *fmt, ...);
|
||||||
int vsnprintf(char *buf, size_t len, const char *fmt, __va_list ap);
|
int vsnprintf(char *buf, size_t len, const char *fmt, __va_list ap);
|
||||||
|
|
||||||
|
/* Automated testing extensions. */
|
||||||
|
|
||||||
|
int tprintf(const char *fmt, ...);
|
||||||
|
int nprintf(const char *fmt, ...);
|
||||||
|
|
||||||
/* Print the argument string and then a newline. Returns 0 or -1 on error. */
|
/* Print the argument string and then a newline. Returns 0 or -1 on error. */
|
||||||
int puts(const char *);
|
int puts(const char *);
|
||||||
|
|
||||||
|
@ -8,6 +8,6 @@
|
|||||||
TOP=../..
|
TOP=../..
|
||||||
.include "$(TOP)/mk/os161.config.mk"
|
.include "$(TOP)/mk/os161.config.mk"
|
||||||
|
|
||||||
SUBDIRS=crt0 libc libtest hostcompat
|
SUBDIRS=crt0 libc libtest libtest161 hostcompat
|
||||||
|
|
||||||
.include "$(TOP)/mk/os161.subdir.mk"
|
.include "$(TOP)/mk/os161.subdir.mk"
|
||||||
|
@ -22,6 +22,11 @@ TOP=../../..
|
|||||||
LIB=hostcompat
|
LIB=hostcompat
|
||||||
SRCS=err.c ntohll.c time.c hostcompat.c
|
SRCS=err.c ntohll.c time.c hostcompat.c
|
||||||
|
|
||||||
|
# printf
|
||||||
|
COMMON=$(TOP)/common/libc
|
||||||
|
SRCS+=\
|
||||||
|
$(COMMON)/printf/tprintf.c
|
||||||
|
|
||||||
HOST_CFLAGS+=$(COMPAT_CFLAGS)
|
HOST_CFLAGS+=$(COMPAT_CFLAGS)
|
||||||
|
|
||||||
MKDIRS=$(INSTALLTOP)/hostinclude
|
MKDIRS=$(INSTALLTOP)/hostinclude
|
||||||
|
@ -35,6 +35,11 @@ void hostcompat_init(int argc, char **argv);
|
|||||||
|
|
||||||
time_t __time(time_t *secs, unsigned long *nsecs);
|
time_t __time(time_t *secs, unsigned long *nsecs);
|
||||||
|
|
||||||
|
/* Automated testing extensions. */
|
||||||
|
|
||||||
|
int tprintf(const char *fmt, ...);
|
||||||
|
int nprintf(const char *fmt, ...);
|
||||||
|
|
||||||
#ifdef DECLARE_NTOHLL
|
#ifdef DECLARE_NTOHLL
|
||||||
uint64_t ntohll(uint64_t);
|
uint64_t ntohll(uint64_t);
|
||||||
#define htonll(x) (ntohll(x))
|
#define htonll(x) (ntohll(x))
|
||||||
|
@ -10,7 +10,8 @@ COMMON=$(TOP)/common/libc
|
|||||||
# printf
|
# printf
|
||||||
SRCS+=\
|
SRCS+=\
|
||||||
$(COMMON)/printf/__printf.c \
|
$(COMMON)/printf/__printf.c \
|
||||||
$(COMMON)/printf/snprintf.c
|
$(COMMON)/printf/snprintf.c \
|
||||||
|
$(COMMON)/printf/tprintf.c
|
||||||
|
|
||||||
# stdio
|
# stdio
|
||||||
SRCS+=\
|
SRCS+=\
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <kern/secret.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* printf - C standard I/O function.
|
* printf - C standard I/O function.
|
||||||
|
@ -139,6 +139,7 @@ verr(int exitcode, const char *fmt, va_list ap)
|
|||||||
{
|
{
|
||||||
__printerr(1, fmt, ap);
|
__printerr(1, fmt, ap);
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
|
// exit() didn't work.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* errx/verrx: don't use errno, but do then exit */
|
/* errx/verrx: don't use errno, but do then exit */
|
||||||
@ -147,6 +148,7 @@ verrx(int exitcode, const char *fmt, va_list ap)
|
|||||||
{
|
{
|
||||||
__printerr(0, fmt, ap);
|
__printerr(0, fmt, ap);
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
|
// exit() didn't work.
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,11 +7,12 @@ TOP=../..
|
|||||||
|
|
||||||
SUBDIRS=add argtest badcall bigexec bigfile bigfork bigseek bloat conman \
|
SUBDIRS=add argtest badcall bigexec bigfile bigfork bigseek bloat conman \
|
||||||
crash ctest dirconc dirseek dirtest f_test factorial farm faulter \
|
crash ctest dirconc dirseek dirtest f_test factorial farm faulter \
|
||||||
filetest forkbomb forktest frack guzzle hash hog huge kitchen \
|
filetest fileonlytest forkbomb forktest frack guzzle hash hog huge kitchen \
|
||||||
malloctest matmult multiexec palin parallelvm poisondisk psort \
|
malloctest matmult multiexec palin parallelvm poisondisk psort \
|
||||||
quinthuge quintmat quintsort randcall redirect rmdirtest rmtest \
|
quinthuge quintmat quintsort randcall redirect rmdirtest rmtest \
|
||||||
sbrktest schedpong sink sort sparsefile sty tail tictac triplehuge \
|
sbrktest schedpong shll sink sort sparsefile spinner sty tail tictac \
|
||||||
triplemat triplesort usemtest zero
|
triplehuge triplemat triplesort usemtest waiter zero \
|
||||||
|
consoletest shelltest opentest readwritetest closetest stacktest
|
||||||
|
|
||||||
# But not:
|
# But not:
|
||||||
# userthreads (no support in kernel API in base system)
|
# userthreads (no support in kernel API in base system)
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
@ -51,7 +52,9 @@ main(int argc, char *argv[])
|
|||||||
i = atoi(argv[1]);
|
i = atoi(argv[1]);
|
||||||
j = atoi(argv[2]);
|
j = atoi(argv[2]);
|
||||||
|
|
||||||
printf("Answer: %d\n", i+j);
|
tprintf("Answer: %d\n", i+j);
|
||||||
|
char buf[16];
|
||||||
|
snprintf(buf, 16, "%d", i+j);
|
||||||
|
secprintf(SECRET, buf, "/testbin/add");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
@ -43,14 +44,18 @@ main(int argc, char *argv[])
|
|||||||
const char *tmp;
|
const char *tmp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("argc: %d\n", argc);
|
tprintf("argc: %d\n", argc);
|
||||||
|
char buf[16];
|
||||||
|
snprintf(buf, 16, "argc: %d", argc);
|
||||||
|
secprintf(SECRET, buf, "/testbin/argtest");
|
||||||
|
|
||||||
for (i=0; i<=argc; i++) {
|
for (i=0; i<=argc; i++) {
|
||||||
tmp = argv[i];
|
tmp = argv[i];
|
||||||
if (tmp==NULL) {
|
if (tmp==NULL) {
|
||||||
tmp = "[NULL]";
|
tmp = "[NULL]";
|
||||||
}
|
}
|
||||||
printf("argv[%d]: %s\n", i, tmp);
|
tprintf("argv[%d]: %s\n", i, tmp);
|
||||||
|
secprintf(SECRET, tmp, "/testbin/argtest");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
chdir_empty(void)
|
chdir_empty(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
@ -49,13 +49,20 @@ chdir_empty(void)
|
|||||||
|
|
||||||
report_begin("chdir to empty string");
|
report_begin("chdir to empty string");
|
||||||
rv = chdir("");
|
rv = chdir("");
|
||||||
report_check2(rv, errno, EINVAL, 0);
|
return report_check2(rv, errno, EINVAL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_chdir(void)
|
test_chdir(void)
|
||||||
{
|
{
|
||||||
test_chdir_path();
|
int ntests = 0, result = 0, lost_points = 0;
|
||||||
chdir_empty();
|
test_chdir_path(&ntests, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = chdir_empty();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,5 +36,9 @@
|
|||||||
void
|
void
|
||||||
test_close(void)
|
test_close(void)
|
||||||
{
|
{
|
||||||
test_close_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
|
test_close_fd(&ntests, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -45,27 +45,29 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
dup2_fd2(int fd, const char *desc)
|
dup2_fd2(int fd, const char *desc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv, failure;
|
||||||
|
|
||||||
report_begin("%s", desc);
|
report_begin("%s", desc);
|
||||||
rv = dup2(STDIN_FILENO, fd);
|
rv = dup2(STDIN_FILENO, fd);
|
||||||
report_check(rv, errno, EBADF);
|
failure = report_check(rv, errno, EBADF);
|
||||||
|
|
||||||
if (rv != -1) {
|
if (rv != -1) {
|
||||||
close(fd); /* just in case */
|
close(fd); /* just in case */
|
||||||
}
|
}
|
||||||
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
dup2_self(void)
|
dup2_self(void)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int rv;
|
int rv;
|
||||||
int testfd;
|
int testfd;
|
||||||
|
int failure;
|
||||||
|
|
||||||
/* use fd that isn't in use */
|
/* use fd that isn't in use */
|
||||||
testfd = CLOSED_FD;
|
testfd = CLOSED_FD;
|
||||||
@ -75,22 +77,23 @@ dup2_self(void)
|
|||||||
rv = dup2(STDIN_FILENO, testfd);
|
rv = dup2(STDIN_FILENO, testfd);
|
||||||
if (rv == -1) {
|
if (rv == -1) {
|
||||||
report_result(rv, errno);
|
report_result(rv, errno);
|
||||||
report_aborted();
|
report_aborted(&failure);
|
||||||
return;
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_begin("dup2 to same fd");
|
report_begin("dup2 to same fd");
|
||||||
rv = dup2(testfd, testfd);
|
rv = dup2(testfd, testfd);
|
||||||
if (rv == testfd) {
|
if (rv == testfd) {
|
||||||
report_passed();
|
report_passed(&failure);
|
||||||
}
|
}
|
||||||
else if (rv<0) {
|
else if (rv<0) {
|
||||||
report_result(rv, errno);
|
report_result(rv, errno);
|
||||||
report_failure();
|
report_failure(&failure);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
report_warnx("returned %d instead", rv);
|
report_warnx("returned %d instead", rv);
|
||||||
report_failure();
|
report_failure(&failure);
|
||||||
|
failure = FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_begin("fstat fd after dup2 to itself");
|
report_begin("fstat fd after dup2 to itself");
|
||||||
@ -100,43 +103,60 @@ dup2_self(void)
|
|||||||
}
|
}
|
||||||
report_result(rv, errno);
|
report_result(rv, errno);
|
||||||
if (rv==0) {
|
if (rv==0) {
|
||||||
report_passed();
|
report_passed(&failure);
|
||||||
}
|
}
|
||||||
else if (errno != ENOSYS) {
|
else if (errno != ENOSYS) {
|
||||||
report_failure();
|
report_failure(&failure);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
report_skipped();
|
report_skipped(&failure);
|
||||||
/* no support for fstat; try lseek */
|
/* no support for fstat; try lseek */
|
||||||
report_begin("lseek fd after dup2 to itself");
|
report_begin("lseek fd after dup2 to itself");
|
||||||
rv = lseek(testfd, 0, SEEK_CUR);
|
rv = lseek(testfd, 0, SEEK_CUR);
|
||||||
report_result(rv, errno);
|
report_result(rv, errno);
|
||||||
if (rv==0 || (rv==-1 && errno==ESPIPE)) {
|
if (rv==0 || (rv==-1 && errno==ESPIPE)) {
|
||||||
report_passed();
|
report_passed(&failure);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
report_failure();
|
report_failure(&failure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(testfd);
|
close(testfd);
|
||||||
|
return failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_dup2(void)
|
test_dup2(void)
|
||||||
{
|
{
|
||||||
|
int ntests = 0, failure, lost_points = 0;
|
||||||
/* This does the first fd. */
|
/* This does the first fd. */
|
||||||
test_dup2_fd();
|
test_dup2_fd(&ntests, &lost_points);
|
||||||
|
|
||||||
/* Any interesting cases added here should also go in common_fds.c */
|
/* Any interesting cases added here should also go in common_fds.c */
|
||||||
dup2_fd2(-1, "dup2 to -1");
|
ntests++;
|
||||||
dup2_fd2(-5, "dup2 to -5");
|
failure = dup2_fd2(-1, "dup2 to -1");
|
||||||
dup2_fd2(IMPOSSIBLE_FD, "dup2 to impossible fd");
|
handle_result(failure, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
failure = dup2_fd2(-5, "dup2 to -5");
|
||||||
|
handle_result(failure, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
failure = dup2_fd2(IMPOSSIBLE_FD, "dup2 to impossible fd");
|
||||||
|
handle_result(failure, &lost_points);
|
||||||
#ifdef OPEN_MAX
|
#ifdef OPEN_MAX
|
||||||
dup2_fd2(OPEN_MAX, "dup2 to OPEN_MAX");
|
ntests++;
|
||||||
|
failure = dup2_fd2(OPEN_MAX, "dup2 to OPEN_MAX");
|
||||||
|
handle_result(failure, &lost_points);
|
||||||
#else
|
#else
|
||||||
warnx("Warning: OPEN_MAX not defined - test skipped");
|
warnx("Warning: OPEN_MAX not defined - test skipped");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dup2_self();
|
ntests++;
|
||||||
|
failure = dup2_self();
|
||||||
|
handle_result(failure, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -42,7 +43,7 @@
|
|||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
exec_common_fork(void)
|
exec_common_fork(int *result)
|
||||||
{
|
{
|
||||||
int pid, rv, status, err;
|
int pid, rv, status, err;
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ exec_common_fork(void)
|
|||||||
err = errno;
|
err = errno;
|
||||||
report_begin("forking for test");
|
report_begin("forking for test");
|
||||||
report_result(pid, err);
|
report_result(pid, err);
|
||||||
report_aborted();
|
report_aborted(result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +71,11 @@ exec_common_fork(void)
|
|||||||
err = errno;
|
err = errno;
|
||||||
report_begin("waiting for test subprocess");
|
report_begin("waiting for test subprocess");
|
||||||
report_result(rv, err);
|
report_result(rv, err);
|
||||||
report_failure();
|
report_failure(result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (WIFEXITED(status) && WEXITSTATUS(status) == MAGIC_STATUS) {
|
if (WIFEXITED(status) && WEXITSTATUS(status) == MAGIC_STATUS) {
|
||||||
|
*result = SUCCESS;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Oops... */
|
/* Oops... */
|
||||||
@ -84,98 +86,134 @@ exec_common_fork(void)
|
|||||||
else {
|
else {
|
||||||
report_warnx("exit %d", WEXITSTATUS(status));
|
report_warnx("exit %d", WEXITSTATUS(status));
|
||||||
}
|
}
|
||||||
report_failure();
|
report_failure(result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
exec_badprog(const void *prog, const char *desc)
|
exec_badprog(const void *prog, const char *desc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
char *args[2];
|
char *args[2];
|
||||||
args[0] = (char *)"foo";
|
args[0] = (char *)"foo";
|
||||||
args[1] = NULL;
|
args[1] = NULL;
|
||||||
|
|
||||||
if (exec_common_fork() != 0) {
|
if (exec_common_fork(&result) != 0) {
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_begin(desc);
|
report_begin(desc);
|
||||||
rv = execv(prog, args);
|
rv = execv(prog, args);
|
||||||
report_check(rv, errno, EFAULT);
|
result = report_check(rv, errno, EFAULT);
|
||||||
exit(MAGIC_STATUS);
|
int code = result ? result : MAGIC_STATUS;
|
||||||
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
exec_emptyprog(void)
|
exec_emptyprog(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
char *args[2];
|
char *args[2];
|
||||||
args[0] = (char *)"foo";
|
args[0] = (char *)"foo";
|
||||||
args[1] = NULL;
|
args[1] = NULL;
|
||||||
|
|
||||||
if (exec_common_fork() != 0) {
|
if (exec_common_fork(&result) != 0) {
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_begin("exec the empty string");
|
report_begin("exec the empty string");
|
||||||
rv = execv("", args);
|
rv = execv("", args);
|
||||||
report_check2(rv, errno, EINVAL, EISDIR);
|
result = report_check2(rv, errno, EINVAL, EISDIR);
|
||||||
exit(MAGIC_STATUS);
|
int code = result ? result : MAGIC_STATUS;
|
||||||
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
exec_badargs(void *args, const char *desc)
|
exec_badargs(void *args, const char *desc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
if (exec_common_fork() != 0) {
|
if (exec_common_fork(&result) != 0) {
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_begin(desc);
|
report_begin(desc);
|
||||||
rv = execv("/bin/true", args);
|
rv = execv("/bin/true", args);
|
||||||
report_check(rv, errno, EFAULT);
|
result = report_check(rv, errno, EFAULT);
|
||||||
exit(MAGIC_STATUS);
|
int code = result ? result : MAGIC_STATUS;
|
||||||
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
exec_onearg(void *ptr, const char *desc)
|
exec_onearg(void *ptr, const char *desc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
char *args[3];
|
char *args[3];
|
||||||
args[0] = (char *)"foo";
|
args[0] = (char *)"foo";
|
||||||
args[1] = (char *)ptr;
|
args[1] = (char *)ptr;
|
||||||
args[2] = NULL;
|
args[2] = NULL;
|
||||||
|
|
||||||
if (exec_common_fork() != 0) {
|
if (exec_common_fork(&result) != 0) {
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_begin(desc);
|
report_begin(desc);
|
||||||
rv = execv("/bin/true", args);
|
rv = execv("/bin/true", args);
|
||||||
report_check(rv, errno, EFAULT);
|
result = report_check(rv, errno, EFAULT);
|
||||||
exit(MAGIC_STATUS);
|
int code = result ? result : MAGIC_STATUS;
|
||||||
|
exit(code);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_execv(void)
|
test_execv(void)
|
||||||
{
|
{
|
||||||
exec_badprog(NULL, "exec with NULL program");
|
int ntests = 0, result = 0, lost_points = 0;
|
||||||
exec_badprog(INVAL_PTR, "exec with invalid pointer program");
|
ntests++;
|
||||||
exec_badprog(KERN_PTR, "exec with kernel pointer program");
|
result = exec_badprog(NULL, "exec with NULL program");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
exec_emptyprog();
|
ntests++;
|
||||||
|
result = exec_badprog(INVAL_PTR, "exec with invalid pointer program");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
exec_badargs(NULL, "exec with NULL arglist");
|
ntests++;
|
||||||
exec_badargs(INVAL_PTR, "exec with invalid pointer arglist");
|
result = exec_badprog(KERN_PTR, "exec with kernel pointer program");
|
||||||
exec_badargs(KERN_PTR, "exec with kernel pointer arglist");
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
exec_onearg(INVAL_PTR, "exec with invalid pointer arg");
|
ntests++;
|
||||||
exec_onearg(KERN_PTR, "exec with kernel pointer arg");
|
result = exec_emptyprog();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = exec_badargs(NULL, "exec with NULL arglist");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = exec_badargs(INVAL_PTR, "exec with invalid pointer arglist");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = exec_badargs(KERN_PTR, "exec with kernel pointer arglist");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = exec_onearg(INVAL_PTR, "exec with invalid pointer arg");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = exec_onearg(KERN_PTR, "exec with kernel pointer arg");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,11 @@
|
|||||||
void
|
void
|
||||||
test_fsync(void)
|
test_fsync(void)
|
||||||
{
|
{
|
||||||
test_fsync_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
|
|
||||||
|
test_fsync_fd(&ntests, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,52 +44,67 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
ftruncate_fd_device(void)
|
ftruncate_fd_device(void)
|
||||||
{
|
{
|
||||||
int rv, fd;
|
int rv, fd;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("ftruncate on device");
|
report_begin("ftruncate on device");
|
||||||
|
|
||||||
fd = open("null:", O_RDWR);
|
fd = open("null:", O_RDWR);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_warn("opening null: failed");
|
report_warn("opening null: failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ftruncate(fd, 6);
|
rv = ftruncate(fd, 6);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
ftruncate_size_neg(void)
|
ftruncate_size_neg(void)
|
||||||
{
|
{
|
||||||
int rv, fd;
|
int rv, fd;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("ftruncate to negative size");
|
report_begin("ftruncate to negative size");
|
||||||
|
|
||||||
fd = open_testfile(NULL);
|
fd = open_testfile(NULL);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ftruncate(fd, -60);
|
rv = ftruncate(fd, -60);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_ftruncate(void)
|
test_ftruncate(void)
|
||||||
{
|
{
|
||||||
test_ftruncate_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
ftruncate_fd_device();
|
test_ftruncate_fd(&ntests, &lost_points);
|
||||||
ftruncate_size_neg();
|
|
||||||
|
ntests++;
|
||||||
|
result = ftruncate_fd_device();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = ftruncate_size_neg();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -36,5 +36,9 @@
|
|||||||
void
|
void
|
||||||
test_getcwd(void)
|
test_getcwd(void)
|
||||||
{
|
{
|
||||||
test_getcwd_buf();
|
int ntests = 0, lost_points = 0;
|
||||||
|
test_getcwd_buf(&ntests, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,11 @@
|
|||||||
void
|
void
|
||||||
test_getdirentry(void)
|
test_getdirentry(void)
|
||||||
{
|
{
|
||||||
test_getdirentry_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
test_getdirentry_buf();
|
|
||||||
|
test_getdirentry_fd(&ntests, &lost_points);
|
||||||
|
test_getdirentry_buf(&ntests, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -41,30 +41,34 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
one_ioctl_badbuf(int fd, int code, const char *codename,
|
one_ioctl_badbuf(int fd, int code, const char *codename,
|
||||||
void *ptr, const char *ptrdesc)
|
void *ptr, const char *ptrdesc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("ioctl %s with %s", codename, ptrdesc);
|
report_begin("ioctl %s with %s", codename, ptrdesc);
|
||||||
rv = ioctl(fd, code, ptr);
|
rv = ioctl(fd, code, ptr);
|
||||||
report_check(rv, errno, EFAULT);
|
result = report_check(rv, errno, EFAULT);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
any_ioctl_badbuf(int fd, int code, const char *codename)
|
any_ioctl_badbuf(int fd, int code, const char *codename)
|
||||||
{
|
{
|
||||||
one_ioctl_badbuf(fd, code, codename, NULL, "NULL pointer");
|
int result;
|
||||||
one_ioctl_badbuf(fd, code, codename, INVAL_PTR, "invalid pointer");
|
result = one_ioctl_badbuf(fd, code, codename, NULL, "NULL pointer");
|
||||||
one_ioctl_badbuf(fd, code, codename, KERN_PTR, "kernel pointer");
|
result |= one_ioctl_badbuf(fd, code, codename, INVAL_PTR, "invalid pointer");
|
||||||
|
result |= one_ioctl_badbuf(fd, code, codename, KERN_PTR, "kernel pointer");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IOCTL(fd, sym) any_ioctl_badbuf(fd, sym, #sym)
|
#define IOCTL(fd, sym) any_ioctl_badbuf(fd, sym, #sym)
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
ioctl_badbuf(void)
|
ioctl_badbuf(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -79,25 +83,39 @@ ioctl_badbuf(void)
|
|||||||
|
|
||||||
/* suppress gcc warning */
|
/* suppress gcc warning */
|
||||||
(void)any_ioctl_badbuf;
|
(void)any_ioctl_badbuf;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
ioctl_badcode(void)
|
ioctl_badcode(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("invalid ioctl");
|
report_begin("invalid ioctl");
|
||||||
rv = ioctl(STDIN_FILENO, NONEXIST_IOCTL, NULL);
|
rv = ioctl(STDIN_FILENO, NONEXIST_IOCTL, NULL);
|
||||||
report_check(rv, errno, EIOCTL);
|
result = report_check(rv, errno, EIOCTL);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_ioctl(void)
|
test_ioctl(void)
|
||||||
{
|
{
|
||||||
test_ioctl_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
test_ioctl_fd(&ntests, &lost_points);
|
||||||
|
|
||||||
/* Since we don't actually define any ioctls, this is not meaningful */
|
/* Since we don't actually define any ioctls, this is not meaningful */
|
||||||
ioctl_badcode();
|
ntests++;
|
||||||
ioctl_badbuf();
|
result = ioctl_badcode();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = ioctl_badbuf();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -37,52 +37,70 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
link_dir(void)
|
link_dir(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("hard link of .");
|
report_begin("hard link of .");
|
||||||
rv = link(".", TESTDIR);
|
rv = link(".", TESTDIR);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
if (rv==0) {
|
if (rv==0) {
|
||||||
/* this might help recover... maybe */
|
/* this might help recover... maybe */
|
||||||
remove(TESTDIR);
|
remove(TESTDIR);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
link_empty1(void)
|
link_empty1(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("hard link of empty string");
|
report_begin("hard link of empty string");
|
||||||
rv = link("", TESTDIR);
|
rv = link("", TESTDIR);
|
||||||
report_check(rv, errno, EINVAL);
|
return report_check(rv, errno, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
link_empty2(void)
|
link_empty2(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result = FAILED;
|
||||||
report_begin("hard link to empty string");
|
report_begin("hard link to empty string");
|
||||||
if (create_testdir()<0) {
|
if (create_testdir()<0) {
|
||||||
/*report_aborted();*/ /* XXX in create_testdir */
|
/*report_aborted();*/ /* XXX in create_testdir */
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
rv = link(TESTDIR, "");
|
rv = link(TESTDIR, "");
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
rmdir(TESTDIR);
|
rmdir(TESTDIR);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_link(void)
|
test_link(void)
|
||||||
{
|
{
|
||||||
test_link_paths();
|
int ntests = 0, lost_points = 0;
|
||||||
link_dir();
|
int result;
|
||||||
link_empty1();
|
|
||||||
link_empty2();
|
test_link_paths(&ntests, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = link_dir();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = link_empty1();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = link_empty2();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -44,34 +44,38 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
lseek_fd_device(void)
|
lseek_fd_device(void)
|
||||||
{
|
{
|
||||||
int fd, rv;
|
int fd, rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("lseek on device");
|
report_begin("lseek on device");
|
||||||
|
|
||||||
fd = open("null:", O_RDONLY);
|
fd = open("null:", O_RDONLY);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_warn("opening null: failed");
|
report_warn("opening null: failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = lseek(fd, 309, SEEK_SET);
|
rv = lseek(fd, 309, SEEK_SET);
|
||||||
report_check(rv, errno, ESPIPE);
|
result = report_check(rv, errno, ESPIPE);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
lseek_file_stdin(void)
|
lseek_file_stdin(void)
|
||||||
{
|
{
|
||||||
int fd, fd2, rv, status;
|
int fd, fd2, rv, status;
|
||||||
const char slogan[] = "There ain't no such thing as a free lunch";
|
const char slogan[] = "There ain't no such thing as a free lunch";
|
||||||
size_t len = strlen(slogan);
|
size_t len = strlen(slogan);
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
report_begin("lseek stdin when open on file");
|
report_begin("lseek stdin when open on file");
|
||||||
|
|
||||||
@ -79,27 +83,27 @@ lseek_file_stdin(void)
|
|||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid<0) {
|
if (pid<0) {
|
||||||
report_warn("fork failed");
|
report_warn("fork failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
else if (pid!=0) {
|
else if (pid!=0) {
|
||||||
/* parent */
|
/* parent */
|
||||||
rv = waitpid(pid, &status, 0);
|
rv = waitpid(pid, &status, 0);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
report_warn("waitpid failed");
|
report_warn("waitpid failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
}
|
}
|
||||||
if (WIFSIGNALED(status)) {
|
if (WIFSIGNALED(status)) {
|
||||||
report_warnx("subprocess exited with signal %d",
|
report_warnx("subprocess exited with signal %d",
|
||||||
WTERMSIG(status));
|
WTERMSIG(status));
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
}
|
}
|
||||||
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
|
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
|
||||||
report_warnx("subprocess exited with code %d",
|
report_warnx("subprocess exited with code %d",
|
||||||
WEXITSTATUS(status));
|
WEXITSTATUS(status));
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
}
|
}
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* child */
|
/* child */
|
||||||
@ -146,133 +150,159 @@ lseek_file_stdin(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* blah */
|
/* blah */
|
||||||
report_skipped();
|
report_skipped(&result);
|
||||||
|
|
||||||
rv = lseek(STDIN_FILENO, 0, SEEK_SET);
|
rv = lseek(STDIN_FILENO, 0, SEEK_SET);
|
||||||
report_begin("try 1: SEEK_SET");
|
report_begin("try 1: SEEK_SET");
|
||||||
report_check(rv, errno, 0);
|
result = report_check(rv, errno, 0);
|
||||||
|
|
||||||
rv = lseek(STDIN_FILENO, 0, SEEK_END);
|
rv = lseek(STDIN_FILENO, 0, SEEK_END);
|
||||||
report_begin("try 2: SEEK_END");
|
report_begin("try 2: SEEK_END");
|
||||||
report_check(rv, errno, 0);
|
result = report_check(rv, errno, 0);
|
||||||
|
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
lseek_loc_negative(void)
|
lseek_loc_negative(void)
|
||||||
{
|
{
|
||||||
int fd, rv;
|
int fd, rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("lseek to negative offset");
|
report_begin("lseek to negative offset");
|
||||||
|
|
||||||
fd = open_testfile(NULL);
|
fd = open_testfile(NULL);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = lseek(fd, -309, SEEK_SET);
|
rv = lseek(fd, -309, SEEK_SET);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
lseek_whence_inval(void)
|
lseek_whence_inval(void)
|
||||||
{
|
{
|
||||||
int fd, rv;
|
int fd, rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("lseek with invalid whence code");
|
report_begin("lseek with invalid whence code");
|
||||||
|
|
||||||
fd = open_testfile(NULL);
|
fd = open_testfile(NULL);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = lseek(fd, 0, 3594);
|
rv = lseek(fd, 0, 3594);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
lseek_loc_pasteof(void)
|
lseek_loc_pasteof(void)
|
||||||
{
|
{
|
||||||
const char *message = "blahblah";
|
const char *message = "blahblah";
|
||||||
int fd;
|
int fd;
|
||||||
off_t pos;
|
off_t pos;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("seek past/to EOF");
|
report_begin("seek past/to EOF");
|
||||||
|
|
||||||
fd = open_testfile(message);
|
fd = open_testfile(message);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = lseek(fd, 5340, SEEK_SET);
|
pos = lseek(fd, 5340, SEEK_SET);
|
||||||
if (pos == -1) {
|
if (pos == -1) {
|
||||||
report_warn("lseek past EOF failed");
|
report_warn("lseek past EOF failed");
|
||||||
report_failure();
|
report_failure(&result);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (pos != 5340) {
|
if (pos != 5340) {
|
||||||
report_warnx("lseek to 5340 got offset %lld", (long long) pos);
|
report_warnx("lseek to 5340 got offset %lld", (long long) pos);
|
||||||
report_failure();
|
report_failure(&result);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = lseek(fd, -50, SEEK_CUR);
|
pos = lseek(fd, -50, SEEK_CUR);
|
||||||
if (pos == -1) {
|
if (pos == -1) {
|
||||||
report_warn("small seek beyond EOF failed");
|
report_warn("small seek beyond EOF failed");
|
||||||
report_failure();
|
report_failure(&result);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (pos != 5290) {
|
if (pos != 5290) {
|
||||||
report_warnx("SEEK_CUR to 5290 got offset %lld",
|
report_warnx("SEEK_CUR to 5290 got offset %lld",
|
||||||
(long long) pos);
|
(long long) pos);
|
||||||
report_failure();
|
report_failure(&result);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = lseek(fd, 0, SEEK_END);
|
pos = lseek(fd, 0, SEEK_END);
|
||||||
if (pos == -1) {
|
if (pos == -1) {
|
||||||
report_warn("seek to EOF failed");
|
report_warn("seek to EOF failed");
|
||||||
report_failure();
|
report_failure(&result);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos != (off_t) strlen(message)) {
|
if (pos != (off_t) strlen(message)) {
|
||||||
report_warnx("seek to EOF got %lld (should be %zu)",
|
report_warnx("seek to EOF got %lld (should be %zu)",
|
||||||
(long long) pos, strlen(message));
|
(long long) pos, strlen(message));
|
||||||
report_failure();
|
report_failure(&result);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_passed();
|
report_passed(&result);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_lseek(void)
|
test_lseek(void)
|
||||||
{
|
{
|
||||||
test_lseek_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
lseek_fd_device();
|
test_lseek_fd(&ntests, &lost_points);
|
||||||
lseek_file_stdin();
|
|
||||||
lseek_loc_negative();
|
ntests++;
|
||||||
lseek_loc_pasteof();
|
result = lseek_fd_device();
|
||||||
lseek_whence_inval();
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = lseek_file_stdin();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = lseek_loc_negative();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = lseek_loc_pasteof();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = lseek_whence_inval();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -44,44 +44,58 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
mkdir_dot(void)
|
mkdir_dot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("mkdir .");
|
report_begin("mkdir .");
|
||||||
rv = mkdir(".", 0775);
|
rv = mkdir(".", 0775);
|
||||||
report_check(rv, errno, EEXIST);
|
return report_check(rv, errno, EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
mkdir_dotdot(void)
|
mkdir_dotdot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("mkdir ..");
|
report_begin("mkdir ..");
|
||||||
rv = mkdir("..", 0775);
|
rv = mkdir("..", 0775);
|
||||||
report_check(rv, errno, EEXIST);
|
return report_check(rv, errno, EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
mkdir_empty(void)
|
mkdir_empty(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("mkdir of empty string");
|
report_begin("mkdir of empty string");
|
||||||
rv = mkdir("", 0775);
|
rv = mkdir("", 0775);
|
||||||
report_check(rv, errno, EINVAL);
|
return report_check(rv, errno, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_mkdir(void)
|
test_mkdir(void)
|
||||||
{
|
{
|
||||||
test_mkdir_path();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
mkdir_dot();
|
test_mkdir_path(&ntests, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = mkdir_dot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
mkdir_dotdot();
|
mkdir_dotdot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
mkdir_empty();
|
mkdir_empty();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -44,35 +44,48 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
open_badflags(void)
|
open_badflags(void)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
report_begin("open null: with bad flags");
|
report_begin("open null: with bad flags");
|
||||||
fd = open("null:", 309842);
|
fd = open("null:", 309842);
|
||||||
report_check(fd, errno, EINVAL);
|
return report_check(fd, errno, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
open_empty(void)
|
open_empty(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("open empty string");
|
report_begin("open empty string");
|
||||||
rv = open("", O_RDONLY);
|
rv = open("", O_RDONLY);
|
||||||
report_check2(rv, errno, 0, EINVAL);
|
result = report_check2(rv, errno, 0, EINVAL);
|
||||||
if (rv>=0) {
|
if (rv>=0) {
|
||||||
close(rv);
|
close(rv);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_open(void)
|
test_open(void)
|
||||||
{
|
{
|
||||||
test_open_path();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
open_badflags();
|
test_open_path(&ntests, &lost_points);
|
||||||
open_empty();
|
|
||||||
|
ntests++;
|
||||||
|
result = open_badflags();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = open_empty();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -44,22 +44,23 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
pipe_badptr(void *ptr, const char *desc)
|
pipe_badptr(void *ptr, const char *desc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("%s", desc);
|
report_begin("%s", desc);
|
||||||
rv = pipe(ptr);
|
rv = pipe(ptr);
|
||||||
report_check(rv, errno, EFAULT);
|
return report_check(rv, errno, EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
pipe_unaligned(void)
|
pipe_unaligned(void)
|
||||||
{
|
{
|
||||||
int fds[3], rv;
|
int fds[3], rv;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("pipe with unaligned pointer");
|
report_begin("pipe with unaligned pointer");
|
||||||
|
|
||||||
@ -67,15 +68,32 @@ pipe_unaligned(void)
|
|||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
rv = pipe((int *)ptr);
|
rv = pipe((int *)ptr);
|
||||||
report_survival(rv, errno);
|
report_survival(rv, errno, &result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_pipe(void)
|
test_pipe(void)
|
||||||
{
|
{
|
||||||
pipe_badptr(NULL, "pipe with NULL pointer");
|
int ntests = 0, lost_points = 0;
|
||||||
pipe_badptr(INVAL_PTR, "pipe with invalid pointer");
|
int result;
|
||||||
pipe_badptr(KERN_PTR, "pipe with kernel pointer");
|
|
||||||
|
|
||||||
pipe_unaligned();
|
ntests++;
|
||||||
|
result = pipe_badptr(NULL, "pipe with NULL pointer");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = pipe_badptr(INVAL_PTR, "pipe with invalid pointer");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = pipe_badptr(KERN_PTR, "pipe with kernel pointer");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = pipe_unaligned();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,13 @@
|
|||||||
void
|
void
|
||||||
test_read(void)
|
test_read(void)
|
||||||
{
|
{
|
||||||
test_read_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
test_read_buf();
|
|
||||||
|
test_read_fd(&ntests, &lost_points);
|
||||||
|
test_read_buf(&ntests, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,26 +37,28 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
readlink_file(void)
|
readlink_file(void)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
int fd, rv;
|
int fd, rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("readlink on file");
|
report_begin("readlink on file");
|
||||||
fd = open_testfile("the question contains an invalid assumption");
|
fd = open_testfile("the question contains an invalid assumption");
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
rv = readlink(TESTFILE, buf, sizeof(buf));
|
rv = readlink(TESTFILE, buf, sizeof(buf));
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
readlink_dir(void)
|
readlink_dir(void)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -64,11 +66,11 @@ readlink_dir(void)
|
|||||||
|
|
||||||
report_begin("readlink on .");
|
report_begin("readlink on .");
|
||||||
rv = readlink(".", buf, sizeof(buf));
|
rv = readlink(".", buf, sizeof(buf));
|
||||||
report_check(rv, errno, EISDIR);
|
return report_check(rv, errno, EISDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
readlink_empty(void)
|
readlink_empty(void)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@ -76,17 +78,31 @@ readlink_empty(void)
|
|||||||
|
|
||||||
report_begin("readlink on empty string");
|
report_begin("readlink on empty string");
|
||||||
rv = readlink("", buf, sizeof(buf));
|
rv = readlink("", buf, sizeof(buf));
|
||||||
report_check2(rv, errno, EISDIR, EINVAL);
|
return report_check2(rv, errno, EISDIR, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_readlink(void)
|
test_readlink(void)
|
||||||
{
|
{
|
||||||
test_readlink_path();
|
int ntests = 0, lost_points = 0;
|
||||||
test_readlink_buf();
|
int result;
|
||||||
|
|
||||||
readlink_file();
|
test_readlink_path(&ntests, &lost_points);
|
||||||
readlink_dir();
|
test_readlink_buf(&ntests, &lost_points);
|
||||||
readlink_empty();
|
|
||||||
|
ntests++;
|
||||||
|
result = readlink_file();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = readlink_dir();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = readlink_empty();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,19 +44,27 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
reboot_badflags(void)
|
reboot_badflags(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
printf("(This should not kill the system...)\n");
|
tprintf("(This should not kill the system...)\n");
|
||||||
report_begin("reboot with invalid flags");
|
report_begin("reboot with invalid flags");
|
||||||
rv = reboot(15353);
|
rv = reboot(15353);
|
||||||
report_check(rv, errno, EINVAL);
|
return report_check(rv, errno, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_reboot(void)
|
test_reboot(void)
|
||||||
{
|
{
|
||||||
reboot_badflags();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = reboot_badflags();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -44,63 +44,83 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
remove_dir(void)
|
remove_dir(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result = FAILED;
|
||||||
|
|
||||||
report_begin("remove() on a directory");
|
report_begin("remove() on a directory");
|
||||||
|
|
||||||
if (create_testdir() < 0) {
|
if (create_testdir() < 0) {
|
||||||
/*report_aborted();*/ /* XXX in create_testdir */
|
/*report_aborted();*/ /* XXX in create_testdir */
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = remove(TESTDIR);
|
rv = remove(TESTDIR);
|
||||||
report_check(rv, errno, EISDIR);
|
result = report_check(rv, errno, EISDIR);
|
||||||
rmdir(TESTDIR);
|
rmdir(TESTDIR);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
remove_dot(void)
|
remove_dot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("remove() on .");
|
report_begin("remove() on .");
|
||||||
rv = remove(".");
|
rv = remove(".");
|
||||||
report_check2(rv, errno, EISDIR, EINVAL);
|
return report_check2(rv, errno, EISDIR, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
remove_dotdot(void)
|
remove_dotdot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("remove() on ..");
|
report_begin("remove() on ..");
|
||||||
rv = remove("..");
|
rv = remove("..");
|
||||||
report_check2(rv, errno, EISDIR, EINVAL);
|
return report_check2(rv, errno, EISDIR, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
remove_empty(void)
|
remove_empty(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("remove() on empty string");
|
report_begin("remove() on empty string");
|
||||||
rv = remove("");
|
rv = remove("");
|
||||||
report_check2(rv, errno, EISDIR, EINVAL);
|
return report_check2(rv, errno, EISDIR, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_remove(void)
|
test_remove(void)
|
||||||
{
|
{
|
||||||
test_remove_path();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
remove_dir();
|
test_remove_path(&ntests, &lost_points);
|
||||||
remove_dot();
|
|
||||||
remove_dotdot();
|
ntests++;
|
||||||
remove_empty();
|
result = remove_dir();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = remove_dot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = remove_dotdot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = remove_empty();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -37,75 +37,100 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rename_dot(void)
|
rename_dot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("rename .");
|
report_begin("rename .");
|
||||||
|
|
||||||
rv = rename(".", TESTDIR);
|
rv = rename(".", TESTDIR);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
if (rv==0) {
|
if (rv==0) {
|
||||||
/* oops... put it back */
|
/* oops... put it back */
|
||||||
rename(TESTDIR, ".");
|
rename(TESTDIR, ".");
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rename_dotdot(void)
|
rename_dotdot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("rename ..");
|
report_begin("rename ..");
|
||||||
rv = rename("..", TESTDIR);
|
rv = rename("..", TESTDIR);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
if (rv==0) {
|
if (rv==0) {
|
||||||
/* oops... put it back */
|
/* oops... put it back */
|
||||||
rename(TESTDIR, "..");
|
rename(TESTDIR, "..");
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rename_empty1(void)
|
rename_empty1(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("rename empty string");
|
report_begin("rename empty string");
|
||||||
rv = rename("", TESTDIR);
|
rv = rename("", TESTDIR);
|
||||||
report_check2(rv, errno, EISDIR, EINVAL);
|
result = report_check2(rv, errno, EISDIR, EINVAL);
|
||||||
if (rv==0) {
|
if (rv==0) {
|
||||||
/* don't try to remove it */
|
/* don't try to remove it */
|
||||||
rename(TESTDIR, TESTDIR "-foo");
|
rename(TESTDIR, TESTDIR "-foo");
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rename_empty2(void)
|
rename_empty2(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result = FAILED;
|
||||||
|
|
||||||
report_begin("rename to empty string");
|
report_begin("rename to empty string");
|
||||||
if (create_testdir()<0) {
|
if (create_testdir()<0) {
|
||||||
/*report_aborted();*/ /* XXX in create_testdir */
|
/*report_aborted();*/ /* XXX in create_testdir */
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
rv = rename(TESTDIR, "");
|
rv = rename(TESTDIR, "");
|
||||||
report_check2(rv, errno, EISDIR, EINVAL);
|
result = report_check2(rv, errno, EISDIR, EINVAL);
|
||||||
rmdir(TESTDIR);
|
rmdir(TESTDIR);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_rename(void)
|
test_rename(void)
|
||||||
{
|
{
|
||||||
test_rename_paths();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
rename_dot();
|
test_rename_paths(&ntests, &lost_points);
|
||||||
rename_dotdot();
|
|
||||||
rename_empty1();
|
ntests++;
|
||||||
rename_empty2();
|
result = rename_dot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = rename_dotdot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = rename_empty1();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = rename_empty2();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,61 +44,83 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rmdir_file(void)
|
rmdir_file(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("rmdir a file");
|
report_begin("rmdir a file");
|
||||||
if (create_testfile()<0) {
|
if (create_testfile()<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
rv = rmdir(TESTFILE);
|
rv = rmdir(TESTFILE);
|
||||||
report_check(rv, errno, ENOTDIR);
|
result = report_check(rv, errno, ENOTDIR);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rmdir_dot(void)
|
rmdir_dot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("rmdir .");
|
report_begin("rmdir .");
|
||||||
rv = rmdir(".");
|
rv = rmdir(".");
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rmdir_dotdot(void)
|
rmdir_dotdot(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("rmdir ..");
|
report_begin("rmdir ..");
|
||||||
rv = rmdir("..");
|
rv = rmdir("..");
|
||||||
report_check2(rv, errno, EINVAL, ENOTEMPTY);
|
return report_check2(rv, errno, EINVAL, ENOTEMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
rmdir_empty(void)
|
rmdir_empty(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("rmdir empty string");
|
report_begin("rmdir empty string");
|
||||||
rv = rmdir("");
|
rv = rmdir("");
|
||||||
report_check(rv, errno, EINVAL);
|
return report_check(rv, errno, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_rmdir(void)
|
test_rmdir(void)
|
||||||
{
|
{
|
||||||
test_rmdir_path();
|
int ntests = 0, lost_points = 0;
|
||||||
|
int result;
|
||||||
|
|
||||||
rmdir_file();
|
test_rmdir_path(&ntests, &lost_points);
|
||||||
rmdir_dot();
|
|
||||||
rmdir_dotdot();
|
ntests++;
|
||||||
rmdir_empty();
|
result = rmdir_file();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = rmdir_dot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = rmdir_dotdot();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = rmdir_empty();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ try_sbrk(long val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
enforce_sbrk(long val, const char *desc, int err)
|
enforce_sbrk(long val, const char *desc, int err)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@ -67,59 +67,79 @@ enforce_sbrk(long val, const char *desc, int err)
|
|||||||
report_begin("sbrk %s", desc);
|
report_begin("sbrk %s", desc);
|
||||||
|
|
||||||
result = try_sbrk(val);
|
result = try_sbrk(val);
|
||||||
report_check(result, errno, err);
|
return report_check(result, errno, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
sbrk_bigpos(void)
|
sbrk_bigpos(void)
|
||||||
{
|
{
|
||||||
enforce_sbrk(4096*1024*256, "huge positive", ENOMEM);
|
return enforce_sbrk(1024*1024*1024 + (1024*1024*1024 - 4096*17), "huge positive", ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
sbrk_bigneg(void)
|
sbrk_bigneg(void)
|
||||||
{
|
{
|
||||||
enforce_sbrk(-4096*1024*256, "huge negative", EINVAL);
|
return enforce_sbrk(-4096*1024*256, "huge negative", EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
sbrk_neg(void)
|
sbrk_neg(void)
|
||||||
{
|
{
|
||||||
enforce_sbrk(-8192, "too-large negative", EINVAL);
|
return enforce_sbrk(-8192, "too-large negative", EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
sbrk_unalignedpos(void)
|
sbrk_unalignedpos(void)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
report_begin("sbrk unaligned positive");
|
report_begin("sbrk unaligned positive");
|
||||||
result = try_sbrk(17);
|
result = try_sbrk(17);
|
||||||
report_check2(result, errno, 0, EINVAL);
|
return report_check2(result, errno, 0, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
sbrk_unalignedneg(void)
|
sbrk_unalignedneg(void)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
report_begin("sbrk unaligned negative");
|
report_begin("sbrk unaligned negative");
|
||||||
result = try_sbrk(-17);
|
result = try_sbrk(-17);
|
||||||
report_check2(result, errno, 0, EINVAL);
|
return report_check2(result, errno, 0, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_sbrk(void)
|
test_sbrk(void)
|
||||||
{
|
{
|
||||||
sbrk_neg();
|
int ntests = 0, lost_points = 0;
|
||||||
sbrk_bigpos();
|
int result;
|
||||||
sbrk_bigneg();
|
|
||||||
sbrk_unalignedpos();
|
ntests++;
|
||||||
sbrk_unalignedneg();
|
result = sbrk_neg();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = sbrk_bigpos();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = sbrk_bigneg();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = sbrk_unalignedpos();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = sbrk_unalignedneg();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ badbuf_stat(struct stat *sb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
common_badbuf(int (*statfunc)(struct stat *), void *ptr,
|
common_badbuf(int (*statfunc)(struct stat *), void *ptr,
|
||||||
const char *call, const char *ptrdesc)
|
const char *call, const char *ptrdesc)
|
||||||
{
|
{
|
||||||
@ -75,22 +75,24 @@ common_badbuf(int (*statfunc)(struct stat *), void *ptr,
|
|||||||
|
|
||||||
report_begin("%s with %s buf", call, ptrdesc);
|
report_begin("%s with %s buf", call, ptrdesc);
|
||||||
rv = statfunc(ptr);
|
rv = statfunc(ptr);
|
||||||
report_check(rv, errno, EFAULT);
|
return report_check(rv, errno, EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
any_badbuf(int (*statfunc)(struct stat *), const char *call)
|
any_badbuf(int (*statfunc)(struct stat *), const char *call)
|
||||||
{
|
{
|
||||||
common_badbuf(statfunc, NULL, call, "NULL");
|
int result;
|
||||||
common_badbuf(statfunc, INVAL_PTR, call, "invalid pointer");
|
result = common_badbuf(statfunc, NULL, call, "NULL");
|
||||||
common_badbuf(statfunc, KERN_PTR, call, "kernel pointer");
|
result |= common_badbuf(statfunc, INVAL_PTR, call, "invalid pointer");
|
||||||
|
result |= common_badbuf(statfunc, KERN_PTR, call, "kernel pointer");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
any_empty(int (*statfunc)(const char *, struct stat *), const char *call)
|
any_empty(int (*statfunc)(const char *, struct stat *), const char *call)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
@ -98,7 +100,7 @@ any_empty(int (*statfunc)(const char *, struct stat *), const char *call)
|
|||||||
|
|
||||||
report_begin("%s on empty string", call);
|
report_begin("%s on empty string", call);
|
||||||
rv = statfunc("", &sb);
|
rv = statfunc("", &sb);
|
||||||
report_check2(rv, errno, 0, EINVAL);
|
return report_check2(rv, errno, 0, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -106,23 +108,56 @@ any_empty(int (*statfunc)(const char *, struct stat *), const char *call)
|
|||||||
void
|
void
|
||||||
test_fstat(void)
|
test_fstat(void)
|
||||||
{
|
{
|
||||||
test_fstat_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
any_badbuf(badbuf_fstat, "fstat");
|
int result;
|
||||||
|
|
||||||
|
test_fstat_fd(&ntests, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = any_badbuf(badbuf_fstat, "fstat");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_lstat(void)
|
test_lstat(void)
|
||||||
{
|
{
|
||||||
test_lstat_path();
|
int ntests = 0, lost_points = 0;
|
||||||
any_empty(lstat, "lstat");
|
int result;
|
||||||
any_badbuf(badbuf_lstat, "lstat");
|
|
||||||
|
test_lstat_path(&ntests, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = any_empty(lstat, "lstat");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = any_badbuf(badbuf_lstat, "lstat");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_stat(void)
|
test_stat(void)
|
||||||
{
|
{
|
||||||
test_stat_path();
|
int ntests = 0, lost_points = 0;
|
||||||
any_empty(stat, "stat");
|
int result;
|
||||||
any_badbuf(badbuf_stat, "stat");
|
|
||||||
|
test_stat_path(&ntests, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = any_empty(stat, "stat");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = any_badbuf(badbuf_stat, "stat");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,32 +37,47 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
symlink_empty1(void)
|
symlink_empty1(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("symlink -> empty string");
|
report_begin("symlink -> empty string");
|
||||||
rv = symlink("", TESTLINK);
|
rv = symlink("", TESTLINK);
|
||||||
report_check2(rv, errno, 0, EINVAL);
|
result = report_check2(rv, errno, 0, EINVAL);
|
||||||
remove(TESTLINK);
|
remove(TESTLINK);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
symlink_empty2(void)
|
symlink_empty2(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("symlink named empty string");
|
report_begin("symlink named empty string");
|
||||||
rv = symlink("foo", "");
|
rv = symlink("foo", "");
|
||||||
report_check(rv, errno, EINVAL);
|
return report_check(rv, errno, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_symlink(void)
|
test_symlink(void)
|
||||||
{
|
{
|
||||||
test_symlink_paths();
|
int ntests = 0, lost_points = 0;
|
||||||
symlink_empty1();
|
int result;
|
||||||
symlink_empty2();
|
|
||||||
|
|
||||||
|
test_symlink_paths(&ntests, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = symlink_empty1();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = symlink_empty2();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -44,33 +44,49 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
time_badsecs(void *ptr, const char *desc)
|
time_badsecs(void *ptr, const char *desc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("%s", desc);
|
report_begin("%s", desc);
|
||||||
rv = __time(ptr, NULL);
|
rv = __time(ptr, NULL);
|
||||||
report_check(rv, errno, EFAULT);
|
return report_check(rv, errno, EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
time_badnsecs(void *ptr, const char *desc)
|
time_badnsecs(void *ptr, const char *desc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
report_begin("%s", desc);
|
report_begin("%s", desc);
|
||||||
rv = __time(NULL, ptr);
|
rv = __time(NULL, ptr);
|
||||||
report_check(rv, errno, EFAULT);
|
return report_check(rv, errno, EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
test_time(void)
|
test_time(void)
|
||||||
{
|
{
|
||||||
time_badsecs(INVAL_PTR, "__time with invalid seconds pointer");
|
int ntests = 0, lost_points = 0;
|
||||||
time_badsecs(KERN_PTR, "__time with kernel seconds pointer");
|
int result;
|
||||||
|
|
||||||
time_badnsecs(INVAL_PTR, "__time with invalid nsecs pointer");
|
ntests++;
|
||||||
time_badnsecs(KERN_PTR, "__time with kernel nsecs pointer");
|
result = time_badsecs(INVAL_PTR, "__time with invalid seconds pointer");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = time_badsecs(KERN_PTR, "__time with kernel seconds pointer");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = time_badnsecs(INVAL_PTR, "__time with invalid nsecs pointer");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = time_badnsecs(KERN_PTR, "__time with kernel nsecs pointer");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_badpid(pid_t pid, const char *desc)
|
wait_badpid(pid_t pid, const char *desc)
|
||||||
{
|
{
|
||||||
pid_t rv;
|
pid_t rv;
|
||||||
@ -59,23 +59,24 @@ wait_badpid(pid_t pid, const char *desc)
|
|||||||
else if (err == ENOSYS) {
|
else if (err == ENOSYS) {
|
||||||
report_saw_enosys();
|
report_saw_enosys();
|
||||||
}
|
}
|
||||||
report_check2(rv, err, ESRCH, ECHILD);
|
return report_check2(rv, err, ESRCH, ECHILD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_nullstatus(void)
|
wait_nullstatus(void)
|
||||||
{
|
{
|
||||||
pid_t pid, rv;
|
pid_t pid, rv;
|
||||||
int x;
|
int x;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("wait with NULL status");
|
report_begin("wait with NULL status");
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid<0) {
|
if (pid<0) {
|
||||||
report_warn("fork failed");
|
report_warn("fork failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (pid==0) {
|
if (pid==0) {
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -83,50 +84,54 @@ wait_nullstatus(void)
|
|||||||
|
|
||||||
/* POSIX explicitly says passing NULL for status is allowed */
|
/* POSIX explicitly says passing NULL for status is allowed */
|
||||||
rv = waitpid(pid, NULL, 0);
|
rv = waitpid(pid, NULL, 0);
|
||||||
report_check(rv, errno, 0);
|
result = report_check(rv, errno, 0);
|
||||||
waitpid(pid, &x, 0);
|
waitpid(pid, &x, 0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_badstatus(void *ptr, const char *desc)
|
wait_badstatus(void *ptr, const char *desc)
|
||||||
{
|
{
|
||||||
pid_t pid, rv;
|
pid_t pid, rv;
|
||||||
int x;
|
int x;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin(desc);
|
report_begin(desc);
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid<0) {
|
if (pid<0) {
|
||||||
report_warn("fork failed");
|
report_warn("fork failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (pid==0) {
|
if (pid==0) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = waitpid(pid, ptr, 0);
|
rv = waitpid(pid, ptr, 0);
|
||||||
report_check(rv, errno, EFAULT);
|
result = report_check(rv, errno, EFAULT);
|
||||||
waitpid(pid, &x, 0);
|
waitpid(pid, &x, 0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_unaligned(void)
|
wait_unaligned(void)
|
||||||
{
|
{
|
||||||
pid_t pid, rv;
|
pid_t pid, rv;
|
||||||
int x;
|
int x;
|
||||||
int status[2]; /* will have integer alignment */
|
int status[2]; /* will have integer alignment */
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("wait with unaligned status");
|
report_begin("wait with unaligned status");
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid<0) {
|
if (pid<0) {
|
||||||
report_warn("fork failed");
|
report_warn("fork failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (pid==0) {
|
if (pid==0) {
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -139,55 +144,61 @@ wait_unaligned(void)
|
|||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
rv = waitpid(pid, (int *)ptr, 0);
|
rv = waitpid(pid, (int *)ptr, 0);
|
||||||
report_survival(rv, errno);
|
report_survival(rv, errno, &result);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
waitpid(pid, &x, 0);
|
waitpid(pid, &x, 0);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_badflags(void)
|
wait_badflags(void)
|
||||||
{
|
{
|
||||||
pid_t pid, rv;
|
pid_t pid, rv;
|
||||||
int x;
|
int x;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("wait with bad flags");
|
report_begin("wait with bad flags");
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid<0) {
|
if (pid<0) {
|
||||||
report_warn("fork failed");
|
report_warn("fork failed");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (pid==0) {
|
if (pid==0) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = waitpid(pid, &x, 309429);
|
rv = waitpid(pid, &x, 309429);
|
||||||
report_check(rv, errno, EINVAL);
|
result = report_check(rv, errno, EINVAL);
|
||||||
waitpid(pid, &x, 0);
|
waitpid(pid, &x, 0);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_self(void)
|
wait_self(void)
|
||||||
{
|
{
|
||||||
pid_t rv;
|
pid_t rv;
|
||||||
int x;
|
int x;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("wait for self");
|
report_begin("wait for self");
|
||||||
|
|
||||||
rv = waitpid(getpid(), &x, 0);
|
rv = waitpid(getpid(), &x, 0);
|
||||||
report_survival(rv, errno);
|
report_survival(rv, errno, &result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_parent(void)
|
wait_parent(void)
|
||||||
{
|
{
|
||||||
pid_t mypid, childpid, rv;
|
pid_t mypid, childpid, rv;
|
||||||
int x;
|
int x;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("wait for parent");
|
report_begin("wait for parent");
|
||||||
report_hassubs();
|
report_hassubs();
|
||||||
@ -196,30 +207,32 @@ wait_parent(void)
|
|||||||
childpid = fork();
|
childpid = fork();
|
||||||
if (childpid<0) {
|
if (childpid<0) {
|
||||||
report_warn("can't fork");
|
report_warn("can't fork");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (childpid==0) {
|
if (childpid==0) {
|
||||||
/* Child. Wait for parent. */
|
/* Child. Wait for parent. */
|
||||||
rv = waitpid(mypid, &x, 0);
|
rv = waitpid(mypid, &x, 0);
|
||||||
report_beginsub("from child:");
|
report_beginsub("from child:");
|
||||||
report_survival(rv, errno);
|
report_survival(rv, errno, &result);
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
rv = waitpid(childpid, &x, 0);
|
rv = waitpid(mypid, &x, 0);
|
||||||
report_beginsub("from parent:");
|
report_beginsub("from parent:");
|
||||||
report_survival(rv, errno);
|
report_survival(rv, errno, &result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_siblings_child(const char *semname)
|
wait_siblings_child(const char *semname)
|
||||||
{
|
{
|
||||||
pid_t pids[2], mypid, otherpid;
|
pid_t pids[2], mypid, otherpid;
|
||||||
int rv, fd, semfd, x;
|
int rv, fd, semfd, x;
|
||||||
char c;
|
char c;
|
||||||
|
int result;
|
||||||
|
|
||||||
mypid = getpid();
|
mypid = getpid();
|
||||||
|
|
||||||
@ -244,7 +257,7 @@ wait_siblings_child(const char *semname)
|
|||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_warn("child process (pid %d) can't open %s",
|
report_warn("child process (pid %d) can't open %s",
|
||||||
mypid, TESTFILE);
|
mypid, TESTFILE);
|
||||||
return;
|
return FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -257,13 +270,13 @@ wait_siblings_child(const char *semname)
|
|||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
report_warn("child process (pid %d) lseek error",
|
report_warn("child process (pid %d) lseek error",
|
||||||
mypid);
|
mypid);
|
||||||
return;
|
return FAILED;
|
||||||
}
|
}
|
||||||
rv = read(fd, pids, sizeof(pids));
|
rv = read(fd, pids, sizeof(pids));
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
report_warn("child process (pid %d) read error",
|
report_warn("child process (pid %d) read error",
|
||||||
mypid);
|
mypid);
|
||||||
return;
|
return FAILED;
|
||||||
}
|
}
|
||||||
} while (rv < (int)sizeof(pids));
|
} while (rv < (int)sizeof(pids));
|
||||||
|
|
||||||
@ -276,23 +289,25 @@ wait_siblings_child(const char *semname)
|
|||||||
else {
|
else {
|
||||||
report_warn("child process (pid %d) got garbage in comm file",
|
report_warn("child process (pid %d) got garbage in comm file",
|
||||||
mypid);
|
mypid);
|
||||||
return;
|
return FAILED;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
rv = waitpid(otherpid, &x, 0);
|
rv = waitpid(otherpid, &x, 0);
|
||||||
report_beginsub("sibling (pid %d)", mypid);
|
report_beginsub("sibling (pid %d)", mypid);
|
||||||
report_survival(rv, errno);
|
report_survival(rv, errno, &result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
wait_siblings(void)
|
wait_siblings(void)
|
||||||
{
|
{
|
||||||
pid_t pids[2];
|
pid_t pids[2];
|
||||||
int rv, fd, semfd, x;
|
int rv, fd, semfd, x;
|
||||||
int bad = 0;
|
int bad = 0;
|
||||||
char semname[32];
|
char semname[32];
|
||||||
|
int result;
|
||||||
|
|
||||||
/* This test may also blow up if FS synchronization is substandard */
|
/* This test may also blow up if FS synchronization is substandard */
|
||||||
|
|
||||||
@ -303,26 +318,26 @@ wait_siblings(void)
|
|||||||
semfd = open(semname, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
semfd = open(semname, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
||||||
if (semfd < 0) {
|
if (semfd < 0) {
|
||||||
report_warn("can't make semaphore");
|
report_warn("can't make semaphore");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open_testfile(NULL);
|
fd = open_testfile(NULL);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
close(semfd);
|
close(semfd);
|
||||||
remove(semname);
|
remove(semname);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pids[0] = fork();
|
pids[0] = fork();
|
||||||
if (pids[0]<0) {
|
if (pids[0]<0) {
|
||||||
report_warn("can't fork");
|
report_warn("can't fork");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
close(fd);
|
close(fd);
|
||||||
close(semfd);
|
close(semfd);
|
||||||
remove(semname);
|
remove(semname);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (pids[0]==0) {
|
if (pids[0]==0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -334,12 +349,12 @@ wait_siblings(void)
|
|||||||
pids[1] = fork();
|
pids[1] = fork();
|
||||||
if (pids[1]<0) {
|
if (pids[1]<0) {
|
||||||
report_warn("can't fork");
|
report_warn("can't fork");
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
/* abandon the other child process :( */
|
/* abandon the other child process :( */
|
||||||
close(fd);
|
close(fd);
|
||||||
close(semfd);
|
close(semfd);
|
||||||
remove(semname);
|
remove(semname);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (pids[1]==0) {
|
if (pids[1]==0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -351,21 +366,21 @@ wait_siblings(void)
|
|||||||
rv = write(fd, pids, sizeof(pids));
|
rv = write(fd, pids, sizeof(pids));
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
report_warn("write error on %s", TESTFILE);
|
report_warn("write error on %s", TESTFILE);
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
/* abandon child procs :( */
|
/* abandon child procs :( */
|
||||||
close(fd);
|
close(fd);
|
||||||
close(semfd);
|
close(semfd);
|
||||||
remove(semname);
|
remove(semname);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
if (rv != (int)sizeof(pids)) {
|
if (rv != (int)sizeof(pids)) {
|
||||||
report_warnx("write error on %s: short count", TESTFILE);
|
report_warnx("write error on %s: short count", TESTFILE);
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
/* abandon child procs :( */
|
/* abandon child procs :( */
|
||||||
close(fd);
|
close(fd);
|
||||||
close(semfd);
|
close(semfd);
|
||||||
remove(semname);
|
remove(semname);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gate the child procs */
|
/* gate the child procs */
|
||||||
@ -388,15 +403,17 @@ wait_siblings(void)
|
|||||||
}
|
}
|
||||||
if (bad) {
|
if (bad) {
|
||||||
/* XXX: aborted, or failure, or what? */
|
/* XXX: aborted, or failure, or what? */
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
report_passed();
|
report_passed(&result);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
close(semfd);
|
close(semfd);
|
||||||
remove(semname);
|
remove(semname);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -404,20 +421,61 @@ wait_siblings(void)
|
|||||||
void
|
void
|
||||||
test_waitpid(void)
|
test_waitpid(void)
|
||||||
{
|
{
|
||||||
wait_badpid(-8, "wait for pid -8");
|
int ntests = 0, lost_points = 0;
|
||||||
wait_badpid(-1, "wait for pid -1");
|
int result;
|
||||||
wait_badpid(0, "pid zero");
|
|
||||||
wait_badpid(NONEXIST_PID, "nonexistent pid");
|
|
||||||
|
|
||||||
wait_nullstatus();
|
ntests++;
|
||||||
wait_badstatus(INVAL_PTR, "wait with invalid pointer status");
|
result = wait_badpid(-8, "wait for pid -8");
|
||||||
wait_badstatus(KERN_PTR, "wait with kernel pointer status");
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
wait_unaligned();
|
ntests++;
|
||||||
|
result = wait_badpid(-1, "wait for pid -1");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
wait_badflags();
|
ntests++;
|
||||||
|
result = wait_badpid(0, "pid zero");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
wait_self();
|
ntests++;
|
||||||
wait_parent();
|
result = wait_badpid(NONEXIST_PID, "nonexistent pid");
|
||||||
wait_siblings();
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_nullstatus();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_badstatus(INVAL_PTR, "wait with invalid pointer status");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_badstatus(KERN_PTR, "wait with kernel pointer status");
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_unaligned();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_badflags();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_self();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_parent();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
ntests++;
|
||||||
|
result = wait_siblings();
|
||||||
|
handle_result(result, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,11 @@
|
|||||||
void
|
void
|
||||||
test_write(void)
|
test_write(void)
|
||||||
{
|
{
|
||||||
test_write_fd();
|
int ntests = 0, lost_points = 0;
|
||||||
test_write_buf();
|
|
||||||
|
test_write_fd(&ntests, &lost_points);
|
||||||
|
test_write_buf(&ntests, &lost_points);
|
||||||
|
|
||||||
|
if(!lost_points)
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/badcall");
|
||||||
}
|
}
|
||||||
|
@ -175,33 +175,46 @@ getcwd_badbuf(void *buf)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
common_badbuf(struct buftest *info, void *buf, const char *bufdesc)
|
common_badbuf(struct buftest *info, void *buf, const char *bufdesc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("%s with %s buffer", info->name, bufdesc);
|
report_begin("%s with %s buffer", info->name, bufdesc);
|
||||||
info->setup();
|
info->setup();
|
||||||
rv = info->op(buf);
|
rv = info->op(buf);
|
||||||
report_check(rv, errno, EFAULT);
|
result = report_check(rv, errno, EFAULT);
|
||||||
info->cleanup();
|
info->cleanup();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
any_badbuf(struct buftest *info)
|
any_badbuf(struct buftest *info, int *ntests, int *lost_points)
|
||||||
{
|
{
|
||||||
common_badbuf(info, NULL, "NULL");
|
int result;
|
||||||
common_badbuf(info, INVAL_PTR, "invalid");
|
|
||||||
common_badbuf(info, KERN_PTR, "kernel-space");
|
*ntests += 1;
|
||||||
|
result = common_badbuf(info, NULL, "NULL");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
|
*ntests += 1;
|
||||||
|
result = common_badbuf(info, INVAL_PTR, "invalid");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
|
*ntests += 1;
|
||||||
|
result = common_badbuf(info, KERN_PTR, "kernel-space");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define T(call) \
|
#define T(call) \
|
||||||
void \
|
void \
|
||||||
test_##call##_buf(void) \
|
test_##call##_buf(int *ntests, int *lost_points) \
|
||||||
{ \
|
{ \
|
||||||
static struct buftest info = { \
|
static struct buftest info = { \
|
||||||
call##_setup, \
|
call##_setup, \
|
||||||
@ -209,7 +222,7 @@ any_badbuf(struct buftest *info)
|
|||||||
call##_cleanup, \
|
call##_cleanup, \
|
||||||
#call, \
|
#call, \
|
||||||
}; \
|
}; \
|
||||||
any_badbuf(&info); \
|
any_badbuf(&info, ntests, lost_points); \
|
||||||
}
|
}
|
||||||
|
|
||||||
T(read);
|
T(read);
|
||||||
|
@ -138,46 +138,58 @@ dup2_cleanup(void)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
any_badfd(int (*func)(int fd), void (*cleanup)(void), const char *callname,
|
any_badfd(int (*func)(int fd), void (*cleanup)(void), const char *callname,
|
||||||
int fd, const char *fddesc)
|
int fd, const char *fddesc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
report_begin("%s using %s", callname, fddesc);
|
report_begin("%s using %s", callname, fddesc);
|
||||||
rv = func(fd);
|
rv = func(fd);
|
||||||
report_check(rv, errno, EBADF);
|
result = report_check(rv, errno, EBADF);
|
||||||
if (cleanup) {
|
if (cleanup) {
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname,
|
runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname,
|
||||||
enum rwtestmodes rw)
|
enum rwtestmodes rw, int *ntests, int *lost_points)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
int result;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If adding cases, also see bad_dup2.c
|
* If adding cases, also see bad_dup2.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* basic invalid case: fd -1 */
|
/* basic invalid case: fd -1 */
|
||||||
any_badfd(func, cleanup, callname, -1, "fd -1");
|
*ntests += 1;
|
||||||
|
result = any_badfd(func, cleanup, callname, -1, "fd -1");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
/* also try -5 in case -1 is special somehow */
|
/* also try -5 in case -1 is special somehow */
|
||||||
any_badfd(func, cleanup, callname, -5, "fd -5");
|
*ntests += 1;
|
||||||
|
result = any_badfd(func, cleanup, callname, -5, "fd -5");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
/* try a fd we know is closed */
|
/* try a fd we know is closed */
|
||||||
any_badfd(func, cleanup, callname, CLOSED_FD, "closed fd");
|
*ntests += 1;
|
||||||
|
result = any_badfd(func, cleanup, callname, CLOSED_FD, "closed fd");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
/* try a positive fd we know is out of range */
|
/* try a positive fd we know is out of range */
|
||||||
any_badfd(func, cleanup, callname, IMPOSSIBLE_FD, "impossible fd");
|
*ntests += 1;
|
||||||
|
result = any_badfd(func, cleanup, callname, IMPOSSIBLE_FD, "impossible fd");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
/* test for off-by-one errors */
|
/* test for off-by-one errors */
|
||||||
#ifdef OPEN_MAX
|
#ifdef OPEN_MAX
|
||||||
any_badfd(func, cleanup, callname, OPEN_MAX, "fd OPEN_MAX");
|
*ntests += 1;
|
||||||
|
result = any_badfd(func, cleanup, callname, OPEN_MAX, "fd OPEN_MAX");
|
||||||
|
handle_result(result, lost_points);
|
||||||
#else
|
#else
|
||||||
warnx("Warning: OPEN_MAX not defined, test skipped");
|
warnx("Warning: OPEN_MAX not defined, test skipped");
|
||||||
#endif
|
#endif
|
||||||
@ -188,8 +200,10 @@ runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname,
|
|||||||
/* already printed a message */
|
/* already printed a message */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
any_badfd(func, cleanup, callname, fd,
|
*ntests += 1;
|
||||||
|
result = any_badfd(func, cleanup, callname, fd,
|
||||||
"fd opened read-only");
|
"fd opened read-only");
|
||||||
|
handle_result(result, lost_points);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@ -199,8 +213,10 @@ runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname,
|
|||||||
/* already printed a message */
|
/* already printed a message */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
any_badfd(func, cleanup, callname, fd,
|
*ntests += 1;
|
||||||
|
result = any_badfd(func, cleanup, callname, fd,
|
||||||
"fd opened write-only");
|
"fd opened write-only");
|
||||||
|
handle_result(result, lost_points);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@ -208,18 +224,18 @@ runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname,
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define T(call, rw) \
|
#define T(call, rw) \
|
||||||
void \
|
void \
|
||||||
test_##call##_fd(void) \
|
test_##call##_fd(int *ntests, int *lost_points) \
|
||||||
{ \
|
{ \
|
||||||
runtest(call##_badfd, NULL, #call, rw); \
|
runtest(call##_badfd, NULL, #call, rw, ntests, lost_points); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TC(call, rw) \
|
#define TC(call, rw) \
|
||||||
void \
|
void \
|
||||||
test_##call##_fd(void) \
|
test_##call##_fd(int *ntests, int *lost_points) \
|
||||||
{ \
|
{ \
|
||||||
runtest(call##_badfd, call##_cleanup, #call, rw);\
|
runtest(call##_badfd, call##_cleanup, #call, rw, ntests, lost_points); \
|
||||||
}
|
}
|
||||||
|
|
||||||
T(read, RW_TEST_WRONLY);
|
T(read, RW_TEST_WRONLY);
|
||||||
|
@ -148,46 +148,58 @@ stat_badpath(const char *name)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
common_badpath(int (*func)(const char *path), int mk, int rm, const char *path,
|
common_badpath(int (*func)(const char *path), int mk, int rm, const char *path,
|
||||||
const char *call, const char *pathdesc)
|
const char *call, const char *pathdesc)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
report_begin("%s with %s path", call, pathdesc);
|
report_begin("%s with %s path", call, pathdesc);
|
||||||
|
|
||||||
if (mk) {
|
if (mk) {
|
||||||
if (create_testfile()<0) {
|
if (create_testfile()<0) {
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = func(path);
|
rv = func(path);
|
||||||
report_check(rv, errno, EFAULT);
|
result = report_check(rv, errno, EFAULT);
|
||||||
|
|
||||||
if (mk || rm) {
|
if (mk || rm) {
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
any_badpath(int (*func)(const char *path), const char *call, int mk, int rm)
|
any_badpath(int (*func)(const char *path), const char *call, int mk, int rm,
|
||||||
|
int *ntests, int *lost_points)
|
||||||
{
|
{
|
||||||
common_badpath(func, mk, rm, NULL, call, "NULL");
|
int result;
|
||||||
common_badpath(func, mk, rm, INVAL_PTR, call, "invalid-pointer");
|
// We have a total of 3 tests
|
||||||
common_badpath(func, mk, rm, KERN_PTR, call, "kernel-pointer");
|
*ntests = *ntests + 3;
|
||||||
|
|
||||||
|
result = common_badpath(func, mk, rm, NULL, call, "NULL");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
|
result = common_badpath(func, mk, rm, INVAL_PTR, call, "invalid-pointer");
|
||||||
|
handle_result(result, lost_points);
|
||||||
|
|
||||||
|
result = common_badpath(func, mk, rm, KERN_PTR, call, "kernel-pointer");
|
||||||
|
handle_result(result, lost_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/* functions with one pathname */
|
/* functions with one pathname */
|
||||||
#define T(call) \
|
#define T(call) \
|
||||||
void \
|
void \
|
||||||
test_##call##_path(void) \
|
test_##call##_path(int *ntests, int *lost_points) \
|
||||||
{ \
|
{ \
|
||||||
any_badpath(call##_badpath, #call, 0, 0); \
|
any_badpath(call##_badpath, #call, 0, 0, ntests, lost_points); \
|
||||||
}
|
}
|
||||||
|
|
||||||
T(open);
|
T(open);
|
||||||
@ -200,12 +212,12 @@ T(stat);
|
|||||||
T(lstat);
|
T(lstat);
|
||||||
|
|
||||||
/* functions with two pathnames */
|
/* functions with two pathnames */
|
||||||
#define T2(call) \
|
#define T2(call) \
|
||||||
void \
|
void \
|
||||||
test_##call##_paths(void) \
|
test_##call##_paths(int *ntests, int *lost_points) \
|
||||||
{ \
|
{ \
|
||||||
any_badpath(call##_badpath1, #call "(arg1)", 0, 1); \
|
any_badpath(call##_badpath1, #call "(arg1)", 0, 1, ntests, lost_points); \
|
||||||
any_badpath(call##_badpath2, #call "(arg2)", 1, 1); \
|
any_badpath(call##_badpath2, #call "(arg2)", 1, 1, ntests, lost_points); \
|
||||||
}
|
}
|
||||||
|
|
||||||
T2(rename);
|
T2(rename);
|
||||||
|
@ -121,16 +121,18 @@ int
|
|||||||
create_testdir(void)
|
create_testdir(void)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
int result;
|
||||||
|
|
||||||
rv = mkdir(TESTDIR, 0775);
|
rv = mkdir(TESTDIR, 0775);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
if (errno == ENOSYS) {
|
if (errno == ENOSYS) {
|
||||||
report_saw_enosys();
|
report_saw_enosys();
|
||||||
report_warnx("mkdir unimplemented; cannot run test");
|
report_warnx("mkdir unimplemented; cannot run test");
|
||||||
report_skipped();
|
report_skipped(&result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
report_warn("mkdir %s failed", TESTDIR);
|
report_warn("mkdir %s failed", TESTDIR);
|
||||||
report_aborted();
|
report_aborted(&result);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -198,20 +200,20 @@ menu(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i=0; ops[i].name; i++) {
|
for (i=0; ops[i].name; i++) {
|
||||||
printf("[%c] %-24s", ops[i].ch, ops[i].name);
|
tprintf("[%c] %-24s", ops[i].ch, ops[i].name);
|
||||||
if (i%2==1) {
|
if (i%2==1) {
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i%2==1) {
|
if (i%2==1) {
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
printf("[1] %-24s", "asst1");
|
tprintf("[1] %-24s", "asst1");
|
||||||
printf("[2] %-24s\n", "asst2");
|
tprintf("[2] %-24s\n", "asst2");
|
||||||
printf("[3] %-24s", "asst3");
|
tprintf("[3] %-24s", "asst3");
|
||||||
printf("[4] %-24s\n", "asst4");
|
tprintf("[4] %-24s\n", "asst4");
|
||||||
printf("[*] %-24s", "all");
|
tprintf("[*] %-24s", "all");
|
||||||
printf("[!] %-24s\n", "quit");
|
tprintf("[!] %-24s\n", "quit");
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -231,7 +233,7 @@ runit(int op)
|
|||||||
|
|
||||||
if (op=='*') {
|
if (op=='*') {
|
||||||
for (i=0; ops[i].name; i++) {
|
for (i=0; ops[i].name; i++) {
|
||||||
printf("[%s]\n", ops[i].name);
|
tprintf("[%s]\n", ops[i].name);
|
||||||
ops[i].f();
|
ops[i].f();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -241,7 +243,7 @@ runit(int op)
|
|||||||
k = op-'0';
|
k = op-'0';
|
||||||
for (i=0; ops[i].name; i++) {
|
for (i=0; ops[i].name; i++) {
|
||||||
if (ops[i].asst <= k) {
|
if (ops[i].asst <= k) {
|
||||||
printf("[%s]\n", ops[i].name);
|
tprintf("[%s]\n", ops[i].name);
|
||||||
ops[i].f();
|
ops[i].f();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +251,7 @@ runit(int op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (op < LOWEST || op > HIGHEST) {
|
if (op < LOWEST || op > HIGHEST) {
|
||||||
printf("Invalid request %c\n", op);
|
tprintf("Invalid request %c\n", op);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,12 +263,12 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int op, i, j;
|
int op, i, j;
|
||||||
|
|
||||||
printf("[%c-%c, 1-4, *, ?=menu, !=quit]\n", LOWEST, HIGHEST);
|
tprintf("[%c-%c, 1-4, *, ?=menu, !=quit]\n", LOWEST, HIGHEST);
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
for (i=1; i<argc; i++) {
|
for (i=1; i<argc; i++) {
|
||||||
for (j=0; argv[i][j]; j++) {
|
for (j=0; argv[i][j]; j++) {
|
||||||
printf("Choose: %c\n",
|
tprintf("Choose: %c\n",
|
||||||
argv[i][j]);
|
argv[i][j]);
|
||||||
runit(argv[i][j]);
|
runit(argv[i][j]);
|
||||||
}
|
}
|
||||||
@ -275,12 +277,12 @@ main(int argc, char **argv)
|
|||||||
else {
|
else {
|
||||||
menu();
|
menu();
|
||||||
while (1) {
|
while (1) {
|
||||||
printf("Choose: ");
|
tprintf("Choose: ");
|
||||||
op = getchar();
|
op = getchar();
|
||||||
if (op==EOF) {
|
if (op==EOF) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("%c\n", op);
|
tprintf("%c\n", op);
|
||||||
runit(op);
|
runit(op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,27 +251,31 @@ report_end(const char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
report_passed(void)
|
report_passed(int *status)
|
||||||
{
|
{
|
||||||
report_end("passed");
|
report_end("passed");
|
||||||
|
*status = SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
report_failure(void)
|
report_failure(int *status)
|
||||||
{
|
{
|
||||||
report_end("FAILURE");
|
report_end("FAILURE");
|
||||||
|
*status = FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
report_skipped(void)
|
report_skipped(int *status)
|
||||||
{
|
{
|
||||||
report_end("------");
|
report_end("------");
|
||||||
|
*status = SKIPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
report_aborted(void)
|
report_aborted(int *status)
|
||||||
{
|
{
|
||||||
report_end("ABORTED");
|
report_end("ABORTED");
|
||||||
|
*status = ABORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -283,18 +287,19 @@ report_aborted(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
report_survival(int rv, int error)
|
report_survival(int rv, int error, int *result)
|
||||||
{
|
{
|
||||||
/* allow any error as long as we survive */
|
/* allow any error as long as we survive */
|
||||||
report_result(rv, error);
|
report_result(rv, error);
|
||||||
report_passed();
|
report_passed(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
int
|
||||||
report_checkN(int rv, int error, int *right_errors, int right_num)
|
report_checkN(int rv, int error, int *right_errors, int right_num)
|
||||||
{
|
{
|
||||||
int i, goterror;
|
int i, goterror;
|
||||||
|
int result = 1;
|
||||||
|
|
||||||
if (rv==-1) {
|
if (rv==-1) {
|
||||||
goterror = error;
|
goterror = error;
|
||||||
@ -306,39 +311,40 @@ report_checkN(int rv, int error, int *right_errors, int right_num)
|
|||||||
for (i=0; i<right_num; i++) {
|
for (i=0; i<right_num; i++) {
|
||||||
if (goterror == right_errors[i]) {
|
if (goterror == right_errors[i]) {
|
||||||
report_result(rv, error);
|
report_result(rv, error);
|
||||||
report_passed();
|
report_passed(&result);
|
||||||
return;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (goterror == ENOSYS) {
|
if (goterror == ENOSYS) {
|
||||||
report_saw_enosys();
|
report_saw_enosys();
|
||||||
say("(unimplemented) ");
|
say("(unimplemented) ");
|
||||||
report_skipped();
|
report_skipped(&result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
report_result(rv, error);
|
report_result(rv, error);
|
||||||
report_failure();
|
report_failure(&result);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
report_check(int rv, int error, int right_error)
|
report_check(int rv, int error, int right_error)
|
||||||
{
|
{
|
||||||
report_checkN(rv, error, &right_error, 1);
|
return report_checkN(rv, error, &right_error, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
report_check2(int rv, int error, int okerr1, int okerr2)
|
report_check2(int rv, int error, int okerr1, int okerr2)
|
||||||
{
|
{
|
||||||
int ok[2];
|
int ok[2];
|
||||||
|
|
||||||
ok[0] = okerr1;
|
ok[0] = okerr1;
|
||||||
ok[1] = okerr2;
|
ok[1] = okerr2;
|
||||||
report_checkN(rv, error, ok, 2);
|
return report_checkN(rv, error, ok, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
report_check3(int rv, int error, int okerr1, int okerr2, int okerr3)
|
report_check3(int rv, int error, int okerr1, int okerr2, int okerr3)
|
||||||
{
|
{
|
||||||
int ok[3];
|
int ok[3];
|
||||||
@ -346,5 +352,13 @@ report_check3(int rv, int error, int okerr1, int okerr2, int okerr3)
|
|||||||
ok[0] = okerr1;
|
ok[0] = okerr1;
|
||||||
ok[1] = okerr2;
|
ok[1] = okerr2;
|
||||||
ok[2] = okerr3;
|
ok[2] = okerr3;
|
||||||
report_checkN(rv, error, ok, 3);
|
return report_checkN(rv, error, ok, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
handle_result(int result, int *lost_points)
|
||||||
|
{
|
||||||
|
if(result)
|
||||||
|
*lost_points = *lost_points + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
#define TESTFILE "badcallfile"
|
#define TESTFILE "badcallfile"
|
||||||
#define TESTDIR "badcalldir"
|
#define TESTDIR "badcalldir"
|
||||||
#define TESTLINK "badcalllink"
|
#define TESTLINK "badcalllink"
|
||||||
@ -37,6 +39,11 @@
|
|||||||
#define PF(a, b)
|
#define PF(a, b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SUCCESS 0
|
||||||
|
#define SKIPPED 1
|
||||||
|
#define FAILED 2
|
||||||
|
#define ABORTED 3
|
||||||
|
|
||||||
/* driver.c */
|
/* driver.c */
|
||||||
int open_testfile(const char *str);
|
int open_testfile(const char *str);
|
||||||
int reopen_testfile(int openflags);
|
int reopen_testfile(int openflags);
|
||||||
@ -52,46 +59,46 @@ PF(1, 2) void report_warn(const char *fmt, ...);
|
|||||||
PF(1, 2) void report_warnx(const char *fmt, ...);
|
PF(1, 2) void report_warnx(const char *fmt, ...);
|
||||||
void report_result(int rv, int error);
|
void report_result(int rv, int error);
|
||||||
void report_saw_enosys(void);
|
void report_saw_enosys(void);
|
||||||
void report_passed(void);
|
void report_passed(int *result);
|
||||||
void report_failure(void);
|
void report_failure(int *result);
|
||||||
void report_skipped(void);
|
void report_skipped(int *result);
|
||||||
void report_aborted(void);
|
void report_aborted(int *result);
|
||||||
void report_survival(int rv, int error);
|
void report_survival(int rv, int error, int *result);
|
||||||
void report_check(int rv, int error, int right_error);
|
int report_check(int rv, int error, int right_error);
|
||||||
void report_check2(int rv, int error, int okerr1, int okerr2);
|
int report_check2(int rv, int error, int okerr1, int okerr2);
|
||||||
void report_check3(int rv, int error, int okerr1, int okerr2, int okerr3);
|
int report_check3(int rv, int error, int okerr1, int okerr2, int okerr3);
|
||||||
|
|
||||||
/* common_buf.c */
|
/* common_buf.c */
|
||||||
void test_read_buf(void);
|
void test_read_buf(int *ntests, int *lost_points);
|
||||||
void test_write_buf(void);
|
void test_write_buf(int *ntests, int *lost_points);
|
||||||
void test_getdirentry_buf(void);
|
void test_getdirentry_buf(int *ntests, int *lost_points);
|
||||||
void test_getcwd_buf(void);
|
void test_getcwd_buf(int *ntests, int *lost_points);
|
||||||
void test_readlink_buf(void);
|
void test_readlink_buf(int *ntests, int *lost_points);
|
||||||
|
|
||||||
/* common_fds.c */
|
/* common_fds.c */
|
||||||
void test_read_fd(void);
|
void test_read_fd(int *ntests, int *lost_points);
|
||||||
void test_write_fd(void);
|
void test_write_fd(int *ntests, int *lost_points);
|
||||||
void test_close_fd(void);
|
void test_close_fd(int *ntests, int *lost_points);
|
||||||
void test_ioctl_fd(void);
|
void test_ioctl_fd(int *ntests, int *lost_points);
|
||||||
void test_lseek_fd(void);
|
void test_lseek_fd(int *ntests, int *lost_points);
|
||||||
void test_fsync_fd(void);
|
void test_fsync_fd(int *ntests, int *lost_points);
|
||||||
void test_ftruncate_fd(void);
|
void test_ftruncate_fd(int *ntests, int *lost_points);
|
||||||
void test_fstat_fd(void);
|
void test_fstat_fd(int *ntests, int *lost_points);
|
||||||
void test_getdirentry_fd(void);
|
void test_getdirentry_fd(int *ntests, int *lost_points);
|
||||||
void test_dup2_fd(void);
|
void test_dup2_fd(int *ntests, int *lost_points);
|
||||||
|
|
||||||
/* common_path.c */
|
/* common_path.c */
|
||||||
void test_open_path(void);
|
void test_open_path(int *ntests, int *lost_points);
|
||||||
void test_remove_path(void);
|
void test_remove_path(int *ntests, int *lost_points);
|
||||||
void test_rename_paths(void);
|
void test_rename_paths(int *ntests, int *lost_points);
|
||||||
void test_link_paths(void);
|
void test_link_paths(int *ntests, int *lost_points);
|
||||||
void test_mkdir_path(void);
|
void test_mkdir_path(int *ntests, int *lost_points);
|
||||||
void test_rmdir_path(void);
|
void test_rmdir_path(int *ntests, int *lost_points);
|
||||||
void test_chdir_path(void);
|
void test_chdir_path(int *ntests, int *lost_points);
|
||||||
void test_symlink_paths(void);
|
void test_symlink_paths(int *ntests, int *lost_points);
|
||||||
void test_readlink_path(void);
|
void test_readlink_path(int *ntests, int *lost_points);
|
||||||
void test_stat_path(void);
|
void test_stat_path(int *ntests, int *lost_points);
|
||||||
void test_lstat_path(void);
|
void test_lstat_path(int *ntests, int *lost_points);
|
||||||
|
|
||||||
/* bad_*.c */
|
/* bad_*.c */
|
||||||
void test_execv(void);
|
void test_execv(void);
|
||||||
@ -122,3 +129,6 @@ void test_time(void);
|
|||||||
void test_getcwd(void);
|
void test_getcwd(void);
|
||||||
void test_stat(void);
|
void test_stat(void);
|
||||||
void test_lstat(void); /* in bad_stat.c */
|
void test_lstat(void); /* in bad_stat.c */
|
||||||
|
|
||||||
|
void handle_result(int result, int *lost_points);
|
||||||
|
|
||||||
|
@ -36,11 +36,13 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
#define _PATH_MYSELF "/testbin/bigexec"
|
#define _PATH_MYSELF "/testbin/bigexec"
|
||||||
|
|
||||||
@ -110,6 +112,7 @@ try(const char *first, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
|
nprintf(".");
|
||||||
assert(first != NULL);
|
assert(first != NULL);
|
||||||
args[0] = _PATH_MYSELF;
|
args[0] = _PATH_MYSELF;
|
||||||
args[1] = first;
|
args[1] = first;
|
||||||
@ -124,6 +127,7 @@ try(const char *first, ...)
|
|||||||
assert(num < 20);
|
assert(num < 20);
|
||||||
args[num++] = s;
|
args[num++] = s;
|
||||||
}
|
}
|
||||||
|
nprintf("\n");
|
||||||
assert(num < 20);
|
assert(num < 20);
|
||||||
args[num] = NULL;
|
args[num] = NULL;
|
||||||
execv(_PATH_MYSELF, (char **)args);
|
execv(_PATH_MYSELF, (char **)args);
|
||||||
@ -137,9 +141,12 @@ trymany(int num, const char *word)
|
|||||||
const char *args[num+2];
|
const char *args[num+2];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
nprintf(".");
|
||||||
args[0] = _PATH_MYSELF;
|
args[0] = _PATH_MYSELF;
|
||||||
for (i=0; i<num; i++) {
|
for (i=0; i<num; i++) {
|
||||||
args[i+1] = word;
|
args[i+1] = word;
|
||||||
|
if(i%10)
|
||||||
|
nprintf(".");
|
||||||
}
|
}
|
||||||
args[num+1] = NULL;
|
args[num+1] = NULL;
|
||||||
execv(_PATH_MYSELF, (char **)args);
|
execv(_PATH_MYSELF, (char **)args);
|
||||||
@ -376,7 +383,9 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else if (checkmany(argc, argv, 1000, word8)) {
|
else if (checkmany(argc, argv, 1000, word8)) {
|
||||||
#endif
|
#endif
|
||||||
|
nprintf("\n");
|
||||||
warnx("Complete.");
|
warnx("Complete.");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/bigexec");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -384,4 +393,5 @@ main(int argc, char *argv[])
|
|||||||
dumpargs(argc, argv);
|
dumpargs(argc, argv);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/bigexec");
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ main(int argc, char *argv[])
|
|||||||
/* round size up */
|
/* round size up */
|
||||||
size = ((size + chunksize - 1) / chunksize) * chunksize;
|
size = ((size + chunksize - 1) / chunksize) * chunksize;
|
||||||
|
|
||||||
printf("Creating a file of size %d in %d-byte chunks\n",
|
tprintf("Creating a file of size %d in %d-byte chunks\n",
|
||||||
size, chunksize);
|
size, chunksize);
|
||||||
|
|
||||||
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC);
|
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC);
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <test/test.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
#define BRANCHES 6
|
#define BRANCHES 6
|
||||||
|
|
||||||
@ -54,6 +56,8 @@
|
|||||||
*/
|
*/
|
||||||
#define DIM 64
|
#define DIM 64
|
||||||
|
|
||||||
|
#define PROGRESS_INTERVAL 25000
|
||||||
|
|
||||||
static int m1[DIM*DIM], m2[DIM*DIM], m3[DIM*DIM], m4[DIM*DIM];
|
static int m1[DIM*DIM], m2[DIM*DIM], m3[DIM*DIM], m4[DIM*DIM];
|
||||||
static const int right[BRANCHES] = {
|
static const int right[BRANCHES] = {
|
||||||
536763422,
|
536763422,
|
||||||
@ -76,7 +80,9 @@ init(void)
|
|||||||
for (j=0; j<DIM; j++) {
|
for (j=0; j<DIM; j++) {
|
||||||
m1[i*DIM+j] = random() % 11 - 5;
|
m1[i*DIM+j] = random() % 11 - 5;
|
||||||
}
|
}
|
||||||
|
TEST161_LPROGRESS(0);
|
||||||
}
|
}
|
||||||
|
nprintf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
@ -96,12 +102,15 @@ static
|
|||||||
void
|
void
|
||||||
mul(int *x, const int *a, const int *b)
|
mul(int *x, const int *a, const int *b)
|
||||||
{
|
{
|
||||||
unsigned i, j, k;
|
unsigned i, j, k, tot;
|
||||||
|
|
||||||
|
tot = 0;
|
||||||
for (i=0; i<DIM; i++) {
|
for (i=0; i<DIM; i++) {
|
||||||
for (j=0; j<DIM; j++) {
|
for (j=0; j<DIM; j++) {
|
||||||
x[i*DIM+j] = 0;
|
x[i*DIM+j] = 0;
|
||||||
for (k=0; k<DIM; k++) {
|
for (k=0; k<DIM; k++) {
|
||||||
|
TEST161_LPROGRESS_N(tot, PROGRESS_INTERVAL);
|
||||||
|
tot++;
|
||||||
x[i*DIM+j] += a[i*DIM+k] * b[k*DIM+j];
|
x[i*DIM+j] += a[i*DIM+k] * b[k*DIM+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,11 +186,15 @@ dowait(pid_t pid)
|
|||||||
exit(failures);
|
exit(failures);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// If the child crashes or waitpid returns -1, we don't know how many errors
|
||||||
|
// resulted (if any), but it's an error if we can't tell.
|
||||||
if (waitpid(pid, &status, 0) < 0) {
|
if (waitpid(pid, &status, 0) < 0) {
|
||||||
warn("waitpid(%d)", pid);
|
warn("waitpid(%d)", pid);
|
||||||
|
failures += 1;
|
||||||
}
|
}
|
||||||
else if (WIFSIGNALED(status)) {
|
else if (WIFSIGNALED(status)) {
|
||||||
warnx("pid %d: signal %d", pid, WTERMSIG(status));
|
warnx("pid %d: signal %d", pid, WTERMSIG(status));
|
||||||
|
failures += 1;
|
||||||
}
|
}
|
||||||
else if (WEXITSTATUS(status) > 0) {
|
else if (WEXITSTATUS(status) > 0) {
|
||||||
failures += WEXITSTATUS(status);
|
failures += WEXITSTATUS(status);
|
||||||
@ -196,7 +209,6 @@ dotest(void)
|
|||||||
unsigned i, me;
|
unsigned i, me;
|
||||||
pid_t pids[BRANCHES];
|
pid_t pids[BRANCHES];
|
||||||
int t;
|
int t;
|
||||||
char msg[128];
|
|
||||||
|
|
||||||
me = 0;
|
me = 0;
|
||||||
for (i=0; i<BRANCHES; i++) {
|
for (i=0; i<BRANCHES; i++) {
|
||||||
@ -207,26 +219,28 @@ dotest(void)
|
|||||||
grind();
|
grind();
|
||||||
t = trace();
|
t = trace();
|
||||||
if (t == right[i]) {
|
if (t == right[i]) {
|
||||||
snprintf(msg, sizeof(msg),
|
lsay("\nStage %u #%u done: %d\n", i, me, trace());
|
||||||
"Stage %u #%u done: %d\n", i, me, trace());
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
snprintf(msg, sizeof(msg),
|
lsay("Stage %u #%u FAILED: got %d, expected %d\n",
|
||||||
"Stage %u #%u FAILED: got %d, expected %d\n",
|
|
||||||
i, me, t, right[i]);
|
i, me, t, right[i]);
|
||||||
|
success(TEST161_FAIL, SECRET, "/testbin/bigfork");
|
||||||
failures++;
|
failures++;
|
||||||
}
|
}
|
||||||
(void)write(STDOUT_FILENO, msg, strlen(msg));
|
TEST161_LPROGRESS(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=BRANCHES; i-- > 0; ) {
|
for (i=BRANCHES; i-- > 0; ) {
|
||||||
dowait(pids[i]);
|
dowait(pids[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failures > 0) {
|
if (failures > 0) {
|
||||||
printf("%u failures.\n", failures);
|
tprintf("%u failures.\n", failures);
|
||||||
|
success(TEST161_FAIL, SECRET, "/testbin/bigfork");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Done.\n");
|
tprintf("Done.\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/bigfork");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ static
|
|||||||
void
|
void
|
||||||
try_seeking(int fd, off_t pos, off_t cursize)
|
try_seeking(int fd, off_t pos, off_t cursize)
|
||||||
{
|
{
|
||||||
printf("Seeking to (and near) 0x%llx\n", pos);
|
tprintf("Seeking to (and near) 0x%llx\n", pos);
|
||||||
|
|
||||||
/* Go to the place. */
|
/* Go to the place. */
|
||||||
dolseek(fd, pos, SEEK_SET, "SEEK_SET", pos);
|
dolseek(fd, pos, SEEK_SET, "SEEK_SET", pos);
|
||||||
@ -215,30 +215,30 @@ main(void)
|
|||||||
off_t cursize;
|
off_t cursize;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
printf("Creating file...\n");
|
tprintf("Creating file...\n");
|
||||||
fd = open(TESTFILE, O_RDWR|O_CREAT|O_TRUNC, 0664);
|
fd = open(TESTFILE, O_RDWR|O_CREAT|O_TRUNC, 0664);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
err(1, "%s", TESTFILE);
|
err(1, "%s", TESTFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Writing something at offset 0\n");
|
tprintf("Writing something at offset 0\n");
|
||||||
write_slogan(fd, 0, false);
|
write_slogan(fd, 0, false);
|
||||||
cursize = strlen(slogans[0]);
|
cursize = strlen(slogans[0]);
|
||||||
|
|
||||||
try_seeking(fd, (off_t)0x1000LL, cursize);
|
try_seeking(fd, (off_t)0x1000LL, cursize);
|
||||||
|
|
||||||
printf("Writing something else\n");
|
tprintf("Writing something else\n");
|
||||||
write_slogan(fd, 1, false);
|
write_slogan(fd, 1, false);
|
||||||
cursize = (off_t)0x1000LL + strlen(slogans[1]);
|
cursize = (off_t)0x1000LL + strlen(slogans[1]);
|
||||||
|
|
||||||
try_seeking(fd, (off_t)0, cursize);
|
try_seeking(fd, (off_t)0, cursize);
|
||||||
|
|
||||||
/* If seek is totally bust, this will fail. */
|
/* If seek is totally bust, this will fail. */
|
||||||
printf("Checking what we wrote\n");
|
tprintf("Checking what we wrote\n");
|
||||||
check_slogan(fd, 0);
|
check_slogan(fd, 0);
|
||||||
|
|
||||||
try_seeking(fd, (off_t)0x1000LL, cursize);
|
try_seeking(fd, (off_t)0x1000LL, cursize);
|
||||||
printf("Checking the other thing we wrote\n");
|
tprintf("Checking the other thing we wrote\n");
|
||||||
check_slogan(fd, 1);
|
check_slogan(fd, 1);
|
||||||
|
|
||||||
try_seeking(fd, (off_t)0x20LL, cursize);
|
try_seeking(fd, (off_t)0x20LL, cursize);
|
||||||
@ -250,19 +250,19 @@ main(void)
|
|||||||
try_seeking(fd, (off_t)0x180000000LL, cursize);
|
try_seeking(fd, (off_t)0x180000000LL, cursize);
|
||||||
try_seeking(fd, (off_t)0x180000020LL, cursize);
|
try_seeking(fd, (off_t)0x180000020LL, cursize);
|
||||||
|
|
||||||
printf("Now trying to read (should get EOF)\n");
|
tprintf("Now trying to read (should get EOF)\n");
|
||||||
try_reading(fd);
|
try_reading(fd);
|
||||||
|
|
||||||
printf("Now trying to write (should get EFBIG)\n");
|
tprintf("Now trying to write (should get EFBIG)\n");
|
||||||
try_writing(fd);
|
try_writing(fd);
|
||||||
|
|
||||||
try_seeking(fd, (off_t)0x100000000LL, cursize);
|
try_seeking(fd, (off_t)0x100000000LL, cursize);
|
||||||
|
|
||||||
/* If seek truncates to 32 bits, this might read the slogan instead */
|
/* If seek truncates to 32 bits, this might read the slogan instead */
|
||||||
printf("Trying to read again (should get EOF)\n");
|
tprintf("Trying to read again (should get EOF)\n");
|
||||||
try_reading(fd);
|
try_reading(fd);
|
||||||
|
|
||||||
printf("Passed.\n");
|
tprintf("Passed.\n");
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(TESTFILE);
|
remove(TESTFILE);
|
||||||
|
@ -131,11 +131,11 @@ static
|
|||||||
void
|
void
|
||||||
printsettings(void)
|
printsettings(void)
|
||||||
{
|
{
|
||||||
printf("Page size: %u\n", PAGE_SIZE);
|
tprintf("Page size: %u\n", PAGE_SIZE);
|
||||||
printf("Allocating %u pages and touching %u pages on each cycle.\n",
|
tprintf("Allocating %u pages and touching %u pages on each cycle.\n",
|
||||||
allocs, touchpages);
|
allocs, touchpages);
|
||||||
printf("Page selection bias: %u\n", bias);
|
tprintf("Page selection bias: %u\n", bias);
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
|
|
||||||
#if defined(__mips__)
|
#if defined(__mips__)
|
||||||
#define KERNEL_ADDR 0x80000000
|
#define KERNEL_ADDR 0x80000000
|
||||||
@ -292,7 +294,7 @@ runop(int op)
|
|||||||
/* intentionally don't check if op is in bounds :) */
|
/* intentionally don't check if op is in bounds :) */
|
||||||
opindex = op-'a';
|
opindex = op-'a';
|
||||||
|
|
||||||
printf("Running: [%c] %s\n", ops[opindex].ch, ops[opindex].name);
|
tprintf("Running: [%c] %s\n", ops[opindex].ch, ops[opindex].name);
|
||||||
|
|
||||||
if (forking) {
|
if (forking) {
|
||||||
pid = fork();
|
pid = fork();
|
||||||
@ -307,25 +309,25 @@ runop(int op)
|
|||||||
}
|
}
|
||||||
ok = 0;
|
ok = 0;
|
||||||
if (WIFSIGNALED(status)) {
|
if (WIFSIGNALED(status)) {
|
||||||
printf("Signal %d\n", WTERMSIG(status));
|
tprintf("Signal %d\n", WTERMSIG(status));
|
||||||
if (WTERMSIG(status) == ops[opindex].sig) {
|
if (WTERMSIG(status) == ops[opindex].sig) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Exit %d\n", WEXITSTATUS(status));
|
tprintf("Exit %d\n", WEXITSTATUS(status));
|
||||||
if (WEXITSTATUS(status) == MAGIC) {
|
if (WEXITSTATUS(status) == MAGIC) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
printf("Ok.\n");
|
tprintf("Ok.\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("FAILED: expected signal %d\n",
|
tprintf("FAILED: expected signal %d\n",
|
||||||
ops[opindex].sig);
|
ops[opindex].sig);
|
||||||
}
|
}
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,14 +353,14 @@ ask(void)
|
|||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
for (i=0; ops[i].name; i++) {
|
for (i=0; ops[i].name; i++) {
|
||||||
printf("[%c] %s\n", ops[i].ch, ops[i].name);
|
tprintf("[%c] %s\n", ops[i].ch, ops[i].name);
|
||||||
}
|
}
|
||||||
printf("[-] Disable forking\n");
|
tprintf("[-] Disable forking\n");
|
||||||
printf("[+] Enable forking (default)\n");
|
tprintf("[+] Enable forking (default)\n");
|
||||||
printf("[*] Run everything\n");
|
tprintf("[*] Run everything\n");
|
||||||
printf("[!] Quit\n");
|
tprintf("[!] Quit\n");
|
||||||
|
|
||||||
printf("Choose: ");
|
tprintf("Choose: ");
|
||||||
op = getchar();
|
op = getchar();
|
||||||
|
|
||||||
if (op == '!') {
|
if (op == '!') {
|
||||||
@ -384,5 +386,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("Should print success\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/crash");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SIZE is the amount of memory used.
|
* SIZE is the amount of memory used.
|
||||||
@ -64,12 +65,12 @@ main(int argc, char **argv)
|
|||||||
stride = atoi(argv[1]);
|
stride = atoi(argv[1]);
|
||||||
}
|
}
|
||||||
if (stride <= 0 || argc > 2) {
|
if (stride <= 0 || argc > 2) {
|
||||||
printf("Usage: ctest [stridesize]\n");
|
tprintf("Usage: ctest [stridesize]\n");
|
||||||
printf(" stridesize should not be a multiple of 2.\n");
|
tprintf(" stridesize should not be a multiple of 2.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Starting ctest: stride %d\n", stride);
|
tprintf("Starting ctest: stride %d\n", stride);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a huge linked list, with each entry pointing to
|
* Generate a huge linked list, with each entry pointing to
|
||||||
@ -90,12 +91,11 @@ main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
e = &array[0];
|
e = &array[0];
|
||||||
for (i=0; i<SIZE; i++) {
|
for (i=0; i<SIZE; i++) {
|
||||||
if (i % stride == 0) {
|
TEST161_LPROGRESS_N(i, stride);
|
||||||
putchar('.');
|
|
||||||
}
|
|
||||||
e = e->e;
|
e = e->e;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\nDone!\n");
|
// Success is not crashing
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/ctest");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ choose_name(char *buf, size_t len)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The purpose of this is to be atomic. In our world, straight
|
* The purpose of this is to be atomic. In our world, straight
|
||||||
* printf tends not to be.
|
* tprintf tends not to be.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
|
@ -205,7 +205,7 @@ firstread(void)
|
|||||||
errx(1, ".: File position after open not 0");
|
errx(1, ".: File position after open not 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Scanning directory...\n");
|
tprintf("Scanning directory...\n");
|
||||||
|
|
||||||
readit();
|
readit();
|
||||||
}
|
}
|
||||||
@ -216,7 +216,7 @@ doreadat0(void)
|
|||||||
{
|
{
|
||||||
off_t pos;
|
off_t pos;
|
||||||
|
|
||||||
printf("Rewinding directory and reading it again...\n");
|
tprintf("Rewinding directory and reading it again...\n");
|
||||||
|
|
||||||
pos = lseek(dirfd, 0, SEEK_SET);
|
pos = lseek(dirfd, 0, SEEK_SET);
|
||||||
if (pos < 0) {
|
if (pos < 0) {
|
||||||
@ -274,7 +274,7 @@ readallonebyone(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("Trying to read each entry again...\n");
|
tprintf("Trying to read each entry again...\n");
|
||||||
for (i=0; testfiles[i].name; i++) {
|
for (i=0; testfiles[i].name; i++) {
|
||||||
doreadone(i);
|
doreadone(i);
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ readallrandomly(void)
|
|||||||
{
|
{
|
||||||
int n, i, x;
|
int n, i, x;
|
||||||
|
|
||||||
printf("Trying to read a bunch of entries randomly...\n");
|
tprintf("Trying to read a bunch of entries randomly...\n");
|
||||||
|
|
||||||
for (i=0; testfiles[i].name; i++);
|
for (i=0; testfiles[i].name; i++);
|
||||||
n = i;
|
n = i;
|
||||||
@ -327,7 +327,7 @@ doreadateof(void)
|
|||||||
off_t pos;
|
off_t pos;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("Trying to read after going to EOF...\n");
|
tprintf("Trying to read after going to EOF...\n");
|
||||||
|
|
||||||
pos = lseek(dirfd, 0, SEEK_END);
|
pos = lseek(dirfd, 0, SEEK_END);
|
||||||
if (pos<0) {
|
if (pos<0) {
|
||||||
@ -364,7 +364,7 @@ dobadreads(void)
|
|||||||
off_t pos, pos2, eof;
|
off_t pos, pos2, eof;
|
||||||
int valid, i, k=0;
|
int valid, i, k=0;
|
||||||
|
|
||||||
printf("Trying some possibly invalid reads...\n");
|
tprintf("Trying some possibly invalid reads...\n");
|
||||||
|
|
||||||
eof = lseek(dirfd, 0, SEEK_END);
|
eof = lseek(dirfd, 0, SEEK_END);
|
||||||
if (eof < 0) {
|
if (eof < 0) {
|
||||||
@ -394,13 +394,13 @@ dobadreads(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k>0) {
|
if (k>0) {
|
||||||
printf("Survived %d invalid reads...\n", k);
|
tprintf("Survived %d invalid reads...\n", k);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Couldn't find any invalid offsets to try...\n");
|
tprintf("Couldn't find any invalid offsets to try...\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Trying to read beyond EOF...\n");
|
tprintf("Trying to read beyond EOF...\n");
|
||||||
pos2 = lseek(dirfd, eof + 1000, SEEK_SET);
|
pos2 = lseek(dirfd, eof + 1000, SEEK_SET);
|
||||||
if (pos2 < 0) {
|
if (pos2 < 0) {
|
||||||
/* this is ok */
|
/* this is ok */
|
||||||
@ -414,10 +414,10 @@ static
|
|||||||
void
|
void
|
||||||
dotest(void)
|
dotest(void)
|
||||||
{
|
{
|
||||||
printf("Opening directory...\n");
|
tprintf("Opening directory...\n");
|
||||||
openit();
|
openit();
|
||||||
|
|
||||||
printf("Running tests...\n");
|
tprintf("Running tests...\n");
|
||||||
|
|
||||||
/* read the whole directory */
|
/* read the whole directory */
|
||||||
firstread();
|
firstread();
|
||||||
@ -443,7 +443,7 @@ dotest(void)
|
|||||||
/* rewind again to make sure the invalid attempts didn't break it */
|
/* rewind again to make sure the invalid attempts didn't break it */
|
||||||
doreadat0();
|
doreadat0();
|
||||||
|
|
||||||
printf("Closing directory...\n");
|
tprintf("Closing directory...\n");
|
||||||
closeit();
|
closeit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +489,7 @@ setup(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("Making directory %s...\n", TESTDIR);
|
tprintf("Making directory %s...\n", TESTDIR);
|
||||||
|
|
||||||
/* Create a directory */
|
/* Create a directory */
|
||||||
if (mkdir(TESTDIR, 0775)<0) {
|
if (mkdir(TESTDIR, 0775)<0) {
|
||||||
@ -501,7 +501,7 @@ setup(void)
|
|||||||
err(1, "%s: chdir", TESTDIR);
|
err(1, "%s: chdir", TESTDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Making some files...\n");
|
tprintf("Making some files...\n");
|
||||||
|
|
||||||
/* Populate it */
|
/* Populate it */
|
||||||
for (i=0; testfiles[i].name; i++) {
|
for (i=0; testfiles[i].name; i++) {
|
||||||
@ -518,7 +518,7 @@ cleanup(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
printf("Cleaning up...\n");
|
tprintf("Cleaning up...\n");
|
||||||
|
|
||||||
/* Remove the files */
|
/* Remove the files */
|
||||||
for (i=0; testfiles[i].name; i++) {
|
for (i=0; testfiles[i].name; i++) {
|
||||||
|
@ -58,7 +58,7 @@ main(void)
|
|||||||
strcpy(dirname, onename);
|
strcpy(dirname, onename);
|
||||||
|
|
||||||
for (i=0; i<MAXLEVELS; i++) {
|
for (i=0; i<MAXLEVELS; i++) {
|
||||||
printf("Creating directory: %s\n", dirname);
|
tprintf("Creating directory: %s\n", dirname);
|
||||||
|
|
||||||
if (mkdir(dirname, 0755)) {
|
if (mkdir(dirname, 0755)) {
|
||||||
err(1, "%s: mkdir", dirname);
|
err(1, "%s: mkdir", dirname);
|
||||||
@ -68,18 +68,18 @@ main(void)
|
|||||||
strcat(dirname, onename);
|
strcat(dirname, onename);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Passed directory creation test.\n");
|
tprintf("Passed directory creation test.\n");
|
||||||
|
|
||||||
for (i=0; i<MAXLEVELS; i++) {
|
for (i=0; i<MAXLEVELS; i++) {
|
||||||
dirname[strlen(dirname) - strlen(onename) - 1] = 0;
|
dirname[strlen(dirname) - strlen(onename) - 1] = 0;
|
||||||
|
|
||||||
printf("Removing directory: %s\n", dirname);
|
tprintf("Removing directory: %s\n", dirname);
|
||||||
|
|
||||||
if (rmdir(dirname)) {
|
if (rmdir(dirname)) {
|
||||||
err(1, "%s: rmdir", dirname);
|
err(1, "%s: rmdir", dirname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Passed directory removal test.\n");
|
tprintf("Passed directory removal test.\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ subproc_read(void)
|
|||||||
int fd;
|
int fd;
|
||||||
int i, res;
|
int i, res;
|
||||||
|
|
||||||
printf("File Reader starting ...\n\n");
|
tprintf("File Reader starting ...\n\n");
|
||||||
|
|
||||||
fd = open(FNAME, O_RDONLY);
|
fd = open(FNAME, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -102,5 +102,5 @@ subproc_read(void)
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
printf("File Read exited successfully!\n");
|
tprintf("File Read exited successfully!\n");
|
||||||
}
|
}
|
||||||
|
@ -124,8 +124,8 @@ big_file(int size)
|
|||||||
{
|
{
|
||||||
int i, j, fileid;
|
int i, j, fileid;
|
||||||
|
|
||||||
printf("[BIGFILE] test starting :\n");
|
tprintf("[BIGFILE] test starting :\n");
|
||||||
printf("\tCreating a file of size: %d\n", size);
|
tprintf("\tCreating a file of size: %d\n", size);
|
||||||
|
|
||||||
fileid = open(BIGFILE_NAME, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
fileid = open(BIGFILE_NAME, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
||||||
if (fileid < 0) {
|
if (fileid < 0) {
|
||||||
@ -136,16 +136,16 @@ big_file(int size)
|
|||||||
fbuffer[i] = LETTER(i);
|
fbuffer[i] = LETTER(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\tWriting to file.\n");
|
tprintf("\tWriting to file.\n");
|
||||||
for (i = 0; i < size; i += BUFFER_SIZE) {
|
for (i = 0; i < size; i += BUFFER_SIZE) {
|
||||||
write(fileid, fbuffer, BUFFER_SIZE);
|
write(fileid, fbuffer, BUFFER_SIZE);
|
||||||
|
|
||||||
if (!(i % (10 * BUFFER_SIZE))) {
|
if (!(i % (10 * BUFFER_SIZE))) {
|
||||||
printf("\rBW : %d", i);
|
tprintf("\rBW : %d", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n\tReading from file.\n");
|
tprintf("\n\tReading from file.\n");
|
||||||
close(fileid);
|
close(fileid);
|
||||||
|
|
||||||
fileid = open(BIGFILE_NAME, O_RDONLY);
|
fileid = open(BIGFILE_NAME, O_RDONLY);
|
||||||
@ -164,7 +164,7 @@ big_file(int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(i % (10 * BUFFER_SIZE))) {
|
if (!(i % (10 * BUFFER_SIZE))) {
|
||||||
printf("\rBR : %d", i);
|
tprintf("\rBR : %d", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check to see that the data is consistent : */
|
/* Check to see that the data is consistent : */
|
||||||
@ -181,7 +181,7 @@ big_file(int size)
|
|||||||
err(1, "[BIGFILE]: %s: remove", BIGFILE_NAME);
|
err(1, "[BIGFILE]: %s: remove", BIGFILE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n[BIGFILE] : Success!\n");
|
tprintf("\n[BIGFILE] : Success!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================
|
/* ===================================================
|
||||||
@ -195,7 +195,7 @@ concur(void)
|
|||||||
int i, fd;
|
int i, fd;
|
||||||
int r1, r2, w1;
|
int r1, r2, w1;
|
||||||
|
|
||||||
printf("Spawning 2 readers, 1 writer.\n");
|
tprintf("Spawning 2 readers, 1 writer.\n");
|
||||||
|
|
||||||
|
|
||||||
fd = open(FNAME, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
fd = open(FNAME, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
||||||
@ -203,7 +203,7 @@ concur(void)
|
|||||||
err(1, "[CONCUR]: %s: open", FNAME);
|
err(1, "[CONCUR]: %s: open", FNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Initializing test file: ");
|
tprintf("Initializing test file: ");
|
||||||
|
|
||||||
for (i = 0; i < SECTOR_SIZE + 1; i++) {
|
for (i = 0; i < SECTOR_SIZE + 1; i++) {
|
||||||
cbuffer[i] = READCHAR;
|
cbuffer[i] = READCHAR;
|
||||||
@ -216,13 +216,13 @@ concur(void)
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
printf("Done initializing. Starting processes...\n");
|
tprintf("Done initializing. Starting processes...\n");
|
||||||
|
|
||||||
r1 = forkoff(subproc_read);
|
r1 = forkoff(subproc_read);
|
||||||
w1 = forkoff(subproc_write);
|
w1 = forkoff(subproc_write);
|
||||||
r2 = forkoff(subproc_read);
|
r2 = forkoff(subproc_read);
|
||||||
|
|
||||||
printf("Waiting for processes.\n");
|
tprintf("Waiting for processes.\n");
|
||||||
|
|
||||||
dowait(r1);
|
dowait(r1);
|
||||||
dowait(r2);
|
dowait(r2);
|
||||||
@ -232,7 +232,7 @@ concur(void)
|
|||||||
err(1, "[CONCUR]: %s: remove", FNAME);
|
err(1, "[CONCUR]: %s: remove", FNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[CONCUR] Done!\n");
|
tprintf("[CONCUR] Done!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================
|
/* ===================================================
|
||||||
@ -253,14 +253,14 @@ dir_test(int depth)
|
|||||||
for (i = 0; i < depth; i++) {
|
for (i = 0; i < depth; i++) {
|
||||||
strcat(dirname, tmp);
|
strcat(dirname, tmp);
|
||||||
|
|
||||||
printf("\tCreating dir : %s\n", dirname);
|
tprintf("\tCreating dir : %s\n", dirname);
|
||||||
|
|
||||||
if (mkdir(dirname, 0775) < 0) {
|
if (mkdir(dirname, 0775) < 0) {
|
||||||
err(1, "[DIRTEST]: %s: mkdir", dirname);
|
err(1, "[DIRTEST]: %s: mkdir", dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(dirname, fmp);
|
strcat(dirname, fmp);
|
||||||
printf("\tCreating file: %s\n", dirname);
|
tprintf("\tCreating file: %s\n", dirname);
|
||||||
|
|
||||||
fd = open(dirname, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
fd = open(dirname, O_WRONLY|O_CREAT|O_TRUNC, 0664);
|
||||||
if (fd<0) {
|
if (fd<0) {
|
||||||
@ -270,19 +270,19 @@ dir_test(int depth)
|
|||||||
dirname[strlen(dirname) - strlen(fmp)] = '\0';
|
dirname[strlen(dirname) - strlen(fmp)] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[DIRTEST] : Passed directory creation test.\n");
|
tprintf("[DIRTEST] : Passed directory creation test.\n");
|
||||||
|
|
||||||
for (i = 0; i < depth; i++) {
|
for (i = 0; i < depth; i++) {
|
||||||
strcat(dirname, fmp);
|
strcat(dirname, fmp);
|
||||||
|
|
||||||
printf("\tDeleting file: %s\n", dirname);
|
tprintf("\tDeleting file: %s\n", dirname);
|
||||||
|
|
||||||
if (remove(dirname)) {
|
if (remove(dirname)) {
|
||||||
err(1, "[DIRTEST]: %s: remove", dirname);
|
err(1, "[DIRTEST]: %s: remove", dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
dirname[strlen(dirname) - strlen(fmp)] = '\0';
|
dirname[strlen(dirname) - strlen(fmp)] = '\0';
|
||||||
printf("\tRemoving dir : %s\n", dirname);
|
tprintf("\tRemoving dir : %s\n", dirname);
|
||||||
|
|
||||||
if (rmdir(dirname)) {
|
if (rmdir(dirname)) {
|
||||||
err(1, "[DIRTEST]: %s: rmdir", dirname);
|
err(1, "[DIRTEST]: %s: rmdir", dirname);
|
||||||
@ -291,8 +291,8 @@ dir_test(int depth)
|
|||||||
dirname[strlen(dirname) - strlen(tmp)] = '\0';
|
dirname[strlen(dirname) - strlen(tmp)] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[DIRTEST] : Passed directory removal test.\n");
|
tprintf("[DIRTEST] : Passed directory removal test.\n");
|
||||||
printf("[DIRTEST] : Success!\n");
|
tprintf("[DIRTEST] : Success!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===================================================
|
/* ===================================================
|
||||||
@ -325,21 +325,21 @@ main(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tv & RUNBIGFILE) {
|
if (tv & RUNBIGFILE) {
|
||||||
printf("[BIGFILE] : Run #1\n");
|
tprintf("[BIGFILE] : Run #1\n");
|
||||||
big_file(BIGFILE_SIZE);
|
big_file(BIGFILE_SIZE);
|
||||||
printf("[BIGFILE] : Run #2\n");
|
tprintf("[BIGFILE] : Run #2\n");
|
||||||
big_file(BIGFILE_SIZE);
|
big_file(BIGFILE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tv & RUNDIRTEST) {
|
if (tv & RUNDIRTEST) {
|
||||||
printf("[DIRTEST] : Run #1\n");
|
tprintf("[DIRTEST] : Run #1\n");
|
||||||
dir_test(DIR_DEPTH);
|
dir_test(DIR_DEPTH);
|
||||||
printf("[DIRTEST] : Run #2\n");
|
tprintf("[DIRTEST] : Run #2\n");
|
||||||
dir_test(DIR_DEPTH);
|
dir_test(DIR_DEPTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tv & RUNCONCUR) {
|
if (tv & RUNCONCUR) {
|
||||||
printf("[CONCUR]\n");
|
tprintf("[CONCUR]\n");
|
||||||
concur();
|
concur();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -67,7 +67,7 @@ subproc_write(void)
|
|||||||
buffer[i] = WRITECHAR;
|
buffer[i] = WRITECHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("File Writer starting ...\n");
|
tprintf("File Writer starting ...\n");
|
||||||
|
|
||||||
fd = open(FNAME, O_WRONLY);
|
fd = open(FNAME, O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -81,5 +81,5 @@ subproc_write(void)
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
printf("File Write exited successfully!\n");
|
tprintf("File Write exited successfully!\n");
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
#define _PATH_SELF "/testbin/factorial"
|
#define _PATH_SELF "/testbin/factorial"
|
||||||
|
|
||||||
@ -245,9 +246,12 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else if (argc == 3) {
|
else if (argc == 3) {
|
||||||
if (!strcmp(argv[1], "1") || !strcmp(argv[1], "0")) {
|
if (!strcmp(argv[1], "1") || !strcmp(argv[1], "0")) {
|
||||||
printf("%s\n", argv[2]);
|
nprintf("\n");
|
||||||
|
tprintf("%s\n", argv[2]);
|
||||||
|
secprintf(SECRET, argv[2], "/testbin/factorial");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
nprintf(".");
|
||||||
number_init(&n1, argv[1]);
|
number_init(&n1, argv[1]);
|
||||||
number_init(&n2, argv[2]);
|
number_init(&n2, argv[2]);
|
||||||
number_init(&multbuf, "0");
|
number_init(&multbuf, "0");
|
||||||
|
@ -45,12 +45,12 @@ main(void)
|
|||||||
{
|
{
|
||||||
volatile int i;
|
volatile int i;
|
||||||
|
|
||||||
printf("\nEntering the faulter program - I should die immediately\n");
|
tprintf("\nEntering the faulter program - I should die immediately\n");
|
||||||
i = *(int *)REALLY_BIG_ADDRESS;
|
i = *(int *)REALLY_BIG_ADDRESS;
|
||||||
|
|
||||||
// gcc 4.8 improperly demands this
|
// gcc 4.8 improperly demands this
|
||||||
(void)i;
|
(void)i;
|
||||||
|
|
||||||
printf("I didn't get killed! Program has a bug\n");
|
tprintf("I didn't get killed! Program has a bug\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,6 @@ main(int argc, char *argv[])
|
|||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
err(1, "%s: remove", file);
|
err(1, "%s: remove", file);
|
||||||
}
|
}
|
||||||
printf("Passed filetest.\n");
|
tprintf("Passed filetest.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,11 @@
|
|||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
|
#define TEST_DURATION 10
|
||||||
|
#define LOCAL_SUCCESS "SUCCESS"
|
||||||
|
|
||||||
static volatile int pid;
|
static volatile int pid;
|
||||||
|
|
||||||
@ -57,8 +62,40 @@ main(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
time_t start_time_s, time_now_s;
|
||||||
|
unsigned long start_time_ns, time_now_ns;
|
||||||
|
__time(&start_time_s, &start_time_ns);
|
||||||
|
int parent_pid = getpid();
|
||||||
|
int did_print = 0;
|
||||||
|
int iters = 0;
|
||||||
|
|
||||||
|
// Do not remove!
|
||||||
|
// We need to cause page faults on the static secprintf buffers so the
|
||||||
|
// pages are available when we print success. With on-demand page allocation,
|
||||||
|
// we will probably be out of pages by the time we try to print success.
|
||||||
|
secprintf(SECRET, "!!< Starting Forkbbbboooommmmbbbb >!!", "/testbin/forkbomb");
|
||||||
|
|
||||||
|
// And now for the success string
|
||||||
|
printf("This should print %s after 10s\n", LOCAL_SUCCESS);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
fork();
|
fork();
|
||||||
|
// Only parent gets to print
|
||||||
|
if(getpid() == parent_pid) {
|
||||||
|
TEST161_LPROGRESS(0);
|
||||||
|
if (iters > 0 && iters % 20 == 0) {
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
iters++;
|
||||||
|
|
||||||
|
__time(&time_now_s, &time_now_ns);
|
||||||
|
if (time_now_s - start_time_s > TEST_DURATION && !did_print) {
|
||||||
|
did_print = 1;
|
||||||
|
// We need to print this using secprintf so that it uses
|
||||||
|
// the same page we warmed up earlier.
|
||||||
|
secprintf(SECRET, LOCAL_SUCCESS, "/testbin/forkbomb");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
|
|
||||||
|
@ -37,10 +37,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
|
||||||
|
#define FORKTEST_FILENAME_BASE "forktest"
|
||||||
|
|
||||||
|
static char filename[32];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is used by all processes, to try to help make sure all
|
* This is used by all processes, to try to help make sure all
|
||||||
@ -48,6 +54,18 @@
|
|||||||
*/
|
*/
|
||||||
static volatile int mypid;
|
static volatile int mypid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to do pow()
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int pow_int(int x, int y) {
|
||||||
|
int i;
|
||||||
|
int result = 1;
|
||||||
|
for(i = 0; i < y; i++)
|
||||||
|
result *= x;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function for fork that prints a warning on error.
|
* Helper function for fork that prints a warning on error.
|
||||||
*/
|
*/
|
||||||
@ -77,6 +95,7 @@ check(void)
|
|||||||
mypid = getpid();
|
mypid = getpid();
|
||||||
|
|
||||||
/* Make sure each fork has its own address space. */
|
/* Make sure each fork has its own address space. */
|
||||||
|
nprintf(".");
|
||||||
for (i=0; i<800; i++) {
|
for (i=0; i<800; i++) {
|
||||||
volatile int seenpid;
|
volatile int seenpid;
|
||||||
seenpid = mypid;
|
seenpid = mypid;
|
||||||
@ -114,13 +133,13 @@ dowait(int nowait, int pid)
|
|||||||
|
|
||||||
if (!nowait) {
|
if (!nowait) {
|
||||||
if (waitpid(pid, &x, 0)<0) {
|
if (waitpid(pid, &x, 0)<0) {
|
||||||
warn("waitpid");
|
errx(1, "waitpid");
|
||||||
}
|
}
|
||||||
else if (WIFSIGNALED(x)) {
|
else if (WIFSIGNALED(x)) {
|
||||||
warnx("pid %d: signal %d", pid, WTERMSIG(x));
|
errx(1, "pid %d: signal %d", pid, WTERMSIG(x));
|
||||||
}
|
}
|
||||||
else if (WEXITSTATUS(x) != 0) {
|
else if (WEXITSTATUS(x) != 0) {
|
||||||
warnx("pid %d: exit %d", pid, WEXITSTATUS(x));
|
errx(1, "pid %d: exit %d", pid, WEXITSTATUS(x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,17 +160,42 @@ test(int nowait)
|
|||||||
* to prevent wait/exit problems if fork corrupts memory.
|
* to prevent wait/exit problems if fork corrupts memory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guru: We have a problem here.
|
||||||
|
* We need to write the output to a file since test161 is
|
||||||
|
* supposed to be as simple as possible. This requires the
|
||||||
|
* test to tell test161 whether it passed or succeeded.
|
||||||
|
* We cannot lseek and read stdout, to check the output,
|
||||||
|
* so we need to write the output to a file and then check it later.
|
||||||
|
*
|
||||||
|
* So far so good. However, if in the future, forktest is
|
||||||
|
* going to be combined with triple/quint/etc, then the filename
|
||||||
|
* cannot be the same across multiple copies. So we need a
|
||||||
|
* unique filename per instance of forktest.
|
||||||
|
* So...
|
||||||
|
*/
|
||||||
|
snprintf(filename, 32, "%s-%d.bin", FORKTEST_FILENAME_BASE, getpid());
|
||||||
|
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
|
||||||
|
if(fd < 3) {
|
||||||
|
// 0, 1, 2 are stdin, stdout, stderr
|
||||||
|
err(1, "Failed to open file to write data into\n");
|
||||||
|
}
|
||||||
|
|
||||||
pid0 = dofork();
|
pid0 = dofork();
|
||||||
putchar('A');
|
nprintf(".");
|
||||||
|
write(fd, "A", 1);
|
||||||
check();
|
check();
|
||||||
pid1 = dofork();
|
pid1 = dofork();
|
||||||
putchar('B');
|
nprintf(".");
|
||||||
|
write(fd, "B", 1);
|
||||||
check();
|
check();
|
||||||
pid2 = dofork();
|
pid2 = dofork();
|
||||||
putchar('C');
|
nprintf(".");
|
||||||
|
write(fd, "C", 1);
|
||||||
check();
|
check();
|
||||||
pid3 = dofork();
|
pid3 = dofork();
|
||||||
putchar('D');
|
nprintf(".");
|
||||||
|
write(fd, "D", 1);
|
||||||
check();
|
check();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -159,11 +203,57 @@ test(int nowait)
|
|||||||
* improperly.
|
* improperly.
|
||||||
*/
|
*/
|
||||||
dowait(nowait, pid3);
|
dowait(nowait, pid3);
|
||||||
|
nprintf(".");
|
||||||
dowait(nowait, pid2);
|
dowait(nowait, pid2);
|
||||||
|
nprintf(".");
|
||||||
dowait(nowait, pid1);
|
dowait(nowait, pid1);
|
||||||
|
nprintf(".");
|
||||||
dowait(nowait, pid0);
|
dowait(nowait, pid0);
|
||||||
|
nprintf(".");
|
||||||
|
|
||||||
putchar('\n');
|
// Check if file contents are correct
|
||||||
|
// lseek may not be implemented..so close and reopen
|
||||||
|
close(fd);
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if(fd < 3) {
|
||||||
|
err(1, "Failed to open file for verification\n");
|
||||||
|
}
|
||||||
|
nprintf(".");
|
||||||
|
|
||||||
|
char buffer[30];
|
||||||
|
int len;
|
||||||
|
int char_idx, i;
|
||||||
|
int observed, expected;
|
||||||
|
char character = 'A';
|
||||||
|
|
||||||
|
memset(buffer, 0, 30);
|
||||||
|
len = read(fd, buffer, 30);
|
||||||
|
printf("\n%s\n", buffer);
|
||||||
|
if(len != 30) {
|
||||||
|
err(1, "Did not get expected number of characters\n");
|
||||||
|
}
|
||||||
|
nprintf(".");
|
||||||
|
// Check if number of instances of each character is correct
|
||||||
|
// 2As; 4Bs; 8Cs; 16Ds
|
||||||
|
for(char_idx = 0; char_idx < 4; char_idx++) {
|
||||||
|
nprintf(".");
|
||||||
|
observed = 0;
|
||||||
|
expected = pow_int(2, char_idx + 1);
|
||||||
|
for(i = 0; i < 30; i++) {
|
||||||
|
// In C, char can be directly converted to an ASCII index
|
||||||
|
// So, A is 65, B is 66, ...
|
||||||
|
if(buffer[i] == character + char_idx) {
|
||||||
|
observed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(observed != expected) {
|
||||||
|
// Failed
|
||||||
|
err(1, "Failed! Expected %d%cs..observed: %d\n", expected, character + char_idx, observed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nprintf("\n");
|
||||||
|
success(TEST161_SUCCESS, SECRET, "/testbin/forktest");
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2148,7 +2148,7 @@ doindent(unsigned depth)
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i=0; i<depth; i++) {
|
for (i=0; i<depth; i++) {
|
||||||
printf(" ");
|
tprintf(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2174,17 +2174,17 @@ printdiffs(unsigned indent, struct fsobject *obja, struct fsobject *objb)
|
|||||||
entb = entb->next) {
|
entb = entb->next) {
|
||||||
if (enta->name == entb->name) {
|
if (enta->name == entb->name) {
|
||||||
doindent(indent);
|
doindent(indent);
|
||||||
printf("%s", name_get(enta->name));
|
tprintf("%s", name_get(enta->name));
|
||||||
if (enta->obj->isdir &&
|
if (enta->obj->isdir &&
|
||||||
!entb->obj->isdir) {
|
!entb->obj->isdir) {
|
||||||
printf(": expected dir, found file;");
|
tprintf(": expected dir, found file;");
|
||||||
printf(" %u names missing.\n",
|
tprintf(" %u names missing.\n",
|
||||||
count_subtree(enta->obj) - 1);
|
count_subtree(enta->obj) - 1);
|
||||||
}
|
}
|
||||||
else if (!enta->obj->isdir &&
|
else if (!enta->obj->isdir &&
|
||||||
entb->obj->isdir) {
|
entb->obj->isdir) {
|
||||||
printf(": expected file, found dir;");
|
tprintf(": expected file, found dir;");
|
||||||
printf(" %u extra names.\n",
|
tprintf(" %u extra names.\n",
|
||||||
count_subtree(entb->obj) - 1);
|
count_subtree(entb->obj) - 1);
|
||||||
}
|
}
|
||||||
else if (!enta->obj->isdir &&
|
else if (!enta->obj->isdir &&
|
||||||
@ -2194,18 +2194,18 @@ printdiffs(unsigned indent, struct fsobject *obja, struct fsobject *objb)
|
|||||||
alen = enta->obj->obj_file.len;
|
alen = enta->obj->obj_file.len;
|
||||||
blen = entb->obj->obj_file.len;
|
blen = entb->obj->obj_file.len;
|
||||||
if (alen == blen) {
|
if (alen == blen) {
|
||||||
printf("\t\t%lld bytes (ok)\n",
|
tprintf("\t\t%lld bytes (ok)\n",
|
||||||
alen);
|
alen);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf(": found %lld bytes, "
|
tprintf(": found %lld bytes, "
|
||||||
"expected %lld "
|
"expected %lld "
|
||||||
"bytes.\n",
|
"bytes.\n",
|
||||||
blen, alen);
|
blen, alen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("/\n");
|
tprintf("/\n");
|
||||||
printdiffs(indent + 1,
|
printdiffs(indent + 1,
|
||||||
enta->obj, entb->obj);
|
enta->obj, entb->obj);
|
||||||
}
|
}
|
||||||
@ -2215,13 +2215,13 @@ printdiffs(unsigned indent, struct fsobject *obja, struct fsobject *objb)
|
|||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
doindent(indent);
|
doindent(indent);
|
||||||
printf("%s: missing ", name_get(enta->name));
|
tprintf("%s: missing ", name_get(enta->name));
|
||||||
if (enta->obj->isdir) {
|
if (enta->obj->isdir) {
|
||||||
printf("subtree with %u names.\n",
|
tprintf("subtree with %u names.\n",
|
||||||
count_subtree(enta->obj) - 1);
|
count_subtree(enta->obj) - 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("file\n");
|
tprintf("file\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2238,13 +2238,13 @@ printdiffs(unsigned indent, struct fsobject *obja, struct fsobject *objb)
|
|||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
doindent(indent);
|
doindent(indent);
|
||||||
printf("%s: extra ", name_get(entb->name));
|
tprintf("%s: extra ", name_get(entb->name));
|
||||||
if (entb->obj->isdir) {
|
if (entb->obj->isdir) {
|
||||||
printf("subtree with %u names.\n",
|
tprintf("subtree with %u names.\n",
|
||||||
count_subtree(entb->obj) - 1);
|
count_subtree(entb->obj) - 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("file\n");
|
tprintf("file\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2326,7 +2326,7 @@ checkfilezeros(int fd, const char *namestr, off_t start, off_t end)
|
|||||||
unsigned poison = 0, trash = 0;
|
unsigned poison = 0, trash = 0;
|
||||||
off_t origstart = start;
|
off_t origstart = start;
|
||||||
|
|
||||||
printf(" %lld - %lld (expecting zeros)\n", start, end);
|
tprintf(" %lld - %lld (expecting zeros)\n", start, end);
|
||||||
|
|
||||||
if (lseek(fd, start, SEEK_SET) == -1) {
|
if (lseek(fd, start, SEEK_SET) == -1) {
|
||||||
err(1, "%s: lseek to %lld", namestr, start);
|
err(1, "%s: lseek to %lld", namestr, start);
|
||||||
@ -2356,19 +2356,19 @@ checkfilezeros(int fd, const char *namestr, off_t start, off_t end)
|
|||||||
start += ret;
|
start += ret;
|
||||||
}
|
}
|
||||||
if (poison > 0 || trash > 0) {
|
if (poison > 0 || trash > 0) {
|
||||||
printf("ERROR: File %s: expected zeros from %lld to %lld; "
|
tprintf("ERROR: File %s: expected zeros from %lld to %lld; "
|
||||||
"found",
|
"found",
|
||||||
namestr, origstart, end);
|
namestr, origstart, end);
|
||||||
if (poison > 0) {
|
if (poison > 0) {
|
||||||
printf(" %u poison bytes", poison);
|
tprintf(" %u poison bytes", poison);
|
||||||
if (trash > 0) {
|
if (trash > 0) {
|
||||||
printf(" and");
|
tprintf(" and");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trash > 0) {
|
if (trash > 0) {
|
||||||
printf(" %u trash bytes", trash);
|
tprintf(" %u trash bytes", trash);
|
||||||
}
|
}
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2440,7 +2440,7 @@ checkfiledata(int fd, const char *namestr, unsigned code, unsigned seq,
|
|||||||
checkend = regionend;
|
checkend = regionend;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" %lld - %lld\n", checkstart, checkend);
|
tprintf(" %lld - %lld\n", checkstart, checkend);
|
||||||
|
|
||||||
readfiledata(fd, namestr,
|
readfiledata(fd, namestr,
|
||||||
regionstart, checkstart, checkend, regionend);
|
regionstart, checkstart, checkend, regionend);
|
||||||
@ -2695,7 +2695,7 @@ checkonefilecontents(const char *namestr, struct fsobject *file,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(change->type == FC_WRITE);
|
assert(change->type == FC_WRITE);
|
||||||
printf("ERROR: File %s is zero length but was expected to "
|
tprintf("ERROR: File %s is zero length but was expected to "
|
||||||
"contain at least %lld bytes at offset %lld!\n",
|
"contain at least %lld bytes at offset %lld!\n",
|
||||||
namestr, change->fc_write.pos, change->fc_write.len);
|
namestr, change->fc_write.pos, change->fc_write.len);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -2704,7 +2704,7 @@ checkonefilecontents(const char *namestr, struct fsobject *file,
|
|||||||
|
|
||||||
/* XXX: this check is wrong too. */
|
/* XXX: this check is wrong too. */
|
||||||
if (change->type == FC_CREAT) {
|
if (change->type == FC_CREAT) {
|
||||||
printf("ERROR: File %s was never written to but has "
|
tprintf("ERROR: File %s was never written to but has "
|
||||||
"length %lld\n",
|
"length %lld\n",
|
||||||
namestr, file->obj_file.len);
|
namestr, file->obj_file.len);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -2741,12 +2741,12 @@ checkonefilecontents(const char *namestr, struct fsobject *file,
|
|||||||
*/
|
*/
|
||||||
while (!change_is_present(fd, namestr, file->obj_file.len, change)) {
|
while (!change_is_present(fd, namestr, file->obj_file.len, change)) {
|
||||||
if (change->version < okversion) {
|
if (change->version < okversion) {
|
||||||
printf("File %s: change for version %u is missing\n",
|
tprintf("File %s: change for version %u is missing\n",
|
||||||
namestr, change->version);
|
namestr, change->version);
|
||||||
}
|
}
|
||||||
change = backup_for_file(change->prev,file->obj_file.identity);
|
change = backup_for_file(change->prev,file->obj_file.identity);
|
||||||
if (change == NULL) {
|
if (change == NULL) {
|
||||||
printf("File %s: no matching version found\n",
|
tprintf("File %s: no matching version found\n",
|
||||||
namestr);
|
namestr);
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
@ -2781,18 +2781,18 @@ checkallfilecontents(struct fsobject *dir, struct fschange *change)
|
|||||||
for (de = dir->obj_dir.entries; de != NULL; de = de->next) {
|
for (de = dir->obj_dir.entries; de != NULL; de = de->next) {
|
||||||
namestr = name_get(de->name);
|
namestr = name_get(de->name);
|
||||||
if (de->obj->isdir) {
|
if (de->obj->isdir) {
|
||||||
printf(" >>> Entering %s\n", namestr);
|
tprintf(" >>> Entering %s\n", namestr);
|
||||||
if (chdir(namestr)) {
|
if (chdir(namestr)) {
|
||||||
err(1, "%s: chdir", namestr);
|
err(1, "%s: chdir", namestr);
|
||||||
}
|
}
|
||||||
checkallfilecontents(de->obj, change);
|
checkallfilecontents(de->obj, change);
|
||||||
printf(" <<< Leaving %s\n", namestr);
|
tprintf(" <<< Leaving %s\n", namestr);
|
||||||
if (chdir("..")) {
|
if (chdir("..")) {
|
||||||
err(1, "..: chdir");
|
err(1, "..: chdir");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("%s...\n", namestr);
|
tprintf("%s...\n", namestr);
|
||||||
checkonefilecontents(namestr, de->obj, change);
|
checkonefilecontents(namestr, de->obj, change);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2813,7 +2813,7 @@ checkfs(void)
|
|||||||
/*
|
/*
|
||||||
* We just built the model; talk about it.
|
* We just built the model; talk about it.
|
||||||
*/
|
*/
|
||||||
printf("Established %u versions across %u directories and %u files\n",
|
tprintf("Established %u versions across %u directories and %u files\n",
|
||||||
changes->version + 1, nextdirnum, nextfilenum);
|
changes->version + 1, nextdirnum, nextfilenum);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2821,7 +2821,7 @@ checkfs(void)
|
|||||||
* FOUND holding the found volume state.
|
* FOUND holding the found volume state.
|
||||||
*/
|
*/
|
||||||
inspectfs();
|
inspectfs();
|
||||||
printf("Found %u subdirs and %u files on the volume\n",
|
tprintf("Found %u subdirs and %u files on the volume\n",
|
||||||
found_subdirs, found_files);
|
found_subdirs, found_files);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2856,7 +2856,7 @@ checkfs(void)
|
|||||||
best = change;
|
best = change;
|
||||||
bestscore = score;
|
bestscore = score;
|
||||||
}
|
}
|
||||||
//printf("version %u score %u\n", change->version, score);
|
//tprintf("version %u score %u\n", change->version, score);
|
||||||
change = change->next;
|
change = change->next;
|
||||||
}
|
}
|
||||||
assert(best != NULL);
|
assert(best != NULL);
|
||||||
@ -2874,9 +2874,9 @@ checkfs(void)
|
|||||||
* differences. XXX: this results in not checking file
|
* differences. XXX: this results in not checking file
|
||||||
* data...
|
* data...
|
||||||
*/
|
*/
|
||||||
printf("FAILURE: Directory tree does not match on any "
|
tprintf("FAILURE: Directory tree does not match on any "
|
||||||
"version.\n");
|
"version.\n");
|
||||||
printf("Best version is %u; describing differences:\n",
|
tprintf("Best version is %u; describing differences:\n",
|
||||||
best->version);
|
best->version);
|
||||||
printdiffs(1, state, found);
|
printdiffs(1, state, found);
|
||||||
return;
|
return;
|
||||||
@ -2886,9 +2886,9 @@ checkfs(void)
|
|||||||
* Ok, we did get an exact match. Print it.
|
* Ok, we did get an exact match. Print it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
printf("Directory tree matched in version %u.\n", best->version);
|
tprintf("Directory tree matched in version %u.\n", best->version);
|
||||||
if (best->partial) {
|
if (best->partial) {
|
||||||
printf("WARNING: this is a version from a partially committed "
|
tprintf("WARNING: this is a version from a partially committed "
|
||||||
"operation.\n");
|
"operation.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2905,7 +2905,7 @@ checkfs(void)
|
|||||||
|
|
||||||
/* now check the file contents */
|
/* now check the file contents */
|
||||||
|
|
||||||
printf("Checking file contents...\n");
|
tprintf("Checking file contents...\n");
|
||||||
checkallfilecontents(state, best);
|
checkallfilecontents(state, best);
|
||||||
printf("Done.\n");
|
tprintf("Done.\n");
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ data_matches(const char *namestr, off_t regionoffset,
|
|||||||
}
|
}
|
||||||
else if (zero_at(where, howmuch)) {
|
else if (zero_at(where, howmuch)) {
|
||||||
if (where >= zerostart) {
|
if (where >= zerostart) {
|
||||||
printf("WARNING: file %s range %lld-%lld is "
|
tprintf("WARNING: file %s range %lld-%lld is "
|
||||||
"zeroed\n",
|
"zeroed\n",
|
||||||
namestr, regionoffset + where,
|
namestr, regionoffset + where,
|
||||||
regionoffset + where + howmuch);
|
regionoffset + where + howmuch);
|
||||||
@ -176,7 +176,7 @@ data_matches(const char *namestr, off_t regionoffset,
|
|||||||
}
|
}
|
||||||
else if (poison_at(where, howmuch)) {
|
else if (poison_at(where, howmuch)) {
|
||||||
if (where >= zerostart) {
|
if (where >= zerostart) {
|
||||||
printf("ERROR: file %s range %lld-%lld is "
|
tprintf("ERROR: file %s range %lld-%lld is "
|
||||||
"poisoned\n",
|
"poisoned\n",
|
||||||
namestr, regionoffset + where,
|
namestr, regionoffset + where,
|
||||||
regionoffset + where + howmuch);
|
regionoffset + where + howmuch);
|
||||||
@ -205,7 +205,7 @@ data_check(const char *namestr, off_t regionoffset,
|
|||||||
|
|
||||||
if (!data_matches(namestr, regionoffset,
|
if (!data_matches(namestr, regionoffset,
|
||||||
code, seq, zerostart, len, checkstart, checklen)) {
|
code, seq, zerostart, len, checkstart, checklen)) {
|
||||||
printf("ERROR: file %s range %lld-%lld contains garbage\n",
|
tprintf("ERROR: file %s range %lld-%lld contains garbage\n",
|
||||||
namestr, regionoffset + checkstart,
|
namestr, regionoffset + checkstart,
|
||||||
regionoffset + checkstart + checklen);
|
regionoffset + checkstart + checklen);
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ do_createfile(unsigned name)
|
|||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
err(1, "%s: create", namestr);
|
err(1, "%s: create", namestr);
|
||||||
}
|
}
|
||||||
printf("create %s\n", namestr);
|
tprintf("create %s\n", namestr);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ do_write(int fd, unsigned name, unsigned code, unsigned seq,
|
|||||||
done += ret;
|
done += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("write %s: %lld at %lld\n", namestr, len, pos);
|
tprintf("write %s: %lld at %lld\n", namestr, len, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -134,7 +134,7 @@ do_truncate(int fd, unsigned name, off_t len)
|
|||||||
if (ftruncate(fd, len) == -1) {
|
if (ftruncate(fd, len) == -1) {
|
||||||
err(1, "%s: truncate to %lld", namestr, len);
|
err(1, "%s: truncate to %lld", namestr, len);
|
||||||
}
|
}
|
||||||
printf("truncate %s: to %lld\n", namestr, len);
|
tprintf("truncate %s: to %lld\n", namestr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -146,7 +146,7 @@ do_mkdir(unsigned name)
|
|||||||
if (mkdir(namestr, 0775) == -1) {
|
if (mkdir(namestr, 0775) == -1) {
|
||||||
err(1, "%s: mkdir", namestr);
|
err(1, "%s: mkdir", namestr);
|
||||||
}
|
}
|
||||||
printf("mkdir %s\n", namestr);
|
tprintf("mkdir %s\n", namestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -158,7 +158,7 @@ do_rmdir(unsigned name)
|
|||||||
if (rmdir(namestr) == -1) {
|
if (rmdir(namestr) == -1) {
|
||||||
err(1, "%s: rmdir", namestr);
|
err(1, "%s: rmdir", namestr);
|
||||||
}
|
}
|
||||||
printf("rmdir %s\n", namestr);
|
tprintf("rmdir %s\n", namestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -170,7 +170,7 @@ do_unlink(unsigned name)
|
|||||||
if (remove(namestr) == -1) {
|
if (remove(namestr) == -1) {
|
||||||
err(1, "%s: remove", namestr);
|
err(1, "%s: remove", namestr);
|
||||||
}
|
}
|
||||||
printf("remove %s\n", namestr);
|
tprintf("remove %s\n", namestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -183,7 +183,7 @@ do_link(unsigned from, unsigned to)
|
|||||||
if (link(fromstr, tostr) == -1) {
|
if (link(fromstr, tostr) == -1) {
|
||||||
err(1, "link %s to %s", fromstr, tostr);
|
err(1, "link %s to %s", fromstr, tostr);
|
||||||
}
|
}
|
||||||
printf("link %s %s\n", fromstr, tostr);
|
tprintf("link %s %s\n", fromstr, tostr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -196,7 +196,7 @@ do_rename(unsigned from, unsigned to)
|
|||||||
if (rename(fromstr, tostr) == -1) {
|
if (rename(fromstr, tostr) == -1) {
|
||||||
err(1, "rename %s to %s", fromstr, tostr);
|
err(1, "rename %s to %s", fromstr, tostr);
|
||||||
}
|
}
|
||||||
printf("rename %s %s\n", fromstr, tostr);
|
tprintf("rename %s %s\n", fromstr, tostr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -216,7 +216,7 @@ do_renamexd(unsigned fromdir, unsigned from, unsigned todir, unsigned to)
|
|||||||
if (rename(frombuf, tobuf) == -1) {
|
if (rename(frombuf, tobuf) == -1) {
|
||||||
err(1, "rename %s to %s", frombuf, tobuf);
|
err(1, "rename %s to %s", frombuf, tobuf);
|
||||||
}
|
}
|
||||||
printf("rename %s %s\n", frombuf, tobuf);
|
tprintf("rename %s %s\n", frombuf, tobuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -228,7 +228,7 @@ do_chdir(unsigned name)
|
|||||||
if (chdir(namestr) == -1) {
|
if (chdir(namestr) == -1) {
|
||||||
err(1, "chdir: %s", namestr);
|
err(1, "chdir: %s", namestr);
|
||||||
}
|
}
|
||||||
printf("chdir %s\n", namestr);
|
tprintf("chdir %s\n", namestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -237,7 +237,7 @@ do_chdirup(void)
|
|||||||
if (chdir("..") == -1) {
|
if (chdir("..") == -1) {
|
||||||
err(1, "chdir: ..");
|
err(1, "chdir: ..");
|
||||||
}
|
}
|
||||||
printf("chdir ..\n");
|
tprintf("chdir ..\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -246,6 +246,6 @@ do_sync(void)
|
|||||||
if (sync()) {
|
if (sync()) {
|
||||||
warn("sync");
|
warn("sync");
|
||||||
}
|
}
|
||||||
printf("sync\n");
|
tprintf("sync\n");
|
||||||
printf("----------------------------------------\n");
|
tprintf("----------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
@ -132,13 +132,13 @@ printworkloads(void)
|
|||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
printf("Supported workloads:\n");
|
tprintf("Supported workloads:\n");
|
||||||
for (i=0; i<numworkloads; i++) {
|
for (i=0; i<numworkloads; i++) {
|
||||||
printf(" %s", workloads[i].name);
|
tprintf(" %s", workloads[i].name);
|
||||||
if (workloads[i].argname) {
|
if (workloads[i].argname) {
|
||||||
printf(" %s", workloads[i].argname);
|
tprintf(" %s", workloads[i].argname);
|
||||||
}
|
}
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
printf("Hash : %d\n", j);
|
tprintf("Hash : %d\n", j);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -39,45 +39,53 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <test161/test161.h>
|
||||||
|
#include <test/test.h>
|
||||||
|
|
||||||
#define PageSize 4096
|
#define PageSize 4096
|
||||||
#define NumPages 512
|
#define NumPages 512
|
||||||
|
|
||||||
int sparse[NumPages][PageSize]; /* use only the first element in the row */
|
int sparse[NumPages][PageSize]; /* use only the first element in the row */
|
||||||
|
|
||||||
|
#define PROGRESS_INTERVAL 20
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
printf("Entering the huge program - I will stress test your VM\n");
|
tprintf("Entering the huge program - I will stress test your VM\n");
|
||||||
|
|
||||||
/* move number in so that sparse[i][0]=i */
|
/* move number in so that sparse[i][0]=i */
|
||||||
for (i=0; i<NumPages; i++) {
|
for (i=0; i<NumPages; i++) {
|
||||||
|
TEST161_LPROGRESS_N(i, PROGRESS_INTERVAL);
|
||||||
sparse[i][0]=i;
|
sparse[i][0]=i;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("stage [1] done\n");
|
lsay("\nstage [1] done\n");
|
||||||
|
|
||||||
/* increment each location 5 times */
|
/* increment each location 5 times */
|
||||||
for (j=0; j<5; j++) {
|
for (j=0; j<5; j++) {
|
||||||
for (i=0; i<NumPages; i++) {
|
for (i=0; i<NumPages; i++) {
|
||||||
|
TEST161_LPROGRESS_N(i, PROGRESS_INTERVAL);
|
||||||
sparse[i][0]++;
|
sparse[i][0]++;
|
||||||
}
|
}
|
||||||
printf("stage [2.%d] done\n", j);
|
lsay("\nstage [2.%d] done\n", j);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("stage [2] done\n");
|
lsay("\nstage [2] done\n");
|
||||||
|
|
||||||
/* check if the numbers are sane */
|
/* check if the numbers are sane */
|
||||||
for (i=NumPages-1; i>=0; i--) {
|
for (i=NumPages-1; i>=0; i--) {
|
||||||
|
TEST161_LPROGRESS_N(i, PROGRESS_INTERVAL);
|
||||||
if (sparse[i][0]!=i+5) {
|
if (sparse[i][0]!=i+5) {
|
||||||
printf("BAD NEWS!!! - your VM mechanism has a bug!\n");
|
lsay("BAD NEWS!!! - your VM mechanism has a bug!\n");
|
||||||
|
success(TEST161_FAIL, SECRET, "/testbin/huge");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("You passed!\n");
|
success(TEST161_SUCCESS, SECRET, "/testbin/huge");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ geti(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ((ch=='\b' || ch==127) && digits>0) {
|
else if ((ch=='\b' || ch==127) && digits>0) {
|
||||||
printf("\b \b");
|
tprintf("\b \b");
|
||||||
val = val/10;
|
val = val/10;
|
||||||
digits--;
|
digits--;
|
||||||
}
|
}
|
||||||
@ -117,11 +117,11 @@ markblock(volatile void *ptr, size_t size, unsigned bias, int doprint)
|
|||||||
val = ((unsigned long)i ^ (unsigned long)bias);
|
val = ((unsigned long)i ^ (unsigned long)bias);
|
||||||
pl[i] = val;
|
pl[i] = val;
|
||||||
if (doprint && (i%64==63)) {
|
if (doprint && (i%64==63)) {
|
||||||
printf(".");
|
tprintf(".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doprint) {
|
if (doprint) {
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,9 +143,9 @@ checkblock(volatile void *ptr, size_t size, unsigned bias, int doprint)
|
|||||||
val = ((unsigned long)i ^ (unsigned long)bias);
|
val = ((unsigned long)i ^ (unsigned long)bias);
|
||||||
if (pl[i] != val) {
|
if (pl[i] != val) {
|
||||||
if (doprint) {
|
if (doprint) {
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
printf("FAILED: data mismatch at offset %lu of block "
|
tprintf("FAILED: data mismatch at offset %lu of block "
|
||||||
"at 0x%lx: %lu vs. %lu\n",
|
"at 0x%lx: %lu vs. %lu\n",
|
||||||
(unsigned long) (i*sizeof(unsigned long)),
|
(unsigned long) (i*sizeof(unsigned long)),
|
||||||
(unsigned long)(uintptr_t)pl,
|
(unsigned long)(uintptr_t)pl,
|
||||||
@ -153,11 +153,11 @@ checkblock(volatile void *ptr, size_t size, unsigned bias, int doprint)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (doprint && (i%64==63)) {
|
if (doprint && (i%64==63)) {
|
||||||
printf(".");
|
tprintf(".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (doprint) {
|
if (doprint) {
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -178,23 +178,23 @@ test1(void)
|
|||||||
{
|
{
|
||||||
volatile unsigned *x;
|
volatile unsigned *x;
|
||||||
|
|
||||||
printf("*** Malloc test 1 ***\n");
|
tprintf("*** Malloc test 1 ***\n");
|
||||||
printf("Allocating %u bytes\n", BIGSIZE);
|
tprintf("Allocating %u bytes\n", BIGSIZE);
|
||||||
x = malloc(BIGSIZE);
|
x = malloc(BIGSIZE);
|
||||||
if (x==NULL) {
|
if (x==NULL) {
|
||||||
printf("FAILED: malloc failed\n");
|
tprintf("FAILED: malloc failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
markblock(x, BIGSIZE, 0, 0);
|
markblock(x, BIGSIZE, 0, 0);
|
||||||
if (checkblock(x, BIGSIZE, 0, 0)) {
|
if (checkblock(x, BIGSIZE, 0, 0)) {
|
||||||
printf("FAILED: data corrupt\n");
|
tprintf("FAILED: data corrupt\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free((void *)x);
|
free((void *)x);
|
||||||
|
|
||||||
printf("Passed malloc test 1.\n");
|
tprintf("Passed malloc test 1.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -237,43 +237,43 @@ test2(void)
|
|||||||
volatile unsigned *x;
|
volatile unsigned *x;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
printf("Entering malloc test 2.\n");
|
tprintf("Entering malloc test 2.\n");
|
||||||
printf("Make sure you read and understand the comment in malloctest.c "
|
tprintf("Make sure you read and understand the comment in malloctest.c "
|
||||||
"that\nexplains the conditions this test assumes.\n\n");
|
"that\nexplains the conditions this test assumes.\n\n");
|
||||||
|
|
||||||
printf("Testing how much memory we can allocate:\n");
|
tprintf("Testing how much memory we can allocate:\n");
|
||||||
|
|
||||||
for (size = HUGESIZE; (x = malloc(size))==NULL; size = size/2) {
|
for (size = HUGESIZE; (x = malloc(size))==NULL; size = size/2) {
|
||||||
printf(" %9lu bytes: failed\n", (unsigned long) size);
|
tprintf(" %9lu bytes: failed\n", (unsigned long) size);
|
||||||
}
|
}
|
||||||
printf(" %9lu bytes: succeeded\n", (unsigned long) size);
|
tprintf(" %9lu bytes: succeeded\n", (unsigned long) size);
|
||||||
|
|
||||||
printf("Passed part 1\n");
|
tprintf("Passed part 1\n");
|
||||||
|
|
||||||
printf("Touching all the words in the block.\n");
|
tprintf("Touching all the words in the block.\n");
|
||||||
markblock(x, size, 0, 1);
|
markblock(x, size, 0, 1);
|
||||||
|
|
||||||
printf("Validating the words in the block.\n");
|
tprintf("Validating the words in the block.\n");
|
||||||
if (checkblock(x, size, 0, 1)) {
|
if (checkblock(x, size, 0, 1)) {
|
||||||
printf("FAILED: data corrupt\n");
|
tprintf("FAILED: data corrupt\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("Passed part 2\n");
|
tprintf("Passed part 2\n");
|
||||||
|
|
||||||
|
|
||||||
printf("Freeing the block\n");
|
tprintf("Freeing the block\n");
|
||||||
free((void *)x);
|
free((void *)x);
|
||||||
printf("Passed part 3\n");
|
tprintf("Passed part 3\n");
|
||||||
printf("Allocating another block\n");
|
tprintf("Allocating another block\n");
|
||||||
|
|
||||||
x = malloc(size);
|
x = malloc(size);
|
||||||
if (x==NULL) {
|
if (x==NULL) {
|
||||||
printf("FAILED: free didn't return the memory?\n");
|
tprintf("FAILED: free didn't return the memory?\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
free((void *)x);
|
free((void *)x);
|
||||||
|
|
||||||
printf("Passed malloc test 2.\n");
|
tprintf("Passed malloc test 2.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -304,11 +304,11 @@ test3(void)
|
|||||||
int ct=0, failed=0;
|
int ct=0, failed=0;
|
||||||
void *x;
|
void *x;
|
||||||
|
|
||||||
printf("Entering malloc test 3.\n");
|
tprintf("Entering malloc test 3.\n");
|
||||||
printf("Make sure you read and understand the comment in malloctest.c "
|
tprintf("Make sure you read and understand the comment in malloctest.c "
|
||||||
"that\nexplains the conditions this test assumes.\n\n");
|
"that\nexplains the conditions this test assumes.\n\n");
|
||||||
|
|
||||||
printf("Testing how much memory we can allocate:\n");
|
tprintf("Testing how much memory we can allocate:\n");
|
||||||
|
|
||||||
while ((tmp = malloc(sizeof(struct test3))) != NULL) {
|
while ((tmp = malloc(sizeof(struct test3))) != NULL) {
|
||||||
|
|
||||||
@ -322,33 +322,33 @@ test3(void)
|
|||||||
|
|
||||||
ct++;
|
ct++;
|
||||||
if (ct%128==0) {
|
if (ct%128==0) {
|
||||||
printf(".");
|
tprintf(".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Allocated %lu bytes\n", (unsigned long) tot);
|
tprintf("Allocated %lu bytes\n", (unsigned long) tot);
|
||||||
|
|
||||||
printf("Trying some more allocations which I expect to fail...\n");
|
tprintf("Trying some more allocations which I expect to fail...\n");
|
||||||
|
|
||||||
x = malloc(SMALLSIZE);
|
x = malloc(SMALLSIZE);
|
||||||
if (x != NULL) {
|
if (x != NULL) {
|
||||||
printf("FAILED: malloc(%u) succeeded\n", SMALLSIZE);
|
tprintf("FAILED: malloc(%u) succeeded\n", SMALLSIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = malloc(MEDIUMSIZE);
|
x = malloc(MEDIUMSIZE);
|
||||||
if (x != NULL) {
|
if (x != NULL) {
|
||||||
printf("FAILED: malloc(%u) succeeded\n", MEDIUMSIZE);
|
tprintf("FAILED: malloc(%u) succeeded\n", MEDIUMSIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = malloc(BIGSIZE);
|
x = malloc(BIGSIZE);
|
||||||
if (x != NULL) {
|
if (x != NULL) {
|
||||||
printf("FAILED: malloc(%u) succeeded\n", BIGSIZE);
|
tprintf("FAILED: malloc(%u) succeeded\n", BIGSIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Ok, now I'm going to free everything...\n");
|
tprintf("Ok, now I'm going to free everything...\n");
|
||||||
|
|
||||||
while (list != NULL) {
|
while (list != NULL) {
|
||||||
tmp = list->next;
|
tmp = list->next;
|
||||||
@ -363,20 +363,20 @@ test3(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (failed) {
|
if (failed) {
|
||||||
printf("FAILED: data corruption\n");
|
tprintf("FAILED: data corruption\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Let me see if I can allocate some more now...\n");
|
tprintf("Let me see if I can allocate some more now...\n");
|
||||||
|
|
||||||
x = malloc(MEDIUMSIZE);
|
x = malloc(MEDIUMSIZE);
|
||||||
if (x == NULL) {
|
if (x == NULL) {
|
||||||
printf("FAIL: Nope, I couldn't.\n");
|
tprintf("FAIL: Nope, I couldn't.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
free(x);
|
free(x);
|
||||||
|
|
||||||
printf("Passed malloc test 3\n");
|
tprintf("Passed malloc test 3\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -397,34 +397,34 @@ test4(void)
|
|||||||
void *x, *y, *z;
|
void *x, *y, *z;
|
||||||
unsigned long lx, ly, lz, overhead, zsize;
|
unsigned long lx, ly, lz, overhead, zsize;
|
||||||
|
|
||||||
printf("Entering malloc test 4.\n");
|
tprintf("Entering malloc test 4.\n");
|
||||||
printf("This test is intended for first/best-fit based mallocs.\n");
|
tprintf("This test is intended for first/best-fit based mallocs.\n");
|
||||||
printf("This test may not work correctly if run after other tests.\n");
|
tprintf("This test may not work correctly if run after other tests.\n");
|
||||||
|
|
||||||
printf("Testing free list coalescing:\n");
|
tprintf("Testing free list coalescing:\n");
|
||||||
|
|
||||||
x = malloc(SMALLSIZE);
|
x = malloc(SMALLSIZE);
|
||||||
if (x==NULL) {
|
if (x==NULL) {
|
||||||
printf("FAILED: malloc(%u) failed\n", SMALLSIZE);
|
tprintf("FAILED: malloc(%u) failed\n", SMALLSIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
y = malloc(MEDIUMSIZE);
|
y = malloc(MEDIUMSIZE);
|
||||||
if (y==NULL) {
|
if (y==NULL) {
|
||||||
printf("FAILED: malloc(%u) failed\n", MEDIUMSIZE);
|
tprintf("FAILED: malloc(%u) failed\n", MEDIUMSIZE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(unsigned long) < sizeof(void *)) {
|
if (sizeof(unsigned long) < sizeof(void *)) {
|
||||||
printf("Buh? I can't fit a void * in an unsigned long\n");
|
tprintf("Buh? I can't fit a void * in an unsigned long\n");
|
||||||
printf("ENVIRONMENT FAILED...\n");
|
tprintf("ENVIRONMENT FAILED...\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lx = (unsigned long)x;
|
lx = (unsigned long)x;
|
||||||
ly = (unsigned long)y;
|
ly = (unsigned long)y;
|
||||||
|
|
||||||
printf("x is 0x%lx; y is 0x%lx\n", lx, ly);
|
tprintf("x is 0x%lx; y is 0x%lx\n", lx, ly);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The memory should look something like this:
|
* The memory should look something like this:
|
||||||
@ -436,7 +436,7 @@ test4(void)
|
|||||||
|
|
||||||
/* This is obviously wrong. */
|
/* This is obviously wrong. */
|
||||||
if (lx == ly) {
|
if (lx == ly) {
|
||||||
printf("FAIL: x == y\n");
|
tprintf("FAIL: x == y\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,11 +447,11 @@ test4(void)
|
|||||||
* or the other block's start is within the first block.)
|
* or the other block's start is within the first block.)
|
||||||
*/
|
*/
|
||||||
if (lx < ly && lx + SMALLSIZE > ly) {
|
if (lx < ly && lx + SMALLSIZE > ly) {
|
||||||
printf("FAIL: y starts within x\n");
|
tprintf("FAIL: y starts within x\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ly < lx && ly + MEDIUMSIZE > lx) {
|
if (ly < lx && ly + MEDIUMSIZE > lx) {
|
||||||
printf("FAIL: x starts within y\n");
|
tprintf("FAIL: x starts within y\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +461,7 @@ test4(void)
|
|||||||
* free list.
|
* free list.
|
||||||
*/
|
*/
|
||||||
if (ly < lx) {
|
if (ly < lx) {
|
||||||
printf("TEST UNSUITABLE: y is below x\n");
|
tprintf("TEST UNSUITABLE: y is below x\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,39 +469,39 @@ test4(void)
|
|||||||
* Compute the space used by index structures.
|
* Compute the space used by index structures.
|
||||||
*/
|
*/
|
||||||
overhead = ly - (lx + SMALLSIZE);
|
overhead = ly - (lx + SMALLSIZE);
|
||||||
printf("Apparent block overhead: %lu\n", overhead);
|
tprintf("Apparent block overhead: %lu\n", overhead);
|
||||||
|
|
||||||
if (overhead > ABSURD_OVERHEAD) {
|
if (overhead > ABSURD_OVERHEAD) {
|
||||||
printf("TEST UNSUITABLE: block overhead absurdly large.\n");
|
tprintf("TEST UNSUITABLE: block overhead absurdly large.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (overhead > OVERHEAD) {
|
if (overhead > OVERHEAD) {
|
||||||
printf("FAIL: block overhead is too large.\n");
|
tprintf("FAIL: block overhead is too large.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Freeing blocks...\n");
|
tprintf("Freeing blocks...\n");
|
||||||
free(x);
|
free(x);
|
||||||
free(y);
|
free(y);
|
||||||
|
|
||||||
zsize = SMALLSIZE + MEDIUMSIZE + overhead;
|
zsize = SMALLSIZE + MEDIUMSIZE + overhead;
|
||||||
|
|
||||||
printf("Now allocating %lu bytes... should reuse the space.\n", zsize);
|
tprintf("Now allocating %lu bytes... should reuse the space.\n", zsize);
|
||||||
z = malloc(zsize);
|
z = malloc(zsize);
|
||||||
if (z == NULL) {
|
if (z == NULL) {
|
||||||
printf("FAIL: Allocation failed...\n");
|
tprintf("FAIL: Allocation failed...\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lz = (unsigned long) z;
|
lz = (unsigned long) z;
|
||||||
|
|
||||||
printf("z is 0x%lx (x was 0x%lx, y 0x%lx)\n", lz, lx, ly);
|
tprintf("z is 0x%lx (x was 0x%lx, y 0x%lx)\n", lz, lx, ly);
|
||||||
|
|
||||||
if (lz==lx) {
|
if (lz==lx) {
|
||||||
printf("Passed.\n");
|
tprintf("Passed.\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Failed.\n");
|
tprintf("Failed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(z);
|
free(z);
|
||||||
@ -530,7 +530,7 @@ test567(int testno, unsigned long seed)
|
|||||||
int i, n, size, failed=0;
|
int i, n, size, failed=0;
|
||||||
|
|
||||||
srandom(seed);
|
srandom(seed);
|
||||||
printf("Seeded random number generator with %lu.\n", seed);
|
tprintf("Seeded random number generator with %lu.\n", seed);
|
||||||
|
|
||||||
for (i=0; i<32; i++) {
|
for (i=0; i<32; i++) {
|
||||||
ptrs[i] = NULL;
|
ptrs[i] = NULL;
|
||||||
@ -544,7 +544,7 @@ test567(int testno, unsigned long seed)
|
|||||||
ptrs[n] = malloc(size);
|
ptrs[n] = malloc(size);
|
||||||
psizes[n] = size;
|
psizes[n] = size;
|
||||||
if (ptrs[n] == NULL) {
|
if (ptrs[n] == NULL) {
|
||||||
printf("\nmalloc %u failed\n", size);
|
tprintf("\nmalloc %u failed\n", size);
|
||||||
failed = 1;
|
failed = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -561,10 +561,10 @@ test567(int testno, unsigned long seed)
|
|||||||
psizes[n] = 0;
|
psizes[n] = 0;
|
||||||
}
|
}
|
||||||
if (i%256==0) {
|
if (i%256==0) {
|
||||||
printf(".");
|
tprintf(".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
tprintf("\n");
|
||||||
|
|
||||||
for (i=0; i<32; i++) {
|
for (i=0; i<32; i++) {
|
||||||
if (ptrs[i] != NULL) {
|
if (ptrs[i] != NULL) {
|
||||||
@ -573,10 +573,10 @@ test567(int testno, unsigned long seed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (failed) {
|
if (failed) {
|
||||||
printf("FAILED malloc test %d\n", testno);
|
tprintf("FAILED malloc test %d\n", testno);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Passed malloc test %d\n", testno);
|
tprintf("Passed malloc test %d\n", testno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +584,7 @@ static
|
|||||||
void
|
void
|
||||||
test5(void)
|
test5(void)
|
||||||
{
|
{
|
||||||
printf("Beginning malloc test 5\n");
|
tprintf("Beginning malloc test 5\n");
|
||||||
test567(5, 0);
|
test567(5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,7 +595,7 @@ test6(void)
|
|||||||
int fd, len;
|
int fd, len;
|
||||||
unsigned long seed;
|
unsigned long seed;
|
||||||
|
|
||||||
printf("Beginning malloc test 6\n");
|
tprintf("Beginning malloc test 6\n");
|
||||||
|
|
||||||
fd = open(_PATH_RANDOM, O_RDONLY);
|
fd = open(_PATH_RANDOM, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -619,9 +619,9 @@ test7(void)
|
|||||||
{
|
{
|
||||||
unsigned long seed;
|
unsigned long seed;
|
||||||
|
|
||||||
printf("Beginning malloc test 7\n");
|
tprintf("Beginning malloc test 7\n");
|
||||||
|
|
||||||
printf("Enter random seed: ");
|
tprintf("Enter random seed: ");
|
||||||
seed = geti();
|
seed = geti();
|
||||||
|
|
||||||
test567(7, seed);
|
test567(7, seed);
|
||||||
@ -673,12 +673,12 @@ main(int argc, char *argv[])
|
|||||||
while (1) {
|
while (1) {
|
||||||
if (menu) {
|
if (menu) {
|
||||||
for (i=0; tests[i].num>=0; i++) {
|
for (i=0; tests[i].num>=0; i++) {
|
||||||
printf(" %2d %s\n", tests[i].num,
|
tprintf(" %2d %s\n", tests[i].num,
|
||||||
tests[i].desc);
|
tests[i].desc);
|
||||||
}
|
}
|
||||||
menu = 0;
|
menu = 0;
|
||||||
}
|
}
|
||||||
printf("malloctest: ");
|
tprintf("malloctest: ");
|
||||||
tn = geti();
|
tn = geti();
|
||||||
if (tn < 0) {
|
if (tn < 0) {
|
||||||
break;
|
break;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user