another attempt at cpu-local variables.

this time do it ourselves instead of piggybacking on TLS.
add -fno-pic to Makefile; pic code breaks our fake TLS.
This commit is contained in:
Russ Cox 2009-09-02 10:07:59 -07:00
parent 374362c55c
commit 7e0cc8e36e
4 changed files with 16 additions and 18 deletions

View file

@ -37,7 +37,7 @@ AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump OBJDUMP = $(TOOLPREFIX)objdump
CFLAGS = -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
ASFLAGS = -m32 ASFLAGS = -m32
# FreeBSD ld wants ``elf_i386_fbsd'' # FreeBSD ld wants ``elf_i386_fbsd''
@ -49,8 +49,8 @@ xv6.img: bootblock kernel fs.img
dd if=kernel of=xv6.img seek=1 conv=notrunc dd if=kernel of=xv6.img seek=1 conv=notrunc
bootblock: bootasm.S bootmain.c bootblock: bootasm.S bootmain.c
$(CC) $(CFLAGS) -O -nostdinc -I. -c bootmain.c $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c
$(CC) $(CFLAGS) -nostdinc -I. -c bootasm.S $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S
$(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o
$(OBJDUMP) -S bootblock.o > bootblock.asm $(OBJDUMP) -S bootblock.o > bootblock.asm
$(OBJCOPY) -S -O binary -j .text bootblock.o bootblock $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock
@ -93,7 +93,7 @@ _forktest: forktest.o $(ULIB)
$(OBJDUMP) -S _forktest > forktest.asm $(OBJDUMP) -S _forktest > forktest.asm
mkfs: mkfs.c fs.h mkfs: mkfs.c fs.h
gcc $(CFLAGS) -Wall -o mkfs mkfs.c gcc -Wall -o mkfs mkfs.c
UPROGS=\ UPROGS=\
_cat\ _cat\
@ -139,7 +139,7 @@ bochs : fs.img xv6.img
bochs -q bochs -q
qemu: fs.img xv6.img qemu: fs.img xv6.img
qemu -parallel stdio -hdb fs.img xv6.img qemu -parallel stdio -smp 2 -hdb fs.img xv6.img
qemutty: fs.img xv6.img qemutty: fs.img xv6.img
qemu -nographic -smp 2 -hdb fs.img xv6.img qemu -nographic -smp 2 -hdb fs.img xv6.img

4
main.c
View file

@ -5,9 +5,6 @@
#include "proc.h" #include "proc.h"
#include "x86.h" #include "x86.h"
__thread struct cpu *cpu;
__thread struct proc *proc;
static void bootothers(void); static void bootothers(void);
static void mpmain(void) __attribute__((noreturn)); static void mpmain(void) __attribute__((noreturn));
@ -22,6 +19,7 @@ main(void)
ioapicinit(); // another interrupt controller ioapicinit(); // another interrupt controller
consoleinit(); // I/O devices & their interrupts consoleinit(); // I/O devices & their interrupts
uartinit(); // serial port uartinit(); // serial port
cprintf("cpus %p cpu %p\n", cpus, cpu);
cprintf("\ncpu%d: starting xv6\n\n", cpu->id); cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
kinit(); // physical memory allocator kinit(); // physical memory allocator

3
proc.c
View file

@ -70,12 +70,11 @@ ksegment(void)
c = &cpus[cpunum()]; c = &cpus[cpunum()];
c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0); c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0);
c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
c->gdt[SEG_KCPU] = SEG(STA_W, &c->tlsstruct, 0xffffffff, 0); c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);
lgdt(c->gdt, sizeof(c->gdt)); lgdt(c->gdt, sizeof(c->gdt));
loadfsgs(SEG_KCPU << 3); loadfsgs(SEG_KCPU << 3);
// Initialize cpu-local storage. // Initialize cpu-local storage.
c->tlsstruct = &c->tlsstruct;
asm volatile(""); // Do not let gcc reorder across this line. asm volatile(""); // Do not let gcc reorder across this line.
cpu = c; cpu = c;
proc = 0; proc = 0;

17
proc.h
View file

@ -59,10 +59,9 @@ struct cpu {
int ncli; // Depth of pushcli nesting. int ncli; // Depth of pushcli nesting.
int intena; // Were interrupts enabled before pushcli? int intena; // Were interrupts enabled before pushcli?
// "Thread"-local storage variables // Cpu-local storage variables; see below
struct cpu *cpu; struct cpu *cpu;
struct proc *proc; struct proc *proc;
void *tlsstruct;
}; };
extern struct cpu cpus[NCPU]; extern struct cpu cpus[NCPU];
@ -70,9 +69,11 @@ extern int ncpu;
// Per-CPU variables, holding pointers to the // Per-CPU variables, holding pointers to the
// current cpu and to the current process. // current cpu and to the current process.
// The __thread prefix tells gcc to refer to them in the segment // The asm suffix tells gcc to use "%gs:0" to refer to cpu
// pointed at by gs; the name __thread derives from the use // and "%gs:4" to refer to proc. ksegment sets up the
// of the same mechanism to provide per-thread storage in // %gs segment register so that %gs refers to the memory
// multithreaded user programs. // holding those two variables in the local cpu's struct cpu.
extern __thread struct cpu *cpu; // This cpu. // This is similar to how thread-local variables are implemented
extern __thread struct proc *proc; // Current process on this cpu. // in thread libraries such as Linux pthreads.
extern struct cpu *cpu asm("%gs:0"); // This cpu.
extern struct proc *proc asm("%gs:4"); // Current proc on this cpu.