BeRTOS
Defines | Functions
Process (Threads) management
Kernel facilities

BeRTOS Kernel core (Process scheduler). More...

Defines

#define proc_new(entry, data, size, stack)   proc_new_with_name(NULL,(entry),(data),(size),(stack))
 Create a new named process and schedules it for execution.
#define proc_allowed()   proc_preemptAllowed()
 Deprecated, use the proc_preemptAllowed() macro.
#define PROC_ATOMIC(CODE)
 Execute a block of CODE atomically with respect to task scheduling.
#define KERN_MINSTACKSIZE
 Default stack size for each thread, in bytes.
#define PROC_DEFINE_STACK(name, size)
 Utility macro to allocate a stack of size size.

Functions

void proc_init (void)
 Initialize the process subsystem (kernel).
void proc_exit (void)
 Terminate the execution of the current process.
void proc_yield (void)
 Voluntarily release the CPU.
bool proc_needPreempt (void)
 Check if we need to schedule another task.
void proc_preempt (void)
 Preempt the current task.
void proc_rename (struct Process *proc, const char *name)
 Rename a process.
const char * proc_name (struct Process *proc)
 Return the name of the specified process.
const char * proc_currentName (void)
 Return the name of the currently running process.
iptr_t proc_currentUserData (void)
 Return a pointer to the user data of the current process.
struct Process * proc_current (void)
 Return the context structure of the currently running process.
void proc_setPri (struct Process *proc, int pri)
 Change the scheduling priority of a process.
void proc_forbid (void)
 Disable preemptive task switching.
void proc_permit (void)
 Re-enable preemptive task switching.
bool proc_preemptAllowed (void)

Detailed Description

BeRTOS Kernel core (Process scheduler).

This is the core kernel module. It allows you to create new processes (which are called threads in other systems) and set the priority of each process.

A process needs a work area (called stack) to run. To create a process, you need to declare a stack area, then create the process. You may also pass NULL for the stack area, if you have enabled kernel heap: in this case the stack will be automatically allocated.

Example:

 PROC_DEFINE_STACK(stack1, 200);

 void NORETURN proc1_run(void)
 {
    while (1)
    {
       LOG_INFO("I'm alive!\n");
       timer_delay(1000);
    }
 }


 int main()
 {
    Process *p1 = proc_new(proc1_run, NULL, stack1, sizeof(stack1));
    // here the process is already running
    proc_setPri(p1, 2);
    // ...
 }

The Process struct must be regarded as an opaque data type, do not access any of its members directly.

The entry point function should be declared as NORETURN, because it will remove a warning and enable compiler optimizations.

You can temporarily disable preemption calling proc_forbid(); remember to enable it again calling proc_permit().

Note:
You should hardly need to manually release the CPU; however you can do it using the cpu_relax() function. It is illegal to release the CPU with preemption disabled.
Author:
Bernie Innocenti <bernie@codewiz.org>

Define Documentation

#define KERN_MINSTACKSIZE
Value:
(sizeof(Process) + CPU_SAVED_REGS_CNT * 2 * sizeof(cpu_stack_t) \
            + 32 * sizeof(int) * 2)

Default stack size for each thread, in bytes.

The goal here is to allow a minimal task to save all of its registers twice, plus push a maximum of 32 variables on the stack. We add also struct Process size since we save it into the process' stack.

The actual size computed by the default formula greatly depends on what options are active and on the architecture.

Note that on most 16bit architectures, interrupts will also run on the stack of the currently running process. Nested interrupts will greatly increases the amount of stack space required per process. Use irqmanager to minimize stack usage.

Definition at line 391 of file proc.h.

#define proc_allowed ( )    proc_preemptAllowed()

Deprecated, use the proc_preemptAllowed() macro.

Definition at line 344 of file proc.h.

#define PROC_DEFINE_STACK (   name,
  size 
)
Value:
cpu_stack_t name[((size) + sizeof(cpu_stack_t) - 1) / sizeof(cpu_stack_t)]; \
    STATIC_ASSERT((size) >= KERN_MINSTACKSIZE);

Utility macro to allocate a stack of size size.

This macro define a static stack for one process and do check if given stack size is enough to run process.

Note:
If you plan to use kprintf() and similar functions, you will need at least KERN_MINSTACKSIZE * 2 bytes.
Parameters:
nameVariable name for the stack.
sizeStack size in bytes. It must be at least KERN_MINSTACKSIZE.

Definition at line 420 of file proc.h.

#define proc_new (   entry,
  data,
  size,
  stack 
)    proc_new_with_name(NULL,(entry),(data),(size),(stack))

Create a new named process and schedules it for execution.

When defining the stacksize take into account that you may want at least:

  • save all the registers for each nested function call;
  • have memory for the struct Process, which is positioned at the bottom of the stack;
  • have some memory for temporary variables inside called functions.

The value given by KERN_MINSTACKSIZE is rather safe to use in the first place.

Parameters:
entryFunction that the process will execute.
dataPointer to user data.
sizeLength of the stack.
stackPointer to the memory area to be used as a stack.
Returns:
Process structure of new created process if successful, NULL otherwise.

Definition at line 178 of file proc.h.


Function Documentation

struct Process* proc_current ( void  ) [read]

Return the context structure of the currently running process.

The details of the Process structure are private to the scheduler. The address returned by this function is an opaque pointer that can be passed as an argument to other process-related functions.

Definition at line 235 of file proc.h.

iptr_t proc_currentUserData ( void  ) [inline]

Return a pointer to the user data of the current process.

To obtain user data, just call this function inside the process. Remember to cast the returned pointer to the correct type.

Returns:
Pointer to the user data of the current process.

Definition at line 218 of file proc.h.

void proc_forbid ( void  ) [inline]

Disable preemptive task switching.

The scheduler maintains a global nesting counter. Task switching is effectively re-enabled only when the number of calls to proc_permit() matches the number of calls to proc_forbid().

Note:
Calling functions that could sleep while task switching is disabled is dangerous and unsupported.
proc_permit() expands inline to 1-2 asm instructions, so it's a very efficient locking primitive in simple but performance-critical situations. In all other cases, semaphores offer a more flexible and fine-grained locking primitive.
See also:
proc_permit()

Definition at line 268 of file proc.h.

void proc_init ( void  )

Initialize the process subsystem (kernel).

It must be called before using any process related function.

Definition at line 201 of file proc.c.

const char* proc_name ( struct Process *  proc)

Return the name of the specified process.

NULL is a legal argument and will return the name "<NULL>".

Definition at line 393 of file proc.c.

void proc_permit ( void  ) [inline]

Re-enable preemptive task switching.

See also:
proc_forbid()

Definition at line 308 of file proc.h.

bool proc_preemptAllowed ( void  ) [inline]
Returns:
true if preemptive task switching is allowed.
Note:
This accessor is needed because preempt_count must be absoultely private.

Definition at line 332 of file proc.h.

void proc_setPri ( struct Process *  proc,
int  pri 
)

Change the scheduling priority of a process.

Process piorities are signed ints, whereas a larger integer value means higher scheduling priority. The default priority for new processes is 0. The idle process runs with the lowest possible priority: INT_MIN.

A process with a higher priority always preempts lower priority processes. Processes of equal priority share the CPU time according to a simple round-robin policy.

As a general rule to maximize responsiveness, compute-bound processes should be assigned negative priorities and tight, interactive processes should be assigned positive priorities.

To avoid interfering with system background activities such as input processing, application processes should remain within the range -10 and +10.

Definition at line 440 of file proc.c.