NPTL support for m68k/ColdFire
This commit is contained in:
parent
75e73e66e4
commit
40111cb9e1
@ -1,5 +1,45 @@
|
||||
2010-03-09 Maxim Kuvyrkov <maxim@codesourcery.com>
|
||||
|
||||
NPTL support for m68k/ColdFire
|
||||
* sysdeps/unix/sysv/linux/m68k/sysdep.h (tls.h): Include.
|
||||
(INTERNAL_SYSCALL): Convert to INTERNAL_SYSCALL_NCS.
|
||||
(PTR_MANGLE, PTR_DEMANGLE): Define.
|
||||
(NEED_STATIC_SYSINFO_DSO): Define.
|
||||
* sysdeps/unix/sysv/linux/m68k/clone.S: Support RESET_PID.
|
||||
* sysdeps/unix/sysv/linux/m68k/m68k-helpers.S: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/Makefile: Add new files to lists.
|
||||
* sysdeps/unix/sysv/linux/m68k/vfork.S: Add SAVE_PID/RESTORE_PID.
|
||||
* sysdeps/unix/sysv/linux/m68k/m68k-vdso.c: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/libc-m68k-vdso.c: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/bits/m68k-vdso.h: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/coldfire/nptl/bits/atomic.h: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/Versions: Add symbols for NPTL support.
|
||||
* sysdeps/unix/sysv/linux/m68k/init-first.c: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/sysdep-cancel.h: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/bits/pthreadtypes.h: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/bits/semaphore.h: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/clone.S: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/fork.c: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/lowlevellock.h: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/vfork.S: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/pt-vfork.S: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/createthread.c: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/nptl/pthread_once.c: New.
|
||||
* sysdeps/unix/sysv/linux/m68k/socket.S: Update cancelation code.
|
||||
* sysdeps/m68k/dl-tls.h: New.
|
||||
* sysdeps/m68k/libc-tls.c: New.
|
||||
* sysdeps/m68k/tls-macros.h: New.
|
||||
* sysdeps/m68k/dl-machine.h (RTLD_START): Terminate stack frame to
|
||||
generate better backtraces.
|
||||
(elf_machine_type_class, elf_machine_rela): Handle TLS relocations.
|
||||
* sysdeps/m68k/dl-machine.h: Handle TLS relocations.
|
||||
* sysdeps/m68k/nptl/tcb-offsets.sym: New.
|
||||
* sysdeps/m68k/nptl/pthread_spin_trylock.c: New.
|
||||
* sysdeps/m68k/nptl/tls.h: New.
|
||||
* sysdeps/m68k/nptl/pthread_spin_lock.c: New.
|
||||
* sysdeps/m68k/nptl/pthreaddef.h: New.
|
||||
* sysdeps/m68k/nptl/Makefile: New.
|
||||
|
||||
* sysdeps/unix/sysv/linux/m68k/bits/sigcontext.h: Remove.
|
||||
* sysdeps/unix/sysv/linux/m68k/register-dump.h: Update.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Machine-dependent ELF dynamic relocation inline functions. m68k version.
|
||||
Copyright (C) 1996-2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2010
|
||||
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
|
||||
@ -24,6 +25,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sysdep.h>
|
||||
#include <dl-tls.h>
|
||||
|
||||
/* Return nonzero iff ELF header is compatible with the running host. */
|
||||
static inline int
|
||||
@ -121,6 +123,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
|
||||
.globl _start\n\
|
||||
.type _start,@function\n\
|
||||
_start:\n\
|
||||
sub.l %fp, %fp\n\
|
||||
move.l %sp, -(%sp)\n\
|
||||
jbsr _dl_start\n\
|
||||
addq.l #4, %sp\n\
|
||||
@ -159,12 +162,16 @@ _dl_start_user:\n\
|
||||
.size _dl_start_user, . - _dl_start_user\n\
|
||||
.previous");
|
||||
|
||||
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
|
||||
PLT entries should not be allowed to define the value.
|
||||
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
|
||||
TLS variable, so undefined references should not be allowed to
|
||||
define the value.
|
||||
ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
|
||||
of the main executable's symbols, as for a COPY reloc. */
|
||||
#define elf_machine_type_class(type) \
|
||||
((((type) == R_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
|
||||
((((type) == R_68K_JMP_SLOT \
|
||||
|| (type) == R_68K_TLS_DTPMOD32 \
|
||||
|| (type) == R_68K_TLS_DTPREL32 \
|
||||
|| (type) == R_68K_TLS_TPREL32) * ELF_RTYPE_CLASS_PLT) \
|
||||
| (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
|
||||
|
||||
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
|
||||
@ -262,6 +269,25 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
|
||||
case R_68K_PC32:
|
||||
*reloc_addr = value + reloc->r_addend - (Elf32_Addr) reloc_addr;
|
||||
break;
|
||||
#if defined USE_TLS && !defined RTLD_BOOTSTRAP
|
||||
case R_68K_TLS_DTPMOD32:
|
||||
/* Get the information from the link map returned by the
|
||||
resolv function. */
|
||||
if (sym_map != NULL)
|
||||
*reloc_addr = sym_map->l_tls_modid;
|
||||
break;
|
||||
case R_68K_TLS_DTPREL32:
|
||||
if (sym != NULL)
|
||||
*reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
|
||||
break;
|
||||
case R_68K_TLS_TPREL32:
|
||||
if (sym != NULL)
|
||||
{
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
*reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
|
||||
}
|
||||
break;
|
||||
#endif /* defined USE_TLS && !defined RTLD_BOOTSTRAP */
|
||||
case R_68K_NONE: /* Alright, Wilbur. */
|
||||
break;
|
||||
default:
|
||||
|
48
sysdeps/m68k/dl-tls.h
Normal file
48
sysdeps/m68k/dl-tls.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Thread-local storage handling in the ELF dynamic linker. M68K version.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
|
||||
/* Type used for the representation of TLS information in the GOT. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned long int ti_module;
|
||||
unsigned long int ti_offset;
|
||||
} tls_index;
|
||||
|
||||
/* The thread pointer points 0x7000 past the first static TLS block. */
|
||||
#define TLS_TP_OFFSET 0x7000
|
||||
|
||||
/* Dynamic thread vector pointers point 0x8000 past the start of each
|
||||
TLS block. */
|
||||
#define TLS_DTV_OFFSET 0x8000
|
||||
|
||||
/* Compute the value for a TPREL reloc. */
|
||||
#define TLS_TPREL_VALUE(sym_map, sym, reloc) \
|
||||
((sym_map)->l_tls_offset + (sym)->st_value + (reloc)->r_addend \
|
||||
- TLS_TP_OFFSET)
|
||||
|
||||
/* Compute the value for a DTPREL reloc. */
|
||||
#define TLS_DTPREL_VALUE(sym, reloc) \
|
||||
((sym)->st_value + (reloc)->r_addend - TLS_DTV_OFFSET)
|
||||
|
||||
extern void *__tls_get_addr (tls_index *ti);
|
||||
|
||||
#define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET)
|
||||
#define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET)
|
38
sysdeps/m68k/libc-tls.c
Normal file
38
sysdeps/m68k/libc-tls.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* Thread-local storage handling in the ELF dynamic linker. m68k version.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <csu/libc-tls.c>
|
||||
#include <dl-tls.h>
|
||||
|
||||
#if USE_TLS
|
||||
|
||||
/* On M68K, linker optimizations are not required, so __tls_get_addr
|
||||
can be called even in statically linked binaries. In this case module
|
||||
must be always 1 and PT_TLS segment exist in the binary, otherwise it
|
||||
would not link. */
|
||||
|
||||
void *
|
||||
__tls_get_addr (tls_index *ti)
|
||||
{
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET;
|
||||
}
|
||||
|
||||
#endif
|
22
sysdeps/m68k/nptl/Makefile
Normal file
22
sysdeps/m68k/nptl/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
# Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
#
|
||||
# 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, write to the Free
|
||||
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
# 02111-1307 USA.
|
||||
|
||||
ifeq ($(subdir),csu)
|
||||
gen-as-const-headers += tcb-offsets.sym
|
||||
endif
|
31
sysdeps/m68k/nptl/pthread_spin_lock.c
Normal file
31
sysdeps/m68k/nptl/pthread_spin_lock.c
Normal file
@ -0,0 +1,31 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <atomic.h>
|
||||
#include "pthreadP.h"
|
||||
|
||||
int
|
||||
pthread_spin_lock (pthread_spinlock_t *lock)
|
||||
{
|
||||
while (atomic_compare_and_exchange_val_acq(lock, 1, 0) != 0)
|
||||
while (*lock != 0)
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
28
sysdeps/m68k/nptl/pthread_spin_trylock.c
Normal file
28
sysdeps/m68k/nptl/pthread_spin_trylock.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <atomic.h>
|
||||
#include "pthreadP.h"
|
||||
|
||||
int
|
||||
pthread_spin_trylock (pthread_spinlock_t *lock)
|
||||
{
|
||||
return atomic_compare_and_exchange_val_acq(lock, 1, 0) ? EBUSY : 0;
|
||||
}
|
39
sysdeps/m68k/nptl/pthreaddef.h
Normal file
39
sysdeps/m68k/nptl/pthreaddef.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Default stack size. */
|
||||
#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
|
||||
|
||||
/* Required stack pointer alignment at beginning. */
|
||||
#define STACK_ALIGN 16
|
||||
|
||||
/* Minimal stack size after allocating thread descriptor and guard size. */
|
||||
#define MINIMAL_REST_STACK 2048
|
||||
|
||||
/* Alignment requirement for TCB. */
|
||||
#define TCB_ALIGNMENT 16
|
||||
|
||||
|
||||
/* Location of current stack frame. */
|
||||
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
|
||||
|
||||
|
||||
/* XXX Until we have a better place keep the definitions here. */
|
||||
#define __exit_thread_inline(val) \
|
||||
INLINE_SYSCALL (exit, 1, (val))
|
11
sysdeps/m68k/nptl/tcb-offsets.sym
Normal file
11
sysdeps/m68k/nptl/tcb-offsets.sym
Normal file
@ -0,0 +1,11 @@
|
||||
#include <sysdep.h>
|
||||
#include <tls.h>
|
||||
|
||||
--
|
||||
|
||||
-- Derive offsets relative to the thread register.
|
||||
#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
|
||||
|
||||
MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
|
||||
PID_OFFSET thread_offsetof (pid)
|
||||
TID_OFFSET thread_offsetof (tid)
|
171
sysdeps/m68k/nptl/tls.h
Normal file
171
sysdeps/m68k/nptl/tls.h
Normal file
@ -0,0 +1,171 @@
|
||||
/* Definition for thread-local data handling. NPTL/m68k version.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _TLS_H
|
||||
#define _TLS_H 1
|
||||
|
||||
#include <dl-sysdep.h>
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
# include <stdbool.h>
|
||||
# include <stddef.h>
|
||||
# include <stdint.h>
|
||||
|
||||
/* Type for the dtv. */
|
||||
typedef union dtv
|
||||
{
|
||||
size_t counter;
|
||||
struct
|
||||
{
|
||||
void *val;
|
||||
bool is_static;
|
||||
} pointer;
|
||||
} dtv_t;
|
||||
|
||||
#else /* __ASSEMBLER__ */
|
||||
# include <tcb-offsets.h>
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
/* Signal that TLS support is available. */
|
||||
#define USE_TLS 1
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
/* Get system call information. */
|
||||
# include <sysdep.h>
|
||||
|
||||
/* The TP points to the start of the thread blocks. */
|
||||
# define TLS_DTV_AT_TP 1
|
||||
|
||||
/* Get the thread descriptor definition. */
|
||||
# include <nptl/descr.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
dtv_t *dtv;
|
||||
void *private;
|
||||
} tcbhead_t;
|
||||
|
||||
/* This is the size of the initial TCB. Because our TCB is before the thread
|
||||
pointer, we don't need this. */
|
||||
# define TLS_INIT_TCB_SIZE 0
|
||||
|
||||
/* Alignment requirements for the initial TCB. */
|
||||
# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
|
||||
|
||||
/* This is the size of the TCB. Because our TCB is before the thread
|
||||
pointer, we don't need this. */
|
||||
# define TLS_TCB_SIZE 0
|
||||
|
||||
/* Alignment requirements for the TCB. */
|
||||
# define TLS_TCB_ALIGN __alignof__ (struct pthread)
|
||||
|
||||
/* This is the size we need before TCB - actually, it includes the TCB. */
|
||||
# define TLS_PRE_TCB_SIZE \
|
||||
(sizeof (struct pthread) \
|
||||
+ ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
|
||||
|
||||
/* The thread pointer (TP) points to the end of the
|
||||
TCB + 0x7000, as for PowerPC and MIPS. This implies that TCB address is
|
||||
TP - 0x7000. As we define TLS_DTV_AT_TP we can
|
||||
assume that the pthread struct is allocated immediately ahead of the
|
||||
TCB. This implies that the pthread_descr address is
|
||||
TP - (TLS_PRE_TCB_SIZE + 0x7000). */
|
||||
# define TLS_TCB_OFFSET 0x7000
|
||||
|
||||
/* Install the dtv pointer. The pointer passed is to the element with
|
||||
index -1 which contain the length. */
|
||||
# define INSTALL_DTV(tcbp, dtvp) \
|
||||
((tcbhead_t *) (tcbp))[-1].dtv = dtvp + 1
|
||||
|
||||
/* Install new dtv for current thread. */
|
||||
# define INSTALL_NEW_DTV(dtv) \
|
||||
(THREAD_DTV () = (dtv))
|
||||
|
||||
/* Return dtv of given thread descriptor. */
|
||||
# define GET_DTV(tcbp) \
|
||||
(((tcbhead_t *) (tcbp))[-1].dtv)
|
||||
|
||||
/* Code to initially initialize the thread pointer. This might need
|
||||
special attention since 'errno' is not yet available and if the
|
||||
operation can cause a failure 'errno' must not be touched. */
|
||||
# define TLS_INIT_TP(tcbp, secondcall) \
|
||||
({ \
|
||||
INTERNAL_SYSCALL_DECL (err); \
|
||||
int _sys_result; \
|
||||
\
|
||||
_sys_result = INTERNAL_SYSCALL (set_thread_area, err, 1, \
|
||||
((void *) (tcbp)) + TLS_TCB_OFFSET); \
|
||||
INTERNAL_SYSCALL_ERROR_P (_sys_result, err) ? "unknown error" : NULL; })
|
||||
|
||||
extern void * __m68k_read_tp (void);
|
||||
|
||||
/* Return the address of the dtv for the current thread. */
|
||||
# define THREAD_DTV() \
|
||||
(((tcbhead_t *) (__m68k_read_tp () - TLS_TCB_OFFSET))[-1].dtv)
|
||||
|
||||
/* Return the thread descriptor for the current thread. */
|
||||
# define THREAD_SELF \
|
||||
((struct pthread *) (__m68k_read_tp () - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
|
||||
|
||||
/* Magic for libthread_db to know how to do THREAD_SELF. */
|
||||
# define DB_THREAD_SELF \
|
||||
CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
|
||||
|
||||
/* Access to data in the thread descriptor is easy. */
|
||||
# define THREAD_GETMEM(descr, member) \
|
||||
descr->member
|
||||
# define THREAD_GETMEM_NC(descr, member, idx) \
|
||||
descr->member[idx]
|
||||
# define THREAD_SETMEM(descr, member, value) \
|
||||
descr->member = (value)
|
||||
# define THREAD_SETMEM_NC(descr, member, idx, value) \
|
||||
descr->member[idx] = (value)
|
||||
|
||||
/* l_tls_offset == 0 is perfectly valid on M68K, so we have to use some
|
||||
different value to mean unset l_tls_offset. */
|
||||
# define NO_TLS_OFFSET -1
|
||||
|
||||
/* Get and set the global scope generation counter in struct pthread. */
|
||||
#define THREAD_GSCOPE_FLAG_UNUSED 0
|
||||
#define THREAD_GSCOPE_FLAG_USED 1
|
||||
#define THREAD_GSCOPE_FLAG_WAIT 2
|
||||
#define THREAD_GSCOPE_RESET_FLAG() \
|
||||
do \
|
||||
{ int __res \
|
||||
= atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \
|
||||
THREAD_GSCOPE_FLAG_UNUSED); \
|
||||
if (__res == THREAD_GSCOPE_FLAG_WAIT) \
|
||||
lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
|
||||
} \
|
||||
while (0)
|
||||
#define THREAD_GSCOPE_SET_FLAG() \
|
||||
do \
|
||||
{ \
|
||||
THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
|
||||
atomic_write_barrier (); \
|
||||
} \
|
||||
while (0)
|
||||
#define THREAD_GSCOPE_WAIT() \
|
||||
GL(dl_wait_lookup_done) ()
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
|
||||
#endif /* tls.h */
|
70
sysdeps/m68k/tls-macros.h
Normal file
70
sysdeps/m68k/tls-macros.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* Macros for accessing thread-local storage. m68k version.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#define TLS_GD(x) \
|
||||
({ \
|
||||
void *__result; \
|
||||
extern void *__tls_get_addr (void *); \
|
||||
\
|
||||
asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \
|
||||
"lea (-6, %%pc, %0), %0\n\t" \
|
||||
"lea " #x "@TLSGD(%0), %0" \
|
||||
: "=&a" (__result)); \
|
||||
(int *) __tls_get_addr (__result); })
|
||||
|
||||
#define TLS_LD(x) \
|
||||
({ \
|
||||
char *__tp; \
|
||||
int __offset; \
|
||||
extern void *__tls_get_addr (void *); \
|
||||
\
|
||||
asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \
|
||||
"lea (-6, %%pc, %0), %0\n\t" \
|
||||
"lea " #x "@TLSLDM(%0), %0" \
|
||||
: "=&a" (__tp)); \
|
||||
__tp = (char *) __tls_get_addr (__tp); \
|
||||
asm ("movel #" #x "@TLSLDO, %0" \
|
||||
: "=a" (__offset)); \
|
||||
(int *) (__tp + __offset); })
|
||||
|
||||
#define TLS_IE(x) \
|
||||
({ \
|
||||
char *__tp; \
|
||||
int __offset; \
|
||||
extern void * __m68k_read_tp (void); \
|
||||
\
|
||||
__tp = (char *) __m68k_read_tp (); \
|
||||
asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \
|
||||
"lea (-6, %%pc, %0), %0\n\t" \
|
||||
"movel " #x "@TLSIE(%0), %0" \
|
||||
: "=&a" (__offset)); \
|
||||
(int *) (__tp + __offset); })
|
||||
|
||||
#define TLS_LE(x) \
|
||||
({ \
|
||||
char *__tp; \
|
||||
int __offset; \
|
||||
extern void * __m68k_read_tp (void); \
|
||||
\
|
||||
__tp = (char *) __m68k_read_tp (); \
|
||||
asm ("movel #" #x "@TLSLE, %0" \
|
||||
: "=a" (__offset)); \
|
||||
(int *) (__tp + __offset); })
|
||||
|
@ -2,12 +2,18 @@
|
||||
|
||||
m68k-syntax-flag = -DMOTOROLA_SYNTAX
|
||||
|
||||
ifeq ($(subdir),csu)
|
||||
sysdep_routines += m68k-helpers
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),misc)
|
||||
sysdep_routines += mremap
|
||||
sysdep_headers += sys/reg.h
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
sysdep_routines += dl-vdso libc-m68k-vdso
|
||||
sysdep-rtld-routines += m68k-vdso
|
||||
sysdep-others += lddlibc4
|
||||
install-bin += lddlibc4
|
||||
endif
|
||||
|
@ -32,4 +32,18 @@ libc {
|
||||
GLIBC_2.11 {
|
||||
fallocate64;
|
||||
}
|
||||
GLIBC_2.12 {
|
||||
__m68k_read_tp;
|
||||
}
|
||||
GLIBC_PRIVATE {
|
||||
__vdso_atomic_cmpxchg_32; __vdso_atomic_barrier;
|
||||
}
|
||||
}
|
||||
|
||||
ld {
|
||||
GLIBC_PRIVATE {
|
||||
__rtld___vdso_read_tp;
|
||||
__rtld___vdso_atomic_cmpxchg_32;
|
||||
__rtld___vdso_atomic_barrier;
|
||||
}
|
||||
}
|
||||
|
61
sysdeps/unix/sysv/linux/m68k/bits/m68k-vdso.h
Normal file
61
sysdeps/unix/sysv/linux/m68k/bits/m68k-vdso.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* Resolve function pointers to VDSO functions.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
|
||||
#ifndef _M68K_VDSO_H
|
||||
#define _M68K_VDSO_H
|
||||
|
||||
#ifdef SHARED
|
||||
|
||||
# ifdef IS_IN_rtld
|
||||
# define M68K_VDSO_SYMBOL(name) __rtld_##name
|
||||
# define STR_M68K_VDSO_SYMBOL(name) "__rtld_" #name
|
||||
# else
|
||||
# define M68K_VDSO_SYMBOL(name) name
|
||||
# define STR_M68K_VDSO_SYMBOL(name) #name
|
||||
# endif
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
|
||||
/* We define __rtld_* copies for rtld.
|
||||
We need them visible in libc to initialize. */
|
||||
# if defined IS_IN_rtld || !defined NOT_IN_libc
|
||||
extern void *__rtld___vdso_read_tp;
|
||||
extern void *__rtld___vdso_atomic_cmpxchg_32;
|
||||
extern void *__rtld___vdso_atomic_barrier;
|
||||
|
||||
/* These stubs are meant to be invoked only from the assembly. */
|
||||
extern void __vdso_read_tp_stub (void);
|
||||
extern void __vdso_atomic_cmpxchg_32_stub (void);
|
||||
extern void __vdso_atomic_barrier_stub (void);
|
||||
# endif /* IS_IN_rtld || !NOT_IN_libc */
|
||||
|
||||
/* RTLD should only use its own copies. */
|
||||
# ifndef IS_IN_rtld
|
||||
extern void *__vdso_read_tp;
|
||||
extern void *__vdso_atomic_cmpxchg_32;
|
||||
extern void *__vdso_atomic_barrier;
|
||||
# endif /* !IS_IN_rtld */
|
||||
|
||||
# endif /* !__ASSEMBLER__ */
|
||||
|
||||
#endif /* SHARED */
|
||||
|
||||
#endif /* _M68K_VDSO_H */
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996,97,98,2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996,97,98,2002,2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Andreas Schwab (schwab@issan.informatik.uni-dortmund.de)
|
||||
|
||||
@ -17,14 +17,21 @@
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* clone is even more special than fork as it mucks with stacks
|
||||
/* clone() is even more special than fork() as it mucks with stacks
|
||||
and invokes a function in the right context after its all over. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#define _ERRNO_H 1
|
||||
#include <bits/errno.h>
|
||||
#ifdef RESET_PID
|
||||
#include <tls.h>
|
||||
#endif
|
||||
|
||||
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
|
||||
#define CLONE_VM 0x00000100
|
||||
#define CLONE_THREAD 0x00010000
|
||||
|
||||
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
|
||||
void *parent_tidptr, void *tls, void *child_tidptr) */
|
||||
|
||||
.text
|
||||
ENTRY (__clone)
|
||||
@ -42,7 +49,17 @@ ENTRY (__clone)
|
||||
movel 16(%sp), -(%a1)
|
||||
|
||||
/* Do the system call */
|
||||
movel 12(%sp), %d1 /* get flags */
|
||||
movel 12+0(%sp), %d1 /* get flags */
|
||||
movel %d3, -(%a1) /* save %d3 and get parent_tidptr */
|
||||
movel %d3, -(%sp)
|
||||
movel 20+4(%sp), %d3
|
||||
movel %d4, -(%a1) /* save %d4 and get child_tidptr */
|
||||
movel %d4, -(%sp)
|
||||
movel 28+8(%sp), %d4
|
||||
movel %d5, -(%a1) /* save %d5 and get tls */
|
||||
movel %d5, -(%sp)
|
||||
movel 24+12(%sp), %d5
|
||||
/* save %d2 and get stack pointer */
|
||||
#ifdef __mcoldfire__
|
||||
movel %d2, -(%a1)
|
||||
movel %d2, -(%sp)
|
||||
@ -57,6 +74,9 @@ ENTRY (__clone)
|
||||
#else
|
||||
exg %d2, %a1 /* restore %d2 */
|
||||
#endif
|
||||
movel (%sp)+, %d5 /* restore %d5, %d4 and %d3 */
|
||||
movel (%sp)+, %d4
|
||||
movel (%sp)+, %d3
|
||||
|
||||
tstl %d0
|
||||
jmi SYSCALL_ERROR_LABEL
|
||||
@ -65,11 +85,35 @@ ENTRY (__clone)
|
||||
rts
|
||||
|
||||
thread_start:
|
||||
cfi_startproc
|
||||
cfi_undefined (pc) /* Mark end of stack */
|
||||
subl %fp, %fp /* terminate the stack frame */
|
||||
#ifdef RESET_PID
|
||||
/* Check and see if we need to reset the PID. */
|
||||
movel %d1, %a1
|
||||
andl #CLONE_THREAD, %d1
|
||||
jne donepid
|
||||
movel %a1, %d1
|
||||
movel #-1, %d0
|
||||
andl #CLONE_VM, %d1
|
||||
jne gotpid
|
||||
movel #SYS_ify (getpid), %d0
|
||||
trap #0
|
||||
gotpid:
|
||||
movel %a0, -(%sp)
|
||||
movel %d0, -(%sp)
|
||||
bsrl __m68k_read_tp@PLTPC
|
||||
movel (%sp)+, %d0
|
||||
movel %d0, PID_OFFSET(%a0)
|
||||
movel %d0, TID_OFFSET(%a0)
|
||||
movel (%sp)+, %a0
|
||||
donepid:
|
||||
#endif
|
||||
jsr (%a0)
|
||||
movel %d0, %d1
|
||||
movel #SYS_ify (exit), %d0
|
||||
trap #0
|
||||
cfi_endproc
|
||||
|
||||
PSEUDO_END (__clone)
|
||||
|
||||
|
105
sysdeps/unix/sysv/linux/m68k/coldfire/nptl/bits/atomic.h
Normal file
105
sysdeps/unix/sysv/linux/m68k/coldfire/nptl/bits/atomic.h
Normal file
@ -0,0 +1,105 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _BITS_ATOMIC_H
|
||||
#define _BITS_ATOMIC_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sysdep.h>
|
||||
#include <bits/m68k-vdso.h>
|
||||
|
||||
/* Coldfire has no atomic compare-and-exchange operation, but the
|
||||
kernel provides userspace atomicity operations. Use them. */
|
||||
|
||||
typedef int32_t atomic32_t;
|
||||
typedef uint32_t uatomic32_t;
|
||||
typedef int_fast32_t atomic_fast32_t;
|
||||
typedef uint_fast32_t uatomic_fast32_t;
|
||||
|
||||
typedef intptr_t atomicptr_t;
|
||||
typedef uintptr_t uatomicptr_t;
|
||||
typedef intmax_t atomic_max_t;
|
||||
typedef uintmax_t uatomic_max_t;
|
||||
|
||||
/* The only basic operation needed is compare and exchange. */
|
||||
/* For ColdFire we'll have to trap into the kernel mode anyway,
|
||||
so trap from the library rather then from the kernel wrapper. */
|
||||
#ifdef SHARED
|
||||
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
|
||||
({ \
|
||||
/* Use temporary variables to workaround call-clobberness of */ \
|
||||
/* the registers. */ \
|
||||
__typeof (mem) _mem = mem; \
|
||||
__typeof (oldval) _oldval = oldval; \
|
||||
__typeof (newval) _newval = newval; \
|
||||
register __typeof (mem) _a0 asm ("a0") = _mem; \
|
||||
register __typeof (oldval) _d0 asm ("d0") = _oldval; \
|
||||
register __typeof (newval) _d1 asm ("d1") = _newval; \
|
||||
void *tmp; \
|
||||
\
|
||||
asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %2\n\t" \
|
||||
"lea (-6, %%pc, %2), %2\n\t" \
|
||||
"movel " STR_M68K_VDSO_SYMBOL (__vdso_atomic_cmpxchg_32) \
|
||||
"@GOT(%2), %2\n\t" \
|
||||
"movel (%2), %2\n\t" \
|
||||
"jsr (%2)\n\t" \
|
||||
: "+d" (_d0), "+m" (*_a0), "=&a" (tmp) \
|
||||
: "a" (_a0), "d" (_d1)); \
|
||||
_d0; \
|
||||
})
|
||||
#else
|
||||
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
|
||||
({ \
|
||||
/* Use temporary variables to workaround call-clobberness of */ \
|
||||
/* the registers. */ \
|
||||
__typeof (mem) _mem = mem; \
|
||||
__typeof (oldval) _oldval = oldval; \
|
||||
__typeof (newval) _newval = newval; \
|
||||
register __typeof (oldval) _d0 asm ("d0") \
|
||||
= SYS_ify (atomic_cmpxchg_32); \
|
||||
register __typeof (mem) _a0 asm ("a0") = _mem; \
|
||||
register __typeof (oldval) _d2 asm ("d2") = _oldval; \
|
||||
register __typeof (newval) _d1 asm ("d1") = _newval; \
|
||||
\
|
||||
asm ("trap #0" \
|
||||
: "+d" (_d0), "+m" (*_a0) \
|
||||
: "a" (_a0), "d" (_d2), "d" (_d1)); \
|
||||
_d0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifdef SHARED
|
||||
# define atomic_full_barrier() \
|
||||
({ \
|
||||
void *tmp; \
|
||||
\
|
||||
asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \
|
||||
"lea (-6, %pc, %0), %0\n\t" \
|
||||
"movel " STR_M68K_VDSO_SYMBOL (__vdso_atomic_barrier) \
|
||||
"@GOT(%0), %0\n\t" \
|
||||
"movel (%0), %0\n\t" \
|
||||
"jsr (%0)\n\t" \
|
||||
: "=&a" (tmp)); \
|
||||
})
|
||||
#else
|
||||
# define atomic_full_barrier() \
|
||||
(INTERNAL_SYSCALL (atomic_barrier, , 0), (void) 0)
|
||||
#endif
|
||||
|
||||
#endif
|
74
sysdeps/unix/sysv/linux/m68k/init-first.c
Normal file
74
sysdeps/unix/sysv/linux/m68k/init-first.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Note: linking in vDSO to a static binary requires changes to
|
||||
the main GLIBC proper. Not yet implemented. */
|
||||
#ifdef SHARED
|
||||
|
||||
#include <dl-vdso.h>
|
||||
#include <bits/m68k-vdso.h>
|
||||
|
||||
static inline void
|
||||
_libc_vdso_platform_setup (void)
|
||||
{
|
||||
void *p;
|
||||
|
||||
PREPARE_VERSION (linux26, "LINUX_2.6", 61765110);
|
||||
|
||||
/* It may happen that rtld didn't initialize the vDSO, so fallback
|
||||
to the syscall implementations if _dl_vdso_vsym returns NULL.
|
||||
This may happen when a static executable dlopen's a dynamic library.
|
||||
This really is nothing more than a workaround for rtld/csu
|
||||
deficiency. Ideally, init code would setup the vDSO for static
|
||||
binaries too. */
|
||||
|
||||
p = _dl_vdso_vsym ("__kernel_read_tp", &linux26);
|
||||
if (p != NULL)
|
||||
{
|
||||
__vdso_read_tp = p;
|
||||
__rtld___vdso_read_tp = p;
|
||||
}
|
||||
else
|
||||
assert (__vdso_read_tp == (void *) __vdso_read_tp_stub);
|
||||
|
||||
p = _dl_vdso_vsym ("__kernel_atomic_cmpxchg_32", &linux26);
|
||||
if (p != NULL)
|
||||
{
|
||||
__vdso_atomic_cmpxchg_32 = p;
|
||||
__rtld___vdso_atomic_cmpxchg_32 = p;
|
||||
}
|
||||
else
|
||||
assert (__vdso_atomic_cmpxchg_32
|
||||
== (void *) __vdso_atomic_cmpxchg_32_stub);
|
||||
|
||||
p = _dl_vdso_vsym ("__kernel_atomic_barrier", &linux26);
|
||||
if (p != NULL)
|
||||
{
|
||||
__vdso_atomic_barrier = p;
|
||||
__rtld___vdso_atomic_barrier = p;
|
||||
}
|
||||
else
|
||||
assert (__vdso_atomic_barrier == (void *) __vdso_atomic_barrier_stub);
|
||||
}
|
||||
|
||||
#define VDSO_SETUP _libc_vdso_platform_setup
|
||||
|
||||
#endif /* SHARED */
|
||||
|
||||
#include <sysdeps/unix/sysv/linux/init-first.c>
|
1
sysdeps/unix/sysv/linux/m68k/libc-m68k-vdso.c
Normal file
1
sysdeps/unix/sysv/linux/m68k/libc-m68k-vdso.c
Normal file
@ -0,0 +1 @@
|
||||
#include "m68k-vdso.c"
|
105
sysdeps/unix/sysv/linux/m68k/m68k-helpers.S
Normal file
105
sysdeps/unix/sysv/linux/m68k/m68k-helpers.S
Normal file
@ -0,0 +1,105 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file with other
|
||||
programs, and to distribute those programs without any restriction
|
||||
coming from the use of this file. (The GNU Lesser General Public
|
||||
License restrictions do apply in other respects; for example, they
|
||||
cover modification of the file, and distribution when not linked
|
||||
into another program.)
|
||||
|
||||
Note that people who make modified versions of this file are not
|
||||
obligated to grant this special exception for their modified
|
||||
versions; it is their choice whether to do so. The GNU Lesser
|
||||
General Public License gives permission to release a modified
|
||||
version without this exception; this exception also makes it
|
||||
possible to release a modified version which carries forward this
|
||||
exception.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <bits/m68k-vdso.h>
|
||||
|
||||
.text
|
||||
|
||||
.hidden __vdso_read_tp_stub
|
||||
ENTRY (__vdso_read_tp_stub)
|
||||
cfi_startproc
|
||||
move.l #__NR_get_thread_area, %d0
|
||||
trap #0
|
||||
move.l %d0, %a0
|
||||
rts
|
||||
cfi_endproc
|
||||
END (__vdso_read_tp_stub)
|
||||
|
||||
# ifdef SHARED
|
||||
/* GCC will emit calls to this routine. Linux has an
|
||||
equivalent helper function (which clobbers fewer registers than
|
||||
a normal function call) in a vdso; tail call to the
|
||||
helper. */
|
||||
# ifdef IS_IN_rtld
|
||||
/* rtld gets a hidden copy of __m68k_read_tp. */
|
||||
.hidden __m68k_read_tp
|
||||
# endif
|
||||
ENTRY (__m68k_read_tp)
|
||||
cfi_startproc
|
||||
move.l #_GLOBAL_OFFSET_TABLE_@GOTPC, %a0
|
||||
lea (-6, %pc, %a0), %a0
|
||||
move.l M68K_VDSO_SYMBOL (__vdso_read_tp)@GOT(%a0), %a0
|
||||
move.l (%a0), %a0
|
||||
jmp (%a0)
|
||||
cfi_endproc
|
||||
END (__m68k_read_tp)
|
||||
|
||||
/* The following two stubs are for macros in atomic.h, they can't
|
||||
clobber anything. */
|
||||
|
||||
.hidden __vdso_atomic_cmpxchg_32_stub
|
||||
ENTRY (__vdso_atomic_cmpxchg_32_stub)
|
||||
cfi_startproc
|
||||
move.l %d2, -(%sp)
|
||||
cfi_adjust_cfa_offset (4)
|
||||
cfi_rel_offset (%d2, 0)
|
||||
move.l %d0, %d2
|
||||
move.l #SYS_ify (atomic_cmpxchg_32), %d0
|
||||
trap #0
|
||||
move.l (%sp)+, %d2
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
cfi_restore (%d2)
|
||||
rts
|
||||
cfi_endproc
|
||||
END (__vdso_atomic_cmpxchg_32_stub)
|
||||
|
||||
.hidden __vdso_atomic_barrier_stub
|
||||
ENTRY (__vdso_atomic_barrier_stub)
|
||||
cfi_startproc
|
||||
move.l %d0, -(%sp)
|
||||
cfi_adjust_cfa_offset (4)
|
||||
move.l #SYS_ify (atomic_barrier), %d0
|
||||
trap #0
|
||||
move.l (%sp)+, %d0
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
rts
|
||||
cfi_endproc
|
||||
END (__vdso_atomic_barrier_stub)
|
||||
# else /* !SHARED */
|
||||
/* If the vDSO is not available, use a syscall to get TP. */
|
||||
strong_alias (__vdso_read_tp_stub, __m68k_read_tp)
|
||||
# endif /* SHARED */
|
35
sysdeps/unix/sysv/linux/m68k/m68k-vdso.c
Normal file
35
sysdeps/unix/sysv/linux/m68k/m68k-vdso.c
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifdef SHARED
|
||||
|
||||
#include <bits/m68k-vdso.h>
|
||||
|
||||
/* Because these pointers are used from other libraries than libc,
|
||||
they are exported at GLIBC_PRIVATE version.
|
||||
We initialize them to syscall implementation so that they will be ready
|
||||
to use from the very beginning. */
|
||||
void * M68K_VDSO_SYMBOL (__vdso_read_tp)
|
||||
= (void *) __vdso_read_tp_stub;
|
||||
void * M68K_VDSO_SYMBOL (__vdso_atomic_cmpxchg_32)
|
||||
= (void *) __vdso_atomic_cmpxchg_32_stub;
|
||||
void * M68K_VDSO_SYMBOL (__vdso_atomic_barrier)
|
||||
= (void *) __vdso_atomic_barrier_stub;
|
||||
|
||||
#endif /* SHARED */
|
172
sysdeps/unix/sysv/linux/m68k/nptl/bits/pthreadtypes.h
Normal file
172
sysdeps/unix/sysv/linux/m68k/nptl/bits/pthreadtypes.h
Normal file
@ -0,0 +1,172 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _BITS_PTHREADTYPES_H
|
||||
#define _BITS_PTHREADTYPES_H 1
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#define __SIZEOF_PTHREAD_ATTR_T 36
|
||||
#define __SIZEOF_PTHREAD_MUTEX_T 24
|
||||
#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
|
||||
#define __SIZEOF_PTHREAD_COND_T 48
|
||||
#define __SIZEOF_PTHREAD_CONDATTR_T 4
|
||||
#define __SIZEOF_PTHREAD_RWLOCK_T 32
|
||||
#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
|
||||
#define __SIZEOF_PTHREAD_BARRIER_T 20
|
||||
#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
|
||||
|
||||
|
||||
/* Thread identifiers. The structure of the attribute type is
|
||||
deliberately not exposed. */
|
||||
typedef unsigned long int pthread_t;
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_ATTR_T];
|
||||
long int __align;
|
||||
} pthread_attr_t;
|
||||
|
||||
|
||||
typedef struct __pthread_internal_slist
|
||||
{
|
||||
struct __pthread_internal_slist *__next;
|
||||
} __pthread_slist_t;
|
||||
|
||||
|
||||
/* Data structures for mutex handling. The structure of the attribute
|
||||
type is deliberately not exposed. */
|
||||
typedef union
|
||||
{
|
||||
struct __pthread_mutex_s
|
||||
{
|
||||
int __lock;
|
||||
unsigned int __count;
|
||||
int __owner;
|
||||
/* KIND must stay at this position in the structure to maintain
|
||||
binary compatibility. */
|
||||
int __kind;
|
||||
unsigned int __nusers;
|
||||
__extension__ union
|
||||
{
|
||||
int __spins;
|
||||
__pthread_slist_t __list;
|
||||
};
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_MUTEX_T];
|
||||
long int __align;
|
||||
} pthread_mutex_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
|
||||
int __align;
|
||||
} pthread_mutexattr_t;
|
||||
|
||||
|
||||
/* Data structure for conditional variable handling. The structure of
|
||||
the attribute type is deliberately not exposed. */
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int __lock;
|
||||
unsigned int __futex;
|
||||
__extension__ unsigned long long int __total_seq;
|
||||
__extension__ unsigned long long int __wakeup_seq;
|
||||
__extension__ unsigned long long int __woken_seq;
|
||||
void *__mutex;
|
||||
unsigned int __nwaiters;
|
||||
unsigned int __broadcast_seq;
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_COND_T];
|
||||
__extension__ long long int __align;
|
||||
} pthread_cond_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_CONDATTR_T];
|
||||
int __align;
|
||||
} pthread_condattr_t;
|
||||
|
||||
|
||||
/* Keys for thread-specific data */
|
||||
typedef unsigned int pthread_key_t;
|
||||
|
||||
|
||||
/* Once-only execution */
|
||||
typedef int pthread_once_t;
|
||||
|
||||
|
||||
#if defined __USE_UNIX98 || defined __USE_XOPEN2K
|
||||
/* Data structure for read-write lock variable handling. The
|
||||
structure of the attribute type is deliberately not exposed. */
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
int __lock;
|
||||
unsigned int __nr_readers;
|
||||
unsigned int __readers_wakeup;
|
||||
unsigned int __writer_wakeup;
|
||||
unsigned int __nr_readers_queued;
|
||||
unsigned int __nr_writers_queued;
|
||||
unsigned char __pad1;
|
||||
unsigned char __pad2;
|
||||
unsigned char __shared;
|
||||
/* FLAGS must stay at this position in the structure to maintain
|
||||
binary compatibility. */
|
||||
unsigned char __flags;
|
||||
int __writer;
|
||||
} __data;
|
||||
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
|
||||
long int __align;
|
||||
} pthread_rwlock_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
|
||||
long int __align;
|
||||
} pthread_rwlockattr_t;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __USE_XOPEN2K
|
||||
/* POSIX spinlock data type. */
|
||||
typedef volatile int pthread_spinlock_t;
|
||||
|
||||
|
||||
/* POSIX barriers data type. The structure of the type is
|
||||
deliberately not exposed. */
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_BARRIER_T];
|
||||
long int __align;
|
||||
} pthread_barrier_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
|
||||
int __align;
|
||||
} pthread_barrierattr_t;
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* bits/pthreadtypes.h */
|
36
sysdeps/unix/sysv/linux/m68k/nptl/bits/semaphore.h
Normal file
36
sysdeps/unix/sysv/linux/m68k/nptl/bits/semaphore.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#ifndef _SEMAPHORE_H
|
||||
# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
|
||||
#endif
|
||||
|
||||
|
||||
#define __SIZEOF_SEM_T 16
|
||||
|
||||
|
||||
/* Value returned if `sem_open' failed. */
|
||||
#define SEM_FAILED ((sem_t *) 0)
|
||||
|
||||
|
||||
typedef union
|
||||
{
|
||||
char __size[__SIZEOF_SEM_T];
|
||||
long int __align;
|
||||
} sem_t;
|
2
sysdeps/unix/sysv/linux/m68k/nptl/clone.S
Normal file
2
sysdeps/unix/sysv/linux/m68k/nptl/clone.S
Normal file
@ -0,0 +1,2 @@
|
||||
#define RESET_PID
|
||||
#include "../clone.S"
|
25
sysdeps/unix/sysv/linux/m68k/nptl/createthread.c
Normal file
25
sysdeps/unix/sysv/linux/m68k/nptl/createthread.c
Normal file
@ -0,0 +1,25 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Value passed to 'clone' for initialization of the thread register. */
|
||||
#define TLS_VALUE ((void *) (pd) \
|
||||
+ TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
|
||||
|
||||
/* Get the real implementation. */
|
||||
#include <nptl/sysdeps/pthread/createthread.c>
|
30
sysdeps/unix/sysv/linux/m68k/nptl/fork.c
Normal file
30
sysdeps/unix/sysv/linux/m68k/nptl/fork.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <sysdep.h>
|
||||
#include <tls.h>
|
||||
|
||||
#define ARCH_FORK() \
|
||||
INLINE_SYSCALL (clone, 5, \
|
||||
CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \
|
||||
NULL, &THREAD_SELF->tid, NULL)
|
||||
|
||||
#include <sysdeps/unix/sysv/linux/fork.c>
|
281
sysdeps/unix/sysv/linux/m68k/nptl/lowlevellock.h
Normal file
281
sysdeps/unix/sysv/linux/m68k/nptl/lowlevellock.h
Normal file
@ -0,0 +1,281 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
/* Borrowed from ARM's version. */
|
||||
|
||||
#ifndef _LOWLEVELLOCK_H
|
||||
#define _LOWLEVELLOCK_H 1
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/param.h>
|
||||
#include <bits/pthreadtypes.h>
|
||||
#include <atomic.h>
|
||||
#include <sysdep.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
#define FUTEX_WAIT 0
|
||||
#define FUTEX_WAKE 1
|
||||
#define FUTEX_REQUEUE 3
|
||||
#define FUTEX_CMP_REQUEUE 4
|
||||
#define FUTEX_WAKE_OP 5
|
||||
#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
|
||||
#define FUTEX_LOCK_PI 6
|
||||
#define FUTEX_UNLOCK_PI 7
|
||||
#define FUTEX_TRYLOCK_PI 8
|
||||
#define FUTEX_WAIT_BITSET 9
|
||||
#define FUTEX_WAKE_BITSET 10
|
||||
#define FUTEX_PRIVATE_FLAG 128
|
||||
#define FUTEX_CLOCK_REALTIME 256
|
||||
|
||||
#define FUTEX_BITSET_MATCH_ANY 0xffffffff
|
||||
|
||||
/* Values for 'private' parameter of locking macros. Yes, the
|
||||
definition seems to be backwards. But it is not. The bit will be
|
||||
reversed before passing to the system call. */
|
||||
#define LLL_PRIVATE 0
|
||||
#define LLL_SHARED FUTEX_PRIVATE_FLAG
|
||||
|
||||
|
||||
#if !defined NOT_IN_libc || defined IS_IN_rtld
|
||||
/* In libc.so or ld.so all futexes are private. */
|
||||
# ifdef __ASSUME_PRIVATE_FUTEX
|
||||
# define __lll_private_flag(fl, private) \
|
||||
((fl) | FUTEX_PRIVATE_FLAG)
|
||||
# else
|
||||
# define __lll_private_flag(fl, private) \
|
||||
((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
|
||||
# endif
|
||||
#else
|
||||
# ifdef __ASSUME_PRIVATE_FUTEX
|
||||
# define __lll_private_flag(fl, private) \
|
||||
(((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
|
||||
# else
|
||||
# define __lll_private_flag(fl, private) \
|
||||
(__builtin_constant_p (private) \
|
||||
? ((private) == 0 \
|
||||
? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
|
||||
: (fl)) \
|
||||
: ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
|
||||
& THREAD_GETMEM (THREAD_SELF, header.private_futex))))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#define lll_futex_wait(futexp, val, private) \
|
||||
lll_futex_timed_wait(futexp, val, NULL, private)
|
||||
|
||||
#define lll_futex_timed_wait(futexp, val, timespec, private) \
|
||||
({ \
|
||||
INTERNAL_SYSCALL_DECL (__err); \
|
||||
long int __ret; \
|
||||
__ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
|
||||
__lll_private_flag (FUTEX_WAIT, private), \
|
||||
(val), (timespec)); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define lll_futex_wake(futexp, nr, private) \
|
||||
({ \
|
||||
INTERNAL_SYSCALL_DECL (__err); \
|
||||
long int __ret; \
|
||||
__ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
|
||||
__lll_private_flag (FUTEX_WAKE, private), \
|
||||
(nr), 0); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define lll_robust_dead(futexv, private) \
|
||||
do \
|
||||
{ \
|
||||
int *__futexp = &(futexv); \
|
||||
atomic_or (__futexp, FUTEX_OWNER_DIED); \
|
||||
lll_futex_wake (__futexp, 1, private); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Returns non-zero if error happened, zero if success. */
|
||||
#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
|
||||
({ \
|
||||
INTERNAL_SYSCALL_DECL (__err); \
|
||||
long int __ret; \
|
||||
__ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
|
||||
__lll_private_flag (FUTEX_CMP_REQUEUE, private),\
|
||||
(nr_wake), (nr_move), (mutex), (val)); \
|
||||
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
|
||||
})
|
||||
|
||||
/* Returns non-zero if error happened, zero if success. */
|
||||
#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
|
||||
({ \
|
||||
INTERNAL_SYSCALL_DECL (__err); \
|
||||
long int __ret; \
|
||||
__ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
|
||||
__lll_private_flag (FUTEX_WAKE_OP, private), \
|
||||
(nr_wake), (nr_wake2), (futexp2), \
|
||||
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
|
||||
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
|
||||
})
|
||||
|
||||
#define lll_trylock(lock) \
|
||||
atomic_compare_and_exchange_val_acq (&(lock), 1, 0)
|
||||
|
||||
#define lll_cond_trylock(lock) \
|
||||
atomic_compare_and_exchange_val_acq (&(lock), 2, 0)
|
||||
|
||||
#define lll_robust_trylock(lock, id) \
|
||||
atomic_compare_and_exchange_val_acq (&(lock), id, 0)
|
||||
|
||||
extern void __lll_lock_wait_private (int *futex) attribute_hidden;
|
||||
extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
|
||||
extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
|
||||
|
||||
#define __lll_lock(futex, private) \
|
||||
((void) ({ \
|
||||
int *__futex = (futex); \
|
||||
if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, \
|
||||
1, 0), 0)) \
|
||||
{ \
|
||||
if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
|
||||
__lll_lock_wait_private (__futex); \
|
||||
else \
|
||||
__lll_lock_wait (__futex, private); \
|
||||
} \
|
||||
}))
|
||||
#define lll_lock(futex, private) __lll_lock (&(futex), private)
|
||||
|
||||
|
||||
#define __lll_robust_lock(futex, id, private) \
|
||||
({ \
|
||||
int *__futex = (futex); \
|
||||
int __val = 0; \
|
||||
\
|
||||
if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
|
||||
0), 0)) \
|
||||
__val = __lll_robust_lock_wait (__futex, private); \
|
||||
__val; \
|
||||
})
|
||||
#define lll_robust_lock(futex, id, private) \
|
||||
__lll_robust_lock (&(futex), id, private)
|
||||
|
||||
|
||||
#define __lll_cond_lock(futex, private) \
|
||||
((void) ({ \
|
||||
int *__futex = (futex); \
|
||||
if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0)) \
|
||||
__lll_lock_wait (__futex, private); \
|
||||
}))
|
||||
#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
|
||||
|
||||
|
||||
#define lll_robust_cond_lock(futex, id, private) \
|
||||
__lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
|
||||
|
||||
|
||||
extern int __lll_timedlock_wait (int *futex, const struct timespec *,
|
||||
int private) attribute_hidden;
|
||||
extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
|
||||
int private) attribute_hidden;
|
||||
|
||||
#define __lll_timedlock(futex, abstime, private) \
|
||||
({ \
|
||||
int *__futex = (futex); \
|
||||
int __val = 0; \
|
||||
\
|
||||
if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0)) \
|
||||
__val = __lll_timedlock_wait (__futex, abstime, private); \
|
||||
__val; \
|
||||
})
|
||||
#define lll_timedlock(futex, abstime, private) \
|
||||
__lll_timedlock (&(futex), abstime, private)
|
||||
|
||||
|
||||
#define __lll_robust_timedlock(futex, abstime, id, private) \
|
||||
({ \
|
||||
int *__futex = (futex); \
|
||||
int __val = 0; \
|
||||
\
|
||||
if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
|
||||
0), 0)) \
|
||||
__val = __lll_robust_timedlock_wait (__futex, abstime, private); \
|
||||
__val; \
|
||||
})
|
||||
#define lll_robust_timedlock(futex, abstime, id, private) \
|
||||
__lll_robust_timedlock (&(futex), abstime, id, private)
|
||||
|
||||
|
||||
#define __lll_unlock(futex, private) \
|
||||
(void) \
|
||||
({ int *__futex = (futex); \
|
||||
int __oldval = atomic_exchange_rel (__futex, 0); \
|
||||
if (__builtin_expect (__oldval > 1, 0)) \
|
||||
lll_futex_wake (__futex, 1, private); \
|
||||
})
|
||||
#define lll_unlock(futex, private) __lll_unlock(&(futex), private)
|
||||
|
||||
|
||||
#define __lll_robust_unlock(futex, private) \
|
||||
(void) \
|
||||
({ int *__futex = (futex); \
|
||||
int __oldval = atomic_exchange_rel (__futex, 0); \
|
||||
if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \
|
||||
lll_futex_wake (__futex, 1, private); \
|
||||
})
|
||||
#define lll_robust_unlock(futex, private) \
|
||||
__lll_robust_unlock(&(futex), private)
|
||||
|
||||
|
||||
#define lll_islocked(futex) \
|
||||
(futex != 0)
|
||||
|
||||
|
||||
/* Our internal lock implementation is identical to the binary-compatible
|
||||
mutex implementation. */
|
||||
|
||||
/* Initializers for lock. */
|
||||
#define LLL_LOCK_INITIALIZER (0)
|
||||
#define LLL_LOCK_INITIALIZER_LOCKED (1)
|
||||
|
||||
/* The states of a lock are:
|
||||
0 - untaken
|
||||
1 - taken by one user
|
||||
>1 - taken by more users */
|
||||
|
||||
/* The kernel notifies a process which uses CLONE_CLEARTID via futex
|
||||
wakeup when the clone terminates. The memory location contains the
|
||||
thread ID while the clone is running and is reset to zero
|
||||
afterwards. */
|
||||
#define lll_wait_tid(tid) \
|
||||
do { \
|
||||
__typeof (tid) __tid; \
|
||||
while ((__tid = (tid)) != 0) \
|
||||
lll_futex_wait (&(tid), __tid, LLL_SHARED); \
|
||||
} while (0)
|
||||
|
||||
extern int __lll_timedwait_tid (int *, const struct timespec *)
|
||||
attribute_hidden;
|
||||
|
||||
#define lll_timedwait_tid(tid, abstime) \
|
||||
({ \
|
||||
int __res = 0; \
|
||||
if ((tid) != 0) \
|
||||
__res = __lll_timedwait_tid (&(tid), (abstime)); \
|
||||
__res; \
|
||||
})
|
||||
|
||||
#endif /* lowlevellock.h */
|
36
sysdeps/unix/sysv/linux/m68k/nptl/pt-vfork.S
Normal file
36
sysdeps/unix/sysv/linux/m68k/nptl/pt-vfork.S
Normal file
@ -0,0 +1,36 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <tcb-offsets.h>
|
||||
|
||||
#define SAVE_PID \
|
||||
bsrl __m68k_read_tp@PLTPC ; /* Get the thread pointer. */ \
|
||||
movel %a0, %a1 ; /* Save TP for RESTORE_PID. */ \
|
||||
movel PID_OFFSET(%a1), %d0 ; /* Get the PID. */ \
|
||||
movel %d0, %d1 ; /* Save PID for RESTORE_PID. */ \
|
||||
negl %d0 ; /* Negate the PID. */ \
|
||||
movel %d0, PID_OFFSET(%a1) ; /* Store the temporary PID. */
|
||||
|
||||
#define RESTORE_PID \
|
||||
tstl %d0 ; \
|
||||
beq 1f ; /* If we are the parent... */ \
|
||||
movel %d1, PID_OFFSET(%a1) ; /* Restore the PID. */ \
|
||||
1:
|
||||
|
||||
#include <sysdeps/unix/sysv/linux/m68k/vfork.S>
|
91
sysdeps/unix/sysv/linux/m68k/nptl/pthread_once.c
Normal file
91
sysdeps/unix/sysv/linux/m68k/nptl/pthread_once.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include "pthreadP.h"
|
||||
#include <lowlevellock.h>
|
||||
|
||||
unsigned long int __fork_generation attribute_hidden;
|
||||
|
||||
static void
|
||||
clear_once_control (void *arg)
|
||||
{
|
||||
pthread_once_t *once_control = (pthread_once_t *) arg;
|
||||
|
||||
*once_control = 0;
|
||||
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
|
||||
}
|
||||
|
||||
int
|
||||
__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
int oldval;
|
||||
int newval;
|
||||
|
||||
/* Pseudo code:
|
||||
newval = __fork_generation | 1;
|
||||
oldval = *once_control;
|
||||
if ((oldval & 2) == 0)
|
||||
*once_control = newval;
|
||||
Do this atomically.
|
||||
*/
|
||||
do
|
||||
{
|
||||
newval = __fork_generation | 1;
|
||||
oldval = *once_control;
|
||||
if (oldval & 2)
|
||||
break;
|
||||
} while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);
|
||||
|
||||
/* Check if the initializer has already been done. */
|
||||
if ((oldval & 2) != 0)
|
||||
return 0;
|
||||
|
||||
/* Check if another thread already runs the initializer. */
|
||||
if ((oldval & 1) == 0)
|
||||
break;
|
||||
|
||||
/* Check whether the initializer execution was interrupted by a fork. */
|
||||
if (oldval != newval)
|
||||
break;
|
||||
|
||||
/* Same generation, some other thread was faster. Wait. */
|
||||
lll_futex_wait (once_control, oldval, LLL_PRIVATE);
|
||||
}
|
||||
|
||||
/* This thread is the first here. Do the initialization.
|
||||
Register a cleanup handler so that in case the thread gets
|
||||
interrupted the initialization can be restarted. */
|
||||
pthread_cleanup_push (clear_once_control, once_control);
|
||||
|
||||
init_routine ();
|
||||
|
||||
pthread_cleanup_pop (0);
|
||||
|
||||
/* Say that the initialisation is done. */
|
||||
*once_control = __fork_generation | 2;
|
||||
|
||||
/* Wake up all other threads. */
|
||||
lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
weak_alias (__pthread_once, pthread_once)
|
||||
strong_alias (__pthread_once, __pthread_once_internal)
|
141
sysdeps/unix/sysv/linux/m68k/nptl/sysdep-cancel.h
Normal file
141
sysdeps/unix/sysv/linux/m68k/nptl/sysdep-cancel.h
Normal file
@ -0,0 +1,141 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <sysdep.h>
|
||||
#include <tls.h>
|
||||
#ifndef __ASSEMBLER__
|
||||
# include <nptl/pthreadP.h>
|
||||
#endif
|
||||
|
||||
#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
|
||||
|
||||
# undef PSEUDO
|
||||
# define PSEUDO(name, syscall_name, args) \
|
||||
.text; \
|
||||
ENTRY (name) \
|
||||
SINGLE_THREAD_P; \
|
||||
jne .Lpseudo_cancel; \
|
||||
.type __##syscall_name##_nocancel,@function; \
|
||||
.globl __##syscall_name##_nocancel; \
|
||||
__##syscall_name##_nocancel: \
|
||||
DO_CALL (syscall_name, args); \
|
||||
cmp.l &-4095, %d0; \
|
||||
jcc SYSCALL_ERROR_LABEL; \
|
||||
rts; \
|
||||
.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \
|
||||
.Lpseudo_cancel: \
|
||||
cfi_startproc; \
|
||||
CENABLE; \
|
||||
DOCARGS_##args \
|
||||
move.l %d0, -(%sp); /* Save result of CENABLE. */ \
|
||||
cfi_adjust_cfa_offset (4); \
|
||||
move.l &SYS_ify (syscall_name), %d0; \
|
||||
trap &0; \
|
||||
move.l %d0, %d2; \
|
||||
CDISABLE; \
|
||||
addq.l &4, %sp; /* Remove result of CENABLE from the stack. */ \
|
||||
cfi_adjust_cfa_offset (-4); \
|
||||
move.l %d2, %d0; \
|
||||
UNDOCARGS_##args \
|
||||
cmp.l &-4095, %d0; \
|
||||
jcc SYSCALL_ERROR_LABEL; \
|
||||
cfi_endproc
|
||||
|
||||
/* Note: we use D2 to save syscall's return value as D0 will be clobbered in
|
||||
CDISABLE. */
|
||||
# define DOCARGS_0 move.l %d2, -(%sp); \
|
||||
cfi_adjust_cfa_offset (4); cfi_rel_offset (%d2, 0);
|
||||
# define UNDOCARGS_0 move.l (%sp)+, %d2; \
|
||||
cfi_adjust_cfa_offset (-4); cfi_restore (%d2);
|
||||
|
||||
# define DOCARGS_1 _DOCARGS_1 (4); DOCARGS_0
|
||||
# define _DOCARGS_1(n) move.l n(%sp), %d1;
|
||||
# define UNDOCARGS_1 UNDOCARGS_0
|
||||
|
||||
# define DOCARGS_2 _DOCARGS_2 (8)
|
||||
# define _DOCARGS_2(n) DOCARGS_0 move.l n+4(%sp), %d2; _DOCARGS_1 (n)
|
||||
# define UNDOCARGS_2 UNDOCARGS_0
|
||||
|
||||
/* TODO: We can optimize DOCARGS_{3, 4} by saving registers to a0 and a1
|
||||
instead of pushing them on stack. */
|
||||
# define DOCARGS_3 _DOCARGS_3 (12)
|
||||
# define _DOCARGS_3(n) move.l %d3, -(%sp); \
|
||||
cfi_adjust_cfa_offset (4); cfi_rel_offset (%d3, 0); \
|
||||
move.l n+4(%sp), %d3; _DOCARGS_2 (n)
|
||||
# define UNDOCARGS_3 UNDOCARGS_2 move.l (%sp)+, %d3; \
|
||||
cfi_adjust_cfa_offset (-4); cfi_restore (%d3);
|
||||
|
||||
# define DOCARGS_4 _DOCARGS_4 (16)
|
||||
# define _DOCARGS_4(n) move.l %d4, -(%sp); \
|
||||
cfi_adjust_cfa_offset (4); cfi_rel_offset (%d4, 0); \
|
||||
move.l n+4(%sp), %d4; _DOCARGS_3 (n)
|
||||
# define UNDOCARGS_4 UNDOCARGS_3 move.l (%sp)+, %d4; \
|
||||
cfi_adjust_cfa_offset (-4); cfi_restore (%d4);
|
||||
|
||||
# define DOCARGS_5 _DOCARGS_5 (20)
|
||||
# define _DOCARGS_5(n) move.l %d5, %a1; cfi_register (%d5, a1); \
|
||||
move.l n(%sp), %d5; _DOCARGS_4 (n-4)
|
||||
# define UNDOCARGS_5 UNDOCARGS_4 move.l %a1, %d5; cfi_restore (%d5);
|
||||
|
||||
# define DOCARGS_6 _DOCARGS_6 (24)
|
||||
# define _DOCARGS_6(n) move.l n(%sp), %a0; _DOCARGS_5 (n-4)
|
||||
# define UNDOCARGS_6 UNDOCARGS_5
|
||||
|
||||
# ifdef PIC
|
||||
# define PSEUDO_JMP(sym) jbsr sym ## @PLTPC
|
||||
# else
|
||||
# define PSEUDO_JMP(sym) jbsr sym
|
||||
# endif
|
||||
|
||||
# ifdef IS_IN_libpthread
|
||||
# define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel)
|
||||
# define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel)
|
||||
# elif !defined NOT_IN_libc
|
||||
# define CENABLE PSEUDO_JMP (__libc_enable_asynccancel)
|
||||
# define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel)
|
||||
# elif defined IS_IN_librt
|
||||
# define CENABLE PSEUDO_JMP (__librt_enable_asynccancel)
|
||||
# define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel)
|
||||
# else
|
||||
# error Unsupported library
|
||||
# endif
|
||||
|
||||
# ifndef __ASSEMBLER__
|
||||
# define SINGLE_THREAD_P \
|
||||
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
|
||||
header.multiple_threads) == 0, 1)
|
||||
# else
|
||||
# define SINGLE_THREAD_P \
|
||||
PSEUDO_JMP (__m68k_read_tp); \
|
||||
tst.l MULTIPLE_THREADS_OFFSET(%a0)
|
||||
# endif
|
||||
|
||||
#elif !defined __ASSEMBLER__
|
||||
|
||||
# define SINGLE_THREAD_P (1)
|
||||
# define NO_CANCELLATION (1)
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
# define RTLD_SINGLE_THREAD_P \
|
||||
__builtin_expect (THREAD_GETMEM (THREAD_SELF, \
|
||||
header.multiple_threads) == 0, \
|
||||
1)
|
||||
#endif
|
38
sysdeps/unix/sysv/linux/m68k/nptl/vfork.S
Normal file
38
sysdeps/unix/sysv/linux/m68k/nptl/vfork.S
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
|
||||
|
||||
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, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <tcb-offsets.h>
|
||||
|
||||
#define SAVE_PID \
|
||||
bsrl __m68k_read_tp@PLTPC ; /* Get the thread pointer. */ \
|
||||
movel %a0, %a1 ; /* Save TP for RESTORE_PID. */ \
|
||||
movel PID_OFFSET(%a1), %d0 ; /* Get the PID. */ \
|
||||
movel %d0, %d1 ; /* Save PID for RESTORE_PID. */ \
|
||||
negl %d0 ; /* Negate the PID. */ \
|
||||
bne 1f ; /* If it was zero... */ \
|
||||
movel #0x80000000, %d0 ; /* use 0x80000000 instead. */ \
|
||||
1: movel %d0, PID_OFFSET(%a1) ; /* Store the temporary PID. */
|
||||
|
||||
#define RESTORE_PID \
|
||||
tstl %d0 ; \
|
||||
beq 1f ; /* If we are the parent... */ \
|
||||
movel %d1, PID_OFFSET(%a1) ; /* Restore the PID. */ \
|
||||
1:
|
||||
|
||||
#include <sysdeps/unix/sysv/linux/m68k/vfork.S>
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 1998, 2010 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
|
||||
@ -41,8 +41,11 @@
|
||||
|
||||
.globl __socket
|
||||
ENTRY (__socket)
|
||||
#if defined NEED_CANCELLATION && defined CENABLE
|
||||
SINGLE_THREAD_P (%a0)
|
||||
#ifdef NEED_CANCELLATION
|
||||
# if !defined CENABLE || !defined CDISABLE
|
||||
# error CENABLE and/or CDISABLE is not defined
|
||||
# endif
|
||||
SINGLE_THREAD_P
|
||||
jne 1f
|
||||
#endif
|
||||
|
||||
@ -69,21 +72,26 @@ ENTRY (__socket)
|
||||
/* Successful; return the syscall's value. */
|
||||
rts
|
||||
|
||||
#if defined NEED_CANCELLATION && defined CENABLE
|
||||
1: /* Enable asynchronous cancellation. */
|
||||
#ifdef NEED_CANCELLATION
|
||||
1: cfi_startproc
|
||||
/* Enable asynchronous cancellation. */
|
||||
CENABLE
|
||||
|
||||
/* Save registers. */
|
||||
/* Save D2. */
|
||||
move.l %d2, -(%sp)
|
||||
move.l %d0, -(%sp)
|
||||
cfi_adjust_cfa_offset (4)
|
||||
cfi_rel_offset (%d2, 0)
|
||||
|
||||
move.l #SYS_ify (socketcall), %d0 /* System call number in %d0. */
|
||||
/* Save the result of CENABLE. */
|
||||
move.l %d0, -(%sp)
|
||||
cfi_adjust_cfa_offset (4)
|
||||
|
||||
/* Use ## so `socket' is a separate token that might be #define'd. */
|
||||
move.l #P (SOCKOP_,socket), %d1 /* Subcode is first arg to syscall. */
|
||||
lea 4+8(%sp), %a1 /* Address of args is 2nd arg. */
|
||||
move.l %a1, %d2
|
||||
|
||||
move.l #SYS_ify (socketcall), %d0 /* System call number in %d0. */
|
||||
/* Do the system call trap. */
|
||||
trap #0
|
||||
|
||||
@ -91,14 +99,18 @@ ENTRY (__socket)
|
||||
move.l %d0, %d2
|
||||
CDISABLE
|
||||
addq.l #4, %sp
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
move.l %d2, %d0
|
||||
|
||||
/* Restore registers. */
|
||||
move.l (%sp)+, %d2
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
cfi_restore (%d2)
|
||||
|
||||
/* %d0 is < 0 if there was an error. */
|
||||
tst.l %d0
|
||||
jmi SYSCALL_ERROR_LABEL
|
||||
cfi_endproc
|
||||
|
||||
/* Successful; return the syscall's value. */
|
||||
rts
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004, 2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2010
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Written by Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>,
|
||||
December 1995.
|
||||
@ -23,6 +24,7 @@
|
||||
|
||||
#include <sysdeps/unix/sysdep.h>
|
||||
#include <sysdeps/m68k/sysdep.h>
|
||||
#include <tls.h>
|
||||
|
||||
/* Defines RTLD_PRIVATE_ERRNO. */
|
||||
#include <dl-sysdep.h>
|
||||
@ -148,9 +150,11 @@ SYSCALL_ERROR_LABEL: \
|
||||
arg 3 %d3 call-saved
|
||||
arg 4 %d4 call-saved
|
||||
arg 5 %d5 call-saved
|
||||
arg 6 %a0 call-clobbered
|
||||
|
||||
The stack layout upon entering the function is:
|
||||
|
||||
24(%sp) Arg# 6
|
||||
20(%sp) Arg# 5
|
||||
16(%sp) Arg# 4
|
||||
12(%sp) Arg# 3
|
||||
@ -229,7 +233,7 @@ SYSCALL_ERROR_LABEL: \
|
||||
normally. It will never touch errno. This returns just what the kernel
|
||||
gave back. */
|
||||
#undef INTERNAL_SYSCALL
|
||||
#define INTERNAL_SYSCALL(name, err, nr, args...) \
|
||||
#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
|
||||
({ unsigned int _sys_result; \
|
||||
{ \
|
||||
/* Load argument values in temporary variables
|
||||
@ -237,7 +241,7 @@ SYSCALL_ERROR_LABEL: \
|
||||
before the call used registers are set. */ \
|
||||
LOAD_ARGS_##nr (args) \
|
||||
LOAD_REGS_##nr \
|
||||
register int _d0 asm ("%d0") = __NR_##name; \
|
||||
register int _d0 asm ("%d0") = name; \
|
||||
asm volatile ("trap #0" \
|
||||
: "=d" (_d0) \
|
||||
: "0" (_d0) ASM_ARGS_##nr \
|
||||
@ -245,6 +249,8 @@ SYSCALL_ERROR_LABEL: \
|
||||
_sys_result = _d0; \
|
||||
} \
|
||||
(int) _sys_result; })
|
||||
#define INTERNAL_SYSCALL(name, err, nr, args...) \
|
||||
INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
|
||||
|
||||
#undef INTERNAL_SYSCALL_ERROR_P
|
||||
#define INTERNAL_SYSCALL_ERROR_P(val, err) \
|
||||
@ -300,4 +306,15 @@ SYSCALL_ERROR_LABEL: \
|
||||
#define ASM_ARGS_6 ASM_ARGS_5, "a" (_a0)
|
||||
|
||||
#endif /* not __ASSEMBLER__ */
|
||||
|
||||
/* Pointer mangling is not yet supported for M68K. */
|
||||
#define PTR_MANGLE(var) (void) (var)
|
||||
#define PTR_DEMANGLE(var) (void) (var)
|
||||
|
||||
#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
|
||||
/* M68K needs system-supplied DSO to access TLS helpers
|
||||
even when statically linked. */
|
||||
# define NEED_STATIC_SYSINFO_DSO 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999, 2002, 2003, 2010 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Andreas Schwab <schwab@gnu.org>.
|
||||
|
||||
@ -22,6 +22,14 @@
|
||||
#include <bits/errno.h>
|
||||
#include <kernel-features.h>
|
||||
|
||||
#ifndef SAVE_PID
|
||||
#define SAVE_PID
|
||||
#endif
|
||||
|
||||
#ifndef RESTORE_PID
|
||||
#define RESTORE_PID
|
||||
#endif
|
||||
|
||||
/* Clone the calling process, but without copying the whole address space.
|
||||
The calling process is suspended until the new process exits or is
|
||||
replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
|
||||
@ -31,12 +39,20 @@ ENTRY (__vfork)
|
||||
|
||||
#ifdef __NR_vfork
|
||||
|
||||
/* SAVE_PID clobbers call-clobbered registers and
|
||||
saves data in D1 and A1. */
|
||||
|
||||
SAVE_PID
|
||||
|
||||
/* Pop the return PC value into A0. */
|
||||
movel %sp@+, %a0
|
||||
|
||||
/* Stuff the syscall number in D0 and trap into the kernel. */
|
||||
movel #SYS_ify (vfork), %d0
|
||||
trap #0
|
||||
|
||||
RESTORE_PID
|
||||
|
||||
tstl %d0
|
||||
jmi .Lerror /* Branch forward if it failed. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user