Back to index

glibc  2.9
td_thr_validate.c
Go to the documentation of this file.
00001 /* Validate a thread handle.
00002    Copyright (C) 1999,2001,2002,2003,2004,2007,2008
00003        Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #include "thread_dbP.h"
00023 #include <stdbool.h>
00024 
00025 static td_err_e
00026 check_thread_list (const td_thrhandle_t *th, psaddr_t head, bool *uninit)
00027 {
00028   td_err_e err;
00029   psaddr_t next, ofs;
00030 
00031   err = DB_GET_FIELD (next, th->th_ta_p, head, list_t, next, 0);
00032   if (err == TD_OK)
00033     {
00034       if (next == 0)
00035        {
00036          *uninit = true;
00037          return TD_NOTHR;
00038        }
00039       err = DB_GET_FIELD_ADDRESS (ofs, th->th_ta_p, 0, pthread, list, 0);
00040     }
00041 
00042   while (err == TD_OK)
00043     {
00044       if (next == head)
00045        return TD_NOTHR;
00046 
00047       if (next - (ofs - (psaddr_t) 0) == th->th_unique)
00048        return TD_OK;
00049 
00050       err = DB_GET_FIELD (next, th->th_ta_p, next, list_t, next, 0);
00051     }
00052 
00053   return err;
00054 }
00055 
00056 
00057 td_err_e
00058 td_thr_validate (const td_thrhandle_t *th)
00059 {
00060   td_err_e err;
00061   psaddr_t list;
00062 
00063   LOG ("td_thr_validate");
00064 
00065   /* First check the list with threads using user allocated stacks.  */
00066   bool uninit = false;
00067   err = DB_GET_SYMBOL (list, th->th_ta_p, __stack_user);
00068   if (err == TD_OK)
00069     err = check_thread_list (th, list, &uninit);
00070 
00071   /* If our thread is not on this list search the list with stack
00072      using implementation allocated stacks.  */
00073   if (err == TD_NOTHR)
00074     {
00075       err = DB_GET_SYMBOL (list, th->th_ta_p, stack_used);
00076       if (err == TD_OK)
00077        err = check_thread_list (th, list, &uninit);
00078 
00079       if (err == TD_NOTHR && uninit && th->th_unique == 0)
00080        /* __pthread_initialize_minimal has not run yet.
00081           There is only the special case thread handle.  */
00082        err = TD_OK;
00083     }
00084 
00085   if (err == TD_OK)
00086     {
00087       /* Verify that this is not a stale element in a fork child.  */
00088       pid_t match_pid = ps_getpid (th->th_ta_p->ph);
00089       psaddr_t pid;
00090       err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique, pthread, pid, 0);
00091       if (err == TD_OK && (pid_t) (uintptr_t) pid < 0)
00092        {
00093          /* This was a thread that was about to fork, or it is the new sole
00094             thread in a fork child.  In the latter case, its tid was stored
00095             via CLONE_CHILD_SETTID and so is already the proper child PID.  */
00096          if (-(pid_t) (uintptr_t) pid == match_pid)
00097            /* It is about to do a fork, but is really still the parent PID.  */
00098            pid = (psaddr_t) (uintptr_t) match_pid;
00099          else
00100            /* It must be a fork child, whose new PID is in the tid field.  */
00101            err = DB_GET_FIELD (pid, th->th_ta_p, th->th_unique,
00102                             pthread, tid, 0);
00103        }
00104       if (err == TD_OK && (pid_t) (uintptr_t) pid != match_pid)
00105        err = TD_NOTHR;
00106     }
00107 
00108   return err;
00109 }