threads.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2007 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library 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 GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  17. * Boston, MA 02111-1307, USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include "threads.h"
  22. #include <stdlib.h>
  23. #include <errno.h>
  24. #include "alMain.h"
  25. #include "alThunk.h"
  26. #define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */
  27. #ifdef _WIN32
  28. #define WIN32_LEAN_AND_MEAN
  29. #include <windows.h>
  30. typedef struct althread_info {
  31. ALuint (*func)(ALvoid*);
  32. ALvoid *ptr;
  33. HANDLE hdl;
  34. } althread_info;
  35. static DWORD CALLBACK StarterFunc(void *ptr)
  36. {
  37. althread_info *inf = (althread_info*)ptr;
  38. ALuint ret;
  39. ret = inf->func(inf->ptr);
  40. ExitThread((DWORD)ret);
  41. return (DWORD)ret;
  42. }
  43. ALboolean StartThread(althread_t *thread, ALuint (*func)(ALvoid*), ALvoid *ptr)
  44. {
  45. althread_info *info;
  46. DWORD dummy;
  47. info = malloc(sizeof(*info));
  48. if(!info) return AL_FALSE;
  49. info->func = func;
  50. info->ptr = ptr;
  51. info->hdl = CreateThread(NULL, THREAD_STACK_SIZE, StarterFunc, info, 0, &dummy);
  52. if(!info->hdl)
  53. {
  54. free(info);
  55. return AL_FALSE;
  56. }
  57. *thread = info;
  58. return AL_TRUE;
  59. }
  60. ALuint StopThread(althread_t thread)
  61. {
  62. DWORD ret = 0;
  63. WaitForSingleObject(thread->hdl, INFINITE);
  64. GetExitCodeThread(thread->hdl, &ret);
  65. CloseHandle(thread->hdl);
  66. free(thread);
  67. return (ALuint)ret;
  68. }
  69. void SetThreadName(const char *name)
  70. {
  71. #if defined(_MSC_VER)
  72. #define MS_VC_EXCEPTION 0x406D1388
  73. struct {
  74. DWORD dwType; // Must be 0x1000.
  75. LPCSTR szName; // Pointer to name (in user addr space).
  76. DWORD dwThreadID; // Thread ID (-1=caller thread).
  77. DWORD dwFlags; // Reserved for future use, must be zero.
  78. } info;
  79. info.dwType = 0x1000;
  80. info.szName = name;
  81. info.dwThreadID = -1;
  82. info.dwFlags = 0;
  83. __try {
  84. RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info);
  85. }
  86. __except(EXCEPTION_CONTINUE_EXECUTION) {
  87. }
  88. #undef MS_VC_EXCEPTION
  89. #else
  90. TRACE("Can't set thread %04lx name to \"%s\"\n", GetCurrentThreadId(), name);
  91. #endif
  92. }
  93. #else
  94. #include <pthread.h>
  95. typedef struct althread_info {
  96. ALuint (*func)(ALvoid*);
  97. ALvoid *ptr;
  98. ALuint ret;
  99. pthread_t hdl;
  100. } althread_info;
  101. static void *StarterFunc(void *ptr)
  102. {
  103. althread_info *inf = (althread_info*)ptr;
  104. inf->ret = inf->func(inf->ptr);
  105. return NULL;
  106. }
  107. ALboolean StartThread(althread_t *thread, ALuint (*func)(ALvoid*), ALvoid *ptr)
  108. {
  109. pthread_attr_t attr;
  110. althread_info *info;
  111. info = malloc(sizeof(*info));
  112. if(!info) return AL_FALSE;
  113. if(pthread_attr_init(&attr) != 0)
  114. {
  115. free(info);
  116. return AL_FALSE;
  117. }
  118. if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0)
  119. {
  120. pthread_attr_destroy(&attr);
  121. free(info);
  122. return AL_FALSE;
  123. }
  124. info->func = func;
  125. info->ptr = ptr;
  126. if(pthread_create(&info->hdl, &attr, StarterFunc, info) != 0)
  127. {
  128. pthread_attr_destroy(&attr);
  129. free(info);
  130. return AL_FALSE;
  131. }
  132. pthread_attr_destroy(&attr);
  133. *thread = info;
  134. return AL_TRUE;
  135. }
  136. ALuint StopThread(althread_t thread)
  137. {
  138. ALuint ret;
  139. pthread_join(thread->hdl, NULL);
  140. ret = thread->ret;
  141. free(thread);
  142. return ret;
  143. }
  144. void SetThreadName(const char *name)
  145. {
  146. #if defined(HAVE_PTHREAD_SETNAME_NP)
  147. #if defined(__GNUC__)
  148. if(pthread_setname_np(pthread_self(), name) != 0)
  149. #elif defined(__APPLE__)
  150. if(pthread_setname_np(name) != 0)
  151. #endif
  152. WARN("Failed to set thread name to \"%s\": %s\n", name, strerror(errno));
  153. #elif defined(HAVE_PTHREAD_SET_NAME_NP)
  154. pthread_set_name_np(pthread_self(), name);
  155. #else
  156. TRACE("Can't set thread name to \"%s\"\n", name);
  157. #endif
  158. }
  159. #endif