Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 // -*- c++ -*-
     19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     20 
     21 //                  OSCL_T H R E A D (T H R E A D  I M P L E M E N T A T I O N)
     22 
     23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     24 
     25 /*! \file oscl_thread.cpp .This file provides THREAD implementation that can be ported
     26 to three OS LINUX, SYMBIAN, WIN32
     27 */
     28 
     29 
     30 
     31 // Implementation file for OSCL threads
     32 #include "oscl_thread.h"
     33 
     34 
     35 
     36 /*
     37  * Class contructor
     38  */
     39 OSCL_EXPORT_REF OsclThread::OsclThread()
     40 {
     41     bCreated = false;
     42     iJoined = false;
     43 }
     44 
     45 
     46 
     47 /*
     48  * Class destructor
     49  */
     50 OSCL_EXPORT_REF OsclThread::~OsclThread()
     51 {
     52 
     53     ;
     54 
     55 }
     56 
     57 
     58 /**
     59  * OSCL Proc layer function
     60  * Input Argument:
     61  * function_name  =  Name of the thread Function
     62  * stack_size  =  Size of the thread stack
     63  * argument = Argument to be passed to thread function
     64  * Thread_State = Enumeration which specifies the state of the thread on creation
     65  *        with values Running and Suspend
     66  * Return value : eOsclProcError
     67  */
     68 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Create(TOsclThreadFuncPtr function_name,
     69         int32 stack_size,
     70         TOsclThreadFuncArg argument,
     71         OsclThread_State state,
     72         bool oIsJoinable)
     73 {
     74     if (stack_size < 0)
     75         return OsclProcStatus::INVALID_PARAM_ERROR;
     76 
     77     if (function_name == NULL)
     78         return OsclProcStatus::INVALID_PARAM_ERROR;
     79 
     80     //Reset thread creation state, since the thread may
     81     //have exited.
     82     if (bCreated)
     83         bCreated = false;
     84 
     85 
     86     switch (state)
     87     {
     88         case Start_on_creation:
     89             break;
     90         case Suspend_on_creation:
     91             //can't create suspended pthread.
     92             return OsclProcStatus::INVALID_PARAM_ERROR;
     93     }
     94     pthread_attr_t attr;
     95     pthread_attr_init(&attr);
     96     if (stack_size != 0)
     97         pthread_attr_setstacksize(&attr, stack_size);
     98 
     99     // Default detachstate attribute to PTHREAD_CREATE_DETACHED state
    100     int detach_ret;
    101     if (oIsJoinable)
    102     {
    103         detach_ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    104         iJoined = true;
    105     }
    106     else
    107     {
    108         detach_ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    109     }
    110     switch (detach_ret)
    111     {
    112         case 0: // successful, continue thread creation
    113             break;
    114         case EINVAL:
    115         default:
    116             return OsclProcStatus::PSHARED_ATTRIBUTE_SETTING_ERROR;
    117     }
    118 
    119     int result = pthread_create(
    120                      (pthread_t*) & ObjThread,
    121                      &attr,
    122                      function_name,
    123                      (void*)argument);
    124 
    125     switch (result)
    126     {
    127         case 0:
    128             bCreated = true;
    129             return OsclProcStatus::SUCCESS_ERROR;
    130         case EAGAIN:
    131             return OsclProcStatus::NOT_ENOUGH_RESOURCES_ERROR;
    132         default:
    133             return OsclProcStatus::OTHER_ERROR;
    134     }
    135 
    136 }
    137 
    138 
    139 /**
    140  * OSCL Proc layer function
    141  * ExitThread is a static function which is used to end the current thread. When called it
    142  * just ends the execution of the current thread.
    143  * Input Argument:
    144  * exitcode  =  Exitcode of the thread. This can be used by other threads to know the
    145  *              exit status of this thread.
    146  * Return value : None
    147 */
    148 OSCL_EXPORT_REF void OsclThread::Exit(OsclAny* exitcode)
    149 {
    150     //intentionally not implemented.
    151     OSCL_UNUSED_ARG(exitcode);
    152 
    153 }
    154 
    155 OSCL_EXPORT_REF void OsclThread::EnableKill()
    156 {
    157     ; //nothing needed
    158 
    159 }
    160 
    161 /**
    162  * OSCL Proc layer function
    163  * Suspend current thread execution for specified time.
    164  * @param msec, t2: sleep time in milliseconds.
    165  */
    166 OSCL_EXPORT_REF void OsclThread::SleepMillisec(const int32 msec)
    167 {
    168     struct timespec reqt, remt;
    169     reqt.tv_sec = msec / 1000;
    170     reqt.tv_nsec = 1000000 * (msec % 1000);
    171     nanosleep(&reqt, &remt) ;
    172 
    173 }
    174 
    175 
    176 /**
    177 
    178  * OSCL Proc layer function
    179 
    180  * This is used to terminate a thread other than the current thread.
    181 
    182  * Input Argument:
    183 
    184  * exitcode  =  Exitcode of the thread. This can be used by other threads to know the
    185 
    186  *              exit status of this thread.
    187 
    188  * Return value : Error code
    189 
    190  */
    191 
    192 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Terminate(OsclAny* oscl_ExitCode)
    193 {
    194 
    195 
    196     if (!bCreated)
    197         return OsclProcStatus::INVALID_OPERATION_ERROR;
    198 
    199     {
    200         OSCL_UNUSED_ARG(oscl_ExitCode);
    201 
    202         bCreated = false;
    203         if (iJoined)
    204         {
    205             if (pthread_join(ObjThread, NULL) == 0)
    206             {
    207                 return OsclProcStatus::SUCCESS_ERROR;
    208             }
    209             else
    210             {
    211                 return OsclProcStatus::OTHER_ERROR;
    212             }
    213         }
    214         return OsclProcStatus::NOT_IMPLEMENTED;
    215     }
    216 }
    217 
    218 
    219 
    220 
    221 
    222 
    223 
    224 /**
    225 
    226  * OSCL Proc layer function
    227 
    228  * This API suspends the thread being referred. The thread can later be brought into execution
    229 
    230  * by calling OSCL_ResumeThread() on it.
    231 
    232  * Input Argument: None
    233 
    234  * Return value : Error code
    235 
    236  */
    237 
    238 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Suspend()
    239 
    240 {
    241 
    242     if (!bCreated)
    243         return OsclProcStatus::INVALID_OPERATION_ERROR;
    244 
    245 
    246 
    247 
    248     {
    249         //pthread doesn't support suspend/resume
    250         return OsclProcStatus::NOT_IMPLEMENTED;
    251 
    252     }
    253 
    254 
    255 }
    256 
    257 
    258 
    259 
    260 
    261 
    262 
    263 /**
    264 
    265  * OSCL Proc layer function
    266 
    267  * ResumeThread resumes the suspended thread and brings it into execution.
    268 
    269  * Input Argument: None
    270 
    271  * Return value : Error code
    272 
    273  */
    274 
    275 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::Resume()
    276 
    277 {
    278 
    279     if (!bCreated)
    280         return OsclProcStatus::INVALID_OPERATION_ERROR;
    281 
    282 
    283 
    284 
    285     {
    286 
    287         //pthread doesn't support suspend/resume
    288         return OsclProcStatus::NOT_IMPLEMENTED;
    289 
    290     }
    291 
    292 
    293 }
    294 
    295 
    296 
    297 
    298 
    299 /**
    300 
    301  * OSCL Proc layer function
    302 
    303  * GetThreadPriority gets the priority of the thread. It takes reference of the input argument
    304 
    305  * and assigns priority to it from one of the already defined priorities.
    306 
    307  * Input Argument:
    308 
    309  * int16& refThreadPriority : Output Priority value
    310 
    311  * Return value : Error code
    312 
    313  */
    314 
    315 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::GetPriority(OsclThreadPriority& refThreadPriority)
    316 
    317 {
    318     if (!bCreated)
    319         return OsclProcStatus::INVALID_OPERATION_ERROR;
    320 
    321     struct sched_param schedparam;
    322     int sched_policy = 0;
    323     int pri;
    324     int result;
    325     result = pthread_getschedparam(ObjThread, &sched_policy, &schedparam);
    326     if (result != 0)
    327     {
    328         switch (result)
    329         {
    330             case ESRCH:
    331                 return OsclProcStatus::INVALID_THREAD_ERROR;
    332             case EFAULT:
    333                 return OsclProcStatus::INVALID_PARAM_ERROR;
    334             default:
    335                 return OsclProcStatus::OTHER_ERROR;
    336         }
    337     }
    338 
    339     pri = schedparam.sched_priority;
    340     switch (sched_policy)
    341     {
    342         case SCHED_RR:
    343         case SCHED_FIFO:
    344         {
    345             //static priority is 1..99
    346             if (pri < 1)
    347                 return OsclProcStatus::OTHER_ERROR;
    348             else if (pri == 1)
    349                 refThreadPriority = ThreadPriorityLowest;
    350             else if (pri <= 20)
    351                 refThreadPriority = ThreadPriorityLow;
    352             else if (pri <= 40)
    353                 refThreadPriority = ThreadPriorityBelowNormal;
    354             else if (pri <= 55)
    355                 refThreadPriority = ThreadPriorityNormal;
    356             else if (pri <= 75)
    357                 refThreadPriority = ThreadPriorityAboveNormal;
    358             else if (pri <= 98)
    359                 refThreadPriority = ThreadPriorityHighest;
    360             else if (pri == 99)
    361                 refThreadPriority = ThreadPriorityTimeCritical;
    362             else if (pri > 99)
    363                 return OsclProcStatus::OTHER_ERROR;
    364             return OsclProcStatus::SUCCESS_ERROR;
    365         }
    366         break;
    367 
    368         case SCHED_OTHER:
    369         {
    370             //static priority is always zero.
    371             if (pri != 0)
    372                 return OsclProcStatus::OTHER_ERROR;
    373             refThreadPriority = ThreadPriorityNormal;
    374             return OsclProcStatus::SUCCESS_ERROR;
    375         }
    376         break;
    377 
    378         default:
    379             return OsclProcStatus::OTHER_ERROR;
    380     }
    381 }
    382 
    383 
    384 
    385 /**
    386  * OSCL Proc layer function
    387  * SetThreadPriority sets the priority of the thread. It takes priority as the input argument
    388  * and assigns it to the thread referred.
    389  * Input Argument:
    390  * ePriorityLevel : Input Priority value
    391  * Return value : Error code
    392  */
    393 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::SetPriority(OsclThreadPriority ePriority)
    394 {
    395     if (!bCreated)
    396         return OsclProcStatus::INVALID_OPERATION_ERROR;
    397 
    398     //not supported.
    399     OSCL_UNUSED_ARG(ePriority);
    400     return OsclProcStatus::NOT_IMPLEMENTED;
    401 
    402 }
    403 
    404 
    405 
    406 /**
    407 
    408  * OSCL Proc layer function
    409 
    410  * This is used to compare whether the thread ID's are equal.
    411 
    412  * @param Thread ID passed by the application
    413 
    414  * @return Error code
    415 
    416  */
    417 
    418 OSCL_EXPORT_REF OsclProcStatus::eOsclProcError OsclThread::GetId(TOsclThreadId& refThreadId)
    419 
    420 {
    421 
    422 
    423 
    424 
    425     refThreadId = pthread_self();
    426 
    427     return OsclProcStatus::SUCCESS_ERROR;
    428 
    429 
    430 }
    431 
    432 
    433 OSCL_EXPORT_REF bool OsclThread::CompareId(TOsclThreadId &t1, TOsclThreadId &t2)
    434 //static routine
    435 {
    436     return (pthread_equal(t1, t2) != 0);
    437 }
    438 
    439 
    440 
    441 
    442 
    443 
    444 /**
    445 
    446  * Helper Function
    447 
    448  * Map the Operating system errors to OSCL defined erros
    449 
    450  * Input Argument:
    451 
    452  * error : Input error as one of the OS errors
    453 
    454  * Return value : Error code ( User defined )
    455 
    456  */
    457 
    458 
    459 
    460 
    461 
    462 
    463