diff options
Diffstat (limited to 'pk/kernel/pk_api.h')
-rw-r--r-- | pk/kernel/pk_api.h | 1016 |
1 files changed, 0 insertions, 1016 deletions
diff --git a/pk/kernel/pk_api.h b/pk/kernel/pk_api.h deleted file mode 100644 index 66ed1324..00000000 --- a/pk/kernel/pk_api.h +++ /dev/null @@ -1,1016 +0,0 @@ -#ifndef __PK_API_H__ -#define __PK_API_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_api.h -/// \brief Macros and declarations for the PK API. - -// Basic constants - -/// Although the number of threads is defined as a manifest constant, -/// numerous parts of the PK code assume this definition. The number of -/// supported threads _can not_ be changed simply by changing this constant. - -#define PK_THREADS 32 - -#define PK_IDLE_THREAD_PRIORITY PK_THREADS - -// Interrupt API - -#define PK_IRQ_POLARITY_ACTIVE_LOW 0 -#define PK_IRQ_POLARITY_ACTIVE_HIGH 1 - -#define PK_IRQ_TRIGGER_LEVEL_SENSITIVE 0 -#define PK_IRQ_TRIGGER_EDGE_SENSITIVE 1 - -// API return codes - -#define PK_OK 0 -#define PK_ILLEGAL_CONTEXT_THREAD_CONTEXT 0x00779002 -#define PK_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT 0x00779003 -#define PK_ILLEGAL_CONTEXT_THREAD 0x00779004 -#define PK_ILLEGAL_CONTEXT_TIMER 0x00779005 -#define PK_INVALID_THREAD_AT_RESUME1 0x00779007 -#define PK_INVALID_THREAD_AT_RESUME2 0x00779008 -#define PK_INVALID_THREAD_AT_SUSPEND1 0x00779009 -#define PK_INVALID_THREAD_AT_SUSPEND2 0x0077900a -#define PK_INVALID_THREAD_AT_DELETE 0x0077900b -#define PK_INVALID_THREAD_AT_INFO 0x0077900c -#define PK_INVALID_THREAD_AT_CHANGE 0x0077900d -#define PK_INVALID_THREAD_AT_SWAP1 0x0077900e -#define PK_INVALID_THREAD_AT_SWAP2 0x0077900f -#define PK_INVALID_THREAD_AT_CREATE 0x00779010 -#define PK_INVALID_SEMAPHORE_AT_POST 0x00779011 -#define PK_INVALID_SEMAPHORE_AT_PEND 0x00779012 -#define PK_INVALID_SEMAPHORE_AT_RELEASE 0x00779013 -#define PK_INVALID_SEMAPHORE_AT_INFO 0x00779014 -#define PK_INVALID_SEMAPHORE_AT_CREATE 0x00779015 -#define PK_INVALID_TIMER_AT_SCHEDULE 0x00779016 -#define PK_INVALID_TIMER_AT_CANCEL 0x00779017 -#define PK_INVALID_TIMER_AT_INFO 0x00779018 -#define PK_INVALID_TIMER_AT_CREATE 0x00779019 -#define PK_INVALID_ARGUMENT_IRQ_SETUP 0x0077901a -#define PK_INVALID_ARGUMENT_IRQ_HANDLER 0x0077901b -#define PK_INVALID_ARGUMENT_INTERRUPT 0x00779024 -#define PK_INVALID_ARGUMENT_CONTEXT_SET 0x00779025 -#define PK_INVALID_ARGUMENT_CONTEXT_GET 0x00779026 -#define PK_INVALID_ARGUMENT_FIT 0x00779027 -#define PK_INVALID_ARGUMENT_WATCHDOG 0x00779028 -#define PK_INVALID_ARGUMENT_INIT 0x00779029 -#define PK_INVALID_ARGUMENT_SEMAPHORE 0x0077902a -#define PK_INVALID_ARGUMENT_THREAD_CHANGE 0x0077902b -#define PK_INVALID_ARGUMENT_THREAD_PRIORITY 0x0077902c -#define PK_INVALID_ARGUMENT_THREAD1 0x0077902d -#define PK_INVALID_ARGUMENT_THREAD2 0x0077902e -#define PK_INVALID_ARGUMENT_THREAD3 0x0077902f -#define PK_STACK_OVERFLOW 0x00779030 -#define PK_TIMER_ACTIVE 0x00779031 -#define PK_TIMER_NOT_ACTIVE 0x00779032 -#define PK_PRIORITY_IN_USE_AT_RESUME 0x00779033 -#define PK_PRIORITY_IN_USE_AT_CHANGE 0x00779034 -#define PK_PRIORITY_IN_USE_AT_SWAP 0x00779035 -#define PK_SEMAPHORE_OVERFLOW 0x00779036 -#define PK_SEMAPHORE_PEND_NO_WAIT 0x00779037 -#define PK_SEMAPHORE_PEND_TIMED_OUT 0x00779038 -#define PK_SEMAPHORE_PEND_WOULD_BLOCK 0x00779039 -#define PK_INVALID_DEQUE_SENTINEL 0x0077903a -#define PK_INVALID_DEQUE_ELEMENT 0x0077903b -#define PK_INVALID_OBJECT 0x0077903c - -// Kernel panics - -#define PK_NO_TIMER_SUPPORT 0x0077903d -#define PK_START_THREADS_RETURNED 0x0077903e -#define PK_UNIMPLEMENTED 0x0077903f -#define PK_SCHEDULING_INVARIANT 0x00779040 -#define PK_TIMER_HANDLER_INVARIANT 0x00779041 -#define PK_THREAD_TIMEOUT_STATE 0x00779045 - -// Application-level panic offsets -// (Use these as offsets for your application code panics and keep -// track of them locally in your application code domain, including -// sharing the panic defines with other developers making codes -// for the same engine.) - -#define PK_APP_OFFSET_SBE 0x0077a000 -#define PK_APP_OFFSET_GPE0 0x0077b000 -#define PK_APP_OFFSET_GPE1 0x0077c000 -#define PK_APP_OFFSET_GPE2 0x0077d000 -#define PK_APP_OFFSET_GPE3 0x0077e000 -#define PK_APP_OFFSET_CME 0x0077f000 - -/// \defgroup pk_thread_states PK Thread States -/// -/// Threads are created in the state PK_THREAD_STATE_SUSPENDED_RUNNABLE. -/// When the thread is mapped it transitions to state PK_THREAD_STATE_MAPPED. -/// A mapped thread is runnable if it appears in the run queue; there is no -/// other flag or status to indicate a runnable thread. If a blocked thread -/// is suspended it goes into state PK_THREAD_STATE_SUSPENDED_BLOCKED. For -/// all threads the reason for blockage is detailed in the \a flags field of -/// the thread; See \ref pk_thread_flags. PK_THREAD_STATE_DELETED and -/// PK_THREAD_STATE_COMPLETED are effectively equivalent but named -/// individually for reporting purposes. -/// -/// \note This separation of the thread \a state and \a flags allows the use -/// of an PK semaphore as a thread barrier, as it supports a non-iterative -/// implementation of pk_semaphore_release_all() in which all threads blocked -/// on the semaphore are simultaneously inserted into the run queue with an -/// atomic operation, followed by each individual thread readjusting its flags -/// appropriately once the thread runs again. -/// -/// @{ - -#define PK_THREAD_STATE_SUSPENDED_RUNNABLE 1 -#define PK_THREAD_STATE_MAPPED 2 -#define PK_THREAD_STATE_SUSPENDED_BLOCKED 3 -#define PK_THREAD_STATE_COMPLETED 4 -#define PK_THREAD_STATE_DELETED 5 - -/// @} - - -/// \defgroup pk_thread_flags PK Thread Flags -/// -/// The \a flag field of the thread extends the information contained in the -/// \a state field; See \ref pk_thread_states. Blocked threads will show -/// PK_THREAD_FLAG_SEMAPHORE_PEND, PK_THREAD_FLAG_TIMER_PEND or both (if -/// blocked on a semaphore with timeout). The flag PK_THREAD_FLAG_TIMED_OUT -/// indicates that a thread timer timed out before the thread became -/// runnable. Currently only the semaphore-pend-with-timeout code uses this -/// flag. -/// -/// Note that a thread can be mapped and runnable (in the run queue) even -/// though PK_THREAD_FLAG_SEMAPHORE_PEND and/or PK_THREAD_FLAG_TIMER_PEND -/// are set. These flags are always cleared by the thread itself, not the code -/// that unblocks the thread. This allows the implementation of the -/// pk_semaphore_release_all() as explained in \ref pk_thread_states. -/// -/// @{ - -#define PK_THREAD_FLAG_SEMAPHORE_PEND 0x1 -#define PK_THREAD_FLAG_TIMER_PEND 0x2 -#define PK_THREAD_FLAG_TIMED_OUT 0x4 - -/// @} - - -// Critical Sections - -/// Enter a critical section, saving the current machine -/// context. - -#define pk_critical_section_enter(pctx) \ - pk_interrupt_disable(pctx) - -/// Exit a critical section by restoring the previous machine context. - -#define pk_critical_section_exit(pctx) \ - pk_machine_context_set(pctx) - - -/// Execute a statement atomically - -#define PK_ATOMIC(stmt) \ - do { \ - PkMachineContext __ctx; \ - pk_critical_section_enter(&__ctx); \ - stmt; \ - pk_critical_section_exit(&__ctx); \ - } while (0) - - -// Application-overrideable definitions - -/// Control whether or not the API functions check for errors. -/// -/// This definition can be overriden by the application. - -#ifndef PK_ERROR_CHECK_API -#define PK_ERROR_CHECK_API 1 -#endif - -/// Control whether API errors cause kernel panics or return negative error -/// codes. -/// -/// This selection is only valid if \c PK_ERROR_CHECK_API is defined -/// non-0. This definition can be overriden by the application. - -#ifndef PK_ERROR_PANIC -#define PK_ERROR_PANIC 1 -#endif - -/// Control whether or not the PK kernel checks key invariants. -/// -/// Violations of kernel invariants always cause kernel panics. This -/// definition can be overriden by the application. - -#ifndef PK_ERROR_CHECK_KERNEL -#define PK_ERROR_CHECK_KERNEL 1 -#endif - -/// Define the time interval type, which must be an unsigned type of a size -/// less then or equal to the size of \c PkTimebase. This definition can be -/// overridden by the application. - -#ifndef PK_TIME_INTERVAL_TYPE -#define PK_TIME_INTERVAL_TYPE uint32_t -#endif - -/// Provide support for the PkTimer APIs in addition to the default -/// initerrupt APIs. This definition can be overridden by the application. - -#ifndef PK_TIMER_SUPPORT -#define PK_TIMER_SUPPORT 1 -#endif - -/// Provide support for the all PK APIs. Thread support requires/implies -/// support for time services and semaphores. This definition can be -/// overridden by the application. - -#ifndef PK_THREAD_SUPPORT -#define PK_THREAD_SUPPORT 1 -#endif - -/// Control the level of stack checking. -/// -/// This definition can be overriden by the application. -/// -/// 0 : No stack prepatterning or checking is made for thread and kernel -/// stacks. -/// -/// 1 : Kernel interrupt stacks are prepatterned during -/// \c pk_initialize(). Thread stacks are prepatterned during -/// \c pk_thread_create(). -/// -/// 2 : (\b Default - Currently Unimplemented) In addition to prepatterning, -/// stack utilization is computed at the exit of context switches and -/// interrupt processing. The maximum utilization is stored in -/// the thread data structure. The kernel will panic if stack overflow is -/// detected. Stack utilization is not computed for the idle thread. - -#ifndef PK_STACK_CHECK -#define PK_STACK_CHECK 1 -#endif - -/// A hook for main() -/// -/// This hook macro is expanded in the body of __pk_main() prior to the call -/// of the application main(). The application can redefine this hook macro -/// in (or in headers referred to in) the application header -/// pk_app_cfg.h. The PK_MAIN_HOOK will run on the stack of main(). - -#ifndef PK_MAIN_HOOK -#define PK_MAIN_HOOK do {} while (0) -#endif - -/// A hook for pk_start_threads() -/// -/// This hook macro is expanded in the call-tree of pk_start_threads() before -/// threads are actually started. The application can redefine this hook -/// macro in (or in headers referred to in) the application header -/// pk_app_cfg.h. -/// -/// The PK_START_THREADS_HOOK runs as a pseudo-interrupt handler on the -/// kernel stack, with external interrupts disabled. - -#ifndef PK_START_THREADS_HOOK -#define PK_START_THREADS_HOOK do {} while (0) -#endif - -/// The maximum value of the \c PkTimebase type. - -#define PK_TIMEBASE_MAX ((PkTimebase)-1) - -/// A special value that specifies that the timebase will not be reset during -/// pk_init(). - -#define PK_TIMEBASE_CONTINUES PK_TIMEBASE_MAX - -/// By convention, a timeout value indicating 'no waiting' in a call of \c -/// pk_semaphore_pend(). - -#define PK_NO_WAIT 0 - -/// By convention, a timeout value indicating 'wait forever' in a call of \c -/// pk_semaphore_pend(). - -#define PK_WAIT_FOREVER ((PkInterval)-1) - -/// The PK timebase frequency in Hz -/// -/// Earlier version of PK defined the timbase frequency as a preprocessor -/// macro. Now, the timebase frequency is specified as a parameter of the -/// pk_initialize() API. The macro remains defined for backwards -/// compatibility, however all kernel uses of the timebase frequency are now -/// optimized around the timebase parameter. - -#define PK_TIMEBASE_FREQUENCY_HZ __pk_timebase_frequency_hz - -/// This is the unscaled timebase frequency in Hz. -#ifdef APPCFG_USE_EXT_TIMEBASE -#define PK_BASE_FREQ_HZ (uint32_t)25000000 -#else -#define PK_BASE_FREQ_HZ (uint32_t)400000000 -#endif /* APPCFG_USE_EXT_TIMEBASE */ -#define PK_BASE_FREQ_KHZ (PK_BASE_FREQ_HZ / 1000) -#define PK_BASE_FREQ_MHZ (PK_BASE_FREQ_HZ / 1000000) - -/// Scale a time interval to be _closer_ to what was actually requested -/// base on the actual timebase frequency. -#define PK_INTERVAL_SCALE(interval) ((interval) + ((interval) >> __pk_timebase_rshift)) - -/// Convert a time in integral seconds to a time interval - overflows are -/// ignored. The application can redefine this macro. - -#ifndef PK_SECONDS -#define PK_SECONDS(s) ((PkInterval)(PK_BASE_FREQ_HZ * (s))) -#endif - -/// Convert a time in integral milliseconds to a time interval - overflows are -/// ignored, and a frequency evenly (or closely) divisible by 1000 is -/// assumed. The application can redefine this macro. - -#ifndef PK_MILLISECONDS -#define PK_MILLISECONDS(m) ( (PkInterval)(PK_BASE_FREQ_KHZ * (m)) ) -#endif - -/// Convert a time in integral microseconds to a time interval - overflows are -/// ignored, and a frequncy evenly (or closely) divisible by 1,000,000 is -/// assumed. The application can redefine this macro. - -#ifndef PK_MICROSECONDS -#define PK_MICROSECONDS(u) ( (PkInterval)(PK_BASE_FREQ_MHZ * (u)) ) -#endif - -/// Convert a time in integral nanoseconds to a time interval - overflows are -/// ignored, and a frequeyncy evenly (or closely) divisible by 1,000,000 is -/// assumed. The application can redefine this macro. - -#ifndef PK_NANOSECONDS -#define PK_NANOSECONDS(n) ( (PkInterval)( ( ((PK_BASE_FREQ_MHZ<<10)/1000) * (n) ) >> 10) ) -#endif - - -/// Enable PK application tracing (enabled by default) -#ifndef PK_TRACE_ENABLE -#define PK_TRACE_ENABLE 1 -#endif - -/// Enable PK kernel tracing (disabled by default) -#ifndef PK_KERNEL_TRACE_ENABLE -#define PK_KERNEL_TRACE_ENABLE 0 -#endif - -//Application trace macros -#if !PK_TRACE_ENABLE -#define PK_TRACE(...) -#define PK_TRACE_BIN(str, bufp, buf_size) -#else -#define PK_TRACE(...) PKTRACE(__VA_ARGS__) -#define PK_TRACE_BIN(str, bufp, buf_size) PKTRACE_BIN(str, bufp, buf_size) -#endif - - -//Kernel trace macros -#if !PK_KERNEL_TRACE_ENABLE -#define PK_KERN_TRACE(...) -#define PK_KERN_TRACE_ASM16(...) -#else -#define PK_KERN_TRACE(...) PK_TRACE(__VA_ARGS__) -#define PK_KERN_TRACE_ASM16(...) PK_TRACE_ASM16(__VA_ARGS__) -#endif /* PK_KERNEL_TRACE_ENABLE */ - - -/// Add a string to the trace buffer with an optional register holding a 16bit value -/// WARNING: This calls a c function which may clobber any of the volatile registers -#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) -#define PK_TRACE_ASM16(...) TRACE_ASM_HELPER16(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) -#else -#define PK_TRACE_ASM16(...) -#endif /* PK_TRACE_SUPPORT */ - -/// The following macros are helper macros for tracing. They should not be called -/// directly. -#define VARG_COUNT_HELPER(_0, _1, _2, _3, _4, _5, _6, _7, N, ...) N -#define VARG_COUNT(...) VARG_COUNT_HELPER(, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) - -#ifdef __ASSEMBLER__ -#define TRACE_ASM_HELPER16_CALL(count, ...) TINY_TRACE_ASM ## count (__VA_ARGS__) -#define TRACE_ASM_HELPER16(count, ...) TRACE_ASM_HELPER16_CALL(count, __VA_ARGS__) - -#define TINY_TRACE_ASM0() .error "format string required" -#define TINY_TRACE_ASM1(str) \ - .tiny_trace_asm1 trace_ppe_hash(str, PK_TRACE_HASH_PREFIX) -#define TINY_TRACE_ASM2(str, reg) \ - .tiny_trace_asm2 trace_ppe_hash(str, PK_TRACE_HASH_PREFIX), reg -#define TINY_TRACE_ASM3() .error "too many parameters" -#define TINY_TRACE_ASM4() .error "too many parameters" -#define TINY_TRACE_ASM5() .error "too many parameters" -#define TINY_TRACE_ASM6() .error "too many parameters" -#define TINY_TRACE_ASM7() .error "too many parameters" - -//TODO: add support for tracing more than 1 parameter and binary data in assembly - - .global pk_trace_tiny - - .macro .tiny_trace_asm1 hash16 - lis %r3, \hash16 - bl pk_trace_tiny - .endm - - .macro .tiny_trace_asm2 hash16, parm16 - clrlwi %r3, \parm16, 16 - oris %r3, %r3, \hash16 - bl pk_trace_tiny - .endm - -#endif /*__ASSEMBLER__*/ - - - -#ifndef __ASSEMBLER__ - -#include <stddef.h> -#include <stdint.h> - -/// The timebase frequency in Hz; A parameter to pk_initialize() -extern uint32_t __pk_timebase_frequency_hz; - -extern uint8_t __pk_timebase_rshift; - -/// The timebase frequency in KHz -extern uint32_t __pk_timebase_frequency_khz; - -/// The timebase frequency in Mhz -extern uint32_t __pk_timebase_frequency_mhz; - - -typedef unsigned long int PkAddress; - -typedef uint8_t PkThreadState; - -typedef uint8_t PkThreadPriority; - -typedef uint8_t PkThreadFlags; - -typedef uint32_t PkSemaphoreCount; - -typedef uint64_t PkTimebase; - -typedef PK_TIME_INTERVAL_TYPE PkInterval; - -#include "pk_port_types.h" - -typedef struct { - - /// A priority queue of threads pending on the semaphore. - PkThreadQueue pending_threads; - - /// The current semaphore count. - PkSemaphoreCount count; - - /// The maximum allowable count - for error checking. - PkSemaphoreCount max_count; - -} PkSemaphore; - - -/// Compile-time initialize a PkSemaphore structure -/// -/// This low-level macro creates a structure initializatin of an PkSemaphore -/// structure. This can be used for example to create compile-time initialized -/// arrays of semaphores. -#define PK_SEMAPHORE_INITIALIZATION(_initial_count, _max_count) \ - {.pending_threads = 0, \ - .count = (_initial_count), \ - .max_count = (_max_count)} - - -/// Declare and initialize a semaphore -#define PK_SEMAPHORE(sem, initial_count, max_count) \ - PkSemaphore sem = PK_SEMAPHORE_INITIALIZATION(initial_count, max_count) - - -/// Trace macros for C functions -#define HASH_ARG_COMBO(str, arg) \ - ((((uint32_t)trace_ppe_hash(str, PK_TRACE_HASH_PREFIX)) << 16) | ((uint32_t)(arg) & 0x0000ffff)) - -#define PKTRACE0(...) pk_trace_tiny() //will fail at compile time - -#define PKTRACE1(str) \ - pk_trace_tiny((trace_ppe_hash(str, PK_TRACE_HASH_PREFIX) << 16)) - -#define PKTRACE2(str, parm0) \ - ((sizeof(parm0) <= 2)? \ - pk_trace_tiny(HASH_ARG_COMBO(str, parm0)): \ - pk_trace_big(HASH_ARG_COMBO(str, 1), ((uint64_t)parm0) << 32, 0)) - -#define PKTRACE3(str, parm0, parm1) \ - pk_trace_big(HASH_ARG_COMBO(str, 2), ((((uint64_t)parm0) << 32) | parm1), 0) - -#define PKTRACE4(str, parm0, parm1, parm2) \ - pk_trace_big(HASH_ARG_COMBO(str, 3), ((((uint64_t)parm0) << 32) | parm1),\ - ((uint64_t)parm2) << 32 ) - -#define PKTRACE5(str, parm0, parm1, parm2, parm3) \ - pk_trace_big(HASH_ARG_COMBO(str, 4), ((((uint64_t)parm0) << 32) | parm1),\ - ((((uint64_t)parm2) << 32) | parm3) ) - -#define PKTRACE6(...) pk_trace_tiny() //will fail at compile time -#define PKTRACE7(...) pk_trace_tiny() //will fail at compile time - -#define PKTRACE_HELPER2(count, ...) PKTRACE ## count (__VA_ARGS__) -#define PKTRACE_HELPER(count, ...) PKTRACE_HELPER2(count, __VA_ARGS__) - -#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) -#define PKTRACE(...) PKTRACE_HELPER(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) -#define PKTRACE_BIN(str, bufp, buf_size) \ - pk_trace_binary(((buf_size < 255)? HASH_ARG_COMBO(str, buf_size): HASH_ARG_COMBO(str, 255)), bufp) -#else -#define PKTRACE(...) -#define PKTRACE_BIN(str, bufp, buf_size) -#endif //PK_TRACE_SUPPORT - - - -/// A generic doubly-linked list object -/// -/// This object functions both as a sentinel mode for a deque as well as a -/// pointer container for elements in deques. The PK API assumes that -/// queueable structures will be defined with an PkDeque structure as the -/// initial 'data member' of the structure. This allows a pointer to a queue -/// element to be cast to a pointer to an PkDeque and vice-versa. - -typedef struct PkDeque { - - /// Pointer to the head or the next element in a deque. - /// - /// When an PkDeque is used as the sentinel node for a queue, \a next - /// points to the head of the queue, and the condition (next == \<self\>) - /// indicates an empty PkDeque. By convention the condition (\a next == - /// 0) is used to indicate that a queue element is not enqueued. - struct PkDeque* next; - - /// Pointer to the tail or previous element in a deque. - /// - /// When a DQueue is used as the sentinel node for a queue, \a previous - /// points to the tail of the queue. - struct PkDeque* previous; - -} PkDeque; - - -typedef void (*PkTimerCallback)(void *); - -#define PK_TIMER_CALLBACK(callback) void callback(void *) - -struct PkTimer; - -/// The PK timer object - -typedef struct PkTimer { - - /// The time queue management pointers - /// - /// This pointer container is defined as the first element of the - /// structure to allow the PkTimer to be cast to an PkDeque and - /// vice-versa. - PkDeque deque; - - /// The absolute timeout of the timer. - PkTimebase timeout; - - /// The timer callback - /// - /// For PK thread timers used to implement Sleep and semaphore pend - /// timeouts this field is initialized to __pk_thread_timeout(). - PkTimerCallback callback; - - /// Private data passed to the callback. - /// - /// For PK thread timers used to implement Sleep and semaphore pend this - /// field is initialized to a pointer to the thread. - void *arg; - -} PkTimer; - - -// Threads - -typedef void (*PkThreadRoutine)(void *arg); - -#define PK_THREAD_ROUTINE(f) void f(void *arg); - -typedef struct { - - /// Stack pointer saved during context switches. Assembler code expects - /// this to always be at address offset 0 from the thread pointer. - PkAddress saved_stack_pointer; - - /// This is 1 past the last valid byte address of the thread stack. - /// Assembler code expects this to always be at address offset (sizeof - /// PkAddress) from the thread pointer. - PkAddress stack_limit; - - /// This is the original base of the stack. - /// Assembler code expects this to always be at address offset 2 * (sizeof - /// PkAddress) from the thread pointer. - PkAddress stack_base; - - /// If the thread is blocked on a semaphore, then this is the semaphore the - /// thread is blocked on. - PkSemaphore *semaphore; - - /// The thread priority. - PkThreadPriority priority; - - /// The thread state; See \ref pk_thread_states - PkThreadState state; - - /// Thread flags; See \ref pk_thread_flags - PkThreadFlags flags; - - /// The timer structure handles Sleep and blocking on a semaphore with - /// timeout. - PkTimer timer; - -} PkThread; - - -typedef void (*PkBhHandler)(void *); - -#define PK_BH_HANDLER(handler) void handler(void *) - -typedef struct { - - /// The bottom half queue management pointers - /// - /// This pointer container is defined as the first element of the - /// structure to allow the PkBottomHalf to be cast to a PkDeque and - /// vice-versa. - PkDeque deque; - - /// The bottom half handler - PkBhHandler bh_handler; - - /// Private data passed to the handler. - void *arg; - -} PkBottomHalf; - - -// Initialization APIs - -int -pk_initialize(PkAddress kernel_stack, - size_t kernel_stack_size, - PkTimebase initial_timebase, - uint32_t timebase_frequency_hz); - - -// Timebase APIs - -PkTimebase -pk_timebase_get(void); - - -// Timer APIs - -int -pk_timer_create(PkTimer *timer, - PkTimerCallback callback, - void *arg); - - -int -pk_timer_schedule(PkTimer *timer, - PkInterval interval); - -int -pk_timer_cancel(PkTimer *timer); - -int -pk_timer_info_get(PkTimer *timer, - PkTimebase *timeout, - int *active); - -// Thread APIs - -int -pk_thread_create(PkThread *thread, - PkThreadRoutine thread_routine, - void *arg, - PkAddress stack, - size_t stack_size, - PkThreadPriority priority); - -int -pk_start_threads(void); - -int -pk_thread_resume(PkThread *thread); - -int -pk_thread_suspend(PkThread *thread); - -int -pk_thread_delete(PkThread *thread); - -int -pk_complete(void); - -int -pk_sleep(PkInterval interval); - -int -pk_thread_info_get(PkThread *thread, - PkThreadState *state, - PkThreadPriority *priority, - int *runnable); - -int -pk_thread_priority_change(PkThread *thread, - PkThreadPriority new_priority, - PkThreadPriority *old_priority); - -int -pk_thread_at_priority(PkThreadPriority priority, - PkThread **thread); - -int -pk_thread_priority_swap(PkThread* thread_a, PkThread* thread_b); - - -// Semaphore APIs - -int -pk_semaphore_create(PkSemaphore *semaphore, - PkSemaphoreCount initial_count, - PkSemaphoreCount max_count); - -int -pk_semaphore_post(PkSemaphore *semaphore); - -int -pk_semaphore_pend(PkSemaphore *semaphore, - PkInterval timeout); - -int -pk_semaphore_release_all(PkSemaphore *semaphore); - - -int -pk_semaphore_info_get(PkSemaphore *semaphore, - PkSemaphoreCount *count, - int *pending); - -void -pk_semaphore_post_handler(void *arg, - PkIrqId irq); - -// Misc. APIs - -void -pk_halt() __attribute__ ((noreturn)); - -// Deque APIs - -int -pk_deque_sentinel_create(PkDeque *deque); - -#define PK_DEQUE_SENTINEL_INIT(dq_addr) \ -{\ - .next = dq_addr, \ - .previous = dq_addr \ -} - -#define PK_DEQUE_SENTINEL_STATIC_CREATE(deque) \ - PkDeque deque = PK_DEQUE_SENTINEL_INIT(&deque) - -int -pk_deque_element_create(PkDeque *element); - -#define PK_DEQUE_ELEMENT_INIT() \ -{\ - .next = 0, \ - .previous = 0 \ -} - -#define PK_DEQUE_ELEMENT_STATIC_CREATE(deque) \ - PkDeque deque = PK_DEQUE_ELEMENT_INIT() - -/// Check for an empty PkDeque -/// -/// \param deque The sentinel node of a deque -/// -/// \retval 0 The PkDeque is not empty -/// -/// \retval 1 The PkDeque is empty - -static inline int -pk_deque_is_empty(PkDeque *deque) -{ - return (deque == deque->next); -} - - -/// Check if an PkDeque element is currently enqueued -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// \retval 0 The element is not currently enqueued -/// -/// \retval 1 The element is currently enqueued - -static inline int -pk_deque_is_queued(PkDeque *element) -{ - return (element->next != 0); -} - - -/// Append an element to the tail of a deque (FIFO order) -/// -/// \param deque The sentinel node of a deque -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// It is an error to call this API on an element that is already enqueued, -/// but the API does not check for this error. - -static inline void -pk_deque_push_back(PkDeque *deque, PkDeque *element) -{ - deque->previous->next = element; - element->previous = deque->previous; - element->next = deque; - deque->previous = element; -} - - -/// Push an element at the head of a deque (LIFO order) -/// -/// \param deque The sentinel node of a deque -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// It is an error to call this API on an element that is already enqueued, -/// but the API does not check for this error. - -static inline void -pk_deque_push_front(PkDeque *deque, PkDeque *element) -{ - deque->next->previous = element; - element->next = deque->next; - element->previous = deque; - deque->next = element; -} - -/// Pop an element from the head of a deque -/// -/// \param deque The sentinel node of a deque -/// -/// \retval 0 The PkDeque was empty prior to the call -/// -/// \retval non-0 A pointer to the previous head of the deque, which has been -/// removed from the deque and marked as no longer queued. - -// The cast of 'head' is used to remove the 'volatile' attribute. - -static inline PkDeque * -pk_deque_pop_front(PkDeque *deque) -{ - PkDeque *head; - - if (pk_deque_is_empty(deque)) { - return 0; - } else { - head = (PkDeque *)(deque->next); - deque->next = head->next; - deque->next->previous = deque; - head->next = 0; - return head; - } -} - - -/// Remove a deque element from any position in the deque -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// It is an error to call this API on an element that is not currently -/// enqueued, but the API does not check for this error. - -static inline void -pk_deque_delete(PkDeque *element) -{ - element->previous->next = element->next; - element->next->previous = element->previous; - element->next = 0; -} - -// Bottom Half APIs - -extern PkDeque _pk_bh_queue; - -static inline void -pk_bh_schedule(PkBottomHalf *bottom_half) -{ - pk_deque_push_back(&_pk_bh_queue, (PkDeque *)bottom_half); -} - -#define PK_BH_INIT(_handler, _arg) \ -{\ - .deque = PK_DEQUE_ELEMENT_INIT(), \ - .bh_handler = _handler, \ - .arg = _arg \ -} - -#define PK_BH_STATIC_CREATE(bh_name, handler, arg) \ -PkBottomHalf bh_name = PK_BH_INIT(handler, arg) - - -//Trace function prototypes -void pk_trace_tiny(uint32_t i_parm); -void pk_trace_big(uint32_t i_hash_and_count, - uint64_t i_parm1, uint64_t i_parm2); -void pk_trace_binary(uint32_t i_hash_and_size, void* bufp); -void pk_trace_set_timebase(PkTimebase timebase); - - -/// Cast a pointer to another type, in a way that won't cause warnings - -#define PK_CAST_POINTER(t, p) ((t)((PkAddress)(p))) - -// Static Assert Macro for Compile time assertions. -// - This macro can be used both inside and outside of a function. -// - A value of false will cause the ASSERT to produce this error -// - This will show up on a compile fail as: -// <file>:<line> error: size of array '_static_assert' is negative -// - It would be trivial to use the macro to paste a more descriptive -// array name for each assert, but we will leave it like this for now. -#define PK_STATIC_ASSERT(cond) extern uint8_t _static_assert[(cond) ? 1 : -1] __attribute__ ((unused)) - -/// \page pk_errors PK API and Kernel Error Handling -/// -/// Error checking in the PK API consumes a significant amount of code space. -/// Approximately 20% of the object code in the PPC405 port is devoted to -/// error checking. Presumably a like amount of time overhead is also added to -/// PK API calls by this checking. -/// -/// API error checking can be disabled to save space and time in the kernel. -/// API errors can also be configured to cause kernel panics, allowing -/// applications to be coded without the overhead of error checking but still -/// providing an escape in the event of application errors or (unlikely) -/// hardware failures. The PK default is to check for API errors and kernel -/// invariants, and panic should errors occur. -/// -/// PK follows the Unix convention that a successful call of an API returns 0 -/// (PK_OK), but returns a negative code in the event of failure, or to -/// provide further information. The error codes are all defined as manifest -/// constants. -/// -/// Some negative codes returned by PK APIs are not considered errors. These -/// conditions are always checked, never cause a panic if they occur, and -/// their interpretation is always left to the application. See the detailed -/// documentation for each API for lists of error and non-error codes returned -/// by the API. -/// -/// There are three configuration options that control error handling in the -/// PK API and kernel: -/// -/// \c PK_ERROR_CHECK_API -/// -/// \arg \b 0 - No PK API error checking. APIs that potentially return error -/// codes will always return 0 (PK_OK) instead of an error code. Those -/// APIs that return negative codes that are not errors (see Table 1.5) -/// always return the negative non-error codes when appropriate. -/// -/// \arg \b 1 - (Default) All PK API errors are checked. The behavior in -/// the event of an error is defined by the configuration option -/// PK_ERROR_PANIC. -/// -/// \c PK_ERROR_CHECK_KERNEL -/// -/// \arg \b 0 - No kernel invariant error checking is done. -/// -/// \arg \b 1 - (Default) Selected kernel invariants are checked. The overhead -/// for these checks should be minimal. -/// -/// \c PK_ERROR_PANIC -/// -/// \arg \b 0 - PK API calls return negative error codes in the event of -/// errors. Note that PK kernel invariants always cause a panic if -/// violations occur. -/// -/// \arg \b 1 - (Default) In the event of errors PK APIs invoke PK_PANIC(code), -/// where code is a positive error code. Kernel invariant checks always -/// cause a panic if violations are detected. - -#endif /* __ASSEMBLER__ */ - -#endif /* __PK_API_H__ */ |