Полный набор регистров часто сохраняется в стеке потока, что означает, что один указатель стека может быть всем, что вам нужно для хранения счетчика программы, регистров состояния и любых других регистров, для которых требуется переключение контекста.
Вот реальный пример TCB / PCB из RTOS, который я открыл несколько месяцев назад ( Atomthreads) :
typedef struct atom_tcb
{
/* Thread's current stack pointer */
POINTER sp_save_ptr;
/* Thread priority (0-255) */
uint8_t priority;
/* Thread entry point and parameter */
void (*entry_point)(uint32_t);
uint32_t entry_param;
/* Queue pointers */
struct atom_tcb *prev_tcb; /* Previous TCB in doubly-linked TCB list */
struct atom_tcb *next_tcb; /* Next TCB in doubly-linked list */
/* Suspension data */
uint8_t suspended; /* TRUE if task is currently suspended */
uint8_t suspend_wake_status; /* Status returned to woken suspend calls */
ATOM_TIMER *suspend_timo_cb; /* Callback registered for suspension timeouts */
} ATOM_TCB;
Помимо указателя стека, мне были нужны следующие ключевые элементы:
- Priority
- Указатели на связанный список: Для управления потоками в очереди готовности для простых планировщиков на основе очереди или для обработки очередей потоков, ожидающих определенного семафора и т. Д.
- Состояние приостановки : Для обработки таких действий, как ожидание на семафоре. Они используются для регистрации функции обратного вызова, вызываемой в случае истечения времени ожидания (например, это может быть обработчик тайм-аута в библиотеке очередей), и для передачи кодов состояния обратно в пробужденный поток.
Это не единственный способ сделать это. Вы обнаружите, что ваши собственные конкретные требования станут ясны, когда вы начнете разрабатывать RTOS и реализовать различные примитивы ОС (семафоры, очереди и т. Д.).