Overhaul the kernel-simulation bits here to use pthreads instead.

If somebody wanted to, this could for the beginning of a "libkernel"
which could be used to run kernel code in userland.

Sponsored by:	DARPA & NAI Labs.
This commit is contained in:
Poul-Henning Kamp 2002-09-13 13:13:00 +00:00
parent f3a49419c0
commit 6309b291ec
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=103288
19 changed files with 144 additions and 160 deletions

View File

@ -5,7 +5,7 @@ NOMAN = no
NOOBJ = youbet
CFLAGS += -g -W -Wall -Wstrict-prototypes -Wmissing-prototypes
CFLAGS += -Wpointer-arith -static -I/usr/src/sys -I../..
CFLAGS += -DKERNELSIM
CFLAGS += -DKERNELSIM -pthread
LDADD += -L../../GLib -lG
LDADD += -L/usr/local/lib -lexpat
DPADD += ../../GLib/libG.a

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{
struct g_consumer *cp;

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{
struct g_consumer *cp;

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{
struct g_consumer *cp;

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{
struct g_consumer *cp;

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -47,7 +47,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -46,7 +46,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
int
void *
thread_sim(void *ptr __unused)
{

View File

@ -66,42 +66,70 @@ conff(char *file)
free(s);
}
static int
static void *
thread_up(void *ptr)
{
struct thread *tp = ptr;
int error;
printf("Running %s\n", tp->name);
error = pthread_cond_init(&ptc_up, NULL);
if (error)
err(1, "pthread_cond_init(ptc_up)");
error = pthread_mutex_init(&ptm_up, NULL);
if (error)
err(1, "pthread_mutex_init(ptm_up)");
error = pthread_mutex_lock(&ptm_up);
if (error)
err(1, "pthread_mutex_init(ptm_up)");
for (;;) {
g_io_schedule_up(tp);
tsleep(&g_wait_up, 0, "up", 0);
error = pthread_cond_wait(&ptc_up, &ptm_up);
}
}
static int
static void *
thread_down(void *ptr)
{
struct thread *tp = ptr;
int error;
printf("Running %s\n", tp->name);
error = pthread_cond_init(&ptc_down, NULL);
if (error)
err(1, "pthread_cond_init(ptc_down)");
error = pthread_mutex_init(&ptm_down, NULL);
if (error)
err(1, "pthread_mutex_init(ptm_down)");
error = pthread_mutex_lock(&ptm_down);
if (error)
err(1, "pthread_mutex_init(ptm_down)");
for (;;) {
g_io_schedule_down(tp);
tsleep(&g_wait_down, 0, "down", 0);
error = pthread_cond_wait(&ptc_down, &ptm_down);
}
}
static int
static void *
thread_event(void *ptr)
{
struct thread *tp = ptr;
/* nice(5); */
int error;
printf("Running %s\n", tp->name);
error = pthread_cond_init(&ptc_event, NULL);
if (error)
err(1, "pthread_cond_init(ptc_event)");
error = pthread_mutex_init(&ptm_event, NULL);
if (error)
err(1, "pthread_mutex_init(ptm_event)");
error = pthread_mutex_lock(&ptm_event);
if (error)
err(1, "pthread_mutex_init(ptm_event)");
for (;;) {
usleep(100000);
g_run_events();
tsleep(&g_wait_event, 0, "events", 0);
error = pthread_cond_wait(&ptc_event, &ptm_event);
}
}

View File

@ -51,6 +51,8 @@
#include <sys/mman.h>
#include <machine/atomic.h>
#include <pthread.h>
#define NTHREAD 30
static struct thread thr[NTHREAD];
@ -61,6 +63,8 @@ int bootverbose = 1;
void
done(void)
{
rattle();
weredone = 1;
exit(0);
}
@ -94,136 +98,108 @@ secrethandshake()
exit(9);
}
static int sleeping;
void
biodone(struct bio *bp)
{
bp->bio_flags |= BIO_DONE;
if (bp->bio_done != NULL)
bp->bio_done(bp);
}
int
biowait(struct bio *bp, const char *wchan __unused)
{
while ((bp->bio_flags & BIO_DONE) == 0)
usleep(10000);
if (!(bp->bio_flags & BIO_ERROR))
return (0);
if (bp->bio_error)
return (bp->bio_error);
return (EIO);
}
void
wakeup(void *chan)
{
int i;
secrethandshake();
for (i = 0; i < NTHREAD; i++)
if (thr[i].wchan == chan) {
printf("wakeup %s\n", thr[i].name);
atomic_clear_int(&sleeping, 1 << i);
write(thr[i].pipe[1], "\0", 1);
}
if (chan == &g_wait_event)
pthread_cond_signal(&ptc_event);
else if (chan == &g_wait_up)
pthread_cond_signal(&ptc_up);
else if (chan == &g_wait_down)
pthread_cond_signal(&ptc_down);
else
return;
}
int hz;
int
tsleep(void *chan, int pri __unused, const char *wmesg, int timo)
tsleep(void *chan __unused, int pri __unused, const char *wmesg __unused, int timo)
{
fd_set r,w,e;
int i, j, fd, pid;
struct timeval tv;
char buf[100];
struct thread *tp;
secrethandshake();
pid = getpid();
tp = NULL;
for (i = 0; i < NTHREAD; i++) {
if (pid != thr[i].pid)
continue;
tp = &thr[i];
break;
}
KASSERT(tp != NULL, ("Confused tp=%p has no name\n", tp));
KASSERT(tp->name != NULL, ("Confused tp=%p has no name\n", tp));
tp->wchan = chan;
tp->wmesg = wmesg;
fd = tp->pipe[0];
printf("tsleep %s %p %s\n", tp->name, chan, wmesg);
for (;;) {
if (timo > 0) {
tv.tv_sec = 1;
tv.tv_usec = 0;
} else {
tv.tv_sec = 3;
tv.tv_usec = 0;
}
FD_ZERO(&r);
FD_ZERO(&w);
FD_ZERO(&e);
FD_SET(fd, &r);
atomic_set_int(&sleeping, 1 << i);
j = select(fd + 1, &r, &w, &e, &tv);
secrethandshake();
break;
}
if (j)
i = read(fd, buf, sizeof(buf));
tp->wchan = 0;
tp->wmesg = 0;
return(i);
usleep(timo);
return (0);
}
void
rattle()
{
int i, j;
int i;
pthread_yield();
for (;;) {
secrethandshake();
usleep(500000);
secrethandshake();
i = sleeping & 7;
if (i != 7)
continue;
usleep(20000);
j = sleeping & 7;
if (i != j)
continue;
printf("Rattle(%d) \"%s\" \"%s\" \"%s\"\n", i, thr[0].wmesg, thr[1].wmesg, thr[2].wmesg);
if (!thr[0].wmesg || strcmp(thr[0].wmesg, "up"))
continue;
if (!thr[1].wmesg || strcmp(thr[1].wmesg, "down"))
continue;
if (!thr[2].wmesg || strcmp(thr[2].wmesg, "events"))
continue;
break;
i = pthread_mutex_trylock(&ptm_up);
if (i != EBUSY) {
i = pthread_mutex_trylock(&ptm_down);
if (i != EBUSY) {
i = pthread_mutex_trylock(&ptm_event);
if (i != EBUSY)
break;
pthread_mutex_unlock(&ptm_down);
}
pthread_mutex_unlock(&ptm_up);
}
usleep(100000);
}
pthread_mutex_unlock(&ptm_event);
pthread_mutex_unlock(&ptm_down);
pthread_mutex_unlock(&ptm_up);
return;
}
void
new_thread(int (*func)(void *arg), char *name)
new_thread(void *(*func)(void *arg), char *name)
{
char *c;
struct thread *tp;
static int nextt;
int error;
tp = thr + nextt++;
c = calloc(1, 65536);
error = pthread_create(&tp->tid, NULL, func, tp);
if (error)
err(1, "pthread_create(%s)", name);
tp->name = name;
pipe(tp->pipe);
tp->pid = rfork_thread(RFPROC|RFMEM, c + 65536 - 16, func, tp);
if (tp->pid <= 0)
err(1, "rfork_thread");
printf("New Thread %d %s %p %d\n", tp - thr, name, tp, tp->pid);
}
#define FASCIST 0
int malloc_lock;
void *
g_malloc(int size, int flags)
{
void *p;
secrethandshake();
while (!atomic_cmpset_int(&malloc_lock, 0, 1))
sched_yield();
#if FASCIST
p = malloc(4096);
printf("Malloc %p \n", p);
#else
p = malloc(size);
#endif
malloc_lock = 0;
if (flags & M_ZERO)
memset(p, 0, size);
else
@ -236,103 +212,76 @@ g_free(void *ptr)
{
secrethandshake();
while (!atomic_cmpset_int(&malloc_lock, 0, 1))
sched_yield();
#if FASCIST
printf("Free %p \n", ptr);
munmap(ptr, 4096);
#else
free(ptr);
#endif
malloc_lock = 0;
}
static pthread_mutex_t pt_topology;
void
g_init(void)
{
pthread_mutex_init(&pt_topology, NULL);
g_io_init();
g_event_init();
}
static int topology_lock;
void
g_topology_lock()
{
int pid;
pid = getpid();
if (atomic_cmpset_int(&topology_lock, 0, pid))
return;
KASSERT(pid != topology_lock,
("Locking topology against myself pid %d\n", pid));
while (!atomic_cmpset_int(&topology_lock, 0, pid)) {
printf("Waiting for topology lock mypid = %d held by %d\n",
pid, topology_lock);
sleep(1);
}
pthread_mutex_lock(&pt_topology);
}
void
g_topology_unlock()
{
KASSERT(topology_lock == getpid(), ("Didn't have topology_lock to release"));
topology_lock = 0;
pthread_mutex_unlock(&pt_topology);
}
void
g_topology_assert()
{
#if 0
if (topology_lock == getpid())
return;
KASSERT(1 == 0, ("Lacking topology_lock"));
}
void
mtx_lock_spin(struct mtx *mp)
{
while(!atomic_cmpset_int(&mp->mtx_lock, 0, 1)) {
printf("trying to get lock...\n");
sched_yield();
}
}
void
mtx_unlock_spin(struct mtx *mp)
{
mp->mtx_lock = 0;
#endif
}
void
mtx_init(struct mtx *mp, const char *bla __unused, const char *yak __unused, int foo __unused)
{
mp->mtx_lock = 0;
pthread_mutex_init((pthread_mutex_t *)&mp->mtx_object, NULL);
}
void
mtx_destroy(struct mtx *mp)
{
mp->mtx_lock = 0;
pthread_mutex_destroy((pthread_mutex_t *)&mp->mtx_object);
}
void
mtx_lock(struct mtx *mp)
{
mp->mtx_lock = 0;
pthread_mutex_lock((pthread_mutex_t *)&mp->mtx_object);
}
void
mtx_unlock(struct mtx *mp)
{
mp->mtx_lock = 0;
pthread_mutex_unlock((pthread_mutex_t *)&mp->mtx_object);
}
struct mtx Giant;

View File

@ -35,19 +35,21 @@
* $FreeBSD$
*/
#include <pthread.h>
pthread_cond_t ptc_up, ptc_down, ptc_event;
pthread_mutex_t ptm_up, ptm_down, ptm_event;
/* bio.h */
struct bio {
enum {
BIO_INVALID = 0,
BIO_READ,
BIO_WRITE,
BIO_FREE,
BIO_DELETE,
BIO_FORMAT,
BIO_GETATTR,
BIO_SETATTR
BIO_READ = 1,
BIO_WRITE = 2,
BIO_DELETE = 4,
BIO_GETATTR = 8,
BIO_SETATTR = 16
} bio_cmd;
struct { int foo; } stats;
TAILQ_ENTRY(bio) bio_queue;
@ -66,8 +68,12 @@ struct bio {
struct bio *bio_linkage;
int bio_flags;
#define BIO_DONE 0x1
#define BIO_ERROR 0x2
};
void biodone(struct bio *bp);
int biowait(struct bio *bp, const char *wchan);
/* geom_dev.c */
void g_dev_init(void *junk);
struct g_consumer *g_dev_opendev(char *name, int w, int r, int e);
@ -76,6 +82,7 @@ int g_dev_request(char *name, struct bio *bp);
/* geom_kernsim.c */
struct thread {
char *name;
pthread_t tid;
int pid;
void *wchan;
const char *wmesg;
@ -90,7 +97,7 @@ int tsleep __P((void *chan, int pri, const char *wmesg, int timo));
#define PPAUSE 0
extern int hz;
void new_thread(int (*func)(void *arg), char *name);
void new_thread(void *(*func)(void *arg), char *name);
extern int bootverbose;
#define KASSERT(cond, txt) do {if (!(cond)) {printf txt; conff("err"); abort();}} while(0)
@ -139,7 +146,7 @@ void g_bsd_init(void);
void g_mbr_init(void);
void g_mbrext_init(void);
int thread_sim(void *ptr);
void *thread_sim(void *ptr);
void dumpf(char *file);
void conff(char *file);