void fonction_periodique (void * arg) { int err; unsigned long depassements; // rend le thread periodique // a partir de TM_NOW // periode en nanosecondes rt_task_set_periodic(rt_task_self(), TM_NOW, 1000000000); // printf pour xenomai rt_printf("[%lld] Timer programmé...\n", rt_timer_read()); // rt_task_wait_period // attend le reveil // depassement : permet de savoir si on a manqué des reveils while ((err = rt_task_wait_period(& depassements)) == 0) { rt_printf("[%lld]", rt_timer_read()); if (depassements != 0) rt_printf(" Depassements : %lu", depassements); rt_printf("\n"); } fprintf(stderr, "rt_task_wait_period(): %s\n",strerror(-err)); exit(EXIT_FAILURE); }
void demo(void *arg) { RTIME starttime, runtime; int num=*(int *)arg; RT_TASK *curtask; RT_TASK_INFO curtaskinfo; curtask=rt_task_self(); rt_printf("Task : %d\n",num); rt_sem_p(&mysync,TM_INFINITE); runtime = 0; while(runtime < EXECTIME) { rt_timer_spin(SPINTIME); // spin cpu doing nothing runtime = runtime + SPINTIME; rt_printf("Running Task : %d at ms : %d\n",num,runtime/1000000); if(runtime == (EXECTIME/2)){ if(num == 2){ rt_task_set_priority(&demo_task[1],MID+10); rt_task_set_priority(&demo_task[0],LOW+10); } } } rt_printf("End Task : %d\n",num); }
// we could implement here the interrupt shield logic. INTERNAL_QUAL int rtos_task_set_scheduler(RTOS_TASK* t, int sched_type) { // xenoptr was initialised from the thread wrapper. if (t->xenoptr != rt_task_self() ) { return -1; } if ( rtos_task_check_scheduler( &sched_type ) == -1) return -1; #if ((CONFIG_XENO_VERSION_MAJOR*1000)+(CONFIG_XENO_VERSION_MINOR*100)+CONFIG_XENO_REVISION_LEVEL) < 2600 if (sched_type == SCHED_XENOMAI_HARD) { if ( rt_task_set_mode( 0, T_PRIMARY, 0 ) == 0 ) { t->sched_type = SCHED_XENOMAI_HARD; return 0; } else { return -1; } } else { if ( sched_type == SCHED_XENOMAI_SOFT) { // This mode setting is only temporary. See rtos_task_wait_period() as well ! if (rt_task_set_mode( T_PRIMARY, 0, 0 ) == 0 ) { t->sched_type = SCHED_XENOMAI_SOFT; return 0; } else { return -1; } } } assert(false); return -1; #else t->sched_type = sched_type; return 0; #endif }
static void main_task(void *arg) { RT_TASK *p; int ret; traceobj_enter(&trobj); p = rt_task_self(); traceobj_assert(&trobj, p != NULL && rt_task_same(p, &t_main)); traceobj_mark(&trobj, 5); ret = rt_alarm_start(&alrm, 200000000ULL, 200000000ULL); traceobj_check(&trobj, ret, 0); traceobj_mark(&trobj, 6); ret = rt_task_suspend(&t_main); traceobj_check(&trobj, ret, 0); traceobj_mark(&trobj, 7); ret = rt_alarm_delete(&alrm); traceobj_check(&trobj, ret, 0); traceobj_exit(&trobj); }
void task_body(void *cookie) { RT_TASK *current_task; RT_TASK_INFO current_task_info; current_task = rt_task_self(); rt_task_inquire(current_task, ¤t_task_info); rt_printf("Task name: %s started with priority %d\n", current_task_info.name, current_task_info.cprio ); for (int i = 0; i < ITERATIONS; i++) { rt_mutex_bind(&mutex, "mutex", TM_NONBLOCK); long int r = shared_resource; r = r + 1; shared_resource = r; rt_mutex_unbind(&mutex); rt_task_sleep(DELAY); } rt_printf("Task name: %s is shutting down\n", current_task_info.name); }
void demo(void *arg) { RT_TASK *curtask; RT_TASK_INFO curtaskinfo; curtask=rt_task_self(); rt_task_inquire(curtask, &curtaskinfo); rt_printf("Task name : %s\n", curtaskinfo.name); }
void _rtapi_task_wrapper(void * task_id_hack) { int ret; int task_id = (int)(long) task_id_hack; // ugly, but I ain't gonna fix it task_data *task = &task_array[task_id]; /* use the argument to point to the task data */ if (task->period < period) task->period = period; task->ratio = task->period / period; rtapi_print_msg(RTAPI_MSG_DBG, "rtapi_task_wrapper: task %p '%s' period=%d " "prio=%d ratio=%d\n", task, task->name, task->ratio * period, task->prio, task->ratio); ostask_self[task_id] = rt_task_self(); // starting the thread with the TF_NOWAIT flag implies it is not periodic // https://github.com/machinekit/machinekit/issues/237#issuecomment-126590880 // NB this assumes rtapi_wait() is NOT called on this thread any more // see thread_task() where this is handled for now if (!(task->flags & TF_NOWAIT)) { if ((ret = rt_task_set_periodic(NULL, TM_NOW, task->ratio * period)) < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "ERROR: rt_task_set_periodic(%d,%s) failed %d %s\n", task_id, task->name, ret, strerror(-ret)); // really nothing one can realistically do here, // so just enable forensics abort(); } } #ifdef USE_SIGXCPU // required to enable delivery of the SIGXCPU signal rt_task_set_mode(0, T_WARNSW, NULL); #endif _rtapi_task_update_stats_hook(); // initial recording #ifdef TRIGGER_SIGXCPU_ONCE // enable this for testing only: // this should cause a domain switch due to the write() // system call and hence a single SIGXCPU posted, // causing an XU_SIGXCPU exception // verifies rtapi_task_update_status_hook() works properly // and thread_status counters are updated printf("--- once in task_wrapper\n"); #endif /* call the task function with the task argument */ (task->taskcode) (task->arg); /* if the task ever returns, we record that fact */ task->state = ENDED; rtapi_print_msg(RTAPI_MSG_ERR, "ERROR: reached end of wrapper for task %d '%s'\n", task_id, task->name); }
void demo(void *arg) { int num = *(int *)arg; RT_TASK *curtask; RT_TASK_INFO curtaskinfo; curtask=rt_task_self(); rt_task_inquire(curtask,&curtaskinfo); rt_printf("Task name: %s with num %d \n", curtaskinfo.name, num); }
void demo(void *arg) { int num = * (int *)arg; RT_TASK *curtask; RT_TASK_INFO curtaskinfo; curtask=rt_task_self(); rt_task_inquire(curtask, &curtaskinfo); rt_sem_p(&sem, TM_INFINITE); rt_printf("Task name: %s - Argument %d\n", curtaskinfo.name, num); rt_sem_v(&sem); }
void task(void *arg) { int a = * (int *) arg; RT_TASK *curtask; RT_TASK_INFO curtaskinfo; curtask=rt_task_self(); rt_task_inquire(curtask,&curtaskinfo); rt_printf("Task name: %s arg: %d \n", curtaskinfo.name, a); }
INTERNAL_QUAL void rtos_xeno_thread_wrapper( void* cookie ) { // store 'self' RTOS_TASK* task = ((ThreadInterface*)((XenoCookie*)cookie)->data)->getTask(); task->xenoptr = rt_task_self(); assert( task->xenoptr ); // call user function ((XenoCookie*)cookie)->wrapper( ((XenoCookie*)cookie)->data ); free(cookie); }
void UnLockPython(void) { if(AtomicCompareExchange( &python_state, PYTHON_BUSY, PYTHON_FREE) == PYTHON_BUSY){ if(rt_task_self()){/*is that the real time task ?*/ char cmd = UNLOCK_PYTHON; rt_pipe_write(&Python_pipe, &cmd, sizeof(cmd), P_NORMAL); }/* otherwise, no signaling from non real time */ } /* as plc does not wait for lock. */ }
void task(void *arg) { rt_sem_p(&semGlobal, TM_INFINITE); int a = * (int *) arg; RT_TASK *curtask; RT_TASK_INFO curtaskinfo; curtask=rt_task_self(); rt_task_inquire(curtask,&curtaskinfo); rt_printf("Task name: %s arg: %d \n", curtaskinfo.name, a); }
INTERNAL_QUAL int rtos_task_is_self(const RTOS_TASK* task) { RT_TASK* self = rt_task_self(); if (self == 0 || task == 0) return -1; // non-xeno thread. We could try to compare pthreads like in gnulinux ? #if ((CONFIG_XENO_VERSION_MAJOR*1000)+(CONFIG_XENO_VERSION_MINOR*100)+CONFIG_XENO_REVISION_LEVEL) >= 2500 if ( rt_task_same( self, task->xenoptr ) != 0 ) return 1; #else // older versions: if ( self == task->xenoptr ) // xenoptr is also set by rt_task_self() during construction. return 1; #endif return 0; }
static void taskPrintInfo( void) { RT_TASK_INFO thisTask; rt_task_inquire( rt_task_self(), &thisTask); LOG_INFO("task %s, has bprio %d, cprio %d", thisTask.name, thisTask.bprio, thisTask.cprio); }
void demo(void *arg) { RT_TASK *curtask; RT_TASK_INFO curtaskinfo; // inquire current task curtask=rt_task_self(); rt_task_inquire(curtask,&curtaskinfo); rt_sem_p(&semGlobal,TM_INFINITE); // print task name int num = * (int *)arg; rt_printf("Task name : %s \n", curtaskinfo.name); }
void demo(void *arg) { RT_TASK *curtask; RT_TASK_INFO curtaskinfo; int num = *(int *) arg; // inquire current task curtask=rt_task_self(); rt_task_inquire(curtask,&curtaskinfo); // print task name rt_printf("Task name : %s \n", curtaskinfo.name); // print argument rt_printf("Task argument : %d \n", num); }
void demo (void *arg){ RT_TASK *curtask; RT_TASK_INFO curtaskinfo; //inquire current task curtask = rt_task_self(); int retval; retval = rt_task_inquire(curtask,&curtaskinfo); if(retval<0){ rt_printf("inquiring error %d:%s\n",-retval,strerror(-retval)); return; } //print task name retval = * (int *)arg; rt_printf("Task name: %s. Has param: %d\n", curtaskinfo.name,retval); }
void demo(void *arg) { RT_TASK *curtask; RT_TASK_INFO curtaskinfo; // hello world rt_printf("Hello World!\n"); // inquire current task curtask=rt_task_self(); rt_task_inquire(curtask,&curtaskinfo); // print task name rt_printf("Task name : %s \n", curtaskinfo.name); }
static void taskValidatePrio( void) { RT_TASK_INFO thisTask; rt_task_inquire( rt_task_self(), &thisTask); if (thisTask.cprio > thisTask.bprio) { LOG_ERR("task %s, has raised prio from %d to %d", thisTask.name, thisTask.bprio, thisTask.cprio); } }
int rt_task_set_periodic(RT_TASK *task, RTIME idate, RTIME period) { int ret; ret = __CURRENT(rt_task_set_periodic(task, idate, period)); if (ret) return ret; if (idate != TM_NOW) { if (task == NULL || task == rt_task_self()) ret = rt_task_wait_period(NULL); else trank_warning("task won't wait for start time"); } return ret; }
void task_body(void *cookie) { rt_sem_p(&sem, TM_INFINITE); RT_TASK *current_task; RT_TASK_INFO current_task_info; current_task = rt_task_self(); rt_task_inquire(current_task, ¤t_task_info); rt_printf("Task name: %s started with priority %d\n", current_task_info.name, current_task_info.cprio ); rt_task_sleep(DELAY * 1000000L); // delay for 1 second rt_printf("Task name: %s is shutting down\n", current_task_info.name); }
void key_handler(void *arg) { int count = 0; int nr_interrupts_waiting; RT_TASK *curtask; RT_TASK_INFO curtaskinfo; while(1) { //rt_printf("%d\n",count++); nr_interrupts_waiting = rt_intr_wait(&keypress,TM_INFINITE); if (nr_interrupts_waiting>0) { // inquire current task curtask=rt_task_self(); rt_task_inquire(curtask,&curtaskinfo); rt_printf("Current priority of handler task: %d \n", curtaskinfo.cprio); } } }
void task_body(void *cookie) { RT_TASK *current_task; RT_TASK_INFO current_task_info; current_task = rt_task_self(); //получаем информацию о таске rt_task_inquire(current_task, ¤t_task_info); rt_printf("Task name: %s started with priority %d\n", current_task_info.name, current_task_info.cprio ); for (int i = 0; i < ITERATIONS; i++) { __sync_fetch_and_add(&shared_resource, 1); rt_task_sleep(DELAY); } // pthread_mutex_unlock(&my_gasu_mutex); rt_printf("Task name: %s is shutting down\n", current_task_info.name); }
void demo (void *arg){ sleep(1); RT_TASK *curtask; RT_TASK_INFO curtaskinfo; //inquire current task curtask = rt_task_self(); int retval; retval = rt_task_inquire(curtask,&curtaskinfo); if(retval<0){ rt_printf("inquiring error %d:%s\n",-retval,strerror(-retval)); } //print task name retval = * (int *)arg; RTIME p = 1e9; p*=retval; rt_task_set_periodic(NULL,TM_NOW,p); while(1){ rt_printf("[%s] %d s periodic\n", curtaskinfo.name,retval); rt_task_wait_period(NULL); } }
int _rtapi_task_self_hook(void) { RT_TASK *ptr; int n; /* ask OS for pointer to its data for the current task */ ptr = rt_task_self(); if (ptr == NULL) { /* called from outside a task? */ return -EINVAL; } /* find matching entry in task array */ n = 1; while (n <= RTAPI_MAX_TASKS) { if (ostask_array[n] == ptr) { /* found a match */ return n; } n++; } return -EINVAL; }
INTERNAL_QUAL int rtos_task_create_main(RTOS_TASK* main) { // first check if root (or if have sufficient privileges) if ( geteuid() != 0 ) { #if ((CONFIG_XENO_VERSION_MAJOR*1000)+(CONFIG_XENO_VERSION_MINOR*100)+CONFIG_XENO_REVISION_LEVEL) >= 2302 printf( "WARNING: You are not root. This program *may* require that you are root.\n"); // \todo verify have sufficient privileges #else printf( "You are not root. This program requires that you are root.\n"); exit(1); #endif } // locking of all memory for this process int rv = mlockall(MCL_CURRENT | MCL_FUTURE); if ( rv != 0 ) { perror( "rtos_task_create_main: Could not lock memory using mlockall" ); // Logger unavailable. exit(1); } struct sched_param param; // we set the MT to the highest sched priority to allow the console // to interrupt a loose running thread. param.sched_priority = sched_get_priority_max(ORO_SCHED_OTHER); if (param.sched_priority != -1 ) sched_setscheduler( 0, ORO_SCHED_OTHER, ¶m); const char* mt_name = "MainThread"; main->sched_type = SCHED_XENOMAI_SOFT; // default for MainThread main->name = strncpy( (char*)malloc( (strlen(mt_name)+1)*sizeof(char) ), mt_name, strlen(mt_name)+1 ); int ret = -1; while( ret != 0) { // name, priority, mode if ( (ret = rt_task_shadow( &(main->xenotask),mt_name, 0, 0)) != 0 ) { if ( ret == -ENOMEM ) { // fail: abort printf( "Cannot rt_task_create() MainThread: Out of memory.\n"); exit(1); } if ( ret == -EBUSY ) { // ok: we are a xeno thread (may log() ): log(Info) << "MainThread already a Xenomai task." <<endlog(); break; } if ( ret == -EEXIST ) { // fail: retry without using a name. mt_name = 0; // do not register continue; } if ( ret == -EPERM ) { // fail: abort printf( "Can not rt_task_create() MainThread: No permission.\n"); exit(1); } // uncaught error: abort printf( "Can not rt_task_create() MainThread: Error %d.\n",ret); exit(1); } } // We are a xeno thread now: // Only use Logger after this point (i.e. when rt_task_shadow was succesful). if ( mt_name == 0) { log(Warning) << "'MainThread' name was already in use. Registered empty name with Xenomai.\n" <<endlog(); } // main is created in main thread. main->xenoptr = rt_task_self(); #ifdef OROSEM_OS_XENO_PERIODIC # if CONFIG_XENO_VERSION_MAJOR == 2 && CONFIG_XENO_VERSION_MINOR == 0 // time in nanoseconds rt_timer_start( ORODAT_OS_XENO_PERIODIC_TICK*1000*1000*1000 ); Logger::In in("Scheduler"); Logger::log() << Logger::Info << "Xenomai Periodic Timer started using "<<ORODAT_OS_XENO_PERIODIC_TICK<<" seconds." << Logger::endl; # else Logger::In in("Scheduler"); Logger::log() << Logger::Error << "Set Xenomai Periodic Timer using the Linux kernel configuration." << Logger::endl; # endif #else # if CONFIG_XENO_VERSION_MAJOR == 2 && CONFIG_XENO_VERSION_MINOR == 0 rt_timer_start( TM_ONESHOT ); Logger::log() << Logger::Info << "Xenomai Periodic Timer runs in preemptive 'one-shot' mode." << Logger::endl; # else # if CONFIG_XENO_OPT_TIMING_PERIODIC Logger::log() << Logger::Info << "Xenomai Periodic Timer configured in 'periodic' mode." << Logger::endl; # else Logger::log() << Logger::Info << "Xenomai Periodic Timer runs in preemptive 'one-shot' mode." << Logger::endl; # endif # endif #endif log(Info) << "Installing SIGXCPU handler." <<endlog(); //signal(SIGXCPU, warn_upon_switch); struct sigaction sa; sa.sa_handler = warn_upon_switch; sigemptyset( &sa.sa_mask ); sa.sa_flags = 0; sigaction(SIGXCPU, &sa, 0); Logger::log() << Logger::Debug << "Xenomai Timer and Main Task Created" << Logger::endl; return 0; }
int __po_hi_initialize_early () { #if defined (XENO_POSIX) || defined (XENO_NATIVE) /* * Once initialization has been done, we avoid ALL * potential paging operations that can introduce * some indeterministic timing behavior. */ #include <sys/mman.h> mlockall (MCL_CURRENT|MCL_FUTURE); #endif #if defined (XENO_NATIVE) main_task_id = rt_task_self (); __po_hi_nb_tasks_to_init--; /* * If we are using the XENO_NATIVE skin, we need * to differentiate the main task (that is non real-time) * from the others since the main task cannot use * the services and operates on resources of real-time tasks. * In addition, we decrement the amount of tasks to * initialize since the main task does not wait * for the initialization of the other tasks. */ #endif #if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX) pthread_mutexattr_t mutex_attr; if (pthread_mutexattr_init (&mutex_attr) != 0) { __DEBUGMSG ("[MAIN] Unable to init mutex attributes\n"); } #ifdef RTEMS_POSIX if (pthread_mutexattr_setprioceiling (&mutex_attr, 50) != 0) { __DEBUGMSG ("[MAIN] Unable to set priority ceiling on mutex\n"); } #endif if (pthread_mutex_init (&mutex_init, &mutex_attr) != 0 ) { __DEBUGMSG ("[MAIN] Unable to init pthread_mutex\n"); return (__PO_HI_ERROR_PTHREAD_MUTEX); } __DEBUGMSG ("[MAIN] Have %d tasks to init\n", __po_hi_nb_tasks_to_init); if (pthread_cond_init (&cond_init, NULL) != 0) { return (__PO_HI_ERROR_PTHREAD_COND); } #endif #if defined (XENO_NATIVE) if (rt_cond_create (&cond_init, NULL)) { __DEBUGMSG ("[MAIN] Unable to init the initialization condition variable \n"); return (__PO_HI_ERROR_PTHREAD_MUTEX); } if (rt_mutex_create (&mutex_init, NULL) != 0) { __DEBUGMSG ("[MAIN] Unable to init the initialization mutex variable \n"); return (__PO_HI_ERROR_PTHREAD_COND); } #endif #if defined (RTEMS_POSIX) || defined (__PO_HI_RTEMS_CLASSIC_API) rtems_status_code ret; rtems_time_of_day time; time.year = 1988; time.month = 12; time.day = 31; time.hour = 9; time.minute = 1; time.second = 10; time.ticks = 0; ret = rtems_clock_set( &time ); if (ret != RTEMS_SUCCESSFUL) { __DEBUGMSG ("[MAIN] Cannot set the clock\n"); return __PO_HI_ERROR_CLOCK; } #endif #ifdef __PO_HI_RTEMS_CLASSIC_API __DEBUGMSG ("[MAIN] Create a barrier that wait for %d tasks\n", __po_hi_nb_tasks_to_init); ret = rtems_barrier_create (rtems_build_name ('B', 'A', 'R', 'M'), RTEMS_BARRIER_AUTOMATIC_RELEASE, __po_hi_nb_tasks_to_init, &__po_hi_main_initialization_barrier); if (ret != RTEMS_SUCCESSFUL) { __DEBUGMSG ("[MAIN] Cannot create the main barrier, return code=%d\n", ret); } #endif #ifdef _WIN32 __po_hi_main_initialization_event = CreateEvent (NULL, FALSE, FALSE, NULL); InitializeCriticalSection (&__po_hi_main_initialization_critical_section); #endif __po_hi_initialize_tasking (); /* Initialize protected objects */ #if __PO_HI_NB_PROTECTED > 0 __po_hi_protected_init(); #endif #if __PO_HI_MONITOR_ENABLED == 1 __po_hi_monitor_init (); #endif return (__PO_HI_SUCCESS); }
int __po_hi_wait_initialization () { #if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX) int cstate; if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &cstate) != 0) { __DEBUGMSG ("[MAIN] Cannot modify the cancel state\n"); } if (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &cstate) != 0) { __DEBUGMSG ("[MAIN] Cannot modify the cancel type\n"); } if (pthread_mutex_lock (&mutex_init) != 0) { __DEBUGMSG ("[MAIN] Unable to lock the mutex\n"); return (__PO_HI_ERROR_PTHREAD_MUTEX); } __po_hi_initialized_tasks++; __DEBUGMSG ("[MAIN] %d task(s) initialized (total to init =%d)\n", __po_hi_initialized_tasks, __po_hi_nb_tasks_to_init); while (__po_hi_initialized_tasks < __po_hi_nb_tasks_to_init) { pthread_cond_wait (&cond_init, &mutex_init); } pthread_cond_broadcast (&cond_init); pthread_mutex_unlock (&mutex_init); __PO_HI_INSTRUMENTATION_VCD_INIT return (__PO_HI_SUCCESS); #elif defined (_WIN32) EnterCriticalSection (&__po_hi_main_initialization_critical_section); __po_hi_initialized_tasks++; __DEBUGMSG ("[MAIN] %d task(s) initialized (total to init =%d)\n", __po_hi_initialized_tasks, __po_hi_nb_tasks_to_init); while (__po_hi_initialized_tasks < __po_hi_nb_tasks_to_init) { LeaveCriticalSection (&__po_hi_main_initialization_critical_section); WaitForSingleObject (__po_hi_main_initialization_event, INFINITE); EnterCriticalSection (&__po_hi_main_initialization_critical_section); } SetEvent (__po_hi_main_initialization_event); LeaveCriticalSection (&__po_hi_main_initialization_critical_section); return (__PO_HI_SUCCESS); #elif defined (__PO_HI_RTEMS_CLASSIC_API) rtems_status_code ret; __DEBUGMSG ("[MAIN] Task wait for the barrier\n"); ret = rtems_barrier_wait (__po_hi_main_initialization_barrier, RTEMS_WAIT); if (ret != RTEMS_SUCCESSFUL) { __DEBUGMSG ("[MAIN] Error while waiting for the barrier, return code=%d\n", ret); return (__PO_HI_ERROR_UNKNOWN); } __DEBUGMSG ("[MAIN] Task release the barrier\n"); return (__PO_HI_SUCCESS); #elif defined (XENO_NATIVE) int ret; if (main_task_id == rt_task_self ()) { /* * Here, this function is called by the main thread (the one that executes * the main() function) so that we don't wait for the initialization of the * other tasks, we automatically pass through the function and immeditaly * return. */ return (__PO_HI_SUCCESS); } ret = rt_mutex_acquire (&mutex_init, TM_INFINITE); if (ret != 0) { __DEBUGMSG ("[MAIN] Cannot acquire mutex (return code = %d)\n", ret); return (__PO_HI_ERROR_PTHREAD_MUTEX); } __po_hi_initialized_tasks++; __DEBUGMSG ("[MAIN] %d task(s) initialized (total to init =%d)\n", __po_hi_initialized_tasks, __po_hi_nb_tasks_to_init); while (__po_hi_initialized_tasks < __po_hi_nb_tasks_to_init) { rt_cond_wait (&cond_init, &mutex_init, TM_INFINITE); } rt_cond_broadcast (&cond_init); rt_mutex_release (&mutex_init); return (__PO_HI_SUCCESS); #else return (__PO_HI_UNAVAILABLE); #endif }