Linux: Add the tgkill function

Message ID 87v9zomhxp.fsf@oldenburg2.str.redhat.com
State Committed
Headers

Commit Message

Florian Weimer April 8, 2019, 7:10 p.m. UTC
  The tgkill function is sometimes used in crash handlers.

<bits/signal_ext.h> follows the same approach as <bits/unistd_ext.h>
(which was added for the gettid system call wrapper).

2019-04-08  Florian Weimer  <fweimer@redhat.com>

	Linux: Add the tgkill function.
	* bits/signal_ext.h: New file.
	* manual/signal.texi (Signaling Another Process): Document tgkill.
	* signal/Makefile (headers): Add bits/signal_ext.h.
	* signal/signal.h: Include <bits/signal_ext.h>.
	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-tgkill.
	(tst-tgkill): Link with libpthread.
	* sysdeps/unix/sysv/linux/Versions (GLIBC_2.30): Export tgkill.
	* sysdeps/unix/sysv/linux/bits/signal_ext.h: New file.
	* sysdeps/unix/sysv/linux/bits/tst-tgkill.c: Likewise.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.30): Add
	tgkill.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/csky/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
  

Comments

Carlos O'Donell May 14, 2019, 4:29 p.m. UTC | #1
On 4/8/19 3:10 PM, Florian Weimer wrote:
> The tgkill function is sometimes used in crash handlers.

Thank you for continuing to work through the list of missing kernel
syscalls which could have use within userspace programs and adding
wrappers for them.

> <bits/signal_ext.h> follows the same approach as <bits/unistd_ext.h>
> (which was added for the gettid system call wrapper).

OK. I like that.

> 2019-04-08  Florian Weimer  <fweimer@redhat.com>
> 
> 	Linux: Add the tgkill function.
> 	* bits/signal_ext.h: New file.
> 	* manual/signal.texi (Signaling Another Process): Document tgkill.
> 	* signal/Makefile (headers): Add bits/signal_ext.h.
> 	* signal/signal.h: Include <bits/signal_ext.h>.
> 	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-tgkill.
> 	(tst-tgkill): Link with libpthread.
> 	* sysdeps/unix/sysv/linux/Versions (GLIBC_2.30): Export tgkill.
> 	* sysdeps/unix/sysv/linux/bits/signal_ext.h: New file.
> 	* sysdeps/unix/sysv/linux/bits/tst-tgkill.c: Likewise.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.30): Add
> 	tgkill.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/csky/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
> 

OK for master if you can explain the usage of EXTRA, and add comments
to the test case.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> diff --git a/NEWS b/NEWS
> index b58e2469d4..61c6575ae5 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -16,7 +16,7 @@ Major new features:
>  * The dynamic linker accepts the --preload argument to preload shared
>    objects, in addition to the LD_PRELOAD environment variable.
>  
> -* On Linux, the gettid function has been added.
> +* On Linux, the gettid and tgkill functions have been added.

OK.

>  
>  * Minguo (Republic of China) calendar support has been added as an
>    alternative calendar for the following locales: zh_TW, cmn_TW, hak_TW,
> diff --git a/bits/signal_ext.h b/bits/signal_ext.h
> new file mode 100644
> index 0000000000..d1bed56e55
> --- /dev/null
> +++ b/bits/signal_ext.h
> @@ -0,0 +1,21 @@
> +/* System-specific extensions of <signal.h>, generic version.

OK.

> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SIGNAL_H
> +# error "Never include <bits/signal_ext.h> directly; use <signal.h> instead."
> +#endif

OK.

> diff --git a/manual/signal.texi b/manual/signal.texi
> index 8b3a52e22a..33e6646975 100644
> --- a/manual/signal.texi
> +++ b/manual/signal.texi
> @@ -2291,6 +2291,21 @@ The @var{pid} argument does not refer to an existing process or group.
>  @end table
>  @end deftypefun
>  
> +@deftypefun int tgkill (pid_t @var{pid}, pid_t @var{tid}, int @var{signum})
> +@standards{Linux, signal.h}
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> +The @code{tgkill} function sends the signal @var{signum} to the thread
> +or process with ID @var{tid}, like the @code{kill} function, but only
> +if the process ID of the thread @var{tid} is equal to @var{pid}.  If
> +the target thread belongs to another process, the function fails with
> +@code{ESRCH}.

OK.

> +
> +The @code{tgkill} function can be used to avoid sending a signal to a
> +thread in the wrong process if the caller ensures that the passed
> +@var{pid} value is not reused by the kernel (for example, if it is the
> +process ID of the current process, as returned by @code{getpid}).
> +@end deftypefun

OK. Well written.

> +
>  @deftypefun int killpg (int @var{pgid}, int @var{signum})
>  @standards{BSD, signal.h}
>  @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
> diff --git a/signal/Makefile b/signal/Makefile
> index 06034fee8e..4596112f0a 100644
> --- a/signal/Makefile
> +++ b/signal/Makefile
> @@ -31,7 +31,7 @@ headers := signal.h sys/signal.h \
>  	   bits/types/sigevent_t.h bits/types/siginfo_t.h \
>  	   bits/types/sigset_t.h bits/types/sigval_t.h \
>  	   bits/types/stack_t.h bits/types/struct_sigstack.h \
> -	   bits/types/__sigval_t.h
> +	   bits/types/__sigval_t.h bits/signal_ext.h

OK.

>  
>  routines	:= signal raise killpg \
>  		   sigaction sigprocmask kill \
> diff --git a/signal/signal.h b/signal/signal.h
> index ee591fcb2d..4c0de7f6ce 100644
> --- a/signal/signal.h
> +++ b/signal/signal.h
> @@ -370,6 +370,9 @@ extern int __libc_current_sigrtmax (void) __THROW;
>  #define SIGRTMIN        (__libc_current_sigrtmin ())
>  #define SIGRTMAX        (__libc_current_sigrtmax ())
>  
> +/* System-specific extensions.  */
> +#include <bits/signal_ext.h>

OK.

> +
>  __END_DECLS
>  
>  #endif /* not signal.h */
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 52ac6ad484..d2f0b60ea9 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -53,7 +53,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
>  tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
>  	 tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
>  	 test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
> -	 tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill
> +	 tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill \
> +	 tst-tgkill

OK.

>  tests-internal += tst-ofdlocks-compat
>  
>  # Generate the list of SYS_* macros for the system calls (__NR_*
> @@ -115,6 +116,7 @@ $(objpfx)tst-mman-consts.out: ../sysdeps/unix/sysv/linux/tst-mman-consts.py
>  
>  $(objpfx)tst-gettid: $(shared-thread-library)
>  $(objpfx)tst-gettid-kill: $(shared-thread-library)
> +$(objpfx)tst-tgkill: $(shared-thread-library)

OK.

>  
>  endif # $(subdir) == misc
>  
> diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
> index 5166ccff25..c7137e2c2c 100644
> --- a/sysdeps/unix/sysv/linux/Versions
> +++ b/sysdeps/unix/sysv/linux/Versions
> @@ -175,7 +175,7 @@ libc {
>      getcpu;
>    }
>    GLIBC_2.30 {
> -    gettid;
> +    gettid; tgkill;

OK.

>    }
>    GLIBC_PRIVATE {
>      # functions used in other libraries
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index f3b44d723f..0b5f7aebaa 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2142,3 +2142,4 @@ GLIBC_2.29 getcpu F
>  GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index fd81fc4ad0..9563d753c7 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2217,6 +2217,7 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F


OK.

>  GLIBC_2.4 _IO_fprintf F
>  GLIBC_2.4 _IO_printf F
>  GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index f451fefac9..6a5ada177a 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -127,6 +127,7 @@ GLIBC_2.29 getcpu F
>  GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _Exit F
>  GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
>  GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
> diff --git a/sysdeps/unix/sysv/linux/bits/signal_ext.h b/sysdeps/unix/sysv/linux/bits/signal_ext.h
> new file mode 100644
> index 0000000000..c07b869fab
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/signal_ext.h
> @@ -0,0 +1,31 @@
> +/* System-specific extensions of <signal.h>, Linux version.

OK.

> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SIGNAL_H
> +# error "Never include <bits/signal_ext.h> directly; use <signal.h> instead."
> +#endif
> +
> +#ifdef __USE_GNU
> +
> +/* Send SIGNAL to the thread TID in the thread group (process)
> +   identified by TGID.  This function behaves like kill, but also
> +   fails with ESRCH if the specified TID does not belong to the
> +   specified thread group.  */
> +extern int tgkill (__pid_t __tgid, __pid_t __tid, int __signal);

OK.

> +
> +#endif /* __USE_GNU */
> diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
> index 018d02b414..2dc527cebd 100644
> --- a/sysdeps/unix/sysv/linux/csky/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
> @@ -2086,3 +2086,4 @@ GLIBC_2.29 xencrypt F
>  GLIBC_2.29 xprt_register F
>  GLIBC_2.29 xprt_unregister F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index fc3c5d5c27..740b83717f 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -2038,6 +2038,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index f2b04dbbff..04fde8ab0f 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2204,6 +2204,7 @@ GLIBC_2.3.4 vm86 F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index 10ecf2e47c..9190624dae 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -2070,6 +2070,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 814e81b9d2..d70c1eaa7a 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -128,6 +128,7 @@ GLIBC_2.29 getcpu F
>  GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _Exit F
>  GLIBC_2.4 _IO_2_1_stderr_ D 0x98
>  GLIBC_2.4 _IO_2_1_stdin_ D 0x98
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 68e80372e7..c265f4c546 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -2147,6 +2147,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> index 31178e4f54..e431ed031b 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -2134,3 +2134,4 @@ GLIBC_2.29 getcpu F
>  GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index 7074573638..590fde4faa 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index 154f9c77fc..9f3ea18f48 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -2119,6 +2119,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index 97b8f42d5c..0271cd04c9 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -2127,6 +2127,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index 5b3e85de93..546c5fd7b8 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -2121,6 +2121,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index 04a130a81c..6c2baff0f1 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2175,3 +2175,4 @@ GLIBC_2.29 getcpu F
>  GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index a701584422..b2d510fe4b 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -2177,6 +2177,7 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _IO_fprintf F
>  GLIBC_2.4 _IO_printf F
>  GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index bbb647cd98..b8923218b2 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -2210,6 +2210,7 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _IO_fprintf F
>  GLIBC_2.4 _IO_printf F
>  GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> index bb23bf61a8..50f200e513 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> @@ -2040,6 +2040,7 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _IO_fprintf F
>  GLIBC_2.4 _IO_printf F
>  GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> index 7921dda979..978d3b586c 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> @@ -2244,3 +2244,4 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> index da123d3867..4f3c033119 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> @@ -2104,3 +2104,4 @@ GLIBC_2.29 getcpu F
>  GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index 2aed339af4..16003407e4 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -2172,6 +2172,7 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _IO_fprintf F
>  GLIBC_2.4 _IO_printf F
>  GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index e46feb56e5..5d3b1547ed 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -2076,6 +2076,7 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _IO_fprintf F
>  GLIBC_2.4 _IO_printf F
>  GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
> index 24a8f934cb..5e7ecd0e26 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -2042,6 +2042,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index ebdbd2c5ae..a3def2c7da 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -2166,6 +2166,7 @@ GLIBC_2.30 __nldbl_vwarnx F
>  GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 _IO_fprintf F
>  GLIBC_2.4 _IO_printf F
>  GLIBC_2.4 _IO_sprintf F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index 0992349b06..c8abe63ad5 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -2093,6 +2093,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
> index 25424e1399..75a2f23a17 100644
> --- a/sysdeps/unix/sysv/linux/syscalls.list
> +++ b/sysdeps/unix/sysv/linux/syscalls.list
> @@ -111,3 +111,4 @@ memfd_create    EXTRA	memfd_create	i:si    memfd_create
>  pkey_alloc	EXTRA	pkey_alloc	i:ii	pkey_alloc
>  pkey_free	EXTRA	pkey_free	i:i	pkey_free
>  gettid          EXTRA   gettid          Ei:     __gettid	gettid
> +tgkill          EXTRA   tgkill          i:ii    __tgkill	tgkill

The signature for tgkill should be i:iii (missing an 'i').

I'll be honest and admit I never paid attention to the semantic meaning of EXTRA.

Why does tgkill have caller EXTRA?

As far as I know 'EXTRA' triggers the object to be added to unix-extra-syscalls,
whose only effect is to put the syscall into sysdep_routines for subdir misc,
and beyond that it isn't clear why it's needed at all (even for all the other
syscalls). What does sysdep_routines really provide here?

> diff --git a/sysdeps/unix/sysv/linux/tst-tgkill.c b/sysdeps/unix/sysv/linux/tst-tgkill.c
> new file mode 100644
> index 0000000000..818e2f58da
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-tgkill.c
> @@ -0,0 +1,132 @@
> +/* Smoke test for the tgkill system call.

OK.

> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +

This test needs to explain what it's doing, and the intent of those
actions. For example, what does the parent process do, what is 
expected from the child processes?

> +#include <errno.h>
> +#include <signal.h>
> +#include <support/check.h>
> +#include <support/namespace.h>
> +#include <support/xthread.h>
> +#include <unistd.h>
> +
> +/* Number of times sigusr1_handler has been invoked.  */
> +static volatile sig_atomic_t signals_delivered;
> +
> +/* Expected TID of the thread receiving the signal.  */
> +static pid_t expected_signal_tid;
> +
> +static void
> +sigusr1_handler (int signo)
> +{
> +  TEST_COMPARE (expected_signal_tid, gettid ());
> +  ++signals_delivered;
> +}
> +
> +struct pid_and_tid
> +{
> +  pid_t pid;
> +  pid_t tid;
> +};
> +
> +/* Send signals from the subprocess which are not expected to be
> +   delivered.  There is no handler for SIGUSR2, so delivery will
> +   result in a test failure.  CLOSURE must point to a valid PID/TID
> +   combination that is still running.  */

Please explain why they are not expected to be delivered.

> +static void
> +subprocess_no_tid_match (void *closure)
> +{
> +  struct pid_and_tid *ids = closure;
> +  TEST_COMPARE (tgkill (ids->pid, gettid (), SIGUSR2), -1);
> +  TEST_COMPARE (errno, ESRCH);
> +
> +  TEST_COMPARE (tgkill (getpid (), ids->tid, SIGUSR2), -1);
> +  TEST_COMPARE (errno, ESRCH);
> +
> +  TEST_COMPARE (tgkill (getppid (), gettid (), SIGUSR2), -1);
> +  TEST_COMPARE (errno, ESRCH);
> +}

OK.

> +
> +/* Called from threadfunc below.  */
> +static void
> +subprocess (void *closure)
> +{
> +  int original_tid = expected_signal_tid;
> +
> +  /* Do not expect that the folloing signals are delivered to the
> +     subprocess.  The parent process retains the original
> +     expected_signal_tid value.  */

Likewise, why are they not expected to be delivered.

> +  expected_signal_tid = 0;
> +  TEST_COMPARE (tgkill (getpid (), original_tid, SIGUSR1), -1);
> +  TEST_COMPARE (errno, ESRCH);
> +  TEST_COMPARE (tgkill (getppid (), gettid (), SIGUSR1), -1);
> +  TEST_COMPARE (errno, ESRCH);
> +  TEST_COMPARE (expected_signal_tid, 0);
> +
> +  /* This call has the correct PID/TID combination and is therefore
> +     expected to suceed.  */
> +  TEST_COMPARE (tgkill (getppid (), original_tid, SIGUSR1), 0);
> +}

OK.

> +
> +static void *
> +threadfunc (void *closure)
> +{
> +  TEST_VERIFY (gettid () != getpid ());
> +  expected_signal_tid = gettid ();
> +  TEST_COMPARE (tgkill (getpid (), gettid (), SIGUSR1), 0);
> +  TEST_COMPARE (signals_delivered, 1);
> +  signals_delivered = 0;
> +
> +  support_isolate_in_subprocess (subprocess, NULL);
> +
> +  /* Check that exactly one signal arrived from the subprocess.  */
> +  TEST_COMPARE (signals_delivered, 1);

OK.

> +
> +  support_isolate_in_subprocess (subprocess_no_tid_match,
> +                                 &(struct pid_and_tid)
> +                                 {
> +                                   .pid = getpid (),
> +                                   .tid = gettid (),
> +                                 });

Needs a comment, particularly explaining the choice of .pid/.tid.

> +
> +  support_isolate_in_subprocess (subprocess_no_tid_match,
> +                                 &(struct pid_and_tid)
> +                                 {
> +                                   .pid = getpid (),
> +                                   .tid = getpid (),
> +                                 });

Needs a comment, particularly explaining the choice of .pid/.tid.

> +
> +  return NULL;
> +}
> +
> +static int
> +do_test (void)
> +{
> +  TEST_VERIFY_EXIT (signal (SIGUSR1, sigusr1_handler) != SIG_ERR);
> +
> +  expected_signal_tid = gettid ();
> +  TEST_COMPARE (gettid (), getpid ());
> +  TEST_COMPARE (tgkill (getpid (), gettid (), SIGUSR1), 0);
> +  TEST_COMPARE (signals_delivered, 1);
> +  signals_delivered = 0;
> +
> +  xpthread_join (xpthread_create (NULL, threadfunc, NULL));
> +
> +  TEST_VERIFY (signal (SIGUSR1, SIG_DFL) == sigusr1_handler);
> +  return 0;
> +}

OK.

> +
> +#include <support/test-driver.c>
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index af004fcff6..8c36a1d36b 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -2051,6 +2051,7 @@ GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
>  GLIBC_2.4 __fgets_unlocked_chk F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index 84015f0a57..182dc92293 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2150,3 +2150,4 @@ GLIBC_2.29 getcpu F
>  GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 tgkill F

OK.

>
  
Florian Weimer May 14, 2019, 7:34 p.m. UTC | #2
* Carlos O'Donell:

>> diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
>> index 25424e1399..75a2f23a17 100644
>> --- a/sysdeps/unix/sysv/linux/syscalls.list
>> +++ b/sysdeps/unix/sysv/linux/syscalls.list
>> @@ -111,3 +111,4 @@ memfd_create    EXTRA	memfd_create	i:si    memfd_create
>>  pkey_alloc	EXTRA	pkey_alloc	i:ii	pkey_alloc
>>  pkey_free	EXTRA	pkey_free	i:i	pkey_free
>>  gettid          EXTRA   gettid          Ei:     __gettid	gettid
>> +tgkill          EXTRA   tgkill          i:ii    __tgkill	tgkill
>
> The signature for tgkill should be i:iii (missing an 'i').

Oops.  This probably worked on x86-64 only. 8-/

> I'll be honest and admit I never paid attention to the semantic
> meaning of EXTRA.
>
> Why does tgkill have caller EXTRA?
>
> As far as I know 'EXTRA' triggers the object to be added to
> unix-extra-syscalls, whose only effect is to put the syscall into
> sysdep_routines for subdir misc, and beyond that it isn't clear why
> it's needed at all (even for all the other syscalls). What does
> sysdep_routines really provide here?

Oh.  There's no stub for tgkill, which is why I think the system call
has to be to routines somewhere, and EXTRA does that.

Are you satisfied with this explanation?

Thanks,
Florian
  
Carlos O'Donell May 14, 2019, 8:50 p.m. UTC | #3
On 5/14/19 3:34 PM, Florian Weimer wrote:
> * Carlos O'Donell:
> 
>>> diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
>>> index 25424e1399..75a2f23a17 100644
>>> --- a/sysdeps/unix/sysv/linux/syscalls.list
>>> +++ b/sysdeps/unix/sysv/linux/syscalls.list
>>> @@ -111,3 +111,4 @@ memfd_create    EXTRA	memfd_create	i:si    memfd_create
>>>  pkey_alloc	EXTRA	pkey_alloc	i:ii	pkey_alloc
>>>  pkey_free	EXTRA	pkey_free	i:i	pkey_free
>>>  gettid          EXTRA   gettid          Ei:     __gettid	gettid
>>> +tgkill          EXTRA   tgkill          i:ii    __tgkill	tgkill
>>
>> The signature for tgkill should be i:iii (missing an 'i').
> 
> Oops.  This probably worked on x86-64 only. 8-/

No worries. Happy to not be seen as a rubber stamp :-)

>> I'll be honest and admit I never paid attention to the semantic
>> meaning of EXTRA.
>>
>> Why does tgkill have caller EXTRA?
>>
>> As far as I know 'EXTRA' triggers the object to be added to
>> unix-extra-syscalls, whose only effect is to put the syscall into
>> sysdep_routines for subdir misc, and beyond that it isn't clear why
>> it's needed at all (even for all the other syscalls). What does
>> sysdep_routines really provide here?
> 
> Oh.  There's no stub for tgkill, which is why I think the system call
> has to be to routines somewhere, and EXTRA does that.
> 
> Are you satisfied with this explanation?

Yes.

If you don't define EXTRA then the build infrastructure expects that
you will define a stub yourself.

When you define EXTRA the following sequence is executed ($caller == EXTRA).

sysdeps/unix/make-syscalls.sh:
209  case x$srcfile"$callnum" in
210  x--)
211   # Undefined callnum for an extra syscall.
212   if [ x$caller != x- ]; then
213     if [ $noerrno != 0 ]; then
214       echo >&2 "$0: no number for $fileno, no-error syscall ($strong $weak)"
215       exit 2
216     fi
217     echo "unix-stub-syscalls += $strong $weak"
218   fi
219   ;;

If you build glibc with kernel headers that don't define the syscall
number for tgkill you will have strong/weak aliases from tgkill to the
single stub created sysdeps/unix/Makefile (stub-syscalls.c).

In this sense "EXTRA" means "extra syscalls not overriding any other
sysdep implementations"

Thanks.
  

Patch

diff --git a/NEWS b/NEWS
index b58e2469d4..61c6575ae5 100644
--- a/NEWS
+++ b/NEWS
@@ -16,7 +16,7 @@  Major new features:
 * The dynamic linker accepts the --preload argument to preload shared
   objects, in addition to the LD_PRELOAD environment variable.
 
-* On Linux, the gettid function has been added.
+* On Linux, the gettid and tgkill functions have been added.
 
 * Minguo (Republic of China) calendar support has been added as an
   alternative calendar for the following locales: zh_TW, cmn_TW, hak_TW,
diff --git a/bits/signal_ext.h b/bits/signal_ext.h
new file mode 100644
index 0000000000..d1bed56e55
--- /dev/null
+++ b/bits/signal_ext.h
@@ -0,0 +1,21 @@ 
+/* System-specific extensions of <signal.h>, generic version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SIGNAL_H
+# error "Never include <bits/signal_ext.h> directly; use <signal.h> instead."
+#endif
diff --git a/manual/signal.texi b/manual/signal.texi
index 8b3a52e22a..33e6646975 100644
--- a/manual/signal.texi
+++ b/manual/signal.texi
@@ -2291,6 +2291,21 @@  The @var{pid} argument does not refer to an existing process or group.
 @end table
 @end deftypefun
 
+@deftypefun int tgkill (pid_t @var{pid}, pid_t @var{tid}, int @var{signum})
+@standards{Linux, signal.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+The @code{tgkill} function sends the signal @var{signum} to the thread
+or process with ID @var{tid}, like the @code{kill} function, but only
+if the process ID of the thread @var{tid} is equal to @var{pid}.  If
+the target thread belongs to another process, the function fails with
+@code{ESRCH}.
+
+The @code{tgkill} function can be used to avoid sending a signal to a
+thread in the wrong process if the caller ensures that the passed
+@var{pid} value is not reused by the kernel (for example, if it is the
+process ID of the current process, as returned by @code{getpid}).
+@end deftypefun
+
 @deftypefun int killpg (int @var{pgid}, int @var{signum})
 @standards{BSD, signal.h}
 @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
diff --git a/signal/Makefile b/signal/Makefile
index 06034fee8e..4596112f0a 100644
--- a/signal/Makefile
+++ b/signal/Makefile
@@ -31,7 +31,7 @@  headers := signal.h sys/signal.h \
 	   bits/types/sigevent_t.h bits/types/siginfo_t.h \
 	   bits/types/sigset_t.h bits/types/sigval_t.h \
 	   bits/types/stack_t.h bits/types/struct_sigstack.h \
-	   bits/types/__sigval_t.h
+	   bits/types/__sigval_t.h bits/signal_ext.h
 
 routines	:= signal raise killpg \
 		   sigaction sigprocmask kill \
diff --git a/signal/signal.h b/signal/signal.h
index ee591fcb2d..4c0de7f6ce 100644
--- a/signal/signal.h
+++ b/signal/signal.h
@@ -370,6 +370,9 @@  extern int __libc_current_sigrtmax (void) __THROW;
 #define SIGRTMIN        (__libc_current_sigrtmin ())
 #define SIGRTMAX        (__libc_current_sigrtmax ())
 
+/* System-specific extensions.  */
+#include <bits/signal_ext.h>
+
 __END_DECLS
 
 #endif /* not signal.h */
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 52ac6ad484..d2f0b60ea9 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -53,7 +53,8 @@  sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
 tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
 	 tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
 	 test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
-	 tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill
+	 tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill \
+	 tst-tgkill
 tests-internal += tst-ofdlocks-compat
 
 # Generate the list of SYS_* macros for the system calls (__NR_*
@@ -115,6 +116,7 @@  $(objpfx)tst-mman-consts.out: ../sysdeps/unix/sysv/linux/tst-mman-consts.py
 
 $(objpfx)tst-gettid: $(shared-thread-library)
 $(objpfx)tst-gettid-kill: $(shared-thread-library)
+$(objpfx)tst-tgkill: $(shared-thread-library)
 
 endif # $(subdir) == misc
 
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 5166ccff25..c7137e2c2c 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -175,7 +175,7 @@  libc {
     getcpu;
   }
   GLIBC_2.30 {
-    gettid;
+    gettid; tgkill;
   }
   GLIBC_PRIVATE {
     # functions used in other libraries
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index f3b44d723f..0b5f7aebaa 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2142,3 +2142,4 @@  GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index fd81fc4ad0..9563d753c7 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2217,6 +2217,7 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index f451fefac9..6a5ada177a 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -127,6 +127,7 @@  GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/bits/signal_ext.h b/sysdeps/unix/sysv/linux/bits/signal_ext.h
new file mode 100644
index 0000000000..c07b869fab
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/bits/signal_ext.h
@@ -0,0 +1,31 @@ 
+/* System-specific extensions of <signal.h>, Linux version.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SIGNAL_H
+# error "Never include <bits/signal_ext.h> directly; use <signal.h> instead."
+#endif
+
+#ifdef __USE_GNU
+
+/* Send SIGNAL to the thread TID in the thread group (process)
+   identified by TGID.  This function behaves like kill, but also
+   fails with ESRCH if the specified TID does not belong to the
+   specified thread group.  */
+extern int tgkill (__pid_t __tgid, __pid_t __tid, int __signal);
+
+#endif /* __USE_GNU */
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 018d02b414..2dc527cebd 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2086,3 +2086,4 @@  GLIBC_2.29 xencrypt F
 GLIBC_2.29 xprt_register F
 GLIBC_2.29 xprt_unregister F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index fc3c5d5c27..740b83717f 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2038,6 +2038,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index f2b04dbbff..04fde8ab0f 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2204,6 +2204,7 @@  GLIBC_2.3.4 vm86 F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 10ecf2e47c..9190624dae 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2070,6 +2070,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 814e81b9d2..d70c1eaa7a 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -128,6 +128,7 @@  GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
 GLIBC_2.4 _IO_2_1_stdin_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 68e80372e7..c265f4c546 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2147,6 +2147,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 31178e4f54..e431ed031b 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2134,3 +2134,4 @@  GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 7074573638..590fde4faa 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2121,6 +2121,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 154f9c77fc..9f3ea18f48 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2119,6 +2119,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 97b8f42d5c..0271cd04c9 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2127,6 +2127,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 5b3e85de93..546c5fd7b8 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2121,6 +2121,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 04a130a81c..6c2baff0f1 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2175,3 +2175,4 @@  GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index a701584422..b2d510fe4b 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2177,6 +2177,7 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index bbb647cd98..b8923218b2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2210,6 +2210,7 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index bb23bf61a8..50f200e513 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2040,6 +2040,7 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 7921dda979..978d3b586c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2244,3 +2244,4 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index da123d3867..4f3c033119 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2104,3 +2104,4 @@  GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 2aed339af4..16003407e4 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2172,6 +2172,7 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index e46feb56e5..5d3b1547ed 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2076,6 +2076,7 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 24a8f934cb..5e7ecd0e26 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -2042,6 +2042,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index ebdbd2c5ae..a3def2c7da 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2166,6 +2166,7 @@  GLIBC_2.30 __nldbl_vwarnx F
 GLIBC_2.30 __nldbl_warn F
 GLIBC_2.30 __nldbl_warnx F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 _IO_fprintf F
 GLIBC_2.4 _IO_printf F
 GLIBC_2.4 _IO_sprintf F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 0992349b06..c8abe63ad5 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2093,6 +2093,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
index 25424e1399..75a2f23a17 100644
--- a/sysdeps/unix/sysv/linux/syscalls.list
+++ b/sysdeps/unix/sysv/linux/syscalls.list
@@ -111,3 +111,4 @@  memfd_create    EXTRA	memfd_create	i:si    memfd_create
 pkey_alloc	EXTRA	pkey_alloc	i:ii	pkey_alloc
 pkey_free	EXTRA	pkey_free	i:i	pkey_free
 gettid          EXTRA   gettid          Ei:     __gettid	gettid
+tgkill          EXTRA   tgkill          i:ii    __tgkill	tgkill
diff --git a/sysdeps/unix/sysv/linux/tst-tgkill.c b/sysdeps/unix/sysv/linux/tst-tgkill.c
new file mode 100644
index 0000000000..818e2f58da
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-tgkill.c
@@ -0,0 +1,132 @@ 
+/* Smoke test for the tgkill system call.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <signal.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/xthread.h>
+#include <unistd.h>
+
+/* Number of times sigusr1_handler has been invoked.  */
+static volatile sig_atomic_t signals_delivered;
+
+/* Expected TID of the thread receiving the signal.  */
+static pid_t expected_signal_tid;
+
+static void
+sigusr1_handler (int signo)
+{
+  TEST_COMPARE (expected_signal_tid, gettid ());
+  ++signals_delivered;
+}
+
+struct pid_and_tid
+{
+  pid_t pid;
+  pid_t tid;
+};
+
+/* Send signals from the subprocess which are not expected to be
+   delivered.  There is no handler for SIGUSR2, so delivery will
+   result in a test failure.  CLOSURE must point to a valid PID/TID
+   combination that is still running.  */
+static void
+subprocess_no_tid_match (void *closure)
+{
+  struct pid_and_tid *ids = closure;
+  TEST_COMPARE (tgkill (ids->pid, gettid (), SIGUSR2), -1);
+  TEST_COMPARE (errno, ESRCH);
+
+  TEST_COMPARE (tgkill (getpid (), ids->tid, SIGUSR2), -1);
+  TEST_COMPARE (errno, ESRCH);
+
+  TEST_COMPARE (tgkill (getppid (), gettid (), SIGUSR2), -1);
+  TEST_COMPARE (errno, ESRCH);
+}
+
+/* Called from threadfunc below.  */
+static void
+subprocess (void *closure)
+{
+  int original_tid = expected_signal_tid;
+
+  /* Do not expect that the folloing signals are delivered to the
+     subprocess.  The parent process retains the original
+     expected_signal_tid value.  */
+  expected_signal_tid = 0;
+  TEST_COMPARE (tgkill (getpid (), original_tid, SIGUSR1), -1);
+  TEST_COMPARE (errno, ESRCH);
+  TEST_COMPARE (tgkill (getppid (), gettid (), SIGUSR1), -1);
+  TEST_COMPARE (errno, ESRCH);
+  TEST_COMPARE (expected_signal_tid, 0);
+
+  /* This call has the correct PID/TID combination and is therefore
+     expected to suceed.  */
+  TEST_COMPARE (tgkill (getppid (), original_tid, SIGUSR1), 0);
+}
+
+static void *
+threadfunc (void *closure)
+{
+  TEST_VERIFY (gettid () != getpid ());
+  expected_signal_tid = gettid ();
+  TEST_COMPARE (tgkill (getpid (), gettid (), SIGUSR1), 0);
+  TEST_COMPARE (signals_delivered, 1);
+  signals_delivered = 0;
+
+  support_isolate_in_subprocess (subprocess, NULL);
+
+  /* Check that exactly one signal arrived from the subprocess.  */
+  TEST_COMPARE (signals_delivered, 1);
+
+  support_isolate_in_subprocess (subprocess_no_tid_match,
+                                 &(struct pid_and_tid)
+                                 {
+                                   .pid = getpid (),
+                                   .tid = gettid (),
+                                 });
+
+  support_isolate_in_subprocess (subprocess_no_tid_match,
+                                 &(struct pid_and_tid)
+                                 {
+                                   .pid = getpid (),
+                                   .tid = getpid (),
+                                 });
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  TEST_VERIFY_EXIT (signal (SIGUSR1, sigusr1_handler) != SIG_ERR);
+
+  expected_signal_tid = gettid ();
+  TEST_COMPARE (gettid (), getpid ());
+  TEST_COMPARE (tgkill (getpid (), gettid (), SIGUSR1), 0);
+  TEST_COMPARE (signals_delivered, 1);
+  signals_delivered = 0;
+
+  xpthread_join (xpthread_create (NULL, threadfunc, NULL));
+
+  TEST_VERIFY (signal (SIGUSR1, SIG_DFL) == sigusr1_handler);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index af004fcff6..8c36a1d36b 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2051,6 +2051,7 @@  GLIBC_2.3.4 setsourcefilter F
 GLIBC_2.3.4 xdr_quad_t F
 GLIBC_2.3.4 xdr_u_quad_t F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 84015f0a57..182dc92293 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2150,3 +2150,4 @@  GLIBC_2.29 getcpu F
 GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
 GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
 GLIBC_2.30 gettid F
+GLIBC_2.30 tgkill F