(root)/
glibc-2.38/
sysdeps/
nptl/
libc_start_call_main.h
       1  /* Invoking main from __libc_start_main.  nptl version.
       2     Copyright (C) 1998-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       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, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <atomic.h>
      20  #include <pthreadP.h>
      21  
      22  _Noreturn static void
      23  __libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
      24                          int argc, char **argv
      25  #ifdef LIBC_START_MAIN_AUXVEC_ARG
      26                              , ElfW(auxv_t) *auxvec
      27  #endif
      28                          )
      29  {
      30    int result;
      31  
      32    /* Memory for the cancellation buffer.  */
      33    struct pthread_unwind_buf unwind_buf;
      34  
      35    int not_first_call;
      36    DIAG_PUSH_NEEDS_COMMENT;
      37  #if __GNUC_PREREQ (7, 0)
      38    /* This call results in a -Wstringop-overflow warning because struct
      39       pthread_unwind_buf is smaller than jmp_buf.  setjmp and longjmp
      40       do not use anything beyond the common prefix (they never access
      41       the saved signal mask), so that is a false positive.  */
      42    DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow=");
      43  #endif
      44    not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
      45    DIAG_POP_NEEDS_COMMENT;
      46    if (__glibc_likely (! not_first_call))
      47      {
      48        struct pthread *self = THREAD_SELF;
      49  
      50        /* Store old info.  */
      51        unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
      52        unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
      53  
      54        /* Store the new cleanup handler info.  */
      55        THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
      56  
      57        /* Run the program.  */
      58        result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
      59      }
      60    else
      61      {
      62        /* Remove the thread-local data.  */
      63        __nptl_deallocate_tsd ();
      64  
      65        /* One less thread.  Decrement the counter.  If it is zero we
      66           terminate the entire process.  */
      67        result = 0;
      68        if (atomic_fetch_add_relaxed (&__nptl_nthreads, -1) != 1)
      69          /* Not much left to do but to exit the thread, not the process.  */
      70  	while (1)
      71  	  INTERNAL_SYSCALL_CALL (exit, 0);
      72      }
      73  
      74    exit (result);
      75  }