mirror of https://github.com/l4ka/hazelnut.git
308 lines
6.8 KiB
C++
308 lines
6.8 KiB
C++
/*********************************************************************
|
|
*
|
|
* Copyright (C) 1999-2002, Karlsruhe University
|
|
*
|
|
* File path: tcb.h
|
|
* Description: The Thread Control Block structure.
|
|
*
|
|
* @LICENSE@
|
|
*
|
|
* $Id: tcb.h,v 1.16 2002/05/29 15:51:54 ud3 Exp $
|
|
*
|
|
********************************************************************/
|
|
#ifndef __TCB_H__
|
|
#define __TCB_H__
|
|
|
|
|
|
#include INC_ARCH(tcb.h)
|
|
|
|
#if defined(CONFIG_SMP)
|
|
# include INC_ARCH(sync.h)
|
|
#endif
|
|
|
|
/* From <arch/space.h> */
|
|
class space_t;
|
|
|
|
|
|
/*
|
|
|
|
Thread Control Block (TCB)
|
|
|
|
A TCB contains the state of a thread. However this is true for all but
|
|
the currently executing threads.
|
|
Every thread has its own kernel stack located behind the TCB. Most people
|
|
use the term TCB for the combination of both the TCB data structure and
|
|
the associated kernel stack.
|
|
|
|
*/
|
|
|
|
typedef struct tcb_t {
|
|
/* TCB_START_MARKER - do NOT delete */
|
|
dword_t ipc_buffer[3];
|
|
timeout_t ipc_timeout;
|
|
dword_t msg_desc;
|
|
|
|
/* don't touch above - hard coded in asm!!! */
|
|
|
|
/*
|
|
* Task state.
|
|
*/
|
|
space_t *space;
|
|
dword_t *pagedir_cache;
|
|
|
|
/*
|
|
* Thread state.
|
|
*/
|
|
l4_threadid_t myself;
|
|
l4_threadid_t pager;
|
|
dword_t excpt;
|
|
ptr_t stack;
|
|
dword_t thread_state;
|
|
dword_t queue_state;
|
|
dword_t priority;
|
|
dword_t flags;
|
|
|
|
sdword_t timeslice;
|
|
sdword_t current_timeslice;
|
|
qword_t absolute_timeout;
|
|
|
|
/*
|
|
* Kernel links.
|
|
*/
|
|
tcb_t *present_prev;
|
|
tcb_t *present_next;
|
|
tcb_t *ready_prev;
|
|
tcb_t *ready_next;
|
|
|
|
/*
|
|
* Wakeup queues
|
|
*/
|
|
tcb_t *wakeup_prev;
|
|
tcb_t *wakeup_next;
|
|
|
|
/*
|
|
* resource management
|
|
*/
|
|
dword_t resources;
|
|
dword_t copy_area1;
|
|
dword_t copy_area2;
|
|
|
|
/*
|
|
* ipc links
|
|
*/
|
|
tcb_t *send_queue;
|
|
tcb_t *send_prev;
|
|
tcb_t *send_next;
|
|
l4_threadid_t partner;
|
|
|
|
/*
|
|
* interrupts
|
|
*/
|
|
dword_t intr_pending;
|
|
|
|
/*
|
|
*
|
|
*/
|
|
ptr_t unwind_ipc_sp;
|
|
|
|
#if defined(CONFIG_SMP)
|
|
/*
|
|
* SMP cpu ownership/control
|
|
*/
|
|
dword_t cpu;
|
|
spinlock_t tcb_spinlock;
|
|
#endif
|
|
|
|
/*
|
|
* This field is not evaluated -> it can be written
|
|
* f.i. to force a write-pgfault in allocate_tcb
|
|
*/
|
|
dword_t scratch;
|
|
|
|
/*
|
|
* TCB magic number (easy to check stack overrun).
|
|
*/
|
|
dword_t magic;
|
|
|
|
/*
|
|
* Architecture-defined layout
|
|
*/
|
|
tcb_priv_t priv[0] __attribute__((aligned(16)));
|
|
|
|
/* TCB_END_MARKER - do NOT delete */
|
|
} tcb_t;
|
|
|
|
typedef union {
|
|
tcb_t tcb __attribute__((aligned(L4_TOTAL_TCB_SIZE)));
|
|
char pad[L4_TOTAL_TCB_SIZE];
|
|
} whole_tcb_t __attribute__((aligned(L4_TOTAL_TCB_SIZE)));
|
|
|
|
|
|
#define TCB_MAGIC 0x3F594857
|
|
|
|
/* The offset from the start of the tcb to the scratch field. */
|
|
#define TCB_SCRATCH_OFFSET ({tcb_t *t; ((dword_t) &t->scratch - (dword_t) t);})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* the bit fields for thread states */
|
|
#define TSB_READY 0x01
|
|
#define TSB_POLLING 0x02
|
|
#define TSB_LOCKED 0x04
|
|
|
|
/*
|
|
* Thread states use negative logic -> eases testing on x86
|
|
*/
|
|
|
|
#if !defined(CONFIG_SMP)
|
|
|
|
/* Running. Present in ready-queue and ready to be scheduled. */
|
|
#define TS_RUNNING (TSB_LOCKED | TSB_POLLING )
|
|
|
|
/* Sending, waiting for partner to receive my message. */
|
|
#define TS_POLLING (TSB_LOCKED | TSB_READY)
|
|
|
|
/* found someone to send me a message */
|
|
#define TS_LOCKED_WAITING ( TSB_POLLING | TSB_READY)
|
|
|
|
/* Running, sending or receiving a message. */
|
|
#define TS_LOCKED_RUNNING ( TSB_POLLING )
|
|
|
|
/* dead */
|
|
#define TS_ABORTED (TSB_LOCKED | TSB_POLLING | TSB_READY)
|
|
|
|
/* waiting for someone to send me a message */
|
|
#define TS_WAITING (~0U)
|
|
|
|
#else /* CONFIG_SMP */
|
|
|
|
#define TSB_XCPU 0x08
|
|
|
|
#define TS_RUNNING (TSB_XCPU | TSB_LOCKED | TSB_POLLING )
|
|
#define TS_POLLING (TSB_XCPU | TSB_LOCKED | TSB_READY)
|
|
#define TS_LOCKED_WAITING (TSB_XCPU | TSB_POLLING | TSB_READY)
|
|
#define TS_LOCKED_RUNNING (TSB_XCPU | TSB_POLLING )
|
|
#define TS_ABORTED (TSB_XCPU | TSB_LOCKED | TSB_POLLING | TSB_READY)
|
|
#define TS_XCPU_LOCKED_WAITING ( TSB_POLLING | TSB_READY)
|
|
#define TS_XCPU_LOCKED_RUNNING ( TSB_POLLING )
|
|
#define TS_WAITING (~0U)
|
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
/* macros for checking thread states in IPC */
|
|
#define IS_WAITING(x) (!(~((x)->thread_state)))
|
|
#define IS_POLLING(x) (!((x)->thread_state & ~TS_POLLING))
|
|
#define IS_RUNNING(x) (!((x)->thread_state & ~TS_RUNNING))
|
|
|
|
|
|
|
|
|
|
|
|
/* Queue membership - these are the bits in the queue_state member of a TCB.
|
|
A set bit indicates that the TCB is in the respective queue, i.e. its
|
|
member pointers for this queue are valid */
|
|
#define TS_QUEUE_READY 0x01
|
|
#define TS_QUEUE_PRESENT 0x02
|
|
#define TS_QUEUE_WAKEUP 0x04
|
|
#define TS_QUEUE_SEND 0x08
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Resource bits for resources that threads can use.
|
|
*/
|
|
|
|
void save_resources(tcb_t *current, tcb_t *dest);
|
|
void load_resources(tcb_t *current);
|
|
|
|
void init_resources(tcb_t * tcb);
|
|
void free_resources(tcb_t * tcb);
|
|
void purge_resources(tcb_t * tcb);
|
|
|
|
#define TR_IPC_MEM1 (1 << 0)
|
|
#define TR_IPC_MEM2 (1 << 1)
|
|
#define TR_IPC_MEM (TR_IPC_MEM1|TR_IPC_MEM2)
|
|
#define TR_FPU (1 << 2)
|
|
#define TR_LONG_IPC_PTAB (1 << 3)
|
|
#define TR_DEBUG_REGS (1 << 4)
|
|
|
|
#if defined(CONFIG_ENABLE_PVI)
|
|
#define TR_PVI (1 << 5)
|
|
#endif
|
|
|
|
#define COPYAREA_INVALID ((dword_t)~0)
|
|
|
|
|
|
/* Various thread flags. */
|
|
#define TF_SENDING_IPC 0x01 /* Set during IPC send phase. */
|
|
|
|
|
|
/* some globally used TCBs */
|
|
extern whole_tcb_t __idle_tcb;
|
|
extern tcb_t * sigma0;
|
|
|
|
|
|
|
|
|
|
/* check, whether the threads belonging to two TCBs are in the same
|
|
address space by comparing the MMU translation table pointers */
|
|
INLINE int same_address_space(tcb_t * tcb1, tcb_t * tcb2)
|
|
{
|
|
return (tcb1->space == tcb2->space);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* idle tcb stuff
|
|
*/
|
|
INLINE tcb_t * get_idle_tcb() {
|
|
return &__idle_tcb.tcb;
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
Present List Handling
|
|
|
|
The present list contains all existing TCBs in a doubly linked list.
|
|
Initially, only the idle_tcb is in the present list. Newly created TCBs
|
|
are added. There is a present list per CPU.
|
|
*/
|
|
|
|
/* enqueue the TCB in the present list */
|
|
INLINE void thread_enqueue_present(tcb_t * tcb)
|
|
{
|
|
/* check if not already in the list */
|
|
if (!(tcb->queue_state & TS_QUEUE_PRESENT))
|
|
{
|
|
/* add the TCB next to the idle_tcb */
|
|
tcb_t * idle = get_idle_tcb();
|
|
|
|
tcb->present_prev = idle;
|
|
tcb->present_next = idle->present_next;
|
|
idle->present_next = tcb;
|
|
tcb->present_next->present_prev = tcb;
|
|
|
|
tcb->queue_state |= TS_QUEUE_PRESENT;
|
|
}
|
|
}
|
|
|
|
INLINE void thread_dequeue_present(tcb_t * tcb)
|
|
{
|
|
if (tcb->queue_state & TS_QUEUE_PRESENT)
|
|
{
|
|
tcb->present_prev->present_next = tcb->present_next;
|
|
tcb->present_next->present_prev = tcb->present_prev;
|
|
tcb->queue_state &= ~TS_QUEUE_PRESENT;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#endif /* __TCB_H__ */
|