attr.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  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. int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
  145. {
  146. attr->__stackaddr = stackaddr;
  147. attr->__stackaddr_set = 1;
  148. return 0;
  149. }
  150. weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
  151. link_warning (pthread_attr_setstackaddr,
  152. "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
  153. int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
  154. {
  155. /* XXX This function has a stupid definition. The standard specifies
  156. no error value but what is if no stack address was set? We simply
  157. return the value we have in the member. */
  158. *stackaddr = attr->__stackaddr;
  159. return 0;
  160. }
  161. weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
  162. link_warning (pthread_attr_getstackaddr,
  163. "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
  164. int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
  165. {
  166. #ifdef FLOATING_STACKS
  167. /* We have to check against the maximum allowed stack size. This is no
  168. problem if the manager is already started and we determined it. If
  169. this hasn't happened, we have to find the limit outself. */
  170. if (__pthread_max_stacksize == 0)
  171. __pthread_init_max_stacksize ();
  172. if (stacksize > __pthread_max_stacksize)
  173. return EINVAL;
  174. #else
  175. /* We have a fixed size limit. */
  176. if (stacksize > STACK_SIZE)
  177. return EINVAL;
  178. #endif
  179. /* We don't accept value smaller than PTHREAD_STACK_MIN. */
  180. if (stacksize < PTHREAD_STACK_MIN)
  181. return EINVAL;
  182. attr->__stacksize = stacksize;
  183. return 0;
  184. }
  185. #if PTHREAD_STACK_MIN == 16384
  186. weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
  187. #else
  188. versioned_symbol (libpthread, __pthread_attr_setstacksize,
  189. pthread_attr_setstacksize, GLIBC_2_3_3);
  190. # if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3)
  191. int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
  192. {
  193. # ifdef FLOATING_STACKS
  194. /* We have to check against the maximum allowed stack size. This is no
  195. problem if the manager is already started and we determined it. If
  196. this hasn't happened, we have to find the limit outself. */
  197. if (__pthread_max_stacksize == 0)
  198. __pthread_init_max_stacksize ();
  199. if (stacksize > __pthread_max_stacksize)
  200. return EINVAL;
  201. # else
  202. /* We have a fixed size limit. */
  203. if (stacksize > STACK_SIZE)
  204. return EINVAL;
  205. # endif
  206. /* We don't accept value smaller than old PTHREAD_STACK_MIN. */
  207. if (stacksize < 16384)
  208. return EINVAL;
  209. attr->__stacksize = stacksize;
  210. return 0;
  211. }
  212. compat_symbol (libpthread, __old_pthread_attr_setstacksize,
  213. pthread_attr_setstacksize, GLIBC_2_1);
  214. # endif
  215. #endif
  216. int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
  217. {
  218. *stacksize = attr->__stacksize;
  219. return 0;
  220. }
  221. weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
  222. int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
  223. size_t stacksize)
  224. {
  225. int err;
  226. if ((((uintptr_t) stackaddr)
  227. & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
  228. err = EINVAL;
  229. else
  230. err = __pthread_attr_setstacksize (attr, stacksize);
  231. if (err == 0)
  232. {
  233. #ifndef _STACK_GROWS_UP
  234. attr->__stackaddr = (char *) stackaddr + stacksize;
  235. #else
  236. attr->__stackaddr = stackaddr;
  237. #endif
  238. attr->__stackaddr_set = 1;
  239. }
  240. return err;
  241. }
  242. #if PTHREAD_STACK_MIN == 16384
  243. weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
  244. #else
  245. versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack,
  246. GLIBC_2_3_3);
  247. # if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
  248. int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
  249. size_t stacksize)
  250. {
  251. int err;
  252. if ((((uintptr_t) stackaddr)
  253. & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
  254. err = EINVAL;
  255. else
  256. err = __old_pthread_attr_setstacksize (attr, stacksize);
  257. if (err == 0)
  258. {
  259. # ifndef _STACK_GROWS_UP
  260. attr->__stackaddr = (char *) stackaddr + stacksize;
  261. # else
  262. attr->__stackaddr = stackaddr;
  263. # endif
  264. attr->__stackaddr_set = 1;
  265. }
  266. return err;
  267. }
  268. compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack,
  269. GLIBC_2_2);
  270. # endif
  271. #endif
  272. int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
  273. size_t *stacksize)
  274. {
  275. /* XXX This function has a stupid definition. The standard specifies
  276. no error value but what is if no stack address was set? We simply
  277. return the value we have in the member. */
  278. #ifndef _STACK_GROWS_UP
  279. *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
  280. #else
  281. *stackaddr = attr->__stackaddr;
  282. #endif
  283. *stacksize = attr->__stacksize;
  284. return 0;
  285. }
  286. weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
  287. int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
  288. {
  289. pthread_handle handle = thread_handle (thread);
  290. pthread_descr descr;
  291. int ret = 0;
  292. if (handle == NULL)
  293. return ENOENT;
  294. descr = handle->h_descr;
  295. attr->__detachstate = (descr->p_detached
  296. ? PTHREAD_CREATE_DETACHED
  297. : PTHREAD_CREATE_JOINABLE);
  298. attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
  299. if (attr->__schedpolicy == -1)
  300. return errno;
  301. if (__sched_getparam (descr->p_pid,
  302. (struct sched_param *) &attr->__schedparam) != 0)
  303. return errno;
  304. attr->__inheritsched = descr->p_inheritsched;
  305. attr->__scope = PTHREAD_SCOPE_SYSTEM;
  306. #ifdef _STACK_GROWS_DOWN
  307. # ifdef USE_TLS
  308. attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr
  309. - descr->p_guardsize;
  310. # else
  311. attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
  312. - descr->p_guardsize;
  313. # endif
  314. #else
  315. # ifdef USE_TLS
  316. attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr;
  317. # else
  318. attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
  319. # endif
  320. #endif
  321. attr->__guardsize = descr->p_guardsize;
  322. attr->__stackaddr_set = descr->p_userstack;
  323. #ifdef NEED_SEPARATE_REGISTER_STACK
  324. if (descr->p_userstack == 0)
  325. attr->__stacksize *= 2;
  326. /* XXX This is awkward. The guard pages are in the middle of the
  327. two stacks. We must count the guard size in the stack size since
  328. otherwise the range of the stack area cannot be computed. */
  329. attr->__stacksize += attr->__guardsize;
  330. #endif
  331. #ifdef USE_TLS
  332. attr->__stackaddr = descr->p_stackaddr;
  333. #else
  334. # ifndef _STACK_GROWS_UP
  335. attr->__stackaddr = (char *)(descr + 1);
  336. # else
  337. attr->__stackaddr = (char *)descr;
  338. # endif
  339. #endif
  340. #ifdef USE_TLS
  341. if (attr->__stackaddr == NULL)
  342. #else
  343. if (descr == &__pthread_initial_thread)
  344. #endif
  345. {
  346. /* Stack size limit. */
  347. struct rlimit rl;
  348. /* The safest way to get the top of the stack is to read
  349. /proc/self/maps and locate the line into which
  350. __libc_stack_end falls. */
  351. FILE *fp = fopen ("/proc/self/maps", "rc");
  352. if (fp == NULL)
  353. ret = errno;
  354. /* We need the limit of the stack in any case. */
  355. else if (getrlimit (RLIMIT_STACK, &rl) != 0)
  356. ret = errno;
  357. else
  358. {
  359. /* We need no locking. */
  360. __fsetlocking (fp, FSETLOCKING_BYCALLER);
  361. /* Until we found an entry (which should always be the case)
  362. mark the result as a failure. */
  363. ret = ENOENT;
  364. char *line = NULL;
  365. size_t linelen = 0;
  366. uintptr_t last_to = 0;
  367. while (! feof_unlocked (fp))
  368. {
  369. if (getdelim (&line, &linelen, '\n', fp) <= 0)
  370. break;
  371. uintptr_t from;
  372. uintptr_t to;
  373. if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
  374. continue;
  375. if (from <= (uintptr_t) __libc_stack_end
  376. && (uintptr_t) __libc_stack_end < to)
  377. {
  378. /* Found the entry. Now we have the info we need. */
  379. attr->__stacksize = rl.rlim_cur;
  380. #ifdef _STACK_GROWS_UP
  381. /* Don't check to enforce a limit on the __stacksize */
  382. attr->__stackaddr = (void *) from;
  383. #else
  384. attr->__stackaddr = (void *) to;
  385. /* The limit might be too high. */
  386. if ((size_t) attr->__stacksize
  387. > (size_t) attr->__stackaddr - last_to)
  388. attr->__stacksize = (size_t) attr->__stackaddr - last_to;
  389. #endif
  390. /* We succeed and no need to look further. */
  391. ret = 0;
  392. break;
  393. }
  394. last_to = to;
  395. }
  396. fclose (fp);
  397. free (line);
  398. }
  399. }
  400. return 0;
  401. }