Back to index

glibc  2.9
attr.c
Go to the documentation of this file.
00001 /* Linuxthreads - a simple clone()-based implementation of Posix        */
00002 /* threads for Linux.                                                   */
00003 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
00004 /*                                                                      */
00005 /* This program is free software; you can redistribute it and/or        */
00006 /* modify it under the terms of the GNU Library General Public License  */
00007 /* as published by the Free Software Foundation; either version 2       */
00008 /* of the License, or (at your option) any later version.               */
00009 /*                                                                      */
00010 /* This program is distributed in the hope that it will be useful,      */
00011 /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
00012 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
00013 /* GNU Library General Public License for more details.                 */
00014 
00015 /* Handling of thread attributes */
00016 
00017 #include <errno.h>
00018 #include <inttypes.h>
00019 #include <stdio.h>
00020 #include <stdio_ext.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 #include <sys/param.h>
00025 #include <sys/resource.h>
00026 #include "pthread.h"
00027 #include "internals.h"
00028 #include <shlib-compat.h>
00029 #include <ldsodefs.h>
00030 
00031 
00032 int __pthread_attr_init_2_1(pthread_attr_t *attr)
00033 {
00034   size_t ps = __getpagesize ();
00035 
00036   attr->__detachstate = PTHREAD_CREATE_JOINABLE;
00037   attr->__schedpolicy = SCHED_OTHER;
00038   attr->__schedparam.sched_priority = 0;
00039   attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
00040   attr->__scope = PTHREAD_SCOPE_SYSTEM;
00041 #ifdef NEED_SEPARATE_REGISTER_STACK
00042   attr->__guardsize = ps + ps;
00043 #else
00044   attr->__guardsize = ps;
00045 #endif
00046   attr->__stackaddr = NULL;
00047   attr->__stackaddr_set = 0;
00048   attr->__stacksize = STACK_SIZE - ps;
00049   return 0;
00050 }
00051 
00052 versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init,
00053                 GLIBC_2_1);
00054 
00055 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
00056 int __pthread_attr_init_2_0(pthread_attr_t *attr)
00057 {
00058   attr->__detachstate = PTHREAD_CREATE_JOINABLE;
00059   attr->__schedpolicy = SCHED_OTHER;
00060   attr->__schedparam.sched_priority = 0;
00061   attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
00062   attr->__scope = PTHREAD_SCOPE_SYSTEM;
00063   return 0;
00064 }
00065 compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init,
00066               GLIBC_2_0);
00067 #endif
00068 
00069 int __pthread_attr_destroy(pthread_attr_t *attr)
00070 {
00071   return 0;
00072 }
00073 strong_alias (__pthread_attr_destroy, pthread_attr_destroy);
00074 
00075 int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
00076 {
00077   if (detachstate < PTHREAD_CREATE_JOINABLE ||
00078       detachstate > PTHREAD_CREATE_DETACHED)
00079     return EINVAL;
00080   attr->__detachstate = detachstate;
00081   return 0;
00082 }
00083 strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate);
00084 
00085 int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
00086 {
00087   *detachstate = attr->__detachstate;
00088   return 0;
00089 }
00090 strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate);
00091 
00092 int __pthread_attr_setschedparam(pthread_attr_t *attr,
00093                                  const struct sched_param *param)
00094 {
00095   int max_prio = __sched_get_priority_max(attr->__schedpolicy);
00096   int min_prio = __sched_get_priority_min(attr->__schedpolicy);
00097 
00098   if (param->sched_priority < min_prio || param->sched_priority > max_prio)
00099     return EINVAL;
00100   memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
00101   return 0;
00102 }
00103 strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam);
00104 
00105 int __pthread_attr_getschedparam(const pthread_attr_t *attr,
00106                                  struct sched_param *param)
00107 {
00108   memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
00109   return 0;
00110 }
00111 strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam);
00112 
00113 int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
00114 {
00115   if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
00116     return EINVAL;
00117   attr->__schedpolicy = policy;
00118   return 0;
00119 }
00120 strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
00121 
00122 int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
00123 {
00124   *policy = attr->__schedpolicy;
00125   return 0;
00126 }
00127 strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
00128 
00129 int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
00130 {
00131   if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
00132     return EINVAL;
00133   attr->__inheritsched = inherit;
00134   return 0;
00135 }
00136 strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched);
00137 
00138 int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
00139 {
00140   *inherit = attr->__inheritsched;
00141   return 0;
00142 }
00143 strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched);
00144 
00145 int __pthread_attr_setscope(pthread_attr_t *attr, int scope)
00146 {
00147   switch (scope) {
00148   case PTHREAD_SCOPE_SYSTEM:
00149     attr->__scope = scope;
00150     return 0;
00151   case PTHREAD_SCOPE_PROCESS:
00152     return ENOTSUP;
00153   default:
00154     return EINVAL;
00155   }
00156 }
00157 strong_alias (__pthread_attr_setscope, pthread_attr_setscope);
00158 
00159 int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
00160 {
00161   *scope = attr->__scope;
00162   return 0;
00163 }
00164 strong_alias (__pthread_attr_getscope, pthread_attr_getscope);
00165 
00166 int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
00167 {
00168   /* The guard size must not be larger than the stack itself */
00169   if (guardsize >= attr->__stacksize) return EINVAL;
00170 
00171   attr->__guardsize = guardsize;
00172 
00173   return 0;
00174 }
00175 weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
00176 
00177 int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
00178 {
00179   *guardsize = attr->__guardsize;
00180   return 0;
00181 }
00182 weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
00183 
00184 int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
00185 {
00186   attr->__stackaddr = stackaddr;
00187   attr->__stackaddr_set = 1;
00188   return 0;
00189 }
00190 weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
00191 
00192 link_warning (pthread_attr_setstackaddr,
00193              "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
00194 
00195 int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
00196 {
00197   /* XXX This function has a stupid definition.  The standard specifies
00198      no error value but what is if no stack address was set?  We simply
00199      return the value we have in the member.  */
00200   *stackaddr = attr->__stackaddr;
00201   return 0;
00202 }
00203 weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
00204 
00205 link_warning (pthread_attr_getstackaddr,
00206              "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
00207 
00208 
00209 int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
00210 {
00211 #ifdef FLOATING_STACKS
00212   /* We have to check against the maximum allowed stack size.  This is no
00213      problem if the manager is already started and we determined it.  If
00214      this hasn't happened, we have to find the limit outself.  */
00215   if (__pthread_max_stacksize == 0)
00216     __pthread_init_max_stacksize ();
00217 
00218   if (stacksize > __pthread_max_stacksize)
00219     return EINVAL;
00220 #else
00221   /* We have a fixed size limit.  */
00222   if (stacksize > STACK_SIZE)
00223     return EINVAL;
00224 #endif
00225 
00226   /* We don't accept value smaller than PTHREAD_STACK_MIN.  */
00227   if (stacksize < PTHREAD_STACK_MIN)
00228     return EINVAL;
00229 
00230   attr->__stacksize = stacksize;
00231   return 0;
00232 }
00233 
00234 #if PTHREAD_STACK_MIN == 16384
00235 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
00236 #else
00237 versioned_symbol (libpthread, __pthread_attr_setstacksize,
00238                   pthread_attr_setstacksize, GLIBC_2_3_3);
00239 
00240 # if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3)
00241 
00242 int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
00243 {
00244 #  ifdef FLOATING_STACKS
00245   /* We have to check against the maximum allowed stack size.  This is no
00246      problem if the manager is already started and we determined it.  If
00247      this hasn't happened, we have to find the limit outself.  */
00248   if (__pthread_max_stacksize == 0)
00249     __pthread_init_max_stacksize ();
00250 
00251   if (stacksize > __pthread_max_stacksize)
00252     return EINVAL;
00253 #  else
00254   /* We have a fixed size limit.  */
00255   if (stacksize > STACK_SIZE)
00256     return EINVAL;
00257 #  endif
00258 
00259   /* We don't accept value smaller than old PTHREAD_STACK_MIN.  */
00260   if (stacksize < 16384)
00261     return EINVAL;
00262 
00263   attr->__stacksize = stacksize;
00264   return 0;
00265 }
00266 compat_symbol (libpthread, __old_pthread_attr_setstacksize,
00267               pthread_attr_setstacksize, GLIBC_2_1);
00268 # endif
00269 #endif
00270 
00271 
00272 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
00273 {
00274   *stacksize = attr->__stacksize;
00275   return 0;
00276 }
00277 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
00278 
00279 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
00280                           size_t stacksize)
00281 {
00282   int err;
00283 
00284   if ((((uintptr_t) stackaddr)
00285        & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
00286     err = EINVAL;
00287   else
00288     err = __pthread_attr_setstacksize (attr, stacksize);
00289   if (err == 0)
00290     {
00291 #ifndef _STACK_GROWS_UP
00292       attr->__stackaddr = (char *) stackaddr + stacksize;
00293 #else
00294       attr->__stackaddr = stackaddr;
00295 #endif
00296       attr->__stackaddr_set = 1;
00297     }
00298 
00299   return err;
00300 }
00301 
00302 #if PTHREAD_STACK_MIN == 16384
00303 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
00304 #else
00305 versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack,
00306                   GLIBC_2_3_3);
00307 # if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
00308 int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
00309                              size_t stacksize)
00310 {
00311   int err;
00312 
00313   if ((((uintptr_t) stackaddr)
00314        & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
00315     err = EINVAL;
00316   else
00317     err = __old_pthread_attr_setstacksize (attr, stacksize);
00318   if (err == 0)
00319     {
00320 #  ifndef _STACK_GROWS_UP
00321       attr->__stackaddr = (char *) stackaddr + stacksize;
00322 #  else
00323       attr->__stackaddr = stackaddr;
00324 #  endif
00325       attr->__stackaddr_set = 1;
00326     }
00327 
00328   return err;
00329 }
00330 
00331 compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack,
00332                GLIBC_2_2);
00333 
00334 # endif
00335 #endif
00336 
00337 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
00338                           size_t *stacksize)
00339 {
00340   /* XXX This function has a stupid definition.  The standard specifies
00341      no error value but what is if no stack address was set?  We simply
00342      return the value we have in the member.  */
00343 #ifndef _STACK_GROWS_UP
00344   *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
00345 #else
00346   *stackaddr = attr->__stackaddr;
00347 #endif
00348   *stacksize = attr->__stacksize;
00349   return 0;
00350 }
00351 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
00352 
00353 int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
00354 {
00355   pthread_handle handle = thread_handle (thread);
00356   pthread_descr descr;
00357   int ret = 0;
00358 
00359   if (handle == NULL)
00360     return ENOENT;
00361 
00362   descr = handle->h_descr;
00363 
00364   attr->__detachstate = (descr->p_detached
00365                       ? PTHREAD_CREATE_DETACHED
00366                       : PTHREAD_CREATE_JOINABLE);
00367 
00368   attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
00369   if (attr->__schedpolicy == -1)
00370     return errno;
00371 
00372   if (__sched_getparam (descr->p_pid,
00373                      (struct sched_param *) &attr->__schedparam) != 0)
00374     return errno;
00375 
00376   attr->__inheritsched = descr->p_inheritsched;
00377   attr->__scope = PTHREAD_SCOPE_SYSTEM;
00378 
00379 #ifdef _STACK_GROWS_DOWN
00380 # ifdef USE_TLS
00381   attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr
00382                     - descr->p_guardsize;
00383 # else
00384   attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
00385                     - descr->p_guardsize;
00386 # endif
00387 #else
00388 # ifdef USE_TLS
00389   attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr;
00390 # else
00391   attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
00392 # endif
00393 #endif
00394   attr->__guardsize = descr->p_guardsize;
00395   attr->__stackaddr_set = descr->p_userstack;
00396 #ifdef NEED_SEPARATE_REGISTER_STACK
00397   if (descr->p_userstack == 0)
00398     attr->__stacksize *= 2;
00399   /* XXX This is awkward.  The guard pages are in the middle of the
00400      two stacks.  We must count the guard size in the stack size since
00401      otherwise the range of the stack area cannot be computed.  */
00402   attr->__stacksize += attr->__guardsize;
00403 #endif
00404 #ifdef USE_TLS
00405   attr->__stackaddr = descr->p_stackaddr;
00406 #else
00407 # ifndef _STACK_GROWS_UP
00408   attr->__stackaddr = (char *)(descr + 1);
00409 # else
00410   attr->__stackaddr = (char *)descr;
00411 # endif
00412 #endif
00413 
00414 #ifdef USE_TLS
00415   if (attr->__stackaddr == NULL)
00416 #else
00417   if (descr == &__pthread_initial_thread)
00418 #endif
00419     {
00420       /* Stack size limit.  */
00421       struct rlimit rl;
00422 
00423       /* The safest way to get the top of the stack is to read
00424         /proc/self/maps and locate the line into which
00425         __libc_stack_end falls.  */
00426       FILE *fp = fopen ("/proc/self/maps", "rc");
00427       if (fp == NULL)
00428        ret = errno;
00429       /* We need the limit of the stack in any case.  */
00430       else if (getrlimit (RLIMIT_STACK, &rl) != 0)
00431        ret = errno;
00432       else
00433        {
00434          /* We need no locking.  */
00435          __fsetlocking (fp, FSETLOCKING_BYCALLER);
00436 
00437          /* Until we found an entry (which should always be the case)
00438             mark the result as a failure.  */
00439          ret = ENOENT;
00440 
00441          char *line = NULL;
00442          size_t linelen = 0;
00443          uintptr_t last_to = 0;
00444 
00445          while (! feof_unlocked (fp))
00446            {
00447              if (__getdelim (&line, &linelen, '\n', fp) <= 0)
00448               break;
00449 
00450              uintptr_t from;
00451              uintptr_t to;
00452              if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
00453               continue;
00454              if (from <= (uintptr_t) __libc_stack_end
00455                 && (uintptr_t) __libc_stack_end < to)
00456               {
00457                 /* Found the entry.  Now we have the info we need.  */
00458                 attr->__stacksize = rl.rlim_cur;
00459 #ifdef _STACK_GROWS_UP
00460                 /* Don't check to enforce a limit on the __stacksize */
00461                 attr->__stackaddr = (void *) from;
00462 #else
00463                 attr->__stackaddr = (void *) to;
00464 
00465                 /* The limit might be too high.  */
00466                 if ((size_t) attr->__stacksize
00467                     > (size_t) attr->__stackaddr - last_to)
00468                   attr->__stacksize = (size_t) attr->__stackaddr - last_to;
00469 #endif
00470 
00471                 /* We succeed and no need to look further.  */
00472                 ret = 0;
00473                 break;
00474               }
00475              last_to = to;
00476            }
00477 
00478          fclose (fp);
00479          free (line);
00480        }
00481     }
00482 
00483   return 0;
00484 
00485 }