From mboxrd@z Thu Jan 1 00:00:00 1970 From: Linus Torvalds To: Lucio De Re Cc: 9fans@cse.psu.edu Subject: Re: [9fans] Re: Threads: Sewing badges of honor onto a Kernel In-Reply-To: <20040227115257.F22848@cackle.proxima.alt.za> Message-ID: References: <20040227101110.E24932@cackle.proxima.alt.za> <64FBCAEA-68FD-11D8-B851-000A95B984D8@mightycheese.com> <20040227103130.E22848@cackle.proxima.alt.za> <20040227115257.F22848@cackle.proxima.alt.za> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Date: Fri, 27 Feb 2004 02:11:27 -0800 Topicbox-Message-UUID: ff108d6a-eacc-11e9-9e20-41e7f4b1d025 On Fri, 27 Feb 2004, Lucio De Re wrote: > On Fri, Feb 27, 2004 at 01:46:27AM -0800, Linus Torvalds wrote: > > > > Why are you ignoring registers? That's what you _should_ use. > > Because they are not in the base language? Because they impair > portability? You literally need _one_ operation: you need the operation of "give me the TLS pointer" (well, your thread setup code obviously needs a way to set the pointer when creating a thread too). The rest _is_ in the language - although if you want nice syntax, you sometimes want more explicit language support. Have you ever looked at those system header files? They contain a lot of magic cruft that is specific to your compiler and your particular architecture. > Because in my C code, I can't instantiate them as variables without > running the risk of my colleagues doing the same in a conflicting > manner? > > Just out of curiosity, how do I get to the private space without > a lock? It's been a long time since I studied these things and lots > of water has flown under bridges, so I could be missing something. In the kernel, the x86 implementation of the thread-local pointer is literally: /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1))); return ti; } That's it. It compiles to _two_ instructions, eg something like movl $-8192,%eax andl %esp,%eax and it's all done. You literally _cannot_ do it faster or smaller. No locking, no memory accesses, no TLB games, no NOTHING. On some other architectures, you have register struct thread_info *__current_thread_info __asm__("$8"); #define current_thread_info() __current_thread_info which just tells the compiler that the thread_info pointer is in hardware register 8. And you're done. The compiler will just automatically use %r8 whenever you do a "current_thread_info()". In user space, there are similar things going on. These days there is more compiler support to make it easier to create these things, but it all boils down to having a thread-local pointer somewhere. Linus