]>
Commit | Line | Data |
---|---|---|
12788f63 MT |
1 | 2010-05-21 Andreas Schwab <schwab@redhat.com> |
2 | ||
3 | * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Add recvmmsg | |
4 | and internal_recvmmsg. | |
5 | * sysdeps/unix/sysv/linux/recvmmsg.c: New file. | |
6 | * sysdeps/unix/sysv/linux/internal_recvmmsg.S: New file. | |
7 | * sysdeps/unix/sysv/linux/socketcall.h (SOCKOP_recvmmsg): Define. | |
8 | * sysdeps/unix/sysv/linux/syscalls.list (recvmmsg): Remove. | |
9 | ||
10 | Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/Makefile | |
11 | =================================================================== | |
12 | --- glibc-2.12-2-gc4ccff1.orig/sysdeps/unix/sysv/linux/Makefile | |
13 | +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/Makefile | |
14 | @@ -12,7 +12,7 @@ CFLAGS-malloc.c += -DMORECORE_CLEARS=2 | |
15 | endif | |
16 | ||
17 | ifeq ($(subdir),socket) | |
18 | -sysdep_routines += internal_accept4 | |
19 | +sysdep_routines += internal_accept4 recvmmsg internal_recvmmsg | |
20 | endif | |
21 | ||
22 | ifeq ($(subdir),misc) | |
23 | Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/internal_recvmmsg.S | |
24 | =================================================================== | |
25 | --- /dev/null | |
26 | +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/internal_recvmmsg.S | |
27 | @@ -0,0 +1,14 @@ | |
28 | +#include <kernel-features.h> | |
29 | +#include <sys/syscall.h> | |
30 | +#if !defined __NR_recvmmsg && defined __NR_socketcall | |
31 | +# define socket recvmmsg | |
32 | +# ifdef __ASSUME_RECVMMSG | |
33 | +# define __socket recvmmsg | |
34 | +# else | |
35 | +# define __socket __internal_recvmmsg | |
36 | +# endif | |
37 | +# define NARGS 5 | |
38 | +# define NEED_CANCELLATION | |
39 | +# define NO_WEAK_ALIAS | |
40 | +# include <socket.S> | |
41 | +#endif | |
42 | Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/kernel-features.h | |
43 | =================================================================== | |
44 | --- glibc-2.12-2-gc4ccff1.orig/sysdeps/unix/sysv/linux/kernel-features.h | |
45 | +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/kernel-features.h | |
46 | @@ -547,3 +547,8 @@ | |
47 | #if __LINUX_KERNEL_VERSION >= 0x020620 | |
48 | # define __ASSUME_F_GETOWN_EX 1 | |
49 | #endif | |
50 | + | |
51 | +/* Support for the recvmmsg syscall was added in 2.6.33. */ | |
52 | +#if __LINUX_KERNEL_VERSION >= 0x020621 | |
53 | +# define __ASSUME_RECVMMSG 1 | |
54 | +#endif | |
55 | Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/recvmmsg.c | |
56 | =================================================================== | |
57 | --- /dev/null | |
58 | +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/recvmmsg.c | |
59 | @@ -0,0 +1,100 @@ | |
60 | +/* Copyright (C) 2010 Free Software Foundation, Inc. | |
61 | + This file is part of the GNU C Library. | |
62 | + Contributed by Andreas Schwab <schwab@redhat.com>, 2010. | |
63 | + | |
64 | + The GNU C Library is free software; you can redistribute it and/or | |
65 | + modify it under the terms of the GNU Lesser General Public | |
66 | + License as published by the Free Software Foundation; either | |
67 | + version 2.1 of the License, or (at your option) any later version. | |
68 | + | |
69 | + The GNU C Library is distributed in the hope that it will be useful, | |
70 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
71 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
72 | + Lesser General Public License for more details. | |
73 | + | |
74 | + You should have received a copy of the GNU Lesser General Public | |
75 | + License along with the GNU C Library; if not, write to the Free | |
76 | + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
77 | + 02111-1307 USA. */ | |
78 | + | |
79 | +#include <errno.h> | |
80 | +#include <sys/socket.h> | |
81 | + | |
82 | +#include <sysdep-cancel.h> | |
83 | +#include <sys/syscall.h> | |
84 | +#include <kernel-features.h> | |
85 | + | |
86 | + | |
87 | +#ifdef __NR_recvmmsg | |
88 | +int | |
89 | +recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, | |
90 | + const struct timespec *tmo) | |
91 | +{ | |
92 | + if (SINGLE_THREAD_P) | |
93 | + return INLINE_SYSCALL (recvmmsg, 5, fd, vmessages, vlen, flags, tmo); | |
94 | + | |
95 | + int oldtype = LIBC_CANCEL_ASYNC (); | |
96 | + | |
97 | + int result = INLINE_SYSCALL (recvmmsg, 5, fd, vmessages, vlen, flags, tmo); | |
98 | + | |
99 | + LIBC_CANCEL_RESET (oldtype); | |
100 | + | |
101 | + return result; | |
102 | +} | |
103 | +#elif defined __NR_socketcall | |
104 | +# ifndef __ASSUME_RECVMMSG | |
105 | +extern int __internal_recvmmsg (int fd, struct mmsghdr *vmessages, | |
106 | + unsigned int vlen, int flags, | |
107 | + const struct timespec *tmo) | |
108 | + attribute_hidden; | |
109 | + | |
110 | +static int have_recvmmsg; | |
111 | + | |
112 | +int | |
113 | +recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, | |
114 | + const struct timespec *tmo) | |
115 | +{ | |
116 | + if (__builtin_expect (have_recvmmsg >= 0, 1)) | |
117 | + { | |
118 | + int ret = __internal_recvmmsg (fd, vmessages, vlen, flags, tmo); | |
119 | + /* The kernel returns -EINVAL for unknown socket operations. | |
120 | + We need to convert that error to an ENOSYS error. */ | |
121 | + if (__builtin_expect (ret < 0, 0) | |
122 | + && have_recvmmsg == 0 | |
123 | + && errno == EINVAL) | |
124 | + { | |
125 | + /* Try another call, this time with an invalid file | |
126 | + descriptor and all other parameters cleared. This call | |
127 | + will not cause any harm and it will return | |
128 | + immediately. */ | |
129 | + ret = __internal_recvmmsg (-1, 0, 0, 0, 0); | |
130 | + if (errno == EINVAL) | |
131 | + { | |
132 | + have_recvmmsg = -1; | |
133 | + __set_errno (ENOSYS); | |
134 | + } | |
135 | + else | |
136 | + { | |
137 | + have_recvmmsg = 1; | |
138 | + __set_errno (EINVAL); | |
139 | + } | |
140 | + return -1; | |
141 | + } | |
142 | + return ret; | |
143 | + } | |
144 | + __set_errno (ENOSYS); | |
145 | + return -1; | |
146 | +} | |
147 | +# else | |
148 | +/* When __ASSUME_RECVMMSG recvmmsg is defined in internal_recvmmsg.S. */ | |
149 | +# endif | |
150 | +#else | |
151 | +int | |
152 | +recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags, | |
153 | + const struct timespec *tmo) | |
154 | +{ | |
155 | + __set_errno (ENOSYS); | |
156 | + return -1; | |
157 | +} | |
158 | +stub_warning (recvmmsg) | |
159 | +#endif | |
160 | Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/socketcall.h | |
161 | =================================================================== | |
162 | --- glibc-2.12-2-gc4ccff1.orig/sysdeps/unix/sysv/linux/socketcall.h | |
163 | +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/socketcall.h | |
164 | @@ -44,5 +44,6 @@ | |
165 | #define SOCKOP_sendmsg 16 | |
166 | #define SOCKOP_recvmsg 17 | |
167 | #define SOCKOP_accept4 18 | |
168 | +#define SOCKOP_recvmmsg 19 | |
169 | ||
170 | #endif /* sys/socketcall.h */ | |
171 | Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/syscalls.list | |
172 | =================================================================== | |
173 | --- glibc-2.12-2-gc4ccff1.orig/sysdeps/unix/sysv/linux/syscalls.list | |
174 | +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/syscalls.list | |
175 | @@ -53,7 +53,6 @@ prctl EXTRA prctl i:iiiii __prctl prc | |
176 | putpmsg - putpmsg i:ippii putpmsg | |
177 | query_module EXTRA query_module i:sipip query_module | |
178 | quotactl EXTRA quotactl i:isip quotactl | |
179 | -recvmmsg EXTRA recvmmsg Ci:ipiip recvmmsg | |
180 | remap_file_pages - remap_file_pages i:piiii __remap_file_pages remap_file_pages | |
181 | sched_getp - sched_getparam i:ip __sched_getparam sched_getparam | |
182 | sched_gets - sched_getscheduler i:i __sched_getscheduler sched_getscheduler |