attr.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /* Linuxthreads - a simple clone()-based implementation of Posix */
  2. /* threads for Linux. */
  3. /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
  4. /* */
  5. /* This program is free software; you can redistribute it and/or */
  6. /* modify it under the terms of the GNU Library General Public License */
  7. /* as published by the Free Software Foundation; either version 2 */
  8. /* of the License, or (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU Library General Public License for more details. */
  14. /* Handling of thread attributes */
  15. #include <errno.h>
  16. #include <inttypes.h>
  17. #include <stdio.h>
  18. #include <stdio_ext.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22. #include <sys/param.h>
  23. #include <sys/resource.h>
  24. #include "pthread.h"
  25. #include "internals.h"
  26. int __pthread_attr_init(pthread_attr_t *attr)
  27. {
  28. size_t ps = __getpagesize ();
  29. attr->__detachstate = PTHREAD_CREATE_JOINABLE;
  30. attr->__schedpolicy = SCHED_OTHER;
  31. attr->__schedparam.sched_priority = 0;
  32. attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
  33. attr->__scope = PTHREAD_SCOPE_SYSTEM;
  34. #ifdef NEED_SEPARATE_REGISTER_STACK
  35. attr->__guardsize = ps + ps;
  36. #else
  37. attr->__guardsize = ps;
  38. #endif
  39. attr->__stackaddr = NULL;
  40. attr->__stackaddr_set = 0;
  41. attr->__stacksize = STACK_SIZE - ps;
  42. return 0;
  43. }
  44. strong_alias (__pthread_attr_init, pthread_attr_init)
  45. int __pthread_attr_destroy(pthread_attr_t *attr)
  46. {
  47. return 0;
  48. }
  49. strong_alias (__pthread_attr_destroy, pthread_attr_destroy)
  50. int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
  51. {
  52. if (detachstate < PTHREAD_CREATE_JOINABLE ||
  53. detachstate > PTHREAD_CREATE_DETACHED)
  54. return EINVAL;
  55. attr->__detachstate = detachstate;
  56. return 0;
  57. }
  58. strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate)
  59. int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
  60. {
  61. *detachstate = attr->__detachstate;
  62. return 0;
  63. }
  64. strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate)
  65. int __pthread_attr_setschedparam(pthread_attr_t *attr,
  66. const struct sched_param *param)
  67. {
  68. int max_prio = __sched_get_priority_max(attr->__schedpolicy);
  69. int min_prio = __sched_get_priority_min(attr->__schedpolicy);
  70. if (param->sched_priority < min_prio || param->sched_priority > max_prio)
  71. return EINVAL;
  72. memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
  73. return 0;
  74. }
  75. strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam)
  76. int __pthread_attr_getschedparam(const pthread_attr_t *attr,
  77. struct sched_param *param)
  78. {
  79. memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
  80. return 0;
  81. }
  82. strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam)
  83. int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
  84. {
  85. if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
  86. return EINVAL;
  87. attr->__schedpolicy = policy;
  88. return 0;
  89. }
  90. strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy)
  91. int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
  92. {
  93. *policy = attr->__schedpolicy;
  94. return 0;
  95. }
  96. strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy)
  97. int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
  98. {
  99. if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
  100. return EINVAL;
  101. attr->__inheritsched = inherit;
  102. return 0;
  103. }
  104. strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched)
  105. int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
  106. {
  107. *inherit = attr->__inheritsched;
  108. return 0;
  109. }
  110. strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched)
  111. int __pthread_attr_setscope(pthread_attr_t *attr, int scope)
  112. {
  113. switch (scope) {
  114. case PTHREAD_SCOPE_SYSTEM:
  115. attr->__scope = scope;
  116. return 0;
  117. case PTHREAD_SCOPE_PROCESS:
  118. return ENOTSUP;
  119. default:
  120. return EINVAL;
  121. }
  122. }
  123. strong_alias (__pthread_attr_setscope, pthread_attr_setscope)
  124. int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
  125. {
  126. *scope = attr->__scope;
  127. return 0;
  128. }
  129. strong_alias (__pthread_attr_getscope, pthread_attr_getscope)
  130. int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
  131. {
  132. /* The guard size must not be larger than the stack itself */
  133. if (guardsize >= attr->__stacksize) return EINVAL;
  134. attr->__guardsize = guardsize;
  135. return 0;
  136. }
  137. weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
  138. int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
  139. {
  140. *guardsize = attr->__guardsize;
  141. return 0;
  142. }
  143. weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
  144. #if 0 /* uClibc: deprecated stuff disabled */
  145. int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
  146. {
  147. attr->__stackaddr = stackaddr;
  148. attr->__stackaddr_set = 1;
  149. return 0;
  150. }
  151. weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
  152. int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
  153. {
  154. /* XXX This function has a stupid definition. The standard specifies
  155. no error value but what is if no stack address was set? We simply
  156. return the value we have in the member. */
  157. *stackaddr = attr->__stackaddr;
  158. return 0;
  159. }
  160. weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
  161. #endif
  162. int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
  163. {
  164. #ifdef FLOATING_STACKS
  165. /* We have to check against the maximum allowed stack size. This is no
  166. problem if the manager is already started and we determined it. If
  167. this hasn't happened, we have to find the limit outself. */
  168. if (__pthread_max_stacksize == 0)
  169. __pthread_init_max_stacksize ();
  170. if (stacksize > __pthread_max_stacksize)
  171. return EINVAL;
  172. #else
  173. /* We have a fixed size limit. */
  174. if (stacksize > STACK_SIZE)
  175. return EINVAL;
  176. #endif
  177. /* We don't accept value smaller than PTHREAD_STACK_MIN. */
  178. if (stacksize < PTHREAD_STACK_MIN)
  179. return EINVAL;
  180. attr->__stacksize = stacksize;
  181. return 0;
  182. }
  183. #if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__
  184. weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
  185. #else
  186. versioned_symbol (libpthread, __pthread_attr_setstacksize,
  187. pthread_attr_setstacksize, GLIBC_2_3_3);
  188. # if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3)
  189. int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
  190. {
  191. # ifdef FLOATING_STACKS
  192. /* We have to check against the maximum allowed stack size. This is no
  193. problem if the manager is already started and we determined it. If
  194. this hasn't happened, we have to find the limit outself. */
  195. if (__pthread_max_stacksize == 0)
  196. __pthread_init_max_stacksize ();
  197. if (stacksize > __pthread_max_stacksize)
  198. return EINVAL;
  199. # else
  200. /* We have a fixed size limit. */
  201. if (stacksize > STACK_SIZE)
  202. return EINVAL;
  203. # endif
  204. /* We don't accept value smaller than old PTHREAD_STACK_MIN. */
  205. if (stacksize < 16384)
  206. return EINVAL;
  207. attr->__stacksize = stacksize;
  208. return 0;
  209. }
  210. compat_symbol (libpthread, __old_pthread_attr_setstacksize,
  211. pthread_attr_setstacksize, GLIBC_2_1);
  212. # endif
  213. #endif
  214. int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
  215. {
  216. *stacksize = attr->__stacksize;
  217. return 0;
  218. }
  219. weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
  220. int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
  221. size_t stacksize)
  222. {
  223. int err;
  224. if ((((uintptr_t) stackaddr)
  225. & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
  226. err = EINVAL;
  227. else
  228. err = __pthread_attr_setstacksize (attr, stacksize);
  229. if (err == 0)
  230. {
  231. #ifndef _STACK_GROWS_UP
  232. attr->__stackaddr = (char *) stackaddr + stacksize;
  233. #else
  234. attr->__stackaddr = stackaddr;
  235. #endif
  236. attr->__stackaddr_set = 1;
  237. }
  238. return err;
  239. }
  240. #if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__
  241. weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
  242. #else
  243. versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack,
  244. GLIBC_2_3_3);
  245. # if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
  246. int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
  247. size_t stacksize)
  248. {
  249. int err;
  250. if ((((uintptr_t) stackaddr)
  251. & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
  252. err = EINVAL;
  253. else
  254. err = __old_pthread_attr_setstacksize (attr, stacksize);
  255. if (err == 0)
  256. {
  257. # ifndef _STACK_GROWS_UP
  258. attr->__stackaddr = (char *) stackaddr + stacksize;
  259. # else
  260. attr->__stackaddr = stackaddr;
  261. # endif
  262. attr->__stackaddr_set = 1;
  263. }
  264. return err;
  265. }
  266. compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack,
  267. GLIBC_2_2);
  268. # endif
  269. #endif
  270. int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
  271. size_t *stacksize)
  272. {
  273. /* XXX This function has a stupid definition. The standard specifies
  274. no error value but what is if no stack address was set? We simply
  275. return the value we have in the member. */
  276. #ifndef _STACK_GROWS_UP
  277. *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
  278. #else
  279. *stackaddr = attr->__stackaddr;
  280. #endif
  281. *stacksize = attr->__stacksize;
  282. return 0;
  283. }
  284. weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
  285. int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
  286. {
  287. pthread_handle handle = thread_handle (thread);
  288. pthread_descr descr;
  289. int ret = 0;
  290. if (handle == NULL)
  291. return ENOENT;
  292. descr = handle->h_descr;
  293. attr->__detachstate = (descr->p_detached
  294. ? PTHREAD_CREATE_DETACHED
  295. : PTHREAD_CREATE_JOINABLE);
  296. attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
  297. if (attr->__schedpolicy == -1)
  298. return errno;
  299. if (__sched_getparam (descr->p_pid,
  300. (struct sched_param *) &attr->__schedparam) != 0)
  301. return errno;
  302. attr->__inheritsched = descr->p_inheritsched;
  303. attr->__scope = PTHREAD_SCOPE_SYSTEM;
  304. #ifdef _STACK_GROWS_DOWN
  305. # ifdef __UCLIBC_HAS_TLS__
  306. attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr
  307. - descr->p_guardsize;
  308. # else
  309. attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
  310. - descr->p_guardsize;
  311. # endif
  312. #else
  313. # ifdef __UCLIBC_HAS_TLS__
  314. attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr;
  315. # else
  316. attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
  317. # endif
  318. #endif
  319. attr->__guardsize = descr->p_guardsize;
  320. attr->__stackaddr_set = descr->p_userstack;
  321. #ifdef NEED_SEPARATE_REGISTER_STACK
  322. if (descr->p_userstack == 0)
  323. attr->__stacksize *= 2;
  324. /* XXX This is awkward. The guard pages are in the middle of the
  325. two stacks. We must count the guard size in the stack size since
  326. otherwise the range of the stack area cannot be computed. */
  327. attr->__stacksize += attr->__guardsize;
  328. #endif
  329. #ifdef __UCLIBC_HAS_TLS__
  330. attr->__stackaddr = descr->p_stackaddr;
  331. #else
  332. # ifndef _STACK_GROWS_UP
  333. attr->__stackaddr = (char *)(descr + 1);
  334. # else
  335. attr->__stackaddr = (char *)descr;
  336. # endif
  337. #endif
  338. #ifdef __UCLIBC_HAS_TLS__
  339. if (attr->__stackaddr == NULL)
  340. #else
  341. if (descr == &__pthread_initial_thread)
  342. #endif
  343. {
  344. /* Stack size limit. */
  345. struct rlimit rl;
  346. /* The safest way to get the top of the stack is to read
  347. /proc/self/maps and locate the line into which
  348. __libc_stack_end falls. */
  349. FILE *fp = fopen ("/proc/self/maps", "rc");
  350. if (fp == NULL)
  351. ret = errno;
  352. /* We need the limit of the stack in any case. */
  353. else if (getrlimit (RLIMIT_STACK, &rl) != 0)
  354. ret = errno;
  355. else
  356. {
  357. /* We need no locking. */
  358. __fsetlocking (fp, FSETLOCKING_BYCALLER);
  359. /* Until we found an entry (which should always be the case)
  360. mark the result as a failure. */
  361. ret = ENOENT;
  362. char *line = NULL;
  363. size_t linelen = 0;
  364. uintptr_t last_to = 0;
  365. while (! feof_unlocked (fp))
  366. {
  367. if (getdelim (&line, &linelen, '\n', fp) <= 0)
  368. break;
  369. uintptr_t from;
  370. uintptr_t to;
  371. if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
  372. continue;
  373. if (from <= (uintptr_t) __libc_stack_end
  374. && (uintptr_t) __libc_stack_end < to)
  375. {
  376. /* Found the entry. Now we have the info we need. */
  377. attr->__stacksize = rl.rlim_cur;
  378. #ifdef _STACK_GROWS_UP
  379. /* Don't check to enforce a limit on the __stacksize */
  380. attr->__stackaddr = (void *) from;
  381. #else
  382. attr->__stackaddr = (void *) to;
  383. /* The limit might be too high. */
  384. if ((size_t) attr->__stacksize
  385. > (size_t) attr->__stackaddr - last_to)
  386. attr->__stacksize = (size_t) attr->__stackaddr - last_to;
  387. #endif
  388. /* We succeed and no need to look further. */
  389. ret = 0;
  390. break;
  391. }
  392. last_to = to;
  393. }
  394. fclose (fp);
  395. free (line);
  396. }
  397. }
  398. return 0;
  399. }