/* Thread library support for -fsplit-stack.  */
/* Copyright (C) 2009-2021 Free Software Foundation, Inc.
   Contributed by Ian Lance Taylor <iant@google.com>.

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 "tconfig.h"
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
#include "libgcc_tm.h"

/* If inhibit_libc is defined, we cannot compile this file.  The
   effect is that people will not be able to use -fsplit-stack.  That
   is much better than failing the build particularly since people
   will want to define inhibit_libc while building a compiler which
   can build glibc.  */

#ifndef inhibit_libc

#include <errno.h>
#include <signal.h>
#include <pthread.h>

#include "generic-morestack.h"

/* We declare the pthread functions we need as weak, so that
   libgcc_s.so does not need to be linked against -lpthread.  */

extern int pthread_once (pthread_once_t *, void (*) (void))
  __attribute__ ((weak));

extern int pthread_key_create (pthread_key_t *, void (*) (void *))
  __attribute__ ((weak));

extern int pthread_setspecific (pthread_key_t, const void *)
  __attribute__ ((weak));

extern int pthread_sigmask (int, const sigset_t *, sigset_t *)
  __attribute__ ((weak));

/* The key for the list of stack segments to free when the thread
   exits.  This is created by pthread_key_create.  */

static pthread_key_t segment_list_key;

/* Used to only run create_key once.  */

static pthread_once_t create_key_once = PTHREAD_ONCE_INIT;

/* Release all the segments for a thread.  This is the destructor
   function used by pthread_key_create, and is called when a thread
   exits.  */

static void
free_segments (void* arg)
{
  /* We must block signals in case the signal handler tries to split
     the stack.  We leave them blocked while the thread exits.  */
  if (pthread_sigmask)
    {
      sigset_t mask;

      sigfillset (&mask);
      pthread_sigmask (SIG_BLOCK, &mask, NULL);
    }

  __morestack_release_segments ((struct stack_segment **) arg, 1);
}

/* Set up the key for the list of segments.  This is called via
   pthread_once.  */

static void
create_key (void)
{
  int err;

  err = pthread_key_create (&segment_list_key, free_segments);
  if (err != 0)
    {
      static const char msg[] = "pthread_key_create failed: errno ";
      __morestack_fail (msg, sizeof msg - 1, err);
    }
}

/* Pass information from the pthread_create wrapper to
   stack_split_initialize_thread.  */

struct pthread_create_args
{
  void *(*start_routine) (void *);
  void *arg;
};

/* Initialize a thread.  This is called via pthread_create.  It calls
   a target dependent function to set up any required stack guard.  */

static void* stack_split_initialize_thread (void *)
  __attribute__ ((no_split_stack));

static void *
stack_split_initialize_thread (void *varg)
{
  struct pthread_create_args *args = (struct pthread_create_args *) varg;
  int err;
  void *(*start_routine) (void *);
  void *arg;

  __stack_split_initialize ();

  err = pthread_setspecific (segment_list_key, (void *) &__morestack_segments);
  if (err != 0)
    {
      static const char msg[] = "pthread_setspecific failed: errno ";
      __morestack_fail (msg, sizeof msg - 1, err);
    }

  start_routine = args->start_routine;
  arg = args->arg;
  free (args);
  return (*start_routine) (arg);
}

/* This function wraps calls to pthread_create to make sure that the
   stack guard is initialized for new threads.  FIXME: This hack will
   not be necessary if glibc supports -fsplit-stack directly.  */

int __wrap_pthread_create (pthread_t *, const pthread_attr_t *,
			   void *(*start_routine) (void *), void *)
  __attribute__ ((visibility ("hidden")));

extern int __real_pthread_create (pthread_t *, const pthread_attr_t *,
				  void *(*start_routine) (void *), void *)
  __attribute__ ((weak));

int
__wrap_pthread_create (pthread_t *tid, const pthread_attr_t *attr,
		       void *(*start_routine) (void *), void *arg)
{
  int err;
  struct pthread_create_args* args;

  err = pthread_once (&create_key_once, create_key);
  if (err != 0)
    {
      static const char msg[] = "pthread_once failed: errno ";
      __morestack_fail (msg, sizeof msg - 1, err);
    }

  args = malloc (sizeof (struct pthread_create_args));
  if (args == NULL)
    return EAGAIN;
  args->start_routine = start_routine;
  args->arg = arg;
  return __real_pthread_create (tid, attr, stack_split_initialize_thread, args);
}

#endif /* !defined (inhibit_libc) */
