/*..........................................................................*/ void QActive_start_(QActive * const me, uint_fast8_t prio, QEvt const *qSto[], uint_fast16_t qLen, void *stkSto, uint_fast16_t stkSize, QEvt const *ie) { /* create the embOS message box for the AO */ OS_CreateMB(&me->eQueue, (OS_U16)sizeof(QEvt *), (OS_UINT)qLen, (void *)&qSto[0]); me->prio = prio; /* save the QF priority */ QF_add_(me); /* make QF aware of this active object */ QMSM_INIT(&me->super, ie); /* thake the top-most initial tran. */ QS_FLUSH(); /* flush the trace buffer to the host */ /* create an embOS task for the AO */ OS_CreateTaskEx(&me->thread, "AO", (OS_PRIO)prio, /* embOS uses the same numbering as QP */ &thread_function, (void OS_STACKPTR *)stkSto, (OS_UINT)stkSize, (OS_UINT)0, /* no AOs at the same prio */ (void *)me); }
/*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie) { int err; me->eQueue = xQueueCreate( qLen , sizeof(QEvent*) ); Q_ASSERT(me->eQueue != (void *)0); /* queue created */ me->prio = prio; /* save the QF priority */ QF_add_(me); /* make QF aware of this active object */ QF_ACTIVE_INIT_(&me->super, ie); /* execute initial transition */ QS_FLUSH(); /* flush the trace buffer to the host */ // vTaskDelay( 0x32 ); /* task is represented by its unique priority */ // me->thread = (uint8_t)(QF_MAX_ACTIVE - me->prio); /* map to OSprio. */ err= xTaskCreate( task_function, task_name[task_idx] , 0x100 * 3, me,tskIDLE_PRIORITY+me->prio, &me->thread); Q_ASSERT(me->thread != (xTaskHandle) NULL ); task_idx++; }
/*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie) { INT8U err; me->eQueue = OSQCreate((void **)qSto, qLen); Q_ASSERT(me->eQueue != (OS_EVENT *)0); /* uC/OS-II queue created */ me->prio = prio; /* save the QF priority */ QF_add_(me); /* make QF aware of this active object */ QF_ACTIVE_INIT_(&me->super, ie); /* execute initial transition */ QS_FLUSH(); /* flush the trace buffer to the host */ /* uC/OS task is represented by its unique priority */ me->thread = (uint8_t)(QF_MAX_ACTIVE - me->prio); /* map to uC/OS prio. */ err = OSTaskCreateExt(&task_function, /* the task function */ me, /* the 'pdata' parameter */ &(((OS_STK *)stkSto)[(stkSize / sizeof(OS_STK)) - 1]), /* ptos */ me->thread, /* uC/OS-II task priority */ me->thread, /* task id */ (OS_STK *)stkSto, /* pbos */ stkSize/sizeof(OS_STK), /* size of the stack in OS_STK units */ (void *)0, /* pext */ (INT16U)OS_TASK_OPT_STK_CLR); /* opt */ Q_ASSERT(err == OS_NO_ERR); /* uC/OS-II task created */ }
/* QActive functions =======================================================*/ void QActive_start_(QActive * const me, uint_fast8_t prio, QEvt const *qSto[], uint_fast16_t qLen, void *stkSto, uint_fast16_t stkSize, QEvt const *ie) { DWORD threadId; int win32Prio; void *fudgedQSto; uint_fast16_t fudgedQLen; Q_REQUIRE_ID(700, ((uint_fast8_t)0 < prio) /* priority must be in range */ && (prio <= (uint_fast8_t)QF_MAX_ACTIVE) && (qSto != (QEvt const **)0) /* queue storage must be... */ && (qLen > (uint_fast16_t)0) /* ...provided */ && (stkSto == (void *)0)); /* statck storage must NOT... * ... be provided */ me->prio = prio; /* set QF priority of this AO before adding it to QF */ QF_add_(me); /* make QF aware of this active object */ /* ignore the original storage for the event queue 'qSto' and * instead allocate an oversized "fudged" storage for the queue. * See also NOTE2 in qf_port.h. */ Q_ASSERT_ID(710, (uint32_t)qLen * QF_WIN32_FUDGE_FACTOR < USHRT_MAX); fudgedQLen = qLen * QF_WIN32_FUDGE_FACTOR; /* fudge the queue length */ fudgedQSto = calloc(fudgedQLen, sizeof(QEvt *)); /* new queue storage */ Q_ASSERT_ID(720, fudgedQSto != (void *)0); /* allocation must succeed */ QEQueue_init(&me->eQueue, (QEvt const **)fudgedQSto, fudgedQLen); /* save osObject as integer, in case it contains the Win32 priority */ win32Prio = (me->osObject != (void *)0) ? (int)me->osObject : THREAD_PRIORITY_NORMAL; /* create the Win32 "event" to throttle the AO's event queue */ me->osObject = CreateEvent(NULL, FALSE, FALSE, NULL); QMSM_INIT(&me->super, ie); /* take the top-most initial tran. */ QS_FLUSH(); /* flush the QS trace buffer to the host */ /* stack size not provided? */ if (stkSize == 0U) { stkSize = 1024U; /* NOTE: will be rounded up to the nearest page */ } /* create a Win32 thread for the AO; * The thread is created with THREAD_PRIORITY_NORMAL */ me->thread = CreateThread(NULL, stkSize, &ao_thread, me, 0, &threadId); Q_ASSERT_ID(730, me->thread != (HANDLE)0); /* thread must be created */ /* was the thread priority provided? */ if (win32Prio != 0) { SetThreadPriority(me->thread, win32Prio); } }
/*..........................................................................*/ void QActive_start_(QActive * const me, uint_fast8_t prio, QEvt const *qSto[], uint_fast16_t qLen, void *stkSto, uint_fast16_t stkSize, QEvt const *ie) { pthread_t thread; pthread_attr_t attr; struct sched_param param; /* p-threads allocate stack internally */ Q_REQUIRE_ID(600, stkSto == (void *)0); QEQueue_init(&me->eQueue, qSto, qLen); pthread_cond_init(&me->osObject, 0); me->prio = (uint8_t)prio; QF_add_(me); /* make QF aware of this active object */ QMSM_INIT(&me->super, ie); /* take the top-most initial tran. */ QS_FLUSH(); /* flush the QS trace buffer to the host */ pthread_attr_init(&attr); /* SCHED_FIFO corresponds to real-time preemptive priority-based scheduler * NOTE: This scheduling policy requires the superuser privileges */ pthread_attr_setschedpolicy(&attr, SCHED_FIFO); /* see NOTE04 */ param.sched_priority = prio + (sched_get_priority_max(SCHED_FIFO) - QF_MAX_ACTIVE - 3); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (stkSize == 0U) { /* set the allowed minimum */ stkSize = (uint_fast16_t)PTHREAD_STACK_MIN; } pthread_attr_setstacksize(&attr, (size_t)stkSize); if (pthread_create(&thread, &attr, &thread_routine, me) != 0) { /* Creating the p-thread with the SCHED_FIFO policy failed. Most * probably this application has no superuser privileges, so we just * fall back to the default SCHED_OTHER policy and priority 0. */ pthread_attr_setschedpolicy(&attr, SCHED_OTHER); param.sched_priority = 0; pthread_attr_setschedparam(&attr, ¶m); Q_ALLEGE(pthread_create(&thread, &attr, &thread_routine, me)== 0); } pthread_attr_destroy(&attr); me->thread = (uint8_t)1; }
/*..........................................................................*/ void QF_run(void) { uint8_t p; QActive *a; QEvent const *e; QF_INT_LOCK_KEY_ QF_onStartup(); /* startup callback */ for (;;) { /* the background loop */ QF_INT_LOCK_(); #if (QF_MAX_ACTIVE <= 8) if (QPSet8_notEmpty(&QF_readySet_)) { QPSet8_findMax(&QF_readySet_, p); #else if (QPSet64_notEmpty(&QF_readySet_)) { QPSet64_findMax(&QF_readySet_, p); #endif a = QF_active_[p]; QF_INT_UNLOCK_(); e = QActive_get_(a); /* get the next event for this AO */ QF_ACTIVE_DISPATCH_(&a->super, e); /* dispatch to the AO */ QF_gc(e); /* determine if event is garbage and collect it if so */ } else { #ifndef QF_INT_KEY_TYPE QF_onIdle(); /* see NOTE01 */ #else QF_onIdle(intLockKey_); /* see NOTE01 */ #endif /* QF_INT_KEY_TYPE */ } } } /*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie) { Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE) && (stkSto == (void *)0)); /* does not need per-actor stack */ (void)stkSize; /* avoid the "unused parameter" compiler warning */ QEQueue_init(&me->eQueue, qSto, (QEQueueCtr)qLen);/* initialize QEQueue */ me->prio = prio; /* set the QF priority of this active object */ QF_add_(me); /* make QF aware of this active object */ QF_ACTIVE_INIT_(&me->super, ie); /* execute initial transition */ QS_FLUSH(); /* flush the trace buffer to the host */ }
/*..........................................................................*/ void QActive_start_(QActive * const me, uint_t prio, QEvt const *qSto[], uint_t qLen, void *stkSto, uint_t stkSize, QEvt const *ie) { DWORD threadId; int p; Q_REQUIRE((qSto != (QEvt const **)0) /* queue storage must be provided */ && (stkSto == (void *)0)); /* Windows allocates stack internally */ me->prio = (uint8_t)prio; QF_add_(me); /* make QF aware of this active object */ QEQueue_init(&me->eQueue, qSto, qLen); me->osObject = CreateEvent(NULL, FALSE, FALSE, NULL); QMSM_INIT(&me->super, ie); /* execute initial transition */ if (stkSize == 0U) { /* stack size not provided? */ stkSize = 1024U; /* NOTE: will be rounded up to the nearest page */ } me->thread = CreateThread(NULL, stkSize, &thread_function, me, 0, &threadId); Q_ASSERT(me->thread != (HANDLE)0); /* thread must be created */ switch (me->prio) { /* remap QF priority to Win32 priority */ case 1: p = THREAD_PRIORITY_IDLE; break; case 2: p = THREAD_PRIORITY_LOWEST; break; case 3: p = THREAD_PRIORITY_BELOW_NORMAL; break; case (QF_MAX_ACTIVE - 1): p = THREAD_PRIORITY_ABOVE_NORMAL; break; case QF_MAX_ACTIVE: p = THREAD_PRIORITY_HIGHEST; break; default: p = THREAD_PRIORITY_NORMAL; break; } SetThreadPriority(me->thread, p); }
/*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie) { pthread_attr_t attr; struct sched_param param; Q_REQUIRE(stkSto == (void *)0); /* p-threads allocate stack internally */ QEQueue_init(&me->eQueue, qSto, (QEQueueCtr)qLen); pthread_cond_init(&me->osObject, 0); me->prio = prio; QF_add_(me); /* make QF aware of this active object */ QF_ACTIVE_INIT_(&me->super, ie); /* execute the initial transition */ QS_FLUSH(); /* flush the trace buffer to the host */ pthread_attr_init(&attr); /* SCHED_FIFO corresponds to real-time preemptive priority-based scheduler * NOTE: This scheduling policy requires the superuser privileges */ pthread_attr_setschedpolicy(&attr, SCHED_FIFO); /* see NOTE04 */ param.sched_priority = prio + (sched_get_priority_max(SCHED_FIFO) - QF_MAX_ACTIVE - 3); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(&me->thread, &attr, &thread_routine, me) != 0) { /* Creating the p-thread with the SCHED_FIFO policy failed. * Most probably this application has no superuser privileges, * so we just fall back to the default SCHED_OTHER policy * and priority 0. */ pthread_attr_setschedpolicy(&attr, SCHED_OTHER); param.sched_priority = 0; pthread_attr_setschedparam(&attr, ¶m); Q_ALLEGE(pthread_create(&me->thread, &attr, &thread_routine, me)== 0); } pthread_attr_destroy(&attr); }
/*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie) { int p; DWORD threadId; Q_REQUIRE((stkSto == (void *)0) /* Windows allocates stack internally */ && (stkSize != 0)); QEQueue_init(&me->eQueue, qSto, (QEQueueCtr)qLen); me->osObject = CreateEvent(NULL, FALSE, FALSE, NULL); me->prio = prio; QF_add_(me); /* make QF aware of this active object */ QF_ACTIVE_INIT_(&me->super, ie); /* execute initial transition */ me->thread = CreateThread(NULL, stkSize, &thread_function, me, 0, &threadId); Q_ASSERT(me->thread != (HANDLE)0); /* thread must be created */ switch (me->prio) { /* remap QF priority to Win32 priority */ case 1: p = THREAD_PRIORITY_IDLE; break; case 2: p = THREAD_PRIORITY_LOWEST; break; case 3: p = THREAD_PRIORITY_BELOW_NORMAL; break; case (QF_MAX_ACTIVE - 1): p = THREAD_PRIORITY_ABOVE_NORMAL; break; case QF_MAX_ACTIVE: p = THREAD_PRIORITY_HIGHEST; break; default: p = THREAD_PRIORITY_NORMAL; break; } SetThreadPriority(me->thread, p); }
/*..........................................................................*/ void QActive_start_(QActive * const me, uint_fast8_t prio, QEvt const *qSto[], uint_fast16_t qLen, void *stkSto, uint_fast16_t stkSize, QEvt const *ie) { /* * The following os_thread_def_AO object specifies the attributes of the * RTX thread for Active Objects. This object is allocated on the stack, * because it only serves to create the specific task for this AO. */ osThreadDef_t os_thread_def_AO; /* no stack storage because RTX pre-allocates stacks internally, * but the queue storage and size must be provided */ Q_REQUIRE_ID(510, (stkSto == (void *)0) && (qSto != (QEvt const **)0) && (qLen > (uint_fast16_t)0)); /* create the QP event queue for the AO */ QEQueue_init(&me->eQueue, qSto, qLen); me->prio = prio; /* save the QF priority */ QF_add_(me); /* make QF aware of this active object */ QMSM_INIT(&me->super, ie); /* thake the top-most initial tran. */ QS_FLUSH(); /* flush the trace buffer to the host */ /* create the RTX thread for the AO... */ os_thread_def_AO.pthread = &ao_thread; /* RTX thread routine for AOs */ os_thread_def_AO.instances = (uint32_t)1; /* # instances of this thread */ os_thread_def_AO.stacksize = (uint32_t)stkSize; /* stack size [BYTES!] */ os_thread_def_AO.tpriority = (me->osObject != (uint32_t)0) /* RTX priority provided? */ ? (osPriority)(me->osObject) /* use the provided value */ : osPriorityNormal; /* use the default */ me->thread = osThreadCreate(&os_thread_def_AO, (void *)me); /* ensure that the thread was created correctly */ Q_ENSURE_ID(520, me->thread != (osThreadId)0); }
/*..........................................................................*/ void QActive_start(QActive *me, uint8_t prio, QEvt const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvt const *ie) { Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE)); QEQueue_init(&me->eQueue, qSto, (QEQueueCtr)qLen); me->prio = prio; QF_add_(me); /* make QF aware of this active object */ #if defined(QK_TLS) || defined(QK_EXT_SAVE) me->osObject = (uint8_t)stkSize; /* osObject contains the thread flags */ me->thread = stkSto;/* contains the pointer to the thread-local storage */ #else Q_ASSERT((stkSto == (void *)0) && (stkSize == (uint32_t)0)); #endif QF_ACTIVE_INIT_(&me->super, ie); /* execute initial transition */ QS_FLUSH(); /* flush the trace buffer to the host */ }