I use %gs as prefix for per-cpu vars. Offset to per-cpu area is kernel only, so I need to swapgs when switching between kernel mode and user mode.
In the code, I use macro and inline assembly to access per-cpu vars of current CPU, just use movsq with %gs prefix.
Recently I heard thread local storage (TLS), and it uses %fs as prefix. What's good about TLS is compilers have good support for it. Just mark the variable with __thread and access it, compiler will generate code with %fs prefix automatically.
It seems per-cpu variables are just kernel version of TLS. Sometimes I need to access per-cpu var of another CPU, but most time I just access per-cpu var of current CPU. So is there a way to configure GCC to use %gs as TLS self pointer? Since x86 only has swapgs, no swapfs.
If I can make kernel TLS use %gs, then the thiscpu() macro can be completely removed, code will be alot simpler.
Thanks.
Is per-CPU var same as thread local storage? Can I use TLS with %gs?
-
- Member
- Posts: 70
- Joined: Fri Jun 28, 2013 1:48 am
- Contact:
Is per-CPU var same as thread local storage? Can I use TLS with %gs?
Reinventing the Wheel, code: https://github.com/songziming/wheel
Re: Is per-CPU var same as thread local storage? Can I use TLS with %gs?
__thread makes many assumptions about how your %fs is set up, and setting it up correctly is not simple. For example, you would need to allocate your TLS and CPU descriptor consecutively, and put your %fs between them. There is also no convenient swapfs instruction, like there is for %gs.
If you want to use fewer macros, I would suggest collecting all per-cpu variables into a structure. Call it "struct cpu". Then start that structure with a pointer to self:
The set %gs to point at the correct struct cpu, and then you can use a trick like this:
And now you can use the CPU pointer like all other pointers.
If you want to use fewer macros, I would suggest collecting all per-cpu variables into a structure. Call it "struct cpu". Then start that structure with a pointer to self:
Code: Select all
struct cpu {
struct cpu *self;
int nr;
...
Code: Select all
static inline struct cpu *cpu_self(void) {
struct cpu *r;
__asm__("mov %%gs:0, %0" : "=r"(r));
return r;
}
Carpe diem!
-
- Member
- Posts: 5560
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Is per-CPU var same as thread local storage? Can I use TLS with %gs?
I don't know of any easy way to change which register GCC uses for thread-local storage, but maybe named address spaces are closer to what you want.
This can be combined with nullplan's suggestion of using a struct that points to itself, like so:
This can be combined with nullplan's suggestion of using a struct that points to itself, like so:
Code: Select all
static inline struct cpu *cpu_self(void) {
return ((__seg_gs struct cpu *)0)->self;
}