-include *.d
-DEFINES =
+DEFINES += -DCNACHOS86
WARNINGS = -Wall -W -Wstrict-prototypes -Wmissing-prototypes
CFLAGS = -g -O3 -MMD $(WARNINGS) $(INCLUDES) $(DEFINES)
-ASFLAGS = $(INCLUDES) $(DEFINES)
+ASFLAGS = -Wa,--gstabs+ $(INCLUDES) $(DEFINES)
# Core kernel.
THREADS_SRC = start.S # Must be linked first.
clean:
rm -f *.o *.d *.bin kernel.bin.data kernel.bin.pad intr-stubs.S
-
-
TOP_SRCDIR = ../..
-DEFINES = -DFILESYS_STUB
+DEFINES = -DFILESYS -DFILESYS_STUB
SOURCES = $(THREADS_SRC) $(DEVICES_SRC) $(LIB_SRC) $(FILESYS_SRC)
INCLUDES = -I$(TOP_SRCDIR)/threads -I$(TOP_SRCDIR)/devices \
-I$(TOP_SRCDIR)/lib -I$(TOP_SRCDIR)/filesys
#include "file.h"
#ifdef FILESYS_STUB
+#include "debug.h"
+#include "filesys-stub.h"
+#include "lib.h"
+#include "malloc.h"
+
+void
+file_close (struct file *file)
+{
+ filesys_stub_lock ();
+ filesys_stub_put_string ("close");
+ filesys_stub_put_file (file);
+ filesys_stub_match_string ("close");
+ filesys_stub_unlock ();
+}
+
off_t
file_read (struct file *file, void *buffer, off_t size)
{
- int32_t retval = -1;
- filesys_stub_send ("s'read' i i", (int32_t) file, (int32_t) size);
- filesys_stub_receive ("s'read' i", &retval);
+ int32_t retval;
+
+ filesys_stub_lock ();
+ filesys_stub_put_string ("read");
+ filesys_stub_put_file (file);
+ filesys_stub_put_uint32 (size);
+ filesys_stub_match_string ("read");
+ retval = filesys_stub_get_int32 ();
if (retval > 0)
{
- if (!filesys_stub_receive ("B", buffer, (size_t) retval))
- retval = -1;
+ ASSERT (retval <= size);
+ filesys_stub_get_bytes (buffer, retval);
}
+ filesys_stub_unlock ();
+
return retval;
}
off_t
file_write (struct file *file, const void *buffer, off_t size)
{
- int32_t retval = -1;
- filesys_stub_send ("s'write' i B", (int32_t) file, buffer, (size_t) size);
- filesys_stub_receive ("s'write' i", &retval);
+ int32_t retval;
+
+ filesys_stub_lock ();
+ filesys_stub_put_string ("write");
+ filesys_stub_put_file (file);
+ filesys_stub_put_uint32 (size);
+ filesys_stub_put_bytes (buffer, size);
+ filesys_stub_match_string ("write");
+ retval = filesys_stub_get_int32 ();
+ ASSERT (retval <= size);
+ filesys_stub_unlock ();
+
return retval;
}
off_t
file_length (struct file *file)
{
- int32_t length = -1;
- filesys_stub_send ("s'length' i", (int32_t) file);
- filesys_stub_receive ("s'length' i", &length);
+ int32_t length;
+
+ filesys_stub_lock ();
+ filesys_stub_put_string ("length");
+ filesys_stub_put_file (file);
+ filesys_stub_match_string ("length");
+ length = filesys_stub_get_int32 ();
+ filesys_stub_unlock ();
+
return length;
}
void
file_seek (struct file *file, off_t pos)
{
- filesys_stub_send ("s'seek' i i", (int32_t) file, (int32_t) pos);
- filesys_stub_receive ("s'seek'");
+ filesys_stub_lock ();
+ filesys_stub_put_string ("seek");
+ filesys_stub_put_file (file);
+ filesys_stub_put_uint32 (pos);
+ filesys_stub_match_string ("seek");
+ filesys_stub_unlock ();
}
off_t
file_tell (struct file *file)
{
- int32_t pos = -1;
- filesys_stub_send ("s'tell' i", (int32_t) file);
- filesys_stub_receive ("s'tell'", &pos);
+ int32_t pos;
+
+ filesys_stub_lock ();
+ filesys_stub_put_string ("tell");
+ filesys_stub_put_file (file);
+ filesys_stub_match_string ("tell");
+ pos = filesys_stub_get_int32 ();
+ filesys_stub_unlock ();
+
return pos;
}
#endif /* FILESYS_STUB */
typedef int32_t off_t;
struct file;
+void file_close (struct file *);
off_t file_read (struct file *, void *, off_t);
off_t file_write (struct file *, const void *, off_t);
off_t file_length (struct file *);
#include "backdoor.h"
#include "debug.h"
#include "io.h"
+#include "lib.h"
+#include "synch.h"
+static struct lock lock;
+
+void
+filesys_stub_init (void)
+{
+ lock_init (&lock, "filesys-stub");
+}
+
+void
+filesys_stub_lock (void)
+{
+ lock_acquire (&lock);
+}
+
+void
+filesys_stub_unlock (void)
+{
+ lock_release (&lock);
+}
+\f
static void
out_byte (uint8_t byte, void *aux UNUSED)
{
outb (0x8901, byte);
}
-void
-filesys_stub_send (const char *types, ...)
+void
+filesys_stub_put_bool (bool b)
+{
+ backdoor_put_bool (b, out_byte, NULL);
+}
+
+void
+filesys_stub_put_bytes (const void *buffer, size_t cnt)
+{
+ backdoor_put_bytes (buffer, cnt, out_byte, NULL);
+}
+
+void
+filesys_stub_put_file (struct file *file)
+{
+ ASSERT (file != NULL);
+ filesys_stub_put_int32 ((int32_t) file - 1);
+}
+
+void
+filesys_stub_put_int32 (int32_t value)
+{
+ backdoor_put_int32 (value, out_byte, NULL);
+}
+
+void
+filesys_stub_put_string (const char *string)
+{
+ backdoor_put_string (string, out_byte, NULL);
+}
+
+void
+filesys_stub_put_uint32 (uint32_t value)
{
- va_list args;
+ backdoor_put_uint32 (value, out_byte, NULL);
+}
- va_start (args, types);
- backdoor_vmarshal (types, args, out_byte, NULL);
- va_end (args);
+static uint8_t
+in_byte (void *aux UNUSED)
+{
+ return inb (0x8901);
}
-static bool
-in_byte (uint8_t *byte, void *aux UNUSED)
+bool
+filesys_stub_get_bool (void)
{
- *byte = inb (0x8901);
- return true;
+ return backdoor_get_bool (in_byte, NULL);
}
-void
-filesys_stub_receive (const char *types, ...)
+void
+filesys_stub_get_bytes (void *buffer, size_t size)
{
- va_list args;
+ backdoor_get_bytes (buffer, size, in_byte, NULL);
+}
- va_start (args, types);
- backdoor_vunmarshal (types, args, in_byte, NULL);
- va_end (args);
+struct file *
+filesys_stub_get_file (void)
+{
+ int32_t fd = filesys_stub_get_int32 ();
+ return fd < 0 ? NULL : (struct file *) (fd + 1);
}
+
+int32_t
+filesys_stub_get_int32 (void)
+{
+ return backdoor_get_int32 (in_byte, NULL);
+}
+
+void
+filesys_stub_match_string (const char *string)
+{
+ if (backdoor_get_uint32 (in_byte, NULL) != strlen (string))
+ panic ("string match failed");
+ while (*string != '\0')
+ {
+ uint8_t c = *string++;
+ if (c != in_byte (NULL))
+ panic ("string match failed");
+ }
+}
+
+uint32_t
+filesys_stub_get_uint32 (void)
+{
+ return backdoor_get_uint32 (in_byte, NULL);
+}
+
#ifndef HEADER_FILESYS_STUB_H
#define HEADER_FILESYS_STUB_H 1
-void filesys_stub_send (const char *types, ...);
-void filesys_stub_receive (const char *types, ...);
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+struct file;
+
+void filesys_stub_init (void);
+void filesys_stub_lock (void);
+void filesys_stub_unlock (void);
+
+void filesys_stub_put_bool (bool);
+void filesys_stub_put_bytes (const void *, size_t);
+void filesys_stub_put_file (struct file *);
+void filesys_stub_put_int32 (int32_t);
+void filesys_stub_put_string (const char *);
+void filesys_stub_put_uint32 (uint32_t);
+
+bool filesys_stub_get_bool (void);
+void filesys_stub_get_bytes (void *, size_t);
+struct file *filesys_stub_get_file (void);
+int32_t filesys_stub_get_int32 (void);
+void filesys_stub_match_string (const char *);
+uint32_t filesys_stub_get_uint32 (void);
#endif /* filesys-stub.h */
#include "filesys.h"
+
#ifdef FILESYS_STUB
+#include <stdint.h>
+#include "debug.h"
+#include "filesys-stub.h"
+#include "lib.h"
+
void
filesys_init (bool reformat)
{
if (reformat)
printk ("filesystem stubs don't support formatting\n");
+ filesys_stub_init ();
}
bool
filesys_create (const char *name)
{
- bool success = false;
- filesys_stub_send ("s'create' s", name);
- filesys_stub_receive ("s'create' b", &success);
+ bool success;
+
+ filesys_stub_lock ();
+ filesys_stub_put_string ("create");
+ filesys_stub_put_string (name);
+ filesys_stub_match_string ("create");
+ success = filesys_stub_get_bool ();
+ filesys_stub_unlock ();
+
return success;
}
struct file *
filesys_open (const char *name)
{
- int32_t handle = -1;
- filesys_stub_stub ("s'open' i", name);
- filesys_stub_receive ("s'open' i", &handle);
- return handle == -1 ? NULL : (struct file *) handle;
+ struct file *file;
+
+ filesys_stub_lock ();
+ filesys_stub_put_string ("open");
+ filesys_stub_put_string (name);
+ filesys_stub_match_string ("open");
+ file = filesys_stub_get_file ();
+ filesys_stub_unlock ();
+
+ return file;
}
bool
filesys_remove (const char *name)
{
- bool success = false;
- filesys_stub_send ("s'create' s", name);
- filesys_stub_receive ("s'create' b", &success);
+ bool success;
+
+ filesys_stub_lock ();
+ filesys_stub_put_string ("remove");
+ filesys_stub_put_string (name);
+ filesys_stub_match_string ("remove");
+ success = filesys_stub_get_bool ();
+ filesys_stub_unlock ();
+
return success;
}
#endif /* FILESYS_STUB */
+
+#undef NDEBUG
+#include "debug.h"
+#include "file.h"
+
+void
+filesys_self_test (void)
+{
+ static const char s[] = "This is a test string.";
+ struct file *file;
+ char s2[sizeof s];
+
+ ASSERT (filesys_create ("foo"));
+ ASSERT ((file = filesys_open ("foo")) != NULL);
+ ASSERT (file_write (file, s, sizeof s) == sizeof s);
+ ASSERT (file_tell (file) == sizeof s);
+ ASSERT (file_length (file) == sizeof s);
+ file_close (file);
+
+ ASSERT ((file = filesys_open ("foo")) != NULL);
+ ASSERT (file_read (file, s2, sizeof s2) == sizeof s2);
+ ASSERT (memcmp (s, s2, sizeof s) == 0);
+ ASSERT (file_tell (file) == sizeof s2);
+ ASSERT (file_length (file) == sizeof s2);
+ file_close (file);
+
+ ASSERT (filesys_remove ("foo"));
+}
struct file *filesys_open (const char *name);
bool filesys_remove (const char *name);
+void filesys_self_test (void);
+
#endif /* filesys.h */
#include <stdlib.h>
#include <string.h>
-static void
-marshal_int32 (int32_t value, void (*out) (uint8_t, void *aux), void *aux)
+void
+backdoor_put_int32 (int32_t value,
+ void (*out) (uint8_t, void *aux), void *aux)
{
out ((value >> 24) & 0xff, aux);
out ((value >> 16) & 0xff, aux);
out (value & 0xff, aux);
}
-static void
-marshal_bytes (const void *buffer, size_t cnt,
- void (*out) (uint8_t, void *aux), void *aux)
+void
+backdoor_put_uint32 (uint32_t value,
+ void (*out) (uint8_t, void *aux), void *aux)
+{
+ out ((value >> 24) & 0xff, aux);
+ out ((value >> 16) & 0xff, aux);
+ out ((value >> 8) & 0xff, aux);
+ out (value & 0xff, aux);
+}
+
+void
+backdoor_put_bytes (const void *buffer, size_t cnt,
+ void (*out) (uint8_t, void *aux), void *aux)
{
const uint8_t *p = buffer;
size_t i;
out (p[i], aux);
}
-enum backdoor_error
-backdoor_vmarshal (const char *types, va_list args,
- void (*out) (uint8_t, void *aux), void *aux)
+void
+backdoor_put_string (const char *string,
+ void (*out) (uint8_t, void *aux), void *aux)
{
- const char *p = types;
-
- for (;;)
- {
- /* Find next type character. */
- while (*p == ' ')
- p++;
- if (*p == '\0')
- return BACKDOOR_OK;
-
- out (*p, aux);
- switch (*p++)
- {
- case 's':
- if (*p == '\'')
- {
- const char *end = strchr (++p, '\'');
- marshal_int32 (end - p, out, aux);
- marshal_bytes (p, end - p, out, aux);
- p = end + 1;
- }
- else
- {
- const char *s = va_arg (args, const char *);
- marshal_int32 (strlen (s), out, aux);
- marshal_bytes (s, strlen (s), out, aux);
- }
- break;
-
- case 'i':
- marshal_int32 (va_arg (args, int32_t), out, aux);
- break;
-
- case 'B':
- {
- const void *buffer = va_arg (args, const void *);
- size_t size = va_arg (args, size_t);
- marshal_int32 (size, out, aux);
- marshal_bytes (buffer, size, out, aux);
- }
- break;
+ size_t length = strlen (string);
- case 'b':
- marshal_int32 (va_arg (args, int), out, aux);
- break;
+ backdoor_put_uint32 (length, out, aux);
+ backdoor_put_bytes (string, length, out, aux);
+}
- default:
- return BACKDOOR_BAD_TYPE;
- }
- }
+void
+backdoor_put_bool (bool b,
+ void (*out) (uint8_t, void *aux), void *aux)
+{
+ backdoor_put_uint32 (b, out, aux);
}
-static bool
-unmarshal_int32 (int32_t *value,
- bool (*in) (uint8_t *, void *aux), void *aux)
+int32_t
+backdoor_get_int32 (uint8_t (*in) (void *aux), void *aux)
{
- int32_t tmp;
+ int32_t value;
int i;
- tmp = 0;
- for (i = 0; i < 4; i++)
- {
- uint8_t b;
- if (!in (&b, aux))
- return false;
+ value = 0;
+ for (i = 0; i < 4; i++)
+ value = (value << 8) | in (aux);
+ return value;
+}
- tmp = (tmp << 8) | b;
- }
- *value = tmp;
- return true;
+uint32_t
+backdoor_get_uint32 (uint8_t (*in) (void *aux), void *aux)
+{
+ return backdoor_get_int32 (in, aux);
}
-static bool
-unmarshal_bytes (void *buffer, size_t cnt,
- bool (*in) (uint8_t *, void *aux), void *aux)
+char *
+backdoor_get_string (uint8_t (*in) (void *aux), void *aux)
+{
+ size_t length = backdoor_get_uint32 (in, aux);
+ char *string = malloc (length + 1);
+ backdoor_get_bytes (string, length, in, aux);
+ string[length] = '\0';
+ return string;
+}
+
+void
+backdoor_get_bytes (void *buffer, size_t cnt,
+ uint8_t (*in) (void *aux), void *aux)
{
uint8_t *p = buffer;
size_t i;
- for (i = 0; i < cnt; i++)
- if (!in (&p[i], aux))
- return false;
- return true;
+ for (i = 0; i < cnt; i++)
+ p[i] = in (aux);
}
-enum backdoor_error
-backdoor_vunmarshal (const char *types, va_list args,
- bool (*in) (uint8_t *, void *aux), void *aux)
+bool
+backdoor_get_bool (uint8_t (*in) (void *aux), void *aux)
{
- const char *p = types;
-
- for (;;)
- {
- uint8_t c;
-
- /* Find next type character. */
- while (*p == ' ')
- p++;
- if (*p == '\0')
- return BACKDOOR_OK;
-
- /* Check type character in input. */
- if (!in (&c, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (c != *p++)
- return BACKDOOR_TYPE_MISMATCH;
-
- switch (c)
- {
- case 's':
- {
- int32_t length;
-
- if (!unmarshal_int32 (&length, in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (length < 0)
- return BACKDOOR_NEGATIVE_SIZE;
- if (*p == '\'')
- {
- const char *end = strchr (++p, '\'');
- if (length != end - p)
- return BACKDOOR_STRING_MISMATCH;
- while (p < end)
- {
- uint8_t q;
- if (!in (&q, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (q != *p++)
- return BACKDOOR_STRING_MISMATCH;
- }
- p++;
- }
- else
- {
- char *s = malloc (length + 1);
- if (s == NULL)
- return BACKDOOR_NOMEM;
- if (!unmarshal_bytes (s, length, in, aux))
- {
- free (s);
- return BACKDOOR_UNEXPECTED_EOF;
- }
- s[length] = '\0';
- *va_arg (args, char **) = s;
- }
- }
- break;
-
- case 'i':
- if (!unmarshal_int32 (va_arg (args, int32_t *), in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- break;
-
- case 'B':
- {
- int32_t size;
- void *buffer;
-
- if (!unmarshal_int32 (&size, in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- if (size < 0)
- return BACKDOOR_NEGATIVE_SIZE;
- buffer = malloc (size);
- if (size > 0 && buffer == NULL)
- return BACKDOOR_NOMEM;
- if (!unmarshal_bytes (buffer, size, in, aux))
- {
- free (buffer);
- return BACKDOOR_UNEXPECTED_EOF;
- }
- *va_arg (args, size_t *) = size;
- *va_arg (args, void **) = buffer;
- }
- break;
-
- case 'b':
- {
- int32_t b;
- if (!unmarshal_int32 (&b, in, aux))
- return BACKDOOR_UNEXPECTED_EOF;
- *va_arg (args, bool *) = b;
- }
- break;
-
- default:
- return BACKDOOR_BAD_TYPE;
- }
- }
+ return backdoor_get_uint32 (in, aux) != 0;
}
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stddef.h>
-enum backdoor_error
- {
- BACKDOOR_OK = 0,
- BACKDOOR_NOMEM = -100,
- BACKDOOR_BAD_TYPE,
- BACKDOOR_TYPE_MISMATCH,
- BACKDOOR_STRING_MISMATCH,
- BACKDOOR_NEGATIVE_SIZE,
- BACKDOOR_UNEXPECTED_EOF
- };
-
-enum backdoor_error
-backdoor_vmarshal (const char *types, va_list args,
- void (*) (uint8_t, void *aux), void *aux);
-enum backdoor_error
-backdoor_vunmarshal (const char *types, va_list args,
- bool (*) (uint8_t *, void *aux), void *aux);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void backdoor_put_int32 (int32_t value,
+ void (*out) (uint8_t, void *aux), void *aux);
+void backdoor_put_uint32 (uint32_t value,
+ void (*out) (uint8_t, void *aux), void *aux);
+void backdoor_put_bytes (const void *buffer, size_t cnt,
+ void (*out) (uint8_t, void *aux), void *aux);
+void backdoor_put_string (const char *string,
+ void (*out) (uint8_t, void *aux), void *aux);
+void backdoor_put_bool (bool b,
+ void (*out) (uint8_t, void *aux), void *aux);
+int32_t backdoor_get_int32 (uint8_t (*in) (void *aux), void *aux);
+uint32_t backdoor_get_uint32 (uint8_t (*in) (void *aux), void *aux);
+char *backdoor_get_string (uint8_t (*in) (void *aux), void *aux);
+void backdoor_get_bytes (void *buffer, size_t cnt,
+ uint8_t (*in) (void *aux), void *aux);
+bool backdoor_get_bool (uint8_t (*in) (void *aux), void *aux);
+
+#ifdef __cplusplus
+};
+#endif
#endif /* backdoor.h */
#include "thread.h"
#include "timer.h"
#include "vga.h"
+#ifdef FILESYS
+#include "filesys.h"
+#endif
/* Size of kernel static code and data, in 4 kB pages. */
size_t kernel_pages;
printk ("%s exiting\n", thread_current ()->name);
break;
}
- count = random_ulong () % 25 * 1000000;
+ count = random_ulong () % 25 * 10000;
printk ("%s waiting %zu: ", thread_current ()->name, count);
for (i = 0; i < count; i++);
printk ("%s\n", thread_current ()->name);
intr_init ();
timer_init ();
kbd_init ();
- intr_enable ();
+
+#ifdef FILESYS
+ filesys_init (false);
+#endif
thread_init ();
{
uint32_t cr2;
asm ("movl %%cr2, %0" : "=r" (cr2));
- printk ("Unexpected interrupt 0x%02x, error code %08x, cr2=%08x, eip=%08x\n",
- regs->vec_no, regs->error_code, cr2, regs->eip);
- for (;;);
+ panic ("Unexpected interrupt 0x%02x, error code %08x, cr2=%08x, eip=%08x",
+ regs->vec_no, regs->error_code, cr2, regs->eip);
}
print <<'EOF';
intr_entry:
+ # FIXME: build a fake stack frame to improve backtraces.
# Save caller's registers.
pushl %ds
pushl %es
static struct arena *
slot_to_arena (struct slot *s)
{
- return (struct arena *) ((uint32_t) s & (NBPG - 1));
+ return (struct arena *) ((uint32_t) s & ~(NBPG - 1));
}
static void *
{
struct thread *cur, *next, *prev;
+ ASSERT (intr_get_level () == IF_OFF);
+
cur = thread_current ();
ASSERT (cur->status != THREAD_RUNNING);
next->status = THREAD_RUNNING;
prev = thread_switch (cur, next);
+
+ /* Prevent GCC from reordering anything around the thread
+ switch. */
+ asm volatile ("" : : : "memory");
+
if (prev != NULL && prev->status == THREAD_DYING)
thread_destroy (prev);
+
+ intr_enable ();
}
void
thread_yield (void)
{
ASSERT (!intr_context ());
+
+ intr_disable ();
thread_ready (thread_current ());
thread_schedule ();
}
void
thread_start (struct thread *t)
{
+ ASSERT (intr_get_level () == IF_OFF);
+
if (t->status == THREAD_READY)
list_remove (&t->rq_elem);
t->status = THREAD_RUNNING;
void
thread_exit (void)
{
- struct thread *t = thread_current ();
- t->status = THREAD_DYING;
+ ASSERT (!intr_context ());
+
+ intr_disable ();
+ thread_current ()->status = THREAD_DYING;
thread_schedule ();
}
void
thread_sleep (void)
{
+ ASSERT (!intr_context ());
ASSERT (intr_get_level () == IF_OFF);
thread_current ()->status = THREAD_BLOCKED;