TLS(2)

NAME
set_tls_area, get_tls_area - kernel TLS (thread local storage) support

LIBRARY
libc

SYNOPSIS
#include <sys/tls.h>
int
set_tls_area(int which, struct tls_info *info, size_t infosize);
int
get_tls_area(int which, struct tls_info *info, size_t infosize);

DESCRIPTION
The set_tls_area() system call creates an entry for the TLS facility which representing thread local storage as specified by the info structure. A descriptor representing the facility is returned, or -1 if an error occurred. The facility may be cleared by specifying a NULL pointer and an infosize of 0. The get_tls_area() system call retrieves the requested TLS facility. A descriptor representing the facility is returned, or -1 if an error occurred. If you simply want the descriptor you may specify a NULL pointer and an infosize of 0.

The returned descriptor and the TLS mechanism is machine-dependent. On IA32 three global segment descriptors are supported (0, 1, and 2) and the %gs load value is returned.

The tls_info structure passed to set_tls_area() should first be zerod (to remain compatible with future extensions) and then initialized.

    struct tls_info {
            void	*base;		/* base address of TLS area */
            int	size;		/* size of TLS area in bytes */
    };

The actual implementation of the area is machine-dependent. If the kernel is unable to accommodate the supplied size it may create a larger area. If the kernel is unable to accommodate the supplied base address an error will be returned.

RETURN VALUES
A return value of 0 is returned on success, -1 on error.

EXAMPLES
    /*
     * Pseudo example showing how the TLS system calls work on IA32.
     */
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/tls.h>
    int X;
    static int getdata(int offset);
    int
    main(int ac, char **av)
    {
        int i;
        int gs;
        struct tls_info info;
        info.base = &X;
        info.size = sizeof(X);
        if ((gs = set_tls_area(0, &info, sizeof(info))) < 0) {
            perror("setarea");
            exit(1);
        }
        printf("gs = %04x\n", gs);
        __asm __volatile("mov %0,%%gs" : : "g" (gs) );
        if (get_tls_area(0, &info, sizeof(info)) < 0) {
            perror("getarea");
            exit(1);
        }
        printf("%p/%d\n", info.base, info.size);
        X = 1;
        printf("should be 1: %d\n", getdata(0));
        X = 2;
        printf("should be 2: %d\n", getdata(0));
        printf("this should fault:\n");
        fflush(stdout);
        getdata(4);
        return(0);
    }
    static int
    getdata(int offset)
    {
        int rv;
        __asm __volatile("movl %%gs:(%0),%%eax; movl %%eax,%1" : "+r" (offset) : "m"
     (rv) : "ax");
        return (rv);
    }

ERRORS

[ERANGE]
    The specified facility index, which, is not supported.

[EINVAL]
    An invalid parameter has been specified.

[ENOENT]
    (get_tls_area) The specified facility has not been initialized with sys_set_tls_area().

SEE ALSO
umtx(2)

HISTORY
The set_tls_area(), and get_tls_area() function calls first appeared in DragonFly 1.1.