// Copyright (C) 2012-2021 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.

// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

#include <cxxabi.h>
#include <cstdlib>
#include <new>
#include "bits/gthr.h"
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

// Simplify it a little for this file.
#ifndef _GLIBCXX_CDTOR_CALLABI
#  define _GLIBCXX_CDTOR_CALLABI
#endif

#if _GLIBCXX_HAVE___CXA_THREAD_ATEXIT

// Libc provides __cxa_thread_atexit definition.

#elif _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL

extern "C" int __cxa_thread_atexit_impl (void (_GLIBCXX_CDTOR_CALLABI *func) (void *),
					 void *arg, void *d);
extern "C" int
__cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
				 void *obj, void *dso_handle)
  _GLIBCXX_NOTHROW
{
  return __cxa_thread_atexit_impl (dtor, obj, dso_handle);
}

#else /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */

namespace {
  // One element in a singly-linked stack of cleanups.
  struct elt
  {
    void (_GLIBCXX_CDTOR_CALLABI *destructor)(void *);
    void *object;
    elt *next;
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
    HMODULE dll;
#endif
  };

  // Keep a per-thread list of cleanups in gthread_key storage.
  __gthread_key_t key;
  // But also support non-threaded mode.
  elt *single_thread;

  // Run the specified stack of cleanups.
  void run (void *p)
  {
    elt *e = static_cast<elt*>(p);
    while (e)
      {
	elt *old_e = e;
	e->destructor (e->object);
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
	/* Decrement DLL count */
	if (e->dll)
	  FreeLibrary (e->dll);
#endif
	e = e->next;
	delete (old_e);
      }
  }

  // Run the stack of cleanups for the current thread.
  void run ()
  {
    void *e;
    if (__gthread_active_p ())
      {
	e = __gthread_getspecific (key);
	__gthread_setspecific (key, NULL);
      }
    else
      {
	e = single_thread;
	single_thread = NULL;
      }
    run (e);
  }

  // Initialize the key for the cleanup stack.  We use a static local for
  // key init/delete rather than atexit so that delete is run on dlclose.
  void key_init() {
    struct key_s {
      key_s() { __gthread_key_create (&key, run); }
      ~key_s() { __gthread_key_delete (key); }
    };
    static key_s ks;
    // Also make sure the destructors are run by std::exit.
    // FIXME TLS cleanups should run before static cleanups and atexit
    // cleanups.
    std::atexit (run);
  }
}

extern "C" int
__cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
				 void *obj, void */*dso_handle*/)
  _GLIBCXX_NOTHROW
{
  // Do this initialization once.
  if (__gthread_active_p ())
    {
      // When threads are active use __gthread_once.
      static __gthread_once_t once = __GTHREAD_ONCE_INIT;
      __gthread_once (&once, key_init);
    }
  else
    {
      // And when threads aren't active use a static local guard.
      static bool queued;
      if (!queued)
	{
	  queued = true;
	  std::atexit (run);
	}
    }

  elt *first;
  if (__gthread_active_p ())
    first = static_cast<elt*>(__gthread_getspecific (key));
  else
    first = single_thread;

  elt *new_elt = new (std::nothrow) elt;
  if (!new_elt)
    return -1;
  new_elt->destructor = dtor;
  new_elt->object = obj;
  new_elt->next = first;
#ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
  /* Store the DLL address for a later call to FreeLibrary in new_elt and
     increment DLL load count.  This blocks the unloading of the DLL
     before the thread-local dtors have been called.  This does NOT help
     if FreeLibrary/dlclose is called in excess. */
  GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
		      (LPCWSTR) dtor, &new_elt->dll);
#endif

  if (__gthread_active_p ())
    __gthread_setspecific (key, new_elt);
  else
    single_thread = new_elt;

  return 0;
}

#endif /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */
