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
00056 gettimeofday(&cur, NULL);
00057
00058
00059 spec->tv_sec = cur.tv_sec + (timeout / 1000);
00060
00061
00062 tmp_usec = cur.tv_usec + ((timeout % 1000) * 1000);
00063
00064
00065 spec->tv_sec += (tmp_usec / 1000000);
00066
00067
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
00435 parg->hr = E_TIMEOUT;
00436 parg->stamp = 0;
00437
00438
00439 start = gettimeofday_msec();
00440
00441
00442 while(*parg->flag_all) {
00443 parg->hr = wait_event(parg->pevt[parg->index], 1);
00444
00445
00446 end = gettimeofday_msec();
00447
00448 if(SUCCEEDED(parg->hr) || (parg->hr != E_TIMEOUT)) {
00449
00450 parg->stamp = end;
00451 break;
00452 }
00453
00454
00455 if((parg->timeout != INFINITE) && (calc_time_diff(start, end) >= parg->timeout)) {
00456 break;
00457 }
00458 }
00459
00460 if(parg->wait_all == 0) {
00461
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
00533 base_stamp = gettimeofday_msec();
00534
00535
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
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 }