forked from Qortal/Brooklyn
230 lines
7.6 KiB
C
230 lines
7.6 KiB
C
/*
|
|
Copyright (c) 2012, Broadcom Europe Ltd
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* Neither the name of the copyright holder nor the
|
|
names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*=============================================================================
|
|
VideoCore OS Abstraction Layer - implementation: joinable thread from plain
|
|
=============================================================================*/
|
|
|
|
/** \file
|
|
*
|
|
* Header file for platforms creating the joinable thread from a lowlevel
|
|
* thread.
|
|
*
|
|
* In addition to the actual thread, the following are also created:
|
|
*
|
|
* - a semaphore to wait on when joining the thread
|
|
* - a semaphore to support counted suspend/resume (used by event group)
|
|
* - a per-thread timer (used by event group, but could be removed)
|
|
*/
|
|
|
|
#ifndef VCOS_JOINABLE_THREAD_FROM_PLAIN_H
|
|
#define VCOS_JOINABLE_THREAD_FROM_PLAIN_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef VCOS_SEMAPHORE_H
|
|
#include "interface/vcos/vcos_semaphore.h"
|
|
#endif
|
|
#ifndef VCOS_LOWLEVEL_THREAD_H
|
|
#include "interface/vcos/vcos_lowlevel_thread.h"
|
|
#endif
|
|
#ifndef VCOS_TIMER_H
|
|
#include "interface/vcos/vcos_timer.h"
|
|
#endif
|
|
|
|
#ifdef VCOS_WANT_TLS_EMULATION
|
|
#include "interface/vcos/generic/vcos_generic_tls.h"
|
|
#endif
|
|
|
|
#define VCOS_THREAD_MAGIC 0x56436a74
|
|
|
|
#define VCOS_THREAD_VALID(t) (t->magic == VCOS_THREAD_MAGIC)
|
|
#define VCOS_HAVE_THREAD_AT_EXIT 1
|
|
|
|
/** Thread attribute structure. Clients should not manipulate this directly, but
|
|
* should instead use the provided functions.
|
|
*/
|
|
typedef struct VCOS_THREAD_ATTR_T
|
|
{
|
|
void *ta_stackaddr;
|
|
VCOS_UNSIGNED ta_stacksz;
|
|
VCOS_UNSIGNED ta_priority;
|
|
VCOS_UNSIGNED ta_affinity;
|
|
VCOS_UNSIGNED ta_timeslice;
|
|
VCOS_UNSIGNED legacy;
|
|
VCOS_UNSIGNED ta_autostart;
|
|
} VCOS_THREAD_ATTR_T;
|
|
|
|
/** Each thread gets a timer, which is for internal VCOS use.
|
|
*/
|
|
typedef struct _VCOS_THREAD_TIMER_T
|
|
{
|
|
VCOS_TIMER_T timer;
|
|
void (*pfn)(void *);
|
|
void *cxt;
|
|
} _VCOS_THREAD_TIMER_T;
|
|
|
|
typedef void (*VCOS_THREAD_EXIT_HANDLER_T)(void *);
|
|
/** Called at thread exit.
|
|
*/
|
|
typedef struct VCOS_THREAD_EXIT_T
|
|
{
|
|
VCOS_THREAD_EXIT_HANDLER_T pfn;
|
|
void *cxt;
|
|
} VCOS_THREAD_EXIT_T;
|
|
#define VCOS_MAX_EXIT_HANDLERS 8
|
|
|
|
/* The name field isn't used for anything, so we can just copy the
|
|
* the pointer. Nucleus makes its own copy.
|
|
*/
|
|
typedef const char * VCOS_LLTHREAD_T_NAME;
|
|
#define _VCOS_LLTHREAD_NAME(dst,src) (dst)=(src)
|
|
|
|
/*
|
|
* Simulated TLS support
|
|
*/
|
|
|
|
|
|
/** Thread structure.
|
|
*
|
|
* \warning Do not access the members of this structure directly!
|
|
*/
|
|
typedef struct VCOS_THREAD_T
|
|
{
|
|
VCOS_LLTHREAD_T thread; /**< The underlying thread */
|
|
char name[16]; /**< The name */
|
|
unsigned int magic; /**< For debug */
|
|
void *exit_data; /**< Exit data passed out in vcos_joinable_thread_exit() */
|
|
void *stack; /**< Stack, if not supplied by caller */
|
|
VCOS_SEMAPHORE_T wait; /**< Semaphore to wait on at join */
|
|
VCOS_SEMAPHORE_T suspend; /**< Semaphore to wait on for counted suspend */
|
|
int16_t joined; /**< Joined yet? For debug. */
|
|
VCOS_UNSIGNED legacy; /**< Use (argc,argv) for entry point arguments */
|
|
void *(*entry)(void*); /**< Entry point */
|
|
void *arg; /**< Argument passed to entry point */
|
|
void *(*term)(void*); /**< Termination function, used by reaper */
|
|
void *term_arg; /**< Argument passed to termination function */
|
|
_VCOS_THREAD_TIMER_T _timer; /**< Internal timer, mainly for event groups */
|
|
#ifdef VCOS_WANT_TLS_EMULATION
|
|
VCOS_TLS_THREAD_T _tls; /**< TLS data when native TLS not available, or NULL */
|
|
#endif
|
|
/** Array of functions to call at thread exit */
|
|
VCOS_THREAD_EXIT_T at_exit[VCOS_MAX_EXIT_HANDLERS];
|
|
|
|
struct VCOS_THREAD_T *next; /**< For linked lists of threads */
|
|
} VCOS_THREAD_T;
|
|
|
|
#if defined(VCOS_INLINE_BODIES)
|
|
|
|
VCOS_INLINE_IMPL
|
|
void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED stacksz) {
|
|
attrs->ta_stackaddr = addr;
|
|
attrs->ta_stacksz = stacksz;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED stacksz) {
|
|
attrs->ta_stacksz = stacksz;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri) {
|
|
attrs->ta_priority = pri;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED affinity) {
|
|
attrs->ta_affinity = affinity;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts) {
|
|
attrs->ta_timeslice = ts;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy) {
|
|
attrs->legacy = legacy;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart) {
|
|
attrs->ta_autostart = autostart;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
VCOS_THREAD_T *vcos_thread_current(void) {
|
|
VCOS_THREAD_T *ret = (VCOS_THREAD_T*)vcos_llthread_current();
|
|
/*If we're called from a non-vcos thread, this assert will fail.
|
|
*XXX FIXME why is this commented out?
|
|
*vcos_assert(ret->magic == VCOS_THREAD_MAGIC);
|
|
*/
|
|
return ret;
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
int vcos_thread_running(VCOS_THREAD_T *thread) {
|
|
return vcos_llthread_running(&thread->thread);
|
|
}
|
|
|
|
VCOS_INLINE_IMPL
|
|
void vcos_thread_resume(VCOS_THREAD_T *thread) {
|
|
vcos_llthread_resume(&thread->thread);
|
|
}
|
|
|
|
#endif /* VCOS_INLINE_BODIES */
|
|
|
|
/**
|
|
* \brief Create a VCOS_THREAD_T for the current thread. This is so we can have
|
|
* VCOS_THREAD_Ts even for threads not originally created by VCOS (eg the
|
|
* thread that calls vcos_init)
|
|
*/
|
|
extern VCOS_STATUS_T _vcos_thread_create_attach(VCOS_THREAD_T *thread,
|
|
const char *name);
|
|
|
|
/**
|
|
* \brief Deletes the VCOS_THREAD_T, but does not wait for the underlying
|
|
* thread to exit. This will cleanup everything created by
|
|
* _vcos_thread_create_attach
|
|
*/
|
|
extern void _vcos_thread_delete(VCOS_THREAD_T *thread);
|
|
|
|
/** Register a function to be called when the current thread exits.
|
|
*/
|
|
extern VCOS_STATUS_T vcos_thread_at_exit(void (*pfn)(void*), void *cxt);
|
|
|
|
/** Deregister a previously registered at-exit function.
|
|
*/
|
|
extern void vcos_thread_deregister_at_exit(void (*pfn)(void*), void *cxt);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* VCOS_JOINABLE_THREAD_FROM_PLAIN_H */
|