diff --git a/mtapi_c/include/embb/mtapi/c/mtapi.h b/mtapi_c/include/embb/mtapi/c/mtapi.h index 380c26f..1165f65 100644 --- a/mtapi_c/include/embb/mtapi/c/mtapi.h +++ b/mtapi_c/include/embb/mtapi/c/mtapi.h @@ -621,6 +621,27 @@ struct mtapi_worker_priority_entry_struct { */ typedef struct mtapi_worker_priority_entry_struct mtapi_worker_priority_entry_t; +#ifdef EMBB_HARD_REALTIME +/** + * Describes the scheduling mode which is used for the tasks of a single node. + */ +enum embb_mtapi_scheduler_mode_enum { + // Victim Higher Priority First. Steal if at least one local queue is empty. + WORK_STEAL_VHPF = 0, + // Local First. Steal if all local queues are empty. + WORK_STEAL_LF = 1, + // Global EDF. No work stealing + GLOBAL_EDF = 2, + + NUM_SCHEDULER_MODES +}; + +/** + * Describes the scheduling mode which is used for the tasks of a single node. + */ +typedef enum embb_mtapi_scheduler_mode_enum embb_mtapi_scheduler_mode_t; +#endif /*EMBB_HARD_REALTIME*/ + /** * Node attributes, to be extended for implementation specific attributes */ @@ -647,6 +668,9 @@ enum mtapi_node_attributes_enum { allowed by the node */ MTAPI_NODE_REUSE_MAIN_THREAD, /**< reuse main thread as worker */ MTAPI_NODE_WORKER_PRIORITIES /**< set worker priorites */ +#ifdef EMBB_HARD_REALTIME + ,MTAPI_NODE_SCHEDULER_MODE /**< set mode of nodes scheduler */ +#endif /*EMBB_HARD_REALTIME*/ }; /** size of the \a MTAPI_NODE_CORE_AFFINITY attribute */ #define MTAPI_NODE_CORE_AFFINITY_SIZE sizeof(embb_core_set_t) @@ -674,6 +698,11 @@ enum mtapi_node_attributes_enum { #define MTAPI_NODE_REUSE_MAIN_THREAD_SIZE sizeof(mtapi_boolean_t) /** size of the \a MTAPI_NODE_WORKER_PRIORITIES attribute */ #define MTAPI_NODE_WORKER_PRIORITIES_SIZE 0 +#ifdef EMBB_MTAPI_HARD_REALTIME +/** size of the \a MTAPI_NODE_SCHEDULER_MODE attribute */ +#define MTAPI_NODE_SCHEDULER_MODE sizeof(embb_mtapi_scheduler_mode_t) +#endif /*EMBB_MTAPI_HARD_REALTIME*/ + /* example attribute value */ #define MTAPI_NODE_TYPE_SMP 1 @@ -797,6 +826,10 @@ struct mtapi_node_attributes_struct { mtapi_worker_priority_entry_t * worker_priorities; /**< stores MTAPI_NODE_WORKER_PRIORITIES */ +#ifdef EMBB_HARD_REALTIME + embb_mtapi_scheduler_mode_t scheduler_mode; + /**< stores MTAPI_NODE_SCHEDULER_MODE */ +#endif /*EMBB_HARD_REALTIME*/ }; /** @@ -1049,6 +1082,9 @@ extern mtapi_group_hndl_t MTAPI_GROUP_NONE; #define MTAPI_NODE_MAX_JOBS_DEFAULT 256 #define MTAPI_NODE_MAX_ACTIONS_PER_JOB_DEFAULT 4 #define MTAPI_NODE_MAX_PRIORITIES_DEFAULT 4 +#ifdef EMBB_HARD_REALTIME +#define MTAPI_NODE_SCHEDULER_MODE_DEFAULT WORK_STEAL_VHPF +#endif /*EMBB_HARD_REALTIME*/ #define MTAPI_JOB_ID_INVALID 0 #define MTAPI_DOMAIN_ID_INVALID 0 diff --git a/mtapi_c/src/embb_mtapi_node_t.c b/mtapi_c/src/embb_mtapi_node_t.c index b3b3c80..ac0b3d9 100644 --- a/mtapi_c/src/embb_mtapi_node_t.c +++ b/mtapi_c/src/embb_mtapi_node_t.c @@ -137,7 +137,12 @@ void mtapi_initialize( if (local_status == MTAPI_SUCCESS) { /* initialize scheduler for local node */ +#ifdef EMBB_HARD_REALTIME + node->scheduler = embb_mtapi_scheduler_new( + node->attributes.scheduler_mode); +#else node->scheduler = embb_mtapi_scheduler_new(); +#endif /*EMBB_HARD_REALTIME*/ if (MTAPI_NULL != node->scheduler) { /* fill information structure */ node->info.mtapi_version = 0x1000; // mtapi version 1.0 diff --git a/mtapi_c/src/embb_mtapi_scheduler_t.c b/mtapi_c/src/embb_mtapi_scheduler_t.c index 4da7031..3127283 100644 --- a/mtapi_c/src/embb_mtapi_scheduler_t.c +++ b/mtapi_c/src/embb_mtapi_scheduler_t.c @@ -584,6 +584,23 @@ void embb_mtapi_scheduler_finalize(embb_mtapi_scheduler_t * that) { } } +#ifdef EMBB_HARD_REALTIME +embb_mtapi_scheduler_t * embb_mtapi_scheduler_new( + embb_mtapi_scheduler_mode_t mode) { + embb_mtapi_scheduler_t * that = + (embb_mtapi_scheduler_t*)embb_mtapi_alloc_allocate( + sizeof(embb_mtapi_scheduler_t)); + if (MTAPI_NULL != that) { + if (MTAPI_FALSE == embb_mtapi_scheduler_initialize_with_mode (that, mode)) { + /* on error delete and return MTAPI_NULL */ + embb_mtapi_scheduler_finalize(that); + embb_mtapi_scheduler_delete(that); + return MTAPI_NULL; + } + } + return that; +} +#else embb_mtapi_scheduler_t * embb_mtapi_scheduler_new() { embb_mtapi_scheduler_t * that = (embb_mtapi_scheduler_t*)embb_mtapi_alloc_allocate( @@ -598,6 +615,7 @@ embb_mtapi_scheduler_t * embb_mtapi_scheduler_new() { } return that; } +#endif /*EMBB_HARD_REALTIME*/ void embb_mtapi_scheduler_delete(embb_mtapi_scheduler_t * that) { assert(MTAPI_NULL != that); diff --git a/mtapi_c/src/embb_mtapi_scheduler_t.h b/mtapi_c/src/embb_mtapi_scheduler_t.h index a4b7b8a..9d9dfed 100644 --- a/mtapi_c/src/embb_mtapi_scheduler_t.h +++ b/mtapi_c/src/embb_mtapi_scheduler_t.h @@ -47,6 +47,7 @@ typedef int (embb_mtapi_scheduler_worker_func_t)(void * args); /* ---- CLASS DECLARATION -------------------------------------------------- */ +#ifndef EMBB_HARD_REALTIME /** * \internal * Scheduler mode type @@ -58,13 +59,9 @@ enum embb_mtapi_scheduler_mode_enum { WORK_STEAL_VHPF = 0, // Local First. Steal if all local queues are empty. WORK_STEAL_LF = 1, -#ifdef EMBB_HARD_REALTIME - // Global EDF. No work stealing - GLOBAL_EDF = 2, -#endif /*EMBB_HARD_REALTIME*/ - NUM_SCHEDULER_MODES }; +#endif /*EMBB_MTAPI_HARD_REALTIME*/ /** * Scheduler mode type. @@ -150,13 +147,23 @@ void embb_mtapi_scheduler_execute_task_or_yield( embb_mtapi_scheduler_t * that, embb_mtapi_node_t * node, embb_mtapi_thread_context_t * thread_context); +#ifdef EMBB_HARD_REALTIME /** * operator new. * \memberof embb_mtapi_scheduler_struct * \returns pointer to the scheduler oder MTAPI_NULL on error */ +embb_mtapi_scheduler_t * embb_mtapi_scheduler_new( + embb_mtapi_scheduler_mode_t mode); +#else +/** + * operator new. + * \memberof embb_mtapi_scheduler_struct + * \returns pointer to the scheduler oder MTAPI_NULL on error + */ embb_mtapi_scheduler_t * embb_mtapi_scheduler_new(); +#endif /*EMBB_HARD_REALTIME*/ /** * operator delete. diff --git a/mtapi_c/src/mtapi_node_attributes_t.c b/mtapi_c/src/mtapi_node_attributes_t.c index b7a99cb..33d253b 100644 --- a/mtapi_c/src/mtapi_node_attributes_t.c +++ b/mtapi_c/src/mtapi_node_attributes_t.c @@ -54,6 +54,9 @@ void mtapi_nodeattr_init( attributes->max_priorities = MTAPI_NODE_MAX_PRIORITIES_DEFAULT; attributes->reuse_main_thread = MTAPI_FALSE; attributes->worker_priorities = NULL; +#ifdef EMBB_HARD_REALTIME + attributes->scheduler_mode = MTAPI_NODE_SCHEDULER_MODE_DEFAULT; +#endif /*EMBB_HARD_REALTIME*/ embb_core_set_init(&attributes->core_affinity, 1); attributes->num_cores = embb_core_set_count(&attributes->core_affinity); @@ -155,6 +158,14 @@ void mtapi_nodeattr_set( attributes->worker_priorities = (mtapi_worker_priority_entry_t*)attribute; break; +#ifdef EMBB_HARD_REALTIME + + case MTAPI_NODE_SCHEDULER_MODE: + // TODO error checking missing + local_status = MTAPI_SUCCESS; + attributes->scheduler_mode = *(embb_mtapi_scheduler_mode_t*)attribute; + break; +#endif /*EMBB_HARD_REALTIME*/ default: /* attribute unknown */ diff --git a/mtapi_cpp/include/embb/mtapi/node_attributes.h b/mtapi_cpp/include/embb/mtapi/node_attributes.h index 9c6c0ab..7a1119a 100644 --- a/mtapi_cpp/include/embb/mtapi/node_attributes.h +++ b/mtapi_cpp/include/embb/mtapi/node_attributes.h @@ -232,6 +232,24 @@ class NodeAttributes { return *this; } +#ifdef EMBB_HARD_REALTIME + /** + * Sets the scheduling mode which is applied to schedule tasks on this node. + * + * \returns Reference to this object. + * \notthreadsafe + */ + NodeAttributes & SetSchedulerMode( + embb_mtapi_scheduler_mode_t value /**< The value to set. */ + ) { + mtapi_status_t status; + mtapi_nodeattr_set(&attributes_, MTAPI_NODE_SCHEDULER_MODE, + &value, sizeof(value), &status); + internal::CheckStatus(status); + return *this; + } + +#endif /*EMBB_HARD_REALTIME*/ /** * Returns the internal representation of this object. * Allows for interoperability with the C interface.