Re: Q: Thread local storage, thread IDs

Borislav Deianov (borislav@ensim.com)
Sat, 31 Jul 1999 02:01:30 -0700


Hi Jörg,

In article <37A02181.AC4DA0EA@trantor.de> you wrote:
> Now, I tried to use the modify_ldt system call. I was able to create a
> new selector (result = 0), but couldn't use it. I guess that's because
> the base address I specified was expected to be in linear (physical)
> address space, not in the flat address space of my process. At least I

There are three types of addresses: virtual (before segment
translation), linear (after segment translation but before paging) and
physical. User space only sees virtual addresses, the base addresses
in the LDT should be linear. Luckily, Linux uses a flat model, so, in
general, virtual addresses are the same as linear addresses. (I think,
I'm not quite an x86 expert.)

> got a segmentation fault. I also tried to read the process LDT and
> modify one of the existing selectors, but the size of the LDT I got from
> Linux was always 0. What did I do wrong?

Looks like processes don't have a LDT until they call modify_ldt for
the first time. Also, see the comments in arch/i386/kernel/ldt.c about
creating a LDT before the first clone.

> Maybe someone with more knowledge in protected mode assembler Linux
> programming could even give me the few lines of assembler code needed to
> solve my complete problem: I have a memory block named TIB where my
> thread information is stored. This block may be 4- or 16-byte-aligned or
> whatever is necessary. I need an FS selector pointing to the block, so
> that FS:[0] is the first longword of my thread information.

I needed this too, so I gave it a shot.

Regards,
Borislav

------------
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <asm/ldt.h>
#include <asm/unistd.h>

int modify_ldt(int func, void *ptr, unsigned long bytecount);
int tib_create(void *tls, size_t size);
int tib_read(unsigned int index);

_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)

int tib_create(void *tib, size_t size)
{
struct modify_ldt_ldt_s entry;

entry.entry_number = 0;
entry.base_addr = (unsigned long)tib;
entry.limit = size;
entry.seg_32bit = 1;
entry.contents = MODIFY_LDT_CONTENTS_DATA;
entry.read_exec_only = 0;
entry.limit_in_pages = 0;
entry.seg_not_present = 0;

return modify_ldt(1, &entry, sizeof(entry));
}

/* assumes that TIB is an array of ints */
int tib_read(unsigned int index)
{
int res;
asm volatile ("pushw $0x0007\n\t" /* index 0, LDT, ring 3 */
"popw %%fs\n\t"
"movl %%fs:(%1), %0\n\t"
: "=r" (res)
: "r" (index*sizeof(int)));
return res;
}

int tib[4];

int main(void)
{
if (tib_create(tib, sizeof(tib)) == -1) {
perror("tib_create");
exit(EXIT_FAILURE);
}

tib[0] = 12345;
printf("tib_read(0) = %d\n", tib_read(0));

exit(EXIT_SUCCESS);
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/