summaryrefslogtreecommitdiff
path: root/sysdeps/mach/hurd/i386/makecontext-helper.c
blob: c6fb90ca5a58af2d4b87ae36843d7fa753d8c030 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/* Helper for makecontext: handle threadvars.
   Copyright (C) 2013-2015 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#include <hurd/threadvar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>

#if 0

void
__makecontext_helper (ucontext_t *ucp)
{
  if (__hurd_threadvar_stack_mask == 0)
    {
      /* We are not using threads, so per init-first.c:init, the threadvars
         live in a malloced space, addressed relative to the base of the
         virtual address space.  Just keep using that one.  */
    }
  else
    {
      /* The following is only prepared to work with libpthread, which only
         keeps the threadvars at the bottom of the stack -- contrary to
         libthreads, which also puts additional data there.  */

      void *s = ucp->uc_stack.ss_sp;
      size_t s_size = ucp->uc_stack.ss_size;

      /* Is the new stack suitable?  Check that that the last threadvar
         occupies the last storage unit within the bounds of the new stack.
         Alignment according to (sp & __hurd_threadvar_stack_mask) == sp is not
         actually a requirement (though, in practice it often will be).  */
      if (__hurd_threadvar_location_from_sp (_HURD_THREADVAR_MAX, s)
          != s + s_size)
        {
          /* Instead of having makecontext return an error, we bail out the
             hard way, as we can't expect its caller to be able to properly
             react to this situation.  */
          fprintf (stderr,
                   "*** makecontext: a stack at %p with size %#x is not "
                   "usable with threadvars\n",
                   s, s_size);
          abort ();
        }

      /* Copy the threadvars to the new stack.  */
      void *t_old = __hurd_threadvar_location (0);
      void *t_new = __hurd_threadvar_location_from_sp (0, s);
      size_t t_size = __hurd_threadvar_max * sizeof (unsigned long int);
      memcpy (t_new, t_old, t_size);
      /* Account for the space taken by the threadvars.  */
      ucp->uc_stack.ss_size -= t_size;
    }
}
#endif