NPTL support for m68k/ColdFire

This commit is contained in:
Maxim Kuvyrkov 2010-03-12 19:50:55 +01:00 committed by Andreas Schwab
parent 75e73e66e4
commit 40111cb9e1
33 changed files with 1886 additions and 20 deletions

View File

@ -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.

View File

@ -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
View 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
View 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

View 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

View 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;
}

View 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;
}

View 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))

View 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
View 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
View 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); })

View File

@ -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

View File

@ -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;
}
}

View 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 */

View File

@ -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)

View 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

View 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>

View File

@ -0,0 +1 @@
#include "m68k-vdso.c"

View 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 */

View 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 */

View 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 */

View 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;

View File

@ -0,0 +1,2 @@
#define RESET_PID
#include "../clone.S"

View 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>

View 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>

View 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 */

View 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>

View 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)

View 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

View 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>

View File

@ -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

View File

@ -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

View File

@ -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. */