summaryrefslogtreecommitdiffstats
path: root/src/ssx/ssx/ssx_api.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssx/ssx/ssx_api.h')
-rwxr-xr-xsrc/ssx/ssx/ssx_api.h888
1 files changed, 888 insertions, 0 deletions
diff --git a/src/ssx/ssx/ssx_api.h b/src/ssx/ssx/ssx_api.h
new file mode 100755
index 0000000..c9657e4
--- /dev/null
+++ b/src/ssx/ssx/ssx_api.h
@@ -0,0 +1,888 @@
+#ifndef __SSX_API_H__
+#define __SSX_API_H__
+
+// $Id: ssx_api.h,v 1.2 2014/02/03 01:30:44 daviddu Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_api.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ssx_api.h
+/// \brief Macros and declarations for the SSX API.
+
+// Basic constants
+
+/// Although the number of threads is defined as a manifest constant,
+/// numerous parts of the SSX code assume this definition. The number of
+/// supported threads _can not_ be changed simply by changing this constant.
+
+#define SSX_THREADS 32
+
+#define SSX_IDLE_THREAD_PRIORITY SSX_THREADS
+
+// Interrupt API
+
+#define SSX_NONCRITICAL 0
+#define SSX_CRITICAL 1
+#define SSX_SUPERCRITICAL 2
+
+#define SSX_IRQ_POLARITY_ACTIVE_LOW 0
+#define SSX_IRQ_POLARITY_ACTIVE_HIGH 1
+
+#define SSX_IRQ_TRIGGER_LEVEL_SENSITIVE 0
+#define SSX_IRQ_TRIGGER_EDGE_SENSITIVE 1
+
+// API return codes
+
+#define SSX_OK 0
+#define SSX_ILLEGAL_CONTEXT_CRITICAL_INTERRUPT 0x00779001
+#define SSX_ILLEGAL_CONTEXT_THREAD_CONTEXT 0x00779002
+#define SSX_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT 0x00779003
+#define SSX_ILLEGAL_CONTEXT_THREAD 0x00779004
+#define SSX_ILLEGAL_CONTEXT_TIMER 0x00779005
+#define SSX_ILLEGAL_CONTEXT_PPC405_CACHE 0x00779006
+#define SSX_INVALID_THREAD_AT_RESUME1 0x00779007
+#define SSX_INVALID_THREAD_AT_RESUME2 0x00779008
+#define SSX_INVALID_THREAD_AT_SUSPEND1 0x00779009
+#define SSX_INVALID_THREAD_AT_SUSPEND2 0x0077900a
+#define SSX_INVALID_THREAD_AT_DELETE 0x0077900b
+#define SSX_INVALID_THREAD_AT_INFO 0x0077900c
+#define SSX_INVALID_THREAD_AT_CHANGE 0x0077900d
+#define SSX_INVALID_THREAD_AT_SWAP1 0x0077900e
+#define SSX_INVALID_THREAD_AT_SWAP2 0x0077900f
+#define SSX_INVALID_THREAD_AT_CREATE 0x00779010
+#define SSX_INVALID_SEMAPHORE_AT_POST 0x00779011
+#define SSX_INVALID_SEMAPHORE_AT_PEND 0x00779012
+#define SSX_INVALID_SEMAPHORE_AT_RELEASE 0x00779013
+#define SSX_INVALID_SEMAPHORE_AT_INFO 0x00779014
+#define SSX_INVALID_SEMAPHORE_AT_CREATE 0x00779015
+#define SSX_INVALID_TIMER_AT_SCHEDULE 0x00779016
+#define SSX_INVALID_TIMER_AT_CANCEL 0x00779017
+#define SSX_INVALID_TIMER_AT_INFO 0x00779018
+#define SSX_INVALID_TIMER_AT_CREATE 0x00779019
+#define SSX_INVALID_ARGUMENT_IRQ_SETUP 0x0077901a
+#define SSX_INVALID_ARGUMENT_IRQ_HANDLER 0x0077901b
+#define SSX_INVALID_ARGUMENT_INTERRUPT 0x00779024
+#define SSX_INVALID_ARGUMENT_CONTEXT_SET 0x00779025
+#define SSX_INVALID_ARGUMENT_CONTEXT_GET 0x00779026
+#define SSX_INVALID_ARGUMENT_PPC405_FIT 0x00779027
+#define SSX_INVALID_ARGUMENT_PPC405_WATCHDOG 0x00779028
+#define SSX_INVALID_ARGUMENT_INIT 0x00779029
+#define SSX_INVALID_ARGUMENT_SEMAPHORE 0x0077902a
+#define SSX_INVALID_ARGUMENT_THREAD_CHANGE 0x0077902b
+#define SSX_INVALID_ARGUMENT_THREAD_PRIORITY 0x0077902c
+#define SSX_INVALID_ARGUMENT_THREAD1 0x0077902d
+#define SSX_INVALID_ARGUMENT_THREAD2 0x0077902e
+#define SSX_INVALID_ARGUMENT_THREAD3 0x0077902f
+#define SSX_STACK_OVERFLOW 0x00779030
+#define SSX_TIMER_ACTIVE 0x00779031
+#define SSX_TIMER_NOT_ACTIVE 0x00779032
+#define SSX_PRIORITY_IN_USE_AT_RESUME 0x00779033
+#define SSX_PRIORITY_IN_USE_AT_CHANGE 0x00779034
+#define SSX_PRIORITY_IN_USE_AT_SWAP 0x00779035
+#define SSX_SEMAPHORE_OVERFLOW 0x00779036
+#define SSX_SEMAPHORE_PEND_NO_WAIT 0x00779037
+#define SSX_SEMAPHORE_PEND_TIMED_OUT 0x00779038
+#define SSX_SEMAPHORE_PEND_WOULD_BLOCK 0x00779039
+#define SSX_INVALID_DEQUE_SENTINEL 0x0077903a
+#define SSX_INVALID_DEQUE_ELEMENT 0x0077903b
+#define SSX_INVALID_OBJECT 0x0077903c
+
+// Kernel panics
+
+#define SSX_NO_TIMER_SUPPORT 0x0077903d
+#define SSX_START_THREADS_RETURNED 0x0077903e
+#define SSX_UNIMPLEMENTED 0x0077903f
+#define SSX_SCHEDULING_INVARIANT 0x00779040
+#define SSX_TIMER_HANDLER_INVARIANT 0x00779041
+#define SSX_THREAD_TIMEOUT_STATE 0x00779045
+
+
+/// \defgroup ssx_thread_states SSX Thread States
+///
+/// Threads are created in the state SSX_THREAD_STATE_SUSPENDED_RUNNABLE.
+/// When the thread is mapped it transitions to state SSX_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 SSX_THREAD_STATE_SUSPENDED_BLOCKED. For
+/// all threads the reason for blockage is detailed in the \a flags field of
+/// the thread; See \ref ssx_thread_flags. SSX_THREAD_STATE_DELETED and
+/// SSX_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 SSX semaphore as a thread barrier, as it supports a non-iterative
+/// implementation of ssx_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 SSX_THREAD_STATE_SUSPENDED_RUNNABLE 1
+#define SSX_THREAD_STATE_MAPPED 2
+#define SSX_THREAD_STATE_SUSPENDED_BLOCKED 3
+#define SSX_THREAD_STATE_COMPLETED 4
+#define SSX_THREAD_STATE_DELETED 5
+
+/// @}
+
+
+/// \defgroup ssx_thread_flags SSX Thread Flags
+///
+/// The \a flag field of the thread extends the information contained in the
+/// \a state field; See \ref ssx_thread_states. Blocked threads will show
+/// SSX_THREAD_FLAG_SEMAPHORE_PEND, SSX_THREAD_FLAG_TIMER_PEND or both (if
+/// blocked on a semaphore with timeout). The flag SSX_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 SSX_THREAD_FLAG_SEMAPHORE_PEND and/or SSX_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
+/// ssx_semaphore_release_all() as explained in \ref ssx_thread_states.
+///
+/// @{
+
+#define SSX_THREAD_FLAG_SEMAPHORE_PEND 0x1
+#define SSX_THREAD_FLAG_TIMER_PEND 0x2
+#define SSX_THREAD_FLAG_TIMED_OUT 0x4
+
+/// @}
+
+
+// Critical Sections
+
+/// Enter a critical section of a given priority, saving the current machine
+/// context.
+
+#define ssx_critical_section_enter(priority, pctx) \
+ ssx_interrupt_disable(priority, pctx)
+
+/// Exit a critical section by restoring the previous machine context.
+
+#define ssx_critical_section_exit(pctx) \
+ ssx_machine_context_set(pctx)
+
+
+/// Execute a statement atomically, in a particular interrupt priority
+/// context.
+
+#define SSX_ATOMIC(priority, stmt) \
+ do { \
+ SsxMachineContext __ctx; \
+ ssx_critical_section_enter((priority), &__ctx); \
+ stmt; \
+ ssx_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 SSX_ERROR_CHECK_API
+#define SSX_ERROR_CHECK_API 1
+#endif
+
+/// Control whether API errors cause kernel panics or return negative error
+/// codes.
+///
+/// This selection is only valid if \c SSX_ERROR_CHECK_API is defined
+/// non-0. This definition can be overriden by the application.
+
+#ifndef SSX_ERROR_PANIC
+#define SSX_ERROR_PANIC 1
+#endif
+
+/// Control whether or not the SSX kernel checks key invariants.
+///
+/// Violations of kernel invariants always cause kernel panics. This
+/// definition can be overriden by the application.
+
+#ifndef SSX_ERROR_CHECK_KERNEL
+#define SSX_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 SsxTimebase. This definition can be
+/// overridden by the application.
+
+#ifndef SSX_TIME_INTERVAL_TYPE
+#define SSX_TIME_INTERVAL_TYPE uint32_t
+#endif
+
+/// Provide support for the SsxTimer APIs in addition to the default
+/// initerrupt APIs. This definition can be overridden by the application.
+
+#ifndef SSX_TIMER_SUPPORT
+#define SSX_TIMER_SUPPORT 1
+#endif
+
+/// Provide support for the all SSX APIs. Thread support requires/implies
+/// support for time services and semaphores. This definition can be
+/// overridden by the application.
+
+#ifndef SSX_THREAD_SUPPORT
+#define SSX_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 ssx_initialize(). Thread stacks are prepatterned during
+/// \c ssx_thread_create().
+///
+/// 2 : (\b Default - Currently Unimplemented) In addition to prepatterning,
+/// stack utilization is computed at the exit of context switches and
+/// noncritical 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 SSX_STACK_CHECK
+#define SSX_STACK_CHECK 1
+#endif
+
+/// A hook for main()
+///
+/// This hook macro is expanded in the body of __ssx_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
+/// ssx_app_cfg.h. The SSX_MAIN_HOOK will run on the stack of main().
+
+#ifndef SSX_MAIN_HOOK
+#define SSX_MAIN_HOOK do {} while (0)
+#endif
+
+/// A hook for ssx_start_threads()
+///
+/// This hook macro is expanded in the call-tree of ssx_start_threads() before
+/// threads are actually started. The application can redefine this hook
+/// macro in (or in headers referred to in) the application header
+/// ssx_app_cfg.h.
+///
+/// The SSX_START_THREADS_HOOK runs as a pseudo-interrupt handler on the
+/// noncritical interrupt stack, with noncritical interrupts disabled.
+
+#ifndef SSX_START_THREADS_HOOK
+#define SSX_START_THREADS_HOOK do {} while (0)
+#endif
+
+/// The maximum value of the \c SsxTimebase type.
+
+#define SSX_TIMEBASE_MAX ((SsxTimebase)-1)
+
+/// A special value that specifies that the timebase will not be reset during
+/// ssx_init().
+
+#define SSX_TIMEBASE_CONTINUES SSX_TIMEBASE_MAX
+
+/// By convention, a timeout value indicating 'no waiting' in a call of \c
+/// ssx_semaphore_pend().
+
+#define SSX_NO_WAIT 0
+
+/// By convention, a timeout value indicating 'wait forever' in a call of \c
+/// ssx_semaphore_pend().
+
+#define SSX_WAIT_FOREVER ((SsxInterval)-1)
+
+/// The SSX timebase frequency in Hz
+///
+/// Earlier version of SSX defined the timbase frequency as a preprocessor
+/// macro. Now, the timebase frequency is specified as a parameter of the
+/// ssx_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 SSX_TIMEBASE_FREQUENCY_HZ __ssx_timebase_frequency_hz
+
+/// Convert a time in integral seconds to a time interval - overflows are
+/// ignored. The application can redefine this macro.
+
+#ifndef SSX_SECONDS
+#define SSX_SECONDS(s) ((SsxInterval)(__ssx_timebase_frequency_hz * (SsxInterval)(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 SSX_MILLISECONDS
+#define SSX_MILLISECONDS(m) ((SsxInterval)(__ssx_timebase_frequency_khz * (SsxInterval)(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 SSX_MICROSECONDS
+#define SSX_MICROSECONDS(u) ((SsxInterval)(__ssx_timebase_frequency_mhz * (SsxInterval)(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 SSX_NANOSECONDS
+#define SSX_NANOSECONDS(n) \
+ ((SsxInterval)((__ssx_timebase_frequency_mhz * (SsxInterval)(n)) / 1000))
+#endif
+
+
+// Application and kernel tracing. Tracing can only be enabled if the port
+// defines the trace macros in that case.
+
+/// Enable SSX application tracing
+#ifndef SSX_TRACE_ENABLE
+#define SSX_TRACE_ENABLE 0
+#endif
+
+/// Enable SSX kernel tracing
+#ifndef SSX_KERNEL_TRACE_ENABLE
+#define SSX_KERNEL_TRACE_ENABLE 0
+#endif
+
+#if !SSX_TRACE_ENABLE
+#define SSX_TRACE(event)
+#endif
+
+#if !SSX_KERNEL_TRACE_ENABLE
+
+#define SSX_TRACE_THREAD_SLEEP(priority)
+#define SSX_TRACE_THREAD_WAKEUP(priority)
+#define SSX_TRACE_THREAD_SEMAPHORE_PEND(priority)
+#define SSX_TRACE_THREAD_SEMAPHORE_POST(priority)
+#define SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT(priority)
+#define SSX_TRACE_THREAD_SUSPENDED(priority)
+#define SSX_TRACE_THREAD_DELETED(priority)
+#define SSX_TRACE_THREAD_COMPLETED(priority)
+#define SSX_TRACE_THREAD_MAPPED_RUNNABLE(priority)
+#define SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND(priority)
+#define SSX_TRACE_THREAD_MAPPED_SLEEPING(priority)
+
+
+#endif /* SSX_KERNEL_TRACE_ENABLE */
+
+
+#ifndef __ASSEMBLER__
+
+#include <stddef.h>
+#include <stdint.h>
+
+/// The timebase frequency in Hz; A parameter to ssx_initialize()
+extern uint32_t __ssx_timebase_frequency_hz;
+
+/// The timebase frequency in KHz
+extern uint32_t __ssx_timebase_frequency_khz;
+
+/// The timebase frequency in Mhz
+extern uint32_t __ssx_timebase_frequency_mhz;
+
+
+typedef unsigned long int SsxAddress;
+
+typedef uint8_t SsxThreadState;
+
+typedef uint8_t SsxThreadPriority;
+
+typedef uint8_t SsxThreadFlags;
+
+typedef uint32_t SsxSemaphoreCount;
+
+typedef uint64_t SsxTimebase;
+
+typedef SSX_TIME_INTERVAL_TYPE SsxInterval;
+
+#include "ssx_port_types.h"
+
+typedef struct {
+
+ /// A priority queue of threads pending on the semaphore.
+ SsxThreadQueue pending_threads;
+
+ /// The current semaphore count.
+ SsxSemaphoreCount count;
+
+ /// The maximum allowable count - for error checking.
+ SsxSemaphoreCount max_count;
+
+} SsxSemaphore;
+
+
+/// Compile-time initialize an SsxSemaphore structure
+///
+/// This low-level macro creates a structure initializatin of an SsxSemaphore
+/// structure. This can be used for example to create compile-time initialized
+/// arrays of semaphores.
+#define SSX_SEMAPHORE_INITIALIZATION(_initial_count, _max_count) \
+ {.pending_threads = 0, \
+ .count = (_initial_count), \
+ .max_count = (_max_count)}
+
+
+/// Declare and initialize a semaphore
+#define SSX_SEMAPHORE(sem, initial_count, max_count) \
+ SsxSemaphore sem = SSX_SEMAPHORE_INITIALIZATION(initial_count, max_count)
+
+
+/// 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 SSX API assumes that
+/// queueable structures will be defined with an SsxDeque 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 SsxDeque and vice-versa.
+
+typedef struct SsxDeque {
+
+ /// Pointer to the head or the next element in a deque.
+ ///
+ /// When an SsxDeque 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 SsxDeque. By convention the condition (\a next ==
+ /// 0) is used to indicate that a queue element is not enqueued.
+ struct SsxDeque* 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 SsxDeque* previous;
+
+} SsxDeque;
+
+
+typedef void (*SsxTimerCallback)(void *);
+
+#define SSX_TIMER_CALLBACK(callback) void callback(void *)
+
+struct SsxTimer;
+
+/// The SSX timer object
+
+typedef struct SsxTimer {
+
+ /// The time queue management pointers
+ ///
+ /// This pointer container is defined as the first element of the
+ /// structure to allow the SsxTimer to be cast to an SsxDeque and
+ /// vice-versa.
+ SsxDeque deque;
+
+ /// The absolute timeout of the timer.
+ SsxTimebase timeout;
+
+ /// The timer period
+ ///
+ /// If not 0, then this is a periodic timer and it will be automatically
+ /// rescheduled in absolute time from the previous timeout.
+ SsxInterval period;
+
+ /// The timer callback
+ ///
+ /// For SSX thread timers used to implement Sleep and semaphore pend
+ /// timeouts this field is initialized to __ssx_thread_timeout().
+ SsxTimerCallback callback;
+
+ /// Private data passed to the callback.
+ ///
+ /// For SSX thread timers used to implement Sleep and semaphore pend this
+ /// field is initialized to a pointer to the thread.
+ void *arg;
+
+ /// Options for timer processing; See \ref ssx_timer_options
+ uint8_t options;
+
+} SsxTimer;
+
+/// \defgroup ssx_timer_options SSX Timer Options
+/// @{
+
+/// Allow interrupt preemption during the callback
+///
+/// This is the normal mode for SsxTimer objects scheduled by SSX kernal
+/// mechanisms. The timer callbacks effectively run as if inside a
+/// highest-priority thread, allowing other interrupts to preempt them.
+#define SSX_TIMER_CALLBACK_PREEMPTIBLE 0x1
+
+/// @}
+
+
+// Threads
+
+typedef void (*SsxThreadRoutine)(void *arg);
+
+#define SSX_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.
+ SsxAddress 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
+ /// SsxAddress) from the thread pointer.
+ SsxAddress stack_limit;
+
+ /// This is the original base of the stack.
+ /// Assembler code expects this to always be at address offset 2 * (sizeof
+ /// SsxAddress) from the thread pointer.
+ SsxAddress stack_base;
+
+ /// If the thread is blocked on a semaphore, then this is the semaphore the
+ /// thread is blocked on.
+ SsxSemaphore *semaphore;
+
+ /// The thread priority.
+ SsxThreadPriority priority;
+
+ /// The thread state; See \ref ssx_thread_states
+ SsxThreadState state;
+
+ /// Thread flags; See \ref ssx_thread_flags
+ SsxThreadFlags flags;
+
+ /// The timer structure handles Sleep and blocking on a semaphore with
+ /// timeout.
+ SsxTimer timer;
+
+} SsxThread;
+
+
+// Initialization APIs
+
+int
+ssx_initialize(SsxAddress noncritical_stack,
+ size_t noncritical_stack_size,
+ SsxAddress critical_stack,
+ size_t critical_stack_size,
+ SsxTimebase initial_timebase,
+ uint32_t timebase_frequency_hz);
+
+
+// Timebase APIs
+
+SsxTimebase
+ssx_timebase_get(void);
+
+void
+ssx_timebase_set(SsxTimebase timebase);
+
+// Interrupt preemption APIs
+
+int
+ssx_interrupt_preemption_enable(void);
+
+int
+ssx_interrupt_preemption_disable(void);
+
+// Timer APIs
+
+int
+ssx_timer_create(SsxTimer *timer,
+ SsxTimerCallback callback,
+ void *arg);
+
+int
+ssx_timer_create_nonpreemptible(SsxTimer *timer,
+ SsxTimerCallback callback,
+ void *arg);
+
+int
+ssx_timer_schedule_absolute(SsxTimer *timer,
+ SsxTimebase time,
+ SsxInterval period);
+
+int
+ssx_timer_schedule(SsxTimer *timer,
+ SsxInterval interval,
+ SsxInterval period);
+
+int
+ssx_timer_cancel(SsxTimer *timer);
+
+int
+ssx_timer_info_get(SsxTimer *timer,
+ SsxTimebase *timeout,
+ int *active);
+
+// Thread APIs
+
+int
+ssx_thread_create(SsxThread *thread,
+ SsxThreadRoutine thread_routine,
+ void *arg,
+ SsxAddress stack,
+ size_t stack_size,
+ SsxThreadPriority priority);
+
+int
+ssx_start_threads(void);
+
+int
+ssx_thread_resume(SsxThread *thread);
+
+int
+ssx_thread_suspend(SsxThread *thread);
+
+int
+ssx_thread_delete(SsxThread *thread);
+
+int
+ssx_complete(void);
+
+int
+ssx_sleep_absolute(SsxTimebase time);
+
+int
+ssx_sleep(SsxInterval interval);
+
+int
+ssx_thread_info_get(SsxThread *thread,
+ SsxThreadState *state,
+ SsxThreadPriority *priority,
+ int *runnable);
+
+int
+ssx_thread_priority_change(SsxThread *thread,
+ SsxThreadPriority new_priority,
+ SsxThreadPriority *old_priority);
+
+int
+ssx_thread_at_priority(SsxThreadPriority priority,
+ SsxThread **thread);
+
+int
+ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b);
+
+
+// Semaphore APIs
+
+int
+ssx_semaphore_create(SsxSemaphore *semaphore,
+ SsxSemaphoreCount initial_count,
+ SsxSemaphoreCount max_count);
+
+int
+ssx_semaphore_post(SsxSemaphore *semaphore);
+
+int
+ssx_semaphore_pend(SsxSemaphore *semaphore,
+ SsxInterval timeout);
+
+int
+ssx_semaphore_release_all(SsxSemaphore *semaphore);
+
+
+int
+ssx_semaphore_info_get(SsxSemaphore *semaphore,
+ SsxSemaphoreCount *count,
+ int *pending);
+
+void
+ssx_semaphore_post_handler(void *arg,
+ SsxIrqId irq,
+ int priority);
+
+// Misc. APIs
+
+void
+ssx_halt() __attribute__ ((noreturn));
+
+// Deque APIs
+
+int
+ssx_deque_sentinel_create(SsxDeque *deque);
+
+int
+ssx_deque_element_create(SsxDeque *element);
+
+
+/// Check for an empty SsxDeque
+///
+/// \param deque The sentinel node of a deque
+///
+/// \retval 0 The SsxDeque is not empty
+///
+/// \retval 1 The SsxDeque is empty
+
+static inline int
+ssx_deque_is_empty(SsxDeque *deque)
+{
+ return (deque == deque->next);
+}
+
+
+/// Check if an SsxDeque element is currently enqueued
+///
+/// \param element Typically the SsxDeque object of a queable structure
+///
+/// \retval 0 The element is not currently enqueued
+///
+/// \retval 1 The element is currently enqueued
+
+static inline int
+ssx_deque_is_queued(SsxDeque *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 SsxDeque 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
+ssx_deque_push_back(SsxDeque *deque, SsxDeque *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 SsxDeque 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
+ssx_deque_push_front(SsxDeque *deque, SsxDeque *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 SsxDeque 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 SsxDeque *
+ssx_deque_pop_front(SsxDeque *deque)
+{
+ SsxDeque *head;
+
+ if (ssx_deque_is_empty(deque)) {
+ return 0;
+ } else {
+ head = (SsxDeque *)(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 SsxDeque 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
+ssx_deque_delete(SsxDeque *element)
+{
+ element->previous->next = element->next;
+ element->next->previous = element->previous;
+ element->next = 0;
+}
+
+
+/// Cast a pointer to another type, in a way that won't cause warnings
+
+#define SSX_CAST_POINTER(t, p) ((t)((SsxAddress)(p)))
+
+
+/// \page ssx_errors SSX API and Kernel Error Handling
+///
+/// Error checking in the SSX 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
+/// SSX 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 SSX default is to check for API errors and kernel
+/// invariants, and panic should errors occur.
+///
+/// SSX follows the Unix convention that a successful call of an API returns 0
+/// (SSX_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 SSX 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
+/// SSX API and kernel:
+///
+/// \c SSX_ERROR_CHECK_API
+///
+/// \arg \b 0 - No SSX API error checking. APIs that potentially return error
+/// codes will always return 0 (SSX_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 SSX API errors are checked. The behavior in
+/// the event of an error is defined by the configuration option
+/// SSX_ERROR_PANIC.
+///
+/// \c SSX_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 SSX_ERROR_PANIC
+///
+/// \arg \b 0 - SSX API calls return negative error codes in the event of
+/// errors. Note that SSX kernel invariants always cause a panic if
+/// violations occur.
+///
+/// \arg \b 1 - (Default) In the event of errors SSX APIs invoke SSX_PANIC(code),
+/// where code is a positive error code. Kernel invariant checks always
+/// cause a panic if violations are detected.
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __SSX_API_H__ */
OpenPOWER on IntegriCloud