SBtrdPthreads.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:19k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. /*****************************************************************************
  23.  *****************************************************************************
  24.  * SBtrd API implementation
  25.  *
  26.  * This provides the Linux implementation of the VXItrd API for basic
  27.  * thread operations and locks. Unlike most of the other VXI APIs,
  28.  * this is implemented in a library (on Windows a DLL with a specific
  29.  * name, on other operating systems as a static, shared, or dynamic
  30.  * library). Implementations of this API are operating system
  31.  * dependant.
  32.  *
  33.  * To avoid cyclic dependancies, this does not perform logging. Clients
  34.  * must do error logging themselves based on passed return codes.
  35.  *
  36.  *****************************************************************************
  37.  *****************************************************************************/
  38. // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <signal.h>
  43. #include <pthread.h>
  44. #include <sys/time.h>
  45. #include <sys/types.h>
  46. #define VXITRD_EXPORTS
  47. #include "VXItrd.h"                   // Header for this API
  48. #ifndef NDEBUG
  49. #include <assert.h>
  50. #endif
  51. extern "C" {
  52. struct VXItrdMutex {
  53.   pthread_mutex_t mutex;
  54. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  55.   volatile bool locked;
  56. #endif
  57. };
  58. }
  59. typedef enum VXItrdThreadState {
  60.   STATE_STARTING = 0,
  61.   STATE_RUNNING = 1,
  62.   STATE_EXITED = 2
  63. } VXItrdThreadState;
  64. extern "C" {
  65. struct VXItrdThread {
  66.   pthread_t thread;                       // Thread handle
  67.   volatile VXItrdThreadState state;       // Thread state
  68.   VXItrdMutex *refCountMutex;             // For reference count protection
  69.   volatile VXIulong refCount;             // References to this structure
  70.   VXItrdThreadStartFunc thread_function;  // user's thread function
  71.   VXItrdThreadArg thread_arg;             // user's thread argument
  72. };
  73. }
  74. extern "C" {
  75. struct VXItrdTimer {
  76.   volatile VXIbool isSleeping;  /* If 1, thread is currently sleeping */
  77.   volatile VXIbool wakeUp;      /* If 1, thread will ignore the next Sleep() */
  78. };
  79. }
  80. static VXIint32 g_threadStackSize = 0;
  81. // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
  82. /**
  83.  * Internal utility function for sleeping
  84.  */
  85. static VXItrdResult VXItrdSleep(VXIint millisecondDelay)
  86. {
  87.   // Do not want to use usleep( ), non-portable and it is usually implemented
  88.   // via signals which may mess up other software in the system which is
  89.   // also trying to use signals. Note that it is very important to set up
  90.   // the timer each time as on some OSes (like Linux) the timeout var is
  91.   // modified to indicate the actual time slept.
  92.   struct timeval timeout;
  93.   timeout.tv_sec = 0;
  94.   timeout.tv_usec = millisecondDelay * 1000;
  95.   if (select (0, NULL, NULL, NULL, &timeout) < 0)
  96.     return VXItrd_RESULT_SYSTEM_ERROR;
  97.   return VXItrd_RESULT_SUCCESS;
  98. }
  99. /**
  100.  * Creates a new mutex initialized to the unlocked state.  If the calling
  101.  * thread terminates, the created mutex is not automatically deallocated as
  102.  * it may be shared among multiple threads.
  103.  *
  104.  * @return -1 Fatal error (ex: system lacks necessary resources for creation)
  105.  *           0 Success; valid mutex has been created
  106.  */
  107. VXITRD_API VXItrdResult VXItrdMutexCreate(VXItrdMutex **mutex)
  108. {
  109.   if (mutex == NULL) 
  110.     return VXItrd_RESULT_INVALID_ARGUMENT;
  111.   *mutex = NULL;
  112.   
  113.   // Create the wrapper object */
  114.   VXItrdMutex *result = new VXItrdMutex;
  115.   if (result == NULL)
  116.     return VXItrd_RESULT_OUT_OF_MEMORY;
  117. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  118.   result->locked = false;
  119. #endif
  120.   // Create the critical section */
  121.   int rc;
  122.   pthread_mutexattr_t mutexattr;
  123.   
  124.   // Create and configure mutex attributes for recursive mutex
  125.   rc = pthread_mutexattr_init(&mutexattr);
  126.   if (rc != 0) {
  127.     delete result;
  128.     return VXItrd_RESULT_NON_FATAL_ERROR;
  129.   }
  130.          
  131. #ifndef _unixware7_
  132.   rc = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
  133.   if (rc != 0) {
  134.     pthread_mutexattr_destroy(&mutexattr);
  135.     delete result;
  136.     return VXItrd_RESULT_NON_FATAL_ERROR;
  137.   }
  138. #endif
  139.   // Initialize mutex with attributes
  140.   rc = pthread_mutex_init(&result->mutex, &mutexattr);
  141.   if (rc != 0) {
  142.     pthread_mutexattr_destroy(&mutexattr);
  143.     delete result;
  144.     return VXItrd_RESULT_NON_FATAL_ERROR;
  145.   }
  146.   rc = pthread_mutexattr_destroy(&mutexattr);
  147.   if (rc != 0) {
  148.     pthread_mutex_destroy(&result->mutex);
  149.     delete result;
  150.     return VXItrd_RESULT_NON_FATAL_ERROR;
  151.   }
  152.   *mutex = result;
  153.   return VXItrd_RESULT_SUCCESS;
  154. }
  155. /**
  156.  * Deletes an existing mutex.  It is illegal to delete a locked mutex.
  157.  *
  158.  * @return -1 Fatal error (ex: invalid mutex)
  159.  *          0 Success; mutex has been destroyed
  160.  *          1 Mutex is locked
  161.  */
  162. VXITRD_API VXItrdResult VXItrdMutexDestroy(VXItrdMutex **mutex)
  163. {
  164.   if ((mutex == NULL) || (*mutex == NULL))
  165.     return VXItrd_RESULT_INVALID_ARGUMENT;
  166. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  167.   // Check the lock state
  168.   if ( (*mutex)->locked ) {
  169.     assert ("VXItrdMutexDestroy( ) on locked mutex" == NULL);
  170.     return VXItrd_RESULT_FATAL_ERROR;
  171.   }
  172. #endif
  173.   int rc = pthread_mutex_destroy(&(*mutex)->mutex);
  174.   if (rc != 0) {
  175.     return VXItrd_RESULT_NON_FATAL_ERROR;
  176.   }
  177.   
  178.   delete *mutex;
  179.   *mutex = NULL;
  180.   return VXItrd_RESULT_SUCCESS;
  181. }
  182. /**
  183.  * Locks an existing mutex.  If the mutex is already locked, the thread waits
  184.  * for the mutex to become available.
  185.  *
  186.  * @return: -1 Fatal error (ex: invalid mutex or deadlock detected)
  187.  *           0 Success; mutex is now locked
  188.  *           1 Mutex already locked by current thread.
  189.  */
  190. VXITRD_API VXItrdResult VXItrdMutexLock(VXItrdMutex *mutex)
  191. {
  192.   if (mutex == NULL)
  193.     return VXItrd_RESULT_INVALID_ARGUMENT;
  194.   
  195.   int rc = pthread_mutex_lock(&mutex->mutex);
  196.   if (rc != 0) {
  197.     return VXItrd_RESULT_NON_FATAL_ERROR;
  198.   }
  199.   
  200. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  201.   // Check the lock state
  202.   if ( mutex->locked ) {
  203.     // Should not be locking the same mutex twice, very OS dependant
  204.     // and not gauranteed by VXItrdMutex
  205.     assert ("VXItrdMutexLock( ) on already locked mutex" == NULL);
  206.     return VXItrd_RESULT_FATAL_ERROR;
  207.   } else {
  208.     mutex->locked = true;
  209.   }
  210. #endif
  211.   return VXItrd_RESULT_SUCCESS;
  212. }
  213. /**
  214.  * Unlocks a mutex owned by the thread.
  215.  *
  216.  * @return: -1 Fatal error (ex: invalid mutex)
  217.  *           0 Success; mutex no longer owned by calling thread
  218.  *           1 Mutex not owned by thread.
  219.  */
  220. VXITRD_API VXItrdResult VXItrdMutexUnlock(VXItrdMutex *mutex)
  221. {
  222.   if (mutex == NULL)
  223.     return VXItrd_RESULT_INVALID_ARGUMENT;
  224. #if ( ! defined(NDEBUG) ) && ( ! defined(VXITRD_RECURSIVE_MUTEX) )
  225.   // Check the lock state
  226.   if ( ! mutex->locked ) {
  227.     // Unlocking a mutex that wasn't locked
  228.     assert ("VXItrdMutexUnlock( ) on unlocked mutex" == NULL);
  229.     return VXItrd_RESULT_FATAL_ERROR;
  230.   } else {
  231.     mutex->locked = false;
  232.   }
  233. #endif
  234.   int rc = pthread_mutex_unlock(&mutex->mutex);
  235.   if (rc != 0) {
  236.     return VXItrd_RESULT_NON_FATAL_ERROR;
  237.   }
  238.   return VXItrd_RESULT_SUCCESS;
  239. }
  240. /**
  241.  * Internal: wrapper functions for starting/cleaning up threads
  242.  */
  243. static void VXItrdThreadCleanup(VXItrdThreadArg userData)
  244. {
  245.   VXItrdThread *thread = (VXItrdThread *) userData;
  246.   // No longer active
  247.   thread->state = STATE_EXITED;
  248.   // Free our copy of the thread handle
  249.   VXItrdThreadDestroyHandle (&thread);
  250. }
  251. static VXITRD_DEFINE_THREAD_FUNC(VXItrdThreadStart, userData)
  252. {
  253.   VXItrdThread *thread = (VXItrdThread *) userData;
  254.   // Set the state and register a cleanup function to finish it,
  255.   // required for ThreadJoin( ) support
  256.   thread->state = STATE_RUNNING;
  257.   pthread_cleanup_push(VXItrdThreadCleanup, userData);
  258.   // Call the user function
  259.   (*thread->thread_function)(thread->thread_arg);
  260.   // Cleanup, the 1 to pop causes the cleanup function to be invoked
  261.   pthread_cleanup_pop(1);
  262.   return NULL;  // never gets called, just to eliminate compile warning
  263. }
  264. /**
  265.  * Create a thread.  Note: thread values are not supported on OS/2.
  266.  *    execution starts on the thread immediately. To pause execution 
  267.  *    use a Mutex between the thread and the thread creator.
  268.  *
  269.  * @param   thread the thread object to be created
  270.  * @param   thread_function the function for the thread to start execution on
  271.  * @param   thread_arg the arguments to the thread function
  272.  * @return  VXItrdResult of operation.  Return SUCCESS if thread has been 
  273.  *          created and started.
  274.  *
  275.  */
  276. VXITRD_API 
  277. VXItrdResult VXItrdThreadCreate(VXItrdThread **thread,
  278. VXItrdThreadStartFunc thread_function,
  279. VXItrdThreadArg thread_arg)
  280. {
  281.   if ((thread == NULL) || (thread_function == NULL))
  282.     return VXItrd_RESULT_INVALID_ARGUMENT;
  283.   *thread = NULL;
  284.   // Create the wrapper object
  285.   VXItrdThread *result = new VXItrdThread;
  286.   if (result == NULL)
  287.     return VXItrd_RESULT_OUT_OF_MEMORY;
  288.   memset(result, 0, sizeof (VXItrdThread));
  289.   result->state = STATE_STARTING;
  290.   result->refCount = 1; // 1 for parent
  291.   result->thread_function = thread_function;
  292.   result->thread_arg = thread_arg;
  293.   if (VXItrdMutexCreate(&result->refCountMutex) != VXItrd_RESULT_SUCCESS) {
  294.     VXItrdThreadDestroyHandle(&result);
  295.     return VXItrd_RESULT_SYSTEM_ERROR;
  296.   }
  297.   // construct thread attribute
  298.   pthread_attr_t thread_attr;
  299.   int prc = pthread_attr_init(&thread_attr);
  300.   if (prc != 0) {
  301.     VXItrdThreadDestroyHandle(&result);
  302.     return VXItrd_RESULT_NON_FATAL_ERROR;
  303.   }
  304.   
  305.   // configure thread attribute
  306. #ifdef USE_DETACHED_THREADS
  307.   prc = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
  308.   if (prc != 0) {
  309.     pthread_attr_destroy(&thread_attr);
  310.     VXItrdThreadDestroyHandle(&result);
  311.     return VXItrd_RESULT_NON_FATAL_ERROR;
  312.   }
  313. #else
  314.   // use joinable threads
  315.   // this is default - no work required
  316. #endif
  317.   // Set the thread's stack size. A zero value means 'let the OS decide'
  318.   if (g_threadStackSize > 0)
  319.     pthread_attr_setstacksize(&thread_attr, g_threadStackSize);
  320.   // Start the thread using our wrapper function
  321.   result->refCount++;  // for child
  322.   prc = pthread_create(&result->thread, &thread_attr, VXItrdThreadStart,
  323.                        (VXItrdThreadArg) result);
  324.   pthread_attr_destroy(&thread_attr);
  325.   if (prc != 0) {
  326.     result->refCount--;
  327.     VXItrdThreadDestroyHandle(&result);
  328.     return VXItrd_RESULT_NON_FATAL_ERROR;
  329.   }
  330.   *thread = result;
  331.   return VXItrd_RESULT_SUCCESS;
  332. }
  333. /**
  334.  * Destroy a thread handle
  335.  *
  336.  * Note: this does NOT stop or destroy the thread, it just releases
  337.  * the handle for accessing it. If this is not done, a memory leak
  338.  * occurs, so if the creator of the thread never needs to communicate
  339.  * with the thread again it should call this immediately after the
  340.  * create if the create was successful.
  341.  *
  342.  * @param  thread  Handle to the thread to destroy
  343.  *
  344.  * @result VXItrdResult 0 on success 
  345.  */
  346. VXITRD_API VXItrdResult VXItrdThreadDestroyHandle(VXItrdThread **thread)
  347. {
  348.   if ((thread == NULL) || (*thread == NULL))
  349.     return VXItrd_RESULT_INVALID_ARGUMENT;
  350.   // Decrement ref count
  351.   VXIulong refs = 0;
  352.   if ((*thread)->refCountMutex) {
  353.     VXItrdMutexLock ((*thread)->refCountMutex);
  354.     (*thread)->refCount--;
  355.     refs = (*thread)->refCount;
  356.     VXItrdMutexUnlock ((*thread)->refCountMutex);
  357.   }
  358.   if (refs == 0) {
  359.     // No longer needed
  360.     if ((*thread)->refCountMutex)
  361.       VXItrdMutexDestroy (&(*thread)->refCountMutex);
  362.     delete *thread;
  363.   }
  364.   *thread = NULL;
  365.   return VXItrd_RESULT_SUCCESS;
  366. }
  367. /**
  368.  * Terminate a thread.  Called by the thread on exit.
  369.  *
  370.  * @param  status  Exit code for the thread
  371.  * @result           N/A, never returns
  372.  */
  373. VXITRD_API void VXItrdThreadExit(VXItrdThreadArg status)
  374. {
  375.   pthread_exit(status);
  376. }
  377. /**
  378.  * Causes the calling thread to wait for the termination of a specified
  379.  *   'thread' with a specified timeout, in milliseconds. 
  380.  *
  381.  * @param   thread the 'thread' that is waited for its termination.
  382.  * @param   status contains the exit value of the thread's start routine.
  383.  * @return  VXItrdResult of operation.  Return SUCCESS if specified 'thread' 
  384.  *          terminating.
  385.  */
  386. VXITRD_API VXItrdResult VXItrdThreadJoin(VXItrdThread *thread,
  387.  VXItrdThreadArg *status,
  388.  long timeout)
  389. {
  390.   if ((thread == NULL ) || (status == NULL) || (timeout < -1))
  391.     return VXItrd_RESULT_INVALID_ARGUMENT;
  392.   VXItrdResult rc = VXItrd_RESULT_SUCCESS;
  393.   if (timeout == -1) {
  394.     // Wait forever
  395.     if (pthread_join(thread->thread, status) != 0)
  396.       rc = VXItrd_RESULT_SYSTEM_ERROR;
  397.   } else {
  398.     // Wait with a timeout, we just do a polling implementation
  399.     long remainingMsec = timeout;
  400.     while ((remainingMsec > 0) && (thread->state != STATE_EXITED) &&
  401.            (rc == VXItrd_RESULT_SUCCESS)) {
  402.       if (remainingMsec > 50) {
  403.         rc = VXItrdSleep (50);
  404.         remainingMsec -= 50;
  405.       } else {
  406.         rc = VXItrdSleep (remainingMsec);
  407.         remainingMsec = 0;
  408.       }
  409.     }
  410.     if (rc == VXItrd_RESULT_SUCCESS) {
  411.       if (thread->state == STATE_EXITED) {
  412.         // Collect the thread
  413.         if (pthread_join(thread->thread, status) != 0)
  414.           rc = VXItrd_RESULT_SYSTEM_ERROR;
  415.       } else {
  416.         rc = VXItrd_RESULT_FAILURE;
  417.       }
  418.     }
  419.   }
  420.   return rc;
  421. }
  422. /**
  423.  * Get the thread ID for the specified thread
  424.  *
  425.  * @param  thread   Handle to the thread to get the ID for
  426.  *
  427.  * @result   Thread ID number
  428.  */
  429. VXITRD_API VXIthreadID VXItrdThreadGetIDFromHandle(VXItrdThread *thread)
  430. {
  431.   if (thread == NULL) 
  432.     return (VXIthreadID) -1;
  433.   return thread->thread;
  434. }
  435. /**
  436.  * Get the ID of the current handle.
  437.  *
  438.  * @return  The current thread handle identifier.
  439.  *
  440.  */
  441. VXITRD_API VXIthreadID VXItrdThreadGetID(void)
  442. {
  443.   return pthread_self(); 
  444. }
  445. /**
  446.  * Purpose Yield the process schedule in the current thread.
  447.  *
  448.  * @return  void
  449.  *
  450.  */
  451. VXITRD_API void VXItrdThreadYield(void)
  452. {
  453. #ifndef NDEBUG
  454.   assert (sched_yield() == 0);
  455. #else
  456.   sched_yield();
  457. #endif
  458. }
  459. /**
  460.  * Create a timer
  461.  *
  462.  * @param   timer  a pointer to a timer
  463.  * @return  VXItrdResult of operation.  Return SUCCESS if timer has been 
  464.  *          created
  465.  *
  466.  */
  467. VXITRD_API VXItrdResult VXItrdTimerCreate(VXItrdTimer **timer)
  468. {
  469.   if (timer == NULL) 
  470.     return VXItrd_RESULT_INVALID_ARGUMENT;
  471.   
  472.   VXItrdTimer *result = new VXItrdTimer;
  473.   if (result == NULL)
  474.     return VXItrd_RESULT_OUT_OF_MEMORY;
  475.   // Initialize all data
  476.   result->isSleeping = FALSE;
  477.   result->wakeUp = FALSE;
  478.   *timer = result;
  479.   return VXItrd_RESULT_SUCCESS;
  480. }
  481. /**
  482.  * Destroy a timer
  483.  *
  484.  * @param   timer  a pointer to a timer
  485.  * @return  VXItrdResult of operation.  Return SUCCESS if timer has been 
  486.  *          created
  487.  *
  488.  */
  489. VXITRD_API VXItrdResult VXItrdTimerDestroy(VXItrdTimer **timer)
  490. {
  491.   if ((timer == NULL) || (*timer == NULL))
  492.     return VXItrd_RESULT_INVALID_ARGUMENT;
  493.   // Don't leave the corresponding thread in a suspended state.
  494.   VXItrdResult rc = VXItrd_RESULT_SUCCESS;
  495.   if ((*timer)->isSleeping) {
  496.     VXItrdTimerWake(*timer);
  497.     
  498.     // Wait for the sleeping thread to wake up, note that on some OSes
  499.     // like Linux the timeout is modified to give the actual amount of
  500.     // time slept so need to re-initialize each time
  501.     while (((*timer)->isSleeping) && 
  502.            ((rc = VXItrdSleep (50)) == VXItrd_RESULT_SUCCESS))
  503.       ; // keep going
  504.   }
  505.   delete *timer;
  506.   *timer = NULL;
  507.   return rc;
  508. }
  509. /**
  510.  * Puts the current thread to sleep for a configurable duration.
  511.  *    Due to other activities of the machine, the delay is the minimum
  512.  *    length that the timer will wait.
  513.  *
  514.  * @param   timer  a pointer to a timer
  515.  * @param   millisecondDelay  the minimum number of milliseconds to wait
  516.  * @param   interrupted  a pointer (may optionally be NULL) indicating whether
  517.  *            or not the sleep was interrupted by VXItrdTimerWake.
  518.  * @return  VXItrdResult of operation.  Return SUCCESS if timer could sleep.
  519.  *
  520.  */
  521. VXITRD_API VXItrdResult VXItrdTimerSleep(VXItrdTimer *timer,
  522.  VXIint millisecondDelay,
  523.  VXIbool *interrupted)
  524. {
  525.   if ((timer == NULL) || (millisecondDelay < 0)) 
  526.     return VXItrd_RESULT_INVALID_ARGUMENT;
  527.  
  528.   if (timer->isSleeping == TRUE)
  529.     return VXItrd_RESULT_FATAL_ERROR;
  530.   timer->isSleeping = TRUE;
  531.   // Sleep, we just do a polling implementation
  532.   VXItrdResult rc = VXItrd_RESULT_SUCCESS;
  533.   VXIint remainingMsec = millisecondDelay;
  534.   while ((remainingMsec > 0) && (timer->wakeUp == FALSE) &&
  535.          (rc == VXItrd_RESULT_SUCCESS)) {
  536.     if (remainingMsec > 50) {
  537.       rc = VXItrdSleep (50);
  538.       remainingMsec -= 50;
  539.     } else {
  540.       rc = VXItrdSleep (remainingMsec);
  541.       remainingMsec = 0;
  542.     }
  543.   }
  544.   if (timer->wakeUp) {
  545.     if (interrupted)
  546.       *interrupted = TRUE;
  547.     timer->wakeUp = FALSE;
  548.   } else if (interrupted) {
  549.     *interrupted = FALSE;
  550.   }
  551.   timer->isSleeping = FALSE;
  552.   return VXItrd_RESULT_SUCCESS;
  553. }
  554. /**
  555.  * Wakes a sleeping thread, if the target is not already sleeping
  556.  *    it immediately wakes when it tries to sleep the next time.
  557.  *
  558.  * @param   timer  a pointer to a timer
  559.  * @return  VXItrdResult of operation.  Return SUCCESS if timer could wake.
  560.  *
  561.  */
  562. VXITRD_API VXItrdResult VXItrdTimerWake(VXItrdTimer *timer)
  563. {
  564.   if (timer == NULL) 
  565.     return VXItrd_RESULT_INVALID_ARGUMENT;
  566.   timer->wakeUp = TRUE;
  567.   return VXItrd_RESULT_SUCCESS;
  568. }
  569. /**
  570.  * Initialize the TRD utilities library
  571.  *
  572.  * @param threadStackSize  Stack size to use when creating new threads.
  573.  *                         Pass 0 to use the default (OS-specific) size,
  574.  *                         usually this means new threads will use the
  575.  *                         same stack size as the main (parent) process.
  576.  *
  577.  * @return VXItrd_RESULT_SUCCESS if sucess, different value on failure
  578.  */
  579. VXITRD_API VXItrdResult VXItrdInit (VXIint32 threadStackSize)
  580. {
  581.   g_threadStackSize = threadStackSize;
  582.   return VXItrd_RESULT_SUCCESS;
  583. }
  584. /**
  585.  * Shutdown the TRD utilities library
  586.  *
  587.  * @return VXItrd_RESULT_SUCCESS if sucess, different value on failure
  588.  */
  589. VXITRD_API VXItrdResult VXItrdShutDown ()
  590. {
  591.   return VXItrd_RESULT_SUCCESS;
  592. }