clang-format

This commit is contained in:
2024-09-10 13:03:02 -04:00
parent 53c617d779
commit d66450e427
381 changed files with 28864 additions and 34170 deletions

View File

@@ -39,19 +39,17 @@
#include <stdlib.h>
#include <err.h>
int
main(int argc, char *argv[])
{
int i, j;
int main(int argc, char *argv[]) {
int i, j;
if (argc != 3) {
errx(1, "Usage: add num1 num2");
}
if (argc != 3) {
errx(1, "Usage: add num1 num2");
}
i = atoi(argv[1]);
j = atoi(argv[2]);
i = atoi(argv[1]);
j = atoi(argv[2]);
printf("Answer: %d\n", i+j);
printf("Answer: %d\n", i + j);
return 0;
return 0;
}

View File

@@ -37,21 +37,19 @@
#include <stdio.h>
int
main(int argc, char *argv[])
{
const char *tmp;
int i;
int main(int argc, char *argv[]) {
const char *tmp;
int i;
printf("argc: %d\n", argc);
printf("argc: %d\n", argc);
for (i=0; i<=argc; i++) {
tmp = argv[i];
if (tmp==NULL) {
tmp = "[NULL]";
}
printf("argv[%d]: %s\n", i, tmp);
}
for (i = 0; i <= argc; i++) {
tmp = argv[i];
if (tmp == NULL) {
tmp = "[NULL]";
}
printf("argv[%d]: %s\n", i, tmp);
}
return 0;
return 0;
}

View File

@@ -37,25 +37,19 @@
#include "test.h"
static
void
chdir_empty(void)
{
int rv;
static void chdir_empty(void) {
int rv;
/*
* This is actually valid by some interpretations.
*/
/*
* This is actually valid by some interpretations.
*/
report_begin("chdir to empty string");
rv = chdir("");
report_check2(rv, errno, EINVAL, 0);
report_begin("chdir to empty string");
rv = chdir("");
report_check2(rv, errno, EINVAL, 0);
}
void
test_chdir(void)
{
test_chdir_path();
chdir_empty();
void test_chdir(void) {
test_chdir_path();
chdir_empty();
}

View File

@@ -33,8 +33,4 @@
#include "test.h"
void
test_close(void)
{
test_close_fd();
}
void test_close(void) { test_close_fd(); }

View File

@@ -44,99 +44,86 @@
#include "config.h"
#include "test.h"
static
void
dup2_fd2(int fd, const char *desc)
{
int rv;
static void dup2_fd2(int fd, const char *desc) {
int rv;
report_begin("%s", desc);
rv = dup2(STDIN_FILENO, fd);
report_check(rv, errno, EBADF);
report_begin("%s", desc);
rv = dup2(STDIN_FILENO, fd);
report_check(rv, errno, EBADF);
if (rv != -1) {
close(fd); /* just in case */
}
if (rv != -1) {
close(fd); /* just in case */
}
}
static
void
dup2_self(void)
{
struct stat sb;
int rv;
int testfd;
static void dup2_self(void) {
struct stat sb;
int rv;
int testfd;
/* use fd that isn't in use */
testfd = CLOSED_FD;
/* use fd that isn't in use */
testfd = CLOSED_FD;
report_begin("copying stdin to test with");
report_begin("copying stdin to test with");
rv = dup2(STDIN_FILENO, testfd);
if (rv == -1) {
report_result(rv, errno);
report_aborted();
return;
}
rv = dup2(STDIN_FILENO, testfd);
if (rv == -1) {
report_result(rv, errno);
report_aborted();
return;
}
report_begin("dup2 to same fd");
rv = dup2(testfd, testfd);
if (rv == testfd) {
report_passed();
}
else if (rv<0) {
report_result(rv, errno);
report_failure();
}
else {
report_warnx("returned %d instead", rv);
report_failure();
}
report_begin("dup2 to same fd");
rv = dup2(testfd, testfd);
if (rv == testfd) {
report_passed();
} else if (rv < 0) {
report_result(rv, errno);
report_failure();
} else {
report_warnx("returned %d instead", rv);
report_failure();
}
report_begin("fstat fd after dup2 to itself");
rv = fstat(testfd, &sb);
if (errno == ENOSYS) {
report_saw_enosys();
}
report_result(rv, errno);
if (rv==0) {
report_passed();
}
else if (errno != ENOSYS) {
report_failure();
}
else {
report_skipped();
/* no support for fstat; try lseek */
report_begin("lseek fd after dup2 to itself");
rv = lseek(testfd, 0, SEEK_CUR);
report_result(rv, errno);
if (rv==0 || (rv==-1 && errno==ESPIPE)) {
report_passed();
}
else {
report_failure();
}
}
report_begin("fstat fd after dup2 to itself");
rv = fstat(testfd, &sb);
if (errno == ENOSYS) {
report_saw_enosys();
}
report_result(rv, errno);
if (rv == 0) {
report_passed();
} else if (errno != ENOSYS) {
report_failure();
} else {
report_skipped();
/* no support for fstat; try lseek */
report_begin("lseek fd after dup2 to itself");
rv = lseek(testfd, 0, SEEK_CUR);
report_result(rv, errno);
if (rv == 0 || (rv == -1 && errno == ESPIPE)) {
report_passed();
} else {
report_failure();
}
}
close(testfd);
close(testfd);
}
void
test_dup2(void)
{
/* This does the first fd. */
test_dup2_fd();
void test_dup2(void) {
/* This does the first fd. */
test_dup2_fd();
/* Any interesting cases added here should also go in common_fds.c */
dup2_fd2(-1, "dup2 to -1");
dup2_fd2(-5, "dup2 to -5");
dup2_fd2(IMPOSSIBLE_FD, "dup2 to impossible fd");
/* Any interesting cases added here should also go in common_fds.c */
dup2_fd2(-1, "dup2 to -1");
dup2_fd2(-5, "dup2 to -5");
dup2_fd2(IMPOSSIBLE_FD, "dup2 to impossible fd");
#ifdef OPEN_MAX
dup2_fd2(OPEN_MAX, "dup2 to OPEN_MAX");
dup2_fd2(OPEN_MAX, "dup2 to OPEN_MAX");
#else
warnx("Warning: OPEN_MAX not defined - test skipped");
warnx("Warning: OPEN_MAX not defined - test skipped");
#endif
dup2_self();
dup2_self();
}

View File

@@ -40,142 +40,124 @@
#include "config.h"
#include "test.h"
static
int
exec_common_fork(void)
{
int pid, rv, status, err;
static int exec_common_fork(void) {
int pid, rv, status, err;
/*
* This does not happen in a test context (from the point of
* view of report.c) so we have to fiddle a bit.
*/
/*
* This does not happen in a test context (from the point of
* view of report.c) so we have to fiddle a bit.
*/
pid = fork();
if (pid<0) {
err = errno;
report_begin("forking for test");
report_result(pid, err);
report_aborted();
return -1;
}
pid = fork();
if (pid < 0) {
err = errno;
report_begin("forking for test");
report_result(pid, err);
report_aborted();
return -1;
}
if (pid==0) {
/* child */
return 0;
}
if (pid == 0) {
/* child */
return 0;
}
rv = waitpid(pid, &status, 0);
if (rv == -1) {
err = errno;
report_begin("waiting for test subprocess");
report_result(rv, err);
report_failure();
return -1;
}
if (WIFEXITED(status) && WEXITSTATUS(status) == MAGIC_STATUS) {
return 1;
}
/* Oops... */
report_begin("exit code of subprocess; should be %d", MAGIC_STATUS);
if (WIFSIGNALED(status)) {
report_warnx("signal %d", WTERMSIG(status));
}
else {
report_warnx("exit %d", WEXITSTATUS(status));
}
report_failure();
return -1;
rv = waitpid(pid, &status, 0);
if (rv == -1) {
err = errno;
report_begin("waiting for test subprocess");
report_result(rv, err);
report_failure();
return -1;
}
if (WIFEXITED(status) && WEXITSTATUS(status) == MAGIC_STATUS) {
return 1;
}
/* Oops... */
report_begin("exit code of subprocess; should be %d", MAGIC_STATUS);
if (WIFSIGNALED(status)) {
report_warnx("signal %d", WTERMSIG(status));
} else {
report_warnx("exit %d", WEXITSTATUS(status));
}
report_failure();
return -1;
}
static
void
exec_badprog(const void *prog, const char *desc)
{
int rv;
char *args[2];
args[0] = (char *)"foo";
args[1] = NULL;
static void exec_badprog(const void *prog, const char *desc) {
int rv;
char *args[2];
args[0] = (char *)"foo";
args[1] = NULL;
if (exec_common_fork() != 0) {
return;
}
if (exec_common_fork() != 0) {
return;
}
report_begin(desc);
rv = execv(prog, args);
report_check(rv, errno, EFAULT);
exit(MAGIC_STATUS);
report_begin(desc);
rv = execv(prog, args);
report_check(rv, errno, EFAULT);
exit(MAGIC_STATUS);
}
static
void
exec_emptyprog(void)
{
int rv;
char *args[2];
args[0] = (char *)"foo";
args[1] = NULL;
static void exec_emptyprog(void) {
int rv;
char *args[2];
args[0] = (char *)"foo";
args[1] = NULL;
if (exec_common_fork() != 0) {
return;
}
if (exec_common_fork() != 0) {
return;
}
report_begin("exec the empty string");
rv = execv("", args);
report_check2(rv, errno, EINVAL, EISDIR);
exit(MAGIC_STATUS);
report_begin("exec the empty string");
rv = execv("", args);
report_check2(rv, errno, EINVAL, EISDIR);
exit(MAGIC_STATUS);
}
static
void
exec_badargs(void *args, const char *desc)
{
int rv;
static void exec_badargs(void *args, const char *desc) {
int rv;
if (exec_common_fork() != 0) {
return;
}
if (exec_common_fork() != 0) {
return;
}
report_begin(desc);
rv = execv("/bin/true", args);
report_check(rv, errno, EFAULT);
exit(MAGIC_STATUS);
report_begin(desc);
rv = execv("/bin/true", args);
report_check(rv, errno, EFAULT);
exit(MAGIC_STATUS);
}
static
void
exec_onearg(void *ptr, const char *desc)
{
int rv;
static void exec_onearg(void *ptr, const char *desc) {
int rv;
char *args[3];
args[0] = (char *)"foo";
args[1] = (char *)ptr;
args[2] = NULL;
char *args[3];
args[0] = (char *)"foo";
args[1] = (char *)ptr;
args[2] = NULL;
if (exec_common_fork() != 0) {
return;
}
if (exec_common_fork() != 0) {
return;
}
report_begin(desc);
rv = execv("/bin/true", args);
report_check(rv, errno, EFAULT);
exit(MAGIC_STATUS);
report_begin(desc);
rv = execv("/bin/true", args);
report_check(rv, errno, EFAULT);
exit(MAGIC_STATUS);
}
void
test_execv(void)
{
exec_badprog(NULL, "exec with NULL program");
exec_badprog(INVAL_PTR, "exec with invalid pointer program");
exec_badprog(KERN_PTR, "exec with kernel pointer program");
void test_execv(void) {
exec_badprog(NULL, "exec with NULL program");
exec_badprog(INVAL_PTR, "exec with invalid pointer program");
exec_badprog(KERN_PTR, "exec with kernel pointer program");
exec_emptyprog();
exec_emptyprog();
exec_badargs(NULL, "exec with NULL arglist");
exec_badargs(INVAL_PTR, "exec with invalid pointer arglist");
exec_badargs(KERN_PTR, "exec with kernel pointer arglist");
exec_badargs(NULL, "exec with NULL arglist");
exec_badargs(INVAL_PTR, "exec with invalid pointer arglist");
exec_badargs(KERN_PTR, "exec with kernel pointer arglist");
exec_onearg(INVAL_PTR, "exec with invalid pointer arg");
exec_onearg(KERN_PTR, "exec with kernel pointer arg");
exec_onearg(INVAL_PTR, "exec with invalid pointer arg");
exec_onearg(KERN_PTR, "exec with kernel pointer arg");
}

View File

@@ -33,9 +33,4 @@
#include "test.h"
void
test_fsync(void)
{
test_fsync_fd();
}
void test_fsync(void) { test_fsync_fd(); }

View File

@@ -43,53 +43,45 @@
#include "config.h"
#include "test.h"
static
void
ftruncate_fd_device(void)
{
int rv, fd;
static void ftruncate_fd_device(void) {
int rv, fd;
report_begin("ftruncate on device");
report_begin("ftruncate on device");
fd = open("null:", O_RDWR);
if (fd<0) {
report_warn("opening null: failed");
report_aborted();
return;
}
fd = open("null:", O_RDWR);
if (fd < 0) {
report_warn("opening null: failed");
report_aborted();
return;
}
rv = ftruncate(fd, 6);
report_check(rv, errno, EINVAL);
rv = ftruncate(fd, 6);
report_check(rv, errno, EINVAL);
close(fd);
close(fd);
}
static
void
ftruncate_size_neg(void)
{
int rv, fd;
static void ftruncate_size_neg(void) {
int rv, fd;
report_begin("ftruncate to negative size");
report_begin("ftruncate to negative size");
fd = open_testfile(NULL);
if (fd<0) {
report_aborted();
return;
}
fd = open_testfile(NULL);
if (fd < 0) {
report_aborted();
return;
}
rv = ftruncate(fd, -60);
report_check(rv, errno, EINVAL);
rv = ftruncate(fd, -60);
report_check(rv, errno, EINVAL);
close(fd);
remove(TESTFILE);
close(fd);
remove(TESTFILE);
}
void
test_ftruncate(void)
{
test_ftruncate_fd();
void test_ftruncate(void) {
test_ftruncate_fd();
ftruncate_fd_device();
ftruncate_size_neg();
ftruncate_fd_device();
ftruncate_size_neg();
}

View File

@@ -33,8 +33,4 @@
#include "test.h"
void
test_getcwd(void)
{
test_getcwd_buf();
}
void test_getcwd(void) { test_getcwd_buf(); }

View File

@@ -33,9 +33,7 @@
#include "test.h"
void
test_getdirentry(void)
{
test_getdirentry_fd();
test_getdirentry_buf();
void test_getdirentry(void) {
test_getdirentry_fd();
test_getdirentry_buf();
}

View File

@@ -40,64 +40,49 @@
#include "config.h"
#include "test.h"
static
void
one_ioctl_badbuf(int fd, int code, const char *codename,
void *ptr, const char *ptrdesc)
{
int rv;
static void one_ioctl_badbuf(int fd, int code, const char *codename, void *ptr,
const char *ptrdesc) {
int rv;
report_begin("ioctl %s with %s", codename, ptrdesc);
rv = ioctl(fd, code, ptr);
report_check(rv, errno, EFAULT);
report_begin("ioctl %s with %s", codename, ptrdesc);
rv = ioctl(fd, code, ptr);
report_check(rv, errno, EFAULT);
}
static
void
any_ioctl_badbuf(int fd, int code, const char *codename)
{
one_ioctl_badbuf(fd, code, codename, NULL, "NULL pointer");
one_ioctl_badbuf(fd, code, codename, INVAL_PTR, "invalid pointer");
one_ioctl_badbuf(fd, code, codename, KERN_PTR, "kernel pointer");
static void any_ioctl_badbuf(int fd, int code, const char *codename) {
one_ioctl_badbuf(fd, code, codename, NULL, "NULL pointer");
one_ioctl_badbuf(fd, code, codename, INVAL_PTR, "invalid pointer");
one_ioctl_badbuf(fd, code, codename, KERN_PTR, "kernel pointer");
}
#define IOCTL(fd, sym) any_ioctl_badbuf(fd, sym, #sym)
static
void
ioctl_badbuf(void)
{
/*
* Since we don't actually define any ioctls, this code won't
* actually run. But if you do define ioctls, turn these tests
* on for those that actually use the data buffer argument for
* anything.
*/
static void ioctl_badbuf(void) {
/*
* Since we don't actually define any ioctls, this code won't
* actually run. But if you do define ioctls, turn these tests
* on for those that actually use the data buffer argument for
* anything.
*/
/* IOCTL(STDIN_FILENO, TIOCGETA); */
/* IOCTL(STDIN_FILENO, TIOCGETA); */
/* suppress gcc warning */
(void)any_ioctl_badbuf;
/* suppress gcc warning */
(void)any_ioctl_badbuf;
}
static
void
ioctl_badcode(void)
{
int rv;
static void ioctl_badcode(void) {
int rv;
report_begin("invalid ioctl");
rv = ioctl(STDIN_FILENO, NONEXIST_IOCTL, NULL);
report_check(rv, errno, EIOCTL);
report_begin("invalid ioctl");
rv = ioctl(STDIN_FILENO, NONEXIST_IOCTL, NULL);
report_check(rv, errno, EIOCTL);
}
void
test_ioctl(void)
{
test_ioctl_fd();
void test_ioctl(void) {
test_ioctl_fd();
/* Since we don't actually define any ioctls, this is not meaningful */
ioctl_badcode();
ioctl_badbuf();
/* Since we don't actually define any ioctls, this is not meaningful */
ioctl_badcode();
ioctl_badbuf();
}

View File

@@ -36,53 +36,42 @@
#include "test.h"
static
void
link_dir(void)
{
int rv;
static void link_dir(void) {
int rv;
report_begin("hard link of .");
rv = link(".", TESTDIR);
report_check(rv, errno, EINVAL);
if (rv==0) {
/* this might help recover... maybe */
remove(TESTDIR);
}
report_begin("hard link of .");
rv = link(".", TESTDIR);
report_check(rv, errno, EINVAL);
if (rv == 0) {
/* this might help recover... maybe */
remove(TESTDIR);
}
}
static
void
link_empty1(void)
{
int rv;
static void link_empty1(void) {
int rv;
report_begin("hard link of empty string");
rv = link("", TESTDIR);
report_check(rv, errno, EINVAL);
report_begin("hard link of empty string");
rv = link("", TESTDIR);
report_check(rv, errno, EINVAL);
}
static
void
link_empty2(void)
{
int rv;
static void link_empty2(void) {
int rv;
report_begin("hard link to empty string");
if (create_testdir()<0) {
/*report_aborted();*/ /* XXX in create_testdir */
return;
}
rv = link(TESTDIR, "");
report_check(rv, errno, EINVAL);
rmdir(TESTDIR);
report_begin("hard link to empty string");
if (create_testdir() < 0) {
/*report_aborted();*/ /* XXX in create_testdir */
return;
}
rv = link(TESTDIR, "");
report_check(rv, errno, EINVAL);
rmdir(TESTDIR);
}
void
test_link(void)
{
test_link_paths();
link_dir();
link_empty1();
link_empty2();
void test_link(void) {
test_link_paths();
link_dir();
link_empty1();
link_empty2();
}

View File

@@ -43,236 +43,213 @@
#include "config.h"
#include "test.h"
static
void
lseek_fd_device(void)
{
int fd, rv;
static void lseek_fd_device(void) {
int fd, rv;
report_begin("lseek on device");
report_begin("lseek on device");
fd = open("null:", O_RDONLY);
if (fd<0) {
report_warn("opening null: failed");
report_aborted();
return;
}
fd = open("null:", O_RDONLY);
if (fd < 0) {
report_warn("opening null: failed");
report_aborted();
return;
}
rv = lseek(fd, 309, SEEK_SET);
report_check(rv, errno, ESPIPE);
rv = lseek(fd, 309, SEEK_SET);
report_check(rv, errno, ESPIPE);
close(fd);
close(fd);
}
static
void
lseek_file_stdin(void)
{
int fd, fd2, rv, status;
const char slogan[] = "There ain't no such thing as a free lunch";
size_t len = strlen(slogan);
pid_t pid;
static void lseek_file_stdin(void) {
int fd, fd2, rv, status;
const char slogan[] = "There ain't no such thing as a free lunch";
size_t len = strlen(slogan);
pid_t pid;
report_begin("lseek stdin when open on file");
report_begin("lseek stdin when open on file");
/* fork so we don't affect our own stdin */
pid = fork();
if (pid<0) {
report_warn("fork failed");
report_aborted();
return;
}
else if (pid!=0) {
/* parent */
rv = waitpid(pid, &status, 0);
if (rv<0) {
report_warn("waitpid failed");
report_aborted();
}
if (WIFSIGNALED(status)) {
report_warnx("subprocess exited with signal %d",
WTERMSIG(status));
report_aborted();
}
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
report_warnx("subprocess exited with code %d",
WEXITSTATUS(status));
report_aborted();
}
return;
}
/* fork so we don't affect our own stdin */
pid = fork();
if (pid < 0) {
report_warn("fork failed");
report_aborted();
return;
} else if (pid != 0) {
/* parent */
rv = waitpid(pid, &status, 0);
if (rv < 0) {
report_warn("waitpid failed");
report_aborted();
}
if (WIFSIGNALED(status)) {
report_warnx("subprocess exited with signal %d", WTERMSIG(status));
report_aborted();
} else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
report_warnx("subprocess exited with code %d", WEXITSTATUS(status));
report_aborted();
}
return;
}
/* child */
/* child */
fd = open_testfile(NULL);
if (fd<0) {
_exit(0);
}
fd = open_testfile(NULL);
if (fd < 0) {
_exit(0);
}
/*
* Move file to stdin.
* Use stdin (rather than stdout or stderr) to maximize the
* chances of detecting any special-case handling of fds 0-2.
* (Writing to stdin is fine as long as it's open for write,
* and it will be.)
*/
fd2 = dup2(fd, STDIN_FILENO);
if (fd2<0) {
report_warn("dup2 to stdin failed");
close(fd);
remove(TESTFILE);
_exit(1);
}
if (fd2 != STDIN_FILENO) {
report_warn("dup2 returned wrong file handle");
close(fd);
remove(TESTFILE);
_exit(1);
}
close(fd);
/*
* Move file to stdin.
* Use stdin (rather than stdout or stderr) to maximize the
* chances of detecting any special-case handling of fds 0-2.
* (Writing to stdin is fine as long as it's open for write,
* and it will be.)
*/
fd2 = dup2(fd, STDIN_FILENO);
if (fd2 < 0) {
report_warn("dup2 to stdin failed");
close(fd);
remove(TESTFILE);
_exit(1);
}
if (fd2 != STDIN_FILENO) {
report_warn("dup2 returned wrong file handle");
close(fd);
remove(TESTFILE);
_exit(1);
}
close(fd);
rv = write(STDIN_FILENO, slogan, len);
if (rv<0) {
report_warn("write to %s (via stdin) failed", TESTFILE);
remove(TESTFILE);
_exit(1);
}
rv = write(STDIN_FILENO, slogan, len);
if (rv < 0) {
report_warn("write to %s (via stdin) failed", TESTFILE);
remove(TESTFILE);
_exit(1);
}
if ((unsigned)rv != len) {
report_warnx("write to %s (via stdin) got short count",
TESTFILE);
remove(TESTFILE);
_exit(1);
}
if ((unsigned)rv != len) {
report_warnx("write to %s (via stdin) got short count", TESTFILE);
remove(TESTFILE);
_exit(1);
}
/* blah */
report_skipped();
/* blah */
report_skipped();
rv = lseek(STDIN_FILENO, 0, SEEK_SET);
report_begin("try 1: SEEK_SET");
report_check(rv, errno, 0);
rv = lseek(STDIN_FILENO, 0, SEEK_SET);
report_begin("try 1: SEEK_SET");
report_check(rv, errno, 0);
rv = lseek(STDIN_FILENO, 0, SEEK_END);
report_begin("try 2: SEEK_END");
report_check(rv, errno, 0);
rv = lseek(STDIN_FILENO, 0, SEEK_END);
report_begin("try 2: SEEK_END");
report_check(rv, errno, 0);
remove(TESTFILE);
_exit(0);
remove(TESTFILE);
_exit(0);
}
static
void
lseek_loc_negative(void)
{
int fd, rv;
static void lseek_loc_negative(void) {
int fd, rv;
report_begin("lseek to negative offset");
report_begin("lseek to negative offset");
fd = open_testfile(NULL);
if (fd<0) {
report_aborted();
return;
}
fd = open_testfile(NULL);
if (fd < 0) {
report_aborted();
return;
}
rv = lseek(fd, -309, SEEK_SET);
report_check(rv, errno, EINVAL);
rv = lseek(fd, -309, SEEK_SET);
report_check(rv, errno, EINVAL);
close(fd);
remove(TESTFILE);
close(fd);
remove(TESTFILE);
}
static
void
lseek_whence_inval(void)
{
int fd, rv;
static void lseek_whence_inval(void) {
int fd, rv;
report_begin("lseek with invalid whence code");
report_begin("lseek with invalid whence code");
fd = open_testfile(NULL);
if (fd<0) {
report_aborted();
return;
}
fd = open_testfile(NULL);
if (fd < 0) {
report_aborted();
return;
}
rv = lseek(fd, 0, 3594);
report_check(rv, errno, EINVAL);
rv = lseek(fd, 0, 3594);
report_check(rv, errno, EINVAL);
close(fd);
remove(TESTFILE);
close(fd);
remove(TESTFILE);
}
static
void
lseek_loc_pasteof(void)
{
const char *message = "blahblah";
int fd;
off_t pos;
static void lseek_loc_pasteof(void) {
const char *message = "blahblah";
int fd;
off_t pos;
report_begin("seek past/to EOF");
report_begin("seek past/to EOF");
fd = open_testfile(message);
if (fd<0) {
report_aborted();
return;
}
fd = open_testfile(message);
if (fd < 0) {
report_aborted();
return;
}
pos = lseek(fd, 5340, SEEK_SET);
if (pos == -1) {
report_warn("lseek past EOF failed");
report_failure();
goto out;
}
if (pos != 5340) {
report_warnx("lseek to 5340 got offset %lld", (long long) pos);
report_failure();
goto out;
}
pos = lseek(fd, 5340, SEEK_SET);
if (pos == -1) {
report_warn("lseek past EOF failed");
report_failure();
goto out;
}
if (pos != 5340) {
report_warnx("lseek to 5340 got offset %lld", (long long)pos);
report_failure();
goto out;
}
pos = lseek(fd, -50, SEEK_CUR);
if (pos == -1) {
report_warn("small seek beyond EOF failed");
report_failure();
goto out;
}
if (pos != 5290) {
report_warnx("SEEK_CUR to 5290 got offset %lld",
(long long) pos);
report_failure();
goto out;
}
pos = lseek(fd, -50, SEEK_CUR);
if (pos == -1) {
report_warn("small seek beyond EOF failed");
report_failure();
goto out;
}
if (pos != 5290) {
report_warnx("SEEK_CUR to 5290 got offset %lld", (long long)pos);
report_failure();
goto out;
}
pos = lseek(fd, 0, SEEK_END);
if (pos == -1) {
report_warn("seek to EOF failed");
report_failure();
goto out;
}
pos = lseek(fd, 0, SEEK_END);
if (pos == -1) {
report_warn("seek to EOF failed");
report_failure();
goto out;
}
if (pos != (off_t) strlen(message)) {
report_warnx("seek to EOF got %lld (should be %zu)",
(long long) pos, strlen(message));
report_failure();
goto out;
}
if (pos != (off_t)strlen(message)) {
report_warnx("seek to EOF got %lld (should be %zu)", (long long)pos,
strlen(message));
report_failure();
goto out;
}
report_passed();
report_passed();
out:
close(fd);
remove(TESTFILE);
return;
out:
close(fd);
remove(TESTFILE);
return;
}
void
test_lseek(void)
{
test_lseek_fd();
void test_lseek(void) {
test_lseek_fd();
lseek_fd_device();
lseek_file_stdin();
lseek_loc_negative();
lseek_loc_pasteof();
lseek_whence_inval();
lseek_fd_device();
lseek_file_stdin();
lseek_loc_negative();
lseek_loc_pasteof();
lseek_whence_inval();
}

View File

@@ -43,45 +43,34 @@
#include "config.h"
#include "test.h"
static
void
mkdir_dot(void)
{
int rv;
static void mkdir_dot(void) {
int rv;
report_begin("mkdir .");
rv = mkdir(".", 0775);
report_check(rv, errno, EEXIST);
report_begin("mkdir .");
rv = mkdir(".", 0775);
report_check(rv, errno, EEXIST);
}
static
void
mkdir_dotdot(void)
{
int rv;
static void mkdir_dotdot(void) {
int rv;
report_begin("mkdir ..");
rv = mkdir("..", 0775);
report_check(rv, errno, EEXIST);
report_begin("mkdir ..");
rv = mkdir("..", 0775);
report_check(rv, errno, EEXIST);
}
static
void
mkdir_empty(void)
{
int rv;
static void mkdir_empty(void) {
int rv;
report_begin("mkdir of empty string");
rv = mkdir("", 0775);
report_check(rv, errno, EINVAL);
report_begin("mkdir of empty string");
rv = mkdir("", 0775);
report_check(rv, errno, EINVAL);
}
void
test_mkdir(void)
{
test_mkdir_path();
void test_mkdir(void) {
test_mkdir_path();
mkdir_dot();
mkdir_dotdot();
mkdir_empty();
mkdir_dot();
mkdir_dotdot();
mkdir_empty();
}

View File

@@ -43,36 +43,28 @@
#include "config.h"
#include "test.h"
static
void
open_badflags(void)
{
int fd;
static void open_badflags(void) {
int fd;
report_begin("open null: with bad flags");
fd = open("null:", 309842);
report_check(fd, errno, EINVAL);
report_begin("open null: with bad flags");
fd = open("null:", 309842);
report_check(fd, errno, EINVAL);
}
static
void
open_empty(void)
{
int rv;
static void open_empty(void) {
int rv;
report_begin("open empty string");
rv = open("", O_RDONLY);
report_check(rv, errno, EINVAL);
if (rv>=0) {
close(rv);
}
report_begin("open empty string");
rv = open("", O_RDONLY);
report_check(rv, errno, EINVAL);
if (rv >= 0) {
close(rv);
}
}
void
test_open(void)
{
test_open_path();
void test_open(void) {
test_open_path();
open_badflags();
open_empty();
open_badflags();
open_empty();
}

View File

@@ -43,44 +43,36 @@
#include "config.h"
#include "test.h"
static
void
pipe_badptr(void *ptr, const char *desc)
{
int rv;
static void pipe_badptr(void *ptr, const char *desc) {
int rv;
report_begin("%s", desc);
rv = pipe(ptr);
report_check(rv, errno, EFAULT);
report_begin("%s", desc);
rv = pipe(ptr);
report_check(rv, errno, EFAULT);
}
static
void
pipe_unaligned(void)
{
int fds[3], rv;
char *ptr;
static void pipe_unaligned(void) {
int fds[3], rv;
char *ptr;
report_begin("pipe with unaligned pointer");
report_begin("pipe with unaligned pointer");
ptr = (char *)&fds[0];
ptr++;
ptr = (char *)&fds[0];
ptr++;
rv = pipe((int *)ptr);
report_survival(rv, errno);
if (rv == 0) {
memmove(fds, ptr, 2*sizeof(int));
close(fds[0]);
close(fds[1]);
}
rv = pipe((int *)ptr);
report_survival(rv, errno);
if (rv == 0) {
memmove(fds, ptr, 2 * sizeof(int));
close(fds[0]);
close(fds[1]);
}
}
void
test_pipe(void)
{
pipe_badptr(NULL, "pipe with NULL pointer");
pipe_badptr(INVAL_PTR, "pipe with invalid pointer");
pipe_badptr(KERN_PTR, "pipe with kernel pointer");
void test_pipe(void) {
pipe_badptr(NULL, "pipe with NULL pointer");
pipe_badptr(INVAL_PTR, "pipe with invalid pointer");
pipe_badptr(KERN_PTR, "pipe with kernel pointer");
pipe_unaligned();
pipe_unaligned();
}

View File

@@ -33,10 +33,7 @@
#include "test.h"
void
test_read(void)
{
test_read_fd();
test_read_buf();
void test_read(void) {
test_read_fd();
test_read_buf();
}

View File

@@ -36,57 +36,45 @@
#include "test.h"
static
void
readlink_file(void)
{
char buf[128];
int fd, rv;
static void readlink_file(void) {
char buf[128];
int fd, rv;
report_begin("readlink on file");
fd = open_testfile("the question contains an invalid assumption");
if (fd<0) {
report_aborted();
return;
}
close(fd);
rv = readlink(TESTFILE, buf, sizeof(buf));
report_check(rv, errno, EINVAL);
remove(TESTFILE);
report_begin("readlink on file");
fd = open_testfile("the question contains an invalid assumption");
if (fd < 0) {
report_aborted();
return;
}
close(fd);
rv = readlink(TESTFILE, buf, sizeof(buf));
report_check(rv, errno, EINVAL);
remove(TESTFILE);
}
static
void
readlink_dir(void)
{
char buf[128];
int rv;
static void readlink_dir(void) {
char buf[128];
int rv;
report_begin("readlink on .");
rv = readlink(".", buf, sizeof(buf));
report_check(rv, errno, EISDIR);
report_begin("readlink on .");
rv = readlink(".", buf, sizeof(buf));
report_check(rv, errno, EISDIR);
}
static
void
readlink_empty(void)
{
char buf[128];
int rv;
static void readlink_empty(void) {
char buf[128];
int rv;
report_begin("readlink on empty string");
rv = readlink("", buf, sizeof(buf));
report_check2(rv, errno, EISDIR, EINVAL);
report_begin("readlink on empty string");
rv = readlink("", buf, sizeof(buf));
report_check2(rv, errno, EISDIR, EINVAL);
}
void
test_readlink(void)
{
test_readlink_path();
test_readlink_buf();
void test_readlink(void) {
test_readlink_path();
test_readlink_buf();
readlink_file();
readlink_dir();
readlink_empty();
readlink_file();
readlink_dir();
readlink_empty();
}

View File

@@ -43,20 +43,13 @@
#include "config.h"
#include "test.h"
static
void
reboot_badflags(void)
{
int rv;
static void reboot_badflags(void) {
int rv;
printf("(This should not kill the system...)\n");
report_begin("reboot with invalid flags");
rv = reboot(15353);
report_check(rv, errno, EINVAL);
printf("(This should not kill the system...)\n");
report_begin("reboot with invalid flags");
rv = reboot(15353);
report_check(rv, errno, EINVAL);
}
void
test_reboot(void)
{
reboot_badflags();
}
void test_reboot(void) { reboot_badflags(); }

View File

@@ -43,64 +43,50 @@
#include "config.h"
#include "test.h"
static
void
remove_dir(void)
{
int rv;
static void remove_dir(void) {
int rv;
report_begin("remove() on a directory");
report_begin("remove() on a directory");
if (create_testdir() < 0) {
/*report_aborted();*/ /* XXX in create_testdir */
return;
}
if (create_testdir() < 0) {
/*report_aborted();*/ /* XXX in create_testdir */
return;
}
rv = remove(TESTDIR);
report_check(rv, errno, EISDIR);
rmdir(TESTDIR);
rv = remove(TESTDIR);
report_check(rv, errno, EISDIR);
rmdir(TESTDIR);
}
static
void
remove_dot(void)
{
int rv;
static void remove_dot(void) {
int rv;
report_begin("remove() on .");
rv = remove(".");
report_check2(rv, errno, EISDIR, EINVAL);
report_begin("remove() on .");
rv = remove(".");
report_check2(rv, errno, EISDIR, EINVAL);
}
static
void
remove_dotdot(void)
{
int rv;
static void remove_dotdot(void) {
int rv;
report_begin("remove() on ..");
rv = remove("..");
report_check2(rv, errno, EISDIR, EINVAL);
report_begin("remove() on ..");
rv = remove("..");
report_check2(rv, errno, EISDIR, EINVAL);
}
static
void
remove_empty(void)
{
int rv;
static void remove_empty(void) {
int rv;
report_begin("remove() on empty string");
rv = remove("");
report_check2(rv, errno, EISDIR, EINVAL);
report_begin("remove() on empty string");
rv = remove("");
report_check2(rv, errno, EISDIR, EINVAL);
}
void
test_remove(void)
{
test_remove_path();
void test_remove(void) {
test_remove_path();
remove_dir();
remove_dot();
remove_dotdot();
remove_empty();
remove_dir();
remove_dot();
remove_dotdot();
remove_empty();
}

View File

@@ -36,76 +36,61 @@
#include "test.h"
static
void
rename_dot(void)
{
int rv;
static void rename_dot(void) {
int rv;
report_begin("rename .");
report_begin("rename .");
rv = rename(".", TESTDIR);
report_check(rv, errno, EINVAL);
if (rv==0) {
/* oops... put it back */
rename(TESTDIR, ".");
}
rv = rename(".", TESTDIR);
report_check(rv, errno, EINVAL);
if (rv == 0) {
/* oops... put it back */
rename(TESTDIR, ".");
}
}
static
void
rename_dotdot(void)
{
int rv;
static void rename_dotdot(void) {
int rv;
report_begin("rename ..");
rv = rename("..", TESTDIR);
report_check(rv, errno, EINVAL);
if (rv==0) {
/* oops... put it back */
rename(TESTDIR, "..");
}
report_begin("rename ..");
rv = rename("..", TESTDIR);
report_check(rv, errno, EINVAL);
if (rv == 0) {
/* oops... put it back */
rename(TESTDIR, "..");
}
}
static
void
rename_empty1(void)
{
int rv;
static void rename_empty1(void) {
int rv;
report_begin("rename empty string");
rv = rename("", TESTDIR);
report_check2(rv, errno, EISDIR, EINVAL);
if (rv==0) {
/* don't try to remove it */
rename(TESTDIR, TESTDIR "-foo");
}
report_begin("rename empty string");
rv = rename("", TESTDIR);
report_check2(rv, errno, EISDIR, EINVAL);
if (rv == 0) {
/* don't try to remove it */
rename(TESTDIR, TESTDIR "-foo");
}
}
static
void
rename_empty2(void)
{
int rv;
static void rename_empty2(void) {
int rv;
report_begin("rename to empty string");
if (create_testdir()<0) {
/*report_aborted();*/ /* XXX in create_testdir */
return;
}
rv = rename(TESTDIR, "");
report_check2(rv, errno, EISDIR, EINVAL);
rmdir(TESTDIR);
report_begin("rename to empty string");
if (create_testdir() < 0) {
/*report_aborted();*/ /* XXX in create_testdir */
return;
}
rv = rename(TESTDIR, "");
report_check2(rv, errno, EISDIR, EINVAL);
rmdir(TESTDIR);
}
void
test_rename(void)
{
test_rename_paths();
void test_rename(void) {
test_rename_paths();
rename_dot();
rename_dotdot();
rename_empty1();
rename_empty2();
rename_dot();
rename_dotdot();
rename_empty1();
rename_empty2();
}

View File

@@ -43,62 +43,48 @@
#include "config.h"
#include "test.h"
static
void
rmdir_file(void)
{
int rv;
static void rmdir_file(void) {
int rv;
report_begin("rmdir a file");
if (create_testfile()<0) {
report_aborted();
return;
}
rv = rmdir(TESTFILE);
report_check(rv, errno, ENOTDIR);
remove(TESTFILE);
report_begin("rmdir a file");
if (create_testfile() < 0) {
report_aborted();
return;
}
rv = rmdir(TESTFILE);
report_check(rv, errno, ENOTDIR);
remove(TESTFILE);
}
static
void
rmdir_dot(void)
{
int rv;
static void rmdir_dot(void) {
int rv;
report_begin("rmdir .");
rv = rmdir(".");
report_check(rv, errno, EINVAL);
report_begin("rmdir .");
rv = rmdir(".");
report_check(rv, errno, EINVAL);
}
static
void
rmdir_dotdot(void)
{
int rv;
static void rmdir_dotdot(void) {
int rv;
report_begin("rmdir ..");
rv = rmdir("..");
report_check2(rv, errno, EINVAL, ENOTEMPTY);
report_begin("rmdir ..");
rv = rmdir("..");
report_check2(rv, errno, EINVAL, ENOTEMPTY);
}
static
void
rmdir_empty(void)
{
int rv;
static void rmdir_empty(void) {
int rv;
report_begin("rmdir empty string");
rv = rmdir("");
report_check(rv, errno, EINVAL);
report_begin("rmdir empty string");
rv = rmdir("");
report_check(rv, errno, EINVAL);
}
void
test_rmdir(void)
{
test_rmdir_path();
void test_rmdir(void) {
test_rmdir_path();
rmdir_file();
rmdir_dot();
rmdir_dotdot();
rmdir_empty();
rmdir_file();
rmdir_dot();
rmdir_dotdot();
rmdir_empty();
}

View File

@@ -46,80 +46,56 @@
/*
* typing wrapper around sbrk
*/
static
int
try_sbrk(long val)
{
void *rv;
rv = sbrk(val);
if (rv==(void *)-1) {
return -1;
}
return 0;
static int try_sbrk(long val) {
void *rv;
rv = sbrk(val);
if (rv == (void *)-1) {
return -1;
}
return 0;
}
static
void
enforce_sbrk(long val, const char *desc, int err)
{
int result;
static void enforce_sbrk(long val, const char *desc, int err) {
int result;
report_begin("sbrk %s", desc);
report_begin("sbrk %s", desc);
result = try_sbrk(val);
report_check(result, errno, err);
result = try_sbrk(val);
report_check(result, errno, err);
}
static
void
sbrk_bigpos(void)
{
enforce_sbrk(4096*1024*256, "huge positive", ENOMEM);
static void sbrk_bigpos(void) {
enforce_sbrk(4096 * 1024 * 256, "huge positive", ENOMEM);
}
static
void
sbrk_bigneg(void)
{
enforce_sbrk(-4096*1024*256, "huge negative", EINVAL);
static void sbrk_bigneg(void) {
enforce_sbrk(-4096 * 1024 * 256, "huge negative", EINVAL);
}
static
void
sbrk_neg(void)
{
enforce_sbrk(-8192, "too-large negative", EINVAL);
static void sbrk_neg(void) {
enforce_sbrk(-8192, "too-large negative", EINVAL);
}
static
void
sbrk_unalignedpos(void)
{
int result;
static void sbrk_unalignedpos(void) {
int result;
report_begin("sbrk unaligned positive");
result = try_sbrk(17);
report_check2(result, errno, 0, EINVAL);
report_begin("sbrk unaligned positive");
result = try_sbrk(17);
report_check2(result, errno, 0, EINVAL);
}
static
void
sbrk_unalignedneg(void)
{
int result;
static void sbrk_unalignedneg(void) {
int result;
report_begin("sbrk unaligned negative");
result = try_sbrk(-17);
report_check2(result, errno, 0, EINVAL);
report_begin("sbrk unaligned negative");
result = try_sbrk(-17);
report_check2(result, errno, 0, EINVAL);
}
void
test_sbrk(void)
{
sbrk_neg();
sbrk_bigpos();
sbrk_bigneg();
sbrk_unalignedpos();
sbrk_unalignedneg();
void test_sbrk(void) {
sbrk_neg();
sbrk_bigpos();
sbrk_bigneg();
sbrk_unalignedpos();
sbrk_unalignedneg();
}

View File

@@ -45,84 +45,54 @@
////////////////////////////////////////////////////////////
static
int
badbuf_fstat(struct stat *sb)
{
return fstat(STDIN_FILENO, sb);
static int badbuf_fstat(struct stat *sb) { return fstat(STDIN_FILENO, sb); }
static int badbuf_lstat(struct stat *sb) { return lstat("null:", sb); }
static int badbuf_stat(struct stat *sb) { return stat("null:", sb); }
static void common_badbuf(int (*statfunc)(struct stat *), void *ptr,
const char *call, const char *ptrdesc) {
int rv;
report_begin("%s with %s buf", call, ptrdesc);
rv = statfunc(ptr);
report_check(rv, errno, EFAULT);
}
static
int
badbuf_lstat(struct stat *sb)
{
return lstat("null:", sb);
}
static
int
badbuf_stat(struct stat *sb)
{
return stat("null:", sb);
}
static
void
common_badbuf(int (*statfunc)(struct stat *), void *ptr,
const char *call, const char *ptrdesc)
{
int rv;
report_begin("%s with %s buf", call, ptrdesc);
rv = statfunc(ptr);
report_check(rv, errno, EFAULT);
}
static
void
any_badbuf(int (*statfunc)(struct stat *), const char *call)
{
common_badbuf(statfunc, NULL, call, "NULL");
common_badbuf(statfunc, INVAL_PTR, call, "invalid pointer");
common_badbuf(statfunc, KERN_PTR, call, "kernel pointer");
static void any_badbuf(int (*statfunc)(struct stat *), const char *call) {
common_badbuf(statfunc, NULL, call, "NULL");
common_badbuf(statfunc, INVAL_PTR, call, "invalid pointer");
common_badbuf(statfunc, KERN_PTR, call, "kernel pointer");
}
////////////////////////////////////////////////////////////
static
void
any_empty(int (*statfunc)(const char *, struct stat *), const char *call)
{
struct stat sb;
int rv;
static void any_empty(int (*statfunc)(const char *, struct stat *),
const char *call) {
struct stat sb;
int rv;
report_begin("%s on empty string", call);
rv = statfunc("", &sb);
report_check2(rv, errno, 0, EINVAL);
report_begin("%s on empty string", call);
rv = statfunc("", &sb);
report_check2(rv, errno, 0, EINVAL);
}
////////////////////////////////////////////////////////////
void
test_fstat(void)
{
test_fstat_fd();
any_badbuf(badbuf_fstat, "fstat");
void test_fstat(void) {
test_fstat_fd();
any_badbuf(badbuf_fstat, "fstat");
}
void
test_lstat(void)
{
test_lstat_path();
any_empty(lstat, "lstat");
any_badbuf(badbuf_lstat, "lstat");
void test_lstat(void) {
test_lstat_path();
any_empty(lstat, "lstat");
any_badbuf(badbuf_lstat, "lstat");
}
void
test_stat(void)
{
test_stat_path();
any_empty(stat, "stat");
any_badbuf(badbuf_stat, "stat");
void test_stat(void) {
test_stat_path();
any_empty(stat, "stat");
any_badbuf(badbuf_stat, "stat");
}

View File

@@ -36,33 +36,25 @@
#include "test.h"
static
void
symlink_empty1(void)
{
int rv;
static void symlink_empty1(void) {
int rv;
report_begin("symlink -> empty string");
rv = symlink("", TESTLINK);
report_check2(rv, errno, 0, EINVAL);
remove(TESTLINK);
report_begin("symlink -> empty string");
rv = symlink("", TESTLINK);
report_check2(rv, errno, 0, EINVAL);
remove(TESTLINK);
}
static
void
symlink_empty2(void)
{
int rv;
static void symlink_empty2(void) {
int rv;
report_begin("symlink named empty string");
rv = symlink("foo", "");
report_check(rv, errno, EINVAL);
report_begin("symlink named empty string");
rv = symlink("foo", "");
report_check(rv, errno, EINVAL);
}
void
test_symlink(void)
{
test_symlink_paths();
symlink_empty1();
symlink_empty2();
void test_symlink(void) {
test_symlink_paths();
symlink_empty1();
symlink_empty2();
}

View File

@@ -43,34 +43,26 @@
#include "config.h"
#include "test.h"
static
void
time_badsecs(void *ptr, const char *desc)
{
int rv;
static void time_badsecs(void *ptr, const char *desc) {
int rv;
report_begin("%s", desc);
rv = __time(ptr, NULL);
report_check(rv, errno, EFAULT);
report_begin("%s", desc);
rv = __time(ptr, NULL);
report_check(rv, errno, EFAULT);
}
static
void
time_badnsecs(void *ptr, const char *desc)
{
int rv;
static void time_badnsecs(void *ptr, const char *desc) {
int rv;
report_begin("%s", desc);
rv = __time(NULL, ptr);
report_check(rv, errno, EFAULT);
report_begin("%s", desc);
rv = __time(NULL, ptr);
report_check(rv, errno, EFAULT);
}
void
test_time(void)
{
time_badsecs(INVAL_PTR, "__time with invalid seconds pointer");
time_badsecs(KERN_PTR, "__time with kernel seconds pointer");
void test_time(void) {
time_badsecs(INVAL_PTR, "__time with invalid seconds pointer");
time_badsecs(KERN_PTR, "__time with kernel seconds pointer");
time_badnsecs(INVAL_PTR, "__time with invalid nsecs pointer");
time_badnsecs(KERN_PTR, "__time with kernel nsecs pointer");
time_badnsecs(INVAL_PTR, "__time with invalid nsecs pointer");
time_badnsecs(KERN_PTR, "__time with kernel nsecs pointer");
}

View File

@@ -41,383 +41,344 @@
#include "config.h"
#include "test.h"
static
void
wait_badpid(pid_t pid, const char *desc)
{
pid_t rv;
int x;
int err;
static void wait_badpid(pid_t pid, const char *desc) {
pid_t rv;
int x;
int err;
report_begin(desc);
rv = waitpid(pid, &x, 0);
err = errno;
/* Allow ENOSYS for 0 or negative values of pid only */
if (pid <= 0 && rv == -1 && err == ENOSYS) {
err = ESRCH;
}
else if (err == ENOSYS) {
report_saw_enosys();
}
report_check2(rv, err, ESRCH, ECHILD);
report_begin(desc);
rv = waitpid(pid, &x, 0);
err = errno;
/* Allow ENOSYS for 0 or negative values of pid only */
if (pid <= 0 && rv == -1 && err == ENOSYS) {
err = ESRCH;
} else if (err == ENOSYS) {
report_saw_enosys();
}
report_check2(rv, err, ESRCH, ECHILD);
}
static
void
wait_nullstatus(void)
{
pid_t pid, rv;
int x;
static void wait_nullstatus(void) {
pid_t pid, rv;
int x;
report_begin("wait with NULL status");
report_begin("wait with NULL status");
pid = fork();
if (pid<0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid==0) {
exit(0);
}
pid = fork();
if (pid < 0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid == 0) {
exit(0);
}
/* POSIX explicitly says passing NULL for status is allowed */
rv = waitpid(pid, NULL, 0);
report_check(rv, errno, 0);
waitpid(pid, &x, 0);
/* POSIX explicitly says passing NULL for status is allowed */
rv = waitpid(pid, NULL, 0);
report_check(rv, errno, 0);
waitpid(pid, &x, 0);
}
static
void
wait_badstatus(void *ptr, const char *desc)
{
pid_t pid, rv;
int x;
static void wait_badstatus(void *ptr, const char *desc) {
pid_t pid, rv;
int x;
report_begin(desc);
report_begin(desc);
pid = fork();
if (pid<0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid==0) {
exit(0);
}
pid = fork();
if (pid < 0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid == 0) {
exit(0);
}
rv = waitpid(pid, ptr, 0);
report_check(rv, errno, EFAULT);
waitpid(pid, &x, 0);
rv = waitpid(pid, ptr, 0);
report_check(rv, errno, EFAULT);
waitpid(pid, &x, 0);
}
static
void
wait_unaligned(void)
{
pid_t pid, rv;
int x;
int status[2]; /* will have integer alignment */
char *ptr;
static void wait_unaligned(void) {
pid_t pid, rv;
int x;
int status[2]; /* will have integer alignment */
char *ptr;
report_begin("wait with unaligned status");
report_begin("wait with unaligned status");
pid = fork();
if (pid<0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid==0) {
exit(0);
}
pid = fork();
if (pid < 0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid == 0) {
exit(0);
}
/* start with proper integer alignment */
ptr = (char *)(&status[0]);
/* start with proper integer alignment */
ptr = (char *)(&status[0]);
/* generate improper alignment on platforms with restrictions */
ptr++;
/* generate improper alignment on platforms with restrictions */
ptr++;
rv = waitpid(pid, (int *)ptr, 0);
report_survival(rv, errno);
if (rv<0) {
waitpid(pid, &x, 0);
}
rv = waitpid(pid, (int *)ptr, 0);
report_survival(rv, errno);
if (rv < 0) {
waitpid(pid, &x, 0);
}
}
static
void
wait_badflags(void)
{
pid_t pid, rv;
int x;
static void wait_badflags(void) {
pid_t pid, rv;
int x;
report_begin("wait with bad flags");
report_begin("wait with bad flags");
pid = fork();
if (pid<0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid==0) {
exit(0);
}
pid = fork();
if (pid < 0) {
report_warn("fork failed");
report_aborted();
return;
}
if (pid == 0) {
exit(0);
}
rv = waitpid(pid, &x, 309429);
report_check(rv, errno, EINVAL);
waitpid(pid, &x, 0);
rv = waitpid(pid, &x, 309429);
report_check(rv, errno, EINVAL);
waitpid(pid, &x, 0);
}
static
void
wait_self(void)
{
pid_t rv;
int x;
static void wait_self(void) {
pid_t rv;
int x;
report_begin("wait for self");
report_begin("wait for self");
rv = waitpid(getpid(), &x, 0);
report_survival(rv, errno);
rv = waitpid(getpid(), &x, 0);
report_survival(rv, errno);
}
static
void
wait_parent(void)
{
pid_t mypid, childpid, rv;
int x;
static void wait_parent(void) {
pid_t mypid, childpid, rv;
int x;
report_begin("wait for parent");
report_hassubs();
report_begin("wait for parent");
report_hassubs();
mypid = getpid();
childpid = fork();
if (childpid<0) {
report_warn("can't fork");
report_aborted();
return;
}
if (childpid==0) {
/* Child. Wait for parent. */
rv = waitpid(mypid, &x, 0);
report_beginsub("from child:");
report_survival(rv, errno);
_exit(0);
}
rv = waitpid(childpid, &x, 0);
report_beginsub("from parent:");
report_survival(rv, errno);
mypid = getpid();
childpid = fork();
if (childpid < 0) {
report_warn("can't fork");
report_aborted();
return;
}
if (childpid == 0) {
/* Child. Wait for parent. */
rv = waitpid(mypid, &x, 0);
report_beginsub("from child:");
report_survival(rv, errno);
_exit(0);
}
rv = waitpid(childpid, &x, 0);
report_beginsub("from parent:");
report_survival(rv, errno);
}
////////////////////////////////////////////////////////////
static
void
wait_siblings_child(const char *semname)
{
pid_t pids[2], mypid, otherpid;
int rv, fd, semfd, x;
char c;
static void wait_siblings_child(const char *semname) {
pid_t pids[2], mypid, otherpid;
int rv, fd, semfd, x;
char c;
mypid = getpid();
mypid = getpid();
/*
* Get our own handle for the semaphore, in case naive
* file-level synchronization causes concurrent use to
* deadlock.
*/
semfd = open(semname, O_RDONLY);
if (semfd < 0) {
report_warn("child process (pid %d) can't open %s",
mypid, semname);
}
else {
if (read(semfd, &c, 1) < 0) {
report_warn("in pid %d: %s: read", mypid, semname);
}
close(semfd);
}
/*
* Get our own handle for the semaphore, in case naive
* file-level synchronization causes concurrent use to
* deadlock.
*/
semfd = open(semname, O_RDONLY);
if (semfd < 0) {
report_warn("child process (pid %d) can't open %s", mypid, semname);
} else {
if (read(semfd, &c, 1) < 0) {
report_warn("in pid %d: %s: read", mypid, semname);
}
close(semfd);
}
fd = open(TESTFILE, O_RDONLY);
if (fd<0) {
report_warn("child process (pid %d) can't open %s",
mypid, TESTFILE);
return;
}
fd = open(TESTFILE, O_RDONLY);
if (fd < 0) {
report_warn("child process (pid %d) can't open %s", mypid, TESTFILE);
return;
}
/*
* In case the semaphore above didn't work, as a backup
* busy-wait until the parent writes the pids into the
* file. If the semaphore did work, this shouldn't loop.
*/
do {
rv = lseek(fd, 0, SEEK_SET);
if (rv<0) {
report_warn("child process (pid %d) lseek error",
mypid);
return;
}
rv = read(fd, pids, sizeof(pids));
if (rv<0) {
report_warn("child process (pid %d) read error",
mypid);
return;
}
} while (rv < (int)sizeof(pids));
/*
* In case the semaphore above didn't work, as a backup
* busy-wait until the parent writes the pids into the
* file. If the semaphore did work, this shouldn't loop.
*/
do {
rv = lseek(fd, 0, SEEK_SET);
if (rv < 0) {
report_warn("child process (pid %d) lseek error", mypid);
return;
}
rv = read(fd, pids, sizeof(pids));
if (rv < 0) {
report_warn("child process (pid %d) read error", mypid);
return;
}
} while (rv < (int)sizeof(pids));
if (mypid==pids[0]) {
otherpid = pids[1];
}
else if (mypid==pids[1]) {
otherpid = pids[0];
}
else {
report_warn("child process (pid %d) got garbage in comm file",
mypid);
return;
}
close(fd);
if (mypid == pids[0]) {
otherpid = pids[1];
} else if (mypid == pids[1]) {
otherpid = pids[0];
} else {
report_warn("child process (pid %d) got garbage in comm file", mypid);
return;
}
close(fd);
rv = waitpid(otherpid, &x, 0);
report_beginsub("sibling (pid %d)", mypid);
report_survival(rv, errno);
rv = waitpid(otherpid, &x, 0);
report_beginsub("sibling (pid %d)", mypid);
report_survival(rv, errno);
}
static
void
wait_siblings(void)
{
pid_t pids[2];
int rv, fd, semfd, x;
int bad = 0;
char semname[32];
static void wait_siblings(void) {
pid_t pids[2];
int rv, fd, semfd, x;
int bad = 0;
char semname[32];
/* This test may also blow up if FS synchronization is substandard */
/* This test may also blow up if FS synchronization is substandard */
report_begin("siblings wait for each other");
report_hassubs();
report_begin("siblings wait for each other");
report_hassubs();
snprintf(semname, sizeof(semname), "sem:badcall.%d", (int)getpid());
semfd = open(semname, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (semfd < 0) {
report_warn("can't make semaphore");
report_aborted();
return;
}
snprintf(semname, sizeof(semname), "sem:badcall.%d", (int)getpid());
semfd = open(semname, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (semfd < 0) {
report_warn("can't make semaphore");
report_aborted();
return;
}
fd = open_testfile(NULL);
if (fd<0) {
report_aborted();
close(semfd);
remove(semname);
return;
}
fd = open_testfile(NULL);
if (fd < 0) {
report_aborted();
close(semfd);
remove(semname);
return;
}
pids[0] = fork();
if (pids[0]<0) {
report_warn("can't fork");
report_aborted();
close(fd);
close(semfd);
remove(semname);
return;
}
if (pids[0]==0) {
close(fd);
close(semfd);
wait_siblings_child(semname);
_exit(0);
}
pids[0] = fork();
if (pids[0] < 0) {
report_warn("can't fork");
report_aborted();
close(fd);
close(semfd);
remove(semname);
return;
}
if (pids[0] == 0) {
close(fd);
close(semfd);
wait_siblings_child(semname);
_exit(0);
}
pids[1] = fork();
if (pids[1]<0) {
report_warn("can't fork");
report_aborted();
/* abandon the other child process :( */
close(fd);
close(semfd);
remove(semname);
return;
}
if (pids[1]==0) {
close(fd);
close(semfd);
wait_siblings_child(semname);
_exit(0);
}
pids[1] = fork();
if (pids[1] < 0) {
report_warn("can't fork");
report_aborted();
/* abandon the other child process :( */
close(fd);
close(semfd);
remove(semname);
return;
}
if (pids[1] == 0) {
close(fd);
close(semfd);
wait_siblings_child(semname);
_exit(0);
}
rv = write(fd, pids, sizeof(pids));
if (rv < 0) {
report_warn("write error on %s", TESTFILE);
report_aborted();
/* abandon child procs :( */
close(fd);
close(semfd);
remove(semname);
return;
}
if (rv != (int)sizeof(pids)) {
report_warnx("write error on %s: short count", TESTFILE);
report_aborted();
/* abandon child procs :( */
close(fd);
close(semfd);
remove(semname);
return;
}
rv = write(fd, pids, sizeof(pids));
if (rv < 0) {
report_warn("write error on %s", TESTFILE);
report_aborted();
/* abandon child procs :( */
close(fd);
close(semfd);
remove(semname);
return;
}
if (rv != (int)sizeof(pids)) {
report_warnx("write error on %s: short count", TESTFILE);
report_aborted();
/* abandon child procs :( */
close(fd);
close(semfd);
remove(semname);
return;
}
/* gate the child procs */
rv = write(semfd, " ", 2);
if (rv < 0) {
report_warn("%s: write", semname);
bad = 1;
}
/* gate the child procs */
rv = write(semfd, " ", 2);
if (rv < 0) {
report_warn("%s: write", semname);
bad = 1;
}
report_beginsub("overall");
rv = waitpid(pids[0], &x, 0);
if (rv<0) {
report_warn("error waiting for child 0 (pid %d)", pids[0]);
bad = 1;
}
rv = waitpid(pids[1], &x, 0);
if (rv<0) {
report_warn("error waiting for child 1 (pid %d)", pids[1]);
bad = 1;
}
if (bad) {
/* XXX: aborted, or failure, or what? */
report_aborted();
}
else {
report_passed();
}
close(fd);
close(semfd);
remove(semname);
remove(TESTFILE);
report_beginsub("overall");
rv = waitpid(pids[0], &x, 0);
if (rv < 0) {
report_warn("error waiting for child 0 (pid %d)", pids[0]);
bad = 1;
}
rv = waitpid(pids[1], &x, 0);
if (rv < 0) {
report_warn("error waiting for child 1 (pid %d)", pids[1]);
bad = 1;
}
if (bad) {
/* XXX: aborted, or failure, or what? */
report_aborted();
} else {
report_passed();
}
close(fd);
close(semfd);
remove(semname);
remove(TESTFILE);
}
////////////////////////////////////////////////////////////
void
test_waitpid(void)
{
wait_badpid(-8, "wait for pid -8");
wait_badpid(-1, "wait for pid -1");
wait_badpid(0, "pid zero");
wait_badpid(NONEXIST_PID, "nonexistent pid");
void test_waitpid(void) {
wait_badpid(-8, "wait for pid -8");
wait_badpid(-1, "wait for pid -1");
wait_badpid(0, "pid zero");
wait_badpid(NONEXIST_PID, "nonexistent pid");
wait_nullstatus();
wait_badstatus(INVAL_PTR, "wait with invalid pointer status");
wait_badstatus(KERN_PTR, "wait with kernel pointer status");
wait_nullstatus();
wait_badstatus(INVAL_PTR, "wait with invalid pointer status");
wait_badstatus(KERN_PTR, "wait with kernel pointer status");
wait_unaligned();
wait_unaligned();
wait_badflags();
wait_badflags();
wait_self();
wait_parent();
wait_siblings();
wait_self();
wait_parent();
wait_siblings();
}

View File

@@ -33,9 +33,7 @@
#include "test.h"
void
test_write(void)
{
test_write_fd();
test_write_buf();
void test_write(void) {
test_write_fd();
test_write_buf();
}

View File

@@ -47,169 +47,108 @@
static int buf_fd;
struct buftest {
int (*setup)(void);
int (*op)(void *);
void (*cleanup)(void);
const char *name;
int (*setup)(void);
int (*op)(void *);
void (*cleanup)(void);
const char *name;
};
////////////////////////////////////////////////////////////
static
int
read_setup(void)
{
buf_fd = open_testfile("i do not like green eggs and ham");
if (buf_fd<0) {
return -1;
}
return 0;
static int read_setup(void) {
buf_fd = open_testfile("i do not like green eggs and ham");
if (buf_fd < 0) {
return -1;
}
return 0;
}
static
int
read_badbuf(void *buf)
{
return read(buf_fd, buf, 128);
}
static int read_badbuf(void *buf) { return read(buf_fd, buf, 128); }
static
void
read_cleanup(void)
{
close(buf_fd);
remove(TESTFILE);
static void read_cleanup(void) {
close(buf_fd);
remove(TESTFILE);
}
//////////
static
int
write_setup(void)
{
buf_fd = open_testfile(NULL);
if (buf_fd<0) {
return -1;
}
return 0;
static int write_setup(void) {
buf_fd = open_testfile(NULL);
if (buf_fd < 0) {
return -1;
}
return 0;
}
static
int
write_badbuf(void *ptr)
{
return write(buf_fd, ptr, 128);
}
static int write_badbuf(void *ptr) { return write(buf_fd, ptr, 128); }
static
void
write_cleanup(void)
{
close(buf_fd);
remove(TESTFILE);
static void write_cleanup(void) {
close(buf_fd);
remove(TESTFILE);
}
//////////
static
int
getdirentry_setup(void)
{
buf_fd = open(".", O_RDONLY);
if (buf_fd < 0) {
warn("UH-OH: couldn't open .");
return -1;
}
return 0;
static int getdirentry_setup(void) {
buf_fd = open(".", O_RDONLY);
if (buf_fd < 0) {
warn("UH-OH: couldn't open .");
return -1;
}
return 0;
}
static
int
getdirentry_badbuf(void *ptr)
{
return getdirentry(buf_fd, ptr, 1024);
static int getdirentry_badbuf(void *ptr) {
return getdirentry(buf_fd, ptr, 1024);
}
static
void
getdirentry_cleanup(void)
{
close(buf_fd);
}
static void getdirentry_cleanup(void) { close(buf_fd); }
//////////
static
int
readlink_setup(void)
{
return create_testlink();
}
static int readlink_setup(void) { return create_testlink(); }
static
int
readlink_badbuf(void *buf)
{
return readlink(TESTLINK, buf, 168);
}
static int readlink_badbuf(void *buf) { return readlink(TESTLINK, buf, 168); }
static
void
readlink_cleanup(void)
{
remove(TESTLINK);
}
static void readlink_cleanup(void) { remove(TESTLINK); }
//////////
static int getcwd_setup(void) { return 0; }
static void getcwd_cleanup(void) {}
static
int
getcwd_badbuf(void *buf)
{
return __getcwd(buf, 408);
static int getcwd_badbuf(void *buf) { return __getcwd(buf, 408); }
////////////////////////////////////////////////////////////
static void common_badbuf(struct buftest *info, void *buf,
const char *bufdesc) {
int rv;
report_begin("%s with %s buffer", info->name, bufdesc);
info->setup();
rv = info->op(buf);
report_check(rv, errno, EFAULT);
info->cleanup();
}
static void any_badbuf(struct buftest *info) {
common_badbuf(info, NULL, "NULL");
common_badbuf(info, INVAL_PTR, "invalid");
common_badbuf(info, KERN_PTR, "kernel-space");
}
////////////////////////////////////////////////////////////
static
void
common_badbuf(struct buftest *info, void *buf, const char *bufdesc)
{
int rv;
report_begin("%s with %s buffer", info->name, bufdesc);
info->setup();
rv = info->op(buf);
report_check(rv, errno, EFAULT);
info->cleanup();
}
static
void
any_badbuf(struct buftest *info)
{
common_badbuf(info, NULL, "NULL");
common_badbuf(info, INVAL_PTR, "invalid");
common_badbuf(info, KERN_PTR, "kernel-space");
}
////////////////////////////////////////////////////////////
#define T(call) \
void \
test_##call##_buf(void) \
{ \
static struct buftest info = { \
call##_setup, \
call##_badbuf, \
call##_cleanup, \
#call, \
}; \
any_badbuf(&info); \
#define T(call) \
void test_##call##_buf(void) { \
static struct buftest info = { \
call##_setup, \
call##_badbuf, \
call##_cleanup, \
#call, \
}; \
any_badbuf(&info); \
}
T(read);

View File

@@ -44,182 +44,119 @@
#include "config.h"
#include "test.h"
enum rwtestmodes {
RW_TEST_NONE,
RW_TEST_RDONLY,
RW_TEST_WRONLY,
RW_TEST_NONE,
RW_TEST_RDONLY,
RW_TEST_WRONLY,
};
static
int
read_badfd(int fd)
{
char buf[128];
return read(fd, buf, sizeof(buf));
static int read_badfd(int fd) {
char buf[128];
return read(fd, buf, sizeof(buf));
}
static
int
write_badfd(int fd)
{
char buf[128];
memset(buf, 'a', sizeof(buf));
return write(fd, buf, sizeof(buf));
static int write_badfd(int fd) {
char buf[128];
memset(buf, 'a', sizeof(buf));
return write(fd, buf, sizeof(buf));
}
static int close_badfd(int fd) { return close(fd); }
static
int
close_badfd(int fd)
{
return close(fd);
static int ioctl_badfd(int fd) { return ioctl(fd, 0, NULL); }
static int lseek_badfd(int fd) { return lseek(fd, 0, SEEK_SET); }
static int fsync_badfd(int fd) { return fsync(fd); }
static int ftruncate_badfd(int fd) { return ftruncate(fd, 60); }
static int fstat_badfd(int fd) {
struct stat sb;
return fstat(fd, &sb);
}
static
int
ioctl_badfd(int fd)
{
return ioctl(fd, 0, NULL);
static int getdirentry_badfd(int fd) {
char buf[32];
return getdirentry(fd, buf, sizeof(buf));
}
static
int
lseek_badfd(int fd)
{
return lseek(fd, 0, SEEK_SET);
static int dup2_badfd(int fd) {
/* use the +1 to avoid doing dup2(CLOSED_FD, CLOSED_FD) */
return dup2(fd, CLOSED_FD + 1);
}
static
int
fsync_badfd(int fd)
{
return fsync(fd);
}
static
int
ftruncate_badfd(int fd)
{
return ftruncate(fd, 60);
}
static
int
fstat_badfd(int fd)
{
struct stat sb;
return fstat(fd, &sb);
}
static
int
getdirentry_badfd(int fd)
{
char buf[32];
return getdirentry(fd, buf, sizeof(buf));
}
static
int
dup2_badfd(int fd)
{
/* use the +1 to avoid doing dup2(CLOSED_FD, CLOSED_FD) */
return dup2(fd, CLOSED_FD+1);
}
static
void
dup2_cleanup(void)
{
close(CLOSED_FD+1);
}
static void dup2_cleanup(void) { close(CLOSED_FD + 1); }
////////////////////////////////////////////////////////////
static
void
any_badfd(int (*func)(int fd), void (*cleanup)(void), const char *callname,
int fd, const char *fddesc)
{
int rv;
static void any_badfd(int (*func)(int fd), void (*cleanup)(void),
const char *callname, int fd, const char *fddesc) {
int rv;
report_begin("%s using %s", callname, fddesc);
rv = func(fd);
report_check(rv, errno, EBADF);
if (cleanup) {
cleanup();
}
report_begin("%s using %s", callname, fddesc);
rv = func(fd);
report_check(rv, errno, EBADF);
if (cleanup) {
cleanup();
}
}
static
void
runtest(int (*func)(int fd), void (*cleanup)(void), const char *callname,
enum rwtestmodes rw)
{
int fd;
static void runtest(int (*func)(int fd), void (*cleanup)(void),
const char *callname, enum rwtestmodes rw) {
int fd;
/*
* If adding cases, also see bad_dup2.c
*/
/*
* If adding cases, also see bad_dup2.c
*/
/* basic invalid case: fd -1 */
any_badfd(func, cleanup, callname, -1, "fd -1");
/* basic invalid case: fd -1 */
any_badfd(func, cleanup, callname, -1, "fd -1");
/* also try -5 in case -1 is special somehow */
any_badfd(func, cleanup, callname, -5, "fd -5");
/* also try -5 in case -1 is special somehow */
any_badfd(func, cleanup, callname, -5, "fd -5");
/* try a fd we know is closed */
any_badfd(func, cleanup, callname, CLOSED_FD, "closed fd");
/* try a fd we know is closed */
any_badfd(func, cleanup, callname, CLOSED_FD, "closed fd");
/* try a positive fd we know is out of range */
any_badfd(func, cleanup, callname, IMPOSSIBLE_FD, "impossible fd");
/* try a positive fd we know is out of range */
any_badfd(func, cleanup, callname, IMPOSSIBLE_FD, "impossible fd");
/* test for off-by-one errors */
/* test for off-by-one errors */
#ifdef OPEN_MAX
any_badfd(func, cleanup, callname, OPEN_MAX, "fd OPEN_MAX");
any_badfd(func, cleanup, callname, OPEN_MAX, "fd OPEN_MAX");
#else
warnx("Warning: OPEN_MAX not defined, test skipped");
warnx("Warning: OPEN_MAX not defined, test skipped");
#endif
if (rw == RW_TEST_RDONLY) {
fd = reopen_testfile(O_RDONLY|O_CREAT);
if (fd < 0) {
/* already printed a message */
}
else {
any_badfd(func, cleanup, callname, fd,
"fd opened read-only");
}
close(fd);
}
if (rw == RW_TEST_WRONLY) {
fd = reopen_testfile(O_WRONLY|O_CREAT);
if (fd < 0) {
/* already printed a message */
}
else {
any_badfd(func, cleanup, callname, fd,
"fd opened write-only");
}
close(fd);
}
if (rw == RW_TEST_RDONLY) {
fd = reopen_testfile(O_RDONLY | O_CREAT);
if (fd < 0) {
/* already printed a message */
} else {
any_badfd(func, cleanup, callname, fd, "fd opened read-only");
}
close(fd);
}
if (rw == RW_TEST_WRONLY) {
fd = reopen_testfile(O_WRONLY | O_CREAT);
if (fd < 0) {
/* already printed a message */
} else {
any_badfd(func, cleanup, callname, fd, "fd opened write-only");
}
close(fd);
}
}
////////////////////////////////////////////////////////////
#define T(call, rw) \
void \
test_##call##_fd(void) \
{ \
runtest(call##_badfd, NULL, #call, rw); \
}
#define T(call, rw) \
void test_##call##_fd(void) { runtest(call##_badfd, NULL, #call, rw); }
#define TC(call, rw) \
void \
test_##call##_fd(void) \
{ \
runtest(call##_badfd, call##_cleanup, #call, rw);\
#define TC(call, rw) \
void test_##call##_fd(void) { \
runtest(call##_badfd, call##_cleanup, #call, rw); \
}
T(read, RW_TEST_WRONLY);

View File

@@ -44,151 +44,83 @@
#include "config.h"
#include "test.h"
static
int
open_badpath(const char *path)
{
return open(path, O_RDONLY);
static int open_badpath(const char *path) { return open(path, O_RDONLY); }
static int remove_badpath(const char *path) { return remove(path); }
static int rename_badpath1(const char *path) { return rename(path, TESTFILE); }
static int rename_badpath2(const char *path) { return rename(TESTFILE, path); }
static int link_badpath1(const char *path) { return link(path, TESTFILE); }
static int link_badpath2(const char *path) { return link(TESTFILE, path); }
static int mkdir_badpath(const char *path) { return mkdir(path, 0775); }
static int rmdir_badpath(const char *path) { return rmdir(path); }
static int chdir_badpath(const char *path) { return chdir(path); }
static int symlink_badpath1(const char *path) {
return symlink(path, TESTFILE);
}
static
int
remove_badpath(const char *path)
{
return remove(path);
static int symlink_badpath2(const char *path) {
return symlink(TESTFILE, path);
}
static
int
rename_badpath1(const char *path)
{
return rename(path, TESTFILE);
static int readlink_badpath(const char *path) {
char buf[128];
return readlink(path, buf, sizeof(buf));
}
static
int
rename_badpath2(const char *path)
{
return rename(TESTFILE, path);
static int lstat_badpath(const char *name) {
struct stat sb;
return lstat(name, &sb);
}
static
int
link_badpath1(const char *path)
{
return link(path, TESTFILE);
}
static
int
link_badpath2(const char *path)
{
return link(TESTFILE, path);
}
static
int
mkdir_badpath(const char *path)
{
return mkdir(path, 0775);
}
static
int
rmdir_badpath(const char *path)
{
return rmdir(path);
}
static
int
chdir_badpath(const char *path)
{
return chdir(path);
}
static
int
symlink_badpath1(const char *path)
{
return symlink(path, TESTFILE);
}
static
int
symlink_badpath2(const char *path)
{
return symlink(TESTFILE, path);
}
static
int
readlink_badpath(const char *path)
{
char buf[128];
return readlink(path, buf, sizeof(buf));
}
static
int
lstat_badpath(const char *name)
{
struct stat sb;
return lstat(name, &sb);
}
static
int
stat_badpath(const char *name)
{
struct stat sb;
return stat(name, &sb);
static int stat_badpath(const char *name) {
struct stat sb;
return stat(name, &sb);
}
////////////////////////////////////////////////////////////
static
void
common_badpath(int (*func)(const char *path), int mk, int rm, const char *path,
const char *call, const char *pathdesc)
{
int rv;
static void common_badpath(int (*func)(const char *path), int mk, int rm,
const char *path, const char *call,
const char *pathdesc) {
int rv;
report_begin("%s with %s path", call, pathdesc);
report_begin("%s with %s path", call, pathdesc);
if (mk) {
if (create_testfile()<0) {
report_aborted();
return;
}
}
if (mk) {
if (create_testfile() < 0) {
report_aborted();
return;
}
}
rv = func(path);
report_check(rv, errno, EFAULT);
rv = func(path);
report_check(rv, errno, EFAULT);
if (mk || rm) {
remove(TESTFILE);
}
if (mk || rm) {
remove(TESTFILE);
}
}
static
void
any_badpath(int (*func)(const char *path), const char *call, int mk, int rm)
{
common_badpath(func, mk, rm, NULL, call, "NULL");
common_badpath(func, mk, rm, INVAL_PTR, call, "invalid-pointer");
common_badpath(func, mk, rm, KERN_PTR, call, "kernel-pointer");
static void any_badpath(int (*func)(const char *path), const char *call, int mk,
int rm) {
common_badpath(func, mk, rm, NULL, call, "NULL");
common_badpath(func, mk, rm, INVAL_PTR, call, "invalid-pointer");
common_badpath(func, mk, rm, KERN_PTR, call, "kernel-pointer");
}
////////////////////////////////////////////////////////////
/* functions with one pathname */
#define T(call) \
void \
test_##call##_path(void) \
{ \
any_badpath(call##_badpath, #call, 0, 0); \
}
#define T(call) \
void test_##call##_path(void) { any_badpath(call##_badpath, #call, 0, 0); }
T(open);
T(remove);
@@ -200,12 +132,10 @@ T(stat);
T(lstat);
/* functions with two pathnames */
#define T2(call) \
void \
test_##call##_paths(void) \
{ \
any_badpath(call##_badpath1, #call "(arg1)", 0, 1); \
any_badpath(call##_badpath2, #call "(arg2)", 1, 1); \
#define T2(call) \
void test_##call##_paths(void) { \
any_badpath(call##_badpath1, #call "(arg1)", 0, 1); \
any_badpath(call##_badpath2, #call "(arg2)", 1, 1); \
}
T2(rename);

View File

@@ -35,8 +35,8 @@
*/
#if defined(__mips__)
#define KERN_PTR ((void *)0x80000000) /* addr within kernel */
#define INVAL_PTR ((void *)0x40000000) /* addr not part of program */
#define KERN_PTR ((void *)0x80000000) /* addr within kernel */
#define INVAL_PTR ((void *)0x40000000) /* addr not part of program */
#else
#error "Please fix this"
#endif
@@ -45,16 +45,16 @@
* We assume CLOSED_FD is a legal fd that won't be open when we're running.
* CLOSED_FD+1 should also be legal and not open.
*/
#define CLOSED_FD 10
#define CLOSED_FD 10
/* We assume IMPOSSIBLE_FD is a fd that is completely not allowed. */
#define IMPOSSIBLE_FD 1234567890
#define IMPOSSIBLE_FD 1234567890
/* We assume this pid won't exist while we're running. Change as needed. */
#define NONEXIST_PID 34000
#define NONEXIST_PID 34000
/* An arbitrary process exit code that hopefully won't occur by accident */
#define MAGIC_STATUS 107
#define MAGIC_STATUS 107
/* An ioctl that doesn't exist */
#define NONEXIST_IOCTL 12345
#define NONEXIST_IOCTL 12345

View File

@@ -42,74 +42,68 @@
////////////////////////////////////////////////////////////
int
open_testfile(const char *string)
{
int fd, rv;
size_t len;
int open_testfile(const char *string) {
int fd, rv;
size_t len;
fd = open(TESTFILE, O_RDWR|O_CREAT|O_TRUNC, 0664);
if (fd<0) {
report_warn("creating %s: failed", TESTFILE);
return -1;
}
fd = open(TESTFILE, O_RDWR | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
report_warn("creating %s: failed", TESTFILE);
return -1;
}
if (string) {
len = strlen(string);
rv = write(fd, string, len);
if (rv<0) {
report_warn("write to %s failed", TESTFILE);
close(fd);
remove(TESTFILE);
return -1;
}
if ((unsigned)rv != len) {
report_warn("write to %s got short count", TESTFILE);
close(fd);
remove(TESTFILE);
return -1;
}
rv = lseek(fd, 0, SEEK_SET);
if (rv<0) {
report_warn("rewind of %s failed", TESTFILE);
close(fd);
remove(TESTFILE);
return -1;
}
}
return fd;
if (string) {
len = strlen(string);
rv = write(fd, string, len);
if (rv < 0) {
report_warn("write to %s failed", TESTFILE);
close(fd);
remove(TESTFILE);
return -1;
}
if ((unsigned)rv != len) {
report_warn("write to %s got short count", TESTFILE);
close(fd);
remove(TESTFILE);
return -1;
}
rv = lseek(fd, 0, SEEK_SET);
if (rv < 0) {
report_warn("rewind of %s failed", TESTFILE);
close(fd);
remove(TESTFILE);
return -1;
}
}
return fd;
}
int
create_testfile(void)
{
int fd, rv;
int create_testfile(void) {
int fd, rv;
fd = open_testfile(NULL);
if (fd<0) {
return -1;
}
fd = open_testfile(NULL);
if (fd < 0) {
return -1;
}
rv = close(fd);
if (rv<0) {
report_warn("closing %s failed", TESTFILE);
return -1;
}
rv = close(fd);
if (rv < 0) {
report_warn("closing %s failed", TESTFILE);
return -1;
}
return 0;
return 0;
}
int
reopen_testfile(int openflags)
{
int fd;
int reopen_testfile(int openflags) {
int fd;
fd = open(TESTFILE, openflags, 0664);
if (fd < 0) {
report_warn("reopening %s: failed", TESTFILE);
return -1;
}
return fd;
fd = open(TESTFILE, openflags, 0664);
if (fd < 0) {
report_warn("reopening %s: failed", TESTFILE);
return -1;
}
return fd;
}
/*
@@ -117,173 +111,155 @@ reopen_testfile(int openflags)
* otherwise it has to communicate to the caller which to call and
* that's a pain.
*/
int
create_testdir(void)
{
int rv;
rv = mkdir(TESTDIR, 0775);
if (rv<0) {
if (errno == ENOSYS) {
report_saw_enosys();
report_warnx("mkdir unimplemented; cannot run test");
report_skipped();
}
else {
report_warn("mkdir %s failed", TESTDIR);
report_aborted();
}
return -1;
}
return 0;
int create_testdir(void) {
int rv;
rv = mkdir(TESTDIR, 0775);
if (rv < 0) {
if (errno == ENOSYS) {
report_saw_enosys();
report_warnx("mkdir unimplemented; cannot run test");
report_skipped();
} else {
report_warn("mkdir %s failed", TESTDIR);
report_aborted();
}
return -1;
}
return 0;
}
int
create_testlink(void)
{
int rv;
rv = symlink("blahblah", TESTLINK);
if (rv<0) {
report_warn("making symlink %s failed", TESTLINK);
return -1;
}
return 0;
int create_testlink(void) {
int rv;
rv = symlink("blahblah", TESTLINK);
if (rv < 0) {
report_warn("making symlink %s failed", TESTLINK);
return -1;
}
return 0;
}
////////////////////////////////////////////////////////////
static
struct {
int ch;
int asst;
const char *name;
void (*f)(void);
} ops[] = {
{ 'a', 2, "execv", test_execv },
{ 'b', 2, "waitpid", test_waitpid },
{ 'c', 2, "open", test_open },
{ 'd', 2, "read", test_read },
{ 'e', 2, "write", test_write },
{ 'f', 2, "close", test_close },
{ 'g', 0, "reboot", test_reboot },
{ 'h', 3, "sbrk", test_sbrk },
{ 'i', 5, "ioctl", test_ioctl },
{ 'j', 2, "lseek", test_lseek },
{ 'k', 4, "fsync", test_fsync },
{ 'l', 4, "ftruncate", test_ftruncate },
{ 'm', 4, "fstat", test_fstat },
{ 'n', 4, "remove", test_remove },
{ 'o', 4, "rename", test_rename },
{ 'p', 5, "link", test_link },
{ 'q', 4, "mkdir", test_mkdir },
{ 'r', 4, "rmdir", test_rmdir },
{ 's', 2, "chdir", test_chdir },
{ 't', 4, "getdirentry", test_getdirentry },
{ 'u', 5, "symlink", test_symlink },
{ 'v', 5, "readlink", test_readlink },
{ 'w', 2, "dup2", test_dup2 },
{ 'x', 5, "pipe", test_pipe },
{ 'y', 5, "__time", test_time },
{ 'z', 2, "__getcwd", test_getcwd },
{ '{', 5, "stat", test_stat },
{ '|', 5, "lstat", test_lstat },
{ 0, 0, NULL, NULL }
};
static struct {
int ch;
int asst;
const char *name;
void (*f)(void);
} ops[] = {{'a', 2, "execv", test_execv},
{'b', 2, "waitpid", test_waitpid},
{'c', 2, "open", test_open},
{'d', 2, "read", test_read},
{'e', 2, "write", test_write},
{'f', 2, "close", test_close},
{'g', 0, "reboot", test_reboot},
{'h', 3, "sbrk", test_sbrk},
{'i', 5, "ioctl", test_ioctl},
{'j', 2, "lseek", test_lseek},
{'k', 4, "fsync", test_fsync},
{'l', 4, "ftruncate", test_ftruncate},
{'m', 4, "fstat", test_fstat},
{'n', 4, "remove", test_remove},
{'o', 4, "rename", test_rename},
{'p', 5, "link", test_link},
{'q', 4, "mkdir", test_mkdir},
{'r', 4, "rmdir", test_rmdir},
{'s', 2, "chdir", test_chdir},
{'t', 4, "getdirentry", test_getdirentry},
{'u', 5, "symlink", test_symlink},
{'v', 5, "readlink", test_readlink},
{'w', 2, "dup2", test_dup2},
{'x', 5, "pipe", test_pipe},
{'y', 5, "__time", test_time},
{'z', 2, "__getcwd", test_getcwd},
{'{', 5, "stat", test_stat},
{'|', 5, "lstat", test_lstat},
{0, 0, NULL, NULL}};
#define LOWEST 'a'
#define LOWEST 'a'
#define HIGHEST '|'
static
void
menu(void)
{
int i;
for (i=0; ops[i].name; i++) {
printf("[%c] %-24s", ops[i].ch, ops[i].name);
if (i%2==1) {
printf("\n");
}
}
if (i%2==1) {
printf("\n");
}
printf("[1] %-24s", "asst1");
printf("[2] %-24s\n", "asst2");
printf("[3] %-24s", "asst3");
printf("[4] %-24s\n", "asst4");
printf("[*] %-24s", "all");
printf("[!] %-24s\n", "quit");
static void menu(void) {
int i;
for (i = 0; ops[i].name; i++) {
printf("[%c] %-24s", ops[i].ch, ops[i].name);
if (i % 2 == 1) {
printf("\n");
}
}
if (i % 2 == 1) {
printf("\n");
}
printf("[1] %-24s", "asst1");
printf("[2] %-24s\n", "asst2");
printf("[3] %-24s", "asst3");
printf("[4] %-24s\n", "asst4");
printf("[*] %-24s", "all");
printf("[!] %-24s\n", "quit");
}
static
void
runit(int op)
{
int i, k;
static void runit(int op) {
int i, k;
if (op=='!') {
exit(0);
}
if (op == '!') {
exit(0);
}
if (op=='?') {
menu();
return;
}
if (op == '?') {
menu();
return;
}
if (op=='*') {
for (i=0; ops[i].name; i++) {
printf("[%s]\n", ops[i].name);
ops[i].f();
}
return;
}
if (op == '*') {
for (i = 0; ops[i].name; i++) {
printf("[%s]\n", ops[i].name);
ops[i].f();
}
return;
}
if (op>='1' && op <= '4') {
k = op-'0';
for (i=0; ops[i].name; i++) {
if (ops[i].asst <= k) {
printf("[%s]\n", ops[i].name);
ops[i].f();
}
}
return;
}
if (op >= '1' && op <= '4') {
k = op - '0';
for (i = 0; ops[i].name; i++) {
if (ops[i].asst <= k) {
printf("[%s]\n", ops[i].name);
ops[i].f();
}
}
return;
}
if (op < LOWEST || op > HIGHEST) {
printf("Invalid request %c\n", op);
return;
}
if (op < LOWEST || op > HIGHEST) {
printf("Invalid request %c\n", op);
return;
}
ops[op-'a'].f();
ops[op - 'a'].f();
}
int
main(int argc, char **argv)
{
int op, i, j;
int main(int argc, char **argv) {
int op, i, j;
printf("[%c-%c, 1-4, *, ?=menu, !=quit]\n", LOWEST, HIGHEST);
printf("[%c-%c, 1-4, *, ?=menu, !=quit]\n", LOWEST, HIGHEST);
if (argc > 1) {
for (i=1; i<argc; i++) {
for (j=0; argv[i][j]; j++) {
printf("Choose: %c\n",
argv[i][j]);
runit(argv[i][j]);
}
}
}
else {
menu();
while (1) {
printf("Choose: ");
op = getchar();
if (op==EOF) {
break;
}
printf("%c\n", op);
runit(op);
}
}
if (argc > 1) {
for (i = 1; i < argc; i++) {
for (j = 0; argv[i][j]; j++) {
printf("Choose: %c\n", argv[i][j]);
runit(argv[i][j]);
}
}
} else {
menu();
while (1) {
printf("Choose: ");
op = getchar();
if (op == EOF) {
break;
}
printf("%c\n", op);
runit(op);
}
}
return 0;
return 0;
}

View File

@@ -58,63 +58,50 @@ static size_t outbufpos;
/*
* Print things.
*/
static
void
vsay(const char *fmt, va_list ap)
{
size_t begin, i;
static void vsay(const char *fmt, va_list ap) {
size_t begin, i;
assert(outbufpos < sizeof(outbuf));
assert(outbufpos < sizeof(outbuf));
begin = outbufpos;
vsnprintf(outbuf + outbufpos, sizeof(outbuf) - outbufpos, fmt, ap);
outbufpos = strlen(outbuf);
begin = outbufpos;
vsnprintf(outbuf + outbufpos, sizeof(outbuf) - outbufpos, fmt, ap);
outbufpos = strlen(outbuf);
for (i=begin; i<outbufpos; i++) {
if (outbuf[i] == '\n') {
horizpos = 0;
}
else {
horizpos++;
}
}
for (i = begin; i < outbufpos; i++) {
if (outbuf[i] == '\n') {
horizpos = 0;
} else {
horizpos++;
}
}
}
static
void
say(const char *fmt, ...)
{
va_list ap;
static void say(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vsay(fmt, ap);
va_end(ap);
va_start(ap, fmt);
vsay(fmt, ap);
va_end(ap);
}
/*
* Indent to a given horizontal position.
*/
static
void
indent_to(size_t pos)
{
while (horizpos < pos) {
assert(outbufpos < sizeof(outbuf) - 1);
outbuf[outbufpos++] = ' ';
outbuf[outbufpos] = 0;
horizpos++;
}
static void indent_to(size_t pos) {
while (horizpos < pos) {
assert(outbufpos < sizeof(outbuf) - 1);
outbuf[outbufpos++] = ' ';
outbuf[outbufpos] = 0;
horizpos++;
}
}
/*
* Flush the output.
*/
static
void
flush(void)
{
write(STDOUT_FILENO, outbuf, outbufpos);
outbufpos = 0;
static void flush(void) {
write(STDOUT_FILENO, outbuf, outbufpos);
outbufpos = 0;
}
////////////////////////////////////////////////////////////
@@ -123,28 +110,24 @@ flush(void)
* Begin a test. This flushes the description so it can be seen before
* the test happens, in case the test explodes or deadlocks the system.
*/
void
report_begin(const char *descfmt, ...)
{
va_list ap;
void report_begin(const char *descfmt, ...) {
va_list ap;
say("badcall: ");
va_start(ap, descfmt);
vsay(descfmt, ap);
va_end(ap);
say("... ");
flush();
say("badcall: ");
va_start(ap, descfmt);
vsay(descfmt, ap);
va_end(ap);
say("... ");
flush();
}
/*
* Prepare to be able to print subreports.
*/
void
report_hassubs(void)
{
subpos = horizpos;
say("\n");
flush();
void report_hassubs(void) {
subpos = horizpos;
say("\n");
flush();
}
/*
@@ -152,17 +135,15 @@ report_hassubs(void)
* subreports are in subprocesses and we want each one to print a
* whole line at once to avoid output interleaving.
*/
void
report_beginsub(const char *descfmt, ...)
{
va_list ap;
void report_beginsub(const char *descfmt, ...) {
va_list ap;
assert(horizpos == 0);
say(" ");
va_start(ap, descfmt);
vsay(descfmt, ap);
va_end(ap);
indent_to(subpos);
assert(horizpos == 0);
say(" ");
va_start(ap, descfmt);
vsay(descfmt, ap);
va_end(ap);
indent_to(subpos);
}
/*
@@ -170,52 +151,45 @@ report_beginsub(const char *descfmt, ...)
* extra line for the warning. The warnx form is the same but doesn't
* add errno.
*/
void
report_warn(const char *fmt, ...)
{
size_t pos;
const char *errmsg;
va_list ap;
void report_warn(const char *fmt, ...) {
size_t pos;
const char *errmsg;
va_list ap;
pos = horizpos;
errmsg = strerror(errno);
say("\n OOPS: ");
va_start(ap, fmt);
vsay(fmt, ap);
va_end(ap);
say(": %s\n", errmsg);
indent_to(pos);
flush();
pos = horizpos;
errmsg = strerror(errno);
say("\n OOPS: ");
va_start(ap, fmt);
vsay(fmt, ap);
va_end(ap);
say(": %s\n", errmsg);
indent_to(pos);
flush();
}
void
report_warnx(const char *fmt, ...)
{
size_t pos;
va_list ap;
void report_warnx(const char *fmt, ...) {
size_t pos;
va_list ap;
pos = horizpos;
say("\n oops: ");
va_start(ap, fmt);
vsay(fmt, ap);
va_end(ap);
say("\n");
indent_to(pos);
flush();
pos = horizpos;
say("\n oops: ");
va_start(ap, fmt);
vsay(fmt, ap);
va_end(ap);
say("\n");
indent_to(pos);
flush();
}
/*
* Report a system call result.
*/
void
report_result(int rv, int error)
{
if (rv == -1) {
say("%s ", strerror(error));
}
else {
say("Success ");
}
void report_result(int rv, int error) {
if (rv == -1) {
say("%s ", strerror(error));
} else {
say("Success ");
}
}
/*
@@ -227,13 +201,11 @@ report_result(int rv, int error)
*
* XXX this is pretty gross.
*/
void
report_saw_enosys(void)
{
size_t pos = horizpos;
void report_saw_enosys(void) {
size_t pos = horizpos;
horizpos = 0;
indent_to(pos);
horizpos = 0;
indent_to(pos);
}
/*
@@ -241,38 +213,19 @@ report_saw_enosys(void)
* in the result column, and add the final newline.
*/
static
void
report_end(const char *msg)
{
indent_to(RESULT_COLUMN);
say("%s\n", msg);
flush();
static void report_end(const char *msg) {
indent_to(RESULT_COLUMN);
say("%s\n", msg);
flush();
}
void
report_passed(void)
{
report_end("passed");
}
void report_passed(void) { report_end("passed"); }
void
report_failure(void)
{
report_end("FAILURE");
}
void report_failure(void) { report_end("FAILURE"); }
void
report_skipped(void)
{
report_end("------");
}
void report_skipped(void) { report_end("------"); }
void
report_aborted(void)
{
report_end("ABORTED");
}
void report_aborted(void) { report_end("ABORTED"); }
////////////////////////////////////////////////////////////
@@ -282,69 +235,56 @@ report_aborted(void)
* matches one or more expected results.
*/
void
report_survival(int rv, int error)
{
/* allow any error as long as we survive */
report_result(rv, error);
report_passed();
void report_survival(int rv, int error) {
/* allow any error as long as we survive */
report_result(rv, error);
report_passed();
}
static
void
report_checkN(int rv, int error, int *right_errors, int right_num)
{
int i, goterror;
static void report_checkN(int rv, int error, int *right_errors, int right_num) {
int i, goterror;
if (rv==-1) {
goterror = error;
}
else {
goterror = 0;
}
if (rv == -1) {
goterror = error;
} else {
goterror = 0;
}
for (i=0; i<right_num; i++) {
if (goterror == right_errors[i]) {
report_result(rv, error);
report_passed();
return;
}
}
for (i = 0; i < right_num; i++) {
if (goterror == right_errors[i]) {
report_result(rv, error);
report_passed();
return;
}
}
if (goterror == ENOSYS) {
report_saw_enosys();
say("(unimplemented) ");
report_skipped();
}
else {
report_result(rv, error);
report_failure();
}
if (goterror == ENOSYS) {
report_saw_enosys();
say("(unimplemented) ");
report_skipped();
} else {
report_result(rv, error);
report_failure();
}
}
void
report_check(int rv, int error, int right_error)
{
report_checkN(rv, error, &right_error, 1);
void report_check(int rv, int error, int right_error) {
report_checkN(rv, error, &right_error, 1);
}
void
report_check2(int rv, int error, int okerr1, int okerr2)
{
int ok[2];
void report_check2(int rv, int error, int okerr1, int okerr2) {
int ok[2];
ok[0] = okerr1;
ok[1] = okerr2;
report_checkN(rv, error, ok, 2);
ok[0] = okerr1;
ok[1] = okerr2;
report_checkN(rv, error, ok, 2);
}
void
report_check3(int rv, int error, int okerr1, int okerr2, int okerr3)
{
int ok[3];
void report_check3(int rv, int error, int okerr1, int okerr2, int okerr3) {
int ok[3];
ok[0] = okerr1;
ok[1] = okerr2;
ok[2] = okerr3;
report_checkN(rv, error, ok, 3);
ok[0] = okerr1;
ok[1] = okerr2;
ok[2] = okerr3;
report_checkN(rv, error, ok, 3);
}

View File

@@ -28,7 +28,7 @@
*/
#define TESTFILE "badcallfile"
#define TESTDIR "badcalldir"
#define TESTDIR "badcalldir"
#define TESTLINK "badcalllink"
#if defined(__clang__) || defined(__GNUC__)
@@ -106,7 +106,7 @@ void test_ioctl(void);
void test_lseek(void);
void test_fsync(void);
void test_ftruncate(void);
void test_fstat(void); /* in bad_stat.c */
void test_fstat(void); /* in bad_stat.c */
void test_remove(void);
void test_rename(void);
void test_link(void);
@@ -121,4 +121,4 @@ void test_pipe(void);
void test_time(void);
void test_getcwd(void);
void test_stat(void);
void test_lstat(void); /* in bad_stat.c */
void test_lstat(void); /* in bad_stat.c */

View File

@@ -52,336 +52,288 @@ static char word4050[4051];
static char word16320[16321];
static char word65500[65501];
static
void
fill(char *buf, size_t buflen)
{
static const char *const names[22] = {
"Alhammitt", "Biffa", "Cennoreth", "Dastgandlen", "Enblith",
"Fenna", "Gull", "Hern", "Hildrida", "Kankredin", "Kialan",
"Lenina", "Manaliabrid", "Mayelbridwen", "Noreth", "Osfameron",
"Robin", "Tanamil", "Tanamoril", "Tanaqui", "Ynen", "Ynynen"
};
static void fill(char *buf, size_t buflen) {
static const char *const names[22] = {
"Alhammitt", "Biffa", "Cennoreth", "Dastgandlen", "Enblith",
"Fenna", "Gull", "Hern", "Hildrida", "Kankredin",
"Kialan", "Lenina", "Manaliabrid", "Mayelbridwen", "Noreth",
"Osfameron", "Robin", "Tanamil", "Tanamoril", "Tanaqui",
"Ynen", "Ynynen"};
const char *name;
size_t len;
const char *name;
size_t len;
while (buflen > 4) {
name = names[random()%22];
len = strlen(name);
if (len < buflen) {
strcpy(buf, name);
buf += len;
buflen -= len;
if (buflen > 1) {
*buf = ' ';
buf++;
buflen--;
}
}
}
while (buflen > 1) {
*buf = '.';
buf++;
buflen--;
}
*buf = 0;
while (buflen > 4) {
name = names[random() % 22];
len = strlen(name);
if (len < buflen) {
strcpy(buf, name);
buf += len;
buflen -= len;
if (buflen > 1) {
*buf = ' ';
buf++;
buflen--;
}
}
}
while (buflen > 1) {
*buf = '.';
buf++;
buflen--;
}
*buf = 0;
}
static
void
prepwords(void)
{
srandom(16581);
fill(word4050, sizeof(word4050));
fill(word16320, sizeof(word16320));
fill(word65500, sizeof(word65500));
static void prepwords(void) {
srandom(16581);
fill(word4050, sizeof(word4050));
fill(word16320, sizeof(word16320));
fill(word65500, sizeof(word65500));
}
////////////////////////////////////////////////////////////
// execing/checking
static
void
try(const char *first, ...)
{
const char *args[20];
const char *s;
va_list ap;
int num;
static void try(const char *first, ...) {
const char *args[20];
const char *s;
va_list ap;
int num;
assert(first != NULL);
args[0] = _PATH_MYSELF;
args[1] = first;
num = 2;
assert(first != NULL);
args[0] = _PATH_MYSELF;
args[1] = first;
num = 2;
va_start(ap, first);
while (1) {
s = va_arg(ap, const char *);
if (s == NULL) {
break;
}
assert(num < 20);
args[num++] = s;
}
assert(num < 20);
args[num] = NULL;
execv(_PATH_MYSELF, (char **)args);
err(1, "execv");
va_start(ap, first);
while (1) {
s = va_arg(ap, const char *);
if (s == NULL) {
break;
}
assert(num < 20);
args[num++] = s;
}
assert(num < 20);
args[num] = NULL;
execv(_PATH_MYSELF, (char **)args);
err(1, "execv");
}
static
void
trymany(int num, const char *word)
{
const char *args[num+2];
int i;
static void trymany(int num, const char *word) {
const char *args[num + 2];
int i;
args[0] = _PATH_MYSELF;
for (i=0; i<num; i++) {
args[i+1] = word;
}
args[num+1] = NULL;
execv(_PATH_MYSELF, (char **)args);
err(1, "execv");
args[0] = _PATH_MYSELF;
for (i = 0; i < num; i++) {
args[i + 1] = word;
}
args[num + 1] = NULL;
execv(_PATH_MYSELF, (char **)args);
err(1, "execv");
}
static
int
check(int argc, char *argv[], const char *first, ...)
{
const char *s;
va_list ap;
int pos;
static int check(int argc, char *argv[], const char *first, ...) {
const char *s;
va_list ap;
int pos;
pos = 1;
va_start(ap, first);
s = first;
while (s != NULL) {
if (pos == argc) {
/* not enough args */
return 0;
}
assert(pos < argc);
if (argv[pos] == NULL) {
/* woops */
warnx("argv[%d] is null but argc is %d", pos, argc);
return 0;
}
if (strcmp(argv[pos], s) != 0) {
/* does not match */
return 0;
}
s = va_arg(ap, const char *);
pos++;
}
if (pos != argc) {
/* too many args */
return 0;
}
if (argv[pos] != NULL) {
warnx("argv[argc] is not null");
return 0;
}
return 1;
pos = 1;
va_start(ap, first);
s = first;
while (s != NULL) {
if (pos == argc) {
/* not enough args */
return 0;
}
assert(pos < argc);
if (argv[pos] == NULL) {
/* woops */
warnx("argv[%d] is null but argc is %d", pos, argc);
return 0;
}
if (strcmp(argv[pos], s) != 0) {
/* does not match */
return 0;
}
s = va_arg(ap, const char *);
pos++;
}
if (pos != argc) {
/* too many args */
return 0;
}
if (argv[pos] != NULL) {
warnx("argv[argc] is not null");
return 0;
}
return 1;
}
static
int
checkmany(int argc, char *argv[], int num, const char *word)
{
int i;
static int checkmany(int argc, char *argv[], int num, const char *word) {
int i;
if (argc != num + 1) {
/* wrong number of args */
return 0;
}
for (i=1; i<argc; i++) {
if (strcmp(argv[i], word) != 0) {
/* doesn't match */
return 0;
}
}
return 1;
if (argc != num + 1) {
/* wrong number of args */
return 0;
}
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], word) != 0) {
/* doesn't match */
return 0;
}
}
return 1;
}
////////////////////////////////////////////////////////////
// test driver
static
void
dumpargs(int argc, char *argv[])
{
const char *s;
int i;
static void dumpargs(int argc, char *argv[]) {
const char *s;
int i;
warnx("%d args", argc);
warnx("argv[0]: %s", argv[0]);
for (i=1; i<=argc; i++) {
s = argv[i];
if (s == NULL) {
warnx("argv[%d]: is null", i);
}
else if (!strcmp(s, word8)) {
warnx("argv[%d] is word8", i);
}
else if (!strcmp(s, word4050)) {
warnx("argv[%d] is word4050", i);
}
else if (!strcmp(s, word16320)) {
warnx("argv[%d] is word16320", i);
}
else if (!strcmp(s, word65500)) {
warnx("argv[%d] is word65500", i);
}
else if (strlen(s) < 72) {
warnx("argv[%d]: %s", i, s);
}
else {
warnx("argv[%d] is %zu bytes, begins %.64s",
i, strlen(s), s);
}
}
warnx("%d args", argc);
warnx("argv[0]: %s", argv[0]);
for (i = 1; i <= argc; i++) {
s = argv[i];
if (s == NULL) {
warnx("argv[%d]: is null", i);
} else if (!strcmp(s, word8)) {
warnx("argv[%d] is word8", i);
} else if (!strcmp(s, word4050)) {
warnx("argv[%d] is word4050", i);
} else if (!strcmp(s, word16320)) {
warnx("argv[%d] is word16320", i);
} else if (!strcmp(s, word65500)) {
warnx("argv[%d] is word65500", i);
} else if (strlen(s) < 72) {
warnx("argv[%d]: %s", i, s);
} else {
warnx("argv[%d] is %zu bytes, begins %.64s", i, strlen(s), s);
}
}
}
int
main(int argc, char *argv[])
{
if (argc < 0) {
err(1, "argc is negative!?");
}
int main(int argc, char *argv[]) {
if (argc < 0) {
err(1, "argc is negative!?");
}
prepwords();
assert(strlen(word8) == 8);
assert(strlen(word4050) == 4050);
assert(strlen(word16320) == 16320);
assert(strlen(word65500) == 65500);
prepwords();
assert(strlen(word8) == 8);
assert(strlen(word4050) == 4050);
assert(strlen(word16320) == 16320);
assert(strlen(word65500) == 65500);
assert(ARG_MAX >= 65536);
assert(ARG_MAX >= 65536);
if (argv == NULL || argc == 0 || argc == 1) {
/* no args -- start the test */
warnx("Starting.");
if (argv == NULL || argc == 0 || argc == 1) {
/* no args -- start the test */
warnx("Starting.");
/*
* 1. Should always fit no matter what.
*/
warnx("1. Execing with one 8-letter word.");
try(word8, NULL);
}
else if (check(argc, argv, word8, NULL)) {
/*
* 2. Fits in one page.
*/
warnx("2. Execing with one 4050-letter word.");
try(word4050, NULL);
}
else if (check(argc, argv, word4050, NULL)) {
/*
* 3. Requires two pages but each word fits on a page.
*/
warnx("3. Execing with two 4050-letter words.");
try(word4050, word4050, NULL);
}
else if (check(argc, argv, word4050, word4050, NULL)) {
/*
* 4. Requires the full 64K argv buffer, in large
* chunks, with a little space for slop. Each word
* fits on a page though. With null terminators and
* 4-byte pointers the size is 4085*16 = 65360, and
* with 8-byte pointers it would become 65424.
*
* Don't forget that argv[0] will be another 21 or 25
* bytes and some implementations may reasonably need
* to stash an ending NULL in the buffer too.
*/
warnx("4. Execing with 16 4050-letter words.");
try(word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050,
NULL);
}
else if (check(argc, argv,
word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050,
NULL)) {
/*
* 5. Requires more than one page for a single word.
*/
warnx("5. Execing with one 16320-letter word.");
try(word16320, NULL);
}
else if (check(argc, argv, word16320, NULL)) {
/*
* 6. Ditto but makes sure it works with two of them.
*/
warnx("6. Execing with two 16320-letter words.");
try(word16320, word16320, NULL);
}
else if (check(argc, argv, word16320, word16320, NULL)) {
/*
* 7. Requires the full 64K argv buffer.
*/
warnx("7. Execing with four 16320-letter words.");
try(word16320, word16320, word16320, word16320,
NULL);
}
else if (check(argc, argv, word16320, word16320,
word16320, word16320, NULL)) {
/*
* 8. Also requires the full 64K argv buffer, but with
* only one huge word.
*/
warnx("8. Execing with one 65500-letter word.");
try(word65500, NULL);
}
else if (check(argc, argv, word65500, NULL)) {
/*
* 9. This fits on one page. Given 4-byte pointers,
* (8+1+4)*300 = 3900. With 8-byte pointers, it
* doesn't, but we aren't doing that. (Update this if
* we ever move to a 64-bit platform.)
*/
assert((8+1+sizeof(char *))*300 < 4096);
warnx("9. Execing with 300 8-letter words.");
trymany(300, word8);
}
else if (checkmany(argc, argv, 300, word8)) {
/*
* 1. Should always fit no matter what.
*/
warnx("1. Execing with one 8-letter word.");
try(word8, NULL);
} else if (check(argc, argv, word8, NULL)) {
/*
* 2. Fits in one page.
*/
warnx("2. Execing with one 4050-letter word.");
try(word4050, NULL);
} else if (check(argc, argv, word4050, NULL)) {
/*
* 3. Requires two pages but each word fits on a page.
*/
warnx("3. Execing with two 4050-letter words.");
try(word4050, word4050, NULL);
} else if (check(argc, argv, word4050, word4050, NULL)) {
/*
* 4. Requires the full 64K argv buffer, in large
* chunks, with a little space for slop. Each word
* fits on a page though. With null terminators and
* 4-byte pointers the size is 4085*16 = 65360, and
* with 8-byte pointers it would become 65424.
*
* Don't forget that argv[0] will be another 21 or 25
* bytes and some implementations may reasonably need
* to stash an ending NULL in the buffer too.
*/
warnx("4. Execing with 16 4050-letter words.");
try(word4050, word4050, word4050, word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050, word4050, word4050, word4050,
word4050, word4050, NULL);
} else if (check(argc, argv, word4050, word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050, word4050, word4050,
word4050, word4050, word4050, word4050, word4050, NULL)) {
/*
* 5. Requires more than one page for a single word.
*/
warnx("5. Execing with one 16320-letter word.");
try(word16320, NULL);
} else if (check(argc, argv, word16320, NULL)) {
/*
* 6. Ditto but makes sure it works with two of them.
*/
warnx("6. Execing with two 16320-letter words.");
try(word16320, word16320, NULL);
} else if (check(argc, argv, word16320, word16320, NULL)) {
/*
* 7. Requires the full 64K argv buffer.
*/
warnx("7. Execing with four 16320-letter words.");
try(word16320, word16320, word16320, word16320, NULL);
} else if (check(argc, argv, word16320, word16320, word16320, word16320,
NULL)) {
/*
* 8. Also requires the full 64K argv buffer, but with
* only one huge word.
*/
warnx("8. Execing with one 65500-letter word.");
try(word65500, NULL);
} else if (check(argc, argv, word65500, NULL)) {
/*
* 9. This fits on one page. Given 4-byte pointers,
* (8+1+4)*300 = 3900. With 8-byte pointers, it
* doesn't, but we aren't doing that. (Update this if
* we ever move to a 64-bit platform.)
*/
assert((8 + 1 + sizeof(char *)) * 300 < 4096);
warnx("9. Execing with 300 8-letter words.");
trymany(300, word8);
} else if (checkmany(argc, argv, 300, word8)) {
#if 1 /* enforce the full size */
/*
* 10. This requires the full 64K argv buffer.
* With 4-byte pointers, (8+1+4)*5020 = 65260.
* It also doesn't fit with 8-byte pointers.
*
* XXX for the time being, we'll allow less efficient
* implementations that use two pointers per word.
* Hence, (8+1+4+4)*3850 = 65450.
*/
assert((8+1+sizeof(char *))*5020 < 65536);
assert((8+1+2*sizeof(char *))*3850 < 65536);
warnx("10. Execing with 3850 8-letter words.");
trymany(3850, word8);
}
else if (checkmany(argc, argv, 3850, word8)) {
/*
* 10. This requires the full 64K argv buffer.
* With 4-byte pointers, (8+1+4)*5020 = 65260.
* It also doesn't fit with 8-byte pointers.
*
* XXX for the time being, we'll allow less efficient
* implementations that use two pointers per word.
* Hence, (8+1+4+4)*3850 = 65450.
*/
assert((8 + 1 + sizeof(char *)) * 5020 < 65536);
assert((8 + 1 + 2 * sizeof(char *)) * 3850 < 65536);
warnx("10. Execing with 3850 8-letter words.");
trymany(3850, word8);
} else if (checkmany(argc, argv, 3850, word8)) {
#else
/*
* 10a. This requires more than one page using small
* words. With 4-byte pointers, (8+1+4)*1000 = 13000.
*/
warnx("10. Execing with 1000 8-letter words.");
trymany(1000, word8);
}
else if (checkmany(argc, argv, 1000, word8)) {
/*
* 10a. This requires more than one page using small
* words. With 4-byte pointers, (8+1+4)*1000 = 13000.
*/
warnx("10. Execing with 1000 8-letter words.");
trymany(1000, word8);
} else if (checkmany(argc, argv, 1000, word8)) {
#endif
warnx("Complete.");
return 0;
}
else {
warnx("Received unknown/unexpected args:");
dumpargs(argc, argv);
return 1;
}
warnx("Complete.");
return 0;
} else {
warnx("Received unknown/unexpected args:");
dumpargs(argc, argv);
return 1;
}
}

View File

@@ -44,64 +44,60 @@
static char buffer[8192 + 1];
int
main(int argc, char *argv[])
{
const char *filename;
char *s;
size_t i, size, chunksize, offset;
ssize_t len;
int fd;
int main(int argc, char *argv[]) {
const char *filename;
char *s;
size_t i, size, chunksize, offset;
ssize_t len;
int fd;
if (argc != 3) {
warnx("Usage: bigfile <filename> <size>");
errx(1, " or: bigfile <filename> <size>/<chunksize>");
}
if (argc != 3) {
warnx("Usage: bigfile <filename> <size>");
errx(1, " or: bigfile <filename> <size>/<chunksize>");
}
filename = argv[1];
s = strchr(argv[2], '/');
if (s != NULL) {
*s++ = 0;
chunksize = atoi(s);
if (chunksize >= sizeof(buffer)) {
chunksize = sizeof(buffer) - 1;
}
if (chunksize == 0) {
errx(1, "Really?");
}
}
else {
chunksize = 10;
}
size = atoi(argv[2]);
filename = argv[1];
s = strchr(argv[2], '/');
if (s != NULL) {
*s++ = 0;
chunksize = atoi(s);
if (chunksize >= sizeof(buffer)) {
chunksize = sizeof(buffer) - 1;
}
if (chunksize == 0) {
errx(1, "Really?");
}
} else {
chunksize = 10;
}
size = atoi(argv[2]);
/* round size up */
size = ((size + chunksize - 1) / chunksize) * chunksize;
/* round size up */
size = ((size + chunksize - 1) / chunksize) * chunksize;
printf("Creating a file of size %d in %d-byte chunks\n",
size, chunksize);
printf("Creating a file of size %d in %d-byte chunks\n", size, chunksize);
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC);
if (fd < 0) {
err(1, "%s: create", filename);
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
if (fd < 0) {
err(1, "%s: create", filename);
}
i=0;
while (i<size) {
snprintf(buffer, sizeof(buffer), "%d\n", i);
if (strlen(buffer) < chunksize) {
offset = chunksize - strlen(buffer);
memmove(buffer + offset, buffer, strlen(buffer)+1);
memset(buffer, ' ', offset);
}
len = write(fd, buffer, strlen(buffer));
if (len<0) {
err(1, "%s: write", filename);
}
i += len;
}
i = 0;
while (i < size) {
snprintf(buffer, sizeof(buffer), "%d\n", i);
if (strlen(buffer) < chunksize) {
offset = chunksize - strlen(buffer);
memmove(buffer + offset, buffer, strlen(buffer) + 1);
memset(buffer, ' ', offset);
}
len = write(fd, buffer, strlen(buffer));
if (len < 0) {
err(1, "%s: write", filename);
}
i += len;
}
close(fd);
close(fd);
return 0;
return 0;
}

View File

@@ -54,186 +54,145 @@
*/
#define DIM 64
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] = {
536763422,
478946723,
375722852,
369910585,
328220902,
62977821,
536763422, 478946723, 375722852, 369910585, 328220902, 62977821,
};
static unsigned failures;
static
void
init(void)
{
unsigned i, j;
static void init(void) {
unsigned i, j;
srandom(73771);
for (i=0; i<DIM; i++) {
for (j=0; j<DIM; j++) {
m1[i*DIM+j] = random() % 11 - 5;
}
}
srandom(73771);
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
m1[i * DIM + j] = random() % 11 - 5;
}
}
}
static
void
add(int *x, const int *a, const int *b)
{
unsigned i, j;
static void add(int *x, const int *a, const int *b) {
unsigned i, j;
for (i=0; i<DIM; i++) {
for (j=0; j<DIM; j++) {
x[i*DIM+j] = a[i*DIM+j] + b[i*DIM+j];
}
}
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
x[i * DIM + j] = a[i * DIM + j] + b[i * DIM + j];
}
}
}
static
void
mul(int *x, const int *a, const int *b)
{
unsigned i, j, k;
static void mul(int *x, const int *a, const int *b) {
unsigned i, j, k;
for (i=0; i<DIM; i++) {
for (j=0; j<DIM; j++) {
x[i*DIM+j] = 0;
for (k=0; k<DIM; k++) {
x[i*DIM+j] += a[i*DIM+k] * b[k*DIM+j];
}
}
}
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
x[i * DIM + j] = 0;
for (k = 0; k < DIM; k++) {
x[i * DIM + j] += a[i * DIM + k] * b[k * DIM + j];
}
}
}
}
static
void
scale(int *x, const int *a, int b)
{
unsigned i, j;
static void scale(int *x, const int *a, int b) {
unsigned i, j;
for (i=0; i<DIM; i++) {
for (j=0; j<DIM; j++) {
x[i*DIM+j] = a[i*DIM+j] / b;
}
}
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
x[i * DIM + j] = a[i * DIM + j] / b;
}
}
}
static
void
grind(void)
{
/*
* compute: m2 = m1*m1, m3 = m2+m1, m4 = m3*m3, m1 = m4 / 2
*/
mul(m2, m1, m1);
add(m3, m2, m1);
mul(m4, m3, m3);
scale(m1, m4, 2);
static void grind(void) {
/*
* compute: m2 = m1*m1, m3 = m2+m1, m4 = m3*m3, m1 = m4 / 2
*/
mul(m2, m1, m1);
add(m3, m2, m1);
mul(m4, m3, m3);
scale(m1, m4, 2);
}
static
int
trace(void)
{
unsigned i;
int val = 0;
static int trace(void) {
unsigned i;
int val = 0;
for (i=0; i<DIM; i++) {
val += m1[i*DIM+i];
}
while (val < 0) {
val += 0x20000000;
}
return val % 0x20000000;
for (i = 0; i < DIM; i++) {
val += m1[i * DIM + i];
}
while (val < 0) {
val += 0x20000000;
}
return val % 0x20000000;
}
static
pid_t
dofork(void)
{
pid_t pid;
static pid_t dofork(void) {
pid_t pid;
pid = fork();
if (pid < 0) {
warn("fork");
}
return pid;
pid = fork();
if (pid < 0) {
warn("fork");
}
return pid;
}
static
void
dowait(pid_t pid)
{
int status;
static void dowait(pid_t pid) {
int status;
if (pid == -1) {
failures++;
return;
}
if (pid == 0) {
exit(failures);
}
else {
if (waitpid(pid, &status, 0) < 0) {
warn("waitpid(%d)", pid);
}
else if (WIFSIGNALED(status)) {
warnx("pid %d: signal %d", pid, WTERMSIG(status));
}
else if (WEXITSTATUS(status) > 0) {
failures += WEXITSTATUS(status);
}
}
if (pid == -1) {
failures++;
return;
}
if (pid == 0) {
exit(failures);
} else {
if (waitpid(pid, &status, 0) < 0) {
warn("waitpid(%d)", pid);
} else if (WIFSIGNALED(status)) {
warnx("pid %d: signal %d", pid, WTERMSIG(status));
} else if (WEXITSTATUS(status) > 0) {
failures += WEXITSTATUS(status);
}
}
}
static
void
dotest(void)
{
unsigned i, me;
pid_t pids[BRANCHES];
int t;
char msg[128];
static void dotest(void) {
unsigned i, me;
pid_t pids[BRANCHES];
int t;
char msg[128];
me = 0;
for (i=0; i<BRANCHES; i++) {
pids[i] = dofork();
if (pids[i] == 0) {
me += 1U<<i;
}
grind();
t = trace();
if (t == right[i]) {
snprintf(msg, sizeof(msg),
"Stage %u #%u done: %d\n", i, me, trace());
}
else {
snprintf(msg, sizeof(msg),
"Stage %u #%u FAILED: got %d, expected %d\n",
i, me, t, right[i]);
failures++;
}
(void)write(STDOUT_FILENO, msg, strlen(msg));
}
me = 0;
for (i = 0; i < BRANCHES; i++) {
pids[i] = dofork();
if (pids[i] == 0) {
me += 1U << i;
}
grind();
t = trace();
if (t == right[i]) {
snprintf(msg, sizeof(msg), "Stage %u #%u done: %d\n", i, me, trace());
} else {
snprintf(msg, sizeof(msg), "Stage %u #%u FAILED: got %d, expected %d\n",
i, me, t, right[i]);
failures++;
}
(void)write(STDOUT_FILENO, msg, strlen(msg));
}
for (i=BRANCHES; i-- > 0; ) {
dowait(pids[i]);
}
if (failures > 0) {
printf("%u failures.\n", failures);
}
else {
printf("Done.\n");
}
for (i = BRANCHES; i-- > 0;) {
dowait(pids[i]);
}
if (failures > 0) {
printf("%u failures.\n", failures);
} else {
printf("Done.\n");
}
}
int
main(void)
{
init();
dotest();
return 0;
int main(void) {
init();
dotest();
return 0;
}

View File

@@ -63,208 +63,184 @@
#define TESTFILE "bigseekfile"
static const char *slogans[] = {
"QUO USQUE TANDEM ABUTERE CATILINA PATENTIA NOSTRA",
"QUEM IN FINEM SESE EFFRENATA IACTABIT AUDACIA"
};
"QUO USQUE TANDEM ABUTERE CATILINA PATENTIA NOSTRA",
"QUEM IN FINEM SESE EFFRENATA IACTABIT AUDACIA"};
static
void
write_slogan(int fd, unsigned which, bool failok)
{
size_t len;
ssize_t r;
static void write_slogan(int fd, unsigned which, bool failok) {
size_t len;
ssize_t r;
len = strlen(slogans[which]);
r = write(fd, slogans[which], len);
if (r < 0) {
if (failok && errno == EFBIG) {
return;
}
err(1, "write");
}
if (failok) {
errx(1, "write: expected failure but wrote %zd bytes", r);
}
if ((size_t)r != len) {
errx(1, "write: result %zd bytes, expected %zu", r, len);
}
len = strlen(slogans[which]);
r = write(fd, slogans[which], len);
if (r < 0) {
if (failok && errno == EFBIG) {
return;
}
err(1, "write");
}
if (failok) {
errx(1, "write: expected failure but wrote %zd bytes", r);
}
if ((size_t)r != len) {
errx(1, "write: result %zd bytes, expected %zu", r, len);
}
}
static
void
check_slogan(int fd, unsigned which)
{
char buf[256];
size_t len;
ssize_t r;
unsigned i, wrongcount;
static void check_slogan(int fd, unsigned which) {
char buf[256];
size_t len;
ssize_t r;
unsigned i, wrongcount;
r = read(fd, buf, sizeof(buf));
if (r < 0) {
err(1, "read");
}
if (r == 0) {
errx(1, "read: Unexpected EOF");
}
r = read(fd, buf, sizeof(buf));
if (r < 0) {
err(1, "read");
}
if (r == 0) {
errx(1, "read: Unexpected EOF");
}
/* we should get either a full buffer or the length of the slogan */
len = strlen(slogans[which]);
if ((size_t)r != sizeof(buf) && (size_t)r != len) {
errx(1, "read: result %zd bytes, expected %zu or %zu",
r, sizeof(buf), len);
}
/* we should get either a full buffer or the length of the slogan */
len = strlen(slogans[which]);
if ((size_t)r != sizeof(buf) && (size_t)r != len) {
errx(1, "read: result %zd bytes, expected %zu or %zu", r, sizeof(buf), len);
}
/* slogan should match */
if (memcmp(buf, slogans[which], len) != 0) {
warnx("read: got wrong data");
warnx("expected: %s", slogans[which]);
buf[sizeof(buf) - 1] = 0;
errx(1, "found: %s", buf);
}
/* slogan should match */
if (memcmp(buf, slogans[which], len) != 0) {
warnx("read: got wrong data");
warnx("expected: %s", slogans[which]);
buf[sizeof(buf) - 1] = 0;
errx(1, "found: %s", buf);
}
/* bytes past the slogan (if any) should be 0 */
wrongcount = 0;
for (i=len; i<(size_t)r; i++) {
if (buf[i] != 0) {
warnx("read: buf[%zu] was 0x%x, expected 0", i,
(unsigned char)buf[i]);
wrongcount++;
}
}
if (wrongcount > 0) {
errx(1, "%u bytes of trash in file", wrongcount);
}
/* bytes past the slogan (if any) should be 0 */
wrongcount = 0;
for (i = len; i < (size_t)r; i++) {
if (buf[i] != 0) {
warnx("read: buf[%zu] was 0x%x, expected 0", i, (unsigned char)buf[i]);
wrongcount++;
}
}
if (wrongcount > 0) {
errx(1, "%u bytes of trash in file", wrongcount);
}
}
static
void
try_reading(int fd)
{
char buf[16];
ssize_t r;
static void try_reading(int fd) {
char buf[16];
ssize_t r;
r = read(fd, buf, sizeof(buf));
if (r == 0) {
/* expected EOF */
return;
}
if (r < 0) {
err(1, "read");
}
errx(1, "read: Expected EOF but got %zd bytes", r);
r = read(fd, buf, sizeof(buf));
if (r == 0) {
/* expected EOF */
return;
}
if (r < 0) {
err(1, "read");
}
errx(1, "read: Expected EOF but got %zd bytes", r);
}
static
void
try_writing(int fd)
{
write_slogan(fd, 1, true);
static void try_writing(int fd) { write_slogan(fd, 1, true); }
static void dolseek(int fd, off_t pos, int whence, const char *whencestr,
off_t expected) {
off_t result;
result = lseek(fd, pos, whence);
if (result == -1) {
err(1, "lseek(fd, 0x%llx, %s)", pos, whencestr);
}
if (result != expected) {
errx(1,
"lseek(fd, 0x%llx, %s): Wrong return value"
" (got 0x%llx, expected 0x%llx)",
pos, whencestr, result, expected);
}
}
static
void
dolseek(int fd, off_t pos, int whence, const char *whencestr, off_t expected)
{
off_t result;
static void try_seeking(int fd, off_t pos, off_t cursize) {
printf("Seeking to (and near) 0x%llx\n", pos);
result = lseek(fd, pos, whence);
if (result == -1) {
err(1, "lseek(fd, 0x%llx, %s)", pos, whencestr);
}
if (result != expected) {
errx(1, "lseek(fd, 0x%llx, %s): Wrong return value"
" (got 0x%llx, expected 0x%llx)", pos, whencestr,
result, expected);
}
/* Go to the place. */
dolseek(fd, pos, SEEK_SET, "SEEK_SET", pos);
/* Go to where we already are. */
dolseek(fd, 0, SEEK_CUR, "SEEK_CUR", pos);
if (pos >= 10) {
/* Back up a little. */
dolseek(fd, -10, SEEK_CUR, "SEEK_CUR", pos - 10);
/* Forward a little. */
dolseek(fd, 20, SEEK_CUR, "SEEK_CUR", pos + 10);
} else {
/* Just forward a little. */
dolseek(fd, 10, SEEK_CUR, "SEEK_CUR", pos + 10);
}
/* Via SEEK_END. */
dolseek(fd, pos, SEEK_END, "SEEK_END", pos + cursize);
/* Go back to the exact place. */
dolseek(fd, pos, SEEK_SET, "SEEK_SET", pos);
}
static
void
try_seeking(int fd, off_t pos, off_t cursize)
{
printf("Seeking to (and near) 0x%llx\n", pos);
int main(void) {
off_t cursize;
int fd;
/* Go to the place. */
dolseek(fd, pos, SEEK_SET, "SEEK_SET", pos);
printf("Creating file...\n");
fd = open(TESTFILE, O_RDWR | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s", TESTFILE);
}
/* Go to where we already are. */
dolseek(fd, 0, SEEK_CUR, "SEEK_CUR", pos);
printf("Writing something at offset 0\n");
write_slogan(fd, 0, false);
cursize = strlen(slogans[0]);
if (pos >= 10) {
/* Back up a little. */
dolseek(fd, -10, SEEK_CUR, "SEEK_CUR", pos - 10);
try_seeking(fd, (off_t)0x1000LL, cursize);
/* Forward a little. */
dolseek(fd, 20, SEEK_CUR, "SEEK_CUR", pos + 10);
}
else {
/* Just forward a little. */
dolseek(fd, 10, SEEK_CUR, "SEEK_CUR", pos + 10);
}
printf("Writing something else\n");
write_slogan(fd, 1, false);
cursize = (off_t)0x1000LL + strlen(slogans[1]);
/* Via SEEK_END. */
dolseek(fd, pos, SEEK_END, "SEEK_END", pos + cursize);
try_seeking(fd, (off_t)0, cursize);
/* Go back to the exact place. */
dolseek(fd, pos, SEEK_SET, "SEEK_SET", pos);
}
int
main(void)
{
off_t cursize;
int fd;
printf("Creating file...\n");
fd = open(TESTFILE, O_RDWR|O_CREAT|O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s", TESTFILE);
}
printf("Writing something at offset 0\n");
write_slogan(fd, 0, false);
cursize = strlen(slogans[0]);
try_seeking(fd, (off_t)0x1000LL, cursize);
printf("Writing something else\n");
write_slogan(fd, 1, false);
cursize = (off_t)0x1000LL + strlen(slogans[1]);
try_seeking(fd, (off_t)0, cursize);
/* If seek is totally bust, this will fail. */
printf("Checking what we wrote\n");
check_slogan(fd, 0);
try_seeking(fd, (off_t)0x1000LL, cursize);
printf("Checking the other thing we wrote\n");
check_slogan(fd, 1);
try_seeking(fd, (off_t)0x20LL, cursize);
try_seeking(fd, (off_t)0x7fffffffLL, cursize);
try_seeking(fd, (off_t)0x80000000LL, cursize);
try_seeking(fd, (off_t)0x80000020LL, cursize);
try_seeking(fd, (off_t)0x100000000LL, cursize);
try_seeking(fd, (off_t)0x100000020LL, cursize);
try_seeking(fd, (off_t)0x180000000LL, cursize);
try_seeking(fd, (off_t)0x180000020LL, cursize);
printf("Now trying to read (should get EOF)\n");
try_reading(fd);
printf("Now trying to write (should get EFBIG)\n");
try_writing(fd);
try_seeking(fd, (off_t)0x100000000LL, cursize);
/* If seek truncates to 32 bits, this might read the slogan instead */
printf("Trying to read again (should get EOF)\n");
try_reading(fd);
printf("Passed.\n");
close(fd);
remove(TESTFILE);
return 0;
/* If seek is totally bust, this will fail. */
printf("Checking what we wrote\n");
check_slogan(fd, 0);
try_seeking(fd, (off_t)0x1000LL, cursize);
printf("Checking the other thing we wrote\n");
check_slogan(fd, 1);
try_seeking(fd, (off_t)0x20LL, cursize);
try_seeking(fd, (off_t)0x7fffffffLL, cursize);
try_seeking(fd, (off_t)0x80000000LL, cursize);
try_seeking(fd, (off_t)0x80000020LL, cursize);
try_seeking(fd, (off_t)0x100000000LL, cursize);
try_seeking(fd, (off_t)0x100000020LL, cursize);
try_seeking(fd, (off_t)0x180000000LL, cursize);
try_seeking(fd, (off_t)0x180000020LL, cursize);
printf("Now trying to read (should get EOF)\n");
try_reading(fd);
printf("Now trying to write (should get EFBIG)\n");
try_writing(fd);
try_seeking(fd, (off_t)0x100000000LL, cursize);
/* If seek truncates to 32 bits, this might read the slogan instead */
printf("Trying to read again (should get EOF)\n");
try_reading(fd);
printf("Passed.\n");
close(fd);
remove(TESTFILE);
return 0;
}

View File

@@ -32,173 +32,145 @@ static unsigned touchpages;
/* when touching pages, the extent to which we favor the middle of the range */
static unsigned bias;
static void moremem(void) {
static unsigned totalpages;
static
void
moremem(void)
{
static unsigned totalpages;
void *ptr;
unsigned i;
void *ptr;
unsigned i;
for (i=0; i<allocs; i++) {
ptr = sbrk(PAGE_SIZE);
if (ptr == (void *)-1) {
err(1, "After %u pages: sbrk", totalpages);
}
totalpages++;
lastpage = ptr;
if (firstpage == NULL) {
firstpage = ptr;
}
}
for (i = 0; i < allocs; i++) {
ptr = sbrk(PAGE_SIZE);
if (ptr == (void *)-1) {
err(1, "After %u pages: sbrk", totalpages);
}
totalpages++;
lastpage = ptr;
if (firstpage == NULL) {
firstpage = ptr;
}
}
}
static
void
touchpage(unsigned pagenum)
{
int *ptr;
static void touchpage(unsigned pagenum) {
int *ptr;
ptr = (void *)((uintptr_t)firstpage + PAGE_SIZE * pagenum);
*ptr = pagenum;
ptr = (void *)((uintptr_t)firstpage + PAGE_SIZE * pagenum);
*ptr = pagenum;
}
static
unsigned
pickpage(unsigned numpages)
{
unsigned mnum, moffset;
unsigned span, val, i;
static unsigned pickpage(unsigned numpages) {
unsigned mnum, moffset;
unsigned span, val, i;
/* take 1 in 1000 pages uniformly from the entire space */
if (random() % 1000 == 0) {
return random() % numpages;
}
/* take 1 in 1000 pages uniformly from the entire space */
if (random() % 1000 == 0) {
return random() % numpages;
}
/* the rest is taken from the middle 1% */
/* the rest is taken from the middle 1% */
mnum = numpages / 100;
if (mnum < touchpages * 2) {
mnum = touchpages * 2;
}
if (mnum >= numpages) {
mnum = numpages;
}
moffset = numpages / 2 - mnum / 2;
mnum = numpages / 100;
if (mnum < touchpages * 2) {
mnum = touchpages * 2;
}
if (mnum >= numpages) {
mnum = numpages;
}
moffset = numpages / 2 - mnum / 2;
assert(bias >= 1);
span = (mnum + bias - 1) / bias;
assert(bias >= 1);
span = (mnum + bias - 1) / bias;
do {
val = 0;
for (i=0; i<bias; i++) {
val += random() % span;
}
} while (val >= mnum);
return moffset + val;
do {
val = 0;
for (i = 0; i < bias; i++) {
val += random() % span;
}
} while (val >= mnum);
return moffset + val;
}
static
void
touchmem(void)
{
unsigned i, num;
static void touchmem(void) {
unsigned i, num;
num = (((uintptr_t)lastpage - (uintptr_t)firstpage) / PAGE_SIZE) + 1;
num = (((uintptr_t)lastpage - (uintptr_t)firstpage) / PAGE_SIZE) + 1;
if (num % 256 == 0) {
warnx("%u pages", num);
}
if (num % 256 == 0) {
warnx("%u pages", num);
}
for (i=0; i<touchpages; i++) {
touchpage(pickpage(num));
}
for (i = 0; i < touchpages; i++) {
touchpage(pickpage(num));
}
}
static
void
run(void)
{
while (1) {
moremem();
touchmem();
}
static void run(void) {
while (1) {
moremem();
touchmem();
}
}
static
void
printsettings(void)
{
printf("Page size: %u\n", PAGE_SIZE);
printf("Allocating %u pages and touching %u pages on each cycle.\n",
allocs, touchpages);
printf("Page selection bias: %u\n", bias);
printf("\n");
static void printsettings(void) {
printf("Page size: %u\n", PAGE_SIZE);
printf("Allocating %u pages and touching %u pages on each cycle.\n", allocs,
touchpages);
printf("Page selection bias: %u\n", bias);
printf("\n");
}
static
void
usage(void)
{
warnx("bloat [-a allocs] [-b bias] [-p pages]");
warnx(" allocs: number of pages allocated per cycle (default 4)");
warnx(" bias: number of dice rolled to touch pages (default 8)");
warnx(" pages: pages touched per cycle (default 8)");
exit(1);
static void usage(void) {
warnx("bloat [-a allocs] [-b bias] [-p pages]");
warnx(" allocs: number of pages allocated per cycle (default 4)");
warnx(" bias: number of dice rolled to touch pages (default 8)");
warnx(" pages: pages touched per cycle (default 8)");
exit(1);
}
int
main(int argc, char *argv[])
{
int i;
int main(int argc, char *argv[]) {
int i;
/* default mode */
allocs = 4;
touchpages = 8;
bias = 8;
/* default mode */
allocs = 4;
touchpages = 8;
bias = 8;
srandom(1234);
srandom(1234);
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-a")) {
i++;
if (i == argc) {
errx(1, "-a: option requires argument");
}
allocs = atoi(argv[i]);
if (allocs == 0) {
errx(1, "-a: must not be zero");
}
}
else if (!strcmp(argv[i], "-b")) {
i++;
if (i == argc) {
errx(1, "-b: option requires argument");
}
bias = atoi(argv[i]);
if (bias == 0) {
errx(1, "-b: must not be zero");
}
}
else if (!strcmp(argv[i], "-h")) {
usage();
}
else if (!strcmp(argv[i], "-p")) {
i++;
if (i == argc) {
errx(1, "-p: option requires argument");
}
touchpages = atoi(argv[i]);
}
else {
errx(1, "Argument %s not recognized", argv[i]);
usage();
}
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-a")) {
i++;
if (i == argc) {
errx(1, "-a: option requires argument");
}
allocs = atoi(argv[i]);
if (allocs == 0) {
errx(1, "-a: must not be zero");
}
} else if (!strcmp(argv[i], "-b")) {
i++;
if (i == argc) {
errx(1, "-b: option requires argument");
}
bias = atoi(argv[i]);
if (bias == 0) {
errx(1, "-b: must not be zero");
}
} else if (!strcmp(argv[i], "-h")) {
usage();
} else if (!strcmp(argv[i], "-p")) {
i++;
if (i == argc) {
errx(1, "-p: option requires argument");
}
touchpages = atoi(argv[i]);
} else {
errx(1, "Argument %s not recognized", argv[i]);
usage();
}
}
printsettings();
run();
return 0;
printsettings();
run();
return 0;
}

View File

@@ -37,22 +37,20 @@
#include <unistd.h>
#include <err.h>
int
main(void)
{
char ch=0;
int len;
int main(void) {
char ch = 0;
int len;
while (ch!='q') {
len = read(STDIN_FILENO, &ch, 1);
if (len < 0) {
err(1, "stdin: read");
}
if (len==0) {
/* EOF */
break;
}
write(STDOUT_FILENO, &ch, 1);
}
return 0;
while (ch != 'q') {
len = read(STDIN_FILENO, &ch, 1);
if (len < 0) {
err(1, "stdin: read");
}
if (len == 0) {
/* EOF */
break;
}
write(STDOUT_FILENO, &ch, 1);
}
return 0;
}

View File

@@ -48,341 +48,276 @@
#include <err.h>
#if defined(__mips__)
#define KERNEL_ADDR 0x80000000
#define INVAL_ADDR 0x40000000
#define INSN_TYPE uint32_t
#define INVAL_INSN 0x0000003f
#define KERNEL_ADDR 0x80000000
#define INVAL_ADDR 0x40000000
#define INSN_TYPE uint32_t
#define INVAL_INSN 0x0000003f
#else
#error "Please fix this"
#endif
#define MAGIC 123456
#define MAGIC 123456
typedef void (*func)(void);
static int forking = 1;
static
void
read_from_null(void)
{
int *null = NULL;
volatile int x;
static void read_from_null(void) {
int *null = NULL;
volatile int x;
x = *null;
x = *null;
// gcc 4.8 improperly demands this
(void)x;
// gcc 4.8 improperly demands this
(void)x;
}
static
void
read_from_inval(void)
{
int *ptr = (int *) INVAL_ADDR;
volatile int x;
static void read_from_inval(void) {
int *ptr = (int *)INVAL_ADDR;
volatile int x;
x = *ptr;
x = *ptr;
// gcc 4.8 improperly demands this
(void)x;
// gcc 4.8 improperly demands this
(void)x;
}
static
void
read_from_kernel(void)
{
int *ptr = (int *) KERNEL_ADDR;
volatile int x;
static void read_from_kernel(void) {
int *ptr = (int *)KERNEL_ADDR;
volatile int x;
x = *ptr;
x = *ptr;
// gcc 4.8 improperly demands this
(void)x;
// gcc 4.8 improperly demands this
(void)x;
}
static
void
write_to_null(void)
{
int *null = NULL;
*null = 6;
static void write_to_null(void) {
int *null = NULL;
*null = 6;
}
static
void
write_to_inval(void)
{
int *ptr = (int *) INVAL_ADDR;
*ptr = 8;
static void write_to_inval(void) {
int *ptr = (int *)INVAL_ADDR;
*ptr = 8;
}
static
void
write_to_code(void)
{
INSN_TYPE *x = (INSN_TYPE *)write_to_code;
*x = INVAL_INSN;
static void write_to_code(void) {
INSN_TYPE *x = (INSN_TYPE *)write_to_code;
*x = INVAL_INSN;
}
static
void
write_to_kernel(void)
{
int *ptr = (int *) KERNEL_ADDR;
*ptr = 8;
static void write_to_kernel(void) {
int *ptr = (int *)KERNEL_ADDR;
*ptr = 8;
}
static
void
jump_to_null(void)
{
func f = NULL;
f();
static void jump_to_null(void) {
func f = NULL;
f();
}
static
void
jump_to_inval(void)
{
func f = (func) INVAL_ADDR;
f();
static void jump_to_inval(void) {
func f = (func)INVAL_ADDR;
f();
}
static
void
jump_to_kernel(void)
{
func f = (func) KERNEL_ADDR;
f();
static void jump_to_kernel(void) {
func f = (func)KERNEL_ADDR;
f();
}
static
void
illegal_instruction(void)
{
static void illegal_instruction(void) {
#if defined(__mips__)
asm(".long 0x0000003f");
asm(".long 0x0000003f");
#else
#error "Please fix this"
#endif
}
static
void
alignment_error(void)
{
int x;
int *ptr, *badptr;
volatile uintptr_t ptrval;
volatile int j;
static void alignment_error(void) {
int x;
int *ptr, *badptr;
volatile uintptr_t ptrval;
volatile int j;
x = 0;
ptr = &x;
/*
* Try to hide what's going on from gcc; gcc 4.8 seems to
* detect the unaligned access and issue unaligned read
* instructions for it, so then it doesn't fault. Feh.
*/
ptrval = (uintptr_t)ptr;
ptrval++;
badptr = (int *)ptrval;
x = 0;
ptr = &x;
/*
* Try to hide what's going on from gcc; gcc 4.8 seems to
* detect the unaligned access and issue unaligned read
* instructions for it, so then it doesn't fault. Feh.
*/
ptrval = (uintptr_t)ptr;
ptrval++;
badptr = (int *)ptrval;
j = *badptr;
j = *badptr;
// gcc 4.8 improperly demands this
(void)j;
// gcc 4.8 improperly demands this
(void)j;
}
static
void
divide_by_zero(void)
{
volatile int x = 6;
volatile int z = 0;
volatile int a;
static void divide_by_zero(void) {
volatile int x = 6;
volatile int z = 0;
volatile int a;
a = x/z;
a = x / z;
// gcc 4.8 improperly demands this
(void)a;
// gcc 4.8 improperly demands this
(void)a;
}
static
void
mod_by_zero(void)
{
volatile int x = 6;
volatile int z = 0;
volatile int a;
static void mod_by_zero(void) {
volatile int x = 6;
volatile int z = 0;
volatile int a;
a = x%z;
a = x % z;
// gcc 4.8 improperly demands this
(void)a;
// gcc 4.8 improperly demands this
(void)a;
}
static
void
recurse_inf(void)
{
volatile char buf[16];
static void recurse_inf(void) {
volatile char buf[16];
buf[0] = 0;
recurse_inf();
buf[0] = 1;
buf[0] = 0;
recurse_inf();
buf[0] = 1;
// gcc 4.8 improperly demands this
(void)buf;
// gcc 4.8 improperly demands this
(void)buf;
}
static struct {
int ch;
const char *name;
func f;
int sig;
} ops[] = {{'a', "read from NULL", read_from_null, SIGSEGV},
{'b', "read from invalid address", read_from_inval, SIGSEGV},
{'c', "read from kernel address", read_from_kernel, SIGBUS},
{'d', "write to NULL", write_to_null, SIGSEGV},
{'e', "write to invalid address", write_to_inval, SIGSEGV},
{'f', "write to code segment", write_to_code, SIGSEGV},
{'g', "write to kernel address", write_to_kernel, SIGBUS},
{'h', "jump to NULL", jump_to_null, SIGSEGV},
{'i', "jump to invalid address", jump_to_inval, SIGSEGV},
{'j', "jump to kernel address", jump_to_kernel, SIGBUS},
{'k', "alignment error", alignment_error, SIGBUS},
{'l', "illegal instruction", illegal_instruction, SIGILL},
{'m', "divide by zero", divide_by_zero, SIGTRAP},
{'n', "mod by zero", mod_by_zero, SIGTRAP},
{'o', "Recurse infinitely", recurse_inf, SIGSEGV},
{0, NULL, NULL, 0}};
static
struct {
int ch;
const char *name;
func f;
int sig;
} ops[] = {
{ 'a', "read from NULL", read_from_null, SIGSEGV },
{ 'b', "read from invalid address", read_from_inval, SIGSEGV },
{ 'c', "read from kernel address", read_from_kernel, SIGBUS },
{ 'd', "write to NULL", write_to_null, SIGSEGV },
{ 'e', "write to invalid address", write_to_inval, SIGSEGV },
{ 'f', "write to code segment", write_to_code, SIGSEGV },
{ 'g', "write to kernel address", write_to_kernel, SIGBUS },
{ 'h', "jump to NULL", jump_to_null, SIGSEGV },
{ 'i', "jump to invalid address", jump_to_inval, SIGSEGV },
{ 'j', "jump to kernel address", jump_to_kernel, SIGBUS },
{ 'k', "alignment error", alignment_error, SIGBUS },
{ 'l', "illegal instruction", illegal_instruction, SIGILL },
{ 'm', "divide by zero", divide_by_zero, SIGTRAP },
{ 'n', "mod by zero", mod_by_zero, SIGTRAP },
{ 'o', "Recurse infinitely", recurse_inf, SIGSEGV },
{ 0, NULL, NULL, 0 }
};
static void runop(int op) {
int opindex;
pid_t pid;
int status;
int ok;
static
void
runop(int op)
{
int opindex;
pid_t pid;
int status;
int ok;
if (op == '*') {
for (unsigned i = 0; ops[i].name; i++) {
runop(ops[i].ch);
}
return;
} else if (op == '-') {
forking = 0;
warnx("Forking disabled - next try will be the last");
return;
} else if (op == '+') {
forking = 1;
warnx("Forking enabled.");
return;
}
if (op=='*') {
for (unsigned i=0; ops[i].name; i++) {
runop(ops[i].ch);
}
return;
}
else if (op == '-') {
forking = 0;
warnx("Forking disabled - next try will be the last");
return;
}
else if (op == '+') {
forking = 1;
warnx("Forking enabled.");
return;
}
/* intentionally don't check if op is in bounds :) */
opindex = op - 'a';
/* intentionally don't check if op is in bounds :) */
opindex = op-'a';
printf("Running: [%c] %s\n", ops[opindex].ch, ops[opindex].name);
printf("Running: [%c] %s\n", ops[opindex].ch, ops[opindex].name);
if (forking) {
pid = fork();
if (pid < 0) {
/* error */
err(1, "fork");
} else if (pid > 0) {
/* parent */
if (waitpid(pid, &status, 0) < 0) {
err(1, "waitpid");
}
ok = 0;
if (WIFSIGNALED(status)) {
printf("Signal %d\n", WTERMSIG(status));
if (WTERMSIG(status) == ops[opindex].sig) {
ok = 1;
}
} else {
printf("Exit %d\n", WEXITSTATUS(status));
if (WEXITSTATUS(status) == MAGIC) {
ok = 1;
}
}
if (ok) {
printf("Ok.\n");
} else {
printf("FAILED: expected signal %d\n", ops[opindex].sig);
}
printf("\n");
return;
}
}
/* child, or not forking */
if (forking) {
pid = fork();
if (pid < 0) {
/* error */
err(1, "fork");
}
else if (pid > 0) {
/* parent */
if (waitpid(pid, &status, 0) < 0) {
err(1, "waitpid");
}
ok = 0;
if (WIFSIGNALED(status)) {
printf("Signal %d\n", WTERMSIG(status));
if (WTERMSIG(status) == ops[opindex].sig) {
ok = 1;
}
}
else {
printf("Exit %d\n", WEXITSTATUS(status));
if (WEXITSTATUS(status) == MAGIC) {
ok = 1;
}
}
if (ok) {
printf("Ok.\n");
}
else {
printf("FAILED: expected signal %d\n",
ops[opindex].sig);
}
printf("\n");
return;
}
}
/* child, or not forking */
ops[opindex].f();
ops[opindex].f();
if (op == 'f') {
warnx(".... I guess you don't support read-only segments");
/* use this magic signaling value so parent doesn't say FAIL */
_exit(MAGIC);
}
errx(1, "I wasn't killed!");
if (op == 'f') {
warnx(".... I guess you don't support read-only segments");
/* use this magic signaling value so parent doesn't say FAIL */
_exit(MAGIC);
}
errx(1, "I wasn't killed!");
}
static
void
ask(void)
{
unsigned i;
int op;
static void ask(void) {
unsigned i;
int op;
while (1) {
while (1) {
for (i=0; ops[i].name; i++) {
printf("[%c] %s\n", ops[i].ch, ops[i].name);
}
printf("[-] Disable forking\n");
printf("[+] Enable forking (default)\n");
printf("[*] Run everything\n");
printf("[!] Quit\n");
for (i = 0; ops[i].name; i++) {
printf("[%c] %s\n", ops[i].ch, ops[i].name);
}
printf("[-] Disable forking\n");
printf("[+] Enable forking (default)\n");
printf("[*] Run everything\n");
printf("[!] Quit\n");
printf("Choose: ");
op = getchar();
printf("Choose: ");
op = getchar();
if (op == '!') {
break;
}
if (op == '!') {
break;
}
runop(op);
}
runop(op);
}
}
int
main(int argc, char **argv)
{
if (argc == 0 || argc == 1) {
/* no arguments */
ask();
}
else {
/* run the selected ops */
for (int i=1; i<argc; i++) {
for (size_t j=0; argv[i][j]; j++) {
runop(argv[i][j]);
}
}
}
return 0;
int main(int argc, char **argv) {
if (argc == 0 || argc == 1) {
/* no arguments */
ask();
} else {
/* run the selected ops */
for (int i = 1; i < argc; i++) {
for (size_t j = 0; argv[i][j]; j++) {
runop(argv[i][j]);
}
}
}
return 0;
}

View File

@@ -44,58 +44,56 @@
* DEFAULT is the default stride.
* Note that SIZE and DEFAULT should be relatively prime.
*/
#define SIZE (1024*1024/sizeof(struct entry))
#define DEFAULT 477
#define SIZE (1024 * 1024 / sizeof(struct entry))
#define DEFAULT 477
struct entry {
struct entry *e;
struct entry *e;
};
struct entry array[SIZE];
int
main(int argc, char **argv)
{
volatile struct entry *e;
unsigned i, stride;
int main(int argc, char **argv) {
volatile struct entry *e;
unsigned i, stride;
stride = DEFAULT;
if (argc == 2) {
stride = atoi(argv[1]);
}
if (stride <= 0 || argc > 2) {
printf("Usage: ctest [stridesize]\n");
printf(" stridesize should not be a multiple of 2.\n");
return 1;
}
stride = DEFAULT;
if (argc == 2) {
stride = atoi(argv[1]);
}
if (stride <= 0 || argc > 2) {
printf("Usage: ctest [stridesize]\n");
printf(" stridesize should not be a multiple of 2.\n");
return 1;
}
printf("Starting ctest: stride %d\n", stride);
printf("Starting ctest: stride %d\n", stride);
/*
* Generate a huge linked list, with each entry pointing to
* the slot STRIDE entries above it. As long as STRIDE and SIZE
* are relatively prime, this will put all the entries on one
* list. Otherwise you will get multiple disjoint lists. (All
* these lists will be circular.)
*/
for (i=0; i<SIZE; i++) {
array[i].e = &array[(i+stride) % SIZE];
}
/*
* Generate a huge linked list, with each entry pointing to
* the slot STRIDE entries above it. As long as STRIDE and SIZE
* are relatively prime, this will put all the entries on one
* list. Otherwise you will get multiple disjoint lists. (All
* these lists will be circular.)
*/
for (i = 0; i < SIZE; i++) {
array[i].e = &array[(i + stride) % SIZE];
}
/*
* Traverse the list. We stop after hitting each element once.
*
* (If STRIDE was even, this will hit some elements more than
* once and others not at all.)
*/
e = &array[0];
for (i=0; i<SIZE; i++) {
if (i % stride == 0) {
putchar('.');
}
e = e->e;
}
/*
* Traverse the list. We stop after hitting each element once.
*
* (If STRIDE was even, this will hit some elements more than
* once and others not at all.)
*/
e = &array[0];
for (i = 0; i < SIZE; i++) {
if (i % stride == 0) {
putchar('.');
}
e = e->e;
}
printf("\nDone!\n");
return 0;
printf("\nDone!\n");
return 0;
}

View File

@@ -44,40 +44,37 @@
#include <stdarg.h>
#include <string.h>
#define NTRIES 100 /* loop count */
#define NPROCS 5 /* actually totals 4x this +1 processes */
#define NTRIES 100 /* loop count */
#define NPROCS 5 /* actually totals 4x this +1 processes */
#define TESTDIR "dirconc"
#define NNAMES 4
#define NAMESIZE 32
#define TESTDIR "dirconc"
#define NNAMES 4
#define NAMESIZE 32
////////////////////////////////////////////////////////////
static const char *const names[NNAMES] = {
"aaaa",
"bbbb",
"cccc",
"dddd",
"aaaa",
"bbbb",
"cccc",
"dddd",
};
static
void
choose_name(char *buf, size_t len)
{
const char *a, *b, *c;
static void choose_name(char *buf, size_t len) {
const char *a, *b, *c;
a = names[random()%NNAMES];
if (random()%2==0) {
snprintf(buf, len, "%s", a);
return;
}
b = names[random()%NNAMES];
if (random()%2==0) {
snprintf(buf, len, "%s/%s", a, b);
return;
}
c = names[random()%NNAMES];
snprintf(buf, len, "%s/%s/%s", a, b, c);
a = names[random() % NNAMES];
if (random() % 2 == 0) {
snprintf(buf, len, "%s", a);
return;
}
b = names[random() % NNAMES];
if (random() % 2 == 0) {
snprintf(buf, len, "%s/%s", a, b);
return;
}
c = names[random() % NNAMES];
snprintf(buf, len, "%s/%s/%s", a, b, c);
}
////////////////////////////////////////////////////////////
@@ -86,277 +83,224 @@ choose_name(char *buf, size_t len)
* The purpose of this is to be atomic. In our world, straight
* printf tends not to be.
*/
static
void
static void
#ifdef __GNUC__
__attribute__((__format__(__printf__, 1, 2)))
__attribute__((__format__(__printf__, 1, 2)))
#endif
say(const char *fmt, ...)
{
char buf[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
write(STDOUT_FILENO, buf, strlen(buf));
say(const char *fmt, ...) {
char buf[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
write(STDOUT_FILENO, buf, strlen(buf));
}
////////////////////////////////////////////////////////////
static
void
dorename(const char *name1, const char *name2)
{
if (rename(name1, name2) < 0) {
switch (errno) {
case ENOENT:
case ENOTEMPTY:
case EINVAL:
break;
default:
say("pid %d: rename %s -> %s: %s\n",
getpid(), name1, name2, strerror(errno));
break;
}
}
static void dorename(const char *name1, const char *name2) {
if (rename(name1, name2) < 0) {
switch (errno) {
case ENOENT:
case ENOTEMPTY:
case EINVAL:
break;
default:
say("pid %d: rename %s -> %s: %s\n", getpid(), name1, name2,
strerror(errno));
break;
}
}
}
static
void
domkdir(const char *name)
{
if (mkdir(name, 0775)<0) {
switch (errno) {
case ENOENT:
case EEXIST:
break;
default:
say("pid %d: mkdir %s: %s\n",
getpid(), name, strerror(errno));
break;
}
}
static void domkdir(const char *name) {
if (mkdir(name, 0775) < 0) {
switch (errno) {
case ENOENT:
case EEXIST:
break;
default:
say("pid %d: mkdir %s: %s\n", getpid(), name, strerror(errno));
break;
}
}
}
static
void
dormdir(const char *name)
{
if (rmdir(name)<0) {
switch (errno) {
case ENOENT:
case ENOTEMPTY:
break;
default:
say("pid %d: rmdir %s: %s\n",
getpid(), name, strerror(errno));
break;
}
}
static void dormdir(const char *name) {
if (rmdir(name) < 0) {
switch (errno) {
case ENOENT:
case ENOTEMPTY:
break;
default:
say("pid %d: rmdir %s: %s\n", getpid(), name, strerror(errno));
break;
}
}
}
static
void
cleanup_rmdir(const char *name)
{
if (rmdir(name)<0) {
switch (errno) {
case ENOENT:
break;
default:
say("cleanup (pid %d): rmdir %s: %s\n",
getpid(), name, strerror(errno));
break;
}
}
static void cleanup_rmdir(const char *name) {
if (rmdir(name) < 0) {
switch (errno) {
case ENOENT:
break;
default:
say("cleanup (pid %d): rmdir %s: %s\n", getpid(), name, strerror(errno));
break;
}
}
}
////////////////////////////////////////////////////////////
static
void
rename_proc(void)
{
char name1[NAMESIZE], name2[NAMESIZE];
int ct;
static void rename_proc(void) {
char name1[NAMESIZE], name2[NAMESIZE];
int ct;
for (ct=0; ct<NTRIES; ct++) {
choose_name(name1, sizeof(name1));
choose_name(name2, sizeof(name2));
say("pid %2d: rename %s -> %s\n", (int)getpid(), name1, name2);
dorename(name1, name2);
}
for (ct = 0; ct < NTRIES; ct++) {
choose_name(name1, sizeof(name1));
choose_name(name2, sizeof(name2));
say("pid %2d: rename %s -> %s\n", (int)getpid(), name1, name2);
dorename(name1, name2);
}
}
static
void
mkdir_proc(void)
{
char name[NAMESIZE];
int ct;
static void mkdir_proc(void) {
char name[NAMESIZE];
int ct;
for (ct=0; ct<NTRIES; ct++) {
choose_name(name, sizeof(name));
say("pid %2d: mkdir %s\n", (int)getpid(), name);
domkdir(name);
}
for (ct = 0; ct < NTRIES; ct++) {
choose_name(name, sizeof(name));
say("pid %2d: mkdir %s\n", (int)getpid(), name);
domkdir(name);
}
}
static
void
rmdir_proc(void)
{
char name[NAMESIZE];
int ct;
static void rmdir_proc(void) {
char name[NAMESIZE];
int ct;
for (ct=0; ct<NTRIES; ct++) {
choose_name(name, sizeof(name));
say("pid %2d: rmdir %s\n", (int)getpid(), name);
dormdir(name);
}
for (ct = 0; ct < NTRIES; ct++) {
choose_name(name, sizeof(name));
say("pid %2d: rmdir %s\n", (int)getpid(), name);
dormdir(name);
}
}
////////////////////////////////////////////////////////////
static
pid_t
dofork(void (*func)(void))
{
pid_t pid;
static pid_t dofork(void (*func)(void)) {
pid_t pid;
pid = fork();
if (pid < 0) {
say("fork: %s\n", strerror(errno));
return -1;
}
if (pid == 0) {
/* child */
func();
exit(0);
}
return pid;
pid = fork();
if (pid < 0) {
say("fork: %s\n", strerror(errno));
return -1;
}
if (pid == 0) {
/* child */
func();
exit(0);
}
return pid;
}
static
void
run(void)
{
pid_t pids[NPROCS*4], wp;
int i, status;
static void run(void) {
pid_t pids[NPROCS * 4], wp;
int i, status;
for (i=0; i<NPROCS; i++) {
pids[i*4] = dofork(mkdir_proc);
pids[i*4+1] = dofork(mkdir_proc);
pids[i*4+2] = dofork(rename_proc);
pids[i*4+3] = dofork(rmdir_proc);
}
for (i = 0; i < NPROCS; i++) {
pids[i * 4] = dofork(mkdir_proc);
pids[i * 4 + 1] = dofork(mkdir_proc);
pids[i * 4 + 2] = dofork(rename_proc);
pids[i * 4 + 3] = dofork(rmdir_proc);
}
for (i=0; i<NPROCS*4; i++) {
if (pids[i]>=0) {
wp = waitpid(pids[i], &status, 0);
if (wp<0) {
say("waitpid %d: %s\n", (int) pids[i],
strerror(errno));
}
else if (WIFSIGNALED(status)) {
say("pid %d: signal %d\n", (int) pids[i],
WTERMSIG(status));
}
else if (WIFEXITED(status) && WEXITSTATUS(status)!=0) {
say("pid %d: exit %d\n", (int) pids[i],
WEXITSTATUS(status));
}
}
}
for (i = 0; i < NPROCS * 4; i++) {
if (pids[i] >= 0) {
wp = waitpid(pids[i], &status, 0);
if (wp < 0) {
say("waitpid %d: %s\n", (int)pids[i], strerror(errno));
} else if (WIFSIGNALED(status)) {
say("pid %d: signal %d\n", (int)pids[i], WTERMSIG(status));
} else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
say("pid %d: exit %d\n", (int)pids[i], WEXITSTATUS(status));
}
}
}
}
////////////////////////////////////////////////////////////
static
void
setup(const char *fs)
{
if (chdir(fs)<0) {
say("chdir: %s: %s\n", fs, strerror(errno));
exit(1);
}
if (mkdir(TESTDIR, 0775)<0) {
say("mkdir: %s: %s\n", TESTDIR, strerror(errno));
exit(1);
}
if (chdir(TESTDIR)<0) {
say("chdir: %s: %s\n", TESTDIR, strerror(errno));
exit(1);
}
static void setup(const char *fs) {
if (chdir(fs) < 0) {
say("chdir: %s: %s\n", fs, strerror(errno));
exit(1);
}
if (mkdir(TESTDIR, 0775) < 0) {
say("mkdir: %s: %s\n", TESTDIR, strerror(errno));
exit(1);
}
if (chdir(TESTDIR) < 0) {
say("chdir: %s: %s\n", TESTDIR, strerror(errno));
exit(1);
}
}
static
void
recursive_cleanup(const char *sofar, int depth)
{
char buf[NAMESIZE*32];
int i;
static void recursive_cleanup(const char *sofar, int depth) {
char buf[NAMESIZE * 32];
int i;
for (i=0; i<NNAMES; i++) {
snprintf(buf, sizeof(buf), "%s/%s", sofar, names[i]);
if (rmdir(buf)<0) {
if (errno==ENOTEMPTY) {
recursive_cleanup(buf, depth+1);
cleanup_rmdir(buf);
}
else if (errno!=ENOENT) {
say("cleanup (pid %d): rmdir %s: %s\n",
getpid(), buf, strerror(errno));
}
}
}
for (i = 0; i < NNAMES; i++) {
snprintf(buf, sizeof(buf), "%s/%s", sofar, names[i]);
if (rmdir(buf) < 0) {
if (errno == ENOTEMPTY) {
recursive_cleanup(buf, depth + 1);
cleanup_rmdir(buf);
} else if (errno != ENOENT) {
say("cleanup (pid %d): rmdir %s: %s\n", getpid(), buf, strerror(errno));
}
}
}
}
static
void
cleanup(void)
{
recursive_cleanup(".", 0);
static void cleanup(void) {
recursive_cleanup(".", 0);
chdir("..");
cleanup_rmdir(TESTDIR);
chdir("..");
cleanup_rmdir(TESTDIR);
}
////////////////////////////////////////////////////////////
int
main(int argc, char *argv[])
{
const char *fs;
long seed = 0;
int main(int argc, char *argv[]) {
const char *fs;
long seed = 0;
say("Concurrent directory ops test\n");
say("Concurrent directory ops test\n");
if (argc==0 || argv==NULL) {
say("Warning: argc is 0 - assuming you mean to run on lhd1: "
"with seed 0\n");
fs = "lhd1:";
}
else if (argc==2) {
fs = argv[1];
}
else if (argc==3) {
fs = argv[1];
seed = atoi(argv[2]);
}
else {
say("Usage: dirconc filesystem [random-seed]\n");
exit(1);
}
if (argc == 0 || argv == NULL) {
say("Warning: argc is 0 - assuming you mean to run on lhd1: "
"with seed 0\n");
fs = "lhd1:";
} else if (argc == 2) {
fs = argv[1];
} else if (argc == 3) {
fs = argv[1];
seed = atoi(argv[2]);
} else {
say("Usage: dirconc filesystem [random-seed]\n");
exit(1);
}
srandom(seed);
setup(fs);
say("Starting in %s/%s\n", fs, TESTDIR);
srandom(seed);
setup(fs);
say("Starting in %s/%s\n", fs, TESTDIR);
run();
run();
say("Cleaning up\n");
cleanup();
say("Cleaning up\n");
cleanup();
return 0;
return 0;
}

View File

@@ -57,32 +57,17 @@
#define TESTDIR "seektestdir"
static struct {
const char *name;
int make_it;
off_t pos;
const char *name;
int make_it;
off_t pos;
} testfiles[] = {
{ ".", 0, -1 },
{ "..", 0, -1 },
{ "ridcully", 1, -1 },
{ "weatherwax", 1, -1 },
{ "ogg", 1, -1 },
{ "vorbis", 1, -1 },
{ "verence", 1, -1 },
{ "magrat", 1, -1 },
{ "agnes", 1, -1 },
{ "rincewind", 1, -1 },
{ "angua", 1, -1 },
{ "cherry", 1, -1 },
{ "dorfl", 1, -1 },
{ "nobby", 1, -1 },
{ "carrot", 1, -1 },
{ "vimes", 1, -1 },
{ "detritus", 1, -1 },
{ "twoflower", 1, -1 },
{ "teatime", 1, -1 },
{ "qu", 1, -1 },
{ NULL, 0, 0 }
};
{".", 0, -1}, {"..", 0, -1}, {"ridcully", 1, -1},
{"weatherwax", 1, -1}, {"ogg", 1, -1}, {"vorbis", 1, -1},
{"verence", 1, -1}, {"magrat", 1, -1}, {"agnes", 1, -1},
{"rincewind", 1, -1}, {"angua", 1, -1}, {"cherry", 1, -1},
{"dorfl", 1, -1}, {"nobby", 1, -1}, {"carrot", 1, -1},
{"vimes", 1, -1}, {"detritus", 1, -1}, {"twoflower", 1, -1},
{"teatime", 1, -1}, {"qu", 1, -1}, {NULL, 0, 0}};
/************************************************************/
/* Test code */
@@ -90,466 +75,412 @@ static struct {
static int dirfd;
static
int
findentry(const char *name)
{
int i;
static int findentry(const char *name) {
int i;
for (i=0; testfiles[i].name; i++) {
if (!strcmp(testfiles[i].name, name)) {
return i;
}
}
return -1;
for (i = 0; testfiles[i].name; i++) {
if (!strcmp(testfiles[i].name, name)) {
return i;
}
}
return -1;
}
static
void
openit(void)
{
dirfd = open(".", O_RDONLY);
if (dirfd < 0) {
err(1, ".: open");
}
static void openit(void) {
dirfd = open(".", O_RDONLY);
if (dirfd < 0) {
err(1, ".: open");
}
}
static
void
closeit(void)
{
if (close(dirfd)<0) {
err(1, ".: close");
}
dirfd = -1;
static void closeit(void) {
if (close(dirfd) < 0) {
err(1, ".: close");
}
dirfd = -1;
}
static
void
readit(void)
{
char buf[4096];
off_t pos;
int len;
int n, i, ix;
static void readit(void) {
char buf[4096];
off_t pos;
int len;
int n, i, ix;
for (i=0; testfiles[i].name; i++) {
testfiles[i].pos = -1;
}
for (i = 0; testfiles[i].name; i++) {
testfiles[i].pos = -1;
}
pos = lseek(dirfd, 0, SEEK_CUR);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_CUR)");
}
n = 0;
pos = lseek(dirfd, 0, SEEK_CUR);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_CUR)");
}
n = 0;
while ((len = getdirentry(dirfd, buf, sizeof(buf)-1)) > 0) {
while ((len = getdirentry(dirfd, buf, sizeof(buf) - 1)) > 0) {
if ((unsigned)len >= sizeof(buf)-1) {
errx(1, ".: entry %d: getdirentry returned "
"invalid length %d", n, len);
}
buf[len] = 0;
ix = findentry(buf);
if (ix < 0) {
errx(1, ".: entry %d: getdirentry returned "
"unexpected name %s", n, buf);
}
if ((unsigned)len >= sizeof(buf) - 1) {
errx(1,
".: entry %d: getdirentry returned "
"invalid length %d",
n, len);
}
buf[len] = 0;
ix = findentry(buf);
if (ix < 0) {
errx(1,
".: entry %d: getdirentry returned "
"unexpected name %s",
n, buf);
}
if (testfiles[ix].pos >= 0) {
errx(1, ".: entry %d: getdirentry returned "
"%s a second time", n, buf);
}
if (testfiles[ix].pos >= 0) {
errx(1,
".: entry %d: getdirentry returned "
"%s a second time",
n, buf);
}
testfiles[ix].pos = pos;
testfiles[ix].pos = pos;
pos = lseek(dirfd, 0, SEEK_CUR);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_CUR)");
}
n++;
}
if (len<0) {
err(1, ".: entry %d: getdirentry", n);
}
pos = lseek(dirfd, 0, SEEK_CUR);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_CUR)");
}
n++;
}
if (len < 0) {
err(1, ".: entry %d: getdirentry", n);
}
for (i=0; testfiles[i].name; i++) {
if (testfiles[i].pos < 0) {
errx(1, ".: getdirentry failed to return %s",
testfiles[i].name);
}
}
if (i!=n) {
/*
* If all of the other checks have passed, this should not
* be able to fail. But... just in case I forgot something
* or there's a bug...
*/
for (i = 0; testfiles[i].name; i++) {
if (testfiles[i].pos < 0) {
errx(1, ".: getdirentry failed to return %s", testfiles[i].name);
}
}
if (i != n) {
/*
* If all of the other checks have passed, this should not
* be able to fail. But... just in case I forgot something
* or there's a bug...
*/
errx(1, ".: getdirentry returned %d names, not %d (huh...?)",
n, i);
}
errx(1, ".: getdirentry returned %d names, not %d (huh...?)", n, i);
}
}
static
void
firstread(void)
{
off_t pos;
static void firstread(void) {
off_t pos;
pos = lseek(dirfd, 0, SEEK_CUR);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_CUR)");
}
if (pos != 0) {
errx(1, ".: File position after open not 0");
}
pos = lseek(dirfd, 0, SEEK_CUR);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_CUR)");
}
if (pos != 0) {
errx(1, ".: File position after open not 0");
}
printf("Scanning directory...\n");
printf("Scanning directory...\n");
readit();
readit();
}
static
void
doreadat0(void)
{
off_t pos;
static void doreadat0(void) {
off_t pos;
printf("Rewinding directory and reading it again...\n");
printf("Rewinding directory and reading it again...\n");
pos = lseek(dirfd, 0, SEEK_SET);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_SET)");
}
if (pos != 0) {
errx(1, ".: lseek(0, SEEK_SET) returned %ld", (long) pos);
}
pos = lseek(dirfd, 0, SEEK_SET);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_SET)");
}
if (pos != 0) {
errx(1, ".: lseek(0, SEEK_SET) returned %ld", (long)pos);
}
readit();
readit();
}
static
void
readone(const char *shouldbe)
{
char buf[4096];
int len;
static void readone(const char *shouldbe) {
char buf[4096];
int len;
len = getdirentry(dirfd, buf, sizeof(buf)-1);
if (len < 0) {
err(1, ".: getdirentry");
}
if ((unsigned)len >= sizeof(buf)-1) {
errx(1, ".: getdirentry returned invalid length %d", len);
}
buf[len] = 0;
len = getdirentry(dirfd, buf, sizeof(buf) - 1);
if (len < 0) {
err(1, ".: getdirentry");
}
if ((unsigned)len >= sizeof(buf) - 1) {
errx(1, ".: getdirentry returned invalid length %d", len);
}
buf[len] = 0;
if (strcmp(buf, shouldbe)) {
errx(1, ".: getdirentry returned %s (expected %s)",
buf, shouldbe);
}
if (strcmp(buf, shouldbe)) {
errx(1, ".: getdirentry returned %s (expected %s)", buf, shouldbe);
}
}
static
void
doreadone(int which)
{
off_t pos;
pos = lseek(dirfd, testfiles[which].pos, SEEK_SET);
if (pos<0) {
err(1, ".: lseek(%ld, SEEK_SET)", (long) testfiles[which].pos);
}
if (pos != testfiles[which].pos) {
errx(1, ".: lseek(%ld, SEEK_SET) returned %ld",
(long) testfiles[which].pos, (long) pos);
}
static void doreadone(int which) {
off_t pos;
pos = lseek(dirfd, testfiles[which].pos, SEEK_SET);
if (pos < 0) {
err(1, ".: lseek(%ld, SEEK_SET)", (long)testfiles[which].pos);
}
if (pos != testfiles[which].pos) {
errx(1, ".: lseek(%ld, SEEK_SET) returned %ld", (long)testfiles[which].pos,
(long)pos);
}
readone(testfiles[which].name);
readone(testfiles[which].name);
}
static
void
readallonebyone(void)
{
int i;
static void readallonebyone(void) {
int i;
printf("Trying to read each entry again...\n");
for (i=0; testfiles[i].name; i++) {
doreadone(i);
}
printf("Trying to read each entry again...\n");
for (i = 0; testfiles[i].name; i++) {
doreadone(i);
}
}
static
void
readallrandomly(void)
{
int n, i, x;
static void readallrandomly(void) {
int n, i, x;
printf("Trying to read a bunch of entries randomly...\n");
printf("Trying to read a bunch of entries randomly...\n");
for (i=0; testfiles[i].name; i++);
n = i;
for (i = 0; testfiles[i].name; i++)
;
n = i;
srandom(39584);
for (i=0; i<512; i++) {
x = (int)(random()%n);
doreadone(x);
}
srandom(39584);
for (i = 0; i < 512; i++) {
x = (int)(random() % n);
doreadone(x);
}
}
static
void
readateof(void)
{
char buf[4096];
int len;
static void readateof(void) {
char buf[4096];
int len;
len = getdirentry(dirfd, buf, sizeof(buf)-1);
if (len < 0) {
err(1, ".: at EOF: getdirentry");
}
if (len==0) {
return;
}
if ((unsigned)len >= sizeof(buf)-1) {
errx(1, ".: at EOF: getdirentry returned "
"invalid length %d", len);
}
buf[len] = 0;
errx(1, ".: at EOF: got unexpected name %s", buf);
len = getdirentry(dirfd, buf, sizeof(buf) - 1);
if (len < 0) {
err(1, ".: at EOF: getdirentry");
}
if (len == 0) {
return;
}
if ((unsigned)len >= sizeof(buf) - 1) {
errx(1,
".: at EOF: getdirentry returned "
"invalid length %d",
len);
}
buf[len] = 0;
errx(1, ".: at EOF: got unexpected name %s", buf);
}
static
void
doreadateof(void)
{
off_t pos;
int i;
static void doreadateof(void) {
off_t pos;
int i;
printf("Trying to read after going to EOF...\n");
printf("Trying to read after going to EOF...\n");
pos = lseek(dirfd, 0, SEEK_END);
if (pos<0) {
err(1, ".: lseek(0, SEEK_END)");
}
pos = lseek(dirfd, 0, SEEK_END);
if (pos < 0) {
err(1, ".: lseek(0, SEEK_END)");
}
for (i=0; testfiles[i].name; i++) {
if (pos <= testfiles[i].pos) {
errx(1, ".: EOF position %ld below position %ld of %s",
pos, testfiles[i].pos, testfiles[i].name);
}
}
for (i = 0; testfiles[i].name; i++) {
if (pos <= testfiles[i].pos) {
errx(1, ".: EOF position %ld below position %ld of %s", pos,
testfiles[i].pos, testfiles[i].name);
}
}
readateof();
readateof();
}
static
void
inval_read(void)
{
char buf[4096];
int len;
static void inval_read(void) {
char buf[4096];
int len;
len = getdirentry(dirfd, buf, sizeof(buf)-1);
len = getdirentry(dirfd, buf, sizeof(buf) - 1);
/* Any result is ok, as long as the system doesn't crash */
(void)len;
/* Any result is ok, as long as the system doesn't crash */
(void)len;
}
static
void
dobadreads(void)
{
off_t pos, pos2, eof;
int valid, i, k=0;
static void dobadreads(void) {
off_t pos, pos2, eof;
int valid, i, k = 0;
printf("Trying some possibly invalid reads...\n");
printf("Trying some possibly invalid reads...\n");
eof = lseek(dirfd, 0, SEEK_END);
if (eof < 0) {
err(1, ".: lseek(0, SEEK_END)");
}
eof = lseek(dirfd, 0, SEEK_END);
if (eof < 0) {
err(1, ".: lseek(0, SEEK_END)");
}
for (pos=0; pos < eof; pos++) {
valid = 0;
for (i=0; testfiles[i].name; i++) {
if (pos==testfiles[i].pos) {
valid = 1;
}
}
if (valid) {
/* don't try offsets that are known to be valid */
continue;
}
for (pos = 0; pos < eof; pos++) {
valid = 0;
for (i = 0; testfiles[i].name; i++) {
if (pos == testfiles[i].pos) {
valid = 1;
}
}
if (valid) {
/* don't try offsets that are known to be valid */
continue;
}
pos2 = lseek(dirfd, pos, SEEK_SET);
if (pos2 < 0) {
/* this is ok */
}
else {
inval_read();
k++;
}
}
pos2 = lseek(dirfd, pos, SEEK_SET);
if (pos2 < 0) {
/* this is ok */
} else {
inval_read();
k++;
}
}
if (k>0) {
printf("Survived %d invalid reads...\n", k);
}
else {
printf("Couldn't find any invalid offsets to try...\n");
}
if (k > 0) {
printf("Survived %d invalid reads...\n", k);
} else {
printf("Couldn't find any invalid offsets to try...\n");
}
printf("Trying to read beyond EOF...\n");
pos2 = lseek(dirfd, eof + 1000, SEEK_SET);
if (pos2 < 0) {
/* this is ok */
}
else {
inval_read();
}
printf("Trying to read beyond EOF...\n");
pos2 = lseek(dirfd, eof + 1000, SEEK_SET);
if (pos2 < 0) {
/* this is ok */
} else {
inval_read();
}
}
static
void
dotest(void)
{
printf("Opening directory...\n");
openit();
static void dotest(void) {
printf("Opening directory...\n");
openit();
printf("Running tests...\n");
printf("Running tests...\n");
/* read the whole directory */
firstread();
/* read the whole directory */
firstread();
/* make sure eof behaves right */
readateof();
/* make sure eof behaves right */
readateof();
/* read all the filenames again by seeking */
readallonebyone();
/* read all the filenames again by seeking */
readallonebyone();
/* try reading at eof */
doreadateof();
/* try reading at eof */
doreadateof();
/* read a bunch of the filenames over and over again */
readallrandomly();
/* read a bunch of the filenames over and over again */
readallrandomly();
/* rewind and read the whole thing again, to make sure that works */
doreadat0();
/* rewind and read the whole thing again, to make sure that works */
doreadat0();
/* do invalid reads */
dobadreads();
/* do invalid reads */
dobadreads();
/* rewind again to make sure the invalid attempts didn't break it */
doreadat0();
/* rewind again to make sure the invalid attempts didn't break it */
doreadat0();
printf("Closing directory...\n");
closeit();
printf("Closing directory...\n");
closeit();
}
/************************************************************/
/* Setup code */
/************************************************************/
static
void
mkfile(const char *name)
{
int fd, i, r;
static const char message[] = "The turtle moves!\n";
char buf[32*sizeof(message)+1];
static void mkfile(const char *name) {
int fd, i, r;
static const char message[] = "The turtle moves!\n";
char buf[32 * sizeof(message) + 1];
buf[0]=0;
for (i=0; i<32; i++) {
strcat(buf, message);
}
buf[0] = 0;
for (i = 0; i < 32; i++) {
strcat(buf, message);
}
/* Use O_EXCL, because we know the file shouldn't already be there */
fd = open(name, O_WRONLY|O_CREAT|O_EXCL, 0664);
if (fd<0) {
err(1, "%s: create", name);
}
/* Use O_EXCL, because we know the file shouldn't already be there */
fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0664);
if (fd < 0) {
err(1, "%s: create", name);
}
r = write(fd, buf, strlen(buf));
if (r<0) {
err(1, "%s: write", name);
}
if ((unsigned)r != strlen(buf)) {
errx(1, "%s: short write (%d bytes)", name, r);
}
r = write(fd, buf, strlen(buf));
if (r < 0) {
err(1, "%s: write", name);
}
if ((unsigned)r != strlen(buf)) {
errx(1, "%s: short write (%d bytes)", name, r);
}
if (close(fd)<0) {
err(1, "%s: close", name);
}
if (close(fd) < 0) {
err(1, "%s: close", name);
}
}
static
void
setup(void)
{
int i;
static void setup(void) {
int i;
printf("Making directory %s...\n", TESTDIR);
printf("Making directory %s...\n", TESTDIR);
/* Create a directory */
if (mkdir(TESTDIR, 0775)<0) {
err(1, "%s: mkdir", TESTDIR);
}
/* Create a directory */
if (mkdir(TESTDIR, 0775) < 0) {
err(1, "%s: mkdir", TESTDIR);
}
/* Switch to it */
if (chdir(TESTDIR)<0) {
err(1, "%s: chdir", TESTDIR);
}
/* Switch to it */
if (chdir(TESTDIR) < 0) {
err(1, "%s: chdir", TESTDIR);
}
printf("Making some files...\n");
printf("Making some files...\n");
/* Populate it */
for (i=0; testfiles[i].name; i++) {
if (testfiles[i].make_it) {
mkfile(testfiles[i].name);
}
testfiles[i].pos = -1;
}
/* Populate it */
for (i = 0; testfiles[i].name; i++) {
if (testfiles[i].make_it) {
mkfile(testfiles[i].name);
}
testfiles[i].pos = -1;
}
}
static
void
cleanup(void)
{
int i;
static void cleanup(void) {
int i;
printf("Cleaning up...\n");
printf("Cleaning up...\n");
/* Remove the files */
for (i=0; testfiles[i].name; i++) {
if (testfiles[i].make_it) {
if (remove(testfiles[i].name)<0) {
err(1, "%s: remove", testfiles[i].name);
}
}
}
/* Remove the files */
for (i = 0; testfiles[i].name; i++) {
if (testfiles[i].make_it) {
if (remove(testfiles[i].name) < 0) {
err(1, "%s: remove", testfiles[i].name);
}
}
}
/* Leave the dir */
if (chdir("..")<0) {
err(1, "..: chdir");
}
/* Leave the dir */
if (chdir("..") < 0) {
err(1, "..: chdir");
}
/* Remove the dir */
if (rmdir(TESTDIR)<0) {
err(1, "%s: rmdir", TESTDIR);
}
/* Remove the dir */
if (rmdir(TESTDIR) < 0) {
err(1, "%s: rmdir", TESTDIR);
}
}
int main(void) {
setup();
int
main(void)
{
setup();
/* Do the whole thing twice */
dotest();
dotest();
/* Do the whole thing twice */
dotest();
dotest();
cleanup();
return 0;
cleanup();
return 0;
}

View File

@@ -46,41 +46,38 @@
#include <string.h>
#include <err.h>
#define MAXLEVELS 5
#define MAXLEVELS 5
int
main(void)
{
int i;
const char *onename = "testdir";
char dirname[512];
int main(void) {
int i;
const char *onename = "testdir";
char dirname[512];
strcpy(dirname, onename);
strcpy(dirname, onename);
for (i=0; i<MAXLEVELS; i++) {
printf("Creating directory: %s\n", dirname);
for (i = 0; i < MAXLEVELS; i++) {
printf("Creating directory: %s\n", dirname);
if (mkdir(dirname, 0755)) {
err(1, "%s: mkdir", dirname);
}
if (mkdir(dirname, 0755)) {
err(1, "%s: mkdir", dirname);
}
strcat(dirname, "/");
strcat(dirname, onename);
}
strcat(dirname, "/");
strcat(dirname, onename);
}
printf("Passed directory creation test.\n");
printf("Passed directory creation test.\n");
for (i=0; i<MAXLEVELS; i++) {
dirname[strlen(dirname) - strlen(onename) - 1] = 0;
for (i = 0; i < MAXLEVELS; i++) {
dirname[strlen(dirname) - strlen(onename) - 1] = 0;
printf("Removing directory: %s\n", dirname);
printf("Removing directory: %s\n", dirname);
if (rmdir(dirname)) {
err(1, "%s: rmdir", dirname);
}
}
printf("Passed directory removal test.\n");
if (rmdir(dirname)) {
err(1, "%s: rmdir", dirname);
}
}
printf("Passed directory removal test.\n");
return 0;
return 0;
}

View File

@@ -41,14 +41,14 @@
*
*/
#define SectorSize 512
#define SectorSize 512
#define TMULT 50
#define FSIZE ((SectorSize + 1) * TMULT)
#define TMULT 50
#define FSIZE ((SectorSize + 1) * TMULT)
#define FNAME "f-testfile"
#define READCHAR 'r'
#define WRITECHAR 'w'
#define FNAME "f-testfile"
#define READCHAR 'r'
#define WRITECHAR 'w'
#include <stdio.h>
#include <unistd.h>
@@ -57,50 +57,45 @@
static char buffer[SectorSize + 1];
static
void
check_buffer(void)
{
int i;
char ch = buffer[0];
static void check_buffer(void) {
int i;
char ch = buffer[0];
for (i = 1; i < SectorSize + 1; i++) {
if (buffer[i] != ch) {
errx(1, "Read error: %s", buffer);
}
}
for (i = 1; i < SectorSize + 1; i++) {
if (buffer[i] != ch) {
errx(1, "Read error: %s", buffer);
}
}
putchar(ch);
putchar(ch);
}
void
subproc_read(void)
{
int fd;
int i, res;
void subproc_read(void) {
int fd;
int i, res;
printf("File Reader starting ...\n\n");
printf("File Reader starting ...\n\n");
fd = open(FNAME, O_RDONLY);
if (fd < 0) {
err(1, "%s: open", FNAME);
}
fd = open(FNAME, O_RDONLY);
if (fd < 0) {
err(1, "%s: open", FNAME);
}
for (i=0; i<TMULT; i++) {
res = read(fd, buffer, SectorSize + 1);
if (res < 0) {
err(1, "%s: read", FNAME);
}
for (i = 0; i < TMULT; i++) {
res = read(fd, buffer, SectorSize + 1);
if (res < 0) {
err(1, "%s: read", FNAME);
}
// yield();
// yield();
if (res != SectorSize + 1) {
errx(1, "%s: read: short count", FNAME);
}
check_buffer();
}
if (res != SectorSize + 1) {
errx(1, "%s: read: short count", FNAME);
}
check_buffer();
}
close(fd);
close(fd);
printf("File Read exited successfully!\n");
printf("File Read exited successfully!\n");
}

View File

@@ -48,10 +48,9 @@
#include <err.h>
#include "f_hdr.h"
#define SECTOR_SIZE 512
#define SECTOR_SIZE 512
#define BUFFER_SIZE (2 * SECTOR_SIZE + 1)
#define BUFFER_SIZE (2 * SECTOR_SIZE + 1)
#define BIGFILE_SIZE (270 * BUFFER_SIZE)
#define BIGFILE_NAME "large-f"
@@ -60,289 +59,262 @@
char fbuffer[BUFFER_SIZE];
char ibuffer[32];
#define DIR_DEPTH 8
#define DIR_NAME "/t"
#define DIRFILE_NAME "a"
#define DIR_DEPTH 8
#define DIR_NAME "/t"
#define DIRFILE_NAME "a"
#define FNAME "f-testfile"
#define TMULT 50
#define FSIZE ((SECTOR_SIZE + 1) * TMULT)
#define FNAME "f-testfile"
#define TMULT 50
#define FSIZE ((SECTOR_SIZE + 1) * TMULT)
#define READCHAR 'r'
#define WRITECHAR 'w'
#define READCHAR 'r'
#define WRITECHAR 'w'
char cbuffer[SECTOR_SIZE + 1];
/* ===================================================
*/
static
pid_t
forkoff(void (*func)(void))
{
pid_t pid = fork();
switch (pid) {
case -1:
warn("fork");
return -1;
case 0:
func();
_exit(0);
default: break;
}
return pid;
static pid_t forkoff(void (*func)(void)) {
pid_t pid = fork();
switch (pid) {
case -1:
warn("fork");
return -1;
case 0:
func();
_exit(0);
default:
break;
}
return pid;
}
static
void
dowait(int pid)
{
int status;
static void dowait(int pid) {
int status;
if (waitpid(pid, &status, 0)<0) {
warn("waitpid for %d", pid);
}
else if (WIFSIGNALED(status)) {
warnx("pid %d: signal %d", pid, WTERMSIG(status));
}
else if (WEXITSTATUS(status) != 0) {
warnx("pid %d: exit %d", pid, WEXITSTATUS(status));
}
if (waitpid(pid, &status, 0) < 0) {
warn("waitpid for %d", pid);
} else if (WIFSIGNALED(status)) {
warnx("pid %d: signal %d", pid, WTERMSIG(status));
} else if (WEXITSTATUS(status) != 0) {
warnx("pid %d: exit %d", pid, WEXITSTATUS(status));
}
}
/* ===================================================
*/
static
void
big_file(int size)
{
int i, j, fileid;
static void big_file(int size) {
int i, j, fileid;
printf("[BIGFILE] test starting :\n");
printf("\tCreating a file of size: %d\n", size);
printf("[BIGFILE] test starting :\n");
printf("\tCreating a file of size: %d\n", size);
fileid = open(BIGFILE_NAME, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (fileid < 0) {
err(1, "[BIGFILE]: %s: open for write", BIGFILE_NAME);
}
fileid = open(BIGFILE_NAME, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fileid < 0) {
err(1, "[BIGFILE]: %s: open for write", BIGFILE_NAME);
}
for(i = 0; i < BUFFER_SIZE; i++) {
fbuffer[i] = LETTER(i);
}
for (i = 0; i < BUFFER_SIZE; i++) {
fbuffer[i] = LETTER(i);
}
printf("\tWriting to file.\n");
for (i = 0; i < size; i += BUFFER_SIZE) {
write(fileid, fbuffer, BUFFER_SIZE);
printf("\tWriting to file.\n");
for (i = 0; i < size; i += BUFFER_SIZE) {
write(fileid, fbuffer, BUFFER_SIZE);
if (!(i % (10 * BUFFER_SIZE))) {
printf("\rBW : %d", i);
}
}
if (!(i % (10 * BUFFER_SIZE))) {
printf("\rBW : %d", i);
}
}
printf("\n\tReading from file.\n");
close(fileid);
printf("\n\tReading from file.\n");
close(fileid);
fileid = open(BIGFILE_NAME, O_RDONLY);
if (fileid < 0) {
err(1, "[BIGFILE]: %s: open for read", BIGFILE_NAME);
}
fileid = open(BIGFILE_NAME, O_RDONLY);
if (fileid < 0) {
err(1, "[BIGFILE]: %s: open for read", BIGFILE_NAME);
}
for (i = 0; i < size; i += BUFFER_SIZE) {
j = read(fileid, fbuffer, BUFFER_SIZE);
if (j<0) {
err(1, "[BIGFILE]: read");
}
if (j != BUFFER_SIZE) {
errx(1, "[BIGFILE]: read: only %d bytes", j);
}
}
for (i = 0; i < size; i += BUFFER_SIZE) {
j = read(fileid, fbuffer, BUFFER_SIZE);
if (j < 0) {
err(1, "[BIGFILE]: read");
}
if (j != BUFFER_SIZE) {
errx(1, "[BIGFILE]: read: only %d bytes", j);
}
}
if (!(i % (10 * BUFFER_SIZE))) {
printf("\rBR : %d", i);
}
if (!(i % (10 * BUFFER_SIZE))) {
printf("\rBR : %d", i);
}
/* Check to see that the data is consistent : */
for (j = 0; j < BUFFER_SIZE; j++) {
if (fbuffer[j] != LETTER(j)) {
errx(1, "[BIGFILE] : Failed read check : "
"inconsistent data read: %d", i+j);
}
}
/* Check to see that the data is consistent : */
for (j = 0; j < BUFFER_SIZE; j++) {
if (fbuffer[j] != LETTER(j)) {
errx(1,
"[BIGFILE] : Failed read check : "
"inconsistent data read: %d",
i + j);
}
}
close(fileid);
if (remove(BIGFILE_NAME)) {
err(1, "[BIGFILE]: %s: remove", BIGFILE_NAME);
}
close(fileid);
if (remove(BIGFILE_NAME)) {
err(1, "[BIGFILE]: %s: remove", BIGFILE_NAME);
}
printf("\n[BIGFILE] : Success!\n");
printf("\n[BIGFILE] : Success!\n");
}
/* ===================================================
*/
static
void
concur(void)
{
int i, fd;
int r1, r2, w1;
static void concur(void) {
int i, fd;
int r1, r2, w1;
printf("Spawning 2 readers, 1 writer.\n");
printf("Spawning 2 readers, 1 writer.\n");
fd = open(FNAME, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
err(1, "[CONCUR]: %s: open", FNAME);
}
fd = open(FNAME, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (fd < 0) {
err(1, "[CONCUR]: %s: open", FNAME);
}
printf("Initializing test file: ");
printf("Initializing test file: ");
for (i = 0; i < SECTOR_SIZE + 1; i++) {
cbuffer[i] = READCHAR;
}
for (i = 0; i < SECTOR_SIZE + 1; i++) {
cbuffer[i] = READCHAR;
}
for (i = 0; i < TMULT; i++) {
write(fd, cbuffer, SECTOR_SIZE + 1);
}
for (i = 0; i < TMULT; i++) {
write(fd, cbuffer, SECTOR_SIZE + 1);
}
close(fd);
printf("Done initializing. Starting processes...\n");
close(fd);
r1 = forkoff(subproc_read);
w1 = forkoff(subproc_write);
r2 = forkoff(subproc_read);
printf("Done initializing. Starting processes...\n");
printf("Waiting for processes.\n");
r1 = forkoff(subproc_read);
w1 = forkoff(subproc_write);
r2 = forkoff(subproc_read);
dowait(r1);
dowait(r2);
dowait(w1);
printf("Waiting for processes.\n");
if (remove(FNAME)) {
err(1, "[CONCUR]: %s: remove", FNAME);
}
dowait(r1);
dowait(r2);
dowait(w1);
if (remove(FNAME)) {
err(1, "[CONCUR]: %s: remove", FNAME);
}
printf("[CONCUR] Done!\n");
printf("[CONCUR] Done!\n");
}
/* ===================================================
*/
static
void
dir_test(int depth)
{
int i, fd;
char tmp[] = DIR_NAME;
char fmp[] = DIRFILE_NAME;
char dirname[64];
static void dir_test(int depth) {
int i, fd;
char tmp[] = DIR_NAME;
char fmp[] = DIRFILE_NAME;
char dirname[64];
strcpy(dirname, ".");
strcpy(dirname, ".");
for (i = 0; i < depth; i++) {
strcat(dirname, tmp);
for (i = 0; i < depth; i++) {
strcat(dirname, tmp);
printf("\tCreating dir : %s\n", dirname);
printf("\tCreating dir : %s\n", dirname);
if (mkdir(dirname, 0775) < 0) {
err(1, "[DIRTEST]: %s: mkdir", dirname);
}
if (mkdir(dirname, 0775) < 0) {
err(1, "[DIRTEST]: %s: mkdir", dirname);
}
strcat(dirname, fmp);
printf("\tCreating file: %s\n", dirname);
strcat(dirname, fmp);
printf("\tCreating file: %s\n", dirname);
fd = open(dirname, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (fd<0) {
err(1, "[DIRTEST]: %s: open", dirname);
}
fd = open(dirname, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
err(1, "[DIRTEST]: %s: open", dirname);
}
dirname[strlen(dirname) - strlen(fmp)] = '\0';
}
dirname[strlen(dirname) - strlen(fmp)] = '\0';
}
printf("[DIRTEST] : Passed directory creation test.\n");
printf("[DIRTEST] : Passed directory creation test.\n");
for (i = 0; i < depth; i++) {
strcat(dirname, fmp);
for (i = 0; i < depth; i++) {
strcat(dirname, fmp);
printf("\tDeleting file: %s\n", dirname);
printf("\tDeleting file: %s\n", dirname);
if (remove(dirname)) {
err(1, "[DIRTEST]: %s: remove", dirname);
}
if (remove(dirname)) {
err(1, "[DIRTEST]: %s: remove", dirname);
}
dirname[strlen(dirname) - strlen(fmp)] = '\0';
printf("\tRemoving dir : %s\n", dirname);
dirname[strlen(dirname) - strlen(fmp)] = '\0';
printf("\tRemoving dir : %s\n", dirname);
if (rmdir(dirname)) {
err(1, "[DIRTEST]: %s: rmdir", dirname);
}
if (rmdir(dirname)) {
err(1, "[DIRTEST]: %s: rmdir", dirname);
}
dirname[strlen(dirname) - strlen(tmp)] = '\0';
}
dirname[strlen(dirname) - strlen(tmp)] = '\0';
}
printf("[DIRTEST] : Passed directory removal test.\n");
printf("[DIRTEST] : Success!\n");
printf("[DIRTEST] : Passed directory removal test.\n");
printf("[DIRTEST] : Success!\n");
}
/* ===================================================
*/
#define RUNBIGFILE 0x1
#define RUNDIRTEST 0x2
#define RUNCONCUR 0x4
#define RUNTHEMALL (RUNBIGFILE | RUNDIRTEST | RUNCONCUR)
#define RUNBIGFILE 0x1
#define RUNDIRTEST 0x2
#define RUNCONCUR 0x4
#define RUNTHEMALL (RUNBIGFILE | RUNDIRTEST | RUNCONCUR)
int
main(int argc, char * argv[])
{
int tv = 0;
int main(int argc, char *argv[]) {
int tv = 0;
if (argc > 1) {
if (*argv[1]=='1') {
tv = RUNBIGFILE;
}
else if (*argv[1]=='2') {
tv = RUNDIRTEST;
}
else if (*argv[1]=='3') {
tv = RUNCONCUR;
}
}
else {
tv = RUNTHEMALL;
}
if (argc > 1) {
if (*argv[1] == '1') {
tv = RUNBIGFILE;
} else if (*argv[1] == '2') {
tv = RUNDIRTEST;
} else if (*argv[1] == '3') {
tv = RUNCONCUR;
}
} else {
tv = RUNTHEMALL;
}
if (tv & RUNBIGFILE) {
printf("[BIGFILE] : Run #1\n");
big_file(BIGFILE_SIZE);
printf("[BIGFILE] : Run #2\n");
big_file(BIGFILE_SIZE);
}
if (tv & RUNBIGFILE) {
printf("[BIGFILE] : Run #1\n");
big_file(BIGFILE_SIZE);
printf("[BIGFILE] : Run #2\n");
big_file(BIGFILE_SIZE);
}
if (tv & RUNDIRTEST) {
printf("[DIRTEST] : Run #1\n");
dir_test(DIR_DEPTH);
printf("[DIRTEST] : Run #2\n");
dir_test(DIR_DEPTH);
}
if (tv & RUNDIRTEST) {
printf("[DIRTEST] : Run #1\n");
dir_test(DIR_DEPTH);
printf("[DIRTEST] : Run #2\n");
dir_test(DIR_DEPTH);
}
if (tv & RUNCONCUR) {
printf("[CONCUR]\n");
concur();
}
return 0;
if (tv & RUNCONCUR) {
printf("[CONCUR]\n");
concur();
}
return 0;
}

View File

@@ -41,14 +41,14 @@
*
*/
#define SectorSize 512
#define SectorSize 512
#define TMULT 50
#define FSIZE ((SectorSize + 1) * TMULT)
#define TMULT 50
#define FSIZE ((SectorSize + 1) * TMULT)
#define FNAME "f-testfile"
#define READCHAR 'r'
#define WRITECHAR 'w'
#define FNAME "f-testfile"
#define READCHAR 'r'
#define WRITECHAR 'w'
#include <unistd.h>
#include <stdio.h>
@@ -57,29 +57,27 @@
static char buffer[SectorSize + 1];
void
subproc_write(void)
{
int fd;
int i;
void subproc_write(void) {
int fd;
int i;
for (i=0; i < SectorSize + 1; i++) {
buffer[i] = WRITECHAR;
}
for (i = 0; i < SectorSize + 1; i++) {
buffer[i] = WRITECHAR;
}
printf("File Writer starting ...\n");
printf("File Writer starting ...\n");
fd = open(FNAME, O_WRONLY);
if (fd < 0) {
err(1, "%s: open", FNAME);
}
fd = open(FNAME, O_WRONLY);
if (fd < 0) {
err(1, "%s: open", FNAME);
}
for (i=0; i<TMULT; i++) {
// yield();
write(fd, buffer, SectorSize + 1);
}
for (i = 0; i < TMULT; i++) {
// yield();
write(fd, buffer, SectorSize + 1);
}
close(fd);
close(fd);
printf("File Write exited successfully!\n");
printf("File Write exited successfully!\n");
}

View File

@@ -57,207 +57,178 @@
#define NUMSIZE 8191
struct number {
char buf[NUMSIZE+1]; /* includes space for a null-terminator */
size_t first; /* first valid digit */
char buf[NUMSIZE + 1]; /* includes space for a null-terminator */
size_t first; /* first valid digit */
};
static struct number scratch;
static
void
number_init(struct number *n, const char *txt)
{
size_t len, i;
static void number_init(struct number *n, const char *txt) {
size_t len, i;
len = strlen(txt);
if (len > NUMSIZE) {
warnx("%s", txt);
errx(1, "Number too large");
}
n->first = NUMSIZE - len;
strcpy(n->buf + n->first, txt);
len = strlen(txt);
if (len > NUMSIZE) {
warnx("%s", txt);
errx(1, "Number too large");
}
n->first = NUMSIZE - len;
strcpy(n->buf + n->first, txt);
#if 0
for (i=0; i<n->first; i++) {
n->buf[i] = '0';
}
#endif
for (i=n->first; i<NUMSIZE; i++) {
if (n->buf[i] < '0' || n->buf[i] > '9') {
warnx("%s", txt);
errx(1, "Number contained non-digit characters");
}
}
assert(n->buf[NUMSIZE] == 0);
while (n->first < NUMSIZE && n->buf[n->first] == '0') {
n->first++;
}
for (i = n->first; i < NUMSIZE; i++) {
if (n->buf[i] < '0' || n->buf[i] > '9') {
warnx("%s", txt);
errx(1, "Number contained non-digit characters");
}
}
assert(n->buf[NUMSIZE] == 0);
while (n->first < NUMSIZE && n->buf[n->first] == '0') {
n->first++;
}
}
static
char *
number_get(struct number *n)
{
size_t pos;
static char *number_get(struct number *n) {
size_t pos;
pos = n->first;
while (pos < NUMSIZE && n->buf[pos] == '0') {
pos++;
}
if (pos == NUMSIZE) {
pos--;
n->buf[pos] = '0';
}
return &n->buf[pos];
pos = n->first;
while (pos < NUMSIZE && n->buf[pos] == '0') {
pos++;
}
if (pos == NUMSIZE) {
pos--;
n->buf[pos] = '0';
}
return &n->buf[pos];
}
static
void
finishcarry(struct number *r, const struct number *b, size_t pos,
unsigned carry)
{
if (carry > 0 && b->first == 0) {
/* if b->first is 0, pos may now be 2^32-1 */
errx(1, "Overflow");
}
while (carry > 0) {
if (pos == 0) {
errx(1, "Overflow");
}
r->buf[pos--] = carry % 10 + '0';
carry = carry / 10;
}
r->first = pos + 1;
static void finishcarry(struct number *r, const struct number *b, size_t pos,
unsigned carry) {
if (carry > 0 && b->first == 0) {
/* if b->first is 0, pos may now be 2^32-1 */
errx(1, "Overflow");
}
while (carry > 0) {
if (pos == 0) {
errx(1, "Overflow");
}
r->buf[pos--] = carry % 10 + '0';
carry = carry / 10;
}
r->first = pos + 1;
}
static
void
pluseq(struct number *r, const struct number *b)
{
size_t pos;
unsigned an, bn, rn, carry;
static void pluseq(struct number *r, const struct number *b) {
size_t pos;
unsigned an, bn, rn, carry;
carry = 0;
for (pos = NUMSIZE; pos-- > b->first; ) {
an = pos < r->first ? 0 : r->buf[pos] - '0';
bn = b->buf[pos] - '0';
rn = an + bn + carry;
r->buf[pos] = rn % 10 + '0';
carry = rn / 10;
}
finishcarry(r, b, pos, carry);
carry = 0;
for (pos = NUMSIZE; pos-- > b->first;) {
an = pos < r->first ? 0 : r->buf[pos] - '0';
bn = b->buf[pos] - '0';
rn = an + bn + carry;
r->buf[pos] = rn % 10 + '0';
carry = rn / 10;
}
finishcarry(r, b, pos, carry);
}
static
void
dec(struct number *r)
{
size_t pos;
static void dec(struct number *r) {
size_t pos;
for (pos = NUMSIZE; pos-- > r->first; ) {
if (r->buf[pos] == '0') {
r->buf[pos] = '9';
}
else {
r->buf[pos]--;
return;
}
}
/* This should really not happen. */
errx(1, "Underflow");
for (pos = NUMSIZE; pos-- > r->first;) {
if (r->buf[pos] == '0') {
r->buf[pos] = '9';
} else {
r->buf[pos]--;
return;
}
}
/* This should really not happen. */
errx(1, "Underflow");
}
static
void
multc(struct number *r, const struct number *a, unsigned bn, size_t offset)
{
size_t pos;
unsigned an, rn, carry;
static void multc(struct number *r, const struct number *a, unsigned bn,
size_t offset) {
size_t pos;
unsigned an, rn, carry;
for (pos = NUMSIZE; pos-- > NUMSIZE - offset; ) {
r->buf[pos] = '0';
}
carry = 0;
for (pos = NUMSIZE; pos-- > a->first; ) {
an = a->buf[pos] - '0';
rn = an * bn + carry;
if (pos < offset) {
errx(1, "Overflow");
}
r->buf[pos - offset] = rn % 10 + '0';
carry = rn / 10;
}
if (carry > 0 && pos < offset) {
errx(1, "Overflow");
}
finishcarry(r, a, pos - offset, carry);
for (pos = NUMSIZE; pos-- > NUMSIZE - offset;) {
r->buf[pos] = '0';
}
carry = 0;
for (pos = NUMSIZE; pos-- > a->first;) {
an = a->buf[pos] - '0';
rn = an * bn + carry;
if (pos < offset) {
errx(1, "Overflow");
}
r->buf[pos - offset] = rn % 10 + '0';
carry = rn / 10;
}
if (carry > 0 && pos < offset) {
errx(1, "Overflow");
}
finishcarry(r, a, pos - offset, carry);
}
static
void
mult(struct number *r, const struct number *a, const struct number *b)
{
unsigned offset;
size_t apos;
static void mult(struct number *r, const struct number *a,
const struct number *b) {
unsigned offset;
size_t apos;
/* B should normally be the larger number */
if (a->first < b->first) {
mult(r, b, a);
return;
}
/* B should normally be the larger number */
if (a->first < b->first) {
mult(r, b, a);
return;
}
number_init(&scratch, "0");
offset = 0;
for (apos = NUMSIZE; apos-- > a->first; ) {
multc(&scratch, b, a->buf[apos] - '0', offset);
pluseq(r, &scratch);
offset++;
}
number_init(&scratch, "0");
offset = 0;
for (apos = NUMSIZE; apos-- > a->first;) {
multc(&scratch, b, a->buf[apos] - '0', offset);
pluseq(r, &scratch);
offset++;
}
}
////////////////////////////////////////////////////////////
// argv logic
static
void
self(const char *arg1, const char *arg2)
{
const char *args[4];
static void self(const char *arg1, const char *arg2) {
const char *args[4];
args[0] = _PATH_SELF;
args[1] = arg1;
args[2] = arg2;
args[3] = NULL;
execv(_PATH_SELF, (char **)args);
err(1, "execv");
args[0] = _PATH_SELF;
args[1] = arg1;
args[2] = arg2;
args[3] = NULL;
execv(_PATH_SELF, (char **)args);
err(1, "execv");
}
static struct number n1, n2, multbuf;
int
main(int argc, char *argv[])
{
if (argc == 0) {
/* Assume we've just been run from the menu. */
self("404", "1");
}
else if (argc == 2) {
self(argv[1], "1");
}
else if (argc == 3) {
if (!strcmp(argv[1], "1") || !strcmp(argv[1], "0")) {
printf("%s\n", argv[2]);
}
else {
number_init(&n1, argv[1]);
number_init(&n2, argv[2]);
number_init(&multbuf, "0");
mult(&multbuf, &n1, &n2);
dec(&n1);
self(number_get(&n1), number_get(&multbuf));
}
}
else {
warnx("Usage: factorial N");
}
return 0;
int main(int argc, char *argv[]) {
if (argc == 0) {
/* Assume we've just been run from the menu. */
self("404", "1");
} else if (argc == 2) {
self(argv[1], "1");
} else if (argc == 3) {
if (!strcmp(argv[1], "1") || !strcmp(argv[1], "0")) {
printf("%s\n", argv[2]);
} else {
number_init(&n1, argv[1]);
number_init(&n2, argv[2]);
number_init(&multbuf, "0");
mult(&multbuf, &n1, &n2);
dec(&n1);
self(number_get(&n1), number_get(&multbuf));
}
} else {
warnx("Usage: factorial N");
}
return 0;
}

View File

@@ -40,72 +40,52 @@
#include <unistd.h>
#include <err.h>
static char *hargv[2] = { (char *)"hog", NULL };
static char *cargv[3] = { (char *)"cat", (char *)"catfile", NULL };
static char *hargv[2] = {(char *)"hog", NULL};
static char *cargv[3] = {(char *)"cat", (char *)"catfile", NULL};
#define MAXPROCS 6
#define MAXPROCS 6
static int pids[MAXPROCS], npids;
static
void
spawnv(const char *prog, char **argv)
{
int pid = fork();
switch (pid) {
case -1:
err(1, "fork");
case 0:
/* child */
execv(prog, argv);
err(1, "%s", prog);
default:
/* parent */
pids[npids++] = pid;
break;
}
static void spawnv(const char *prog, char **argv) {
int pid = fork();
switch (pid) {
case -1:
err(1, "fork");
case 0:
/* child */
execv(prog, argv);
err(1, "%s", prog);
default:
/* parent */
pids[npids++] = pid;
break;
}
}
static
void
waitall(void)
{
int i, status;
for (i=0; i<npids; i++) {
if (waitpid(pids[i], &status, 0)<0) {
warn("waitpid for %d", pids[i]);
}
else if (WIFSIGNALED(status)) {
warnx("pid %d: signal %d", pids[i], WTERMSIG(status));
}
else if (WEXITSTATUS(status) != 0) {
warnx("pid %d: exit %d", pids[i], WEXITSTATUS(status));
}
}
static void waitall(void) {
int i, status;
for (i = 0; i < npids; i++) {
if (waitpid(pids[i], &status, 0) < 0) {
warn("waitpid for %d", pids[i]);
} else if (WIFSIGNALED(status)) {
warnx("pid %d: signal %d", pids[i], WTERMSIG(status));
} else if (WEXITSTATUS(status) != 0) {
warnx("pid %d: exit %d", pids[i], WEXITSTATUS(status));
}
}
}
static
void
hog(void)
{
spawnv("/testbin/hog", hargv);
}
static
void
cat(void)
{
spawnv("/bin/cat", cargv);
}
int
main(void)
{
hog();
hog();
hog();
cat();
waitall();
return 0;
static void hog(void) { spawnv("/testbin/hog", hargv); }
static void cat(void) { spawnv("/bin/cat", cargv); }
int main(void) {
hog();
hog();
hog();
cat();
waitall();
return 0;
}

View File

@@ -38,19 +38,17 @@
#include <stdio.h>
#define REALLY_BIG_ADDRESS 0x40000000
#define REALLY_BIG_ADDRESS 0x40000000
int
main(void)
{
volatile int i;
int main(void) {
volatile int i;
printf("\nEntering the faulter program - I should die immediately\n");
i = *(int *)REALLY_BIG_ADDRESS;
printf("\nEntering the faulter program - I should die immediately\n");
i = *(int *)REALLY_BIG_ADDRESS;
// gcc 4.8 improperly demands this
(void)i;
// gcc 4.8 improperly demands this
(void)i;
printf("I didn't get killed! Program has a bug\n");
return 0;
printf("I didn't get killed! Program has a bug\n");
return 0;
}

View File

@@ -43,66 +43,61 @@
#include <unistd.h>
#include <err.h>
int
main(int argc, char *argv[])
{
static char writebuf[41] = "Twiddle dee dee, Twiddle dum dum.......\n";
static char readbuf[41];
int main(int argc, char *argv[]) {
static char writebuf[41] = "Twiddle dee dee, Twiddle dum dum.......\n";
static char readbuf[41];
const char *file;
int fd, rv;
const char *file;
int fd, rv;
if (argc == 0) {
warnx("No arguments - running on \"testfile\"");
file = "testfile";
}
else if (argc == 2) {
file = argv[1];
}
else {
errx(1, "Usage: filetest <filename>");
}
if (argc == 0) {
warnx("No arguments - running on \"testfile\"");
file = "testfile";
} else if (argc == 2) {
file = argv[1];
} else {
errx(1, "Usage: filetest <filename>");
}
fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (fd<0) {
err(1, "%s: open for write", file);
}
fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s: open for write", file);
}
rv = write(fd, writebuf, 40);
if (rv < 0) {
err(1, "%s: write", file);
}
rv = write(fd, writebuf, 40);
if (rv<0) {
err(1, "%s: write", file);
}
rv = close(fd);
if (rv < 0) {
err(1, "%s: close (1st time)", file);
}
rv = close(fd);
if (rv<0) {
err(1, "%s: close (1st time)", file);
}
fd = open(file, O_RDONLY);
if (fd < 0) {
err(1, "%s: open for read", file);
}
fd = open(file, O_RDONLY);
if (fd<0) {
err(1, "%s: open for read", file);
}
rv = read(fd, readbuf, 40);
if (rv < 0) {
err(1, "%s: read", file);
}
rv = close(fd);
if (rv < 0) {
err(1, "%s: close (2nd time)", file);
}
/* ensure null termination */
readbuf[40] = 0;
rv = read(fd, readbuf, 40);
if (rv<0) {
err(1, "%s: read", file);
}
rv = close(fd);
if (rv<0) {
err(1, "%s: close (2nd time)", file);
}
/* ensure null termination */
readbuf[40] = 0;
if (strcmp(readbuf, writebuf)) {
errx(1, "Buffer data mismatch!");
}
if (strcmp(readbuf, writebuf)) {
errx(1, "Buffer data mismatch!");
}
rv = remove(file);
if (rv<0) {
err(1, "%s: remove", file);
}
printf("Passed filetest.\n");
return 0;
rv = remove(file);
if (rv < 0) {
err(1, "%s: remove", file);
}
printf("Passed filetest.\n");
return 0;
}

View File

@@ -52,25 +52,24 @@
static volatile int pid;
int
main(void)
{
int i;
int main(void) {
int i;
while (1) {
fork();
while (1) {
fork();
pid = getpid();
pid = getpid();
/* Make sure each fork has its own address space. */
for (i=0; i<300; i++) {
volatile int seenpid;
seenpid = pid;
if (seenpid != getpid()) {
errx(1, "pid mismatch (%d, should be %d) "
"- your vm is broken!",
seenpid, getpid());
}
}
}
/* Make sure each fork has its own address space. */
for (i = 0; i < 300; i++) {
volatile int seenpid;
seenpid = pid;
if (seenpid != getpid()) {
errx(1,
"pid mismatch (%d, should be %d) "
"- your vm is broken!",
seenpid, getpid());
}
}
}
}

View File

@@ -51,16 +51,13 @@ static volatile int mypid;
/*
* Helper function for fork that prints a warning on error.
*/
static
int
dofork(void)
{
int pid;
pid = fork();
if (pid < 0) {
warn("fork");
}
return pid;
static int dofork(void) {
int pid;
pid = fork();
if (pid < 0) {
warn("fork");
}
return pid;
}
/*
@@ -68,24 +65,22 @@ dofork(void)
* the pid into the data segment and read it back repeatedly, making
* sure it's correct every time.
*/
static
void
check(void)
{
int i;
static void check(void) {
int i;
mypid = getpid();
mypid = getpid();
/* Make sure each fork has its own address space. */
for (i=0; i<800; i++) {
volatile int seenpid;
seenpid = mypid;
if (seenpid != getpid()) {
errx(1, "pid mismatch (%d, should be %d) "
"- your vm is broken!",
seenpid, getpid());
}
}
/* Make sure each fork has its own address space. */
for (i = 0; i < 800; i++) {
volatile int seenpid;
seenpid = mypid;
if (seenpid != getpid()) {
errx(1,
"pid mismatch (%d, should be %d) "
"- your vm is broken!",
seenpid, getpid());
}
}
}
/*
@@ -97,121 +92,109 @@ check(void)
* generated the current process; that means it's time to exit. Only
* the parent of all the processes returns from the chain of dowaits.
*/
static
void
dowait(int nowait, int pid)
{
int x;
static void dowait(int nowait, int pid) {
int x;
if (pid<0) {
/* fork in question failed; just return */
return;
}
if (pid==0) {
/* in the fork in question we were the child; exit */
exit(0);
}
if (pid < 0) {
/* fork in question failed; just return */
return;
}
if (pid == 0) {
/* in the fork in question we were the child; exit */
exit(0);
}
if (!nowait) {
if (waitpid(pid, &x, 0)<0) {
warn("waitpid");
}
else if (WIFSIGNALED(x)) {
warnx("pid %d: signal %d", pid, WTERMSIG(x));
}
else if (WEXITSTATUS(x) != 0) {
warnx("pid %d: exit %d", pid, WEXITSTATUS(x));
}
}
if (!nowait) {
if (waitpid(pid, &x, 0) < 0) {
warn("waitpid");
} else if (WIFSIGNALED(x)) {
warnx("pid %d: signal %d", pid, WTERMSIG(x));
} else if (WEXITSTATUS(x) != 0) {
warnx("pid %d: exit %d", pid, WEXITSTATUS(x));
}
}
}
/*
* Actually run the test.
*/
static
void
test(int nowait)
{
int pid0, pid1, pid2, pid3;
int depth = 0;
static void test(int nowait) {
int pid0, pid1, pid2, pid3;
int depth = 0;
/*
* Caution: This generates processes geometrically.
*
* It is unrolled to encourage gcc to registerize the pids,
* to prevent wait/exit problems if fork corrupts memory.
*
* Note: if the depth prints trigger and show that the depth
* is too small, the most likely explanation is that the fork
* child is returning from the write() inside putchar()
* instead of from fork() and thus skipping the depth++. This
* is a fairly common problem caused by races in the kernel
* fork code.
*/
/*
* Caution: This generates processes geometrically.
*
* It is unrolled to encourage gcc to registerize the pids,
* to prevent wait/exit problems if fork corrupts memory.
*
* Note: if the depth prints trigger and show that the depth
* is too small, the most likely explanation is that the fork
* child is returning from the write() inside putchar()
* instead of from fork() and thus skipping the depth++. This
* is a fairly common problem caused by races in the kernel
* fork code.
*/
pid0 = dofork();
depth++;
putchar('A');
if (depth != 1) {
warnx("depth %d, should be 1", depth);
}
check();
pid0 = dofork();
depth++;
putchar('A');
if (depth != 1) {
warnx("depth %d, should be 1", depth);
}
check();
pid1 = dofork();
depth++;
putchar('B');
if (depth != 2) {
warnx("depth %d, should be 2", depth);
}
check();
pid1 = dofork();
depth++;
putchar('B');
if (depth != 2) {
warnx("depth %d, should be 2", depth);
}
check();
pid2 = dofork();
depth++;
putchar('C');
if (depth != 3) {
warnx("depth %d, should be 3", depth);
}
check();
pid2 = dofork();
depth++;
putchar('C');
if (depth != 3) {
warnx("depth %d, should be 3", depth);
}
check();
pid3 = dofork();
depth++;
putchar('D');
if (depth != 4) {
warnx("depth %d, should be 4", depth);
}
check();
pid3 = dofork();
depth++;
putchar('D');
if (depth != 4) {
warnx("depth %d, should be 4", depth);
}
check();
/*
* These must be called in reverse order to avoid waiting
* improperly.
*/
dowait(nowait, pid3);
dowait(nowait, pid2);
dowait(nowait, pid1);
dowait(nowait, pid0);
/*
* These must be called in reverse order to avoid waiting
* improperly.
*/
dowait(nowait, pid3);
dowait(nowait, pid2);
dowait(nowait, pid1);
dowait(nowait, pid0);
putchar('\n');
putchar('\n');
}
int
main(int argc, char *argv[])
{
static const char expected[] =
"|----------------------------|\n";
int nowait=0;
int main(int argc, char *argv[]) {
static const char expected[] = "|----------------------------|\n";
int nowait = 0;
if (argc==2 && !strcmp(argv[1], "-w")) {
nowait=1;
}
else if (argc!=1 && argc!=0) {
warnx("usage: forktest [-w]");
return 1;
}
warnx("Starting. Expect this many:");
write(STDERR_FILENO, expected, strlen(expected));
if (argc == 2 && !strcmp(argv[1], "-w")) {
nowait = 1;
} else if (argc != 1 && argc != 0) {
warnx("usage: forktest [-w]");
return 1;
}
warnx("Starting. Expect this many:");
write(STDERR_FILENO, expected, strlen(expected));
test(nowait);
test(nowait);
warnx("Complete.");
return 0;
warnx("Complete.");
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -28,24 +28,22 @@
* SUCH DAMAGE.
*/
int check_createfile(unsigned name);
int check_openfile(unsigned name);
void check_closefile(int handle, unsigned name);
void check_write(int handle, unsigned name, unsigned code, unsigned seq,
off_t pos, off_t len);
off_t pos, off_t len);
void check_truncate(int handle, unsigned name, off_t len);
void check_mkdir(unsigned name);
void check_rmdir(unsigned name);
void check_unlink(unsigned name);
void check_link(unsigned from, unsigned to);
void check_rename(unsigned from, unsigned to);
void check_renamexd(unsigned fromdir, unsigned from,
unsigned todir, unsigned to);
void check_renamexd(unsigned fromdir, unsigned from, unsigned todir,
unsigned to);
void check_chdir(unsigned name);
void check_chdirup(void);
void check_sync(void);
void check_setup(void);
void checkfs(void);

View File

@@ -43,68 +43,51 @@
static char databuf[DATA_MAXSIZE];
static char readbuf[DATA_MAXSIZE];
static
void
prepdata(unsigned code, unsigned seq, char *buf, off_t len)
{
char smallbuf[32];
char letter;
size_t slen;
static void prepdata(unsigned code, unsigned seq, char *buf, off_t len) {
char smallbuf[32];
char letter;
size_t slen;
snprintf(smallbuf, sizeof(smallbuf), "%u@%u\n", seq, code);
slen = strlen(smallbuf);
snprintf(smallbuf, sizeof(smallbuf), "%u@%u\n", seq, code);
slen = strlen(smallbuf);
while (len >= slen) {
memcpy(buf, smallbuf, slen);
buf += slen;
len -= slen;
}
if (len > 1) {
letter = 'A' + (code + seq) % 26;
memset(buf, letter, len - 1);
buf += len - 1;
}
if (len > 0) {
*buf = '\n';
}
while (len >= slen) {
memcpy(buf, smallbuf, slen);
buf += slen;
len -= slen;
}
if (len > 1) {
letter = 'A' + (code + seq) % 26;
memset(buf, letter, len - 1);
buf += len - 1;
}
if (len > 0) {
*buf = '\n';
}
}
static
int
matches_at(size_t start, size_t len)
{
if (!memcmp(databuf + start, readbuf + start, len)) {
return 1;
}
return 0;
static int matches_at(size_t start, size_t len) {
if (!memcmp(databuf + start, readbuf + start, len)) {
return 1;
}
return 0;
}
static
int
byte_at(size_t start, size_t len, unsigned char val)
{
size_t i;
static int byte_at(size_t start, size_t len, unsigned char val) {
size_t i;
for (i=0; i<len; i++) {
if ((unsigned char)readbuf[start + i] != val) {
return 0;
}
}
return 1;
for (i = 0; i < len; i++) {
if ((unsigned char)readbuf[start + i] != val) {
return 0;
}
}
return 1;
}
static
int
zero_at(size_t start, size_t len)
{
return byte_at(start, len, 0);
}
static int zero_at(size_t start, size_t len) { return byte_at(start, len, 0); }
static
int
poison_at(size_t start, size_t len)
{
return byte_at(start, len, POISON_VAL);
static int poison_at(size_t start, size_t len) {
return byte_at(start, len, POISON_VAL);
}
/*
@@ -119,109 +102,93 @@ poison_at(size_t start, size_t len)
* CHECKSTART is the offset into the write region where we begin checking.
* CHECKLEN is the length of the region we check.
*/
int
data_matches(const char *namestr, off_t regionoffset,
unsigned code, unsigned seq, off_t zerostart, off_t len,
off_t checkstart, off_t checklen)
{
int ret;
off_t where;
size_t howmuch;
off_t absend, slop;
int data_matches(const char *namestr, off_t regionoffset, unsigned code,
unsigned seq, off_t zerostart, off_t len, off_t checkstart,
off_t checklen) {
int ret;
off_t where;
size_t howmuch;
off_t absend, slop;
assert(len <= DATA_MAXSIZE);
assert(checklen > 0);
assert(checklen <= len);
assert(checkstart >= 0 && checkstart < len);
assert(checkstart + checklen <= len);
assert(zerostart >= 0);
assert(zerostart <= len);
assert(len <= DATA_MAXSIZE);
assert(checklen > 0);
assert(checklen <= len);
assert(checkstart >= 0 && checkstart < len);
assert(checkstart + checklen <= len);
assert(zerostart >= 0);
assert(zerostart <= len);
prepdata(code, seq, databuf, len);
prepdata(code, seq, databuf, len);
ret = 1;
while (checklen > 0) {
/* check one block at a time */
where = checkstart;
howmuch = BLOCKSIZE;
/* no more than is left to do */
if (howmuch > checklen) {
howmuch = checklen;
}
/* if we stick over a block boundary, stop there */
absend = regionoffset + where + howmuch;
slop = absend % BLOCKSIZE;
if (slop != 0 && slop < howmuch) {
howmuch -= slop;
}
/* if we go past the zerostart point, stop there */
if (where < zerostart && where + howmuch > zerostart) {
howmuch = zerostart - where;
}
assert(howmuch > 0);
ret = 1;
while (checklen > 0) {
/* check one block at a time */
where = checkstart;
howmuch = BLOCKSIZE;
/* no more than is left to do */
if (howmuch > checklen) {
howmuch = checklen;
}
/* if we stick over a block boundary, stop there */
absend = regionoffset + where + howmuch;
slop = absend % BLOCKSIZE;
if (slop != 0 && slop < howmuch) {
howmuch -= slop;
}
/* if we go past the zerostart point, stop there */
if (where < zerostart && where + howmuch > zerostart) {
howmuch = zerostart - where;
}
assert(howmuch > 0);
if (matches_at(where, howmuch)) {
/* nothing */
}
else if (zero_at(where, howmuch)) {
if (where >= zerostart) {
printf("WARNING: file %s range %lld-%lld is "
"zeroed\n",
namestr, regionoffset + where,
regionoffset + where + howmuch);
}
else {
ret = 0;
}
}
else if (poison_at(where, howmuch)) {
if (where >= zerostart) {
printf("ERROR: file %s range %lld-%lld is "
"poisoned\n",
namestr, regionoffset + where,
regionoffset + where + howmuch);
}
else {
ret = 0;
}
}
else {
ret = 0;
}
if (matches_at(where, howmuch)) {
/* nothing */
} else if (zero_at(where, howmuch)) {
if (where >= zerostart) {
printf("WARNING: file %s range %lld-%lld is "
"zeroed\n",
namestr, regionoffset + where, regionoffset + where + howmuch);
} else {
ret = 0;
}
} else if (poison_at(where, howmuch)) {
if (where >= zerostart) {
printf("ERROR: file %s range %lld-%lld is "
"poisoned\n",
namestr, regionoffset + where, regionoffset + where + howmuch);
} else {
ret = 0;
}
} else {
ret = 0;
}
checkstart += howmuch;
checklen -= howmuch;
}
return ret;
checkstart += howmuch;
checklen -= howmuch;
}
return ret;
}
void
data_check(const char *namestr, off_t regionoffset,
unsigned code, unsigned seq, off_t zerostart, off_t len,
off_t checkstart, off_t checklen)
{
assert(zerostart >= 0);
assert(zerostart <= len);
void data_check(const char *namestr, off_t regionoffset, unsigned code,
unsigned seq, off_t zerostart, off_t len, off_t checkstart,
off_t checklen) {
assert(zerostart >= 0);
assert(zerostart <= len);
if (!data_matches(namestr, regionoffset,
code, seq, zerostart, len, checkstart, checklen)) {
printf("ERROR: file %s range %lld-%lld contains garbage\n",
namestr, regionoffset + checkstart,
regionoffset + checkstart + checklen);
}
if (!data_matches(namestr, regionoffset, code, seq, zerostart, len,
checkstart, checklen)) {
printf("ERROR: file %s range %lld-%lld contains garbage\n", namestr,
regionoffset + checkstart, regionoffset + checkstart + checklen);
}
}
void *
data_map(unsigned code, unsigned seq, off_t len)
{
assert(len <= DATA_MAXSIZE);
prepdata(code, seq, databuf, len);
return databuf;
void *data_map(unsigned code, unsigned seq, off_t len) {
assert(len <= DATA_MAXSIZE);
prepdata(code, seq, databuf, len);
return databuf;
}
void *
data_mapreadbuf(off_t len)
{
assert(len <= DATA_MAXSIZE);
return readbuf;
void *data_mapreadbuf(off_t len) {
assert(len <= DATA_MAXSIZE);
return readbuf;
}

View File

@@ -30,12 +30,12 @@
void *data_map(unsigned code, unsigned seq, off_t len);
void *data_mapreadbuf(off_t len);
int data_matches(const char *namestr, off_t regionoffset,
unsigned code, unsigned seq, off_t zerostart, off_t len,
off_t checkstart, off_t checklen);
void data_check(const char *namestr, off_t regionoffset,
unsigned code, unsigned seq, off_t zerostart, off_t len,
off_t checkstart, off_t checklen);
int data_matches(const char *namestr, off_t regionoffset, unsigned code,
unsigned seq, off_t zerostart, off_t len, off_t checkstart,
off_t checklen);
void data_check(const char *namestr, off_t regionoffset, unsigned code,
unsigned seq, off_t zerostart, off_t len, off_t checkstart,
off_t checklen);
#define DATA_MAXSIZE 65536
#define POISON_VAL 0xa9

View File

@@ -39,213 +39,180 @@
#include "name.h"
#include "do.h"
int
do_opendir(unsigned name)
{
const char *namestr;
int fd;
int do_opendir(unsigned name) {
const char *namestr;
int fd;
namestr = name_get(name);
fd = open(namestr, O_RDONLY);
if (fd < 0) {
err(1, "%s: opendir", namestr);
}
return fd;
namestr = name_get(name);
fd = open(namestr, O_RDONLY);
if (fd < 0) {
err(1, "%s: opendir", namestr);
}
return fd;
}
void
do_closedir(int fd, unsigned name)
{
if (close(fd)) {
warn("%s: closedir", name_get(name));
}
void do_closedir(int fd, unsigned name) {
if (close(fd)) {
warn("%s: closedir", name_get(name));
}
}
int
do_createfile(unsigned name)
{
const char *namestr;
int fd;
int do_createfile(unsigned name) {
const char *namestr;
int fd;
namestr = name_get(name);
fd = open(namestr, O_WRONLY|O_CREAT|O_EXCL, 0664);
if (fd < 0) {
err(1, "%s: create", namestr);
}
printf("create %s\n", namestr);
return fd;
namestr = name_get(name);
fd = open(namestr, O_WRONLY | O_CREAT | O_EXCL, 0664);
if (fd < 0) {
err(1, "%s: create", namestr);
}
printf("create %s\n", namestr);
return fd;
}
int
do_openfile(unsigned name, int dotrunc)
{
const char *namestr;
int fd;
int do_openfile(unsigned name, int dotrunc) {
const char *namestr;
int fd;
namestr = name_get(name);
fd = open(namestr, O_WRONLY | (dotrunc ? O_TRUNC : 0), 0664);
if (fd < 0) {
err(1, "%s: open", namestr);
}
return fd;
namestr = name_get(name);
fd = open(namestr, O_WRONLY | (dotrunc ? O_TRUNC : 0), 0664);
if (fd < 0) {
err(1, "%s: open", namestr);
}
return fd;
}
void
do_closefile(int fd, unsigned name)
{
if (close(fd)) {
warn("%s: close", name_get(name));
}
void do_closefile(int fd, unsigned name) {
if (close(fd)) {
warn("%s: close", name_get(name));
}
}
void
do_write(int fd, unsigned name, unsigned code, unsigned seq,
off_t pos, off_t len)
{
off_t done = 0;
ssize_t ret;
char *buf;
const char *namestr;
void do_write(int fd, unsigned name, unsigned code, unsigned seq, off_t pos,
off_t len) {
off_t done = 0;
ssize_t ret;
char *buf;
const char *namestr;
namestr = name_get(name);
buf = data_map(code, seq, len);
if (lseek(fd, pos, SEEK_SET) == -1) {
err(1, "%s: lseek to %lld", name_get(name), pos);
}
namestr = name_get(name);
buf = data_map(code, seq, len);
if (lseek(fd, pos, SEEK_SET) == -1) {
err(1, "%s: lseek to %lld", name_get(name), pos);
}
while (done < len) {
ret = write(fd, buf + done, len - done);
if (ret == -1) {
err(1, "%s: write %lld at %lld", name_get(name),
len, pos);
}
done += ret;
}
while (done < len) {
ret = write(fd, buf + done, len - done);
if (ret == -1) {
err(1, "%s: write %lld at %lld", name_get(name), len, pos);
}
done += ret;
}
printf("write %s: %lld at %lld\n", namestr, len, pos);
printf("write %s: %lld at %lld\n", namestr, len, pos);
}
void
do_truncate(int fd, unsigned name, off_t len)
{
const char *namestr;
void do_truncate(int fd, unsigned name, off_t len) {
const char *namestr;
namestr = name_get(name);
if (ftruncate(fd, len) == -1) {
err(1, "%s: truncate to %lld", namestr, len);
}
printf("truncate %s: to %lld\n", namestr, len);
namestr = name_get(name);
if (ftruncate(fd, len) == -1) {
err(1, "%s: truncate to %lld", namestr, len);
}
printf("truncate %s: to %lld\n", namestr, len);
}
void
do_mkdir(unsigned name)
{
const char *namestr;
void do_mkdir(unsigned name) {
const char *namestr;
namestr = name_get(name);
if (mkdir(namestr, 0775) == -1) {
err(1, "%s: mkdir", namestr);
}
printf("mkdir %s\n", namestr);
namestr = name_get(name);
if (mkdir(namestr, 0775) == -1) {
err(1, "%s: mkdir", namestr);
}
printf("mkdir %s\n", namestr);
}
void
do_rmdir(unsigned name)
{
const char *namestr;
void do_rmdir(unsigned name) {
const char *namestr;
namestr = name_get(name);
if (rmdir(namestr) == -1) {
err(1, "%s: rmdir", namestr);
}
printf("rmdir %s\n", namestr);
namestr = name_get(name);
if (rmdir(namestr) == -1) {
err(1, "%s: rmdir", namestr);
}
printf("rmdir %s\n", namestr);
}
void
do_unlink(unsigned name)
{
const char *namestr;
void do_unlink(unsigned name) {
const char *namestr;
namestr = name_get(name);
if (remove(namestr) == -1) {
err(1, "%s: remove", namestr);
}
printf("remove %s\n", namestr);
namestr = name_get(name);
if (remove(namestr) == -1) {
err(1, "%s: remove", namestr);
}
printf("remove %s\n", namestr);
}
void
do_link(unsigned from, unsigned to)
{
const char *fromstr, *tostr;
void do_link(unsigned from, unsigned to) {
const char *fromstr, *tostr;
fromstr = name_get(from);
tostr = name_get(to);
if (link(fromstr, tostr) == -1) {
err(1, "link %s to %s", fromstr, tostr);
}
printf("link %s %s\n", fromstr, tostr);
fromstr = name_get(from);
tostr = name_get(to);
if (link(fromstr, tostr) == -1) {
err(1, "link %s to %s", fromstr, tostr);
}
printf("link %s %s\n", fromstr, tostr);
}
void
do_rename(unsigned from, unsigned to)
{
const char *fromstr, *tostr;
void do_rename(unsigned from, unsigned to) {
const char *fromstr, *tostr;
fromstr = name_get(from);
tostr = name_get(to);
if (rename(fromstr, tostr) == -1) {
err(1, "rename %s to %s", fromstr, tostr);
}
printf("rename %s %s\n", fromstr, tostr);
fromstr = name_get(from);
tostr = name_get(to);
if (rename(fromstr, tostr) == -1) {
err(1, "rename %s to %s", fromstr, tostr);
}
printf("rename %s %s\n", fromstr, tostr);
}
void
do_renamexd(unsigned fromdir, unsigned from, unsigned todir, unsigned to)
{
char frombuf[64];
char tobuf[64];
void do_renamexd(unsigned fromdir, unsigned from, unsigned todir, unsigned to) {
char frombuf[64];
char tobuf[64];
strcpy(frombuf, name_get(fromdir));
strcat(frombuf, "/");
strcat(frombuf, name_get(from));
strcpy(frombuf, name_get(fromdir));
strcat(frombuf, "/");
strcat(frombuf, name_get(from));
strcpy(tobuf, name_get(todir));
strcat(tobuf, "/");
strcat(tobuf, name_get(to));
strcpy(tobuf, name_get(todir));
strcat(tobuf, "/");
strcat(tobuf, name_get(to));
if (rename(frombuf, tobuf) == -1) {
err(1, "rename %s to %s", frombuf, tobuf);
}
printf("rename %s %s\n", frombuf, tobuf);
if (rename(frombuf, tobuf) == -1) {
err(1, "rename %s to %s", frombuf, tobuf);
}
printf("rename %s %s\n", frombuf, tobuf);
}
void
do_chdir(unsigned name)
{
const char *namestr;
void do_chdir(unsigned name) {
const char *namestr;
namestr = name_get(name);
if (chdir(namestr) == -1) {
err(1, "chdir: %s", namestr);
}
printf("chdir %s\n", namestr);
namestr = name_get(name);
if (chdir(namestr) == -1) {
err(1, "chdir: %s", namestr);
}
printf("chdir %s\n", namestr);
}
void
do_chdirup(void)
{
if (chdir("..") == -1) {
err(1, "chdir: ..");
}
printf("chdir ..\n");
void do_chdirup(void) {
if (chdir("..") == -1) {
err(1, "chdir: ..");
}
printf("chdir ..\n");
}
void
do_sync(void)
{
if (sync()) {
warn("sync");
}
printf("sync\n");
printf("----------------------------------------\n");
void do_sync(void) {
if (sync()) {
warn("sync");
}
printf("sync\n");
printf("----------------------------------------\n");
}

View File

@@ -28,14 +28,13 @@
* SUCH DAMAGE.
*/
int do_opendir(unsigned name);
void do_closedir(int handle, unsigned name);
int do_createfile(unsigned name);
int do_openfile(unsigned name, int dotrunc);
void do_closefile(int handle, unsigned name);
void do_write(int handle, unsigned name, unsigned code, unsigned seq,
off_t pos, off_t len);
void do_write(int handle, unsigned name, unsigned code, unsigned seq, off_t pos,
off_t len);
void do_truncate(int handle, unsigned name, off_t len);
void do_mkdir(unsigned name);
void do_rmdir(unsigned name);

View File

@@ -37,160 +37,148 @@
#include "main.h"
struct workload {
const char *name;
const char *argname;
union {
void (*witharg)(const char *);
void (*noarg)(void);
} run;
const char *name;
const char *argname;
union {
void (*witharg)(const char *);
void (*noarg)(void);
} run;
};
#define WL(n) { .name = #n, .argname = NULL, .run.noarg = wl_##n }
#define WLA(n,a) { .name = #n, .argname = #a, .run.witharg = wl_##n }
#define WL(n) {.name = #n, .argname = NULL, .run.noarg = wl_##n}
#define WLA(n, a) {.name = #n, .argname = #a, .run.witharg = wl_##n}
static const struct workload workloads[] = {
WLA(createwrite, size),
WLA(rewrite, size),
WLA(randupdate, size),
WLA(truncwrite, size),
WLA(makehole, size),
WLA(fillhole, size),
WLA(truncfill, size),
WLA(append, size),
WLA(trunczero, size),
WLA(trunconeblock, size),
WLA(truncsmallersize, size),
WLA(trunclargersize, size),
WLA(appendandtrunczero, size),
WLA(appendandtruncpartly, size),
WL(mkfile),
WL(mkdir),
WL(mkmanyfile),
WL(mkmanydir),
WL(mktree),
WLA(mkrandtree, seed),
WL(rmfile),
WL(rmdir),
WL(rmfiledelayed),
WL(rmfiledelayedappend),
WL(rmdirdelayed),
WL(rmmanyfile),
WL(rmmanyfiledelayed),
WL(rmmanyfiledelayedandappend),
WL(rmmanydir),
WL(rmmanydirdelayed),
WL(rmtree),
WLA(rmrandtree, seed),
WL(linkfile),
WL(linkmanyfile),
WL(unlinkfile),
WL(unlinkmanyfile),
WL(linkunlinkfile),
WL(renamefile),
WL(renamedir),
WL(renamesubtree),
WL(renamexdfile),
WL(renamexddir),
WL(renamexdsubtree),
WL(renamemanyfile),
WL(renamemanydir),
WL(renamemanysubtree),
WL(copyandrename),
WL(untar),
WL(compile),
WL(cvsupdate),
WLA(writefileseq, seed),
WLA(writetruncseq, seed),
WLA(mkrmseq, seed),
WLA(linkunlinkseq, seed),
WLA(renameseq, seed),
WLA(diropseq, seed),
WLA(genseq, seed),
WLA(createwrite, size),
WLA(rewrite, size),
WLA(randupdate, size),
WLA(truncwrite, size),
WLA(makehole, size),
WLA(fillhole, size),
WLA(truncfill, size),
WLA(append, size),
WLA(trunczero, size),
WLA(trunconeblock, size),
WLA(truncsmallersize, size),
WLA(trunclargersize, size),
WLA(appendandtrunczero, size),
WLA(appendandtruncpartly, size),
WL(mkfile),
WL(mkdir),
WL(mkmanyfile),
WL(mkmanydir),
WL(mktree),
WLA(mkrandtree, seed),
WL(rmfile),
WL(rmdir),
WL(rmfiledelayed),
WL(rmfiledelayedappend),
WL(rmdirdelayed),
WL(rmmanyfile),
WL(rmmanyfiledelayed),
WL(rmmanyfiledelayedandappend),
WL(rmmanydir),
WL(rmmanydirdelayed),
WL(rmtree),
WLA(rmrandtree, seed),
WL(linkfile),
WL(linkmanyfile),
WL(unlinkfile),
WL(unlinkmanyfile),
WL(linkunlinkfile),
WL(renamefile),
WL(renamedir),
WL(renamesubtree),
WL(renamexdfile),
WL(renamexddir),
WL(renamexdsubtree),
WL(renamemanyfile),
WL(renamemanydir),
WL(renamemanysubtree),
WL(copyandrename),
WL(untar),
WL(compile),
WL(cvsupdate),
WLA(writefileseq, seed),
WLA(writetruncseq, seed),
WLA(mkrmseq, seed),
WLA(linkunlinkseq, seed),
WLA(renameseq, seed),
WLA(diropseq, seed),
WLA(genseq, seed),
};
static const unsigned numworkloads = sizeof(workloads) / sizeof(workloads[0]);
#undef WL
#undef WLA
static
const struct workload *
findworkload(const char *name)
{
unsigned i;
static const struct workload *findworkload(const char *name) {
unsigned i;
for (i=0; i<numworkloads; i++) {
if (!strcmp(workloads[i].name, name)) {
return &workloads[i];
}
}
return NULL;
for (i = 0; i < numworkloads; i++) {
if (!strcmp(workloads[i].name, name)) {
return &workloads[i];
}
}
return NULL;
}
static
void
printworkloads(void)
{
unsigned i;
static void printworkloads(void) {
unsigned i;
printf("Supported workloads:\n");
for (i=0; i<numworkloads; i++) {
printf(" %s", workloads[i].name);
if (workloads[i].argname) {
printf(" %s", workloads[i].argname);
}
printf("\n");
}
printf("Supported workloads:\n");
for (i = 0; i < numworkloads; i++) {
printf(" %s", workloads[i].name);
if (workloads[i].argname) {
printf(" %s", workloads[i].argname);
}
printf("\n");
}
}
int
main(int argc, char *argv[])
{
const char *workloadname;
const struct workload *workload;
int checkmode = 0;
int main(int argc, char *argv[]) {
const char *workloadname;
const struct workload *workload;
int checkmode = 0;
if (argc == 2 && !strcmp(argv[1], "list")) {
printworkloads();
exit(0);
}
if (argc == 2 && !strcmp(argv[1], "list")) {
printworkloads();
exit(0);
}
if (argc < 3) {
warnx("Usage: %s do|check workload [arg]", argv[0]);
warnx("Use \"list\" for a list of workloads");
exit(1);
}
if (argc < 3) {
warnx("Usage: %s do|check workload [arg]", argv[0]);
warnx("Use \"list\" for a list of workloads");
exit(1);
}
if (!strcmp(argv[1], "do")) {
checkmode = 0;
}
else if (!strcmp(argv[1], "check")) {
checkmode = 1;
}
else {
errx(1, "Action must be \"do\" or \"check\"");
}
if (!strcmp(argv[1], "do")) {
checkmode = 0;
} else if (!strcmp(argv[1], "check")) {
checkmode = 1;
} else {
errx(1, "Action must be \"do\" or \"check\"");
}
workloadname = argv[2];
workload = findworkload(workloadname);
if (workload == NULL) {
errx(1, "Unknown workload %s\n", workloadname);
printworkloads();
exit(1);
}
setcheckmode(checkmode);
if (workload->argname) {
if (argc != 4) {
errx(1, "%s requires argument %s\n",
workloadname, workload->argname);
}
workload->run.witharg(argv[3]);
}
else {
if (argc != 3) {
errx(1, "Stray argument for workload %s",workloadname);
}
workload->run.noarg();
}
complete();
return 0;
workloadname = argv[2];
workload = findworkload(workloadname);
if (workload == NULL) {
errx(1, "Unknown workload %s\n", workloadname);
printworkloads();
exit(1);
}
setcheckmode(checkmode);
if (workload->argname) {
if (argc != 4) {
errx(1, "%s requires argument %s\n", workloadname, workload->argname);
}
workload->run.witharg(argv[3]);
} else {
if (argc != 3) {
errx(1, "Stray argument for workload %s", workloadname);
}
workload->run.noarg();
}
complete();
return 0;
}

View File

@@ -37,57 +37,28 @@
#define MAXNAMES 32
static const char *const names[MAXNAMES] = {
"allspice",
"anise",
"basil",
"cardamom",
"cayenne",
"cilantro",
"cinnamon",
"cloves",
"coriander",
"cumin",
"dill",
"fennel",
"fenugreek",
"galangal",
"ginger",
"horseradish",
"lemongrass",
"licorice",
"mace",
"marjoram",
"mustard",
"nutmeg",
"oregano",
"parsley",
"paprika",
"pepper",
"saffron",
"sage",
"rosemary",
"thyme",
"turmeric",
"wasabi",
"allspice", "anise", "basil", "cardamom", "cayenne",
"cilantro", "cinnamon", "cloves", "coriander", "cumin",
"dill", "fennel", "fenugreek", "galangal", "ginger",
"horseradish", "lemongrass", "licorice", "mace", "marjoram",
"mustard", "nutmeg", "oregano", "parsley", "paprika",
"pepper", "saffron", "sage", "rosemary", "thyme",
"turmeric", "wasabi",
};
const char *
name_get(unsigned name)
{
assert(name < MAXNAMES);
return names[name];
const char *name_get(unsigned name) {
assert(name < MAXNAMES);
return names[name];
}
unsigned
name_find(const char *namestr)
{
unsigned i;
unsigned name_find(const char *namestr) {
unsigned i;
for (i=0; i<MAXNAMES; i++) {
if (!strcmp(namestr, names[i])) {
return i;
}
}
errx(1, "Encountered unknown/unexpected name %s", namestr);
return 0;
for (i = 0; i < MAXNAMES; i++) {
if (!strcmp(namestr, names[i])) {
return i;
}
}
errx(1, "Encountered unknown/unexpected name %s", namestr);
return 0;
}

View File

@@ -28,6 +28,5 @@
* SUCH DAMAGE.
*/
const char *name_get(unsigned name);
unsigned name_find(const char *namestr);

View File

@@ -41,26 +41,24 @@
#include "main.h"
struct file {
unsigned name;
unsigned testcode;
unsigned seq;
int handle;
unsigned name;
unsigned testcode;
unsigned seq;
int handle;
};
struct dir {
unsigned name;
int handle;
unsigned name;
int handle;
};
static int checkmode;
void
setcheckmode(int mode)
{
checkmode = mode;
if (checkmode) {
check_setup();
}
void setcheckmode(int mode) {
checkmode = mode;
if (checkmode) {
check_setup();
}
}
////////////////////////////////////////////////////////////
@@ -69,33 +67,27 @@ setcheckmode(int mode)
#define MAXDIRS 32
DECLPOOL(dir, MAXDIRS);
struct dir *
op_opendir(unsigned name)
{
struct dir *ret;
struct dir *op_opendir(unsigned name) {
struct dir *ret;
ret = POOLALLOC(dir);
ret->name = name;
if (checkmode) {
ret->handle = -1;
}
else {
ret->handle = do_opendir(name);
}
return ret;
ret = POOLALLOC(dir);
ret->name = name;
if (checkmode) {
ret->handle = -1;
} else {
ret->handle = do_opendir(name);
}
return ret;
}
void
op_closedir(struct dir *d)
{
if (checkmode) {
/* nothing */
(void)d;
}
else {
do_closedir(d->handle, d->name);
}
POOLFREE(dir, d);
void op_closedir(struct dir *d) {
if (checkmode) {
/* nothing */
(void)d;
} else {
do_closedir(d->handle, d->name);
}
POOLFREE(dir, d);
}
////////////////////////////////////////////////////////////
@@ -104,212 +96,166 @@ op_closedir(struct dir *d)
#define MAXFILES 32
DECLPOOL(file, MAXFILES);
struct file *
op_open(unsigned testcode, unsigned name, unsigned openflags)
{
struct file *ret;
int dotrunc;
struct file *op_open(unsigned testcode, unsigned name, unsigned openflags) {
struct file *ret;
int dotrunc;
if (openflags == O_TRUNC) {
openflags = 0;
dotrunc = 1;
}
else {
dotrunc = 0;
}
if (openflags == O_TRUNC) {
openflags = 0;
dotrunc = 1;
} else {
dotrunc = 0;
}
assert(openflags == 0 || openflags == (O_CREAT|O_EXCL));
assert(openflags == 0 || openflags == (O_CREAT | O_EXCL));
ret = POOLALLOC(file);
ret->name = name;
ret->testcode = testcode;
ret->seq = 0;
if (checkmode) {
if (openflags) {
ret->handle = check_createfile(name);
}
else {
ret->handle = check_openfile(name);
}
}
else {
if (openflags) {
assert(dotrunc == 0);
ret->handle = do_createfile(name);
}
else {
/*
* XXX: as of 2013 OS/161 doesn't provide a
* truncate call - neither truncate() nor
* ftruncate()! You can only O_TRUNC. Oops...
*/
ret->handle = do_openfile(name, dotrunc);
dotrunc = 0;
}
}
if (dotrunc) {
op_truncate(ret, 0);
}
return ret;
ret = POOLALLOC(file);
ret->name = name;
ret->testcode = testcode;
ret->seq = 0;
if (checkmode) {
if (openflags) {
ret->handle = check_createfile(name);
} else {
ret->handle = check_openfile(name);
}
} else {
if (openflags) {
assert(dotrunc == 0);
ret->handle = do_createfile(name);
} else {
/*
* XXX: as of 2013 OS/161 doesn't provide a
* truncate call - neither truncate() nor
* ftruncate()! You can only O_TRUNC. Oops...
*/
ret->handle = do_openfile(name, dotrunc);
dotrunc = 0;
}
}
if (dotrunc) {
op_truncate(ret, 0);
}
return ret;
}
void
op_close(struct file *f)
{
if (checkmode) {
check_closefile(f->handle, f->name);
}
else {
do_closefile(f->handle, f->name);
}
POOLFREE(file, f);
void op_close(struct file *f) {
if (checkmode) {
check_closefile(f->handle, f->name);
} else {
do_closefile(f->handle, f->name);
}
POOLFREE(file, f);
}
void
op_write(struct file *f, off_t pos, off_t len)
{
off_t amount;
void op_write(struct file *f, off_t pos, off_t len) {
off_t amount;
while (len > 0) {
amount = len;
if (amount > DATA_MAXSIZE) {
amount = DATA_MAXSIZE;
}
while (len > 0) {
amount = len;
if (amount > DATA_MAXSIZE) {
amount = DATA_MAXSIZE;
}
if (checkmode) {
check_write(f->handle, f->name, f->testcode, f->seq,
pos, amount);
}
else {
do_write(f->handle, f->name, f->testcode, f->seq,
pos, amount);
}
f->seq++;
pos += amount;
len -= amount;
}
if (checkmode) {
check_write(f->handle, f->name, f->testcode, f->seq, pos, amount);
} else {
do_write(f->handle, f->name, f->testcode, f->seq, pos, amount);
}
f->seq++;
pos += amount;
len -= amount;
}
}
void
op_truncate(struct file *f, off_t len)
{
if (checkmode) {
check_truncate(f->handle, f->name, len);
}
else {
do_truncate(f->handle, f->name, len);
}
void op_truncate(struct file *f, off_t len) {
if (checkmode) {
check_truncate(f->handle, f->name, len);
} else {
do_truncate(f->handle, f->name, len);
}
}
////////////////////////////////////////////////////////////
// dirops
void
op_mkdir(unsigned name)
{
if (checkmode) {
check_mkdir(name);
}
else {
do_mkdir(name);
}
void op_mkdir(unsigned name) {
if (checkmode) {
check_mkdir(name);
} else {
do_mkdir(name);
}
}
void
op_rmdir(unsigned name)
{
if (checkmode) {
check_rmdir(name);
}
else {
do_rmdir(name);
}
void op_rmdir(unsigned name) {
if (checkmode) {
check_rmdir(name);
} else {
do_rmdir(name);
}
}
void
op_unlink(unsigned name)
{
if (checkmode) {
check_unlink(name);
}
else {
do_unlink(name);
}
void op_unlink(unsigned name) {
if (checkmode) {
check_unlink(name);
} else {
do_unlink(name);
}
}
void
op_link(unsigned from, unsigned to)
{
if (checkmode) {
check_link(from, to);
}
else {
do_link(from, to);
}
void op_link(unsigned from, unsigned to) {
if (checkmode) {
check_link(from, to);
} else {
do_link(from, to);
}
}
void
op_rename(unsigned from, unsigned to)
{
if (checkmode) {
check_rename(from, to);
}
else {
do_rename(from, to);
}
void op_rename(unsigned from, unsigned to) {
if (checkmode) {
check_rename(from, to);
} else {
do_rename(from, to);
}
}
void
op_renamexd(unsigned fromdir, unsigned from, unsigned todir, unsigned to)
{
if (checkmode) {
check_renamexd(fromdir, from, todir, to);
}
else {
do_renamexd(fromdir, from, todir, to);
}
void op_renamexd(unsigned fromdir, unsigned from, unsigned todir, unsigned to) {
if (checkmode) {
check_renamexd(fromdir, from, todir, to);
} else {
do_renamexd(fromdir, from, todir, to);
}
}
void
op_chdir(unsigned name)
{
if (checkmode) {
check_chdir(name);
}
else {
do_chdir(name);
}
void op_chdir(unsigned name) {
if (checkmode) {
check_chdir(name);
} else {
do_chdir(name);
}
}
void
op_chdirup(void)
{
if (checkmode) {
check_chdirup();
}
else {
do_chdirup();
}
void op_chdirup(void) {
if (checkmode) {
check_chdirup();
} else {
do_chdirup();
}
}
////////////////////////////////////////////////////////////
// other
void
op_sync(void)
{
if (checkmode) {
check_sync();
}
else {
do_sync();
}
void op_sync(void) {
if (checkmode) {
check_sync();
} else {
do_sync();
}
}
void
complete(void)
{
if (checkmode) {
checkfs();
}
void complete(void) {
if (checkmode) {
checkfs();
}
}

View File

@@ -34,37 +34,33 @@
#include "pool.h"
unsigned
poolalloc(struct poolctl *pool)
{
uint32_t mask;
unsigned j, i;
unsigned poolalloc(struct poolctl *pool) {
uint32_t mask;
unsigned j, i;
assert(pool->max % 32 == 0);
for (j=0; j<pool->max/32; j++) {
for (mask=1, i=0; i<32; mask<<=1, i++) {
if ((pool->inuse[j] & mask) == 0) {
pool->inuse[j] |= mask;
return j*32 + i;
}
}
}
errx(1, "Too many %s -- increase %s in %s",
pool->itemtype, pool->maxname, pool->file);
return 0;
assert(pool->max % 32 == 0);
for (j = 0; j < pool->max / 32; j++) {
for (mask = 1, i = 0; i < 32; mask <<= 1, i++) {
if ((pool->inuse[j] & mask) == 0) {
pool->inuse[j] |= mask;
return j * 32 + i;
}
}
}
errx(1, "Too many %s -- increase %s in %s", pool->itemtype, pool->maxname,
pool->file);
return 0;
}
void
poolfree(struct poolctl *pool, unsigned num)
{
uint32_t mask;
unsigned pos;
void poolfree(struct poolctl *pool, unsigned num) {
uint32_t mask;
unsigned pos;
assert(num < pool->max);
assert(num < pool->max);
pos = num / 32;
mask = 1 << (num % 32);
pos = num / 32;
mask = 1 << (num % 32);
assert(pool->inuse[pos] & mask);
pool->inuse[pos] &= ~(uint32_t)mask;
assert(pool->inuse[pos] & mask);
pool->inuse[pos] &= ~(uint32_t)mask;
}

View File

@@ -29,26 +29,24 @@
*/
struct poolctl {
uint32_t *inuse;
unsigned max;
const char *itemtype;
const char *maxname;
const char *file;
uint32_t *inuse;
unsigned max;
const char *itemtype;
const char *maxname;
const char *file;
};
#define DIVROUNDUP(a, b) (((a) + (b) - 1) / (b))
#define ROUNDUP(a, b) (DIVROUNDUP(a, b) * (b))
#define DIVROUNDUP(a, b) (((a) + (b) - 1) / (b))
#define ROUNDUP(a, b) (DIVROUNDUP(a, b) * (b))
#define DECLPOOL(T, MAX) \
static struct T pool_space_##T[ROUNDUP(MAX, 32)]; \
static uint32_t pool_inuse_##T[DIVROUNDUP(MAX, 32)]; \
static struct poolctl pool_##T = { \
.inuse = pool_inuse_##T, \
.max = ROUNDUP(MAX, 32), \
.itemtype = "struct " #T, \
.maxname = #MAX, \
.file = __FILE__ \
}
#define DECLPOOL(T, MAX) \
static struct T pool_space_##T[ROUNDUP(MAX, 32)]; \
static uint32_t pool_inuse_##T[DIVROUNDUP(MAX, 32)]; \
static struct poolctl pool_##T = {.inuse = pool_inuse_##T, \
.max = ROUNDUP(MAX, 32), \
.itemtype = "struct " #T, \
.maxname = #MAX, \
.file = __FILE__}
#define POOLALLOC(T) (&pool_space_##T[poolalloc(&pool_##T)])
#define POOLFREE(T, x) (poolfree(&pool_##T, (x) - pool_space_##T))

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,6 @@
* SUCH DAMAGE.
*/
/*
* The VFS-interface operations that can write to the fs are:
*

View File

@@ -49,35 +49,34 @@
#define HASHP 104729
int
main(int argc, char *argv[])
{
int fd;
char readbuf[1];
int j = 0;
int main(int argc, char *argv[]) {
int fd;
char readbuf[1];
int j = 0;
#ifdef HOST
hostcompat_init(argc, argv);
hostcompat_init(argc, argv);
#endif
if (argc != 2) {
errx(1, "Usage: hash filename");
}
if (argc != 2) {
errx(1, "Usage: hash filename");
}
fd = open(argv[1], O_RDONLY, 0664);
fd = open(argv[1], O_RDONLY, 0664);
if (fd<0) {
err(1, "%s", argv[1]);
}
if (fd < 0) {
err(1, "%s", argv[1]);
}
for (;;) {
if (read(fd, readbuf, 1) <= 0) break;
j = ((j*8) + (int) readbuf[0]) % HASHP;
}
for (;;) {
if (read(fd, readbuf, 1) <= 0)
break;
j = ((j * 8) + (int)readbuf[0]) % HASHP;
}
close(fd);
close(fd);
printf("Hash : %d\n", j);
printf("Hash : %d\n", j);
return 0;
return 0;
}

View File

@@ -34,20 +34,18 @@
* Loops consuming CPU cycles.
*/
int
main(void)
{
volatile int i;
volatile int k, l, m;
int main(void) {
volatile int i;
volatile int k, l, m;
k = 1283;
l = 53;
for (i=0; i<15000000; i++) {
l = m + k;
}
k = 1283;
l = 53;
for (i = 0; i < 15000000; i++) {
l = m + k;
}
// gcc 4.8 improperly demands this
(void)l;
// gcc 4.8 improperly demands this
(void)l;
return 0;
return 0;
}

View File

@@ -40,45 +40,42 @@
#include <stdio.h>
#include <stdlib.h>
#define PageSize 4096
#define NumPages 512
#define PageSize 4096
#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 */
int
main(void)
{
int i,j;
int main(void) {
int i, j;
printf("Entering the huge program - I will stress test your VM\n");
printf("Entering the huge program - I will stress test your VM\n");
/* move number in so that sparse[i][0]=i */
for (i=0; i<NumPages; i++) {
sparse[i][0]=i;
}
/* move number in so that sparse[i][0]=i */
for (i = 0; i < NumPages; i++) {
sparse[i][0] = i;
}
printf("stage [1] done\n");
printf("stage [1] done\n");
/* increment each location 5 times */
for (j=0; j<5; j++) {
for (i=0; i<NumPages; i++) {
sparse[i][0]++;
}
printf("stage [2.%d] done\n", j);
}
/* increment each location 5 times */
for (j = 0; j < 5; j++) {
for (i = 0; i < NumPages; i++) {
sparse[i][0]++;
}
printf("stage [2.%d] done\n", j);
}
printf("stage [2] done\n");
printf("stage [2] done\n");
/* check if the numbers are sane */
for (i=NumPages-1; i>=0; i--) {
if (sparse[i][0]!=i+5) {
printf("BAD NEWS!!! - your VM mechanism has a bug!\n");
exit(1);
}
}
/* check if the numbers are sane */
for (i = NumPages - 1; i >= 0; i--) {
if (sparse[i][0] != i + 5) {
printf("BAD NEWS!!! - your VM mechanism has a bug!\n");
exit(1);
}
}
printf("You passed!\n");
printf("You passed!\n");
return 0;
return 0;
}

View File

@@ -49,52 +49,45 @@
#include <assert.h>
#include <err.h>
#define _PATH_RANDOM "random:"
#define _PATH_RANDOM "random:"
#define SMALLSIZE 72
#define MEDIUMSIZE 896
#define BIGSIZE 16384
#define HUGESIZE (1024 * 1024 * 1024)
#define SMALLSIZE 72
#define MEDIUMSIZE 896
#define BIGSIZE 16384
#define HUGESIZE (1024 * 1024 * 1024)
/* Maximum amount of space per block we allow for indexing structures */
#define OVERHEAD 32
#define OVERHEAD 32
/* Point past which we assume something else is going on */
#define ABSURD_OVERHEAD 256
#define ABSURD_OVERHEAD 256
static
int
geti(void)
{
int val=0;
int ch, digits=0;
static int geti(void) {
int val = 0;
int ch, digits = 0;
while (1) {
ch = getchar();
if (ch=='\n' || ch=='\r') {
putchar('\n');
break;
}
else if ((ch=='\b' || ch==127) && digits>0) {
printf("\b \b");
val = val/10;
digits--;
}
else if (ch>='0' && ch<='9') {
putchar(ch);
val = val*10 + (ch-'0');
digits++;
}
else {
putchar('\a');
}
}
while (1) {
ch = getchar();
if (ch == '\n' || ch == '\r') {
putchar('\n');
break;
} else if ((ch == '\b' || ch == 127) && digits > 0) {
printf("\b \b");
val = val / 10;
digits--;
} else if (ch >= '0' && ch <= '9') {
putchar(ch);
val = val * 10 + (ch - '0');
digits++;
} else {
putchar('\a');
}
}
if (digits==0) {
return -1;
}
return val;
if (digits == 0) {
return -1;
}
return val;
}
////////////////////////////////////////////////////////////
@@ -102,65 +95,60 @@ geti(void)
/*
* Fill a block of memory with a test pattern.
*/
static
void
markblock(volatile void *ptr, size_t size, unsigned bias, int doprint)
{
size_t n, i;
unsigned long *pl;
unsigned long val;
static void markblock(volatile void *ptr, size_t size, unsigned bias,
int doprint) {
size_t n, i;
unsigned long *pl;
unsigned long val;
pl = (unsigned long *)ptr;
n = size / sizeof(unsigned long);
pl = (unsigned long *)ptr;
n = size / sizeof(unsigned long);
for (i=0; i<n; i++) {
val = ((unsigned long)i ^ (unsigned long)bias);
pl[i] = val;
if (doprint && (i%64==63)) {
printf(".");
}
}
if (doprint) {
printf("\n");
}
for (i = 0; i < n; i++) {
val = ((unsigned long)i ^ (unsigned long)bias);
pl[i] = val;
if (doprint && (i % 64 == 63)) {
printf(".");
}
}
if (doprint) {
printf("\n");
}
}
/*
* Check a block marked with markblock()
*/
static
int
checkblock(volatile void *ptr, size_t size, unsigned bias, int doprint)
{
size_t n, i;
unsigned long *pl;
unsigned long val;
static int checkblock(volatile void *ptr, size_t size, unsigned bias,
int doprint) {
size_t n, i;
unsigned long *pl;
unsigned long val;
pl = (unsigned long *)ptr;
n = size / sizeof(unsigned long);
pl = (unsigned long *)ptr;
n = size / sizeof(unsigned long);
for (i=0; i<n; i++) {
val = ((unsigned long)i ^ (unsigned long)bias);
if (pl[i] != val) {
if (doprint) {
printf("\n");
}
printf("FAILED: data mismatch at offset %lu of block "
"at 0x%lx: %lu vs. %lu\n",
(unsigned long) (i*sizeof(unsigned long)),
(unsigned long)(uintptr_t)pl,
pl[i], val);
return -1;
}
if (doprint && (i%64==63)) {
printf(".");
}
}
if (doprint) {
printf("\n");
}
for (i = 0; i < n; i++) {
val = ((unsigned long)i ^ (unsigned long)bias);
if (pl[i] != val) {
if (doprint) {
printf("\n");
}
printf("FAILED: data mismatch at offset %lu of block "
"at 0x%lx: %lu vs. %lu\n",
(unsigned long)(i * sizeof(unsigned long)),
(unsigned long)(uintptr_t)pl, pl[i], val);
return -1;
}
if (doprint && (i % 64 == 63)) {
printf(".");
}
}
if (doprint) {
printf("\n");
}
return 0;
return 0;
}
////////////////////////////////////////////////////////////
@@ -172,32 +160,28 @@ checkblock(volatile void *ptr, size_t size, unsigned bias, int doprint)
* allocated.
*/
static
void
test1(void)
{
volatile unsigned *x;
static void test1(void) {
volatile unsigned *x;
printf("*** Malloc test 1 ***\n");
printf("Allocating %u bytes\n", BIGSIZE);
x = malloc(BIGSIZE);
if (x==NULL) {
printf("FAILED: malloc failed\n");
return;
}
printf("*** Malloc test 1 ***\n");
printf("Allocating %u bytes\n", BIGSIZE);
x = malloc(BIGSIZE);
if (x == NULL) {
printf("FAILED: malloc failed\n");
return;
}
markblock(x, BIGSIZE, 0, 0);
if (checkblock(x, BIGSIZE, 0, 0)) {
printf("FAILED: data corrupt\n");
return;
}
markblock(x, BIGSIZE, 0, 0);
if (checkblock(x, BIGSIZE, 0, 0)) {
printf("FAILED: data corrupt\n");
return;
}
free((void *)x);
free((void *)x);
printf("Passed malloc test 1.\n");
printf("Passed malloc test 1.\n");
}
////////////////////////////////////////////////////////////
/*
@@ -230,53 +214,48 @@ test1(void)
* available.
*/
static
void
test2(void)
{
volatile unsigned *x;
size_t size;
static void test2(void) {
volatile unsigned *x;
size_t size;
printf("Entering malloc test 2.\n");
printf("Make sure you read and understand the comment in malloctest.c "
"that\nexplains the conditions this test assumes.\n\n");
printf("Entering malloc test 2.\n");
printf("Make sure you read and understand the comment in malloctest.c "
"that\nexplains the conditions this test assumes.\n\n");
printf("Testing how much memory we can allocate:\n");
printf("Testing how much memory we can allocate:\n");
for (size = HUGESIZE; (x = malloc(size))==NULL; size = size/2) {
printf(" %9lu bytes: failed\n", (unsigned long) size);
}
printf(" %9lu bytes: succeeded\n", (unsigned long) size);
for (size = HUGESIZE; (x = malloc(size)) == NULL; size = size / 2) {
printf(" %9lu bytes: failed\n", (unsigned long)size);
}
printf(" %9lu bytes: succeeded\n", (unsigned long)size);
printf("Passed part 1\n");
printf("Passed part 1\n");
printf("Touching all the words in the block.\n");
markblock(x, size, 0, 1);
printf("Touching all the words in the block.\n");
markblock(x, size, 0, 1);
printf("Validating the words in the block.\n");
if (checkblock(x, size, 0, 1)) {
printf("FAILED: data corrupt\n");
return;
}
printf("Passed part 2\n");
printf("Validating the words in the block.\n");
if (checkblock(x, size, 0, 1)) {
printf("FAILED: data corrupt\n");
return;
}
printf("Passed part 2\n");
printf("Freeing the block\n");
free((void *)x);
printf("Passed part 3\n");
printf("Allocating another block\n");
printf("Freeing the block\n");
free((void *)x);
printf("Passed part 3\n");
printf("Allocating another block\n");
x = malloc(size);
if (x == NULL) {
printf("FAILED: free didn't return the memory?\n");
return;
}
free((void *)x);
x = malloc(size);
if (x==NULL) {
printf("FAILED: free didn't return the memory?\n");
return;
}
free((void *)x);
printf("Passed malloc test 2.\n");
printf("Passed malloc test 2.\n");
}
////////////////////////////////////////////////////////////
/*
@@ -291,92 +270,88 @@ test2(void)
*/
struct test3 {
struct test3 *next;
char junk[(SMALLSIZE - sizeof(struct test3 *))];
struct test3 *next;
char junk[(SMALLSIZE - sizeof(struct test3 *))];
};
static
void
test3(void)
{
struct test3 *list = NULL, *tmp;
size_t tot=0;
int ct=0, failed=0;
void *x;
static void test3(void) {
struct test3 *list = NULL, *tmp;
size_t tot = 0;
int ct = 0, failed = 0;
void *x;
printf("Entering malloc test 3.\n");
printf("Make sure you read and understand the comment in malloctest.c "
"that\nexplains the conditions this test assumes.\n\n");
printf("Entering malloc test 3.\n");
printf("Make sure you read and understand the comment in malloctest.c "
"that\nexplains the conditions this test assumes.\n\n");
printf("Testing how much memory we can allocate:\n");
printf("Testing how much memory we can allocate:\n");
while ((tmp = malloc(sizeof(struct test3))) != NULL) {
while ((tmp = malloc(sizeof(struct test3))) != NULL) {
assert(tmp != list);
tmp->next = list;
list = tmp;
assert(tmp != list);
tmp->next = list;
list = tmp;
tot += sizeof(struct test3);
tot += sizeof(struct test3);
markblock(list->junk, sizeof(list->junk), (uintptr_t)list, 0);
markblock(list->junk, sizeof(list->junk), (uintptr_t)list, 0);
ct++;
if (ct%128==0) {
printf(".");
}
}
ct++;
if (ct % 128 == 0) {
printf(".");
}
}
printf("Allocated %lu bytes\n", (unsigned long) tot);
printf("Allocated %lu bytes\n", (unsigned long)tot);
printf("Trying some more allocations which I expect to fail...\n");
printf("Trying some more allocations which I expect to fail...\n");
x = malloc(SMALLSIZE);
if (x != NULL) {
printf("FAILED: malloc(%u) succeeded\n", SMALLSIZE);
return;
}
x = malloc(SMALLSIZE);
if (x != NULL) {
printf("FAILED: malloc(%u) succeeded\n", SMALLSIZE);
return;
}
x = malloc(MEDIUMSIZE);
if (x != NULL) {
printf("FAILED: malloc(%u) succeeded\n", MEDIUMSIZE);
return;
}
x = malloc(MEDIUMSIZE);
if (x != NULL) {
printf("FAILED: malloc(%u) succeeded\n", MEDIUMSIZE);
return;
}
x = malloc(BIGSIZE);
if (x != NULL) {
printf("FAILED: malloc(%u) succeeded\n", BIGSIZE);
return;
}
x = malloc(BIGSIZE);
if (x != NULL) {
printf("FAILED: malloc(%u) succeeded\n", BIGSIZE);
return;
}
printf("Ok, now I'm going to free everything...\n");
printf("Ok, now I'm going to free everything...\n");
while (list != NULL) {
tmp = list->next;
while (list != NULL) {
tmp = list->next;
if (checkblock(list->junk, sizeof(list->junk),
(uintptr_t)list, 0)) {
failed = 1;
}
if (checkblock(list->junk, sizeof(list->junk), (uintptr_t)list, 0)) {
failed = 1;
}
free(list);
list = tmp;
}
free(list);
list = tmp;
}
if (failed) {
printf("FAILED: data corruption\n");
return;
}
if (failed) {
printf("FAILED: data corruption\n");
return;
}
printf("Let me see if I can allocate some more now...\n");
printf("Let me see if I can allocate some more now...\n");
x = malloc(MEDIUMSIZE);
if (x == NULL) {
printf("FAIL: Nope, I couldn't.\n");
return;
}
free(x);
x = malloc(MEDIUMSIZE);
if (x == NULL) {
printf("FAIL: Nope, I couldn't.\n");
return;
}
free(x);
printf("Passed malloc test 3\n");
printf("Passed malloc test 3\n");
}
////////////////////////////////////////////////////////////
@@ -390,121 +365,117 @@ test3(void)
* next-fit/best-fit algorithm is used.
*/
static
void
test4(void)
{
void *x, *y, *z;
unsigned long lx, ly, lz, overhead, zsize;
static void test4(void) {
void *x, *y, *z;
unsigned long lx, ly, lz, overhead, zsize;
printf("Entering malloc test 4.\n");
printf("This test is intended for first/best-fit based mallocs.\n");
printf("This test may not work correctly if run after other tests.\n");
printf("Entering malloc test 4.\n");
printf("This test is intended for first/best-fit based mallocs.\n");
printf("This test may not work correctly if run after other tests.\n");
printf("Testing free list coalescing:\n");
printf("Testing free list coalescing:\n");
x = malloc(SMALLSIZE);
if (x==NULL) {
printf("FAILED: malloc(%u) failed\n", SMALLSIZE);
return;
}
x = malloc(SMALLSIZE);
if (x == NULL) {
printf("FAILED: malloc(%u) failed\n", SMALLSIZE);
return;
}
y = malloc(MEDIUMSIZE);
if (y==NULL) {
printf("FAILED: malloc(%u) failed\n", MEDIUMSIZE);
return;
}
y = malloc(MEDIUMSIZE);
if (y == NULL) {
printf("FAILED: malloc(%u) failed\n", MEDIUMSIZE);
return;
}
if (sizeof(unsigned long) < sizeof(void *)) {
printf("Buh? I can't fit a void * in an unsigned long\n");
printf("ENVIRONMENT FAILED...\n");
return;
}
if (sizeof(unsigned long) < sizeof(void *)) {
printf("Buh? I can't fit a void * in an unsigned long\n");
printf("ENVIRONMENT FAILED...\n");
return;
}
lx = (unsigned long)x;
ly = (unsigned long)y;
lx = (unsigned long)x;
ly = (unsigned long)y;
printf("x is 0x%lx; y is 0x%lx\n", lx, ly);
printf("x is 0x%lx; y is 0x%lx\n", lx, ly);
/*
* The memory should look something like this:
*
* OXXXOYYYYYYYYYYY
*
* where O are optional overhead (indexing) blocks.
*/
/*
* The memory should look something like this:
*
* OXXXOYYYYYYYYYYY
*
* where O are optional overhead (indexing) blocks.
*/
/* This is obviously wrong. */
if (lx == ly) {
printf("FAIL: x == y\n");
return;
}
/* This is obviously wrong. */
if (lx == ly) {
printf("FAIL: x == y\n");
return;
}
/*
* Check for overlap. It is sufficient to check if the start
* of each block is within the other block. (If the end of a
* block is within the other block, either the start is too,
* or the other block's start is within the first block.)
*/
if (lx < ly && lx + SMALLSIZE > ly) {
printf("FAIL: y starts within x\n");
return;
}
if (ly < lx && ly + MEDIUMSIZE > lx) {
printf("FAIL: x starts within y\n");
return;
}
/*
* Check for overlap. It is sufficient to check if the start
* of each block is within the other block. (If the end of a
* block is within the other block, either the start is too,
* or the other block's start is within the first block.)
*/
if (lx < ly && lx + SMALLSIZE > ly) {
printf("FAIL: y starts within x\n");
return;
}
if (ly < lx && ly + MEDIUMSIZE > lx) {
printf("FAIL: x starts within y\n");
return;
}
/*
* If y is lower than x, some memory scheme we don't
* understand is in use, or else there's already stuff on the
* free list.
*/
if (ly < lx) {
printf("TEST UNSUITABLE: y is below x\n");
return;
}
/*
* If y is lower than x, some memory scheme we don't
* understand is in use, or else there's already stuff on the
* free list.
*/
if (ly < lx) {
printf("TEST UNSUITABLE: y is below x\n");
return;
}
/*
* Compute the space used by index structures.
*/
overhead = ly - (lx + SMALLSIZE);
printf("Apparent block overhead: %lu\n", overhead);
/*
* Compute the space used by index structures.
*/
overhead = ly - (lx + SMALLSIZE);
printf("Apparent block overhead: %lu\n", overhead);
if (overhead > ABSURD_OVERHEAD) {
printf("TEST UNSUITABLE: block overhead absurdly large.\n");
return;
}
if (overhead > OVERHEAD) {
printf("FAIL: block overhead is too large.\n");
return;
}
if (overhead > ABSURD_OVERHEAD) {
printf("TEST UNSUITABLE: block overhead absurdly large.\n");
return;
}
if (overhead > OVERHEAD) {
printf("FAIL: block overhead is too large.\n");
return;
}
printf("Freeing blocks...\n");
free(x);
free(y);
printf("Freeing blocks...\n");
free(x);
free(y);
zsize = SMALLSIZE + MEDIUMSIZE + overhead;
zsize = SMALLSIZE + MEDIUMSIZE + overhead;
printf("Now allocating %lu bytes... should reuse the space.\n", zsize);
z = malloc(zsize);
if (z == NULL) {
printf("FAIL: Allocation failed...\n");
return;
}
printf("Now allocating %lu bytes... should reuse the space.\n", zsize);
z = malloc(zsize);
if (z == NULL) {
printf("FAIL: Allocation failed...\n");
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);
printf("z is 0x%lx (x was 0x%lx, y 0x%lx)\n", lz, lx, ly);
if (lz==lx) {
printf("Passed.\n");
}
else {
printf("Failed.\n");
}
if (lz == lx) {
printf("Passed.\n");
} else {
printf("Failed.\n");
}
free(z);
free(z);
}
////////////////////////////////////////////////////////////
@@ -519,176 +490,152 @@ test4(void)
* Test 7 asks for a seed.
*/
static
void
test567(int testno, unsigned long seed)
{
static const int sizes[8] = { 13, 17, 69, 176, 433, 871, 1150, 6060 };
static void test567(int testno, unsigned long seed) {
static const int sizes[8] = {13, 17, 69, 176, 433, 871, 1150, 6060};
void *ptrs[32];
int psizes[32];
int i, n, size, failed=0;
void *ptrs[32];
int psizes[32];
int i, n, size, failed = 0;
srandom(seed);
printf("Seeded random number generator with %lu.\n", seed);
srandom(seed);
printf("Seeded random number generator with %lu.\n", seed);
for (i=0; i<32; i++) {
ptrs[i] = NULL;
psizes[i] = 0;
}
for (i = 0; i < 32; i++) {
ptrs[i] = NULL;
psizes[i] = 0;
}
for (i=0; i<100000; i++) {
n = random()%32;
if (ptrs[n] == NULL) {
size = sizes[random()%8];
ptrs[n] = malloc(size);
psizes[n] = size;
if (ptrs[n] == NULL) {
printf("\nmalloc %u failed\n", size);
failed = 1;
break;
}
markblock(ptrs[n], size, n, 0);
}
else {
size = psizes[n];
if (checkblock(ptrs[n], size, n, 0)) {
failed = 1;
break;
}
free(ptrs[n]);
ptrs[n] = NULL;
psizes[n] = 0;
}
if (i%256==0) {
printf(".");
}
}
printf("\n");
for (i = 0; i < 100000; i++) {
n = random() % 32;
if (ptrs[n] == NULL) {
size = sizes[random() % 8];
ptrs[n] = malloc(size);
psizes[n] = size;
if (ptrs[n] == NULL) {
printf("\nmalloc %u failed\n", size);
failed = 1;
break;
}
markblock(ptrs[n], size, n, 0);
} else {
size = psizes[n];
if (checkblock(ptrs[n], size, n, 0)) {
failed = 1;
break;
}
free(ptrs[n]);
ptrs[n] = NULL;
psizes[n] = 0;
}
if (i % 256 == 0) {
printf(".");
}
}
printf("\n");
for (i=0; i<32; i++) {
if (ptrs[i] != NULL) {
free(ptrs[i]);
}
}
for (i = 0; i < 32; i++) {
if (ptrs[i] != NULL) {
free(ptrs[i]);
}
}
if (failed) {
printf("FAILED malloc test %d\n", testno);
}
else {
printf("Passed malloc test %d\n", testno);
}
if (failed) {
printf("FAILED malloc test %d\n", testno);
} else {
printf("Passed malloc test %d\n", testno);
}
}
static
void
test5(void)
{
printf("Beginning malloc test 5\n");
test567(5, 0);
static void test5(void) {
printf("Beginning malloc test 5\n");
test567(5, 0);
}
static
void
test6(void)
{
int fd, len;
unsigned long seed;
static void test6(void) {
int fd, len;
unsigned long seed;
printf("Beginning malloc test 6\n");
printf("Beginning malloc test 6\n");
fd = open(_PATH_RANDOM, O_RDONLY);
if (fd < 0) {
err(1, "%s", _PATH_RANDOM);
}
len = read(fd, &seed, sizeof(seed));
if (len < 0) {
err(1, "%s", _PATH_RANDOM);
}
else if (len < (int)sizeof(seed)) {
errx(1, "%s: Short read", _PATH_RANDOM);
}
close(fd);
fd = open(_PATH_RANDOM, O_RDONLY);
if (fd < 0) {
err(1, "%s", _PATH_RANDOM);
}
len = read(fd, &seed, sizeof(seed));
if (len < 0) {
err(1, "%s", _PATH_RANDOM);
} else if (len < (int)sizeof(seed)) {
errx(1, "%s: Short read", _PATH_RANDOM);
}
close(fd);
test567(6, seed);
test567(6, seed);
}
static
void
test7(void)
{
unsigned long seed;
static void test7(void) {
unsigned long seed;
printf("Beginning malloc test 7\n");
printf("Beginning malloc test 7\n");
printf("Enter random seed: ");
seed = geti();
printf("Enter random seed: ");
seed = geti();
test567(7, seed);
test567(7, seed);
}
////////////////////////////////////////////////////////////
static struct {
int num;
const char *desc;
void (*func)(void);
} tests[] = {
{ 1, "Simple allocation test", test1 },
{ 2, "Allocate all memory in a big chunk", test2 },
{ 3, "Allocate all memory in small chunks", test3 },
{ 4, "Free list coalescing test (first/next/best-fit only)", test4 },
{ 5, "Stress test", test5 },
{ 6, "Randomized stress test", test6 },
{ 7, "Stress test with particular seed", test7 },
{ -1, NULL, NULL }
};
int num;
const char *desc;
void (*func)(void);
} tests[] = {{1, "Simple allocation test", test1},
{2, "Allocate all memory in a big chunk", test2},
{3, "Allocate all memory in small chunks", test3},
{4, "Free list coalescing test (first/next/best-fit only)", test4},
{5, "Stress test", test5},
{6, "Randomized stress test", test6},
{7, "Stress test with particular seed", test7},
{-1, NULL, NULL}};
static
int
dotest(int tn)
{
int i;
for (i=0; tests[i].num>=0; i++) {
if (tests[i].num == tn) {
tests[i].func();
return 0;
}
}
return -1;
static int dotest(int tn) {
int i;
for (i = 0; tests[i].num >= 0; i++) {
if (tests[i].num == tn) {
tests[i].func();
return 0;
}
}
return -1;
}
int
main(int argc, char *argv[])
{
int i, tn, menu=1;
int main(int argc, char *argv[]) {
int i, tn, menu = 1;
if (argc > 1) {
for (i=1; i<argc; i++) {
dotest(atoi(argv[i]));
}
return 0;
}
if (argc > 1) {
for (i = 1; i < argc; i++) {
dotest(atoi(argv[i]));
}
return 0;
}
while (1) {
if (menu) {
for (i=0; tests[i].num>=0; i++) {
printf(" %2d %s\n", tests[i].num,
tests[i].desc);
}
menu = 0;
}
printf("malloctest: ");
tn = geti();
if (tn < 0) {
break;
}
while (1) {
if (menu) {
for (i = 0; tests[i].num >= 0; i++) {
printf(" %2d %s\n", tests[i].num, tests[i].desc);
}
menu = 0;
}
printf("malloctest: ");
tn = geti();
if (tn < 0) {
break;
}
if (dotest(tn)) {
menu = 1;
}
}
if (dotest(tn)) {
menu = 1;
}
}
return 0;
return 0;
}

View File

@@ -48,41 +48,39 @@
#include <unistd.h>
#include <stdio.h>
#define Dim 360 /* sum total of the arrays doesn't fit in
* physical memory
*/
#define Dim \
360 /* sum total of the arrays doesn't fit in \
* physical memory \
*/
#define RIGHT 46397160 /* correct answer */
#define RIGHT 46397160 /* correct answer */
int A[Dim][Dim];
int B[Dim][Dim];
int C[Dim][Dim];
int
main(void)
{
int i, j, k, r;
int main(void) {
int i, j, k, r;
for (i = 0; i < Dim; i++) /* first initialize the matrices */
for (j = 0; j < Dim; j++) {
A[i][j] = i;
B[i][j] = j;
C[i][j] = 0;
}
for (i = 0; i < Dim; i++) /* then multiply them together */
for (j = 0; j < Dim; j++)
for (k = 0; k < Dim; k++)
C[i][j] += A[i][k] * B[k][j];
printf("matmult-orig finished.\n");
r = C[Dim-1][Dim-1];
printf("answer is: %d (should be %d)\n", r, RIGHT);
if (r != RIGHT) {
printf("FAILED\n");
for (i = 0; i < Dim; i++) /* first initialize the matrices */
for (j = 0; j < Dim; j++) {
A[i][j] = i;
B[i][j] = j;
C[i][j] = 0;
}
else {
printf("Passed.\n");
}
return 0;
for (i = 0; i < Dim; i++) /* then multiply them together */
for (j = 0; j < Dim; j++)
for (k = 0; k < Dim; k++)
C[i][j] += A[i][k] * B[k][j];
printf("matmult-orig finished.\n");
r = C[Dim - 1][Dim - 1];
printf("answer is: %d (should be %d)\n", r, RIGHT);
if (r != RIGHT) {
printf("FAILED\n");
} else {
printf("Passed.\n");
}
return 0;
}

View File

@@ -42,49 +42,48 @@
#include <unistd.h>
#include <stdio.h>
#define Dim 72 /* sum total of the arrays doesn't fit in
* physical memory
*/
#define Dim \
72 /* sum total of the arrays doesn't fit in \
* physical memory \
*/
#define RIGHT 8772192 /* correct answer */
#define RIGHT 8772192 /* correct answer */
int A[Dim][Dim];
int B[Dim][Dim];
int C[Dim][Dim];
int T[Dim][Dim][Dim];
int
main(void)
{
int i, j, k, r;
int main(void) {
int i, j, k, r;
for (i = 0; i < Dim; i++) /* first initialize the matrices */
for (j = 0; j < Dim; j++) {
A[i][j] = i;
B[i][j] = j;
C[i][j] = 0;
}
for (i = 0; i < Dim; i++) /* then multiply them together */
for (j = 0; j < Dim; j++)
for (k = 0; k < Dim; k++)
T[i][j][k] = A[i][k] * B[k][j];
for (i = 0; i < Dim; i++)
for (j = 0; j < Dim; j++)
for (k = 0; k < Dim; k++)
C[i][j] += T[i][j][k];
r = 0;
for (i = 0; i < Dim; i++)
r += C[i][i];
printf("matmult finished.\n");
printf("answer is: %d (should be %d)\n", r, RIGHT);
if (r != RIGHT) {
printf("FAILED\n");
return 1;
for (i = 0; i < Dim; i++) /* first initialize the matrices */
for (j = 0; j < Dim; j++) {
A[i][j] = i;
B[i][j] = j;
C[i][j] = 0;
}
printf("Passed.\n");
return 0;
for (i = 0; i < Dim; i++) /* then multiply them together */
for (j = 0; j < Dim; j++)
for (k = 0; k < Dim; k++)
T[i][j][k] = A[i][k] * B[k][j];
for (i = 0; i < Dim; i++)
for (j = 0; j < Dim; j++)
for (k = 0; k < Dim; k++)
C[i][j] += T[i][j][k];
r = 0;
for (i = 0; i < Dim; i++)
r += C[i][i];
printf("matmult finished.\n");
printf("answer is: %d (should be %d)\n", r, RIGHT);
if (r != RIGHT) {
printf("FAILED\n");
return 1;
}
printf("Passed.\n");
return 0;
}

View File

@@ -81,74 +81,52 @@
*/
struct usem {
char name[32];
int fd;
char name[32];
int fd;
};
static
void
semcreate(const char *tag, struct usem *sem)
{
int fd;
static void semcreate(const char *tag, struct usem *sem) {
int fd;
snprintf(sem->name, sizeof(sem->name), "sem:multiexec.%s.%d",
tag, (int)getpid());
snprintf(sem->name, sizeof(sem->name), "sem:multiexec.%s.%d", tag,
(int)getpid());
fd = open(sem->name, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s: create", sem->name);
}
close(fd);
fd = open(sem->name, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s: create", sem->name);
}
close(fd);
}
static
void
semopen(struct usem *sem)
{
sem->fd = open(sem->name, O_RDWR, 0664);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
static void semopen(struct usem *sem) {
sem->fd = open(sem->name, O_RDWR, 0664);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
}
static
void
semclose(struct usem *sem)
{
close(sem->fd);
static void semclose(struct usem *sem) { close(sem->fd); }
static void semdestroy(struct usem *sem) { remove(sem->name); }
static void semP(struct usem *sem, size_t num) {
char c[num];
if (read(sem->fd, c, num) < 0) {
err(1, "%s: read", sem->name);
}
(void)c;
}
static
void
semdestroy(struct usem *sem)
{
remove(sem->name);
}
static void semV(struct usem *sem, size_t num) {
char c[num];
static
void
semP(struct usem *sem, size_t num)
{
char c[num];
/* semfs does not use these values, but be conservative */
memset(c, 0, num);
if (read(sem->fd, c, num) < 0) {
err(1, "%s: read", sem->name);
}
(void)c;
}
static
void
semV(struct usem *sem, size_t num)
{
char c[num];
/* semfs does not use these values, but be conservative */
memset(c, 0, num);
if (write(sem->fd, c, num) < 0) {
err(1, "%s: write", sem->name);
}
if (write(sem->fd, c, num) < 0) {
err(1, "%s: write", sem->name);
}
}
////////////////////////////////////////////////////////////
@@ -158,115 +136,105 @@ semV(struct usem *sem, size_t num)
static char *subargv[SUBARGC_MAX];
static int subargc = 0;
static
void
spawn(int njobs)
{
struct usem s1, s2;
pid_t pids[njobs];
int failed, status;
int i;
static void spawn(int njobs) {
struct usem s1, s2;
pid_t pids[njobs];
int failed, status;
int i;
semcreate("1", &s1);
semcreate("2", &s2);
semcreate("1", &s1);
semcreate("2", &s2);
printf("Forking %d child processes...\n", njobs);
printf("Forking %d child processes...\n", njobs);
for (i=0; i<njobs; i++) {
pids[i] = fork();
if (pids[i] == -1) {
/* continue with the procs we have; cannot kill them */
warn("fork");
warnx("*** Only started %u processes ***", i);
njobs = i;
break;
}
if (pids[i] == 0) {
/* child */
semopen(&s1);
semopen(&s2);
semV(&s1, 1);
semP(&s2, 1);
semclose(&s1);
semclose(&s2);
execv(subargv[0], subargv);
warn("execv: %s", subargv[0]);
_exit(1);
}
}
for (i = 0; i < njobs; i++) {
pids[i] = fork();
if (pids[i] == -1) {
/* continue with the procs we have; cannot kill them */
warn("fork");
warnx("*** Only started %u processes ***", i);
njobs = i;
break;
}
if (pids[i] == 0) {
/* child */
semopen(&s1);
semopen(&s2);
semV(&s1, 1);
semP(&s2, 1);
semclose(&s1);
semclose(&s2);
execv(subargv[0], subargv);
warn("execv: %s", subargv[0]);
_exit(1);
}
}
semopen(&s1);
semopen(&s2);
printf("Waiting for fork...\n");
semP(&s1, njobs);
printf("Starting the execs...\n");
semV(&s2, njobs);
semopen(&s1);
semopen(&s2);
printf("Waiting for fork...\n");
semP(&s1, njobs);
printf("Starting the execs...\n");
semV(&s2, njobs);
failed = 0;
for (i=0; i<njobs; i++) {
if (waitpid(pids[i], &status, 0) < 0) {
warn("waitpid");
failed++;
}
else if (WIFSIGNALED(status)) {
warnx("pid %d (child %d): Signal %d",
(int)pids[i], i, WTERMSIG(status));
failed++;
}
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
warnx("pid %d (child %d): Exit %d",
(int)pids[i], i, WEXITSTATUS(status));
failed++;
}
}
if (failed > 0) {
warnx("%d children failed", failed);
}
else {
printf("Succeeded\n");
}
failed = 0;
for (i = 0; i < njobs; i++) {
if (waitpid(pids[i], &status, 0) < 0) {
warn("waitpid");
failed++;
} else if (WIFSIGNALED(status)) {
warnx("pid %d (child %d): Signal %d", (int)pids[i], i, WTERMSIG(status));
failed++;
} else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
warnx("pid %d (child %d): Exit %d", (int)pids[i], i, WEXITSTATUS(status));
failed++;
}
}
if (failed > 0) {
warnx("%d children failed", failed);
} else {
printf("Succeeded\n");
}
semclose(&s1);
semclose(&s2);
semdestroy(&s1);
semdestroy(&s2);
semclose(&s1);
semclose(&s2);
semdestroy(&s1);
semdestroy(&s2);
}
int
main(int argc, char *argv[])
{
static char default_prog[] = "/bin/pwd";
int main(int argc, char *argv[]) {
static char default_prog[] = "/bin/pwd";
int njobs = 12;
int i;
int njobs = 12;
int i;
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-j")) {
i++;
if (argv[i] == NULL) {
errx(1, "Option -j requires an argument");
}
njobs = atoi(argv[i]);
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-j")) {
i++;
if (argv[i] == NULL) {
errx(1, "Option -j requires an argument");
}
njobs = atoi(argv[i]);
}
#if 0 /* XXX we apparently don't have strncmp? */
else if (!strncmp(argv[i], "-j", 2)) {
njobs = atoi(argv[i] + 2);
}
#endif
else {
subargv[subargc++] = argv[i];
if (subargc >= SUBARGC_MAX) {
errx(1, "Too many arguments");
}
}
}
else {
subargv[subargc++] = argv[i];
if (subargc >= SUBARGC_MAX) {
errx(1, "Too many arguments");
}
}
}
if (subargc == 0) {
subargv[subargc++] = default_prog;
}
subargv[subargc] = NULL;
if (subargc == 0) {
subargv[subargc++] = default_prog;
}
subargv[subargc] = NULL;
spawn(njobs);
spawn(njobs);
return 0;
return 0;
}

View File

@@ -29,19 +29,19 @@
/*
Test suite.
Test suite.
This program takes the palindrome below and checks if it's
a palindrome or not. It will hopefully exhibit an interesting
page fault pattern.
This program takes the palindrome below and checks if it's
a palindrome or not. It will hopefully exhibit an interesting
page fault pattern.
The palindrome was taken from
The palindrome was taken from
http://www.cs.brown.edu/people/nfp/palindrome.html
http://www.cs.brown.edu/people/nfp/palindrome.html
This is not large enough to really stress the VM system, but
might be useful for testing in the early stages of the VM
assignment.
This is not large enough to really stress the VM system, but
might be useful for testing in the early stages of the VM
assignment.
*/
/*
@@ -85,114 +85,112 @@ a canal - Panama!
#include <string.h>
char palindrome[8000] =
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama"
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama"
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama"
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama";
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama"
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama"
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama"
"amanaplanacaretabanamyriadasumalacaliarahoopapintacatalpaagasanoil"
"abirdayellavatacawapaxawagataxanayaramacapayamagayatsarawalla"
"caralugerawardabinawomanavassalawolfatunaanitapallafretawattabaya"
"daubatanacabadatumagallahatafagazapasayajawalayawetagallopatuga"
"trotatrapatramatorracaperatopatonkatollaballafairasaxaminimatenora"
"bassapasseracapitalarutanamenatedacabalatangasunanassamawasaga"
"jamadamasubasaltanaxonasailanadawadiaradianaroomaroodaripatada"
"pariaharevelareelareedapoolaplugapinapeekaparabolaadogapatacudanua"
"fanapalarumanodanetaalaganeelabatikamugamotanapamaximamooda"
"leekagrubagobageladrabacitadelatotalacedaratapagagaratamanorabara"
"galacolaapapayawatabarajagabanagapaganabagajarabatawayapapaa"
"localagarabaronamataragagapataradecalatotaledaticabardalegaboga"
"burgakeeladoomamixamapanatomagumakitabaleenagalaatenadonamurala"
"panafaunaducatapagodaalobarapakeepanipagulpaloopadeeraleeralevera"
"hairapadatapiradooramooranaidaraidawadanaliasanoxanatlasabusamadam"
"ajagasawamassananusagnatalabacadetanemanaturalatipacaressapassa"
"baronetaminimaxasariafallaballotaknotapotarepacarrotamartapartatorta"
"gutapollagatewayalawajayasapazagafatahallagamutadabacanatabuaday"
"abattawaterfallapatinaanutaflowalassavanamowanibadrawaregularacalla"
"warastayagamayapacamarayanaxatagawaxapawacatavalleyadribaliona"
"sagaaplatacatnipapooharailacalamusadairymanabateracanalpanama";
int
main(void)
{
char *start, *end;
int main(void) {
char *start, *end;
printf("Welcome to the palindrome tester!\n");
printf("I will take a large palindrome and test it.\n");
printf("Here it is:\n");
printf("%s\n", palindrome);
printf("Welcome to the palindrome tester!\n");
printf("I will take a large palindrome and test it.\n");
printf("Here it is:\n");
printf("%s\n", palindrome);
printf("Testing...");
/* skip to end */
end = palindrome+strlen(palindrome);
end--;
printf("Testing...");
/* skip to end */
end = palindrome + strlen(palindrome);
end--;
for (start = palindrome; start <= end; start++, end--) {
putchar('.');
if (*start != *end) {
printf("NOT a palindrome\n");
return 0;
}
}
for (start = palindrome; start <= end; start++, end--) {
putchar('.');
if (*start != *end) {
printf("NOT a palindrome\n");
return 0;
}
}
printf("IS a palindrome\n");
return 0;
printf("IS a palindrome\n");
return 0;
}

View File

@@ -46,43 +46,23 @@
#include <unistd.h>
#include <err.h>
#define NJOBS 24
#define NJOBS 24
#define DIM 35
#define NMATS 11
#define JOBSIZE ((NMATS+1)*DIM*DIM*sizeof(int))
#define DIM 35
#define NMATS 11
#define JOBSIZE ((NMATS + 1) * DIM * DIM * sizeof(int))
static const int right_answers[NJOBS] = {
-1337312809,
356204544,
-537881911,
-65406976,
1952063315,
-843894784,
1597000869,
-993925120,
838840559,
-1616928768,
-182386335,
-364554240,
251084843,
-61403136,
295326333,
1488013312,
1901440647,
0,
-1901440647,
-1488013312,
-295326333,
61403136,
-251084843,
364554240,
-1337312809, 356204544, -537881911, -65406976, 1952063315, -843894784,
1597000869, -993925120, 838840559, -1616928768, -182386335, -364554240,
251084843, -61403136, 295326333, 1488013312, 1901440647, 0,
-1901440647, -1488013312, -295326333, 61403136, -251084843, 364554240,
};
////////////////////////////////////////////////////////////
struct matrix {
int m_data[DIM][DIM];
int m_data[DIM][DIM];
};
////////////////////////////////////////////////////////////
@@ -91,129 +71,100 @@ struct matrix {
* Use this instead of just calling printf so we know each printout
* is atomic; this prevents the lines from getting intermingled.
*/
static
void
say(const char *fmt, ...)
{
char buf[256];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
write(STDOUT_FILENO, buf, strlen(buf));
static void say(const char *fmt, ...) {
char buf[256];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
write(STDOUT_FILENO, buf, strlen(buf));
}
////////////////////////////////////////////////////////////
static
void
multiply(struct matrix *res, const struct matrix *m1, const struct matrix *m2)
{
int i, j, k;
static void multiply(struct matrix *res, const struct matrix *m1,
const struct matrix *m2) {
int i, j, k;
for (i=0; i<DIM; i++) {
for (j=0; j<DIM; j++) {
int val=0;
for (k=0; k<DIM; k++) {
val += m1->m_data[i][k]*m2->m_data[k][j];
}
res->m_data[i][j] = val;
}
}
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
int val = 0;
for (k = 0; k < DIM; k++) {
val += m1->m_data[i][k] * m2->m_data[k][j];
}
res->m_data[i][j] = val;
}
}
}
static
void
addeq(struct matrix *m1, const struct matrix *m2)
{
int i, j;
for (i=0; i<DIM; i++) {
for (j=0; j<DIM; j++) {
m1->m_data[i][j] += m2->m_data[i][j];
}
}
static void addeq(struct matrix *m1, const struct matrix *m2) {
int i, j;
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
m1->m_data[i][j] += m2->m_data[i][j];
}
}
}
static
int
trace(const struct matrix *m1)
{
int i, t=0;
for (i=0; i<DIM; i++) {
t += m1->m_data[i][i];
}
return t;
static int trace(const struct matrix *m1) {
int i, t = 0;
for (i = 0; i < DIM; i++) {
t += m1->m_data[i][i];
}
return t;
}
////////////////////////////////////////////////////////////
static struct matrix mats[NMATS];
static
void
populate_initial_matrixes(int mynum)
{
int i,j;
struct matrix *m = &mats[0];
for (i=0; i<DIM; i++) {
for (j=0; j<DIM; j++) {
m->m_data[i][j] = mynum+i-2*j;
}
}
static void populate_initial_matrixes(int mynum) {
int i, j;
struct matrix *m = &mats[0];
for (i = 0; i < DIM; i++) {
for (j = 0; j < DIM; j++) {
m->m_data[i][j] = mynum + i - 2 * j;
}
}
multiply(&mats[1], &mats[0], &mats[0]);
multiply(&mats[1], &mats[0], &mats[0]);
}
static
void
compute(int n)
{
struct matrix tmp;
int i, j;
static void compute(int n) {
struct matrix tmp;
int i, j;
for (i=0,j=n-1; i<j; i++,j--) {
multiply(&tmp, &mats[i], &mats[j]);
addeq(&mats[n], &tmp);
}
for (i = 0, j = n - 1; i < j; i++, j--) {
multiply(&tmp, &mats[i], &mats[j]);
addeq(&mats[n], &tmp);
}
}
static
void
computeall(int mynum)
{
int i;
populate_initial_matrixes(mynum);
for (i=2; i<NMATS; i++) {
compute(i);
}
static void computeall(int mynum) {
int i;
populate_initial_matrixes(mynum);
for (i = 2; i < NMATS; i++) {
compute(i);
}
}
static
int
answer(void)
{
return trace(&mats[NMATS-1]);
}
static int answer(void) { return trace(&mats[NMATS - 1]); }
static
void
go(int mynum)
{
int r;
static void go(int mynum) {
int r;
say("Process %d (pid %d) starting computation...\n", mynum,
(int) getpid());
say("Process %d (pid %d) starting computation...\n", mynum, (int)getpid());
computeall(mynum);
r = answer();
computeall(mynum);
r = answer();
if (r != right_answers[mynum]) {
say("Process %d answer %d: FAILED, should be %d\n",
mynum, r, right_answers[mynum]);
exit(1);
}
say("Process %d answer %d: passed\n", mynum, r);
exit(0);
if (r != right_answers[mynum]) {
say("Process %d answer %d: FAILED, should be %d\n", mynum, r,
right_answers[mynum]);
exit(1);
}
say("Process %d answer %d: passed\n", mynum, r);
exit(0);
}
////////////////////////////////////////////////////////////
@@ -235,191 +186,157 @@ go(int mynum)
*/
struct usem {
char name[32];
int fd;
char name[32];
int fd;
};
static
void
semcreate(const char *tag, struct usem *sem)
{
int fd;
static void semcreate(const char *tag, struct usem *sem) {
int fd;
snprintf(sem->name, sizeof(sem->name), "sem:parallelvm.%s.%d",
tag, (int)getpid());
snprintf(sem->name, sizeof(sem->name), "sem:parallelvm.%s.%d", tag,
(int)getpid());
fd = open(sem->name, O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s: create", sem->name);
}
close(fd);
fd = open(sem->name, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s: create", sem->name);
}
close(fd);
}
static
void
semopen(struct usem *sem)
{
sem->fd = open(sem->name, O_RDWR, 0664);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
static void semopen(struct usem *sem) {
sem->fd = open(sem->name, O_RDWR, 0664);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
}
static
void
semclose(struct usem *sem)
{
close(sem->fd);
static void semclose(struct usem *sem) { close(sem->fd); }
static void semdestroy(struct usem *sem) { remove(sem->name); }
static void semP(struct usem *sem, size_t num) {
char c[num];
if (read(sem->fd, c, num) < 0) {
err(1, "%s: read", sem->name);
}
(void)c;
}
static
void
semdestroy(struct usem *sem)
{
remove(sem->name);
}
static void semV(struct usem *sem, size_t num) {
char c[num];
static
void
semP(struct usem *sem, size_t num)
{
char c[num];
/* semfs does not use these values, but be conservative */
memset(c, 0, num);
if (read(sem->fd, c, num) < 0) {
err(1, "%s: read", sem->name);
}
(void)c;
}
static
void
semV(struct usem *sem, size_t num)
{
char c[num];
/* semfs does not use these values, but be conservative */
memset(c, 0, num);
if (write(sem->fd, c, num) < 0) {
err(1, "%s: write", sem->name);
}
if (write(sem->fd, c, num) < 0) {
err(1, "%s: write", sem->name);
}
}
////////////////////////////////////////////////////////////
// driver
static
int
status_is_failure(int status)
{
/* Proper interpretation of Unix exit status */
if (WIFSIGNALED(status)) {
return 1;
}
if (!WIFEXITED(status)) {
/* ? */
return 1;
}
status = WEXITSTATUS(status);
return status != 0;
static int status_is_failure(int status) {
/* Proper interpretation of Unix exit status */
if (WIFSIGNALED(status)) {
return 1;
}
if (!WIFEXITED(status)) {
/* ? */
return 1;
}
status = WEXITSTATUS(status);
return status != 0;
}
static
void
makeprocs(bool dowait)
{
int i, status, failcount;
struct usem s1, s2;
pid_t pids[NJOBS];
static void makeprocs(bool dowait) {
int i, status, failcount;
struct usem s1, s2;
pid_t pids[NJOBS];
if (dowait) {
semcreate("1", &s1);
semcreate("2", &s2);
}
if (dowait) {
semcreate("1", &s1);
semcreate("2", &s2);
}
printf("Job size approximately %lu bytes\n", (unsigned long) JOBSIZE);
printf("Forking %d jobs; total load %luk\n", NJOBS,
(unsigned long) (NJOBS * JOBSIZE)/1024);
printf("Job size approximately %lu bytes\n", (unsigned long)JOBSIZE);
printf("Forking %d jobs; total load %luk\n", NJOBS,
(unsigned long)(NJOBS * JOBSIZE) / 1024);
for (i=0; i<NJOBS; i++) {
pids[i] = fork();
if (pids[i]<0) {
warn("fork (process %d)", i);
if (dowait) {
semopen(&s1);
semV(&s1, 1);
semclose(&s1);
}
}
if (pids[i]==0) {
/* child */
if (dowait) {
say("Process %d forked\n", i);
semopen(&s1);
semopen(&s2);
semV(&s1, 1);
semP(&s2, 1);
semclose(&s1);
semclose(&s2);
}
go(i);
}
}
for (i = 0; i < NJOBS; i++) {
pids[i] = fork();
if (pids[i] < 0) {
warn("fork (process %d)", i);
if (dowait) {
semopen(&s1);
semV(&s1, 1);
semclose(&s1);
}
}
if (pids[i] == 0) {
/* child */
if (dowait) {
say("Process %d forked\n", i);
semopen(&s1);
semopen(&s2);
semV(&s1, 1);
semP(&s2, 1);
semclose(&s1);
semclose(&s2);
}
go(i);
}
}
if (dowait) {
semopen(&s1);
semopen(&s2);
say("Waiting for fork...\n");
semP(&s1, NJOBS);
say("Starting computation.\n");
semV(&s2, NJOBS);
}
if (dowait) {
semopen(&s1);
semopen(&s2);
say("Waiting for fork...\n");
semP(&s1, NJOBS);
say("Starting computation.\n");
semV(&s2, NJOBS);
}
failcount=0;
for (i=0; i<NJOBS; i++) {
if (pids[i]<0) {
failcount++;
}
else {
if (waitpid(pids[i], &status, 0)<0) {
err(1, "waitpid");
}
if (status_is_failure(status)) {
failcount++;
}
}
}
failcount = 0;
for (i = 0; i < NJOBS; i++) {
if (pids[i] < 0) {
failcount++;
} else {
if (waitpid(pids[i], &status, 0) < 0) {
err(1, "waitpid");
}
if (status_is_failure(status)) {
failcount++;
}
}
}
if (failcount>0) {
printf("%d subprocesses failed\n", failcount);
exit(1);
}
printf("Test complete\n");
if (failcount > 0) {
printf("%d subprocesses failed\n", failcount);
exit(1);
}
printf("Test complete\n");
semclose(&s1);
semclose(&s2);
semdestroy(&s1);
semdestroy(&s2);
semclose(&s1);
semclose(&s2);
semdestroy(&s1);
semdestroy(&s2);
}
int
main(int argc, char *argv[])
{
bool dowait = false;
int main(int argc, char *argv[]) {
bool dowait = false;
if (argc == 0) {
/* broken/unimplemented argv handling; do nothing */
}
else if (argc == 1) {
/* nothing */
}
else if (argc == 2 && !strcmp(argv[1], "-w")) {
dowait = true;
}
else {
printf("Usage: parallelvm [-w]\n");
return 1;
}
makeprocs(dowait);
return 0;
if (argc == 0) {
/* broken/unimplemented argv handling; do nothing */
} else if (argc == 1) {
/* nothing */
} else if (argc == 2 && !strcmp(argv[1], "-w")) {
dowait = true;
} else {
printf("Usage: parallelvm [-w]\n");
return 1;
}
makeprocs(dowait);
return 0;
}

View File

@@ -46,29 +46,24 @@
#define POISON_BYTE 0xa9
#define BLOCKSIZE 512
static
void
poison(void)
{
char buf[BLOCKSIZE];
off_t sectors, i;
static void poison(void) {
char buf[BLOCKSIZE];
off_t sectors, i;
memset(buf, POISON_BYTE, sizeof(buf));
memset(buf, POISON_BYTE, sizeof(buf));
sectors = diskblocks();
for (i=0; i<sectors; i++) {
diskwrite(buf, i);
}
sectors = diskblocks();
for (i = 0; i < sectors; i++) {
diskwrite(buf, i);
}
}
int
main(int argc, char *argv[])
{
if (argc != 2) {
errx(1, "Usage: %s disk-image", argv[0]);
}
opendisk(argv[1]);
poison();
closedisk();
return 0;
int main(int argc, char *argv[]) {
if (argc != 2) {
errx(1, "Usage: %s disk-image", argv[0]);
}
opendisk(argv[1]);
poison();
closedisk();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -33,134 +33,110 @@
#include "extern.h"
static
void
randchar(char *c)
{
static void randchar(char *c) {
#if RAND_MAX != 0x7fffffff
#error "This code assumes RAND_MAX is 0x7fffffff"
#endif
static long lbits = 0;
static long lnum = 0;
static long lbits = 0;
static long lnum = 0;
long bit;
int ct = 0;
long bit;
int ct = 0;
*c = 0;
*c = 0;
while (ct < CHAR_BIT) {
if (lnum==0) {
lbits = random();
lnum = 31;
}
while (ct < CHAR_BIT) {
if (lnum == 0) {
lbits = random();
lnum = 31;
}
bit = lbits & 1;
if (bit) {
(*c) |= 1;
}
(*c) <<= 1;
ct++;
lbits >>= 1;
lnum--;
}
bit = lbits & 1;
if (bit) {
(*c) |= 1;
}
(*c) <<= 1;
ct++;
lbits >>= 1;
lnum--;
}
}
static
void
fillrand(void *p, size_t len)
{
size_t i;
char *cp = p;
for (i=0; i<len; i++) {
randchar(&cp[i]);
}
static void fillrand(void *p, size_t len) {
size_t i;
char *cp = p;
for (i = 0; i < len; i++) {
randchar(&cp[i]);
}
}
void *
randptr(void)
{
void *x;
fillrand(&x, sizeof(x));
return x;
void *randptr(void) {
void *x;
fillrand(&x, sizeof(x));
return x;
}
int
randint(void)
{
int x;
fillrand(&x, sizeof(x));
return x;
int randint(void) {
int x;
fillrand(&x, sizeof(x));
return x;
}
off_t
randoff(void)
{
off_t x;
fillrand(&x, sizeof(x));
return x;
off_t randoff(void) {
off_t x;
fillrand(&x, sizeof(x));
return x;
}
size_t
randsize(void)
{
size_t x;
fillrand(&x, sizeof(x));
return x;
size_t randsize(void) {
size_t x;
fillrand(&x, sizeof(x));
return x;
}
static
void
usage(void)
{
printf("Usage: randcall [-f] [-c count] [-r seed] 2|3|4|all\n");
printf(" -f suppress forking\n");
printf(" -c set iteration count (default 100)\n");
printf(" -r set pseudorandom seed (default 0)\n");
exit(1);
static void usage(void) {
printf("Usage: randcall [-f] [-c count] [-r seed] 2|3|4|all\n");
printf(" -f suppress forking\n");
printf(" -c set iteration count (default 100)\n");
printf(" -r set pseudorandom seed (default 0)\n");
exit(1);
}
int
main(int argc, char *argv[])
{
int count=100, seed = 0, dofork = 1;
int an, i;
int main(int argc, char *argv[]) {
int count = 100, seed = 0, dofork = 1;
int an, i;
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-f")) {
dofork = 0;
}
else if (!strcmp(argv[i], "-c") && i<argc-1) {
count = atoi(argv[++i]);
}
else if (!strcmp(argv[i], "-r") && i<argc-1) {
seed = atoi(argv[++i]);
}
else if (argv[i][0] == '-') {
usage();
}
else {
break;
}
}
if (i != argc-1) {
usage();
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-f")) {
dofork = 0;
} else if (!strcmp(argv[i], "-c") && i < argc - 1) {
count = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-r") && i < argc - 1) {
seed = atoi(argv[++i]);
} else if (argv[i][0] == '-') {
usage();
} else {
break;
}
}
if (i != argc - 1) {
usage();
}
if (!strcmp(argv[i], "all")) {
an = 5;
}
else {
an = atoi(argv[i]);
if (an <2 || an > 4) {
usage();
}
}
if (!strcmp(argv[i], "all")) {
an = 5;
} else {
an = atoi(argv[i]);
if (an < 2 || an > 4) {
usage();
}
}
printf("Seed: %d Count: %d\n", seed, count);
printf("Seed: %d Count: %d\n", seed, count);
srandom(seed);
trycalls(an, dofork, count);
srandom(seed);
trycalls(an, dofork, count);
return 0;
return 0;
}

View File

@@ -50,148 +50,128 @@
static const char slogan[] = "CECIDI, ET NON SURGERE POSSUM!\n";
static
int
doopen(const char *path, int openflags)
{
int fd;
static int doopen(const char *path, int openflags) {
int fd;
fd = open(path, openflags, 0664);
if (fd < 0) {
err(1, "%s", path);
}
return fd;
fd = open(path, openflags, 0664);
if (fd < 0) {
err(1, "%s", path);
}
return fd;
}
static
void
dodup2(int ofd, int nfd, const char *file)
{
int r;
static void dodup2(int ofd, int nfd, const char *file) {
int r;
r = dup2(ofd, nfd);
if (r < 0) {
err(1, "%s: dup2", file);
}
if (r != nfd) {
errx(1, "%s: dup2: Expected %d, got %d", nfd, r);
}
r = dup2(ofd, nfd);
if (r < 0) {
err(1, "%s: dup2", file);
}
if (r != nfd) {
errx(1, "%s: dup2: Expected %d, got %d", nfd, r);
}
}
static
void
doclose(int fd, const char *file)
{
if (close(fd)) {
warnx("%s: close", file);
}
static void doclose(int fd, const char *file) {
if (close(fd)) {
warnx("%s: close", file);
}
}
static
void
mkfile(void)
{
int fd;
ssize_t r;
static void mkfile(void) {
int fd;
ssize_t r;
fd = doopen(INFILE, O_WRONLY|O_CREAT|O_TRUNC);
fd = doopen(INFILE, O_WRONLY | O_CREAT | O_TRUNC);
r = write(fd, slogan, strlen(slogan));
if (r < 0) {
err(1, "%s: write", INFILE);
}
if ((size_t)r != strlen(slogan)) {
errx(1, "%s: write: Short count (got %zd, expected %zu)",
INFILE, r, strlen(slogan));
}
r = write(fd, slogan, strlen(slogan));
if (r < 0) {
err(1, "%s: write", INFILE);
}
if ((size_t)r != strlen(slogan)) {
errx(1, "%s: write: Short count (got %zd, expected %zu)", INFILE, r,
strlen(slogan));
}
doclose(fd, INFILE);
doclose(fd, INFILE);
}
static
void
chkfile(void)
{
char buf[256];
ssize_t r;
int fd;
static void chkfile(void) {
char buf[256];
ssize_t r;
int fd;
fd = doopen(OUTFILE, O_RDONLY);
fd = doopen(OUTFILE, O_RDONLY);
r = read(fd, buf, sizeof(buf));
if (r < 0) {
err(1, "%s: read", OUTFILE);
}
if (r == 0) {
errx(1, "%s: read: Unexpected EOF", OUTFILE);
}
if ((size_t)r != strlen(slogan)) {
errx(1, "%s: read: Short count (got %zd, expected %zu)",
OUTFILE, r, strlen(slogan));
}
r = read(fd, buf, sizeof(buf));
if (r < 0) {
err(1, "%s: read", OUTFILE);
}
if (r == 0) {
errx(1, "%s: read: Unexpected EOF", OUTFILE);
}
if ((size_t)r != strlen(slogan)) {
errx(1, "%s: read: Short count (got %zd, expected %zu)", OUTFILE, r,
strlen(slogan));
}
doclose(fd, OUTFILE);
doclose(fd, OUTFILE);
}
static
void
cat(void)
{
pid_t pid;
int rfd, wfd, result, status;
const char *args[2];
static void cat(void) {
pid_t pid;
int rfd, wfd, result, status;
const char *args[2];
rfd = doopen(INFILE, O_RDONLY);
wfd = doopen(OUTFILE, O_WRONLY|O_CREAT|O_TRUNC);
rfd = doopen(INFILE, O_RDONLY);
wfd = doopen(OUTFILE, O_WRONLY | O_CREAT | O_TRUNC);
pid = fork();
if (pid < 0) {
err(1, "fork");
}
pid = fork();
if (pid < 0) {
err(1, "fork");
}
if (pid == 0) {
/* child */
dodup2(rfd, STDIN_FILENO, INFILE);
dodup2(wfd, STDOUT_FILENO, OUTFILE);
doclose(rfd, INFILE);
doclose(wfd, OUTFILE);
args[0] = "cat";
args[1] = NULL;
execv(PATH_CAT, (char **)args);
warn("%s: execv", PATH_CAT);
_exit(1);
}
if (pid == 0) {
/* child */
dodup2(rfd, STDIN_FILENO, INFILE);
dodup2(wfd, STDOUT_FILENO, OUTFILE);
doclose(rfd, INFILE);
doclose(wfd, OUTFILE);
args[0] = "cat";
args[1] = NULL;
execv(PATH_CAT, (char **)args);
warn("%s: execv", PATH_CAT);
_exit(1);
}
/* parent */
doclose(rfd, INFILE);
doclose(wfd, OUTFILE);
/* parent */
doclose(rfd, INFILE);
doclose(wfd, OUTFILE);
result = waitpid(pid, &status, 0);
if (result == -1) {
err(1, "waitpid");
}
if (WIFSIGNALED(status)) {
errx(1, "pid %d: Signal %d", (int)pid, WTERMSIG(status));
}
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
errx(1, "pid %d: Exit %d", (int)pid, WEXITSTATUS(status));
}
result = waitpid(pid, &status, 0);
if (result == -1) {
err(1, "waitpid");
}
if (WIFSIGNALED(status)) {
errx(1, "pid %d: Signal %d", (int)pid, WTERMSIG(status));
}
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
errx(1, "pid %d: Exit %d", (int)pid, WEXITSTATUS(status));
}
}
int
main(void)
{
printf("Creating %s...\n", INFILE);
mkfile();
int main(void) {
printf("Creating %s...\n", INFILE);
mkfile();
printf("Running cat < %s > %s\n", INFILE, OUTFILE);
cat();
printf("Running cat < %s > %s\n", INFILE, OUTFILE);
cat();
printf("Checking %s...\n", OUTFILE);
chkfile();
printf("Checking %s...\n", OUTFILE);
chkfile();
printf("Passed.\n");
(void)remove(INFILE);
(void)remove(OUTFILE);
return 0;
printf("Passed.\n");
(void)remove(INFILE);
(void)remove(OUTFILE);
return 0;
}

View File

@@ -46,7 +46,6 @@
#include <limits.h>
#include <err.h>
static const char testdir[] = "testdir";
static char startpoint[PATH_MAX - sizeof(testdir)];
@@ -55,21 +54,18 @@ static char startpoint[PATH_MAX - sizeof(testdir)];
* where we came from.
*/
static
void
startup(void)
{
if (getcwd(startpoint, sizeof(startpoint))==NULL) {
err(1, "getcwd (not in test dir)");
}
static void startup(void) {
if (getcwd(startpoint, sizeof(startpoint)) == NULL) {
err(1, "getcwd (not in test dir)");
}
if (mkdir(testdir, 0775) < 0) {
err(1, "%s: mkdir", testdir);
}
if (mkdir(testdir, 0775) < 0) {
err(1, "%s: mkdir", testdir);
}
if (chdir(testdir) < 0) {
err(1, "%s: chdir", testdir);
}
if (chdir(testdir) < 0) {
err(1, "%s: chdir", testdir);
}
}
/*
@@ -80,16 +76,13 @@ startup(void)
* from the current directory, which is justifiably prohibited.
*/
static
void
killdir(void)
{
char tmp[PATH_MAX];
static void killdir(void) {
char tmp[PATH_MAX];
snprintf(tmp, sizeof(tmp), "%s/%s", startpoint, testdir);
if (rmdir(tmp)<0) {
err(1, "%s: rmdir", tmp);
}
snprintf(tmp, sizeof(tmp), "%s/%s", startpoint, testdir);
if (rmdir(tmp) < 0) {
err(1, "%s: rmdir", tmp);
}
}
/*
@@ -97,13 +90,10 @@ killdir(void)
* can try again.
*/
static
void
finish(void)
{
if (chdir(startpoint)<0) {
err(1, "%s: chdir", startpoint);
}
static void finish(void) {
if (chdir(startpoint) < 0) {
err(1, "%s: chdir", startpoint);
}
}
/*************************************************************/
@@ -112,293 +102,262 @@ finish(void)
* Basic test - just try removing the directory without doing anything
* evil.
*/
static
void
test1(void)
{
printf("Making %s\n", testdir);
startup();
static void test1(void) {
printf("Making %s\n", testdir);
startup();
printf("Removing %s while in it\n", testdir);
killdir();
printf("Removing %s while in it\n", testdir);
killdir();
printf("Leaving the test directory\n");
finish();
printf("Leaving the test directory\n");
finish();
}
/*
* Now do it while we also have the directory open.
*/
static
void
test2(void)
{
int fd;
static void test2(void) {
int fd;
printf("Now trying with the directory open...\n");
startup();
fd = open(".", O_RDONLY);
if (fd<0) {
err(1, ".: open");
}
killdir();
finish();
printf("Now trying with the directory open...\n");
startup();
fd = open(".", O_RDONLY);
if (fd < 0) {
err(1, ".: open");
}
killdir();
finish();
/* close *after* leaving, just for excitement */
if (close(fd)<0) {
err(1, "removed %s: close", testdir);
}
/* close *after* leaving, just for excitement */
if (close(fd) < 0) {
err(1, "removed %s: close", testdir);
}
}
/*
* Now see if . and .. work after rmdir.
*/
static
void
test3(void)
{
char buf[PATH_MAX];
int fd;
static void test3(void) {
char buf[PATH_MAX];
int fd;
printf("Checking if . exists after rmdir\n");
startup();
killdir();
printf("Checking if . exists after rmdir\n");
startup();
killdir();
fd = open(".", O_RDONLY);
if (fd<0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, ".");
break;
}
}
else {
close(fd);
}
fd = open(".", O_RDONLY);
if (fd < 0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, ".");
break;
}
} else {
close(fd);
}
fd = open("..", O_RDONLY);
if (fd<0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "..");
break;
}
}
else {
warnx("..: openable after rmdir - might be bad");
close(fd);
}
fd = open("..", O_RDONLY);
if (fd < 0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "..");
break;
}
} else {
warnx("..: openable after rmdir - might be bad");
close(fd);
}
snprintf(buf, sizeof(buf), "../%s", testdir);
fd = open(buf, O_RDONLY);
if (fd<0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "%s", buf);
break;
}
}
else {
errx(1, "%s: works after rmdir", buf);
}
snprintf(buf, sizeof(buf), "../%s", testdir);
fd = open(buf, O_RDONLY);
if (fd < 0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "%s", buf);
break;
}
} else {
errx(1, "%s: works after rmdir", buf);
}
finish();
finish();
}
/*
* Now try to create files.
*/
static
void
test4(void)
{
char buf[4096];
int fd;
static void test4(void) {
char buf[4096];
int fd;
printf("Checking if creating files works after rmdir...\n");
startup();
killdir();
printf("Checking if creating files works after rmdir...\n");
startup();
killdir();
fd = open("newfile", O_WRONLY|O_CREAT|O_TRUNC, 0664);
if (fd<0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "%s", buf);
break;
}
}
else {
warnx("newfile: creating files after rmdir works");
warnx("(this is only ok if the space gets reclaimed)");
fd = open("newfile", O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "%s", buf);
break;
}
} else {
warnx("newfile: creating files after rmdir works");
warnx("(this is only ok if the space gets reclaimed)");
/*
* Waste a bunch of space so we'll be able to tell
*/
memset(buf, 'J', sizeof(buf));
write(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
close(fd);
}
/*
* Waste a bunch of space so we'll be able to tell
*/
memset(buf, 'J', sizeof(buf));
write(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
close(fd);
}
finish();
finish();
}
/*
* Now try to create directories.
*/
static
void
test5(void)
{
printf("Checking if creating subdirs works after rmdir...\n");
startup();
killdir();
static void test5(void) {
printf("Checking if creating subdirs works after rmdir...\n");
startup();
killdir();
if (mkdir("newdir", 0775)<0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "mkdir in removed dir");
break;
}
}
else {
warnx("newfile: creating directories after rmdir works");
warnx("(this is only ok if the space gets reclaimed)");
if (mkdir("newdir", 0775) < 0) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "mkdir in removed dir");
break;
}
} else {
warnx("newfile: creating directories after rmdir works");
warnx("(this is only ok if the space gets reclaimed)");
/*
* Waste a bunch of space so we'll be able to tell
*/
mkdir("newdir/t0", 0775);
mkdir("newdir/t1", 0775);
mkdir("newdir/t2", 0775);
mkdir("newdir/t3", 0775);
mkdir("newdir/t4", 0775);
mkdir("newdir/t5", 0775);
}
/*
* Waste a bunch of space so we'll be able to tell
*/
mkdir("newdir/t0", 0775);
mkdir("newdir/t1", 0775);
mkdir("newdir/t2", 0775);
mkdir("newdir/t3", 0775);
mkdir("newdir/t4", 0775);
mkdir("newdir/t5", 0775);
}
finish();
finish();
}
/*
* Now try listing the directory.
*/
static
void
test6(void)
{
char buf[PATH_MAX];
int fd, len;
static void test6(void) {
char buf[PATH_MAX];
int fd, len;
printf("Now trying to list the directory...\n");
startup();
fd = open(".", O_RDONLY);
if (fd<0) {
err(1, ".: open");
}
killdir();
printf("Now trying to list the directory...\n");
startup();
fd = open(".", O_RDONLY);
if (fd < 0) {
err(1, ".: open");
}
killdir();
while ((len = getdirentry(fd, buf, sizeof(buf)-1))>0) {
if ((unsigned)len >= sizeof(buf)-1) {
errx(1, ".: getdirentry: returned invalid length");
}
buf[len] = 0;
if (!strcmp(buf, ".") || !strcmp(buf, "..")) {
/* these are allowed to appear */
continue;
}
errx(1, ".: getdirentry: returned unexpected name %s", buf);
}
if (len==0) {
/* EOF - ok */
}
else { /* len < 0 */
switch (errno) {
case EINVAL:
case EIO:
break;
default:
err(1, ".: getdirentry");
break;
}
}
while ((len = getdirentry(fd, buf, sizeof(buf) - 1)) > 0) {
if ((unsigned)len >= sizeof(buf) - 1) {
errx(1, ".: getdirentry: returned invalid length");
}
buf[len] = 0;
if (!strcmp(buf, ".") || !strcmp(buf, "..")) {
/* these are allowed to appear */
continue;
}
errx(1, ".: getdirentry: returned unexpected name %s", buf);
}
if (len == 0) {
/* EOF - ok */
} else { /* len < 0 */
switch (errno) {
case EINVAL:
case EIO:
break;
default:
err(1, ".: getdirentry");
break;
}
}
finish();
finish();
/* close *after* leaving, just for excitement */
if (close(fd)<0) {
err(1, "removed %s: close", testdir);
}
/* close *after* leaving, just for excitement */
if (close(fd) < 0) {
err(1, "removed %s: close", testdir);
}
}
/*
* Try getcwd.
*/
static
void
test7(void)
{
char buf[PATH_MAX];
static void test7(void) {
char buf[PATH_MAX];
startup();
killdir();
if (getcwd(buf, sizeof(buf))==NULL) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "getcwd after removing %s", testdir);
break;
}
}
else {
errx(1, "getcwd after removing %s: succeeded (got %s)",
testdir, buf);
}
startup();
killdir();
if (getcwd(buf, sizeof(buf)) == NULL) {
switch (errno) {
case EINVAL:
case EIO:
case ENOENT:
break;
default:
err(1, "getcwd after removing %s", testdir);
break;
}
} else {
errx(1, "getcwd after removing %s: succeeded (got %s)", testdir, buf);
}
finish();
finish();
}
/**************************************************************/
int
main(void)
{
test1();
test2();
test3();
test4();
test5();
test6();
test7();
int main(void) {
test1();
test2();
test3();
test4();
test5();
test6();
test7();
printf("Whew... survived.\n");
return 0;
printf("Whew... survived.\n");
return 0;
}

View File

@@ -43,121 +43,110 @@
#include <errno.h>
#include <err.h>
#define TEST "rmdata"
#define TESTDATA "I wish I was a headlight. -- Jerry Garcia"
#define TESTLEN (sizeof(TESTDATA)-1)
#define TEST "rmdata"
#define TESTDATA "I wish I was a headlight. -- Jerry Garcia"
#define TESTLEN (sizeof(TESTDATA) - 1)
static
void
dorm(int fd)
{
/*
* This used to spawn a copy of /bin/rm, but that's silly.
* However, we will do the remove() from a subprocess, so
* that various kinds of improper hacks to make this test
* run won't work.
*
* Close the file in the subprocess, for similar reasons.
*/
static void dorm(int fd) {
/*
* This used to spawn a copy of /bin/rm, but that's silly.
* However, we will do the remove() from a subprocess, so
* that various kinds of improper hacks to make this test
* run won't work.
*
* Close the file in the subprocess, for similar reasons.
*/
pid_t pid;
int status;
pid_t pid;
int status;
pid = fork();
if (pid<0) {
err(1, "fork");
}
if (pid==0) {
/* child process */
close(fd);
if (remove(TEST)) {
err(1, "%s: remove", TEST);
}
_exit(0);
}
/* parent process */
if (waitpid(pid, &status, 0)<0) {
err(1, "waitpid");
}
else if (WIFSIGNALED(status)) {
warn("child process exited with signal %d", WTERMSIG(status));
}
else if (WEXITSTATUS(status) != 0) {
warnx("child process exited with code %d",WEXITSTATUS(status));
}
pid = fork();
if (pid < 0) {
err(1, "fork");
}
if (pid == 0) {
/* child process */
close(fd);
if (remove(TEST)) {
err(1, "%s: remove", TEST);
}
_exit(0);
}
/* parent process */
if (waitpid(pid, &status, 0) < 0) {
err(1, "waitpid");
} else if (WIFSIGNALED(status)) {
warn("child process exited with signal %d", WTERMSIG(status));
} else if (WEXITSTATUS(status) != 0) {
warnx("child process exited with code %d", WEXITSTATUS(status));
}
}
static
int
same(const char *a, const char *b, int len)
{
while (len-- > 0) {
if (*a++ != *b++) return 0;
}
return 1;
static int same(const char *a, const char *b, int len) {
while (len-- > 0) {
if (*a++ != *b++)
return 0;
}
return 1;
}
int
main(void)
{
int file, len;
char buf[TESTLEN];
int main(void) {
int file, len;
char buf[TESTLEN];
/* create test data file */
file = open(TEST, O_WRONLY | O_CREAT | O_TRUNC, 0664);
write(file, TESTDATA, TESTLEN);
close(file);
/* create test data file */
file = open(TEST, O_WRONLY | O_CREAT | O_TRUNC, 0664);
write(file, TESTDATA, TESTLEN);
close(file);
/* make sure the data is there */
file = open(TEST, O_RDONLY);
len = read(file, buf, TESTLEN);
if (len < 0) {
warn("read: before deletion");
}
else if (len < (int)TESTLEN) {
warnx("read: before deletion: short count %d", len);
}
if (!same(buf, TESTDATA, TESTLEN)) {
errx(1, "Failed: data read back was not the same");
}
/* make sure the data is there */
file = open(TEST, O_RDONLY);
len = read(file, buf, TESTLEN);
if (len < 0) {
warn("read: before deletion");
} else if (len < (int)TESTLEN) {
warnx("read: before deletion: short count %d", len);
}
if (!same(buf, TESTDATA, TESTLEN)) {
errx(1, "Failed: data read back was not the same");
}
/* rewind the file */
if (lseek(file, 0, SEEK_SET)) {
err(1, "lseek");
}
/* rewind the file */
if (lseek(file, 0, SEEK_SET)) {
err(1, "lseek");
}
/* now spawn our killer and wait for it to do its work */
dorm(file);
/* now spawn our killer and wait for it to do its work */
dorm(file);
/* we should be still able to read the data */
memset(buf, '\0', TESTLEN);
len = read(file, buf, TESTLEN);
if (len < 0) {
warn("read: after deletion");
}
else if (len < (int)TESTLEN) {
warnx("read: after deletion: short count %d", len);
}
/* we should be still able to read the data */
memset(buf, '\0', TESTLEN);
len = read(file, buf, TESTLEN);
if (len < 0) {
warn("read: after deletion");
} else if (len < (int)TESTLEN) {
warnx("read: after deletion: short count %d", len);
}
if (!same(buf, TESTDATA, TESTLEN)) {
errx(1, "Failed: data read after deletion was not the same");
}
if (!same(buf, TESTDATA, TESTLEN)) {
errx(1, "Failed: data read after deletion was not the same");
}
/* ok, close the file and it should go away */
close(file);
/* ok, close the file and it should go away */
close(file);
/* try to open it again */
file = open(TEST, O_RDONLY);
if (file >= 0) {
close(file);
errx(1, "Failed: the file could still be opened");
}
/* try to open it again */
file = open(TEST, O_RDONLY);
if (file >= 0) {
close(file);
errx(1, "Failed: the file could still be opened");
}
if (errno!=ENOENT) {
err(1, "Unexpected error reopening the file");
}
if (errno != ENOENT) {
err(1, "Unexpected error reopening the file");
}
printf("Succeeded!\n");
printf("Succeeded!\n");
return 0;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -40,46 +40,40 @@
/*
* comparison functions for qsort
*/
static
int
uintcmp(const void *av, const void *bv)
{
unsigned a = *(const unsigned *)av;
unsigned b = *(const unsigned *)bv;
static int uintcmp(const void *av, const void *bv) {
unsigned a = *(const unsigned *)av;
unsigned b = *(const unsigned *)bv;
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
static
int
altcmp(const void *av, const void *bv)
{
unsigned a = *(const unsigned *)av;
unsigned b = *(const unsigned *)bv;
unsigned ax = (a & 0xffff0000) >> 16;
unsigned ay = a & 0xffff;
unsigned bx = (b & 0xffff0000) >> 16;
unsigned by = b & 0xffff;
static int altcmp(const void *av, const void *bv) {
unsigned a = *(const unsigned *)av;
unsigned b = *(const unsigned *)bv;
unsigned ax = (a & 0xffff0000) >> 16;
unsigned ay = a & 0xffff;
unsigned bx = (b & 0xffff0000) >> 16;
unsigned by = b & 0xffff;
if (ax < bx) {
return 1;
}
if (ax > bx) {
return -1;
}
if (ay < by) {
return -1;
}
if (ay > by) {
return 1;
}
return 0;
if (ax < bx) {
return 1;
}
if (ax > bx) {
return -1;
}
if (ay < by) {
return -1;
}
if (ay > by) {
return 1;
}
return 0;
}
#if 0
@@ -104,35 +98,29 @@ shuffle(unsigned *p, unsigned n)
/*
* Compute first differences.
*/
static
void
diffs(unsigned *p, unsigned n)
{
unsigned p0;
unsigned i;
static void diffs(unsigned *p, unsigned n) {
unsigned p0;
unsigned i;
p0 = p[0];
p0 = p[0];
for (i=0; i<n-1; i++) {
p[i] = p[i] - p[i+1];
}
p[n-1] = p[n-1] - p0;
for (i = 0; i < n - 1; i++) {
p[i] = p[i] - p[i + 1];
}
p[n - 1] = p[n - 1] - p0;
}
/*
* Take the sum.
*/
static
unsigned
sum(const unsigned *p, unsigned n)
{
unsigned t, i;
static unsigned sum(const unsigned *p, unsigned n) {
unsigned t, i;
t = 0;
for (i=0; i<n; i++) {
t += p[i];
}
return t;
t = 0;
for (i = 0; i < n; i++) {
t += p[i];
}
return t;
}
/*
@@ -140,66 +128,64 @@ sum(const unsigned *p, unsigned n)
*
* Note that this won't work until you have a VM system.
*/
void
grind(unsigned groupid, unsigned id)
{
unsigned *p;
unsigned i, n, s;
void grind(unsigned groupid, unsigned id) {
unsigned *p;
unsigned i, n, s;
(void)groupid;
(void)groupid;
waitstart();
waitstart();
/* each grind task uses 768K */
n = (768*1024) / sizeof(*p);
p = malloc(n * sizeof(*p));
if (p == NULL) {
if (errno == ENOSYS) {
/*
* If we don't have sbrk, just bail out with
* "success" instead of failing the whole
* workload.
*/
errx(0, "grind: sbrk/malloc not implemented");
}
err(1, "malloc");
}
/* each grind task uses 768K */
n = (768 * 1024) / sizeof(*p);
p = malloc(n * sizeof(*p));
if (p == NULL) {
if (errno == ENOSYS) {
/*
* If we don't have sbrk, just bail out with
* "success" instead of failing the whole
* workload.
*/
errx(0, "grind: sbrk/malloc not implemented");
}
err(1, "malloc");
}
/* First, get some random integers. */
warnx("grind %u: seeding", id);
srandom(1753);
for (i=0; i<n; i++) {
p[i] = random();
}
/* First, get some random integers. */
warnx("grind %u: seeding", id);
srandom(1753);
for (i = 0; i < n; i++) {
p[i] = random();
}
/* Now sort them. */
warnx("grind %u: sorting", id);
qsort(p, n, sizeof(p[0]), uintcmp);
/* Now sort them. */
warnx("grind %u: sorting", id);
qsort(p, n, sizeof(p[0]), uintcmp);
/* Sort by a different comparison. */
warnx("grind %u: sorting alternately", id);
qsort(p, n, sizeof(p[0]), altcmp);
/* Sort by a different comparison. */
warnx("grind %u: sorting alternately", id);
qsort(p, n, sizeof(p[0]), altcmp);
/* Take the sum. */
warnx("grind %u: summing", id);
s = sum(p, n);
warnx("grind %u: sum is %u (should be %u)", id, s, RIGHT);
if (s != RIGHT) {
errx(1, "grind %u FAILED", id);
}
/* Take the sum. */
warnx("grind %u: summing", id);
s = sum(p, n);
warnx("grind %u: sum is %u (should be %u)", id, s, RIGHT);
if (s != RIGHT) {
errx(1, "grind %u FAILED", id);
}
/* Take first differences. */
warnx("grind %u: first differences", id);
diffs(p, n);
/* Take first differences. */
warnx("grind %u: first differences", id);
diffs(p, n);
/* Sort. */
warnx("grind %u: sorting", id);
qsort(p, n, sizeof(p[0]), uintcmp);
/* Sort. */
warnx("grind %u: sorting", id);
qsort(p, n, sizeof(p[0]), uintcmp);
warnx("grind %u: summing", id);
s = sum(p, n);
warnx("grind %u: sum is %u (should be 0)", id, s);
if (s != 0) {
errx(1, "grind %u FAILED", id);
}
warnx("grind %u: summing", id);
s = sum(p, n);
warnx("grind %u: sum is %u (should be 0)", id, s);
if (s != 0) {
errx(1, "grind %u FAILED", id);
}
}

View File

@@ -48,91 +48,81 @@ struct usem startsem;
/*
* Task hook function that does nothing.
*/
static
void
nop(unsigned groupid, unsigned count)
{
(void)groupid;
(void)count;
static void nop(unsigned groupid, unsigned count) {
(void)groupid;
(void)count;
}
/*
* Wrapper for wait.
*/
static
unsigned
dowait(pid_t pid)
{
int r;
int status;
static unsigned dowait(pid_t pid) {
int r;
int status;
r = waitpid(pid, &status, 0);
if (r < 0) {
err(1, "waitpid");
}
if (WIFSIGNALED(status)) {
warnx("pid %d signal %d", pid, WTERMSIG(status));
return 1;
}
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
warnx("pid %d exit %d", pid, WEXITSTATUS(status));
return 1;
}
return 0;
r = waitpid(pid, &status, 0);
if (r < 0) {
err(1, "waitpid");
}
if (WIFSIGNALED(status)) {
warnx("pid %d signal %d", pid, WTERMSIG(status));
return 1;
}
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
warnx("pid %d exit %d", pid, WEXITSTATUS(status));
return 1;
}
return 0;
}
/*
* Do a task group: fork the processes, then wait for them.
*/
static
void
runtaskgroup(unsigned count,
void (*prep)(unsigned, unsigned),
void (*task)(unsigned, unsigned),
void (*cleanup)(unsigned, unsigned),
unsigned groupid)
{
pid_t mypids[count];
unsigned i;
unsigned failures = 0;
time_t secs;
unsigned long nsecs;
static void runtaskgroup(unsigned count, void (*prep)(unsigned, unsigned),
void (*task)(unsigned, unsigned),
void (*cleanup)(unsigned, unsigned),
unsigned groupid) {
pid_t mypids[count];
unsigned i;
unsigned failures = 0;
time_t secs;
unsigned long nsecs;
prep(groupid, count);
prep(groupid, count);
for (i=0; i<count; i++) {
mypids[i] = fork();
if (mypids[i] < 0) {
err(1, "fork");
}
if (mypids[i] == 0) {
/* child (of second fork) */
task(groupid, i);
exit(0);
}
/* parent (of second fork) - continue */
}
for (i = 0; i < count; i++) {
mypids[i] = fork();
if (mypids[i] < 0) {
err(1, "fork");
}
if (mypids[i] == 0) {
/* child (of second fork) */
task(groupid, i);
exit(0);
}
/* parent (of second fork) - continue */
}
/*
* now wait for the task to finish
*/
/*
* now wait for the task to finish
*/
for (i=0; i<count; i++) {
failures += dowait(mypids[i]);
}
for (i = 0; i < count; i++) {
failures += dowait(mypids[i]);
}
/*
* Store the end time.
*/
/*
* Store the end time.
*/
__time(&secs, &nsecs);
openresultsfile(O_WRONLY);
putresult(groupid, secs, nsecs);
closeresultsfile();
__time(&secs, &nsecs);
openresultsfile(O_WRONLY);
putresult(groupid, secs, nsecs);
closeresultsfile();
cleanup(groupid, count);
cleanup(groupid, count);
exit(failures ? 1 : 0);
exit(failures ? 1 : 0);
}
/*
@@ -143,177 +133,150 @@ runtaskgroup(unsigned count,
* get timing results even on kernels that don't support waitpid with
* WNOHANG.
*/
static
void
forkem(unsigned count,
void (*prep)(unsigned, unsigned),
void (*task)(unsigned, unsigned),
void (*cleanup)(unsigned, unsigned),
unsigned groupid,
pid_t *retpid)
{
*retpid = fork();
if (*retpid < 0) {
err(1, "fork");
}
if (*retpid == 0) {
/* child */
runtaskgroup(count, prep, task, cleanup, groupid);
}
/* parent -- just return */
static void forkem(unsigned count, void (*prep)(unsigned, unsigned),
void (*task)(unsigned, unsigned),
void (*cleanup)(unsigned, unsigned), unsigned groupid,
pid_t *retpid) {
*retpid = fork();
if (*retpid < 0) {
err(1, "fork");
}
if (*retpid == 0) {
/* child */
runtaskgroup(count, prep, task, cleanup, groupid);
}
/* parent -- just return */
}
/*
* Wait for the task group directors to exit.
*/
static
void
waitall(pid_t *pids, unsigned numpids)
{
unsigned failures = 0;
unsigned i;
static void waitall(pid_t *pids, unsigned numpids) {
unsigned failures = 0;
unsigned i;
for (i=0; i<numpids; i++) {
failures += dowait(pids[i]);
}
if (failures) {
errx(1, "TEST FAILURE: one or more subprocesses broke");
}
for (i = 0; i < numpids; i++) {
failures += dowait(pids[i]);
}
if (failures) {
errx(1, "TEST FAILURE: one or more subprocesses broke");
}
}
/*
* Fetch, compute, and print the timing for one task group.
*/
static
void
calcresult(unsigned groupid, time_t startsecs, unsigned long startnsecs,
char *buf, size_t bufmax)
{
time_t secs;
unsigned long nsecs;
static void calcresult(unsigned groupid, time_t startsecs,
unsigned long startnsecs, char *buf, size_t bufmax) {
time_t secs;
unsigned long nsecs;
getresult(groupid, &secs, &nsecs);
getresult(groupid, &secs, &nsecs);
/* secs.nsecs -= startsecs.startnsecs */
if (nsecs < startnsecs) {
nsecs += 1000000000;
secs--;
}
nsecs -= startnsecs;
secs -= startsecs;
snprintf(buf, bufmax, "%lld.%09lu", (long long)secs, nsecs);
/* secs.nsecs -= startsecs.startnsecs */
if (nsecs < startnsecs) {
nsecs += 1000000000;
secs--;
}
nsecs -= startnsecs;
secs -= startsecs;
snprintf(buf, bufmax, "%lld.%09lu", (long long)secs, nsecs);
}
/*
* Used by the tasks to wait to start.
*/
void
waitstart(void)
{
usem_open(&startsem);
P(&startsem);
usem_close(&startsem);
void waitstart(void) {
usem_open(&startsem);
P(&startsem);
usem_close(&startsem);
}
/*
* Run the whole workload.
*/
static
void
runit(unsigned numthinkers, unsigned numgrinders,
unsigned numponggroups, unsigned ponggroupsize)
{
pid_t pids[numponggroups + 2];
time_t startsecs;
unsigned long startnsecs;
char buf[32];
unsigned i;
static void runit(unsigned numthinkers, unsigned numgrinders,
unsigned numponggroups, unsigned ponggroupsize) {
pid_t pids[numponggroups + 2];
time_t startsecs;
unsigned long startnsecs;
char buf[32];
unsigned i;
printf("Running with %u thinkers, %u grinders, and %u pong groups "
"of size %u each.\n", numthinkers, numgrinders, numponggroups,
ponggroupsize);
printf("Running with %u thinkers, %u grinders, and %u pong groups "
"of size %u each.\n",
numthinkers, numgrinders, numponggroups, ponggroupsize);
usem_init(&startsem, STARTSEM);
createresultsfile();
forkem(numthinkers, nop, think, nop, 0, &pids[0]);
forkem(numgrinders, nop, grind, nop, 1, &pids[1]);
for (i=0; i<numponggroups; i++) {
forkem(ponggroupsize, pong_prep, pong, pong_cleanup, i+2,
&pids[i+2]);
}
usem_open(&startsem);
printf("Forking done; starting the workload.\n");
__time(&startsecs, &startnsecs);
Vn(&startsem, numthinkers + numgrinders +
numponggroups * ponggroupsize);
waitall(pids, numponggroups + 2);
usem_close(&startsem);
usem_cleanup(&startsem);
usem_init(&startsem, STARTSEM);
createresultsfile();
forkem(numthinkers, nop, think, nop, 0, &pids[0]);
forkem(numgrinders, nop, grind, nop, 1, &pids[1]);
for (i = 0; i < numponggroups; i++) {
forkem(ponggroupsize, pong_prep, pong, pong_cleanup, i + 2, &pids[i + 2]);
}
usem_open(&startsem);
printf("Forking done; starting the workload.\n");
__time(&startsecs, &startnsecs);
Vn(&startsem, numthinkers + numgrinders + numponggroups * ponggroupsize);
waitall(pids, numponggroups + 2);
usem_close(&startsem);
usem_cleanup(&startsem);
openresultsfile(O_RDONLY);
openresultsfile(O_RDONLY);
printf("--- Timings ---\n");
if (numthinkers > 0) {
calcresult(0, startsecs, startnsecs, buf, sizeof(buf));
printf("Thinkers: %s\n", buf);
}
printf("--- Timings ---\n");
if (numthinkers > 0) {
calcresult(0, startsecs, startnsecs, buf, sizeof(buf));
printf("Thinkers: %s\n", buf);
}
if (numgrinders > 0) {
calcresult(1, startsecs, startnsecs, buf, sizeof(buf));
printf("Grinders: %s\n", buf);
}
if (numgrinders > 0) {
calcresult(1, startsecs, startnsecs, buf, sizeof(buf));
printf("Grinders: %s\n", buf);
}
for (i=0; i<numponggroups; i++) {
calcresult(i+2, startsecs, startnsecs, buf, sizeof(buf));
printf("Pong group %u: %s\n", i, buf);
}
for (i = 0; i < numponggroups; i++) {
calcresult(i + 2, startsecs, startnsecs, buf, sizeof(buf));
printf("Pong group %u: %s\n", i, buf);
}
closeresultsfile();
destroyresultsfile();
closeresultsfile();
destroyresultsfile();
}
static
void
usage(const char *av0)
{
warnx("Usage: %s [options]", av0);
warnx(" [-t thinkers] set number of thinkers (default 2)");
warnx(" [-g grinders] set number of grinders (default 0)");
warnx(" [-p ponggroups] set number of pong groups (default 1)");
warnx(" [-s ponggroupsize] set pong group size (default 6)");
warnx("Thinkers are CPU bound; grinders are memory-bound;");
warnx("pong groups are I/O bound.");
exit(1);
static void usage(const char *av0) {
warnx("Usage: %s [options]", av0);
warnx(" [-t thinkers] set number of thinkers (default 2)");
warnx(" [-g grinders] set number of grinders (default 0)");
warnx(" [-p ponggroups] set number of pong groups (default 1)");
warnx(" [-s ponggroupsize] set pong group size (default 6)");
warnx("Thinkers are CPU bound; grinders are memory-bound;");
warnx("pong groups are I/O bound.");
exit(1);
}
int
main(int argc, char *argv[])
{
unsigned numthinkers = 2;
unsigned numgrinders = 0;
unsigned numponggroups = 1;
unsigned ponggroupsize = 6;
int main(int argc, char *argv[]) {
unsigned numthinkers = 2;
unsigned numgrinders = 0;
unsigned numponggroups = 1;
unsigned ponggroupsize = 6;
int i;
int i;
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-t")) {
numthinkers = atoi(argv[++i]);
}
else if (!strcmp(argv[i], "-g")) {
numgrinders = atoi(argv[++i]);
}
else if (!strcmp(argv[i], "-p")) {
numponggroups = atoi(argv[++i]);
}
else if (!strcmp(argv[i], "-s")) {
ponggroupsize = atoi(argv[++i]);
}
else {
usage(argv[0]);
}
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-t")) {
numthinkers = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-g")) {
numgrinders = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-p")) {
numponggroups = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-s")) {
ponggroupsize = atoi(argv[++i]);
} else {
usage(argv[0]);
}
}
runit(numthinkers, numgrinders, numponggroups, ponggroupsize);
return 0;
runit(numthinkers, numgrinders, numponggroups, ponggroupsize);
return 0;
}

View File

@@ -41,7 +41,7 @@
#define MAXCOUNT 64
#define PONGLOOPS 1000
//#define VERBOSE_PONG
// #define VERBOSE_PONG
static struct usem sems[MAXCOUNT];
static unsigned nsems;
@@ -55,31 +55,27 @@ static unsigned nsems;
* that way each task process has its own file handles and they don't
* interfere with each other if file handle locking isn't so great.
*/
void
pong_prep(unsigned groupid, unsigned count)
{
unsigned i;
void pong_prep(unsigned groupid, unsigned count) {
unsigned i;
if (count > MAXCOUNT) {
err(1, "pong: too many pongers -- recompile pong.c");
}
for (i=0; i<count; i++) {
usem_init(&sems[i], "sem:pong-%u-%u", groupid, i);
}
nsems = count;
if (count > MAXCOUNT) {
err(1, "pong: too many pongers -- recompile pong.c");
}
for (i = 0; i < count; i++) {
usem_init(&sems[i], "sem:pong-%u-%u", groupid, i);
}
nsems = count;
}
void
pong_cleanup(unsigned groupid, unsigned count)
{
unsigned i;
void pong_cleanup(unsigned groupid, unsigned count) {
unsigned i;
assert(nsems == count);
(void)groupid;
for (i=0; i<count; i++) {
usem_cleanup(&sems[i]);
}
assert(nsems == count);
(void)groupid;
for (i = 0; i < count; i++) {
usem_cleanup(&sems[i]);
}
}
/*
@@ -87,36 +83,33 @@ pong_cleanup(unsigned groupid, unsigned count)
* If we're id 0, don't wait the first go so things start, but do
* wait the last go.
*/
static
void
pong_cyclic(unsigned id)
{
unsigned i;
unsigned nextid;
static void pong_cyclic(unsigned id) {
unsigned i;
unsigned nextid;
nextid = (id + 1) % nsems;
for (i=0; i<PONGLOOPS; i++) {
if (i > 0 || id > 0) {
P(&sems[id]);
}
nextid = (id + 1) % nsems;
for (i = 0; i < PONGLOOPS; i++) {
if (i > 0 || id > 0) {
P(&sems[id]);
}
#ifdef VERBOSE_PONG
printf(" %u", id);
printf(" %u", id);
#else
if (nextid == 0 && i % 16 == 0) {
putchar('.');
}
if (nextid == 0 && i % 16 == 0) {
putchar('.');
}
#endif
V(&sems[nextid]);
}
if (id == 0) {
P(&sems[id]);
}
V(&sems[nextid]);
}
if (id == 0) {
P(&sems[id]);
}
#ifdef VERBOSE_PONG
putchar('\n');
putchar('\n');
#else
if (nextid == 0) {
putchar('\n');
}
if (nextid == 0) {
putchar('\n');
}
#endif
}
@@ -124,88 +117,80 @@ pong_cyclic(unsigned id)
* Pong back and forth. This runs the tasks with middle numbers more
* often.
*/
static
void
pong_reciprocating(unsigned id)
{
unsigned i, n;
unsigned nextfwd, nextback;
unsigned gofwd = 1;
static void pong_reciprocating(unsigned id) {
unsigned i, n;
unsigned nextfwd, nextback;
unsigned gofwd = 1;
if (id == 0) {
nextfwd = nextback = 1;
n = PONGLOOPS;
}
else if (id == nsems - 1) {
nextfwd = nextback = nsems - 2;
n = PONGLOOPS;
}
else {
nextfwd = id + 1;
nextback = id - 1;
n = PONGLOOPS * 2;
}
if (id == 0) {
nextfwd = nextback = 1;
n = PONGLOOPS;
} else if (id == nsems - 1) {
nextfwd = nextback = nsems - 2;
n = PONGLOOPS;
} else {
nextfwd = id + 1;
nextback = id - 1;
n = PONGLOOPS * 2;
}
for (i=0; i<n; i++) {
if (i > 0 || id > 0) {
P(&sems[id]);
}
for (i = 0; i < n; i++) {
if (i > 0 || id > 0) {
P(&sems[id]);
}
#ifdef VERBOSE_PONG
printf(" %u", id);
printf(" %u", id);
#else
if (id == 0 && i % 16 == 0) {
putchar('.');
}
if (id == 0 && i % 16 == 0) {
putchar('.');
}
#endif
if (gofwd) {
V(&sems[nextfwd]);
gofwd = 0;
}
else {
V(&sems[nextback]);
gofwd = 1;
}
}
if (id == 0) {
P(&sems[id]);
}
if (gofwd) {
V(&sems[nextfwd]);
gofwd = 0;
} else {
V(&sems[nextback]);
gofwd = 1;
}
}
if (id == 0) {
P(&sems[id]);
}
#ifdef VERBOSE_PONG
putchar('\n');
putchar('\n');
#else
if (id == 0) {
putchar('\n');
}
if (id == 0) {
putchar('\n');
}
#endif
}
/*
* Do the pong thing.
*/
void
pong(unsigned groupid, unsigned id)
{
unsigned idfwd, idback;
void pong(unsigned groupid, unsigned id) {
unsigned idfwd, idback;
(void)groupid;
(void)groupid;
idfwd = (id + 1) % nsems;
idback = (id + nsems - 1) % nsems;
usem_open(&sems[id]);
usem_open(&sems[idfwd]);
usem_open(&sems[idback]);
idfwd = (id + 1) % nsems;
idback = (id + nsems - 1) % nsems;
usem_open(&sems[id]);
usem_open(&sems[idfwd]);
usem_open(&sems[idback]);
waitstart();
pong_cyclic(id);
waitstart();
pong_cyclic(id);
#ifdef VERBOSE_PONG
printf("--------------------------------\n");
printf("--------------------------------\n");
#endif
pong_reciprocating(id);
pong_reciprocating(id);
#ifdef VERBOSE_PONG
printf("--------------------------------\n");
printf("--------------------------------\n");
#endif
pong_cyclic(id);
pong_cyclic(id);
usem_close(&sems[id]);
usem_close(&sems[idfwd]);
usem_close(&sems[idback]);
usem_close(&sems[id]);
usem_close(&sems[idfwd]);
usem_close(&sems[idback]);
}

View File

@@ -44,34 +44,30 @@ static int resultsfile = -1;
* Create the file that the timing results are written to.
* This is done first, in the main process.
*/
void
createresultsfile(void)
{
int fd;
void createresultsfile(void) {
int fd;
assert(resultsfile == -1);
assert(resultsfile == -1);
fd = open(RESULTSFILE, O_RDWR|O_CREAT|O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s", RESULTSFILE);
}
if (close(fd) == -1) {
warn("%s: close", RESULTSFILE);
}
fd = open(RESULTSFILE, O_RDWR | O_CREAT | O_TRUNC, 0664);
if (fd < 0) {
err(1, "%s", RESULTSFILE);
}
if (close(fd) == -1) {
warn("%s: close", RESULTSFILE);
}
}
/*
* Remove the timing results file.
* This is done last, in the main process.
*/
void
destroyresultsfile(void)
{
if (remove(RESULTSFILE) == -1) {
if (errno != ENOSYS) {
warn("%s: remove", RESULTSFILE);
}
}
void destroyresultsfile(void) {
if (remove(RESULTSFILE) == -1) {
if (errno != ENOSYS) {
warn("%s: remove", RESULTSFILE);
}
}
}
/*
@@ -80,90 +76,82 @@ destroyresultsfile(void)
* then require extra semaphoring to coordinate...) and afterwards
* done for reading in the main process.
*/
void
openresultsfile(int openflags)
{
assert(openflags == O_RDONLY || openflags == O_WRONLY);
assert(resultsfile == -1);
void openresultsfile(int openflags) {
assert(openflags == O_RDONLY || openflags == O_WRONLY);
assert(resultsfile == -1);
resultsfile = open(RESULTSFILE, openflags, 0);
if (resultsfile < 0) {
err(1, "%s", RESULTSFILE);
}
resultsfile = open(RESULTSFILE, openflags, 0);
if (resultsfile < 0) {
err(1, "%s", RESULTSFILE);
}
}
/*
* Close the timing results file.
*/
void
closeresultsfile(void)
{
assert(resultsfile >= 0);
void closeresultsfile(void) {
assert(resultsfile >= 0);
if (close(resultsfile) == -1) {
warn("%s: close", RESULTSFILE);
}
resultsfile = -1;
if (close(resultsfile) == -1) {
warn("%s: close", RESULTSFILE);
}
resultsfile = -1;
}
/*
* Write a result into the timing results file.
*/
void
putresult(unsigned groupid, time_t secs, unsigned long nsecs)
{
off_t pos;
ssize_t r;
void putresult(unsigned groupid, time_t secs, unsigned long nsecs) {
off_t pos;
ssize_t r;
assert(resultsfile >= 0);
assert(resultsfile >= 0);
pos = groupid * (sizeof(secs) + sizeof(nsecs));
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
err(1, "%s: lseek", RESULTSFILE);
}
r = write(resultsfile, &secs, sizeof(secs));
if (r < 0) {
err(1, "%s: write (seconds)", RESULTSFILE);
}
if ((size_t)r < sizeof(secs)) {
errx(1, "%s: write (seconds): Short write", RESULTSFILE);
}
r = write(resultsfile, &nsecs, sizeof(nsecs));
if (r < 0) {
err(1, "%s: write (nsecs)", RESULTSFILE);
}
if ((size_t)r < sizeof(nsecs)) {
errx(1, "%s: write (nsecs): Short write", RESULTSFILE);
}
pos = groupid * (sizeof(secs) + sizeof(nsecs));
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
err(1, "%s: lseek", RESULTSFILE);
}
r = write(resultsfile, &secs, sizeof(secs));
if (r < 0) {
err(1, "%s: write (seconds)", RESULTSFILE);
}
if ((size_t)r < sizeof(secs)) {
errx(1, "%s: write (seconds): Short write", RESULTSFILE);
}
r = write(resultsfile, &nsecs, sizeof(nsecs));
if (r < 0) {
err(1, "%s: write (nsecs)", RESULTSFILE);
}
if ((size_t)r < sizeof(nsecs)) {
errx(1, "%s: write (nsecs): Short write", RESULTSFILE);
}
}
/*
* Read a result from the timing results file.
*/
void
getresult(unsigned groupid, time_t *secs, unsigned long *nsecs)
{
off_t pos;
ssize_t r;
void getresult(unsigned groupid, time_t *secs, unsigned long *nsecs) {
off_t pos;
ssize_t r;
assert(resultsfile >= 0);
assert(resultsfile >= 0);
pos = groupid * (sizeof(*secs) + sizeof(*nsecs));
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
err(1, "%s: lseek", RESULTSFILE);
}
r = read(resultsfile, secs, sizeof(*secs));
if (r < 0) {
err(1, "%s: read (seconds)", RESULTSFILE);
}
if ((size_t)r < sizeof(*secs)) {
errx(1, "%s: read (seconds): Unexpected EOF", RESULTSFILE);
}
r = read(resultsfile, nsecs, sizeof(*nsecs));
if (r < 0) {
err(1, "%s: read (nsecs)", RESULTSFILE);
}
if ((size_t)r < sizeof(*nsecs)) {
errx(1, "%s: read (nsecs): Unexpected EOF", RESULTSFILE);
}
pos = groupid * (sizeof(*secs) + sizeof(*nsecs));
if (lseek(resultsfile, pos, SEEK_SET) == -1) {
err(1, "%s: lseek", RESULTSFILE);
}
r = read(resultsfile, secs, sizeof(*secs));
if (r < 0) {
err(1, "%s: read (seconds)", RESULTSFILE);
}
if ((size_t)r < sizeof(*secs)) {
errx(1, "%s: read (seconds): Unexpected EOF", RESULTSFILE);
}
r = read(resultsfile, nsecs, sizeof(*nsecs));
if (r < 0) {
err(1, "%s: read (nsecs)", RESULTSFILE);
}
if ((size_t)r < sizeof(*nsecs)) {
errx(1, "%s: read (nsecs): Unexpected EOF", RESULTSFILE);
}
}

View File

@@ -35,21 +35,19 @@
*
* All we do is loop.
*/
void
think(unsigned groupid, unsigned id)
{
volatile unsigned long k, m;
volatile unsigned i;
void think(unsigned groupid, unsigned id) {
volatile unsigned long k, m;
volatile unsigned i;
(void)groupid;
(void)id;
(void)groupid;
(void)id;
waitstart();
waitstart();
k = 15;
m = 7;
k = 15;
m = 7;
#define LOOPCOUNT 35000000
for (i=0; i<LOOPCOUNT; i++) {
k += k*m;
}
for (i = 0; i < LOOPCOUNT; i++) {
k += k * m;
}
}

View File

@@ -41,87 +41,65 @@
#include "usem.h"
void
usem_init(struct usem *sem, const char *namefmt, ...)
{
va_list ap;
void usem_init(struct usem *sem, const char *namefmt, ...) {
va_list ap;
va_start(ap, namefmt);
vsnprintf(sem->name, sizeof(sem->name), namefmt, ap);
va_end(ap);
va_start(ap, namefmt);
vsnprintf(sem->name, sizeof(sem->name), namefmt, ap);
va_end(ap);
sem->fd = open(sem->name, O_RDWR|O_CREAT|O_TRUNC, 0664);
if (sem->fd < 0) {
err(1, "%s: create", sem->name);
}
close(sem->fd);
sem->fd = -1;
sem->fd = open(sem->name, O_RDWR | O_CREAT | O_TRUNC, 0664);
if (sem->fd < 0) {
err(1, "%s: create", sem->name);
}
close(sem->fd);
sem->fd = -1;
}
void
usem_open(struct usem *sem)
{
sem->fd = open(sem->name, O_RDWR);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
void usem_open(struct usem *sem) {
sem->fd = open(sem->name, O_RDWR);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
}
void
usem_close(struct usem *sem)
{
if (close(sem->fd) == -1) {
warn("%s: close", sem->name);
}
void usem_close(struct usem *sem) {
if (close(sem->fd) == -1) {
warn("%s: close", sem->name);
}
}
void
usem_cleanup(struct usem *sem)
{
(void)remove(sem->name);
void usem_cleanup(struct usem *sem) { (void)remove(sem->name); }
void Pn(struct usem *sem, unsigned count) {
ssize_t r;
char c[count];
r = read(sem->fd, c, count);
if (r < 0) {
err(1, "%s: read", sem->name);
}
if ((size_t)r < count) {
errx(1, "%s: read: unexpected EOF", sem->name);
}
}
void
Pn(struct usem *sem, unsigned count)
{
ssize_t r;
char c[count];
void P(struct usem *sem) { Pn(sem, 1); }
r = read(sem->fd, c, count);
if (r < 0) {
err(1, "%s: read", sem->name);
}
if ((size_t)r < count) {
errx(1, "%s: read: unexpected EOF", sem->name);
}
void Vn(struct usem *sem, unsigned count) {
ssize_t r;
char c[count];
/* semfs does not use these values, but be conservative */
memset(c, 0, count);
r = write(sem->fd, c, count);
if (r < 0) {
err(1, "%s: write", sem->name);
}
if ((size_t)r < count) {
errx(1, "%s: write: Short count", sem->name);
}
}
void
P(struct usem *sem)
{
Pn(sem, 1);
}
void
Vn(struct usem *sem, unsigned count)
{
ssize_t r;
char c[count];
/* semfs does not use these values, but be conservative */
memset(c, 0, count);
r = write(sem->fd, c, count);
if (r < 0) {
err(1, "%s: write", sem->name);
}
if ((size_t)r < count) {
errx(1, "%s: write: Short count", sem->name);
}
}
void
V(struct usem *sem)
{
Vn(sem, 1);
}
void V(struct usem *sem) { Vn(sem, 1); }

View File

@@ -32,8 +32,8 @@
* Semaphore structure.
*/
struct usem {
char name[32];
int fd;
char name[32];
int fd;
};
/* XXX this should be in sys/cdefs.h */

View File

@@ -41,8 +41,7 @@
#include <err.h>
/* Larger than physical memory */
#define SIZE (144*1024)
#define SIZE (144 * 1024)
/*
* Quicksort.
@@ -54,82 +53,69 @@
* Also, quicksort has somewhat more interesting memory usage patterns.
*/
static
void
sort(int *arr, int size)
{
static int tmp[SIZE];
int pivot, i, j, k;
static void sort(int *arr, int size) {
static int tmp[SIZE];
int pivot, i, j, k;
if (size<2) {
return;
}
if (size < 2) {
return;
}
pivot = size/2;
sort(arr, pivot);
sort(&arr[pivot], size-pivot);
pivot = size / 2;
sort(arr, pivot);
sort(&arr[pivot], size - pivot);
i = 0;
j = pivot;
k = 0;
while (i<pivot && j<size) {
if (arr[i] < arr[j]) {
tmp[k++] = arr[i++];
}
else {
tmp[k++] = arr[j++];
}
}
while (i<pivot) {
tmp[k++] = arr[i++];
}
while (j<size) {
tmp[k++] = arr[j++];
}
i = 0;
j = pivot;
k = 0;
while (i < pivot && j < size) {
if (arr[i] < arr[j]) {
tmp[k++] = arr[i++];
} else {
tmp[k++] = arr[j++];
}
}
while (i < pivot) {
tmp[k++] = arr[i++];
}
while (j < size) {
tmp[k++] = arr[j++];
}
memcpy(arr, tmp, size*sizeof(int));
memcpy(arr, tmp, size * sizeof(int));
}
////////////////////////////////////////////////////////////
static int A[SIZE];
static
void
initarray(void)
{
int i;
static void initarray(void) {
int i;
/*
* Initialize the array, with pseudo-random but deterministic contents.
*/
srandom(533);
/*
* Initialize the array, with pseudo-random but deterministic contents.
*/
srandom(533);
for (i = 0; i < SIZE; i++) {
A[i] = random();
}
for (i = 0; i < SIZE; i++) {
A[i] = random();
}
}
static
void
check(void)
{
int i;
static void check(void) {
int i;
for (i=0; i<SIZE-1; i++) {
if (A[i] > A[i+1]) {
errx(1, "Failed: A[%d] is %d, A[%d] is %d",
i, A[i], i+1, A[i+1]);
}
}
warnx("Passed.");
for (i = 0; i < SIZE - 1; i++) {
if (A[i] > A[i + 1]) {
errx(1, "Failed: A[%d] is %d, A[%d] is %d", i, A[i], i + 1, A[i + 1]);
}
}
warnx("Passed.");
}
int
main(void)
{
initarray();
sort(A, SIZE);
check();
return 0;
int main(void) {
initarray();
sort(A, SIZE);
check();
return 0;
}

View File

@@ -42,46 +42,43 @@
#include <fcntl.h>
#include <err.h>
int
main(int argc, char *argv[])
{
const char *filename;
int size;
int fd;
int r;
char byte;
int main(int argc, char *argv[]) {
const char *filename;
int size;
int fd;
int r;
char byte;
if (argc != 3) {
errx(1, "Usage: sparsefile <filename> <size>");
}
if (argc != 3) {
errx(1, "Usage: sparsefile <filename> <size>");
}
filename = argv[1];
size = atoi(argv[2]);
byte = '\n';
filename = argv[1];
size = atoi(argv[2]);
byte = '\n';
if (size == 0) {
err(1, "Sparse files of length zero are not meaningful");
}
if (size == 0) {
err(1, "Sparse files of length zero are not meaningful");
}
printf("Creating a sparse file of size %d\n", size);
printf("Creating a sparse file of size %d\n", size);
fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC);
if (fd < 0) {
err(1, "%s: create", filename);
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
if (fd < 0) {
err(1, "%s: create", filename);
}
if (lseek(fd, size-1, SEEK_SET) == -1) {
err(1, "%s: lseek", filename);
}
r = write(fd, &byte, 1);
if (r < 0) {
err(1, "%s: write", filename);
}
else if (r != 1) {
errx(1, "%s: write: Unexpected result count %d", filename, r);
}
if (lseek(fd, size - 1, SEEK_SET) == -1) {
err(1, "%s: lseek", filename);
}
r = write(fd, &byte, 1);
if (r < 0) {
err(1, "%s: write", filename);
} else if (r != 1) {
errx(1, "%s: write: Unexpected result count %d", filename, r);
}
close(fd);
close(fd);
return 0;
return 0;
}

View File

@@ -47,35 +47,29 @@
char buffer[BUFSIZE];
static
void
tail(int file, off_t where, const char *filename)
{
int len;
static void tail(int file, off_t where, const char *filename) {
int len;
if (lseek(file, where, SEEK_SET)<0) {
err(1, "%s", filename);
}
if (lseek(file, where, SEEK_SET) < 0) {
err(1, "%s", filename);
}
while ((len = read(file, buffer, sizeof(buffer))) > 0) {
write(STDOUT_FILENO, buffer, len);
}
while ((len = read(file, buffer, sizeof(buffer))) > 0) {
write(STDOUT_FILENO, buffer, len);
}
}
int
main(int argc, char **argv)
{
int file;
int main(int argc, char **argv) {
int file;
if (argc < 3) {
errx(1, "Usage: tail <file> <location>");
}
file = open(argv[1], O_RDONLY);
if (file < 0) {
err(1, "%s", argv[1]);
}
tail(file, atoi(argv[2]), argv[1]);
close(file);
return 0;
if (argc < 3) {
errx(1, "Usage: tail <file> <location>");
}
file = open(argv[1], O_RDONLY);
if (file < 0) {
err(1, "%s", argv[1]);
}
tail(file, atoi(argv[2]), argv[1]);
close(file);
return 0;
}

View File

@@ -42,14 +42,14 @@
#include <unistd.h>
#define NEWLINE 012
#define EMPTY 0
#define X_PLAYER 1
#define O_PLAYER 2
#define X_MARKER 1
#define O_MARKER 2
#define DIM 3
#define DIMCHAR "2"
#define MAXSTRING 100
#define EMPTY 0
#define X_PLAYER 1
#define O_PLAYER 2
#define X_MARKER 1
#define O_MARKER 2
#define DIM 3
#define DIMCHAR "2"
#define MAXSTRING 100
typedef enum { FALSE, TRUE } bool;
@@ -58,7 +58,7 @@ bool ask_yesno(const char *msg);
bool do_move(int player);
void initialize_board(void);
bool is_win(int x, int y);
int read_string(char *buf, int length);
int read_string(char *buf, int length);
void print_board(void);
void print_instructions(void);
bool win_column(int y, int marker);
@@ -67,7 +67,6 @@ bool win_diag_right(int x, int y, int marker);
bool win_row(int x, int marker);
bool Strcmp(const char *a, const char *b);
/*
* The board is gloabally defined.
*/
@@ -75,37 +74,35 @@ int board[DIM][DIM];
/* Console I/O routines */
int
main(void)
{
bool win = FALSE;
int move, max_moves;
int player;
int main(void) {
bool win = FALSE;
int move, max_moves;
int player;
print_instructions();
max_moves = DIM * DIM; /* Maximum number of moves in a game */
print_instructions();
max_moves = DIM * DIM; /* Maximum number of moves in a game */
while (TRUE) {
initialize_board();
for (move = 1; move <= max_moves; move++) {
player = move % 2 == 0 ? 2 : 1;
win = do_move(player);
print_board();
if (win) {
printf("Player %d, you WON!\n\n", player);
break; /* out of for loop */
}
}
/*
* If we got here by falling through the loop, then it is a
* tie game.
*/
if (!win)
printf("Tie Game!\n\n");
if (!ask_yesno("Do you wish to play again?"))
break; /* out of while loop */
}
return 0;
while (TRUE) {
initialize_board();
for (move = 1; move <= max_moves; move++) {
player = move % 2 == 0 ? 2 : 1;
win = do_move(player);
print_board();
if (win) {
printf("Player %d, you WON!\n\n", player);
break; /* out of for loop */
}
}
/*
* If we got here by falling through the loop, then it is a
* tie game.
*/
if (!win)
printf("Tie Game!\n\n");
if (!ask_yesno("Do you wish to play again?"))
break; /* out of while loop */
}
return 0;
}
/*
@@ -118,12 +115,10 @@ main(void)
* Error
* None
*/
void
print_instructions(void)
{
printf("Welcome to tic-tac-toe!\n");
printf("Player 1 always plays X and player 2 always play O\n");
printf("Good luck!\n\n\n");
void print_instructions(void) {
printf("Welcome to tic-tac-toe!\n");
printf("Player 1 always plays X and player 2 always play O\n");
printf("Good luck!\n\n\n");
}
void
@@ -139,25 +134,33 @@ void
*/
print_board(void)
{
int i, j;
int i, j;
/* Print labels across the top */
printf("\n 0 1 2\n");
/* Print labels across the top */
printf("\n 0 1 2\n");
for (i = 0; i < DIM; i++) {
/* Print row labels */
printf(" %d ", i);
for (j = 0; j < DIM; j++) {
switch (board[i][j]) {
case EMPTY: printf(" "); break;
case X_MARKER: printf(" X "); break;
case O_MARKER: printf(" O "); break;
default: printf("???"); break;
}
}
printf("\n");
}
printf("\n");
for (i = 0; i < DIM; i++) {
/* Print row labels */
printf(" %d ", i);
for (j = 0; j < DIM; j++) {
switch (board[i][j]) {
case EMPTY:
printf(" ");
break;
case X_MARKER:
printf(" X ");
break;
case O_MARKER:
printf(" O ");
break;
default:
printf("???");
break;
}
}
printf("\n");
}
printf("\n");
}
/*
@@ -175,22 +178,20 @@ print_board(void)
* Error
* None
*/
bool
ask_yesno(const char *msg)
{
char answer[MAXSTRING];
bool ask_yesno(const char *msg) {
char answer[MAXSTRING];
while (TRUE) {
printf("%s [yes/no] ", msg);
if (read_string(answer, MAXSTRING) < 0)
return(FALSE);
if (Strcmp(answer, "yes"))
return(TRUE);
else if (Strcmp(answer, "no"))
return(FALSE);
else
printf("Please answer either yes or no\n");
}
while (TRUE) {
printf("%s [yes/no] ", msg);
if (read_string(answer, MAXSTRING) < 0)
return (FALSE);
if (Strcmp(answer, "yes"))
return (TRUE);
else if (Strcmp(answer, "no"))
return (FALSE);
else
printf("Please answer either yes or no\n");
}
}
/*
@@ -209,47 +210,42 @@ ask_yesno(const char *msg)
* Error
* None
*/
bool
do_move(int player)
{
int x, y;
char answer[MAXSTRING];
char cx;
bool do_move(int player) {
int x, y;
char answer[MAXSTRING];
char cx;
printf("Player %d (%c), your move\n", player,
player == X_PLAYER ? 'X' : 'O');
printf("Player %d (%c), your move\n", player, player == X_PLAYER ? 'X' : 'O');
while (TRUE) {
printf("Which row [0-%d]: ", DIM-1);
if (read_string(answer, MAXSTRING) < 0)
return(FALSE);
cx = answer[0];
x = cx - '0';
if (x < 0 || x >= DIM) {
printf("Invalid row; must be >= 0 and < %d\n", DIM-1);
continue;
}
printf("Which column [0-%d]: ", DIM-1);
if (read_string(answer, MAXSTRING) < 0)
return(FALSE);
cx = answer[0];
y = cx - '0';
if (y < 0 || y >= DIM) {
printf("Invalid column; must be >= 0 and < %d\n",
DIM-1);
continue;
}
while (TRUE) {
printf("Which row [0-%d]: ", DIM - 1);
if (read_string(answer, MAXSTRING) < 0)
return (FALSE);
cx = answer[0];
x = cx - '0';
if (x < 0 || x >= DIM) {
printf("Invalid row; must be >= 0 and < %d\n", DIM - 1);
continue;
}
printf("Which column [0-%d]: ", DIM - 1);
if (read_string(answer, MAXSTRING) < 0)
return (FALSE);
cx = answer[0];
y = cx - '0';
if (y < 0 || y >= DIM) {
printf("Invalid column; must be >= 0 and < %d\n", DIM - 1);
continue;
}
if (board[x][y] != EMPTY) {
printf("That location is occupied; please try again\n");
print_board();
} else
break;
}
board[x][y] = player == X_PLAYER ? X_MARKER : O_MARKER;
return(is_win(x, y));
if (board[x][y] != EMPTY) {
printf("That location is occupied; please try again\n");
print_board();
} else
break;
}
board[x][y] = player == X_PLAYER ? X_MARKER : O_MARKER;
return (is_win(x, y));
}
/*
@@ -274,124 +270,106 @@ do_move(int player)
* TRUE if player won
* FALSE otherwise
*/
bool
is_win(int x, int y)
{
int marker;
bool is_win(int x, int y) {
int marker;
marker = board[x][y];
marker = board[x][y];
/*
* Note that C "short circuit evaluation". As soon as any one
* of these functions returns TRUE, we know that the expression
* is true. Therefore, we can return TRUE without executing
* any of the other routines.
*/
return(win_row(x, marker) || win_column(y, marker) ||
win_diag_left(x, y, marker) || win_diag_right(x, y, marker));
/*
* Note that C "short circuit evaluation". As soon as any one
* of these functions returns TRUE, we know that the expression
* is true. Therefore, we can return TRUE without executing
* any of the other routines.
*/
return (win_row(x, marker) || win_column(y, marker) ||
win_diag_left(x, y, marker) || win_diag_right(x, y, marker));
}
/*
* Four helper functions for determining a win.
*/
bool
win_column(int y, int marker)
{
int i;
for (i = 0; i < DIM; i++)
if (board[i][y] != marker)
return(FALSE);
return(TRUE);
bool win_column(int y, int marker) {
int i;
for (i = 0; i < DIM; i++)
if (board[i][y] != marker)
return (FALSE);
return (TRUE);
}
bool
win_row(int x, int marker)
{
int i;
for (i = 0; i < DIM; i++)
if (board[x][i] != marker)
return(FALSE);
return(TRUE);
bool win_row(int x, int marker) {
int i;
for (i = 0; i < DIM; i++)
if (board[x][i] != marker)
return (FALSE);
return (TRUE);
}
bool
win_diag_left(int x, int y, int marker)
{
int i;
bool win_diag_left(int x, int y, int marker) {
int i;
/* Check that move is on the diagonal */
if (x != y)
return(FALSE);
/* Check that move is on the diagonal */
if (x != y)
return (FALSE);
for (i = 0; i < DIM; i++)
if (board[i][i] != marker)
return(FALSE);
return(TRUE);
for (i = 0; i < DIM; i++)
if (board[i][i] != marker)
return (FALSE);
return (TRUE);
}
bool
win_diag_right(int x, int y, int marker)
{
int i;
bool win_diag_right(int x, int y, int marker) {
int i;
/* Check that move is on the diagonal */
if (x + y != DIM - 1)
return(FALSE);
for (i = 0; i < DIM; i++)
if (board[i][DIM - 1 - i] != marker)
return(FALSE);
return(TRUE);
/* Check that move is on the diagonal */
if (x + y != DIM - 1)
return (FALSE);
for (i = 0; i < DIM; i++)
if (board[i][DIM - 1 - i] != marker)
return (FALSE);
return (TRUE);
}
void
initialize_board(void)
{
int i, j;
void initialize_board(void) {
int i, j;
for (i = 0; i < DIM; i++)
for (j = 0; j < DIM; j++)
board[i][j] = EMPTY;
for (i = 0; i < DIM; i++)
for (j = 0; j < DIM; j++)
board[i][j] = EMPTY;
}
int
read_string(char *buf, int length)
{
int char_read;
int i;
int read_string(char *buf, int length) {
int char_read;
int i;
i = 0;
while ((char_read = getchar()) != EOF && char_read != NEWLINE &&
i < length) {
buf[i] = (char) char_read;
i++;
putchar(char_read);
}
i = 0;
while ((char_read = getchar()) != EOF && char_read != NEWLINE && i < length) {
buf[i] = (char)char_read;
i++;
putchar(char_read);
}
if (char_read == EOF)
return(-1);
if (char_read == EOF)
return (-1);
/*
* If the input overflows the buffer, just cut it short
* at length - 1 characters.
*/
if (i >= length)
i--;
buf[i] = 0;
return(i);
/*
* If the input overflows the buffer, just cut it short
* at length - 1 characters.
*/
if (i >= length)
i--;
buf[i] = 0;
return (i);
}
bool
Strcmp(const char *a, const char *b)
{
if (a == NULL)
return(b == NULL);
if (b == NULL)
return(FALSE);
bool Strcmp(const char *a, const char *b) {
if (a == NULL)
return (b == NULL);
if (b == NULL)
return (FALSE);
while (*a && *b)
if (*a++ != *b++)
return(FALSE);
return(*a == *b);
while (*a && *b)
if (*a++ != *b++)
return (FALSE);
return (*a == *b);
}

View File

@@ -37,9 +37,7 @@
#include <test/triple.h>
int
main(void)
{
triple("/testbin/huge");
return 0;
int main(void) {
triple("/testbin/huge");
return 0;
}

View File

@@ -37,9 +37,7 @@
#include <test/triple.h>
int
main(void)
{
triple("/testbin/matmult");
return 0;
int main(void) {
triple("/testbin/matmult");
return 0;
}

View File

@@ -37,9 +37,7 @@
#include <test/triple.h>
int
main(void)
{
triple("/testbin/sort");
return 0;
int main(void) {
triple("/testbin/sort");
return 0;
}

View File

@@ -45,25 +45,22 @@
#include <fcntl.h>
#include <err.h>
#define ONCELOOPS 3
#define TWICELOOPS 2
#define ONCELOOPS 3
#define TWICELOOPS 2
#define THRICELOOPS 1
#define LOOPS (ONCELOOPS + 2*TWICELOOPS + 3*THRICELOOPS)
#define LOOPS (ONCELOOPS + 2 * TWICELOOPS + 3 * THRICELOOPS)
#define NUMJOBS 4
/*
* Print to the console, one character at a time to encourage
* interleaving if the semaphores aren't working.
*/
static
void
say(const char *str)
{
size_t i;
static void say(const char *str) {
size_t i;
for (i=0; str[i]; i++) {
putchar(str[i]);
}
for (i = 0; str[i]; i++) {
putchar(str[i]);
}
}
#if 0 /* not used */
@@ -85,26 +82,21 @@ sayf(const char *str, ...)
/*
* This should probably be in libtest.
*/
static
void
dowait(pid_t pid, unsigned num)
{
pid_t r;
int status;
static void dowait(pid_t pid, unsigned num) {
pid_t r;
int status;
r = waitpid(pid, &status, 0);
if (r < 0) {
warn("waitpid");
return;
}
if (WIFSIGNALED(status)) {
warnx("pid %d (subprocess %u): Signal %d", (int)pid,
num, WTERMSIG(status));
}
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
warnx("pid %d (subprocess %u): Exit %d", (int)pid,
num, WEXITSTATUS(status));
}
r = waitpid(pid, &status, 0);
if (r < 0) {
warn("waitpid");
return;
}
if (WIFSIGNALED(status)) {
warnx("pid %d (subprocess %u): Signal %d", (int)pid, num, WTERMSIG(status));
} else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
warnx("pid %d (subprocess %u): Exit %d", (int)pid, num,
WEXITSTATUS(status));
}
}
////////////////////////////////////////////////////////////
@@ -114,276 +106,238 @@ dowait(pid_t pid, unsigned num)
* Semaphore structure.
*/
struct usem {
char name[32];
int fd;
char name[32];
int fd;
};
static
void
usem_init(struct usem *sem, const char *tag, unsigned num)
{
snprintf(sem->name, sizeof(sem->name), "sem:usemtest.%s%u", tag, num);
sem->fd = open(sem->name, O_RDWR|O_CREAT|O_TRUNC, 0664);
if (sem->fd < 0) {
err(1, "%s: create", sem->name);
}
close(sem->fd);
sem->fd = -1;
static void usem_init(struct usem *sem, const char *tag, unsigned num) {
snprintf(sem->name, sizeof(sem->name), "sem:usemtest.%s%u", tag, num);
sem->fd = open(sem->name, O_RDWR | O_CREAT | O_TRUNC, 0664);
if (sem->fd < 0) {
err(1, "%s: create", sem->name);
}
close(sem->fd);
sem->fd = -1;
}
static
void
usem_open(struct usem *sem)
{
sem->fd = open(sem->name, O_RDWR);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
static void usem_open(struct usem *sem) {
sem->fd = open(sem->name, O_RDWR);
if (sem->fd < 0) {
err(1, "%s: open", sem->name);
}
}
static
void
usem_close(struct usem *sem)
{
if (close(sem->fd) == -1) {
warn("%s: close", sem->name);
}
static void usem_close(struct usem *sem) {
if (close(sem->fd) == -1) {
warn("%s: close", sem->name);
}
}
static
void
usem_cleanup(struct usem *sem)
{
(void)remove(sem->name);
static void usem_cleanup(struct usem *sem) { (void)remove(sem->name); }
static void P(struct usem *sem) {
ssize_t r;
char c;
r = read(sem->fd, &c, 1);
if (r < 0) {
err(1, "%s: read", sem->name);
}
if (r == 0) {
errx(1, "%s: read: unexpected EOF", sem->name);
}
}
static
void
P(struct usem *sem)
{
ssize_t r;
char c;
static void V(struct usem *sem) {
ssize_t r;
char c;
r = read(sem->fd, &c, 1);
if (r < 0) {
err(1, "%s: read", sem->name);
}
if (r == 0) {
errx(1, "%s: read: unexpected EOF", sem->name);
}
}
static
void
V(struct usem *sem)
{
ssize_t r;
char c;
r = write(sem->fd, &c, 1);
if (r < 0) {
err(1, "%s: write", sem->name);
}
if (r == 0) {
errx(1, "%s: write: short count", sem->name);
}
r = write(sem->fd, &c, 1);
if (r < 0) {
err(1, "%s: write", sem->name);
}
if (r == 0) {
errx(1, "%s: write: short count", sem->name);
}
}
////////////////////////////////////////////////////////////
// test components
static
void
child_plain(struct usem *gosem, struct usem *waitsem, unsigned num)
{
static const char *const strings[NUMJOBS] = {
"Nitwit!",
"Blubber!",
"Oddment!",
"Tweak!",
};
static void child_plain(struct usem *gosem, struct usem *waitsem,
unsigned num) {
static const char *const strings[NUMJOBS] = {
"Nitwit!",
"Blubber!",
"Oddment!",
"Tweak!",
};
const char *string;
unsigned i;
const char *string;
unsigned i;
string = strings[num];
for (i=0; i<LOOPS; i++) {
P(gosem);
say(string);
V(waitsem);
}
string = strings[num];
for (i = 0; i < LOOPS; i++) {
P(gosem);
say(string);
V(waitsem);
}
}
static
void
child_with_own_fd(struct usem *gosem, struct usem *waitsem, unsigned num)
{
usem_open(gosem);
usem_open(waitsem);
child_plain(gosem, waitsem, num);
usem_close(gosem);
usem_close(waitsem);
static void child_with_own_fd(struct usem *gosem, struct usem *waitsem,
unsigned num) {
usem_open(gosem);
usem_open(waitsem);
child_plain(gosem, waitsem, num);
usem_close(gosem);
usem_close(waitsem);
}
static
void
baseparent(struct usem *gosems, struct usem *waitsems)
{
unsigned i, j;
static void baseparent(struct usem *gosems, struct usem *waitsems) {
unsigned i, j;
for (i=0; i<NUMJOBS; i++) {
usem_open(&gosems[i]);
usem_open(&waitsems[i]);
}
for (i = 0; i < NUMJOBS; i++) {
usem_open(&gosems[i]);
usem_open(&waitsems[i]);
}
say("Once...\n");
for (j=0; j<ONCELOOPS; j++) {
for (i=0; i<NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
}
putchar('\n');
}
say("Once...\n");
for (j = 0; j < ONCELOOPS; j++) {
for (i = 0; i < NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
}
putchar('\n');
}
say("Twice...\n");
for (j=0; j<TWICELOOPS; j++) {
for (i=0; i<NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
}
putchar('\n');
}
say("Twice...\n");
for (j = 0; j < TWICELOOPS; j++) {
for (i = 0; i < NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
}
putchar('\n');
}
say("Three times...\n");
for (j=0; j<THRICELOOPS; j++) {
for (i=0; i<NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
V(&gosems[i]);
P(&waitsems[i]);
putchar('\n');
}
}
say("Three times...\n");
for (j = 0; j < THRICELOOPS; j++) {
for (i = 0; i < NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
V(&gosems[i]);
P(&waitsems[i]);
putchar('\n');
}
}
for (i=0; i<NUMJOBS; i++) {
usem_close(&gosems[i]);
usem_close(&waitsems[i]);
}
for (i = 0; i < NUMJOBS; i++) {
usem_close(&gosems[i]);
usem_close(&waitsems[i]);
}
}
static
void
basetest(void)
{
unsigned i;
struct usem gosems[NUMJOBS], waitsems[NUMJOBS];
pid_t pids[NUMJOBS];
static void basetest(void) {
unsigned i;
struct usem gosems[NUMJOBS], waitsems[NUMJOBS];
pid_t pids[NUMJOBS];
for (i=0; i<NUMJOBS; i++) {
usem_init(&gosems[i], "g", i);
usem_init(&waitsems[i], "w", i);
}
for (i = 0; i < NUMJOBS; i++) {
usem_init(&gosems[i], "g", i);
usem_init(&waitsems[i], "w", i);
}
for (i=0; i<NUMJOBS; i++) {
pids[i] = fork();
if (pids[i] < 0) {
err(1, "fork");
}
if (pids[i] == 0) {
child_with_own_fd(&gosems[i], &waitsems[i], i);
_exit(0);
}
}
baseparent(gosems, waitsems);
for (i = 0; i < NUMJOBS; i++) {
pids[i] = fork();
if (pids[i] < 0) {
err(1, "fork");
}
if (pids[i] == 0) {
child_with_own_fd(&gosems[i], &waitsems[i], i);
_exit(0);
}
}
baseparent(gosems, waitsems);
for (i=0; i<NUMJOBS; i++) {
dowait(pids[i], i);
}
for (i = 0; i < NUMJOBS; i++) {
dowait(pids[i], i);
}
for (i=0; i<NUMJOBS; i++) {
usem_cleanup(&gosems[i]);
usem_cleanup(&waitsems[i]);
}
for (i = 0; i < NUMJOBS; i++) {
usem_cleanup(&gosems[i]);
usem_cleanup(&waitsems[i]);
}
}
static
void
concparent(struct usem *gosems, struct usem *waitsems)
{
unsigned i, j;
static void concparent(struct usem *gosems, struct usem *waitsems) {
unsigned i, j;
/*
* Print this *before* forking as we frequently hang *in* fork.
*say("Shoot...\n");
*/
for (j=0; j<LOOPS; j++) {
for (i=0; i<NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
}
putchar('\n');
}
/*
* Print this *before* forking as we frequently hang *in* fork.
*say("Shoot...\n");
*/
for (j = 0; j < LOOPS; j++) {
for (i = 0; i < NUMJOBS; i++) {
V(&gosems[i]);
P(&waitsems[i]);
putchar(' ');
}
putchar('\n');
}
}
static
void
conctest(void)
{
unsigned i;
struct usem gosems[NUMJOBS], waitsems[NUMJOBS];
pid_t pids[NUMJOBS];
static void conctest(void) {
unsigned i;
struct usem gosems[NUMJOBS], waitsems[NUMJOBS];
pid_t pids[NUMJOBS];
say("Shoot...\n");
say("Shoot...\n");
for (i=0; i<NUMJOBS; i++) {
usem_init(&gosems[i], "g", i);
usem_init(&waitsems[i], "w", i);
usem_open(&gosems[i]);
usem_open(&waitsems[i]);
}
for (i = 0; i < NUMJOBS; i++) {
usem_init(&gosems[i], "g", i);
usem_init(&waitsems[i], "w", i);
usem_open(&gosems[i]);
usem_open(&waitsems[i]);
}
for (i=0; i<NUMJOBS; i++) {
pids[i] = fork();
if (pids[i] < 0) {
err(1, "fork");
}
if (pids[i] == 0) {
child_plain(&gosems[i], &waitsems[i], i);
_exit(0);
}
}
concparent(gosems, waitsems);
for (i = 0; i < NUMJOBS; i++) {
pids[i] = fork();
if (pids[i] < 0) {
err(1, "fork");
}
if (pids[i] == 0) {
child_plain(&gosems[i], &waitsems[i], i);
_exit(0);
}
}
concparent(gosems, waitsems);
for (i=0; i<NUMJOBS; i++) {
dowait(pids[i], i);
}
for (i = 0; i < NUMJOBS; i++) {
dowait(pids[i], i);
}
for (i=0; i<NUMJOBS; i++) {
usem_close(&gosems[i]);
usem_close(&waitsems[i]);
usem_cleanup(&gosems[i]);
usem_cleanup(&waitsems[i]);
}
for (i = 0; i < NUMJOBS; i++) {
usem_close(&gosems[i]);
usem_close(&waitsems[i]);
usem_cleanup(&gosems[i]);
usem_cleanup(&waitsems[i]);
}
}
////////////////////////////////////////////////////////////
// concurrent use test
int
main(void)
{
basetest();
conctest();
say("Passed.\n");
return 0;
int main(void) {
basetest();
conctest();
say("Passed.\n");
return 0;
}

Some files were not shown because too many files have changed in this diff Show More