Trying to get closer to the original OS/161 sources.

This commit is contained in:
Geoffrey Challen 2016-01-11 20:54:52 -05:00
parent 202cc3eab4
commit a6878c822b
13 changed files with 164 additions and 161 deletions

View File

@ -437,11 +437,13 @@ file test/synchtest.c
file test/semunit.c file test/semunit.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 test/whalemating.c
optfile synchprobs synchprobs/stoplight.c optfile synchprobs test/stoplight.c
optfile synchprobs test/synchprobs.c optfile synchprobs test/synchprobs.c
defoption automationtest defoption automationtest

View File

@ -194,16 +194,5 @@ void kprintf_bootstrap(void);
#define DIVROUNDUP(a,b) (((a)+(b)-1)/(b)) #define DIVROUNDUP(a,b) (((a)+(b)-1)/(b))
#define ROUNDUP(a,b) (DIVROUNDUP(a,b)*b) #define ROUNDUP(a,b) (DIVROUNDUP(a,b)*b)
void random_yielder(uint32_t);
void random_spinner(uint32_t);
/*
* Testing variants of kprintf. tprintf is silent during automated testing.
* sprintf prefixes the kernel secret to kprintf messages during automated
* testing. nprintf is not silent during automated testing.
*/
int tkprintf(const char *format, ...) __PF(1,2);
int nkprintf(const char *format, ...) __PF(1,2);
#endif /* _LIB_H_ */ #endif /* _LIB_H_ */

View File

@ -62,7 +62,7 @@ typedef __va_list va_list;
* or split the definition of va_list into another header file, none * or split the definition of va_list into another header file, none
* of which seems entirely desirable. * of which seems entirely desirable.
*/ */
int vkprintf(const char *fmt, va_list ap) __PF(1,0); void vkprintf(const char *fmt, va_list ap) __PF(1,0);
int vsnprintf(char *buf, size_t maxlen, const char *fmt, va_list ap) __PF(3,0); int vsnprintf(char *buf, size_t maxlen, const char *fmt, va_list ap) __PF(3,0);
/* /*

View File

@ -44,10 +44,10 @@
* internally. * internally.
*/ */
struct semaphore { struct semaphore {
char *sem_name; char *sem_name;
struct wchan *sem_wchan; struct wchan *sem_wchan;
struct spinlock sem_lock; struct spinlock sem_lock;
volatile unsigned sem_count; volatile unsigned sem_count;
}; };
struct semaphore *sem_create(const char *name, unsigned initial_count); struct semaphore *sem_create(const char *name, unsigned initial_count);
@ -56,7 +56,7 @@ void sem_destroy(struct semaphore *);
/* /*
* Operations (both atomic): * Operations (both atomic):
* P (proberen): decrement count. If the count is 0, block until * P (proberen): decrement count. If the count is 0, block until
* the count is 1 again before decrementing. * the count is 1 again before decrementing.
* V (verhogen): increment count. * V (verhogen): increment count.
*/ */
void P(struct semaphore *); void P(struct semaphore *);
@ -73,9 +73,9 @@ void V(struct semaphore *);
* (should be) made internally. * (should be) made internally.
*/ */
struct lock { struct lock {
char *lk_name; char *lk_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 lock *lock_create(const char *name); struct lock *lock_create(const char *name);
@ -84,11 +84,11 @@ void lock_destroy(struct lock *);
/* /*
* Operations: * Operations:
* lock_acquire - Get the lock. Only one thread can hold the lock at the * lock_acquire - Get the lock. Only one thread can hold the lock at the
* same time. * same time.
* lock_release - Free the lock. Only the thread holding the lock may do * lock_release - Free the lock. Only the thread holding the lock may do
* this. * this.
* lock_do_i_hold - Return true if the current thread holds the lock; * lock_do_i_hold - Return true if the current thread holds the lock;
* false otherwise. * false otherwise.
* *
* These operations must be atomic. You get to write them. * These operations must be atomic. You get to write them.
*/ */
@ -112,9 +112,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);
@ -122,8 +122,8 @@ void cv_destroy(struct cv *);
/* /*
* Operations: * Operations:
* cv_wait - Release the supplied lock, go to sleep, and, after * cv_wait - Release the supplied lock, go to sleep, and, after
* waking up again, re-acquire the lock. * waking up again, re-acquire the lock.
* cv_signal - Wake up one thread that's sleeping on this CV. * cv_signal - Wake up one thread that's sleeping on this CV.
* cv_broadcast - Wake up all threads sleeping on this CV. * cv_broadcast - Wake up all threads sleeping on this CV.
* *

View File

@ -1,28 +0,0 @@
#ifndef _SYNCHPROBS_H_
#define _SYNCHPROBS_H_
/*
* Synchronization problem primitives.
*/
/*
* whalemating.c.
*/
void whalemating_init(void);
void whalemating_cleanup(void);
void male(void);
void female(void);
void matchmaker(void);
/*
* stoplight.c.
*/
void gostraight(uint32_t);
void turnleft(uint32_t);
void turnright(uint32_t);
void stoplight_init(void);
void stoplight_cleanup(void);
#endif /* _SYNCHPROBS_H_ */

View File

@ -30,6 +30,9 @@
#ifndef _TEST_H_ #ifndef _TEST_H_
#define _TEST_H_ #define _TEST_H_
/* Get __PF() for declaring printf-like functions. */
#include <cdefs.h>
#include "opt-synchprobs.h" #include "opt-synchprobs.h"
#include "opt-automationtest.h" #include "opt-automationtest.h"
@ -126,6 +129,30 @@ void inQuadrant(int);
void leaveIntersection(void); void leaveIntersection(void);
int stoplight(int, char **); int stoplight(int, char **);
/*
* Synchronization problem primitives.
*/
/*
* whalemating.c.
*/
void whalemating_init(void);
void whalemating_cleanup(void);
void male(void);
void female(void);
void matchmaker(void);
/*
* stoplight.c.
*/
void gostraight(uint32_t);
void turnleft(uint32_t);
void turnright(uint32_t);
void stoplight_init(void);
void stoplight_cleanup(void);
#endif #endif
/* /*
@ -138,4 +165,16 @@ int ll1test(int, char **);
int ll16test(int, char **); int ll16test(int, char **);
#endif #endif
void random_yielder(uint32_t);
void random_spinner(uint32_t);
/*
* Testing variants of kprintf. tprintf is silent during automated testing.
* sprintf prefixes the kernel secret to kprintf messages during automated
* testing. nprintf is not silent during automated testing.
*/
int tkprintf(const char *format, ...) __PF(1,2);
int nkprintf(const char *format, ...) __PF(1,2);
#endif /* _TEST_H_ */ #endif /* _TEST_H_ */

View File

@ -40,6 +40,7 @@
#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 <kern/secret.h>
#include <test.h>
/* Flags word for DEBUG() macro. */ /* Flags word for DEBUG() macro. */
@ -93,9 +94,10 @@ console_send(void *junk, const char *data, size_t len)
/* /*
* kprintf and tprintf helper function. * kprintf and tprintf helper function.
*/ */
static
inline inline
int int
vkprintf(const char *fmt, va_list ap) __kprintf(const char *fmt, va_list ap)
{ {
int chars; int chars;
bool dolock; bool dolock;
@ -134,7 +136,7 @@ kprintf(const char *fmt, ...)
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
chars = vkprintf(fmt, ap); chars = __kprintf(fmt, ap);
va_end(ap); va_end(ap);
return chars; return chars;
@ -154,7 +156,7 @@ tkprintf(const char *fmt, ...)
} }
va_start(ap, fmt); va_start(ap, fmt);
chars = vkprintf(fmt, ap); chars = __kprintf(fmt, ap);
va_end(ap); va_end(ap);
return chars; return chars;
@ -173,7 +175,7 @@ nkprintf(const char *fmt, ...)
} }
va_start(ap, fmt); va_start(ap, fmt);
chars = vkprintf(fmt, ap); chars = __kprintf(fmt, ap);
va_end(ap); va_end(ap);
return chars; return chars;

View File

@ -30,7 +30,6 @@
#include <types.h> #include <types.h>
#include <kern/errmsg.h> #include <kern/errmsg.h>
#include <lib.h> #include <lib.h>
#include <thread.h>
/* /*
* Like strdup, but calls kmalloc. * Like strdup, but calls kmalloc.
@ -61,27 +60,3 @@ strerror(int errcode)
panic("Invalid error code %d\n", errcode); panic("Invalid error code %d\n", errcode);
return NULL; return NULL;
} }
/*
* 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;
}
}

27
kern/test/lib.c Normal file
View File

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

View File

@ -68,7 +68,6 @@
#include <thread.h> #include <thread.h>
#include <test.h> #include <test.h>
#include <synch.h> #include <synch.h>
#include <synchprobs.h>
/* /*
* Called by the driver during initialization. * Called by the driver during initialization.

View File

@ -11,7 +11,6 @@
#include <test.h> #include <test.h>
#include <current.h> #include <current.h>
#include <synch.h> #include <synch.h>
#include <synchprobs.h>
#define PROBLEMS_MAX_YIELDER 16 #define PROBLEMS_MAX_YIELDER 16
#define PROBLEMS_MAX_SPINNER 8192 #define PROBLEMS_MAX_SPINNER 8192

View File

@ -39,7 +39,6 @@
#include <thread.h> #include <thread.h>
#include <test.h> #include <test.h>
#include <synch.h> #include <synch.h>
#include <synchprobs.h>
/* /*
* Called by the driver during initialization. * Called by the driver during initialization.

View File

@ -47,18 +47,18 @@
struct semaphore * struct semaphore *
sem_create(const char *name, unsigned initial_count) sem_create(const char *name, unsigned initial_count)
{ {
struct semaphore *sem; struct semaphore *sem;
sem = kmalloc(sizeof(*sem)); sem = kmalloc(sizeof(*sem));
if (sem == NULL) { if (sem == NULL) {
return NULL; return NULL;
} }
sem->sem_name = kstrdup(name); sem->sem_name = kstrdup(name);
if (sem->sem_name == NULL) { if (sem->sem_name == NULL) {
kfree(sem); kfree(sem);
return NULL; return NULL;
} }
sem->sem_wchan = wchan_create(sem->sem_name); sem->sem_wchan = wchan_create(sem->sem_name);
if (sem->sem_wchan == NULL) { if (sem->sem_wchan == NULL) {
@ -68,39 +68,39 @@ sem_create(const char *name, unsigned initial_count)
} }
spinlock_init(&sem->sem_lock); spinlock_init(&sem->sem_lock);
sem->sem_count = initial_count; sem->sem_count = initial_count;
return sem; return sem;
} }
void void
sem_destroy(struct semaphore *sem) sem_destroy(struct semaphore *sem)
{ {
KASSERT(sem != NULL); KASSERT(sem != NULL);
/* wchan_cleanup will assert if anyone's waiting on it */ /* wchan_cleanup will assert if anyone's waiting on it */
spinlock_cleanup(&sem->sem_lock); spinlock_cleanup(&sem->sem_lock);
wchan_destroy(sem->sem_wchan); wchan_destroy(sem->sem_wchan);
kfree(sem->sem_name); kfree(sem->sem_name);
kfree(sem); kfree(sem);
} }
void void
P(struct semaphore *sem) P(struct semaphore *sem)
{ {
KASSERT(sem != NULL); KASSERT(sem != NULL);
/* /*
* May not block in an interrupt handler. * May not block in an interrupt handler.
* *
* For robustness, always check, even if we can actually * For robustness, always check, even if we can actually
* complete the P without blocking. * complete the P without blocking.
*/ */
KASSERT(curthread->t_in_interrupt == false); KASSERT(curthread->t_in_interrupt == false);
/* Use the semaphore spinlock to protect the wchan as well. */ /* Use the semaphore spinlock to protect the wchan as well. */
spinlock_acquire(&sem->sem_lock); spinlock_acquire(&sem->sem_lock);
while (sem->sem_count == 0) { while (sem->sem_count == 0) {
/* /*
* *
* Note that we don't maintain strict FIFO ordering of * Note that we don't maintain strict FIFO ordering of
@ -114,21 +114,21 @@ P(struct semaphore *sem)
* ordering? * ordering?
*/ */
wchan_sleep(sem->sem_wchan, &sem->sem_lock); wchan_sleep(sem->sem_wchan, &sem->sem_lock);
} }
KASSERT(sem->sem_count > 0); KASSERT(sem->sem_count > 0);
sem->sem_count--; sem->sem_count--;
spinlock_release(&sem->sem_lock); spinlock_release(&sem->sem_lock);
} }
void void
V(struct semaphore *sem) V(struct semaphore *sem)
{ {
KASSERT(sem != NULL); KASSERT(sem != NULL);
spinlock_acquire(&sem->sem_lock); spinlock_acquire(&sem->sem_lock);
sem->sem_count++; sem->sem_count++;
KASSERT(sem->sem_count > 0); KASSERT(sem->sem_count > 0);
wchan_wakeone(sem->sem_wchan, &sem->sem_lock); wchan_wakeone(sem->sem_wchan, &sem->sem_lock);
spinlock_release(&sem->sem_lock); spinlock_release(&sem->sem_lock);
@ -141,59 +141,59 @@ V(struct semaphore *sem)
struct lock * struct lock *
lock_create(const char *name) lock_create(const char *name)
{ {
struct lock *lock; struct lock *lock;
lock = kmalloc(sizeof(*lock)); lock = kmalloc(sizeof(*lock));
if (lock == NULL) { if (lock == NULL) {
return NULL; return NULL;
} }
lock->lk_name = kstrdup(name); lock->lk_name = kstrdup(name);
if (lock->lk_name == NULL) { if (lock->lk_name == NULL) {
kfree(lock); kfree(lock);
return NULL; return NULL;
} }
// add stuff here as needed // add stuff here as needed
return lock; return lock;
} }
void void
lock_destroy(struct lock *lock) lock_destroy(struct lock *lock)
{ {
KASSERT(lock != NULL); KASSERT(lock != NULL);
// add stuff here as needed // add stuff here as needed
kfree(lock->lk_name); kfree(lock->lk_name);
kfree(lock); kfree(lock);
} }
void void
lock_acquire(struct lock *lock) lock_acquire(struct lock *lock)
{ {
// Write this // Write this
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
} }
void void
lock_release(struct lock *lock) lock_release(struct lock *lock)
{ {
// Write this // Write this
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
} }
bool bool
lock_do_i_hold(struct lock *lock) lock_do_i_hold(struct lock *lock)
{ {
// Write this // Write this
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
return true; // dummy until code gets written return true; // dummy until code gets written
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -204,47 +204,47 @@ lock_do_i_hold(struct lock *lock)
struct cv * struct cv *
cv_create(const char *name) cv_create(const char *name)
{ {
struct cv *cv; struct cv *cv;
cv = kmalloc(sizeof(*cv)); cv = kmalloc(sizeof(*cv));
if (cv == NULL) { if (cv == NULL) {
return NULL; return NULL;
} }
cv->cv_name = kstrdup(name); cv->cv_name = kstrdup(name);
if (cv->cv_name==NULL) { if (cv->cv_name==NULL) {
kfree(cv); kfree(cv);
return NULL; return NULL;
} }
// add stuff here as needed // add stuff here as needed
return cv; return cv;
} }
void void
cv_destroy(struct cv *cv) cv_destroy(struct cv *cv)
{ {
KASSERT(cv != NULL); KASSERT(cv != NULL);
// add stuff here as needed // add stuff here as needed
kfree(cv->cv_name); kfree(cv->cv_name);
kfree(cv); kfree(cv);
} }
void void
cv_wait(struct cv *cv, struct lock *lock) cv_wait(struct cv *cv, struct lock *lock)
{ {
// Write this // Write this
(void)cv; // suppress warning until code gets written (void)cv; // suppress warning until code gets written
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
} }
void void
cv_signal(struct cv *cv, struct lock *lock) cv_signal(struct cv *cv, struct lock *lock)
{ {
// Write this // Write this
(void)cv; // suppress warning until code gets written (void)cv; // suppress warning until code gets written
(void)lock; // suppress warning until code gets written (void)lock; // suppress warning until code gets written
} }