thread.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "apr.h"
  17. #include "apr_portable.h"
  18. #include "apr_arch_threadproc.h"
  19. #if APR_HAS_THREADS
  20. #if APR_HAVE_PTHREAD_H
  21. /* Destroy the threadattr object */
  22. static apr_status_t threadattr_cleanup(void *data)
  23. {
  24. apr_threadattr_t *attr = data;
  25. apr_status_t rv;
  26. rv = pthread_attr_destroy(&attr->attr);
  27. #ifdef PTHREAD_SETS_ERRNO
  28. if (rv) {
  29. rv = errno;
  30. }
  31. #endif
  32. return rv;
  33. }
  34. APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new,
  35. apr_pool_t *pool)
  36. {
  37. apr_status_t stat;
  38. (*new) = apr_palloc(pool, sizeof(apr_threadattr_t));
  39. (*new)->pool = pool;
  40. stat = pthread_attr_init(&(*new)->attr);
  41. if (stat == 0) {
  42. apr_pool_cleanup_register(pool, *new, threadattr_cleanup,
  43. apr_pool_cleanup_null);
  44. return APR_SUCCESS;
  45. }
  46. #ifdef PTHREAD_SETS_ERRNO
  47. stat = errno;
  48. #endif
  49. return stat;
  50. }
  51. #define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE)
  52. APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr,
  53. apr_int32_t on)
  54. {
  55. apr_status_t stat;
  56. #ifdef PTHREAD_ATTR_SETDETACHSTATE_ARG2_ADDR
  57. int arg = DETACH_ARG(v);
  58. if ((stat = pthread_attr_setdetachstate(&attr->attr, &arg)) == 0) {
  59. #else
  60. if ((stat = pthread_attr_setdetachstate(&attr->attr,
  61. DETACH_ARG(on))) == 0) {
  62. #endif
  63. return APR_SUCCESS;
  64. }
  65. else {
  66. #ifdef PTHREAD_SETS_ERRNO
  67. stat = errno;
  68. #endif
  69. return stat;
  70. }
  71. }
  72. APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr)
  73. {
  74. int state;
  75. #ifdef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG
  76. state = pthread_attr_getdetachstate(&attr->attr);
  77. #else
  78. pthread_attr_getdetachstate(&attr->attr, &state);
  79. #endif
  80. if (state == 1)
  81. return APR_DETACH;
  82. return APR_NOTDETACH;
  83. }
  84. APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
  85. apr_size_t stacksize)
  86. {
  87. int stat;
  88. stat = pthread_attr_setstacksize(&attr->attr, stacksize);
  89. if (stat == 0) {
  90. return APR_SUCCESS;
  91. }
  92. #ifdef PTHREAD_SETS_ERRNO
  93. stat = errno;
  94. #endif
  95. return stat;
  96. }
  97. APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
  98. apr_size_t size)
  99. {
  100. #ifdef HAVE_PTHREAD_ATTR_SETGUARDSIZE
  101. apr_status_t rv;
  102. rv = pthread_attr_setguardsize(&attr->attr, size);
  103. if (rv == 0) {
  104. return APR_SUCCESS;
  105. }
  106. #ifdef PTHREAD_SETS_ERRNO
  107. rv = errno;
  108. #endif
  109. return rv;
  110. #else
  111. return APR_ENOTIMPL;
  112. #endif
  113. }
  114. static void *dummy_worker(void *opaque)
  115. {
  116. apr_thread_t *thread = (apr_thread_t*)opaque;
  117. #ifdef HAVE_PTHREAD_SETSCHEDPARAM
  118. if (thread->priority) {
  119. int policy;
  120. struct sched_param param = { 0 };
  121. pthread_t tt = pthread_self();
  122. pthread_getschedparam(tt, &policy, &param);
  123. param.sched_priority = thread->priority;
  124. pthread_setschedparam(tt, policy, &param);
  125. }
  126. #endif
  127. return thread->func(thread, thread->data);
  128. }
  129. APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new,
  130. apr_threadattr_t *attr,
  131. apr_thread_start_t func,
  132. void *data,
  133. apr_pool_t *pool)
  134. {
  135. apr_status_t stat;
  136. pthread_attr_t *temp;
  137. pthread_t tt;
  138. (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
  139. if ((*new) == NULL) {
  140. return APR_ENOMEM;
  141. }
  142. (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t));
  143. if ((*new)->td == NULL) {
  144. return APR_ENOMEM;
  145. }
  146. (*new)->pool = pool;
  147. (*new)->data = data;
  148. (*new)->func = func;
  149. if (attr)
  150. temp = &attr->attr;
  151. else
  152. temp = NULL;
  153. stat = apr_pool_create(&(*new)->pool, pool);
  154. if (stat != APR_SUCCESS) {
  155. return stat;
  156. }
  157. if (attr && attr->priority) {
  158. (*new)->priority = attr->priority;
  159. }
  160. if ((stat = pthread_create(&tt, temp, dummy_worker, (*new))) == 0) {
  161. *(*new)->td = tt;
  162. return APR_SUCCESS;
  163. }
  164. else {
  165. #ifdef PTHREAD_SETS_ERRNO
  166. stat = errno;
  167. #endif
  168. return stat;
  169. }
  170. }
  171. APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void)
  172. {
  173. return pthread_self();
  174. }
  175. APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1,
  176. apr_os_thread_t tid2)
  177. {
  178. return pthread_equal(tid1, tid2);
  179. }
  180. APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd,
  181. apr_status_t retval)
  182. {
  183. thd->exitval = retval;
  184. apr_pool_destroy(thd->pool);
  185. pthread_exit(NULL);
  186. return APR_SUCCESS;
  187. }
  188. APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval,
  189. apr_thread_t *thd)
  190. {
  191. apr_status_t stat;
  192. apr_status_t *thread_stat;
  193. if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) {
  194. *retval = thd->exitval;
  195. return APR_SUCCESS;
  196. }
  197. else {
  198. #ifdef PTHREAD_SETS_ERRNO
  199. stat = errno;
  200. #endif
  201. return stat;
  202. }
  203. }
  204. APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd)
  205. {
  206. apr_status_t stat;
  207. #ifdef PTHREAD_DETACH_ARG1_ADDR
  208. if ((stat = pthread_detach(thd->td)) == 0) {
  209. #else
  210. if ((stat = pthread_detach(*thd->td)) == 0) {
  211. #endif
  212. return APR_SUCCESS;
  213. }
  214. else {
  215. #ifdef PTHREAD_SETS_ERRNO
  216. stat = errno;
  217. #endif
  218. return stat;
  219. }
  220. }
  221. void apr_thread_yield()
  222. {
  223. }
  224. APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key,
  225. apr_thread_t *thread)
  226. {
  227. return apr_pool_userdata_get(data, key, thread->pool);
  228. }
  229. APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key,
  230. apr_status_t (*cleanup)(void *),
  231. apr_thread_t *thread)
  232. {
  233. return apr_pool_userdata_set(data, key, cleanup, thread->pool);
  234. }
  235. APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
  236. apr_thread_t *thd)
  237. {
  238. *thethd = thd->td;
  239. return APR_SUCCESS;
  240. }
  241. APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
  242. apr_os_thread_t *thethd,
  243. apr_pool_t *pool)
  244. {
  245. if (pool == NULL) {
  246. return APR_ENOPOOL;
  247. }
  248. if ((*thd) == NULL) {
  249. (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t));
  250. (*thd)->pool = pool;
  251. }
  252. (*thd)->td = thethd;
  253. return APR_SUCCESS;
  254. }
  255. APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
  256. apr_pool_t *p)
  257. {
  258. static const pthread_once_t once_init = PTHREAD_ONCE_INIT;
  259. *control = apr_palloc(p, sizeof(**control));
  260. (*control)->once = once_init;
  261. return APR_SUCCESS;
  262. }
  263. APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
  264. void (*func)(void))
  265. {
  266. return pthread_once(&control->once, func);
  267. }
  268. APR_POOL_IMPLEMENT_ACCESSOR(thread)
  269. #endif /* HAVE_PTHREAD_H */
  270. #endif /* APR_HAS_THREADS */
  271. #if !APR_HAS_THREADS
  272. /* avoid warning for no prototype */
  273. APR_DECLARE(apr_status_t) apr_os_thread_get(void);
  274. APR_DECLARE(apr_status_t) apr_os_thread_get(void)
  275. {
  276. return APR_ENOTIMPL;
  277. }
  278. #endif