dn_thread.c
Go to the documentation of this file.
00001 
00025 #include "stdint.h"
00026 #include <stdlib.h>
00027 
00028 #if defined(_USE_WIN_API)
00029 #include <process.h>
00030 #include <windows.h>
00031 #elif defined(_USE_LINUX_API)
00032 #include <errno.h>
00033 #include <pthread.h>
00034 #include <time.h>
00035 #include <sys/time.h>
00036 #else
00037 #include "dn_additional.h"
00038 #endif
00039 
00040 #include "dn_common.h"
00041 #include "dn_thread.h"
00042 
00043 #if defined(_USE_LINUX_API)
00044 
00050 static HRESULT create_timeout(struct timespec *spec, uint32_t timeout)
00051 {
00052   uint32_t tmp_usec;
00053   struct timeval cur;
00054 
00055   /* Gets current time */
00056   gettimeofday(&cur, NULL);
00057 
00058   /* Sets timeout seconds */
00059   spec->tv_sec = cur.tv_sec + (timeout / 1000);
00060 
00061   /* Temporary calcurates timeout microseconds */
00062   tmp_usec = cur.tv_usec + ((timeout % 1000) * 1000);
00063 
00064   /* Adds timeout seconds */
00065   spec->tv_sec += (tmp_usec / 1000000);
00066 
00067   /* Sets timeout nanoseconds */
00068   spec->tv_nsec = (tmp_usec % 1000000) * 1000;
00069 
00070   return S_OK;
00071 }
00072 #endif
00073 
00079 HRESULT
00080 initialize_mutex(MUTEX *pmutex)
00081 {
00082   HRESULT hr = S_OK;
00083 
00084   if (pmutex == NULL)
00085     return E_INVALIDARG;
00086 
00087 #if defined(_USE_WIN_API)
00088   *pmutex = CreateMutex(NULL, FALSE, NULL);
00089   if(*pmutex == NULL) {
00090     hr = E_UNEXPECTED;
00091   }
00092 #elif defined(_USE_LINUX_API)
00093   pthread_mutex_init(pmutex, NULL);
00094 #else
00095   hr = _initialize_mutex(pmutex);
00096 #endif
00097 
00098   return hr;
00099 }
00100 
00107 HRESULT
00108 release_mutex(MUTEX *pmutex)
00109 {
00110   HRESULT hr = S_OK;
00111 
00112   if (pmutex == NULL)
00113     return E_INVALIDARG;
00114 
00115 #if defined(_USE_WIN_API)
00116   if(*pmutex != NULL) {
00117     BOOL ret;
00118     ret = CloseHandle(*pmutex);
00119     if(ret != 0) {
00120       *pmutex = NULL;
00121     } else {
00122       hr = E_ACCESSDENIED;
00123     }
00124   }
00125 #elif defined(_USE_LINUX_API)
00126   int ret;
00127   ret = pthread_mutex_destroy(pmutex);
00128   if(ret != 0) {
00129     hr = E_ACCESSDENIED;
00130   }
00131 #else
00132   hr = _release_mutex(pmutex);
00133 #endif
00134 
00135   return hr;
00136 }
00137 
00144 HRESULT
00145 lock_mutex(MUTEX *pmutex, uint32_t timeout)
00146 {
00147   HRESULT hr = E_INVALIDARG;
00148 
00149   if (pmutex != NULL) {
00150 #if defined(_USE_WIN_API)
00151     if(*pmutex != NULL) {
00152       DWORD dwRet = WaitForSingleObject(*pmutex, timeout);
00153       if(dwRet == WAIT_OBJECT_0) {
00154         hr = S_OK;
00155       } else {
00156         hr = E_TIMEOUT;
00157       }
00158     }
00159 #elif defined(_USE_LINUX_API)
00160     int ret;
00161     if(timeout == INFINITE) {
00162       ret = pthread_mutex_lock(pmutex);
00163     } else {
00164       struct timespec spec;
00165       create_timeout(&spec, timeout);
00166       ret = pthread_mutex_timedlock(pmutex, &spec);
00167     }
00168     if(ret == 0) {
00169       hr = S_OK;
00170     }
00171     else if(ret == ETIMEDOUT) {
00172       hr = E_TIMEOUT;
00173     }
00174 #else
00175     hr = _lock_mutex(pmutex, timeout);
00176 #endif
00177   }
00178 
00179   return hr;
00180 }
00181 
00187 HRESULT
00188 unlock_mutex(MUTEX *pmutex)
00189 {
00190   HRESULT hr = E_INVALIDARG;
00191 
00192   if (pmutex != NULL) {
00193 #if defined(_USE_WIN_API)
00194     if(*pmutex != NULL) {
00195       ReleaseMutex(*pmutex);
00196       hr = S_OK;
00197     }
00198 #elif defined(_USE_LINUX_API)
00199     int ret;
00200     ret = pthread_mutex_unlock(pmutex);
00201     if(ret == 0) {
00202       hr = S_OK;
00203     }
00204 #else
00205     hr = _unlock_mutex(pmutex);
00206 #endif
00207   }
00208 
00209   return hr;
00210 }
00211 
00219 HRESULT
00220 create_event(EVENT *pevt, int reset_mode, int init_signal)
00221 {
00222   HRESULT hr = S_OK;
00223 
00224   if (pevt == NULL)
00225     return E_INVALIDARG;
00226 
00227 #if defined(_USE_WIN_API)
00228   *pevt = CreateEvent(NULL, reset_mode, init_signal, NULL);
00229   if(*pevt == NULL) {
00230     hr = E_UNEXPECTED;
00231   }
00232 #elif defined(_USE_LINUX_API)
00233   pthread_mutex_init(&pevt->mutex, NULL);
00234   pthread_cond_init(&pevt->cond, NULL);
00235   pevt->mode = (reset_mode != 0);
00236   pevt->signal = (init_signal != 0);
00237 #else
00238   hr = _create_event(pevt, reset_mode, init_signal);
00239 #endif
00240 
00241   return hr;
00242 }
00243 
00250 HRESULT
00251 destroy_event(EVENT *pevt)
00252 {
00253   HRESULT hr = S_OK;
00254 
00255   if (pevt == NULL)
00256     return E_INVALIDARG;
00257 
00258 #if defined(_USE_WIN_API)
00259   if(*pevt != NULL) {
00260       BOOL ret;
00261       ret = CloseHandle(*pevt);
00262       if(ret != 0) {
00263         *pevt = NULL;
00264       } else {
00265         hr = E_ACCESSDENIED;
00266       }
00267     }
00268 #elif defined(_USE_LINUX_API)
00269   int ret;
00270   ret = pthread_mutex_destroy(&pevt->mutex);
00271   if(ret != 0) {
00272     return E_ACCESSDENIED;
00273   }
00274 
00275   ret = pthread_cond_destroy(&pevt->cond);
00276   if(ret != 0) {
00277     return E_ACCESSDENIED;
00278   }
00279 
00280   pevt->mode = 0;
00281   pevt->signal = 0;
00282 #else
00283   hr = _destroy_event(pevt);
00284 #endif
00285 
00286   return hr;
00287 }
00288 
00294 HRESULT
00295 set_event(EVENT *pevt)
00296 {
00297   HRESULT hr = E_INVALIDARG;
00298 
00299   if (pevt != NULL) {
00300 #if defined(_USE_WIN_API)
00301     if(*pevt != NULL) {
00302       SetEvent(*pevt);
00303       hr = S_OK;
00304     }
00305 #elif defined(_USE_LINUX_API)
00306     int ret;
00307     ret = pthread_mutex_lock(&pevt->mutex);
00308     if(ret == 0) {
00309       pthread_cond_broadcast(&pevt->cond);
00310       pevt->signal = 1;
00311       pthread_mutex_unlock(&pevt->mutex);
00312       hr = S_OK;
00313     }
00314 #else
00315     hr = _set_event(pevt);
00316 #endif
00317   }
00318 
00319   return hr;
00320 }
00321 
00327 HRESULT
00328 reset_event(EVENT *pevt)
00329 {
00330   HRESULT hr = E_INVALIDARG;
00331 
00332   if (pevt != NULL) {
00333 #if defined(_USE_WIN_API)
00334     if(*pevt != NULL) {
00335       ResetEvent(*pevt);
00336       hr = S_OK;
00337     }
00338 #elif defined(_USE_LINUX_API)
00339     int ret;
00340     ret = pthread_mutex_lock(&pevt->mutex);
00341     if(ret == 0) {
00342       pevt->signal = 0;
00343       pthread_mutex_unlock(&pevt->mutex);
00344       hr = S_OK;
00345     }
00346 #else
00347     hr = _reset_event(pevt);
00348 #endif
00349   }
00350 
00351   return hr;
00352 }
00353 
00360 HRESULT
00361 wait_event(EVENT *pevt, uint32_t timeout)
00362 {
00363   HRESULT hr = E_INVALIDARG;
00364 
00365   if (pevt != NULL) {
00366 #if defined(_USE_WIN_API)
00367     if(*pevt != NULL) {
00368       DWORD dwRet = WaitForSingleObject(*pevt, timeout);
00369       if(dwRet == WAIT_OBJECT_0) {
00370         hr = S_OK;
00371       } else {
00372         hr = E_TIMEOUT;
00373       }
00374     }
00375 #elif defined(_USE_LINUX_API)
00376     int ret;
00377     if(timeout == INFINITE) {
00378       ret = pthread_mutex_lock(&pevt->mutex);
00379       if(ret == 0) {
00380         if(pevt->signal == 0) {
00381           pthread_cond_wait(&pevt->cond, &pevt->mutex);
00382         }
00383         if(pevt->mode == 0) {
00384           pevt->signal = 0;
00385         }
00386         pthread_mutex_unlock(&pevt->mutex);
00387       }
00388     } else {
00389       ret = pthread_mutex_lock(&pevt->mutex);
00390       if(ret == 0) {
00391         if(pevt->signal == 0) {
00392           struct timespec spec;
00393           create_timeout(&spec, timeout);
00394           ret = pthread_cond_timedwait(&pevt->cond, &pevt->mutex, &spec);
00395         }
00396         if((ret == 0) && (pevt->mode == 0)) {
00397           pevt->signal = 0;
00398         }
00399         pthread_mutex_unlock(&pevt->mutex);
00400       }
00401     }
00402     if(ret == 0) {
00403       hr = S_OK;
00404     }
00405     else if(ret == ETIMEDOUT) {
00406       hr = E_TIMEOUT;
00407     }
00408 #else
00409     hr = _wait_event(pevt, timeout);
00410 #endif
00411   }
00412 
00413   return hr;
00414 }
00415 
00416 #if defined(_USE_LINUX_API)
00417 struct multi_arg
00418 {
00419   EVENT **pevt;
00420   HRESULT hr;
00421   uint32_t count;
00422   uint32_t index;
00423   uint32_t timeout;
00424   uint32_t stamp;
00425   int wait_all;
00426   volatile int *flag_all;
00427 };
00428 
00429 static void *_wait_event_multi(void *arg)
00430 {
00431   uint32_t start, end;
00432   struct multi_arg *parg = (struct multi_arg *)arg;
00433 
00434   /* Initializes return value */
00435   parg->hr = E_TIMEOUT;
00436   parg->stamp = 0;
00437 
00438   /* Sets start time */
00439   start = gettimeofday_msec();
00440 
00441   /* Waits single event object */
00442   while(*parg->flag_all) {
00443     parg->hr = wait_event(parg->pevt[parg->index], 1);
00444 
00445     /* Gets finished time */
00446     end = gettimeofday_msec();
00447 
00448     if(SUCCEEDED(parg->hr) || (parg->hr != E_TIMEOUT)) {
00449       /* Sets finished time to return value */
00450       parg->stamp = end;
00451       break;
00452     }
00453 
00454     /* Checks timeout */
00455     if((parg->timeout != INFINITE) && (calc_time_diff(start, end) >= parg->timeout)) {
00456       break;
00457     }
00458   }
00459 
00460   if(parg->wait_all == 0) {
00461     /* Signals all event objects */
00462     *parg->flag_all = 0;
00463   }
00464 
00465   return arg;
00466 }
00467 #endif
00468 
00477 HRESULT
00478 wait_event_multi(EVENT **pevt, uint32_t count, uint32_t timeout, int wait_all)
00479 {
00480   HRESULT hr = E_INVALIDARG;
00481 
00482   if (pevt != NULL) {
00483 #if defined(_USE_WIN_API)
00484     if(*pevt != NULL) {
00485       uint32_t i;
00486       DWORD dwRet;
00487       HANDLE *evts = (HANDLE *)malloc(count * sizeof(HANDLE));
00488 
00489       if(evts == NULL) {
00490         hr = E_OUTOFMEMORY;
00491         goto exit_proc;
00492       }
00493 
00494       if(count == 0) {
00495         hr = E_INVALIDARG;
00496         goto exit_proc;
00497       }
00498 
00499       for(i = 0; i < count; i++) {
00500         evts[i] = *pevt[i];
00501       }
00502 
00503       dwRet = WaitForMultipleObjects(count, evts, wait_all, timeout);
00504       if(dwRet < WAIT_OBJECT_0 + count) {
00505         hr = dwRet;
00506       } else {
00507         hr = E_TIMEOUT;
00508       }
00509 
00510 exit_proc:
00511       if(evts != NULL) {
00512         free(evts);
00513       }
00514     }
00515 #elif defined(_USE_LINUX_API)
00516     volatile int flag_all = 1;
00517     uint32_t i, min_index = (uint32_t)-1,
00518     base_stamp, diff_stamp, min_stamp = (uint32_t)-1;
00519     THREAD *pthread = (THREAD *)malloc(count * sizeof(THREAD));
00520     struct multi_arg *pret, *parg = (struct multi_arg *)malloc(count * sizeof(struct multi_arg));
00521 
00522     if((pthread == NULL) || (parg == NULL)) {
00523       hr = E_OUTOFMEMORY;
00524       goto exit_proc;
00525     }
00526 
00527     if(count == 0) {
00528       hr = E_INVALIDARG;
00529       goto exit_proc;
00530     }
00531 
00532     /* Sets base time */
00533     base_stamp = gettimeofday_msec();
00534 
00535     /* Waits single event object */
00536     for(i = 0; i < count; i++) {
00537       parg[i].pevt = pevt;
00538       parg[i].count = count;
00539       parg[i].index = i;
00540       parg[i].timeout = timeout;
00541       parg[i].wait_all = wait_all;
00542       parg[i].flag_all = &flag_all;
00543       pthread_create(&pthread[i], NULL, _wait_event_multi, &parg[i]);
00544     }
00545 
00546     /* Checks result */
00547     hr = S_OK;
00548     for(i = 0; i < count; i++) {
00549       pthread_join(pthread[i], (void **)&pret);
00550 
00551       if(SUCCEEDED(pret->hr)) {
00552         diff_stamp = calc_time_diff(base_stamp, pret->stamp);
00553         if(diff_stamp < min_stamp) {
00554           min_index = i;
00555           min_stamp = diff_stamp;
00556         }
00557       } else {
00558         hr = pret->hr;
00559       }
00560     }
00561 
00562     if(wait_all == 0) {
00563       if(min_index != (uint32_t)-1) {
00564         hr = WAIT_OBJECT_0 + min_index;
00565       }
00566     }
00567 
00568 exit_proc:
00569     if(pthread != NULL) {
00570       free(pthread);
00571     }
00572 
00573     if(parg != NULL) {
00574       free(parg);
00575     }
00576 #else
00577     hr = _wait_event_multi(pevt, count, timeout, wait_all);
00578 #endif
00579   }
00580 
00581   return hr;
00582 }
00583 
00588 uint32_t
00589 gettimeofday_msec()
00590 {
00591 #if defined(_USE_WIN_API)
00592   return GetTickCount();
00593 #elif defined(_USE_LINUX_API)
00594   struct timeval tv;
00595   gettimeofday(&tv, NULL);
00596   return (uint32_t)(tv.tv_sec * 1e+3 + tv.tv_usec * 1e-3);
00597 #else
00598   return _gettimeofday_msec();
00599 #endif
00600 }


bcap_core
Author(s): DENSO WAVE INCORPORATED
autogenerated on Thu Jun 6 2019 21:00:03