Encapsulates os specific threading model.
If you call lockflag_thread or unlockflag_thread you need to include AtomicOps first.
Thread | Encapsulates os specific threading model. |
Copyright | This program is free software. |
Files | |
C-kern/ | Header file of Thread. |
C-kern/ | Linux specific implementation Thread Linux. |
Types | |
struct thread_t | Export thread_t. |
thread_f | Defines function type executed by thread_t. |
Functions | |
test | |
unittest_platform_task_thread | Tests thread_t interface. |
thread_t | Describes a system thread. |
nextwait | Points to next thread which waits on the same thrmutex_t or waitlist_t. |
lockflag ; | Lock flag used to protect access to data members. |
main_task | Function executed after thread has been created. |
main_arg | Parameter of executed main_task function. |
returncode | Contains the return value of main_task. |
sys_thread | Contains system specific ID of thread. |
tls_addr | Contains start address of thread local storage. |
continuecontext | Contains thread machine context before main_task is called. |
lifetime | |
thread_FREE | Static initializer. |
initmain_thread | Initializes main thread. |
new_thread | Creates and starts a new system thread. |
newgeneric_thread | Same as new_thread except that it accepts functions with generic argument type. |
delete_thread | Calls join_thread (if not already called) and deletes resources. |
query | |
self_thread | Returns a pointer to own thread_t. |
returncode_thread | Returns the returncode of the joined thread. |
maintask_thread | Returns thread_t.main_task. |
mainarg_thread | Reads thread_t.main_arg field of thread_t object. |
ismain_thread | Returns true if the calling thread is the main thread. |
update | |
lockflag_thread | Wait until thread->lockflag (<lockflag>) is cleared and set it atomically. |
unlockflag_thread | Clear thread->lockflag (<lockflag>). |
settask_thread | Changes values returned by maintask_thread and mainarg_thread. |
setreturncode_thread | Changes value returned by returncode_thread. |
synchronize | |
join_thread | The function suspends execution of the caller until threadobj terminates. |
change-run-state | |
suspend_thread | The calling thread will sleep until resume_thread is called. |
trysuspend_thread | The function returns 0 if the calling thread has been resumed. |
resume_thread | The thread which is refered by threadobj is woken up. |
sleepms_thread | Makes calling thread to sleep msec milli-seconds. |
yield_thread | Schedules another thread on this Processor. |
exit_thread | Ends the calling thread and sets retcode as its return code. |
abort | |
abort_thread | Aborts the calling thread. |
setcontinue_thread | Stores the current execution context and returns 0 on success. |
inline implementation | |
Macros | |
ismain_thread | Implements thread_t.ismain_thread. |
lockflag_thread | Implements thread_t.lockflag_thread. |
newgeneric_thread | Implements thread_t.newgeneric_thread. |
maintask_thread | Implements thread_t.maintask_thread. |
mainarg_thread | Implements thread_t.mainarg_thread. |
returncode_thread | Implements thread_t.returncode_thread. |
self_thread | Implements thread_t.self_thread. |
setcontinue_thread | Implements thread_t.setcontinue_thread. |
settask_thread | Implements thread_t.settask_thread. |
setreturncode_thread | Implements thread_t.setreturncode_thread. |
unlockflag_thread | Implements thread_t.unlockflag_thread. |
yield_thread | Implements thread_t.yield_thread. |
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.
© 2011 Jörg Seebohn
Header file of Thread.
Linux specific implementation Thread Linux.
typedef struct thread_t thread_t
Export thread_t.
typedef int ( * thread_f ) (void * main_arg)
Defines function type executed by thread_t.
test | |
unittest_platform_task_thread | Tests thread_t interface. |
int unittest_platform_task_thread( void )
Tests thread_t interface.
struct thread_t
Describes a system thread.
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.
nextwait | Points to next thread which waits on the same thrmutex_t or waitlist_t. |
lockflag ; | Lock flag used to protect access to data members. |
main_task | Function executed after thread has been created. |
main_arg | Parameter of executed main_task function. |
returncode | Contains the return value of main_task. |
sys_thread | Contains system specific ID of thread. |
tls_addr | Contains start address of thread local storage. |
continuecontext | Contains thread machine context before main_task is called. |
lifetime | |
thread_FREE | Static initializer. |
initmain_thread | Initializes main thread. |
new_thread | Creates and starts a new system thread. |
newgeneric_thread | Same as new_thread except that it accepts functions with generic argument type. |
delete_thread | Calls join_thread (if not already called) and deletes resources. |
query | |
self_thread | Returns a pointer to own thread_t. |
returncode_thread | Returns the returncode of the joined thread. |
maintask_thread | Returns thread_t.main_task. |
mainarg_thread | Reads thread_t.main_arg field of thread_t object. |
ismain_thread | Returns true if the calling thread is the main thread. |
update | |
lockflag_thread | Wait until thread->lockflag (<lockflag>) is cleared and set it atomically. |
unlockflag_thread | Clear thread->lockflag (<lockflag>). |
settask_thread | Changes values returned by maintask_thread and mainarg_thread. |
setreturncode_thread | Changes value returned by returncode_thread. |
synchronize | |
join_thread | The function suspends execution of the caller until threadobj terminates. |
change-run-state | |
suspend_thread | The calling thread will sleep until resume_thread is called. |
trysuspend_thread | The function returns 0 if the calling thread has been resumed. |
resume_thread | The thread which is refered by threadobj is woken up. |
sleepms_thread | Makes calling thread to sleep msec milli-seconds. |
yield_thread | Schedules another thread on this Processor. |
exit_thread | Ends the calling thread and sets retcode as its return code. |
abort | |
abort_thread | Aborts the calling thread. |
setcontinue_thread | Stores the current execution context and returns 0 on success. |
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.
void * main_arg
Parameter of executed main_task function.
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.
#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.
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.
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.
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*).
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 !
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. The returncode is only valid if join_thread was called before. 0 is returned in case the thread has not already been joined.
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.
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.
void lockflag_thread( thread_t * thread )
Wait until thread->lockflag (<lockflag>) is cleared and set it atomically. Includes an acuire memory barrier (see AtomicOps).
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).
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.
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).
void suspend_thread( void )
The calling thread will sleep until resume_thread is called. resume_thread must be called from another thread.
Internally sigwaitinfo wirh signal SIGINT is used to sleep.
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.
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.
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.
Internally pthread_kill with signal SIGINT is used to wake up a another thread from sleeping.
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.
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.
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 | Implements thread_t.ismain_thread. |
lockflag_thread | Implements thread_t.lockflag_thread. |
newgeneric_thread | Implements thread_t.newgeneric_thread. |
maintask_thread | Implements thread_t.maintask_thread. |
mainarg_thread | Implements thread_t.mainarg_thread. |
returncode_thread | Implements thread_t.returncode_thread. |
self_thread | Implements thread_t.self_thread. |
setcontinue_thread | Implements thread_t.setcontinue_thread. |
settask_thread | Implements thread_t.settask_thread. |
setreturncode_thread | Implements thread_t.setreturncode_thread. |
unlockflag_thread | Implements thread_t.unlockflag_thread. |
yield_thread | Implements thread_t.yield_thread. |
#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.
(threadobj)->returncode
#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.
Export thread_t.
typedef struct thread_t thread_t
Describes a system thread.
struct thread_t
Defines function type executed by thread_t.
typedef int ( * thread_f ) (void * main_arg)
Tests thread_t interface.
int unittest_platform_task_thread( void )
Points to next thread which waits on the same thrmutex_t or waitlist_t.
struct slist_node_t * nextwait
Function executed after thread has been created.
thread_f main_task
Parameter of executed main_task function.
void * main_arg
Contains the return value of main_task.
int returncode
Contains system specific ID of thread.
sys_thread_t sys_thread
Contains start address of thread local storage.
uint8_t * tls_addr
Contains thread machine context before main_task is called.
ucontext_t continuecontext
Static initializer.
#define thread_FREE { 0, 0, 0, 0, 0, sys_thread_FREE, 0, { .uc_link = 0 } }
Initializes main thread.
int initmain_thread( /*out*/thread_t * thread )
Creates and starts a new system thread.
int new_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 newgeneric_thread( /*out*/thread_t ** threadobj, thread_f thread_main, void * main_arg ) ;
Calls join_thread (if not already called) and deletes resources.
int delete_thread( thread_t ** threadobj )
The function suspends execution of the caller until threadobj terminates.
int join_thread( thread_t * threadobj )
Returns a pointer to own thread_t.
thread_t * self_thread( void )
Returns the returncode of the joined thread.
int returncode_thread( const thread_t * threadobj )
Returns thread_t.main_task.
thread_f maintask_thread( const thread_t * threadobj )
Reads thread_t.main_arg field of thread_t object.
void * mainarg_thread( const thread_t * threadobj )
Returns true if the calling thread is the main thread.
bool ismain_thread( const thread_t * thread )
Wait until thread->lockflag (lockflag) is cleared and set it atomically.
void lockflag_thread( thread_t * thread )
Clear thread->lockflag (lockflag).
void unlockflag_thread( thread_t * thread )
Changes values returned by maintask_thread and mainarg_thread.
void settask_thread( thread_t * thread, thread_f main, void * main_arg )
Changes value returned by returncode_thread.
void setreturncode_thread( thread_t * thread, int retcode )
The calling thread will sleep until resume_thread is called.
void suspend_thread( void )
The thread which is refered by threadobj is woken up.
void resume_thread( thread_t * threadobj )
The function returns 0 if the calling thread has been resumed.
int trysuspend_thread( void )
Makes calling thread to sleep msec milli-seconds.
void sleepms_thread( uint32_t msec )
Schedules another thread on this Processor.
void yield_thread( void )
Ends the calling thread and sets retcode as its return code.
int exit_thread( int retcode )
Aborts the calling thread.
void abort_thread( void )
Stores the current execution context and returns 0 on success.
int setcontinue_thread( bool * is_abort )
Implements thread_t.ismain_thread.
#define ismain_thread( thread ) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (thread) ; (0 == _thr->tls_addr) ; }))
Implements thread_t.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.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.maintask_thread.
#define maintask_thread( threadobj ) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->main_task ; }))
Implements thread_t.mainarg_thread.
#define mainarg_thread( threadobj ) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->main_arg ; }))
Implements thread_t.returncode_thread.
#define returncode_thread( threadobj ) ( __extension__ ({ volatile const thread_t * _thr ; _thr = (threadobj) ; _thr->returncode ; }))
Implements thread_t.self_thread.
#define self_thread( ) (sys_thread_threadtls())
Implements thread_t.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.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.setreturncode_thread.
#define setreturncode_thread( thread, retcode ) do { volatile typeof(*(thread)) * _thr ; _thr = (thread) ; _thr->returncode = (retcode) ; } while(0)
Implements thread_t.unlockflag_thread.
#define unlockflag_thread( thread ) (atomicclear_int(&(thread)->lockflag))
Implements thread_t.yield_thread.
#define yield_thread( ) (pthread_yield())
Initialize system context and calls main_thread.
int init_platform( mainthread_f main_thread, void * user )
Exits the whole process in a controlled manner.
void abort_maincontext( int err )
Frees global context.
int free_maincontext( void )
Initializes global program context.
int init_maincontext( const maincontext_e context_type, int argc, const char ** argv )