664324745e
fix race in schedule()
135 lines
4.5 KiB
Text
135 lines
4.5 KiB
Text
bochs 2.2.6:
|
|
./configure --enable-smp --enable-disasm --enable-debugger --enable-all-optimizations --enable-4meg-pages --enable-global-pages --enable-pae --disable-reset-on-triple-fault
|
|
bochs CVS after 2.2.6:
|
|
./configure --enable-smp --enable-disasm --enable-debugger --enable-all-optimizations --enable-4meg-pages --enable-global-pages --enable-pae
|
|
|
|
bootmain.c doesn't work right if the ELF sections aren't
|
|
sector-aligned. so you can't use ld -N. and the sections may also need
|
|
to be non-zero length, only really matters for tiny "kernels".
|
|
|
|
kernel loaded at 1 megabyte. stack same place that bootasm.S left it.
|
|
|
|
kinit() should find real mem size
|
|
and rescue useable memory below 1 meg
|
|
|
|
no paging, no use of page table hardware, just segments
|
|
|
|
no user area: no magic kernel stack mapping
|
|
so no copying of kernel stack during fork
|
|
though there is a kernel stack page for each process
|
|
|
|
no kernel malloc(), just kalloc() for user core
|
|
|
|
user pointers aren't valid in the kernel
|
|
|
|
setting up first process
|
|
we do want a process zero, as template
|
|
but not runnable
|
|
just set up return-from-trap frame on new kernel stack
|
|
fake user program that calls exec
|
|
|
|
map text read-only?
|
|
shared text?
|
|
|
|
what's on the stack during a trap or sys call?
|
|
PUSHA before scheduler switch? for callee-saved registers.
|
|
segment contents?
|
|
what does iret need to get out of the kernel?
|
|
how does INT know what kernel stack to use?
|
|
|
|
are interrupts turned on in the kernel? probably.
|
|
|
|
per-cpu curproc
|
|
one tss per process, or one per cpu?
|
|
one segment array per cpu, or per process?
|
|
|
|
pass curproc explicitly, or implicit from cpu #?
|
|
e.g. argument to newproc()?
|
|
hmm, you need a global curproc[cpu] for trap() &c
|
|
|
|
test stack expansion
|
|
test running out of memory, process slots
|
|
|
|
we can't really use a separate stack segment, since stack addresses
|
|
need to work correctly as ordinary pointers. the same may be true of
|
|
data vs text. how can we have a gap between data and stack, so that
|
|
both can grow, without committing 4GB of physical memory? does this
|
|
mean we need paging?
|
|
|
|
what's the simplest way to add the paging we need?
|
|
one page table, re-write it each time we leave the kernel?
|
|
page table per process?
|
|
probably need to use 0-0xffffffff segments, so that
|
|
both data and stack pointers always work
|
|
so is it now worth it to make a process's phys mem contiguous?
|
|
or could use segment limits and 4 meg pages?
|
|
but limits would prevent using stack pointers as data pointers
|
|
how to write-protect text? not important?
|
|
|
|
perhaps have fixed-size stack, put it in the data segment?
|
|
|
|
oops, if kernel stack is in contiguous user phys mem, then moving
|
|
users' memory (e.g. to expand it) will wreck any pointers into the
|
|
kernel stack.
|
|
|
|
do we need to set fs and gs? so user processes can't abuse them?
|
|
|
|
setupsegs() may modify current segment table, is that legal?
|
|
|
|
trap() ought to lgdt on return, since currently only done in swtch()
|
|
|
|
protect hardware interrupt vectors from user INT instructions?
|
|
|
|
test out-of-fd cases for creating pipe.
|
|
test pipe reader closes then write
|
|
test two readers, two writers.
|
|
test children being inherited by grandparent &c
|
|
|
|
some sleep()s should be interruptible by kill()
|
|
|
|
cli/sti in acquire/release should nest!
|
|
in case you acquire two locks
|
|
|
|
what would need fixing if we got rid of kernel_lock?
|
|
console output
|
|
proc_exit() needs lock on proc *array* to deallocate
|
|
kill() needs lock on proc *array*
|
|
allocator's free list
|
|
global fd table (really free-ness)
|
|
sys_close() on fd table
|
|
fork on proc list, also next pid
|
|
hold lock until public slots in proc struct initialized
|
|
|
|
locks
|
|
init_lock
|
|
sequences CPU startup
|
|
proc_table_lock
|
|
also protects next_pid
|
|
per-fd lock *just* protects count read-modify-write
|
|
also maybe freeness?
|
|
memory allocator
|
|
printf
|
|
|
|
wakeup needs proc_table_lock
|
|
so we need recursive locks?
|
|
or you must hold the lock to call wakeup?
|
|
|
|
if locks contain proc *, they can't be used at interrupt time
|
|
only proc_table_lock will be used at interrupt time?
|
|
maybe it doesn't matter if we use curproc?
|
|
|
|
in general, the table locks protect both free-ness and
|
|
public variables of table elements
|
|
in many cases you can use table elements w/o a lock
|
|
e.g. if you are the process, or you are using an fd
|
|
|
|
why can't i get a lock in console code?
|
|
always triple fault
|
|
lock code shouldn't call cprintf...
|
|
ide_init doesn't work now?
|
|
and IOAPIC: read from unsupported address
|
|
when running pre-empt user test
|
|
so maybe something wrong with clock interrupts
|
|
no! if one cpu holds lock w/ curproc0=,
|
|
then another cpu can take it, it looks like
|
|
a recursive acquire()
|