Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2568 → Rev 2586

/trunk/uspace/lib/libc/generic/tls.c/thread.c
30,31 → 30,18
* @{
*/
/** @file
*
* Support for thread-local storage, as described in:
* Drepper U.: ELF Handling For Thread-Local Storage, 2005
*
* Only static model is supported.
*/
 
#include <thread.h>
#include <libc.h>
#include <stdlib.h>
#include <libarch/faddr.h>
#include <kernel/proc/uarg.h>
#include <fibril.h>
#include <tls.h>
#include <malloc.h>
#include <string.h>
#include <async.h>
#include <align.h>
 
#include <stdio.h>
 
 
#ifndef THREAD_INITIAL_STACK_PAGES_NO
#define THREAD_INITIAL_STACK_PAGES_NO 1
#endif
 
static LIST_INITIALIZE(thread_garbage);
 
extern char _tdata_start;
extern char _tdata_end;
extern char _tbss_start;
extern char _tbss_end;
 
/** Create TLS (Thread Local Storage) data structures.
*
* The code requires, that sections .tdata and .tbss are adjacent. It may be
89,127 → 76,66
__free_tls_arch(tcb, tls_size);
}
 
/** Main thread function.
#ifdef CONFIG_TLS_VARIANT_1
/** Allocate TLS variant 1 data structures.
*
* This function is called from __thread_entry() and is used
* to call the thread's implementing function and perform cleanup
* and exit when thread returns back. Do not call this function
* directly.
*
* @param uarg Pointer to userspace argument structure.
* @param data Start of TLS section. This is an output argument.
* @param size Size of tdata + tbss section.
* @return Pointer to tcb_t structure.
*/
void __thread_main(uspace_arg_t *uarg)
tcb_t *tls_alloc_variant_1(void **data, size_t size)
{
fibril_t *f;
tcb_t *result;
 
f = fibril_setup();
__tcb_set(f->tcb);
 
uarg->uspace_thread_function(uarg->uspace_thread_arg);
/* XXX: we cannot free the userspace stack while running on it */
// free(uarg->uspace_stack);
// free(uarg);
 
/* If there is a manager, destroy it */
async_destroy_manager();
fibril_teardown(f);
 
thread_exit(0);
result = malloc(sizeof(tcb_t) + size);
*data = ((void *)result) + sizeof(tcb_t);
return result;
}
 
/** Create userspace thread.
/** Free TLS variant I data structures.
*
* This function creates new userspace thread and allocates userspace
* stack and userspace argument structure for it.
*
* @param function Function implementing the thread.
* @param arg Argument to be passed to thread.
* @param name Symbolic name of the thread.
* @param tid Thread ID of the newly created thread.
*
* @return Zero on success or a code from @ref errno.h on failure.
* @param tcb Pointer to TCB structure.
* @param size This argument is ignored.
*/
int thread_create(void (* function)(void *), void *arg, char *name,
thread_id_t *tid)
void tls_free_variant_1(tcb_t *tcb, size_t size)
{
char *stack;
uspace_arg_t *uarg;
int rc;
 
stack = (char *) malloc(getpagesize() * THREAD_INITIAL_STACK_PAGES_NO);
if (!stack)
return -1;
uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t));
if (!uarg) {
free(stack);
return -1;
}
uarg->uspace_entry = (void *) FADDR(__thread_entry);
uarg->uspace_stack = (void *) stack;
uarg->uspace_thread_function = function;
uarg->uspace_thread_arg = arg;
uarg->uspace_uarg = uarg;
rc = __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name,
(sysarg_t) tid);
if (rc) {
/*
* Failed to create a new thread.
* Free up the allocated structures.
*/
free(uarg);
free(stack);
}
 
return rc;
free(tcb);
}
#endif
 
/** Terminate current thread.
#ifdef CONFIG_TLS_VARIANT_2
/** Allocate TLS variant II data structures.
*
* @param status Exit status. Currently not used.
* @param data Pointer to pointer to thread local data. This is
* actually an output argument.
* @param size Size of thread local data.
* @return Pointer to TCB structure.
*/
void thread_exit(int status)
tcb_t * tls_alloc_variant_2(void **data, size_t size)
{
__SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
}
tcb_t *tcb;
size = ALIGN_UP(size, &_tls_alignment);
*data = memalign(&_tls_alignment, sizeof(tcb_t) + size);
 
/** Detach thread.
*
* Currently not implemented.
*
* @param thread TID.
*/
void thread_detach(thread_id_t thread)
{
}
tcb = (tcb_t *) (*data + size);
tcb->self = tcb;
 
/** Join thread.
*
* Currently not implemented.
*
* @param thread TID.
*
* @return Thread exit status.
*/
int thread_join(thread_id_t thread)
{
return tcb;
}
 
/** Get current thread ID.
/** Free TLS variant II data structures.
*
* @return Current thread ID.
* @param tcb Pointer to TCB structure.
* @param size Size of thread local data.
*/
thread_id_t thread_get_id(void)
void tls_free_variant_2(tcb_t *tcb, size_t size)
{
thread_id_t thread_id;
 
(void) __SYSCALL1(SYS_THREAD_GET_ID, (sysarg_t) &thread_id);
 
return thread_id;
size = ALIGN_UP(size, &_tls_alignment);
void *start = ((void *) tcb) - size;
free(start);
}
#endif
 
/** @}
*/