Compare commits

...

No commits in common. "a5e4d1920066b074918662d75f2455e33051c215" and "1c7aa6edda81e2a2138a69f2b7880a2c83b5a14a" have entirely different histories.

286 changed files with 3142 additions and 13982 deletions

13
.gitignore vendored
View File

@ -1,14 +1,3 @@
/.depend kern/compile/
/.settings
/.project
/.cproject
/.root
/kern/compile/
/defs.mk
build
/userland/testbin/randcall/calls.c
/root/
*.swo
*.swp
build/* build/*
**/build **/build

View File

@ -46,6 +46,7 @@ tools:
build: build:
(cd userland && $(MAKE) build) (cd userland && $(MAKE) build)
(cd man && $(MAKE) install-staging) (cd man && $(MAKE) install-staging)
(cd testscripts && $(MAKE) build)
includes tags depend: includes tags depend:
(cd kern && $(MAKE) $@) (cd kern && $(MAKE) $@)

View File

@ -128,4 +128,3 @@ I would put the machine dependent stuffs in `kern/arch` and everything else outs
The function `splx()` and `splhigh()` is used to enable and restore interrupts The function `splx()` and `splhigh()` is used to enable and restore interrupts
This would not be sufficient to ensure mutual exclusion as we still need spinlocks. This would not be sufficient to ensure mutual exclusion as we still need spinlocks.

View File

@ -1,46 +0,0 @@
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <kern/secret.h>
#ifdef HOST
#include "hostcompat.h"
#endif
/* printf variant that is quiet during automated testing */
int
tprintf(const char *fmt, ...)
{
int chars;
va_list ap;
#ifdef SECRET_TESTING
return 0;
#endif
va_start(ap, fmt);
chars = vprintf(fmt, ap);
va_end(ap);
return chars;
}
/* printf variant that is loud during automated testing */
int
nprintf(const char *fmt, ...)
{
int chars;
va_list ap;
#ifndef SECRET_TESTING
return 0;
#endif
va_start(ap, fmt);
chars = vprintf(fmt, ap);
va_end(ap);
return chars;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,206 +0,0 @@
// Beware, this code is shared between the kernel and userspace.
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#include <kern/errno.h>
#else
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#endif
#include <kern/secure.h>
#include "sha256.h"
// The full length (with null) of the hex string of a byte array
#define HEXLEN(a) 2*a+1
#define SHA256_BLOCK_SIZE 64
#define SHA256_OUTPUT_SIZE 32
// Keep this divisible by 4, or else change make_salt()
#define SALT_BYTES 8
// inner and outer padding for HMAC.
static const unsigned char ipad[SHA256_BLOCK_SIZE] = { [0 ... SHA256_BLOCK_SIZE-1] = 0x36 };
static const unsigned char opad[SHA256_BLOCK_SIZE] = { [0 ... SHA256_BLOCK_SIZE-1] = 0x5c };
// Hack for not having a userspace malloc until ASST3. We 'allocate' these statuc buffers.
// This works because the process single-threaded.
#define NUM_BUFFERS 4
#define BUFFER_LEN 1024
static char temp_buffers[NUM_BUFFERS][BUFFER_LEN];
static int buf_num = 0;
#ifndef _KERNEL
static int did_random = 0;
#define NSEC_PER_MSEC 1000000ULL
#define MSEC_PER_SEC 1000ULL
#endif
// Both userspace and the kernel are using the temp buffers now.
static void * _alloc(size_t size)
{
(void)size;
void *ptr = temp_buffers[buf_num];
buf_num++;
buf_num = buf_num % NUM_BUFFERS;
return ptr;
}
static void _free(void *ptr)
{
(void)ptr;
}
/*
* hamc_sha256 follows FIPS 198-1 HMAC using sha256.
* See http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf for details.
* NOTE: This is only thread-safe if called from within secprintf()!!!
*/
static int hmac_sha256(const char *msg, size_t msg_len, const char *key, size_t key_len,
unsigned char output[SHA256_OUTPUT_SIZE])
{
// We use a total of 320 bytes of array data on the stack
unsigned char k0[SHA256_BLOCK_SIZE];
// Steps 1-3. Anything less than 64 bytes gets 0s appended.
memset(k0, 0, SHA256_BLOCK_SIZE);
if (key_len <= SHA256_BLOCK_SIZE) {
memcpy(k0, key, key_len);
} else {
mbedtls_sha256((unsigned char *)key, key_len, k0, 0);
}
// Steps 4 and 7.
unsigned char k_ipad[SHA256_BLOCK_SIZE];
unsigned char k_opad[SHA256_BLOCK_SIZE];
int i;
for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
k_ipad[i] = k0[i] ^ ipad[i];
k_opad[i] = k0[i] ^ opad[i];
}
// Step 5 (K0 xor ipad) || msg
// We have no idea how big the message is so we allocate this on the heap.
unsigned char *data = (unsigned char *)_alloc(msg_len + SHA256_BLOCK_SIZE);
if (!data)
return ENOMEM;
memcpy(data, k_ipad, SHA256_BLOCK_SIZE);
memcpy(data+SHA256_BLOCK_SIZE, msg, msg_len);
// Step6: H((k0 xor ipad) || msg)
unsigned char h1[SHA256_OUTPUT_SIZE];
mbedtls_sha256(data, msg_len + SHA256_BLOCK_SIZE, h1, 0);
_free(data);
// Step 8: (k0 xor opad) || H((k0 xor ipad) || msg)
unsigned char inner[SHA256_OUTPUT_SIZE + SHA256_BLOCK_SIZE];
memcpy(inner, k_opad, SHA256_BLOCK_SIZE);
memcpy(inner + SHA256_BLOCK_SIZE, h1, SHA256_OUTPUT_SIZE);
// Step 9: Finally, H((k0 xor opad) || H((k0 xor ipad) || msg))
mbedtls_sha256(inner, SHA256_OUTPUT_SIZE + SHA256_BLOCK_SIZE, output, 0);
return 0;
}
static inline char to_hex(int n)
{
return n < 10 ? '0'+n : 'a' + (n-10);
}
static void array_to_hex(unsigned char *a, size_t len, char *res)
{
size_t i, j;
j = 0;
for (i = 0; i < len; i++) {
res[j++] = to_hex(a[i] >> 4);
res[j++] = to_hex(a[i] & 0xF);
}
res[j] = '\0';
}
static void make_salt(char *salt_str)
{
#ifndef _KERNEL
if (!did_random) {
did_random = 1;
time_t sec;
unsigned long ns;
unsigned long long ms;
__time(&sec, &ns);
ms = (unsigned long long)sec * MSEC_PER_SEC;
ms += (ns / NSEC_PER_MSEC);
srandom((unsigned long)ms);
}
#endif
// Compute salt value
uint32_t salt[SALT_BYTES/sizeof(uint32_t)];
size_t i;
for (i = 0; i < SALT_BYTES/sizeof(uint32_t); i++)
{
salt[i] = random();
}
// Convert to hex string
array_to_hex((unsigned char *)salt, SALT_BYTES, salt_str);
}
int hmac(const char *msg, size_t msg_len, const char *key, size_t key_len,
char **hash_str)
{
*hash_str = _alloc(HEXLEN(SHA256_OUTPUT_SIZE));
if (!(*hash_str))
return ENOMEM;
// Hash it
unsigned char hash[SHA256_OUTPUT_SIZE];
int res = hmac_sha256(msg, msg_len, key, key_len, hash);
if (res)
return res;
// Convert to hex string
array_to_hex(hash, SHA256_OUTPUT_SIZE, *hash_str);
return 0;
}
// NOTE: This is only thread-safe if called from within secprintf()!!!
int hmac_salted(const char *msg, size_t msg_len, const char *key, size_t key_len,
char **hash_str, char **salt_str)
{
*salt_str = _alloc(HEXLEN(SALT_BYTES));
if (!(*salt_str))
return ENOMEM;
// Create the salt value
make_salt(*salt_str);
// Concatenate the key and salt, with the resulting string being null-terminated
size_t key2_len = key_len + HEXLEN(SALT_BYTES)-1;
char *key2 = (char *)_alloc(key2_len+1);
if (!key2)
return ENOMEM;
strcpy(key2, key);
strcpy(key2+key_len, *salt_str);
key2[key2_len] = '\0';
// Hash it
return hmac(msg, msg_len, key2, key2_len, hash_str);
}

View File

@ -1,451 +0,0 @@
/*
* FIPS-180-2 compliant SHA-256 implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA256_C)
#include "sha256.h"
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <types/size_t.h>
#include <string.h>
#endif // _KERNEL
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_SHA256_ALT)
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
*dst = *src;
}
/*
* SHA-256 context setup
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
if( is224 == 0 )
{
/* SHA-256 */
ctx->state[0] = 0x6A09E667;
ctx->state[1] = 0xBB67AE85;
ctx->state[2] = 0x3C6EF372;
ctx->state[3] = 0xA54FF53A;
ctx->state[4] = 0x510E527F;
ctx->state[5] = 0x9B05688C;
ctx->state[6] = 0x1F83D9AB;
ctx->state[7] = 0x5BE0CD19;
}
else
{
/* SHA-224 */
ctx->state[0] = 0xC1059ED8;
ctx->state[1] = 0x367CD507;
ctx->state[2] = 0x3070DD17;
ctx->state[3] = 0xF70E5939;
ctx->state[4] = 0xFFC00B31;
ctx->state[5] = 0x68581511;
ctx->state[6] = 0x64F98FA7;
ctx->state[7] = 0xBEFA4FA4;
}
ctx->is224 = is224;
}
#if !defined(MBEDTLS_SHA256_PROCESS_ALT)
static const uint32_t K[] =
{
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
};
#define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
#define F0(x,y,z) ((x & y) | (z & (x | y)))
#define F1(x,y,z) (z ^ (x & (y ^ z)))
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
}
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
{
uint32_t temp1, temp2, W[64];
uint32_t A[8];
unsigned int i;
for( i = 0; i < 8; i++ )
A[i] = ctx->state[i];
#if defined(MBEDTLS_SHA256_SMALLER)
for( i = 0; i < 64; i++ )
{
if( i < 16 )
GET_UINT32_BE( W[i], data, 4 * i );
else
R( i );
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
}
#else /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 16; i++ )
GET_UINT32_BE( W[i], data, 4 * i );
for( i = 0; i < 16; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] );
}
for( i = 16; i < 64; i += 8 )
{
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] );
}
#endif /* MBEDTLS_SHA256_SMALLER */
for( i = 0; i < 8; i++ )
ctx->state[i] += A[i];
}
#endif /* !MBEDTLS_SHA256_PROCESS_ALT */
/*
* SHA-256 process buffer
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen )
{
size_t fill;
uint32_t left;
if( ilen == 0 )
return;
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++;
if( left && ilen >= fill )
{
memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_sha256_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
mbedtls_sha256_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
static const unsigned char sha256_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] )
{
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_sha256_update( ctx, sha256_padding, padn );
mbedtls_sha256_update( ctx, msglen, 8 );
PUT_UINT32_BE( ctx->state[0], output, 0 );
PUT_UINT32_BE( ctx->state[1], output, 4 );
PUT_UINT32_BE( ctx->state[2], output, 8 );
PUT_UINT32_BE( ctx->state[3], output, 12 );
PUT_UINT32_BE( ctx->state[4], output, 16 );
PUT_UINT32_BE( ctx->state[5], output, 20 );
PUT_UINT32_BE( ctx->state[6], output, 24 );
if( ctx->is224 == 0 )
PUT_UINT32_BE( ctx->state[7], output, 28 );
}
#endif /* !MBEDTLS_SHA256_ALT */
/*
* output = SHA-256( input buffer )
*/
void mbedtls_sha256( const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 )
{
mbedtls_sha256_context ctx;
mbedtls_sha256_init( &ctx );
mbedtls_sha256_starts( &ctx, is224 );
mbedtls_sha256_update( &ctx, input, ilen );
mbedtls_sha256_finish( &ctx, output );
mbedtls_sha256_free( &ctx );
}
#if defined(MBEDTLS_SELF_TEST)
/*
* FIPS-180-2 test vectors
*/
static const unsigned char sha256_test_buf[3][57] =
{
{ "abc" },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ "" }
};
static const int sha256_test_buflen[3] =
{
3, 56, 1000
};
static const unsigned char sha256_test_sum[6][32] =
{
/*
* SHA-224 test vectors
*/
{ 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
0xE3, 0x6C, 0x9D, 0xA7 },
{ 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
0x52, 0x52, 0x25, 0x25 },
{ 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
0x4E, 0xE7, 0xAD, 0x67 },
/*
* SHA-256 test vectors
*/
{ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
{ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
{ 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
};
/*
* Checkup routine
*/
int mbedtls_sha256_self_test( int verbose )
{
int i, j, k, buflen, ret = 0;
unsigned char buf[1024];
unsigned char sha256sum[32];
mbedtls_sha256_context ctx;
mbedtls_sha256_init( &ctx );
for( i = 0; i < 6; i++ )
{
j = i % 3;
k = i < 3;
if( verbose != 0 )
mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 );
mbedtls_sha256_starts( &ctx, k );
if( j == 2 )
{
memset( buf, 'a', buflen = 1000 );
for( j = 0; j < 1000; j++ )
mbedtls_sha256_update( &ctx, buf, buflen );
}
else
mbedtls_sha256_update( &ctx, sha256_test_buf[j],
sha256_test_buflen[j] );
mbedtls_sha256_finish( &ctx, sha256sum );
if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto exit;
}
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
if( verbose != 0 )
mbedtls_printf( "\n" );
exit:
mbedtls_sha256_free( &ctx );
return( ret );
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_SHA256_C */

View File

@ -1,146 +0,0 @@
/**
* \file sha256.h
*
* \brief SHA-224 and SHA-256 cryptographic hash function
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_SHA256_H
#define MBEDTLS_SHA256_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <types/size_t.h>
#include <stdint.h>
#endif //_KERNEL
#if !defined(MBEDTLS_SHA256_ALT)
// Regular implementation
//
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief SHA-256 context structure
*/
typedef struct
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int is224; /*!< 0 => SHA-256, else SHA-224 */
}
mbedtls_sha256_context;
/**
* \brief Initialize SHA-256 context
*
* \param ctx SHA-256 context to be initialized
*/
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
/**
* \brief Clear SHA-256 context
*
* \param ctx SHA-256 context to be cleared
*/
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
/**
* \brief Clone (the state of) a SHA-256 context
*
* \param dst The destination context
* \param src The context to be cloned
*/
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src );
/**
* \brief SHA-256 context setup
*
* \param ctx context to be initialized
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
/**
* \brief SHA-256 process buffer
*
* \param ctx SHA-256 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen );
/**
* \brief SHA-256 final digest
*
* \param ctx SHA-256 context
* \param output SHA-224/256 checksum result
*/
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] );
/* Internal use */
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
#ifdef __cplusplus
}
#endif
#else /* MBEDTLS_SHA256_ALT */
#include "sha256_alt.h"
#endif /* MBEDTLS_SHA256_ALT */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Output = SHA-256( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output SHA-224/256 checksum result
* \param is224 0 = use SHA256, 1 = use SHA224
*/
void mbedtls_sha256( const unsigned char *input, size_t ilen,
unsigned char output[32], int is224 );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mbedtls_sha256_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* mbedtls_sha256.h */

View File

@ -1,188 +0,0 @@
// Beware, this code is shared between the kernel and userspace.
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#include <synch.h>
#include <kern/errno.h>
#include <kern/secure.h>
#include <kern/test161.h>
#else
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <test161/test161.h>
#include <test161/secure.h>
#endif
// Hack for allocating userspace memory without malloc, and for
// allowing secprintf in kmalloc when we're out of memory.
#define BUFFER_SIZE 1024
static char temp_buffer[BUFFER_SIZE];
#ifndef _KERNEL
static char write_buffer[BUFFER_SIZE];
#endif
#ifdef _KERNEL
// secprintf needs to be synchronized in the kernel because multiple threads
// may be trying to secprintf at the same time.
static struct semaphore *test161_sem;
#endif
// For now, allocating just passes a reference to our static temp buffer, and
// free does nothing.
static inline void * _alloc()
{
return temp_buffer;
}
static inline void _free(void *ptr)
{
(void)ptr;
}
/*
* Common success function for kernel tests. If SECRET_TESTING is defined,
* ksecprintf will compute the hmac/sha256 hash of any message using the
* shared secret and a random salt value. The (secure) server also knows
* the secret and can verify the message was generated by a trusted source.
* The salt value prevents against replay attacks.
*/
int
success(int status, const char * secret, const char * name) {
if (status == TEST161_SUCCESS) {
return secprintf(secret, "SUCCESS", name);
} else {
return secprintf(secret, "FAIL", name);
}
}
int
partial_credit(const char *secret, const char *name, int scored, int total)
{
char buffer[128];
snprintf(buffer, 128, "PARTIAL CREDIT %d OF %d", scored, total);
return secprintf(secret, buffer, name);
}
#ifndef _KERNEL
// Borrowed from parallelvm. We need atomic console writes so our
// output doesn't get intermingled since test161 works with lines.
static
int
say(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(write_buffer, BUFFER_SIZE, fmt, ap);
va_end(ap);
return write(STDOUT_FILENO, write_buffer, strlen(write_buffer));
}
#endif
#ifndef SECRET_TESTING
int
snsecprintf(size_t len, char *buffer, const char *secret, const char *msg, const char *name)
{
(void)secret;
return snprintf(buffer, len, "%s: %s", name, msg);
}
int
secprintf(const char * secret, const char * msg, const char * name)
{
(void)secret;
#ifdef _KERNEL
return kprintf("\n%s: %s\n", name, msg);
#else
return say("\n%s: %s\n", name, msg);
#endif
}
#else
static int
secprintf_common(int use_buf, size_t b_len, char *buffer,
const char *secret, const char *msg, const char *name)
{
char *hash, *salt, *fullmsg;
int res;
size_t len;
#ifdef _KERNEL
if (test161_sem == NULL) {
panic("test161_sem is NULL. Your kernel is missing test161_bootstrap.");
}
P(test161_sem);
#endif
hash = salt = fullmsg = NULL;
// test161 expects "name: msg"
len = strlen(name) + strlen(msg) + 3; // +3 for " :" and null terminator
fullmsg = (char *)_alloc(len);
if (fullmsg == NULL) {
res = -ENOMEM;
goto out;
}
snprintf(fullmsg, len, "%s: %s", name, msg);
res = hmac_salted(fullmsg, len-1, secret, strlen(secret), &hash, &salt);
if (res) {
res = -res;
goto out;
}
if (!use_buf) {
#ifdef _KERNEL
res = kprintf("\n(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg);
#else
res = say("\n(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg);
#endif
} else {
res = snprintf(buffer, b_len, "\n(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg);
}
out:
// These may be NULL, but that's OK
_free(hash);
_free(salt);
_free(fullmsg);
#ifdef _KERNEL
V(test161_sem);
#endif
return res;
}
int
snsecprintf(size_t b_len, char *buffer, const char *secret, const char *msg, const char *name)
{
return secprintf_common(1, b_len, buffer, secret, msg, name);
}
int
secprintf(const char * secret, const char * msg, const char * name)
{
return secprintf_common(0, 0, NULL, secret, msg, name);
}
#endif
#ifdef _KERNEL
void test161_bootstrap()
{
test161_sem = sem_create("test161", 1);
if (test161_sem == NULL) {
panic("Failed to create test161 secprintf semaphore");
}
}
#endif

28
configure vendored
View File

@ -29,6 +29,9 @@ DEBUG='-O2'
# when make runs rather than when this script runs. # when make runs rather than when this script runs.
OSTREE='$(HOME)/os161/root' OSTREE='$(HOME)/os161/root'
# By default don't explicitly configure a Python interpreter.
PYTHON_INTERPRETER=
# Assume this # Assume this
HOST_CC=gcc HOST_CC=gcc
@ -134,6 +137,28 @@ else
HOST_CFLAGS="${HOST_CFLAGS} -DDECLARE_NTOHLL" HOST_CFLAGS="${HOST_CFLAGS} -DDECLARE_NTOHLL"
fi fi
# Look for a Python interpreter.
PYTHON=
for PYNAME in \
python python2.7 \
/usr/local/bin/python /usr/local/bin/python2.7 \
/usr/pkg/bin/python /usr/pkg/bin/python2.7 \
/opt/bin/python /opt/bin/python2.7 \
; do
PYVERSION=`($PYNAME -V) 2>&1 || echo none`
case "$PYVERSION" in
Python\ 2.*|Python\ 3.*) PYTHON=$PYNAME;;
none) ;;
*) ;; # ?
esac
done
case "$PYTHON" in
python) ;;
/*) PYTHON_INTERPRETER="$PYTHON";;
*) PYTHON_INTERPRETER="/usr/bin/env $PYTHON";;
esac
#################### ####################
# Now generate defs.mk. # Now generate defs.mk.
@ -167,5 +192,8 @@ EOF
if [ "x$HOST_CFLAGS" != x ]; then if [ "x$HOST_CFLAGS" != x ]; then
echo "HOST_CFLAGS+=$HOST_CFLAGS" echo "HOST_CFLAGS+=$HOST_CFLAGS"
fi fi
if [ "x$PYTHON_INTERPRETER" != x ]; then
echo "PYTHON_INTERPRETER=$PYTHON_INTERPRETER"
fi
) > defs.mk ) > defs.mk

22
defs.mk Normal file
View File

@ -0,0 +1,22 @@
# This file was generated by configure. Edits will disappear if you rerun
# configure. If you find that you need to edit this file to make things
# work, let the course staff know and we'll try to fix the configure script.
#
# The purpose of this file is to hold all the makefile definitions
# needed to adjust the OS/161 build process to any particular
# environment. If I've done it right, all you need to do is rerun the
# configure script and make clean if you start working on a different
# host OS. If I've done it mostly right, you may need to edit this
# file but you still hopefully won't need to edit any of the
# makefiles.
#
# The things that can be set here are documented in mk/os161.config.mk.
#
OSTREE=/root/os161/root
PLATFORM=sys161
MACHINE=mips
COMPAT_CFLAGS= -DNEED_NTOHLL
COMPAT_TARGETS=
HOST_CFLAGS+= -DDECLARE_NTOHLL
PYTHON_INTERPRETER=/usr/bin/env

View File

@ -126,15 +126,6 @@ free_kpages(vaddr_t addr)
(void)addr; (void)addr;
} }
unsigned
int
coremap_used_bytes() {
/* dumbvm doesn't track page allocations. Return 0 so that khu works. */
return 0;
}
void void
vm_tlbshootdown(const struct tlbshootdown *ts) vm_tlbshootdown(const struct tlbshootdown *ts)
{ {

View File

@ -1,33 +0,0 @@
# Kernel config file using dumbvm.
# This should be used until you have your own VM system.
include conf/conf.kern # get definitions of available options
debug # Compile with debug info.
#
# Device drivers for hardware.
#
device lamebus0 # System/161 main bus
device emu* at lamebus* # Emulator passthrough filesystem
device ltrace* at lamebus* # trace161 trace control device
device ltimer* at lamebus* # Timer device
device lrandom* at lamebus* # Random device
device lhd* at lamebus* # Disk device
device lser* at lamebus* # Serial port
#device lscreen* at lamebus* # Text screen (not supported yet)
#device lnet* at lamebus* # Network interface (not supported yet)
device beep0 at ltimer* # Abstract beep handler device
device con0 at lser* # Abstract console on serial port
#device con0 at lscreen* # Abstract console on screen (not supported)
device rtclock0 at ltimer* # Abstract realtime clock
device random0 at lrandom* # Abstract randomness device
#options net # Network stack (not supported)
options semfs # Semaphores for userland
options sfs # Always use the file system
#options netfs # You might write this as a project.
options dumbvm # Chewing gum and baling wire.
options synchprobs # Uncomment to enable ASST1 synchronization problems

View File

@ -1,33 +0,0 @@
# Kernel config file using dumbvm.
# This should be used until you have your own VM system.
include conf/conf.kern # get definitions of available options
debug # Compile with debug info.
#
# Device drivers for hardware.
#
device lamebus0 # System/161 main bus
device emu* at lamebus* # Emulator passthrough filesystem
device ltrace* at lamebus* # trace161 trace control device
device ltimer* at lamebus* # Timer device
device lrandom* at lamebus* # Random device
device lhd* at lamebus* # Disk device
device lser* at lamebus* # Serial port
#device lscreen* at lamebus* # Text screen (not supported yet)
#device lnet* at lamebus* # Network interface (not supported yet)
device beep0 at ltimer* # Abstract beep handler device
device con0 at lser* # Abstract console on serial port
#device con0 at lscreen* # Abstract console on screen (not supported)
device rtclock0 at ltimer* # Abstract realtime clock
device random0 at lrandom* # Abstract randomness device
#options net # Network stack (not supported)
options semfs # Semaphores for userland
options sfs # Always use the file system
#options netfs # You might write this as a project.
options dumbvm # Chewing gum and baling wire.
#options synchprobs # Uncomment to enable ASST1 synchronization problems

View File

@ -1,33 +0,0 @@
# Kernel config file for an ordinary, generic kernel.
# This config file should be used once you start working on
# your own VM system.
include conf/conf.kern # get definitions of available options
debug # Compile with debug info.
#
# Device drivers for hardware.
#
device lamebus0 # System/161 main bus
device emu* at lamebus* # Emulator passthrough filesystem
device ltrace* at lamebus* # trace161 trace control device
device ltimer* at lamebus* # Timer device
device lrandom* at lamebus* # Random device
device lhd* at lamebus* # Disk device
device lser* at lamebus* # Serial port
#device lscreen* at lamebus* # Text screen (not supported yet)
#device lnet* at lamebus* # Network interface (not supported yet)
device beep0 at ltimer* # Abstract beep handler device
device con0 at lser* # Abstract console on serial port
#device con0 at lscreen* # Abstract console on screen (not supported)
device rtclock0 at ltimer* # Abstract realtime clock
device random0 at lrandom* # Abstract randomness device
#options net # Network stack (not supported)
options semfs # Semaphores for userland
options sfs # Always use the file system
#options netfs # You might write this as a project.
#options dumbvm # Use your own VM system now.

View File

@ -32,4 +32,4 @@ options sfs # Always use the file system
#options netfs # You might write this as a project. #options netfs # You might write this as a project.
options dumbvm # Chewing gum and baling wire. options dumbvm # Chewing gum and baling wire.
options synchprobs # Uncomment to enable ASST1 synchronization problems options synchprobs

View File

@ -309,14 +309,6 @@ file ../common/libc/string/strlen.c
file ../common/libc/string/strrchr.c file ../common/libc/string/strrchr.c
file ../common/libc/string/strtok_r.c file ../common/libc/string/strtok_r.c
#
# libtest161 shared code and security functions
#
file ../common/libtest161/test161.c
file ../common/libtest161/secure.c
file ../common/libtest161/sha256.c
######################################## ########################################
# # # #
# Core kernel source files # # Core kernel source files #
@ -445,19 +437,12 @@ file test/threadlisttest.c
file test/threadtest.c file test/threadtest.c
file test/tt3.c file test/tt3.c
file test/synchtest.c file test/synchtest.c
file test/rwtest.c
file test/semunit.c file test/semunit.c
file test/hmacunit.c
file test/kmalloctest.c file test/kmalloctest.c
file test/fstest.c file test/fstest.c
file test/lib.c
optfile net test/nettest.c optfile net test/nettest.c
defoption synchprobs defoption synchprobs
optfile synchprobs synchprobs/whalemating.c optfile synchprobs synchprobs/whalemating.c
optfile synchprobs synchprobs/stoplight.c optfile synchprobs synchprobs/stoplight.c
optfile synchprobs test/synchprobs.c optfile synchprobs test/synchprobs.c
defoption automationtest
optfile automationtest test/automationtest.c

View File

@ -208,7 +208,7 @@ echo "$CONFNAME" $CONFTMP | awk '
# #
if [ ! -d "$COMPILEDIR" ]; then if [ ! -d "$COMPILEDIR" ]; then
mkdir -p $COMPILEDIR mkdir $COMPILEDIR
fi fi
echo -n 'Generating files...' echo -n 'Generating files...'

View File

@ -35,7 +35,6 @@
#include <threadlist.h> #include <threadlist.h>
#include <machine/vm.h> /* for TLBSHOOTDOWN_MAX */ #include <machine/vm.h> /* for TLBSHOOTDOWN_MAX */
extern unsigned num_cpus;
/* /*
* Per-cpu structure * Per-cpu structure

View File

@ -1,50 +0,0 @@
/*
* NO NOT MODIFY THIS FILE
*
* All the contents of this file are overwritten during automated
* testing. Please consider this before changing anything in this file.
*/
/*
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _SECRET_H_
#define _SECRET_H_
/*
* During automated testing all instances of KERNEL_SECRET in trusted tests
* are rewritten to a random value to ensure that the kernel is actually
* running the appropriate tests. So this value is never actually used, but
* allows normally compilation and operation.
*/
#undef SECRET_TESTING
#define SECRET "SECRET"
#endif /* _SECRET_H_ */

View File

@ -1,18 +0,0 @@
#ifndef _KERN_SECURE_H_
#define _KERN_SECURE_H_
/*
* Compute the FIPS 198-1 complient HMAC of msg using SHA256.
*
* hmac_with_salt uses a salted key and sets salt_str to this value (in hex).
* Both functions below create hash_str with the hex readable version of the hash.
*
* Callers need to free hash_str (and salt_str) when done.
*/
int hmac(const char *msg, size_t msg_len, const char *key, size_t key_len,
char **hash_str);
int hmac_salted(const char *msg, size_t msg_len, const char *key, size_t key_len,
char **hash_str, char **salt_str);
#endif //_KERN_SECURE_H_

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _KERN_TEST161_H_
#define _KERN_TEST161_H_
#define TEST161_SUCCESS 0
#define TEST161_FAIL 1
#include <kern/secret.h>
#ifdef _KERNEL
#define __TEST161_PROGRESS_N(iter, mod) do { \
if (((iter) % mod) == 0) { \
kprintf("."); \
} \
} while (0)
#else
#include <stdio.h>
#define __TEST161_PROGRESS_N(iter, mod) do { \
if (((iter) % mod) == 0) { \
printf("."); \
} \
} while (0)
#endif
// Always loud
#define TEST161_LPROGRESS_N(iter, mod) __TEST161_PROGRESS_N(iter, mod)
#define TEST161_LPROGRESS(iter) __TEST161_PROGRESS_N(iter, 100)
// Depends on whether or not it's automated testing. Some tests are
// quite verbose with useful information so these should just stay quiet.
#ifdef SECRET_TESTING
#define TEST161_TPROGRESS_N(iter, mod) __TEST161_PROGRESS_N(iter, mod)
#define TEST161_TPROGRESS(iter) __TEST161_PROGRESS_N(iter, 100)
#else
#define TEST161_TPROGRESS_N(iter, mod)
#define TEST161_TPROGRESS(iter)
#endif
int success(int, const char *, const char *);
int secprintf(const char *secret, const char *msg, const char *name);
int snsecprintf(size_t len, char *buffer, const char *secret, const char *msg, const char *name);
int partial_credit(const char *secret, const char *name, int scored, int total);
#ifdef _KERNEL
void test161_bootstrap(void);
#endif
#endif /* _KERN_TEST161_H_ */

View File

@ -129,8 +129,6 @@ uint32_t random(void);
void *kmalloc(size_t size); void *kmalloc(size_t size);
void kfree(void *ptr); void kfree(void *ptr);
void kheap_printstats(void); void kheap_printstats(void);
void kheap_printused(void);
unsigned long kheap_getused(void);
void kheap_nextgeneration(void); void kheap_nextgeneration(void);
void kheap_dump(void); void kheap_dump(void);
void kheap_dumpall(void); void kheap_dumpall(void);

View File

@ -1,47 +0,0 @@
/*
* NO NOT MODIFY THIS FILE
*
* All the contents of this file are overwritten during automated
* testing. Please consider this before changing anything in this file.
*/
/*
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _PROMPT_H_
#define _PROMPT_H_
/*
* You can set a custom prompt here, but the default will be used during
* testing.
*/
#define KERNEL_PROMPT "OS/161 kernel [? for menu]: "
#endif /* _PROMPT_H_ */

View File

@ -74,8 +74,8 @@ int splx(int);
/* /*
* Integer interrupt priority levels. * Integer interrupt priority levels.
*/ */
#define IPL_NONE 0 #define IPL_NONE 0
#define IPL_HIGH 1 #define IPL_HIGH 1
/* /*
* Lower-level functions for explicitly raising and lowering * Lower-level functions for explicitly raising and lowering
@ -92,18 +92,9 @@ void spllower(int oldipl, int newipl);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SPL_INLINE SPL_INLINE
int int spl0(void) { return splx(IPL_NONE); }
spl0(void)
{
return splx(IPL_NONE);
}
SPL_INLINE SPL_INLINE
int int splhigh(void) { return splx(IPL_HIGH); }
splhigh(void)
{
return splx(IPL_HIGH);
}
#endif /* _SPL_H_ */ #endif /* _SPL_H_ */

View File

@ -34,7 +34,6 @@
* Header file for synchronization primitives. * Header file for synchronization primitives.
*/ */
#include <spinlock.h> #include <spinlock.h>
/* /*
@ -44,10 +43,10 @@
* internally. * internally.
*/ */
struct semaphore { struct semaphore {
char *sem_name; char *sem_name;
struct wchan *sem_wchan; struct wchan *sem_wchan;
struct spinlock sem_lock; struct spinlock sem_lock;
volatile unsigned sem_count; volatile unsigned sem_count;
}; };
struct semaphore *sem_create(const char *name, unsigned initial_count); struct semaphore *sem_create(const char *name, unsigned initial_count);
@ -62,7 +61,6 @@ void sem_destroy(struct semaphore *);
void P(struct semaphore *); void P(struct semaphore *);
void V(struct semaphore *); void V(struct semaphore *);
/* /*
* Simple lock for mutual exclusion. * Simple lock for mutual exclusion.
* *
@ -73,10 +71,10 @@ void V(struct semaphore *);
* (should be) made internally. * (should be) made internally.
*/ */
struct lock { struct lock {
char *lk_name; char *lk_name;
HANGMAN_LOCKABLE(lk_hangman); /* Deadlock detector hook. */ HANGMAN_LOCKABLE(lk_hangman); /* Deadlock detector hook. */
// add what you need here // add what you need here
// (don't forget to mark things volatile as needed) // (don't forget to mark things volatile as needed)
}; };
struct lock *lock_create(const char *name); struct lock *lock_create(const char *name);
@ -97,7 +95,6 @@ void lock_acquire(struct lock *);
void lock_release(struct lock *); void lock_release(struct lock *);
bool lock_do_i_hold(struct lock *); bool lock_do_i_hold(struct lock *);
/* /*
* Condition variable. * Condition variable.
* *
@ -113,9 +110,9 @@ bool lock_do_i_hold(struct lock *);
*/ */
struct cv { struct cv {
char *cv_name; char *cv_name;
// add what you need here // add what you need here
// (don't forget to mark things volatile as needed) // (don't forget to mark things volatile as needed)
}; };
struct cv *cv_create(const char *name); struct cv *cv_create(const char *name);
@ -138,40 +135,4 @@ void cv_wait(struct cv *cv, struct lock *lock);
void cv_signal(struct cv *cv, struct lock *lock); void cv_signal(struct cv *cv, struct lock *lock);
void cv_broadcast(struct cv *cv, struct lock *lock); void cv_broadcast(struct cv *cv, struct lock *lock);
/*
* Reader-writer locks.
*
* When the lock is created, no thread should be holding it. Likewise,
* when the lock is destroyed, no thread should be holding it.
*
* The name field is for easier debugging. A copy of the name is
* (should be) made internally.
*/
struct rwlock {
char *rwlock_name;
// add what you need here
// (don't forget to mark things volatile as needed)
};
struct rwlock * rwlock_create(const char *);
void rwlock_destroy(struct rwlock *);
/*
* Operations:
* rwlock_acquire_read - Get the lock for reading. Multiple threads can
* hold the lock for reading at the same time.
* rwlock_release_read - Free the lock.
* rwlock_acquire_write - Get the lock for writing. Only one thread can
* hold the write lock at one time.
* rwlock_release_write - Free the write lock.
*
* These operations must be atomic. You get to write them.
*/
void rwlock_acquire_read(struct rwlock *);
void rwlock_release_read(struct rwlock *);
void rwlock_acquire_write(struct rwlock *);
void rwlock_release_write(struct rwlock *);
#endif /* _SYNCH_H_ */ #endif /* _SYNCH_H_ */

View File

@ -30,13 +30,6 @@
#ifndef _TEST_H_ #ifndef _TEST_H_
#define _TEST_H_ #define _TEST_H_
/* Get __PF() for declaring printf-like functions. */
#include <cdefs.h>
#include <kern/secret.h>
#include "opt-synchprobs.h"
#include "opt-automationtest.h"
/* /*
* Declarations for test code and other miscellaneous high-level * Declarations for test code and other miscellaneous high-level
* functions. * functions.
@ -59,20 +52,8 @@ int threadtest2(int, char **);
int threadtest3(int, char **); int threadtest3(int, char **);
int semtest(int, char **); int semtest(int, char **);
int locktest(int, char **); int locktest(int, char **);
int locktest2(int, char **);
int locktest3(int, char **);
int locktest4(int, char **);
int locktest5(int, char **);
int cvtest(int, char **); int cvtest(int, char **);
int cvtest2(int, char **); int cvtest2(int, char **);
int cvtest3(int, char **);
int cvtest4(int, char **);
int cvtest5(int, char **);
int rwtest(int, char **);
int rwtest2(int, char **);
int rwtest3(int, char **);
int rwtest4(int, char **);
int rwtest5(int, char **);
/* semaphore unit tests */ /* semaphore unit tests */
int semu1(int, char **); int semu1(int, char **);
@ -107,15 +88,11 @@ int longstress(int, char **);
int createstress(int, char **); int createstress(int, char **);
int printfile(int, char **); int printfile(int, char **);
/* HMAC/hash tests */
int hmacu1(int, char**);
/* other tests */ /* other tests */
int kmalloctest(int, char **); int kmalloctest(int, char **);
int kmallocstress(int, char **); int kmallocstress(int, char **);
int kmalloctest3(int, char **); int kmalloctest3(int, char **);
int kmalloctest4(int, char **); int kmalloctest4(int, char **);
int kmalloctest5(int, char **);
int nettest(int, char **); int nettest(int, char **);
/* Routine for running a user-level program. */ /* Routine for running a user-level program. */
@ -127,75 +104,5 @@ void menu(char *argstr);
/* The main function, called from start.S. */ /* The main function, called from start.S. */
void kmain(char *bootstring); void kmain(char *bootstring);
#if OPT_SYNCHPROBS
/*
* Synchronization driver primitives.
*/
void male_start(uint32_t);
void male_end(uint32_t);
void female_start(uint32_t);
void female_end(uint32_t);
void matchmaker_start(uint32_t);
void matchmaker_end(uint32_t);
int whalemating(int, char **);
void inQuadrant(int, uint32_t);
void leaveIntersection(uint32_t);
int stoplight(int, char **);
/*
* Synchronization problem primitives.
*/
/*
* whalemating.c.
*/
void whalemating_init(void);
void whalemating_cleanup(void);
void male(uint32_t);
void female(uint32_t);
void matchmaker(uint32_t);
/*
* stoplight.c.
*/
void gostraight(uint32_t, uint32_t);
void turnleft(uint32_t, uint32_t);
void turnright(uint32_t, uint32_t);
void stoplight_init(void);
void stoplight_cleanup(void);
#endif
/*
* Automation tests for detecting kernel deadlocks and livelocks.
*/
#if OPT_AUTOMATIONTEST
int dltest(int, char **);
int ll1test(int, char **);
int ll16test(int, char **);
#endif
void random_yielder(uint32_t);
void random_spinner(uint32_t);
/*
* kprintf variants that do not (or only) print during automated testing.
*/
#ifdef SECRET_TESTING
#define kprintf_t(...) kprintf(__VA_ARGS__)
#define kprintf_n(...) silent(__VA_ARGS__)
#else
#define kprintf_t(...) silent(__VA_ARGS__)
#define kprintf_n(...) kprintf(__VA_ARGS__)
#endif
static inline void silent(const char * fmt, ...) { (void)fmt; };
#endif /* _TEST_H_ */ #endif /* _TEST_H_ */

View File

@ -48,7 +48,6 @@ struct cpu;
/* Size of kernel stacks; must be power of 2 */ /* Size of kernel stacks; must be power of 2 */
#define STACK_SIZE 4096 #define STACK_SIZE 4096
#define MAX_NAME_LENGTH 64
/* Mask for extracting the stack base address of a kernel stack pointer */ /* Mask for extracting the stack base address of a kernel stack pointer */
#define STACK_MASK (~(vaddr_t)(STACK_SIZE-1)) #define STACK_MASK (~(vaddr_t)(STACK_SIZE-1))
@ -71,16 +70,7 @@ struct thread {
* These go up front so they're easy to get to even if the * These go up front so they're easy to get to even if the
* debugger is messed up. * debugger is messed up.
*/ */
char *t_name; /* Name of this thread */
/*
* Name of this thread. Used to be dynamically allocated using kmalloc, but
* this can cause small changes in the amount of available memory due to the
* fact that it was cleaned up in exorcise. This produces more predictable
* behavior at the cost of a small amount of memory overhead and the
* inability to give threads huge names.
*/
char t_name[MAX_NAME_LENGTH];
const char *t_wchan_name; /* Name of wait channel, if sleeping */ const char *t_wchan_name; /* Name of wait channel, if sleeping */
threadstate_t t_state; /* State this thread is in */ threadstate_t t_state; /* State this thread is in */
@ -179,7 +169,5 @@ void schedule(void);
*/ */
void thread_consider_migration(void); void thread_consider_migration(void);
extern unsigned thread_count;
void thread_wait_for_count(unsigned);
#endif /* _THREAD_H_ */ #endif /* _THREAD_H_ */

View File

@ -55,13 +55,6 @@ int vm_fault(int faulttype, vaddr_t faultaddress);
vaddr_t alloc_kpages(unsigned npages); vaddr_t alloc_kpages(unsigned npages);
void free_kpages(vaddr_t addr); void free_kpages(vaddr_t addr);
/*
* Return amount of memory (in bytes) used by allocated coremap pages. If
* there are ongoing allocations, this value could change after it is returned
* to the caller. But it should have been correct at some point in time.
*/
unsigned int coremap_used_bytes(void);
/* TLB shootdown handling called from interprocessor_interrupt */ /* TLB shootdown handling called from interprocessor_interrupt */
void vm_tlbshootdown(const struct tlbshootdown *); void vm_tlbshootdown(const struct tlbshootdown *);

View File

@ -37,11 +37,8 @@
#include <current.h> #include <current.h>
#include <synch.h> #include <synch.h>
#include <mainbus.h> #include <mainbus.h>
#include <vfs.h> // for vfs_sync() #include <vfs.h> // for vfs_sync()
#include <lamebus/ltrace.h> // for ltrace_stop() #include <lamebus/ltrace.h> // for ltrace_stop()
#include <kern/secret.h>
#include <test.h>
/* Flags word for DEBUG() macro. */ /* Flags word for DEBUG() macro. */
uint32_t dbflags = 0; uint32_t dbflags = 0;
@ -52,94 +49,66 @@ static struct lock *kprintf_lock;
/* Lock for polled kprintfs */ /* Lock for polled kprintfs */
static struct spinlock kprintf_spinlock; static struct spinlock kprintf_spinlock;
/* /*
* Warning: all this has to work from interrupt handlers and when * Warning: all this has to work from interrupt handlers and when
* interrupts are disabled. * interrupts are disabled.
*/ */
/* /*
* Create the kprintf lock. Must be called before creating a second * Create the kprintf lock. Must be called before creating a second
* thread or enabling a second CPU. * thread or enabling a second CPU.
*/ */
void void kprintf_bootstrap(void) {
kprintf_bootstrap(void) KASSERT(kprintf_lock == NULL);
{
KASSERT(kprintf_lock == NULL);
kprintf_lock = lock_create("kprintf_lock"); kprintf_lock = lock_create("kprintf_lock");
if (kprintf_lock == NULL) { if (kprintf_lock == NULL) {
panic("Could not create kprintf_lock\n"); panic("Could not create kprintf_lock\n");
} }
spinlock_init(&kprintf_spinlock); spinlock_init(&kprintf_spinlock);
} }
/* /*
* Send characters to the console. Backend for __printf. * Send characters to the console. Backend for __printf.
*/ */
static static void console_send(void *junk, const char *data, size_t len) {
void size_t i;
console_send(void *junk, const char *data, size_t len)
{
size_t i;
(void)junk; (void)junk;
for (i=0; i<len; i++) { for (i = 0; i < len; i++) {
putch(data[i]); putch(data[i]);
} }
}
/*
* kprintf and tprintf helper function.
*/
static
inline
int
__kprintf(const char *fmt, va_list ap)
{
int chars;
bool dolock;
dolock = kprintf_lock != NULL
&& curthread->t_in_interrupt == false
&& curthread->t_curspl == 0
&& curcpu->c_spinlocks == 0;
if (dolock) {
lock_acquire(kprintf_lock);
}
else {
spinlock_acquire(&kprintf_spinlock);
}
chars = __vprintf(console_send, NULL, fmt, ap);
if (dolock) {
lock_release(kprintf_lock);
}
else {
spinlock_release(&kprintf_spinlock);
}
return chars;
} }
/* /*
* Printf to the console. * Printf to the console.
*/ */
int int kprintf(const char *fmt, ...) {
kprintf(const char *fmt, ...) int chars;
{ va_list ap;
int chars; bool dolock;
va_list ap;
va_start(ap, fmt); dolock = kprintf_lock != NULL && curthread->t_in_interrupt == false &&
chars = __kprintf(fmt, ap); curthread->t_curspl == 0 && curcpu->c_spinlocks == 0;
va_end(ap);
return chars; if (dolock) {
lock_acquire(kprintf_lock);
} else {
spinlock_acquire(&kprintf_spinlock);
}
va_start(ap, fmt);
chars = __vprintf(console_send, NULL, fmt, ap);
va_end(ap);
if (dolock) {
lock_release(kprintf_lock);
} else {
spinlock_release(&kprintf_spinlock);
}
return chars;
} }
/* /*
@ -147,87 +116,83 @@ kprintf(const char *fmt, ...)
* passed and then halts the system. * passed and then halts the system.
*/ */
void void panic(const char *fmt, ...) {
panic(const char *fmt, ...) va_list ap;
{
va_list ap;
/* /*
* When we reach panic, the system is usually fairly screwed up. * When we reach panic, the system is usually fairly screwed up.
* It's not entirely uncommon for anything else we try to do * It's not entirely uncommon for anything else we try to do
* here to trigger more panics. * here to trigger more panics.
* *
* This variable makes sure that if we try to do something here, * This variable makes sure that if we try to do something here,
* and it causes another panic, *that* panic doesn't try again; * and it causes another panic, *that* panic doesn't try again;
* trying again almost inevitably causes infinite recursion. * trying again almost inevitably causes infinite recursion.
* *
* This is not excessively paranoid - these things DO happen! * This is not excessively paranoid - these things DO happen!
*/ */
static volatile int evil; static volatile int evil;
if (evil == 0) { if (evil == 0) {
evil = 1; evil = 1;
/* /*
* Not only do we not want to be interrupted while * Not only do we not want to be interrupted while
* panicking, but we also want the console to be * panicking, but we also want the console to be
* printing in polling mode so as not to do context * printing in polling mode so as not to do context
* switches. So turn interrupts off on this CPU. * switches. So turn interrupts off on this CPU.
*/ */
splhigh(); splhigh();
} }
if (evil == 1) { if (evil == 1) {
evil = 2; evil = 2;
/* Kill off other threads and halt other CPUs. */ /* Kill off other threads and halt other CPUs. */
thread_panic(); thread_panic();
} }
if (evil == 2) { if (evil == 2) {
evil = 3; evil = 3;
/* Print the message. */ /* Print the message. */
kprintf("panic: "); kprintf("panic: ");
va_start(ap, fmt); va_start(ap, fmt);
__vprintf(console_send, NULL, fmt, ap); __vprintf(console_send, NULL, fmt, ap);
va_end(ap); va_end(ap);
} }
if (evil == 3) { if (evil == 3) {
evil = 4; evil = 4;
/* Drop to the debugger. */ /* Drop to the debugger. */
ltrace_stop(0); ltrace_stop(0);
} }
if (evil == 4) { if (evil == 4) {
evil = 5; evil = 5;
/* Try to sync the disks. */ /* Try to sync the disks. */
vfs_sync(); vfs_sync();
} }
if (evil == 5) { if (evil == 5) {
evil = 6; evil = 6;
/* Shut down or reboot the system. */ /* Shut down or reboot the system. */
mainbus_panic(); mainbus_panic();
} }
/* /*
* Last resort, just in case. * Last resort, just in case.
*/ */
for (;;); for (;;)
;
} }
/* /*
* Assertion failures go through this. * Assertion failures go through this.
*/ */
void void badassert(const char *expr, const char *file, int line, const char *func) {
badassert(const char *expr, const char *file, int line, const char *func) panic("Assertion failed: %s, at %s:%d (%s)\n", expr, file, line, func);
{
panic("Assertion failed: %s, at %s:%d (%s)\n",
expr, file, line, func);
} }

View File

@ -48,10 +48,8 @@
#include <device.h> #include <device.h>
#include <syscall.h> #include <syscall.h>
#include <test.h> #include <test.h>
#include <kern/test161.h>
#include <version.h> #include <version.h>
#include "autoconf.h" // for pseudoconfig #include "autoconf.h" // for pseudoconfig
/* /*
* These two pieces of data are maintained by the makefiles and build system. * These two pieces of data are maintained by the makefiles and build system.
@ -72,93 +70,85 @@ static const char harvard_copyright[] =
"Copyright (c) 2000, 2001-2005, 2008-2011, 2013, 2014\n" "Copyright (c) 2000, 2001-2005, 2008-2011, 2013, 2014\n"
" President and Fellows of Harvard College. All rights reserved.\n"; " President and Fellows of Harvard College. All rights reserved.\n";
/* /*
* Initial boot sequence. * Initial boot sequence.
*/ */
static static void boot(void) {
void /*
boot(void) * The order of these is important!
{ * Don't go changing it without thinking about the consequences.
/* *
* The order of these is important! * Among other things, be aware that console output gets
* Don't go changing it without thinking about the consequences. * buffered up at first and does not actually appear until
* * mainbus_bootstrap() attaches the console device. This can
* Among other things, be aware that console output gets * be remarkably confusing if a bug occurs at this point. So
* buffered up at first and does not actually appear until * don't put new code before mainbus_bootstrap if you don't
* mainbus_bootstrap() attaches the console device. This can * absolutely have to.
* be remarkably confusing if a bug occurs at this point. So *
* don't put new code before mainbus_bootstrap if you don't * Also note that the buffer for this is only 1k. If you
* absolutely have to. * overflow it, the system will crash without printing
* * anything at all. You can make it larger though (it's in
* Also note that the buffer for this is only 1k. If you * dev/generic/console.c).
* overflow it, the system will crash without printing */
* anything at all. You can make it larger though (it's in
* dev/generic/console.c).
*/
kprintf("\n"); kprintf("\n");
kprintf("OS/161 base system version %s\n", BASE_VERSION); kprintf("OS/161 base system version %s\n", BASE_VERSION);
kprintf("%s", harvard_copyright); kprintf("%s", harvard_copyright);
kprintf("\n"); kprintf("\n");
kprintf("Put-your-group-name-here's system version %s (%s #%d)\n", kprintf("Minh Tran's system version %s (%s #%d)\n", GROUP_VERSION,
GROUP_VERSION, buildconfig, buildversion); buildconfig, buildversion);
kprintf("\n"); kprintf("\n");
/* Early initialization. */ /* Early initialization. */
ram_bootstrap(); ram_bootstrap();
proc_bootstrap(); proc_bootstrap();
thread_bootstrap(); thread_bootstrap();
hardclock_bootstrap(); hardclock_bootstrap();
vfs_bootstrap(); vfs_bootstrap();
kheap_nextgeneration(); kheap_nextgeneration();
/* Probe and initialize devices. Interrupts should come on. */ /* Probe and initialize devices. Interrupts should come on. */
kprintf("Device probe...\n"); kprintf("Device probe...\n");
KASSERT(curthread->t_curspl > 0); KASSERT(curthread->t_curspl > 0);
mainbus_bootstrap(); mainbus_bootstrap();
KASSERT(curthread->t_curspl == 0); KASSERT(curthread->t_curspl == 0);
/* Now do pseudo-devices. */ /* Now do pseudo-devices. */
pseudoconfig(); pseudoconfig();
kprintf("\n"); kprintf("\n");
kheap_nextgeneration(); kheap_nextgeneration();
/* Late phase of initialization. */ /* Late phase of initialization. */
vm_bootstrap(); vm_bootstrap();
kprintf_bootstrap(); kprintf_bootstrap();
thread_start_cpus(); thread_start_cpus();
test161_bootstrap();
/* Default bootfs - but ignore failure, in case emu0 doesn't exist */ /* Default bootfs - but ignore failure, in case emu0 doesn't exist */
vfs_setbootfs("emu0"); vfs_setbootfs("emu0");
kheap_nextgeneration(); kheap_nextgeneration();
/* /*
* Make sure various things aren't screwed up. * Make sure various things aren't screwed up.
*/ */
COMPILE_ASSERT(sizeof(userptr_t) == sizeof(char *)); COMPILE_ASSERT(sizeof(userptr_t) == sizeof(char *));
COMPILE_ASSERT(sizeof(*(userptr_t)0) == sizeof(char)); COMPILE_ASSERT(sizeof(*(userptr_t)0) == sizeof(char));
} }
/* /*
* Shutdown sequence. Opposite to boot(). * Shutdown sequence. Opposite to boot().
*/ */
static static void shutdown(void) {
void
shutdown(void)
{
kprintf("Shutting down.\n"); kprintf("Shutting down.\n");
vfs_clearbootfs(); vfs_clearbootfs();
vfs_clearcurdir(); vfs_clearcurdir();
vfs_unmountall(); vfs_unmountall();
thread_shutdown(); thread_shutdown();
splhigh(); splhigh();
} }
/*****************************************/ /*****************************************/
@ -170,49 +160,45 @@ shutdown(void)
* not because this is where system call code should go. Other syscall * not because this is where system call code should go. Other syscall
* code should probably live in the "syscall" directory. * code should probably live in the "syscall" directory.
*/ */
int int sys_reboot(int code) {
sys_reboot(int code) switch (code) {
{ case RB_REBOOT:
switch (code) { case RB_HALT:
case RB_REBOOT: case RB_POWEROFF:
case RB_HALT: break;
case RB_POWEROFF: default:
break; return EINVAL;
default: }
return EINVAL;
}
shutdown(); shutdown();
switch (code) { switch (code) {
case RB_HALT: case RB_HALT:
kprintf("The system is halted.\n"); kprintf("The system is halted.\n");
mainbus_halt(); mainbus_halt();
break; break;
case RB_REBOOT: case RB_REBOOT:
kprintf("Rebooting...\n"); kprintf("Rebooting...\n");
mainbus_reboot(); mainbus_reboot();
break; break;
case RB_POWEROFF: case RB_POWEROFF:
kprintf("The system is halted.\n"); kprintf("The system is halted.\n");
mainbus_poweroff(); mainbus_poweroff();
break; break;
} }
panic("reboot operation failed\n"); panic("reboot operation failed\n");
return 0; return 0;
} }
/* /*
* Kernel main. Boot up, then fork the menu thread; wait for a reboot * Kernel main. Boot up, then fork the menu thread; wait for a reboot
* request, and then shut down. * request, and then shut down.
*/ */
void void kmain(char *arguments) {
kmain(char *arguments) boot();
{
boot();
menu(arguments); menu(arguments);
/* Should not get here */ /* Should not get here */
} }

View File

@ -43,11 +43,8 @@
#include <sfs.h> #include <sfs.h>
#include <syscall.h> #include <syscall.h>
#include <test.h> #include <test.h>
#include <prompt.h>
#include "opt-sfs.h" #include "opt-sfs.h"
#include "opt-net.h" #include "opt-net.h"
#include "opt-synchprobs.h"
#include "opt-automationtest.h"
/* /*
* In-kernel menu and command dispatcher. * In-kernel menu and command dispatcher.
@ -119,7 +116,6 @@ common_prog(int nargs, char **args)
{ {
struct proc *proc; struct proc *proc;
int result; int result;
unsigned tc;
/* Create a process for the new program to run in. */ /* Create a process for the new program to run in. */
proc = proc_create_runprogram(args[0] /* name */); proc = proc_create_runprogram(args[0] /* name */);
@ -127,8 +123,6 @@ common_prog(int nargs, char **args)
return ENOMEM; return ENOMEM;
} }
tc = thread_count;
result = thread_fork(args[0] /* thread name */, result = thread_fork(args[0] /* thread name */,
proc /* new process */, proc /* new process */,
cmd_progthread /* thread function */, cmd_progthread /* thread function */,
@ -144,10 +138,6 @@ common_prog(int nargs, char **args)
* once you write the code for handling that. * once you write the code for handling that.
*/ */
// Wait for all threads to finish cleanup, otherwise khu be a bit behind,
// especially once swapping is enabled.
thread_wait_for_count(tc);
return 0; return 0;
} }
@ -475,18 +465,6 @@ cmd_kheapstats(int nargs, char **args)
return 0; return 0;
} }
static
int
cmd_kheapused(int nargs, char **args)
{
(void)nargs;
(void)args;
kheap_printused();
return 0;
}
static static
int int
cmd_kheapgeneration(int nargs, char **args) cmd_kheapgeneration(int nargs, char **args)
@ -582,33 +560,16 @@ static const char *testmenu[] = {
"[km2] kmalloc stress test ", "[km2] kmalloc stress test ",
"[km3] Large kmalloc test ", "[km3] Large kmalloc test ",
"[km4] Multipage kmalloc test ", "[km4] Multipage kmalloc test ",
"[km5] kmalloc coremap alloc test ",
"[tt1] Thread test 1 ", "[tt1] Thread test 1 ",
"[tt2] Thread test 2 ", "[tt2] Thread test 2 ",
"[tt3] Thread test 3 ", "[tt3] Thread test 3 ",
#if OPT_NET #if OPT_NET
"[net] Network test ", "[net] Network test ",
#endif #endif
"[sem1] Semaphore test ", "[sy1] Semaphore test ",
"[lt1] Lock test 1 (1) ", "[sy2] Lock test (1) ",
"[lt2] Lock test 2 (1*) ", "[sy3] CV test (1) ",
"[lt3] Lock test 3 (1*) ", "[sy4] CV test #2 (1) ",
"[lt4] Lock test 4 (1*) ",
"[lt5] Lock test 5 (1*) ",
"[cvt1] CV test 1 (1) ",
"[cvt2] CV test 2 (1) ",
"[cvt3] CV test 3 (1*) ",
"[cvt4] CV test 4 (1*) ",
"[cvt5] CV test 5 (1) ",
"[rwt1] RW lock test (1?) ",
"[rwt2] RW lock test 2 (1?) ",
"[rwt3] RW lock test 3 (1?) ",
"[rwt4] RW lock test 4 (1?) ",
"[rwt5] RW lock test 5 (1?) ",
#if OPT_SYNCHPROBS
"[sp1] Whalemating test (1) ",
"[sp2] Stoplight test (1) ",
#endif
"[semu1-22] Semaphore unit tests ", "[semu1-22] Semaphore unit tests ",
"[fs1] Filesystem test ", "[fs1] Filesystem test ",
"[fs2] FS read stress ", "[fs2] FS read stress ",
@ -616,7 +577,6 @@ static const char *testmenu[] = {
"[fs4] FS write stress 2 ", "[fs4] FS write stress 2 ",
"[fs5] FS long stress ", "[fs5] FS long stress ",
"[fs6] FS create stress ", "[fs6] FS create stress ",
"[hm1] HMAC unit test ",
NULL NULL
}; };
@ -630,41 +590,15 @@ cmd_testmenu(int n, char **a)
showmenu("OS/161 tests menu", testmenu); showmenu("OS/161 tests menu", testmenu);
kprintf(" (1) These tests will fail until you finish the " kprintf(" (1) These tests will fail until you finish the "
"synch assignment.\n"); "synch assignment.\n");
kprintf(" (*) These tests will panic on success.\n");
kprintf(" (?) These tests are left to you to implement.\n");
kprintf("\n"); kprintf("\n");
return 0; return 0;
} }
#if OPT_AUTOMATIONTEST
static const char *automationmenu[] = {
"[dl] Deadlock test (*) ",
"[ll1] Livelock test (1 thread) ",
"[ll16] Livelock test (16 threads) ",
NULL
};
static
int
cmd_automationmenu(int n, char **a)
{
(void)n;
(void)a;
showmenu("OS/161 automation tests menu", automationmenu);
kprintf(" (*) These tests require locks.\n");
kprintf("\n");
return 0;
}
#endif
static const char *mainmenu[] = { static const char *mainmenu[] = {
"[?o] Operations menu ", "[?o] Operations menu ",
"[?t] Tests menu ", "[?t] Tests menu ",
"[kh] Kernel heap stats ", "[kh] Kernel heap stats ",
"[khu] Kernel heap usage ",
"[khgen] Next kernel heap generation ", "[khgen] Next kernel heap generation ",
"[khdump] Dump kernel heap ", "[khdump] Dump kernel heap ",
"[q] Quit and shut down ", "[q] Quit and shut down ",
@ -696,9 +630,6 @@ static struct {
{ "help", cmd_mainmenu }, { "help", cmd_mainmenu },
{ "?o", cmd_opsmenu }, { "?o", cmd_opsmenu },
{ "?t", cmd_testmenu }, { "?t", cmd_testmenu },
#if OPT_AUTOMATIONTEST
{ "?a", cmd_automationmenu },
#endif
/* operations */ /* operations */
{ "s", cmd_shell }, { "s", cmd_shell },
@ -719,7 +650,6 @@ static struct {
/* stats */ /* stats */
{ "kh", cmd_kheapstats }, { "kh", cmd_kheapstats },
{ "khu", cmd_kheapused },
{ "khgen", cmd_kheapgeneration }, { "khgen", cmd_kheapgeneration },
{ "khdump", cmd_kheapdump }, { "khdump", cmd_kheapdump },
@ -732,35 +662,18 @@ static struct {
{ "km2", kmallocstress }, { "km2", kmallocstress },
{ "km3", kmalloctest3 }, { "km3", kmalloctest3 },
{ "km4", kmalloctest4 }, { "km4", kmalloctest4 },
{ "km5", kmalloctest5 },
#if OPT_NET #if OPT_NET
{ "net", nettest }, { "net", nettest },
#endif #endif
{ "tt1", threadtest }, { "tt1", threadtest },
{ "tt2", threadtest2 }, { "tt2", threadtest2 },
{ "tt3", threadtest3 }, { "tt3", threadtest3 },
{ "sy1", semtest },
/* synchronization assignment tests */ /* synchronization assignment tests */
{ "sem1", semtest }, { "sy2", locktest },
{ "lt1", locktest }, { "sy3", cvtest },
{ "lt2", locktest2 }, { "sy4", cvtest2 },
{ "lt3", locktest3 },
{ "lt4", locktest4 },
{ "lt5", locktest5 },
{ "cvt1", cvtest },
{ "cvt2", cvtest2 },
{ "cvt3", cvtest3 },
{ "cvt4", cvtest4 },
{ "cvt5", cvtest5 },
{ "rwt1", rwtest },
{ "rwt2", rwtest2 },
{ "rwt3", rwtest3 },
{ "rwt4", rwtest4 },
{ "rwt5", rwtest5 },
#if OPT_SYNCHPROBS
{ "sp1", whalemating },
{ "sp2", stoplight },
#endif
/* semaphore unit tests */ /* semaphore unit tests */
{ "semu1", semu1 }, { "semu1", semu1 },
@ -794,16 +707,6 @@ static struct {
{ "fs5", longstress }, { "fs5", longstress },
{ "fs6", createstress }, { "fs6", createstress },
/* HMAC unit tests */
{ "hm1", hmacu1 },
#if OPT_AUTOMATIONTEST
/* automation tests */
{ "dl", dltest },
{ "ll1", ll1test },
{ "ll16", ll16test },
#endif
{ NULL, NULL } { NULL, NULL }
}; };
@ -917,11 +820,7 @@ menu(char *args)
menu_execute(args, 1); menu_execute(args, 1);
while (1) { while (1) {
/* kprintf("OS/161 kernel [? for menu]: ");
* Defined in overwrite.h. If you want to change the kernel prompt, please
* do it in that file. Otherwise automated test testing will break.
*/
kprintf(KERNEL_PROMPT);
kgets(buf, sizeof(buf)); kgets(buf, sizeof(buf));
menu_execute(buf, 0); menu_execute(buf, 0);
} }

View File

@ -1,118 +0,0 @@
/*
* Copyright (c) 2001, 2002, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Driver code is in kern/tests/synchprobs.c We will replace that file. This
* file is yours to modify as you see fit.
*
* You should implement your solution to the stoplight problem below. The
* quadrant and direction mappings for reference: (although the problem is, of
* course, stable under rotation)
*
* |0 |
* - --
* 01 1
* 3 32
* -- --
* | 2|
*
* As way to think about it, assuming cars drive on the right: a car entering
* the intersection from direction X will enter intersection quadrant X first.
* The semantics of the problem are that once a car enters any quadrant it has
* to be somewhere in the intersection until it call leaveIntersection(),
* which it should call while in the final quadrant.
*
* As an example, let's say a car approaches the intersection and needs to
* pass through quadrants 0, 3 and 2. Once you call inQuadrant(0), the car is
* considered in quadrant 0 until you call inQuadrant(3). After you call
* inQuadrant(2), the car is considered in quadrant 2 until you call
* leaveIntersection().
*
* You will probably want to write some helper functions to assist with the
* mappings. Modular arithmetic can help, e.g. a car passing straight through
* the intersection entering from direction X will leave to direction (X + 2)
* % 4 and pass through quadrants X and (X + 3) % 4. Boo-yah.
*
* Your solutions below should call the inQuadrant() and leaveIntersection()
* functions in synchprobs.c to record their progress.
*/
#include <types.h>
#include <lib.h>
#include <thread.h>
#include <test.h>
#include <synch.h>
/*
* Called by the driver during initialization.
*/
void
stoplight_init() {
return;
}
/*
* Called by the driver during teardown.
*/
void stoplight_cleanup() {
return;
}
void
turnright(uint32_t direction, uint32_t index)
{
(void)direction;
(void)index;
/*
* Implement this function.
*/
return;
}
void
gostraight(uint32_t direction, uint32_t index)
{
(void)direction;
(void)index;
/*
* Implement this function.
*/
return;
}
void
turnleft(uint32_t direction, uint32_t index)
{
(void)direction;
(void)index;
/*
* Implement this function.
*/
return;
}

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 2001, 2002, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Driver code is in kern/tests/synchprobs.c We will
* replace that file. This file is yours to modify as you see fit.
*
* You should implement your solution to the whalemating problem below.
*/
#include <types.h>
#include <lib.h>
#include <thread.h>
#include <test.h>
#include <synch.h>
/*
* Called by the driver during initialization.
*/
void whalemating_init() {
return;
}
/*
* Called by the driver during teardown.
*/
void
whalemating_cleanup() {
return;
}
void
male(uint32_t index)
{
(void)index;
/*
* Implement this function by calling male_start and male_end when
* appropriate.
*/
return;
}
void
female(uint32_t index)
{
(void)index;
/*
* Implement this function by calling female_start and female_end when
* appropriate.
*/
return;
}
void
matchmaker(uint32_t index)
{
(void)index;
/*
* Implement this function by calling matchmaker_start and matchmaker_end
* when appropriate.
*/
return;
}

View File

@ -1,175 +0,0 @@
/*
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Automation test code for creating (and detecting) kernel dead and livelocks.
*/
#include <types.h>
#include <kern/wait.h>
#include <lib.h>
#include <clock.h>
#include <thread.h>
#include <synch.h>
#include <test.h>
#include <kern/secret.h>
#include <spinlock.h>
#define MAX_SPINNERS 16
static struct lock *deadlock_locks[2];
static struct semaphore *deadlock_sem;
struct spinlock spinners_lock[MAX_SPINNERS];
static
void
inititems(void)
{
int i;
for (i = 0; i < 2; i++) {
deadlock_locks[i] = lock_create("deadlock lock");
if (deadlock_locks[i] == NULL) {
panic("automationtest: lock_create failed\n");
}
}
deadlock_sem = sem_create("deadlock sem", 0);
if (deadlock_sem == NULL) {
panic("automationtest: sem_create failed\n");
}
for (i = 0; i < MAX_SPINNERS; i++) {
spinlock_init(&(spinners_lock[i]));
}
}
static
void
dltestthread(void *junk1, unsigned long junk2)
{
(void)junk1;
(void)junk2;
lock_acquire(deadlock_locks[1]);
V(deadlock_sem);
lock_acquire(deadlock_locks[0]);
}
int
dltest(int nargs, char **args)
{
int result;
(void)nargs;
(void)args;
inititems();
lock_acquire(deadlock_locks[0]);
result = thread_fork("dltest", NULL, dltestthread, NULL, (unsigned long)0);
if (result) {
panic("dltest: thread_fork failed: %s\n", strerror(result));
}
P(deadlock_sem);
lock_acquire(deadlock_locks[1]);
panic("dltest: didn't create deadlock (locks probably don't work)\n");
// 09 Jan 2015 : GWA : Shouldn't return.
return 0;
}
inline
static
void
infinite_spinner(unsigned long i)
{
(void)i;
volatile int j;
for (j=0; j<10000000; j++);
spinlock_acquire(&(spinners_lock[i]));
for (j=0; j<=1000; j++) {
if (j == 1000) {
j = 0;
}
}
panic("ll1test: infinite spin loop completed\n");
}
int
ll1test(int nargs, char **args)
{
(void)nargs;
(void)args;
inititems();
infinite_spinner((unsigned long) 0);
// 09 Jan 2015 : GWA : Shouldn't return.
return 0;
}
static
void
ll16testthread(void *junk1, unsigned long i)
{
(void)junk1;
infinite_spinner(i);
}
int
ll16test(int nargs, char **args)
{
int i, result;
inititems();
(void)nargs;
(void)args;
for (i=1; i<16; i++) {
result = thread_fork("ll16testthread", NULL, ll16testthread, NULL, (unsigned long)i);
if (result) {
panic("ll16test: thread_fork failed: %s\n", strerror(result));
}
}
infinite_spinner(0);
// 09 Jan 2015 : GWA : Shouldn't return.
return 0;
}

View File

@ -1,99 +0,0 @@
/*
* Copyright (c) 2015
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <types.h>
#include <lib.h>
#include <spinlock.h>
#include <synch.h>
#include <thread.h>
#include <current.h>
#include <clock.h>
#include <test.h>
#include <kern/secure.h>
/*
* Unit tests for hmac/sha256 hashing.
*/
////////////////////////////////////////////////////////////
// support code
static
void
ok(void)
{
kprintf("Test passed.\n");
}
/*
* Unit test 1
*
* Test some known msg/key/hashes to make sure we produce the
* right results.
*/
static const char *plaintext1[] = {
"The quick brown fox jumps over the lazy dog",
"The only people for me are the mad ones",
"I don't exactly know what I mean by that, but I mean it.",
};
static const char *keys1[] = {
"xqWmgzbvGuLIeeKOrwMA",
"ZxuvolLXL7C68pDjsclX",
"PYeuVzKuB03awYDgJotS",
};
static const char *hashes1[] = {
"251ab1da03c94435daf44898fcd11606669e222270e4ac90d04a18a9df8fdfd6",
"75bbf48c53ccba08c244447ef7eff2e0a02f23acfdac6502282ec431823fb393",
"6d7d2b5eabcda504f26de7547185483b19f9953a6eaeec6c364bb45e20b28598",
};
#define N_TESTS_1 3
int
hmacu1(int nargs, char **args)
{
char *hash;
int res;
(void)nargs; (void)args;
int i;
for (i = 0; i < N_TESTS_1; i++)
{
res = hmac(plaintext1[i], strlen(plaintext1[i]), keys1[i], strlen(keys1[i]), &hash);
KASSERT(!res);
KASSERT(strcmp(hash, hashes1[i]) == 0);
kfree(hash);
}
ok();
/* clean up */
return 0;
}

View File

@ -33,19 +33,13 @@
#include <types.h> #include <types.h>
#include <kern/errno.h> #include <kern/errno.h>
#include <lib.h> #include <lib.h>
#include <cpu.h>
#include <thread.h> #include <thread.h>
#include <synch.h> #include <synch.h>
#include <vm.h> /* for PAGE_SIZE */ #include <vm.h> /* for PAGE_SIZE */
#include <test.h> #include <test.h>
#include <kern/test161.h>
#include <mainbus.h>
#include "opt-dumbvm.h" #include "opt-dumbvm.h"
// from arch/mips/vm/ram.c
extern vaddr_t firstfree;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// km1/km2 // km1/km2
@ -64,12 +58,6 @@ extern vaddr_t firstfree;
#define ITEMSIZE 997 #define ITEMSIZE 997
#define NTHREADS 8 #define NTHREADS 8
#define PROGRESS(iter) do { \
if ((iter % 100) == 0) { \
kprintf("."); \
} \
} while (0)
static static
void void
kmallocthread(void *sm, unsigned long num) kmallocthread(void *sm, unsigned long num)
@ -81,16 +69,15 @@ kmallocthread(void *sm, unsigned long num)
int i; int i;
for (i=0; i<NTRIES; i++) { for (i=0; i<NTRIES; i++) {
PROGRESS(i);
ptr = kmalloc(ITEMSIZE); ptr = kmalloc(ITEMSIZE);
if (ptr==NULL) { if (ptr==NULL) {
if (sem) { if (sem) {
kprintf("thread %lu: kmalloc returned NULL\n", kprintf("thread %lu: kmalloc returned NULL\n",
num); num);
panic("kmalloc test failed"); goto done;
} }
kprintf("kmalloc returned null; test failed.\n"); kprintf("kmalloc returned null; test failed.\n");
panic("kmalloc test failed"); goto done;
} }
if (oldptr2) { if (oldptr2) {
kfree(oldptr2); kfree(oldptr2);
@ -98,7 +85,7 @@ kmallocthread(void *sm, unsigned long num)
oldptr2 = oldptr; oldptr2 = oldptr;
oldptr = ptr; oldptr = ptr;
} }
done:
if (oldptr2) { if (oldptr2) {
kfree(oldptr2); kfree(oldptr2);
} }
@ -118,8 +105,7 @@ kmalloctest(int nargs, char **args)
kprintf("Starting kmalloc test...\n"); kprintf("Starting kmalloc test...\n");
kmallocthread(NULL, 0); kmallocthread(NULL, 0);
kprintf("\n"); kprintf("kmalloc test done\n");
success(TEST161_SUCCESS, SECRET, "km1");
return 0; return 0;
} }
@ -154,8 +140,7 @@ kmallocstress(int nargs, char **args)
} }
sem_destroy(sem); sem_destroy(sem);
kprintf("\n"); kprintf("kmalloc stress test done\n");
success(TEST161_SUCCESS, SECRET, "km2");
return 0; return 0;
} }
@ -267,7 +252,6 @@ kmalloctest3(int nargs, char **args)
curpos = 0; curpos = 0;
cursizeindex = 0; cursizeindex = 0;
for (i=0; i<numptrs; i++) { for (i=0; i<numptrs; i++) {
PROGRESS(i);
cursize = sizes[cursizeindex]; cursize = sizes[cursizeindex];
ptr = ptrblocks[curblock][curpos]; ptr = ptrblocks[curblock][curpos];
KASSERT(ptr != NULL); KASSERT(ptr != NULL);
@ -298,15 +282,13 @@ kmalloctest3(int nargs, char **args)
/* Free the lower tier. */ /* Free the lower tier. */
for (i=0; i<numptrblocks; i++) { for (i=0; i<numptrblocks; i++) {
PROGRESS(i);
KASSERT(ptrblocks[i] != NULL); KASSERT(ptrblocks[i] != NULL);
kfree(ptrblocks[i]); kfree(ptrblocks[i]);
} }
/* Free the upper tier. */ /* Free the upper tier. */
kfree(ptrblocks); kfree(ptrblocks);
kprintf("\n"); kprintf("kmalloctest3: passed\n");
success(TEST161_SUCCESS, SECRET, "km3");
return 0; return 0;
} }
@ -318,24 +300,20 @@ void
kmalloctest4thread(void *sm, unsigned long num) kmalloctest4thread(void *sm, unsigned long num)
{ {
#define NUM_KM4_SIZES 5 #define NUM_KM4_SIZES 5
#define ITERATIONS 50
static const unsigned sizes[NUM_KM4_SIZES] = { 1, 3, 5, 2, 4 }; static const unsigned sizes[NUM_KM4_SIZES] = { 1, 3, 5, 2, 4 };
struct semaphore *sem = sm; struct semaphore *sem = sm;
void *ptrs[NUM_KM4_SIZES]; void *ptrs[NUM_KM4_SIZES];
unsigned p, q; unsigned p, q;
unsigned i, j, k; unsigned i;
uint32_t magic;
for (i=0; i<NUM_KM4_SIZES; i++) { for (i=0; i<NUM_KM4_SIZES; i++) {
ptrs[i] = NULL; ptrs[i] = NULL;
} }
p = 0; p = 0;
q = NUM_KM4_SIZES / 2; q = NUM_KM4_SIZES / 2;
magic = random();
for (i=0; i<NTRIES; i++) { for (i=0; i<NTRIES; i++) {
PROGRESS(i);
if (ptrs[q] != NULL) { if (ptrs[q] != NULL) {
kfree(ptrs[q]); kfree(ptrs[q]);
ptrs[q] = NULL; ptrs[q] = NULL;
@ -346,24 +324,6 @@ kmalloctest4thread(void *sm, unsigned long num)
"allocating %u pages failed\n", "allocating %u pages failed\n",
num, sizes[p]); num, sizes[p]);
} }
// Write to each page of the allocated memory and make sure nothing
// overwrites it.
for (k = 0; k < sizes[p]; k++) {
*((uint32_t *)ptrs[p] + k*PAGE_SIZE/sizeof(uint32_t)) = magic;
}
for (j = 0; j < ITERATIONS; j++) {
random_yielder(4);
for (k = 0; k < sizes[p]; k++) {
uint32_t actual = *((uint32_t *)ptrs[p] + k*PAGE_SIZE/sizeof(uint32_t));
if (actual != magic) {
panic("km4: expected %u got %u. Your VM is broken!",
magic, actual);
}
}
}
magic++;
p = (p + 1) % NUM_KM4_SIZES; p = (p + 1) % NUM_KM4_SIZES;
q = (q + 1) % NUM_KM4_SIZES; q = (q + 1) % NUM_KM4_SIZES;
} }
@ -415,193 +375,6 @@ kmalloctest4(int nargs, char **args)
} }
sem_destroy(sem); sem_destroy(sem);
kprintf("Multipage kmalloc test done\n");
kprintf("\n");
success(TEST161_SUCCESS, SECRET, "km4");
return 0;
}
static inline
void
km5_usage()
{
kprintf("usage: km5 [--avail <num_pages>] [--kernel <num_pages>]\n");
}
/*
* Allocate and free all physical memory a number of times. Along the we, we
* check coremap_used_bytes to make sure it's reporting the number we're
* expecting.
*/
int
kmalloctest5(int nargs, char **args)
{
#define KM5_ITERATIONS 5
// We're expecting an even number of arguments, less arg[0].
if (nargs > 5 || (nargs % 2) == 0) {
km5_usage();
return 0;
}
unsigned avail_page_slack = 0, kernel_page_limit = 0;
int arg = 1;
while (arg < nargs) {
if (strcmp(args[arg], "--avail") == 0) {
arg++;
avail_page_slack = atoi(args[arg++]);
} else if (strcmp(args[arg], "--kernel") == 0) {
arg++;
kernel_page_limit = atoi(args[arg++]);
} else {
km5_usage();
return 0;
}
}
#if OPT_DUMBVM
kprintf("(This test will not work with dumbvm)\n");
#endif
// First, we need to figure out how much memory we're running with and how
// much space it will take up if we maintain a pointer to each allocated
// page. We do something similar to km3 - for 32 bit systems with
// PAGE_SIZE == 4096, we can store 1024 pointers on a page. We keep an array
// of page size blocks of pointers which in total can hold enough pointers
// for each page of available physical memory.
unsigned orig_used, ptrs_per_page, num_ptr_blocks, max_pages;
unsigned total_ram, avail_ram, magic, orig_magic, known_pages;
ptrs_per_page = PAGE_SIZE / sizeof(void *);
total_ram = mainbus_ramsize();
avail_ram = total_ram - (uint32_t)(firstfree - MIPS_KSEG0);
max_pages = (avail_ram + PAGE_SIZE-1) / PAGE_SIZE;
num_ptr_blocks = (max_pages + ptrs_per_page-1) / ptrs_per_page;
// The array can go on the stack, we won't have that many
// (sys161 16M max => 4 blocks)
void **ptrs[num_ptr_blocks];
for (unsigned i = 0; i < num_ptr_blocks; i++) {
ptrs[i] = kmalloc(PAGE_SIZE);
if (ptrs[i] == NULL) {
panic("Can't allocate ptr page!");
}
bzero(ptrs[i], PAGE_SIZE);
}
kprintf("km5 --> phys ram: %uk avail ram: %uk (%u pages) ptr blocks: %u\n", total_ram/1024,
avail_ram/1024, max_pages, num_ptr_blocks);
// Initially, there must be at least 1 page allocated for each thread stack,
// one page for kmalloc for this thread struct, plus what we just allocated).
// This probably isn't the GLB, but its a decent lower bound.
orig_used = coremap_used_bytes();
known_pages = num_cpus + num_ptr_blocks + 1;
if (orig_used < known_pages * PAGE_SIZE) {
panic ("Not enough pages initially allocated");
}
if ((orig_used % PAGE_SIZE) != 0) {
panic("Coremap used bytes should be a multiple of PAGE_SIZE");
}
// Test for kernel bloat.
if (kernel_page_limit > 0) {
uint32_t kpages = (total_ram - avail_ram + PAGE_SIZE) / PAGE_SIZE;
if (kpages > kernel_page_limit) {
panic("You're kernel is bloated! Max allowed pages: %d, used pages: %d",
kernel_page_limit, kpages);
}
}
orig_magic = magic = random();
for (int i = 0; i < KM5_ITERATIONS; i++) {
// Step 1: allocate all physical memory, with checks along the way
unsigned int block, pos, oom, pages, used, prev;
void *page;
block = pos = oom = pages = used = 0;
prev = orig_used;
while (pages < max_pages+1) {
PROGRESS(pages);
page = kmalloc(PAGE_SIZE);
if (page == NULL) {
oom = 1;
break;
}
// Make sure we can write to the page
*(uint32_t *)page = magic++;
// Make sure the number of used bytes is going up, and by increments of PAGE_SIZE
used = coremap_used_bytes();
if (used != prev + PAGE_SIZE) {
panic("Allocation not equal to PAGE_SIZE. prev: %u used: %u", prev, used);
}
prev = used;
ptrs[block][pos] = page;
pos++;
if (pos >= ptrs_per_page) {
pos = 0;
block++;
}
pages++;
}
// Step 2: Check that we were able to allocate a reasonable number of pages
unsigned expected;
if (avail_page_slack > 0 ) {
// max avail pages + what we can prove we allocated + some slack
expected = max_pages - (known_pages + avail_page_slack);
} else {
// At the very least, just so we know things are working.
expected = 3;
}
if (pages < expected) {
panic("Expected to allocate at least %d pages, only allocated %d",
expected, pages);
}
// We tried to allocate 1 more page than is available in physical memory. That
// should fail unless you're swapping out kernel pages, which you should
// probably not be doing.
if (!oom) {
panic("Allocated more pages than physical memory. Are you swapping kernel pages?");
}
// Step 3: free everything and check that we're back to where we started
for (block = 0; block < num_ptr_blocks; block++) {
for (pos = 0; pos < ptrs_per_page; pos++) {
if (ptrs[block][pos] != NULL) {
// Make sure we got unique addresses
if ((*(uint32_t *)ptrs[block][pos]) != orig_magic++) {
panic("km5: expected %u got %u - your VM is broken!",
orig_magic-1, (*(uint32_t *)ptrs[block][pos]));
}
kfree(ptrs[block][pos]);
}
}
}
// Check that we're back to where we started
used = coremap_used_bytes();
if (used != orig_used) {
panic("orig (%u) != used (%u)", orig_used, used);
}
}
//Clean up the pointer blocks
for (unsigned i = 0; i < num_ptr_blocks; i++) {
kfree(ptrs[i]);
}
kprintf("\n");
success(TEST161_SUCCESS, SECRET, "km5");
return 0; return 0;
} }

View File

@ -1,28 +0,0 @@
#include <types.h>
#include <thread.h>
#include <test.h>
#include <lib.h>
/*
* Helper functions used by testing and problem driver code
* to establish better mixtures of threads.
*/
void
random_yielder(uint32_t max_yield_count)
{
uint32_t i;
for (i = 0; i < random() % max_yield_count; i++) {
thread_yield();
}
}
void
random_spinner(uint32_t max_spin_count)
{
uint32_t i;
volatile int spin;
for (i = 0; i < random() % max_spin_count; i++) {
spin += i;
}
}

View File

@ -1,67 +0,0 @@
/*
* All the contents of this file are overwritten during automated
* testing. Please consider this before changing anything in this file.
*/
#include <types.h>
#include <lib.h>
#include <clock.h>
#include <thread.h>
#include <synch.h>
#include <test.h>
#include <kern/test161.h>
#include <spinlock.h>
/*
* Use these stubs to test your reader-writer locks.
*/
int rwtest(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("rwt1 unimplemented\n");
success(TEST161_FAIL, SECRET, "rwt1");
return 0;
}
int rwtest2(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("rwt2 unimplemented\n");
success(TEST161_FAIL, SECRET, "rwt2");
return 0;
}
int rwtest3(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("rwt3 unimplemented\n");
success(TEST161_FAIL, SECRET, "rwt3");
return 0;
}
int rwtest4(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("rwt4 unimplemented\n");
success(TEST161_FAIL, SECRET, "rwt4");
return 0;
}
int rwtest5(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("rwt5 unimplemented\n");
success(TEST161_FAIL, SECRET, "rwt5");
return 0;
}

View File

@ -1,688 +0,0 @@
/*
* All the contents of this file are overwritten during automated
* testing. Please consider this before changing anything in this file.
*/
#include <types.h>
#include <lib.h>
#include <thread.h>
#include <test.h>
#include <current.h>
#include <synch.h>
#include <kern/test161.h>
#include <spinlock.h>
#define PROBLEMS_MAX_YIELDER 16
#define PROBLEMS_MAX_SPINNER 8192
#define TEST161_SUCCESS 0
#define TEST161_FAIL 1
/*
* Shared initialization routines
*/
static uint32_t startcount;
static struct lock *testlock;
static struct cv *startcv;
static struct semaphore *startsem;
static struct semaphore *endsem;
struct spinlock status_lock;
static bool test_status = TEST161_FAIL;
const char *test_message;
static
bool
failif(bool condition, const char *message) {
if (condition) {
spinlock_acquire(&status_lock);
test_status = TEST161_FAIL;
test_message = message;
spinlock_release(&status_lock);
}
return condition;
}
/*
* Helper function to initialize the thread pool.
*/
static
void
initialize_thread(volatile void* threads[], uint32_t index) {
failif((threads[index] != NULL), "failed: incorrect thread type");
threads[index] = curthread->t_stack;
}
/*
* Helper function to check whether current thread is valid.
*/
static
void
check_thread(volatile void* threads[], uint32_t index) {
failif((threads[index] != curthread->t_stack), "failed: incorrect thread type");
}
/*
* Driver code for the whalemating problem.
*/
#define NMATING 10
#define MALE 0
#define FEMALE 1
#define MATCHMAKER 2
#define CHECK_TIMES 32
static volatile int male_start_count;
static volatile int male_end_count;
static volatile int female_start_count;
static volatile int female_end_count;
static volatile int matchmaker_start_count;
static volatile int matchmaker_end_count;
static volatile int match_count;
static volatile int concurrent_matchmakers;
static volatile int max_concurrent_matchmakers;
static volatile void* whale_threads[3 * NMATING];
static volatile int whale_roles[3 * NMATING];
static struct semaphore *matcher_sem;
/*
* Enforce male_start() and male_end() called from male thread.
* Similar for female and matchmaker threads
*/
static
void
check_role(uint32_t index, int role) {
failif((whale_roles[index] != role), "failed: incorrect role");
}
static
void
male_wrapper(void * unused1, unsigned long index) {
(void)unused1;
random_yielder(4);
lock_acquire(testlock);
initialize_thread(whale_threads, (uint32_t)index);
whale_roles[index] = MALE;
lock_release(testlock);
male((uint32_t)index);
return;
}
void
male_start(uint32_t index) {
(void)index;
lock_acquire(testlock);
check_thread(whale_threads, index);
check_role(index, MALE);
male_start_count++;
kprintf_n("%s starting\n", curthread->t_name);
kprintf_t(".");
lock_release(testlock);
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
V(startsem);
}
void
male_end(uint32_t index) {
(void)index;
lock_acquire(testlock);
check_thread(whale_threads, index);
check_role(index, MALE);
male_end_count++;
kprintf_n("%s ending\n", curthread->t_name);
kprintf_t(".");
lock_release(testlock);
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
V(endsem);
}
static
void
female_wrapper(void * unused1, unsigned long index) {
(void)unused1;
random_yielder(4);
lock_acquire(testlock);
initialize_thread(whale_threads, (uint32_t)index);
whale_roles[index] = FEMALE;
lock_release(testlock);
female((uint32_t)index);
return;
}
void
female_start(uint32_t index) {
(void) index;
lock_acquire(testlock);
check_thread(whale_threads, index);
check_role(index, FEMALE);
female_start_count++;
kprintf_n("%s starting\n", curthread->t_name);
kprintf_t(".");
lock_release(testlock);
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
V(startsem);
}
void
female_end(uint32_t index) {
(void) index;
lock_acquire(testlock);
check_thread(whale_threads, index);
check_role(index, FEMALE);
female_end_count++;
kprintf_n("%s ending\n", curthread->t_name);
kprintf_t(".");
lock_release(testlock);
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
V(endsem);
}
static
void
matchmaker_wrapper(void * unused1, unsigned long index) {
(void)unused1;
random_yielder(4);
lock_acquire(testlock);
initialize_thread(whale_threads, (uint32_t)index);
whale_roles[index] = MATCHMAKER;
lock_release(testlock);
matchmaker((uint32_t)index);
return;
}
void
matchmaker_start(uint32_t index) {
(void)index;
P(matcher_sem);
lock_acquire(testlock);
check_thread(whale_threads, index);
check_role(index, MATCHMAKER);
matchmaker_start_count++;
concurrent_matchmakers++;
if (concurrent_matchmakers > max_concurrent_matchmakers) {
max_concurrent_matchmakers = concurrent_matchmakers;
}
kprintf_n("%s starting\n", curthread->t_name);
kprintf_t(".");
lock_release(testlock);
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
V(startsem);
}
void
matchmaker_end(uint32_t index) {
(void)index;
lock_acquire(testlock);
check_thread(whale_threads, index);
check_role(index, MATCHMAKER);
match_count++;
matchmaker_end_count++;
concurrent_matchmakers--;
kprintf_n("%s ending\n", curthread->t_name);
kprintf_t(".");
lock_release(testlock);
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
V(endsem);
}
int
whalemating(int nargs, char **args) {
(void) nargs;
(void) args;
int i, j, err = 0;
char name[32];
bool loop_status;
int total_count = 0;
male_start_count = 0 ;
male_end_count = 0 ;
female_start_count = 0 ;
female_end_count = 0 ;
matchmaker_start_count = 0;
matchmaker_end_count = 0;
match_count = 0;
concurrent_matchmakers = 0;
max_concurrent_matchmakers = 0;
kprintf_n("Starting sp1...\n");
kprintf_n("If this tests hangs, your solution is incorrect.\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("sp1: lock_create failed\n");
}
startsem = sem_create("startsem", 0);
if (startsem == NULL) {
panic("sp1: sem_create failed\n");
}
endsem = sem_create("endsem", 0);
if (endsem == NULL) {
panic("sp1: sem_create failed\n");
}
matcher_sem = sem_create("matcher_sem", 0);
if (matcher_sem == NULL) {
panic("sp1: sem_create failed\n");
}
spinlock_init(&status_lock);
test_status = TEST161_SUCCESS;
test_message = "";
whalemating_init();
/* Start males and females only. */
for (i = 0; i < 2; i++) {
for (j = 0; j < NMATING; j++) {
kprintf_t(".");
int index = (i * NMATING) + j;
whale_threads[index] = NULL;
switch (i) {
case 0:
snprintf(name, sizeof(name), "Male Whale Thread %d", index);
err = thread_fork(name, NULL, male_wrapper, NULL, index);
break;
case 1:
snprintf(name, sizeof(name), "Female Whale Thread %d", index);
err = thread_fork(name, NULL, female_wrapper, NULL, index);
break;
}
total_count += 1;
if (err) {
panic("sp1: thread_fork failed: (%s)\n", strerror(err));
}
}
}
/* Wait for males and females to start. */
for (i = 0; i < NMATING * 2; i++) {
kprintf_t(".");
P(startsem);
}
/* Make sure nothing is happening... */
loop_status = TEST161_SUCCESS;
for (i = 0; i < CHECK_TIMES && loop_status == TEST161_SUCCESS; i++) {
kprintf_t(".");
random_spinner(PROBLEMS_MAX_SPINNER);
lock_acquire(testlock);
if ((male_start_count != NMATING) || (female_start_count != NMATING) ||
(matchmaker_start_count + male_end_count + female_end_count + matchmaker_end_count != 0)) {
loop_status = TEST161_FAIL;
}
lock_release(testlock);
}
if (failif((loop_status == TEST161_FAIL), "failed: uncoordinated matchmaking is occurring")) {
goto done;
}
/* Create the matchmakers */
for (j = 0; j < NMATING; j++) {
kprintf_t(".");
int index = (2 * NMATING) + j;
whale_threads[index] = NULL;
snprintf(name, sizeof(name), "Matchmaker Whale Thread %d", index);
err = thread_fork(name, NULL, matchmaker_wrapper, NULL, index);
if (err) {
panic("sp1: thread_fork failed: (%s)\n", strerror(err));
}
total_count++;
}
/*
* Release a random number of matchmakers and wait for them and their
* matches to finish.
*/
int pivot = (random() % (NMATING - 2)) + 1;
for (i = 0; i < pivot; i++) {
kprintf_t(".");
V(matcher_sem);
}
for (i = 0; i < 3 * pivot; i++) {
kprintf_t(".");
P(endsem);
total_count--;
}
/* Make sure nothing else is happening... */
loop_status = TEST161_SUCCESS;
for (i = 0; i < CHECK_TIMES && loop_status == TEST161_SUCCESS; i++) {
kprintf_t(".");
random_spinner(PROBLEMS_MAX_SPINNER);
lock_acquire(testlock);
if ((male_start_count != NMATING) || (female_start_count != NMATING) ||
(matchmaker_start_count != pivot) || (male_end_count != pivot) ||
(female_end_count != pivot) || (matchmaker_end_count != pivot)) {
loop_status = TEST161_FAIL;
}
lock_release(testlock);
}
if (failif((loop_status == TEST161_FAIL), "failed: uncoordinated matchmaking is occurring")) {
goto done;
}
/*
* Release the rest of the matchmakers and wait for everyone to finish.
*/
for (i = pivot; i < NMATING; i++) {
kprintf_t(".");
V(matcher_sem);
}
for (i = 0; i < 3; i++) {
for (j = pivot; j < NMATING; j++) {
kprintf_t(".");
P(endsem);
total_count--;
}
}
failif((max_concurrent_matchmakers == 1), "failed: no matchmaker concurrency");
whalemating_cleanup();
done:
for (i = 0; i < total_count; i++) {
P(endsem);
}
lock_destroy(testlock);
sem_destroy(startsem);
sem_destroy(endsem);
sem_destroy(matcher_sem);
kprintf_t("\n");
if (test_status != TEST161_SUCCESS) {
secprintf(SECRET, test_message, "sp1");
}
success(test_status, SECRET, "sp1");
return 0;
}
/*
* Driver code for the stoplight problem.
*/
#define NCARS 64
#define NUM_QUADRANTS 4
#define UNKNOWN_CAR -1
#define PASSED_CAR -2
#define GO_STRAIGHT 0
#define TURN_LEFT 1
#define TURN_RIGHT 2
static volatile int quadrant_array[NUM_QUADRANTS];
static volatile int max_car_count;
static volatile int all_quadrant;
static volatile int car_locations[NCARS];
static volatile int car_directions[NCARS];
static volatile int car_turns[NCARS];
static volatile int car_turn_times[NCARS];
static volatile void* car_threads[NCARS];
static
void
initialize_car_thread(uint32_t index, uint32_t direction, uint32_t turn) {
initialize_thread(car_threads, index);
car_directions[index] = direction;
car_turns[index] = turn;
car_turn_times[index] = 0;
}
static
void
check_intersection() {
int n = 0;
for (int i = 0; i < NUM_QUADRANTS; i++) {
failif((quadrant_array[i] > 1), "failed: collision");
n += quadrant_array[i];
}
max_car_count = n > max_car_count ? n : max_car_count;
}
/*
* When car move, must call this function and hold a lock.
* It first checks current intersection status make sure no more than one car in one quadrant.
* Then it removes current car from previous location.
* In the end, it returns current car's index for inQuadrant, to let inQuadrant update car_locations array.
*/
static
int
move(uint32_t index) {
check_thread(car_threads, index);
check_intersection();
int pre_location = car_locations[index];
if (pre_location != UNKNOWN_CAR && pre_location != PASSED_CAR) {
quadrant_array[pre_location]--;
}
return pre_location;
}
static
void
turnright_wrapper(void *index, unsigned long direction)
{
random_yielder(4);
lock_acquire(testlock);
initialize_car_thread((uint32_t)index, (uint32_t)direction, TURN_RIGHT);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, testlock);
} else {
cv_wait(startcv, testlock);
}
lock_release(testlock);
turnright((uint32_t)direction, (uint32_t)index);
V(endsem);
return;
}
static
void
gostraight_wrapper(void *index, unsigned long direction)
{
random_yielder(4);
lock_acquire(testlock);
initialize_car_thread((uint32_t)index, (uint32_t)direction, GO_STRAIGHT);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, testlock);
} else {
cv_wait(startcv, testlock);
}
lock_release(testlock);
gostraight((uint32_t)direction, (uint32_t)index);
V(endsem);
return;
}
static
void
turnleft_wrapper(void *index, unsigned long direction)
{
random_yielder(4);
lock_acquire(testlock);
initialize_car_thread((uint32_t)index, (uint32_t)direction, TURN_LEFT);
startcount--;
if (startcount == 0) {
cv_broadcast(startcv, testlock);
} else {
cv_wait(startcv, testlock);
}
lock_release(testlock);
turnleft((uint32_t)direction, (uint32_t)index);
V(endsem);
return;
}
void
inQuadrant(int quadrant, uint32_t index) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
lock_acquire(testlock);
int pre_quadrant = move(index);
int target_quadrant = car_directions[index];
switch (car_turn_times[index]) {
case 0:
failif((pre_quadrant != UNKNOWN_CAR), "failed: invalid turn");
break;
case 1:
failif((pre_quadrant != target_quadrant), "failed: invalid turn");
target_quadrant = (target_quadrant + NUM_QUADRANTS - 1) % NUM_QUADRANTS;
break;
case 2:
target_quadrant = (target_quadrant + NUM_QUADRANTS - 1) % NUM_QUADRANTS;
failif((pre_quadrant != target_quadrant), "failed: invalid turn");
target_quadrant = (target_quadrant + NUM_QUADRANTS - 1) % NUM_QUADRANTS;
break;
default:
failif(true, "failed: invalid turn");
break;
}
failif((quadrant != target_quadrant), "failed: invalid turn");
car_turn_times[index]++;
failif((quadrant_array[quadrant] > 0), "failed: collision");
quadrant_array[quadrant]++;
car_locations[index] = quadrant;
all_quadrant++;
lock_release(testlock);
kprintf_n("%s in quadrant %d\n", curthread->t_name, quadrant);
}
void
leaveIntersection(uint32_t index) {
random_yielder(PROBLEMS_MAX_YIELDER);
random_spinner(PROBLEMS_MAX_SPINNER);
lock_acquire(testlock);
move(index);
switch (car_turns[index]) {
case GO_STRAIGHT:
failif((car_turn_times[index] != 2), "failed: incorrect turn");
break;
case TURN_LEFT:
failif((car_turn_times[index] != 3), "failed: incorrect turn");
break;
case TURN_RIGHT:
failif((car_turn_times[index] != 1), "failed: incorrect turn");
break;
default:
failif(true, "failed: incorrect turn");
break;
}
car_locations[index] = PASSED_CAR;
lock_release(testlock);
kprintf_n("%s left the intersection\n", curthread->t_name);
}
int stoplight(int nargs, char **args) {
(void) nargs;
(void) args;
int i, direction, turn, err = 0;
char name[32];
int required_quadrant = 0;
int passed = 0;
max_car_count = 0;
all_quadrant = 0;
kprintf_n("Starting sp2...\n");
kprintf_n("If this tests hangs, your solution is incorrect.\n");
for (i = 0; i < NUM_QUADRANTS; i++) {
quadrant_array[i] = 0;
}
for (i = 0; i < NCARS; i++) {
car_locations[i] = UNKNOWN_CAR;
car_threads[i] = NULL;
car_directions[i] = -1;
}
startcount = NCARS;
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("sp2: lock_create failed\n");
}
startcv = cv_create("startcv");
if (startcv == NULL) {
panic("sp2: cv_create failed\n");
}
endsem = sem_create("endsem", 0);
if (endsem == NULL) {
panic("sp2: sem_create failed\n");
}
spinlock_init(&status_lock);
test_status = TEST161_SUCCESS;
stoplight_init();
for (i = 0; i < NCARS; i++) {
kprintf_t(".");
direction = random() % 4;
turn = random() % 3;
snprintf(name, sizeof(name), "Car Thread %d", i);
switch (turn) {
case GO_STRAIGHT:
err = thread_fork(name, NULL, gostraight_wrapper, (void *)i, direction);
required_quadrant += 2;
break;
case TURN_LEFT:
err = thread_fork(name, NULL, turnleft_wrapper, (void *)i, direction);
required_quadrant += 3;
break;
case TURN_RIGHT:
err = thread_fork(name, NULL, turnright_wrapper, (void *)i, direction);
required_quadrant += 1;
break;
}
if (err) {
panic("sp2: thread_fork failed: (%s)\n", strerror(err));
}
}
for (i = 0; i < NCARS; i++) {
kprintf_t(".");
P(endsem);
}
stoplight_cleanup();
for (i = 0; i < NCARS; i++) {
passed += car_locations[i] == PASSED_CAR ? 1 : 0;
}
if ((test_status == TEST161_SUCCESS) &&
(!(failif((passed != NCARS), "failed: not enough cars"))) &&
(!(failif((all_quadrant != required_quadrant), "failed: didn't do the right turns"))) &&
(!(failif((max_car_count <= 1), "failed: no concurrency achieved")))) {};
lock_destroy(testlock);
cv_destroy(startcv);
sem_destroy(endsem);
kprintf_t("\n");
if (test_status != TEST161_SUCCESS) {
secprintf(SECRET, test_message, "sp2");
}
success(test_status, SECRET, "sp2");
return 0;
}

View File

@ -29,9 +29,6 @@
/* /*
* Synchronization test code. * Synchronization test code.
*
* All the contents of this file are overwritten during automated
* testing. Please consider this before changing anything in this file.
*/ */
#include <types.h> #include <types.h>
@ -40,462 +37,222 @@
#include <thread.h> #include <thread.h>
#include <synch.h> #include <synch.h>
#include <test.h> #include <test.h>
#include <kern/test161.h>
#include <spinlock.h>
#define CREATELOOPS 8
#define NSEMLOOPS 63 #define NSEMLOOPS 63
#define NLOCKLOOPS 120 #define NLOCKLOOPS 120
#define NCVLOOPS 5 #define NCVLOOPS 5
#define NTHREADS 32 #define NTHREADS 32
#define SYNCHTEST_YIELDER_MAX 16
static volatile unsigned long testval1; static volatile unsigned long testval1;
static volatile unsigned long testval2; static volatile unsigned long testval2;
static volatile unsigned long testval3; static volatile unsigned long testval3;
static volatile int32_t testval4; static struct semaphore *testsem;
static struct lock *testlock;
static struct semaphore *testsem = NULL; static struct cv *testcv;
static struct semaphore *testsem2 = NULL; static struct semaphore *donesem;
static struct lock *testlock = NULL;
static struct lock *testlock2 = NULL;
static struct cv *testcv = NULL;
static struct semaphore *donesem = NULL;
struct spinlock status_lock;
static bool test_status = TEST161_FAIL;
static unsigned long semtest_current;
static static
bool void
failif(bool condition) { inititems(void)
if (condition) { {
spinlock_acquire(&status_lock); if (testsem==NULL) {
test_status = TEST161_FAIL; testsem = sem_create("testsem", 2);
spinlock_release(&status_lock); if (testsem == NULL) {
panic("synchtest: sem_create failed\n");
}
}
if (testlock==NULL) {
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("synchtest: lock_create failed\n");
}
}
if (testcv==NULL) {
testcv = cv_create("testlock");
if (testcv == NULL) {
panic("synchtest: cv_create failed\n");
}
}
if (donesem==NULL) {
donesem = sem_create("donesem", 0);
if (donesem == NULL) {
panic("synchtest: sem_create failed\n");
}
} }
return condition;
} }
static static
void void
semtestthread(void *junk, unsigned long num) semtestthread(void *junk, unsigned long num)
{ {
(void)junk;
int i; int i;
(void)junk;
random_yielder(4);
/* /*
* Only one of these should print at a time. * Only one of these should print at a time.
*/ */
P(testsem); P(testsem);
semtest_current = num; kprintf("Thread %2lu: ", num);
kprintf_n("Thread %2lu: ", num);
for (i=0; i<NSEMLOOPS; i++) { for (i=0; i<NSEMLOOPS; i++) {
kprintf_t("."); kprintf("%c", (int)num+64);
kprintf_n("%2lu", num);
random_yielder(4);
failif((semtest_current != num));
} }
kprintf_n("\n"); kprintf("\n");
V(donesem); V(donesem);
} }
int int
semtest(int nargs, char **args) semtest(int nargs, char **args)
{ {
int i, result;
(void)nargs; (void)nargs;
(void)args; (void)args;
int i, result; inititems();
kprintf("Starting semaphore test...\n");
kprintf_n("Starting sem1...\n"); kprintf("If this hangs, it's broken: ");
for (i=0; i<CREATELOOPS; i++) {
kprintf_t(".");
testsem = sem_create("testsem", 2);
if (testsem == NULL) {
panic("sem1: sem_create failed\n");
}
donesem = sem_create("donesem", 0);
if (donesem == NULL) {
panic("sem1: sem_create failed\n");
}
if (i != CREATELOOPS - 1) {
sem_destroy(testsem);
sem_destroy(donesem);
}
}
spinlock_init(&status_lock);
test_status = TEST161_SUCCESS;
kprintf_n("If this hangs, it's broken: ");
P(testsem); P(testsem);
P(testsem); P(testsem);
kprintf_n("OK\n"); kprintf("ok\n");
kprintf_t(".");
for (i=0; i<NTHREADS; i++) { for (i=0; i<NTHREADS; i++) {
kprintf_t(".");
result = thread_fork("semtest", NULL, semtestthread, NULL, i); result = thread_fork("semtest", NULL, semtestthread, NULL, i);
if (result) { if (result) {
panic("sem1: thread_fork failed: %s\n", panic("semtest: thread_fork failed: %s\n",
strerror(result)); strerror(result));
} }
} }
for (i=0; i<NTHREADS; i++) { for (i=0; i<NTHREADS; i++) {
kprintf_t(".");
V(testsem); V(testsem);
P(donesem); P(donesem);
} }
sem_destroy(testsem); /* so we can run it again */
sem_destroy(donesem); V(testsem);
testsem = donesem = NULL; V(testsem);
kprintf_t("\n");
success(test_status, SECRET, "sem1");
kprintf("Semaphore test done.\n");
return 0; return 0;
} }
static
void
fail(unsigned long num, const char *msg)
{
kprintf("thread %lu: Mismatch on %s\n", num, msg);
kprintf("Test failed\n");
lock_release(testlock);
V(donesem);
thread_exit();
}
static static
void void
locktestthread(void *junk, unsigned long num) locktestthread(void *junk, unsigned long num)
{ {
int i;
(void)junk; (void)junk;
int i;
for (i=0; i<NLOCKLOOPS; i++) { for (i=0; i<NLOCKLOOPS; i++) {
kprintf_t(".");
KASSERT(!(lock_do_i_hold(testlock)));
lock_acquire(testlock); lock_acquire(testlock);
KASSERT(lock_do_i_hold(testlock));
random_yielder(4);
testval1 = num; testval1 = num;
testval2 = num*num; testval2 = num*num;
testval3 = num%3; testval3 = num%3;
if (testval2 != testval1*testval1) { if (testval2 != testval1*testval1) {
goto fail; fail(num, "testval2/testval1");
} }
random_yielder(4);
KASSERT(lock_do_i_hold(testlock));
if (testval2%3 != (testval3*testval3)%3) { if (testval2%3 != (testval3*testval3)%3) {
goto fail; fail(num, "testval2/testval3");
} }
random_yielder(4);
KASSERT(lock_do_i_hold(testlock));
if (testval3 != testval1%3) { if (testval3 != testval1%3) {
goto fail; fail(num, "testval3/testval1");
} }
random_yielder(4);
KASSERT(lock_do_i_hold(testlock));
if (testval1 != num) { if (testval1 != num) {
goto fail; fail(num, "testval1/num");
} }
random_yielder(4);
KASSERT(lock_do_i_hold(testlock));
if (testval2 != num*num) { if (testval2 != num*num) {
goto fail; fail(num, "testval2/num");
} }
random_yielder(4);
KASSERT(lock_do_i_hold(testlock));
if (testval3 != num%3) { if (testval3 != num%3) {
goto fail; fail(num, "testval3/num");
} }
random_yielder(4);
KASSERT(lock_do_i_hold(testlock));
if (!(lock_do_i_hold(testlock))) {
goto fail;
}
random_yielder(4);
KASSERT(lock_do_i_hold(testlock));
lock_release(testlock); lock_release(testlock);
KASSERT(!(lock_do_i_hold(testlock)));
} }
/* Check for solutions that don't track ownership properly */
for (i=0; i<NLOCKLOOPS; i++) {
kprintf_t(".");
if (lock_do_i_hold(testlock)) {
goto fail2;
}
}
V(donesem); V(donesem);
return;
fail:
lock_release(testlock);
fail2:
failif(true);
V(donesem);
return;
} }
int int
locktest(int nargs, char **args) locktest(int nargs, char **args)
{ {
int i, result;
(void)nargs; (void)nargs;
(void)args; (void)args;
int i, result; inititems();
kprintf("Starting lock test...\n");
kprintf_n("Starting lt1...\n");
for (i=0; i<CREATELOOPS; i++) {
kprintf_t(".");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("lt1: lock_create failed\n");
}
donesem = sem_create("donesem", 0);
if (donesem == NULL) {
panic("lt1: sem_create failed\n");
}
if (i != CREATELOOPS - 1) {
lock_destroy(testlock);
sem_destroy(donesem);
}
}
spinlock_init(&status_lock);
test_status = TEST161_SUCCESS;
for (i=0; i<NTHREADS; i++) { for (i=0; i<NTHREADS; i++) {
kprintf_t("."); result = thread_fork("synchtest", NULL, locktestthread,
result = thread_fork("synchtest", NULL, locktestthread, NULL, i); NULL, i);
if (result) { if (result) {
panic("lt1: thread_fork failed: %s\n", strerror(result)); panic("locktest: thread_fork failed: %s\n",
strerror(result));
} }
} }
for (i=0; i<NTHREADS; i++) { for (i=0; i<NTHREADS; i++) {
kprintf_t(".");
P(donesem); P(donesem);
} }
lock_destroy(testlock); kprintf("Lock test done.\n");
sem_destroy(donesem);
testlock = NULL;
donesem = NULL;
kprintf_t("\n");
success(test_status, SECRET, "lt1");
return 0; return 0;
} }
/*
* Note that the following tests that panic on success do minimal cleanup
* afterward. This is to avoid causing a panic that could be unintentiontally
* considered a success signal by test161. As a result, they leak memory,
* don't destroy synchronization primitives, etc.
*/
int
locktest2(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("Starting lt2...\n");
kprintf_n("(This test panics on success!)\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("lt2: lock_create failed\n");
}
secprintf(SECRET, "Should panic...", "lt2");
lock_release(testlock);
/* Should not get here on success. */
success(TEST161_FAIL, SECRET, "lt2");
/* Don't do anything that could panic. */
testlock = NULL;
return 0;
}
int
locktest3(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("Starting lt3...\n");
kprintf_n("(This test panics on success!)\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("lt3: lock_create failed\n");
}
secprintf(SECRET, "Should panic...", "lt3");
lock_acquire(testlock);
lock_destroy(testlock);
/* Should not get here on success. */
success(TEST161_FAIL, SECRET, "lt3");
/* Don't do anything that could panic. */
testlock = NULL;
return 0;
}
/*
* Used by both lt4 and lt5 below. Simply acquires a lock in a separate
* thread. Uses a semaphore as a barrier to make sure it gets the lock before
* the driver completes.
*/
static
void
locktestacquirer(void * junk, unsigned long num)
{
(void)junk;
(void)num;
lock_acquire(testlock);
V(donesem);
return;
}
int
locktest4(int nargs, char **args) {
(void) nargs;
(void) args;
int result;
kprintf_n("Starting lt4...\n");
kprintf_n("(This test panics on success!)\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("lt4: lock_create failed\n");
}
donesem = sem_create("donesem", 0);
if (donesem == NULL) {
lock_destroy(testlock);
panic("lt4: sem_create failed\n");
}
result = thread_fork("lt4", NULL, locktestacquirer, NULL, 0);
if (result) {
panic("lt4: thread_fork failed: %s\n", strerror(result));
}
P(donesem);
secprintf(SECRET, "Should panic...", "lt4");
lock_release(testlock);
/* Should not get here on success. */
success(TEST161_FAIL, SECRET, "lt4");
/* Don't do anything that could panic. */
testlock = NULL;
donesem = NULL;
return 0;
}
int
locktest5(int nargs, char **args) {
(void) nargs;
(void) args;
int result;
kprintf_n("Starting lt5...\n");
kprintf_n("(This test panics on success!)\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("lt5: lock_create failed\n");
}
donesem = sem_create("donesem", 0);
if (donesem == NULL) {
lock_destroy(testlock);
panic("lt5: sem_create failed\n");
}
result = thread_fork("lt5", NULL, locktestacquirer, NULL, 0);
if (result) {
panic("lt5: thread_fork failed: %s\n", strerror(result));
}
P(donesem);
secprintf(SECRET, "Should panic...", "lt5");
KASSERT(lock_do_i_hold(testlock));
/* Should not get here on success. */
success(TEST161_FAIL, SECRET, "lt5");
/* Don't do anything that could panic. */
testlock = NULL;
donesem = NULL;
return 0;
}
static static
void void
cvtestthread(void *junk, unsigned long num) cvtestthread(void *junk, unsigned long num)
{ {
(void)junk;
int i; int i;
volatile int j; volatile int j;
struct timespec ts1, ts2; struct timespec ts1, ts2;
(void)junk;
for (i=0; i<NCVLOOPS; i++) { for (i=0; i<NCVLOOPS; i++) {
kprintf_t(".");
lock_acquire(testlock); lock_acquire(testlock);
while (testval1 != num) { while (testval1 != num) {
testval2 = 0;
random_yielder(4);
gettime(&ts1); gettime(&ts1);
cv_wait(testcv, testlock); cv_wait(testcv, testlock);
gettime(&ts2); gettime(&ts2);
random_yielder(4);
/* ts2 -= ts1 */ /* ts2 -= ts1 */
timespec_sub(&ts2, &ts1, &ts2); timespec_sub(&ts2, &ts1, &ts2);
/* Require at least 2000 cpu cycles (we're 25mhz) */ /* Require at least 2000 cpu cycles (we're 25mhz) */
if (ts2.tv_sec == 0 && ts2.tv_nsec < 40*2000) { if (ts2.tv_sec == 0 && ts2.tv_nsec < 40*2000) {
kprintf_n("cv_wait took only %u ns\n", ts2.tv_nsec); kprintf("cv_wait took only %u ns\n",
kprintf_n("That's too fast... you must be busy-looping\n"); ts2.tv_nsec);
failif(true); kprintf("That's too fast... you must be "
"busy-looping\n");
V(donesem); V(donesem);
thread_exit(); thread_exit();
} }
testval2 = 0xFFFFFFFF;
} }
testval2 = num; kprintf("Thread %lu\n", num);
testval1 = (testval1 + NTHREADS - 1)%NTHREADS;
/* /*
* loop a little while to make sure we can measure the * loop a little while to make sure we can measure the
@ -503,13 +260,7 @@ cvtestthread(void *junk, unsigned long num)
*/ */
for (j=0; j<3000; j++); for (j=0; j<3000; j++);
random_yielder(4);
cv_broadcast(testcv, testlock); cv_broadcast(testcv, testlock);
random_yielder(4);
failif((testval1 != testval2));
kprintf_n("Thread %lu\n", testval2);
testval1 = (testval1 + NTHREADS - 1) % NTHREADS;
lock_release(testlock); lock_release(testlock);
} }
V(donesem); V(donesem);
@ -518,57 +269,30 @@ cvtestthread(void *junk, unsigned long num)
int int
cvtest(int nargs, char **args) cvtest(int nargs, char **args)
{ {
(void)nargs;
(void)args;
int i, result; int i, result;
kprintf_n("Starting cvt1...\n"); (void)nargs;
for (i=0; i<CREATELOOPS; i++) { (void)args;
kprintf_t(".");
testlock = lock_create("testlock"); inititems();
if (testlock == NULL) { kprintf("Starting CV test...\n");
panic("cvt1: lock_create failed\n"); kprintf("Threads should print out in reverse order.\n");
}
testcv = cv_create("testcv");
if (testcv == NULL) {
panic("cvt1: cv_create failed\n");
}
donesem = sem_create("donesem", 0);
if (donesem == NULL) {
panic("cvt1: sem_create failed\n");
}
if (i != CREATELOOPS - 1) {
lock_destroy(testlock);
cv_destroy(testcv);
sem_destroy(donesem);
}
}
spinlock_init(&status_lock);
test_status = TEST161_SUCCESS;
testval1 = NTHREADS-1; testval1 = NTHREADS-1;
for (i=0; i<NTHREADS; i++) { for (i=0; i<NTHREADS; i++) {
kprintf_t("."); result = thread_fork("synchtest", NULL, cvtestthread, NULL, i);
result = thread_fork("cvt1", NULL, cvtestthread, NULL, (long unsigned) i);
if (result) { if (result) {
panic("cvt1: thread_fork failed: %s\n", strerror(result)); panic("cvtest: thread_fork failed: %s\n",
strerror(result));
} }
} }
for (i=0; i<NTHREADS; i++) { for (i=0; i<NTHREADS; i++) {
kprintf_t(".");
P(donesem); P(donesem);
} }
lock_destroy(testlock); kprintf("CV test done\n");
cv_destroy(testcv);
sem_destroy(donesem);
testlock = NULL;
testcv = NULL;
donesem = NULL;
kprintf_t("\n");
success(test_status, SECRET, "cvt1");
return 0; return 0;
} }
@ -594,28 +318,19 @@ static
void void
sleepthread(void *junk1, unsigned long junk2) sleepthread(void *junk1, unsigned long junk2)
{ {
unsigned i, j;
(void)junk1; (void)junk1;
(void)junk2; (void)junk2;
unsigned i, j;
random_yielder(4);
for (j=0; j<NLOOPS; j++) { for (j=0; j<NLOOPS; j++) {
kprintf_t(".");
for (i=0; i<NCVS; i++) { for (i=0; i<NCVS; i++) {
lock_acquire(testlocks[i]); lock_acquire(testlocks[i]);
random_yielder(4);
V(gatesem); V(gatesem);
random_yielder(4);
spinlock_acquire(&status_lock);
testval4++;
spinlock_release(&status_lock);
cv_wait(testcvs[i], testlocks[i]); cv_wait(testcvs[i], testlocks[i]);
random_yielder(4);
lock_release(testlocks[i]); lock_release(testlocks[i]);
} }
kprintf_n("sleepthread: %u\n", j); kprintf("sleepthread: %u\n", j);
} }
V(exitsem); V(exitsem);
} }
@ -624,28 +339,19 @@ static
void void
wakethread(void *junk1, unsigned long junk2) wakethread(void *junk1, unsigned long junk2)
{ {
unsigned i, j;
(void)junk1; (void)junk1;
(void)junk2; (void)junk2;
unsigned i, j;
random_yielder(4);
for (j=0; j<NLOOPS; j++) { for (j=0; j<NLOOPS; j++) {
kprintf_t(".");
for (i=0; i<NCVS; i++) { for (i=0; i<NCVS; i++) {
random_yielder(4);
P(gatesem); P(gatesem);
random_yielder(4);
lock_acquire(testlocks[i]); lock_acquire(testlocks[i]);
random_yielder(4);
testval4--;
failif((testval4 != 0));
cv_signal(testcvs[i], testlocks[i]); cv_signal(testcvs[i], testlocks[i]);
random_yielder(4);
lock_release(testlocks[i]); lock_release(testlocks[i]);
} }
kprintf_n("wakethread: %u\n", j); kprintf("wakethread: %u\n", j);
} }
V(exitsem); V(exitsem);
} }
@ -653,44 +359,30 @@ wakethread(void *junk1, unsigned long junk2)
int int
cvtest2(int nargs, char **args) cvtest2(int nargs, char **args)
{ {
(void)nargs;
(void)args;
unsigned i; unsigned i;
int result; int result;
kprintf_n("Starting cvt2...\n"); (void)nargs;
for (i=0; i<CREATELOOPS; i++) { (void)args;
kprintf_t(".");
gatesem = sem_create("gatesem", 0);
if (gatesem == NULL) {
panic("cvt2: sem_create failed\n");
}
exitsem = sem_create("exitsem", 0);
if (exitsem == NULL) {
panic("cvt2: sem_create failed\n");
}
if (i != CREATELOOPS - 1) {
sem_destroy(gatesem);
sem_destroy(exitsem);
}
}
for (i=0; i<NCVS; i++) { for (i=0; i<NCVS; i++) {
kprintf_t(".");
testlocks[i] = lock_create("cvtest2 lock"); testlocks[i] = lock_create("cvtest2 lock");
testcvs[i] = cv_create("cvtest2 cv"); testcvs[i] = cv_create("cvtest2 cv");
} }
spinlock_init(&status_lock); gatesem = sem_create("gatesem", 0);
test_status = TEST161_SUCCESS; exitsem = sem_create("exitsem", 0);
result = thread_fork("cvt2", NULL, sleepthread, NULL, 0); kprintf("cvtest2...\n");
result = thread_fork("cvtest2", NULL, sleepthread, NULL, 0);
if (result) { if (result) {
panic("cvt2: thread_fork failed\n"); panic("cvtest2: thread_fork failed\n");
} }
result = thread_fork("cvt2", NULL, wakethread, NULL, 0); result = thread_fork("cvtest2", NULL, wakethread, NULL, 0);
if (result) { if (result) {
panic("cvt2: thread_fork failed\n"); panic("cvtest2: thread_fork failed\n");
} }
P(exitsem); P(exitsem);
P(exitsem); P(exitsem);
@ -698,194 +390,12 @@ cvtest2(int nargs, char **args)
sem_destroy(gatesem); sem_destroy(gatesem);
exitsem = gatesem = NULL; exitsem = gatesem = NULL;
for (i=0; i<NCVS; i++) { for (i=0; i<NCVS; i++) {
kprintf_t(".");
lock_destroy(testlocks[i]); lock_destroy(testlocks[i]);
cv_destroy(testcvs[i]); cv_destroy(testcvs[i]);
testlocks[i] = NULL; testlocks[i] = NULL;
testcvs[i] = NULL; testcvs[i] = NULL;
} }
kprintf_t("\n"); kprintf("cvtest2 done\n");
success(test_status, SECRET, "cvt2");
return 0;
}
int
cvtest3(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("Starting cvt3...\n");
kprintf_n("(This test panics on success!)\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("cvt3: lock_create failed\n");
}
testcv = cv_create("testcv");
if (testcv == NULL) {
panic("cvt3: cv_create failed\n");
}
secprintf(SECRET, "Should panic...", "cvt3");
cv_wait(testcv, testlock);
/* Should not get here on success. */
success(TEST161_FAIL, SECRET, "cvt3");
lock_destroy(testlock);
cv_destroy(testcv);
testcv = NULL;
testlock = NULL;
return 0;
}
int
cvtest4(int nargs, char **args) {
(void)nargs;
(void)args;
kprintf_n("Starting cvt4...\n");
kprintf_n("(This test panics on success!)\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("cvt4: lock_create failed\n");
}
testcv = cv_create("testcv");
if (testcv == NULL) {
panic("cvt4: cv_create failed\n");
}
secprintf(SECRET, "Should panic...", "cvt4");
cv_broadcast(testcv, testlock);
/* Should not get here on success. */
success(TEST161_FAIL, SECRET, "cvt4");
lock_destroy(testlock);
cv_destroy(testcv);
testcv = NULL;
testlock = NULL;
return 0;
}
static
void
sleeperthread(void *junk1, unsigned long junk2) {
(void)junk1;
(void)junk2;
random_yielder(4);
lock_acquire(testlock);
random_yielder(4);
failif((testval1 != 0));
testval1 = 1;
cv_signal(testcv, testlock);
random_yielder(4);
cv_wait(testcv, testlock);
failif((testval1 != 3));
testval1 = 4;
random_yielder(4);
lock_release(testlock);
random_yielder(4);
V(exitsem);
}
static
void
wakerthread(void *junk1, unsigned long junk2) {
(void)junk1;
(void)junk2;
random_yielder(4);
lock_acquire(testlock2);
failif((testval1 != 2));
testval1 = 3;
random_yielder(4);
cv_signal(testcv, testlock2);
random_yielder(4);
lock_release(testlock2);
random_yielder(4);
V(exitsem);
}
int
cvtest5(int nargs, char **args) {
(void)nargs;
(void)args;
int result;
kprintf_n("Starting cvt5...\n");
testlock = lock_create("testlock");
if (testlock == NULL) {
panic("cvt5: lock_create failed\n");
}
testlock2 = lock_create("testlock2");
if (testlock == NULL) {
panic("cvt5: lock_create failed\n");
}
testcv = cv_create("testcv");
if (testcv == NULL) {
panic("cvt5: cv_create failed\n");
}
exitsem = sem_create("exitsem", 0);
if (exitsem == NULL) {
panic("cvt5: sem_create failed\n");
}
spinlock_init(&status_lock);
test_status = TEST161_SUCCESS;
testval1 = 0;
lock_acquire(testlock);
lock_acquire(testlock2);
result = thread_fork("cvt5", NULL, sleeperthread, NULL, 0);
if (result) {
panic("cvt5: thread_fork failed\n");
}
result = thread_fork("cvt5", NULL, wakerthread, NULL, 0);
if (result) {
panic("cvt5: thread_fork failed\n");
}
random_yielder(4);
cv_wait(testcv, testlock);
failif((testval1 != 1));
testval1 = 2;
random_yielder(4);
lock_release(testlock);
random_yielder(4);
lock_release(testlock2);
P(exitsem);
P(exitsem);
failif((testval1 != 4));
sem_destroy(exitsem);
cv_destroy(testcv);
lock_destroy(testlock2);
lock_destroy(testlock);
success(test_status, SECRET, "cvt5");
exitsem = NULL;
testcv = NULL;
testlock2 = NULL;
testlock = NULL;
testsem2 = NULL;
testsem = NULL;
return 0; return 0;
} }

View File

@ -66,7 +66,10 @@ fakethread_create(const char *name)
} }
/* ignore most of the fields, zero everything for tidiness */ /* ignore most of the fields, zero everything for tidiness */
bzero(t, sizeof(*t)); bzero(t, sizeof(*t));
strcpy(t->t_name, name); t->t_name = kstrdup(name);
if (t->t_name == NULL) {
panic("threadlisttest: Out of memory\n");
}
t->t_stack = FAKE_MAGIC; t->t_stack = FAKE_MAGIC;
threadlistnode_init(&t->t_listnode, t); threadlistnode_init(&t->t_listnode, t);
return t; return t;
@ -81,6 +84,7 @@ fakethread_destroy(struct thread *t)
{ {
KASSERT(t->t_stack == FAKE_MAGIC); KASSERT(t->t_stack == FAKE_MAGIC);
threadlistnode_cleanup(&t->t_listnode); threadlistnode_cleanup(&t->t_listnode);
kfree(t->t_name);
kfree(t); kfree(t);
} }

View File

@ -44,226 +44,197 @@
// //
// Semaphore. // Semaphore.
struct semaphore * struct semaphore *sem_create(const char *name, unsigned initial_count) {
sem_create(const char *name, unsigned initial_count) struct semaphore *sem;
{
struct semaphore *sem;
sem = kmalloc(sizeof(*sem)); sem = kmalloc(sizeof(*sem));
if (sem == NULL) { if (sem == NULL) {
return NULL; return NULL;
} }
sem->sem_name = kstrdup(name); sem->sem_name = kstrdup(name);
if (sem->sem_name == NULL) { if (sem->sem_name == NULL) {
kfree(sem); kfree(sem);
return NULL; return NULL;
} }
sem->sem_wchan = wchan_create(sem->sem_name); sem->sem_wchan = wchan_create(sem->sem_name);
if (sem->sem_wchan == NULL) { if (sem->sem_wchan == NULL) {
kfree(sem->sem_name); kfree(sem->sem_name);
kfree(sem); kfree(sem);
return NULL; return NULL;
} }
spinlock_init(&sem->sem_lock); spinlock_init(&sem->sem_lock);
sem->sem_count = initial_count; sem->sem_count = initial_count;
return sem; return sem;
} }
void void sem_destroy(struct semaphore *sem) {
sem_destroy(struct semaphore *sem) KASSERT(sem != NULL);
{
KASSERT(sem != NULL);
/* wchan_cleanup will assert if anyone's waiting on it */ /* wchan_cleanup will assert if anyone's waiting on it */
spinlock_cleanup(&sem->sem_lock); spinlock_cleanup(&sem->sem_lock);
wchan_destroy(sem->sem_wchan); wchan_destroy(sem->sem_wchan);
kfree(sem->sem_name); kfree(sem->sem_name);
kfree(sem); kfree(sem);
} }
void void P(struct semaphore *sem) {
P(struct semaphore *sem) KASSERT(sem != NULL);
{
KASSERT(sem != NULL);
/* /*
* May not block in an interrupt handler. * May not block in an interrupt handler.
* *
* For robustness, always check, even if we can actually * For robustness, always check, even if we can actually
* complete the P without blocking. * complete the P without blocking.
*/ */
KASSERT(curthread->t_in_interrupt == false); KASSERT(curthread->t_in_interrupt == false);
/* Use the semaphore spinlock to protect the wchan as well. */ /* Use the semaphore spinlock to protect the wchan as well. */
spinlock_acquire(&sem->sem_lock); spinlock_acquire(&sem->sem_lock);
while (sem->sem_count == 0) { while (sem->sem_count == 0) {
/* /*
* *
* Note that we don't maintain strict FIFO ordering of * Note that we don't maintain strict FIFO ordering of
* threads going through the semaphore; that is, we * threads going through the semaphore; that is, we
* might "get" it on the first try even if other * might "get" it on the first try even if other
* threads are waiting. Apparently according to some * threads are waiting. Apparently according to some
* textbooks semaphores must for some reason have * textbooks semaphores must for some reason have
* strict ordering. Too bad. :-) * strict ordering. Too bad. :-)
* *
* Exercise: how would you implement strict FIFO * Exercise: how would you implement strict FIFO
* ordering? * ordering?
*/ */
wchan_sleep(sem->sem_wchan, &sem->sem_lock); wchan_sleep(sem->sem_wchan, &sem->sem_lock);
} }
KASSERT(sem->sem_count > 0); KASSERT(sem->sem_count > 0);
sem->sem_count--; sem->sem_count--;
spinlock_release(&sem->sem_lock); spinlock_release(&sem->sem_lock);
} }
void void V(struct semaphore *sem) {
V(struct semaphore *sem) KASSERT(sem != NULL);
{
KASSERT(sem != NULL);
spinlock_acquire(&sem->sem_lock); spinlock_acquire(&sem->sem_lock);
sem->sem_count++; sem->sem_count++;
KASSERT(sem->sem_count > 0); KASSERT(sem->sem_count > 0);
wchan_wakeone(sem->sem_wchan, &sem->sem_lock); wchan_wakeone(sem->sem_wchan, &sem->sem_lock);
spinlock_release(&sem->sem_lock); spinlock_release(&sem->sem_lock);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// //
// Lock. // Lock.
struct lock * struct lock *lock_create(const char *name) {
lock_create(const char *name) struct lock *lock;
{
struct lock *lock;
lock = kmalloc(sizeof(*lock)); lock = kmalloc(sizeof(*lock));
if (lock == NULL) { if (lock == NULL) {
return NULL; return NULL;
} }
lock->lk_name = kstrdup(name); lock->lk_name = kstrdup(name);
if (lock->lk_name == NULL) { if (lock->lk_name == NULL) {
kfree(lock); kfree(lock);
return NULL; return NULL;
} }
HANGMAN_LOCKABLEINIT(&lock->lk_hangman, lock->lk_name); HANGMAN_LOCKABLEINIT(&lock->lk_hangman, lock->lk_name);
// add stuff here as needed // add stuff here as needed
return lock; return lock;
} }
void void lock_destroy(struct lock *lock) {
lock_destroy(struct lock *lock) KASSERT(lock != NULL);
{
KASSERT(lock != NULL);
// add stuff here as needed // add stuff here as needed
kfree(lock->lk_name); kfree(lock->lk_name);
kfree(lock); kfree(lock);
} }
void void lock_acquire(struct lock *lock) {
lock_acquire(struct lock *lock) /* Call this (atomically) before waiting for a lock */
{ // HANGMAN_WAIT(&curthread->t_hangman, &lock->lk_hangman);
/* Call this (atomically) before waiting for a lock */
//HANGMAN_WAIT(&curthread->t_hangman, &lock->lk_hangman);
// Write this // Write this
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
/* Call this (atomically) once the lock is acquired */ /* Call this (atomically) once the lock is acquired */
//HANGMAN_ACQUIRE(&curthread->t_hangman, &lock->lk_hangman); // HANGMAN_ACQUIRE(&curthread->t_hangman, &lock->lk_hangman);
} }
void void lock_release(struct lock *lock) {
lock_release(struct lock *lock) /* Call this (atomically) when the lock is released */
{ // HANGMAN_RELEASE(&curthread->t_hangman, &lock->lk_hangman);
/* Call this (atomically) when the lock is released */
//HANGMAN_RELEASE(&curthread->t_hangman, &lock->lk_hangman);
// Write this // Write this
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
} }
bool bool lock_do_i_hold(struct lock *lock) {
lock_do_i_hold(struct lock *lock) // Write this
{
// Write this
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
return true; // dummy until code gets written return true; // dummy until code gets written
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// //
// CV // CV
struct cv *cv_create(const char *name) {
struct cv *cv;
struct cv * cv = kmalloc(sizeof(*cv));
cv_create(const char *name) if (cv == NULL) {
{ return NULL;
struct cv *cv; }
cv = kmalloc(sizeof(*cv)); cv->cv_name = kstrdup(name);
if (cv == NULL) { if (cv->cv_name == NULL) {
return NULL; kfree(cv);
} return NULL;
}
cv->cv_name = kstrdup(name); // add stuff here as needed
if (cv->cv_name==NULL) {
kfree(cv);
return NULL;
}
// add stuff here as needed return cv;
return cv;
} }
void void cv_destroy(struct cv *cv) {
cv_destroy(struct cv *cv) KASSERT(cv != NULL);
{
KASSERT(cv != NULL);
// add stuff here as needed // add stuff here as needed
kfree(cv->cv_name); kfree(cv->cv_name);
kfree(cv); kfree(cv);
} }
void void cv_wait(struct cv *cv, struct lock *lock) {
cv_wait(struct cv *cv, struct lock *lock) // Write this
{ (void)cv; // suppress warning until code gets written
// Write this (void)lock; // suppress warning until code gets written
(void)cv; // suppress warning until code gets written
(void)lock; // suppress warning until code gets written
} }
void void cv_signal(struct cv *cv, struct lock *lock) {
cv_signal(struct cv *cv, struct lock *lock) // Write this
{ (void)cv; // suppress warning until code gets written
// Write this (void)lock; // suppress warning until code gets written
(void)cv; // suppress warning until code gets written
(void)lock; // suppress warning until code gets written
} }
void void cv_broadcast(struct cv *cv, struct lock *lock) {
cv_broadcast(struct cv *cv, struct lock *lock) // Write this
{ (void)cv; // suppress warning until code gets written
// Write this (void)lock; // suppress warning until code gets written
(void)cv; // suppress warning until code gets written
(void)lock; // suppress warning until code gets written
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -49,7 +49,7 @@ Standard C Library (libc, -lc)
<p> <p>
<tt>#include &lt;unistd.h&gt;</tt><br> <tt>#include &lt;unistd.h&gt;</tt><br>
<br> <br>
<tt>void</tt><br> <tt>void,</tt><br>
<tt>_exit(int </tt><em>exitcode</em><tt>);</tt> <tt>_exit(int </tt><em>exitcode</em><tt>);</tt>
</p> </p>

View File

@ -55,8 +55,8 @@ Standard C Library (libc, -lc)
<h3>Description</h3> <h3>Description</h3>
<p> <p>
The file handle identified by file descriptor <em>fd</em> is closed. The file handle <em>fd</em> is closed. The same file handle may then
The same file handle may then be returned again from <A HREF=open.html>open</A>, be returned again from <A HREF=open.html>open</A>,
<A HREF=dup2.html>dup2</A>, <A HREF=pipe.html>pipe</A>, or similar <A HREF=dup2.html>dup2</A>, <A HREF=pipe.html>pipe</A>, or similar
calls. calls.
</p> </p>
@ -87,7 +87,7 @@ mentioned here.
<table width=90%> <table width=90%>
<tr><td width=5% rowspan=10>&nbsp;</td> <tr><td width=5% rowspan=10>&nbsp;</td>
<td width=10%>EBADF</td> <td width=10%>EBADF</td>
<td><em>fd</em> is not a valid file descriptor.</td></tr> <td><em>fd</em> is not a valid file handle.</td></tr>
<tr><td>EIO</td> <td>A hard I/O error occurred.</td></tr> <tr><td>EIO</td> <td>A hard I/O error occurred.</td></tr>
</table> </table>
</p> </p>

View File

@ -55,9 +55,9 @@ Standard C Library (libc, -lc)
<h3>Description</h3> <h3>Description</h3>
<p> <p>
<tt>dup2</tt> clones the file handle identifed by file descriptor <em>oldfd</em> <tt>dup2</tt> clones the file handle <em>oldfd</em> onto the file
onto the file handle identified by <em>newfd</em>. If <em>newfd</em> handle <em>newfd</em>. If <em>newfd</em> names an already-open file,
names an already-open file, that file is closed. that file is closed.
</p> </p>
<p> <p>
@ -74,8 +74,8 @@ dup2 is most commonly used to relocate opened files onto
</p> </p>
<p> <p>
Both file descriptors must be non-negative, and, if applicable, Both filehandles must be non-negative, and, if applicable, smaller
smaller than the maximum allowed file handle number. than the maximum allowed file handle number.
</p> </p>
<p> <p>
@ -116,9 +116,9 @@ here.
<tr><td width=5% rowspan=3>&nbsp;</td> <tr><td width=5% rowspan=3>&nbsp;</td>
<td width=10% valign=top>EBADF</td> <td width=10% valign=top>EBADF</td>
<td><em>oldfd</em> is not a valid file <td><em>oldfd</em> is not a valid file
descriptor, or <em>newfd</em> is a value handle, or <em>newfd</em> is a value
that cannot be a valid file that cannot be a valid file
descriptor.</td></tr> handle.</td></tr>
<tr><td valign=top>EMFILE</td> <td>The process's file table was full, or a <tr><td valign=top>EMFILE</td> <td>The process's file table was full, or a
process-specific limit on open files process-specific limit on open files
was reached.</td></tr> was reached.</td></tr>

View File

@ -57,7 +57,7 @@ struct stat *</tt><em>statbuf</em><tt>);</tt>
<h3>Description</h3> <h3>Description</h3>
<p> <p>
<tt>fstat</tt> retrieves status information about the file referred to <tt>fstat</tt> retrieves status information about the file referred to
by the file descriptor <em>fd</em> and stores it in the stat structure by the file handle <em>fd</em> and stores it in the stat structure
pointed to by <em>statbuf</em>. pointed to by <em>statbuf</em>.
</p> </p>

View File

@ -87,8 +87,8 @@ mentioned here.
<table width=90%> <table width=90%>
<tr><td width=5% rowspan=3>&nbsp;</td> <tr><td width=5% rowspan=3>&nbsp;</td>
<td width=10% valign=top>EBADF</td> <td width=10% valign=top>EBADF</td>
<td><em>fd</em> is not a valid file descriptor, <td><em>fd</em> is not a valid file handle, or
or it is not open for writing.</td></tr> it is not open for writing.</td></tr>
<tr><td valign=top>EIO</td> <td>A hard I/O error occurred.</td></tr> <tr><td valign=top>EIO</td> <td>A hard I/O error occurred.</td></tr>
<tr><td valign=top>EFAULT</td> <td><em>buf</em> points to an invalid <tr><td valign=top>EFAULT</td> <td><em>buf</em> points to an invalid
address.</td></tr> address.</td></tr>

View File

@ -57,7 +57,7 @@ size_t </tt><em>buflen</em><tt>);</tt>
<h3>Description</h3> <h3>Description</h3>
<p> <p>
<tt>getdirentry</tt> retrieves the next filename from a directory <tt>getdirentry</tt> retrieves the next filename from a directory
referred to by the file descriptor <em>fd</em>. The name is stored referred to by the file handle <em>filehandle</em>. The name is stored
in <em>buf</em>, an area of size <em>buflen</em>. The length of of the in <em>buf</em>, an area of size <em>buflen</em>. The length of of the
name actually found is returned. name actually found is returned.
</p> </p>

View File

@ -57,7 +57,7 @@ void *</tt><em>data</em><tt>);</tt>
<h3>Description</h3> <h3>Description</h3>
<p> <p>
<tt>ioctl</tt> performs an object-specific operation <em>code</em> on <tt>ioctl</tt> performs an object-specific operation <em>code</em> on
the object referred to by the file descriptor <em>fd</em>. The the object referred to by the file handle <em>fd</em>. The
<em>data</em> argument may point to supplemental data required or <em>data</em> argument may point to supplemental data required or
returned by the operation. The size of buffer required, if any, and returned by the operation. The size of buffer required, if any, and
other such matters are operation-specific. other such matters are operation-specific.

View File

@ -57,8 +57,8 @@ int </tt><em>whence</em><tt>);</tt>
<h3>Description</h3> <h3>Description</h3>
<p> <p>
<tt>lseek</tt> alters the current seek position of the file handle <tt>lseek</tt> alters the current seek position of the file handle
identified by file descriptor <em>fd</em>, seeking to a new position <em>filehandle</em>, seeking to a new position based on <em>pos</em>
based on <em>pos</em> and <em>whence</em>. and <em>whence</em>.
</p> </p>
<p> <p>
@ -122,7 +122,7 @@ mentioned here.
<tr><td width=5% rowspan=4>&nbsp;</td> <tr><td width=5% rowspan=4>&nbsp;</td>
<td width=10% valign=top>EBADF</td> <td width=10% valign=top>EBADF</td>
<td><em>fd</em> is not a valid file <td><em>fd</em> is not a valid file
descriptor.</td></tr> handle.</td></tr>
<tr><td valign=top>ESPIPE</td> <td><em>fd</em> refers to an object <tr><td valign=top>ESPIPE</td> <td><em>fd</em> refers to an object
which does not support seeking.</td></tr> which does not support seeking.</td></tr>
<tr><td valign=top>EINVAL</td> <td><em>whence</em> is invalid.</td></tr> <tr><td valign=top>EINVAL</td> <td><em>whence</em> is invalid.</td></tr>

View File

@ -99,12 +99,12 @@ course's assignments.)
</p> </p>
<p> <p>
<tt>open</tt> returns a file descriptor suitable for passing to <tt>open</tt> returns a file handle suitable for passing to
<A HREF=read.html>read</A>, <A HREF=read.html>read</A>,
<A HREF=write.html>write</A>, <A HREF=write.html>write</A>,
<A HREF=close.html>close</A>, <A HREF=close.html>close</A>,
etc. This file descriptor must be greater than or equal to zero. Note etc. This file handle must be greater than or equal to zero. Note
that file descriptors 0 (STDIN_FILENO), 1 (STDOUT_FILENO), and 2 that file handles 0 (STDIN_FILENO), 1 (STDOUT_FILENO), and 2
(STDERR_FILENO) are used in special ways and are typically assumed by (STDERR_FILENO) are used in special ways and are typically assumed by
user-level code to always be open. user-level code to always be open.
</p> </p>
@ -128,9 +128,9 @@ contain <tt>..</tt> is usually not quite atomic.
<h3>Return Values</h3> <h3>Return Values</h3>
<p> <p>
On success, <tt>open</tt> returns a nonnegative file descriptor. On On success, <tt>open</tt> returns a nonnegative file handle. On error,
error, -1 is returned, and <A HREF=errno.html>errno</A> is set -1 is returned, and <A HREF=errno.html>errno</A> is set according to
according to the error encountered. the error encountered.
</p> </p>
<h3>Errors</h3> <h3>Errors</h3>

View File

@ -51,7 +51,7 @@ Standard C Library (libc, -lc)
<br> <br>
<tt>ssize_t</tt><br> <tt>ssize_t</tt><br>
<tt>write(int </tt><em>fd</em><tt>, const void *</tt><em>buf</em><tt>, <tt>write(int </tt><em>fd</em><tt>, const void *</tt><em>buf</em><tt>,
size_t </tt><em>buflen</em><tt>);</tt> size_t </tt><em>nbytes</em><tt>);</tt>
</p> </p>
<h3>Description</h3> <h3>Description</h3>

View File

@ -87,6 +87,15 @@
# These build variables can be set explicitly for further control if # These build variables can be set explicitly for further control if
# desired, but should in general not need attention. # desired, but should in general not need attention.
# #
# (Tools.)
#
# PYTHON_INTERPRETER Location of Python interpreter.
# Default is "/usr/bin/env python".
#
# This may need to be changed on some platforms; but the configure
# script is supposed to take care of it for you. If that fails, or
# picks the wrong thing, please file a bug report.
#
# (Locations.) # (Locations.)
# #
# BUILDTOP Top of tree where .o files go. # BUILDTOP Top of tree where .o files go.
@ -470,7 +479,7 @@ MORECFLAGS+=-I$(INSTALLTOP)/include
LDFLAGS+=-nostdlib -L$(INSTALLTOP)/lib $(INSTALLTOP)/lib/crt0.o LDFLAGS+=-nostdlib -L$(INSTALLTOP)/lib $(INSTALLTOP)/lib/crt0.o
MORELIBS+=-lc MORELIBS+=-lc
LIBDEPS+=$(INSTALLTOP)/lib/crt0.o $(INSTALLTOP)/lib/libc.a LIBDEPS+=$(INSTALLTOP)/lib/crt0.o $(INSTALLTOP)/lib/libc.a
LIBS+=-ltest161
############################################################ ############################################################
# end. # end.

View File

@ -56,7 +56,7 @@ all-local: $(MYBUILDDIR) .WAIT $(MYBUILDDIR)/$(_LIB_)
install-staging-local: $(TOOLDIR)/hostlib .WAIT $(TOOLDIR)/hostlib/$(_LIB_) install-staging-local: $(TOOLDIR)/hostlib .WAIT $(TOOLDIR)/hostlib/$(_LIB_)
$(TOOLDIR)/hostlib/$(_LIB_): $(MYBUILDDIR)/$(_LIB_) $(TOOLDIR)/hostlib/$(_LIB_): $(MYBUILDDIR)/$(_LIB_)
rm -f $(.TARGET) rm -f $(.TARGET)
ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) >/dev/null 2>&1 || \ ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) || \
cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET) cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET)
install-local: install-local:

View File

@ -76,14 +76,14 @@ cleanhostprog:
install-staging-local: $(_INSTALLDIR_) .WAIT $(_INSTALLDIR_)/$(_PROG_) install-staging-local: $(_INSTALLDIR_) .WAIT $(_INSTALLDIR_)/$(_PROG_)
$(_INSTALLDIR_)/$(_PROG_): $(MYBUILDDIR)/$(_PROG_) $(_INSTALLDIR_)/$(_PROG_): $(MYBUILDDIR)/$(_PROG_)
rm -f $(.TARGET) rm -f $(.TARGET)
ln $(MYBUILDDIR)/$(_PROG_) $(.TARGET) >/dev/null 2>&1 || \ ln $(MYBUILDDIR)/$(_PROG_) $(.TARGET) || \
cp $(MYBUILDDIR)/$(_PROG_) $(.TARGET) cp $(MYBUILDDIR)/$(_PROG_) $(.TARGET)
.if defined(HOSTBINDIR) .if defined(HOSTBINDIR)
install-local: install-hostprog install-local: install-hostprog
install-hostprog: $(OSTREE)$(HOSTBINDIR) $(MYBUILDDIR)/$(_PROG_) install-hostprog: $(OSTREE)$(HOSTBINDIR) $(MYBUILDDIR)/$(_PROG_)
rm -f $(OSTREE)$(HOSTBINDIR)/$(_PROG_) rm -f $(OSTREE)$(HOSTBINDIR)/$(_PROG_)
ln $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) >/dev/null 2>&1 || \ ln $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) || \
cp $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_) cp $(MYBUILDDIR)/$(_PROG_) $(OSTREE)$(HOSTBINDIR)/$(_PROG_)
.else .else
install-local: install-local:

View File

@ -163,9 +163,6 @@ includelinks:
clean: clean:
rm -f *.o *.a tags $(KERNEL) rm -f *.o *.a tags $(KERNEL)
rm -rf includelinks rm -rf includelinks
@ABSTOP=$$(readlink -f $(TOP))
rm -f $(OSTREE)/.src
rm -f $(TOP)/.root
distclean cleandir: clean distclean cleandir: clean
rm -f .depend rm -f .depend
@ -191,9 +188,6 @@ install:
cp $(KERNEL) $(OSTREE)/$(KERNEL)-$(CONFNAME) cp $(KERNEL) $(OSTREE)/$(KERNEL)-$(CONFNAME)
-rm -f $(OSTREE)/$(KERNEL) -rm -f $(OSTREE)/$(KERNEL)
ln -s $(KERNEL)-$(CONFNAME) $(OSTREE)/$(KERNEL) ln -s $(KERNEL)-$(CONFNAME) $(OSTREE)/$(KERNEL)
@ABSTOP=$$(readlink -f $(TOP))
ln -Tsf $(ABSTOP) $(OSTREE)/.src
ln -Tsf $(OSTREE) $(ABSTOP)/.root
# #
# Run tags on all the sources and header files. This is probably not # Run tags on all the sources and header files. This is probably not

View File

@ -59,13 +59,13 @@ all-local: $(MYBUILDDIR) .WAIT $(MYBUILDDIR)/$(_LIB_)
install-staging-local: $(INSTALLTOP)$(LIBDIR) .WAIT $(INSTALLTOP)$(LIBDIR)/$(_LIB_) install-staging-local: $(INSTALLTOP)$(LIBDIR) .WAIT $(INSTALLTOP)$(LIBDIR)/$(_LIB_)
$(INSTALLTOP)$(LIBDIR)/$(_LIB_): $(MYBUILDDIR)/$(_LIB_) $(INSTALLTOP)$(LIBDIR)/$(_LIB_): $(MYBUILDDIR)/$(_LIB_)
rm -f $(.TARGET) rm -f $(.TARGET)
ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) >/dev/null 2>&1 || \ ln $(MYBUILDDIR)/$(_LIB_) $(.TARGET) || \
cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET) cp $(MYBUILDDIR)/$(_LIB_) $(.TARGET)
install-local: $(OSTREE)$(LIBDIR) $(MYBUILDDIR)/$(_LIB_) install-local: $(OSTREE)$(LIBDIR) $(MYBUILDDIR)/$(_LIB_)
@echo "Warning: manually installing library without relinking anything" @echo "Warning: manually installing library without relinking anything"
rm -f $(OSTREE)$(LIBDIR)/$(_LIB_) rm -f $(OSTREE)$(LIBDIR)/$(_LIB_)
ln $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) >/dev/null 2>&1 || \ ln $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) || \
cp $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_) cp $(MYBUILDDIR)/$(_LIB_) $(OSTREE)$(LIBDIR)/$(_LIB_)
# Build the library. # Build the library.

View File

@ -44,14 +44,14 @@ install-staging-local: $(INSTALLTOP)$(MANDIR) .WAIT
install-staging-local: $(INSTALLTOP)$(MANDIR)/$(_F_) install-staging-local: $(INSTALLTOP)$(MANDIR)/$(_F_)
$(INSTALLTOP)$(MANDIR)/$(_F_): $(_F_) $(INSTALLTOP)$(MANDIR)/$(_F_): $(_F_)
rm -f $(.TARGET) rm -f $(.TARGET)
ln $(_F_) $(.TARGET) >/dev/null 2>&1 || cp $(_F_) $(.TARGET) ln $(_F_) $(.TARGET) || cp $(_F_) $(.TARGET)
.endfor .endfor
install-local: $(OSTREE)$(MANDIR) .WAIT installmanpages install-local: $(OSTREE)$(MANDIR) .WAIT installmanpages
installmanpages: installmanpages:
.for _F_ in $(MANFILES) .for _F_ in $(MANFILES)
rm -f $(OSTREE)$(MANDIR)/$(_F_) rm -f $(OSTREE)$(MANDIR)/$(_F_)
ln $(_F_) $(OSTREE)$(MANDIR)/$(_F_) >/dev/null 2>&1 || \ ln $(_F_) $(OSTREE)$(MANDIR)/$(_F_) || \
cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_) cp $(_F_) $(OSTREE)$(MANDIR)/$(_F_)
.endfor .endfor

View File

@ -61,13 +61,13 @@ cleanprog:
install-staging-local: $(INSTALLTOP)$(BINDIR) .WAIT $(INSTALLTOP)$(BINDIR)/$(PROG) install-staging-local: $(INSTALLTOP)$(BINDIR) .WAIT $(INSTALLTOP)$(BINDIR)/$(PROG)
$(INSTALLTOP)$(BINDIR)/$(PROG): $(MYBUILDDIR)/$(PROG) $(INSTALLTOP)$(BINDIR)/$(PROG): $(MYBUILDDIR)/$(PROG)
rm -f $(.TARGET) rm -f $(.TARGET)
ln $(MYBUILDDIR)/$(PROG) $(.TARGET) >/dev/null 2>&1 || \ ln $(MYBUILDDIR)/$(PROG) $(.TARGET) || \
cp $(MYBUILDDIR)/$(PROG) $(.TARGET) cp $(MYBUILDDIR)/$(PROG) $(.TARGET)
install-local: install-prog install-local: install-prog
install-prog: $(OSTREE)$(BINDIR) $(MYBUILDDIR)/$(PROG) install-prog: $(OSTREE)$(BINDIR) $(MYBUILDDIR)/$(PROG)
rm -f $(OSTREE)$(BINDIR)/$(PROG) rm -f $(OSTREE)$(BINDIR)/$(PROG)
ln $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) >/dev/null 2>&1 || \ ln $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) || \
cp $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG) cp $(MYBUILDDIR)/$(PROG) $(OSTREE)$(BINDIR)/$(PROG)
# Link the program. # Link the program.

View File

@ -1,61 +0,0 @@
templates:
- name: /testbin/consoletest
panics: maybe
output:
- text: "/testbin/consoletest: Able was i ere i saw elbA"
- name: /testbin/opentest
panics: maybe
- name: /testbin/readwritetest
panics: maybe
output:
- text: "/testbin/readwritetest: h4xa0rRq0Vgbc96tiYJ^!#nXzZSAKPO"
- name: /testbin/closetest
panics: maybe
- name: /testbin/fileonlytest
panics: maybe
- name: /testbin/redirect
- name: /testbin/sparsefile
panics: maybe
- name: /testbin/badcall
- name: faulter
- name: /testbin/forkbomb
timesout: yes
timeout: 15.0
- name: kmalloc
output:
- text: "kmalloc: out of memory"
- name: /testbin/crash
- name: /testbin/forktest
- name: /testbin/randcall
- name: /testbin/shelltest
output:
- text: "/testbin/shelltest: line-1: Able was i ere i saw elbA"
- text: "/testbin/shelltest: line-2: Able was i ere i saw elbA"
- text: "/testbin/shelltest: line-3: Able was i ere i saw elbA"
- name: /testbin/argtest
input:
- "{{randString 1 2}}"
- "{{randString 4 5}}"
- "{{randString 9 10}}"
- "{{randString 10 11}}"
- "{{randString 11 12}}"
- "{{randString 12 13}}"
- "{{randString 13 14}}"
- "{{randString 200 513}}"
output:
- text: "/testbin/argtest: argc: {{add 1 .ArgLen}}"
- text: "/testbin/argtest: /testbin/argtest"
- text: "{{range $index, $element := .Args}}/testbin/argtest: {{$element}}\n{{end}}"
- text: "/testbin/argtest: [NULL]"
- name: /testbin/bigexec
- name: /testbin/factorial
input:
- "{{randInt 6 10}}"
output:
- text: "/testbin/factorial: {{$n:= index .Args 0 | atoi}}{{factorial $n}}\n"
- name: /testbin/add
input:
- "{{randInt 2 1000}}"
- "{{randInt 2 4000}}"
output:
- text: "/testbin/add: {{$x:= index .Args 0 | atoi}}{{$y := index .Args 1 | atoi}}{{add $x $y}}"

View File

@ -1,6 +0,0 @@
templates:
- name: km1
- name: km2
- name: km3
- name: km4
- name: km5

View File

@ -1,34 +0,0 @@
# These commands expect no output, but must not panic
templates:
- name: tt1
output:
- text: ""
- name: tt2
output:
- text: ""
- name: tt3
output:
- text: ""
- name: khu
output:
- text: ""
- name: q
output:
- text: ""
- name: s
output:
- text: ""
- name: boot
output:
- text:
- name: exit
output:
- text: ""

View File

@ -1,38 +0,0 @@
templates:
- name: sem1
- name: lt1
- name: lt2
panics: yes
output:
- text: "lt2: Should panic..."
- name: lt3
panics: yes
output:
- text: "lt3: Should panic..."
- name: cvt1
- name: cvt2
- name: cvt3
panics: yes
output:
- text: "cvt3: Should panic..."
- name: cvt4
panics: yes
output:
- text: "cvt4: Should panic..."
- name: cvt5
- name: rwt1
- name: rwt2
- name: rwt3
panics: yes
output:
- text: "rwt3: Should panic..."
- name: rwt4
panics: yes
output:
- text: "rwt4: Should panic..."
- name: rwt5
panics: yes
output:
- text: "rwt5: Should panic..."
- name: sp1
- name: sp2

View File

@ -1,52 +0,0 @@
templates:
#Single tests - everything has the default output
- name: /testbin/bigfork
- name: /testbin/ctest
- name: /testbin/huge
- name: /testbin/matmult
- name: /testbin/palin
- name: /testbin/parallelvm
- name: /testbin/sbrktest
- name: /testbin/sort
- name: /testbin/stacktest
- name: /testbin/zero
#Triples
- name: /testbin/triplehuge
output:
- {text: /testbin/huge, external: true, trusted: true}
- {text: /testbin/huge, external: true, trusted: true}
- {text: /testbin/huge, external: true, trusted: true}
- name: /testbin/triplemat
output:
- {text: /testbin/matmult, external: true, trusted: true}
- {text: /testbin/matmult, external: true, trusted: true}
- {text: /testbin/matmult, external: true, trusted: true}
- name: /testbin/triplesort
output:
- {text: /testbin/sort, external: true, trusted: true}
- {text: /testbin/sort, external: true, trusted: true}
- {text: /testbin/sort, external: true, trusted: true}
#Quints
- name: /testbin/quinthuge
output:
- {text: /testbin/huge, external: true, trusted: true}
- {text: /testbin/huge, external: true, trusted: true}
- {text: /testbin/huge, external: true, trusted: true}
- {text: /testbin/huge, external: true, trusted: true}
- {text: /testbin/huge, external: true, trusted: true}
- name: /testbin/quintmat
output:
- {text: /testbin/matmult, external: true, trusted: true}
- {text: /testbin/matmult, external: true, trusted: true}
- {text: /testbin/matmult, external: true, trusted: true}
- {text: /testbin/matmult, external: true, trusted: true}
- {text: /testbin/matmult, external: true, trusted: true}
- name: /testbin/quintsort
output:
- {text: /testbin/sort, external: true, trusted: true}
- {text: /testbin/sort, external: true, trusted: true}
- {text: /testbin/sort, external: true, trusted: true}
- {text: /testbin/sort, external: true, trusted: true}
- {text: /testbin/sort, external: true, trusted: true}

View File

@ -1,70 +0,0 @@
tags:
- name: badcall
desc: "All badcall tests for the various system calls"
- name: boot
desc: "Tests that check if your kernel can boot"
- name: console
desc: "Tests that check if you have a working userspace console"
- name: coremap
desc: "All coremap-related tests"
- name: crash
desc: "Tests that attempt to crash your kernel"
- name: cvs
desc: "Condition variable tests"
- name: filesyscalls
desc: "Filesystem syscall tests, e.g. read, write, open, close, etc."
- name: kleaks
desc: "Synch tests that also check for memory leaks"
- name: locks
desc: "Kernel lock tests"
- name: not-dumbvm
desc: "Tests that verify your coremap is not using dumbvm"
- name: not-dumbvm-vm
desc: "Tests that verify your VM system is not using dumbvm"
- name: proc
desc: "Misc. process system call tests"
- name: procsyscalls
desc: "Tests that test process system calls, e.g. fork, exec, waitpid"
- name: rwlocks
desc: "Reader/writer lock tests"
- name: sbrk
desc: "sbrk tests"
- name: semaphores
desc: "Kernel semaphore tests"
- name: shell
desc: "Tests that check for a working userspace shell"
- name: stability
desc: "System call stability tests that stress test and check various error conditions"
- name: stability-vm
desc: "VM stress testing"
- name: swap
desc: "Tests that stress test your VM swapping implementation"
- name: swap-basic
desc: "Less stressful swap tests to ensure a swapping implementation"
- name: synch
desc: "All sychronization primitive tests"
- name: synchprobs
desc: "Synchronization problems that test your ablility to use synch primitives"
- name: sys_close
desc: "close() syscall tests"
- name: sys_dup2
desc: "dup2() syscall tests"
- name: sys_exec
desc: "exec() syscall tests"
- name: sys_fork
desc: "fork() syscall tests"
- name: sys_lseek
desc: "lseek() syscall tests"
- name: sys_open
desc: "open() syscall tests"
- name: sys_read
desc: "read() syscall tests"
- name: sys_write
desc: "write() syscall tests"
- name: syscalls
desc: "Tests that check the basic functionality of your system call implementations"
- name: threads
desc: "Kernel thread tests"
- name: vm
desc: "All non-swapping VM tests"

View File

@ -1,40 +0,0 @@
name: asst1
print_name: ASST1
description: >
In this assignment you will implement new synchronization
primitives for OS/161 and use them to solve several synchronization problems.
version: 1
points: 50
type: asst
kconfig: ASST1
tests:
- id: synch/lt1.t
points: 8
- id: synch/lt2.t
points: 1
- id: synch/lt3.t
points: 1
- id: synch/cvt1.t
points: 4
- id: synch/cvt2.t
points: 3
- id: synch/cvt3.t
points: 1
- id: synch/cvt4.t
points: 1
- id: synch/cvt5.t
points: 1
- id: synch/rwt1.t
points: 5
- id: synch/rwt2.t
points: 2
- id: synch/rwt3.t
points: 1
- id: synch/rwt4.t
points: 1
- id: synch/rwt5.t
points: 1
- id: synchprobs/sp1.t
points: 10
- id: synchprobs/sp2.t
points: 10

View File

@ -1,51 +0,0 @@
name: asst2-single
print_name: "ASST2 (Single)"
description: >
In this assignment you will add process and system call support to your
OS/161 kernel. This is the single-submitter version for students that are
working alone and were provided the file system system calls.
leaderboard: false
version: 1
points: 80
type: asst
kconfig: ASST2
userland: true
tests:
# Process system call tests (50 points)
- id: syscalls/forktest.t
points: 15
- id: syscalls/shell.t
points: 10
- id: syscalls/argtest.t
points: 5
- id: syscalls/bigexec.t
points: 10
- id: syscalls/factorial.t
points: 5
- id: syscalls/add.t
points: 5
# Stability tests (30 points)
# Bad calls (5 points)
- id: stability/badcall/badcall-execv.t
points: 3
- id: stability/badcall/badcall-waitpid.t
points: 2
# crash
- id: stability/crash/crash-allS.t
points: 3
# randcall
- id: stability/randcall.t
points: 2
commands:
- id: /testbin/randcall
args:
- "-f"
- "-c 100"
- "-r 421"
- "2"
# forkbomb
- id: stability/forkbomb.t
points: 10
# forktest
- id: stability/forktest-stability.t
points: 10

View File

@ -1,15 +0,0 @@
name: asst2.1
print_name: ASST2.1
description: >
In this part of the assignment, you will add console support.
version: 1
points: 20
type: asst
kconfig: ASST2
userland: true
meta_name: asst2
leaderboard: false
tests:
# Make sure the console works (10 points)
- id: syscalls/consoletest.t
points: 20

View File

@ -1,76 +0,0 @@
name: asst2.2
print_name: ASST2.1
description: >
In this assignment you will add process and system call support to your
OS/161 kernel.
version: 1
points: 130
type: asst
kconfig: ASST2
userland: true
meta_name: asst2
leaderboard: false
tests:
# File system system calls (47 points)
- id: syscalls/opentest.t
points: 5
- id: syscalls/closetest.t
points: 5
- id: syscalls/readwritetest.t
points: 10
- id: syscalls/fileonlytest.t
points: 12
- id: syscalls/redirect.t
points: 10
- id: syscalls/sparsefile.t
points: 5
# Process system call tests (47 points)
- id: syscalls/forktest.t
points: 15
- id: syscalls/shell.t
points: 10
- id: syscalls/argtest.t
points: 5
- id: syscalls/bigexec.t
points: 8
- id: syscalls/factorial.t
points: 5
- id: syscalls/add.t
points: 4
# Stability tests (36 points)
# Bad calls (8 points)
- id: stability/badcall/badcall-open.t
points: 1
- id: stability/badcall/badcall-close.t
points: 1
- id: stability/badcall/badcall-read.t
points: 1
- id: stability/badcall/badcall-write.t
points: 1
- id: stability/badcall/badcall-lseek.t
points: 1
- id: stability/badcall/badcall-dup2.t
points: 1
- id: stability/badcall/badcall-execv.t
points: 1
- id: stability/badcall/badcall-waitpid.t
points: 1
# crash
- id: stability/crash/crash-allS.t
points: 4
# randcall
- id: stability/randcall.t
points: 4
commands:
- id: /testbin/randcall
args:
- "-f"
- "-c 100"
- "-r 421"
- "2"
# forkbomb
- id: stability/forkbomb.t
points: 10
# forktest
- id: stability/forktest-stability.t
points: 10

View File

@ -1,12 +0,0 @@
name: asst2
print_name: ASST2
description: >
In this assignment you will add process and system call support to your
OS/161 kernel.
version: 2
points: 150
type: asst
kconfig: ASST2
userland: true
is_meta_target: true
sub_target_names: ["asst2.1", "asst2.2"]

View File

@ -1,31 +0,0 @@
name: asst3.1
print_name: ASST3.1
description: >
In this part of ASST3, you will begin writing your own VM by adding your
coremap and page allocator.
version: 1
points: 60
type: asst
kconfig: ASST3
userland: true
meta_name: asst3
leaderboard: false
tests:
- id: coremap/not-dumbvm.t
points: 15
- id: coremap/km1.t
points: 5
mem_leak_points: 2
- id: coremap/km2.t
points: 5
mem_leak_points: 2
- id: coremap/km3.t
points: 5
mem_leak_points: 2
- id: coremap/km4.t
points: 15
mem_leak_points: 2
- id: coremap/coremap-loose.t
points: 5
- id: coremap/coremap-tight.t
points: 10

View File

@ -1,55 +0,0 @@
name: asst3.2
print_name: ASST3.2
description: >
In this part of ASST3, you will add virtual address spaces to your VM.
version: 1
points: 120
type: asst
kconfig: ASST3
userland: true
meta_name: asst3
leaderboard: false
tests:
# Basic VM (30 points)
- id: vm/not-dumbvm-vm.t
points: 5
- id: vm/sort.t
points: 5
- id: vm/palin.t
points: 5
- id: vm/matmult.t
mem_leak_points: 2
points: 5
- id: vm/ctest.t
points: 5
- id: vm/stacktest.t
points: 5
# Concurrent VM (50 points)
- id: vm/bigfork.t
points: 10
mem_leak_points: 2
- id: vm/parallelvm.t
points: 10
- id: vm/quintsort.t
points: 10
- id: vm/quintmat.t
points: 10
- id: vm/quinthuge.t
points: 10
# Heap (10 points)
- id: vm/sbrktest.t
points: 8
mem_leak_points: 2
- id: vm/sbrk-badcall.t
points: 2
# Stress tests/misc (30 points)
- id: vm/zero.t
points: 5
- id: vm/stability/vm-stability.t
points: 20
mem_leak_points: 2
- id: vm/stability/forkbomb.t
points: 5

View File

@ -1,37 +0,0 @@
name: asst3.3
print_name: ASST3.3
description: >
In this part of ASST3, you will add swapping to your VM.
version: 1
points: 120
type: asst
kconfig: ASST3
userland: true
meta_name: asst3
leaderboard: false
tests:
# Basic Swapping (40 points)
- id: vm/swap/sort.t
mem_leak_points: 2
points: 20
- id: vm/swap/matmult.t
mem_leak_points: 2
points: 20
# Concurrent Swapping (80 points)
- id: vm/swap/bigfork.t
points: 10
- id: vm/swap/bigfork-32.t
points: 15
mem_leak_points: 2
- id: vm/swap/parallelvm.t
points: 10
- id: vm/swap/parallelvm-32.t
points: 15
- id: vm/swap/quintsort.t
points: 10
- id: vm/swap/quintmat.t
points: 10
- id: vm/swap/quinthuge.t
points: 10
mem_leak_points: 2

View File

@ -1,12 +0,0 @@
name: asst3
print_name: ASST3
description: >
In this assignment you will add support for virtual memory to your OS/161
kernel.
version: 4
points: 300
type: asst
kconfig: ASST3
userland: true
is_meta_target: true
sub_target_names: ["asst3.1", "asst3.2", "asst3.3"]

View File

@ -1,9 +0,0 @@
---
name: Kernel Boot
description:
Tests whether your kernel will boot.
tags: [boot]
sys161:
cpus: 2
---
q

View File

@ -1,11 +0,0 @@
---
name: "Coremap Test (Loose Bounds)"
description: >
Allocates and frees all physical memory multiple times checking
that the amount allocated is within a reasonable bound.
tags: [coremap]
depends: [not-dumbvm.t]
sys161:
ram: 4M
---
| km5 --avail 32 --kernel 125

View File

@ -1,11 +0,0 @@
---
name: "Coremap Test (Tight Bounds)"
description: >
Allocates and frees all physical memory multiple times checking
that the amount allocated is within a reasonable bound.
tags: [coremap]
depends: [not-dumbvm.t]
sys161:
ram: 4M
---
| km5 --avail 20 --kernel 105

View File

@ -1,9 +0,0 @@
---
name: "Basic kmalloc Test"
description: >
Tests the kernel subpage allocator by allocating a large number of objects
and freeing them somewhat later.
tags: [coremap]
depends: [not-dumbvm.t]
---
| km1

View File

@ -1,8 +0,0 @@
---
name: "kmalloc Stress Test"
description: >
Similar to km1 but uses multiple concurrent threads.
tags: [coremap]
depends: [not-dumbvm.t]
---
| km2

View File

@ -1,9 +0,0 @@
---
name: "Large kmalloc Test"
description: >
Stresses the subpage allocator by allocating and freeing a large number of
objects of various sizes.
tags: [coremap]
depends: [not-dumbvm.t]
---
| km3 5000

View File

@ -1,9 +0,0 @@
---
name: "Multipage allococation Test"
description: >
Allocates and frees between 1 and 5 pages a number of times by a number of
concurrent threads.
tags: [coremap]
depends: [not-dumbvm.t]
---
| km4

View File

@ -1,9 +0,0 @@
---
name: "Smarter VM"
description:
Test whether you are using dumbvm by allocating and freeing all physical
memory multiple times.
tags: [coremap, not-dumbvm]
depends: [boot]
---
| km5

View File

@ -1,10 +0,0 @@
---
name: "Bad Close"
description: >
Stability test for sys_close.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall f

View File

@ -1,10 +0,0 @@
---
name: "Bad Dup"
description:
Stability test for sys_dup2.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall w

View File

@ -1,10 +0,0 @@
---
name: "Bad Exec"
description:
Stability test for sys_exec.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall a

View File

@ -1,10 +0,0 @@
---
name: "Bad Seek"
description:
Stability test for sys_lseek.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall j

View File

@ -1,10 +0,0 @@
---
name: "Bad Open"
description:
Stability test for sys_open.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall c

View File

@ -1,10 +0,0 @@
---
name: "Bad Read"
description:
Stability test for sys_read.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall d

View File

@ -1,10 +0,0 @@
---
name: "Bad Wait"
description:
Stability test for sys_wait.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall b

View File

@ -1,10 +0,0 @@
---
name: "Bad Write"
description:
Stability test for sys_write.
tags: [badcall,stability]
depends: [shell]
sys161:
ram: 2M
---
$ /testbin/badcall e

View File

@ -1,11 +0,0 @@
---
name: "Crash"
description: >
Tests whether your system correctly handles a variety of bad process
behavior.
tags: [crash,stability]
depends: [shell,sys_fork]
sys161:
ram: 4M
---
$ /testbin/crash *

View File

@ -1,10 +0,0 @@
---
name: "Crash-template Test"
description:
Tests whether your system correctly handles a variety of
illegal attempts from userspace processes to access resources that
do not belong to it. Please see userland/testbin/crash for more info.
tags: [stability, crash]
depends: [console]
---
p /extratests/crash-template

View File

@ -1,54 +0,0 @@
import os,sys
import subprocess
RANGE=[chr(i) for i in range(ord('a'), ord('p'))]
# First create crash-a/b/c.t files
template = open('crash-template').read()
def add_sys161_opts(content, sys161_opts):
content = content.split('\n')
idx = content[1:].index('---') + 1
content.insert(idx, sys161_opts.strip())
content = '\n'.join(content)
return content
def create_crash(char, sys161_opts=None):
content = template.replace('-template', '-%s' % char)
content = content.replace(', crash]', ', crash-fork]')
content = content.replace('[console]', '[console, /asst2/process/forktest.t]')
if sys161_opts:
content = add_sys161_opts(content, sys161_opts)
with open('crash-%s.t' % char, 'w') as f:
f.write(content)
# now do the F version
content = template.replace('-template', '-%sF' % char)
if sys161_opts:
content = add_sys161_opts(content, sys161_opts)
with open('crash-%sF.t' % char, 'w') as f:
f.write(content)
for char in RANGE:
create_crash(char)
# Now do the 'all'
sys161_opts = \
'''
sys161:
ram: 2M
'''
create_crash('all', sys161_opts)
#p = subprocess.Popen('ls *.t', shell=True, stdout=subprocess.PIPE)
#stdout, stderr = p.communicate()
#files = stdout.strip().split('\n')
#
#for f in files:
# name, ext = os.path.splitext(f)
#
# new_file = name + 'F' + ext
# letters = name[name.index('-'):]
# subprocess.check_call('cp %s %s' % (f, new_file), shell=True)
# subprocess.check_call('''sed -i 's/%s/%sF/g' %s''' % (letters, letters, new_file), shell=True)

View File

@ -1,10 +0,0 @@
---
name: "Faulter Test"
description:
Tests whether kill_curthread is implemented correctly.
Attempts to access an invalid memory address expecting the kernel
to gracefully kill the current process instead of panicking.
tags: [proc]
depends: [console]
---
p /testbin/faulter

View File

@ -1,17 +0,0 @@
---
name: "Calm Like a Fork Bomb"
tags: [stability]
depends: [console,sys_fork]
sys161:
ram: 2M
monitor:
progresstimeout: 40.0
user:
enablemin: true
min: 0.001
max: 1.0
kernel:
enablemin: true
min: 0.01
---
p /testbin/forkbomb

View File

@ -1,14 +0,0 @@
---
name: "Fork Stability Test"
description:
Runs forktest 5 times to check for synchronization issues.
tags: [stability]
depends: [shell]
sys161:
ram: 16M
---
$ /testbin/forktest
$ /testbin/forktest
$ /testbin/forktest
$ /testbin/forktest
$ /testbin/forktest

View File

@ -1,10 +0,0 @@
---
name: "Randcall Test"
description: >
Invokes system calls with random arguments.
tags: [stability]
depends: [shell]
sys161:
ram: 16M
---
$ /testbin/randcall -f -c 100 -r 421 2

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