Compare commits
No commits in common. "a5e4d1920066b074918662d75f2455e33051c215" and "1c7aa6edda81e2a2138a69f2b7880a2c83b5a14a" have entirely different histories.
a5e4d19200
...
1c7aa6edda
13
.gitignore
vendored
13
.gitignore
vendored
@ -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
|
||||||
|
1
Makefile
1
Makefile
@ -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) $@)
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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
@ -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);
|
|
||||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
28
configure
vendored
@ -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
22
defs.mk
Normal 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
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
||||||
|
@ -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
|
|
||||||
|
@ -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...'
|
||||||
|
@ -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
|
||||||
|
@ -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_ */
|
|
@ -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_
|
|
@ -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_ */
|
|
@ -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);
|
||||||
|
@ -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_ */
|
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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 *);
|
||||||
|
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
194
kern/main/main.c
194
kern/main/main.c
@ -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 */
|
||||||
}
|
}
|
||||||
|
119
kern/main/menu.c
119
kern/main/menu.c
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
1541
kern/thread/thread.c
1541
kern/thread/thread.c
File diff suppressed because it is too large
Load Diff
1341
kern/vm/kmalloc.c
1341
kern/vm/kmalloc.c
File diff suppressed because it is too large
Load Diff
@ -49,7 +49,7 @@ Standard C Library (libc, -lc)
|
|||||||
<p>
|
<p>
|
||||||
<tt>#include <unistd.h></tt><br>
|
<tt>#include <unistd.h></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>
|
||||||
|
|
||||||
|
@ -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> </td>
|
<tr><td width=5% rowspan=10> </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>
|
||||||
|
@ -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> </td>
|
<tr><td width=5% rowspan=3> </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>
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -87,8 +87,8 @@ mentioned here.
|
|||||||
<table width=90%>
|
<table width=90%>
|
||||||
<tr><td width=5% rowspan=3> </td>
|
<tr><td width=5% rowspan=3> </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>
|
||||||
|
@ -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>
|
||||||
|
@ -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.
|
||||||
|
@ -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> </td>
|
<tr><td width=5% rowspan=4> </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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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.
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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}}"
|
|
@ -1,6 +0,0 @@
|
|||||||
templates:
|
|
||||||
- name: km1
|
|
||||||
- name: km2
|
|
||||||
- name: km3
|
|
||||||
- name: km4
|
|
||||||
- name: km5
|
|
@ -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: ""
|
|
||||||
|
|
@ -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
|
|
@ -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}
|
|
@ -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"
|
|
||||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"]
|
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
name: Kernel Boot
|
|
||||||
description:
|
|
||||||
Tests whether your kernel will boot.
|
|
||||||
tags: [boot]
|
|
||||||
sys161:
|
|
||||||
cpus: 2
|
|
||||||
---
|
|
||||||
q
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
name: "kmalloc Stress Test"
|
|
||||||
description: >
|
|
||||||
Similar to km1 but uses multiple concurrent threads.
|
|
||||||
tags: [coremap]
|
|
||||||
depends: [not-dumbvm.t]
|
|
||||||
---
|
|
||||||
| km2
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Close"
|
|
||||||
description: >
|
|
||||||
Stability test for sys_close.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall f
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Dup"
|
|
||||||
description:
|
|
||||||
Stability test for sys_dup2.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall w
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Exec"
|
|
||||||
description:
|
|
||||||
Stability test for sys_exec.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall a
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Seek"
|
|
||||||
description:
|
|
||||||
Stability test for sys_lseek.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall j
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Open"
|
|
||||||
description:
|
|
||||||
Stability test for sys_open.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall c
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Read"
|
|
||||||
description:
|
|
||||||
Stability test for sys_read.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall d
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Wait"
|
|
||||||
description:
|
|
||||||
Stability test for sys_wait.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall b
|
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: "Bad Write"
|
|
||||||
description:
|
|
||||||
Stability test for sys_write.
|
|
||||||
tags: [badcall,stability]
|
|
||||||
depends: [shell]
|
|
||||||
sys161:
|
|
||||||
ram: 2M
|
|
||||||
---
|
|
||||||
$ /testbin/badcall e
|
|
@ -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 *
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
Loading…
x
Reference in New Issue
Block a user