dn_thread.c
Go to the documentation of this file.
1 
25 #include "stdint.h"
26 #include <stdlib.h>
27 
28 #if defined(_USE_WIN_API)
29 #include <process.h>
30 #include <windows.h>
31 #elif defined(_USE_LINUX_API)
32 #include <errno.h>
33 #include <pthread.h>
34 #include <time.h>
35 #include <sys/time.h>
36 #else
37 #include "dn_additional.h"
38 #endif
39 
40 #include "dn_common.h"
41 #include "dn_thread.h"
42 
43 #if defined(_USE_LINUX_API)
44 
50 static HRESULT create_timeout(struct timespec *spec, uint32_t timeout)
51 {
52  uint32_t tmp_usec;
53  struct timeval cur;
54 
55  /* Gets current time */
56  gettimeofday(&cur, NULL);
57 
58  /* Sets timeout seconds */
59  spec->tv_sec = cur.tv_sec + (timeout / 1000);
60 
61  /* Temporary calcurates timeout microseconds */
62  tmp_usec = cur.tv_usec + ((timeout % 1000) * 1000);
63 
64  /* Adds timeout seconds */
65  spec->tv_sec += (tmp_usec / 1000000);
66 
67  /* Sets timeout nanoseconds */
68  spec->tv_nsec = (tmp_usec % 1000000) * 1000;
69 
70  return S_OK;
71 }
72 #endif
73 
79 HRESULT
81 {
82  HRESULT hr = S_OK;
83 
84  if (pmutex == NULL)
85  return E_INVALIDARG;
86 
87 #if defined(_USE_WIN_API)
88  *pmutex = CreateMutex(NULL, FALSE, NULL);
89  if(*pmutex == NULL) {
90  hr = E_UNEXPECTED;
91  }
92 #elif defined(_USE_LINUX_API)
93  pthread_mutex_init(pmutex, NULL);
94 #else
95  hr = _initialize_mutex(pmutex);
96 #endif
97 
98  return hr;
99 }
100 
107 HRESULT
109 {
110  HRESULT hr = S_OK;
111 
112  if (pmutex == NULL)
113  return E_INVALIDARG;
114 
115 #if defined(_USE_WIN_API)
116  if(*pmutex != NULL) {
117  BOOL ret;
118  ret = CloseHandle(*pmutex);
119  if(ret != 0) {
120  *pmutex = NULL;
121  } else {
122  hr = E_ACCESSDENIED;
123  }
124  }
125 #elif defined(_USE_LINUX_API)
126  int ret;
127  ret = pthread_mutex_destroy(pmutex);
128  if(ret != 0) {
129  hr = E_ACCESSDENIED;
130  }
131 #else
132  hr = _release_mutex(pmutex);
133 #endif
134 
135  return hr;
136 }
137 
144 HRESULT
145 lock_mutex(MUTEX *pmutex, uint32_t timeout)
146 {
147  HRESULT hr = E_INVALIDARG;
148 
149  if (pmutex != NULL) {
150 #if defined(_USE_WIN_API)
151  if(*pmutex != NULL) {
152  DWORD dwRet = WaitForSingleObject(*pmutex, timeout);
153  if(dwRet == WAIT_OBJECT_0) {
154  hr = S_OK;
155  } else {
156  hr = E_TIMEOUT;
157  }
158  }
159 #elif defined(_USE_LINUX_API)
160  int ret;
161  if(timeout == INFINITE) {
162  ret = pthread_mutex_lock(pmutex);
163  } else {
164  struct timespec spec;
165  create_timeout(&spec, timeout);
166  ret = pthread_mutex_timedlock(pmutex, &spec);
167  }
168  if(ret == 0) {
169  hr = S_OK;
170  }
171  else if(ret == ETIMEDOUT) {
172  hr = E_TIMEOUT;
173  }
174 #else
175  hr = _lock_mutex(pmutex, timeout);
176 #endif
177  }
178 
179  return hr;
180 }
181 
187 HRESULT
189 {
190  HRESULT hr = E_INVALIDARG;
191 
192  if (pmutex != NULL) {
193 #if defined(_USE_WIN_API)
194  if(*pmutex != NULL) {
195  ReleaseMutex(*pmutex);
196  hr = S_OK;
197  }
198 #elif defined(_USE_LINUX_API)
199  int ret;
200  ret = pthread_mutex_unlock(pmutex);
201  if(ret == 0) {
202  hr = S_OK;
203  }
204 #else
205  hr = _unlock_mutex(pmutex);
206 #endif
207  }
208 
209  return hr;
210 }
211 
219 HRESULT
220 create_event(EVENT *pevt, int reset_mode, int init_signal)
221 {
222  HRESULT hr = S_OK;
223 
224  if (pevt == NULL)
225  return E_INVALIDARG;
226 
227 #if defined(_USE_WIN_API)
228  *pevt = CreateEvent(NULL, reset_mode, init_signal, NULL);
229  if(*pevt == NULL) {
230  hr = E_UNEXPECTED;
231  }
232 #elif defined(_USE_LINUX_API)
233  pthread_mutex_init(&pevt->mutex, NULL);
234  pthread_cond_init(&pevt->cond, NULL);
235  pevt->mode = (reset_mode != 0);
236  pevt->signal = (init_signal != 0);
237 #else
238  hr = _create_event(pevt, reset_mode, init_signal);
239 #endif
240 
241  return hr;
242 }
243 
250 HRESULT
252 {
253  HRESULT hr = S_OK;
254 
255  if (pevt == NULL)
256  return E_INVALIDARG;
257 
258 #if defined(_USE_WIN_API)
259  if(*pevt != NULL) {
260  BOOL ret;
261  ret = CloseHandle(*pevt);
262  if(ret != 0) {
263  *pevt = NULL;
264  } else {
265  hr = E_ACCESSDENIED;
266  }
267  }
268 #elif defined(_USE_LINUX_API)
269  int ret;
270  ret = pthread_mutex_destroy(&pevt->mutex);
271  if(ret != 0) {
272  return E_ACCESSDENIED;
273  }
274 
275  ret = pthread_cond_destroy(&pevt->cond);
276  if(ret != 0) {
277  return E_ACCESSDENIED;
278  }
279 
280  pevt->mode = 0;
281  pevt->signal = 0;
282 #else
283  hr = _destroy_event(pevt);
284 #endif
285 
286  return hr;
287 }
288 
294 HRESULT
296 {
297  HRESULT hr = E_INVALIDARG;
298 
299  if (pevt != NULL) {
300 #if defined(_USE_WIN_API)
301  if(*pevt != NULL) {
302  SetEvent(*pevt);
303  hr = S_OK;
304  }
305 #elif defined(_USE_LINUX_API)
306  int ret;
307  ret = pthread_mutex_lock(&pevt->mutex);
308  if(ret == 0) {
309  pthread_cond_broadcast(&pevt->cond);
310  pevt->signal = 1;
311  pthread_mutex_unlock(&pevt->mutex);
312  hr = S_OK;
313  }
314 #else
315  hr = _set_event(pevt);
316 #endif
317  }
318 
319  return hr;
320 }
321 
327 HRESULT
329 {
330  HRESULT hr = E_INVALIDARG;
331 
332  if (pevt != NULL) {
333 #if defined(_USE_WIN_API)
334  if(*pevt != NULL) {
335  ResetEvent(*pevt);
336  hr = S_OK;
337  }
338 #elif defined(_USE_LINUX_API)
339  int ret;
340  ret = pthread_mutex_lock(&pevt->mutex);
341  if(ret == 0) {
342  pevt->signal = 0;
343  pthread_mutex_unlock(&pevt->mutex);
344  hr = S_OK;
345  }
346 #else
347  hr = _reset_event(pevt);
348 #endif
349  }
350 
351  return hr;
352 }
353 
360 HRESULT
361 wait_event(EVENT *pevt, uint32_t timeout)
362 {
363  HRESULT hr = E_INVALIDARG;
364 
365  if (pevt != NULL) {
366 #if defined(_USE_WIN_API)
367  if(*pevt != NULL) {
368  DWORD dwRet = WaitForSingleObject(*pevt, timeout);
369  if(dwRet == WAIT_OBJECT_0) {
370  hr = S_OK;
371  } else {
372  hr = E_TIMEOUT;
373  }
374  }
375 #elif defined(_USE_LINUX_API)
376  int ret;
377  if(timeout == INFINITE) {
378  ret = pthread_mutex_lock(&pevt->mutex);
379  if(ret == 0) {
380  if(pevt->signal == 0) {
381  pthread_cond_wait(&pevt->cond, &pevt->mutex);
382  }
383  if(pevt->mode == 0) {
384  pevt->signal = 0;
385  }
386  pthread_mutex_unlock(&pevt->mutex);
387  }
388  } else {
389  ret = pthread_mutex_lock(&pevt->mutex);
390  if(ret == 0) {
391  if(pevt->signal == 0) {
392  struct timespec spec;
393  create_timeout(&spec, timeout);
394  ret = pthread_cond_timedwait(&pevt->cond, &pevt->mutex, &spec);
395  }
396  if((ret == 0) && (pevt->mode == 0)) {
397  pevt->signal = 0;
398  }
399  pthread_mutex_unlock(&pevt->mutex);
400  }
401  }
402  if(ret == 0) {
403  hr = S_OK;
404  }
405  else if(ret == ETIMEDOUT) {
406  hr = E_TIMEOUT;
407  }
408 #else
409  hr = _wait_event(pevt, timeout);
410 #endif
411  }
412 
413  return hr;
414 }
415 
416 #if defined(_USE_LINUX_API)
417 struct multi_arg
418 {
419  EVENT **pevt;
420  HRESULT hr;
421  uint32_t count;
422  uint32_t index;
423  uint32_t timeout;
424  uint32_t stamp;
425  int wait_all;
426  volatile int *flag_all;
427 };
428 
429 static void *_wait_event_multi(void *arg)
430 {
431  uint32_t start, end;
432  struct multi_arg *parg = (struct multi_arg *)arg;
433 
434  /* Initializes return value */
435  parg->hr = E_TIMEOUT;
436  parg->stamp = 0;
437 
438  /* Sets start time */
439  start = gettimeofday_msec();
440 
441  /* Waits single event object */
442  while(*parg->flag_all) {
443  parg->hr = wait_event(parg->pevt[parg->index], 1);
444 
445  /* Gets finished time */
446  end = gettimeofday_msec();
447 
448  if(SUCCEEDED(parg->hr) || (parg->hr != E_TIMEOUT)) {
449  /* Sets finished time to return value */
450  parg->stamp = end;
451  break;
452  }
453 
454  /* Checks timeout */
455  if((parg->timeout != INFINITE) && (calc_time_diff(start, end) >= parg->timeout)) {
456  break;
457  }
458  }
459 
460  if(parg->wait_all == 0) {
461  /* Signals all event objects */
462  *parg->flag_all = 0;
463  }
464 
465  return arg;
466 }
467 #endif
468 
477 HRESULT
478 wait_event_multi(EVENT **pevt, uint32_t count, uint32_t timeout, int wait_all)
479 {
480  HRESULT hr = E_INVALIDARG;
481 
482  if (pevt != NULL) {
483 #if defined(_USE_WIN_API)
484  if(*pevt != NULL) {
485  uint32_t i;
486  DWORD dwRet;
487  HANDLE *evts = (HANDLE *)malloc(count * sizeof(HANDLE));
488 
489  if(evts == NULL) {
490  hr = E_OUTOFMEMORY;
491  goto exit_proc;
492  }
493 
494  if(count == 0) {
495  hr = E_INVALIDARG;
496  goto exit_proc;
497  }
498 
499  for(i = 0; i < count; i++) {
500  evts[i] = *pevt[i];
501  }
502 
503  dwRet = WaitForMultipleObjects(count, evts, wait_all, timeout);
504  if(dwRet < WAIT_OBJECT_0 + count) {
505  hr = dwRet;
506  } else {
507  hr = E_TIMEOUT;
508  }
509 
510 exit_proc:
511  if(evts != NULL) {
512  free(evts);
513  }
514  }
515 #elif defined(_USE_LINUX_API)
516  volatile int flag_all = 1;
517  uint32_t i, min_index = (uint32_t)-1,
518  base_stamp, diff_stamp, min_stamp = (uint32_t)-1;
519  THREAD *pthread = (THREAD *)malloc(count * sizeof(THREAD));
520  struct multi_arg *pret, *parg = (struct multi_arg *)malloc(count * sizeof(struct multi_arg));
521 
522  if((pthread == NULL) || (parg == NULL)) {
523  hr = E_OUTOFMEMORY;
524  goto exit_proc;
525  }
526 
527  if(count == 0) {
528  hr = E_INVALIDARG;
529  goto exit_proc;
530  }
531 
532  /* Sets base time */
533  base_stamp = gettimeofday_msec();
534 
535  /* Waits single event object */
536  for(i = 0; i < count; i++) {
537  parg[i].pevt = pevt;
538  parg[i].count = count;
539  parg[i].index = i;
540  parg[i].timeout = timeout;
541  parg[i].wait_all = wait_all;
542  parg[i].flag_all = &flag_all;
543  pthread_create(&pthread[i], NULL, _wait_event_multi, &parg[i]);
544  }
545 
546  /* Checks result */
547  hr = S_OK;
548  for(i = 0; i < count; i++) {
549  pthread_join(pthread[i], (void **)&pret);
550 
551  if(SUCCEEDED(pret->hr)) {
552  diff_stamp = calc_time_diff(base_stamp, pret->stamp);
553  if(diff_stamp < min_stamp) {
554  min_index = i;
555  min_stamp = diff_stamp;
556  }
557  } else {
558  hr = pret->hr;
559  }
560  }
561 
562  if(wait_all == 0) {
563  if(min_index != (uint32_t)-1) {
564  hr = WAIT_OBJECT_0 + min_index;
565  }
566  }
567 
568 exit_proc:
569  if(pthread != NULL) {
570  free(pthread);
571  }
572 
573  if(parg != NULL) {
574  free(parg);
575  }
576 #else
577  hr = _wait_event_multi(pevt, count, timeout, wait_all);
578 #endif
579  }
580 
581  return hr;
582 }
583 
588 uint32_t
590 {
591 #if defined(_USE_WIN_API)
592  return GetTickCount();
593 #elif defined(_USE_LINUX_API)
594  struct timeval tv;
595  gettimeofday(&tv, NULL);
596  return (uint32_t)(tv.tv_sec * 1e+3 + tv.tv_usec * 1e-3);
597 #else
598  return _gettimeofday_msec();
599 #endif
600 }
static int32_t _release_mutex(MUTEX *pmutex)
static int32_t _lock_mutex(MUTEX *pmutex, uint32_t timeout)
HRESULT wait_event_multi(EVENT **pevt, uint32_t count, uint32_t timeout, int wait_all)
Waits multiple events.
Definition: dn_thread.c:478
static int32_t _wait_event_multi(EVENT **pevt, uint32_t count, uint32_t timeout, int wait_all)
unsigned uint32_t
Definition: stdint.h:43
long tv_sec
Definition: dn_additional.h:56
static int32_t _reset_event(EVENT *pevt)
#define S_OK
Succeeded.
Definition: dn_common.h:89
static int32_t _initialize_mutex(MUTEX *pmutex)
HRESULT destroy_event(EVENT *pevt)
Destroys a event object.
Definition: dn_thread.c:251
Thread and mutex API file.
#define calc_time_diff(start, end)
A macro that calculates the time difference between start and end.
Definition: dn_thread.h:199
#define E_ACCESSDENIED
Failed because the resource is not ready.
Definition: dn_common.h:113
int THREAD
#define E_INVALIDARG
Failed because some arguments are invalid.
Definition: dn_common.h:131
int MUTEX
HRESULT set_event(EVENT *pevt)
Sets a event.
Definition: dn_thread.c:295
long tv_usec
Definition: dn_additional.h:57
static uint32_t _gettimeofday_msec()
uint32_t gettimeofday_msec()
Gets the current time value [ms].
Definition: dn_thread.c:589
int32_t HRESULT
Definition: dn_common.h:61
#define E_UNEXPECTED
Failed because unexpected error happens.
Definition: dn_common.h:137
HRESULT release_mutex(MUTEX *pmutex)
Releases mutex handle.
Definition: dn_thread.c:108
#define E_OUTOFMEMORY
Failed because there is no enough memory space.
Definition: dn_common.h:125
#define SUCCEEDED(hr)
A macro that returns TRUE/FALSE. If hr is zero or more, then returns TRUE.
Definition: dn_common.h:71
static int32_t _create_event(EVENT *pevt, int reset_mode, int init_signal)
Common API file.
int EVENT
#define INFINITE
A definition for infinite wait.
Definition: dn_thread.h:95
User own API file.
HRESULT initialize_mutex(MUTEX *pmutex)
Initializes mutex handle.
Definition: dn_thread.c:80
static int32_t _destroy_event(EVENT *pevt)
HRESULT reset_event(EVENT *pevt)
Resets a event.
Definition: dn_thread.c:328
#define WAIT_OBJECT_0
static int32_t _wait_event(EVENT *pevt, uint32_t timeout)
HRESULT wait_event(EVENT *pevt, uint32_t timeout)
Waits a event.
Definition: dn_thread.c:361
HRESULT unlock_mutex(MUTEX *pmutex)
Unlocks mutex handle.
Definition: dn_thread.c:188
HRESULT create_event(EVENT *pevt, int reset_mode, int init_signal)
Creates a event object.
Definition: dn_thread.c:220
static int32_t _unlock_mutex(MUTEX *pmutex)
#define E_TIMEOUT
Failed because the communication timed out.
Definition: dn_common.h:169
static int32_t _set_event(EVENT *pevt)
HRESULT lock_mutex(MUTEX *pmutex, uint32_t timeout)
Locks mutex handle.
Definition: dn_thread.c:145


bcap_core
Author(s): DENSO WAVE INCORPORATED
autogenerated on Mon Jun 10 2019 13:12:20