(linenum→info "unix/slp.c:2238")

glibc/2.7/nptl/pthread_getattr_np.c

    1: /* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3:    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library 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 GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <assert.h>
   21: #include <errno.h>
   22: #include <inttypes.h>
   23: #include <stdio.h>
   24: #include <stdio_ext.h>
   25: #include <stdlib.h>
   26: #include <string.h>
   27: #include <sys/resource.h>
   28: #include "pthreadP.h"
   29: #include <lowlevellock.h>
   30: #include <ldsodefs.h>
   31: 
   32: 
   33: int
   34: pthread_getattr_np (thread_id, attr)
   35:      pthread_t thread_id;
   36:      pthread_attr_t *attr;
   37: {
   38:   struct pthread *thread = (struct pthread *) thread_id;
   39:   struct pthread_attr *iattr = (struct pthread_attr *) attr;
   40:   int ret = 0;
   41: 
   42:   lll_lock (thread->lock, LLL_PRIVATE);
   43: 
   44:   /* The thread library is responsible for keeping the values in the
   45:      thread desriptor up-to-date in case the user changes them.  */
   46:   memcpy (&iattr->schedparam, &thread->schedparam,
   47:           sizeof (struct sched_param));
   48:   iattr->schedpolicy = thread->schedpolicy;
   49: 
   50:   /* Clear the flags work.  */
   51:   iattr->flags = thread->flags;
   52: 
   53:   /* The thread might be detached by now.  */
   54:   if (IS_DETACHED (thread))
   55:     iattr->flags |= ATTR_FLAG_DETACHSTATE;
   56: 
   57:   /* This is the guardsize after adjusting it.  */
   58:   iattr->guardsize = thread->reported_guardsize;
   59: 
   60:   /* The sizes are subject to alignment.  */
   61:   if (__builtin_expect (thread->stackblock != NULL, 1))
   62:     {
   63:       iattr->stacksize = thread->stackblock_size;
   64:       iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
   65:     }
   66:   else
   67:     {
   68:       /* No stack information available.  This must be for the initial
   69:          thread.  Get the info in some magical way.  */
   70:       assert (abs (thread->pid) == thread->tid);
   71: 
   72:       /* Stack size limit.  */
   73:       struct rlimit rl;
   74: 
   75:       /* The safest way to get the top of the stack is to read
   76:          /proc/self/maps and locate the line into which
   77:          __libc_stack_end falls.  */
   78:       FILE *fp = fopen ("/proc/self/maps", "rc");
   79:       if (fp == NULL)
   80:         ret = errno;
   81:       /* We need the limit of the stack in any case.  */
   82:       else
   83:         {
   84:           if (getrlimit (RLIMIT_STACK, &rl) != 0)
   85:             ret = errno;
   86:           else
   87:             {
   88:               /* We need no locking.  */
   89:               __fsetlocking (fp, FSETLOCKING_BYCALLER);
   90: 
   91:               /* Until we found an entry (which should always be the case)
   92:                  mark the result as a failure.  */
   93:               ret = ENOENT;
   94: 
   95:               char *line = NULL;
   96:               size_t linelen = 0;
   97:               uintptr_t last_to = 0;
   98: 
   99:               while (! feof_unlocked (fp))
  100:                 {
  101:                   if (__getdelim (&line, &linelen, '\n', fp) <= 0)
  102:                     break;
  103: 
  104:                   uintptr_t from;
  105:                   uintptr_t to;
  106:                   if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
  107:                     continue;
  108:                   if (from <= (uintptr_t) __libc_stack_end
  109:                       && (uintptr_t) __libc_stack_end < to)
  110:                     {
  111:                       /* Found the entry.  Now we have the info we need.  */
  112:                       iattr->stacksize = rl.rlim_cur;
  113:                       iattr->stackaddr = (void *) to;
  114: 
  115:                       /* The limit might be too high.  */
  116:                       if ((size_t) iattr->stacksize
  117:                           > (size_t) iattr->stackaddr - last_to)
  118:                         iattr->stacksize = (size_t) iattr->stackaddr - last_to;
  119: 
  120:                       /* We succeed and no need to look further.  */
  121:                       ret = 0;
  122:                       break;
  123:                     }
  124:                   last_to = to;
  125:                 }
  126: 
  127:               free (line);
  128:             }
  129: 
  130:           fclose (fp);
  131:         }
  132:     }
  133: 
  134:   iattr->flags |= ATTR_FLAG_STACKADDR;
  135: 
  136:   if (ret == 0)
  137:     {
  138:       size_t size = 16;
  139:       cpu_set_t *cpuset = NULL;
  140: 
  141:       do
  142:         {
  143:           size <<= 1;
  144: 
  145:           void *newp = realloc (cpuset, size);
  146:           if (newp == NULL)
  147:             {
  148:               ret = ENOMEM;
  149:               break;
  150:             }
  151:           cpuset = (cpu_set_t *) newp;
  152: 
  153:           ret = __pthread_getaffinity_np (thread_id, size, cpuset);
  154:         }
  155:       /* Pick some ridiculous upper limit.  Is 8 million CPUs enough?  */
  156:       while (ret == EINVAL && size < 1024 * 1024);
  157: 
  158:       if (ret == 0)
  159:         {
  160:           iattr->cpuset = cpuset;
  161:           iattr->cpusetsize = size;
  162:         }
  163:       else
  164:         {
  165:           free (cpuset);
  166:           if (ret == ENOSYS)
  167:             {    
  168:               /* There is no such functionality.  */
  169:               ret = 0;
  170:               iattr->cpuset = NULL;
  171:               iattr->cpusetsize = 0;
  172:             }
  173:         }
  174:     }
  175: 
  176:   lll_unlock (thread->lock, LLL_PRIVATE);
  177: 
  178:   return ret;
  179: }
Syntax (Markdown)