libc_start_call_main.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /* Invoking main from __libc_start_main. nptl version.
  2. Copyright (C) 1998-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <atomic.h>
  16. #include <pthreadP.h>
  17. #include <futex-internal.h>
  18. _Noreturn static void
  19. __libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
  20. int argc, char **argv
  21. #ifdef LIBC_START_MAIN_AUXVEC_ARG
  22. , ElfW(auxv_t) *auxvec
  23. #endif
  24. )
  25. {
  26. int result;
  27. /* Memory for the cancellation buffer. */
  28. struct pthread_unwind_buf unwind_buf;
  29. int not_first_call;
  30. DIAG_PUSH_NEEDS_COMMENT;
  31. #if __GNUC_PREREQ (7, 0)
  32. /* This call results in a -Wstringop-overflow warning because struct
  33. pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp
  34. do not use anything beyond the common prefix (they never access
  35. the saved signal mask), so that is a false positive. */
  36. DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow=");
  37. #endif
  38. not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf);
  39. DIAG_POP_NEEDS_COMMENT;
  40. if (__glibc_likely (! not_first_call))
  41. {
  42. struct pthread *self = THREAD_SELF;
  43. /* Store old info. */
  44. unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
  45. unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
  46. /* Store the new cleanup handler info. */
  47. THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf);
  48. /* Run the program. */
  49. result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
  50. }
  51. else
  52. {
  53. /* Remove the thread-local data. */
  54. __nptl_deallocate_tsd ();
  55. /* One less thread. Decrement the counter. If it is zero we
  56. terminate the entire process. */
  57. result = 0;
  58. /* For the case a thread is waiting for the main thread to finish. */
  59. internal_sigset_t set;
  60. internal_signal_block_all (&set);
  61. struct pthread *self = THREAD_SELF;
  62. atomic_store_release (&self->joinstate, THREAD_STATE_EXITED);
  63. futex_wake (&self->joinstate, 1, FUTEX_SHARED);
  64. if (atomic_fetch_add_relaxed (&__nptl_nthreads, -1) != 1)
  65. /* Not much left to do but to exit the thread, not the process. */
  66. while (1)
  67. INTERNAL_SYSCALL_CALL (exit, 0);
  68. }
  69. exit (result);
  70. }