Ejemplo n.º 1
0
/*
 * Extend the os_procAttr struct with scheduling
 * settings derived from the u_scheduler class.
 * All other attributes from the os_procAttr struct
 * are not modified.
 */
u_result u_procAttrInit(
    struct v_schedulePolicy *v_schedParam,
    os_procAttr *os_procParam
    )
{
    if (v_schedParam->kind == V_SCHED_DEFAULT) {
	os_procParam->schedClass = os_procAttrGetClass ();
    } else if (v_schedParam->kind == V_SCHED_REALTIME) {
	os_procParam->schedClass = OS_SCHED_REALTIME;
    } else if (v_schedParam->kind == V_SCHED_TIMESHARING) {
	os_procParam->schedClass = OS_SCHED_TIMESHARE;
    }
    if (v_schedParam->priorityKind == V_SCHED_PRIO_RELATIVE) {
	os_procParam->schedPriority = os_procAttrGetPriority () + v_schedParam->priority;
    } else {
	os_procParam->schedPriority = v_schedParam->priority;
    }
    return U_RESULT_OK;
}
Ejemplo n.º 2
0
/** \brief Create a new thread
 *
 * \b os_threadCreate creates a thread by calling \b pthread_create.
 * But first it processes all thread attributes in \b threadAttr and
 * sets the scheduling properties with \b pthread_attr_setscope
 * to create a bounded thread, \b pthread_attr_setschedpolicy to
 * set the scheduling class and \b pthread_attr_setschedparam to
 * set the scheduling priority.
 * \b pthread_attr_setdetachstate is called with parameter
 * \PTHREAD_CREATE_JOINABLE to make the thread joinable, which
 * is needed to be able to wait for the threads termination
 * in \b os_threadWaitExit.
 */
os_result
os_threadCreate (
    os_threadId *threadId,
    const char *name,
    const os_threadAttr *threadAttr,
    void *(* start_routine)(void *),
    void *arg)
{
    pthread_attr_t attr;
    struct sched_param sched_param;
    os_result rv = os_resultSuccess;
    os_threadContext *threadContext;
    os_threadAttr tattr;
    int result, create_ret;
    int policy;

    assert (threadId != NULL);
    assert (name != NULL);
    assert (threadAttr != NULL);
    assert (start_routine != NULL);
    tattr = *threadAttr;

    if (tattr.schedClass == OS_SCHED_DEFAULT) {
#ifndef PIKEOS_POSIX
#ifndef VXWORKS_RTP
        tattr.schedClass = os_procAttrGetClass ();
#endif
        tattr.schedPriority = os_procAttrGetPriority ();
#endif
    }
    if (pthread_attr_init (&attr) != 0)
    {
       rv = os_resultFail;
    }
    else
    {
#ifdef VXWORKS_RTP
       (void)pthread_attr_setname(&attr, name);
#endif
       if (pthread_getschedparam(pthread_self(), &policy, &sched_param) != 0 ||
#if !defined (OS_RTEMS_DEFS_H) && !defined (PIKEOS_POSIX)
           pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM) != 0 ||
#endif
           pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE) != 0 ||
           pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED) != 0)
       {
          rv = os_resultFail;
       }
       else
       {
          if (tattr.stackSize != 0) {
#ifdef PTHREAD_STACK_MIN
             if ( tattr.stackSize < PTHREAD_STACK_MIN ) {
                tattr.stackSize = PTHREAD_STACK_MIN;
             }
#endif
#ifdef OSPL_STACK_MAX
             if ( tattr.stackSize > OSPL_STACK_MAX ) {
                tattr.stackSize = OSPL_STACK_MAX;
             }
#endif
             if (pthread_attr_setstacksize (&attr, tattr.stackSize) != 0) {
                rv = os_resultFail;
             }
          }
       }

       if (rv == os_resultSuccess) {
          if (tattr.schedClass == OS_SCHED_REALTIME) {
             result = pthread_attr_setschedpolicy (&attr, SCHED_FIFO);

             if (result != 0) {
                OS_REPORT (OS_WARNING, "os_threadCreate", 2,
                             "pthread_attr_setschedpolicy failed for SCHED_FIFO with "\
                             "error %d (%s) for thread '%s', reverting to SCHED_OTHER.",
                             result, os_strError(result), name);

                result = pthread_attr_setschedpolicy (&attr, SCHED_OTHER);
                if (result != 0) {
                   OS_REPORT (OS_WARNING, "os_threadCreate", 2, "pthread_attr_setschedpolicy failed with error %d (%s)", result, name);
                }
             }
          } else {
             result = pthread_attr_setschedpolicy (&attr, SCHED_OTHER);

             if (result != 0) {
                OS_REPORT (OS_WARNING, "os_threadCreate", 2,
                             "pthread_attr_setschedpolicy failed with error %d (%s)",
                             result, name);
             }
          }
          pthread_attr_getschedpolicy(&attr, &policy);

          if ((tattr.schedPriority < sched_get_priority_min(policy)) ||
              (tattr.schedPriority > sched_get_priority_max(policy))) {
             OS_REPORT (OS_WARNING, "os_threadCreate", 2,
                          "scheduling priority outside valid range for the policy "\
                          "reverted to valid value (%s)", name);
             sched_param.sched_priority = (sched_get_priority_min(policy) +
                                           sched_get_priority_max(policy)) / 2;
          } else {
             sched_param.sched_priority = tattr.schedPriority;
          }
          /* Take over the thread context: name, start routine and argument */
          threadContext = os_malloc (sizeof (os_threadContext));
          threadContext->threadName = os_malloc (strlen (name)+1);
          os_strncpy (threadContext->threadName, name, strlen (name)+1);
          threadContext->startRoutine = start_routine;
          threadContext->arguments = arg;

          /* start the thread */
          result = pthread_attr_setschedparam (&attr, &sched_param);
          if (result != 0) {
             OS_REPORT (OS_WARNING, "os_threadCreate", 2,
                          "pthread_attr_setschedparam failed with error %d (%s)",
                          result, name);
          }

          create_ret = pthread_create(threadId, &attr, os_startRoutineWrapper,
                                      threadContext);
          if (create_ret != 0) {
             /* In case real-time thread creation failed due to a lack
              * of permissions, try reverting to time-sharing and continue.
              */
             if((create_ret == EPERM) && (tattr.schedClass == OS_SCHED_REALTIME))
             {
                OS_REPORT (OS_WARNING, "os_threadCreate", 2,
                             "pthread_create failed with SCHED_FIFO "     \
                             "for thread '%s', reverting to SCHED_OTHER.",
                             name);
                pthread_attr_setschedpolicy (&attr, SCHED_OTHER);
                pthread_attr_getschedpolicy(&attr, &policy);

                if ((tattr.schedPriority < sched_get_priority_min(policy)) ||
                    (tattr.schedPriority > sched_get_priority_max(policy)))
                {
                   OS_REPORT (OS_WARNING, "os_threadCreate", 2,
                                "scheduling priority outside valid range for the " \
                                "policy reverted to valid value (%s)", name);
                   sched_param.sched_priority =
                   (sched_get_priority_min(policy) +
                    sched_get_priority_max(policy)) / 2;
                } else {
                   sched_param.sched_priority = tattr.schedPriority;
                }

                result = pthread_attr_setschedparam (&attr, &sched_param);
                if (result != 0) {
                   OS_REPORT (OS_WARNING, "os_threadCreate", 2,
                                "pthread_attr_setschedparam failed "      \
                                "with error %d (%s)", result, name);
                } else {
                   create_ret = pthread_create(threadId, &attr,
                                               os_startRoutineWrapper, threadContext);
                }
             }
          } else {
             rv = os_resultSuccess;
          }
          if(create_ret != 0){
             os_free (threadContext->threadName);
             os_free (threadContext);
             OS_REPORT (OS_WARNING, "os_threadCreate", 2, "pthread_create failed with error %d (%s)", create_ret, name);
             rv = os_resultFail;
          }
       }
       pthread_attr_destroy (&attr);
    }
    return rv;
}