Thread

Encapsulates os specific threading model.

Includes

If you call lockflag_thread or unlockflag_thread you need to include AtomicOps first.

Summary
ThreadEncapsulates os specific threading model.
CopyrightThis program is free software.
Files
C-kern/api/platform/task/thread.hHeader file of Thread.
C-kern/platform/Linux/task/thread.cLinux specific implementation Thread Linux.
Types
struct thread_tExport thread_t.
thread_fDefines function type executed by thread_t.
Functions
test
unittest_platform_task_threadTests thread_t interface.
thread_tDescribes a system thread.
nextwaitPoints to next thread which waits on the same thrmutex_t or waitlist_t.
lockflag ;Lock flag used to protect access to data members.
main_taskFunction executed after thread has been created.
main_argParameter of executed main_task function.
returncodeContains the return value of main_task.
sys_threadContains system specific ID of thread.
tls_addrContains start address of thread local storage.
continuecontextContains thread machine context before main_task is called.
lifetime
thread_FREEStatic initializer.
initmain_threadInitializes main thread.
new_threadCreates and starts a new system thread.
newgeneric_threadSame as new_thread except that it accepts functions with generic argument type.
delete_threadCalls join_thread (if not already called) and deletes resources.
query
self_threadReturns a pointer to own thread_t.
returncode_threadReturns the returncode of the joined thread.
maintask_threadReturns thread_t.main_task.
mainarg_threadReads thread_t.main_arg field of thread_t object.
ismain_threadReturns true if the calling thread is the main thread.
update
lockflag_threadWait until thread->lockflag (<lockflag>) is cleared and set it atomically.
unlockflag_threadClear thread->lockflag (<lockflag>).
settask_threadChanges values returned by maintask_thread and mainarg_thread.
setreturncode_threadChanges value returned by returncode_thread.
synchronize
join_threadThe function suspends execution of the caller until threadobj terminates.
change-run-state
suspend_threadThe calling thread will sleep until resume_thread is called.
trysuspend_threadThe function returns 0 if the calling thread has been resumed.
resume_threadThe thread which is refered by threadobj is woken up.
sleepms_threadMakes calling thread to sleep msec milli-seconds.
yield_threadSchedules another thread on this Processor.
exit_threadEnds the calling thread and sets retcode as its return code.
abort
abort_threadAborts the calling thread.
setcontinue_threadStores the current execution context and returns 0 on success.
inline implementation
Macros
ismain_threadImplements thread_t.ismain_thread.
lockflag_threadImplements thread_t.lockflag_thread.
newgeneric_threadImplements thread_t.newgeneric_thread.
maintask_threadImplements thread_t.maintask_thread.
mainarg_threadImplements thread_t.mainarg_thread.
returncode_threadImplements thread_t.returncode_thread.
self_threadImplements thread_t.self_thread.
setcontinue_threadImplements thread_t.setcontinue_thread.
settask_threadImplements thread_t.settask_thread.
setreturncode_threadImplements thread_t.setreturncode_thread.
unlockflag_threadImplements thread_t.unlockflag_thread.
yield_threadImplements thread_t.yield_thread.

Copyright

This program is free software.  You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

Author

© 2011 Jörg Seebohn

Files

C-kern/api/platform/task/thread.h

Header file of Thread.

C-kern/platform/Linux/task/thread.c

Linux specific implementation Thread Linux.

Types

struct thread_t

typedef struct thread_t thread_t

Export thread_t.

thread_f

typedef int (*thread_f) (void * main_arg)

Defines function type executed by thread_t.

Functions

test

unittest_platform_task_thread

int unittest_platform_task_thread(void)

Tests thread_t interface.

thread_t

struct thread_t

Describes a system thread.

Attention

Never forget to lock / unlock a thread object before you access the fields which can be changed by other threads.  This ensures that you read a consistent state and that on some architectures proper read and write barriers are executed.

Use <lock_thread> and <unlock_thread> for that matter.

Summary
nextwaitPoints to next thread which waits on the same thrmutex_t or waitlist_t.
lockflag ;Lock flag used to protect access to data members.
main_taskFunction executed after thread has been created.
main_argParameter of executed main_task function.
returncodeContains the return value of main_task.
sys_threadContains system specific ID of thread.
tls_addrContains start address of thread local storage.
continuecontextContains thread machine context before main_task is called.
lifetime
thread_FREEStatic initializer.
initmain_threadInitializes main thread.
new_threadCreates and starts a new system thread.
newgeneric_threadSame as new_thread except that it accepts functions with generic argument type.
delete_threadCalls join_thread (if not already called) and deletes resources.
query
self_threadReturns a pointer to own thread_t.
returncode_threadReturns the returncode of the joined thread.
maintask_threadReturns thread_t.main_task.
mainarg_threadReads thread_t.main_arg field of thread_t object.
ismain_threadReturns true if the calling thread is the main thread.
update
lockflag_threadWait until thread->lockflag (<lockflag>) is cleared and set it atomically.
unlockflag_threadClear thread->lockflag (<lockflag>).
settask_threadChanges values returned by maintask_thread and mainarg_thread.
setreturncode_threadChanges value returned by returncode_thread.
synchronize
join_threadThe function suspends execution of the caller until threadobj terminates.
change-run-state
suspend_threadThe calling thread will sleep until resume_thread is called.
trysuspend_threadThe function returns 0 if the calling thread has been resumed.
resume_threadThe thread which is refered by threadobj is woken up.
sleepms_threadMakes calling thread to sleep msec milli-seconds.
yield_threadSchedules another thread on this Processor.
exit_threadEnds the calling thread and sets retcode as its return code.
abort
abort_threadAborts the calling thread.
setcontinue_threadStores the current execution context and returns 0 on success.

nextwait

struct slist_node_t * nextwait

Points to next thread which waits on the same thrmutex_t or waitlist_t.  This ensures that waiting does not need to allocate list nodes and therefore never generate error ENOMEM.

lockflag ;

Lock flag used to protect access to data members.  Set and cleared with atomic operations.

main_task

thread_f main_task

Function executed after thread has been created.

main_arg

void * main_arg

Parameter of executed main_task function.

returncode

int returncode

Contains the return value of main_task.  This value is only valid after main_task has returned.

sys_thread

sys_thread_t sys_thread

Contains system specific ID of thread.

tls_addr

uint8_t * tls_addr

Contains start address of thread local storage.  See <thread_tls>.

continuecontext

ucontext_t continuecontext

Contains thread machine context before main_task is called.  This context could be used in any aborthandler.  The aborthandler should call abort_thread which sets returncode to value ENOTRECOVERABLE and calls setcontext (see: man 2 setcontext) with continuecontext as argument.

lifetime

thread_FREE

#define thread_FREE { 0, 0, 0, 0, 0, sys_thread_FREE, 0, { .uc_link = 0 } }

Static initializer.  Used to initialize thread in thread_tls_t.

initmain_thread

int initmain_thread(/*out*/thread_t *thread)

Initializes main thread.  Called from platform_t.init_platform.  Returns EINVAL if thread is not the main thread.

new_thread

int new_thread(/*out*/thread_t **threadobj,
thread_f thread_main,
void *main_arg)

Creates and starts a new system thread.  On success the parameter threadobj points to the new thread object.  The thread has to do some internal initialization after running the first time and before thread_main is called.  If the internal preparation goes wrong maincontext_t.abort_maincontext is called.  It is unspecified if thread_main is called before new_thread returns.  On Linux new_thread returns before the newly created thread is scheduled.

newgeneric_thread

int newgeneric_thread(/*out*/thread_t **threadobj,
thread_f thread_main,
void *main_arg) ;

Same as new_thread except that it accepts functions with generic argument type.  The function argument must be of size sizeof(void*).

delete_thread

int delete_thread(thread_t **threadobj)

Calls join_thread (if not already called) and deletes resources.  This function waits until the thread has terminated.  So be careful !

query

self_thread

thread_t * self_thread(void)

Returns a pointer to own thread_t.

returncode_thread

int returncode_thread(const thread_t *threadobj)

Returns the returncode of the joined thread.  The returncode is only valid if join_thread was called before.  0 is returned in case the thread has not already been joined.

maintask_thread

thread_f maintask_thread(const thread_t *threadobj)

Returns thread_t.main_task.  This value is set to thread_main given as parameter in new_thread.

mainarg_thread

void * mainarg_thread(const thread_t *threadobj)

Reads thread_t.main_arg field of thread_t object.  This value is set to main_arg given as parameter in new_thread.

ismain_thread

bool ismain_thread(const thread_t *thread)

Returns true if the calling thread is the main thread.

update

lockflag_thread

void lockflag_thread(thread_t *thread)

Wait until thread->lockflag (<lockflag>) is cleared and set it atomically.  Includes an acuire memory barrier (see AtomicOps).

unlockflag_thread

void unlockflag_thread(thread_t *thread)

Clear thread->lockflag (<lockflag>).  The function assumes that the flag was previously set by a call to lockflag_thread.  Include a release memory barrier (see AtomicOps).

settask_thread

void settask_thread(thread_t *thread,
thread_f main,
void *main_arg)

Changes values returned by maintask_thread and mainarg_thread.

setreturncode_thread

void setreturncode_thread(thread_t *thread,
int retcode)

Changes value returned by returncode_thread.

synchronize

join_thread

int join_thread(thread_t *threadobj)

The function suspends execution of the caller until threadobj terminates.  If the thread has already been joined this function returns immediately.  The error EDEADLK is returned if you want to join self_thread.  The error ESRCH is returned if the thread has exited already (if threadobj is not updated properly).

change-run-state

suspend_thread

void suspend_thread(void)

The calling thread will sleep until resume_thread is called.  resume_thread must be called from another thread.

Linux specific

Internally sigwaitinfo wirh signal SIGINT is used to sleep.

Attention !

It is possible that signals are received which are generated from outside this process therefore make sure with some other mechanism that returning from suspend_thread emanates from a corresponding call to resume_thread.

trysuspend_thread

int trysuspend_thread(void)

The function returns 0 if the calling thread has been resumed.  IF the functions returns 0 this is the same as calling suspend_thread and returning immediately.  The resume event is consumed.  It returns EAGAIN if no there is no pending resume.  Nothing is done in this case.  Use this function to poll for any pending resume_thread without sleeping.

resume_thread

void resume_thread(thread_t *threadobj)

The thread which is refered by threadobj is woken up.  The status of resume is conserved if the other thread is currently not sleeping.  So the next call to suspend will return immediately.  This behaviour is needed cause a thread calling suspend could be preempted before it really enters a sleep state.

Linux specific

Internally pthread_kill with signal SIGINT is used to wake up a another thread from sleeping.

sleepms_thread

void sleepms_thread(uint32_t msec)

Makes calling thread to sleep msec milli-seconds.

yield_thread

void yield_thread(void)

Schedules another thread on this Processor.

exit_thread

int exit_thread(int retcode)

Ends the calling thread and sets retcode as its return code.  If the caller is the main thread the value EPROTO is returned and nothing is done.  The main thread must calle maincontext_t.free_maincontext and exit(retcode).  No cleanup handlers are executed.

abort

abort_thread

void abort_thread(void)

Aborts the calling thread.  This functions sets returncode (see returncode_thread) to value ENOTRECOVERABLE and continues execution at the place which was marked with setcontinue_thread previously.  No cleanup handlers are executed.

setcontinue_thread

int setcontinue_thread(bool *is_abort)

Stores the current execution context and returns 0 on success.  Parameter is_abort is set to false if setcontinue_thread stored the execution context where execution should continue if abort_thread will be called.  Parameter is_abort is set to true if setcontinue_thread returns as a reaction to a call to abort_thread.  For any started thread setcontinue_thread is called before thread_main (parameter in new_thread) will be called.  The main thread which calls maincontext_t.init_maincontext must call setcontinue_thread explicitly.

Macros

ismain_thread

#define ismain_thread(
   thread
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (thread) ; (0 == _thr->tls_addr) ; }))

Implements thread_t.ismain_thread.

lockflag_thread

#define lockflag_thread(
   thread
) do { thread_t * const _thread = (thread) ; while (0 != atomicset_int(&_thread->lockflag)) { yield_thread() ; } } while (0)

Implements thread_t.lockflag_thread.

newgeneric_thread

#define newgeneric_thread(
   threadobj,
   thread_main,
   main_arg
) ( __extension__ ({ int (*_thread_main) (typeof(main_arg)) ; _thread_main = (thread_main) ; static_assert( sizeof(main_arg) == sizeof(void*), "same as void*") ; new_thread( threadobj, (thread_f)_thread_main, (void*)main_arg) ; }))

Implements thread_t.newgeneric_thread.

maintask_thread

#define maintask_thread(
   threadobj
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->main_task ; }))

Implements thread_t.maintask_thread.

mainarg_thread

#define mainarg_thread(
   threadobj
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->main_arg ; }))

Implements thread_t.mainarg_thread.

returncode_thread

#define returncode_thread(
   threadobj
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->returncode ; }))

Implements thread_t.returncode_thread.

(threadobj)->returncode

self_thread

#define self_thread() (sys_thread_threadtls())

Implements thread_t.self_thread.

setcontinue_thread

#define setcontinue_thread(
   is_abort
) ( __extension__ ({ thread_t * _self ; _self = self_thread() ; setreturncode_thread( _self, 0) ; int _err = getcontext( &_self->continuecontext) ; if (_err) { _err = errno ; TRACESYSCALL_ERRLOG( "getcontext", _err) ; } if (returncode_thread( _self)) { *(is_abort) = true ; } else { *(is_abort) = false ; } _err ; }))

Implements thread_t.setcontinue_thread.

settask_thread

#define settask_thread(
   thread,
   _main,
   _main_arg
) do { volatile typeof(*(thread)) * _thr ; _thr = (thread) ; _thr->main_task = (_main) ; _thr->main_arg = (_main_arg) ; } while(0)

Implements thread_t.settask_thread.

setreturncode_thread

#define setreturncode_thread(
   thread,
   retcode
) do { volatile typeof(*(thread)) * _thr ; _thr = (thread) ; _thr->returncode = (retcode) ; } while(0)

Implements thread_t.setreturncode_thread.

unlockflag_thread

#define unlockflag_thread(thread) (atomicclear_int(&(thread)->lockflag))

Implements thread_t.unlockflag_thread.

yield_thread

#define yield_thread() (pthread_yield())

Implements thread_t.yield_thread.

Encapsulates os specific threading model.
Implements Thread.
typedef struct thread_t thread_t
Export thread_t.
struct thread_t
Describes a system thread.
typedef int (*thread_f) (void * main_arg)
Defines function type executed by thread_t.
int unittest_platform_task_thread(void)
Tests thread_t interface.
struct slist_node_t * nextwait
Points to next thread which waits on the same thrmutex_t or waitlist_t.
thread_f main_task
Function executed after thread has been created.
void * main_arg
Parameter of executed main_task function.
int returncode
Contains the return value of main_task.
sys_thread_t sys_thread
Contains system specific ID of thread.
uint8_t * tls_addr
Contains start address of thread local storage.
ucontext_t continuecontext
Contains thread machine context before main_task is called.
#define thread_FREE { 0, 0, 0, 0, 0, sys_thread_FREE, 0, { .uc_link = 0 } }
Static initializer.
int initmain_thread(/*out*/thread_t *thread)
Initializes main thread.
int new_thread(/*out*/thread_t **threadobj,
thread_f thread_main,
void *main_arg)
Creates and starts a new system thread.
int newgeneric_thread(/*out*/thread_t **threadobj,
thread_f thread_main,
void *main_arg) ;
Same as new_thread except that it accepts functions with generic argument type.
int delete_thread(thread_t **threadobj)
Calls join_thread (if not already called) and deletes resources.
int join_thread(thread_t *threadobj)
The function suspends execution of the caller until threadobj terminates.
thread_t * self_thread(void)
Returns a pointer to own thread_t.
int returncode_thread(const thread_t *threadobj)
Returns the returncode of the joined thread.
thread_f maintask_thread(const thread_t *threadobj)
Returns thread_t.main_task.
void * mainarg_thread(const thread_t *threadobj)
Reads thread_t.main_arg field of thread_t object.
bool ismain_thread(const thread_t *thread)
Returns true if the calling thread is the main thread.
void lockflag_thread(thread_t *thread)
Wait until thread->lockflag (lockflag) is cleared and set it atomically.
void unlockflag_thread(thread_t *thread)
Clear thread->lockflag (lockflag).
void settask_thread(thread_t *thread,
thread_f main,
void *main_arg)
Changes values returned by maintask_thread and mainarg_thread.
void setreturncode_thread(thread_t *thread,
int retcode)
Changes value returned by returncode_thread.
void suspend_thread(void)
The calling thread will sleep until resume_thread is called.
void resume_thread(thread_t *threadobj)
The thread which is refered by threadobj is woken up.
int trysuspend_thread(void)
The function returns 0 if the calling thread has been resumed.
void sleepms_thread(uint32_t msec)
Makes calling thread to sleep msec milli-seconds.
void yield_thread(void)
Schedules another thread on this Processor.
int exit_thread(int retcode)
Ends the calling thread and sets retcode as its return code.
void abort_thread(void)
Aborts the calling thread.
int setcontinue_thread(bool *is_abort)
Stores the current execution context and returns 0 on success.
#define ismain_thread(
   thread
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (thread) ; (0 == _thr->tls_addr) ; }))
Implements thread_t.ismain_thread.
#define lockflag_thread(
   thread
) do { thread_t * const _thread = (thread) ; while (0 != atomicset_int(&_thread->lockflag)) { yield_thread() ; } } while (0)
Implements thread_t.lockflag_thread.
#define newgeneric_thread(
   threadobj,
   thread_main,
   main_arg
) ( __extension__ ({ int (*_thread_main) (typeof(main_arg)) ; _thread_main = (thread_main) ; static_assert( sizeof(main_arg) == sizeof(void*), "same as void*") ; new_thread( threadobj, (thread_f)_thread_main, (void*)main_arg) ; }))
Implements thread_t.newgeneric_thread.
#define maintask_thread(
   threadobj
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->main_task ; }))
Implements thread_t.maintask_thread.
#define mainarg_thread(
   threadobj
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->main_arg ; }))
Implements thread_t.mainarg_thread.
#define returncode_thread(
   threadobj
) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->returncode ; }))
Implements thread_t.returncode_thread.
#define self_thread() (sys_thread_threadtls())
Implements thread_t.self_thread.
#define setcontinue_thread(
   is_abort
) ( __extension__ ({ thread_t * _self ; _self = self_thread() ; setreturncode_thread( _self, 0) ; int _err = getcontext( &_self->continuecontext) ; if (_err) { _err = errno ; TRACESYSCALL_ERRLOG( "getcontext", _err) ; } if (returncode_thread( _self)) { *(is_abort) = true ; } else { *(is_abort) = false ; } _err ; }))
Implements thread_t.setcontinue_thread.
#define settask_thread(
   thread,
   _main,
   _main_arg
) do { volatile typeof(*(thread)) * _thr ; _thr = (thread) ; _thr->main_task = (_main) ; _thr->main_arg = (_main_arg) ; } while(0)
Implements thread_t.settask_thread.
#define setreturncode_thread(
   thread,
   retcode
) do { volatile typeof(*(thread)) * _thr ; _thr = (thread) ; _thr->returncode = (retcode) ; } while(0)
Implements thread_t.setreturncode_thread.
#define unlockflag_thread(thread) (atomicclear_int(&(thread)->lockflag))
Implements thread_t.unlockflag_thread.
#define yield_thread() (pthread_yield())
Implements thread_t.yield_thread.
Offers atomic operations for type integers.
int init_platform(mainthread_f main_thread,
void *user)
Initialize system context and calls main_thread.
void abort_maincontext(int err)
Exits the whole process in a controlled manner.
int free_maincontext(void)
Frees global context.
int init_maincontext(const maincontext_e context_type,
int argc,
const char **argv)
Initializes global program context.
Close