PebbleOS
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Enumerations | Functions
Threads

Thread creation, lifecycle and per-thread state. More...

Data Structures

struct  pbl_thread_attr
 Thread creation attributes. More...
 
struct  pbl_thread
 Thread object. More...
 

Macros

#define PBL_THREAD_NAME_LEN   16
 Size of a thread name, including the terminating NUL.
 
#define PBL_THREAD_MAX_MEM_REGIONS   4
 Number of MPU regions switched in with each thread.
 
#define PBL_THREAD_STACK_DEFINE(name, size)    static uint8_t name[size] PBL_ALIGNED(CONFIG_KERNEL_STACK_ALIGN)
 Define a thread stack with the alignment the MPU port needs for a guard region.
 

Typedefs

typedef void(* pbl_thread_entry_t) (void *arg)
 Thread entry function.
 

Enumerations

enum  pbl_thread_state {
  PBL_THREAD_READY , PBL_THREAD_RUNNING , PBL_THREAD_BLOCKED , PBL_THREAD_SUSPENDED ,
  PBL_THREAD_DEAD
}
 Thread state. More...
 

Functions

int pbl_thread_create (struct pbl_thread *t, const struct pbl_thread_attr *attr)
 Create and start a thread.
 
void pbl_thread_abort (struct pbl_thread *t)
 End a thread.
 
void pbl_thread_suspend (struct pbl_thread *t)
 Stop scheduling a thread until pbl_thread_resume().
 
void pbl_thread_resume (struct pbl_thread *t)
 Make a suspended thread runnable again.
 
void pbl_thread_yield (void)
 Let other ready threads of the same priority run.
 
void pbl_thread_sleep (pbl_timeout_t timeout)
 Block the calling thread for a while.
 
struct pbl_thread * pbl_thread_current (void)
 Get the calling thread.
 
struct pbl_thread * pbl_thread_idle (void)
 Get the kernel's idle thread.
 
void pbl_thread_prio_set (struct pbl_thread *t, pbl_prio_t prio)
 Change the base priority of a thread.
 
pbl_prio_t pbl_thread_prio_get (const struct pbl_thread *t)
 Get the base priority of a thread.
 
enum pbl_thread_state pbl_thread_state (const struct pbl_thread *t)
 Get the state of a thread.
 
static const char * pbl_thread_name (const struct pbl_thread *t)
 Get the name of a thread.
 
static uint32_t pbl_thread_id (const struct pbl_thread *t)
 Get the creation ID of a thread.
 
void pbl_thread_regions_set (struct pbl_thread *t, const MpuRegion *const *regions)
 Replace the MPU regions of a thread.
 
static void * pbl_thread_tls_get (const struct pbl_thread *t, unsigned int slot)
 Read a thread-local pointer slot.
 
static void pbl_thread_tls_set (struct pbl_thread *t, unsigned int slot, void *v)
 Write a thread-local pointer slot.
 
void pbl_thread_stack_overflow (struct pbl_thread *t, const char *name)
 Handle a thread that overran its stack.
 
bool pbl_kernel_privilege_raise_allowed (uint32_t caller_pc)
 Decide whether code may raise privilege through the kernel's supervisor call.
 
uint32_t * pbl_kernel_syscall_stack (uintptr_t *base_out)
 Provide a dedicated privileged stack for the current thread's syscalls.
 
void pbl_kernel_syscall_entered (uintptr_t orig_sp, uintptr_t *lr_slot)
 Notify the application that privilege is being raised for a syscall.
 

Detailed Description

Thread creation, lifecycle and per-thread state.

Threads are scheduled by fixed priority, highest first; threads of equal priority round-robin on every tick and on pbl_thread_yield(). The thread struct and its stack are owned by the caller and must outlive the thread. Returning from the entry function ends the thread, after which the struct may be reused for a new one.

PBL_THREAD_STACK_DEFINE(s_worker_stack, 1024);
static struct pbl_thread s_worker;
static void prv_worker(void *arg) {
for (;;) {
do_work(arg);
}
}
void worker_start(void) {
const struct pbl_thread_attr attr = {
.name = "Worker",
.entry = prv_worker,
.prio = 2,
.privileged = true,
.stack = s_worker_stack,
.stack_size = sizeof(s_worker_stack),
};
pbl_thread_create(&s_worker, &attr);
}
const char * name
Name, truncated to PBL_THREAD_NAME_LEN - 1 characters.
Definition thread.h:75
Thread creation attributes.
Definition thread.h:73
Thread object.
Definition thread.h:97
int pbl_thread_create(struct pbl_thread *t, const struct pbl_thread_attr *attr)
Create and start a thread.
void pbl_thread_sleep(pbl_timeout_t timeout)
Block the calling thread for a while.
#define PBL_THREAD_STACK_DEFINE(name, size)
Define a thread stack with the alignment the MPU port needs for a guard region.
Definition thread.h:124
#define PBL_MSEC(ms)
Timeout in milliseconds, rounded down to whole ticks.
Definition types.h:62

Data Structure Documentation

◆ pbl_thread_attr

struct pbl_thread_attr

Thread creation attributes.

Data Fields
void * arg Argument passed to entry.
pbl_thread_entry_t entry Entry function.
const char * name Name, truncated to PBL_THREAD_NAME_LEN - 1 characters.
pbl_prio_t prio Priority, PBL_PRIO_IDLE to PBL_PRIO_MAX.
bool privileged Run in privileged mode; unprivileged threads are confined by the MPU.
const MpuRegion * regions[PBL_THREAD_MAX_MEM_REGIONS] MPU regions switched in with the thread.

NULL entries are ignored.

void * stack Lowest address of the stack; the caller owns the memory.
size_t stack_size Stack size in bytes, at least 128.

◆ pbl_thread

struct pbl_thread

Thread object.

Caller-owned; set up by pbl_thread_create(). Read fields through the accessor functions.

Data Fields
struct pbl_thread_backend backend Backend state; first, the arch code relies on its offset.
uint32_t id Unique per creation, never 0.
char name[PBL_THREAD_NAME_LEN] NUL-terminated name.
pbl_prio_t prio Effective priority, including any boost inherited through a mutex.
bool privileged Runs in privileged mode.
void * stack Lowest address of the stack.
size_t stack_size Stack size in bytes.
void * tls[CONFIG_KERNEL_THREAD_TLS_SLOTS] Thread-local pointer slots, see pbl_thread_tls_get().

Macro Definition Documentation

◆ PBL_THREAD_MAX_MEM_REGIONS

#define PBL_THREAD_MAX_MEM_REGIONS   4

Number of MPU regions switched in with each thread.

◆ PBL_THREAD_NAME_LEN

#define PBL_THREAD_NAME_LEN   16

Size of a thread name, including the terminating NUL.

◆ PBL_THREAD_STACK_DEFINE

#define PBL_THREAD_STACK_DEFINE (   name,
  size 
)     static uint8_t name[size] PBL_ALIGNED(CONFIG_KERNEL_STACK_ALIGN)

Define a thread stack with the alignment the MPU port needs for a guard region.

Expands to a static array; CONFIG_KERNEL_STACK_ALIGN gives the alignment.

Parameters
nameName of the stack array.
sizeStack size in bytes.

Typedef Documentation

◆ pbl_thread_entry_t

typedef void(* pbl_thread_entry_t) (void *arg)

Thread entry function.

Parameters
argArgument given in pbl_thread_attr::arg.

Enumeration Type Documentation

◆ pbl_thread_state

Thread state.

Enumerator
PBL_THREAD_READY 

Runnable, waiting for the CPU.

PBL_THREAD_RUNNING 

Currently executing.

PBL_THREAD_BLOCKED 

Waiting on an object or sleeping.

PBL_THREAD_SUSPENDED 

Stopped by pbl_thread_suspend() until pbl_thread_resume().

PBL_THREAD_DEAD 

Ended or aborted; the struct may be reused.

Function Documentation

◆ pbl_kernel_privilege_raise_allowed()

bool pbl_kernel_privilege_raise_allowed ( uint32_t  caller_pc)

Decide whether code may raise privilege through the kernel's supervisor call.

Implemented by the application. Called from the SVC handler on every privilege-raise request.

Parameters
caller_pcAddress of the instruction after the SVC.
Returns
true to grant privileged mode to the caller.

◆ pbl_kernel_syscall_entered()

void pbl_kernel_syscall_entered ( uintptr_t  orig_sp,
uintptr_t *  lr_slot 
)

Notify the application that privilege is being raised for a syscall.

Implemented by the application. Called from the SVC handler just before the thread is made privileged.

Parameters
orig_spCaller's stack pointer before the SVC.
[in,out]lr_slotStacked return address of the syscall; may be rewritten to redirect the return, e.g. through code that drops privilege again.

◆ pbl_kernel_syscall_stack()

uint32_t * pbl_kernel_syscall_stack ( uintptr_t *  base_out)

Provide a dedicated privileged stack for the current thread's syscalls.

Implemented by the application; the kernel's weak default returns NULL. Called from the SVC handler once a privilege raise is allowed: the exception frame and the caller's stacked arguments are copied onto the returned stack, so the syscall body runs there.

Parameters
[out]base_outLowest address of the stack, used as the stack limit where supported.
Returns
Top of the stack, or NULL to run syscalls on the caller's stack.

◆ pbl_thread_abort()

void pbl_thread_abort ( struct pbl_thread *  t)

End a thread.

Mutexes it holds are not released.

Parameters
tThread to end, or NULL for the calling thread, in which case this does not return.

◆ pbl_thread_create()

int pbl_thread_create ( struct pbl_thread *  t,
const struct pbl_thread_attr *  attr 
)

Create and start a thread.

The stack is filled with a pattern for high-water tracking. The new thread runs as soon as it is the highest priority runnable thread, possibly before this call returns. Returning from the entry function ends the thread. Asserts if t still holds a live thread.

Parameters
[out]tThread object, caller-owned.
attrCreation attributes; only read during the call.
Returns
0.

◆ pbl_thread_current()

struct pbl_thread * pbl_thread_current ( void  )

Get the calling thread.

Callable from unprivileged code.

Returns
The running thread, or the interrupted thread when called from an ISR.

◆ pbl_thread_id()

static uint32_t pbl_thread_id ( const struct pbl_thread *  t)
inlinestatic

Get the creation ID of a thread.

Distinguishes successive threads created in the same struct.

Parameters
tThread.
Returns
ID, unique per creation and never 0.

References pbl_thread::id.

◆ pbl_thread_idle()

struct pbl_thread * pbl_thread_idle ( void  )

Get the kernel's idle thread.

Returns
The idle thread, which runs at PBL_PRIO_IDLE when nothing else is runnable.

◆ pbl_thread_name()

static const char * pbl_thread_name ( const struct pbl_thread *  t)
inlinestatic

Get the name of a thread.

Parameters
tThread.
Returns
NUL-terminated name, owned by t.

References pbl_thread::name.

◆ pbl_thread_prio_get()

pbl_prio_t pbl_thread_prio_get ( const struct pbl_thread *  t)

Get the base priority of a thread.

Parameters
tThread.
Returns
Priority set at creation or by pbl_thread_prio_set(), without inherited boosts.

◆ pbl_thread_prio_set()

void pbl_thread_prio_set ( struct pbl_thread *  t,
pbl_prio_t  prio 
)

Change the base priority of a thread.

A priority boost inherited through a mutex is kept until the mutex is released.

Parameters
tThread.
prioNew priority, at most PBL_PRIO_MAX.

◆ pbl_thread_regions_set()

void pbl_thread_regions_set ( struct pbl_thread *  t,
const MpuRegion *const *  regions 
)

Replace the MPU regions of a thread.

Used for the idle thread, whose regions cannot be passed at creation.

Parameters
tThread.
regionsArray of PBL_THREAD_MAX_MEM_REGIONS regions; NULL entries are ignored.

◆ pbl_thread_resume()

void pbl_thread_resume ( struct pbl_thread *  t)

Make a suspended thread runnable again.

Has no effect if t is not suspended.

Parameters
tThread to resume.

◆ pbl_thread_sleep()

void pbl_thread_sleep ( pbl_timeout_t  timeout)

Block the calling thread for a while.

Parameters
timeoutTime to sleep; PBL_NO_WAIT yields instead.

◆ pbl_thread_stack_overflow()

void pbl_thread_stack_overflow ( struct pbl_thread *  t,
const char *  name 
)

Handle a thread that overran its stack.

Implemented by the application.

Parameters
tThread that overflowed.
nameIts name.

◆ pbl_thread_state()

enum pbl_thread_state pbl_thread_state ( const struct pbl_thread *  t)

Get the state of a thread.

Parameters
tThread.
Returns
Current state.

◆ pbl_thread_suspend()

void pbl_thread_suspend ( struct pbl_thread *  t)

Stop scheduling a thread until pbl_thread_resume().

A thread suspended while blocked sees the blocking call fail with -EINTR once resumed. Has no effect on a suspended or dead thread.

Parameters
tThread to suspend, or NULL for the calling thread.

◆ pbl_thread_tls_get()

static void * pbl_thread_tls_get ( const struct pbl_thread *  t,
unsigned int  slot 
)
inlinestatic

Read a thread-local pointer slot.

Parameters
tThread.
slotSlot index, below CONFIG_KERNEL_THREAD_TLS_SLOTS.
Returns
Stored pointer, NULL if never set.

References pbl_thread::tls.

◆ pbl_thread_tls_set()

static void pbl_thread_tls_set ( struct pbl_thread *  t,
unsigned int  slot,
void *  v 
)
inlinestatic

Write a thread-local pointer slot.

Parameters
tThread.
slotSlot index, below CONFIG_KERNEL_THREAD_TLS_SLOTS.
vPointer to store.

References pbl_thread::tls.

◆ pbl_thread_yield()

void pbl_thread_yield ( void  )

Let other ready threads of the same priority run.