sema.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2009-2011 Nokia Corporation and/or its subsidiary(-ies).
  3. * All rights reserved.
  4. * This component and the accompanying materials are made available
  5. * under the terms of the License "Eclipse Public License v1.0"
  6. * which accompanies this distribution, and is available
  7. * at the URL "http://www.eclipse.org/legal/epl-v10.html".
  8. *
  9. * Initial Contributors:
  10. * Nokia Corporation - initial contribution.
  11. *
  12. * Contributors:
  13. *
  14. * Description:
  15. *
  16. */
  17. #include "sema.h"
  18. #include "log.h"
  19. // OS specific headers
  20. #ifdef WIN32
  21. #include <windows.h>
  22. #include <tlhelp32.h>
  23. #else
  24. #include <semaphore.h>
  25. #include <sys/types.h>
  26. #include <signal.h>
  27. #include <fcntl.h>
  28. #include <time.h>
  29. #endif
  30. #include <unistd.h>
  31. void sema_create(sbs_semaphore *s)
  32. {
  33. #ifdef WIN32
  34. s->handle = CreateSemaphore(NULL, 1, 1, s->name);
  35. if (s->handle)
  36. CloseHandle(s->handle);
  37. else
  38. error("unable to create semaphore %s", s->name);
  39. #else
  40. s->handle = sem_open(s->name, O_CREAT | O_EXCL, 0644, 1);
  41. if (s->handle == SEM_FAILED)
  42. {
  43. sem_close(s->handle);
  44. error("unable to create semaphore %s", s->name);
  45. }
  46. sem_close(s->handle);
  47. #endif
  48. }
  49. void sema_destroy(sbs_semaphore *s)
  50. {
  51. #ifdef WIN32
  52. /* can't destroy a windows semaphore... */
  53. #else
  54. if (sem_unlink(s->name) != 0)
  55. error("unable to unlink semaphore", s->name);
  56. #endif
  57. }
  58. int sema_wait(sbs_semaphore *s)
  59. {
  60. /* try and open the semaphore now */
  61. #ifdef WIN32
  62. s->handle = CreateSemaphore(NULL, 1, 1, s->name);
  63. if (!s->handle)
  64. {
  65. error("unable to open semaphore %s", s->name);
  66. return -2;
  67. }
  68. #else
  69. struct timespec tmout;
  70. s->handle = sem_open(s->name, 0);
  71. if (s->handle == SEM_FAILED)
  72. {
  73. sem_close(s->handle);
  74. error("unable to open semaphore %s\n", s->name);
  75. return -2;
  76. }
  77. #endif
  78. /* wait for the semaphore to be free [timeout if it takes too long] */
  79. int timedOutFlag = 0;
  80. #ifdef WIN32
  81. timedOutFlag = (WaitForSingleObject(s->handle, s->timeout) != WAIT_OBJECT_0);
  82. #else
  83. int semcount = 0;
  84. sem_getvalue(s->handle, &semcount);
  85. debug("sema: count before wait: %d\n", semcount);
  86. debug("sema: timeout: %d\n", s->timeout);
  87. if (clock_gettime(CLOCK_REALTIME, &tmout) == -1)
  88. {
  89. error("sema: clock_gettime failed - can't do timed wait");
  90. return -1;
  91. }
  92. tmout.tv_sec += (s->timeout / 1000);
  93. tmout.tv_nsec += (s->timeout % 1000) * 1000;
  94. timedOutFlag = sem_timedwait(s->handle, &tmout);
  95. /* roughly speaking the return value indicates timeouts. It also indicated
  96. * signals. We are glossing over this for the moment since it isn't really
  97. * interesting in this application
  98. * */
  99. #endif
  100. return timedOutFlag;
  101. }
  102. void sema_release(sbs_semaphore *s)
  103. {
  104. if (s->handle)
  105. {
  106. /* release the semaphore */
  107. #ifdef WIN32
  108. ReleaseSemaphore(s->handle, 1, NULL);
  109. #else
  110. sem_post(s->handle);
  111. #endif
  112. /* clean up */
  113. #ifdef WIN32
  114. CloseHandle(s->handle);
  115. #else
  116. sem_close(s->handle);
  117. #endif
  118. s->handle = NULL; /* prevent double release */
  119. } else {
  120. error("sema: attempt to release an semaphore that wasn't 'held'");
  121. }
  122. }